X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fauth.c;h=3e0fd5ebeecae396babc23d48c6d7ee859e99a1e;hb=d28f176330075b2789ce4d50a64fc3fe5d6bbe9b;hp=9923ac4ee0a2c0ec204f32c946d43864be48def2;hpb=16d2aa6c8fb26418a16ae52a1cc969b15cbc8403;p=netatalk.git diff --git a/etc/afpd/auth.c b/etc/afpd/auth.c index 9923ac4e..3e0fd5eb 100644 --- a/etc/afpd/auth.c +++ b/etc/afpd/auth.c @@ -1,6 +1,4 @@ /* - * $Id: auth.c,v 1.64 2009-09-28 09:21:09 franklahm Exp $ - * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. */ @@ -28,9 +26,6 @@ #include #include #include -#include -#include -#include #ifdef TRU64 #include @@ -41,17 +36,19 @@ extern void afp_get_cmdline( int *ac, char ***av ); #endif /* TRU64 */ +#include +#include +#include + #include "globals.h" #include "auth.h" #include "uam_auth.h" #include "switch.h" #include "status.h" #include "fork.h" -#ifdef HAVE_NFSv4_ACLS -#include "acls.h" -#endif -#ifdef HAVE_EXT_ATTRS #include "extattrs.h" +#ifdef HAVE_ACLS +#include "acls.h" #endif int afp_version = 11; @@ -76,15 +73,17 @@ 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 }, #ifdef AFP3x { "AFPX03", 30 }, { "AFP3.1", 31 }, { "AFP3.2", 32 } -#endif +#endif /* AFP3x */ }; static struct uam_mod uam_modules = {NULL, NULL, &uam_modules, &uam_modules}; @@ -96,18 +95,30 @@ static struct uam_obj uam_changepw = {"", "", 0, {{NULL, NULL, NULL, NULL}}, &ua static struct uam_obj *afp_uam = NULL; -void status_versions( data ) - char *data; +void status_versions( char *data, const ASP asp, const DSI *dsi) { char *start = data; u_int16_t status; - int len, num, i; + 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++; + } data += ntohs( status ); - *data++ = num; + *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; memcpy( data, afp_versions[ i ].av_name , len ); @@ -161,19 +172,15 @@ static int send_reply(const AFPObj *obj, const int err) return AFP_OK; } -static int afp_errpwdexpired(obj, ibuf, ibuflen, rbuf, rbuflen ) - AFPObj *obj _U_; - char *ibuf _U_, *rbuf _U_; - int ibuflen _U_, *rbuflen; +static int afp_errpwdexpired(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, + char *rbuf _U_, size_t *rbuflen) { *rbuflen = 0; return AFPERR_PWDEXPR; } -static int afp_null_nolog(obj, ibuf, ibuflen, rbuf, rbuflen ) - AFPObj *obj _U_; - char *ibuf _U_, *rbuf _U_; - int ibuflen _U_, *rbuflen; +static int afp_null_nolog(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, + char *rbuf _U_, size_t *rbuflen) { *rbuflen = 0; return( AFPERR_NOOP ); @@ -202,21 +209,19 @@ static int set_auth_switch(int expired) afp_switch = postauth_switch; switch (afp_version) { case 32: - uam_afpserver_action(AFP_SPOTLIGHT_PRIVATE, UAM_AFPSERVER_POSTAUTH, afp_null_nolog, NULL); - uam_afpserver_action(AFP_SYNCDIR, UAM_AFPSERVER_POSTAUTH, afp_syncdir, NULL); - uam_afpserver_action(AFP_SYNCFORK, UAM_AFPSERVER_POSTAUTH, afp_syncfork, NULL); -#ifdef HAVE_NFSv4_ACLS +#ifdef HAVE_ACLS uam_afpserver_action(AFP_GETACL, UAM_AFPSERVER_POSTAUTH, afp_getacl, NULL); uam_afpserver_action(AFP_SETACL, UAM_AFPSERVER_POSTAUTH, afp_setacl, NULL); uam_afpserver_action(AFP_ACCESS, UAM_AFPSERVER_POSTAUTH, afp_access, NULL); -#endif -#ifdef HAVE_EXT_ATTRS +#endif /* HAVE_ACLS */ uam_afpserver_action(AFP_GETEXTATTR, UAM_AFPSERVER_POSTAUTH, afp_getextattr, NULL); uam_afpserver_action(AFP_SETEXTATTR, UAM_AFPSERVER_POSTAUTH, afp_setextattr, NULL); uam_afpserver_action(AFP_REMOVEATTR, UAM_AFPSERVER_POSTAUTH, afp_remextattr, NULL); uam_afpserver_action(AFP_LISTEXTATTR, UAM_AFPSERVER_POSTAUTH, afp_listextattr, NULL); -#endif 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_ENUMERATE_EXT2, UAM_AFPSERVER_POSTAUTH, afp_enumerate_ext2, NULL); case 30: uam_afpserver_action(AFP_ENUMERATE_EXT, UAM_AFPSERVER_POSTAUTH, afp_enumerate_ext, NULL); @@ -257,8 +262,8 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi return AFPERR_NOTAUTH; } - LOG(log_info, logtype_afpd, "login %s (uid %d, gid %d) %s", pwd->pw_name, - pwd->pw_uid, pwd->pw_gid , afp_versions[afp_version_index].av_name); + 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) { @@ -327,9 +332,8 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi } #ifdef ADMIN_GRP -#ifdef DEBUG - LOG(log_info, logtype_afpd, "obj->options.admingid == %d", obj->options.admingid); -#endif /* DEBUG */ + 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++) { @@ -341,7 +345,7 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi LOG(log_info, logtype_afpd, "admin login -- %s", pwd->pw_name ); } if (!admin) -#endif /* DEBUG */ +#endif /* ADMIN_GRP */ #ifdef TRU64 { struct DSI *dsi = obj->handle; @@ -384,17 +388,40 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi } #endif /* TRU64 */ - /* There's probably a better way to do this, but for now, we just - play root */ + 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); + } + /* There's probably a better way to do this, but for now, we just play root */ #ifdef ADMIN_GRP - if (admin) uuid = 0; + if (admin) + uuid = 0; else #endif /* ADMIN_GRP */ uuid = pwd->pw_uid; set_auth_switch(expired); - + /* save our euid, we need it for preexec_close */ + obj->uid = geteuid(); obj->logout = logout; #ifdef FORCE_UIDGID @@ -406,10 +433,10 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi } /* ---------------------- */ -int afp_zzz (obj, ibuf, ibuflen, rbuf, rbuflen ) /* Function 122 */ - AFPObj *obj; - char *ibuf _U_, *rbuf; - unsigned int ibuflen _U_, *rbuflen; +int afp_zzz ( /* Function 122 */ + AFPObj *obj, + char *ibuf _U_, size_t ibuflen _U_, + char *rbuf, size_t *rbuflen) { u_int32_t retdata; @@ -464,10 +491,10 @@ static int create_session_key(AFPObj *obj) /* ---------------------- */ -int afp_getsession(obj, ibuf, ibuflen, rbuf, rbuflen ) - AFPObj *obj; - char *ibuf, *rbuf; - unsigned int ibuflen, *rbuflen; +int afp_getsession( + AFPObj *obj, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) { u_int16_t type; u_int32_t idlen = 0; @@ -479,6 +506,10 @@ int afp_getsession(obj, ibuf, ibuflen, rbuf, rbuflen ) *rbuflen = 0; tklen = 0; + if (ibuflen < 2 + sizeof(type)) { + return AFPERR_PARAM; + } + ibuf += 2; ibuflen -= 2; @@ -515,7 +546,7 @@ int afp_getsession(obj, ibuf, ibuflen, rbuf, rbuflen ) token = obj->sinfo.sessiontoken; } break; - case 3: /* Jaguar */ + case 3: case 4: if (ibuflen >= 8 ) { p = ibuf; @@ -528,7 +559,7 @@ int afp_getsession(obj, ibuf, ibuflen, rbuf, rbuflen ) if (ibuflen < idlen || idlen > (90-10)) { return AFPERR_PARAM; } - server_ipc_write(IPC_GETSESSION, idlen+8, p ); + ipc_child_write(obj->ipc_fd, IPC_GETSESSION, idlen+8, p); tklen = obj->sinfo.sessiontoken_len; token = obj->sinfo.sessiontoken; } @@ -558,13 +589,10 @@ int afp_getsession(obj, ibuf, ibuflen, rbuf, rbuflen ) } /* ---------------------- */ -int afp_disconnect(obj, ibuf, ibuflen, rbuf, rbuflen ) - AFPObj *obj _U_; - char *ibuf, *rbuf _U_; - int ibuflen _U_, *rbuflen; +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; pid_t token; int i; @@ -605,19 +633,30 @@ int afp_disconnect(obj, ibuf, ibuflen, rbuf, rbuflen ) } } - /* killed old session, not easy */ - server_ipc_write(IPC_KILLTOKEN, tklen, &token); - sleep(1); + LOG(log_note, logtype_afpd, "afp_disconnect: trying primary reconnect"); - return AFPERR_SESSCLOS; /* was AFP_OK */ + /* check for old session, possibly transfering session from here to there */ + if (ipc_child_write(obj->ipc_fd, IPC_DISCOLDSESSION, tklen, &token) == -1) + goto exit; + /* write uint16_t DSI request ID */ + if (writet(obj->ipc_fd, &dsi->header.dsi_requestID, 2, 0, 2) != 2) { + LOG(log_error, logtype_afpd, "afp_disconnect: couldn't send DSI request ID"); + goto exit; + } + /* 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 */ + /* has been transfered to a old disconnected session, or we continue */ + sleep(2); + +exit: + LOG(log_error, logtype_afpd, "afp_disconnect: primary reconnect failed"); + return AFPERR_MISC; } /* ---------------------- */ -static int get_version(obj, ibuf, ibuflen, len) - AFPObj *obj; - char *ibuf; - int ibuflen; - int len; +static int get_version(AFPObj *obj, char *ibuf, size_t ibuflen, size_t len) { int num,i; @@ -648,20 +687,18 @@ static int get_version(obj, ibuf, ibuflen, len) } /* ---------------------- */ -int afp_login(obj, ibuf, ibuflen, rbuf, rbuflen ) - AFPObj *obj; - char *ibuf, *rbuf; - int ibuflen, *rbuflen; +int afp_login(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) { struct passwd *pwd = NULL; - int len, i; + size_t len; + int i; *rbuflen = 0; if ( nologin & 1) return send_reply(obj, AFPERR_SHUTDOWN ); - if (ibuflen <= 1) + if (ibuflen < 2) return send_reply(obj, AFPERR_BADVERS ); ibuf++; @@ -672,12 +709,12 @@ int afp_login(obj, ibuf, ibuflen, rbuf, rbuflen ) if (i) return send_reply(obj, i ); + if (ibuflen <= len) + return send_reply(obj, AFPERR_BADUAM); + ibuf += len; ibuflen -= len; - if (ibuflen <= 1) - return send_reply(obj, AFPERR_BADUAM); - len = (unsigned char) *ibuf++; ibuflen--; @@ -701,13 +738,10 @@ int afp_login(obj, ibuf, ibuflen, rbuf, rbuflen ) } /* ---------------------- */ -int afp_login_ext(obj, ibuf, ibuflen, rbuf, rbuflen ) - AFPObj *obj; - char *ibuf, *rbuf; - unsigned int ibuflen, *rbuflen; +int afp_login_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) { struct passwd *pwd = NULL; - unsigned int len; + size_t len; int i; char type; u_int16_t len16; @@ -718,7 +752,7 @@ int afp_login_ext(obj, ibuf, ibuflen, rbuf, rbuflen ) if ( nologin & 1) return send_reply(obj, AFPERR_SHUTDOWN ); - if (ibuflen <= 4) + if (ibuflen < 5) return send_reply(obj, AFPERR_BADVERS ); ibuf++; @@ -733,12 +767,12 @@ int afp_login_ext(obj, ibuf, ibuflen, rbuf, rbuflen ) if (i) return send_reply(obj, i ); + if (ibuflen <= len) + return send_reply(obj, AFPERR_BADUAM); + ibuf += len; ibuflen -= len; - if (ibuflen <= 1) - return send_reply(obj, AFPERR_BADUAM); - len = (unsigned char) *ibuf; ibuf++; ibuflen--; @@ -756,7 +790,7 @@ int afp_login_ext(obj, ibuf, ibuflen, rbuf, rbuflen ) return send_reply(obj, AFPERR_BADUAM); } /* user name */ - if (len <= 1 +sizeof(len16)) + if (ibuflen <= 1 +sizeof(len16)) return send_reply(obj, AFPERR_PARAM); type = *ibuf; username = ibuf; @@ -831,15 +865,12 @@ int afp_login_ext(obj, ibuf, ibuflen, rbuf, rbuflen ) } /* ---------------------- */ -int afp_logincont(obj, ibuf, ibuflen, rbuf, rbuflen) - AFPObj *obj; - char *ibuf, *rbuf; - int ibuflen, *rbuflen; +int afp_logincont(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) { struct passwd *pwd = NULL; int err; - if ( afp_uam == NULL || afp_uam->u.uam_login.logincont == NULL ) { + if ( afp_uam == NULL || afp_uam->u.uam_login.logincont == NULL || ibuflen < 2 ) { *rbuflen = 0; return send_reply(obj, AFPERR_NOTAUTH ); } @@ -854,12 +885,9 @@ int afp_logincont(obj, ibuf, ibuflen, rbuf, rbuflen) } -int afp_logout(obj, ibuf, ibuflen, rbuf, rbuflen) - AFPObj *obj; - char *ibuf _U_, *rbuf _U_; - int ibuflen _U_, *rbuflen _U_; +int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen _U_) { - LOG(log_info, logtype_afpd, "logout %s", obj->username); + LOG(log_note, logtype_afpd, "AFP logout by %s", obj->username); close_all_vol(); obj->exit(0); return AFP_OK; @@ -872,10 +900,7 @@ int afp_logout(obj, ibuf, ibuflen, rbuf, rbuflen) * to work. this also does a little pre-processing before it hands * it off to the uam. */ -int afp_changepw(obj, ibuf, ibuflen, rbuf, rbuflen ) - AFPObj *obj; - char *ibuf, *rbuf; - int ibuflen, *rbuflen; +int afp_changepw(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) { char username[MACFILELEN + 1], *start = ibuf; struct uam_obj *uam; @@ -928,6 +953,9 @@ int afp_changepw(obj, ibuf, ibuflen, rbuf, rbuflen ) return AFPERR_PARAM; /* send it off to the uam. we really don't use ibuflen right now. */ + if (ibuflen < (size_t)(ibuf - start)) + return AFPERR_PARAM; + ibuflen -= (ibuf - start); ret = uam->u.uam_changepw(obj, username, pwd, ibuf, ibuflen, rbuf, rbuflen); @@ -942,14 +970,12 @@ int afp_changepw(obj, ibuf, ibuflen, rbuf, rbuflen ) /* FPGetUserInfo */ -int afp_getuserinfo(obj, ibuf, ibuflen, rbuf, rbuflen ) - AFPObj *obj _U_; - char *ibuf, *rbuf; - int ibuflen _U_, *rbuflen; +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; + char *bitmapp; LOG(log_debug, logtype_afpd, "begin afp_getuserinfo:"); @@ -968,8 +994,9 @@ int afp_getuserinfo(obj, ibuf, ibuflen, rbuf, rbuflen ) if ((bitmap & USERIBIT_ALL) != bitmap) return AFPERR_BITMAP; - /* copy the bitmap back to reply buffer */ + /* remember place where we store the possibly modified bitmap later */ memcpy(rbuf, ibuf, sizeof(bitmap)); + bitmapp = rbuf; rbuf += sizeof(bitmap); *rbuflen = sizeof(bitmap); @@ -988,29 +1015,27 @@ int afp_getuserinfo(obj, ibuf, ibuflen, rbuf, rbuflen ) *rbuflen += sizeof(id); } -#ifdef HAVE_NFSv4_ACLS if (bitmap & USERIBIT_UUID) { - int ret; - uuid_t uuid; - char *uuidstring; - - if ( ! (obj->options.flags & OPTION_UUID)) - return AFPERR_BITMAP; - LOG(log_debug, logtype_afpd, "afp_getuserinfo: get UUID for \'%s\'", obj->username); - ret = getuuidfromname( obj->username, UUID_USER, uuid); - if (ret != 0) { - LOG(log_info, logtype_afpd, "afp_getuserinfo: error getting UUID !"); - return AFPERR_NOITEM; - } - if (0 == (uuid_bin2string( uuid, &uuidstring))) { - LOG(log_debug, logtype_afpd, "afp_getuserinfo: got UUID: %s", uuidstring); - free(uuidstring); + if ( ! (obj->options.flags & OPTION_UUID)) { + bitmap &= ~USERIBIT_UUID; + bitmap = htons(bitmap); + memcpy(bitmapp, &bitmap, sizeof(bitmap)); + } else { + LOG(log_debug, logtype_afpd, "afp_getuserinfo: get UUID for \'%s\'", obj->username); + int ret; + atalk_uuid_t uuid; + ret = getuuidfromname( obj->username, UUID_USER, uuid); + if (ret != 0) { + 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)); + + memcpy(rbuf, uuid, UUID_BINSIZE); + rbuf += UUID_BINSIZE; + *rbuflen += UUID_BINSIZE; } - memcpy(rbuf, uuid, UUID_BINSIZE); - rbuf += UUID_BINSIZE; - *rbuflen += UUID_BINSIZE; } -#endif LOG(log_debug, logtype_afpd, "END afp_getuserinfo:"); return AFP_OK; @@ -1082,9 +1107,9 @@ int auth_load(const char *path, const char *list) if (stat(name, &st) == 0) { if ((mod = uam_load(name, p))) { uam_attach(&uam_modules, mod); - LOG(log_info, logtype_afpd, "uam: %s loaded", p); + LOG(log_debug, logtype_afpd, "uam: %s loaded", p); } else { - LOG(log_info, logtype_afpd, "uam: %s load failure",p); + LOG(log_error, logtype_afpd, "uam: %s load failure",p); } } else { LOG(log_info, logtype_afpd, "uam: uam not found (status=%d)", stat(name, &st)); @@ -1096,7 +1121,7 @@ int auth_load(const char *path, const char *list) } /* get rid of all of the uams */ -void auth_unload() +void auth_unload(void) { struct uam_mod *mod, *prev, *start = &uam_modules;