#include <inttypes.h>
#include <time.h>
#include <regex.h>
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+#if HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
#include <atalk/afp.h>
#include <atalk/util.h>
q++;
}
} else if (IS_VAR(p, "$c")) {
- DSI *dsi = obj->dsi;
- if (obj->username[0]) {
+ if (IS_AFP_SESSION(obj)) {
+ DSI *dsi = obj->dsi;
len = sprintf(dest, "%s:%u",
getip_string((struct sockaddr *)&dsi->client),
getip_port((struct sockaddr *)&dsi->client));
- } else {
+ dest += len;
+ destlen -= len;
}
- dest += len;
- destlen -= len;
} else if (IS_VAR(p, "$d")) {
q = path;
} else if (pwd && IS_VAR(p, "$f")) {
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(val) );
+ }
else
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);
+ }
EC_NULL( volume->v_maccodepage = strdup(val) );
+ }
else
- EC_NULL( volume->v_maccodepage = strdup(obj->options.maccodepage) );
+ EC_NULL( volume->v_maccodepage = strdup(obj->options.maccodepage) );
bstring dbpath;
EC_NULL_LOG( val = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol dbpath", _PATH_STATEDIR "CNID/") );
if (getoption_bool(obj->iniconfig, section, "read only", preset, 0))
volume->v_flags |= AFPVOL_RO;
- if (!getoption_bool(obj->iniconfig, section, "hex encoding", preset, 1))
- volume->v_flags |= AFPVOL_NOHEX;
- if (getoption_bool(obj->iniconfig, section, "use dots", preset, 1))
- volume->v_flags |= AFPVOL_USEDOTS;
if (getoption_bool(obj->iniconfig, section, "invisible dots", preset, 0))
volume->v_flags |= AFPVOL_INV_DOTS;
if (!getoption_bool(obj->iniconfig, section, "stat vol", preset, 1))
volume->v_ad_options |= ADVOL_INVDOTS;
/* Mac to Unix conversion flags*/
- 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;
volume->v_mtou_flags |= CONV_TOLOWER;
/* Unix to Mac conversion flags*/
- volume->v_utom_flags = CONV_IGNORE | CONV_UNESCAPEHEX;
+ volume->v_utom_flags = CONV_IGNORE;
if ((volume->v_casefold & AFPVOL_UTOMUPPER))
volume->v_utom_flags |= CONV_TOUPPER;
else if ((volume->v_casefold & AFPVOL_UTOMLOWER))
static int readvolfile(AFPObj *obj, const struct passwd *pwent)
{
EC_INIT;
+ static int regexerr = -1;
+ static regex_t reg;
char path[MAXPATHLEN + 1];
char volname[AFPVOL_U8MNAMELEN + 1];
char tmp[MAXPATHLEN + 1];
- const char *preset, *default_preset, *p;
+ 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 (STRCMP(secname, ==, INISEC_HOMES)) {
have_uservol = 1;
- if (obj->username[0] == 0
+ if (!IS_AFP_SESSION(obj)
|| strcmp(obj->username, obj->options.guest) == 0)
/* not an AFP session, but cnid daemon, dbd or ad util, or guest login */
continue;
+ if (pwent->pw_dir == NULL || STRCMP("", ==, pwent->pw_dir))
+ /* no user home */
+ continue;
+
+ /* check if user home matches our "basedir regex" */
+ if ((basedir = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL)) == NULL) {
+ LOG(log_error, logtype_afpd, "\"basedir regex =\" must be defined in [Homes] section");
+ continue;
+ }
+ LOG(log_debug, logtype_afpd, "readvolfile: basedir regex: '%s'", basedir);
+
+ if (regexerr != 0 && (regexerr = regcomp(®, basedir, REG_EXTENDED)) != 0) {
+ char errbuf[1024];
+ regerror(regexerr, ®, errbuf, sizeof(errbuf));
+ LOG(log_debug, logtype_default, "readvolfile: bad basedir regex: %s", errbuf);
+ }
+
+ if (regexec(®, pwent->pw_dir, 1, match, 0) == REG_NOMATCH) {
+ LOG(log_debug, logtype_default, "readvolfile: user home \"%s\" doesn't match basedir regex \"%s\"",
+ pwent->pw_dir, basedir);
+ continue;
+ }
+
strlcpy(tmp, pwent->pw_dir, MAXPATHLEN);
strlcat(tmp, "/", MAXPATHLEN);
if (p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))
/* do variable substitution for volume name */
if (STRCMP(secname, ==, INISEC_HOMES)) {
- if (p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "home name", "$u's home"))
- strlcpy(tmp, p, MAXPATHLEN);
- else
- strlcpy(tmp, p, MAXPATHLEN);
+ p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "home name", "$u's home");
+ if (strstr(p, "$u") == NULL) {
+ LOG(log_warning, logtype_afpd, "home name must contain $u.");
+ p = "$u's home";
+ }
+ strlcpy(tmp, p, MAXPATHLEN);
} else {
strlcpy(tmp, secname, AFPVOL_U8MNAMELEN);
}
* @param obj (r) handle
* @param delvol_fn (r) callback called for deleted volumes
*/
-int load_volumes(AFPObj *obj, void (*delvol_fn)(struct vol *))
+int load_volumes(AFPObj *obj, void (*delvol_fn)(const AFPObj *obj, struct vol *))
{
EC_INIT;
int fd = -1;
goto EC_CLEANUP;
have_uservol = 0;
for (vol = Volumes; vol; vol = vol->v_next) {
- if (vol->v_flags & AFPVOL_UNIX_CTXT)
- continue;
vol->v_deleted = 1;
}
} else {
if (vol->v_deleted) {
LOG(log_debug, logtype_afpd, "load_volumes: deleted: %s", vol->v_localname);
if (delvol_fn)
- delvol_fn(vol);
+ delvol_fn(obj, vol);
vol = Volumes;
}
}
struct vol *getvolbypath(AFPObj *obj, const char *path)
{
EC_INIT;
+ static int regexerr = -1;
+ static regex_t reg;
struct vol *vol;
struct vol *tmp;
const struct passwd *pw;
char tmpbuf[MAXPATHLEN + 1];
const char *secname, *basedir, *p = NULL, *subpath = NULL, *subpathconfig;
char *user = NULL, *prw;
- int regexerr = -1;
- static regex_t reg;
regmatch_t match[1];
LOG(log_debug, logtype_afpd, "getvolbypath(\"%s\")", path);
if (prw != 0)
subpath = prw;
- strlcpy(obj->username, user, MAXUSERLEN);
strlcat(tmpbuf, user, MAXPATHLEN);
+ strlcat(obj->username, user, MAXUSERLEN);
strlcat(tmpbuf, "/", MAXPATHLEN);
/* (6) */
/* do variable substitution for volume name */
p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "home name", "$u's home");
+ if (strstr(p, "$u") == NULL)
+ p = "$u's home";
strlcpy(tmpbuf, p, AFPVOL_U8MNAMELEN);
EC_NULL_LOG( volxlate(obj, volname, sizeof(volname) - 1, tmpbuf, pw, volpath, NULL) );
/*!
* Initialize an AFPObj and options from ini config file
*/
-int afp_config_parse(AFPObj *AFPObj)
+int afp_config_parse(AFPObj *AFPObj, char *processname)
{
EC_INIT;
dictionary *config;
char *q, *r;
char val[MAXVAL];
+ if (processname != NULL)
+ set_processname(processname);
+
AFPObj->afp_version = 11;
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");
- options->flags = OPTION_ACL2MACCESS | OPTION_UUID | OPTION_SERVERNOTIF | AFPObj->cmdlineflags;
+ options->flags = OPTION_UUID | AFPObj->cmdlineflags;
if ((config = iniparser_load(AFPObj->options.configfile)) == NULL)
return -1;
options->logconfig = iniparser_getstrdup(config, INISEC_GLOBAL, "log level", "default:note");
options->logfile = iniparser_getstrdup(config, INISEC_GLOBAL, "log file", NULL);
+ setuplog(options->logconfig, options->logfile);
+
/* "server options" boolean options */
if (!iniparser_getboolean(config, INISEC_GLOBAL, "zeroconf", 1))
options->flags |= OPTION_NOZEROCONF;
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", 1))
+ if (!iniparser_getboolean(config, INISEC_GLOBAL, "client polling", 0))
options->flags |= OPTION_SERVERNOTIF;
if (!iniparser_getboolean(config, INISEC_GLOBAL, "use sendfile", 1))
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, "afp read locks", 0))
+ options->flags |= OPTION_AFP_READ_LOCK;
if (!iniparser_getboolean(config, INISEC_GLOBAL, "save password", 1))
options->passwdbits |= PASSWD_NOSAVE;
if (iniparser_getboolean(config, INISEC_GLOBAL, "set password", 0))
options->passwdbits |= PASSWD_SET;
/* figure out options w values */
- options->loginmesg = iniparser_getstrdup(config, INISEC_GLOBAL, "login message", "");
+ options->loginmesg = iniparser_getstrdup(config, INISEC_GLOBAL, "login message", NULL);
options->guest = iniparser_getstrdup(config, INISEC_GLOBAL, "guest account", "nobody");
options->passwdfile = iniparser_getstrdup(config, INISEC_GLOBAL, "passwd file",_PATH_AFPDPWFILE);
options->uampath = iniparser_getstrdup(config, INISEC_GLOBAL, "uam path", _PATH_AFPDUAMPATH);
/* unix charset is in [G] only */
if (!(p = iniparser_getstring(config, INISEC_GLOBAL, "unix charset", NULL))) {
- options->unixcharset = CH_UNIX;
- options->unixcodepage = strdup("LOCALE");
+ options->unixcodepage = strdup("UTF8");
+ charset_names[CH_UNIX] = strdup("UTF8");
} 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 charset to '%s' failed", p);
- } else {
- options->unixcodepage = strdup(p);
+ if (strcasecmp(p, "LOCALE") == 0) {
+#if defined(CODESET)
+ setlocale(LC_ALL, "");
+ p = nl_langinfo(CODESET);
+ LOG(log_debug, logtype_afpd, "Locale charset is '%s'", p);
+#else /* system doesn't have LOCALE support */
+ LOG(log_warning, logtype_afpd, "system doesn't have LOCALE support");
+ p = strdup("UTF8");
+#endif
+ }
+ if (strcasecmp(p, "UTF-8") == 0) {
+ p = strdup("UTF8");
}
+ options->unixcodepage = strdup(p);
+ charset_names[CH_UNIX] = strdup(p);
}
+ options->unixcharset = CH_UNIX;
+ LOG(log_debug, logtype_afpd, "Global unix charset is %s", options->unixcodepage);
- /* vol charset is in [G[ and [V] */
+ /* vol charset is in [G] and [V] */
if (!(p = iniparser_getstring(config, INISEC_GLOBAL, "vol charset", NULL))) {
- options->volcodepage = strdup("UTF8");
+ options->volcodepage = strdup(options->unixcodepage);
} else {
+ if (strcasecmp(p, "UTF-8") == 0) {
+ p = strdup("UTF8");
+ }
options->volcodepage = strdup(p);
}
-
+ LOG(log_debug, logtype_afpd, "Global vol charset is %s", options->volcodepage);
+
/* mac charset is in [G] and [V] */
if (!(p = iniparser_getstring(config, INISEC_GLOBAL, "mac charset", NULL))) {
- options->maccharset = CH_MAC;
options->maccodepage = strdup("MAC_ROMAN");
+ charset_names[CH_MAC] = 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 mac charset to '%s' failed", p);
- } else {
- options->maccodepage = strdup(p);
+ if (strncasecmp(p, "MAC", 3) != 0) {
+ LOG(log_warning, logtype_afpd, "Is '%s' really mac charset? ", p);
}
+ options->maccodepage = strdup(p);
+ charset_names[CH_MAC] = strdup(p);
}
+ options->maccharset = CH_MAC;
+ LOG(log_debug, logtype_afpd, "Global mac charset is %s", options->maccodepage);
/* Check for sane values */
if (options->tickleval <= 0)