import from HEAD:
[freeradius.git] / src / modules / rlm_unix / rlm_unix.c
index 255604a..1db9607 100644 (file)
@@ -37,14 +37,10 @@ static const char rcsid[] = "$Id$";
 
 #include "config.h"
 
-#if HAVE_SHADOW_H
+#ifdef HAVE_SHADOW_H
 #  include     <shadow.h>
 #endif
 
-#if HAVE_CRYPT_H
-#  include <crypt.h>
-#endif
-
 #ifdef OSFC2
 #  include     <sys/security.h>
 #  include     <prot.h>
@@ -84,7 +80,7 @@ static CONF_PARSER module_config[] = {
         *      Cache the password by default.
         */
        { "cache",    PW_TYPE_BOOLEAN,
-         offsetof(struct unix_instance,cache_passwd), NULL, "yes" },
+         offsetof(struct unix_instance,cache_passwd), NULL, "no" },
        { "passwd",   PW_TYPE_STRING_PTR,
          offsetof(struct unix_instance,passwd_file), NULL,  NULL },
        { "shadow",   PW_TYPE_STRING_PTR,
@@ -92,12 +88,12 @@ static CONF_PARSER module_config[] = {
        { "group",    PW_TYPE_STRING_PTR,
          offsetof(struct unix_instance,group_file), NULL,   NULL },
        { "radwtmp",  PW_TYPE_STRING_PTR,
-         offsetof(struct unix_instance,radwtmp), NULL,   "${logdir}/radwtmp" },
+         offsetof(struct unix_instance,radwtmp), NULL,   "NULL" },
        { "usegroup", PW_TYPE_BOOLEAN,
          offsetof(struct unix_instance,usegroup), NULL,     "no" },
        { "cache_reload", PW_TYPE_INTEGER,
          offsetof(struct unix_instance,cache_reload), NULL, "600" },
-       
+
        { NULL, -1, 0, NULL, NULL }             /* end the list */
 };
 
@@ -115,16 +111,17 @@ static struct unix_instance *group_inst;
  * file) or not ("Group=" was bound to the first instance of rlm_unix */
 static int group_inst_explicit;
 
-#if HAVE_GETSPNAM
+#ifdef HAVE_GETSPNAM
 #if defined(M_UNIX)
-       static inline const char *get_shadow_name(shadow_pwd_t *spwd) {
-               if (spwd == NULL) return NULL;
-               return (spwd->pw_name);
-       }
-       static inline const char *get_shadow_encrypted_pwd(shadow_pwd_t *spwd) {
-               if (spwd == NULL) return NULL;
-               return (spwd->pw_passwd);
-       }
+static inline const char *get_shadow_name(shadow_pwd_t *spwd) {
+       if (spwd == NULL) return NULL;
+       return (spwd->pw_name);
+}
+
+static inline const char *get_shadow_encrypted_pwd(shadow_pwd_t *spwd) {
+       if (spwd == NULL) return NULL;
+       return (spwd->pw_passwd);
+}
 #else /* M_UNIX */
        static inline const char *get_shadow_name(shadow_pwd_t *spwd) {
                if (spwd == NULL) return NULL;
@@ -171,7 +168,7 @@ static struct group *fgetgrnam(const char *fname, const char *name) {
        return grp;
 }
 
-#if HAVE_GETSPNAM
+#ifdef HAVE_GETSPNAM
 
 static shadow_pwd_t *fgetspnam(const char *fname, const char *name) {
        FILE            *file = fopen(fname, "ro");
@@ -194,14 +191,16 @@ static shadow_pwd_t *fgetspnam(const char *fname, const char *name) {
 /*
  *     The Group = handler.
  */
-static int groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,
-       VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+static int groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request,
+                   VALUE_PAIR *check, VALUE_PAIR *check_pairs,
+                   VALUE_PAIR **reply_pairs)
 {
        struct passwd   *pwd;
        struct group    *grp;
        char            **member;
        char            *username;
        int             retval;
+       VALUE_PAIR      *vp;
 
        instance = instance;
        check_pairs = check_pairs;
@@ -212,9 +211,19 @@ static int groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE_PAI
                return 1;
        }
 
-       username = (char *)request->strvalue;
+       /*
+        *      No user name, doesn't compare.
+        */
+       vp = pairfind(request, PW_STRIPPED_USER_NAME);
+       if (!vp) {
+               vp = pairfind(request, PW_USER_NAME);
+               if (!vp) {
+                       return -1;
+               }
+       }
+       username = (char *)vp->strvalue;
 
-       if (group_inst->cache_passwd &&
+       if (group_inst->cache &&
            (retval = H_groupcmp(group_inst->cache, check, username)) != -2)
                return retval;
 
@@ -265,7 +274,11 @@ static int unix_instantiate(CONF_SECTION *conf, void **instance)
        /*
         *      Allocate room for the instance.
         */
-       inst = *instance = rad_malloc(sizeof(struct unix_instance));
+       inst = *instance = rad_malloc(sizeof(*inst));
+       if (!inst) {
+               return -1;
+       }
+       memset(inst, 0, sizeof(*inst));
 
        /*
         *      Parse the configuration, failing if we can't do so.
@@ -284,10 +297,14 @@ static int unix_instantiate(CONF_SECTION *conf, void **instance)
                 {
                        radlog(L_ERR, "HASH:  unable to create user "
                                "hash table.  disable caching and run debugs");
-                       free((char *) inst->passwd_file);
-                       free((char *) inst->shadow_file);
-                       free((char *) inst->group_file);
-                       free((char *) inst->radwtmp);
+                       if (inst->passwd_file)
+                               free((char *) inst->passwd_file);
+                       if (inst->shadow_file)
+                               free((char *) inst->shadow_file);
+                       if (inst->group_file)
+                               free((char *) inst->group_file);
+                       if (inst->radwtmp)
+                               free((char *) inst->radwtmp);
                        free(inst);
                        return -1;
                }
@@ -325,10 +342,14 @@ static int unix_detach(void *instance)
                group_inst = NULL;
                group_inst_explicit = 0;
        }
-       free((char *) inst->passwd_file);
-       free((char *) inst->shadow_file);
-       free((char *) inst->group_file);
-       free((char *) inst->radwtmp);
+       if (inst->passwd_file)
+               free((char *) inst->passwd_file);
+       if (inst->shadow_file)
+               free((char *) inst->shadow_file);
+       if (inst->group_file)
+               free((char *) inst->group_file);
+       if (inst->radwtmp)
+               free((char *) inst->radwtmp);
        if (inst->cache) {
                unix_freepwcache(inst->cache);
        }
@@ -356,10 +377,9 @@ static int unix_authenticate(void *instance, REQUEST *request)
 #define inst ((struct unix_instance *)instance)
        char *name, *passwd;
        struct passwd   *pwd;
-       char            *encpw;
-       char            *encrypted_pass;
+       const char      *encrypted_pass;
        int             ret;
-#if HAVE_GETSPNAM
+#ifdef HAVE_GETSPNAM
        shadow_pwd_t    *spwd = NULL;
 #endif
 #ifdef OSFC2
@@ -454,7 +474,7 @@ static int unix_authenticate(void *instance, REQUEST *request)
        name = (char *)request->username->strvalue;
        passwd = (char *)request->password->strvalue;
 
-       if (inst->cache_passwd &&
+       if (inst->cache &&
            (ret = H_unix_pass(inst->cache, name, passwd, &request->reply->vps)) != -2)
                return (ret == 0) ? RLM_MODULE_OK : RLM_MODULE_REJECT;
 
@@ -497,7 +517,7 @@ static int unix_authenticate(void *instance, REQUEST *request)
        encrypted_pass = pwd->pw_passwd;
 #endif /* OSFC2 */
 
-#if HAVE_GETSPNAM
+#ifdef HAVE_GETSPNAM
        /*
         *      See if there is a shadow password.
         *
@@ -532,7 +552,7 @@ static int unix_authenticate(void *instance, REQUEST *request)
        }
 #endif
 
-#if HAVE_GETUSERSHELL
+#ifdef HAVE_GETUSERSHELL
        /*
         *      Check /etc/shells for a valid shell. If that file
         *      contains /RADIUSD/ANY/SHELL then any shell will do.
@@ -592,8 +612,7 @@ static int unix_authenticate(void *instance, REQUEST *request)
        /*
         *      Check encrypted password.
         */
-       encpw = crypt(passwd, encrypted_pass);
-       if (strcmp(encpw, encrypted_pass)) {
+       if (lrad_crypt_check(passwd, encrypted_pass)) {
                radlog(L_AUTH, "rlm_unix: [%s]: invalid password", name);
                return RLM_MODULE_REJECT;
        }
@@ -637,7 +656,7 @@ static char *uue(void *in)
 static int unix_accounting(void *instance, REQUEST *request)
 {
        VALUE_PAIR      *vp;
-       NAS             *cl;
+       RADCLIENT       *cl;
        FILE            *fp;
        struct utmp     ut;
        time_t          t;
@@ -654,10 +673,18 @@ static int unix_accounting(void *instance, REQUEST *request)
        struct unix_instance *inst = (struct unix_instance *) instance;
 
        /*
+        *      No radwtmp.  Don't do anything.
+        */
+       if (!inst->radwtmp) {
+               DEBUG2("rlm_unix: No radwtmp file configured.  Ignoring accounting request.");
+               return RLM_MODULE_NOOP;
+       }
+
+       /*
         *      Which type is this.
         */
        if ((vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE))==NULL) {
-               radlog(L_ERR, "Accounting: no Accounting-Status-Type record.");
+               radlog(L_ERR, "rlm_unix: no Accounting-Status-Type attribute in request.");
                return RLM_MODULE_NOOP;
        }
        status = vp->lvalue;
@@ -701,7 +728,7 @@ static int unix_accounting(void *instance, REQUEST *request)
                        case PW_NAS_IP_ADDRESS:
                                nas_address = vp->lvalue;
                                break;
-                       case PW_NAS_PORT_ID:
+                       case PW_NAS_PORT:
                                nas_port = vp->lvalue;
                                port_seen = 1;
                                break;
@@ -716,7 +743,7 @@ static int unix_accounting(void *instance, REQUEST *request)
 
        /*
         *      We don't store !root sessions, or sessions
-        *      where we didn't see a PW_NAS_PORT_ID.
+        *      where we didn't see a NAS-Port attribute.
         */
        if (strncmp(ut.ut_name, "!root", sizeof(ut.ut_name)) == 0 || !port_seen)
                return RLM_MODULE_NOOP;
@@ -739,7 +766,7 @@ static int unix_accounting(void *instance, REQUEST *request)
         *      and address so that the tty field is unique.
         */
        s = "";
-       if ((cl = nas_find(nas_address)) != NULL)
+       if ((cl = client_find(nas_address)) != NULL)
                s = cl->shortname;
        if (s == NULL || s[0] == 0) s = uue(&(nas_address));
        sprintf(buf, "%03d:%s", nas_port, s);
@@ -751,7 +778,7 @@ static int unix_accounting(void *instance, REQUEST *request)
 #ifdef UT_HOSTSIZE
        if (framed_address) {
                ip_ntoa(buf, framed_address);
-               strncpy(ut.ut_host, buf, UT_HOSTSIZE);
+               strncpy(ut.ut_host, buf, sizeof(ut.ut_host));
        }
 #endif
 #ifdef HAVE_UTMPX_H
@@ -788,7 +815,7 @@ static int unix_accounting(void *instance, REQUEST *request)
                        return RLM_MODULE_FAIL;
                }
                fclose(fp);
-       } else 
+       } else
                return RLM_MODULE_FAIL;
 
        return RLM_MODULE_OK;
@@ -805,7 +832,10 @@ module_t rlm_unix = {
          NULL,                 /* authorization */
          NULL,                 /* preaccounting */
          unix_accounting,      /* accounting */
-         NULL                  /* checksimul */
+         NULL,                  /* checksimul */
+         NULL,                 /* pre-proxy */
+         NULL,                 /* post-proxy */
+         NULL                  /* post-auth */
   },
   unix_detach,                         /* detach */
   unix_destroy,                  /* destroy */