(file) Return to PAMBasicAuthenticatorUnix.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Security / Authentication

Diff for /pegasus/src/Pegasus/Security/Authentication/PAMBasicAuthenticatorUnix.cpp between version 1.12 and 1.30

version 1.12, 2003/03/13 23:09:35 version 1.30, 2005/07/19 19:14:48
Line 1 
Line 1 
 //%/////////////////////////////////////////////////////////////////////////////  //%2005////////////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,  // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
 // The Open Group, Tivoli Systems  // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
   // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
   // IBM Corp.; EMC Corporation, The Open Group.
   // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
   // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
   // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
   // EMC Corporation; VERITAS Software Corporation; The Open Group.
 // //
 // Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to // of this software and associated documentation files (the "Software"), to
Line 26 
Line 32 
 // Modified By: Yi Zhou, Hewlett-Packard Company(yi_zhou@hp.com) // Modified By: Yi Zhou, Hewlett-Packard Company(yi_zhou@hp.com)
 //            : Sushma Fernandes, Hewlett-Packard Company //            : Sushma Fernandes, Hewlett-Packard Company
 //                (sushma_fernandes@hp.com) //                (sushma_fernandes@hp.com)
   //                Josephine Eskaline Joyce (jojustin@in.ibm.com) for PEP#101
 // //
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
 #include <Pegasus/Common/System.h> #include <Pegasus/Common/System.h>
 #include <Pegasus/Common/Tracer.h> #include <Pegasus/Common/Tracer.h>
 #include <Pegasus/Common/Destroyer.h>  
 #include <Pegasus/Config/ConfigManager.h> #include <Pegasus/Config/ConfigManager.h>
   #include <Pegasus/Common/FileSystem.h>
   #include <Pegasus/Common/Signal.h>
  
 #ifdef PEGASUS_OS_HPUX  #if defined (PEGASUS_OS_HPUX)
 #include <pwd.h>  
 #include <prot.h> #include <prot.h>
 #endif #endif
  
 #include "PAMBasicAuthenticator.h"  #if defined (PEGASUS_USE_PAM_STANDALONE_PROC)
   #include <Pegasus/Common/Logger.h>
   #include <Pegasus/Common/IPC.h>
   #include <pwd.h>
   #include <sys/stat.h>
   #include <unistd.h>
   #include <sys/types.h>
   #include <sys/resource.h>
   #if defined(PEGASUS_HAS_SIGNALS)
   # include <sys/wait.h>
   #endif
   #endif
   
  
   #include "PAMBasicAuthenticator.h"
  
 PEGASUS_USING_STD; PEGASUS_USING_STD;
  
Line 48 
Line 68 
  
 #include <security/pam_appl.h> #include <security/pam_appl.h>
  
   #if defined(PEGASUS_OS_LSB)
   #ifndef PAM_MAX_MSG_SIZE
   #define PAM_MAX_MSG_SIZE      512
   #endif
   #endif
   
 #define BUFFERLEN 1024 #define BUFFERLEN 1024
  
 /** /**
Line 55 
Line 81 
 */ */
 static const String BASIC_CHALLENGE_HEADER = "WWW-Authenticate: Basic \""; static const String BASIC_CHALLENGE_HEADER = "WWW-Authenticate: Basic \"";
  
   Mutex PAMBasicAuthenticator::_authSerializeMutex;
  
 /** Service name for pam_start */ /** Service name for pam_start */
 const char *service = "wbem"; const char *service = "wbem";
Line 88 
Line 115 
     _realm.append(":");     _realm.append(":");
     _realm.append(port);     _realm.append(port);
  
 #ifdef PEGASUS_OS_HPUX  
     //  
     // get the configured usePAMAuthentication flag  
     //  
   
     if (String::equal(  
         configManager->getCurrentValue("usePAMAuthentication"), "true"))  
     {  
         _usePAM = true;  
     }  
     else  
     {  
         _usePAM = false;  
     }  
 #endif  
   
   
     PEG_METHOD_EXIT();     PEG_METHOD_EXIT();
 } }
  
Line 126 
Line 136 
  
     Boolean authenticated;     Boolean authenticated;
  
 #ifndef PEGASUS_OS_HPUX  #if !defined(PEGASUS_USE_PAM_STANDALONE_PROC)
     authenticated = _authenticateByPAM(userName, password);     authenticated = _authenticateByPAM(userName, password);
 #else #else
     if (_usePAM)  
     {  
         //  
         // Check if the system has been converted to a trusted system.  
         // ATTN-SF-P3-20030211 - This code to use getpwpwnam on a trusted sytem has  
         // been added as there is a known problem with trusted mode with PAM based  
         // Authentication.  
         //  
   
         if (iscomsec())  
         {  
             authenticated            = false;  
             String currPassword      = String::EMPTY;  
             String encryptedPassword = String::EMPTY;  
             String saltStr           = String::EMPTY;  
             char*  userNamecstr      = strcpy(  
                                    new char[strlen(userName.getCString()) + 1],  
                                    userName.getCString());  
   
             // system is a trusted system  
             // use interface getprpwnam to get pr_passwd structure  
   
             struct pr_passwd * pwd;  
   
             // getprpwnam returns a pointer to a pr_passwd structure upon success  
             if ( (pwd = getprpwnam(userNamecstr)) != NULL)  
             {  
                Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4,  
                   "getprpwnam call successful.");  
                // get user's password from pr_passwd structure  
                 currPassword = pwd->ufld.fd_encrypt;  
             }  
             delete [] userNamecstr;  
   
             //             //
             // Check if the specified password mathches user's password          // Mutex to Serialize Authentication calls.
             //             //
             saltStr = currPassword.subString(0,2);  
   
             encryptedPassword = System::encryptPassword(password.getCString(),  
                                 saltStr.getCString());  
   
             if (String::equal(currPassword, encryptedPassword))  
             {  
                 authenticated = true;  
                 Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4,                 Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4,
                   "Password match successful.");             "Authentication Mutex lock.");
             }          AutoMutex lock(_authSerializeMutex);
         }          authenticated = _pamBasicAuthenticatorStandAlone.authenticate(
         else              userName, password);
         {  
             authenticated = _authenticateByPAM(userName, password);  
         }  
     }  
     else  
     {  
         authenticated = _authenticateByPwnam(userName.getCString(), password);  
     }  
 #endif #endif
  
     PEG_METHOD_EXIT();     PEG_METHOD_EXIT();
Line 259 
Line 219 
     return (authenticated);     return (authenticated);
 } }
  
 #ifdef PEGASUS_OS_HPUX  Boolean PAMBasicAuthenticator::validateUser(const String& userName)
 Boolean PAMBasicAuthenticator::_authenticateByPwnam(  
     const char * userName,  
     const String& password)  
 { {
     PEG_METHOD_ENTER(TRC_AUTHENTICATION,     PEG_METHOD_ENTER(TRC_AUTHENTICATION,
         "PAMBasicAuthenticator::_authenticateByPwnam()");          "PAMBasicAuthenticator::validateUser()");
  
     Boolean authenticated = false;     Boolean authenticated = false;
  
     String currPassword         = String::EMPTY;  #if !defined(PEGASUS_USE_PAM_STANDALONE_PROC)
     String encryptedPassword    = String::EMPTY;      struct pam_conv pconv;
     String saltStr              = String::EMPTY;      pam_handle_t *phandle;
       char *name;
       APP_DATA mydata;
   
       const char *service = "wbem";
       pconv.conv = PAMBasicAuthenticator::pamValidateUserCallback;
       pconv.appdata_ptr = &mydata;
  
     //     //
     // check if the system has been converted to a trusted system.      // Call pam_start since you need to before making any other PAM calls
     //     //
       if ( pam_start(service,
     if (iscomsec())       (const char *)userName.getCString(), &pconv, &phandle) != PAM_SUCCESS)
     {     {
         // system is a trusted system          PEG_METHOD_EXIT();
         // use interface getprpwnam to get pr_passwd structure          return (authenticated);
       }
         struct pr_passwd * pwd;  
   
         char* _userName = strcpy(new char[strlen(userName) + 1], userName);  
  
         // getprpwnam returns a pointer to a pr_passwd structure  upon success      //
         if ( (pwd = getprpwnam(_userName)) != NULL)      // Call pam_acct_mgmt, to check if the user account is valid. This includes
       // checking for account expiration, as well as verifying access
       // hour restrictions.
       //
       if ( pam_acct_mgmt(phandle, 0) == PAM_SUCCESS )
         {         {
            Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4,          authenticated = true;
               "getprpwnam successful.");  
            // get user's password from pr_passwd structure  
             currPassword = pwd->ufld.fd_encrypt;  
         }         }
  
         delete [] _userName;  
     }  
     else  
     {  
         //         //
         // system is not a trusted system      //Call pam_end to end our PAM work
         // use reentrant interface getpwnam_r to get password structure  
         //         //
         struct passwd pwd;      pam_end(phandle, 0);
         struct passwd *result;  
         char pwdBuffer[BUFFERLEN];  
  
         // getpwnam_r returns zero upon success  #else
         if (getpwnam_r(userName, &pwd, pwdBuffer, BUFFERLEN, &result) == 0)      //
         {      // Mutex to Serialize Authentication calls.
       //
            Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4,            Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4,
               "getpwnam_r successful.");             "Authentication Mutex lock.");
            // get user's password from password file      AutoMutex lock(_authSerializeMutex);
             currPassword = pwd.pw_passwd;      authenticated = _pamBasicAuthenticatorStandAlone.validateUser(
         }              userName);
   #endif
   
       PEG_METHOD_EXIT();
       return (authenticated);
   
     }     }
  
   Sint32 PAMBasicAuthenticator::pamValidateUserCallback( Sint32 num_msg,
   #if defined (PEGASUS_OS_LINUX)
           const struct pam_message **msg,
   #else
           struct pam_message **msg,
   #endif
           struct pam_response **resp,
           void *appdata_ptr)
   {
       PEG_METHOD_ENTER(TRC_AUTHENTICATION,
           "PAMBasicAuthenticator::pamValidateUserCallback()");
   
       //
       // Allocate the response buffers
     //     //
     // Check if the specified password mathches user's password      if ( num_msg > 0 )
       {
     //     //
     saltStr = currPassword.subString(0,2);          // Since resp->resp needs to be initialized in all possible scenarios,
           // use calloc for memory allocation.
     encryptedPassword = System::encryptPassword(password.getCString(),          //
                         saltStr.getCString());          *resp =
             (struct pam_response *)calloc(num_msg, sizeof(struct pam_response));
  
     if (String::equal(currPassword, encryptedPassword))          if ( *resp == NULL )
     {     {
         authenticated = true;              PEG_METHOD_EXIT();
         Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4,              return PAM_BUF_ERR;
                   "Password match successful.");  
     }     }
       }
       else
       {
     PEG_METHOD_EXIT();     PEG_METHOD_EXIT();
           return PAM_CONV_ERR;
       }
  
     return (authenticated);      PEG_METHOD_EXIT();
       return PAM_SUCCESS;
 } }
 #endif  
  
 // //
 // Create authentication response header // Create authentication response header
Line 380 
Line 359 
     //     //
     if ( num_msg > 0 )     if ( num_msg > 0 )
     {     {
         *resp = (struct pam_response *)malloc(sizeof(struct pam_response)*num_msg);          //
           // Since resp->resp needs to be initialized in all possible scenarios,
           // use calloc for memory allocation.
           //
           *resp = (struct pam_response *)calloc(num_msg, sizeof(struct pam_response));
  
         if ( *resp == NULL )         if ( *resp == NULL )
         {         {
Line 418 
Line 401 
     return PAM_SUCCESS;     return PAM_SUCCESS;
 } }
  
   /** Routines to access PAM Authentication via a standalone process **/
   
   #if defined(PEGASUS_USE_PAM_STANDALONE_PROC)
   
   int     fd_1[2], fd_2[2];
   Boolean continue_PAMauthentication;
   Boolean printed_err_since_success=false;
   
   const String PAMBasicAuthenticatorStandAlone::PAM_OPERATION_SUCCESS = "T";
   
   const String PAMBasicAuthenticatorStandAlone::OPERATION_PAM_AUTHENTICATION = "A";
   
   const String PAMBasicAuthenticatorStandAlone::OPERATION_PAM_ACCT_MGMT = "M";
   
   /* constructor. */
   PAMBasicAuthenticatorStandAlone::PAMBasicAuthenticatorStandAlone()
   {
       PEG_METHOD_ENTER(TRC_AUTHENTICATION,
           "PAMBasicAuthenticatorStandAlone::PAMBasicAuthenticatorStandAlone()");
   
   #if defined(PEGASUS_HAS_SIGNALS)
       _pid = -1;
   #endif
   
       _createPAMStandalone();
   
       SignalHandler::ignore(PEGASUS_SIGPIPE);
   
       PEG_METHOD_EXIT();
   }
   
   /* destructor. */
   PAMBasicAuthenticatorStandAlone::~PAMBasicAuthenticatorStandAlone()
   {
       PEG_METHOD_ENTER(TRC_AUTHENTICATION,
           "PAMBasicAuthenticatorStandAlone::~PAMBasicAuthenticatorStandAlone()");
   
   #if defined(PEGASUS_HAS_SIGNALS)
       // Harvest the status of the previous standalone process, if any
       if (_pid != -1)
       {
           waitpid(_pid, 0, WNOHANG);
           _pid = -1;
       }
   #endif
   
       PEG_METHOD_EXIT();
   }
   
   Boolean PAMBasicAuthenticatorStandAlone::authenticate(
       const String& userName,
       const String& password)
   {
       PEG_METHOD_ENTER(TRC_AUTHENTICATION,
           "PAMBasicAuthenticatorStandAlone::authenticate()");
   
       Boolean authenticated = false;
   
       // Send over the username ...
       if (continue_PAMauthentication)
       {
           //
           // On a broken connection, try restarting the authentication process
           // and resend username.
           //
           if (_writeString (userName) ==
                   PAMBasicAuthenticatorStandAlone::BROKEN_CONNECTION)
           {
               _restartProcess();
               _writeString (userName);
           }
       }
   
       // Send over the password ...
       if (continue_PAMauthentication)
       {
           _writeString (password);
       }
   
       // Send over the operation code.
       if (continue_PAMauthentication)
       {
           _writeString (OPERATION_PAM_AUTHENTICATION);
       }
   
       // Now read back the PAM Authentication status value (T/F)
       if (continue_PAMauthentication)
       {
           if (_readString() == PAM_OPERATION_SUCCESS)
           {
               authenticated = true;
               printed_err_since_success = false;
           }
       }
   
       PEG_METHOD_EXIT();
       return (authenticated);
   }
   
   Boolean PAMBasicAuthenticatorStandAlone::validateUser(
       const String& userName)
   {
       PEG_METHOD_ENTER(TRC_AUTHENTICATION,
           "PAMBasicAuthenticatorStandAlone::validateUser()");
   
       Boolean authenticated = false;
   
       // Send over the username ...
       if (continue_PAMauthentication)
       {
           //
           // On a broken connection, try restarting the authentication process
           // and resend username.
           //
           if (_writeString (userName) ==
                   PAMBasicAuthenticatorStandAlone::BROKEN_CONNECTION)
           {
               _restartProcess();
               _writeString(userName);
           }
       }
   
       // Send over the password ...
       if (continue_PAMauthentication)
       {
           _writeString(String::EMPTY);
       }
   
       // Send over the operation code.
       if (continue_PAMauthentication)
       {
           _writeString (OPERATION_PAM_ACCT_MGMT);
       }
   
       // Now read back the PAM Authentication status value (T/F)
       if (continue_PAMauthentication)
       {
           if (_readString() == PAM_OPERATION_SUCCESS)
           {
               authenticated = true;
               printed_err_since_success = false;
           }
       }
   
       PEG_METHOD_EXIT();
       return (authenticated);
   }
   
   PAMBasicAuthenticatorStandAlone::_Status
            PAMBasicAuthenticatorStandAlone::_writeString(const String& text)
   {
       char        line[BUFFERLEN];
       int         n, ret_code;
       PAMBasicAuthenticatorStandAlone::_Status    status =
                           PAMBasicAuthenticatorStandAlone::SUCCESS;
   
       CString copy_of_text=text.getCString();
       n = strlen(copy_of_text);
   
       sprintf(line, "%4u%s", n, (const char*)copy_of_text);
       n = strlen(line);
   
       continue_PAMauthentication = true;
       ret_code = write(fd_1[1], line, n);
   
       if (ret_code != n)
       {
           continue_PAMauthentication = false;
           status = PAMBasicAuthenticatorStandAlone::OTHER_ERROR;
   
           if (errno == EPIPE)
           {
               status = PAMBasicAuthenticatorStandAlone::BROKEN_CONNECTION;
           }
           if (printed_err_since_success == false)
           {
               printed_err_since_success = true;
               Logger::put(Logger::ERROR_LOG, "CIMServer",
                           Logger::SEVERE,
                          "Error processing PAM Authentication request (write).");
           }
       }
   
       return status;
   }
   
   
   void PAMBasicAuthenticatorStandAlone::_restartProcess(void)
   {
       _createPAMStandalone();
   }
   
   String PAMBasicAuthenticatorStandAlone::_readString()
   {
       char authReply[10];
   
       authReply[0] = '\0';
       int n = read(fd_2[0], authReply, 2);  /* read back the reply */
   
       if (n < 0)
       {
           continue_PAMauthentication = false;
           if (printed_err_since_success == false)
           {
               printed_err_since_success = true;
               //L10N TODO
               Logger::put(Logger::ERROR_LOG, "CIMServer",
                 Logger::SEVERE,
                "Error processing PAM Authentication request (read).");
           }
       }
       else
       {
           authReply[n] = '\0';
       }
   
       return (String(authReply));
   }
   
   void PAMBasicAuthenticatorStandAlone::_createPAMStandalone()
   {
       pid_t   pid;
   
   #if defined(PEGASUS_HAS_SIGNALS)
       // Harvest the status of the previous standalone process, if any
       if (_pid != -1)
       {
           waitpid(_pid, 0, WNOHANG);
           _pid = -1;
       }
   #endif
   
       continue_PAMauthentication = true;
       if (pipe(fd_1) < 0)   // Pipe to write to authentication proc
       {
           continue_PAMauthentication = false;
           if (printed_err_since_success == false)
           {
               printed_err_since_success = true;
               //L10N TODO
               Logger::put(Logger::ERROR_LOG, "CIMServer",
                     Logger::SEVERE,
                     "Error processing PAM Authentication request (pipe).");
           }
       }
       if (continue_PAMauthentication)
       {
           if (pipe(fd_2) < 0)   // Pipe to read from the authentication proc
           {
               continue_PAMauthentication = false;
               if (printed_err_since_success == false)
               {
                   printed_err_since_success = true;
                   //L10N TODO
                   Logger::put(Logger::ERROR_LOG, "CIMServer",
                         Logger::SEVERE,
                         "Error processing PAM Authentication request (pipe).");
               }
           }
       }
   
       if (continue_PAMauthentication)
       {
           if ((pid = fork()) < 0)
           {
               continue_PAMauthentication = false;
               if (printed_err_since_success == false)
               {
                   printed_err_since_success = true;
                   //L10N TODO
                   Logger::put(Logger::ERROR_LOG, "CIMServer",
                         Logger::SEVERE,
                         "Error processing PAM Authentication request (fork).");
               }
           }
           else if (pid > 0)       // This is the PARENT side of the fork
           {
               close(fd_1[0]);     // close read end on 1st pipe
               close(fd_2[1]);     // close write end on 2nd pipe
   #if defined(PEGASUS_HAS_SIGNALS)
               _pid = pid;
   #endif
           }
           else                     // This is the CHILD side of the fork
           {
               close(fd_1[1]);      // close write end on 1st pipe
               close(fd_2[0]);      // close read end on 2nd pipe
               if (fd_1[0] != STDIN_FILENO)
               {
                   if (dup2(fd_1[0], STDIN_FILENO) == -1)
                   {
                       continue_PAMauthentication = false;
                       if (printed_err_since_success == false)
                       {
                           printed_err_since_success = true;
                           //L10N TODO
                           Logger::put(Logger::ERROR_LOG, "CIMServer",
                                 Logger::SEVERE,
                                 "Error processing PAM Authentication request (dup2).");
                       }
                   }
                   close(fd_1[0]);  // don't need this after dup2
               }
               if (continue_PAMauthentication)
               {
                   if (fd_2[1] != STDOUT_FILENO)
                   {
                       if (dup2(fd_2[1], STDOUT_FILENO) == -1)
                       {
                           continue_PAMauthentication = false;
                           if (printed_err_since_success == false)
                           {
                               printed_err_since_success = true;
                               //L10N TODO
                               Logger::put(Logger::ERROR_LOG, "CIMServer",
                                   Logger::SEVERE,
                                   "Error processing PAM Authentication request (dup2).");
                           }
                       }
                       close(fd_2[1]);   // don't need this after dup2
                   }
                   if (continue_PAMauthentication)
                   {
                       //
                       // Get environment variables:
                       //
                       String certpath = ConfigManager::getHomedPath(
                           PEGASUS_PAM_STANDALONE_PROC_NAME);
                       if (execl((const char*)certpath.getCString(),
                                 (const char*)certpath.getCString(), (char*)0) < 0)
                       {
                           continue_PAMauthentication = false;
                           if (printed_err_since_success == false)
                           {
                               printed_err_since_success = true;
                               //L10N TODO
                               Logger::put(Logger::ERROR_LOG, "CIMServer",
                                   Logger::SEVERE,
                                   "Error creating PAM Authentication process (execl).");
                           }
                           exit(0);
                       }
                   }
               }
           }
       }
   }
   
   #endif  /* if defined(PEGASUS_OS_HPUX) || ... */
   
   
   
   
   
 PEGASUS_NAMESPACE_END PEGASUS_NAMESPACE_END
   


Legend:
Removed from v.1.12  
changed lines
  Added in v.1.30

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2