X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fuam.c;h=0f5afb41c4a4e0f15e67f771d543e34fa5731a24;hb=b0bcb8f6b0571592a50ce039882c9319e012a270;hp=08ba1cdac08a767d8c4a9a6218a7739dcf2171c0;hpb=2124172d8708b74ec0851366f9a5cdcc530c91b3;p=netatalk.git diff --git a/etc/afpd/uam.c b/etc/afpd/uam.c index 08ba1cda..0f5afb41 100644 --- a/etc/afpd/uam.c +++ b/etc/afpd/uam.c @@ -1,5 +1,5 @@ /* - * $Id: uam.c,v 1.24 2003-04-16 22:45:11 samnoble Exp $ + * $Id: uam.c,v 1.35 2009-11-08 01:15:31 didg Exp $ * * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu) * All Rights Reserved. See COPYRIGHT. @@ -11,28 +11,9 @@ #include #include - -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - -#ifdef HAVE_UNISTD_H #include -#endif /* HAVE_UNISTD_H */ -#ifdef HAVE_FCNTL_H #include -#endif /* HAVE_FCNTL_H */ #include #include #include @@ -45,17 +26,17 @@ char *strchr (), *strrchr (); #include #include -#include -#include #include #include #include +#include -#include "globals.h" #include "afp_config.h" #include "auth.h" #include "uam_auth.h" +#define utf8_encoding() (afp_version >= 30) + #ifdef TRU64 #include #include @@ -64,9 +45,6 @@ char *strchr (), *strrchr (); #endif /* TRU64 */ /* --- server uam functions -- */ -#ifndef NO_LOAD_UAM -extern int uam_setup(const char *path); -#endif /* uam_load. uams must have a uam_setup function. */ struct uam_mod *uam_load(const char *path, const char *name) @@ -75,24 +53,20 @@ struct uam_mod *uam_load(const char *path, const char *name) struct uam_mod *mod; void *module; -#ifndef NO_LOAD_UAM if ((module = mod_open(path)) == NULL) { LOG(log_error, logtype_afpd, "uam_load(%s): failed to load: %s", name, mod_error()); return NULL; } -#endif if ((mod = (struct uam_mod *) malloc(sizeof(struct uam_mod))) == NULL) { LOG(log_error, logtype_afpd, "uam_load(%s): malloc failed", name); goto uam_load_fail; } - strncpy(buf, name, sizeof(buf)); - buf[sizeof(buf) - 1] = '\0'; + strlcpy(buf, name, sizeof(buf)); if ((p = strchr(buf, '.'))) *p = '\0'; -#ifndef NO_LOAD_UAM if ((mod->uam_fcn = mod_symbol(module, buf)) == NULL) { LOG(log_error, logtype_afpd, "uam_load(%s): mod_symbol error for symbol %s", name, @@ -113,9 +87,6 @@ struct uam_mod *uam_load(const char *path, const char *name) LOG(log_error, logtype_afpd, "uam_load(%s): uam_setup failed", name); goto uam_load_err; } -#else - uam_setup(name); -#endif mod->uam_module = module; return mod; @@ -135,19 +106,17 @@ void uam_unload(struct uam_mod *mod) if (mod->uam_fcn->uam_cleanup) (*mod->uam_fcn->uam_cleanup)(); -#ifndef NO_LOAD_UAM mod_close(mod->uam_module); -#endif free(mod); } /* -- client-side uam functions -- */ -#ifndef ATACC /* set up stuff for this uam. */ int uam_register(const int type, const char *path, const char *name, ...) { va_list ap; struct uam_obj *uam; + int ret; if (!name) return -1; @@ -197,77 +166,14 @@ int uam_register(const int type, const char *path, const char *name, ...) va_end(ap); /* attach to other uams */ - if (auth_register(type, uam) < 0) { + ret = auth_register(type, uam); + if ( ret) { free(uam->uam_path); free(uam); - return -1; } - return 0; + return ret; } -#endif - -#ifdef ATACC -int uam_register_fn(const int type, const char *path, const char *name, void *fn1, void *fn2, - void *fn3, void *fn4) -{ - va_list ap; - struct uam_obj *uam; - - if (!name) - return -1; - - /* see if it already exists. */ - if ((uam = auth_uamfind(type, name, strlen(name)))) { - if (strcmp(uam->uam_path, path)) { - /* it exists, but it's not the same module. */ - LOG(log_error, logtype_afpd, "uam_register: \"%s\" already loaded by %s", - name, path); - return -1; - } - uam->uam_count++; - return 0; - } - - /* allocate space for uam */ - if ((uam = calloc(1, sizeof(struct uam_obj))) == NULL) - return -1; - - uam->uam_name = name; - uam->uam_path = strdup(path); - uam->uam_count++; - - switch (type) { - case UAM_SERVER_LOGIN_EXT: /* expect four arguments */ - uam->u.uam_login.login_ext = fn4; - uam->u.uam_login.login = fn1; - uam->u.uam_login.logincont = fn2; - uam->u.uam_login.logout = fn3; - break; - case UAM_SERVER_LOGIN: /* expect three arguments */ - uam->u.uam_login.login_ext = NULL; - uam->u.uam_login.login = fn1; - uam->u.uam_login.logincont = fn2; - uam->u.uam_login.logout = fn3; - break; - case UAM_SERVER_CHANGEPW: /* one argument */ - uam->u.uam_changepw = fn1; - break; - case UAM_SERVER_PRINTAUTH: /* x arguments */ - default: - break; - } - - /* attach to other uams */ - if (auth_register(type, uam) < 0) { - free(uam->uam_path); - free(uam); - return -1; - } - - return 0; -} -#endif void uam_unregister(const int type, const char *name) { @@ -285,33 +191,71 @@ void uam_unregister(const int type, const char *name) free(uam); } -/* --- helper functions for plugin uams --- */ +/* --- helper functions for plugin uams --- + * name: user name + * len: size of name buffer. +*/ -struct passwd *uam_getname(char *name, const int len) +struct passwd *uam_getname(void *private, char *name, const int len) { + AFPObj *obj = private; struct passwd *pwent; - char *user; - int i; + static char username[256]; + static char user[256]; + static char pwname[256]; + char *p; + size_t namelen, gecoslen = 0, pwnamelen = 0; if ((pwent = getpwnam(name))) return pwent; - + + /* if we have a NT domain name try with it */ + if (obj->options.ntdomain && obj->options.ntseparator) { + /* FIXME What about charset ? */ + size_t ulen = strlen(obj->options.ntdomain) + strlen(obj->options.ntseparator) + strlen(name); + if ((p = malloc(ulen +1))) { + strcpy(p, obj->options.ntdomain); + strcat(p, obj->options.ntseparator); + strcat(p, name); + pwent = getpwnam(p); + free(p); + if (pwent) { + int len = strlen(pwent->pw_name); + if (len < MAXUSERLEN) { + strncpy(name,pwent->pw_name, MAXUSERLEN); + }else{ + LOG(log_error, logtype_uams, "MAJOR:The name %s is longer than %d",pwent->pw_name,MAXUSERLEN); + } + + return pwent; + } + } + } #ifndef NO_REAL_USER_NAME - for (i = 0; i < len; i++) - name[i] = tolower(name[i]); + + if ( (size_t) -1 == (namelen = convert_string((utf8_encoding())?CH_UTF8_MAC:obj->options.maccharset, + CH_UCS2, name, -1, username, sizeof(username)))) + return NULL; setpwent(); while ((pwent = getpwent())) { - if ((user = strchr(pwent->pw_gecos, ','))) - *user = '\0'; - user = pwent->pw_gecos; + if ((p = strchr(pwent->pw_gecos, ','))) + *p = '\0'; + + if ((size_t)-1 == ( gecoslen = convert_string(obj->options.unixcharset, CH_UCS2, + pwent->pw_gecos, -1, user, sizeof(username))) ) + continue; + if ((size_t)-1 == ( pwnamelen = convert_string(obj->options.unixcharset, CH_UCS2, + pwent->pw_name, -1, pwname, sizeof(username))) ) + continue; + /* check against both the gecos and the name fields. the user * might have just used a different capitalization. */ - if ((strncasecmp(user, name, len) == 0) || - (strncasecmp(pwent->pw_name, name, len) == 0)) { - strncpy(name, pwent->pw_name, len); - name[len - 1] = '\0'; + + if ( (namelen == gecoslen && strncasecmp_w((ucs2_t*)user, (ucs2_t*)username, len) == 0) || + ( namelen == pwnamelen && strncasecmp_w ( (ucs2_t*) pwname, (ucs2_t*) username, len) == 0)) { + strlcpy(name, pwent->pw_name, len); break; } } @@ -334,7 +278,6 @@ int uam_checkuser(const struct passwd *pwd) LOG(log_info, logtype_afpd, "uam_checkuser: User %s does not have a shell", pwd->pw_name); return -1; } -#endif while ((p = getusershell())) { if ( strcmp( p, pwd->pw_shell ) == 0 ) @@ -342,7 +285,6 @@ int uam_checkuser(const struct passwd *pwd) } endusershell(); -#ifndef DISABLE_SHELLCHECK if (!p) { LOG(log_info, logtype_afpd, "illegal shell %s for %s", pwd->pw_shell, pwd->pw_name); return -1; @@ -352,27 +294,57 @@ int uam_checkuser(const struct passwd *pwd) return 0; } +int uam_random_string (AFPObj *obj, char *buf, int len) +{ + u_int32_t result; + int ret; + int fd; + + if ( (len <= 0) || (len % sizeof(result))) + return -1; + + /* construct a random number */ + if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { + struct timeval tv; + struct timezone tz; + int i; + + if (gettimeofday(&tv, &tz) < 0) + return -1; + srandom(tv.tv_sec + (unsigned long) obj + (unsigned long) obj->handle); + for (i = 0; i < len; i += sizeof(result)) { + result = random(); + memcpy(buf + i, &result, sizeof(result)); + } + } else { + ret = read(fd, buf, len); + close(fd); + if (ret <= 0) + return -1; + } + return 0; +} + /* afp-specific functions */ int uam_afpserver_option(void *private, const int what, void *option, - int *len) + size_t *len) { -AFPObj *obj = private; - char **buf = (char **) option; /* most of the options are this */ - int32_t result; - int fd; + AFPObj *obj = private; + const char **buf = (const char **) option; /* most of the options are this */ + struct session_info **sinfo = (struct session_info **) option; if (!obj || !option) return -1; switch (what) { case UAM_OPTION_USERNAME: - *buf = (void *) obj->username; + *buf = &(obj->username[0]); if (len) *len = sizeof(obj->username) - 1; break; case UAM_OPTION_GUEST: - *buf = (void *) obj->options.guest; + *buf = obj->options.guest; if (len) *len = strlen(obj->options.guest); break; @@ -383,7 +355,7 @@ AFPObj *obj = private; switch (*len) { case UAM_PASSWD_FILENAME: - *buf = (void *) obj->options.passwdfile; + *buf = obj->options.passwdfile; *len = strlen(obj->options.passwdfile); break; @@ -411,54 +383,36 @@ AFPObj *obj = private; break; case UAM_OPTION_RANDNUM: /* returns a random number in 4-byte units. */ - if (!len || (*len < 0) || (*len % sizeof(result))) + if (!len) return -1; - /* construct a random number */ - if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { - struct timeval tv; - struct timezone tz; - char *randnum = (char *) option; - int i; - - if (gettimeofday(&tv, &tz) < 0) - return -1; - srandom(tv.tv_sec + (unsigned long) obj + (unsigned long) obj->handle); - for (i = 0; i < *len; i += sizeof(result)) { - result = random(); - memcpy(randnum + i, &result, sizeof(result)); - } - } else { - result = read(fd, option, *len); - close(fd); - if (result < 0) - return -1; - } + return uam_random_string(obj, option, *len); break; case UAM_OPTION_HOSTNAME: - *buf = (void *) obj->options.hostname; + *buf = obj->options.hostname; if (len) *len = strlen(obj->options.hostname); break; case UAM_OPTION_PROTOCOL: - *buf = (void *) obj->proto; + *((int *) option) = obj->proto; break; + case UAM_OPTION_CLIENTNAME: - { - struct DSI *dsi = obj->handle; - struct hostent *hp; - - hp = gethostbyaddr( (char *) &dsi->client.sin_addr, - sizeof( struct in_addr ), - dsi->client.sin_family ); - if( hp ) - *buf = (void *) hp->h_name; - else - *buf = (void *) inet_ntoa( dsi->client.sin_addr ); - } + { + struct DSI *dsi = obj->handle; + const struct sockaddr *sa; + static char hbuf[NI_MAXHOST]; + + sa = (struct sockaddr *)&dsi->client; + if (getnameinfo(sa, sizeof(dsi->client), hbuf, sizeof(hbuf), NULL, 0, 0) == 0) + *buf = hbuf; + else + *buf = getip_string((struct sockaddr *)&dsi->client); + break; + } case UAM_OPTION_COOKIE: /* it's up to the uam to actually store something useful here. * this just passes back a handle to the cookie. the uam side @@ -469,8 +423,29 @@ AFPObj *obj = private; case UAM_OPTION_KRB5SERVICE: *buf = obj->options.k5service; if (len) - *len = strlen(obj->options.k5service); + *len = (*buf)?strlen(*buf):0; + break; + case UAM_OPTION_KRB5REALM: + *buf = obj->options.k5realm; + if (len) + *len = (*buf)?strlen(*buf):0; break; + case UAM_OPTION_FQDN: + *buf = obj->options.fqdn; + if (len) + *len = (*buf)?strlen(*buf):0; + break; + case UAM_OPTION_MACCHARSET: + *((int *) option) = obj->options.maccharset; + *len = sizeof(obj->options.maccharset); + break; + case UAM_OPTION_UNIXCHARSET: + *((int *) option) = obj->options.unixcharset; + *len = sizeof(obj->options.unixcharset); + break; + case UAM_OPTION_SESSIONINFO: + *sinfo = &(obj->sinfo); + break; default: return -1; break; @@ -482,7 +457,7 @@ AFPObj *obj = private; /* if we need to maintain a connection, this is how we do it. * because an action pointer gets passed in, we can stream * DSI connections */ -int uam_afp_read(void *handle, char *buf, int *buflen, +int uam_afp_read(void *handle, char *buf, size_t *buflen, int (*action)(void *, void *, const int)) { AFPObj *obj = handle; @@ -491,14 +466,6 @@ int uam_afp_read(void *handle, char *buf, int *buflen, if (!obj) return AFPERR_PARAM; - switch (obj->proto) { - case AFPPROTO_ASP: - if ((len = asp_wrtcont(obj->handle, buf, buflen )) < 0) - goto uam_afp_read_err; - return action(handle, buf, *buflen); - break; - - case AFPPROTO_DSI: len = dsi_writeinit(obj->handle, buf, *buflen); if (!len || ((len = action(handle, buf, len)) < 0)) { dsi_writeflush(obj->handle); @@ -511,8 +478,6 @@ int uam_afp_read(void *handle, char *buf, int *buflen, goto uam_afp_read_err; } } - break; - } return 0; uam_afp_read_err: @@ -572,7 +537,9 @@ int uam_sia_validate_user(sia_collect_func_t * collect, int argc, char **argv, #endif /* TRU64 */ /* --- papd-specific functions (just placeholders) --- */ -void append(void *pf, char *data, int len) +struct papfile; + +UAM_MODULE_EXPORT void append(struct papfile *pf _U_, const char *data _U_, int len _U_) { return; }