version 1.2, 2002/05/03 23:37:22
|
version 1.12, 2003/03/13 23:09:35
|
|
|
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001 BMC Software, Hewlett-Packard Company, IBM, |
// Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM, |
// The Open Group, Tivoli Systems | // The Open Group, Tivoli Systems |
// | // |
// Permission is hereby granted, free of charge, to any person obtaining a |
// Permission is hereby granted, free of charge, to any person obtaining a copy |
// copy of this software and associated documentation files (the "Software"), |
// of this software and associated documentation files (the "Software"), to |
// to deal in the Software without restriction, including without limitation |
// deal in the Software without restriction, including without limitation the |
// the rights to use, copy, modify, merge, publish, distribute, sublicense, |
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
// and/or sell copies of the Software, and to permit persons to whom the |
// sell copies of the Software, and to permit persons to whom the Software is |
// Software is furnished to do so, subject to the following conditions: |
// furnished to do so, subject to the following conditions: |
// |
// |
// The above copyright notice and this permission notice shall be included in |
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN |
// all copies of substantial portions of this software. |
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED |
// |
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
// DEALINGS IN THE SOFTWARE. |
|
// | // |
//============================================================================== | //============================================================================== |
// | // |
// Author: Nag Boranna, Hewlett-Packard Company(nagaraja_boranna@hp.com) | // Author: Nag Boranna, Hewlett-Packard Company(nagaraja_boranna@hp.com) |
// | // |
// Modified By: |
// Modified By: Yi Zhou, Hewlett-Packard Company(yi_zhou@hp.com) |
|
// : Sushma Fernandes, Hewlett-Packard Company |
|
// (sushma_fernandes@hp.com) |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
#include <security/pam_appl.h> |
|
|
|
#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/Common/Destroyer.h> |
#include <Pegasus/Config/ConfigManager.h> | #include <Pegasus/Config/ConfigManager.h> |
| |
|
#ifdef PEGASUS_OS_HPUX |
|
#include <pwd.h> |
|
#include <prot.h> |
|
#endif |
|
|
#include "PAMBasicAuthenticator.h" | #include "PAMBasicAuthenticator.h" |
| |
| |
|
|
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
|
#include <security/pam_appl.h> |
|
|
|
#define BUFFERLEN 1024 |
| |
/** | /** |
Constant representing the Basic authentication challenge header. | Constant representing the Basic authentication challenge header. |
|
|
/** Service name for pam_start */ | /** Service name for pam_start */ |
const char *service = "wbem"; | const char *service = "wbem"; |
| |
char* userPassword = 0; |
typedef struct |
|
{ |
|
CString userPassword; |
|
} APP_DATA; |
| |
/* constructor. */ | /* constructor. */ |
PAMBasicAuthenticator::PAMBasicAuthenticator() | PAMBasicAuthenticator::PAMBasicAuthenticator() |
|
|
// | // |
ConfigManager* configManager = ConfigManager::getInstance(); | ConfigManager* configManager = ConfigManager::getInstance(); |
| |
String port = configManager->getCurrentValue("port"); |
String port = configManager->getCurrentValue("httpPort"); |
| |
// | // |
// Create realm that will be used for Basic challenges | // Create realm that will be used for Basic challenges |
|
|
_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(); |
} | } |
| |
|
|
PEG_METHOD_ENTER(TRC_AUTHENTICATION, | PEG_METHOD_ENTER(TRC_AUTHENTICATION, |
"PAMBasicAuthenticator::authenticate()"); | "PAMBasicAuthenticator::authenticate()"); |
| |
|
Boolean authenticated; |
|
|
|
#ifndef PEGASUS_OS_HPUX |
|
authenticated = _authenticateByPAM(userName, password); |
|
#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 |
|
// |
|
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, |
|
"Password match successful."); |
|
} |
|
} |
|
else |
|
{ |
|
authenticated = _authenticateByPAM(userName, password); |
|
} |
|
} |
|
else |
|
{ |
|
authenticated = _authenticateByPwnam(userName.getCString(), password); |
|
} |
|
#endif |
|
|
|
PEG_METHOD_EXIT(); |
|
return (authenticated); |
|
} |
|
|
|
Boolean PAMBasicAuthenticator::_authenticateByPAM( |
|
const String& userName, |
|
const String& password) |
|
{ |
|
PEG_METHOD_ENTER(TRC_AUTHENTICATION, |
|
"PAMBasicAuthenticator::_authenticateByPAM()"); |
|
|
Boolean authenticated = false; | Boolean authenticated = false; |
struct pam_conv pconv; | struct pam_conv pconv; |
pam_handle_t *phandle; | pam_handle_t *phandle; |
char *name; | char *name; |
|
APP_DATA mydata; |
| |
pconv.conv = PAMBasicAuthenticator::PAMCallback; |
// |
pconv.appdata_ptr = NULL; |
// Store the password for PAM authentication |
|
// |
|
mydata.userPassword = password.getCString(); |
| |
ArrayDestroyer<char> p(password.allocateCString()); |
pconv.conv = PAMBasicAuthenticator::PAMCallback; |
userPassword = p.getPointer(); |
pconv.appdata_ptr = &mydata; |
| |
ArrayDestroyer<char> user(userName.allocateCString()); |
// WARNING: Should only be uncommented for debugging in a secure environment. |
|
// Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4, |
|
// "PAMBasicAuthenticator::_authenticateByPAM() - userName = %s; userPassword = %s", |
|
// (const char *)userName.getCString(), (const char *)password.getCString()); |
| |
// | // |
//Call pam_start since you need to before making any other PAM calls | //Call pam_start since you need to before making any other PAM calls |
// | // |
if ( ( pam_start(service, | if ( ( pam_start(service, |
(const char *)user.getPointer(), &pconv, &phandle) ) != PAM_SUCCESS ) |
(const char *)userName.getCString(), &pconv, &phandle) ) != PAM_SUCCESS ) |
{ | { |
userPassword = 0; |
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
return (authenticated); | return (authenticated); |
} | } |
|
|
// | // |
if ( ( pam_authenticate(phandle, 0) ) == PAM_SUCCESS ) | if ( ( pam_authenticate(phandle, 0) ) == PAM_SUCCESS ) |
{ | { |
|
Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4, |
|
"pam_authenticate successful."); |
// | // |
//Call pam_acct_mgmt, to check if the user account is valid. This includes | //Call pam_acct_mgmt, to check if the user account is valid. This includes |
//checking for password and account expiration, as well as verifying access | //checking for password and account expiration, as well as verifying access |
|
|
// | // |
if ( ( pam_acct_mgmt(phandle, 0) ) == PAM_SUCCESS ) | if ( ( pam_acct_mgmt(phandle, 0) ) == PAM_SUCCESS ) |
{ | { |
|
Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4, |
|
"pam_acct_mgmt successful."); |
authenticated = true; | authenticated = true; |
} | } |
} | } |
|
|
// | // |
pam_end(phandle, 0); | pam_end(phandle, 0); |
| |
userPassword = 0; |
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
| |
return (authenticated); | return (authenticated); |
} | } |
| |
|
#ifdef PEGASUS_OS_HPUX |
|
Boolean PAMBasicAuthenticator::_authenticateByPwnam( |
|
const char * userName, |
|
const String& password) |
|
{ |
|
PEG_METHOD_ENTER(TRC_AUTHENTICATION, |
|
"PAMBasicAuthenticator::_authenticateByPwnam()"); |
|
|
|
Boolean authenticated = false; |
|
|
|
String currPassword = String::EMPTY; |
|
String encryptedPassword = String::EMPTY; |
|
String saltStr = String::EMPTY; |
|
|
|
// |
|
// check if the system has been converted to a trusted system. |
|
// |
|
|
|
if (iscomsec()) |
|
{ |
|
// system is a trusted system |
|
// use interface getprpwnam to get pr_passwd structure |
|
|
|
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) |
|
{ |
|
Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4, |
|
"getprpwnam successful."); |
|
// get user's password from pr_passwd structure |
|
currPassword = pwd->ufld.fd_encrypt; |
|
} |
|
|
|
delete [] _userName; |
|
} |
|
else |
|
{ |
|
// |
|
// system is not a trusted system |
|
// use reentrant interface getpwnam_r to get password structure |
|
// |
|
struct passwd pwd; |
|
struct passwd *result; |
|
char pwdBuffer[BUFFERLEN]; |
|
|
|
// getpwnam_r returns zero upon success |
|
if (getpwnam_r(userName, &pwd, pwdBuffer, BUFFERLEN, &result) == 0) |
|
{ |
|
Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4, |
|
"getpwnam_r successful."); |
|
// get user's password from password file |
|
currPassword = pwd.pw_passwd; |
|
} |
|
} |
|
|
|
// |
|
// Check if the specified password mathches user's password |
|
// |
|
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, |
|
"Password match successful."); |
|
} |
|
|
|
PEG_METHOD_EXIT(); |
|
|
|
return (authenticated); |
|
} |
|
#endif |
|
|
// | // |
// Create authentication response header | // Create authentication response header |
// | // |
|
|
return (responseHeader); | return (responseHeader); |
} | } |
| |
|
#if defined PEGASUS_OS_LINUX |
|
Sint32 PAMBasicAuthenticator::PAMCallback(Sint32 num_msg, const struct pam_message **msg, |
|
struct pam_response **resp, void *appdata_ptr) |
|
#else |
Sint32 PAMBasicAuthenticator::PAMCallback(Sint32 num_msg, struct pam_message **msg, | Sint32 PAMBasicAuthenticator::PAMCallback(Sint32 num_msg, struct pam_message **msg, |
struct pam_response **resp, void *appdata_ptr) | struct pam_response **resp, void *appdata_ptr) |
|
#endif |
{ | { |
PEG_METHOD_ENTER(TRC_AUTHENTICATION, | PEG_METHOD_ENTER(TRC_AUTHENTICATION, |
"PAMBasicAuthenticator::PAMCallback()"); | "PAMBasicAuthenticator::PAMCallback()"); |
|
|
|
// |
|
// Copy the application specific data from the PAM structure. |
|
// |
|
APP_DATA *mydata; |
|
mydata = (APP_DATA *) appdata_ptr; |
|
|
// | // |
// Allocate the response buffers | // Allocate the response buffers |
// | // |
|
|
return PAM_CONV_ERR; | return PAM_CONV_ERR; |
} | } |
| |
for ( Uint32 i = 0; i < num_msg; i++ ) |
for ( Sint32 i = 0; i < num_msg; i++ ) |
{ | { |
switch ( msg[i]->msg_style ) | switch ( msg[i]->msg_style ) |
{ | { |
|
|
// copy the user password | // copy the user password |
// | // |
resp[i]->resp = (char *)malloc(PAM_MAX_MSG_SIZE); | resp[i]->resp = (char *)malloc(PAM_MAX_MSG_SIZE); |
strcpy(resp[i]->resp, userPassword); |
strcpy(resp[i]->resp, mydata->userPassword); |
resp[i]->resp_retcode = 0; | resp[i]->resp_retcode = 0; |
break; | break; |
| |