[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

radius in pwdb and pam_pwdb



Witam
 
 I wrote a patch for pam_pwdb to support pwdb_radius autenthication.
 I had to change some things in pwdb also. Both patches are very dirt,
they contains lots of checkpoints i used to debug.
 Patch for pwdb_0.55preA is not tested, i cuoldn't compile it becceuse of
som strange errores in rpc/*.h. 
How it works:
 Libwdb now on both ACK and NAK response from radius server returns a
"good" pwdb struct. A special pwdb entry named "Code" is appended to 
pwdb struct containing a type of packet received ("ACK" or "NAK").
Pam_pwdb using that entry makes an decision to grant or deny user.
 
 With some changes to dictionary file (adding uid,gid,gecos,dir and shell
attributes) it is possible to login user using only radius database.
Howewer account managerment is not done yet so you have to set pam_permit
for this stage. 

Comments are welcome ;-) 
   
Grzegorz Stanislawski
Open-Net / PKFL
diff -ruN old/pam_pwdb/support.-c new/pam_pwdb/support.-c
--- old/pam_pwdb/support.-c	Sat Jan 31 23:42:29 1998
+++ new/pam_pwdb/support.-c	Mon Dec 21 21:37:57 1998
@@ -418,6 +418,7 @@
     char *pp;
     char *data_name;
     int retval;
+    int radius=0;
 
     D(("called"));
 
@@ -432,16 +433,31 @@
 
     D(("locating user's record"));
     retval = pwdb_locate("user", PWDB_DEFAULT, name, PWDB_ID_UNKNOWN, &pw);
+    pwdb_print_pwdb_struct(pw);
     if (retval == PWDB_PASS_PHRASE_REQD) {
 	/*
 	 * give the password to the pwdb library. It may be needed to
 	 * access the database
 	 */
-
-	retval = pwdb_set_entry( pw, "pass_phrase", p, 1+strlen(p)
+/*        retval = pwdb_delete(&pw);
+	if (retval != PWDB_SUCCESS) {
+	    _log_err(LOG_ALERT, "find pass1; %s", pwdb_strerror(retval));
+	    (void) pwdb_delete(&pw);
+	    p = NULL;
+	    return PAM_CRED_INSUFFICIENT;
+	}
+	retval = pwdb_new(&pw,20);
+	if (retval != PWDB_SUCCESS) {
+	    _log_err(LOG_ALERT, "find pass2; %s", pwdb_strerror(retval));
+	    (void) pwdb_delete(&pw);
+	    p = NULL;
+	    return PAM_CRED_INSUFFICIENT;
+	}
+*/	retval = pwdb_set_entry( pw, "pass_phrase", p, 1+strlen(p)
 				 , NULL, NULL, 0);
+        radius=1;
 	if (retval != PWDB_SUCCESS) {
-	    _log_err(LOG_ALERT, "find pass; %s", pwdb_strerror(retval));
+	    _log_err(LOG_ALERT, "find pass3; %s", pwdb_strerror(retval));
 	    (void) pwdb_delete(&pw);
 	    p = NULL;
 	    return PAM_CRED_INSUFFICIENT;
@@ -449,7 +465,8 @@
 
 	retval = pwdb_locate("user", pw->source, name, PWDB_ID_UNKNOWN, &pw);
     }
-
+     _log_err(LOG_ALERT,"check00 %p",pw);
+    pwdb_print_pwdb_struct(pw);
     if (retval != PWDB_SUCCESS) {
 	D(("user's record unavailable"));
 	if ( on(UNIX_AUDIT, ctrl) ) {
@@ -464,13 +481,35 @@
 	return PAM_USER_UNKNOWN;
     }
 
+     _log_err(LOG_ALERT,"check0a %p",pw);
+    if (radius) {
+      pwdb_print_pwdb_struct(pw);
+      retval = pwdb_get_entry(pw, "Code", &pwe);
+      _log_err(LOG_ALERT,"check0b %p",pw);
+     _log_err(LOG_ALERT,"check0c %d,%d,%d",retval,PWDB_SUCCESS,PWDB_NOT_FOUND);
+      if (retval != PWDB_SUCCESS ) {
+         retval = PAM_AUTHINFO_UNAVAIL;
+         _log_err(LOG_ALERT, "get passwd; %s", pwdb_strerror(retval)); 
+ 	 (void) pwdb_delete(&pw);
+	 p = NULL;
+	 return retval;
+      }
+      salt = (const char *) pwe->value;
+      if ( strcmp( "ACK", salt ) == 0 ) {
+
+  	retval = PAM_SUCCESS;
+	if (data_name) {                     /* reset failures */
+	    pam_set_data(pamh, data_name, NULL, _cleanup_failures);
+	} 
+      }      
+    } else {
     /*
      * courtesy of PWDB the password for the user is stored in
      * encrypted form in the "passwd" entry of pw.
      */
-
-    retval = pwdb_get_entry(pw, "passwd", &pwe);
-    if (retval != PWDB_SUCCESS) {
+     retval = pwdb_get_entry(pw, "passwd", &pwe);
+     _log_err(LOG_ALERT,"check1 %d,%d,%d",retval,PWDB_SUCCESS,PWDB_NOT_FOUND);
+     if (retval != PWDB_SUCCESS ) {
 	if (geteuid()) {
 	    /* we are not root perhaps this is the reason? Run helper */
 	    D(("running helper binary"));
@@ -482,16 +521,18 @@
 	(void) pwdb_delete(&pw);
 	p = NULL;
 	return retval;
-    }
-    salt = (const char *) pwe->value;
-
+      }
+      salt = (const char *) pwe->value;
+      _log_err(LOG_ALERT,"check2");
+    
     /*
      * XXX: Cristian, the above is not the case for RADIUS(?) Some
      * lines should be added for RADIUS to verify the password in
      * clear text...
      */
 
-    if ( ( !salt ) && ( !p ) ) {
+      if ( ( !salt ) && ( !p ) ) {
+        _log_err(LOG_ALERT,"check3");
 
 	/* the stored password is NULL */
 
@@ -503,28 +544,31 @@
 	} else {
 	    return PAM_AUTH_ERR;
 	}
-    }
-
-    pp = _pam_md(p, salt);
-    p = NULL;                                /* no longer needed here */
-
-    data_name = (char *) malloc(sizeof(FAIL_PREFIX)+strlen(name));
-    if ( data_name == NULL ) {
-	_log_err(LOG_CRIT, "no memory for data-name");
-    }
-    strcpy(data_name, FAIL_PREFIX);
-    strcpy(data_name + sizeof(FAIL_PREFIX)-1, name);
+      }      
+      pp = _pam_md(p, salt);
+      _log_err(LOG_ALERT,"%s",pp);
+      p = NULL;                                /* no longer needed here */
+
+      _log_err(LOG_ALERT,"check4");
+
+      data_name = (char *) malloc(sizeof(FAIL_PREFIX)+strlen(name));
+      if ( data_name == NULL ) {
+  	_log_err(LOG_CRIT, "no memory for data-name");
+      }
+      strcpy(data_name, FAIL_PREFIX);
+      strcpy(data_name + sizeof(FAIL_PREFIX)-1, name);
 
     /* the moment of truth -- do we agree with the password? */
 
-    if ( strcmp( pp, salt ) == 0 ) {
+      if ( strcmp( pp, salt ) == 0 ) {
 
-	retval = PAM_SUCCESS;
+  	retval = PAM_SUCCESS;
 	if (data_name) {                     /* reset failures */
 	    pam_set_data(pamh, data_name, NULL, _cleanup_failures);
 	}
-
-    } else {
+     }
+   } 
+      if (retval !=PAM_SUCCESS) {
 
 	retval = PAM_AUTH_ERR;
 	if (data_name != NULL) {
@@ -560,7 +604,7 @@
 	    }
 	}
 
-    }
+     }
 
     (void) pwdb_entry_delete(&pwe);
     (void) pwdb_delete(&pw);
diff -ruN old/libpwdb-0.54preC/include/pwdb/pwdb_radius.h new/libpwdb-0.54preC/include/pwdb/pwdb_radius.h
--- old/libpwdb-0.54preC/include/pwdb/pwdb_radius.h	Sat Jan  4 17:24:22 1997
+++ new/libpwdb-0.54preC/include/pwdb/pwdb_radius.h	Mon Dec 21 20:33:07 1998
@@ -61,6 +61,7 @@
 #define PWDB_RADIUS_LOCAL_ERR	6	/* local error - services file, etc. */
 #define PWDB_RADIUS_SOCKET_ERR	7	/* socket creation/communication error */
 #define PWDB_RADIUS_TIMEOUT     8       /* timeout communicating with the server */
+#define PWDB_RADIUS_REJECT      9       /* reject */
 
 /* Helper RADIUS functions */
 const char *radstr_ust(u_int type);
diff -ruN old/libpwdb-0.54preC/libpwdb/pwdb/interface/radius/user.c new/libpwdb-0.54preC/libpwdb/pwdb/interface/radius/user.c
--- old/libpwdb-0.54preC/libpwdb/pwdb/interface/radius/user.c	Fri Jan  3 03:12:14 1997
+++ new/libpwdb-0.54preC/libpwdb/pwdb/interface/radius/user.c	Mon Dec 21 22:58:14 1998
@@ -8,7 +8,7 @@
  */
 
 static int _pwdb_radius_return_data(RADIUS_RESULT rad_result,
-                                    const struct pwdb **p)
+                                    const struct pwdb **p,int code)
 {
     int         length;
     u_char        *buffer;
@@ -30,6 +30,11 @@
     /*
      * Extract attribute-value pairs
      */
+    if (code==PWDB_RADIUS_SUCCESS) {
+      retval = pwdb_set_entry(*p, "Code", "ACK", 4, NULL, txtcpy, 4);
+    } else {
+      retval = pwdb_set_entry(*p, "Code", "NAK", 4, NULL, txtcpy, 4);
+    }
     ptr = buffer;
     while(length > 0) {
 	attribute = *ptr++;
@@ -172,7 +177,7 @@
     }    
 
     /* now is a good time to clear&destroy the pass_phrase entry */
-    retval = pwdb_set_entry(*p,"pass_phrase",NULL,-1,NULL,NULL,0); \
+    retval = pwdb_set_entry(*p,"pass_phrase",NULL,-1,NULL,NULL,0); 
     if (retval != PWDB_SUCCESS) {
         pwdb_entry_user = _pwdb_delete_string(pwdb_entry_user);
         clear_password = _pwdb_delete_string(clear_password);
@@ -194,7 +199,7 @@
     retval = rad_authenticate(rad_server, name, clear_password,&rad_result);
     clear_password = _pwdb_delete_string(clear_password);
     pwdb_entry_user = _pwdb_delete_string(pwdb_entry_user);
-    if (retval != PWDB_RADIUS_SUCCESS) {
+    if ((retval != PWDB_RADIUS_SUCCESS)&&(retval != PWDB_RADIUS_REJECT)) {
         switch (retval) {
             case PWDB_RADIUS_CONF_ERR:
             case PWDB_RADIUS_LOCAL_ERR:
@@ -207,7 +212,7 @@
                 return PWDB_ABORT;
         }
     }
-    retval = _pwdb_radius_return_data(rad_result,p);
+    retval = _pwdb_radius_return_data(rad_result,p,retval);
     return retval;
 }
 
@@ -309,7 +314,7 @@
     clear_old_password = _pwdb_delete_string(clear_old_password);
     clear_new_password = _pwdb_delete_string(clear_new_password);
     pwdb_entry_user = _pwdb_delete_string(pwdb_entry_user);
-    if (retval != PWDB_RADIUS_SUCCESS) {
+    if ((retval != PWDB_RADIUS_SUCCESS)&&(retval != PWDB_RADIUS_REJECT)) {
         switch (retval) {
             case PWDB_RADIUS_CONF_ERR:
             case PWDB_RADIUS_LOCAL_ERR:
@@ -322,7 +327,7 @@
                 return PWDB_ABORT;
         }
     }
-    retval = _pwdb_radius_return_data(rad_result,p);
+    retval = _pwdb_radius_return_data(rad_result,p,retval);
     return retval;
 }
 
diff -ruN old/libpwdb-0.54preC/libpwdb/radius/public.h new/libpwdb-0.54preC/libpwdb/radius/public.h
--- old/libpwdb-0.54preC/libpwdb/radius/public.h	Sat Jan  4 17:24:22 1997
+++ new/libpwdb-0.54preC/libpwdb/radius/public.h	Mon Dec 21 20:33:07 1998
@@ -61,6 +61,7 @@
 #define PWDB_RADIUS_LOCAL_ERR	6	/* local error - services file, etc. */
 #define PWDB_RADIUS_SOCKET_ERR	7	/* socket creation/communication error */
 #define PWDB_RADIUS_TIMEOUT     8       /* timeout communicating with the server */
+#define PWDB_RADIUS_REJECT      9       /* reject */
 
 /* Helper RADIUS functions */
 const char *radstr_ust(u_int type);
diff -ruN old/libpwdb-0.54preC/libpwdb/radius/radius.c new/libpwdb-0.54preC/libpwdb/radius/radius.c
--- old/libpwdb-0.54preC/libpwdb/radius/radius.c	Sat Jan  4 14:05:19 1997
+++ new/libpwdb-0.54preC/libpwdb/radius/radius.c	Mon Dec 21 22:51:15 1998
@@ -554,7 +554,7 @@
     if (!server.hostname || !server.secret)
         return PWDB_RADIUS_BAD_REQ;
 
-    svp = getservbyname ("radius", "udp");
+    svp = getservbyname ("radacct", "udp");
     if (svp == (struct servent *) 0) {
         return PWDB_RADIUS_LOCAL_ERR;
     }
diff -ruN old/libpwdb-0.55preA/modules/radius_user/module.h new/libpwdb-0.55preA/modules/radius_user/module.h
--- old/libpwdb-0.55preA/modules/radius_user/module.h	Tue Apr  8 06:19:39 1997
+++ new/libpwdb-0.55preA/modules/radius_user/module.h	Thu Dec 24 05:06:28 1998
@@ -64,6 +64,7 @@
 #define PWDB_RADIUS_LOCAL_ERR	6	/* local error - services file, etc. */
 #define PWDB_RADIUS_SOCKET_ERR	7	/* socket creation/communication error */
 #define PWDB_RADIUS_TIMEOUT     8       /* timeout communicating with the server */
+#define PWDB_RADIUS_REJECT      9       /* reject */
 
 /* Helper RADIUS functions */
 const char *radstr_ust(u_int type);
diff -ruN old/libpwdb-0.55preA/modules/radius_user/radius.c new/libpwdb-0.55preA/modules/radius_user/radius.c
--- old/libpwdb-0.55preA/modules/radius_user/radius.c	Tue Apr  8 06:19:36 1997
+++ new/libpwdb-0.55preA/modules/radius_user/radius.c	Thu Dec 24 05:05:39 1998
@@ -553,7 +553,7 @@
     if (!server.hostname || !server.secret)
         return PWDB_RADIUS_BAD_REQ;
 
-    svp = getservbyname ("radius", "udp");
+    svp = getservbyname ("radacct", "udp");
     if (svp == (struct servent *) 0) {
         return PWDB_RADIUS_LOCAL_ERR;
     }
diff -ruN old/libpwdb-0.55preA/modules/radius_user/radius_user.c new/libpwdb-0.55preA/modules/radius_user/radius_user.c
--- old/libpwdb-0.55preA/modules/radius_user/radius_user.c	Tue Apr  8 20:30:42 1997
+++ new/libpwdb-0.55preA/modules/radius_user/radius_user.c	Thu Dec 24 05:17:40 1998
@@ -10,7 +10,7 @@
 };
 
 static int _pwdb_radius_return_data(RADIUS_RESULT rad_result,
-                                    const struct pwdb **p)
+                                    const struct pwdb **p,int code)
 {
     int         length;
     u_char        *buffer;
@@ -32,6 +32,11 @@
     /*
      * Extract attribute-value pairs
      */
+    if (code==PWDB_RADIUS_SUCCESS) {
+      retval = pwdb_set_entry(*p, "Code", "ACK", 4, NULL, txtcpy, 4);
+    } else {
+      retval = pwdb_set_entry(*p, "Code", "NAK", 4, NULL, txtcpy, 4);
+    }
     ptr = buffer;
     while(length > 0) {
 	attribute = *ptr++;
@@ -194,7 +199,7 @@
     retval = rad_authenticate(rad_server, name, clear_password,&rad_result);
     clear_password = _pwdb_delete_string(clear_password);
     pwdb_entry_user = _pwdb_delete_string(pwdb_entry_user);
-    if (retval != PWDB_RADIUS_SUCCESS) {
+    if ((retval != PWDB_RADIUS_SUCCESS)&&(retval != PWDB_RADIUS_REJECT)) {
         switch (retval) {
             case PWDB_RADIUS_CONF_ERR:
             case PWDB_RADIUS_LOCAL_ERR:
@@ -207,7 +212,7 @@
                 return PWDB_ABORT;
         }
     }
-    retval = _pwdb_radius_return_data(rad_result,p);
+    retval = _pwdb_radius_return_data(rad_result,p,retval);
     return retval;
 }
 
@@ -306,7 +311,7 @@
     clear_old_password = _pwdb_delete_string(clear_old_password);
     clear_new_password = _pwdb_delete_string(clear_new_password);
     pwdb_entry_user = _pwdb_delete_string(pwdb_entry_user);
-    if (retval != PWDB_RADIUS_SUCCESS) {
+    if ((retval != PWDB_RADIUS_SUCCESS)&&(retval != PWDB_RADIUS_REJECT)) {
         switch (retval) {
             case PWDB_RADIUS_CONF_ERR:
             case PWDB_RADIUS_LOCAL_ERR:
@@ -319,7 +324,7 @@
                 return PWDB_ABORT;
         }
     }
-    retval = _pwdb_radius_return_data(rad_result,p);
+    retval = _pwdb_radius_return_data(rad_result,p,retval);
     return retval;
 }
 

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index] []