SecureMyi.com Security and Systems Management Newsletter for the IBM i April 22, 2015 - Vol 5, Issue 5
Real-Time Alerts for CL Command Execution
By Dan Riehl
Do you want to be alerted when someone tries to restore objects onto your system? Or maybe you want to know when someone starts up a TCP/IP server, or changes a System Value. You can do this using Control Language Command Exit Programs.
In part one of this series on CL Command Exit Programs the focus of the article was the exit points available for CL commands, and dealt quite specifically with the Command Analyzer Change Command exit point. As noted in that article, there is another Command Exit Point that may be used to monitor and audit commands as they are executing. This is the Command Analyzer Retrieve Command exit point.
This capability allows you to capture commands as they execute and do something with the information collected. Unlike the Command Analyzer Change Command exit point discussed earlier, the Retrieve Command exit point does not allow you to send information back to the command analyzer. This seemingly limits the capabilities of this Exit Point to be a logging and auditing Exit Point only. We'll see additional undocumented capabilities in Part 3 of this series on the CL Command Exit Points.
The example program supplied in this article is called whenever someone executes the Restore Object(RSTOBJ) command. It retrieves the command information and records the entire RSTOBJ command string and other useful information in the system's QHST history log, and also sending an alert message to a Message Queue named Restore. You could certainly do other things with the command string data, but the purpose of this simple example is to illustrate the process of being able to create real-time alerts by creating and registering the CL Command Exit Program.
The Command Analyzer Retrieve exit point
Each IBM supplied exit point has an assigned name and an exit point interface. The exit point interface is a list of parameters the command analyzer exchanges with your exit program. The name of the exit point for the Command Analyzer Retrieve Command exit point is QIBM_QCA_RTV_COMMAND. This exit point occurs after the command analyzer has done much of its work, but before control is passed to the Command Processing Program(CPP).
Since our exit program is called before the CPP, the exit program cannot predict whether the command will complete normally or abnormally. It only knows that the command is being attempted, with no knowledge of, or potential impact on, the outcome of the command processing program(i.e. whether the operation will fail or succeed).
The name of the exit point interface for this exit point is named RTVC0100. This exit point interface is similar to the CHGC0100 interface discussed in the previous article. The exit program is not passed the RTVC0100 interface in separate parameters, but as one big lump of data. Your program needs to parse out the individual data elements of the RTVC0100 parameter which is illustrated in Figure 1.
Figure 1 - The Retrieve Command Exit Point Interface
As with all registered exit points, you can add your own exit point program using the ADDEXITPGM(Add Exit Program) command. In the case of the Retrieve Command exit point, you need to specify the name of the command, and the library in which the command resides in the PGMDTA parameter as in the following example. For the Retrieve command exit point, you can register up to 10 programs per command, incrementing the PGMNBR parameter for each consecutive program. This allows you to run a sequence of programs, or allows you to run a third party, or vendor supplied, exit program, and still run your own program.
ADDEXITPGM EXITPNT(QIBM_QCA_RTV_COMMAND) +
TEXT('Exit program for RSTOBJ') +
PGMDTA(*JOB 20 'RSTOBJ QSYS')
The PGMDTA parameter must be specified with a data length of 20. You must specify the command name in the first 10 positions, and the command library name in the next 10 positions, as in the example. The command analyzer is directed to use the exit program RSTOBJEXIT in library MYLIB whenever a request is made to run the RSTOBJ command found in the QSYS library.
There are certain commands for which exit point programs may
not be defined. These include CL compiler directing statements, commands found
in libraries QSYS38 and QUSER38, and a few others.
Figure 2 contains a sample exit program that may be used for the RSTOBJ command. The exit program sends a message to a message queue each time the RSTOBJ command is used. It also sends a message to the QHST history log. The processing performed in this program is quite simple, but it does provide a template that you can use to create your own Logging and Alerting program.
You should note that this exit program is registered to only monitor for the usage of the RSTOBJ command. However, you could use the same program to monitor for all RSTxxx commands by adding the same exit point program(ADDEXITPGM) for each RSTxxx command(e.g. RSTLIB, RST, RSTLICPGM, etc).
Figure 2 - Command Exit Point Program Example
/* Program Name: RSTOBJEXIT */
/* Purpose: This is the exit program for the Command RSTOBJ.  */
/* Exit Point IS QIBM_QCA_RTV_COMMAND */
/* Parameter format is RTVC0100. */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Copyright© 2002-2015 Dan Riehl, The 400 School, Inc. */
DCL &Exitinfo *Char 2000 /* RTVC0100 Interface Data */
DCL &User *Char 10
DCL &JobName *Char 10
DCL &OffsetDec *Dec (7 0)
DCL &CmdLenDec *Dec (7 0)
/* Exit point interface RTVC0100 for QIBM_CA_RTV_COMMAND exit point */
DCL &ExitPoint *CHAR 20 /* Exit Point name */
DCL &ExitFormat *CHAR 8 /* Exit Point Format */
DCL &CmdLib *CHAR 10 /* Command Library */
DCL &OffsetO *CHAR 4 /* Offset to command string */
DCL &CmdLengthO *CHAR 4 /* Command string length */
DCL &OffsetR *CHAR 4 /* Offset to command string */
DCL &CmdLengthR *CHAR 4 /* Command string length */
DCL &CmdString *CHAR 2000 /* Command String */
/* Error handling variables */
DCL &MsgID *CHAR 7
DCL &MsgFile *CHAR 10
DCL &MsgFLib *CHAR 10
DCL &MsgData *CHAR 512
MONMSG CPF0000 EXEC(GOTO ERROR)
/* Parse out the exit info data */
CHGVAR &ExitPoint %SST(&ExitInfo 1 20)
CHGVAR &ExitFormat %SST(&ExitInfo 21 8)
CHGVAR &CmdName %SST(&ExitInfo 29 10)
CHGVAR &CmdLib %SST(&ExitInfo 39 10)
CHGVAR &CmdLengthO %SST(&ExitInfo 57 4)
CHGVAR &OffsetR %SST(&ExitInfo 61 4)
CHGVAR &CmdLengthR %SST(&ExitInfo 65 4)
/* Check to see if command was replaced by Change Command Exit */
IF (%BIN(&OffsetR) = 0) DO /* Command not replaced */
CHGVAR &CmdLenDec %BIN(&CmdlengthO)
CHGVAR &CmdLenDec %BIN(&CmdlengthR)
CHGVAR &OffsetDec (%BIN(&OffsetR) + 1) /* Set offset */
CHGVAR &CmdString %SST(&ExitInfo &OffsetDec &CmdLenDec)
RTVJOBA JOB(&JobName) USER(&User)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Restore +
*TCAT '. The command executed is:' *BCAT +
&CmdString) TOMSGQ(RESTORE QHST)
/* Error handling */
ERROR: RCVMSG MSGTYPE(*LAST) MSGDTA(&MsgData) +
MSGID(&MsgID) MSGF(&MsgFile) +
MONMSG CPF0000 EXEC(RETURN)
SNDPGMMSG MSGID(&MsgID) MSGF(&MSGFLIB/&MsgFile) +
MONMSG CPF0000 EXEC(RETURN)
Examining the RSTOBJ Command Exit Program
The exit program receives only one parameter. As mentioned, the parameter contains the RTVC0100 data structure that must be parsed into its individual fields. At A in Figure 2, the fields are defined that will be used to store the RTVC0100 format data once it is parsed. At B , the RTVC0100 format is parsed into it's component parts.
At C , a determination is made as to whether the original command was replaced by a Command Analyzer Change Exit program. If it was replaced, then the command string that is being executed is found at the offset stored in the variable &OFFSETR, otherwise the offset to the command is found in the variable &OFFSETO. As you can see, the determination is made by checking the replacement offset(&OFFSETR) for a value of 0(zero). If the replacement offset is 0, the command was not replaced by a Change Command Exit program.
At D in Figure 2, the User and Job name are retrieved from the job running the RSTOBJ command. This information is collected so that it can be included in the informational message that is sent, also at D . The message is sent to two message queues; RESTORE and QHST. You can replace these in the code to suit your individual requirements.
Figure 3 below shows the resulting Display Messages screen when after a few RSTOBJ commands are executed. The same information is written to the QHST history log to assist in your auditing for the use of the RSTOBJ command.
Don't forget to Exit
IBM has added numerous exit points to the system. As you become familiar with command exit points and the customized processing you can perform, you may want to delve further into more of the exit points. There are exit points for all kinds of things, like Save and Restore functions, User Profile maintenance, and network access control. The toolbox is booming! You can use exit point programs to make your system administration tasks a lot easier than they might have been in the past. So don't forget to Exit!
Figure 3 - The resulting Display Messages screen
Queue . . . . . : RESTORE Program . . . . : *DSPMSG
Library . . . : QUSRSYS Library . . . :
Severity . . . : 00 Delivery . . . : *BREAK
Type reply (if required), press Enter.
Restore operation in progress from user TESTUSER from job QPADEV0013. The
command executed is: RSTOBJ OBJ(QXXXXX) SAVLIB(MYLIB) DEV(*SAVF)
Restore operation in progress from user ANYUSER from job QPADEV0015. The
command executed is: RSTOBJ OBJ(QCLSRC) SAVLIB(YOURLIB) DEV(*SAVF)
Restore operation in progress from user QSYSOPR from job QPADEV0010. The
command executed is: RSTOBJ OBJ(MYPROGRAM) SAVLIB(QGPL) DEV(*SAVF)
F3=Exit F11=Remove a message F12=Cancel
F13=Remove all F16=Remove all except unanswered F24=More keys
©2004-2015 Dan Riehl All Rights Reserved
About the Author
Dan performs IBM i security assessments and provides security consulting, remediation, forensic evaluations, and other customized security services for his clients. He also provides training in all aspects of IBM i security and other technical areas through The 400 School, Inc.