This is an example of a simple File Transfer Protocol (FTP) Server Logon exit program. It is written in C programming language.
This code is not complete, but provides a starting point to help you create your own program.
(Pre formatted text in the following example will flow outside the frame.)
/* Module Description *************************************************/ /* */ /**********************************************************************/ /* */ /* Note: This program is a sample only and has NOT undergone any */ / formal review or testing. */ /* */ /**********************************************************************/ /* */ /* Source File Name: qtmfsvrlgn.c */ /* */ /* Module Name: FTP Server Logon exit program. */ /* */ /* Service Program Name: n/a */ /* */ /* Source File Description: */ /* This example exit program provides additional control over the */ /* process of authenticating a user to a TCP/IP application server.*/ /* When installed, this example exit program would be called each */ /* time a user attempts to log on to the server. */ /* */ /**********************************************************************/ /* */ /* Function List: main - FTP Server Logon exit program main. */ /* qtmfsvrlgn - FTP Server Logon exit function. */ /* CheckClientAddress - Check originating sessions IP */ /* address. */ /* */ /* End Module Description *********************************************/ #define _QTMFSVRLGN_C /**********************************************************************/ /* All file scoped includes go here */ /**********************************************************************/ #ifndef __stdio_h #include <stdio.h> #endif #ifndef __ctype_h #include <ctype.h> #endif #ifndef __string_h #include <string.h> #endif #ifndef __stdlib_h #include <stdlib.h> #endif #include "qusec.h" /* Include for API error code structure */ #include "qsyrusri.h" /* Include for User Information API */ /**********************************************************************/ /* All file scoped Constants go here */ /**********************************************************************/ #define EQ == #define NEQ != #define BLANK ' ' #define FWIDTH 128 /* Width of one database file record */ #define FNAME 21 /* Qualified database file name width */ /* Valid characters for Client IP address. The CheckClientAddress() */ /* function will check the Client IP address input argument */ /* (ClientIPaddr_p) to ensure it is in valid dotted-decimal format. */ /* This is one example of an input validity check. */ const char ValidChars[] = "0123456789."; /**********************************************************************/ /* All file scoped type declarations go here */ /**********************************************************************/ /**********************************************************************/ /* All file-scoped macro calls go here */ /**********************************************************************/ /**********************************************************************/ /* All internal function prototypes go here */ /**********************************************************************/ static void qtmfsvrlgn (int,char *,int,char *,int,char *,int,int *,char *,char *,char *); static int CheckClientAddress(char *, int); /**********************************************************************/ /* All file scoped variable declarations go here */ /**********************************************************************/ /**********************************************************************/ /* ** NOTE ** */ /* The following client IP address are for example purposes only. Any */ /* resemblance to actual system IP addresses is purely coincidental. */ /**********************************************************************/ /* EXCLUSIVE system lists, ie - Logon attempts from any client IP */ /* addresses NOT in one of these lists */ /* are allowed to continue. */ /* Reject server logon attempts of users attempting to log in from */ /* these client systems (return code = 0) */ char Reject[] = "1.2.3.4 5.6.7.8"; /* Limit logon abilities of users attempting to log in as ANONYMOUS */ /* from these client systems (return code = 6). */ /* In this example program, the initial current library is set and */ /* returned as an output parameter for users attempting to log in */ /* as ANONYMOUS from these specific client systems. */ char Limit[] = "9.8.7.6 4.3.2.1 8.7.6.5"; /* Function Specification *********************************************/ /* */ /* Function Name: Main */ /* */ /* Descriptive Name: FTP Server Logon exit program main. */ /* */ /* This example exit program allows access to a TCP/IP server to */ /* be controlled by the address of the originating session, gives */ /* additional control over the initial current library to a user, */ /* and provides the capability to implement "anonymous" FTP. */ /* */ /* Notes: */ /* */ /* Dependencies: */ /* FTP Server Logon exit point QIBM_QTMF_SVR_LOGON was registered */ /* during FTP product installation. */ /* */ /* Restrictions: */ /* */ /* None */ /* */ /* Messages: */ /* */ /* None */ /* */ /* Side Effects: */ /* */ /* None */ /* */ /* Functions/Macros called: */ /* */ /* qtmfsvrlgn - Server Logon exit function. */ /* */ /* Input: */ /* int * argv[1] - Identifies requesting application */ /* (FTP Client =0, FTP Server = 1). */ /* char * argv[2] - User identifier from client program. */ /* (For FTP server, this is user CMD data */ /* int * argv[3] - Length (in bytes) of User ID string. */ /* char * argv[4] - Authentication string from client. */ /* (For FTP server, this is the password) */ /* int * argv[5] - Length (bytes) Authentication string. */ /* char * argv[6] - Internet Protocol address from which */ /* the session originates. */ /* int * argv[7] - Length (in bytes) of IP address. */ /* int * argv[8] - Return code (received as 0). */ /* char * argv[9] - User profile (received as blanks). */ /* char * argv[10] - Password (received as blanks). */ /* char * argv[11] - Initial current library (received as blanks)*/ /* */ /* Exit Normal: Return Return Code, User Profile, Password, Initial */ /* Current Library to server application. */ /* */ /* Exit Error: None */ /* */ /* End Function Specification *****************************************/ void main(int argc, char *argv[]) { /********************************************************************/ /* Code */ /********************************************************************/ /********************************************************************/ /* Collect input arguments and call function to determine if client */ /* should be allowed to log in to an FTP server application. */ /********************************************************************/ qtmfsvrlgn(*((int *)(argv[1])), /* Application Identifier (Input) */ argv[2], /* User Identifier (Input) */ *((int *)(argv[3])), /* Length User of Identifier(Input) */ argv[4], /* Authentication String (Input) */ *((int *)(argv[5])), /* Length of Authentication string */ (Input) */ argv[6], /* Client IP Address (Input) */ *((int *)(argv[7])), /* Length of Client IP Address */ (Input) */ (int *)(argv[8]), /* Return Code (Output)*/ argv[9], /* User Profile (Output)*/ argv[10], /* Password (Output)*/ argv[11]); /* Initial Current Library (Output)*/ return; } /* Function Specification *********************************************/ /* */ /* Function Name: qtmfsvrlgn */ /* */ /* Descriptive Name: Server Logon exit function. */ /* */ /* This exit function provides control over user authentication to */ /* an FTP server. */ /* */ /* Notes: */ /* */ /* Dependencies: */ /* */ /* FTP Server Logon exit point QIBM_QTMF_SVR_LOGON was */ /* registered during FTP product installation. */ /* */ /* Restrictions: */ /* */ /* None */ /* */ /* Messages: */ /* */ /* None */ /* */ /* Side Effects: */ /* */ /* None */ /* */ /* Functions/Macros called: */ /* */ /* CheckClientAddress - Check the ClientIPaddr_p input argument.*/ /* memcpy - Copy bytes from source to destination. */ /* memset - Set bytes to value. */ /* strstr - Locate first occurrence of substring. */ /* sprintf - Formatted print to buffer. */ /* */ /* Input: */ /* int ApplId - Application Identifier (Server = 1). */ /* char * UserId_p - User identifier from client program. */ /* (For FTP server, USER subcommand data)*/ /* int Lgth_UserId - Length (in bytes) of user ID string. */ /* char * AuthStr_p - Authentication string from client. */ /* (For FTP server, this is the password)*/ /* int Lgth_AuthStr - Length (bytes) Authentication string. */ /* char * ClientIPaddr_p - Internet Protocol address from which */ /* the session originates. */ /* int * Lgth_ClientIPaddr - Length (in bytes) of IP address. */ /* */ /* Output: */ /* int * ReturnCode: Indicates degree of success of operation: */ /* ReturnCode = 0 - Reject logon. */ /* ReturnCode = 1 - Continue logon; use initial current library*/ /* ReturnCode = 2 - Continue logon; override initial current */ /* library */ /* ReturnCode = 3 - Continue logon; override user, password */ /* ReturnCode = 4 - Continue logon; override user, password, */ /* current library */ /* ReturnCode = 5 - Accept logon; override user profile */ /* ReturnCode = 6 - Accept logon; override user profile, */ /* current library */ /* char * UserProfile - User profile to use for this session */ /* char * Password - Password to use for this session */ /* char * Init_Cur_Lib - Initial current library for this session */ /* */ /* Exit Normal: (See OUTPUT) */ /* */ /* Exit Error: None */ /* */ /* End Function Specification *****************************************/ static void qtmfsvrlgn(int ApplId, /* Entry point */ char *UserId_p, int Lgth_UserId, char *AuthStr_p, int Lgth_AuthStr, char *ClientIPaddr_p, int Lgth_ClientIPaddr, int *ReturnCode, char *UserProfile_p, char *Password_p, char *InitCurrLib_p) { /********************************************************************/ /* Local Variables */ /********************************************************************/ /* The following lists serve as an example of an additional layer */ /* of control over user authentication to an application server. */ /* Here, logon operations using the following user identifiers */ /* will be allowed to continue, but the output parameters returned */ /* by this example exit program will vary depending on which list */ /* a user identifier (UserId_p) is found in. */ /* For example, attempts to logon as FTPUSR11 or FTPUSR2 will be */ /* allowed, and this example exit will return the initial current */ /* library as an output parameter along with a return code of 2. */ /********************************************************************/ /* Continue the logon operation, Return Code = 1 */ char Return1[] = "FTPUSR10 "; /* Continue the logon operation, Return Code = 2 */ char Return2[] = "FTPUSR11 FTPUSR2 "; /* Continue the logon operation, Return Code = 3 */ char Return3[] = "FTPUSR12 FTPUSR3 FTPUSR23 "; /* Continue the logon operation, Return Code = 4 */ char Return4[] = "FTPUSER FTPUSR4 FTPUSR24 FTPUSR94 "; int rc; /* Results of server logon request */ Qsy_USRI0300_T Receiver_var; /* QSYRUSRI API Receiver variable */ int Lgth_Receiver_var; /* Receiver variable length */ char Format_Name[8]; /* Format name buffer */ char User_Id[10]; /* User Identifier buffer */ Qus_EC_t error_code = /* QSYRUSRI API error code structure: */ { sizeof(Qus_EC_t), /* Set bytes provided */ 0, /* Initialize bytes available */ ' ',' ',' ',' ',' ',' ',' ' /* Initialize Exception Id */ }; char *pcTest_p; /* Upper-case User Identifier pointer*/ int i; /* "For" loop counter variable */ /********************************************************************/ /* Code */ /********************************************************************/ /* Test validity of application ID input argument. */ if(1 NEQ ApplId) { /* ERROR - Not FTP server application. */ /* Return Code of 0 is used here to indicate */ /* that an incorrect input argument was received. */ /* The server logon operation will be rejected. */ rc = 0; /* Application ID not valid */ } /* End If the application identifier is NOT for FTP server */ else /* FTP server application identifier */ { /* Validate the client IP address input argument. */ rc = CheckClientAddress(ClientIPaddr_p, Lgth_ClientIPaddr); if(0 NEQ rc) /* Valid, acceptable client address */ { /* Initialize User_Id; used to hold upper-cased user identifier */ memset(User_Id, BLANK, sizeof(User_Id)); /* Initialize pcTest_p to point to UserId_p input argument. */ pcTest_p = UserId_p; /* Uppercase all of the user ID to compare for ANONYMOUS user. */ for(i = 0; i < Lgth_UserId; i++) { User_Id[i] = (char)toupper(*pcTest_p); pcTest_p += 1; } /* If user has logged in as ANONYMOUS. */ if(0 == memcmp("ANONYMOUS ", User_Id, 10)) { /* Determine how to continue with ANONYMOUS logon attempt. */ if(NULL NEQ strstr(Limit, ClientIPaddr_p)) { /* If users system IP address is found in the "Limit" list, */ /* return ReturnCode of 6, user profile and initial */ /* current library values as output parameters. */ memcpy(UserProfile_p, "USERA1 ", 10); memcpy(InitCurrLib_p, "PUBLIC ", 10); rc = 6; } else { /* Users system IP address is NOT found in the "Limit" list,*/ /* return ReturnCode of 5, user profile output parameter; */ /* use the initial current library that is specified by the */ /* user profile information. */ memcpy(UserProfile_p, "USERA1 ", 10); rc = 5; } } /* End If USER is ANONYMOUS */ else /* Else USER is not ANONYMOUS */ { /* Set receiver variable length. */ Lgth_Receiver_var = sizeof(Qsy_USRI0300_T); /* Set return information format. */ memcpy(Format_Name, "USRI0300", sizeof(Format_Name)); /* Set user identifier passed in. */ memset(User_Id, BLANK, sizeof(User_Id)); memcpy(User_Id, UserId_p, Lgth_UserId); /* Call QSYRUSRI - Retrieve User Information API */ QSYRUSRI(&Receiver_var, /* Return Information receiver var */ Lgth_Receiver_var,/* Receiver variable length */ Format_Name, /* Return information format name */ User_Id, /* User ID seeking information */ &error_code); /* Error return information */ /* Check if an error occurred (byte_available not equal 0) */ if(0 NEQ error_code.Bytes_Available) { /* Return ReturnCode of 0 only (Reject logon); */ rc = 0; /* Reject the logon operation */ *ReturnCode = rc; /* Assign result to ReturnCode */ } else /* No error occurred from Retrieve User Info */ { /* (Bytes_Available = 0) */ /* Set current library for user profile. */ memcpy(InitCurrLib_p, Receiver_var.Current_Library, 10); if(NULL NEQ strstr("*CRTDFT ", Receiver_var.Current_Library)) { memcpy(InitCurrLib_p, "FTPDEFAULT", 10); } else { if(NULL NEQ strstr(Return1, UserId_p)) { /* Return ReturnCode of 1 (Continue logon); */ /* Also return user profile and password output */ /* parameters to endure they are ignored by the server.*/ memcpy(UserProfile_p, UserId_p, Lgth_UserId); memcpy(Password_p, AuthStr_p, Lgth_AuthStr); rc = 1; /* Continue the logon operation */ } else { if(NULL NEQ strstr(Return2, UserId_p)) { /* Return ReturnCode of 2, and initial current library*/ /* Also return user profile and password values */ /* even though they will be ignored by the server. */ memcpy(UserProfile_p, UserId_p, Lgth_UserId); memcpy(Password_p, AuthStr_p, Lgth_AuthStr); memcpy(InitCurrLib_p, "FTPEXT2", strlen("FTPEXT2")); rc = 2; /* Continue logon; return InitCurLib */ } else { if(NULL NEQ strstr(Return3, UserId_p)) { /* Return ReturnCode of 3, user profile, password. */ /* Also return initial current library value, */ /* even though it will be ignored. */ memcpy(UserProfile_p, UserId_p, Lgth_UserId); memcpy(Password_p, AuthStr_p, Lgth_AuthStr); memcpy(InitCurrLib_p, "FTPEXT3", strlen("FTPEXT3")); /* Server ignores */ rc = 3; } else { if(NULL NEQ strstr(Return4, UserId_p)) { /*Return ReturnCode of 4, user profile, */ /* password, and initial current library values */ memcpy(UserProfile_p, UserId_p, Lgth_UserId); memcpy(Password_p, AuthStr_p, Lgth_AuthStr); memcpy(InitCurrLib_p, "FTPEXT4", strlen("FTPEXT4")); rc = 4; } else /* This is the default return code for logon */ /* attempts using any user identifier not */ /* explicitly found in one of the four lists in */ /* the local variables section of this function. */ { /*Return ReturnCode of 1, continue logon operation*/ rc = 1; } } } } } } /* End No error occurred (byte_available = 0) */ } /* End Else USER is not ANONYMOUS */ } /* End Valid, acceptable client address */ } /* End FTP server application identifier */ *ReturnCode = rc; return; } /* End program qtmfsvrlgn.c */ /* Function Specification *********************************************/ /* */ /* Function Name: CheckClientAddress */ /* */ /* Descriptive Name: Check the IP address of the originating session */ /* from the input argument (ClientIPaddr_p) to */ /* ensure it is in valid dotted-decimal format, */ /* and that the client system is allowed access. */ /* This is an example of an input validity check. */ /* */ /* Notes: */ /* */ /* Dependencies: */ /* None */ /* */ /* Restrictions: */ /* None */ /* */ /* Messages: */ /* None */ /* */ /* Side Effects: */ /* None */ /* */ /* Functions/Macros called: */ /* */ /* strspn - Search for first occurrence of a string. */ /* */ /* Input: */ /* char * ClientIPaddr_p - Internet Protocol address from which */ /* the session originates. */ /* int * Lgth_ClientIPaddr - Length (in bytes) of IP address. */ /* */ /* Output: */ /* int rc - Return code indicating validity of IP */ /* address from ClientIPaddr_p input. */ /* 0 = Reject the logon operation. */ /* ClientIPaddr_p is one that is not */ /* allowed, or contains a character */ /* that is not valid. */ /* 1 = Continue the logon operation. */ /* */ /* Exit Normal: (See OUTPUT) */ /* */ /* Exit Error: None. */ /* */ /* End Function Specification *****************************************/ static int CheckClientAddress(char *ClientIPaddr_p, /* Entry point */ int Lgth_ClientIPaddr) { /********************************************************************/ /* Local Variables */ /********************************************************************/ int rc; /* Return code */ /********************************************************************/ /* Code */ /********************************************************************/ /* Check that client IP address input argument is dotted-decimal */ /* format of minimum length, with no leading blanks or periods, */ /* and contains only valid characters. */ if((Lgth_ClientIPaddr < 7) || /* Minimum IP address size */ (strspn(ClientIPaddr_p, ValidChars) < Lgth_ClientIPaddr)|| (strspn(ClientIPaddr_p, ".") EQ 1)|| /* Leading '.' in IP */ (strspn(ClientIPaddr_p, " ") EQ 1)) /* Leading blank in IP */ { /* Client's IP address not valid, or contains an incorrect character */ rc = 0; /* Client IP address input argument not valid */ } else { /* Is client system allowed to log in to FTP server? */ if(NULL NEQ strstr(Reject, ClientIPaddr_p)) { /* Return code = 0 - Reject the server logon operation, as the */ /* client IP address is found in the global */ /* "Reject" list. */ rc = 0; /* Reject the logon operation */ } else { /* Continue the server logon operation checks. */ rc = 1; /* Continue the logon operation */ } } return(rc); } #undef _QTMFSVRLGN_C