]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/auth.c
Merge remote-tracking branch 'origin/branch-netatalk-3-0' into develop
[netatalk.git] / etc / afpd / auth.c
index a41c624d8db739edfe5e46554aeb3fc8a7e7d1f8..f04404edd2f469af47152fccf96db6ccae7d23e8 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
-#ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif /* HAVE_UNISTD_H */
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/stat.h>
-#include <netatalk/endian.h>
+#include <arpa/inet.h>
+
 #include <atalk/afp.h>
 #include <atalk/compat.h>
 #include <atalk/util.h>
@@ -40,6 +39,8 @@ extern void afp_get_cmdline( int *ac, char ***av );
 #include <atalk/server_ipc.h>
 #include <atalk/uuid.h>
 #include <atalk/globals.h>
+#include <atalk/spotlight.h>
+#include <atalk/unix.h>
 
 #include "auth.h"
 #include "uam_auth.h"
@@ -51,40 +52,7 @@ extern void afp_get_cmdline( int *ac, char ***av );
 #include "acls.h"
 #endif
 
-int afp_version = 11;
 static int afp_version_index;
-
-uid_t   uuid;
-
-#if defined( sun ) && !defined( __svr4__ ) || defined( ultrix )
-
-int *groups;
-#define GROUPS_SIZE sizeof(int)
-
-#else /* sun __svr4__ ultrix */
-
-gid_t   *groups;
-#define GROUPS_SIZE sizeof(gid_t)
-#endif /* sun ultrix */
-
-int ngroups;
-
-/*
- * These numbers are scattered throughout the code.
- */
-static struct afp_versions  afp_versions[] = {
-#ifndef NO_DDP
-    { "AFPVersion 1.1", 11 },
-    { "AFPVersion 2.0", 20 },
-    { "AFPVersion 2.1", 21 },
-#endif /* ! NO_DDP */
-    { "AFP2.2", 22 },
-    { "AFPX03", 30 },
-    { "AFP3.1", 31 },
-    { "AFP3.2", 32 },
-    { "AFP3.3", 33 }
-};
-
 static struct uam_mod uam_modules = {NULL, NULL, &uam_modules, &uam_modules};
 static struct uam_obj uam_login = {"", "", 0, {{NULL, NULL, NULL, NULL }}, &uam_login,
                                    &uam_login};
@@ -94,19 +62,16 @@ static struct uam_obj uam_changepw = {"", "", 0, {{NULL, NULL, NULL, NULL}}, &ua
 static struct uam_obj *afp_uam = NULL;
 
 
-void status_versions( char *data, const ASP asp, const DSI *dsi)
+void status_versions( char *data, const DSI *dsi)
 {
     char                *start = data;
-    u_int16_t           status;
+    uint16_t           status;
     int         len, num, i, count = 0;
 
     memcpy(&status, start + AFPSTATUS_VERSOFF, sizeof(status));
     num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ] );
 
     for ( i = 0; i < num; i++ ) {
-#ifndef NO_DDP
-        if ( !asp && (afp_versions[ i ].av_number <= 21)) continue;
-#endif /* ! NO_DDP */
         if ( !dsi && (afp_versions[ i ].av_number >= 22)) continue;
         count++;
     }
@@ -114,9 +79,6 @@ void status_versions( char *data, const ASP asp, const DSI *dsi)
     *data++ = count;
 
     for ( i = 0; i < num; i++ ) {
-#ifndef NO_DDP
-        if ( !asp && (afp_versions[ i ].av_number <= 21)) continue;
-#endif /* ! NO_DDP */
         if ( !dsi && (afp_versions[ i ].av_number >= 22)) continue;
         len = strlen( afp_versions[ i ].av_name );
         *data++ = len;
@@ -130,7 +92,7 @@ void status_versions( char *data, const ASP asp, const DSI *dsi)
 void status_uams(char *data, const char *authlist)
 {
     char                *start = data;
-    u_int16_t           status;
+    uint16_t           status;
     struct uam_obj      *uams;
     int         len, num = 0;
 
@@ -165,7 +127,7 @@ static int send_reply(const AFPObj *obj, const int err)
     if ((err == AFP_OK) || (err == AFPERR_AUTHCONT))
         return err;
 
-    obj->reply(obj->handle, err);
+    obj->reply(obj->dsi, err);
     obj->exit(0);
 
     return AFP_OK;
@@ -185,7 +147,7 @@ static int afp_null_nolog(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_,
     return( AFPERR_NOOP );
 }
 
-static int set_auth_switch(int expired)
+static int set_auth_switch(const AFPObj *obj, int expired)
 {
     int i;
 
@@ -206,7 +168,7 @@ static int set_auth_switch(int expired)
     }
     else {
         afp_switch = postauth_switch;
-        switch (afp_version) {
+        switch (obj->afp_version) {
 
         case 33:
         case 32:
@@ -223,7 +185,7 @@ static int set_auth_switch(int expired)
         case 31:
             uam_afpserver_action(AFP_SYNCDIR, UAM_AFPSERVER_POSTAUTH, afp_syncdir, NULL);
             uam_afpserver_action(AFP_SYNCFORK, UAM_AFPSERVER_POSTAUTH, afp_syncfork, NULL);
-            uam_afpserver_action(AFP_SPOTLIGHT_PRIVATE, UAM_AFPSERVER_POSTAUTH, afp_null_nolog, NULL);
+            uam_afpserver_action(AFP_SPOTLIGHT_PRIVATE, UAM_AFPSERVER_POSTAUTH, afp_spotlight_rpc, NULL);
             uam_afpserver_action(AFP_ENUMERATE_EXT2, UAM_AFPSERVER_POSTAUTH, afp_enumerate_ext2, NULL);
 
         case 30:
@@ -256,91 +218,29 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi
     int admin = 0;
 #endif /* ADMIN_GRP */
 
-#if 0
-    set_processname("afpd");
-#endif
-
     if ( pwd->pw_uid == 0 ) {   /* don't allow root login */
         LOG(log_error, logtype_afpd, "login: root login denied!" );
         return AFPERR_NOTAUTH;
     }
 
-    LOG(log_note, logtype_afpd, "%s Login by %s",
-        afp_versions[afp_version_index].av_name, pwd->pw_name);
-
-#ifndef NO_DDP
-    if (obj->proto == AFPPROTO_ASP) {
-        ASP asp = obj->handle;
-        int addr_net = ntohs( asp->asp_sat.sat_addr.s_net );
-        int addr_node  = asp->asp_sat.sat_addr.s_node;
-
-        if (obj->options.authprintdir) {
-            if(addr_net && addr_node) { /* Do we have a valid Appletalk address? */
-                char nodename[256];
-                FILE *fp;
-                int mypid = getpid();
-                struct stat stat_buf;
-
-                sprintf(nodename, "%s/net%d.%dnode%d", obj->options.authprintdir,
-                        addr_net / 256, addr_net % 256, addr_node);
-                LOG(log_info, logtype_afpd, "registering %s (uid %d) on %u.%u as %s",
-                    pwd->pw_name, pwd->pw_uid, addr_net, addr_node, nodename);
-
-                if (stat(nodename, &stat_buf) == 0) { /* file exists */
-                    if (S_ISREG(stat_buf.st_mode)) { /* normal file */
-                        unlink(nodename);
-                        fp = fopen(nodename, "w");
-                        fprintf(fp, "%s:%d\n", pwd->pw_name, mypid);
-                        fclose(fp);
-                        chown( nodename, pwd->pw_uid, -1 );
-                    } else { /* somebody is messing with us */
-                        LOG(log_error, logtype_afpd, "print authfile %s is not a normal file, it will not be modified", nodename );
-                    }
-                } else { /* file 'nodename' does not exist */
-                    fp = fopen(nodename, "w");
-                    fprintf(fp, "%s:%d\n", pwd->pw_name, mypid);
-                    fclose(fp);
-                    chown( nodename, pwd->pw_uid, -1 );
-                }
-            } /* if (addr_net && addr_node ) */
-        } /* if (options->authprintdir) */
-    } /* if (obj->proto == AFPPROTO_ASP) */
-#endif
-
-    if (initgroups( pwd->pw_name, pwd->pw_gid ) < 0) {
-#ifdef RUN_AS_USER
-        LOG(log_info, logtype_afpd, "running with uid %d", geteuid());
-#else /* RUN_AS_USER */
-        LOG(log_error, logtype_afpd, "login: %s", strerror(errno));
-        return AFPERR_BADUAM;
-#endif /* RUN_AS_USER */
-
-    }
-
-    /* Basically if the user is in the admin group, we stay root */
-
-    if (( ngroups = getgroups( 0, NULL )) < 0 ) {
-        LOG(log_error, logtype_afpd, "login: %s getgroups: %s", pwd->pw_name, strerror(errno) );
-        return AFPERR_BADUAM;
+    if (obj->cnx_cnt > obj->cnx_max) {
+        LOG(log_error, logtype_dsi, "login: too many connections, limit: %d", obj->cnx_max);
+        return AFPERR_MAXSESS;
     }
 
-    if ( NULL == (groups = calloc(ngroups, GROUPS_SIZE)) ) {
-        LOG(log_error, logtype_afpd, "login: %s calloc: %d", ngroups);
-        return AFPERR_BADUAM;
-    }
+    LOG(log_note, logtype_afpd, "%s Login by %s",
+        afp_versions[afp_version_index].av_name, pwd->pw_name);
 
-    if (( ngroups = getgroups( ngroups, groups )) < 0 ) {
-        LOG(log_error, logtype_afpd, "login: %s getgroups: %s", pwd->pw_name, strerror(errno) );
+    if (set_groups(obj, pwd) != 0)
         return AFPERR_BADUAM;
-    }
 
 #ifdef ADMIN_GRP
     LOG(log_debug, logtype_afpd, "obj->options.admingid == %d", obj->options.admingid);
 
     if (obj->options.admingid != 0) {
         int i;
-        for (i = 0; i < ngroups; i++) {
-            if (groups[i] == obj->options.admingid) admin = 1;
+        for (i = 0; i < obj->ngroups; i++) {
+            if (obj->groups[i] == obj->options.admingid) admin = 1;
         }
     }
     if (admin) {
@@ -391,46 +291,26 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi
     }
 #endif /* TRU64 */
 
-    if (ngroups > 0) {
-        #define GROUPSTR_BUFSIZE 1024
-        char groupsstr[GROUPSTR_BUFSIZE];
-        char *s = groupsstr;
-        int j = GROUPSTR_BUFSIZE;
-
-        int n = snprintf(groupsstr, GROUPSTR_BUFSIZE, "%u", groups[0]);
-        j -= n;
-        s += n;
-
-        for (int i = 1; i < ngroups; i++) {
-            n = snprintf(s, j, ", %u", groups[i]);
-            if (n == j) {
-                /* Buffer full */
-                LOG(log_debug, logtype_afpd, "login: group string buffer overflow");
-                break;
-            }
-            j -= n;
-            s += n;
-        }
-        LOG(log_debug, logtype_afpd, "login: %u supplementary groups: %s", ngroups, groupsstr);
-    }
+    LOG(log_debug, logtype_afpd, "login: supplementary groups: %s", print_groups(obj->ngroups, obj->groups));
 
     /* There's probably a better way to do this, but for now, we just play root */
 #ifdef ADMIN_GRP
     if (admin)
-        uuid = 0;
+        obj->uid = 0;
     else
 #endif /* ADMIN_GRP */
-        uuid = pwd->pw_uid;
+        obj->uid = geteuid();
 
-    set_auth_switch(expired);
+    set_auth_switch(obj, expired);
     /* save our euid, we need it for preexec_close */
     obj->uid = geteuid();
     obj->logout = logout;
 
-#ifdef FORCE_UIDGID
-    obj->force_uid = 1;
-    save_uidgid ( &obj->uidgid );
-#endif
+    /* pam_umask or similar might have changed our umask */
+    (void)umask(obj->options.umask);
+
+    /* Some PAM module might have reset our signal handlers and timer, so we need to reestablish them */
+    afp_over_dsi_sighandlers(obj);
 
     return( AFP_OK );
 }
@@ -439,7 +319,7 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi
 int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
 {
     uint32_t data;
-    DSI *dsi = (DSI *)AFPobj->handle;
+    DSI *dsi = (DSI *)AFPobj->dsi;
 
     *rbuflen = 0;
     ibuf += 2;
@@ -461,6 +341,7 @@ int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen
         if (dsi->flags & DSI_EXTSLEEP) {
             LOG(log_note, logtype_afpd, "afp_zzz: waking up from extended sleep");
             dsi->flags &= ~(DSI_SLEEPING | DSI_EXTSLEEP);
+            ipc_child_state(obj, DSI_RUNNING);
         }
     } else {
         /* sleep request */
@@ -468,8 +349,10 @@ int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen
         if (data & AFPZZZ_EXT_SLEEP) {
             LOG(log_note, logtype_afpd, "afp_zzz: entering extended sleep");
             dsi->flags |= DSI_EXTSLEEP;
+            ipc_child_state(obj, DSI_EXTSLEEP);
         } else {
             LOG(log_note, logtype_afpd, "afp_zzz: entering normal sleep");
+            ipc_child_state(obj, DSI_SLEEPING);
         }
     }
 
@@ -531,10 +414,10 @@ int afp_getsession(
     char   *ibuf, size_t ibuflen, 
     char   *rbuf, size_t *rbuflen)
 {
-    u_int16_t           type;
-    u_int32_t           idlen = 0;
-    u_int32_t       boottime;
-    u_int32_t           tklen, tp;
+    uint16_t           type;
+    uint32_t           idlen = 0;
+    uint32_t       boottime;
+    uint32_t           tklen, tp;
     char                *token;
     char                *p;
 
@@ -632,9 +515,9 @@ int afp_getsession(
 /* ---------------------- */
 int afp_disconnect(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
 {
-    DSI                 *dsi = (DSI *)obj->handle;
-    u_int16_t           type;
-    u_int32_t           tklen;
+    DSI                 *dsi = (DSI *)obj->dsi;
+    uint16_t           type;
+    uint32_t           tklen;
     pid_t               token;
     int                 i;
 
@@ -722,7 +605,7 @@ static int get_version(AFPObj *obj, char *ibuf, size_t ibuflen, size_t len)
     num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ]);
     for ( i = 0; i < num; i++ ) {
         if ( strncmp( ibuf, afp_versions[ i ].av_name , len ) == 0 ) {
-            afp_version = afp_versions[ i ].av_number;
+            obj->afp_version = afp_versions[ i ].av_number;
             afp_version_index = i;
             break;
         }
@@ -730,11 +613,8 @@ static int get_version(AFPObj *obj, char *ibuf, size_t ibuflen, size_t len)
     if ( i == num )                 /* An inappropo version */
         return AFPERR_BADVERS ;
 
-    if (afp_version >= 30 && obj->proto != AFPPROTO_DSI)
-        return AFPERR_BADVERS ;
-
     /* FIXME Hack */
-    if (afp_version >= 30 && sizeof(off_t) != 8) {
+    if (obj->afp_version >= 30 && sizeof(off_t) != 8) {
         LOG(log_error, logtype_afpd, "get_version: no LARGE_FILE support recompile!" );
         return AFPERR_BADVERS ;
     }
@@ -800,7 +680,7 @@ int afp_login_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *r
     size_t  len;
     int     i;
     char        type;
-    u_int16_t   len16;
+    uint16_t   len16;
     char        *username;
 
     *rbuflen = 0;
@@ -943,11 +823,11 @@ int afp_logincont(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *r
 
 int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen  _U_, char *rbuf  _U_, size_t *rbuflen)
 {
-    DSI *dsi = (DSI *)(obj->handle);
+    DSI *dsi = (DSI *)(obj->dsi);
 
     LOG(log_note, logtype_afpd, "AFP logout by %s", obj->username);
-    of_close_all_forks();
-    close_all_vol();
+    of_close_all_forks(obj);
+    close_all_vol(obj);
     dsi->flags = DSI_AFP_LOGGED_OUT;
     *rbuflen = 0;
     return AFP_OK;
@@ -986,7 +866,7 @@ int afp_changepw(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rb
     if ((len + 1) & 1) /* pad byte */
         ibuf++;
 
-    if ( afp_version < 30) {
+    if (obj->afp_version < 30) {
         len = (unsigned char) *ibuf++;
         if ( len > sizeof(username) - 1) {
             return AFPERR_PARAM;
@@ -1001,7 +881,7 @@ int afp_changepw(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rb
         if ( ibuf[0] != '\0' || ibuf[1] != '\0')
             return AFPERR_PARAM;
         ibuf += 2;
-        len = MIN(sizeof(username), strlen(obj->username));
+        len = MIN(sizeof(username) - 1, strlen(obj->username));
         memcpy(username, obj->username, len);
         username[ len ] = '\0';
     }
@@ -1023,7 +903,7 @@ int afp_changepw(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rb
         (ret == AFPERR_AUTHCONT) ? "continued" :
         (ret ? "failed" : "succeeded"));
     if ( ret == AFP_OK )
-        set_auth_switch(0);
+        set_auth_switch(obj, 0);
 
     return ret;
 }
@@ -1032,9 +912,9 @@ int afp_changepw(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rb
 /* FPGetUserInfo */
 int afp_getuserinfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
 {
-    u_int8_t  thisuser;
-    u_int32_t id;
-    u_int16_t bitmap;
+    uint8_t  thisuser;
+    uint32_t id;
+    uint16_t bitmap;
     char *bitmapp;
 
     LOG(log_debug, logtype_afpd, "begin afp_getuserinfo:");
@@ -1138,7 +1018,7 @@ int auth_register(const int type, struct uam_obj *uam)
 }
 
 /* load all of the modules */
-int auth_load(const char *path, const char *list)
+int auth_load(AFPObj *obj, const char *path, const char *list)
 {
     char name[MAXPATHLEN + 1], buf[MAXPATHLEN + 1], *p;
     struct uam_mod *mod;
@@ -1149,7 +1029,7 @@ int auth_load(const char *path, const char *list)
         return -1;
 
     strlcpy(buf, list, sizeof(buf));
-    if ((p = strtok(buf, ",")) == NULL)
+    if ((p = strtok(buf, ", ")) == NULL)
         return -1;
 
     strcpy(name, path);
@@ -1165,7 +1045,7 @@ int auth_load(const char *path, const char *list)
           if ((stat(name, &st) == 0) && (mod = uam_load(name, p))) {
         */
         if (stat(name, &st) == 0) {
-            if ((mod = uam_load(name, p))) {
+            if ((mod = uam_load(obj, name, p))) {
                 uam_attach(&uam_modules, mod);
                 LOG(log_debug, logtype_afpd, "uam: %s loaded", p);
             } else {
@@ -1174,7 +1054,7 @@ int auth_load(const char *path, const char *list)
         } else {
             LOG(log_info, logtype_afpd, "uam: uam not found (status=%d)", stat(name, &st));
         }
-        p = strtok(NULL, ",");
+        p = strtok(NULL, ", ");
     }
 
     return 0;