A Practical Exercise in Securing an OpenVMS System Rob McMillan Prentice Centre The University Of Queensland Now at Griffith University E-Mail: R.McMillan@itc.gu.edu.au Phone: 07 875 6557 Postal: Information Technology Services Griffith University Nathan Qld 4111 A Practical Exercise In Securing An OpenVMS System Abstract _________________________________________________________ OpenVMS machines have many features that can be used to defend them from attack. To properly defend your machine, you need to make use of these features from the moment of delivery. In this paper, I present the series of steps taken by a typical systems programmer (namely the author) in tuning the defense mechanisms of an OpenVMS machine, and outline some non-standard mechanisms employed in the defence of this machine. All too often, emphasis is placed on particular accents, such as access prevention, or reactive examination and monitoring after attack. This paper attempts a more holistic approach to the host-based mechanisms that could be employed to defend a machine. Access control mechanisms (such as passwords, user authorisation parameters, and access control wrappers) and activity logging mechanisms (such as audit trails, terminal monitors and FAL logging) are considered. _________________________________________________________ The information contained in this paper is given freely as an account of my own experience, and may be used by the reader as the reader sees fit. No responsibility or liability will be accepted by the author for any damages caused by direct or indirect use of the information or functionality described in this paper. Introduction 1.1 Assumptions This paper will discuss some of the features that can be used to defend an OpenVMS machine from outside attack. The ideas presented in this paper are the result of an exercise in configuring a machine in a university department used for a sensitive research project. All of the mechanisms I consider in this paper can be classed as host based mechanisms. However, the defence of an computer system is not limited to these measures only. Measures that should be used, but that I don't discuss in this paper are: * network based security, * backups, and * physical security. This paper is not intended to present an "expert's view" of securing an OpenVMS machine. The reason for this is simple - whilst my knowledge of OpenVMS security is quite solid, I would not put myself in the "expert" category. Therefore this paper should not be seen as the canonical guide to OpenVMS security - rather, it should be seen as the series of measures that programmers should typically consider in defending their machine. There is absolutely no substitute for reading the Guide to VAX/VMS System Security manual. Finally, this paper is concerned with the defence of a machine. I do not personally make any attempt to crack machines. I will not present any information on how to crack an OpenVMS machine. 1.2 What This Paper Contains The following topics are those considered during the configuration of the machine referred to above. This list is not exhaustive. * System Mechanisms For Configuring The Machine To Control Access : * SYS$MANAGER Command Files * Welcome Messages * Accounts To Disable, Passwords To Change, And Objects To Modify * System Logicals And Logical Definitions * System Passwords * The UAF File * File Protections * ACLs * Tailoring UCX * Proxies * System Mechanisms For Configuring The Machine To Log Activity : * Accounting * Auditing * FAL and Poor Man's Routing * Using Homegrown Or Publicly Available Software : * Wrappers * Single Use PINs * Terminal Monitors * Monitoring The Use of The Machine : * The SHOW INTRUSION Command * Daily Activities * Having a Live Console System Mechanisms For Configuring The Machine To Control Access 2.1 SYS$MANAGER Command Files There are three files in SYS$MANAGER: that are of importance in terms of this paper. They are SYSTARTUP_V5.COM, SYLOGIN.COM and SYLOGICALS.COM. I have left comments about SYLOGICALS.COM for Section 2.4, System Logicals And Logical Definitions. 2.1.1 SYSTARTUP_V5.COM There are several different things to be done here. As discussed in Section 2.5, System Passwords, a system password should be installed. A system password means that the user must enter a password before the login prompt appears. The procedure for doing this is discussed in Section 2.5. However, this is the change you could make in SYSTARTUP_V5.COM to ensure that a console user does not need to enter the password. (The console should be located in a physically secure area.) $! No system password required for console. $ write sys$output "[Modifying console settings]" $ SET TERMINAL OPA0: /PERMANENT /NOSYSPASSWORD This ensures that should the user log in from the console, a system password will not be required. This prevents situations where you are locked out from the machine should the password be changed or forgotten. $! The following commands turn off account logging and $! delete the account log. $! To keep an account log on your system, delete the $! following 5 command lines. $! $! IF (.NOT. MICROVAX) THEN GOTO SKIP_ACCOUNTING $! SET ACCOUNTING/DISABLE $! IF F$SEARCH("SYS$MANAGER:ACCOUNTNG.DAT") .NES. "" THEN - $! DELETE SYS$MANAGER:ACCOUNTNG.DAT;* $!SKIP_ACCOUNTING: When the operating system is installed, this code is not commented out. That is, account logging is not enabled by default. It is good practice to use all logging facilities available to you, and system accounting is one of those facilities that is strongly recommended. You need accounting to provide an extra audit trail on the system. To enable accounting, comment out these lines, as shown on the following page. $! The following commands purge the operator and network $! logs to two versions. $! $! IF (.NOT. MICROVAX) THEN GOTO SKIP_PURGING $! IF F$SEARCH("SYS$MANAGER:OPERATOR.LOG;-1") .NES. "" THEN - $! PURGE SYS$MANAGER:OPERATOR.LOG $! IF F$SEARCH("SYS$MANAGER:EVL.LOG;-1") .NES. "" THEN - $! PURGE SYS$MANAGER:EVL.LOG $!SKIP_PURGING: Here the machine is trying to make a guess about how much information should be saved as current information (the tradeoff being information currency and usefulness against disk space). A more reasonable figure is 10 versions (working on the basis of a new file per day). To implement this, do the following: * Comment out the lines above. * Create artificial OPERATOR.LOG and EVL.LOG files, each 1 version higher than the logs currently open and in use by the system. * Issue SET FILE OPERATOR.LOG /VERSION_LIMIT=10 and SET FILE EVL.LOG /VERSION_LIMIT=10. This is done against the files just created, as the SET FILE command will fail against the logs open and in use by the system. When new files are opened for use by the system, they will be created with a version number of one higher than the logs created artificially, but will inherit the version limit. $! This command defines a message to be displayed before $! each user logs in. $! $! DEFINE /SYSTEM SYS$ANNOUNCE " Welcome to VAX/VMS ''F$GETSYI("VERSION")'" $ DEFINE /SYSTEM SYS$ANNOUNCE "@SYS$MANAGER:ANNOUNCE.TXT" $! $! This command defines a message or file to be $! displayed after each user logs in. $! $ DEFINE /SYSTEM SYS$WELCOME "@SYS$MANAGER:WELCOME.TXT" $! For legal reasons, as set out in SERT Advisory SA-93.03 (See Appendix 1, SERT Advisory SA-93.03, Suggested Login Banner) give people fair warning of the consequences of misuse. The contents of the files ANNOUNCE.TXT and WELCOME.TXT are discussed in Section 2.2, Welcome Messages. To make these files appear, the definitions above are used. 2.1.2 SYLOGIN.COM SYLOGIN.COM is a command file executed when any user logs in. This is the ideal place to install mechanisms to universally check a user's credentials (such as username, source of login, time, terminal or knowledge- based authenticators). The first three lines of SYLOGIN.COM should be as follows (but aren't in the supplied file). $ SET NOON $ SET NOCONTROL_Y $ SET NOVERIFY This prevents a user (and hence crackers in the first instance) from seeing what mechanisms you have installed, and also interrupting the execution of this file to avoid these mechanisms. $! Place your site-specific LOGIN commands below $! $! If they get this far, then there may have been a breakin, $! but at least we can stop them at this point. $! Call the wrapper. $! $ @LOCAL$WRAP:INTERACTIVE.COM $ IF ($Status .NE. %x10000001) $ THEN $ STOP/ID=0 $ ENDIF As the comments outline, we use a command procedure at this point to check credentials. This may or may not involve interactive exchanges. If the person logging in fails to pass the tests, then they are logged out. (You will need to define LOCAL$WRAP, for example, in SYLOGICALS.COM.) 2.2 Welcome Messages For legal reasons, as set out in SERT Advisory SA-93.03 (See Appendix 1, SERT Advisory SA-93.03, Suggested Login Banner) give people fair warning of the consequences of misuse. By default, there is no SYS$WELCOME issued, and SYS$ANNOUNCE welcomes the person logging in. SYS$WELCOME needs to be enabled, and point to a file, and SYS$ANNOUNCE should also point to a file (as shown in Section 2.1.1, SYSTARTUP_V5.COM). These files should outline to people conditions of use, and legal consequences of misuse. SYS$ANNOUNCE is the message or banner that appears immediately before the login prompt (but after the system password has been entered). SYS$WELCOME is the message or banner that appears immediately after the person has logged in. In this way, users should normally see this warning before and after logging in. This message should appear in SYS$MANAGER:ANNOUNCE.TXT: ----- Warning Message ----- ***** This service is for authorised staff only ***** ************************************************************************* * * * WARNING: It is a criminal offence to: * * i. Obtain access to data without authority * * (Penalty 2 years imprisonment) * * ii Damage, delete, alter or insert data without authority * * (Penalty 10 years imprisonment) * * * ************************************************************************* The following message should appear in SYS$MANAGER:WELCOME.TXT. This is {nodename} (VAX/VMS V5.5-2) - Unauthorised access prohibited! ***** This service is for authorised staff only ***** ************************************************************************* * * * WARNING: It is a criminal offence to: * * i. Obtain access to data without authority * * (Penalty 2 years imprisonment) * * ii Damage, delete, alter or insert data without authority * * (Penalty 10 years imprisonment) * * * ************************************************************************* 2.3 Accounts To Disable, Passwords To Change, And Objects To Modify 2.3.1 Accounts VMS is supplied with a number of default accounts. It should be assumed that crackers will attempt to compromise a machine using default account names and passwords. This principle applies to any operating system. The following default accounts should have their passwords changed, and the accounts disabled: DEFAULT, FIELD, MIRRO$SERVER, SYSTEST, SYSTEST_CLIG. The accounts can be disabled thus: $ MCR AUTHORIZE UAF> MODIFY DEFAULT /FLAGS=DISUSER UAF> MODIFY FIELD /FLAGS=DISUSER UAF> MODIFY MIRRO$SERVER /FLAGS=DISUSER UAF> MODIFY SYSTEST /FLAGS=DISUSER UAF> MODIFY SYSTEST_CLIG /FLAGS=DISUSER UAF> EXIT $ Depending upon how you wish to execute batch jobs and carry out general system administration, you may also wish to either similarly treat the SYSTEM account, or alternative apply strict access controls on this account on the UAF file (See Section 2.6, The UAF File). 2.3.2 Objects There are several objects that needed tailoring. Some of the tailoring is to prevent simple security breaches, whereas others (like the modifications to PHONE, TASK and FAL) are to prevent breaches that could occur in whole or in part to Poor Man's Routing (See Section 3.3, FAL and Poor Man's Routing). In the first stage, the PHONE and TASK objects are disabled. In the PHONE application, the directory command can be used to obtain a directory listing of users on remote DECNet nodes. It is essentially a default "finger". Whilst security through obscurity is no security at all, any access to system details should be suppressed where possible. The TASK object is used to execute jobs on your node from remote nodes. Since this is not a desired feature on the machine used in the preparation of this paper, this object was disabled. Alternatively, the object could have been loaded with false information into the permanent database. These objects are created at boot time using default information if there is no information about them in the NCP permanent database. Therefore, a job can be run immediately after booting to remove these objects. The objects can be removed thus: $ MCR NCP CLEAR OBJECT PHONE ALL $ MCR NCP PURGE OBJECT PHONE ALL $ MCR NCP CLEAR OBJECT TASK ALL $ MCR NCP PURGE OBJECT TASK ALL They could alternatively be modified thus: $ MCR NCP SET OBJECT TASK USER ILLEGAL PASSWORD DISABLED $ MCR NCP SET OBJECT TASK PROXY NONE $ MCR NCP SET OBJECT TASK ALIAS INCOMING DISABLED $ MCR NCP SET OBJECT TASK ALIAS OUTGOING DISABLED $ MCR NCP DEFINE OBJECT TASK USER ILLEGAL PASSWORD DISABLED $ MCR NCP DEFINE OBJECT TASK PROXY NONE $ MCR NCP DEFINE OBJECT TASK ALIAS INCOMING DISABLED $ MCR NCP DEFINE OBJECT TASK ALIAS OUTGOING DISABLED $ MCR NCP SET OBJECT PHONE USER ILLEGAL PASSWORD DISABLED $ MCR NCP SET OBJECT PHONE PROXY NONE $ MCR NCP SET OBJECT PHONE ALIAS INCOMING DISABLED $ MCR NCP SET OBJECT PHONE ALIAS OUTGOING DISABLED $ MCR NCP DEFINE OBJECT PHONE USER ILLEGAL PASSWORD DISABLED $ MCR NCP DEFINE OBJECT PHONE PROXY NONE $ MCR NCP DEFINE OBJECT PHONE ALIAS INCOMING DISABLED $ MCR NCP DEFINE OBJECT PHONE ALIAS OUTGOING DISABLED In the second stage below, objects are modified so that they are still usable, but subject to tighter controls than the default. The simplest change is made to the MIRROR object by disabling the MIRRO$SERVER account in the User Authorisation File. The MIRROR object should be kept to allow loopback testing should it become necessary. The account is disabled since it serves no useful purpose (other than for loopback testing), and should be disabled unless in use. The MAIL object should be modified thus according to the VMS v5.5-2 release notes, Section 2.8.7, to restrict outgoing access on the mail server. In v5.5-2, MAIL enables system privileges when it opens a DECnet connection to a remote mail server. By restricting outgoing access on the mail server object (as below), unauthorised users are prevented from placing connections on the mail server object. $ MCR NCP SET OBJECT MAIL OUTGOING CONNECT PRIVILEGE SYSPRV $ MCR NCP DEFINE OBJECT MAIL OUTGOING CONNECT PRIVILEGE SYSPRV This can be undone by executing the same commands with "NOSYSPRV". MAIL_SERVER.EXE (the executable associated with the MAIL object) is installed as a privileged image. Wrappers should also be installed for the FAL and NML objects. The executable images for these are, by default, normally FAL.EXE and NML.EXE respectively. Modify the object database as shown below. $ MCR NCP SET OBJECT FAL FILE LOCAL$WRAP:FAL.COM $ MCR NCP DEFINE OBJECT FAL FILE LOCAL$WRAP:FAL.COM $ MCR NCP SET OBJECT NML FILE LOCAL$WRAP:NML.COM $ MCR NCP DEFINE OBJECT NML FILE LOCAL$WRAP:NML.COM The contents of the wrappers are discussed in Section 4.1, Wrappers. 2.4 System Logicals And Logical Definitions SYS$MANAGER:SYLOGICALS.COM is used to establish important site-specific logical names across the entire system. You can put meaningful local definitions in here as well as the definitions already supplied with the delivered system. $! Undocumented feature to disable poor man's routing $ DEFINE /SYSTEM /EXEC FAL$LOG "03/DISABLE=8" Poor Man's Routing is explained in Section 3.3, FAL and Poor Man's Routing. That section also explains the significance of this definition. It's relevance to this section is merely that it is centrally defined in SYLOGICALS.COM. $! Make network server processes die after 10 seconds $! (to give separate NETSERVER.LOG files for $! each distinct operation) $ DEFINE /SYSTEM /EXEC NETSERVER$TIMEOUT "0000 00:00:10" This forces network server processes to die after 10 seconds of lying idle, thus creating separate NETSERVER.LOG files for each essentially distinct operation. The tradeoff for these distinct files is the price that must be paid in terms of process creation on each network connection. $! System databases $ DEFINE /SYSTEM /EXEC LMF$LICENSE SYS$SYSTEM:LMF$LICENSE.LDB $ DEFINE /SYSTEM /EXEC NETNODE_REMOTE SYS$SYSTEM:NETNODE_REMOTE.DAT $ DEFINE /SYSTEM /EXEC NETPROXY SYS$SYSTEM:NETPROXY.DAT $ DEFINE /SYSTEM /EXEC NETUAF SYS$SYSTEM:NETUAF.DAT $ DEFINE /SYSTEM /EXEC RIGHTSLIST SYS$SYSTEM:RIGHTSLIST.DAT $ DEFINE /SYSTEM /EXEC SYSUAF SYS$SYSTEM:SYSUAF.DAT $ DEFINE /SYSTEM /EXEC VMSMAIL SYS$SYSTEM:VMSMAIL_PROFILE.DAT If these aren't defined, and a user attempts operations on them, new ones can be created by that user. These definitions prevent this. Note file protections for these files in Section 2.7, File Protections. Other system-wide logical symbols (such as LOCAL$WRAP) would also be defined in this file. 2.5 System Passwords VMS systems can have what is called a "system password". This is a password that must be typed BEFORE the host prompts you for login information. So when you initially connect to a system with a "system password", you don't get any prompting on the screen. Once you have typed in the password, the normal prompt message appears. The system password will appear or not depending on the value of the sysgen parameter TTY_DEFCHAR2. A value of %X80000 (i.e. Hex) enables system password. This parameter is not dynamic. The SYSGEN parameter TTY_DEFCHAR2 (bit represented by %X80000) enables system password by default for all terminals (including LAT, X.25 and telnet terminals). The default value for TTY_DEFCHAR2 is 4098 (decimal): $ RUN SYS$SYSTEM:SYSGEN SYSGEN> USE DEFAULT SYSGEN> SHO TTY_DEFCHAR2 Parameter Name Current Default Min. Max. Unit Dynamic -------------- ------- ------- ------ ------ ---- ------- TTY_DEFCHAR2 4098 4098 0 -1 Bit-Encode The correct value can be set by modifying SYS$SYSTEM:MODPARAMS.DAT, and AUTOGENing the system. The required value in MODPARAMS.DAT is set by adding the following lines (amongst other values): TTY_DEFCHAR2 = %X80000 + %X1000 + %X2 ! = 528386 ! %X80000 (bit 19) TT2$M_SYSPWD System password ! %X1000 (bit 12) TT2$M_EDITING Cmd line editing ! %X2 (bit 1) TT2$M_AUTOBAUD Autobaud The actual system password can be set either by DCL or by AUTHORIZE. $ SET PASSWORD /SYSTEM or else by $ RUN SYS$SYSTEM:AUTHORIZE UAF> MODIFY /SYSTEM_PASSWORD={password} Terminals can be set /NOSYSPWD /PERM or /SYSPWD. See Section 2.1.1 SYSTARTUP_V5.COM for an example. 2.6 The UAF File This is an extremely useful file for tuning security on an OpenVMS machine. The UAF file (and associated files) allow you to control access to the system and allocate resources to users. For the purposes of this paper, there are several fields worth considering. Specifically, the ones that can be used include (but are not restricted to) access control fields, password control fields and the rights list. On the particular machine used in the preparation of this paper, there are several accounts that are used for specific purposes, and should be used only within specific time frames. For instance, consider an account (the "USER1" account for the purposes of this example) which should only be used interactively during the hours of 8am to 7pm on primary days (Monday to Friday), but can run batch jobs at any time on any day. All other access is to be denied. This is achieved by the following commands: $ RUN SYS$SYSTEM:AUTHORIZE UAF> MODIFY USER1 /NONETWORK /NODIALUP - /LOCAL=(PRIMARY:8-18) /REMOTE=(PRIMARY:8-18) This results in an access control matrix like the one below. Primary days: Mon Tue Wed Thu Fri Secondary days: Sat Sun Primary 000000000011111111112222 Secondary 00000000001111111111222 Day Hours 012345678901234567890123 Day Hours 012345678901234567890123 Network: ----- No access ------ ----- No access ------ Batch: ##### Full access ###### ##### Full access###### Local: --------###########----- ----- No access ------ Dialup: ----- No access ------ ----- No access ------ Remote: --------###########----- ----- No access ------ Full access can be restored using: $ RUN SYS$SYSTEM:AUTHORIZE UAF> MODIFY USER1 /ACCESS=(PRIMARY:0-24,SECONDARY:0-24) Passwords are historically a weak point in computer systems. A weak password on a single account leaves the entire system vulnerable to attack. (See Appendix 2, SERT Advisory SA-93.04, Guidelines For Developing A Sensible Password Policy.) You must therefore ensure that all accounts have a minimum password length of 8 characters, and that they expire at regular intervals. In addition, privileged accounts should have password lengths greater than that, and passwords should be set using the MODIFY {accountname} /GENERATE_PASSWORD command. The other important use of the AUTHORIZE utility is creating rights list identifiers and using these in conjunction with ACLs to control access to files and devices at individual levels. For instance, on the machine used while preparing this paper, there is a particular device and a directory that should only ever be accessed by a small group of people. This device is used for a research project, and the results are kept in the directory. The entire group of people involved with the experiment needed to read the results (kept in the DISKE:[EXPERIMENT1] directory), whereas only a few people needed write access to this directory. Furthermore, because they were all in the same project team, they were all allocated the same group number. Finally, there was a restricted number of people in this group who were authorised to access the device used in the experiment in question. The first step in controlling this is to create various rights list identifiers, and granting them to people who should access them. The rights list identifiers are created as follows: $ RUN SYS$SYSTEM:AUTHORIZE UAF> ADD /IDENTIFIER EXP1_READ UAF> ADD /IDENTIFIER EXP1_WRITE UAF> ADD /IDENTIFIER EXP1_CONTROL UAF> EXIT Users 1..10 are allowed read access to the results; users 5, 6 and 7 are allowed write access and users 6 and 7 are allowed to control the transducer. $ RUN SYS$SYSTEM:AUTHORIZE UAF> GRANT /IDENTIFIER EXP1_READ USER1 UAF> GRANT /IDENTIFIER EXP1_READ USER2 UAF> GRANT /IDENTIFIER EXP1_READ USER3 UAF> GRANT /IDENTIFIER EXP1_READ USER4 UAF> GRANT /IDENTIFIER EXP1_READ USER8 UAF> GRANT /IDENTIFIER EXP1_READ USER9 UAF> GRANT /IDENTIFIER EXP1_READ USER10 UAF> GRANT /IDENTIFIER EXP1_WRITE USER5 UAF> GRANT /IDENTIFIER EXP1_WRITE USER6 UAF> GRANT /IDENTIFIER EXP1_WRITE USER7 UAF> GRANT /IDENTIFIER EXP1_CONTROL USER6 UAF> GRANT /IDENTIFIER EXP1_CONTROL USER7 UAF> EXIT $ ACLs and protection are then set on the device and directory as set out in Section 2.8, ACLs. Finally, great care has been taken in the allocation of privileges to individual user accounts. In particular, the default privileges must be kept to the minimum required. 2.7 File Protections File protection is an important aspect in preventative security. Checks should be periodically carried out for world-writeable files and directories, and appropriate action taken. In addition, various sensitive files should be confirmed as having the following protection. :[000000]000000.DIR (S:RWE,O:RWE,G:RE,W:E) :[000000]INDEXF.SYS (S:RWE,O:RWE,G:RE,W) * This prevents unauthorised users from finding directory and file names. SYS$SYSTEM:AUTHORIZE.EXE (S:RWE,O:RWE,G:RWE,W) SYS$SYSTEM:NCP.EXE (S:RWE,O:RWE,G:RWE,W) * This ensures that unauthorised users cannot change the NCP and authorisation databases through the use of these programs. Note that merely protecting these programs does not prevent modification of the data files - it is imperative that the data files themselves are protected. SYS$SYSTEM:NETCIRC.DAT (S:RWE,O:RWE,G:RWE,W) SYS$SYSTEM:NETCONF.DAT (S:RWE,O:RWE,G:RWE,W) SYS$SYSTEM:NETLINE.DAT (S:RWE,O:RWE,G:RWE,W) SYS$SYSTEM:NETLOGING.DAT (S:RWE,O:RWE,G:RWE,W) SYS$SYSTEM:NETNODE_LOCAL.DAT (S:RWE,O:RWE,G:RWE,W) SYS$SYSTEM:NETNODE_REMOTE.DAT (S:RWE,O:RWE,G:RWE,W) SYS$SYSTEM:NETOBJECT.DAT (S:RWE,O:RWE,G:RWE,W) SYS$SYSTEM:NETPROXY.DAT (S:RWE,O:RWE,G:RWE,W) SYS$SYSTEM:NETUAF.DAT (S:RWE,O:RWE,G:RWE,W) SYS$SYSTEM:NETX25.DAT (S:RWE,O:RWE,G:RWE,W) SYS$SYSTEM:NETX29.DAT (S:RWE,O:RWE,G:RWE,W) * This ensures that unauthorised users cannot change information in these databases, nor gain information about other users or system configuration from these files. SYS$SYSTEM:RIGHTSLIST.DAT (S:RWE,O:RWE,G:RE,W:RE) SYS$SYSTEM:SYSUAF.DAT (S:RWE,O:RWE,G:RWE,W) ACL=(NETWORK,ACCESS=EXECUTE) SYS$SYSTEM:VMSMAIL.DAT (S:RWE,O:RWE,G:RWE,W) SYS$SYSTEM:VMSMAIL_PROFILE.DATA (S:RWE,O:RWE,G:RWE,W) * This ensures that unauthorised users cannot change information in these databases, nor gain information about other users from these files. For more details on File Protections, see Managing Security in a Multi-Vendor Network by Ron Tencati, and also the Guide to VAX/VMS System Security manual. 2.8 ACLs This section, is a continuation of the example supplied in Section 2.6, The UAF File, about access control using rights list identifiers. In a particular experiment, experimental results are being kept in the DISKE:[EXPERIMENT1] directory. The results are obtained using a transducer controlled on device RCD0:. Various rights list identifiers to read results (EXP1_READ), write a file to the results directory (EXP1_WRITE) and control the transducer (EXP1_CONTROL) have been created. These rights identifiers are used in the the creation of access control lists to enforce these access control principles. The transducer is the first object so modified: $ SET ACL /OBJECT=DEVICE /ACL=( - (IDENTIFIER=SYSTEM,ACCESS=READ+WRITE+EXECUTE+DELETE+CONTROL), - (IDENTIFIER=EXP1_CONTROL,ACCESS=READ+WRITE+DELETE+CONTROL), - (IDENTIFIER=[*,*],ACCESS=NONE)) RCD0: $ SHOW DEVICE RCD0: /FULL : {Device details on NODE1$RCD0: deleted} : device, error logging is enabled. Error count 0 Operations completed 26 Owner process "" Owner UIC [0,0] Owner process ID 00000000 Dev Prot S:RWED,O:RWED,G:RWED,W:RWED Reference count 0 Default buffer size 2048 Density unknown Format {deleted} Volume status: {deleted} Device access control list: (IDENTIFIER=[SYSTEM],ACCESS=READ+WRITE+EXECUTE+DELETE+CONTROL) (IDENTIFIER=EXP1_CONTROL,ACCESS=READ+WRITE+EXECUTE+DELETE+CONTROL) (IDENTIFIER=[*,*],ACCESS=NONE) On the machine used for preparing this paper, the nature of the device prevented us from changing the protection using the SET PROTECTION/DEVICE command. However, the ACL is sufficient to control access to this device. The next step is to protect the directory (and files under it). An ACL is applied to the directory file usinfg the commands on the next page. $ SET ACL /OBJECT=FILE /ACL=( - (IDENTIFIER=EXP1_WRITE,ACCESS=READ+WRITE+EXECUTE+DELETE+CONTROL), - (IDENTIFIER=EXP1_READ, ACCESS=READ+EXECUTE), - (IDENTIFIER=SYSTEM, ACCESS=READ+EXECUTE), - (IDENTIFIER=[*,*], ACCESS=NONE)) DISKE:[000000]EXPERIMENT1.DIR $ $ SET PROTECTION DISKE:[000000]EXPERIMENT1.DIR /PROTECTION=(S,O,G,W) $ $ DIR DISKE:[000000]EXPERIMENT1.DIR /SECURITY Directory DISKE:[000000] EXPERIMENT1.DIR;1 4 17-JUN-1992 11:19:27.01 [SYSTEM] (,,,) (IDENTIFIER=EXP1_WRITE,ACCESS=READ+WRITE+EXECUTE+DELETE+CONTROL) (IDENTIFIER=EXP1_READ,ACCESS=READ+EXECUTE) (IDENTIFIER=[SYSTEM],ACCESS=READ+EXECUTE) (IDENTIFIER=[*,*],ACCESS=NONE) Total of 1 file, 4 blocks. This means that only people who specifically possess the EXP1_WRITE rights list identifier can write to this directory. Users who possess the EXP1_READ identifier can read the contents of the directory as can the SYSTEM account (but not system privileged accounts or system UIC group members). All other access is denied. Note that action is taken on the first match of the ACL. So, for example, if the SYSTEM account is being used to access data in DISKE:[EXPERIMENT1], and the system account has the EXP1_READ right, then SYSTEM can read the data by virtue of this right as opposed to being the system account. The reason for this is that the EXP1_READ identifier occurs before [SYSTEM] in the ACL. Any directories created in this directory after the creation of this ACL will inherit this ACL. 2.9 SYSGEN Parameters There are various SYSGEN parameters that must be considered and/or changed during configuration. Many of these are related to system performance and are not within the scope of this paper. Parameters that must be considered from a security point of view are listed below, with extracts from the SYSGEN HELP facility on their use. (See SYSGEN> HELP PARAMETERS for more details.) TTY_DEFCHAR2: Bit 19 (TT2$M_SYSPWD) is set to allow the use of system passwords. The password was set using the AUTHORIZE utility (see Section 2.5, System Passwords), and the console is modified such that the password is not required when logging on from that source (using SET TERMINAL OPA0: /PERMANENT /NOSYSPASSWORD). (See Section 2.1.1, SYSTARTUP_V5.COM.) All other terminals must enter the system password before the login prompt is issued. This parameter (TTY_DEFCHAR2). amongst others, can be set in SYS$SYSTEM:MODPARAMS.DAT with a single line: TTY_DEFCHAR2 = %X80000 + %X1000 + %X2 ! = 528386 ! %X80000 (bit 19) TT2$M_SYSPWD System password ! %X1000 (bit 12) TT2$M_EDITING Cmd line editing ! %X2 (bit 1) TT2$M_AUTOBAUD Autobaud LGI_PWD_TMO: Period of time, in seconds, a user has to correctly enter the system password on a terminal on which the system password is in effect. LGI_BRK_TMO: Specifies the number of seconds that a user, terminal, or node is permitted to attempt a login before the system assumes that a breakin attempt is occurring and evasive action is required. LGI_BRK_LIM: Specifies the number of failures that may occur at login time before the system will take action against a possible breakin. LGI_RETRY_TMO: Specifies the number of seconds allowed between login retry attempts after a login failure. LGI_RETRY_LIM: Specifies the number of retry attempts allowed for users attempting to login over dialup lines. LGI_HID_TIM: Specifies the number of seconds that evasive action will persist following the detection of a possible breakin attempt. The evasive action consists of refusing to allow any logins during this period, regardless of whether a valid user name and password are specified. LGI_BRK_DISUSER: When set, turns on the DISUSER flag in the UAF record when an attempted breakin is detected, thus permanently locking out that account. LGI_BRK_TERM: Causes the terminal name to be part of the association string for the terminal mode of breakin detection. Note that if parameters are changed using SYSGEN, modify both the CURRENT image and the ACTIVE, running system. Leave DEFAULT as it is. 2.10 Tailoring UCX The machine being configured required only incoming telnet access, and outgoing telnet and ftp. SMTP is handled by a dedicated mail package (MX). Other services like SNMP, NFS and Berkeley "r" commands are not required (or, in fact, desirable). Services not required are shutdown thus: $! -- Shutdown what we don't need $! $ @SYS$MANAGER:RPC$UCX_SHUTDOWN.COM $ @SYS$MANAGER:UCX$LPD_SHUTDOWN.COM $ @SYS$MANAGER:UCX$NFS_SHUTDOWN.COM $ @SYS$MANAGER:UCX$SMTP_SHUTDOWN.COM $ @SYS$MANAGER:UCX$SNMP_SHUTDOWN.COM $! $! -- Disable incoming connections on other services $! $ UCX DISABLE SERVICE FTP $ UCX DISABLE SERVICE REXEC $ UCX DISABLE SERVICE RLOGIN $ UCX DISABLE SERVICE RSH In addition, the relevant UCX accounts are disabled in the User Authorization File (using UAF> MODIFY /flag=DisUser): UCX$FTP, UCX$NFS, UCX$REXEC, UCX$RSH, UCX$SNMP, UCX_LPD, UCX_SMTP. Telnet (interactive) access should be monitored using a wrapper (as discussed in Section 4.1, Wrappers). 2.11 Proxies Proxies should not be allowed if they are not required! If a net proxy is required for file transfer, the proxy must be created on the remote machine, and the required command issued on the local machine. The theory here is that the local machine is less likely to be compromised than an outside machine, and the use of proxies will reduce the instances of access information being transmitted over a network connection. Only allow proxy access to a non-privileged account on the target system. System Mechanisms For Configuring The Machine To Log Activity There are several facilities available to the system administrator to achieve effective logging. Specifically these are accounting and auditing. There is also scope for development of local tools. In this section, I will outline the use of the standard facilities, while homegrown mechanisms will be considered in the next section. Firstly, it will be useful to have a brief look at accounting and auditing. System accounting is a facility for recording information about the use of the machine from a normal system accounting perspective, whereas the system audit logger records similar information, but from a system security perspective. Both of these can be used to construct audit trails of activity. Information from the system audit logger can be gleaned not only from the audit journal, but also from the operator log, as the auditor also sends it's messages to OPCOM. Consider, for example, a situation in which a user (USER1) has made a modification to USER2's entry in the User Authorization File. The audit logger returns the following information: Security alarm (SECURITY) and security audit (SECURITY) on NODE1, system id: 1072 / System UAF record modification Event time: 27-JUL-1993 12:15:17.47 PID: 0000005F Username: USER1 Image name: NODE1$DKA0:[SYS0.SYSCOMMON.][SYSEXE]AUTHORIZE.EXE Object name: SYS$COMMON:[SYSEXE]SYSUAF.DAT;1 Object type: file User record modified: USER2 Fields modified: FLAGS,PRIVILEGES The accounting facility contains this: AUTHORIZE Image Termination --------------------------- Username: USER1 UIC: [STAFF,USER1] Account: STAFF Finish time: 27-JUL-1993 12:15:27.79 Process ID: 0000005F Start time: 27-JUL-1993 12:14:51.23 Owner ID: Elapsed time: 0 00:00:36.56 Terminal name: RTA1: Processor time: 0 00:00:00.22 Remote node addr: 1038 Priority: 4 Remote node name: NODE2 Privilege <31-00>: 10148001 Remote ID: USER2 Privilege <63-32>: 00000040 Queue entry: Final status code: 00000001 Queue name: Job name: Final status text: %SYSTEM-S-NORMAL, normal successful completion Page faults: 238 Direct IO: 32 Page fault reads: 9 Buffered IO: 58 Peak working set: 631 Volumes mounted: 0 Peak page file: 1166 Images executed: 244 Image name: NODE1$DKA0:[SYS0.SYSCOMMON.][SYSEXE]AUTHORIZE.EXE Both facilities tell us that USER1 ran the AUTHORIZE utility successfully under PID 5F at 12:15 pm on 27-Jul- 1993. From the accounting, we can see at a glance where USER1 logged in from. The audit logger tells us exactly what USER1 did whilst running this utility. Consider another example, in which a computer cracker has logged in from an X.25 network address in an attempt to maintain anonymity. The audit server has recorded the following information in the operator log: %%%%%%%%%%% OPCOM 27-Jul-1993 19:38:23.60 %%%%%%%%%%% Message from user AUDIT$SERVER on NODE1 Security alarm (SECURITY) and security audit (SECURITY) on NODE1, system id: 1038 Auditable event: Dialup interactive login Event time: 27-Jul-1993 19:38:23.59 PID: 20205316 Username: USER1 Terminal name: _VTA1514 ({X.25 address deleted}) The system accounting record from the same user logging out returns the following information: LOGINOUT Image Termination -------------------------- Username: USER1 UIC: [STAFF,USER1] Account: STAFF Finish time: 27-Jul-1993 03:36:17.69 Process ID: 20205316 Start time: 27-Jul-1993 19:38:07.19 Owner ID: Elapsed time: 0 07:58:10.50 Terminal name: VTA1514 Processor time: 0 00:00:46.14 Remote node addr: Priority: 4 Remote node name: Privilege <31-00>: 00108000 Remote ID: Privilege <63-32>: 00000000 Queue entry: Final status code: 00000001 Queue name: Job name: Final status text: %SYSTEM-S-NORMAL, normal successful completion Page faults: 4716 Direct IO: 20927 Page fault reads: 208 Buffered IO: 85056 Peak working set: 970 Volumes mounted: 0 Peak page file: 4813 Images executed: 28 Image name: NODE1$DKA0:[SYS0.SYSCOMMON.][SYSEXE]LOGINOUT.EXE The two records act as a useful cross check for each other. The audit logger shows the X.25 address from which the user logged in from (which is not available in this accounting record). The accounting facility shows the length of time that the user was on the system. When this information is collated with the network accounting information, then the cost of the connection can be calculated. Furthermore the accounting records and audit records can be examined to aid in determining the extent of the damage caused by the attacker. 3.1 Accounting Confirm that required system accounting is enabled thus: $ SET ACCOUNTING /ENABLE[=(Keyword...)] The command above enables logging of all activities on the system in the accounting file. Accounting can be enabled to log the following activities. PROCESS any process termination IMAGE image execution INTERACTIVE interactive job termination LOGIN_FAILURE login failures SUBPROCESS subprocess termination DETACHED detached job termination BATCH batch job termination NETWORK network job termination PRINT all print jobs MESSAGE user messages Each day, a new accounting file should be created in order to keep the accounting files of a manageable size, using the command - $ SET ACCOUNTING /NEW_FILE 3.2 Auditing The auditor can be configured to log the following events: ACL Event requested by an Access Control List Item AUTHORIZATION Modification of the system user authorization file BREAKIN Occurrence of a breakin attempt (from various sources) FILE_ACCESS File or global section access (by various methods) INSTALL Occurrence of any INSTALL operation LOGFAILURE Occurrence of a login failure (from various sources) LOGIN A login attempt (from various sources) LOGOUT Occurrence of a logout MOUNT Issuance of a mount or dismount request This is done using SET AUDIT /ENABLE=(keyword[,...]). The /ALARM qualifier is also used to raise an alarm to all terminals enabled as security operators. You can examine the configuration of your system audit server using SHOW AUDIT /ALL. The categories that should be carefully considered are the auditing server characteristics, the alarm failure mode, and the enabled security alarms. Note that within the auditing server characteristics, the default final resource action is to crash the system if the system runs out of virtual memory. This means that if the disk containing the audit journal log is full, the system will crash, thus exposing the system to denial of service attacks. When configuring the audit server, you should carefully consider the final resource action parameter. It can be set using the SET AUDIT command. $ SET AUDIT /SERVER=FINAL_ACTION=action (where action can be one of CRASH, IGNORE_NEW or PURGE_OLD) As with system accounting, a new audit journal should be created each day: $ SET AUDIT /SERVER=NEW_LOG 3.3 FAL and Poor Man's Routing In order to properly explain the step taken in this phase, it is necessary to understand what Poor Man's Routing is, and how it is linked with the File Access Listener (FAL) object and the logical FAL$LOG. The FAL object (File Access Listener) is the DECnet object that allows a remote user to access files on your node. It can be used to browse your node, or perform file transfers. For legitimate users, this is extremely useful - unfortunately, people with malintent also find it useful if your system is not protected. In the context of DECnet networking operations (and specifically FAL), "Poor Man's Routing (PMR) refers to the technique of supplying an explicit path to the required target, rather than letting assigned DECnet routers pick the most optimal path" [Tencati]. When PMR is used, a process is created on each node in the path to forward the connection to the next node in the path. Each of these nodes (including the destination node) only sees the connection from it's path predecessor. It is therefore very difficult to ascertain from the destination node where the connection originated from. The legitimate use of this is in cases where the source node may not know anything about the remote note. Unfortunately, people with malintent can use the properties described above to create a convoluted path to the node they wish to attack (possibly via several timezones and countries) to hide themselves effectively. PMR can also be used to defeat the hiding of DECnet subnets. There is a parameter in the NCP database called the maximum area (see NCP> HELP SET EXECUTOR MAXIMUM AREA). This parameter specifies the largest area number known to an executor's routing layer. If used carefully, this parameter can be used to hide subnets. PMR can be used to circumvent this technique if the attacker has appropriate information about your network design. (The lesson here is to never trust security through obscurity - always rely on robust, proactive methods rather than ignorance.) Ron Tencati's Managing Security in a Multi- Vendor Network gives a good explanation of PMR, and the use of Area Routing. You can configure FAL by use of the logical symbol FAL$LOG. In the machine used in the preparation of this paper, this logical was configured to do two things: * refuse connections made by PMR * supply audit trail information in NETSERVER.LOG files in the case of successful FAL connections. The logical name FAL$LOG translates to a string of the form xx_yy where: * xx is a hexadecimal number representing a longword string value * yy is a hexadecimal number specifying how many bytes of each DAP message are to be displayed in the log file (SYS$OUTPUT:). The hexadecimal flags are: 0001 - log filename/function requests 0002 - log throughput statistics 0004 - log individual DAP messages 0008 - log DAP message packet AST requests (logged at AST level) 0010 - log DAP message packet QIO requests 0020 - reserved 0040 - disable DAP message blocking 0080 - disable DAP CRC error checking In SYS$MANAGER:SYLOGICALS.COM, FAL$LOG should be defined to be the character string "03/DISABLE=8" (See Section 2.4, System Logicals And Logical Definitions). By setting this logical to this value, the following is achieved: * PMR is disabled ("/DISABLE=8") * filename/function requests and throughput statistics are logged (the setting "03" being the addition of "01" and "02" Consider an example where NODE1::USER1 is executing a directory on NODE2::USER2's home directory. In the file NETSERVER.LOG in USER2's directory, we would see the following results. With no definition for FAL$LOG: -------------------------------------------------------- Connect request received at 28-JUL-1993 15:36:45.78 from remote process NODE1::"0=USER1" for object "SYS$COMMON:[SYSEXE]FAL.EXE" -------------------------------------------------------- With FAL$LOG defined to be "03/DISABLE=8", extra information is appended: -------------------------------------------------------- Connect request received at 28-JUL-1993 15:55:40.28 from remote process NODE1::"0=USER1" for object "SYS$COMMON:[SYSEXE]FAL.EXE" -------------------------------------------------------- ======================================================== FAL V5.1-D3 started execution on 28-JUL-1993 15:55:41.12 with SYS$NET = NODE1::"0=USER1" and with FAL$LOG = 03 Logical link was established on 28-JUL-1993 15:55:41.13 Requested file access operation: Directory List Specified file: DISKE:[USER2]L*.*;* Resultant file: DISKE:[USER2]LOGIN.COM;3 Resultant file: DISKE:[USER2]LWK_PERSONAL.LINKBASE;1 Logical link was terminated on 28-JUL-1993 15:55:41.18 Total connect time for logical link was 0 00:00:00.05 Total CPU time used for connection was 0 00:00:00.02 File Access Statistics for RECV-Side XMIT-Side Composite -------------------------- --------- --------- -------- # DAP Message QIO Calls 2 2 4 # DAP Messages Exchanged 2 14 16 # User Records/Blocks 0 0 0 NETSERVER.LOG (continued) # Bytes of User Data 0 0 0 # Bytes in DAP Layer 49 310 359 User Data Throughput (bps) 0 0 0 DAP Layer Throughput (bps) 7840 49600 57440 Average Record/Block Size 0 0 0 % User Data in DAP Layer 0.0% 0.0% 0.0% -------------------------- --------- --------- --------- Negotiated DAP buffer size = 1060 bytes Buffered I/O count during connection = 13 Direct I/O count during connection = 0 Peak working set size for process = 470 pages Successful Start Transaction Branch = 0 Start Transaction Branch loops = 0 FAL terminated execution on 28-JUL-1993 15:55:41.21 ======================================================== Using Homegrown Or Publicly Available Software 4.1 Wrappers A "wrapper" is a piece of software that monitors an attempt to use a service, and based on the details about the source of the attempt (such as remote host and user, time, and connection type), determine whether to allow the use of the service or not. This is the feature that a wrapper has available to it over and above standard system logging software: the use of the wrapper gives the system manager freedom to make decisions whether to allow the use of the machine from a remote site in addition to simply logging that use. Wrappers should be constructed for the NML and FAL objects, and also for interactive logins. Section 2.1.2, SYLOGIN.COM and Section 2.3.2, Objects gives the details on how to install these wrappers. Because the NML and FAL wrappers need to handle DECnet connections only, they are more simple than the interactive login wrapper. The DECnet object wrappers evaluate the connection by comparing the remote node and user combination against a set of rules. The set of rules is described in two files: AllowFile which describes which combinations may make the connection, and DenyFile which describes which combinations may not make the connection. Wildcards are allowed. The general algorithm is: Main () { RemoteUser = f$trnlnm("SYS$REM_ID") RemoteNode = f$trnlnm("SYS$REM_NODE") ConnectionOkay = CheckRules(RemoteNode, RemoteUser) if (ConnectionOkay = Allow) /* ConnectionOkay = Allow|Deny */ then write successful connection record to wrapper log request/to=(network,security) "" run SYS$SYSTEM:FAL.EXE else write failed connection record to wrapper log request/to=(network,security) "" logout endif } end Main CheckRules (RemoteNode, RemoteUser) { if ((result = CheckCombination(RemoteNode, RemoteUser)) != Unknown) then return result if ((result = CheckCombination(RemoteNode, "*")) != Unknown) then return result if ((result = CheckCombination("*", "*")) != Unknown) then return result return Deny } end CheckRules CheckCombination (RemoteNode, RemoteUser) { Search AllowFile for RemoteNode::RemoteUser if found then return Allow Search DenyFile for RemoteNode::RemoteUser if found then return Deny return Unknown } end CheckCombination The search commands used above should be such that a wildcard search matches the literal "*" in a file, not any string (in a similar manner to the VMS "SEARCH" command). Hence the wildcard value of "*" is placed in the file by the system manager. The general philosophy that should be adopted is to use a blanket denial (a single line of "*::*" in the deny file) with specific allowed node::user combinations in the allow file. The interactive connection wrapper is similar, with only a slightly more complicated top level algorithm: Main () { | Establish RemoteUser | Establish RemoteNode ConnectionOkay = CheckRules(RemoteNode, RemoteUser) if (ConnectionOkay = Allow) /* ConnectionOkay = Allow|Deny */ then write successful connection record to wrapper log request/to=(network,security) "" | exit(Success) else write failed connection record to wrapper log request/to=(network,security) "" | exit(Failure) endif } end Main The main problem here is to establish remote user and node identities. Interactive access may take place using DECnet, LAT, TCP/IP and so on. System values used to find this information are: * F$TRNLNM("SYS$REM_ID") * F$TRNLNM("SYS$REM_NODE") * F$GETDVI("SYS$COMMAND","TT_ACCPORNAM") * the DECnet database * the local terminal type of the connection * information from F$TRNLNM("DECW$DISPLAY") Connections are then evaluated not only on remote node and user (if provided by the protocol), but also by the protocol used for the connection and local characteristics (such as the time). It is important to note that any reading from AllowFile or DenyFile, and writing to the wrapper log should be carried out by installed, protected images, and that the command file(s) and executable(s) used are writeable only by system privileged accounts. This prevents modification of behaviour and recorded results by potential attackers. Example code and configuration files appear in Appendix 3, Wrapper Example. 4.2 Single Use PINs A Personal Identification Number (PIN) is simply the numerical equivalent of a text-based password. Unlike a normal password system, though, a single use PIN relies on algorithmic knowledge rather than static value knowledge. The system works thus: when a user logs in, system and user passwords must be supplied as described in previous sections. A numerical challenge is then issued. The user must supply the correct reply to this challenge, or the login will be denied. The correct reply is some permutation of the original challenge. The challenge must be randomly generated, so that every time the user logs in, a different numerical challenge is supplied, requiring a unique reply - only the algorithm used to deduce the reply from the challenge is static. Furthermore, this algorithm is different for each user. The software which issues the challenge and receives the reply must be robust, so that an attacker cannot simply "crash" the software and hence bypass this mechanism. Such systems are available commercially. A smart-card is usually supplied with such systems. The user keys the challenge supplied by the host into the smartcard using the keypad. The smartcard then displays the response, and the user enters this as the reply to the host. A cheaper alternative is to write such a system locally, fulfilling all of these criteria. A usage policy must be in place to effectively manage this system. 4.3 Terminal Monitors Terminal monitors are useful utilities for providing help to users who may be working remotely, or may not be reachable by telephone and require some type of help in real-time (i.e. electronic mail would not suffice). Where such utilities are available on the system, they must be adequately protected to ensure that unauthorised users can neither use them nor copy them. Care must be taken to ensure that explicit permission is sought by the legitimate users concerned or a relevant authority when such a utility is used. Similar principles apply when using system software for capturing a process's recall buffer in order to examine the commands issued by that process. Monitoring The Use Of The Machine It is essential to carry out monitoring on any machine in order to evaluate the health of the system. In addition to checks that should be carried out on a regular basis, steps should be taken to be allow for investigation of unusual security related events as soon as possible. 5.1 The SHOW INTRUSION Command Use the command SHOW INTRUSION regularly. This command displays the contents of the break-in database, providing a quick technique for checking if there have been attempts to break into your system in the immediate past. When using the SHOW INTRUSION command, you must first get some idea if the host has detected any potential breakins: $ SET PROC/PRIV=(CMKRNL,SYSPRV) $ SHOW INTRUSION Intrusion Type Count Expiration Source NETWORK SUSPECT 6 16:32:23.03 NODE2::USER2 TERM_USER SUSPECT 3 16:18:14.16 USER1 In this case, there are two suspect incidents. The records below show that the first was an attempt by USER2 on node NODE2 to login as USER1 on the local host (NODE1) via DECnet. The second is an attempt to login as USER1 on the local host using telnet from NODE3 (which in this case was actually the localhost - 127.0.0.1). The accounting records show the following: LOGIN FAILURE ------------- Username: USER1 UIC: [SYSTEM] Account: Finish time: 3-AUG-1993 16:02:28.80 Process ID: 2080D073 Start time: 3-AUG-1993 16:02:19.59 Owner ID: Elapsed time: 0 00:00:09.21 Terminal name: RTA3: Processor time: 0 00:00:00.23 Remote node addr: 1038 Priority: 4 Remote node name: NODE2 Privilege <31-00>: 0010C000 Remote ID: USER2 Privilege <63-32>: 00000000 Queue entry: Final status code: 10D380FC Queue name: Job name: Final status text: %LOGIN-F-INVPWD, invalid password Page faults: 234 Direct IO: 24 Page fault reads: 5 Buffered IO: 40 Peak working set: 287 Volumes mounted: 0 Peak page file: 1474 Images executed: 1 LOGIN FAILURE ------------- Username: USER1 UIC: [SYSTEM] Account: Finish time: 3-AUG-1993 16:03:20.85 Process ID: 2080D878 Start time: 3-AUG-1993 16:03:11.77 Owner ID: Elapsed time: 0 00:00:09.08 Terminal name: VTA3959 Processor time: 0 00:00:00.21 Remote node addr: Priority 4 Remote node name: Privilege <31-00>: FFFFFFFF Remote ID: Privilege <63-32>: FFFFFFFF Queue entry: Final status code: 10D380FC Queue name: Job name: Final status text: %LOGIN-F-INVPWD, invalid password Page faults: 235 Direct IO: 18 Page fault reads: 5 Buffered IO: 41 Peak working set: 284 Volumes mounted: 0 Peak page file: 1474 Images executed: 1 The audit records show the following: Security alarm (SECURITY) and security audit (SECURITY) on NODE1, system id: 1072 / Remote interactive login failure Event time: 3-AUG-1993 16:02:19.59 PID: 00000D33 Username: USER1 Terminal name: _RTA1: Remote nodename: NODE2 Remote node id: 1184 Remote username: USER2 Status: %LOGIN-F-INVPWD, invalid password Security alarm (SECURITY) and security audit (SECURITY) on NODE1, system id: 1072 / Remote interactive login failure Event time: 3-AUG-1993 16:03:11.77 PID: 00000CB4 Username: USER1 Terminal name: _TNA7: Remote nodename: 127.0. Remote node id: 2130706433 Remote username: TELNET_7F000001 Status: %LOGIN-F-INVPWD, invalid password Note that the remote nodename is always truncated to six characters. The remote node id is a numerical representation of the remote address. Notice from the failed telnet login above that the remote username is given as TELNET_7F000001. This equates to the IP address 127.0.0.1 thus: 7 * 16 + F = 127 0 * 16 + 0 = 0 0 * 16 + 0 = 0 0 * 16 + 1 = 1 Hence if this attempt had come from the Network Information Centre (nic.ddn.mil, Internet address 192.112.36.5), the remote username would have appeared TELNET_C0702405. 5.2 Daily Activities A batch file must be written in order to carry out regular activities on a daily basis. Amongst these activities should be various checks on log files. These are listed below. $ SEARCH/OUTPUT=BREAKIN_CHECK.TMP SYS$MANAGER:OPERATOR.LOG;-1 - "Security alarm"/WINDOW=(3,8) $ ANALYZE/AUDIT/BRIEF/SUMMARY/NOINTERACTIVE/OUTPUT=BREAKIN_CHECK.TMP - SYS$MANAGER:SECURITY_AUDIT.AUDIT$JOURNAL;-1 $ ACCOUNT/LOG/SORT=(TYPE,STARTED)/OUTPUT=BREAKIN_CHECK.TMP ACCOUNTNG;-1 Any one of these can be used for obtaining information about the life of the system. The amount and type of information required should be used to determine which. When any record from the output of these files reveals an incident that appears unusual, then further checking is required. The daily summary returned by any one of the commands above should only be used to indicate that this action is required - you should not rely on just the summary information returned by these commands. $ SHOW AUDIT/ALL/OUTPUT=AUDIT_CHECK.TMP Check daily that the security auditing characteristics you require are in place, and have not been changed. $ ANALYZE/ERROR/SINCE="-1 0:0:0.0"/OUTPUT=ERROR_CHECK.TMP Examine the error log daily as well. This will not necessarily alert you to a security incident, but it will draw your attention to any system problems that could potentially hinder your efforts to recover from disaster. (You could also put the "SHOW ERROR" command in your LOGIN.COM file.) $ MAIL/NOSELF/NOEDIT LOCAL$WRAP:INTERACTIVE.LOG - "@SYS$SYSROOT:[SYSMGR.MAIL]DAILY_BATCH.DIS" - /SUBJECT:"Logged interactive logins" Wrappers were discussed in Section 4.1, Wrappers. As part of your daily checking, you should mail to yourself, and other relevant users, the output from these wrappers on a daily basis. The example above mentions only output from the interactive wrapper log - the implication is that all logs should be checked. 5.3 Having a Live Console Don't rely simply on on-line sinks (such as OPERATOR.LOG) for your security oriented output. In the event of a system compromise, it is quite likely that an attacker will attempt to delete or modify information in system files. A good idea is to enable a security operator's terminal. In addition to (or even instead of) the normal system console (usually OPA0:), you should consider using a security operator's terminal one that provides hardcopy output and is located in a secure location. (A word of caution: even an unsuccessful attack could seriously disrupt your system if the hardcopy printer runs out of paper.) Using the example from the Guide to VMS System Security manual, consider an example where such a terminal (TTA3:) has been designated, and security messages are to be disabled on the console. This can be achieved thus: $ DEFINE/USER SYS$COMMAND OPA0: $ REPLY/DISABLE=SECURITY $ DEFINE/USER SYS$COMMAND TTA3: $ REPLY/ENABLE=SECURITY You can, of course, enable other message classes to this terminal as well. Acknowledgements Most of the undocumented material in this paper is a mixture of my own work and other material that has been passed on to me by various colleagues at The University Of Queensland. The original idea for the wrapper was inspired by Ron Tencati, and Wietse Venema's public domain tcp_wrapper for UNIX systems. References VAX/VMS Documentation manuals: DEC TCP/IP Services for VMS System Management Guide to VAX/VMS System Security Access Control List Editor Utility Accounting Utility Audit Analysis Utility Authorize Utility Guide to Maintaining a VMS System Network Control Program Manual Networking Manual Ron Tencati, Ken Coar and E Eugene Schultz Managing Security in a Multi-Vendor Network, 1992 Appendix 1 SERT Advisory SA-93.03, Suggested Login Banner ============================================================================= SA-93:03A SERT Advisory 31-May-1993 Suggested Login Banner ----------------------------------------------------------------------------- On 7-May-1993, the Security Emergency Response Team released Advisory SA-93:03. Since then, it has been brought to our attention that the word "permission" could be considered ambiguous as Unix file systems use "permission" bits to specify if access is granted to a file or not. Further advice from the Commonwealth Director of Public Prosecutions indicates: "'Permit' does seem to include a meaning of 'allow or let happen even by accident or carelessness'." "'Authority' or 'authorisation' suggest that someone has deliberately turned their mind to an action and formally approved that action." "In light of the fact that there does appear to be a difference in meaning between words 'permit or permission' and 'authority or authorisation' and the fact that computer scientists refer to 'permission' bits on Unix files, it does appear desirable that the words 'authority' or 'authorisation' be used instead of the word 'permission'." Therefore, the Security Emergency Response Team has reissued SA-93:03 as SA-93:03A taking into account the new recommendations. The new Advisory is included below. ---------------------------------------------------------------------------- The SERT team wishes to thank Kate Lance at the University of Newcastle for bringing this problem to our attention. ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- Body of SERT Advisory SA-93:03A ---------------------------------------------------------------------------- The Security Emergency Response Team has received information that a successful prosecution of a computer cracker has taken place in New South Wales. The prosecution was aided by the use of an appropriate login banner. The following is an extract from a letter by the Australian Federal Police: "A major factor, commented upon by the magistrate, was the repeated warning message displayed at logon to your system. Your agreement to implement this feature has certainly started to pay dividends and demonstrates a certain willingness to accept [that] tertiary institutions are not fair game." A recommended login banner is: ----- Warning Message ----- ***** This service is for authorised clients only ***** **************************************************************************** * WARNING: It is a criminal offence to: * * i. Obtain access to data without authority * * (Penalty 2 years imprisonment) * * ii Damage, delete, alter or insert data without authority * * (Penalty 10 years imprisonment) * **************************************************************************** This example login banner was supplied to the Australian Federal Police by the office of the Commonwealth Director of Public Prosecutions. Legal opinion from the Commonwealth Director of Public Prosecutions indicates that this warning will assist in prosecutions of computer crackers for two reasons: "The prosecution in a criminal case must show that the computer hacker's actions are intentional. It would be extremely difficult for a hacker to argue that his actions were by accident or inadvertent when he has to go past such a warning on the system." "A hacker may admit that his actions were intentional. However, upon his sentence, he may argue that he was ignorant of the law or that he was unaware that his actions were unauthorised, thereby inducing the court to mitigate the penalty that it imposes. If the above warning is used, it will be extremely difficult for a hacker to present such arguments." SERT recommends the use of this, or similar banners on ALL systems and access points into the network (such as a modem pool and ftp access). This not only provides forewarning to any crackers that may intrude your system that certain types of activity are illegal, but also advises any legitimate users of their obligations relating to acceptable use of the computer system. The warning is deliberately general in nature as it has not yet been established what type of (if any) crime has been committed. Subsequent prosecution may be performed under Federal or State law, or handled by local institution disciplinary procedures. SERT recommends that any login banner or system initial message should not imply consent to use the computer services (E.g., words such as "greeting" or "welcome"), unless it is the express intention that any user is free to use the system, whether they are authorised or not. You may wish to include some identification information (such as the hostname) so that genuine users know that they have connected to the correct system. For example, "You have connected to node FRED at The University of Wooloomooloo" and follow this with an appropriate warning message. Examples methods for login messages are: VMS: Edit the file SYS$MANAGER:SYSTARTUP_V5.COM and include the line: $DEFINE/SYSTEM SYS$ANNOUNCE "@SYS$MANAGER:ANNOUNCE.TXT" then create the file SYS$MANAGER:ANNOUNCE.TXT with the text that you wish displayed when a user connects to your system. Note that this has implications for LAT as the default service identification is the logical SYS$ANNOUNCE (which will translate to @SYS$MANAGER:ANNOUNCE.TXT). In this case, you should edit the LAT startup procedures to explicitly define a LAT service identification. Unix: Edit the "message of the day" file, (e.g., /etc/motd) and include the text that you wish displayed when a user logs in to your system. This does not cover all ways to connect to a computer (e.g., rlogin, telnet, SET HOST, ftp), but serves as one point of warning in a number of cases. Warnings such as this are a positive step towards providing adequate notice of the obligations and responsibilities relating to the use of the computer equipment. If a person is known to have seen the warning, they cannot subsequently claim ignorance of their responsibilities. ---------------------------------------------------------------------------- The SERT team wishes to thank The University of Sydney, the University of South Australia, the Australian Federal Police, and the Commonwealth Director of Public Prosecutions for their advice and cooperation in this matter. ---------------------------------------------------------------------------- If you believe that your system has been compromised, contact SERT or your representative in FIRST (Forum of Incident Response and Security Teams). Internet Email: sert@sert.edu.au Facsimile: (07) 365 4477 Telephone: (07) 365 4417 SERT personnel answer during business hours (AEST). Security Emergency Response Team Prentice Centre The University Of Queensland Qld. 4072. Appendix 2 SERT Advisory SA-93.04, Guidelines For Developing A Sensible Password Policy ============================================================================= SA-93:04 SERT Advisory 1-Jun-1993 Guidelines For Developing A Sensible Password Policy ----------------------------------------------------------------------------- This advisory contains guidelines for developing a sensible password policy. Please feel free to extract the contents of this advisory, modify to suit local conditions, and then distribute to end users, as it is end users who are responsible in the first instance for individual account security. Without doubt, one of the most popular methods used by computer crackers to compromise a system is password stealing. By stealing your username and password an intruder can, with reduced likelihood of detection, gain access to your system, modify it for his or her own purposes and use that system as a launchpad for attacks on other systems throughout the world - and all in your name. Password protection is one of the most (if not the single most) important principles of system security. It is uniformly important for ALL users, regardless of system privileges or computer literacy. It is up to each and every individual to ensure that their password is safe - a single unsafe password can (and probably will) lead to a computer cracker violating YOUR system. Your best line of defence against attack is a secure password. A password is like a key, and any entry point that allows access by default is not secure. A bad password is like leaving your front door unlocked. Do not underestimate the ease with which your password can be stolen. There are many techniques available to do this. A simple and amazingly successful password theft technique for the cracker is password guessing (i.e. entering your username, and simply guessing what your password might be). The aim of this advisory is to thwart these attempts. How To Select A Safe Password ----------------------------- Some systems automatically (and autocratically) allocate passwords to users. Many systems, however, give the user the option of selecting his or her own password. The following guidelines should help in selecting a password which will be sufficiently robust to prevent a cracker from guessing your password in the majority of cases. There are several principles involved in selecting a safe password. These are covered below. The DO-NOTs DO NOT use simple passwords that are easy to remember and are typically not safe. Examples of such passwords are: - your userid (a common, but extremely dangerous practice); - a word which can be associated with you. For example: - your car make, model or registration number - your child's name - your street name, postcode or other address details - your medicare number - your tax file number - any of your bank account numbers; - a word which someone watching could easily spot (qwertyuiop); - any dictionary word (which a cracker with a PC and an on-line dictionary could discover by exhaustive trial); - words from other guessable word sets such as famous names, proper names, colloquial terms (in various spheres of life) and so on. It is not sufficient to include a single number in the word, or change all O's to 0's and I's or L's to 1's in the word, or to spell the word backwards. DO NOT leave your account without a password. DO NOT use your userid as your password. DO NOT use any word from a dictionary (of any language) as most forms of password attack use dictionaries as a basis for password guessing. DO NOT use birthdays, car registration numbers, room numbers, department names, machine names, locations, wife/husband's names, pet's names, children's names and so on. These may be determined as most of this information is not confidential. DO NOT use keyboard patterns, or duplicating characters such as qwerty or aabbccdd. DO NOT use the same password on multiple accounts. If you have many accounts, then do not use the same password on each account. If one is broken, then all are broken. Also, do not just change one character in the password as this may be easily spotted if one of the passwords is compromised. DO NOT allow anyone to watch while you type your password. DO NOT record your password either on-line. DO NOT write down your passwords. DO NOT tell anyone what your password is. Do not share your password with your partner, your children, your friends. Even telling your dog should be considered risky! Do not tell a person verbally, by electronic mail or by any other means. Remember: if someone has your password, they can commit criminal acts using your account! SERT staff have been alerted to several security breaches at constituent sites which have been attributed (in total or in part) to the sharing of passwords between husband and wife, parent and child, and between friends. The DOs DO use a MINIMUM (not maximum!) of 8 or more characters (system permitting). DO use mixed case wherever possible. DO NOT choose only the first letter as uppercase. (e.g. Mich37bo is not as good as MicH37Bo.) DO include at least two digits or punctuation characters. DO NOT simply replace "o" and "O" with "0", and "I", "l" or "L" with 1. (e.g. fl0pp1mp is not as good as fL0$p*Mp.) DO change passwords frequently, and DO NOT reuse old passwords. Password cracking algorithms have been around for quite a while now. By using computationally intensive processes, a password can be broken in time. Applying the techniques outlined above make the length of time required to break a password prohibitively long. However, the time required to break a password drops significantly as each letter is guessed, or other information is known about a password. Passwords should be changed regularly, so that even if a password is finally guessed, it will be long out of date. A password should never be reused. General techniques for generating safe passwords include: - using two or three short words that are unrelated; - always including some non-alphabetic, non-numeric (i.e. punctuation) characters; - deliberately misspelling; - taking the first letter from each word of a phrase (a passphrase). Note that different operating systems have different rules for the characters that one is allowed to use in a password. Some operating systems will allow any printable characters, whereas others only allow numeric and alphabetic (i.e. non-punctuation) characters. After reading all of that, you may ask "well, what is a good password? What can I use?". One technique would be to use a two or three word phrase, and replace the 1st character of the 1st word with a -1, the 2nd character of the 2nd word with a -2, etc, and uppercase every second character except punctuation. e.g. !Yc@rSm$lLs (my car smells). Another alternative might be to use the first letter from each word in a line from a song, have every third letter in upper case, and replace (aeiou) with ({}:"?). For example, 'Tie A Yellow Ribbon Round That Old Oak Tree' would convert into 't{YrrT""T'. (Rationale: 'Tie A Yellow Ribbon Round That Old Oak Tree' => 'tayrrtoot' Convert every third letter to upper case => 'taYrrTooT' Replace lower case vowels => 't{YrrT""T') Note that these examples should NOT be used as they are now published widely! You should be aware of what characters your system will accept in a password, the length required for a password, and what time period is allowed before the password will have to be changed again. You also need to be aware of the commands used to change passwords. What System Managers Can Do --------------------------- Consider using the following techniques. - Use Crack, a password cracking tool to audit existing passwords. You supply a dictionary, and a list of massaging rules. Crack then tests the encrypted password against the dictionary and rules list to see which passwords it can guess. This is only available for UNIX systems. - Consider also the use of password shadowing, which places the encrypted passwords in a non-world-readable file, not /etc/passwd (which is world-readable). Again, this is only applicable for UNIX systems. - If your system has a facility to enforce rules on minimum password content (e.g. "must include at least 1 upper case and at least 1 numeric"), then use this facility. For UNIX systems which don't have this facility, npasswd or passwd+ are good alternatives. - If your system has a facility to (a) enforce password ageing, and (b) keep a history file of passwords and disallow previous passwords, then use this facility also. - Keep passwords for system accounts distributed amongst the smallest group of people possible. Change these passwords more frequently than passwords for non-privileged accounts. - Take care with the use of facilities that are available for logins which bypass the use of passwords. For instance, on VMS systems, don't allow proxy logins for privileged accounts such as "SYSTEM". On UNIX machines, remove any .rhosts files (or /etc/hosts.equiv) with "+" signs in them. Login programs (such as /bin/login on UNIX systems) are constructed to behave in a certain way. One method used by crackers to obtain passwords is to execute a program (a trojan horse) masquerading as the login program. The trojan horse will accept your username and password, log it into a secret file, and then inform you that the combination entered was incorrect, before finally calling the real login program. The user, thinking that this was merely a typographical error, will proceed as normal unaware that his or her password has been logged for later use. This can be avoided in some cases by typing a few times before entering your username/password combination. Finally, system managers should be aware that X display managers (such as xdm) may bypass several login and system facilities such as message of the day, password ageing etcetera. Depending upon the sensitivity of your site, this may present some problems which will need resolution using more lateral methods. If you believe that your system has been compromised, contact SERT or your representative in FIRST (Forum of Incident Response and Security Teams). Internet Email: sert@sert.edu.au Facsimile: (07) 365 4477 Telephone: (07) 365 4417 SERT personnel answer during business hours (AEST). Security Emergency Response Team Prentice Centre The University Of Queensland Qld 4072 AUSTRALIA. Appendix 3 Wrapper Example The following material is an example of a wrapper that could conceivably used for protecting the FAL object, as outlined in Section 4.1, Wrappers. $ SET NOON $ SET NOCONTROL_Y $ SaveVerify = F$VERIFY(0) $ SET NOVERIFY $! ================================================================ $! $! Example Wrapper $! $! *** NOTE: This file is UNTESTED! *** $! $! Author: Rob McMillan, 1992 $! $! Example wrapper for the FAL object. This command file should be $! specified as the file to execute for the FAL object in the NCP $! database. This file is for example purposes only! $! $! Create allow and deny lists in AllowFile and DenyFile. The $! format of each file is "HOST::USERNAME.". Note the full stop. $! $! eg $! NODE1::USER1. $! $! To have blanket values, use an asterisk *. For instance, to $! have a blanket denial, but allow all people from NODE2::, and $! allow NODE1::USER1, have the following configuration: $! $! DenyFile: $! *::*. $! $! AllowFile: $! NODE2::*. $! NODE1::USER1. $! $! In the absence of enough information in the configuration $! files, or a clash of information (eg denying and allowing $! *::*), the default action is to deny a connection. $! $!================================================================ $! $! -- What object is this wrapper for? $! $ Executable = "SYS$SYSTEM:FAL.EXE" ! Object executable to use $! $! -- Constants $! $ WAllowed == %x10000001 $ WDenied == %x10000002 $ WUnknown == %x10000003 $! $! -- Get connection details $! $ LocalNodeName = F$GETSYI("NODENAME") + "::" $ LocalTime = F$TIME() $ LocalUser = F$GETJPI("","USERNAME") $ LocalUser = F$EXTRACT(0,F$LOCATE(" ",LocalUser),LocalUser) $ RemoteNodeName = F$TRNLNM("SYS$REM_NODE") $ RemoteUser = F$TRNLNM("SYS$REM_ID") $ WrapperLogInfo = - "at ''LocalTime' from ''RemoteNodeName'::''RemoteUser' as ''LocalUser'" $! $! -- Check wrapper configuration $! $! At this point, we can use any of the following to check $! whether we'll allow the connection: $! $! - LocalNode $! - LocalTime $! - LocalUser $! - RemoteNodeName $! - RemoteUser $! $ ConnectionOkay = WUnknown $ CheckFALRules 'LocalNodeName' 'LocalTime' 'LocalUser' - 'RemoteNodeName' 'RemoteUser' $ ConnectionOkay = $Status $ IF (RemoteNodeName .EQS. LocalNodeName) $ THEN $ ConnectionOkay = WAllowed ! Failsafe $ ENDIF $! $! -- Log the event and take action $! $ IF (ConnectionOkay .NE. WAllowed) $ THEN $ WRITE SYS$OUTPUT "Network connect request failed ''WrapperLogInfo'" $ WriteFALLog "Network connect request failed ''WrapperLogInfo'" $ LOGOUT $ ELSE $ WRITE SYS$OUTPUT "Network connect request succeeded ''WrapperLogInfo'" $ WriteFALLog "Network connect request succeeded ''WrapperLogInfo'" $ RUN 'Executable' $ ENDIF $! $! -- Go home now $! $ SaveVerify = F$VERIFY(SaveVerify) $ EXIT 'ConnectionOkay' For interactive connections, the section in which connection details are evaluated would be more complicated. Different mechanisms would be required for finding out these details based upon the type of connection (eg local, DECnet, LAT, telnet). These are mentioned in Section 4.1, Wrappers. These command files should be world executable, but only readable and writeable by system privileged users. The two executables, CheckFALRules and WriteFALLog, should be similarly protected (eg installed, protected images). WriteFALLog is a very simple program which writes the supplied parameters to the log file for this object. CheckFALRules could look something like the following example. /* * CheckFALRules.C * * Author: Rob McMillan, 1992 * * Use current connection details to compare with local rules and * return a value describing whether to allow the connection or * not (Allow). * * The returned value (Allow) can return one of two values: * WAllowed: allow the connection * WDenied: refuse the connection * * This wrapper configuration tests only upon the basis of * RemoteNodeName and RemoteUser. However, any of the details * supplied below can be used, based upon paranoia levels. To * do this, the following must be modified: * * - The CHECK_EXPLICIT_RULE subroutine * - The calls in this subroutine to CHECK_EXPLICIT_RULE * - The header comments at the top of this wrapper * - The allow and deny files. * */ #include #include #include #include #include "CheckFALRules.H" typedef unsigned int BOOLEAN; #define FALSE 0 #define TRUE 1 /* -- Prototypes */ int CheckExplicitRule( char *, char *); int ExitHandler(int, char *); char * Salloc(unsigned int); char * SnarfArgument(char *); int main (argc, argv) int argc; char * argv[]; { char * localNodeName; char * localTime; char * localUser; char * remoteNodeName; char * remoteUser; int status = WUnknown; /* Get and display parameters */ localNodeName= SnarfArgument(argv[1]); localTime = SnarfArgument(argv[2]); localUser = SnarfArgument(argv[3]); remoteNodeName = SnarfArgument(argv[4]); remoteUser = SnarfArgument(argv[5]); if ((localNodeName == (char *)0) || (localTime == (char *)0) || (localUser == (char *)0) || (remoteNodeName == (char *)0) || (remoteUser == (char *)0) ) { fprintf( stderr, "Error snarfing check parameters!\n"); exit( ExitHandler( WDefault, "Error snarfing check parameters!")); } /* Now evaluate whether to allow the connection */ /* -- We will only test based on source node and user. * We can check other details if required at a later stage. * * Note that the order in which these rules are checked is * important. Below, we check in the order of the most * specific rule to the most general. Once a connection * is found to be explicitly allowed or denied * no further rules are checked. */ status = CheckExplicitRule( remoteNodeName, remoteUser); if (status != WUnknown) exit( ExitHandler( status, "On node::user combination")); status = CheckExplicitRule( remoteNodeName, "*"); if (status != WUnknown) exit( ExitHandler( status, "On node::* combination")); status = CheckExplicitRule( "*", "*"); if (status != WUnknown) exit( ExitHandler( status, "On *::* combination")); /* No applicable rules were found, or there were a clash of * rules, so use the default. */ fprintf(stderr, "Warning! Unable to evaluate connection status!\n"); exit ( ExitHandler( WDefault, "Default action taken")); } /* end main */ /* * CheckExplicitRule * * Use the remoteNodeName and remoteUser to return a value * describing whether the proposed connection is explicitly allowed * or denied. The returned value can be one of three values: * * WAllowed: explicitly allow the connection * WDenied: explicitly deny the connection * WUnknown: couldn't evaluate on supplied information * * Allowed configurations are set out in ALLOW_FILE. * Disallowed configurations are set out in DENY_FILE. * * If the record is found in both files, or the record can't be * found in either file, return WUnknown. Otherwise, return * the result explicitly described by the files. * */ int CheckExplicitRule( remoteNodeName, remoteUser) char * remoteNodeName; char * remoteUser; { char inbuf[132]; /* Should be heaps */ char * searchKey; BOOLEAN allow = WUnknown; BOOLEAN foundAllow = FALSE; BOOLEAN foundDeny = FALSE; FILE * fp; if ((searchKey = Salloc(strlen(remoteNodeName) + 3 + strlen(remoteUser))) == (char *)0) return( WUnknown); searchKey = strcpy(searchKey, remoteNodeName); searchKey = strcat(searchKey, "::"); searchKey = strcat(searchKey, remoteUser); /* See if there is a matching record in the allow file */ if ((fp = fopen( ALLOW_FILE, "r")) == (FILE *)NULL) { fprintf(stderr, "Error! Cannot open wrapper AllowFile! \n"); return( WUnknown); } else { /* Search file for matching record */ while ((foundAllow == FALSE) && (fgets(inbuf, 132, fp) != (char *)NULL)) if (strncmp(searchKey, inbuf, strlen(searchKey)) == 0) foundAllow = TRUE; fclose(fp); } /* Now search deny file as well */ if ((fp = fopen( DENY_FILE, "r")) == (FILE *)NULL) { fprintf(stderr, "Error! Cannot open wrapper DenyFile! \n"); return( WUnknown); } else { /* Search file for matching record */ while ((foundDeny == FALSE) && (fgets(inbuf, 132, fp) != (char *)NULL)) if (strncmp(searchKey, inbuf, strlen(searchKey)) == 0) foundDeny = TRUE; fclose(fp); } /* If we get a strict decision, then return the result. If we * get two FALSEs or two TRUEs, then there is no decision. */ if ((foundAllow == TRUE) && (foundDeny == FALSE)) allow = WAllowed; if ((foundAllow == FALSE) && (foundDeny == TRUE)) allow = WDenied; return( allow); } /* end CheckExplicitRule */ /* * ExitHandler * * Carry out any cleaning up required whilst exiting. * */ int ExitHandler( exitCode, diagnostic) int exitCode; char * diagnostic; { #ifdef DEBUG switch (exitCode) { case WAllowed: fprintf( stdout, "\nConnection allowed: "); fprintf( stdout, "%s.\n", diagnostic); break; case WDenied: fprintf( stdout, "\nConnection denied: "); fprintf( stdout, "%s.\n", diagnostic); break; case WUnknown: fprintf( stdout, "\nCan't figure out to allow connection or not: "); fprintf( stdout, "%s.\n", diagnostic); break; default: fprintf( stdout, "\nError. Unknown exit code: "); fprintf( stdout, "%s.\n", diagnostic); break; } #endif return( exitCode); } /* end ExitHandler */ /* * Salloc * * Safe malloc * * See P321 "C Programming in a UNIX Environment" * by Judy Kay and Bob Kummerfeld, * Addison-Wesley, 1989. * */ char * Salloc(size) unsigned int size; { char * result; if ((result = malloc(size)) == (char *)0) fprintf(stderr, "Cannot malloc %d bytes.\n", size); return result; } /* end Salloc */ /* * SnarfArgument * * Make a copy of arg string. * */ char * SnarfArgument( arg) char * arg; { char * result; if ((result = Salloc(strlen(arg)+1)) != (char *)0) result = strcpy(result, arg); return( result); } /* end SnarfArgument */ The header file for this program would contain the following: /* * CheckFALRules.H * * Author: Rob McMillan, 1992 * * See comments in CheckFALRules.C. * * THE CONTENTS OF THIS FILE MUST MATCH THOSE IN THE WRAPPER COMMAND FILE! * */ /* -- Define file paths */ #define DEBUG #ifdef DEBUG #define ALLOW_FILE "{Allow File name here}" #define DENY_FILE "{Deny File name here}" #else #define ALLOW_FILE "local$wrap:{Allow File name here}" #define DENY_FILE "local$wrap:{Deny File name here}" #endif /* -- Define exit values */ #define WAllowed 0x10000001 #define WDenied 0x10000002 #define WUnknown 0x10000003 #define WDefault WDenied