X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fauth.c;h=3b5177d45a0cc518413f016b7b57f4a15d79a5e0;hb=a7349ad51dd4d6e119ab7414fd19d6a8467f3f35;hp=01ce135b0475bfa9e54e00c4b3b548b4d32ac990;hpb=458fcac4e6aee7eb54ba744f57169f70cce12505;p=netatalk.git diff --git a/etc/afpd/auth.c b/etc/afpd/auth.c index 01ce135b..3b5177d4 100644 --- a/etc/afpd/auth.c +++ b/etc/afpd/auth.c @@ -1,15 +1,20 @@ /* + * $Id: auth.c,v 1.20 2001-12-03 05:03:38 jmarcus Exp $ + * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. */ #ifdef HAVE_CONFIG_H #include "config.h" -#endif +#endif /* HAVE_CONFIG_H */ #include #include +#include +#ifdef HAVE_UNISTD_H #include +#endif /* HAVE_UNISTD_H */ #include #include #include @@ -23,12 +28,21 @@ #ifdef SHADOWPW #include -#endif +#endif /* SHADOWPW */ #include #include #include +#ifdef TRU64 +#include +#include +#include +#include + +extern void afp_get_cmdline( int *ac, char ***av ); +#endif /* TRU64 */ + #include "globals.h" #include "auth.h" #include "uam_auth.h" @@ -39,44 +53,38 @@ int afp_version = 11; uid_t uuid; #if defined( __svr4__ ) && !defined( NGROUPS ) #define NGROUPS NGROUPS_MAX -#endif __svr4__ NGROUPS +#endif /* __svr4__ NGROUPS */ #if defined( sun ) && !defined( __svr4__ ) || defined( ultrix ) int groups[ NGROUPS ]; -#else sun __svr4__ ultrix +#else /* sun __svr4__ ultrix */ #if defined( __svr4__ ) && !defined( NGROUPS ) #define NGROUPS NGROUPS_MAX -#endif __svr4__ NGROUPS +#endif /* __svr4__ NGROUPS */ gid_t groups[ NGROUPS ]; -#endif sun ultrix +#endif /* sun ultrix */ int ngroups; /* * These numbers are scattered throughout the code. */ static struct afp_versions afp_versions[] = { - { "AFPVersion 1.1", 11 }, - { "AFPVersion 2.0", 20 }, - { "AFPVersion 2.1", 21 }, - { "AFP2.2", 22 } -}; + { "AFPVersion 1.1", 11 }, + { "AFPVersion 2.0", 20 }, + { "AFPVersion 2.1", 21 }, + { "AFP2.2", 22 } + }; static struct uam_mod uam_modules = {NULL, NULL, &uam_modules, &uam_modules}; static struct uam_obj uam_login = {"", "", 0, {{NULL}}, &uam_login, - &uam_login}; -static struct uam_obj uam_changepw = {"", "", 0, {{NULL}}, &uam_changepw, - &uam_changepw}; + &uam_login}; +static struct uam_obj uam_changepw = {"", "", 0, {{NULL}}, &uam_changepw, + &uam_changepw}; static struct uam_obj *afp_uam = NULL; -/* Variables for CAP style printer authentication */ -#ifdef CAPDIR -extern int addr_net, addr_node, addr_uid; -extern char addr_name[32]; -#endif /* CAPDIR */ - void status_versions( data ) - char *data; +char *data; { char *start = data; u_int16_t status; @@ -87,10 +95,10 @@ void status_versions( data ) data += ntohs( status ); *data++ = num; for ( i = 0; i < num; i++ ) { - len = strlen( afp_versions[ i ].av_name ); - *data++ = len; - memcpy( data, afp_versions[ i ].av_name , len ); - data += len; + len = strlen( afp_versions[ i ].av_name ); + *data++ = len; + memcpy( data, afp_versions[ i ].av_name , len ); + data += len; } status = htons( data - start ); memcpy(start + AFPSTATUS_UAMSOFF, &status, sizeof(status)); @@ -106,20 +114,20 @@ void status_uams(char *data, const char *authlist) memcpy(&status, start + AFPSTATUS_UAMSOFF, sizeof(status)); uams = &uam_login; while ((uams = uams->uam_prev) != &uam_login) { - if (strstr(authlist, uams->uam_path)) - num++; + if (strstr(authlist, uams->uam_path)) + num++; } data += ntohs( status ); *data++ = num; while ((uams = uams->uam_prev) != &uam_login) { - if (strstr(authlist, uams->uam_path)) { - syslog(LOG_INFO, "uam: \"%s\" available", uams->uam_name); - len = strlen( uams->uam_name); - *data++ = len; - memcpy( data, uams->uam_name, len ); - data += len; - } + if (strstr(authlist, uams->uam_path)) { + syslog(LOG_INFO, "uam: \"%s\" available", uams->uam_name); + len = strlen( uams->uam_name); + *data++ = len; + memcpy( data, uams->uam_name, len ); + data += len; + } } /* icon offset */ @@ -131,135 +139,224 @@ void status_uams(char *data, const char *authlist) * by the afp_* functions. */ static int send_reply(const AFPObj *obj, const int err) { - if ((err == AFP_OK) || (err == AFPERR_AUTHCONT)) - return err; + if ((err == AFP_OK) || (err == AFPERR_AUTHCONT)) + return err; - obj->reply(obj->handle, err); - obj->exit(0); + obj->reply(obj->handle, err); + obj->exit(0); + + return AFP_OK; } static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void)) { -#ifdef CAPDIR - char nodename[256]; - FILE *fp; -#endif /* CAPDIR */ +#ifdef ADMIN_GRP + int admin = 0; +#endif /* ADMIN_GRP */ + + /* UAM had syslog control; afpd needs to reassert itself */ + openlog( "afpd", LOG_NDELAY|LOG_PID, LOG_DAEMON); if ( pwd->pw_uid == 0 ) { /* don't allow root login */ - syslog( LOG_ERR, "login: root login denied!" ); - return AFPERR_NOTAUTH; + syslog( LOG_ERR, "login: root login denied!" ); + return AFPERR_NOTAUTH; } syslog( LOG_INFO, "login %s (uid %d, gid %d)", pwd->pw_name, - pwd->pw_uid, pwd->pw_gid ); - -#ifdef CAPDIR - if(addr_net && addr_node) { /* Do we have a valid Appletalk address? */ - addr_uid = pwd->pw_uid; - strncpy(addr_name, pwd->pw_name, 32); - sprintf(nodename, "%s/net%d.%dnode%d", CAPDIR, addr_net / 256, addr_net % 256, addr_node); - syslog (LOG_INFO, "registering %s (uid %d) on %u.%u as %s", - addr_name, addr_uid, addr_net, addr_node, nodename); - fp = fopen(nodename, "w"); - fprintf(fp, "%s\n", addr_name); - fclose(fp); - } -#endif /* CAPDIR */ + pwd->pw_uid, pwd->pw_gid ); + + 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; + struct stat stat_buf; + + sprintf(nodename, "%s/net%d.%dnode%d", obj->options.authprintdir, + addr_net / 256, addr_net % 256, addr_node); + syslog (LOG_INFO, "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\n", pwd->pw_name); + fclose(fp); + chown( nodename, pwd->pw_uid, -1 ); + } else { /* somebody is messing with us */ + syslog( LOG_ERR, "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\n", pwd->pw_name); + fclose(fp); + chown( nodename, pwd->pw_uid, -1 ); + } + } /* if (addr_net && addr_node ) */ + } /* if (options->authprintdir) */ + } /* if (obj->proto == AFPPROTO_ASP) */ if (initgroups( pwd->pw_name, pwd->pw_gid ) < 0) { #ifdef RUN_AS_USER - syslog(LOG_INFO, "running with uid %d", geteuid()); -#else - syslog(LOG_ERR, "login: %m"); - return AFPERR_BADUAM; -#endif - } - - if (setegid( pwd->pw_gid ) < 0 || seteuid( pwd->pw_uid ) < 0) { - syslog( LOG_ERR, "login: %m" ); - return AFPERR_BADUAM; + syslog(LOG_INFO, "running with uid %d", geteuid()); +#else /* RUN_AS_USER */ + syslog(LOG_ERR, "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( NGROUPS, groups )) < 0 ) { - syslog( LOG_ERR, "login: getgroups: %m" ); - return AFPERR_BADUAM; + syslog( LOG_ERR, "login: getgroups: %s", strerror(errno) ); + return AFPERR_BADUAM; } - uuid = pwd->pw_uid; +#ifdef ADMIN_GRP +#ifdef DEBUG + syslog(LOG_INFO, "obj->options.admingid == %d", obj->options.admingid); +#endif /* DEBUG */ + if (obj->options.admingid != 0) { + int i; + for (i = 0; i < ngroups; i++) { + if (groups[i] == obj->options.admingid) admin = 1; + } + } + if (admin) syslog( LOG_INFO, "admin login -- %s", pwd->pw_name ); + if (!admin) +#endif /* DEBUG */ +#ifdef TRU64 + { + struct DSI *dsi = obj->handle; + struct hostent *hp; + char *clientname; + int argc; + char **argv; + char hostname[256]; + + afp_get_cmdline( &argc, &argv ); + + hp = gethostbyaddr( (char *) &dsi->client.sin_addr, + sizeof( struct in_addr ), + dsi->client.sin_family ); + + if( hp ) + clientname = hp->h_name; + else + clientname = inet_ntoa( dsi->client.sin_addr ); + + sprintf( hostname, "%s@%s", pwd->pw_name, clientname ); + + if( sia_become_user( NULL, argc, argv, hostname, pwd->pw_name, + NULL, FALSE, NULL, NULL, + SIA_BEU_REALLOGIN ) != SIASUCCESS ) + return AFPERR_BADUAM; + + syslog( LOG_INFO, "session from %s (%s)", hostname, + inet_ntoa( dsi->client.sin_addr ) ); + + if (setegid( pwd->pw_gid ) < 0 || seteuid( pwd->pw_uid ) < 0) { + syslog( LOG_ERR, "login: %m" ); + return AFPERR_BADUAM; + } + } +#else /* TRU64 */ + if (setegid( pwd->pw_gid ) < 0 || seteuid( pwd->pw_uid ) < 0) { + syslog( LOG_ERR, "login: %s", strerror(errno) ); + return AFPERR_BADUAM; + } +#endif /* TRU64 */ + + /* There's probably a better way to do this, but for now, we just + play root */ + +#ifdef ADMIN_GRP + if (admin) uuid = 0; + else +#endif /* ADMIN_GRP */ + uuid = pwd->pw_uid; afp_switch = postauth_switch; obj->logout = logout; + return( AFP_OK ); } int afp_login(obj, ibuf, ibuflen, rbuf, rbuflen ) - AFPObj *obj; - char *ibuf, *rbuf; - int ibuflen, *rbuflen; +AFPObj *obj; +char *ibuf, *rbuf; +int ibuflen, *rbuflen; { struct passwd *pwd = NULL; int len, i, num; *rbuflen = 0; - if ( nologin & 1) - return send_reply(obj, AFPERR_SHUTDOWN ); + if ( nologin & 1) + return send_reply(obj, AFPERR_SHUTDOWN ); ibuf++; len = (unsigned char) *ibuf++; 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; - break; - } + if ( strncmp( ibuf, afp_versions[ i ].av_name , len ) == 0 ) { + afp_version = afp_versions[ i ].av_number; + break; + } } if ( i == num ) /* An inappropo version */ - return send_reply(obj, AFPERR_BADVERS ); + return send_reply(obj, AFPERR_BADVERS ); ibuf += len; len = (unsigned char) *ibuf++; if ((afp_uam = auth_uamfind(UAM_SERVER_LOGIN, ibuf, len)) == NULL) - return send_reply(obj, AFPERR_BADUAM); + return send_reply(obj, AFPERR_BADUAM); ibuf += len; i = afp_uam->u.uam_login.login(obj, &pwd, ibuf, ibuflen, rbuf, rbuflen); - if (i || !pwd) - return send_reply(obj, i); - + if (i || !pwd) + return send_reply(obj, i); + return send_reply(obj, login(obj, pwd, afp_uam->u.uam_login.logout)); } int afp_logincont(obj, ibuf, ibuflen, rbuf, rbuflen) - AFPObj *obj; - char *ibuf, *rbuf; - int ibuflen, *rbuflen; +AFPObj *obj; +char *ibuf, *rbuf; +int ibuflen, *rbuflen; { struct passwd *pwd = NULL; int err; if ( afp_uam == NULL || afp_uam->u.uam_login.logincont == NULL ) { - *rbuflen = 0; - return send_reply(obj, AFPERR_NOTAUTH ); + *rbuflen = 0; + return send_reply(obj, AFPERR_NOTAUTH ); } ibuf += 2; err = afp_uam->u.uam_login.logincont(obj, &pwd, ibuf, ibuflen, - rbuf, rbuflen); + rbuf, rbuflen); if (err || !pwd) - return send_reply(obj, err); + return send_reply(obj, err); return send_reply(obj, login(obj, pwd, afp_uam->u.uam_login.logout)); } int afp_logout(obj, ibuf, ibuflen, rbuf, rbuflen) - AFPObj *obj; - char *ibuf, *rbuf; - int ibuflen, *rbuflen; +AFPObj *obj; +char *ibuf, *rbuf; +int ibuflen, *rbuflen; { - syslog(LOG_INFO, "logout %s", obj->username); - obj->exit(0); + syslog(LOG_INFO, "logout %s", obj->username); + obj->exit(0); + return AFP_OK; } @@ -270,78 +367,78 @@ int afp_logout(obj, ibuf, ibuflen, rbuf, rbuflen) * it off to the uam. */ int afp_changepw(obj, ibuf, ibuflen, rbuf, rbuflen ) - AFPObj *obj; - char *ibuf, *rbuf; - int ibuflen, *rbuflen; +AFPObj *obj; +char *ibuf, *rbuf; +int ibuflen, *rbuflen; { - char username[MACFILELEN + 1], *start = ibuf; - struct uam_obj *uam; - struct passwd *pwd; - int len; + char username[MACFILELEN + 1], *start = ibuf; + struct uam_obj *uam; + struct passwd *pwd; + int len; - *rbuflen = 0; - ibuf += 2; + *rbuflen = 0; + ibuf += 2; - /* make sure we can deal w/ this uam */ - len = (unsigned char) *ibuf++; - if ((uam = auth_uamfind(UAM_SERVER_CHANGEPW, ibuf, len)) == NULL) - return AFPERR_BADUAM; + /* make sure we can deal w/ this uam */ + len = (unsigned char) *ibuf++; + if ((uam = auth_uamfind(UAM_SERVER_CHANGEPW, ibuf, len)) == NULL) + return AFPERR_BADUAM; - ibuf += len; - if ((len + 1) & 1) /* pad byte */ - ibuf++; + ibuf += len; + if ((len + 1) & 1) /* pad byte */ + ibuf++; - len = (unsigned char) *ibuf++; - if ( len > sizeof(username) - 1) { - return AFPERR_PARAM; - } - memcpy(username, ibuf, len); - username[ len ] = '\0'; - ibuf += len; - if ((len + 1) & 1) /* pad byte */ - ibuf++; - - syslog(LOG_INFO, "changing password for <%s>", username); - - if (( pwd = uam_getname( username, sizeof(username))) == NULL ) - return AFPERR_PARAM; - - /* send it off to the uam. we really don't use ibuflen right now. */ - ibuflen -= (ibuf - start); - len = uam->u.uam_changepw(obj, username, pwd, ibuf, ibuflen, - rbuf, rbuflen); - syslog(LOG_INFO, "password change %s.", - (len == AFPERR_AUTHCONT) ? "continued" : - (len ? "failed" : "succeeded")); - return len; + len = (unsigned char) *ibuf++; + if ( len > sizeof(username) - 1) { + return AFPERR_PARAM; + } + memcpy(username, ibuf, len); + username[ len ] = '\0'; + ibuf += len; + if ((len + 1) & 1) /* pad byte */ + ibuf++; + + syslog(LOG_INFO, "changing password for <%s>", username); + + if (( pwd = uam_getname( username, sizeof(username))) == NULL ) + return AFPERR_PARAM; + + /* send it off to the uam. we really don't use ibuflen right now. */ + ibuflen -= (ibuf - start); + len = uam->u.uam_changepw(obj, username, pwd, ibuf, ibuflen, + rbuf, rbuflen); + syslog(LOG_INFO, "password change %s.", + (len == AFPERR_AUTHCONT) ? "continued" : + (len ? "failed" : "succeeded")); + return len; } /* FPGetUserInfo */ int afp_getuserinfo(obj, ibuf, ibuflen, rbuf, rbuflen ) - AFPObj *obj; - char *ibuf, *rbuf; - int ibuflen, *rbuflen; +AFPObj *obj; +char *ibuf, *rbuf; +int ibuflen, *rbuflen; { u_int8_t thisuser; u_int32_t id; u_int16_t bitmap; - + *rbuflen = 0; ibuf++; thisuser = *ibuf++; ibuf += sizeof(id); /* userid is not used in AFP 2.0 */ memcpy(&bitmap, ibuf, sizeof(bitmap)); bitmap = ntohs(bitmap); - - /* deal with error cases. we don't have to worry about + + /* deal with error cases. we don't have to worry about * AFPERR_ACCESS or AFPERR_NOITEM as geteuid and getegid always * succeed. */ - if (!thisuser) - return AFPERR_PARAM; + if (!thisuser) + return AFPERR_PARAM; if ((bitmap & USERIBIT_ALL) != bitmap) - return AFPERR_BITMAP; - + return AFPERR_BITMAP; + /* copy the bitmap back to reply buffer */ memcpy(rbuf, ibuf, sizeof(bitmap)); rbuf += sizeof(bitmap); @@ -349,21 +446,21 @@ int afp_getuserinfo(obj, ibuf, ibuflen, rbuf, rbuflen ) /* copy the user/group info */ if (bitmap & USERIBIT_USER) { - id = htonl(geteuid()); - memcpy(rbuf, &id, sizeof(id)); - rbuf += sizeof(id); - *rbuflen += sizeof(id); + id = htonl(geteuid()); + memcpy(rbuf, &id, sizeof(id)); + rbuf += sizeof(id); + *rbuflen += sizeof(id); } - + if (bitmap & USERIBIT_GROUP) { - id = htonl(getegid()); - memcpy(rbuf, &id, sizeof(id)); - rbuf += sizeof(id); - *rbuflen += sizeof(id); + id = htonl(getegid()); + memcpy(rbuf, &id, sizeof(id)); + rbuf += sizeof(id); + *rbuflen += sizeof(id); } - + return AFP_OK; -} +} #define UAM_LIST(type) (((type) == UAM_SERVER_LOGIN) ? &uam_login : \ (((type) == UAM_SERVER_CHANGEPW) ? \ @@ -371,76 +468,88 @@ int afp_getuserinfo(obj, ibuf, ibuflen, rbuf, rbuflen ) /* just do a linked list search. this could be sped up with a hashed * list, but i doubt anyone's going to have enough uams to matter. */ -struct uam_obj *auth_uamfind(const int type, const char *name, - const int len) +struct uam_obj *auth_uamfind(const int type, const char *name, + const int len) { - struct uam_obj *prev, *start; + struct uam_obj *prev, *start; - if (!name || !(start = UAM_LIST(type))) - return NULL; + if (!name || !(start = UAM_LIST(type))) + return NULL; - prev = start; - while ((prev = prev->uam_prev) != start) - if (strndiacasecmp(prev->uam_name, name, len) == 0) - return prev; + prev = start; + while ((prev = prev->uam_prev) != start) + if (strndiacasecmp(prev->uam_name, name, len) == 0) + return prev; - return NULL; + return NULL; } int auth_register(const int type, struct uam_obj *uam) { - struct uam_obj *start; + struct uam_obj *start; - if (!uam || !uam->uam_name || (*uam->uam_name == '\0')) - return -1; + if (!uam || !uam->uam_name || (*uam->uam_name == '\0')) + return -1; - if (!(start = UAM_LIST(type))) - return 0; /* silently fail */ + if (!(start = UAM_LIST(type))) + return 0; /* silently fail */ - uam_attach(start, uam); - return 0; + uam_attach(start, uam); + return 0; } /* load all of the modules */ int auth_load(const char *path, const char *list) { - char name[MAXPATHLEN + 1], buf[MAXPATHLEN + 1], *p; - struct uam_mod *mod; - struct stat st; - int len; - - if (!path || !list || (len = strlen(path)) > sizeof(name) - 2) - return -1; - - strncpy(buf, list, sizeof(buf)); - if ((p = strtok(buf, ",")) == NULL) - return -1; - - strcpy(name, path); - if (name[len - 1] != '/') { - strcat(name, "/"); - len++; - } - - while (p) { - strncpy(name + len, p, sizeof(name) - len); - if ((stat(name, &st) == 0) && (mod = uam_load(name, p))) { - uam_attach(&uam_modules, mod); - syslog(LOG_INFO, "uam: %s loaded", p); + char name[MAXPATHLEN + 1], buf[MAXPATHLEN + 1], *p; + struct uam_mod *mod; + struct stat st; + int len; + + if (!path || !list || (len = strlen(path)) > sizeof(name) - 2) + return -1; + + strncpy(buf, list, sizeof(buf)); + if ((p = strtok(buf, ",")) == NULL) + return -1; + + strcpy(name, path); + if (name[len - 1] != '/') { + strcat(name, "/"); + len++; } - p = strtok(NULL, ","); - } + + while (p) { + strncpy(name + len, p, sizeof(name) - len); + syslog(LOG_DEBUG, "uam: loading (%s)", name); + /* + if ((stat(name, &st) == 0) && (mod = uam_load(name, p))) { + */ + if (stat(name, &st) == 0) { + if ((mod = uam_load(name, p))) { + uam_attach(&uam_modules, mod); + syslog(LOG_INFO, "uam: %s loaded", p); + } else { + syslog(LOG_INFO, "uam: %s load failure",p); + } + } else { + syslog(LOG_INFO, "uam: uam not found (status=%d)", stat(name, &st)); + } + p = strtok(NULL, ","); + } + + return 0; } /* get rid of all of the uams */ void auth_unload() { - struct uam_mod *mod, *prev, *start = &uam_modules; - - prev = start->uam_prev; - while ((mod = prev) != start) { - prev = prev->uam_prev; - uam_detach(mod); - uam_unload(mod); - } + struct uam_mod *mod, *prev, *start = &uam_modules; + + prev = start->uam_prev; + while ((mod = prev) != start) { + prev = prev->uam_prev; + uam_detach(mod); + uam_unload(mod); + } }