Browse Source

PAM is not thread safe. Therefore, we must put the code that accesses PAM
in a critical section. This fix creates a mutex at init time and uses that
mutex to create a critical section around all PAM API access.

Rich Megginson 20 years ago
parent
commit
87e9a9fc6d

+ 1 - 0
ldap/servers/plugins/pam_passthru/pam_passthru.h

@@ -131,6 +131,7 @@ 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_ */

+ 23 - 0
ldap/servers/plugins/pam_passthru/pam_ptimpl.c

@@ -39,6 +39,11 @@
 
 #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 */
@@ -271,6 +276,8 @@ do_one_pam_auth(
 	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);
 
@@ -351,6 +358,8 @@ do_one_pam_auth(
 
 	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);
 
@@ -375,6 +384,20 @@ do_one_pam_auth(
 	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

+ 6 - 0
ldap/servers/plugins/pam_passthru/pam_ptpreop.c

@@ -128,6 +128,12 @@ pam_passthru_bindpreop_start( Slapi_PBlock *pb )
 		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 );
 }