X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Fauth.c;h=80cd5339f51494b5dd13d0fd240123c53ddf6b49;hp=e9d658442c16c16b2506451ef501421dfcdb062f;hb=939eb9da6116bd502cdae97f84541993848071b4;hpb=d58499071b03dfcb10c81a0996d34e5611c37b6f diff --git a/etc/afpd/auth.c b/etc/afpd/auth.c index e9d65844..80cd5339 100644 --- a/etc/afpd/auth.c +++ b/etc/afpd/auth.c @@ -10,13 +10,12 @@ #include #include #include -#ifdef HAVE_UNISTD_H #include -#endif /* HAVE_UNISTD_H */ #include #include #include -#include +#include + #include #include #include @@ -39,8 +38,9 @@ extern void afp_get_cmdline( int *ac, char ***av ); #include #include #include +#include +#include -#include "globals.h" #include "auth.h" #include "uam_auth.h" #include "switch.h" @@ -51,40 +51,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 +61,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 +78,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 +91,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 +126,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 +146,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 +167,7 @@ static int set_auth_switch(int expired) } else { afp_switch = postauth_switch; - switch (afp_version) { + switch (obj->afp_version) { case 33: case 32: @@ -256,10 +217,6 @@ 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; @@ -268,79 +225,16 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi 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) ); + if (set_groups(obj, pwd) != 0) return AFPERR_BADUAM; - } - - if ( NULL == (groups = calloc(ngroups, GROUPS_SIZE)) ) { - LOG(log_error, logtype_afpd, "login: %s calloc: %d", ngroups); - return AFPERR_BADUAM; - } - - if (( ngroups = getgroups( ngroups, groups )) < 0 ) { - LOG(log_error, logtype_afpd, "login: %s getgroups: %s", pwd->pw_name, strerror(errno) ); - 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,70 +285,85 @@ 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 ); } /* ---------------------- */ -int afp_zzz ( /* Function 122 */ - AFPObj *obj, - char *ibuf _U_, size_t ibuflen _U_, - char *rbuf, size_t *rbuflen) +int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) { - u_int32_t retdata; + uint32_t data; + DSI *dsi = (DSI *)AFPobj->dsi; *rbuflen = 0; + ibuf += 2; + ibuflen -= 2; + + if (ibuflen < 4) + return AFPERR_MISC; + memcpy(&data, ibuf, 4); /* flag */ + data = ntohl(data); + + /* + * Possible sleeping states: + * 1) normal sleep: DSI_SLEEPING (up to 10.3) + * 2) extended sleep: DSI_SLEEPING | DSI_EXTSLEEP (starting with 10.4) + */ + + if (data & AFPZZZ_EXT_WAKEUP) { + /* wakeup request from exetended sleep */ + 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 */ + dsi->flags |= DSI_SLEEPING; + 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); + } + } - retdata = obj->options.sleep /120; - if (!retdata) { - retdata = 1; + /* + * According to AFP 3.3 spec we should not return anything, + * but eg 10.5.8 server still returns the numbers of hours + * the server is keeping the sessino (ie max sleeptime). + */ + data = obj->options.sleep / 120; /* hours */ + if (!data) { + data = 1; } - *rbuflen = sizeof(retdata); - retdata = htonl(retdata); - memcpy(rbuf, &retdata, sizeof(retdata)); - if (obj->sleep) - obj->sleep(); - rbuf += sizeof(retdata); + *rbuflen = sizeof(data); + data = htonl(data); + memcpy(rbuf, &data, sizeof(data)); + rbuf += sizeof(data); + return AFP_OK; } @@ -499,10 +408,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; @@ -562,7 +471,13 @@ int afp_getsession( if (ibuflen < idlen || idlen > (90-10)) { return AFPERR_PARAM; } - ipc_child_write(obj->ipc_fd, IPC_GETSESSION, idlen+8, p); + if (!obj->sinfo.clientid) { + obj->sinfo.clientid = malloc(idlen + 8); + memcpy(obj->sinfo.clientid, p, idlen + 8); + obj->sinfo.clientid_len = idlen + 8; + } + if (ipc_child_write(obj->ipc_fd, IPC_GETSESSION, idlen+8, p) != 0) + return AFPERR_MISC; tklen = obj->sinfo.sessiontoken_len; token = obj->sinfo.sessiontoken; } @@ -594,9 +509,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; @@ -637,9 +552,14 @@ int afp_disconnect(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, } LOG(log_note, logtype_afpd, "afp_disconnect: trying primary reconnect"); + dsi->flags |= DSI_RECONINPROG; + + /* Deactivate tickle timer */ + const struct itimerval none = {{0, 0}, {0, 0}}; + setitimer(ITIMER_REAL, &none, NULL); /* check for old session, possibly transfering session from here to there */ - if (ipc_child_write(obj->ipc_fd, IPC_DISCOLDSESSION, tklen, &token) == -1) + if (ipc_child_write(obj->ipc_fd, IPC_DISCOLDSESSION, tklen, &token) != 0) goto exit; /* write uint16_t DSI request ID */ if (writet(obj->ipc_fd, &dsi->header.dsi_requestID, 2, 0, 2) != 2) { @@ -649,11 +569,21 @@ int afp_disconnect(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, /* now send our connected AFP client socket */ if (send_fd(obj->ipc_fd, dsi->socket) != 0) goto exit; - /* Now see what happens: either afpd master kills us because our session */ + /* Now see what happens: either afpd master sends us SIGTERM because our session */ /* has been transfered to a old disconnected session, or we continue */ - sleep(2); + sleep(5); + + if (!(dsi->flags & DSI_RECONINPROG)) { /* deleted in SIGTERM handler */ + /* Reconnect succeeded, we exit now after sleeping some more */ + sleep(2); /* sleep some more to give the recon. session time */ + LOG(log_note, logtype_afpd, "afp_disconnect: primary reconnect succeeded"); + exit(0); + } exit: + /* Reinstall tickle timer */ + setitimer(ITIMER_REAL, &dsi->timer, NULL); + LOG(log_error, logtype_afpd, "afp_disconnect: primary reconnect failed"); return AFPERR_MISC; } @@ -669,7 +599,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; } @@ -677,11 +607,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 ; } @@ -747,7 +674,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; @@ -888,11 +815,15 @@ 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 _U_) +int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { + DSI *dsi = (DSI *)(obj->dsi); + LOG(log_note, logtype_afpd, "AFP logout by %s", obj->username); - close_all_vol(); - obj->exit(0); + of_close_all_forks(obj); + close_all_vol(obj); + dsi->flags = DSI_AFP_LOGGED_OUT; + *rbuflen = 0; return AFP_OK; } @@ -929,7 +860,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; @@ -944,7 +875,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'; } @@ -966,7 +897,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; } @@ -975,9 +906,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:"); @@ -1029,7 +960,7 @@ int afp_getuserinfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, atalk_uuid_t uuid; ret = getuuidfromname( obj->username, UUID_USER, uuid); if (ret != 0) { - LOG(log_info, logtype_afpd, "afp_getuserinfo: error getting UUID !"); + LOG(log_info, logtype_afpd, "afp_getuserinfo: error getting UUID!"); return AFPERR_NOITEM; } LOG(log_debug, logtype_afpd, "afp_getuserinfo: got UUID: %s", uuid_bin2string(uuid)); @@ -1092,7 +1023,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); @@ -1117,7 +1048,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;