[PATCH] make 'required_membership_sid' accessible for pam_winbind

Guenther Deschner gd at sernet.de
Wed Jul 7 19:21:26 GMT 2004


Hi,

since some time winbindd has code for honoring a group-sid to make successfull
authentication dependent on group-membership. ntlm_auth uses this feature.
attached is a quick patch that makes it accessible for pam_winbind as well.

This allows to configure:

auth sufficient pam_winbind.so  required_membership=S-1-5-21-3166309798-1443334765-3819889277-519

or even 

auth sufficient pam_winbind.so  required_membership=W2K3TEST\Organisations-Admins

in your pam-stack.

I'm a bit unsure though if the pam-auth-facility is the right place to add it. 

Any comments ?

Thanks,
Guenther

-- 
Guenther Deschner, SerNet Service Network GmbH
Phone: +49-(0)551-370000-0,  Fax: +49-(0)551-370000-9
-------------- next part --------------
Index: source/nsswitch/pam_winbind.c
===================================================================
--- source/nsswitch/pam_winbind.c	(revision 1374)
+++ source/nsswitch/pam_winbind.c	(working copy)
@@ -45,6 +45,8 @@
 			ctrl |= WINBIND_TRY_FIRST_PASS_ARG;
 		else if (!strcasecmp(*argv, "unknown_ok"))
 			ctrl |= WINBIND_UNKNOWN_OK_ARG;
+		else if (!strncasecmp(*argv, "required_membership", strlen("required_membership")))
+			ctrl |= WINBIND_REQUIRED_MEMBERSHIP;
 		else {
 			_pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv);
 		}
@@ -148,7 +150,7 @@
 	switch (retval) {
 	case PAM_AUTH_ERR:
 		/* incorrect password */
-		_pam_log(LOG_WARNING, "user `%s' denied access (incorrect password)", user);
+		_pam_log(LOG_WARNING, "user `%s' denied access (incorrect password or invalid group membership)", user);
 		return retval;
 	case PAM_ACCT_EXPIRED:
 		/* account expired */
@@ -192,7 +194,7 @@
 }
 
 /* talk to winbindd */
-static int winbind_auth_request(const char *user, const char *pass, int ctrl)
+static int winbind_auth_request(const char *user, const char *pass, const char *required_membership, int ctrl)
 {
 	struct winbindd_request request;
 	struct winbindd_response response;
@@ -204,8 +206,57 @@
 
 	strncpy(request.data.auth.pass, pass, 
                 sizeof(request.data.auth.pass)-1);
+
+	if (required_membership == NULL )
+        	return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user);
+
+	/* check if we got a sid or if we need to lookup ourself */
+	if (!strncmp("S-", required_membership, 2) == 0) {
+		
+		char *p;
+
+		struct winbindd_request request;
+		struct winbindd_response response;
+
+		ZERO_STRUCT(request);
+		ZERO_STRUCT(response);
+		
+		if (ctrl & WINBIND_DEBUG_ARG)
+			_pam_log(LOG_DEBUG, "no sid given, trying to lookup: %s\n", required_membership);
+
+		/* split into domain and group */
+		if ( (p = strchr( required_membership, '\\' )) == NULL) {
+			strcpy(request.data.name.name, required_membership);
+		} else {
+			char *domain = strndup(required_membership, strlen(required_membership)-strlen(p));
+			strcpy(request.data.name.dom_name, domain);
+			strcpy(request.data.name.name, p+1);
+		}
+
+
+		/* lookup group */
+		_pam_log(LOG_INFO, "will lookup group: [%s] and domain: [%s]\n", 
+			 request.data.name.name, request.data.name.dom_name);
+													  
+		if (pam_winbind_request_log(WINBINDD_LOOKUPNAME, &request, &response, ctrl, user)) {
+			_pam_log(LOG_INFO, "could not lookup group\n"); 
+			return PAM_AUTH_ERR;
+		}
+
+
+		/* check if sid is really a group sid */
+		if (response.data.sid.type == 2 /*SID_NAME_DOM_GRP */) {
+			required_membership = strdup(response.data.sid.sid);
+		} else {
+			_pam_log(LOG_INFO, "group was not a domain group\n"); 
+			return PAM_AUTH_ERR;
+		}
+
+	}
+
+	strncpy(request.data.auth.required_membership_sid, required_membership, 
+	        sizeof(request.data.auth.required_membership_sid)-1);
 	
-	
         return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user);
 }
 
@@ -419,6 +470,7 @@
 {
      const char *username;
      const char *password;
+     const char *required_membership = NULL;
      int retval = PAM_AUTH_ERR;
     
      /* parse arguments */
@@ -453,8 +505,26 @@
 #endif
      }
 
+     /* Retrieve group membership-string here */
+     int i;
+     for ( i=0; i<argc; i++ ) {
+
+	 if (!strncmp(argv[i], "required_membership", strlen("required_membership"))) {
+
+	     char *p;
+	     char *parm = strdup(argv[i]);
+
+	     if ( (p = strchr( parm, '=' )) == NULL) {
+	     	_pam_log(LOG_INFO, "no \"=\" delimiter found\n");
+		break;
+	     }
+
+	     required_membership = strdup(p+1);
+	 }
+     }
+
      /* Now use the username to look up password */
-     return winbind_auth_request(username, password, ctrl);
+     return winbind_auth_request(username, password, required_membership, ctrl);
 }
 
 PAM_EXTERN
@@ -546,6 +616,7 @@
 
 	/* <DO NOT free() THESE> */
 	const char *user;
+	const char *required_membership = NULL;
 	char *pass_old, *pass_new;
 	/* </DO NOT free() THESE> */
 
@@ -606,7 +677,7 @@
 		}
 		/* verify that this is the password for this user */
 		
-		retval = winbind_auth_request(user, pass_old, ctrl);
+		retval = winbind_auth_request(user, pass_old, required_membership, ctrl);
 		
 		if (retval != PAM_ACCT_EXPIRED 
 		    && retval != PAM_AUTHTOK_EXPIRED
Index: source/nsswitch/pam_winbind.h
===================================================================
--- source/nsswitch/pam_winbind.h	(revision 1374)
+++ source/nsswitch/pam_winbind.h	(working copy)
@@ -82,6 +82,7 @@
 #define WINBIND_TRY_FIRST_PASS_ARG (1<<3)
 #define WINBIND_USE_FIRST_PASS_ARG (1<<4)
 #define WINBIND__OLD_PASSWORD (1<<5)
+#define WINBIND_REQUIRED_MEMBERSHIP (1<<6)
 
 /*
  * here is the string to inform the user that the new passwords they


More information about the samba-technical mailing list