Manage Learn to apply best practices and optimize your operations.

A primer to writing TCP/IP exit point programs

Learn how to use a TCP/IP exit point program and create log to record log-ins.

Dan Riehl

There are a few things that have always bugged me about the TCP/IP services on the iSeries. I want to let you in...

on one of my pet peeves. You probably have one or more of your own, but here's one of mine: There is no FTP logging facility. Even my shareware version of an MS/Windows FTP Server has a nice logging facility. A typical FTP log contains information about every FTP session running on the system. It tells you what users are logged in, and what they're doing (PUTs, GETs, etc). However, on the iSeries, if someone logs in and transfers a file using FTP, no logging of that event occurs -- anywhere.

If Joe Smith from accounting has authority to the Payroll Master file and downloads it to his PC with FTP, I have no way to know. One solution to this problem is to just shut down the FTP server. However, there is a better way.

OS/400 enables you to control access to FTP services using TCP/IP exit point programs. You still cannot create a full-blown FTP logging facility, but you can control access, and create a log of the events you're most concerned about, e.g. log-in requests, file transfer requests.

In this article I'll show you what the TCP/IP exit points are, and how to use a TCP/IP exit point program to create a log that records each time a user tries to log in to your FTP server.

What are TCP/IP exit points?
Within some AS/400's TCP/IP applications such as FTP, IBM has created several pre-defined exit points. For example, within the FTP server application, there are several points at which the server program checks to see if you want to hook your own custom logic into the FTP program's internal logic. It does this by checking to see if you have registered an exit program for a particular pre-defined exit point. If it finds a registered exit program, the program is called at that point in the FTP server processing. Your exit point program receives parameters from the FTP application and returns parameters to the FTP application that controls it's subsequent processing.

Let's look at an example to help clarify what a simple exit point program can actually perform and how it interacts with the iSeries FTP server.

One of the exit points for the FTP server application is named QIBM_QTMF_SVR_LOGON. This exit point occurs immediately after someone has entered a UserID and authentication string (password) to log in to the FTP server. Using an exit point program attached to this exit point, the FTP server program will call your custom program so that you may use your own logic in validating or logging the log-in attempt.

With this, or any exit point, your program must accept and return certain parameters. The incoming parameters for this exit point contain the IP address of the requestor, the UserID and the authentication string (password). Among the parameters that your program must return is a flag to indicate whether the log-in should be accepted or rejected. If you accept the log-in, the normal iSeries security logi-n process is performed. So you are not circumventing the log-in processing, but rather using your exit point program to enhance your control of the logi-n attempt. If your exit program rejects the log-in attempt, the FTP server notifies the user that the FTP log-in failed.

Example of FTP server exit point

|     FTP Server Application            |
|                                                      | 
|                                                      |
|     Server Logon---Exit Point         |             _Interface____               Exit Point Program
|                              <----------------------->  | Parameters    |<--------->|                             |
|              IF accept...                       |           |                      |                |    RPG/CL/etc      | 
|              IF Reject...                       |           ------------------|                |                             |
--------------------------------------------                                                  ------------------------ 

TCP/IP exit points under V3R2/R7
There are dozens of network access exit points on the iSeries. We'll limit our scope to the FTP exit points. Each exit point has a name and an exit point interface. The exit point interface is simply a list of parameters that the exit point must exchange with your exit point program. Although IBM has assigned a name to each exit point interface (list of parameters), the names are really not significant. They are listed here only for your reference. You might notice, however, that the exit point interface VLRQ0100 is used for both the FTP client and the FTP server application. This simply means that an exit program for the FTP client and server application must accept the same parameter list.

Exit Point Exit Point Interface Application

The QIBM_QTMF_CLIENT_REQ exit point occurs when someone using the AS/400 FTP client application requests an FTP subcommand (e.g. GET, PUT). (The FTP client application is accessed using the AS/400 command FTP or STRTCPFTP.)

The QIBM_QTMF_SERVER_REQ exit point occurs when someone accessing the AS/400 FTP server application requests an FTP subcommand.

By attaching an exit point program to those exit points, you can control what subcommands are used, who is using them and what directories/libraries are involved. Using the return parameters, you either accept or reject the request.

As mentioned previously, the QIBM_QTMF_SVR_LOGON exit point occurs immediately after someone has entered a UserID and authentication string (password) to logi n to the FTP server.

Registering your exit point program
Once you have written an exit program that conforms to the specifics of the exit point interface, you must tell the FTP server the name of the program and the library in which in resides. To accomplish this, you must register the exit point program using the WRKREGINF (Work with Registration Information) command. You add the exit program to the FTP server. Then, each time the FTP application reaches the exit point, your program will be called.

Exploring the server log-on exit point
The FTP server log-on exit point program is called each time a user attempts to log in to the FTP server. Using an exit point program, you gain control of the front-end log-in process. This does not take the place of the iSeries log-in security protection, but rather is a log-in preprocessor that allows you to grab the log-in attempt before the log-in processor.

In the exit point program you can direct the FTP server to either accept or reject the log-in attempt. You can also override certain FTP login options. Figure 3 shows the exit point interface (parameter list) for the exit point. Figure 4 shows the values that can be used for the parameters.

Figure 3

Parameter Data type/Length Input/Return
Application ID Bin(4) Input
User ID Char(*) Input
Length of UserID Bin(4) Input
Authentication String Char(*) Input
Length of Authentication String Bin(4) Input
Client IP Address Char(*) Input
Length of Client IP Address Bin(4) Input
Accept/Reject Flag Bin(4) Return
User Profile Char(10) Return
Password Char(10) Return
Initial CURLIB Char(10) Return

Figure 4

Parameter Values Description
Application ID 1 1=FTP Server application
User ID Data from the USER sub-command
Length of UserID Total Bytes in User ID
Authentication String Data from the PASS sub-command
Length of Authentication String Total Bytes in Authentication String
Client IP Address IP address of client in dotted decimal format;Left justified
Length of Client IP Address Total Bytes in Client IP Address
Accept/Reject Flag 0 Reject Login attempt
1 Accept Login attempt
Use UserID for UserID
Use Authentication string for Password
Use CURLIB from User Profile
2 Accept Login attempt
Use UserID for UserID
Use Authentication string for Password
Get CURLIB from the following CURLIB parameter
3 Accept Login attempt
Get the UserID from the following User Profile Parameter
Get the Password from the following Password Parameter
Use CURLIB in User Profile of Profile supplied in the following User Profile Parameter
4 Accept Login attempt
Get the UserID from the following User Profile Parameter
Get the Password from the following Password Parameter
Get CURLIB from the following CURLIB parameter
5 Accept Login attempt
Get the UserID from the following User Profile Parameter
Bypass Password authentication
Use CURLIB in User Profile supplied in the following User Profile Parameter
6 Accept Login attempt
Get the UserID from the following User Profile Parameter
Bypass Password authentication
Get CURLIB from the following CURLIB parameter
User Profile Required if Accept/Reject flag = 3, 4, 5 or 6; Left Justified, blank padded
Password Required if Accept/Reject flag = 3 or 4
CURLIB Required if Accept/Reject flag = 2, 4 or 6

As you view the allowable values for the Accept/Reject flag, it's easier to understand the usage of the User Profile, Password and CURLIB return values. Depending on the value set for the Accept/Reject flag, you may need to place a value in one or more of these return parameters.

The return parameters allow you to override the values that would normally be used in the FTP log-in attempt. For instance, by using the value 3 for the Accept/Reject flag, you tell FTP that you are overriding the values for the User Profile and password with the values that your exit program places into the return parameters User Profile and Password.

With other Accept/Reject Flag values, you decide whether the CURLIB for the FTP session should come from the CURLIB specified in the User Profile object or from the CURLIB return parameter. Using the Accept/Reject flag together with the other return parameters, you can dictate not only the profile and password for the FTP session but also what library will be used as the CURLIB for the session.

You need to be aware that if you return a value of 5 or 6 in the Accept/Reject flag, no further password validation is performed. Although this seems scary, it's really designed to give you the ability to do things like Anonymous FTP. (That's where you allow an unnamed user to access files you want to make publicly available via FTP.) The Authentication string typically used by an Anonymous FTP user will be their e-mail address, and that usually won't work as an AS/400 password, which is limited to 10 characters. So you can use values 5 or 6 to bypass the password checking.

Putting the server log-in exit program to work
There are many interesting things you can do in the Server_Logon exit program. Figure 5 below is an example of an exit program that records all FTP login attempts to a message queue. As you can see, it is a very simple CL program that accepts the parameter group shown in figure 3 and strings together a message that is sent to an iSeries message queue.

Figure 6 below shows the results. It is a record of all FTP Server Login requests. Although it does not show whether the log-in attempt was successful, it does show each log-in attempt. This is quite useful when you want to know who's been logging in to your FTP server. As you can see, it shows the UserID, the IP address of the client, and the time and date of the log-in attempt.

To enable this program as the exit point program for the FTP server login exit point, follow these steps.

Sign on as QSECOFR
Create a library USRTCPIP w/AUT(*EXCLUDE)
Grant user QTCP *USE authority to the Library
Create source file QCLSRC w/AUT(*EXCLUDE)
Enter the source code
Create the program in USRTCPIP w/ AUT(*EXCLUDE)
Create message queue FTPSVRLOG in USRTCPIP w/AUT(*EXCLUDE)
Grant *CHANGE authority to the Message queue to user QTCP
Register the exit point

Graceful exit
The FTP server exit points allow you to customize your FTP environment to a considerable extent. In this article you have seen what the exit points are, how exit programs are called, how to register exit programs, and you have a working version of an exit program that records FTP server log-ins.

About the author: Dan Riehl is president of The 400 School, the popular iSeries training company, and co-founder of The Powertech Group, one of the leading providers of iSeries security software.

Figure 5: CL Exit program USRFTPLOGC

/* Program Name: USRFTPLOGC                                          */
/* Author. . . : Dan Riehl    The Powertech Group, Inc.              */ 
/* Purpose . . : This is the FTP Server Login Exit Point Program to  */
/*               record all FTP Login attempts to a message queue    */
/*               Exit point is QIBM_QTMF_SVR_LOGON                   */
/*               Parameter format is TCPL0100                        */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Security. . : Place in a Secure Library (i.e. PUBLIC(*EXCLUDE)    */
/*               Place source code in a secure library               */
/*               Do not allow retrieval of CL source                 */
/* Compilation : CRTCLPGM PGM(ASecureLibrary/USRFTPLOGC)   +         */
/*                        SRCFILE(ASecureLibrary/QCLSRC)   +         */
/*                        LOG(*NO)                         +         */
/*                        ALWRTVSRC(*NO)                   +         */
/*                        AUT(*EXCLUDE)                              */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    PGM    (  &P_AppID   +
              &P_User    +
              &P_UserLen +
              &P_Pwd     +
              &P_PwdLen  +
              &P_IP      +
              &P_IPLen   +
              &P_RtnOut  +
              &P_UserOut +
              &P_PwdOut  +
              &P_LibOut  )

  /* Parameters for Exit point interface FORMAT TCPL0100             */

  /* Input Parms */
    DCL       &P_AppID     *CHAR   4    /* Application ID (%bin)     */
                                        /* 1 = FTP                   */
    DCL       &P_User      *CHAR 999    /* User ID                   */
    DCL       &P_UserLen   *CHAR   4    /* User ID length (%bin)     */
    DCL       &P_Pwd       *CHAR 999    /* Password                  */
    DCL       &P_PwdLen    *CHAR   4    /* Password Length (%bin)    */
    DCL       &P_IP        *CHAR  15    /* Requestor IP Address      */
    DCL       &P_IPLen     *CHAR   4    /* IP Address Length  (%bin) */
    DCL       &P_IPLen     *CHAR   4    /* IP Address Length  (%bin) */

  /* Output Parms */
    DCL       &P_RtnOut    *CHAR   4    /* Return Code Out           */
                                        /* Values Are:               */
                                        /* 0=Reject                  */
                                        /* 1=Accept, w/Usrprf Curlib */
                                        /* 2=Accept, w/ &P_LibOut    */
                                        /* 3=Accept, w/UsrPrf Curlib */
                                        /*          and &P_UserOut   */
                                        /*          and &P_PwdOut    */
                                        /* 4=Accept, w/ &P_LibOut    */
                                        /*          and &P_UserOut   */
                                        /*          and &P_PwdOut    */
                                        /* 5=Accept, w/UsrPrf Curlib */
                                        /*          and &P_UserOut   */
                                        /*          Password bypass  */
                                        /* 6=Accept, w/ P_LibOut     */
                                        /*          and &P_UserOut   */
                                        /*          Password bypass  */
    DCL       &P_UserOut   *CHAR  10    /* User Profile Out          */
    DCL       &P_PwdOut    *CHAR  10    /* Password Out              */
    DCL       &P_LibOut    *CHAR  10    /* CURLIB Out                */
  /* End of FORMAT TCPL0100                                          */

  /* Variables for Binary Conversions */
    DCL       &AppID       *DEC   (1 0)
    DCL       &UserLen     *DEC   (3 0)
    DCL       &PwdLen      *DEC   (3 0)
    DCL       &IPLen       *DEC   (3 0)

  /* Misc Work Variables               */
    DCL       &Time        *CHAR   6
    DCL       &Date        *CHAR   6
    DCL       &Message     *CHAR 256
    DCL       &Accept1     *DEC    1   Value(1)
    DCL       &MsgQ        *CHAR  10   Value('FTPSVRLOG')
    DCL       &MsgQLib     *CHAR  10   Value('USRTCPIP')

  /* Message Handling Variables */
    DCL       &MsgID       *CHAR   7
    DCL       &MsgF        *CHAR  10
    DCL       &MsgFLib     *CHAR  10
    DCL       &MsgDta      *CHAR 100

    MonMsg    (CPF0000  MCH0000)  Exec(GoTo Error)

     ChgVar    &AppID    %Bin(&P_AppID)
     ChgVar    &UserLen  %Bin(&P_UserLen)
     ChgVar    &PwdLen   %Bin(&P_PwdLen)
     ChgVar    &IPLen    %Bin(&P_IPLen)

     RtvSysVal  QTIME    &Time
     RtvSysVal  QDATE    &Date

     Chgvar    &Message     +
                     ('FTP Logon'                             +
                      *BCAT %SST(&P_User 1 &UserLen)          +
                      *BCAT 'From IP Addr'                    +
                      *BCAT %SST(&P_IP 1 &IPLen)              +
                      *BCAT 'at'                              +
                      *BCAT %SST(&Time 1 2)                   +
                      *CAT  ':'                               +
                      *CAT  %SST(&Time 3 2)                   +
                      *CAT  ':'                               +
                      *CAT  %SST(&Time 5 2)                   +
                      *BCAT 'on'                              +
                      *BCAT %SST(&Date 1 2)                   +
                      *CAT  '/'                               +
                      *CAT  %SST(&Date 3 2)                   +
                      *CAT  '/'                               +
                      *CAT  %SST(&Date 5 2))

     SndPgmMsg  MsgID(CPF9897)               +
                Msgf(QCPFMSG)                +
                MsgDta(&Message)             +

     ChgVar    %Bin(&P_RtnOut)   Value(&Accept1)  /* Return "Accept" */

     Return     /* Normal end of program */

     RcvMsg     Msgtype(*LAST)               +
                MsgDta(&MsgDta)              +
                MsgID(&MsgID)                +
                MsgF(&MsgF)                  +

     /* Prevent loop, just in case           */
     MonMsg     CPF0000

     SndPgmMsg  MsgID(&MsgID)                +
                MsgF(&MsgFLib/&MsgF)         +
                MsgDta(&MsgDta)              +

     /* Prevent loop, just in case           */
     MonMsg     CPF0000

Figure 6: Screen shot of DSPMSG

                              Display Messages                                
                                                       System:   S10128AA       
 Queue . . . . . :   FTPSVRLOG               Program . . . . :   *DSPMSG        
   Library . . . :     USRTCPIP                Library . . . :                  
 Severity  . . . :   00                      Delivery  . . . :   *HOLD          
 Type reply (if required), press Enter.                                         
   FTP Logon DRIEHL From IP Addr at 12:28:54 on 01/12/97        
   FTP Logon PROGRAMMER1 From IP Addr at 12:30:38 on 01/12/97   
   FTP Logon DEVELOPMENT From IP Addr at 12:31:50 on 01/12/97   
   FTP Logon TESTAPP From IP Addr at 12:33:17 on 01/12/97       
   FTP Logon BOSS From IP Addr at 12:34:03 on 01/12/97          
   FTP Logon ANONYMOUS From IP Addr at 12:34:42 on 01/12/97     
   FTP Logon AS400DEV From IP Addr at 12:35:36 on 01/12/97      
   FTP Logon DRIEHL From IP Addr at 12:44:31 on 01/12/97        
 F3=Exit              F11=Remove a message                 F12=Cancel           
 F13=Remove all       F16=Remove all except unanswered     F24=More keys        


Dig Deeper on iSeries system and application security