From 6655a7d0a550224642fc0f83320565d6e1123273 Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Fri, 17 Feb 2012 11:11:41 +0100 Subject: [PATCH] Move volume loading to libatalk --- etc/afpd/acls.c | 75 +- etc/afpd/acls.h | 3 +- etc/afpd/afp_config.c | 18 +- etc/afpd/afp_dsi.c | 3 +- etc/afpd/afp_options.c | 200 ----- etc/afpd/appl.c | 3 +- etc/afpd/auth.c | 34 +- etc/afpd/catsearch.c | 21 +- etc/afpd/desktop.c | 16 +- etc/afpd/dircache.h | 1 - etc/afpd/directory.c | 21 +- etc/afpd/directory.h | 7 +- etc/afpd/enumerate.c | 7 +- etc/afpd/file.c | 35 +- etc/afpd/file.h | 6 +- etc/afpd/filedir.c | 7 +- etc/afpd/fork.c | 15 +- etc/afpd/main.c | 4 + etc/afpd/quota.c | 10 +- etc/afpd/status.h | 6 - etc/afpd/unix.c | 26 +- etc/afpd/unix.h | 5 +- etc/afpd/volume.c | 1393 ++------------------------------- etc/afpd/volume.h | 10 +- include/atalk/Makefile.am | 1 + include/atalk/globals.h | 12 +- include/atalk/netatalk_conf.h | 31 + include/atalk/unix.h | 2 +- include/atalk/volume.h | 5 +- libatalk/util/Makefile.am | 7 +- libatalk/util/logger.c | 4 +- libatalk/util/unix.c | 12 + 32 files changed, 260 insertions(+), 1740 deletions(-) create mode 100644 include/atalk/netatalk_conf.h diff --git a/etc/afpd/acls.c b/etc/afpd/acls.c index 40281bcc..8cb44d8a 100644 --- a/etc/afpd/acls.c +++ b/etc/afpd/acls.c @@ -45,6 +45,8 @@ #include #include #include +#include +#include #include "directory.h" #include "desktop.h" @@ -397,7 +399,9 @@ EC_CLEANUP: * * @returns 0 or -1 on error */ -static int posix_acl_rights(const char *path, + +static int posix_acl_rights(const AFPObj *obj, + const char *path, const struct stat *sb, uint32_t *result) { @@ -422,7 +426,7 @@ static int posix_acl_rights(const char *path, switch (tag) { case ACL_USER_OBJ: - if (sb->st_uid == uuid) { + if (sb->st_uid == obj->uid) { LOG(log_maxdebug, logtype_afpd, "ACL_USER_OBJ: %u", sb->st_uid); rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)); } @@ -431,7 +435,7 @@ static int posix_acl_rights(const char *path, case ACL_USER: EC_NULL_LOG(uid = (uid_t *)acl_get_qualifier(e)); - if (*uid == uuid) { + if (*uid == obj->uid) { LOG(log_maxdebug, logtype_afpd, "ACL_USER: %u", *uid); acl_rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)); } @@ -440,7 +444,7 @@ static int posix_acl_rights(const char *path, break; case ACL_GROUP_OBJ: - if (!(sb->st_uid == uuid) && gmem(sb->st_gid)) { + if (!(sb->st_uid == obj->uid) && gmem(sb->st_gid, obj->ngroups, obj->groups)) { LOG(log_maxdebug, logtype_afpd, "ACL_GROUP_OBJ: %u", sb->st_gid); acl_rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)); } @@ -449,7 +453,7 @@ static int posix_acl_rights(const char *path, case ACL_GROUP: EC_NULL_LOG(gid = (gid_t *)acl_get_qualifier(e)); - if (gmem(*gid)) { + if (gmem(*gid, obj->ngroups, obj->groups)) { LOG(log_maxdebug, logtype_afpd, "ACL_GROUP: %u", *gid); acl_rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)); } @@ -463,7 +467,7 @@ static int posix_acl_rights(const char *path, break; case ACL_OTHER: - if (!(sb->st_uid == uuid) && !gmem(sb->st_gid)) { + if (!(sb->st_uid == obj->uid) && !gmem(sb->st_gid, obj->ngroups, obj->groups)) { LOG(log_maxdebug, logtype_afpd, "ACL_OTHER"); rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)); } @@ -541,7 +545,7 @@ static u_char acl_permset_to_uarights(acl_entry_t entry) { * * @returns 0 or -1 on error */ -static int posix_acls_to_uaperms(const char *path, struct stat *sb, struct maccess *ma) { +static int posix_acls_to_uaperms(const AFPObj *obj, const char *path, struct stat *sb, struct maccess *ma) { EC_INIT; int entry_id = ACL_FIRST_ENTRY; @@ -567,7 +571,7 @@ static int posix_acls_to_uaperms(const char *path, struct stat *sb, struct macce case ACL_USER: EC_NULL_LOG(uid = (uid_t *)acl_get_qualifier(entry)); - if (*uid == uuid && !(whoami == sb->st_uid)) { + if (*uid == obj->uid && !(whoami == sb->st_uid)) { LOG(log_maxdebug, logtype_afpd, "ACL_USER: %u", *uid); acl_rights |= acl_permset_to_uarights(entry); } @@ -578,14 +582,14 @@ static int posix_acls_to_uaperms(const char *path, struct stat *sb, struct macce group_rights = acl_permset_to_uarights(entry); LOG(log_maxdebug, logtype_afpd, "ACL_GROUP_OBJ: %u", sb->st_gid); - if (gmem(sb->st_gid) && !(whoami == sb->st_uid)) + if (gmem(sb->st_gid, obj->ngroups, obj->groups) && !(whoami == sb->st_uid)) acl_rights |= group_rights; break; case ACL_GROUP: EC_NULL_LOG(gid = (gid_t *)acl_get_qualifier(entry)); - if (gmem(*gid) && !(whoami == sb->st_uid)) { + if (gmem(*gid, obj->ngroups, obj->groups) && !(whoami == sb->st_uid)) { LOG(log_maxdebug, logtype_afpd, "ACL_GROUP: %u", *gid); acl_rights |= acl_permset_to_uarights(entry); } @@ -1338,7 +1342,8 @@ EC_CLEANUP: * * @returns AFP result code */ -static int check_acl_access(const struct vol *vol, +static int check_acl_access(const AFPObj *obj, + const struct vol *vol, struct dir *dir, const char *path, const uuidp_t uuid, @@ -1385,7 +1390,7 @@ static int check_acl_access(const struct vol *vol, EC_ZERO_LOG(solaris_acl_rights(path, &st, &allowed_rights)); #endif #ifdef HAVE_POSIX_ACLS - EC_ZERO_LOG(posix_acl_rights(path, &st, &allowed_rights)); + EC_ZERO_LOG(posix_acl_rights(obj, path, &st, &allowed_rights)); #endif /* * The DARWIN_ACE_DELETE right might implicitly result from write acces to the parent @@ -1418,7 +1423,7 @@ static int check_acl_access(const struct vol *vol, EC_ZERO_LOG(solaris_acl_rights(cfrombstr(parent), &st, &parent_rights)); #endif #ifdef HAVE_POSIX_ACLS - EC_ZERO_LOG(posix_acl_rights(path, &st, &parent_rights)); + EC_ZERO_LOG(posix_acl_rights(obj, path, &st, &parent_rights)); #endif if (parent_rights & (DARWIN_ACE_WRITE_DATA | DARWIN_ACE_DELETE_CHILD)) allowed_rights |= DARWIN_ACE_DELETE; /* man, that was a lot of work! */ @@ -1508,7 +1513,7 @@ int afp_access(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size return AFPERR_NOOBJ; } - ret = check_acl_access(vol, dir, s_path->u_name, uuid, darwin_ace_rights); + ret = check_acl_access(obj, vol, dir, s_path->u_name, uuid, darwin_ace_rights); return ret; } @@ -1716,12 +1721,12 @@ int afp_setacl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size * This is the magic function that makes ACLs usable by calculating * the access granted by ACEs to the logged in user. */ -int acltoownermode(const struct vol *vol, char *path, struct stat *st, struct maccess *ma) +int acltoownermode(const AFPObj *obj, const struct vol *vol, char *path, struct stat *st, struct maccess *ma) { EC_INIT; uint32_t rights = 0; - if ( ! (AFPobj->options.flags & OPTION_ACL2MACCESS) + if ( ! (obj->options.flags & OPTION_ACL2MACCESS) || ! (vol->v_flags & AFPVOL_ACLS)) return 0; @@ -1742,7 +1747,7 @@ int acltoownermode(const struct vol *vol, char *path, struct stat *st, struct ma #endif #ifdef HAVE_POSIX_ACLS - EC_ZERO_LOG(posix_acls_to_uaperms(path, st, ma)); + EC_ZERO_LOG(posix_acls_to_uaperms(obj, path, st, ma)); #endif LOG(log_maxdebug, logtype_afpd, "resulting user maccess: 0x%02x group maccess: 0x%02x", ma->ma_user, ma->ma_group); @@ -1750,39 +1755,3 @@ int acltoownermode(const struct vol *vol, char *path, struct stat *st, struct ma EC_CLEANUP: EC_EXIT; } - -/*! - * Check whether a volume supports ACLs - * - * @param vol (r) volume - * - * @returns 0 if not, 1 if yes - */ -int check_vol_acl_support(const struct vol *vol) -{ - int ret = 0; - -#ifdef HAVE_SOLARIS_ACLS - ace_t *aces = NULL; - ret = 1; - if (get_nfsv4_acl(vol->v_path, &aces) == -1) - ret = 0; -#endif -#ifdef HAVE_POSIX_ACLS - acl_t acl = NULL; - ret = 1; - if ((acl = acl_get_file(vol->v_path, ACL_TYPE_ACCESS)) == NULL) - ret = 0; -#endif - -#ifdef HAVE_SOLARIS_ACLS - if (aces) free(aces); -#endif -#ifdef HAVE_POSIX_ACLS - if (acl) acl_free(acl); -#endif /* HAVE_POSIX_ACLS */ - - LOG(log_debug, logtype_afpd, "Volume \"%s\" ACL support: %s", - vol->v_path, ret ? "yes" : "no"); - return ret; -} diff --git a/etc/afpd/acls.h b/etc/afpd/acls.h index 273a9f13..0913eb2e 100644 --- a/etc/afpd/acls.h +++ b/etc/afpd/acls.h @@ -113,6 +113,5 @@ int afp_setacl (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rb extern int acl_ldap_readconfig(char *name); /* Misc funcs */ -extern int acltoownermode(const struct vol *vol, char *path, struct stat *st, struct maccess *ma); -extern int check_vol_acl_support(const struct vol *vol); +extern int acltoownermode(const AFPObj *obj, const struct vol *vol, char *path, struct stat *st, struct maccess *ma); #endif diff --git a/etc/afpd/afp_config.c b/etc/afpd/afp_config.c index d853e0b4..27767c10 100644 --- a/etc/afpd/afp_config.c +++ b/etc/afpd/afp_config.c @@ -88,7 +88,7 @@ int configinit(AFPObj *obj) if (obj->options.listen) { EC_NULL( q = p = strdup(obj->options.listen) ); - EC_NULL( p = strtok(p, ",") ); + EC_NULL( p = strtok(p, ", ") ); } while (1) { @@ -105,7 +105,7 @@ int configinit(AFPObj *obj) if (p) /* p is NULL if ! obj->options.listen */ - p = strtok(NULL, ","); + p = strtok(NULL, ", "); if (!p) break; } @@ -124,6 +124,20 @@ int configinit(AFPObj *obj) zeroconf_register(obj); } + if ((p = iniparser_getstring(obj->iniconfig, INISEC_AFP, "fcelistener", NULL))) { + LOG(log_note, logtype_afpd, "Adding FCE listener: %s", p); + fce_add_udp_socket(p); + } + if ((p = iniparser_getstring(obj->iniconfig, INISEC_AFP, "fcecoalesce", NULL))) { + LOG(log_note, logtype_afpd, "Fce coalesce: %s", p); + fce_set_coalesce(p); + } + if ((p = iniparser_getstring(obj->iniconfig, INISEC_AFP, "fceevents", NULL))) { + LOG(log_note, logtype_afpd, "Fce events: %s", p); + fce_set_events(p); + } + + EC_CLEANUP: if (q) free(q); diff --git a/etc/afpd/afp_dsi.c b/etc/afpd/afp_dsi.c index 2869722e..fd38fa85 100644 --- a/etc/afpd/afp_dsi.c +++ b/etc/afpd/afp_dsi.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "switch.h" #include "auth.h" @@ -528,7 +529,7 @@ void afp_over_dsi(AFPObj *obj) if (reload_request) { reload_request = 0; - load_volumes(AFPobj); + load_volumes(AFPobj, of_closevol); } /* The first SIGINT enables debugging, the next restores the config */ diff --git a/etc/afpd/afp_options.c b/etc/afpd/afp_options.c index 34253ee8..3b37538b 100644 --- a/etc/afpd/afp_options.c +++ b/etc/afpd/afp_options.c @@ -93,206 +93,6 @@ void afp_options_free(struct afp_options *opt) free(opt->unixcodepage); } -#define MAXVAL 1024 -int afp_config_parse(AFPObj *AFPObj) -{ - EC_INIT; - dictionary *config; - struct afp_options *options = &AFPObj->options; - int i, c; - const char *p, *tmp; - char *q, *r; - char val[MAXVAL]; - - options->configfile = AFPObj->cmdlineconfigfile ? strdup(AFPObj->cmdlineconfigfile) : strdup(_PATH_CONFDIR "afp.conf"); - options->sigconffile = strdup(_PATH_CONFDIR "afp_signature.conf"); - options->uuidconf = strdup(_PATH_CONFDIR "afp_voluuid.conf"); - options->flags = OPTION_ACL2MACCESS | OPTION_UUID | OPTION_SERVERNOTIF | AFPObj->cmdlineflags; - - if ((config = iniparser_load(AFPObj->options.configfile)) == NULL) - return -1; - AFPObj->iniconfig = config; - - /* [Global] */ - options->logconfig = iniparser_getstrdup(config, INISEC_GLOBAL, "loglevel", "default:note"); - options->logfile = iniparser_getstrdup(config, INISEC_GLOBAL, "logfile", NULL); - set_processname("afpd"); - setuplog(options->logconfig, options->logfile); - - /* [AFP] "options" options wo values */ - if (p = iniparser_getstrdup(config, INISEC_AFP, "options", NULL)) { - if (p = strtok(q, ", ")) { - while (p) { - if (strcasecmp(p, "nozeroconf")) - options->flags |= OPTION_NOZEROCONF; - if (strcasecmp(p, "icon")) - options->flags |= OPTION_CUSTOMICON; - if (strcasecmp(p, "noicon")) - options->flags &= ~OPTION_CUSTOMICON; - if (strcasecmp(p, "advertise_ssh")) - options->flags |= OPTION_ANNOUNCESSH; - if (strcasecmp(p, "noacl2maccess")) - options->flags &= ~OPTION_ACL2MACCESS; - if (strcasecmp(p, "keepsessions")) - options->flags |= OPTION_KEEPSESSIONS; - if (strcasecmp(p, "closevol")) - options->flags |= OPTION_CLOSEVOL; - if (strcasecmp(p, "client_polling")) - options->flags &= ~OPTION_SERVERNOTIF; - if (strcasecmp(p, "nosavepassword")) - options->passwdbits |= PASSWD_NOSAVE; - if (strcasecmp(p, "savepassword")) - options->passwdbits &= ~PASSWD_NOSAVE; - if (strcasecmp(p, "nosetpassword")) - options->passwdbits &= ~PASSWD_SET; - if (strcasecmp(p, "setpassword")) - options->passwdbits |= PASSWD_SET; - p = strtok(NULL, ","); - } - } - } - /* figure out options w values */ - - options->loginmesg = iniparser_getstrdup(config, INISEC_AFP, "loginmesg", ""); - options->guest = iniparser_getstrdup(config, INISEC_AFP, "guestname", "nobody"); - options->passwdfile = iniparser_getstrdup(config, INISEC_AFP, "passwdfile", _PATH_AFPDPWFILE); - options->uampath = iniparser_getstrdup(config, INISEC_AFP, "uampath", _PATH_AFPDUAMPATH); - options->uamlist = iniparser_getstrdup(config, INISEC_AFP, "uamlist", "uams_dhx.so,uams_dhx2.so"); - options->port = iniparser_getstrdup(config, INISEC_AFP, "port", "548"); - options->signatureopt = iniparser_getstrdup(config, INISEC_AFP, "signature", "auto"); - options->k5service = iniparser_getstrdup(config, INISEC_AFP, "k5service", NULL); - options->k5realm = iniparser_getstrdup(config, INISEC_AFP, "k5realm", NULL); - options->authprintdir = iniparser_getstrdup(config, INISEC_AFP, "authprintdir", NULL); - options->listen = iniparser_getstrdup(config, INISEC_AFP, "listen", NULL); - options->ntdomain = iniparser_getstrdup(config, INISEC_AFP, "ntdomain", NULL); - options->ntseparator = iniparser_getstrdup(config, INISEC_AFP, "ntseparator", NULL); - options->mimicmodel = iniparser_getstrdup(config, INISEC_AFP, "mimicmodel", NULL); - options->adminauthuser = iniparser_getstrdup(config, INISEC_AFP, "adminauthuser", NULL); - options->connections = iniparser_getint (config, INISEC_AFP, "maxcon", 200); - options->passwdminlen = iniparser_getint (config, INISEC_AFP, "passwdminlen", 0); - options->tickleval = iniparser_getint (config, INISEC_AFP, "tickleval", 30); - options->timeout = iniparser_getint (config, INISEC_AFP, "timeout", 4); - options->dsireadbuf = iniparser_getint (config, INISEC_AFP, "dsireadbuf", 12); - options->server_quantum = iniparser_getint (config, INISEC_AFP, "server_quantum", DSI_SERVQUANT_DEF); - options->volnamelen = iniparser_getint (config, INISEC_AFP, "volnamelen", 80); - options->dircachesize = iniparser_getint (config, INISEC_AFP, "dircachesize", DEFAULT_MAX_DIRCACHE_SIZE); - options->tcp_sndbuf = iniparser_getint (config, INISEC_AFP, "tcpsndbuf", 0); - options->tcp_rcvbuf = iniparser_getint (config, INISEC_AFP, "tcprcvbuf", 0); - options->fce_fmodwait = iniparser_getint (config, INISEC_AFP, "fceholdfmod", 60); - options->sleep = iniparser_getint (config, INISEC_AFP, "sleep", 10) * 60 * 2; - options->disconnected = iniparser_getint (config, INISEC_AFP, "disconnect", 24) * 60 * 2; - - if ((p = iniparser_getstring(config, INISEC_AFP, "hostname", NULL))) { - EC_NULL_LOG( options->hostname = strdup(p) ); - } else { - if (gethostname(val, sizeof(val)) < 0 ) { - perror( "gethostname" ); - EC_FAIL; - } - if ((q = strchr(val, '.'))) - *q = '\0'; - options->hostname = strdup(val); - } - - if ((p = iniparser_getstring(config, INISEC_AFP, "k5keytab", NULL))) { - EC_NULL_LOG( options->k5keytab = malloc(strlen(p) + 14) ); - snprintf(options->k5keytab, strlen(p) + 14, "KRB5_KTNAME=%s", p); - putenv(options->k5keytab); - } - -#ifdef ADMIN_GRP - if ((p = iniparser_getstring(config, INISEC_AFP, "admingroup", NULL))) { - struct group *gr = getgrnam(p); - if (gr != NULL) - options->admingid = gr->gr_gid; - } -#endif /* ADMIN_GRP */ - - q = iniparser_getstrdup(config, INISEC_AFP, "cnidserver", "localhost:4700"); - r = strrchr(q, ':'); - if (r) - *r = 0; - options->Cnid_srv = strdup(q); - if (r) - options->Cnid_port = strdup(r + 1); - else - options->Cnid_port = strdup("4700"); - LOG(log_debug, logtype_afpd, "CNID Server: %s:%s", options->Cnid_srv, options->Cnid_port); - if (q) - free(q); - - if ((q = iniparser_getstrdup(config, INISEC_AFP, "fqdn", NULL))) { - /* do a little checking for the domain name. */ - r = strchr(q, ':'); - if (r) - *r = '\0'; - if (gethostbyname(q)) { - if (r) - *r = ':'; - EC_NULL_LOG( options->fqdn = strdup(q) ); - } else { - LOG(log_error, logtype_afpd, "error parsing -fqdn, gethostbyname failed for: %s", c); - } - free(q); - } - - if (!(p = iniparser_getstring(config, INISEC_AFP, "unixcodepage", NULL))) { - options->unixcharset = CH_UNIX; - options->unixcodepage = strdup("LOCALE"); - } else { - if ((options->unixcharset = add_charset(p)) == (charset_t)-1) { - options->unixcharset = CH_UNIX; - options->unixcodepage = strdup("LOCALE"); - LOG(log_warning, logtype_afpd, "Setting Unix codepage to '%s' failed", p); - } else { - options->unixcodepage = strdup(p); - } - } - - if (!(p = iniparser_getstring(config, INISEC_AFP, "maccodepage", NULL))) { - options->maccharset = CH_MAC; - options->maccodepage = strdup("MAC_ROMAN"); - } else { - if ((options->maccharset = add_charset(p)) == (charset_t)-1) { - options->maccharset = CH_MAC; - options->maccodepage = strdup("MAC_ROMAN"); - LOG(log_warning, logtype_afpd, "Setting Unix codepage to '%s' failed", p); - } else { - options->maccodepage = strdup(p); - } - } - - if ((p = iniparser_getstring(config, INISEC_AFP, "fcelistener", NULL))) { - LOG(log_note, logtype_afpd, "Adding FCE listener: %s", p); - fce_add_udp_socket(p); - } - if ((p = iniparser_getstring(config, INISEC_AFP, "fcecoalesce", NULL))) { - LOG(log_note, logtype_afpd, "Fce coalesce: %s", p); - fce_set_coalesce(p); - } - if ((p = iniparser_getstring(config, INISEC_AFP, "fceevents", NULL))) { - LOG(log_note, logtype_afpd, "Fce events: %s", p); - fce_set_events(p); - } - - /* Check for sane values */ - if (options->tickleval <= 0) - options->tickleval = 30; - if (options->timeout <= 0) - options->timeout = 4; - if (options->sleep <= 4) - options->disconnected = options->sleep = 4; - if (options->dsireadbuf < 6) - options->dsireadbuf = 6; - if (options->volnamelen < 8) - options->volnamelen = 8; /* max mangled volname "???#FFFF" */ - if (options->volnamelen > 255) - options->volnamelen = 255; /* AFP3 spec */ - -EC_CLEANUP: - EC_EXIT; -} - /* * Show version information about afpd. * Used by "afp -v". diff --git a/etc/afpd/appl.c b/etc/afpd/appl.c index 59de70e3..379fae22 100644 --- a/etc/afpd/appl.c +++ b/etc/afpd/appl.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "volume.h" #include "directory.h" @@ -481,7 +482,7 @@ int afp_getappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t return( AFPERR_NOITEM ); } buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag ); - if ( getfilparams(vol, bitmap, path, curdir, rbuf + sizeof( bitmap ) + + if ( getfilparams(obj, vol, bitmap, path, curdir, rbuf + sizeof( bitmap ) + sizeof( appltag ), &buflen ) != AFP_OK ) { *rbuflen = 0; return( AFPERR_BITMAP ); diff --git a/etc/afpd/auth.c b/etc/afpd/auth.c index aff77956..d6054f54 100644 --- a/etc/afpd/auth.c +++ b/etc/afpd/auth.c @@ -52,22 +52,6 @@ extern void afp_get_cmdline( int *ac, char ***av ); 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; - 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}; @@ -270,17 +254,17 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi /* Basically if the user is in the admin group, we stay root */ - if (( ngroups = getgroups( 0, NULL )) < 0 ) { + if ((obj->ngroups = getgroups( 0, NULL )) < 0 ) { LOG(log_error, logtype_afpd, "login: %s getgroups: %s", pwd->pw_name, strerror(errno) ); return AFPERR_BADUAM; } - if ( NULL == (groups = calloc(ngroups, GROUPS_SIZE)) ) { - LOG(log_error, logtype_afpd, "login: %s calloc: %d", ngroups); + if ( NULL == (obj->groups = calloc(obj->ngroups, sizeof(gid_t))) ) { + LOG(log_error, logtype_afpd, "login: %s calloc: %d", obj->ngroups); return AFPERR_BADUAM; } - if (( ngroups = getgroups( ngroups, groups )) < 0 ) { + if (( obj->ngroups = getgroups(obj->ngroups, obj->groups )) < 0 ) { LOG(log_error, logtype_afpd, "login: %s getgroups: %s", pwd->pw_name, strerror(errno) ); return AFPERR_BADUAM; } @@ -290,8 +274,8 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi 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) { @@ -342,15 +326,15 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi } #endif /* TRU64 */ - LOG(log_debug, logtype_afpd, "login: supplementary groups: %s", print_groups(ngroups, groups)); + 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); /* save our euid, we need it for preexec_close */ diff --git a/etc/afpd/catsearch.c b/etc/afpd/catsearch.c index ad28c6f6..3a6f4cc9 100644 --- a/etc/afpd/catsearch.c +++ b/etc/afpd/catsearch.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "desktop.h" #include "directory.h" @@ -423,7 +424,7 @@ crit_check_ret: } /* ------------------------------ */ -static int rslt_add ( struct vol *vol, struct path *path, char **buf, int ext) +static int rslt_add (const AFPObj *obj, struct vol *vol, struct path *path, char **buf, int ext) { char *p = *buf; @@ -446,11 +447,11 @@ static int rslt_add ( struct vol *vol, struct path *path, char **buf, int ext) } if ( isdir ) { - ret = getdirparams(vol, c1.dbitmap, path, path->d_dir, p , &tbuf ); + ret = getdirparams(obj, vol, c1.dbitmap, path, path->d_dir, p , &tbuf ); } else { /* FIXME slow if we need the file ID, we already know it, done ? */ - ret = getfilparams ( vol, c1.fbitmap, path, path->d_dir, p, &tbuf); + ret = getfilparams (obj, vol, c1.fbitmap, path, path->d_dir, p, &tbuf); } if ( ret != AFP_OK ) @@ -493,7 +494,8 @@ static int rslt_add ( struct vol *vol, struct path *path, char **buf, int ext) * @param ext (r) extended search flag */ #define NUM_ROUNDS 200 -static int catsearch(struct vol *vol, +static int catsearch(const AFPObj *obj, + struct vol *vol, struct dir *dir, int rmatches, uint32_t *pos, @@ -644,7 +646,7 @@ static int catsearch(struct vol *vol, /* bit 0 means that criteria has been met */ if ((ccr & 1)) { - r = rslt_add ( vol, &path, &rrbuf, ext); + r = rslt_add (obj, vol, &path, &rrbuf, ext); if (r == 0) { result = AFPERR_MISC; @@ -706,7 +708,8 @@ catsearch_end: /* Exiting catsearch: error condition */ * @param rsize (w) length of data written to output buffer * @param ext (r) extended search flag */ -static int catsearch_db(struct vol *vol, +static int catsearch_db(const AFPObj *obj, + struct vol *vol, struct dir *dir, const char *uname, int rmatches, @@ -810,7 +813,7 @@ static int catsearch_db(struct vol *vol, LOG(log_debug, logtype_afpd,"catsearch_db: match: %s/%s", getcwdpath(), path.u_name); /* bit 1 means that criteria has been met */ - r = rslt_add(vol, &path, &rrbuf, ext); + r = rslt_add(obj, vol, &path, &rrbuf, ext); if (r == 0) { result = AFPERR_MISC; goto catsearch_end; @@ -1050,10 +1053,10 @@ static int catsearch_afp(AFPObj *obj _U_, char *ibuf, size_t ibuflen, && (strcmp(vol->v_cnidscheme, "dbd") == 0) && (vol->v_flags & AFPVOL_SEARCHDB)) /* we've got a name and it's a dbd volume, so search CNID database */ - ret = catsearch_db(vol, vol->v_root, uname, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize, ext); + ret = catsearch_db(obj, vol, vol->v_root, uname, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize, ext); else /* perform a slow filesystem tree search */ - ret = catsearch(vol, vol->v_root, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize, ext); + ret = catsearch(obj, vol, vol->v_root, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize, ext); memcpy(rbuf, catpos, sizeof(catpos)); rbuf += sizeof(catpos); diff --git a/etc/afpd/desktop.c b/etc/afpd/desktop.c index 258f3e5f..afcf4178 100644 --- a/etc/afpd/desktop.c +++ b/etc/afpd/desktop.c @@ -28,6 +28,8 @@ #include #include #include +#include + #include "volume.h" #include "directory.h" #include "fork.h" @@ -618,7 +620,7 @@ utompath_error: } /* ------------------------- */ -static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf) +static int ad_addcomment(const AFPObj *obj, struct vol *vol, struct path *path, char *ibuf) { struct ofork *of; char *name, *upath; @@ -630,7 +632,7 @@ static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf) clen = min( clen, 199 ); upath = path->u_name; - if (check_access(upath, OPENACC_WR ) < 0) { + if (check_access(obj, vol, upath, OPENACC_WR ) < 0) { return AFPERR_ACCESS; } @@ -665,7 +667,7 @@ static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf) } /* ----------------------------- */ -int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +int afp_addcomment(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { struct vol *vol; struct dir *dir; @@ -696,7 +698,7 @@ int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _ ibuf++; } - return ad_addcomment(vol, path, ibuf); + return ad_addcomment(obj, vol, path, ibuf); } /* -------------------- */ @@ -774,7 +776,7 @@ int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, } /* ----------------------- */ -static int ad_rmvcomment(struct vol *vol, struct path *path) +static int ad_rmvcomment(const AFPObj *obj, struct vol *vol, struct path *path) { struct adouble ad, *adp; struct ofork *of; @@ -782,7 +784,7 @@ static int ad_rmvcomment(struct vol *vol, struct path *path) char *upath; upath = path->u_name; - if (check_access(upath, OPENACC_WR ) < 0) { + if (check_access(obj, vol, upath, OPENACC_WR ) < 0) { return AFPERR_ACCESS; } @@ -840,5 +842,5 @@ int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _ return get_afp_errno(AFPERR_NOOBJ); } - return ad_rmvcomment(vol, s_path); + return ad_rmvcomment(obj, vol, s_path); } diff --git a/etc/afpd/dircache.h b/etc/afpd/dircache.h index 42466d2d..0b79da01 100644 --- a/etc/afpd/dircache.h +++ b/etc/afpd/dircache.h @@ -21,7 +21,6 @@ #include /* Maximum size of the dircache hashtable */ -#define DEFAULT_MAX_DIRCACHE_SIZE 8192 #define MAX_POSSIBLE_DIRCACHE_SIZE 131072 #define DIRCACHE_FREE_QUANTUM 256 diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index 905c3bd9..844d346a 100644 --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "directory.h" #include "dircache.h" @@ -1413,11 +1414,8 @@ int movecwd(const struct vol *vol, struct dir *dir) * If we aren't the file's owner we can't change its perms when moving it and smb * nfs,... don't even try. */ -#define AFP_CHECK_ACCESS - -int check_access(char *path, int mode) +int check_access(const AFPObj *obj, struct vol *vol, char *path, int mode) { -#ifdef AFP_CHECK_ACCESS struct maccess ma; char *p; @@ -1425,21 +1423,21 @@ int check_access(char *path, int mode) if (!p) return -1; - accessmode(current_vol, p, &ma, curdir, NULL); + accessmode(obj, vol, p, &ma, curdir, NULL); if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE)) return -1; if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD)) return -1; -#endif + return 0; } /* --------------------- */ -int file_access(struct path *path, int mode) +int file_access(const AFPObj *obj, struct vol *vol, struct path *path, int mode) { struct maccess ma; - accessmode(current_vol, path->u_name, &ma, curdir, &path->st); + accessmode(obj, vol, path->u_name, &ma, curdir, &path->st); LOG(log_debug, logtype_afpd, "file_access(\"%s\"): mapped user mode: 0x%02x", path->u_name, ma.ma_user); @@ -1478,7 +1476,8 @@ int dirreenumerate(struct dir *dir, struct stat *st) (name, dir) with curdir:name == dir, from afp_enumerate */ -int getdirparams(const struct vol *vol, +int getdirparams(const AFPObj *obj, + const struct vol *vol, uint16_t bitmap, struct path *s_path, struct dir *dir, char *buf, size_t *buflen ) @@ -1643,7 +1642,7 @@ int getdirparams(const struct vol *vol, break; case DIRPBIT_ACCESS : - accessmode(vol, upath, &ma, dir , st); + accessmode(obj, vol, upath, &ma, dir , st); *data++ = ma.ma_user; *data++ = ma.ma_world; @@ -1679,7 +1678,7 @@ int getdirparams(const struct vol *vol, case DIRPBIT_UNIXPR : /* accessmode may change st_mode with ACLs */ - accessmode(vol, upath, &ma, dir, st); + accessmode(obj, vol, upath, &ma, dir, st); aint = htonl(st->st_uid); memcpy( data, &aint, sizeof( aint )); diff --git a/etc/afpd/directory.h b/etc/afpd/directory.h index 533d30f9..0ef2426e 100644 --- a/etc/afpd/directory.h +++ b/etc/afpd/directory.h @@ -111,8 +111,7 @@ extern struct path *cname (struct vol *, struct dir *, char **); extern int deletecurdir (struct vol *); extern mode_t mtoumode (struct maccess *); -extern void utommode (struct stat *, struct maccess *); -extern int getdirparams (const struct vol *, uint16_t, struct path *, +extern int getdirparams (const AFPObj *obj, const struct vol *, uint16_t, struct path *, struct dir *, char *, size_t *); extern int setdirparams(struct vol *, struct path *, uint16_t, char *); @@ -122,8 +121,8 @@ extern int path_error(struct path *, int error); extern void setdiroffcnt(struct dir *dir, struct stat *st, uint32_t count); extern int dirreenumerate(struct dir *dir, struct stat *st); extern int for_each_dirent(const struct vol *, char *, dir_loop , void *); -extern int check_access(char *name , int mode); -extern int file_access(struct path *path, int mode); +extern int check_access(const AFPObj *obj, struct vol *, char *name , int mode); +extern int file_access(const AFPObj *obj, struct vol *vol, struct path *path, int mode); extern int netatalk_unlink (const char *name); extern int caseenumerate (const struct vol *, struct path *, struct dir *); diff --git a/etc/afpd/enumerate.c b/etc/afpd/enumerate.c index 1a44aa7f..80759a43 100644 --- a/etc/afpd/enumerate.c +++ b/etc/afpd/enumerate.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "desktop.h" #include "directory.h" @@ -386,7 +387,7 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, return AFPERR_MISC; } } - if ((ret = getdirparams(vol, dbitmap, &s_path, dir, data + header , &esz)) != AFP_OK) + if ((ret = getdirparams(obj, vol, dbitmap, &s_path, dir, data + header , &esz)) != AFP_OK) return( ret ); } else { @@ -394,8 +395,8 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, continue; } /* files are added to the dircache in getfilparams() -> getmetadata() */ - if (AFP_OK != ( ret = getfilparams(vol, fbitmap, &s_path, curdir, - data + header , &esz )) ) { + if (AFP_OK != ( ret = getfilparams(obj, vol, fbitmap, &s_path, curdir, + data + header , &esz )) ) { return( ret ); } } diff --git a/etc/afpd/file.c b/etc/afpd/file.c index ce2ab545..07813ef4 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "directory.h" #include "dircache.h" @@ -274,10 +275,11 @@ exit: } /* -------------------------- */ -int getmetadata(struct vol *vol, - uint16_t bitmap, - struct path *path, struct dir *dir, - char *buf, size_t *buflen, struct adouble *adp) +int getmetadata(const AFPObj *obj, + struct vol *vol, + uint16_t bitmap, + struct path *path, struct dir *dir, + char *buf, size_t *buflen, struct adouble *adp) { char *data, *l_nameoff = NULL, *upath; char *utf_nameoff = NULL; @@ -536,7 +538,7 @@ int getmetadata(struct vol *vol, break; case FILPBIT_UNIXPR : /* accessmode may change st_mode with ACLs */ - accessmode(vol, upath, &ma, dir , st); + accessmode(obj, vol, upath, &ma, dir , st); aint = htonl(st->st_uid); memcpy( data, &aint, sizeof( aint )); @@ -589,7 +591,8 @@ int getmetadata(struct vol *vol, } /* ----------------------- */ -int getfilparams(struct vol *vol, +int getfilparams(const AFPObj *obj, + struct vol *vol, uint16_t bitmap, struct path *path, struct dir *dir, char *buf, size_t *buflen ) @@ -627,7 +630,7 @@ int getfilparams(struct vol *vol, } } } - rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp); + rc = getmetadata(obj, vol, bitmap, path, dir, buf, buflen, adp); ad_close(adp, ADFLAGS_HF | flags); return( rc ); @@ -784,7 +787,7 @@ int afp_setfilparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ ibuf++; } - if (AFP_OK == ( rc = setfilparams(vol, s_path, bitmap, ibuf )) ) { + if (AFP_OK == ( rc = setfilparams(obj, vol, s_path, bitmap, ibuf )) ) { setvoltime(obj, vol ); } @@ -797,7 +800,7 @@ int afp_setfilparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ */ extern struct path Cur_Path; -int setfilparams(struct vol *vol, +int setfilparams(const AFPObj *obj, struct vol *vol, struct path *path, uint16_t f_bitmap, char *buf ) { struct adouble ad, *adp; @@ -828,7 +831,7 @@ int setfilparams(struct vol *vol, adp = of_ad(vol, path, &ad); upath = path->u_name; - if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) { + if (!vol_unix_priv(vol) && check_access(obj, vol, upath, OPENACC_WR ) < 0) { return AFPERR_ACCESS; } @@ -1768,8 +1771,8 @@ retry: return AFPERR_NOID; } path.id = cnid; - if (AFP_OK != (err = getfilparams(vol, bitmap, &path , curdir, - rbuf + sizeof(bitmap), &buflen))) { + if (AFP_OK != (err = getfilparams(obj, vol, bitmap, &path , curdir, + rbuf + sizeof(bitmap), &buflen))) { return err; } *rbuflen = buflen + sizeof(bitmap); @@ -1862,7 +1865,7 @@ delete: } /* ------------------------------ */ -static struct adouble *find_adouble(struct path *path, struct ofork **of, struct adouble *adp) +static struct adouble *find_adouble(const AFPObj *obj, struct vol *vol, struct path *path, struct ofork **of, struct adouble *adp) { int ret; @@ -1884,7 +1887,7 @@ static struct adouble *find_adouble(struct path *path, struct ofork **of, struct /* we use file_access both for legacy Mac perm and * for unix privilege, rename will take care of folder perms */ - if (file_access(path, OPENACC_WR ) < 0) { + if (file_access(obj, vol, path, OPENACC_WR ) < 0) { afp_errno = AFPERR_ACCESS; return NULL; } @@ -1980,7 +1983,7 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U } ad_init(&ads, vol); - if (!(adsp = find_adouble( path, &s_of, &ads))) { + if (!(adsp = find_adouble(obj, vol, path, &s_of, &ads))) { return afp_errno; } @@ -2013,7 +2016,7 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U } ad_init(&add, vol); - if (!(addp = find_adouble( path, &d_of, &add))) { + if (!(addp = find_adouble(obj, vol, path, &d_of, &add))) { err = afp_errno; goto err_exchangefile; } diff --git a/etc/afpd/file.h b/etc/afpd/file.h index 76485a3f..937395e5 100644 --- a/etc/afpd/file.h +++ b/etc/afpd/file.h @@ -108,15 +108,15 @@ extern char *set_name (const struct vol *, char *, cnid_t, char *, cnid_t, uin extern struct extmap *getextmap (const char *); extern struct extmap *getdefextmap (void); -extern int getfilparams (struct vol *, uint16_t, struct path *, +extern int getfilparams (const AFPObj *obj, struct vol *, uint16_t, struct path *, struct dir *, char *buf, size_t *); -extern int setfilparams (struct vol *, struct path *, uint16_t, char *); +extern int setfilparams (const AFPObj *obj, struct vol *, struct path *, uint16_t, char *); extern int renamefile (const struct vol *, int, char *, char *, char *, struct adouble *); extern int copyfile (const struct vol *, const struct vol *, int, char *, char *, char *, struct adouble *); extern int deletefile (const struct vol *, int, char *, int); -extern int getmetadata (struct vol *vol, uint16_t bitmap, struct path *path, +extern int getmetadata (const AFPObj *obj, struct vol *vol, uint16_t bitmap, struct path *path, struct dir *dir, char *buf, size_t *buflen, struct adouble *adp); extern void *get_finderinfo (const struct vol *, const char *, struct adouble *, void *, int); diff --git a/etc/afpd/filedir.c b/etc/afpd/filedir.c index d41a439e..e4b88d95 100644 --- a/etc/afpd/filedir.c +++ b/etc/afpd/filedir.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "directory.h" #include "dircache.h" @@ -103,7 +104,7 @@ int afp_getfildirparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *r if (!dir) return AFPERR_NOOBJ; - ret = getdirparams(vol, dbitmap, s_path, dir, + ret = getdirparams(obj, vol, dbitmap, s_path, dir, rbuf + 3 * sizeof( uint16_t ), &buflen ); if (ret != AFP_OK ) return( ret ); @@ -111,7 +112,7 @@ int afp_getfildirparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *r /* this is a directory */ *(rbuf + 2 * sizeof( uint16_t )) = (char) FILDIRBIT_ISDIR; } else { - if (fbitmap && AFP_OK != (ret = getfilparams(vol, fbitmap, s_path, curdir, + if (fbitmap && AFP_OK != (ret = getfilparams(obj, vol, fbitmap, s_path, curdir, rbuf + 3 * sizeof( uint16_t ), &buflen )) ) { return( ret ); } @@ -188,7 +189,7 @@ int afp_setfildirparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf if (S_ISDIR(st->st_mode)) { rc = setdirparams(vol, path, bitmap, ibuf ); } else { - rc = setfilparams(vol, path, bitmap, ibuf ); + rc = setfilparams(obj, vol, path, bitmap, ibuf ); } if ( rc == AFP_OK ) { setvoltime(obj, vol ); diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index 89f15e18..3f8018d0 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "fork.h" #include "file.h" @@ -35,7 +36,7 @@ struct ofork *writtenfork; #endif -static int getforkparams(struct ofork *ofork, uint16_t bitmap, char *buf, size_t *buflen) +static int getforkparams(const AFPObj *obj, struct ofork *ofork, uint16_t bitmap, char *buf, size_t *buflen) { struct path path; struct stat *st; @@ -84,7 +85,7 @@ static int getforkparams(struct ofork *ofork, uint16_t bitmap, char *buf, size_t } } } - return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp ); + return getmetadata(obj, vol, bitmap, &path, dir, buf, buflen, adp ); } static off_t get_off_t(char **ibuf, int is64) @@ -281,11 +282,11 @@ int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si /* FIXME should we check it first ? */ upath = s_path->u_name; if (!vol_unix_priv(vol)) { - if (check_access(upath, access ) < 0) { + if (check_access(obj, vol, upath, access ) < 0) { return AFPERR_ACCESS; } } else { - if (file_access(s_path, access ) < 0) { + if (file_access(obj, vol, s_path, access ) < 0) { return AFPERR_ACCESS; } } @@ -417,7 +418,7 @@ int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si } } - if ((ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof(int16_t), &buflen)) != AFP_OK) { + if ((ret = getforkparams(obj, ofork, bitmap, rbuf + 2 * sizeof(int16_t), &buflen)) != AFP_OK) { ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD); goto openfork_err; } @@ -1281,7 +1282,7 @@ int afp_write_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *r } /* ---------------------------- */ -int afp_getforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +int afp_getforkparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) { struct ofork *ofork; int ret; @@ -1307,7 +1308,7 @@ int afp_getforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbu } } - if (AFP_OK != (ret = getforkparams(ofork, bitmap, rbuf + sizeof( u_short ), &buflen ))) { + if (AFP_OK != (ret = getforkparams(obj, ofork, bitmap, rbuf + sizeof( u_short ), &buflen ))) { return( ret ); } diff --git a/etc/afpd/main.c b/etc/afpd/main.c index f49daf6f..ca35cc8d 100644 --- a/etc/afpd/main.c +++ b/etc/afpd/main.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "afp_config.h" #include "status.h" @@ -238,6 +239,9 @@ int main(int ac, char **av) if (afp_config_parse(&obj) != 0) exit(EXITERR_CONF); + set_processname("afpd"); + setuplog(obj.options.logconfig, obj.options.logfile); + /* Save the user's current umask */ obj.options.save_mask = umask(obj.options.umask); diff --git a/etc/afpd/quota.c b/etc/afpd/quota.c index 1df5eee5..5887c6d6 100644 --- a/etc/afpd/quota.c +++ b/etc/afpd/quota.c @@ -615,7 +615,7 @@ static int getfsquota(struct vol *vol, const int uid, struct dqblk *dq) } -static int getquota( struct vol *vol, struct dqblk *dq, const uint32_t bsize) +static int getquota(const AFPObj *obj, struct vol *vol, struct dqblk *dq, const uint32_t bsize) { char *p; @@ -693,8 +693,8 @@ static int getquota( struct vol *vol, struct dqblk *dq, const uint32_t bsize) return getfsquota(vol, uuid, dq); #else /* TRU64 */ - return vol->v_nfs ? getnfsquota(vol, uuid, bsize, dq) : - getfsquota(vol, uuid, dq); + return vol->v_nfs ? getnfsquota(vol, obj->uid, bsize, dq) : + getfsquota(vol, obj->uid, dq); #endif /* TRU64 */ } @@ -753,14 +753,14 @@ static int overquota( struct dqblk *dqblk) #define tobytes(a, b) dbtob((VolSpace) (a)) #endif -int uquota_getvolspace( struct vol *vol, VolSpace *bfree, VolSpace *btotal, const uint32_t bsize) +int uquota_getvolspace(const AFPObj *obj, struct vol *vol, VolSpace *bfree, VolSpace *btotal, const uint32_t bsize) { uint64_t this_bsize; struct dqblk dqblk; this_bsize = bsize; - if (getquota( vol, &dqblk, bsize) != 0 ) { + if (getquota(obj, vol, &dqblk, bsize) != 0 ) { return( AFPERR_PARAM ); } diff --git a/etc/afpd/status.h b/etc/afpd/status.h index 3057b759..343774ae 100644 --- a/etc/afpd/status.h +++ b/etc/afpd/status.h @@ -33,12 +33,6 @@ /* AFPSTATUS_MACHLEN is the number of characters for the MachineType. */ #define AFPSTATUS_MACHLEN 16 - -#define PASSWD_NONE 0 -#define PASSWD_SET (1 << 0) -#define PASSWD_NOSAVE (1 << 1) -#define PASSWD_ALL (PASSWD_SET | PASSWD_NOSAVE) - extern void status_versions (char * /*status*/, const DSI *); extern void status_uams (char * /*status*/, const char * /*authlist*/); extern void status_init (AFPObj *, DSI *dsi); diff --git a/etc/afpd/unix.c b/etc/afpd/unix.c index 21602ab1..397b99fb 100644 --- a/etc/afpd/unix.c +++ b/etc/afpd/unix.c @@ -98,9 +98,9 @@ static int utombits(mode_t bits) /* -------------------------------- cf AFP 3.0 page 63 */ -void utommode(struct stat *stat, struct maccess *ma) +static void utommode(const AFPObj *obj, const struct stat *stat, struct maccess *ma) { -mode_t mode; + mode_t mode; mode = stat->st_mode; ma->ma_world = utombits( mode ); @@ -114,10 +114,10 @@ mode_t mode; /* ma_user is a union of all permissions but we must follow * unix perm */ - if ( (uuid == stat->st_uid) || (uuid == 0)) { + if ( (obj->uid == stat->st_uid) || (obj->uid == 0)) { ma->ma_user = ma->ma_owner | AR_UOWN; } - else if ( gmem( stat->st_gid )) { + else if (gmem(stat->st_gid, obj->ngroups, obj->groups)) { ma->ma_user = ma->ma_group; } else { @@ -152,7 +152,7 @@ mode_t mode; * * dir parameter is used by AFS */ -void accessmode(const struct vol *vol, char *path, struct maccess *ma, struct dir *dir _U_, struct stat *st) +void accessmode(const AFPObj *obj, const struct vol *vol, char *path, struct maccess *ma, struct dir *dir _U_, struct stat *st) { struct stat sb; @@ -162,24 +162,12 @@ void accessmode(const struct vol *vol, char *path, struct maccess *ma, struct di return; st = &sb; } - utommode( st, ma ); + utommode(obj, st, ma ); #ifdef HAVE_ACLS - acltoownermode(vol, path, st, ma); + acltoownermode(obj, vol, path, st, ma); #endif } -int gmem(const gid_t gid) -{ - int i; - - for ( i = 0; i < ngroups; i++ ) { - if ( groups[ i ] == gid ) { - return( 1 ); - } - } - return( 0 ); -} - static mode_t mtoubits(u_char bits) { mode_t mode; diff --git a/etc/afpd/unix.h b/etc/afpd/unix.h index 417acb17..a81391b5 100644 --- a/etc/afpd/unix.h +++ b/etc/afpd/unix.h @@ -207,13 +207,12 @@ extern int getnfsquota (struct vol *, const int, const uint32_t, struct dqblk *); #endif /* ! HAVE_LIBQUOTA */ -extern int uquota_getvolspace (struct vol *, VolSpace *, VolSpace *, +extern int uquota_getvolspace (const AFPObj *obj, struct vol *, VolSpace *, VolSpace *, const uint32_t); #endif /* NO_QUOTA_SUPPORT */ extern struct afp_options default_options; -extern int gmem (const gid_t); extern int setdeskmode (const mode_t); extern int setdirunixmode (const struct vol *, const char *, mode_t); extern int setdirmode (const struct vol *, const char *, mode_t); @@ -221,7 +220,7 @@ extern int setdeskowner (const uid_t, const gid_t); extern int setdirowner (const struct vol *, const char *, const uid_t, const gid_t); extern int setfilunixmode (const struct vol *, struct path*, const mode_t); extern int setfilowner (const struct vol *, const uid_t, const gid_t, struct path*); -extern void accessmode (const struct vol *, char *, struct maccess *, struct dir *, struct stat *); +extern void accessmode (const AFPObj *obj, const struct vol *, char *, struct maccess *, struct dir *, struct stat *); #ifdef AFS #define accessmode afsmode diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c index 1c6f112a..a8b0754d 100644 --- a/etc/afpd/volume.c +++ b/etc/afpd/volume.c @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef CNID_DB #include @@ -53,54 +54,9 @@ #include "hash.h" #include "acls.h" -extern int afprun(int root, char *cmd, int *outfd); - -/* Globals */ -struct vol *current_vol; /* last volume from getvolbyvid() */ - -static struct vol *Volumes = NULL; -static uint16_t lastvid = 0; -static char *Trash = "\02\024Network Trash Folder"; - -#define VOLOPT_ALLOW 0 /* user allow list */ -#define VOLOPT_DENY 1 /* user deny list */ -#define VOLOPT_RWLIST 2 /* user rw list */ -#define VOLOPT_ROLIST 3 /* user ro list */ -#define VOLOPT_PASSWORD 4 /* volume password */ -#define VOLOPT_CASEFOLD 5 /* character case mangling */ -#define VOLOPT_FLAGS 6 /* various flags */ -#define VOLOPT_DBPATH 7 /* path to database */ -#define VOLOPT_LIMITSIZE 8 /* Limit the size of the volume */ -/* Usable slot: 9 */ -#define VOLOPT_VETO 10 /* list of veto filespec */ -#define VOLOPT_PREEXEC 11 /* preexec command */ -#define VOLOPT_ROOTPREEXEC 12 /* root preexec command */ -#define VOLOPT_POSTEXEC 13 /* postexec command */ -#define VOLOPT_ROOTPOSTEXEC 14 /* root postexec command */ -#define VOLOPT_ENCODING 15 /* mac encoding (pre OSX)*/ -#define VOLOPT_MACCHARSET 16 -#define VOLOPT_CNIDSCHEME 17 -#define VOLOPT_ADOUBLE 18 /* adouble version */ -/* Usable slot: 19/20 */ -#define VOLOPT_UMASK 21 -#define VOLOPT_ALLOWED_HOSTS 22 -#define VOLOPT_DENIED_HOSTS 23 -#define VOLOPT_DPERM 24 /* dperm default directories perms */ -#define VOLOPT_FPERM 25 /* fperm default files perms */ -#define VOLOPT_DFLTPERM 26 /* perm */ -#define VOLOPT_EA_VFS 27 /* Extended Attributes vfs indirection */ -#define VOLOPT_CNIDSERVER 28 /* CNID Server ip address*/ -#define VOLOPT_CNIDPORT 30 /* CNID server tcp port */ - -#define VOLOPT_MAX 31 /* <== IMPORTANT !!!!!! */ -#define VOLOPT_NUM (VOLOPT_MAX + 1) - #define VOLPASSLEN 8 -struct vol_option { - char *c_value; - int i_value; -}; +extern int afprun(int root, char *cmd, int *outfd); typedef struct _special_folder { const char *name; @@ -110,359 +66,17 @@ typedef struct _special_folder { } _special_folder; static const _special_folder special_folders[] = { - {"Network Trash Folder", 1, 0777, 1}, {".AppleDesktop", 1, 0777, 0}, {NULL, 0, 0, 0}}; /* Forward declarations */ static void handle_special_folders (const struct vol *); -static void deletevol(struct vol *vol); -static void volume_free(struct vol *vol); -static void check_ea_support(struct vol *vol); -static char *get_vol_uuid(const AFPObj *obj, const char *volname); - -static void volfree(struct vol_option *options, const struct vol_option *save) -{ - int i; - - if (save) { - for (i = 0; i < VOLOPT_MAX; i++) { - if (options[i].c_value && (options[i].c_value != save[i].c_value)) - free(options[i].c_value); - } - } else { - for (i = 0; i < VOLOPT_MAX; i++) { - if (options[i].c_value) - free(options[i].c_value); - } - } -} - - -#define is_var(a, b) (strncmp((a), (b), 2) == 0) - -/* - * Handle variable substitutions. here's what we understand: - * $b -> basename of path - * $c -> client ip/appletalk address - * $d -> volume pathname on server - * $f -> full name (whatever's in the gecos field) - * $g -> group - * $h -> hostname - * $i -> client ip/appletalk address without port - * $s -> server name (hostname if it doesn't exist) - * $u -> username (guest is usually nobody) - * $v -> volume name or basename if null - * $$ -> $ - * - * This get's called from readvolfile with - * path = NULL, volname = NULL for xlating the volumes path - * path = path, volname = NULL for xlating the volumes name - * ... and from volumes options parsing code when xlating eg dbpath with - * path = path, volname = volname - * - * Using this information we can reject xlation of any variable depeninding on a login - * context which is not given in the afp master, where we must evaluate this whole stuff - * too for the Zeroconf announcements. - */ -static char *volxlate(AFPObj *obj, - char *dest, - size_t destlen, - char *src, - struct passwd *pwd, - char *path, - char *volname) -{ - char *p, *r; - const char *q; - int len; - char *ret; - int afpmaster = 0; - int xlatevolname = 0; - - if (parent_or_child == 0) - afpmaster = 1; - - if (path && !volname) - /* cf above */ - xlatevolname = 1; - - if (!src) { - return NULL; - } - if (!dest) { - dest = calloc(destlen +1, 1); - } - ret = dest; - if (!ret) { - return NULL; - } - strlcpy(dest, src, destlen +1); - if ((p = strchr(src, '$')) == NULL) /* nothing to do */ - return ret; - - /* first part of the path. just forward to the next variable. */ - len = MIN((size_t)(p - src), destlen); - if (len > 0) { - destlen -= len; - dest += len; - } - - while (p && destlen > 0) { - /* now figure out what the variable is */ - q = NULL; - if (is_var(p, "$b")) { - if (afpmaster && xlatevolname) - return NULL; - if (path) { - if ((q = strrchr(path, '/')) == NULL) - q = path; - else if (*(q + 1) != '\0') - q++; - } - } else if (is_var(p, "$c")) { - if (afpmaster && xlatevolname) - return NULL; - DSI *dsi = obj->dsi; - len = sprintf(dest, "%s:%u", - getip_string((struct sockaddr *)&dsi->client), - getip_port((struct sockaddr *)&dsi->client)); - dest += len; - destlen -= len; - } else if (is_var(p, "$d")) { - if (afpmaster && xlatevolname) - return NULL; - q = path; - } else if (pwd && is_var(p, "$f")) { - if (afpmaster && xlatevolname) - return NULL; - if ((r = strchr(pwd->pw_gecos, ','))) - *r = '\0'; - q = pwd->pw_gecos; - } else if (pwd && is_var(p, "$g")) { - if (afpmaster && xlatevolname) - return NULL; - struct group *grp = getgrgid(pwd->pw_gid); - if (grp) - q = grp->gr_name; - } else if (is_var(p, "$h")) { - q = obj->options.hostname; - } else if (is_var(p, "$i")) { - if (afpmaster && xlatevolname) - return NULL; - DSI *dsi = obj->dsi; - q = getip_string((struct sockaddr *)&dsi->client); - } else if (is_var(p, "$s")) { - q = obj->options.hostname; - } else if (obj->username && is_var(p, "$u")) { - if (afpmaster && xlatevolname) - return NULL; - char* sep = NULL; - if ( obj->options.ntseparator && (sep = strchr(obj->username, obj->options.ntseparator[0])) != NULL) - q = sep+1; - else - q = obj->username; - } else if (is_var(p, "$v")) { - if (afpmaster && xlatevolname) - return NULL; - if (volname) { - q = volname; - } - else if (path) { - if ((q = strrchr(path, '/')) == NULL) - q = path; - else if (*(q + 1) != '\0') - q++; - } - } else if (is_var(p, "$$")) { - q = "$"; - } else - q = p; - - /* copy the stuff over. if we don't understand something that we - * should, just skip it over. */ - if (q) { - len = MIN(p == q ? 2 : strlen(q), destlen); - strncpy(dest, q, len); - dest += len; - destlen -= len; - } - - /* stuff up to next $ */ - src = p + 2; - p = strchr(src, '$'); - len = p ? MIN((size_t)(p - src), destlen) : destlen; - if (len > 0) { - strncpy(dest, src, len); - dest += len; - destlen -= len; - } - } - return ret; -} - -/* -------------------- */ -static void setoption(struct vol_option *options, const struct vol_option *save, int opt, const char *val) -{ - if (options[opt].c_value && (!save || options[opt].c_value != save[opt].c_value)) - free(options[opt].c_value); - options[opt].c_value = strdup(val); -} - -/* Parse iniconfig and initalize volume options */ -static void volset(const dictionary *conf, const char *vol, struct vol_option *options, const struct vol_option *save) -{ - const char *val; - char *p, *q; - - if (val = iniparser_getstring(conf, vol, "allow", NULL)) - setoption(options, save, VOLOPT_ALLOW, val); - - if (val = iniparser_getstring(conf, vol, "deny", NULL)) - setoption(options, save, VOLOPT_DENY, val); - - if (val = iniparser_getstring(conf, vol, "rwlist", NULL)) - setoption(options, save, VOLOPT_RWLIST, val); - - if (val = iniparser_getstring(conf, vol, "rolist", NULL)) - setoption(options, save, VOLOPT_ROLIST, val); - - if (val = iniparser_getstring(conf, vol, "volcharset", NULL)) - setoption(options, save, VOLOPT_ENCODING, val); - - if (val = iniparser_getstring(conf, vol, "maccharset", NULL)) - setoption(options, save, VOLOPT_MACCHARSET, val); - - if (val = iniparser_getstring(conf, vol, "veto", NULL)) - setoption(options, save, VOLOPT_VETO, val); - - if (val = iniparser_getstring(conf, vol, "cnidscheme", NULL)) - setoption(options, save, VOLOPT_CNIDSCHEME, val); - - if (val = iniparser_getstring(conf, vol, "dbpath", NULL)) - setoption(options, save, VOLOPT_DBPATH, val); - - if (val = iniparser_getstring(conf, vol, "password", NULL)) - setoption(options, save, VOLOPT_PASSWORD, val); - - if (val = iniparser_getstring(conf, vol, "root_preexec", NULL)) - setoption(options, save, VOLOPT_ROOTPREEXEC, val); - - if (val = iniparser_getstring(conf, vol, "preexec", NULL)) - setoption(options, save, VOLOPT_PREEXEC, val); - - if (val = iniparser_getstring(conf, vol, "root_postexec", NULL)) - setoption(options, save, VOLOPT_ROOTPOSTEXEC, val); - - if (val = iniparser_getstring(conf, vol, "postexec", NULL)) - setoption(options, save, VOLOPT_POSTEXEC, val); - - if (val = iniparser_getstring(conf, vol, "allowed_hosts", NULL)) - setoption(options, save, VOLOPT_ALLOWED_HOSTS, val); - - if (val = iniparser_getstring(conf, vol, "denied_hosts", NULL)) - setoption(options, save, VOLOPT_DENIED_HOSTS, val); - if (val = iniparser_getstring(conf, vol, "umask", NULL)) - options[VOLOPT_UMASK].i_value = (int)strtol(val, NULL, 8); - - if (val = iniparser_getstring(conf, vol, "dperm", NULL)) - options[VOLOPT_DPERM].i_value = (int)strtol(val, NULL, 8); - - if (val = iniparser_getstring(conf, vol, "fperm", NULL)) - options[VOLOPT_FPERM].i_value = (int)strtol(val, NULL, 8); - - if (val = iniparser_getstring(conf, vol, "perm", NULL)) - options[VOLOPT_DFLTPERM].i_value = (int)strtol(val, NULL, 8); - - if (val = iniparser_getstring(conf, vol, "volsizelimit", NULL)) - options[VOLOPT_LIMITSIZE].i_value = (uint32_t)strtoul(val, NULL, 10); - - if (val = iniparser_getstring(conf, vol, "casefold", NULL)) { - if (strcasecmp(val, "tolower") == 0) - options[VOLOPT_CASEFOLD].i_value = AFPVOL_UMLOWER; - else if (strcasecmp(val, "toupper") == 0) - options[VOLOPT_CASEFOLD].i_value = AFPVOL_UMUPPER; - else if (strcasecmp(val, "xlatelower") == 0) - options[VOLOPT_CASEFOLD].i_value = AFPVOL_UUPPERMLOWER; - else if (strcasecmp(val, "xlateupper") == 0) - options[VOLOPT_CASEFOLD].i_value = AFPVOL_ULOWERMUPPER; - } - - if (val = iniparser_getstring(conf, vol, "adouble", NULL)) { - if (strcasecmp(val, "v2") == 0) - options[VOLOPT_ADOUBLE].i_value = AD_VERSION2; - else if (strcasecmp(val, "ea") == 0) - options[VOLOPT_ADOUBLE].i_value = AD_VERSION_EA; - } - - if (val = iniparser_getstring(conf, vol, "ea", NULL)) { - if (strcasecmp(val, "ad") == 0) - options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_AD; - else if (strcasecmp(val, "sys") == 0) - options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_SYS; - else if (strcasecmp(val, "none") == 0) - options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_NONE; - } - - if (p = iniparser_getstrdup(conf, vol, "cnidserver", NULL)) { - if (q = strrchr(val, ':')) { - *q = 0; - setoption(options, save, VOLOPT_CNIDPORT, q + 1); - } - setoption(options, save, VOLOPT_CNIDSERVER, p); - LOG(log_debug, logtype_afpd, "CNID Server for volume '%s': %s:%s", - vol, p, q ? q + 1 : "4700"); - free(p); - } - - if (q = iniparser_getstrdup(conf, vol, "options", NULL)) { - if (p = strtok(q, ", ")) { - while (p) { - if (strcasecmp(p, "ro") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_RO; - else if (strcasecmp(p, "nohex") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_NOHEX; - else if (strcasecmp(p, "nousedots") == 0) - options[VOLOPT_FLAGS].i_value &= ~AFPVOL_USEDOTS; - else if (strcasecmp(p, "invisibledots") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_USEDOTS; - else if (strcasecmp(p, "nostat") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_NOSTAT; - else if (strcasecmp(p, "preexec_close") == 0) - options[VOLOPT_PREEXEC].i_value = 1; - else if (strcasecmp(p, "root_preexec_close") == 0) - options[VOLOPT_ROOTPREEXEC].i_value = 1; - else if (strcasecmp(p, "noupriv") == 0) - options[VOLOPT_FLAGS].i_value &= ~AFPVOL_UNIX_PRIV; - else if (strcasecmp(p, "nodev") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_NODEV; - else if (strcasecmp(p, "caseinsensitive") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_CASEINSEN; - else if (strcasecmp(p, "illegalseq") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_EILSEQ; - else if (strcasecmp(p, "tm") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_TM; - else if (strcasecmp(p, "searchdb") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_SEARCHDB; - else if (strcasecmp(p, "nonetids") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_NONETIDS; - else if (strcasecmp(p, "noacls") == 0) - options[VOLOPT_FLAGS].i_value &= ~AFPVOL_ACLS; - else if (strcasecmp(p, "nov2toeaconv") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_NOV2TOEACONV; - p = strtok(NULL, ","); - } - } - free(q); - } -} - -/* ----------------- */ static void showvol(const ucs2_t *name) { - struct vol *volume; - for ( volume = Volumes; volume; volume = volume->v_next ) { + struct vol *volume = getvolumes(); + + for ( ; volume; volume = volume->v_next ) { if (volume->v_hide && !strcasecmp_w( volume->v_name, name ) ) { volume->v_hide = 0; return; @@ -470,625 +84,37 @@ static void showvol(const ucs2_t *name) } } -/* ------------------------------- */ -static int creatvol(AFPObj *obj, struct passwd *pwd, - char *path, char *name, - struct vol_option *options) -{ - struct vol *volume; - int suffixlen, vlen, tmpvlen, u8mvlen, macvlen; - int hide = 0; - char tmpname[AFPVOL_U8MNAMELEN+1]; - ucs2_t u8mtmpname[(AFPVOL_U8MNAMELEN+1)*2], mactmpname[(AFPVOL_MACNAMELEN+1)*2]; - char suffix[6]; /* max is #FFFF */ - uint16_t flags; - - LOG(log_debug, logtype_afpd, "createvol: Volume '%s'", name); - - if ( name == NULL || *name == '\0' ) { - if ((name = strrchr( path, '/' )) == NULL) { - return -1; /* Obviously not a fully qualified path */ - } - - /* if you wish to share /, you need to specify a name. */ - if (*++name == '\0') - return -1; - } - - /* suffix for mangling use (lastvid + 1) */ - /* because v_vid has not been decided yet. */ - suffixlen = sprintf(suffix, "%c%X", MANGLE_CHAR, lastvid + 1 ); - - vlen = strlen( name ); - - /* Unicode Volume Name */ - /* Firstly convert name from unixcharset to UTF8-MAC */ - flags = CONV_IGNORE; - tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags); - if (tmpvlen <= 0) { - strcpy(tmpname, "???"); - tmpvlen = 3; - } - - /* Do we have to mangle ? */ - if ( (flags & CONV_REQMANGLE) || (tmpvlen > obj->options.volnamelen)) { - if (tmpvlen + suffixlen > obj->options.volnamelen) { - flags = CONV_FORCE; - tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, obj->options.volnamelen - suffixlen, &flags); - tmpname[tmpvlen >= 0 ? tmpvlen : 0] = 0; - } - strcat(tmpname, suffix); - tmpvlen = strlen(tmpname); - } - - /* Secondly convert name from UTF8-MAC to UCS2 */ - if ( 0 >= ( u8mvlen = convert_string(CH_UTF8_MAC, CH_UCS2, tmpname, tmpvlen, u8mtmpname, AFPVOL_U8MNAMELEN*2)) ) - return -1; - - LOG(log_maxdebug, logtype_afpd, "createvol: Volume '%s' -> UTF8-MAC Name: '%s'", name, tmpname); - - /* Maccharset Volume Name */ - /* Firsty convert name from unixcharset to maccharset */ - flags = CONV_IGNORE; - tmpvlen = convert_charset(obj->options.unixcharset, obj->options.maccharset, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags); - if (tmpvlen <= 0) { - strcpy(tmpname, "???"); - tmpvlen = 3; - } - - /* Do we have to mangle ? */ - if ( (flags & CONV_REQMANGLE) || (tmpvlen > AFPVOL_MACNAMELEN)) { - if (tmpvlen + suffixlen > AFPVOL_MACNAMELEN) { - flags = CONV_FORCE; - tmpvlen = convert_charset(obj->options.unixcharset, - obj->options.maccharset, - 0, - name, - vlen, - tmpname, - AFPVOL_MACNAMELEN - suffixlen, - &flags); - tmpname[tmpvlen >= 0 ? tmpvlen : 0] = 0; - } - strcat(tmpname, suffix); - tmpvlen = strlen(tmpname); - } - - /* Secondly convert name from maccharset to UCS2 */ - if ( 0 >= ( macvlen = convert_string(obj->options.maccharset, - CH_UCS2, - tmpname, - tmpvlen, - mactmpname, - AFPVOL_U8MNAMELEN*2)) ) - return -1; - - LOG(log_maxdebug, logtype_afpd, "createvol: Volume '%s' -> Longname: '%s'", name, tmpname); - - /* check duplicate */ - for ( volume = Volumes; volume; volume = volume->v_next ) { - if ((utf8_encoding() && (strcasecmp_w(volume->v_u8mname, u8mtmpname) == 0)) - || - (!utf8_encoding() && (strcasecmp_w(volume->v_macname, mactmpname) == 0))) { - LOG (log_error, logtype_afpd, - "Duplicate volume name, check AppleVolumes files: previous: \"%s\", new: \"%s\"", - volume->v_localname, name); - if (volume->v_deleted) { - volume->v_new = hide = 1; - } - else { - return -1; /* Won't be able to access it, anyway... */ - } - } - } - - if (!( volume = (struct vol *)calloc(1, sizeof( struct vol ))) ) { - LOG(log_error, logtype_afpd, "creatvol: malloc: %s", strerror(errno) ); - return -1; - } - if ( NULL == ( volume->v_localname = strdup(name))) { - LOG(log_error, logtype_afpd, "creatvol: malloc: %s", strerror(errno) ); - free(volume); - return -1; - } - - if ( NULL == ( volume->v_u8mname = strdup_w(u8mtmpname))) { - LOG(log_error, logtype_afpd, "creatvol: malloc: %s", strerror(errno) ); - volume_free(volume); - free(volume); - return -1; - } - if ( NULL == ( volume->v_macname = strdup_w(mactmpname))) { - LOG(log_error, logtype_afpd, "creatvol: malloc: %s", strerror(errno) ); - volume_free(volume); - free(volume); - return -1; - } - if (!( volume->v_path = (char *)malloc( strlen( path ) + 1 )) ) { - LOG(log_error, logtype_afpd, "creatvol: malloc: %s", strerror(errno) ); - volume_free(volume); - free(volume); - return -1; - } - - volume->v_name = utf8_encoding()?volume->v_u8mname:volume->v_macname; - volume->v_hide = hide; - strcpy( volume->v_path, path ); - -#ifdef __svr4__ - volume->v_qfd = -1; -#endif /* __svr4__ */ - /* os X start at 1 and use network order ie. 1 2 3 */ - volume->v_vid = ++lastvid; - volume->v_vid = htons(volume->v_vid); -#ifdef HAVE_ACLS - if (!check_vol_acl_support(volume)) { - LOG(log_debug, logtype_afpd, "creatvol(\"%s\"): disabling ACL support", volume->v_path); - options[VOLOPT_FLAGS].i_value &= ~AFPVOL_ACLS; - } -#endif - - /* handle options */ - if (options) { - volume->v_casefold = options[VOLOPT_CASEFOLD].i_value; - volume->v_flags |= options[VOLOPT_FLAGS].i_value; - - if (options[VOLOPT_EA_VFS].i_value) - volume->v_vfs_ea = options[VOLOPT_EA_VFS].i_value; - - volume->v_ad_options = 0; - if ((volume->v_flags & AFPVOL_NODEV)) - volume->v_ad_options |= ADVOL_NODEV; - if ((volume->v_flags & AFPVOL_UNIX_PRIV)) - volume->v_ad_options |= ADVOL_UNIXPRIV; - if ((volume->v_flags & AFPVOL_INV_DOTS)) - volume->v_ad_options |= ADVOL_INVDOTS; - - if (options[VOLOPT_PASSWORD].c_value) - volume->v_password = strdup(options[VOLOPT_PASSWORD].c_value); - - if (options[VOLOPT_VETO].c_value) - volume->v_veto = strdup(options[VOLOPT_VETO].c_value); - - if (options[VOLOPT_ENCODING].c_value) - volume->v_volcodepage = strdup(options[VOLOPT_ENCODING].c_value); - - if (options[VOLOPT_MACCHARSET].c_value) - volume->v_maccodepage = strdup(options[VOLOPT_MACCHARSET].c_value); - - if (options[VOLOPT_DBPATH].c_value) - volume->v_dbpath = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_DBPATH].c_value, pwd, path, name); - - if (options[VOLOPT_CNIDSCHEME].c_value) - volume->v_cnidscheme = strdup(options[VOLOPT_CNIDSCHEME].c_value); - - if (options[VOLOPT_CNIDSERVER].c_value) - volume->v_cnidserver = strdup(options[VOLOPT_CNIDSERVER].c_value); - - if (options[VOLOPT_CNIDPORT].c_value) - volume->v_cnidport = strdup(options[VOLOPT_CNIDPORT].c_value); - - if (options[VOLOPT_UMASK].i_value) - volume->v_umask = (mode_t)options[VOLOPT_UMASK].i_value; - - if (options[VOLOPT_DPERM].i_value) - volume->v_dperm = (mode_t)options[VOLOPT_DPERM].i_value; - - if (options[VOLOPT_FPERM].i_value) - volume->v_fperm = (mode_t)options[VOLOPT_FPERM].i_value; - - if (options[VOLOPT_DFLTPERM].i_value) - volume->v_perm = (mode_t)options[VOLOPT_DFLTPERM].i_value; - - if (options[VOLOPT_ADOUBLE].i_value) - volume->v_adouble = options[VOLOPT_ADOUBLE].i_value; - else - volume->v_adouble = AD_VERSION; - - if (options[VOLOPT_LIMITSIZE].i_value) - volume->v_limitsize = options[VOLOPT_LIMITSIZE].i_value; - - /* Mac to Unix conversion flags*/ - volume->v_mtou_flags = 0; - if (!(volume->v_flags & AFPVOL_NOHEX)) - volume->v_mtou_flags |= CONV_ESCAPEHEX; - if (!(volume->v_flags & AFPVOL_USEDOTS)) - volume->v_mtou_flags |= CONV_ESCAPEDOTS; - if ((volume->v_flags & AFPVOL_EILSEQ)) - volume->v_mtou_flags |= CONV__EILSEQ; - - if ((volume->v_casefold & AFPVOL_MTOUUPPER)) - volume->v_mtou_flags |= CONV_TOUPPER; - else if ((volume->v_casefold & AFPVOL_MTOULOWER)) - volume->v_mtou_flags |= CONV_TOLOWER; - - /* Unix to Mac conversion flags*/ - volume->v_utom_flags = CONV_IGNORE | CONV_UNESCAPEHEX; - if ((volume->v_casefold & AFPVOL_UTOMUPPER)) - volume->v_utom_flags |= CONV_TOUPPER; - else if ((volume->v_casefold & AFPVOL_UTOMLOWER)) - volume->v_utom_flags |= CONV_TOLOWER; - - if ((volume->v_flags & AFPVOL_EILSEQ)) - volume->v_utom_flags |= CONV__EILSEQ; - - if (options[VOLOPT_PREEXEC].c_value) - volume->v_preexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_PREEXEC].c_value, pwd, path, name); - volume->v_preexec_close = options[VOLOPT_PREEXEC].i_value; - - if (options[VOLOPT_POSTEXEC].c_value) - volume->v_postexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_POSTEXEC].c_value, pwd, path, name); - - if (options[VOLOPT_ROOTPREEXEC].c_value) - volume->v_root_preexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_ROOTPREEXEC].c_value, pwd, path, name); - volume->v_root_preexec_close = options[VOLOPT_ROOTPREEXEC].i_value; - - if (options[VOLOPT_ROOTPOSTEXEC].c_value) - volume->v_root_postexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_ROOTPOSTEXEC].c_value, pwd, path, name); - } - volume->v_dperm |= volume->v_perm; - volume->v_fperm |= volume->v_perm; - - /* Check EA support on volume */ - if (volume->v_vfs_ea == AFPVOL_EA_AUTO || volume->v_adouble == AD_VERSION_EA) - check_ea_support(volume); - initvol_vfs(volume); - - /* get/store uuid from file in afpd master*/ - if ((parent_or_child == 0) && (volume->v_flags & AFPVOL_TM)) { - char *uuid = get_vol_uuid(obj, volume->v_localname); - if (!uuid) { - LOG(log_error, logtype_afpd, "Volume '%s': couldn't get UUID", - volume->v_localname); - } else { - volume->v_uuid = uuid; - LOG(log_debug, logtype_afpd, "Volume '%s': UUID '%s'", - volume->v_localname, volume->v_uuid); - } - } - - volume->v_next = Volumes; - Volumes = volume; - return 0; -} - -/* ---------------- */ -static char *myfgets( char *buf, int size, FILE *fp) -{ - char *p; - int c; - - p = buf; - while ((EOF != ( c = getc( fp )) ) && ( size > 1 )) { - if ( c == '\n' || c == '\r' ) { - if (p != buf && *(p -1) == '\\') { - p--; - size++; - continue; - } - *p++ = '\n'; - break; - } else { - *p++ = c; - } - size--; - } - - if ( p == buf ) { - return( NULL ); - } else { - *p = '\0'; - return( buf ); - } -} - - -/* check access list. this function wants something of the following - * form: - * @group,name,name2,@group2,name3 - * - * a NULL argument allows everybody to have access. - * we return three things: - * -1: no list - * 0: list exists, but name isn't in it - * 1: in list - */ - -#ifndef NO_REAL_USER_NAME -/* authentication is case insensitive - * FIXME should we do the same with group name? - */ -#define access_strcmp strcasecmp - -#else -#define access_strcmp strcmp - -#endif - -static int accessvol(const char *args, const char *name) -{ - char buf[MAXPATHLEN + 1], *p; - struct group *gr; - - if (!args) - return -1; - - strlcpy(buf, args, sizeof(buf)); - if ((p = strtok(buf, ",")) == NULL) /* nothing, return okay */ - return -1; - - while (p) { - if (*p == '@') { /* it's a group */ - if ((gr = getgrnam(p + 1)) && gmem(gr->gr_gid)) - return 1; - } else if (access_strcmp(p, name) == 0) /* it's a user name */ - return 1; - p = strtok(NULL, ","); - } - - return 0; -} - -static int hostaccessvol(int type, const char *volname, const char *args, const AFPObj *obj) +static void closevol(struct vol *vol) { - int mask_int; - char buf[MAXPATHLEN + 1], *p, *b; - DSI *dsi = obj->dsi; - struct sockaddr_storage client; - - if (!args) - return -1; - - strlcpy(buf, args, sizeof(buf)); - if ((p = strtok_r(buf, ",", &b)) == NULL) /* nothing, return okay */ - return -1; - - while (p) { - int ret; - char *ipaddr, *mask_char; - struct addrinfo hints, *ai; - - ipaddr = strtok(p, "/"); - mask_char = strtok(NULL,"/"); + if (!vol) + return; - /* Get address from string with getaddrinfo */ - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - if ((ret = getaddrinfo(ipaddr, NULL, &hints, &ai)) != 0) { - LOG(log_error, logtype_afpd, "hostaccessvol: getaddrinfo: %s\n", gai_strerror(ret)); - continue; - } + vol->v_flags &= ~AFPVOL_OPEN; - /* netmask */ - if (mask_char != NULL) - mask_int = atoi(mask_char); /* apply_ip_mask does range checking on it */ - else { - if (ai->ai_family == AF_INET) /* IPv4 */ - mask_int = 32; - else /* IPv6 */ - mask_int = 128; - } + of_closevol(vol); - /* Apply mask to addresses */ - client = dsi->client; - apply_ip_mask((struct sockaddr *)&client, mask_int); - apply_ip_mask(ai->ai_addr, mask_int); - - if (compare_ip((struct sockaddr *)&client, ai->ai_addr) == 0) { - if (type == VOLOPT_DENIED_HOSTS) - LOG(log_info, logtype_afpd, "AFP access denied for client IP '%s' to volume '%s' by denied list", - getip_string((struct sockaddr *)&client), volname); - freeaddrinfo(ai); - return 1; - } - - /* next address */ - freeaddrinfo(ai); - p = strtok_r(NULL, ",", &b); + dir_free( vol->v_root ); + vol->v_root = NULL; + if (vol->v_cdb != NULL) { + cnid_close(vol->v_cdb); + vol->v_cdb = NULL; } - if (type == VOLOPT_ALLOWED_HOSTS) - LOG(log_info, logtype_afpd, "AFP access denied for client IP '%s' to volume '%s', not in allowed list", - getip_string((struct sockaddr *)&dsi->client), volname); - return 0; -} - -/* ---------------------- - */ -static int volfile_changed(struct afp_options *p) -{ - struct stat st; - - if (!stat(p->configfile, &st) && st.st_mtime > p->volfile.mtime) { - p->volfile.mtime = st.st_mtime; - return 1; + if (vol->v_postexec) { + afprun(0, vol->v_postexec, NULL); } - return 0; -} - -static int vol_section(const char *sec) -{ - if (STRCMP(sec, ==, INISEC_GLOBAL)) - return 0; - if (STRCMP(sec, ==, INISEC_AFP)) - return 0; - if (STRCMP(sec, ==, INISEC_CNID)) - return 0; - return 1; -} - -/* ---------------------- - * Read volumes from iniconfig and add the volumes contained within to - * the global volume list. This gets called from the forked afpd childs. - * The master now reads this too for Zeroconf announcements. - */ -static int readvolfile(AFPObj *obj, struct afp_volume_name *p1, struct passwd *pwent) -{ - char path[MAXPATHLEN + 1]; - char volname[AFPVOL_U8MNAMELEN + 1]; - char tmp[MAXPATHLEN + 1]; - char *u; - const char *p; - int fd; - int i; - struct passwd *pw; - struct vol_option save_options[VOLOPT_NUM]; - struct vol_option default_options[VOLOPT_NUM]; - struct vol_option options[VOLOPT_NUM]; - - LOG(log_debug, logtype_afpd, "readvolfile: BEGIN"); - - memset(default_options, 0, sizeof(default_options)); - - /* Enable some default options for all volumes */ - default_options[VOLOPT_FLAGS].i_value |= AFPVOL_USEDOTS | AFPVOL_UNIX_PRIV; -#ifdef HAVE_ACLS - default_options[VOLOPT_FLAGS].i_value |= AFPVOL_ACLS; -#endif - default_options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_AUTO; - default_options[VOLOPT_UMASK].i_value = obj->options.umask; - memcpy(save_options, default_options, sizeof(options)); - - int secnum = iniparser_getnsec(obj->iniconfig); - LOG(log_debug, logtype_afpd, "readvolfile: sections: %d", secnum); - const char *secname; - - for (i = 0; i < secnum; i++) { - secname = iniparser_getsecname(obj->iniconfig, i); - if (!vol_section(secname)) - continue; - - strlcpy(volname, secname, AFPVOL_U8MNAMELEN); - LOG(log_debug, logtype_afpd, "readvolfile: volume: %s", volname); - - if ((p = iniparser_getstrdup(obj->iniconfig, secname, "path", NULL)) == NULL) - continue; - strlcpy(path, p, MAXPATHLEN); - strcpy(tmp, path); - - - if (!pwent && obj->username) - pwent = getpwnam(obj->username); - - if (volxlate(obj, path, sizeof(path) - 1, tmp, pwent, NULL, NULL) == NULL) - continue; - - memcpy(options, default_options, sizeof(options)); - volset(obj->iniconfig, secname, options, default_options); - - /* check allow/deny lists (if not afpd master loading volumes for Zeroconf reg.): - allow -> either no list (-1), or in list (1) - deny -> either no list (-1), or not in list (0) */ - if (parent_or_child == 0 - || - (accessvol(options[VOLOPT_ALLOW].c_value, obj->username) && - (accessvol(options[VOLOPT_DENY].c_value, obj->username) < 1) && - hostaccessvol(VOLOPT_ALLOWED_HOSTS, volname, options[VOLOPT_ALLOWED_HOSTS].c_value, obj) && - (hostaccessvol(VOLOPT_DENIED_HOSTS, volname, options[VOLOPT_DENIED_HOSTS].c_value, obj) < 1))) { - - /* handle read-only behaviour. semantics: - * 1) neither the rolist nor the rwlist exist -> rw - * 2) rolist exists -> ro if user is in it. - * 3) rwlist exists -> ro unless user is in it. */ - if (parent_or_child == 1 - && - ((options[VOLOPT_FLAGS].i_value & AFPVOL_RO) == 0) - && - ((accessvol(options[VOLOPT_ROLIST].c_value, obj->username) == 1) || - !accessvol(options[VOLOPT_RWLIST].c_value, obj->username))) - options[VOLOPT_FLAGS].i_value |= AFPVOL_RO; - - /* do variable substitution for volname */ - if (volxlate(obj, tmp, sizeof(tmp) - 1, volname, pwent, path, NULL) == NULL) { - volfree(options, default_options); - continue; - } - - creatvol(obj, pwent, path, tmp, options); - } - volfree(options, default_options); + if (vol->v_root_postexec) { + afprun(1, vol->v_root_postexec, NULL); } - volfree(save_options, NULL); - p1->loaded = 1; - return( 0 ); -} -/* ------------------------------- */ -static void volume_free(struct vol *vol) -{ - free(vol->v_localname); - vol->v_localname = NULL; - free(vol->v_u8mname); - vol->v_u8mname = NULL; - free(vol->v_macname); - vol->v_macname = NULL; - free(vol->v_path); - free(vol->v_password); - free(vol->v_veto); - free(vol->v_volcodepage); - free(vol->v_maccodepage); - free(vol->v_cnidscheme); - free(vol->v_dbpath); - free(vol->v_gvs); - if (vol->v_uuid) - free(vol->v_uuid); -} - -/* ------------------------------- */ -static void free_volumes(void ) -{ - struct vol *vol; - struct vol *nvol, *ovol; - - for ( vol = Volumes; vol; vol = vol->v_next ) { - if (( vol->v_flags & AFPVOL_OPEN ) ) { - vol->v_deleted = 1; - continue; - } + if (vol->v_deleted) { + showvol(vol->v_name); volume_free(vol); - } - - for ( vol = Volumes, ovol = NULL; vol; vol = nvol) { - nvol = vol->v_next; - - if (vol->v_localname == NULL) { - if (Volumes == vol) { - Volumes = nvol; - ovol = Volumes; - } - else { - ovol->v_next = nvol; - } - free(vol); - } - else { - ovol = vol; - } + volume_unlink(vol); + free(vol); } } -/* ------------------------------- */ -static void volume_unlink(struct vol *volume) -{ - struct vol *vol, *ovol, *nvol; - - if (volume == Volumes) { - Volumes = Volumes->v_next; - return; - } - for ( vol = Volumes->v_next, ovol = Volumes; vol; vol = nvol) { - nvol = vol->v_next; - - if (vol == volume) { - ovol->v_next = nvol; - break; - } - else { - ovol = vol; - } - } -} /*! * Read band-size info from Info.plist XML file of an TM sparsebundle * @@ -1238,7 +264,7 @@ EC_CLEANUP: EC_EXIT; } -static int getvolspace(struct vol *vol, +static int getvolspace(const AFPObj *obj, struct vol *vol, uint32_t *bfree, uint32_t *btotal, VolSpace *xbfree, VolSpace *xbtotal, uint32_t *bsize) { @@ -1268,7 +294,7 @@ static int getvolspace(struct vol *vol, #ifndef NO_QUOTA_SUPPORT if ( spaceflag == AFPVOL_NONE || spaceflag == AFPVOL_UQUOTA ) { - if ( uquota_getvolspace( vol, &qfree, &qtotal, *bsize ) == AFP_OK ) { + if ( uquota_getvolspace(obj, vol, &qfree, &qtotal, *bsize ) == AFP_OK ) { vol->v_flags = ( ~AFPVOL_GVSMASK & vol->v_flags ) | AFPVOL_UQUOTA; *xbfree = MIN(*xbfree, qfree); *xbtotal = MIN(*xbtotal, qtotal); @@ -1301,7 +327,7 @@ void vol_fce_tm_event(void) { static time_t last; time_t now = time(NULL); - struct vol *vol = Volumes; + struct vol *vol = getvolumes(); if ((last + FCE_TM_DELTA) < now) { last = now; @@ -1319,15 +345,15 @@ void vol_fce_tm_event(void) static void vol_setdate(uint16_t id, struct adouble *adp, time_t date) { struct vol *volume; - struct vol *vol = Volumes; + struct vol *vol = getvolumes(); - for ( volume = Volumes; volume; volume = volume->v_next ) { + for ( volume = getvolumes(); volume; volume = volume->v_next ) { if (volume->v_vid == id) { vol = volume; } else if ((time_t)(AD_DATE_FROM_UNIX(date)) == volume->v_ctime) { date = date+1; - volume = Volumes; /* restart */ + volume = getvolumes(); /* restart */ } } vol->v_ctime = AD_DATE_FROM_UNIX(date); @@ -1335,7 +361,7 @@ static void vol_setdate(uint16_t id, struct adouble *adp, time_t date) } /* ----------------------- */ -static int getvolparams( uint16_t bitmap, struct vol *vol, struct stat *st, char *buf, size_t *buflen) +static int getvolparams(const AFPObj *obj, uint16_t bitmap, struct vol *vol, struct stat *st, char *buf, size_t *buflen) { struct adouble ad; int bit = 0, isad = 1; @@ -1384,7 +410,7 @@ static int getvolparams( uint16_t bitmap, struct vol *vol, struct stat *st, char if (( bitmap & ( (1<v_dev = st.st_dev; buflen = *rbuflen - sizeof( bitmap ); - if (( ret = getvolparams( bitmap, vol, &st, + if (( ret = getvolparams(obj, bitmap, vol, &st, rbuf + sizeof( bitmap ), &buflen )) != AFP_OK ) { *rbuflen = 0; return( ret ); @@ -1564,74 +590,6 @@ static int stat_vol(uint16_t bitmap, struct vol *vol, char *rbuf, size_t *rbufle } -/* ------------------------------- */ -void load_volumes(AFPObj *obj) -{ - EC_INIT; - int fd = -1; - struct passwd *pwent; - struct stat st; - int retries = 0; - - if (parent_or_child == 0) { - LOG(log_debug, logtype_afpd, "load_volumes: AFP MASTER"); - } else { - LOG(log_debug, logtype_afpd, "load_volumes: user: %s", obj->username); - } - - if (Volumes) { - if (!volfile_changed(&obj->options)) - return; - free_volumes(); - } - - /* try putting a read lock on the volume file twice, sleep 1 second if first attempt fails */ - - fd = open(obj->options.configfile, O_RDONLY); - - while (retries < 2) { - if ((read_lock(fd, 0, SEEK_SET, 0)) != 0) { - retries++; - if (!retries) { - LOG(log_error, logtype_afpd, "readvolfile: can't lock configfile \"%s\"", - obj->options.configfile); - EC_FAIL; - } - sleep(1); - continue; - } - break; - } - - if (obj->iniconfig) - iniparser_freedict(obj->iniconfig); - LOG(log_debug, logtype_afpd, "load_volumes: reloading: %s", obj->options.configfile); - obj->iniconfig = iniparser_load(obj->options.configfile); - - if (obj->username) - pwent = getpwnam(obj->username); - else - pwent = NULL; - - readvolfile(obj, &obj->options.volfile, pwent); - - if ( obj->options.flags & OPTION_CLOSEVOL) { - struct vol *vol; - for ( vol = Volumes; vol; vol = vol->v_next ) { - if (vol->v_deleted && !vol->v_new ) { - of_closevol(vol); - deletevol(vol); - vol = Volumes; - } - } - } - -EC_CLEANUP: - if (fd != -1) - (void)close(fd); - return; -} - /* ------------------------------- */ int afp_getsrvrparms(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) { @@ -1643,10 +601,10 @@ int afp_getsrvrparms(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf int vcnt; size_t len; - load_volumes(obj); + load_volumes(obj, of_closevol); data = rbuf + 5; - for ( vcnt = 0, volume = Volumes; volume; volume = volume->v_next ) { + for ( vcnt = 0, volume = getvolumes(); volume; volume = volume->v_next ) { if (!(volume->v_flags & AFPVOL_NOSTAT)) { struct maccess ma; @@ -1658,7 +616,7 @@ int afp_getsrvrparms(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf if (!S_ISDIR(st.st_mode)) { continue; /* not a dir */ } - accessmode(volume, volume->v_path, &ma, NULL, &st); + accessmode(obj, volume, volume->v_path, &ma, NULL, &st); if ((ma.ma_user & (AR_UREAD | AR_USEARCH)) != (AR_UREAD | AR_USEARCH)) { continue; /* no r-x access */ } @@ -1783,71 +741,6 @@ static int volume_openDB(const AFPObj *obj, struct vol *volume) return (!volume->v_cdb)?-1:0; } -/* - Check if the underlying filesystem supports EAs. - If not, switch to ea:ad. - As we can't check (requires write access) on ro-volumes, we switch ea:auto - volumes that are options:ro to ea:none. -*/ -static int do_check_ea_support(const struct vol *vol) -{ - int haseas; - char eaname[] = {"org.netatalk.supports-eas.XXXXXX"}; - const char *eacontent = "yes"; - - if ((vol->v_flags & AFPVOL_RO) == AFPVOL_RO) { - LOG(log_note, logtype_afpd, "read-only volume '%s', can't test for EA support, assuming yes", vol->v_localname); - return 1; - } - - mktemp(eaname); - - become_root(); - - if ((sys_setxattr(vol->v_path, eaname, eacontent, 4, 0)) == 0) { - sys_removexattr(vol->v_path, eaname); - haseas = 1; - } else { - LOG(log_warning, logtype_afpd, "volume \"%s\" does not support Extended Attributes", - vol->v_localname); - haseas = 0; - } - - unbecome_root(); - - return haseas; -} - -static void check_ea_support(struct vol *vol) -{ - int haseas; - char eaname[] = {"org.netatalk.supports-eas.XXXXXX"}; - const char *eacontent = "yes"; - - haseas = do_check_ea_support(vol); - - if (vol->v_vfs_ea == AFPVOL_EA_AUTO) { - if ((vol->v_flags & AFPVOL_RO) == AFPVOL_RO) { - LOG(log_info, logtype_afpd, "read-only volume '%s', can't test for EA support, disabling EAs", vol->v_localname); - vol->v_vfs_ea = AFPVOL_EA_NONE; - return; - } - - if (haseas) { - vol->v_vfs_ea = AFPVOL_EA_SYS; - } else { - LOG(log_warning, logtype_afpd, "volume \"%s\" does not support Extended Attributes, using ea:ad instead", - vol->v_localname); - vol->v_vfs_ea = AFPVOL_EA_AD; - } - } - - if (vol->v_adouble == AD_VERSION_EA) { - if (!haseas) - vol->v_adouble = AD_VERSION2; - } -} - /* ------------------------- * we are the user here */ @@ -1897,9 +790,9 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t if ((len + 1) & 1) /* pad to an even boundary */ ibuf++; - load_volumes(obj); + load_volumes(obj, of_closevol); - for ( volume = Volumes; volume; volume = volume->v_next ) { + for ( volume = getvolumes(); volume; volume = volume->v_next ) { if ( strcasecmp_w( (ucs2_t*) volname, volume->v_name ) == 0 ) { break; } @@ -1916,7 +809,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t if (( volume->v_flags & AFPVOL_OPEN ) ) { /* the volume is already open */ - return stat_vol(bitmap, volume, rbuf, rbuflen); + return stat_vol(obj, bitmap, volume, rbuf, rbuflen); } if (volume->v_root_preexec) { @@ -2025,7 +918,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t goto openvol_err; } - ret = stat_vol(bitmap, volume, rbuf, rbuflen); + ret = stat_vol(obj, bitmap, volume, rbuf, rbuflen); if (ret == AFP_OK) { handle_special_folders(volume); @@ -2053,10 +946,6 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t goto openvol_err; } } - else { - p = Trash; - cname( volume, volume->v_root, &p ); - } return( AFP_OK ); } @@ -2075,33 +964,12 @@ openvol_err: return ret; } -/* ------------------------- */ -static void closevol(struct vol *vol) -{ - if (!vol) - return; - - dir_free( vol->v_root ); - vol->v_root = NULL; - if (vol->v_cdb != NULL) { - cnid_close(vol->v_cdb); - vol->v_cdb = NULL; - } - - if (vol->v_postexec) { - afprun(0, vol->v_postexec, NULL); - } - if (vol->v_root_postexec) { - afprun(1, vol->v_root_postexec, NULL); - } -} - /* ------------------------- */ void close_all_vol(void) { struct vol *ovol; curdir = NULL; - for ( ovol = Volumes; ovol; ovol = ovol->v_next ) { + for ( ovol = getvolumes(); ovol; ovol = ovol->v_next ) { if ( (ovol->v_flags & AFPVOL_OPEN) ) { ovol->v_flags &= ~AFPVOL_OPEN; closevol(ovol); @@ -2109,33 +977,6 @@ void close_all_vol(void) } } -/* ------------------------- */ -static void deletevol(struct vol *vol) -{ - struct vol *ovol; - - vol->v_flags &= ~AFPVOL_OPEN; - for ( ovol = Volumes; ovol; ovol = ovol->v_next ) { - if ( (ovol->v_flags & AFPVOL_OPEN) ) { - break; - } - } - if ( ovol != NULL ) { - /* Even if chdir fails, we can't say afp_closevol fails. */ - if ( chdir( ovol->v_path ) == 0 ) { - curdir = ovol->v_root; - } - } - - closevol(vol); - if (vol->v_deleted) { - showvol(vol->v_name); - volume_free(vol); - volume_unlink(vol); - free(vol); - } -} - /* ------------------------- */ int afp_closevol(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { @@ -2149,31 +990,12 @@ int afp_closevol(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ return( AFPERR_PARAM ); } - deletevol(vol); - current_vol = NULL; + (void)chdir("/"); + closevol(vol); return( AFP_OK ); } -/* ------------------------- */ -struct vol *getvolbyvid(const uint16_t vid ) -{ - struct vol *vol; - - for ( vol = Volumes; vol; vol = vol->v_next ) { - if ( vid == vol->v_vid ) { - break; - } - } - if ( vol == NULL || ( vol->v_flags & AFPVOL_OPEN ) == 0 ) { - return( NULL ); - } - - current_vol = vol; - - return( vol ); -} - /* -------------------------- poll if a volume is changed by other processes. return @@ -2199,7 +1021,7 @@ int pollvoltime(AFPObj *obj) if ( gettimeofday( &tv, NULL ) < 0 ) return 0; - for ( vol = Volumes; vol; vol = vol->v_next ) { + for ( vol = getvolumes(); vol; vol = vol->v_next ) { if ( (vol->v_flags & AFPVOL_OPEN) && vol->v_mtime + 30 < tv.tv_sec) { if ( !stat( vol->v_path, &st ) && vol->v_mtime != st.st_mtime ) { vol->v_mtime = st.st_mtime; @@ -2240,7 +1062,7 @@ void setvoltime(AFPObj *obj, struct vol *vol) } /* ------------------------- */ -int afp_getvolparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,char *rbuf, size_t *rbuflen) +int afp_getvolparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_,char *rbuf, size_t *rbuflen) { struct vol *vol; uint16_t vid, bitmap; @@ -2256,7 +1078,7 @@ int afp_getvolparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,char *rbuf, return( AFPERR_PARAM ); } - return stat_vol(bitmap, vol, rbuf, rbuflen); + return stat_vol(obj, bitmap, vol, rbuf, rbuflen); } /* ------------------------- */ @@ -2386,131 +1208,12 @@ static int create_special_folder (const struct vol *vol, const struct _special_f static void handle_special_folders (const struct vol * vol) { const _special_folder *p = &special_folders[0]; - uid_t process_uid; - process_uid = geteuid(); - if (process_uid) { - if (seteuid(0) == -1) { - process_uid = 0; - } - } + become_root(); for (; p->name != NULL; p++) { create_special_folder (vol, p); } - if (process_uid) { - if (seteuid(process_uid) == -1) { - LOG(log_error, logtype_logger, "can't seteuid back %s", strerror(errno)); - exit(EXITERR_SYS); - } - } -} - -const struct vol *getvolumes(void) -{ - return Volumes; -} - -void unload_volumes(void) -{ - LOG(log_debug, logtype_afpd, "unload_volumes_and_extmap"); - free_volumes(); -} - -/* - * Get a volumes UUID from the config file. - * If there is none, it is generated and stored there. - * - * Returns pointer to allocated storage on success, NULL on error. - */ -static char *get_vol_uuid(const AFPObj *obj, const char *volname) -{ - char *volname_conf; - char buf[1024], uuid[UUID_PRINTABLE_STRING_LENGTH], *p; - FILE *fp; - struct stat tmpstat; - int fd; - - if ((fp = fopen(obj->options.uuidconf, "r")) != NULL) { /* read open? */ - /* scan in the conf file */ - while (fgets(buf, sizeof(buf), fp) != NULL) { - p = buf; - while (p && isblank(*p)) - p++; - if (!p || (*p == '#') || (*p == '\n')) - continue; /* invalid line */ - if (*p == '"') { - p++; - if ((volname_conf = strtok( p, "\"" )) == NULL) - continue; /* syntax error */ - } else { - if ((volname_conf = strtok( p, " \t" )) == NULL) - continue; /* syntax error: invalid name */ - } - p = strchr(p, '\0'); - p++; - if (*p == '\0') - continue; /* syntax error */ - - if (strcmp(volname, volname_conf) != 0) - continue; /* another volume name */ - - while (p && isblank(*p)) - p++; - - if (sscanf(p, "%36s", uuid) == 1 ) { - for (int i=0; uuid[i]; i++) - uuid[i] = toupper(uuid[i]); - LOG(log_debug, logtype_afpd, "get_uuid('%s'): UUID: '%s'", volname, uuid); - fclose(fp); - return strdup(uuid); - } - } - } - - if (fp) - fclose(fp); - - /* not found or no file, reopen in append mode */ - - if (stat(obj->options.uuidconf, &tmpstat)) { /* no file */ - if (( fd = creat(obj->options.uuidconf, 0644 )) < 0 ) { - LOG(log_error, logtype_afpd, "ERROR: Cannot create %s (%s).", - obj->options.uuidconf, strerror(errno)); - return NULL; - } - if (( fp = fdopen( fd, "w" )) == NULL ) { - LOG(log_error, logtype_afpd, "ERROR: Cannot fdopen %s (%s).", - obj->options.uuidconf, strerror(errno)); - close(fd); - return NULL; - } - } else if ((fp = fopen(obj->options.uuidconf, "a+")) == NULL) { /* not found */ - LOG(log_error, logtype_afpd, "Cannot create or append to %s (%s).", - obj->options.uuidconf, strerror(errno)); - return NULL; - } - fseek(fp, 0L, SEEK_END); - if(ftell(fp) == 0) { /* size = 0 */ - fprintf(fp, "# DON'T TOUCH NOR COPY THOUGHTLESSLY!\n"); - fprintf(fp, "# This file is auto-generated by afpd\n"); - fprintf(fp, "# and stores UUIDs for TM volumes.\n\n"); - } else { - fseek(fp, -1L, SEEK_END); - if(fgetc(fp) != '\n') fputc('\n', fp); /* last char is \n? */ - } - - /* generate uuid and write to file */ - atalk_uuid_t id; - const char *cp; - randombytes((void *)id, 16); - cp = uuid_bin2string(id); - - LOG(log_debug, logtype_afpd, "get_uuid('%s'): generated UUID '%s'", volname, cp); - - fprintf(fp, "\"%s\"\t%36s\n", volname, cp); - fclose(fp); - - return strdup(cp); + unbecome_root(); } diff --git a/etc/afpd/volume.h b/etc/afpd/volume.h index 90febbfe..ed59b244 100644 --- a/etc/afpd/volume.h +++ b/etc/afpd/volume.h @@ -14,15 +14,11 @@ #include #include -extern struct vol *getvolbyvid (const uint16_t); extern int ustatfs_getvolspace (const struct vol *, - VolSpace *, VolSpace *, - uint32_t *); + VolSpace *, VolSpace *, + uint32_t *); extern void setvoltime (AFPObj *, struct vol *); extern int pollvoltime (AFPObj *); -extern void load_volumes (AFPObj *obj); -extern const struct vol *getvolumes(void); -extern void unload_volumes(void); extern void vol_fce_tm_event(void); /* FP functions */ @@ -35,6 +31,4 @@ int afp_closevol (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size /* netatalk functions */ extern void close_all_vol (void); -struct vol *current_vol; /* last volume from getvolbyvid() */ - #endif diff --git a/include/atalk/Makefile.am b/include/atalk/Makefile.am index b8c980b7..d59d7fdb 100644 --- a/include/atalk/Makefile.am +++ b/include/atalk/Makefile.am @@ -8,6 +8,7 @@ atalkinclude_HEADERS = \ vfs.h \ cnid.h \ logger.h \ + netatalk_conf.h \ paths.h \ unicode.h \ util.h \ diff --git a/include/atalk/globals.h b/include/atalk/globals.h index 5607b329..2e27cde1 100644 --- a/include/atalk/globals.h +++ b/include/atalk/globals.h @@ -32,6 +32,8 @@ #define MAXUSERLEN 256 +#define DEFAULT_MAX_DIRCACHE_SIZE 8192 + #define OPTION_DEBUG (1 << 0) #define OPTION_CLOSEVOL (1 << 1) #define OPTION_SERVERNOTIF (1 << 2) @@ -42,6 +44,11 @@ #define OPTION_NOZEROCONF (1 << 9) #define OPTION_KEEPSESSIONS (1 << 10) /* preserve sessions across master afpd restart with SIGQUIT */ +#define PASSWD_NONE 0 +#define PASSWD_SET (1 << 0) +#define PASSWD_NOSAVE (1 << 1) +#define PASSWD_ALL (PASSWD_SET | PASSWD_NOSAVE) + /********************************************************************************************** * Ini config sections **********************************************************************************************/ @@ -115,6 +122,10 @@ typedef struct AFPObj { struct session_info sinfo; uid_t uid; /* client running user id */ int ipc_fd; /* anonymous PF_UNIX socket for IPC with afpd parent */ + + gid_t *groups; + int ngroups; + /* Functions */ void (*logout)(void); void (*exit)(int); @@ -139,7 +150,6 @@ extern const char *Cnid_port; extern int get_afp_errno (const int param); extern void afp_options_init (struct afp_options *); extern void afp_options_parse_cmdline(AFPObj *obj, int ac, char **av); -extern int afp_config_parse(AFPObj *AFPObj); extern void afp_options_free(struct afp_options *); extern void setmessage (const char *); extern void readmessage (AFPObj *); diff --git a/include/atalk/netatalk_conf.h b/include/atalk/netatalk_conf.h new file mode 100644 index 00000000..5b6ab571 --- /dev/null +++ b/include/atalk/netatalk_conf.h @@ -0,0 +1,31 @@ +/* + Copyright (c) 2012 Frank Lahm + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + */ + +#ifndef AFP_CONFIG_H +#define AFP_CONFIG_H + +#include + +#include +#include + +extern int afp_config_parse(AFPObj *obj); + +extern int load_volumes(AFPObj *obj, void (*delvol_fn)(const struct vol *)); +extern void unload_volumes(void); +extern struct vol *getvolumes(void); +extern struct vol *getvolbyvid(const uint16_t); +extern void volume_free(struct vol *vol); +extern void volume_unlink(struct vol *volume); +#endif diff --git a/include/atalk/unix.h b/include/atalk/unix.h index 62303692..24c1f7c5 100644 --- a/include/atalk/unix.h +++ b/include/atalk/unix.h @@ -1,5 +1,4 @@ /* - $Id: unix.h,v 1.3 2010-03-12 15:16:49 franklahm Exp $ Copyright (c) 2009 Frank Lahm This program is free software; you can redistribute it and/or modify @@ -46,5 +45,6 @@ extern int copy_ea(const char *ea, int sfd, const char *src, const char *dst, mo extern void become_root(void); extern void unbecome_root(void); +extern int gmem(gid_t gid, int ngroups, gid_t *groups); #endif /* ATALK_UNIX_H */ diff --git a/include/atalk/volume.h b/include/atalk/volume.h index 42b8a170..c179e74b 100644 --- a/include/atalk/volume.h +++ b/include/atalk/volume.h @@ -91,8 +91,11 @@ struct vol { #endif /*__svr4__*/ }; -#define AFPVOL_OPEN (1<<0) +/* load_volumes() flags */ +#define LV_ALL (1 << 0) +/* volume flags */ +#define AFPVOL_OPEN (1<<0) /* flags for AFS and quota 0xxx0 */ #define AFPVOL_GVSMASK (7<<2) #define AFPVOL_NONE (0<<2) diff --git a/libatalk/util/Makefile.am b/libatalk/util/Makefile.am index 17ae747c..8c0927d4 100644 --- a/libatalk/util/Makefile.am +++ b/libatalk/util/Makefile.am @@ -6,6 +6,7 @@ noinst_LTLIBRARIES = libutil.la libutil_la_SOURCES = \ bprint.c \ + config.c \ cnid.c \ fault.c \ getiface.c \ @@ -21,7 +22,11 @@ libutil_la_SOURCES = \ volinfo.c \ unix.c -libutil_la_CFLAGS = -D_PATH_AFPDCONF=\"$(pkgconfdir)/afpd.conf\" +libutil_la_CFLAGS = \ + -D_PATH_CONFDIR=\"$(pkgconfdir)/\" \ + -DSERVERTEXT=\"$(SERVERTEXT)/\" \ + -D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" \ + -D_PATH_AFPDUAMPATH=\"$(UAMS_PATH)/\" if HAVE_ATFUNCS libutil_la_SOURCES += ftw.c diff --git a/libatalk/util/logger.c b/libatalk/util/logger.c index 6d3be477..a7cdd2c1 100644 --- a/libatalk/util/logger.c +++ b/libatalk/util/logger.c @@ -627,7 +627,7 @@ void setuplog(const char *logstr, const char *logfile) save = ptr = strdup(logstr); - ptr = strtok(ptr, ","); + ptr = strtok(ptr, ", "); while (ptr) { while (*ptr) { @@ -649,7 +649,7 @@ void setuplog(const char *logstr, const char *logfile) setuplog_internal(loglevel, logtype, logfile); *ptr = c; } - ptr = strtok(NULL, ","); + ptr = strtok(NULL, ", "); } free(save); diff --git a/libatalk/util/unix.c b/libatalk/util/unix.c index 88371e8a..5b0da03c 100644 --- a/libatalk/util/unix.c +++ b/libatalk/util/unix.c @@ -272,3 +272,15 @@ void randombytes(void *buf, int n) return; } + +int gmem(gid_t gid, int ngroups, gid_t *groups) +{ + int i; + + for ( i = 0; i < ngroups; i++ ) { + if ( groups[ i ] == gid ) { + return( 1 ); + } + } + return( 0 ); +} -- 2.39.2