Index: pam_passthru.h =================================================================== RCS file: /cvs/dirsec/ldapserver/ldap/servers/plugins/pam_passthru/pam_passthru.h,v retrieving revision 1.4 diff -u -8 -r1.4 pam_passthru.h --- pam_passthru.h 19 Apr 2005 22:07:30 -0000 1.4 +++ pam_passthru.h 6 Jul 2005 22:20:33 -0000 @@ -126,11 +126,12 @@ */ int pam_passthru_config( Slapi_Entry *config_e ); Pam_PassthruConfig *pam_passthru_get_config( void ); int pam_passthru_check_suffix(Pam_PassthruConfig *cfg, char *binddn); /* * pam_ptimpl.c */ +int pam_passthru_pam_init( void ); int pam_passthru_do_pam_auth(Slapi_PBlock *pb, Pam_PassthruConfig *cfg); #endif /* _PAM_PASSTHRU_H_ */ Index: pam_ptimpl.c =================================================================== RCS file: /cvs/dirsec/ldapserver/ldap/servers/plugins/pam_passthru/pam_ptimpl.c,v retrieving revision 1.7 diff -u -8 -r1.7 pam_ptimpl.c --- pam_ptimpl.c 19 Apr 2005 22:07:30 -0000 1.7 +++ pam_ptimpl.c 6 Jul 2005 22:20:33 -0000 @@ -34,16 +34,21 @@ * Copyright (C) 2005 Red Hat, Inc. * All rights reserved. * END COPYRIGHT BLOCK **/ #include #include "pam_passthru.h" +/* + * PAM is not thread safe. We have to execute any PAM API calls in + * a critical section. This is the lock that protects that code. + */ +static Slapi_Mutex *PAMLock; /* Utility struct to wrap strings to avoid mallocs if possible - use stack allocated string space */ #define MY_STATIC_BUF_SIZE 256 typedef struct my_str_buf { char fixbuf[MY_STATIC_BUF_SIZE]; char *str; } MyStrBuf; @@ -266,16 +271,18 @@ } else { init_my_str_buf(&pam_id, binddn); } /* do the pam stuff */ my_data.pb = pb; my_data.pam_identity = pam_id.str; my_pam_conv.appdata_ptr = &my_data; + slapi_lock_mutex(PAMLock); + /* from this point on we are in the critical section */ rc = pam_start(pam_service, pam_id.str, &my_pam_conv, &pam_handle); report_pam_error("during pam_start", rc, pam_handle); if (rc == PAM_SUCCESS) { /* use PAM_SILENT - there is no user interaction at this point */ rc = pam_authenticate(pam_handle, 0); report_pam_error("during pam_authenticate", rc, pam_handle); /* check different types of errors here */ @@ -346,16 +353,18 @@ errmsg = PR_smprintf("Unknown PAM error [%s] for user id [%s], bind DN [%s]", pam_strerror(pam_handle, rc), pam_id.str, escape_string(binddn, buf)); retcode = LDAP_OPERATIONS_ERROR; /* unknown */ } } rc = pam_end(pam_handle, rc); report_pam_error("during pam_end", rc, pam_handle); + slapi_unlock_mutex(PAMLock); + /* not in critical section any more */ delete_my_str_buf(&pam_id); if ((retcode == LDAP_SUCCESS) && (rc != PAM_SUCCESS)) { errmsg = PR_smprintf("Unknown PAM error [%d] for user id [%d], bind DN [%s]", rc, pam_id.str, escape_string(binddn, buf)); retcode = LDAP_OPERATIONS_ERROR; } @@ -371,16 +380,30 @@ if (errmsg) { PR_smprintf_free(errmsg); } return retcode; } /* + * Perform any PAM subsystem initialization that must be done at startup time. + * For now, this means only the PAM mutex since PAM is not thread safe. + */ +int +pam_passthru_pam_init( void ) +{ + if (!(PAMLock = slapi_new_mutex())) { + return LDAP_LOCAL_ERROR; + } + + return 0; +} + +/* * Entry point into the PAM auth code. Shields the rest of the app * from PAM API code. Get our config params, then call the actual * code that does the PAM auth. Can call that code up to 3 times, * depending on what methods are set in the config. */ int pam_passthru_do_pam_auth(Slapi_PBlock *pb, Pam_PassthruConfig *cfg) { Index: pam_ptpreop.c =================================================================== RCS file: /cvs/dirsec/ldapserver/ldap/servers/plugins/pam_passthru/pam_ptpreop.c,v retrieving revision 1.4 diff -u -8 -r1.4 pam_ptpreop.c --- pam_ptpreop.c 19 Apr 2005 22:07:30 -0000 1.4 +++ pam_ptpreop.c 6 Jul 2005 22:20:33 -0000 @@ -123,16 +123,22 @@ } if (( rc = pam_passthru_config( config_e )) != LDAP_SUCCESS ) { slapi_log_error( SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, "configuration failed (%s)\n", ldap_err2string( rc )); return( -1 ); } + if (( rc = pam_passthru_pam_init()) != LDAP_SUCCESS ) { + slapi_log_error( SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, + "could not initialize PAM subsystem (%d)\n", rc); + return( -1 ); + } + return( 0 ); } /* * Called right before the Directory Server shuts down. */ static int