/* miCASAd PAM module * * This is a PAM module which is used to capture the workstation * user/password and store the same in miCASAd . * 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 * requires the services of miCASAd. It needs to be present in both * the auth and session stacks of the PAM configuration files. * * In the auth stack, the functionality of the module is to store * 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" #define PAM_SM_AUTH #define PAM_SM_ACCOUNT #define PAM_SM_SESSION #include <sys/syslog.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) { int retVal = 0, rc = 0; const char *user = NULL; const char *wkstnPasswd = NULL; uid_t saved_uid = geteuid(); struct passwd *passwdEntry = NULL; struct pam_message msg[1], *pmsg[1]; struct pam_response *resp; struct pam_conv *conv; /* * Get the username first. */ retVal = pam_get_user(pamh, &user, NULL); if ( PAM_SUCCESS != retVal ) { pam_sscs_log( LOG_ERR, "pam_get_user returned error: %d - %s\n",retVal,pam_strerror(pamh,retVal)); return PAM_SUCCESS; } pam_get_item(pamh,PAM_AUTHTOK,(const void**)&wkstnPasswd); passwdEntry = getpwnam(user); /* SSCS determines the client uid using the SO_PEERCRED socket option. * Hence the euid is temporarily modified to that of the user logging in. */ seteuid( passwdEntry->pw_uid ); do { char *error = NULL; void *ssContext = NULL; SSCS_SECRETSTORE_T ssId = {0}; SSCS_SECRET_ID_T secretID = {0}; SSCS_SECRET_ID_T sharedSecretID = {0}; SSCS_BASIC_CREDENTIAL basicCredential; int credType; void *nsscsIdkHandle = dlopen(NSSCSIDK_LIB,RTLD_NOW); if( NULL == nsscsIdkHandle ) { pam_sscs_log(LOG_ERR,"Unable to open %s\n",NSSCSIDK_LIB); break; } pNSSCSSetCredential = dlsym( nsscsIdkHandle, "miCASASetCredential"); if( (error = dlerror()) != NULL ) { pam_sscs_log(LOG_ERR,"Unable to find miCASASetCredential symbol.- %s\n",error); break; } secretID.len = strlen(WORKSTATION_SECRET_ID) + 1; strcpy(secretID.id,WORKSTATION_SECRET_ID); sharedSecretID.len = strlen(WORKSTATION_SHARED_SECRET_ID) + 1; strcpy(sharedSecretID.id,WORKSTATION_SHARED_SECRET_ID); memset(&basicCredential,0,sizeof(basicCredential)); if (user && wkstnPasswd) { basicCredential.unFlags = 0; strcpy(basicCredential.username,user); basicCredential.unLen = strlen(user) + 1; strcpy(basicCredential.password,wkstnPasswd); basicCredential.pwordLen = strlen(wkstnPasswd) + 1; retVal = (*pNSSCSSetCredential) (0,&secretID,NULL, SSCS_CRED_TYPE_BASIC_F, &basicCredential,NULL); if( retVal != 0) { pam_sscs_log( LOG_ERR,"Setting the default credential failed.Errcode = %d\n",retVal); break; } } }while(0); seteuid(saved_uid); return PAM_SUCCESS; } PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc ,const char **argv) { return PAM_SUCCESS; } /* --- account management functions --- */ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc ,const char **argv) { PRINT_FN_NAME return PAM_SUCCESS; } PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc ,const char **argv) { return PAM_SUCCESS; } 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; uid_t saved_uid = geteuid(); struct passwd *passwdEntry = NULL; PRINT_FN_NAME retVal = pam_get_user(pamh, &user, NULL); if ( PAM_SUCCESS != retVal ) { pam_sscs_log( LOG_ERR, "pam_get_user returned error: %d - %s\n",retVal,pam_strerror(pamh,retVal)); return PAM_SUCCESS; } passwdEntry = getpwnam(user); seteuid( passwdEntry->pw_uid ); do { char *error = NULL; void *ssContext = NULL; SSCS_SECRETSTORE_T ssId = {0}; void *nsscsIdkHandle = dlopen(NSSCSIDK_LIB,RTLD_NOW); if( NULL == nsscsIdkHandle ) { 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,1,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