version 1.6, 2006/01/30 16:18:29 |
version 1.6.30.8, 2007/01/02 17:53:23 |
| |
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
// sell copies of the Software, and to permit persons to whom the Software is | // sell copies of the Software, and to permit persons to whom the 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 OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED | // 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 | // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT |
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
// | // |
//============================================================================== | //============================================================================== |
// | // |
// Author: Ben Heilbronn, Hewlett-Packard Company(ben_heilbronn@hp.com) | |
// | |
// Parts of this code originated within PAMBasicAuthenticator. | |
// | |
// Modified By: Sushma Fernandes, Hewlett-Packard Company(sushma_fernandes@hp.com) | |
// | |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
#include <Pegasus/Common/System.h> | |
#include <Pegasus/Common/String.h> | |
#include <Pegasus/Common/FileSystem.h> | |
#include <Pegasus/Common/PegasusVersion.h> | |
#include <Pegasus/Security/Authentication/PAMBasicAuthenticator.h> | |
| |
#include <sys/stat.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/resource.h> | |
#include <string.h> | |
#include <strings.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
| |
#include "cimservera.h" | #include "cimservera.h" |
| #include <cstdio> |
| #include <syslog.h> |
| |
PEGASUS_USING_STD; | static void Exit(int status) |
| |
PEGASUS_NAMESPACE_BEGIN | |
| |
#include <security/pam_appl.h> | |
| |
#define BUFFERLEN 1024 | |
#define HEADER_LEN 4 | |
| |
typedef struct | |
{ | { |
CString userPassword; | syslog(LOG_INFO, "exit(%d)", status); |
} APP_DATA; | exit(status); |
| } |
| |
// Initialize the constants. | static ssize_t Recv(int sock, void* buffer, size_t size) |
| { |
| size_t r = size; |
| char* p = (char*)buffer; |
| |
const char Cimservera::OPERATION_PAM_AUTHENTICATION = 'A'; | if (size == 0) |
| return -1; |
| |
const char Cimservera::OPERATION_PAM_ACCT_MGMT = 'M'; | while (r) |
| { |
| ssize_t n; |
| |
const char Cimservera::PAM_OPERATION_SUCCESS = 'T'; | CIMSERVERA_RESTART(read(sock, p, r), n); |
| |
const char Cimservera::PAM_OPERATION_FAILURE = 'F'; | if (n == -1) |
| return -1; |
| else if (n == 0) |
| return size - r; |
| |
/* constructor. */ | r -= n; |
Cimservera::Cimservera() | p += n; |
{ | |
} | } |
| |
/* destructor. */ | return size - r; |
Cimservera::~Cimservera() | |
{ | |
} | } |
| |
Boolean Cimservera::authenticateByPAM( | int main(int argc, char* argv[]) |
const String& userName, | |
const String& password) | |
{ | { |
Boolean authenticated = false; | // Open syslog: |
struct pam_conv pconv; | |
pam_handle_t *phandle; | |
char *name; | |
APP_DATA mydata; | |
| |
const char *service = "wbem"; | openlog("cimservera", LOG_PID, LOG_AUTH); |
| syslog(LOG_INFO, "started"); |
| |
// | // ATTN: Insert fingerprint logic to detect running of this program as |
// Store the password for PAM authentication | // non-child of executor. |
// | |
mydata.userPassword = password.getCString(); | |
| |
pconv.conv = Cimservera::PAMCallback; | // Check argumnents. |
pconv.appdata_ptr = &mydata; | |
| |
// | if (argc != 2) |
//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 ) | |
{ | { |
return (authenticated); | fprintf(stderr, "Usage: %s <socket-number>\n", argv[0]); |
| Exit(1); |
} | } |
| |
// | // Open socket stream. |
//Call pam_authenticate to authenticate the user | |
// | |
if ( ( pam_authenticate(phandle, 0) ) == PAM_SUCCESS ) | |
{ | |
// | |
//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 ) | |
{ | |
authenticated = true; | |
} | |
} | |
| |
// | int sock; |
//Call pam_end to end our PAM work | |
// | |
pam_end(phandle, 0); | |
| |
return (authenticated); | |
} | |
| |
#if defined PEGASUS_OS_LINUX | |
Sint32 Cimservera::PAMCallback(Sint32 num_msg, const struct pam_message **msg, | |
struct pam_response **resp, void *appdata_ptr) | |
#else | |
Sint32 Cimservera::PAMCallback(Sint32 num_msg, struct pam_message **msg, | |
struct pam_response **resp, void *appdata_ptr) | |
#endif | |
{ | { |
// | char* end; |
// Copy the application specific data from the PAM structure. | long x = strtoul(argv[1], &end, 10); |
// | |
APP_DATA *mydata; | |
mydata = (APP_DATA *) appdata_ptr; | |
| |
// | if (*end != '\0') |
// 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 ) | |
{ | |
return PAM_BUF_ERR; | |
} | |
} | |
else | |
{ | { |
return PAM_CONV_ERR; | fprintf(stderr, "%s : bad socket argument: %s\n", argv[0], argv[1]); |
| Exit(1); |
} | } |
| |
for ( Sint32 i = 0; i < num_msg; i++ ) | sock = int(x); |
{ | |
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: | |
return PAM_CONV_ERR; | |
} | |
} | } |
| |
return PAM_SUCCESS; | // Wait on request. |
} | |
| |
Boolean Cimservera::performAcctMgmt (const String& userName) | |
{ | |
Boolean authenticated = false; | |
struct pam_conv pconv; | |
pam_handle_t *phandle; | |
char *name; | |
APP_DATA mydata; | |
| |
const char *service = "wbem"; | CimserveraRequest request; |
pconv.conv = PAMBasicAuthenticator::pamValidateUserCallback; | |
pconv.appdata_ptr = &mydata; | |
| |
// | // Wait on request. |
// Call pam_start since you need to before making any other PAM calls | if (Recv(sock, &request, sizeof(request)) != sizeof(request)) |
// | |
if ( pam_start(service, | |
(const char *)userName.getCString(), &pconv, &phandle) != PAM_SUCCESS) | |
{ | { |
return (authenticated); | close(sock); |
} | Exit(1); |
| |
// | |
// Call pam_acct_mgmt, to check if the user account is valid. This include s | |
// checking for account expiration, as well as verifying access | |
// hour restrictions. | |
// | |
if ( pam_acct_mgmt(phandle, 0) == PAM_SUCCESS ) | |
{ | |
authenticated = true; | |
} | |
| |
// | |
//Call pam_end to end our PAM work | |
// | |
pam_end(phandle, 0); | |
| |
return (authenticated); | |
} | } |
| |
PEGASUS_NAMESPACE_END; | if (strcmp(request.arg0, "authenticate") == 0) |
PEGASUS_USING_PEGASUS; | |
| |
int main(int argc, char* argv[]) | |
{ | { |
int n, len; | int status = PAMAuthenticateInProcess(request.arg1, request.arg2); |
char username[BUFFERLEN], password[BUFFERLEN], operation[BUFFERLEN]; | |
char * _username = &username[0]; | |
char * _password = &password[0]; | |
char username_len[10], password_len[10], operation_len[10]; | |
char return_buf[2]; | |
| |
typedef struct | if (status != 0) |
{ | { |
CString userPassword; | syslog(LOG_WARNING, "PAM authentication failed on user \"%s\"", |
} APP_DATA; | request.arg1); |
| |
Boolean authenticated; | |
| |
// STDIN and STDOUT are used on the back-end for reading and writing | |
| |
for (;;) { // Just loop on username/passwords/opcode | |
| |
authenticated = false; | |
| |
// Read in the username | |
| |
len = read(STDIN_FILENO, username_len, HEADER_LEN); | |
if (len != HEADER_LEN) { | |
break; | |
} | } |
username_len[HEADER_LEN] = '\0'; | |
n = atoi(username_len); | |
read(STDIN_FILENO, username, n); | |
username[n] = '\0'; | |
| |
// Read in the password | |
| |
len = read(STDIN_FILENO, password_len, HEADER_LEN); | Exit(status == 0 ? 0 : 1); |
if (len != HEADER_LEN) { | |
break; | |
} | } |
password_len[HEADER_LEN] = '\0'; | else if (strcmp(request.arg0, "validateUser") == 0) |
n = atoi(password_len); | |
read(STDIN_FILENO, password, n); | |
password[n] = '\0'; | |
| |
// Read in the operation | |
| |
len = read(STDIN_FILENO, operation_len, HEADER_LEN); | |
if (len != HEADER_LEN) { | |
break; | |
} | |
operation_len[HEADER_LEN] = '\0'; | |
n = atoi(operation_len); | |
read(STDIN_FILENO, operation, n); | |
operation[n] = '\0'; | |
| |
// | |
// Check the operation flag. | |
// | |
if (operation[0] == Cimservera::OPERATION_PAM_AUTHENTICATION) | |
{ | { |
authenticated = Cimservera::authenticateByPAM(_username, _password); | int status = PAMValidateUserInProcess(request.arg1); |
} | |
else if (operation[0] == Cimservera::OPERATION_PAM_ACCT_MGMT) | if (status != 0) |
{ | { |
authenticated = Cimservera::performAcctMgmt(_username); | syslog(LOG_WARNING, "PAM user validation failed on user \"%s\"", |
| request.arg1); |
} | } |
| |
if (authenticated) | Exit(status == 0 ? 0 : 1); |
{ | } |
return_buf[0] = Cimservera::PAM_OPERATION_SUCCESS; | else |
} else | |
{ | { |
return_buf[0] = Cimservera::PAM_OPERATION_FAILURE; | syslog(LOG_WARNING, "invalid request"); |
| close(sock); |
| Exit(1); |
} | } |
return_buf[1] = '\0'; | |
| |
write(STDOUT_FILENO, return_buf, 1); | close(sock); |
} | Exit(0); |
} | } |