#include <atalk/uuid.h>
#include <atalk/netatalk_conf.h>
#include <atalk/bstrlib.h>
+#include <atalk/bstradd.h>
#define VOLPASSLEN 8
#ifndef UUID_PRINTABLE_STRING_LENGTH
*/
static const char *getoption(const dictionary *conf, const char *vol, const char *opt, const char *defsec, const char *defval)
{
- EC_INIT;
const char *result;
if ((!(result = iniparser_getstring(conf, vol, opt, NULL))) && (defsec != NULL))
result = iniparser_getstring(conf, defsec, opt, NULL);
-EC_CLEANUP:
if (result == NULL)
result = defval;
return result;
*/
static int getoption_bool(const dictionary *conf, const char *vol, const char *opt, const char *defsec, int defval)
{
- EC_INIT;
int result;
if (((result = iniparser_getboolean(conf, vol, opt, -1)) == -1) && (defsec != NULL))
result = iniparser_getboolean(conf, defsec, opt, -1);
-EC_CLEANUP:
if (result == -1)
result = defval;
return result;
volume->v_vfs_ea = AFPVOL_EA_AUTO;
volume->v_umask = obj->options.umask;
- if (val = getoption(obj->iniconfig, section, "password", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "password", preset, NULL)))
EC_NULL( volume->v_password = strdup(val) );
- if (val = getoption(obj->iniconfig, section, "veto files", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "veto files", preset, NULL)))
EC_NULL( volume->v_veto = strdup(val) );
/* vol charset is in [G] and [V] */
- if (val = getoption(obj->iniconfig, section, "vol charset", preset, NULL)) {
+ if ((val = getoption(obj->iniconfig, section, "vol charset", preset, NULL))) {
if (strcasecmp(val, "UTF-8") == 0) {
val = strdup("UTF8");
}
EC_NULL( volume->v_volcodepage = strdup(obj->options.volcodepage) );
/* mac charset is in [G] and [V] */
- if (val = getoption(obj->iniconfig, section, "mac charset", preset, NULL)) {
+ if ((val = getoption(obj->iniconfig, section, "mac charset", preset, NULL))) {
if (strncasecmp(val, "MAC", 3) != 0) {
LOG(log_warning, logtype_afpd, "Is '%s' really mac charset? ", val);
}
if(tmpname[i] == '/') tmpname[i] = ':';
bstring dbpath;
- EC_NULL_LOG( val = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol dbpath", _PATH_STATEDIR "CNID/") );
- EC_NULL_LOG( dbpath = bformat("%s/%s/", val, tmpname) );
- EC_NULL_LOG( volume->v_dbpath = strdup(bdata(dbpath)) );
+ EC_NULL( val = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol dbpath", _PATH_STATEDIR "CNID/") );
+ EC_NULL( dbpath = bformat("%s/%s/", val, tmpname) );
+ EC_NULL( volume->v_dbpath = strdup(cfrombstr(dbpath)) );
bdestroy(dbpath);
- if (val = getoption(obj->iniconfig, section, "cnid scheme", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "cnid scheme", preset, NULL)))
EC_NULL( volume->v_cnidscheme = strdup(val) );
else
volume->v_cnidscheme = strdup(DEFAULT_CNID_SCHEME);
- if (val = getoption(obj->iniconfig, section, "umask", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "umask", preset, NULL)))
volume->v_umask = (int)strtol(val, NULL, 8);
- if (val = getoption(obj->iniconfig, section, "directory perm", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "directory perm", preset, NULL)))
volume->v_dperm = (int)strtol(val, NULL, 8);
- if (val = getoption(obj->iniconfig, section, "file perm", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "file perm", preset, NULL)))
volume->v_fperm = (int)strtol(val, NULL, 8);
- if (val = getoption(obj->iniconfig, section, "vol size limit", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "vol size limit", preset, NULL)))
volume->v_limitsize = (uint32_t)strtoul(val, NULL, 10);
- if (val = getoption(obj->iniconfig, section, "preexec", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "preexec", preset, NULL)))
EC_NULL( volume->v_preexec = volxlate(obj, NULL, MAXPATHLEN, val, pwd, path, name) );
- if (val = getoption(obj->iniconfig, section, "postexec", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "postexec", preset, NULL)))
EC_NULL( volume->v_postexec = volxlate(obj, NULL, MAXPATHLEN, val, pwd, path, name) );
- if (val = getoption(obj->iniconfig, section, "root preexec", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "root preexec", preset, NULL)))
EC_NULL( volume->v_root_preexec = volxlate(obj, NULL, MAXPATHLEN, val, pwd, path, name) );
- if (val = getoption(obj->iniconfig, section, "root postexec", preset, NULL))
+ if ((val = getoption(obj->iniconfig, section, "root postexec", preset, NULL)))
EC_NULL( volume->v_root_postexec = volxlate(obj, NULL, MAXPATHLEN, val, pwd, path, name) );
- if (val = getoption(obj->iniconfig, section, "appledouble", preset, NULL)) {
+ if ((val = getoption(obj->iniconfig, section, "appledouble", preset, NULL))) {
if (strcmp(val, "v2") == 0)
volume->v_adouble = AD_VERSION2;
else if (strcmp(val, "ea") == 0)
volume->v_adouble = AD_VERSION;
}
- if (val = getoption(obj->iniconfig, section, "cnid server", preset, NULL)) {
+ if ((val = getoption(obj->iniconfig, section, "cnid server", preset, NULL))) {
EC_NULL( p = strdup(val) );
volume->v_cnidserver = p;
- if (q = strrchr(val, ':')) {
+ if ((q = strrchr(val, ':'))) {
*q++ = 0;
volume->v_cnidport = strdup(q);
} else {
volume->v_cnidport = strdup(obj->options.Cnid_port);
}
- if (val = getoption(obj->iniconfig, section, "ea", preset, NULL)) {
+ if ((val = getoption(obj->iniconfig, section, "ea", preset, NULL))) {
if (strcasecmp(val, "ad") == 0)
volume->v_vfs_ea = AFPVOL_EA_AD;
else if (strcasecmp(val, "sys") == 0)
volume->v_vfs_ea = AFPVOL_EA_NONE;
}
- if (val = getoption(obj->iniconfig, section, "casefold", preset, NULL)) {
+ if ((val = getoption(obj->iniconfig, section, "casefold", preset, NULL))) {
if (strcasecmp(val, "tolower") == 0)
volume->v_casefold = AFPVOL_UMLOWER;
else if (strcasecmp(val, "toupper") == 0)
volume->v_ad_options |= ADVOL_INVDOTS;
if ((volume->v_flags & AFPVOL_FOLLOWSYM))
volume->v_ad_options |= ADVOL_FOLLO_SYML;
+ if ((volume->v_flags & AFPVOL_RO))
+ volume->v_ad_options |= ADVOL_RO;
/* Mac to Unix conversion flags*/
if ((volume->v_flags & AFPVOL_EILSEQ))
/* Unicode Volume Name */
/* Firstly convert name from unixcharset to UTF8-MAC */
- flags = CONV_IGNORE | CONV_ALLOW_SLASH;
+ flags = CONV_IGNORE;
tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags);
if (tmpvlen <= 0) {
strcpy(tmpname, "???");
/* Do we have to mangle ? */
if ( (flags & CONV_REQMANGLE) || (tmpvlen > obj->options.volnamelen)) {
if (tmpvlen + suffixlen > obj->options.volnamelen) {
- flags = CONV_FORCE | CONV_ALLOW_SLASH;
+ 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;
}
/* Maccharset Volume Name */
/* Firsty convert name from unixcharset to maccharset */
- flags = CONV_IGNORE | CONV_ALLOW_SLASH;
+ flags = CONV_IGNORE;
tmpvlen = convert_charset(obj->options.unixcharset, obj->options.maccharset, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags);
if (tmpvlen <= 0) {
strcpy(tmpname, "???");
/* Do we have to mangle ? */
if ( (flags & CONV_REQMANGLE) || (tmpvlen > AFPVOL_MACNAMELEN)) {
if (tmpvlen + suffixlen > AFPVOL_MACNAMELEN) {
- flags = CONV_FORCE | CONV_ALLOW_SLASH;
+ flags = CONV_FORCE;
tmpvlen = convert_charset(obj->options.unixcharset,
obj->options.maccharset,
0,
initvol_vfs(volume);
/* get/store uuid from file in afpd master*/
- if (!(pwd) && (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);
- }
+ become_root();
+ char *uuid = get_vol_uuid(obj, volume->v_localname);
+ unbecome_root();
+ 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);
}
/* no errors shall happen beyond this point because the cleanup would mess the volume chain up */
char volname[AFPVOL_U8MNAMELEN + 1];
char path[MAXPATHLEN + 1], tmp[MAXPATHLEN + 1];
const char *preset, *default_preset, *p, *basedir;
- char *q, *u;
int i;
- struct passwd *pw;
regmatch_t match[1];
LOG(log_debug, logtype_afpd, "readvolfile: BEGIN");
continue;
}
- if (p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL)) {
+ if ((p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))) {
strlcat(tmp, "/", MAXPATHLEN);
strlcat(tmp, p, MAXPATHLEN);
}
free(realvolpath);
}
-EC_CLEANUP:
+// EC_CLEANUP:
EC_EXIT;
}
LOG(log_debug, logtype_afpd, "load_volumes: BEGIN");
+ if (obj->uid)
+ pwent = getpwuid(obj->uid);
+
if (Volumes) {
if (!volfile_changed(&obj->options))
goto EC_CLEANUP;
for (vol = Volumes; vol; vol = vol->v_next) {
vol->v_deleted = 1;
}
+ if (obj->uid) {
+ become_root();
+ ret = set_groups(obj, pwent);
+ unbecome_root();
+ if (ret != 0) {
+ LOG(log_error, logtype_afpd, "load_volumes: set_groups: %s", strerror(errno));
+ EC_FAIL;
+ }
+ }
} else {
LOG(log_debug, logtype_afpd, "load_volumes: no volumes yet");
EC_ZERO_LOG( lstat(obj->options.configfile, &st) );
break;
}
- if (obj->uid)
- pwent = getpwuid(obj->uid);
-
if (obj->iniconfig)
iniparser_freedict(obj->iniconfig);
LOG(log_debug, logtype_afpd, "load_volumes: loading: %s", obj->options.configfile);
return( vol );
}
+/*
+ * get username by path
+ *
+ * getvolbypath() assumes that the user home directory has the same name as the username.
+ * If that is not true, getuserbypath() is called and tries to retrieve the username
+ * from the directory owner, checking its validity.
+ *
+ * @param path (r) absolute volume path
+ * @returns NULL if no match is found, pointer to username if successfull
+ *
+ */
+static char *getuserbypath(const char *path)
+{
+ EC_INIT;
+ struct stat sbuf;
+ struct passwd *pwd;
+ char *hdir = NULL;
+
+ LOG(log_debug, logtype_afpd, "getuserbypath(\"%s\")", path);
+
+ /* does folder exists? */
+ if (stat(path, &sbuf) != 0)
+ EC_FAIL;
+
+ /* get uid of dir owner */
+ if ((pwd = getpwuid(sbuf.st_uid)) == NULL)
+ EC_FAIL;
+
+ /* does user home directory exists? */
+ if (stat(pwd->pw_dir, &sbuf) != 0)
+ EC_FAIL;
+
+ /* resolve and remove symlinks */
+ if ((hdir = realpath_safe(pwd->pw_dir)) == NULL)
+ EC_FAIL;
+
+ /* handle subdirectories, path = */
+ if (strncmp(path, hdir, strlen(hdir)) != 0)
+ EC_FAIL;
+
+ LOG(log_debug, logtype_afpd, "getuserbypath: match user: %s, home: %s, realhome: %s",
+ pwd->pw_name, pwd->pw_dir, hdir);
+
+EC_CLEANUP:
+ if (hdir)
+ free(hdir);
+ if (ret != 0)
+ return NULL;
+ return pwd->pw_name;
+}
/*!
* Search volume by path, creating user home vols as necessary
*
* (3) If there is, match "path" with "basedir regex" to get the user home parent dir
* (4) Built user home path by appending the basedir matched in (3) and appending the username
* (5) The next path element then is the username
+ * (5b) getvolbypath() assumes that the user home directory has the same name as the username.
+ * If that is not true, getuserbypath() is called and tries to retrieve the username
+ * from the directory owner, checking its validity
* (6) Append [Homes]->path subdirectory if defined
* (7) Create volume
*
p++;
EC_NULL_LOG( user = strdup(p) );
- if (prw = strchr(user, '/'))
+ if ((prw = strchr(user, '/')))
*prw++ = 0;
if (prw != 0)
subpath = prw;
strlcat(tmpbuf, user, MAXPATHLEN);
+ if (getpwnam(user) == NULL) {
+ /* (5b) */
+ char *tuser;
+ if ((tuser = getuserbypath(tmpbuf)) != NULL) {
+ free(user);
+ user = strdup(tuser);
+ }
+ }
strlcpy(obj->username, user, MAXUSERLEN);
strlcat(tmpbuf, "/", MAXPATHLEN);
/* (6) */
- if (subpathconfig = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL)) {
+ if ((subpathconfig = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))) {
/*
if (!subpath || strncmp(subpathconfig, subpath, strlen(subpathconfig)) != 0) {
EC_FAIL;
EC_INIT;
dictionary *config;
struct afp_options *options = &AFPObj->options;
- int i, c;
- const char *p, *tmp;
+ int c;
+ const char *p;
char *q, *r;
char val[MAXVAL];
options->configfile = AFPObj->cmdlineconfigfile ? strdup(AFPObj->cmdlineconfigfile) : strdup(_PATH_CONFDIR "afp.conf");
options->sigconffile = strdup(_PATH_STATEDIR "afp_signature.conf");
options->uuidconf = strdup(_PATH_STATEDIR "afp_voluuid.conf");
+#ifdef HAVE_TRACKER_SPARQL
+ options->slmod_path = strdup(_PATH_AFPDUAMPATH "slmod_sparql.so");
+#endif
+#ifdef HAVE_TRACKER_RDF
+ options->slmod_path = strdup(_PATH_AFPDUAMPATH "slmod_rdf.so");
+#endif
options->flags = OPTION_UUID | AFPObj->cmdlineflags;
if ((config = iniparser_load(AFPObj->options.configfile)) == NULL)
options->flags |= OPTION_NOZEROCONF;
if (iniparser_getboolean(config, INISEC_GLOBAL, "advertise ssh", 0))
options->flags |= OPTION_ANNOUNCESSH;
- if (iniparser_getboolean(config, INISEC_GLOBAL, "map acls", 1))
- options->flags |= OPTION_ACL2MACCESS;
- if (iniparser_getboolean(config, INISEC_GLOBAL, "keep sessions", 0))
- options->flags |= OPTION_KEEPSESSIONS;
if (iniparser_getboolean(config, INISEC_GLOBAL, "close vol", 0))
options->flags |= OPTION_CLOSEVOL;
if (!iniparser_getboolean(config, INISEC_GLOBAL, "client polling", 0))
options->flags |= OPTION_NOSENDFILE;
if (iniparser_getboolean(config, INISEC_GLOBAL, "solaris share reservations", 1))
options->flags |= OPTION_SHARE_RESERV;
+ if (iniparser_getboolean(config, INISEC_GLOBAL, "afpstats", 0))
+ options->flags |= OPTION_DBUS_AFPSTATS;
if (iniparser_getboolean(config, INISEC_GLOBAL, "afp read locks", 0))
options->flags |= OPTION_AFP_READ_LOCK;
+ if (iniparser_getboolean(config, INISEC_GLOBAL, "spotlight", 0))
+ options->flags |= OPTION_SPOTLIGHT;
if (!iniparser_getboolean(config, INISEC_GLOBAL, "save password", 1))
options->passwdbits |= PASSWD_NOSAVE;
if (iniparser_getboolean(config, INISEC_GLOBAL, "set password", 0))
options->k5service = iniparser_getstrdup(config, INISEC_GLOBAL, "k5 service", NULL);
options->k5realm = iniparser_getstrdup(config, INISEC_GLOBAL, "k5 realm", NULL);
options->listen = iniparser_getstrdup(config, INISEC_GLOBAL, "afp listen", NULL);
+ options->interfaces = iniparser_getstrdup(config, INISEC_GLOBAL, "afp interfaces", NULL);
options->ntdomain = iniparser_getstrdup(config, INISEC_GLOBAL, "nt domain", NULL);
options->addomain = iniparser_getstrdup(config, INISEC_GLOBAL, "ad domain", NULL);
options->ntseparator = iniparser_getstrdup(config, INISEC_GLOBAL, "nt separator", NULL);
options->fce_fmodwait = iniparser_getint (config, INISEC_GLOBAL, "fce holdfmod", 60);
options->sleep = iniparser_getint (config, INISEC_GLOBAL, "sleep time", 10);
options->disconnected = iniparser_getint (config, INISEC_GLOBAL, "disconnect time",24);
+ options->tracker_loglevel = iniparser_getint (config, INISEC_GLOBAL, "tracker loglevel", 1);
+
+ p = iniparser_getstring(config, INISEC_GLOBAL, "map acls", "rights");
+ if (STRCMP(p, ==, "rights"))
+ options->flags |= OPTION_ACL2MACCESS;
+ else if (STRCMP(p, ==, "mode"))
+ options->flags |= OPTION_ACL2MODE | OPTION_ACL2MACCESS;
+ else {
+ if (STRCMP(p, !=, "none")) {
+ LOG(log_error, logtype_afpd, "bad ACL mapping option: %s, defaulting to 'rights'", p);
+ options->flags |= OPTION_ACL2MACCESS;
+ }
+ }
if ((p = iniparser_getstring(config, INISEC_GLOBAL, "hostname", NULL))) {
EC_NULL_LOG( options->hostname = strdup(p) );
CONFIG_ARG_FREE(obj->options.k5realm);
if (obj->options.listen)
CONFIG_ARG_FREE(obj->options.listen);
+ if (obj->options.interfaces)
+ CONFIG_ARG_FREE(obj->options.interfaces);
if (obj->options.ntdomain)
CONFIG_ARG_FREE(obj->options.ntdomain);
if (obj->options.addomain)
CONFIG_ARG_FREE(obj->options.Cnid_port);
if (obj->options.fqdn)
CONFIG_ARG_FREE(obj->options.fqdn);
+ if (obj->options.slmod_path)
+ CONFIG_ARG_FREE(obj->options.slmod_path);
if (obj->options.unixcodepage)
CONFIG_ARG_FREE(obj->options.unixcodepage);