Alan DeKok wrote:
Walter Goulet <[EMAIL PROTECTED]> wrote:

Quick question regarding pam_radius_auth. Since you have to have a
local account on the client machine using pam_radius_auth to
authenticate ssh sessions, how would you go about adding a realm to
the username portion of the authentication request?


  Edit the source code to the PAM module, and re-compile.


Can I specify this with the client-id option in the pam_radius_auth
configuration file?


  No.

  Alan DeKok.
- List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html


I took a stab at adding support for specifying a realm as an additional option to the pam module configuration. You can specify the realm that will be appended to all outgoing RADIUS access requests in the application specific pam config files in /etc/pam.d.

auth       sufficient   pam_radius_auth.so debug realm=test.com

I tested this configuration by using openbsd's port of the radius-cistron 1.6.7 server as my RADIUS proxy server and freeradius 1.0.5 as the radius authenticator that owns the realm. Seems to work ok; I took a peek at the RADIUS dialog via Ethereal and the access request is routed correctly to the freeradius server.

I haven't really programmed in C in a while, so please forgive any silly errors I may have made in the code. Also note that I used svn locally to keep track of my work, so my revision 1 corresponds to 1.3.16 downloaded from the freeradius site.

Patch text follows.

Thanks,
Walter

Index: pam_radius_auth.c
===================================================================
--- pam_radius_auth.c   (revision 1)
+++ pam_radius_auth.c   (revision 6)
@@ -25,6 +25,7 @@
  *          no options.  Patch from Jon Nelson <[EMAIL PROTECTED]>
  * 1.3.14 - Don't use PATH_MAX, so it builds on GNU Hurd.
  * 1.3.15 - Implement retry option, miscellanous bug fixes.
+
  *
  *
  *   This program is free software; you can redistribute it and/or modify
@@ -83,12 +84,12 @@

     va_start(args, format);
     vsprintf(buffer, format, args);
-    /* don't do openlog or closelog, but put our name in to be friendly */
+    // don't do openlog or closelog, but put our name in to be friendly
     syslog(err, "%s: %s", pam_module_name, buffer);
     va_end(args);
+    printf("Debug Err: %s: %s",pam_module_name,buffer);
 }

-/* argument parsing */
 static int _pam_parse(int argc, CONST char **argv, radius_conf_t *conf)
 {
   int ctrl=0;
@@ -131,6 +132,8 @@
       } else {
        conf->client_id = (char *) *argv+10; /* point to the client-id */
       }
+    } else if (!strncmp(*argv, "realm=", 6)) {
+ conf->client_realm = (char *) *argv+6; /* point to the client-realm */
     } else if (!strcmp(*argv, "accounting_bug")) {
       conf->accounting_bug = TRUE;

@@ -1050,6 +1053,7 @@
 PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,CONST char **argv)
 {
+  char *user_and_realm;
   CONST char *user;
   char *password = NULL;
   CONST char *rhost;
@@ -1063,10 +1067,13 @@
   AUTH_HDR *response = (AUTH_HDR *) recv_buffer;
   radius_conf_t config;
   int tries;
+  int realm_specified = 0;

   ctrl = _pam_parse(argc, argv, &config);
   tries = ((ctrl & PAM_RETRY) >> 4) + 1;

+  realm_specified = strlen(config.client_realm);
+
   /* grab the user name */
   retval = pam_get_user(pamh, &user, NULL);
   PAM_FAIL_CHECK;
@@ -1084,6 +1091,16 @@

   DPRINT(LOG_DEBUG, "Got user name %s", user);

+  if(realm_specified)
+  {
+ user_and_realm = malloc(strlen(user) + MAXPWNAM); /* making maxlen of realm value MAXPWNAM seems
+                                                           reasonable. */
+      memset(user_and_realm, 0, strlen(user_and_realm));
+      strncat(user_and_realm,user,strlen(user));
+      strncat(user_and_realm,"@",1);
+ strncat(user_and_realm,config.client_realm,strlen(config.client_realm));
+  }
+
   /*
    * Get the IP address of the authentication server
    * Then, open a socket, and bind it to a port
@@ -1133,7 +1150,14 @@
     }
   } /* end of password == NULL */

-  build_radius_packet(request, user, password, &config);
+  if(realm_specified)
+  {
+      build_radius_packet(request, user_and_realm, password, &config);
+  }
+  else
+  {
+      build_radius_packet(request, user_and_realm, password, &config);
+  }
   /* not all servers understand this service type, but some do */
   add_int_attribute(request, PW_USER_SERVICE_TYPE, PW_AUTHENTICATE_ONLY);

@@ -1183,7 +1207,14 @@
retval = rad_converse(pamh, PAM_PROMPT_ECHO_ON, challenge, &resp2challenge);

     /* now that we've got a response, build a new radius packet */
-    build_radius_packet(request, user, resp2challenge, &config);
+    if(realm_specified)
+    {
+ build_radius_packet(request, user_and_realm, resp2challenge, &config);
+    }
+    else
+    {
+        build_radius_packet(request, user, resp2challenge, &config);
+    }
     /* request->code is already PW_AUTHENTICATION_REQUEST */
     request->id++;             /* one up from the request */

@@ -1214,6 +1245,11 @@
             , retval==PAM_SUCCESS ? "succeeded":"failed" );
   }

+  /* don't forget to free user/realm string */
+  if(strlen(user_and_realm))
+  {
+      free(user_and_realm);
+  }
   close(config.sockfd);
   cleanup(config.server);
   _pam_forget(password);
@@ -1251,9 +1287,11 @@
                    int argc, CONST char **argv,
                    int status)
 {
+  char *user_and_realm; /* Need non-const user to add realm info */
   CONST char *user;
   int ctrl;
   int retval = PAM_AUTH_ERR;
+  int realm_specified = 0;

   char recv_buffer[4096];
   char send_buffer[4096];
@@ -1262,7 +1300,18 @@
   radius_conf_t config;

   ctrl = _pam_parse(argc, argv, &config);
+  realm_specified = strlen(config.client_realm);

+  if(realm_specified)
+  {
+ user_and_realm = malloc(strlen(user) + MAXPWNAM); /* making maxlen of realm value MAXPWNAM seems
+                                                           reasonable. */
+      memset(user_and_realm, 0, strlen(user_and_realm));
+      strncat(user_and_realm,user,strlen(user));
+      strncat(user_and_realm,"@",1);
+ strncat(user_and_realm,config.client_realm,strlen(config.client_realm));
+  }
+
   /* grab the user name */
   retval = pam_get_user(pamh, &user, NULL);
   PAM_FAIL_CHECK;
@@ -1298,7 +1347,14 @@
   get_random_vector(request->vector);
request->id = request->vector[0]; /* this should be evenly distributed */

-  build_radius_packet(request, user, NULL, &config);
+  if(realm_specified)
+  {
+      build_radius_packet(request, user_and_realm, NULL, &config);
+  }
+  else
+  {
+      build_radius_packet(request, user, NULL, &config);
+  }

   add_int_attribute(request, PW_ACCT_STATUS_TYPE, status);

@@ -1323,6 +1379,12 @@
     goto error;
   }

+  /* don't forget to free user/realm string */
+  if(strlen(user_and_realm))
+  {
+      free(user_and_realm);
+  }
+
   retval = PAM_SUCCESS;

 error:
@@ -1354,13 +1416,15 @@
 PAM_EXTERN int
pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, CONST char **argv)
 {
-  CONST char *user;
+  char *user_and_realm; /* Need non-const user to add realm info */
+  CONST char *user;
   char *password = NULL;
   char *new_password = NULL;
   char *check_password = NULL;
   int ctrl;
   int retval = PAM_AUTHTOK_ERR;
   int attempts;
+  int realm_specified = 0;

   char recv_buffer[4096];
   char send_buffer[4096];
@@ -1370,6 +1434,10 @@

   ctrl = _pam_parse(argc, argv, &config);

+  if(strlen(config.client_realm) > 0)
+  {
+     realm_specified = 1;
+  }
   /* grab the user name */
   retval = pam_get_user(pamh, &user, NULL);
   PAM_FAIL_CHECK;
@@ -1380,6 +1448,16 @@
     return PAM_USER_UNKNOWN;
   }

+  /* now add the realm to the user name if a realm has been specified */
+  if(realm_specified)
+  {
+ user_and_realm = malloc(strlen(user) + MAXPWNAM); /* making maxlen of realm value MAXPWNAM seems
+                                                           reasonable. */
+      memset(user_and_realm, 0, strlen(user_and_realm));
+      strncat(user_and_realm,user,strlen(user));
+      strncat(user_and_realm,"@",1);
+  }
+
   /*
    * Get the IP address of the authentication server
    * Then, open a socket, and bind it to a port
@@ -1430,7 +1508,15 @@
     get_random_vector(request->vector);
request->id = request->vector[0]; /* this should be evenly distributed */

-    build_radius_packet(request, user, password, &config);
+    if(realm_specified)
+    {
+        build_radius_packet(request, user_and_realm, password, &config);
+    }
+    else
+    {
+        build_radius_packet(request, user, password, &config);
+    }
+
add_int_attribute(request, PW_USER_SERVICE_TYPE, PW_AUTHENTICATE_ONLY);

     retval = talk_radius(&config, request, response, password, NULL, 1);
@@ -1533,7 +1619,14 @@
     _pam_forget(config.server->secret);
     config.server->secret = strdup(password); /* it's free'd later */

-    build_radius_packet(request, user, new_password, &config);
+    if(realm_specified)
+    {
+ build_radius_packet(request, user_and_realm, new_password, &config);
+    }
+    else
+    {
+        build_radius_packet(request, user, new_password, &config);
+    }
     add_password(request, PW_OLD_PASSWORD, password, password);

retval = talk_radius(&config, request, response, new_password, password, 1);
@@ -1567,6 +1660,12 @@
     _pam_log(LOG_DEBUG, "password change %s"
             , retval==PAM_SUCCESS ? "succeeded":"failed" );
   }
+
+  /* don't forget to free user/realm string */
+  if(strlen(user_and_realm))
+  {
+      free(user_and_realm);
+  }

   close(config.sockfd);
   cleanup(config.server);






- List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html

Reply via email to