Copyright 1987-2016 by Kevin G. Barkes All rights reserved. This article may be duplicated or redistributed provided no alterations of any kind are made to this file. This edition of DCL Dialogue is sponsored by Networking Dynamics, developers and marketers of productivity software for OpenVMS systems. Contact our website www.networkingdynamics.com to download free demos of our software and see how you will save time, money and raise productivity! Be sure to mention DCL Dialogue! DCL DIALOGUE Originally published November, 1987 By Kevin G. Barkes "The Joys of Captivity" VAX system sites are often the victims of a double-edged sword. Small to moderate-sized systems require very little in the way of day-to-day management. If extensive magnetic tape handling is not required, the need for full-time operators is eliminated. A "one-person" operation and the economies it provides is one of the major pluses of running VAXen. On the downside, a VAX is a VAX, from MicroVAX to 8800, and there are certain semi-complex functions, such as incremental backup, which must be performed by someone with a relative degree of competence. Here's a "case study" of such a site, and one way of handling the problem: The installation ran in a commercial environment on a 24 hour a day, 7 days/week basis. Data was constantly entered by users into a database management system. All data was maintained on line; operators were not required. Key operations personnel were trained to perform printer-related duties, such as fixing jams and changing paper and ribbons. The necessary queue-management functions were contained in a small suite of DCL command procedures. Because of the volatility of the database, incremental backups were required every eight hours. This was the source of the problem. No systems personnel were on duty after regular business hours; only regular production workers. Management didn't like the idea of leaving privileged accounts open to normal staffers. The system manager had a philosophical problem with scheduling the backups to be executed from batch queues. He opted instead to run the jobs from a captive account. A captive account is one which severely limits the user. Among other restrictions, captive users cannot change their passwords, use the /DISK or /COMMAND qualifiers at login to bypass the default login command procedure, or control-y out of the procedure. The command file executed by the captive account at login can be set up so that the user never gets to the DCL level. This permits the manager to give the account high-level privileges without having to worry about the person logging in gaining free access to the system. Table 1 shows the user authorization record of the captive account used in this application. Note the login flags entry, which insures the user cannot escape to the system. (The "Diswelcome" entry elimiates the display of the welcome message at login.) Although not visible on the UAF record, the account is set up with no password; all that's required is to enter the account name BACKUP. The actual incremental backup is performed by the command file SYS$MANAGER:INCBACK.COM, the procedure executed at login. Added security is provided here by performing several checks. The procedure looks at the terminal where the process is logged in. If it's not the operator's console, the procedure branches to BAD_TERMINAL and logs the user out. If the procedure is executed by a user other than BACKUP, or from an account that isn't captive, the branch to NOT_AUTHORIZED also terminates the session. The normal procedure at the site was for a staffer to enter the computer room, load the appropriate tape on the drive and then log in as BACKUP. The original procedure did no error checking, and if the drive were allocated by someone else or the tape did not mount properly, it would simply bomb through the rest of the procedure and exit, confounding and confusing the user. INCBACK checks the status of the allocate and mount commands, and if either fails, warns the users on the system. It waits a minute, then tries again. Without the /NOASSIST qualifier to the MOUNT command, the procedure would simply notify the operator terminals to mount a tape. Sometimes this message would go unnoticed for hours, especially if the procedure was started by someone who was going off-shift. The actual backup commands are straightforward. At this site, the incrementals all fit on one tape, so no provision was made to notify users should a second volume be necessary. Captive accounts provide one easy-to-implement method of permitting non- technical users to perform tasks which require potentially dangerous privileges, without compromising the integrity of the system. What's your method of handling situations such as these? Send your suggestions to me at any of the addresses listed in the box accompanying this article. ***** MEA CULPA Dave Smith, a SYS$OUTPUT user, noted the privilege stacking procedures in the July issue were more complicated than necessary. "The part I take issue with," Dave notes, "is where you are testing for/setting the CMKRNL privilege. Using UPOP.COM as an example, this is how I would have written the code between the DO_POP: and POP_UIC: labels: $ DO_POP: $ SAVE_PRIV = F$SETPRV("CMKRNL") $ IF F$PRIVILEGE("CMKRNL") THEN- GOTO POP_UIC $ TYPE SYS$INPUT/NOLOG You do not have the privileges required to use this command. $ EXIT $ POP_UIC: . . . "Then, at the end of the procedure to restore the previous privilege:" $ EXIT: $ SAVE_PRIV = F$PRIVILEGE(SAVE_PRIV) $ EXIT Dave caught me on this one. My only excuse is laziness. Like any good DCL writer, I frequently steal hunks of code from other procedures. This segment came from a procedure which passed various privileges to the lexicals and checked to determine whether the requested priv was "legal", since a non- existent priv would return an error. So much for saving time! *************** ! INCBACK.COM ! Command procedure to perform incremental backups. Designed to be run ! by a captive account named BACKUP from the system operator's console. ! !--------------------------------- ! Disable error processing: $ SET NOON ! !--------------------------------- ! Make certain the procedure is being executed from the ! captive BACKUP account, at the operator's console: $ IF F$GETJPI("","TERMINAL") .NES. "OPA0:" THEN GOTO BAD_TERMINAL $ IF F$GETJPI("","USERNAME") .NES. "BACKUP" .OR. - .NOT. F$ENVIRONMENT("CAPTIVE") THEN GOTO NOT_AUTHORIZED ! !--------------------------------- ! Allocate the tape drive. Substitute your tape device throughout, ! or use a logical name assignment. $ ALLOCATE_DRIVE: $ ALLOCATE MTA0: ! !--------------------------------- ! Store the value of $STATUS $ $ALLOSTAT = $STATUS ! !--------------------------------- ! If ALLOCATE failed, scream bloody murder: $ IF .NOT. $ALLOSTAT THEN GOTO BAD_ALLOCATE ! !--------------------------------- ! Mount the tape. The /NOASSIST qualifier forces MOUNT to fail and return ! an error, rather than print out a message at the operator console: $ MOUNT_TAPE: $ MOUNT/NOASSIST/FOREIGN MTA0: ! !--------------------------------- ! Store the value of $STATUS: $ $MOUNTSTAT = $STATUS ! Notify users if MOUNT fails: $ IF .NOT. $MOUNTSTAT THEN GOTO BAD_MOUNT ! !--------------------------------- ! Perform the actual backup. Change disk device names as necessary. $ ON SEVERE_ERROR THEN GOTO ERROR_1 $ REPLY/ALL/BELL "Backing up system disk..." $ BACKUP/REWIND/RECORD/FAST/JOURNAL=SYS$MANAGER:INCSYS.BJL/- IGNORE=INTERLOCK/VERIFY/BUFFER=5 - SYS$SYSDEVICE:[*...]/SINCE=BACKUP MTA0:INCSYS.BCK $ REPLY/ALL/BELL "Backing up DISK1..." $ BACKUP/NOREWIND/RECORD/FAST/JOURNAL=SYS$MANAGER:INCDISK1.BJL/- IGNORE=INTERLOCK/VERIFY/BUFFER=5 - DISK1:[*...]/SINCE=BACKUP MTA0:INCDISK1.BCK ! !--------------------------------- ! Notify users when backup is completed: $ REPLY/ALL/BELL "Incremental backup completed." ! !--------------------------------- ! Exit gracefully: $ FINISH: $ DISMOUNT MTA0: $ DEALLOCATE MTA0: $ EOJ ! ! Error handlers: !--------------------------------- ! Notify users of backup error and exit: $ ERROR_1: $ REPLY/ALL/BELL/URGENT "WARNING! BACKUP FAILURE!" $ REPLY/ALL/BELL/URGENT "NOTIFY SYSTEM MANAGER!" $ DISMOUNT MTA0: $ DEALLOCATE MTA0: $ EOJ ! !--------------------------------- ! Notify users of MOUNT failure and tell them why it failed: $ BAD_MOUNT: $ REPLY/URGENT/BELL/ALL "ERROR MOUNTING TAPE! PLEASE CHECK!!" $ REPLY/URGENT/BELL/ALL "Error: ''F$MESSAGE($MOUNTSTAT)'" ! Wait one minute, then try to mount the tape again: $ WAIT 00:01:00 $ GOTO MOUNT_TAPE ! !--------------------------------- ! Notify users of ALLOCATE failure and tell them why it failed: $ BAD_ALLOCATE: $ REPLY/URGENT/BELL/ALL "ERROR ALLOCATING DRIVE! PLEASE CHECK!!" $ REPLY/URGENT/BELL/ALL "Error: ''F$MESSAGE($ALLOSTAT)'" ! Wait one minute, then try to allocate the drive again: $ WAIT 00:01:00 $ GOTO ALLOCATE_DRIVE ! !---------------------------------- $ BAD_TERMINAL: $ WRITE SYS$OUTPUT "BACKUP must be run from the operator's console." $ EOJ ! !---------------------------------- $ NOT_AUTHORIZED: $ WRITE SYS$OUTPUT "You are not authorized to use this procedure." $ EOJ ************** Username: BACKUP Owner: SYSTEM MANAGER Account: SYSTEM UIC: [1,5] ([SYSTEM,BACKUP]) CLI: DCL Tables: Default: SYS$SYSROOT:[SYSMGR] LGICMD: SYS$MANAGER:INCBACKUP.COM Login Flags: Disctly Captive Diswelcome Primary days: Mon Tue Wed Thu Fri Secondary days: Sat Sun No access restrictions Expiration: (none) Pwdminimum: 8 Login Fails: 0 Pwdlifetime: (none) Pwdchange: (none) Last Login: 2-SEP-1987 17:08 (interactive), (none) (non-interactive) Maxjobs: 0 Fillm: 20 Bytlm: 20480 Maxacctjobs: 0 Shrfillm: 0 Pbytlm: 0 Maxdetach: 0 BIOlm: 18 JTquota: 1024 Prclm: 10 DIOlm: 18 WSdef: 512 Prio: 4 ASTlm: 24 WSquo: 768 Queprio: 0 TQElm: 20 WSextent: 1536 CPU: (none) Enqlm: 30 Pgflquo: 10000 Authorized Privileges: BYPASS LOG_IO PRMMBX TMPMBX OPER NETMBX PHY_IO SYSPRV Default Privileges: BYPASS LOG_IO PRMMBX TMPMBX OPER NETMBX PHY_IO SYSPRV ---------- Kevin G. Barkes is an independent consultant. He publishes the KGB Report newsletter, operates the www.kgbreport.com website, lurks on comp.os.vms, and can be reached at kgbarkes@gmail.com.