Bug 143940. Prevent buffer overflow on usernames and passwords that are longer than buffers.

This commit is contained in:
Jim Norman 2006-02-13 15:58:09 +00:00
parent 78997d2777
commit ec458809d0

View File

@ -1,263 +1,198 @@
/*********************************************************************** /***********************************************************************
* *
* Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved. * Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1 * License as published by the Free Software Foundation; version 2.1
* of the License. * of the License.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details. * Library Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc. * License along with this library; if not, Novell, Inc.
* *
* To contact Novell about this file by physical or electronic mail, * To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com. * you may find current contact information at www.novell.com.
* *
***********************************************************************/ ***********************************************************************/
/* miCASAd PAM module /* miCASAd PAM module
* *
* This is a PAM module which is used to capture the workstation * This is a PAM module which is used to capture the workstation
* user/password and store the same in miCASAd . * user/password and store the same in miCASAd .
* This would be placed in login/xdm/gdm/kdm/sshd PAM configuration files. * This would be placed in login/xdm/gdm/kdm/sshd PAM configuration files.
* *
* This module needs to be present before any other PAM module which * This module needs to be present before any other PAM module which
* requires the services of miCASAd. It needs to be present in both * requires the services of miCASAd. It needs to be present
* the auth and session stacks of the PAM configuration files. * the auth stacks of the PAM configuration files.
* *
* In the auth stack, the functionality of the module is to store * In the auth stack, the functionality of the module is to store
* the workstation user/password in micasad. * the workstation user/password in micasad.
* In the session stack, the functionality of the module is to do *
* a Close of the user's SESSION Keychain. */
*
*/
#include "pam_sscs.h"
#include "pam_sscs.h" #define PAM_SM_AUTH
#define PAM_SM_ACCOUNT
#define PAM_SM_AUTH #define PAM_SM_SESSION
#define PAM_SM_ACCOUNT
#define PAM_SM_SESSION #include <sys/syslog.h>
#include <security/pam_modules.h>
#include <sys/syslog.h> #include <security/_pam_macros.h>
#include <security/pam_modules.h>
#include <security/_pam_macros.h> PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,
const char **argv)
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc, {
const char **argv) int retVal = 0;
{
int retVal = 0, rc = 0; const char *user = NULL;
const char *wkstnPasswd = NULL;
const char *user = NULL;
const char *wkstnPasswd = NULL; uid_t saved_uid = geteuid();
struct passwd *passwdEntry = NULL;
uid_t saved_uid = geteuid();
struct passwd *passwdEntry = NULL; /*
* Get the username first.
struct pam_message msg[1], *pmsg[1]; */
struct pam_response *resp; retVal = pam_get_user(pamh, &user, NULL);
struct pam_conv *conv;
if ( PAM_SUCCESS != retVal )
/* {
* Get the username first. pam_sscs_log( LOG_ERR, "pam_get_user returned error: %d - %s\n",retVal,pam_strerror(pamh,retVal));
*/ return PAM_SUCCESS;
retVal = pam_get_user(pamh, &user, NULL); }
if ( PAM_SUCCESS != retVal ) pam_get_item(pamh,PAM_AUTHTOK,(const void**)&wkstnPasswd);
{ passwdEntry = getpwnam(user);
pam_sscs_log( LOG_ERR, "pam_get_user returned error: %d - %s\n",retVal,pam_strerror(pamh,retVal));
return PAM_SUCCESS; /* CASA determines the client uid using the SO_PEERCRED socket option.
} * Hence the euid is temporarily modified to that of the user logging in.
*/
pam_get_item(pamh,PAM_AUTHTOK,(const void**)&wkstnPasswd); if(passwdEntry)
passwdEntry = getpwnam(user); {
seteuid( passwdEntry->pw_uid );
/* SSCS determines the client uid using the SO_PEERCRED socket option.
* Hence the euid is temporarily modified to that of the user logging in. do
*/ {
if(passwdEntry) char *error = NULL;
{ SSCS_SECRET_ID_T secretID = {0};
seteuid( passwdEntry->pw_uid ); SSCS_BASIC_CREDENTIAL basicCredential;
int credType;
do
{ void *nsscsIdkHandle = dlopen(NSSCSIDK_LIB,RTLD_NOW);
char *error = NULL; if( NULL == nsscsIdkHandle )
void *ssContext = NULL; {
SSCS_SECRETSTORE_T ssId = {0}; pam_sscs_log(LOG_ERR,"Unable to open %s\n",NSSCSIDK_LIB);
break;
SSCS_SECRET_ID_T secretID = {0}; }
SSCS_SECRET_ID_T sharedSecretID = {0};
pNSSCSSetCredential = dlsym( nsscsIdkHandle,
SSCS_BASIC_CREDENTIAL basicCredential; "miCASASetCredential");
int credType; if( (error = dlerror()) != NULL )
{
void *nsscsIdkHandle = dlopen(NSSCSIDK_LIB,RTLD_NOW); pam_sscs_log(LOG_ERR,"Unable to find miCASASetCredential symbol.- %s\n",error);
if( NULL == nsscsIdkHandle ) break;
{ }
pam_sscs_log(LOG_ERR,"Unable to open %s\n",NSSCSIDK_LIB);
break; secretID.len = strlen(WORKSTATION_SECRET_ID) + 1;
} strcpy(secretID.id,WORKSTATION_SECRET_ID);
pNSSCSSetCredential = dlsym( nsscsIdkHandle, memset(&basicCredential,0,sizeof(basicCredential));
"miCASASetCredential");
if( (error = dlerror()) != NULL ) if (user && wkstnPasswd)
{ {
pam_sscs_log(LOG_ERR,"Unable to find miCASASetCredential symbol.- %s\n",error); basicCredential.unFlags = 0;
break; // don't copy a username longer than we can handle
} if ((strlen(user) + 1) > NSSCS_MAX_USERID_LEN)
{
secretID.len = strlen(WORKSTATION_SECRET_ID) + 1; pam_sscs_log( LOG_ERR,"Username is longer than allowed\n");
strcpy(secretID.id,WORKSTATION_SECRET_ID); break;
}
sharedSecretID.len = strlen(WORKSTATION_SHARED_SECRET_ID) + 1; strcpy(basicCredential.username,user);
strcpy(sharedSecretID.id,WORKSTATION_SHARED_SECRET_ID); basicCredential.unLen = strlen(user) + 1;
memset(&basicCredential,0,sizeof(basicCredential)); // don't copy a password longer than we can handle
if ((strlen(wkstnPasswd) + 1) > NSSCS_MAX_PWORD_LEN)
if (user && wkstnPasswd) {
{ pam_sscs_log( LOG_ERR,"Password is longer than allowed\n");
basicCredential.unFlags = 0; break;
strcpy(basicCredential.username,user); }
basicCredential.unLen = strlen(user) + 1; strcpy(basicCredential.password,wkstnPasswd);
strcpy(basicCredential.password,wkstnPasswd); basicCredential.pwordLen = strlen(wkstnPasswd) + 1;
basicCredential.pwordLen = strlen(wkstnPasswd) + 1;
retVal = (*pNSSCSSetCredential) (0,
retVal = (*pNSSCSSetCredential) (0,&secretID,NULL, &secretID,
SSCS_CRED_TYPE_BASIC_F, NULL,
&basicCredential,NULL); SSCS_CRED_TYPE_BASIC_F,
if( retVal != 0) &basicCredential,
{ NULL);
pam_sscs_log( LOG_ERR,"Setting the default credential failed.Errcode = %d\n",retVal); if( retVal != 0)
break; {
} pam_sscs_log( LOG_ERR,"Setting the default credential failed.Errcode = %d\n",retVal);
} break;
}while(0); }
}
seteuid(saved_uid); }while(0);
}
return PAM_SUCCESS; seteuid(saved_uid);
} }
return PAM_SUCCESS;
PAM_EXTERN }
int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
,const char **argv) PAM_EXTERN
{ int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
return PAM_SUCCESS; ,const char **argv)
} {
return PAM_SUCCESS;
/* --- account management functions --- */ }
PAM_EXTERN /* --- account management functions --- */
int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc
,const char **argv) PAM_EXTERN
{ int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc
PRINT_FN_NAME ,const char **argv)
return PAM_SUCCESS; {
} return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc
,const char **argv) PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc
{ ,const char **argv)
return PAM_SUCCESS; {
} return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc
,const char **argv) PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc
{ ,const char **argv)
const char *user = NULL; {
int retVal = 0; return PAM_SUCCESS;
uid_t saved_uid = geteuid(); }
struct passwd *passwdEntry = NULL;
/* end of module definition */
PRINT_FN_NAME
#ifdef PAM_STATIC
retVal = pam_get_user(pamh, &user, NULL);
if ( PAM_SUCCESS != retVal ) /* static module data */
{
pam_sscs_log( LOG_ERR, "pam_get_user returned error: %d - %s\n",retVal,pam_strerror(pamh,retVal)); struct pam_module _pam_passphrase_modstruct = {
return PAM_SUCCESS; "pam_sscs",
} pam_sm_authenticate,
pam_sm_setcred,
passwdEntry = getpwnam(user); NULL,
NULL,
seteuid( passwdEntry->pw_uid ); NULL
pam_sm_acct_mgmt,
do pam_sm_open_session,
{ pam_sm_close_session,
char *error = NULL; #if 0
void *ssContext = NULL; pam_sm_chauthtok
SSCS_SECRETSTORE_T ssId = {0}; #endif
};
void *nsscsIdkHandle = dlopen(NSSCSIDK_LIB,RTLD_NOW);
if( NULL == nsscsIdkHandle ) #endif
{
pam_sscs_log(LOG_ERR,"Unable to open %s\n",NSSCSIDK_LIB);
break;
}
pNSSCSOpenSecretStoreCache = dlsym(nsscsIdkHandle,
"miCASAOpenSecretStoreCache");
if( (error = dlerror()) != NULL )
{
pam_sscs_log(LOG_ERR,"Unable to find miCASAOpenSecretStoreCache symbol. - %s\n",error);
break;
}
pNSSCSCloseSecretStoreCache = dlsym(nsscsIdkHandle,
"miCASACloseSecretStoreCache");
if( (error = dlerror()) != NULL )
{
pam_sscs_log(LOG_ERR,"Unable to find miCASACloseSecretStoreCache symbol. - %s\n",error);
break;
}
strcpy(ssId.ssName, passwdEntry->pw_name);
ssId.version = NSSCS_VERSION_NUMBER;
ssContext = (*pNSSCSOpenSecretStoreCache)(&ssId,0,NULL);
if( NULL == ssContext )
{
pam_sscs_log( LOG_ERR,"Opening SecretStore for the user %s failed.\n",passwdEntry->pw_name);
break;
}
retVal = (*pNSSCSCloseSecretStoreCache) (ssContext,0,NULL);
if( retVal != 0 )
{
pam_sscs_log(LOG_ERR,"Closing SecretStore for the user %s failed.\n",passwdEntry->pw_name);
break;
}
}while(0);
seteuid(saved_uid);
return PAM_SUCCESS;
}
/* end of module definition */
#ifdef PAM_STATIC
/* static module data */
struct pam_module _pam_passphrase_modstruct = {
"pam_sscs",
pam_sm_authenticate,
pam_sm_setcred,
NULL,
NULL,
NULL
pam_sm_acct_mgmt,
pam_sm_open_session,
pam_sm_close_session,
#if 0
pam_sm_chauthtok
#endif
};
#endif