[E3FT_GPL01] / e3ft_gpl01 / nixprojs / cron / 2006 / php_rsa_auth_20061228 / rsa_securid_auth.c Repository:
ViewVC logotype

View of /e3ft_gpl01/nixprojs/cron/2006/php_rsa_auth_20061228/rsa_securid_auth.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (download) (annotate)
Thu Dec 28 21:58:18 2006 UTC (3 years, 8 months ago) by dashley
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +5 -2 lines
Extra lines removed.
//$Header: /hl/cvsroots/e3ft_gpl01/e3ft_gpl01/nixprojs/cron/2006/php_rsa_auth_20061228/rsa_securid_auth.c,v 1.2 2006/12/28 21:58:18 dashley Exp $
//
//rsa_securid_auth.c :  Authenticates a userid and Securid FOB value
//                      passed via the command-line.
//                     
//                      Designed to be called via a PHP script with
//                      UID/GID apch443a.
//
//Invocation:
//  - rsa_securid_auth username fobvalue
//      Attempts to authenticate the username with the FOB value.
//
//  - rsa_securid_auth username fobvalue1 fobvalue2
//      This invocation form will be used if a previous invocation
//      has indicated that the next FOB value is required.  It was
//      determined empirically that the software has a wide enough
//      window that using two successive FOB values (i.e. no "next"
//      sequence, i.e. the first FOB value is "late") will work
//      fine to cover this case.  This makes for easier web
//      programming.
//
//Return values:
//   All information is passed back in the exit code.  Possible
//   values:
//      0 : Authentication successful (either with one or two FOB
//          codes).
//      1 : Next code invocation required.
//      2 : Authentication failed due to return values from the
//          RSA software indicating authentication failure.
//      3 : Authentication failed because the RSA software indicated
//          an error condition.
//      4 : Authentication failed because this program detected
//          an error condition (most likely ill-formed parameters).
//

#ifdef WIN32
#include <windows.h>
#define sleep(x)    Sleep(x*1000)
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef WIN32
#include <termio.h>
#include <fcntl.h>
#endif

// in NT this allows using the aceclnt.lib file for linking
#define USE_ACE_AGENT_API_PROTOTYPES
#include "acexport.h"

#ifndef WIN32
int sd_echo_off(void);
int sd_echo_on(void);
#endif


//If the passed character is an upper-case letter, converts it to lower-case.
//all other data is left unchanged.
//
static char char_to_lower_case(char char_in)
   {
   switch(char_in)
      {
      default:
	 return(char_in);
         break;
      case 'A':
	 return('a');
         break;
      case 'B':
	 return('b');
         break;
      case 'C':
	 return('c');
         break;
      case 'D':
	 return('d');
         break;
      case 'E':
	 return('e');
         break;
      case 'F':
	 return('f');
         break;
      case 'G':
	 return('g');
         break;
      case 'H':
	 return('h');
         break;
      case 'I':
	 return('I');
         break;
      case 'J':
	 return('j');
         break;
      case 'K':
	 return('k');
         break;
      case 'L':
	 return('l');
         break;
      case 'M':
	 return('m');
         break;
      case 'N':
	 return('n');
         break;
      case 'O':
	 return('o');
         break;
      case 'P':
	 return('p');
         break;
      case 'Q':
	 return('q');
         break;
      case 'R':
	 return('r');
         break;
      case 'S':
	 return('s');
         break;
      case 'T':
	 return('t');
         break;
      case 'U':
	 return('u');
         break;
      case 'V':
	 return('v');
         break;
      case 'W':
	 return('w');
         break;
      case 'X':
	 return('x');
         break;
      case 'Y':
	 return('y');
         break;
      case 'Z':
	 return('z');
         break;
      }
   }


//Returns 1 if the passed character is a digit, or 0 otherwise.
//
static int is_a_digit(char char_in)
   {
   switch(char_in)
      {
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
	 return(1);
         break;
      default:
         return(0);
         break;
      }
   }

//Returns 1 if the passed character is a lower-case letter, or 0 otherwise.
//
static int is_a_lc_letter(char char_in)
   {
   switch(char_in)
      {
      case 'a':
      case 'b':
      case 'c':
      case 'd':
      case 'e':
      case 'f':
      case 'g':
      case 'h':
      case 'i':
      case 'j':
      case 'k':
      case 'l':
      case 'm':
      case 'n':
      case 'o':
      case 'p':
      case 'q':
      case 'r':
      case 's':
      case 't':
      case 'u':
      case 'v':
      case 'w':
      case 'x':
      case 'y':
      case 'z':
	 return(1);
         break;
      default:
         return(0);
         break;
      }
   }


//Returns 1 if the passed character is a valid first character of a username
//or 0 otherwise.
//
static int is_valid_username_first_char(char char_in)
   {
   return(is_a_lc_letter(char_in));
   }


//Returns 1 if the passed character is a non-first character of a username
//or 0 otherwise.
//
static int is_valid_username_non_first_char(char char_in)
   {
   return(is_a_lc_letter(char_in) | is_a_digit(char_in));
   }


//Copies a string from src to dst, up to a maximum of n characters.
//The n characters exceed the zero terminator.  If the limit is exceeded
//the string is truncated.
//
static void str_guarded_copy(char *dst, const char *src, int n)
  {
  int i;

  for (i=0; (i<(n-1)) && (src[i]); i++)
     {
     dst[i] = src[i];
     }

  dst[i] = 0;
  }


// a simple main() to drive this program
int main(int argc, char* argv[])
   {
   SDI_HANDLE  aceHdl;
   SD_CHAR     resp[128];
   SD_CHAR     prompt[512];
   SD_I32      promptLen;
   SD_I32      nextRespLen;
   SD_I32      respTimeout;
   SD_BOOL     moreFlag;
   SD_BOOL     noechoFlag;
   SD_I32      AuthStatus;
   int i;
   int ret;
   int rv;
   char username [100];
   char passcode1[100];
   char passcode2[100];

   if ((argc != 3) && (argc != 4))
      {
      exit(4);
      }

   //Copy over the username.  It has to be 20 characters or less, all letters and numbers,
   //starting with a letter.
   str_guarded_copy(username, argv[1], sizeof(username));

   //The username must be at least one character.
   if (! strlen(username))
      exit(4);

   //Convert all characters of the username to lower-case if they are upper.
   for (i=0; i<strlen(username); i++)
      username[i] = char_to_lower_case(username[i]);

   //The first character of the username must be valid for a user name.
   if (! is_valid_username_first_char(username[0]))
      exit(4);

   //Subsequent characters of the username must be valid.
   for (i=1; i<strlen(username); i++)
      if (! is_valid_username_non_first_char(username[i]))
         exit(4);

   //The first passcode must be exactly six digits and must be all digits.
   str_guarded_copy(passcode1, argv[2], sizeof(passcode1));
   if (strlen(passcode1) != 6)
      return(4);
   for (i=0; i<strlen(passcode1); i++)
      if (! is_a_digit(passcode1[i]))
         exit(4);

   //The second passcode, if supplied, must be exactly six digits and must be all digits.
   if (argc >= 4)
      {
      str_guarded_copy(passcode2, argv[3], sizeof(passcode2));
      if (strlen(passcode2) != 6)
         return(4);
      for (i=0; i<strlen(passcode2); i++)
         if (! is_a_digit(passcode2[i]))
            exit(4);
      }
   
   if (!AceInitializeEx(/* "/etc/rsaauthmgr/ace/data/" */ "/etc/rsa_securid_apch443a_auth", NULL, 0))
      {
      exit(3);
      }

   if (SD_Init(&aceHdl) != ACM_OK) /* initialize socket */
      {
      exit(3);
      }

   ret = SD_Lock(aceHdl, username);

   if (ret != ACM_OK)
      {
      exit(3);
      }
 
   ret = SD_Check(aceHdl, passcode1, username);

   switch (ret)
      {
      case ACM_OK:
	 rv = 0;
         break;

      case ACM_ACCESS_DENIED:
	 rv = 2;
         break;

      case ACE_UNDEFINED_PASSCODE:
         rv = 2;
         break;

      case ACE_UNDEFINED_USERNAME:
	 rv = 2;
         break;

      case ACE_ERR_INVALID_HANDLE:
	 rv = 2;
         break;

      case ACM_NEXT_CODE_REQUIRED:
         if (argc == 4)
	    {
	    ret = SD_Next(aceHdl, passcode2);

	    if (ret == ACM_OK)
	       {
	       rv = 0;
               }
            else
	       {
	       rv = 2;
               }
            }
	 else
	    {
	    rv = 1;
            }

        break;

      case ACM_NEW_PIN_REQUIRED:
	 rv = 2;
         break;

      default:
	 rv = 2;
         break;
      }

   SD_Close(aceHdl);    /* Shutdown the network connection */


   return(rv); 
   }


//$Log: rsa_securid_auth.c,v $
//Revision 1.2  2006/12/28 21:58:18  dashley
//Extra lines removed.
//
//Revision 1.1  2006/12/28 21:57:49  dashley
//Initial checkin.

David T. Ashley
ViewVC Help
Powered by ViewVC 1.0.5