From: MERC::"uunet!CRVAX.SRI.COM!RELAY-INFO-VAX" 6-APR-1993 10:09:03.18 To: INFO-VAX CC: Subj: RE: protected terminals (was re: how can i keep somebody . Hi, Nowadays its not often that I'm prompted to contribute to Info-VAX (aka. Info-Glut) but when something positivly dangerous/wrong is posted, I feel the urge to reply... (this goes on a bit, sorry...) In article <1ohggeINNgaf@gap.caltech.edu>, carl@SOL1.GPS.CALTECH.EDU writes... > # > #If the executive-mode logical name SYS$SYLOGIN is defined in the system table, > #that file will be executed before the file defined in the LGICMD field in your > #SYSUAF entry or any file you specify via the /COMM qualifier to your username > #at login. Period. To change this, you'd have to patch LOGINOUT.EXE (or the > #terminal driver, forcing it to trigger something other than LOGINOUT). > > Correction: It is the job controller (JOBCTL) which runs the LOGINOUT image. > That is what one would need to patch to run something else. > Then Bill Laut (laut@alien.gici.com) wrote: > Alternative: Inside the Exec there's a couple of vectors labelled > SYS$AR_JOBCTLMB and TTY$GL_JOBCTLMB. These contain the UCB > address of the mailbox that JOBCTL is receiving messages with. > Instead of patching JOBCTL, an easier proposal might be: > 1) Create another permanent mailbox. > 2) Allocate a chunk of non-paged pool. > 3) Insert your terminal-checking code into the block. > 4) Put the UCB of your other mailbox into the > TTY$GL_JOBCTLMB longword. > 5) Allocate an IRP, dummy it up, and insert the > address of your SUBROUTINE (not procedure) into > the IRP$L_PID offset. > 6) Queue the IRP to the alternate mailbox. > 7) Have a beer. > > Now, when the terminal class driver gets an unsolicited > terminator from a terminal, it will create the usual MBX > message and drop it into the mailbox at TTY$GL_JOBCTLMB, > which now happens to be *your code*. > > Check out the vitals in the mailbox message, and decide if > this is a terminal you want protected. If not, relay the > message to the mailbox in SYS$AR_JOBCTLMB and let JOBCTL > process it as usual. > > If this is a protected terminal, then fire up the program > you want to execute against that terminal. Since you are > currently running in system context, you obviously cannot > issue a $QIO without incurring fatal results. Instead, > scan the process table to locate JOBCTL, and then queue up > a kernel-mode AST to the process, as follows: > > 1) Allocate a block of nonpaged pool for an ACB. > 2) Initialize it as a kernel-mode AST, with the > PROCEDURE (not subroutine) entry point being in > another part of your first pool block. > 3) Grab the SYNCH spinlock and increment the target > process' PCB$B_DPC counter. > 4) Fork down to IPL$_QUEUEAST > 5) Set the desired priority boost in R2. > 6) JSB G^Sch$QAst > 7) Re-initialize the IRP for another read request. > 8) Synch with the Mailbox > 9) Requeue the IRP to the mailbox. > > At this point, the thread is now running as a kernel-mode > thread against JOBCTL. The PCB$B_DPC increment prevents the > process from being deleted until after the AST has finished. > > We now pick it up within the AST: > > 1) Construct a character string, representing the > protected terminal's name. > 2) Invoke $CREPRC, passing the terminal name as > Input, Output, and error, as well as the image > you wish to have executed. > 3) Grab the SYNCH spinlock and decrement PCB$B_DPC. > 4) Release the spinlock. > 5) Stick SS$_NORMAL into R0 and issue RET. > > You now have a detached process created against the protected > terminal, running the image of your choosing. > > Gull Island Consultants, Inc. Phone: (616) 780-3321 > Muskegon, MI 49440 >> "Usual disclaimers, apply within" <<> Gosh! Forgive me if I'm being a bit daft here, but I was taught that the most things (even on VMS) can be done simply. Apart from anything else, Bill's code above will not work on VMS V5.0 or later (and, for all its complexity, on versions prior to that). The terminal class drive DOES NOT USE TTY$GL_JOBCTLMB, it ONLY uses SYS$AR_JOBCTLMB. You MUST NOT UNDER ANY CIRCUMSTANCES alter the vector in SYS$AR_JOBCTLMB because you will break $SNDJBC[W] - ie. SUBMIT, PRINT etc. will ALL break (the $SNDJBC service makes assumptions about the vector). I spent some time developing a system that intercepts unsolicited connections into VMS systems - you have to PATCH TTDRIVER module TTYSUB, routine TTY$FORK_ADDR in the UNSOL fork processing code so that it uses TTY$GL_JOBCTLMB again (instead of SYS$xx_JOBCTLMB) to locate the UCB of the JOB_CONTROLler's mailbox. You can then, in a user mode detached program: 1. Create an ordinary permanent mailbox (MSGMAX=1024, BUFQUO several times that). 2. Queue a read or set a write attention AST on it 3. Assign a channel to the JOB_CONTROLler's mailbox (its hard wired to be MBA1:, or you can determine it from the contents of SYS$xx_JOBCTLMB with a tiny bit of MACRO) 4. When the above 3 steps have been done, use a USER WRITTEN SYSTEM SERVICE to change the value stored in TTY$GL_JOBCTLMB to point to the UCB of your mailbox. eg. ;+ ; REVECTOR_TO_CHAN (IPL 0, Kernel mode service) ; ; 4(ap) Channel number of mailbox to revector to ; r4 => caller's PCB (from change mode dispatcher) ;- .entry REVECTOR_TO_CHAN, ^m movzwl 4(ap), r0 ; r0 = channel number jsb g^IOC$VERIFYCHAN ; Check the channel number blbc r0, 90$ ; Exit on error movl CCB$L_UCB(r1), r1 ; R1 => device UCB bbc #DEV$V_MBX, UCB$L_DEVCHAR(r1), 100$ ; Exit if not a mailbox cmpb UCB$B_DEVCLASS(r1), #DC$_MAILBOX ; Must be a mailbox bneq 100$ ; Exit if not a mailbox movl r1, g^TTY$GL_JOBCTLMB ; Change the TTY vector movzwl #SS$_NORMAL, r0 ; Success 90$: ret 100$: movzwl #SS$_DEVNOTMBX, r0 ; Device is not a mailbox ret The above code is an example - it should work but it should also lock the I/O database while the UCB checks are made. You should use a user written system service so that you can have a kernel mode rundown routine to replace the value in TTY$GL_JOBCTLMB with the address of the REAL JOB_CONTROL mailbox if your server dies for ANY reason (ACCVIO, STOP/ID or whatever). Otherwise, if the server dies, all logins will be disabled. eg. .entry USER_RUNDOWN, ^m .ifdef VMSV55 ; VMS V5.5 uses different vector movl g^SYS$AR_JOBCTLMB, g^TTY$GL_JOBCTLMB .if_false ; VMS V5.4 and earlier movl g^SYS$GL_JOBCTLMB, g^TTY$GL_JOBCTLMB .endc movzwl #SS$_NORMAL, r0 ret In your server, check all mailbox messages for MSG$_TRMUNSOLIC. If its another sort of message, forward it to the JOB_CONTROLler without further ado, else check the device/unit number in the message. If its one you are interested in, then perform further checks, else forward the message to the JOB_CONTROLler... etc. This method is FAR simpler and more reliable - 99.9% of the code you need to write is in user mode, and all the rest is at IPL 0. User written system services are supported - the patch to TTDRIVER is not, but is very simple and does not alter any code path (and thus should not affect any DEC patches to that image). I have used it for many years (since 1987) without any problems. Note that if you intend to run up multiple applications on a terminal whose unsolicited input you have trapped with the above technique, you have to play games with some other flags in the terminal UCB (to prevent the line hanging up on the last deassign). This is no problem, but requires careful thought. Nick NICK@NCDLAB.ULCC.AC.UK PS. For those amongst you who have stuck it this far (!), you may have noticed some interesting possibilities regarding VMS multi-user licenses. Be warned: DEC are aware of this and have a policy on intercepted connection requests - it basically is that you are not breaking the rules if the remote user does not see DCL (or, I suppose, another CLI).