version 1.13, 2003/06/17 21:16:21
|
version 1.36.2.1, 2007/03/23 21:53:54
|
|
|
//%///////////////////////////////////////////////////////////////////////////// |
//%2006//////////////////////////////////////////////////////////////////////// |
// | // |
// 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. |
|
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; Symantec 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 |
|
|
// | // |
//============================================================================== | //============================================================================== |
// | // |
// Author: Nag Boranna, Hewlett-Packard Company(nagaraja_boranna@hp.com) |
|
// |
|
// Modified By: Yi Zhou, Hewlett-Packard Company(yi_zhou@hp.com) |
|
// : Sushma Fernandes, Hewlett-Packard Company |
|
// (sushma_fernandes@hp.com) |
|
// |
|
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
#include <Pegasus/Common/System.h> |
#include <Pegasus/Common/Executor.h> |
#include <Pegasus/Common/Tracer.h> |
|
#include <Pegasus/Common/Destroyer.h> |
|
#include <Pegasus/Config/ConfigManager.h> | #include <Pegasus/Config/ConfigManager.h> |
|
#include <Pegasus/Common/Tracer.h> |
#ifdef PEGASUS_OS_HPUX |
|
#include <pwd.h> |
|
#include <prot.h> |
|
#endif |
|
|
|
#include "PAMBasicAuthenticator.h" | #include "PAMBasicAuthenticator.h" |
| |
|
|
PEGASUS_USING_STD; | PEGASUS_USING_STD; |
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
#include <security/pam_appl.h> |
|
|
|
#define BUFFERLEN 1024 |
|
|
|
/** |
|
Constant representing the Basic authentication challenge header. |
|
*/ |
|
static const String BASIC_CHALLENGE_HEADER = "WWW-Authenticate: Basic \""; |
|
|
|
Mutex PAMBasicAuthenticator::_authSerializeMutex; |
|
|
|
/** Service name for pam_start */ |
|
const char *service = "wbem"; |
|
|
|
typedef struct |
|
{ |
|
CString userPassword; |
|
} APP_DATA; |
|
|
|
/* constructor. */ |
|
PAMBasicAuthenticator::PAMBasicAuthenticator() | PAMBasicAuthenticator::PAMBasicAuthenticator() |
{ | { |
PEG_METHOD_ENTER(TRC_AUTHENTICATION, | PEG_METHOD_ENTER(TRC_AUTHENTICATION, |
"PAMBasicAuthenticator::PAMBasicAuthenticator()"); | "PAMBasicAuthenticator::PAMBasicAuthenticator()"); |
| |
// |
// Build up realm: <hostname>:<port> |
// get the local system name |
|
// |
|
_realm.assign(System::getHostName()); | _realm.assign(System::getHostName()); |
| |
// |
|
// get the configured port number | // get the configured port number |
// |
|
ConfigManager* configManager = ConfigManager::getInstance(); | ConfigManager* configManager = ConfigManager::getInstance(); |
|
|
String port = configManager->getCurrentValue("httpPort"); | String port = configManager->getCurrentValue("httpPort"); |
| |
// | // |
|
|
_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(); |
} | } |
| |
/* destructor. */ |
|
PAMBasicAuthenticator::~PAMBasicAuthenticator() | PAMBasicAuthenticator::~PAMBasicAuthenticator() |
{ | { |
PEG_METHOD_ENTER(TRC_AUTHENTICATION, | PEG_METHOD_ENTER(TRC_AUTHENTICATION, |
|
|
| |
Boolean PAMBasicAuthenticator::authenticate( | Boolean PAMBasicAuthenticator::authenticate( |
const String& userName, | const String& userName, |
const String& password) |
const String& password, |
|
SessionKey& sessionKey) |
{ | { |
PEG_METHOD_ENTER(TRC_AUTHENTICATION, | PEG_METHOD_ENTER(TRC_AUTHENTICATION, |
"PAMBasicAuthenticator::authenticate()"); | "PAMBasicAuthenticator::authenticate()"); |
| |
Boolean authenticated; |
if (Executor::authenticatePassword( |
|
userName.getCString(), password.getCString(), sessionKey) != 0) |
#ifndef PEGASUS_OS_HPUX |
|
authenticated = _authenticateByPAM(userName, password); |
|
#else |
|
// |
|
// Mutex to Serialize Authentication calls. |
|
// |
|
Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4, |
|
"Authentication Mutex lock."); |
|
_authSerializeMutex.lock(pegasus_thread_self()); |
|
try |
|
{ | { |
if (_usePAM) |
return false; |
{ |
|
authenticated = _authenticateByPAM(userName, password); |
|
} | } |
else |
|
{ |
|
authenticated = _authenticateByPwnam(userName.getCString(), password); |
|
} |
|
|
|
Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4, |
|
"Authentication Mutex unlock."); |
|
_authSerializeMutex.unlock(); |
|
} |
|
catch (...) |
|
{ |
|
Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4, |
|
"Authentication Mutex unlock."); |
|
_authSerializeMutex.unlock(); |
|
throw; |
|
} |
|
#endif |
|
| |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
return (authenticated); |
return true; |
} | } |
| |
Boolean PAMBasicAuthenticator::_authenticateByPAM( |
Boolean PAMBasicAuthenticator::validateUser(const String& userName) |
const String& userName, |
|
const String& password) |
|
{ | { |
PEG_METHOD_ENTER(TRC_AUTHENTICATION, | PEG_METHOD_ENTER(TRC_AUTHENTICATION, |
"PAMBasicAuthenticator::_authenticateByPAM()"); |
"PAMBasicAuthenticator::validateUser()"); |
|
|
Boolean authenticated = false; |
|
struct pam_conv pconv; |
|
pam_handle_t *phandle; |
|
char *name; |
|
APP_DATA mydata; |
|
|
|
// |
|
// Store the password for PAM authentication |
|
// |
|
mydata.userPassword = password.getCString(); |
|
|
|
pconv.conv = PAMBasicAuthenticator::PAMCallback; |
|
pconv.appdata_ptr = &mydata; |
|
|
|
// 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 |
|
// |
|
if ( ( pam_start(service, |
|
(const char *)userName.getCString(), &pconv, &phandle) ) != PAM_SUCCESS ) |
|
{ |
|
PEG_METHOD_EXIT(); |
|
return (authenticated); |
|
} |
|
| |
// |
if (Executor::validateUser(userName.getCString()) != 0) |
//Call pam_authenticate to authenticate the user |
return false; |
// |
|
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 |
|
//checking for password and account expiration, as well as verifying access |
|
//hour restrictions. |
|
// |
|
if ( ( pam_acct_mgmt(phandle, 0) ) == PAM_SUCCESS ) |
|
{ |
|
Tracer::trace(TRC_AUTHENTICATION, Tracer::LEVEL4, |
|
"pam_acct_mgmt successful."); |
|
authenticated = true; |
|
} |
|
} |
|
|
|
// |
|
//Call pam_end to end our PAM work |
|
// |
|
pam_end(phandle, 0); |
|
| |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
|
return true; |
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 |
|
// |
|
String PAMBasicAuthenticator::getAuthResponseHeader() | String PAMBasicAuthenticator::getAuthResponseHeader() |
{ | { |
PEG_METHOD_ENTER(TRC_AUTHENTICATION, | PEG_METHOD_ENTER(TRC_AUTHENTICATION, |
"PAMBasicAuthenticator::getAuthResponseHeader()"); | "PAMBasicAuthenticator::getAuthResponseHeader()"); |
| |
// |
// Build response header: WWW-Authenticate: Basic "<hostname>:<port>" |
// build response header using realm |
|
// |
String responseHeader = "WWW-Authenticate: Basic \""; |
String responseHeader = BASIC_CHALLENGE_HEADER; |
|
responseHeader.append(_realm); | responseHeader.append(_realm); |
responseHeader.append("\""); | responseHeader.append("\""); |
| |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
|
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, |
|
struct pam_response **resp, void *appdata_ptr) |
|
#endif |
|
{ |
|
PEG_METHOD_ENTER(TRC_AUTHENTICATION, |
|
"PAMBasicAuthenticator::PAMCallback()"); |
|
|
|
// |
|
// Copy the application specific data from the PAM structure. |
|
// |
|
APP_DATA *mydata; |
|
mydata = (APP_DATA *) appdata_ptr; |
|
|
|
// |
|
// Allocate the response buffers |
|
// |
|
if ( num_msg > 0 ) |
|
{ |
|
// |
|
// 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 ) |
|
{ |
|
PEG_METHOD_EXIT(); |
|
return PAM_BUF_ERR; |
|
} |
|
} |
|
else |
|
{ |
|
PEG_METHOD_EXIT(); |
|
return PAM_CONV_ERR; |
|
} |
|
|
|
for ( Sint32 i = 0; i < num_msg; i++ ) |
|
{ |
|
switch ( msg[i]->msg_style ) |
|
{ |
|
case PAM_PROMPT_ECHO_OFF: |
|
// |
|
// copy the user password |
|
// |
|
resp[i]->resp = (char *)malloc(PAM_MAX_MSG_SIZE); |
|
strcpy(resp[i]->resp, mydata->userPassword); |
|
resp[i]->resp_retcode = 0; |
|
break; |
|
|
|
default: |
|
PEG_METHOD_EXIT(); |
|
return PAM_CONV_ERR; |
|
} |
|
} |
|
|
|
PEG_METHOD_EXIT(); |
|
|
|
return PAM_SUCCESS; |
|
} | } |
| |
PEGASUS_NAMESPACE_END | PEGASUS_NAMESPACE_END |