]> arthur.barton.de Git - netatalk.git/commitdiff
Use a regex to find user homes basedir
authorFrank Lahm <franklahm@googlemail.com>
Thu, 1 Mar 2012 11:53:05 +0000 (12:53 +0100)
committerFrank Lahm <franklahm@googlemail.com>
Thu, 1 Mar 2012 11:53:05 +0000 (12:53 +0100)
include/atalk/adouble.h
include/atalk/errchk.h
libatalk/adouble/ad_open.c
libatalk/util/netatalk_conf.c
libatalk/vfs/vfs.c

index 9291e9c261bac90caab9b237d72782f4f7644616..72106aef6719a401591f20aa15a91d422f762fe4 100644 (file)
@@ -404,7 +404,7 @@ extern int ad_metadata    (const char *, int, struct adouble *);
 extern int ad_metadataat  (int, const char *, int, struct adouble *);
 extern mode_t ad_hf_mode(mode_t mode);
 extern int ad_convert(const char *path, const struct stat *sp, const struct vol *vol);
-
+extern int ad_valid_header_osx(const char *path);
 /* ad_read.c/ad_write.c */
 extern int     sys_ftruncate(int fd, off_t length);
 extern ssize_t ad_read(struct adouble *, uint32_t, off_t, char *, size_t);
index 78e530a8e95227eac265a01e27dcdedbc7081216..094065b9d5a7d6a799680eba3f2eac91c197e65a 100644 (file)
 #define EC_INIT int ret = 0
 #define EC_STATUS(a) ret = (a)
 #define EC_FAIL do { ret = -1; goto cleanup; } while (0)
+#define EC_FAIL_LOG(a, ...)                     \
+    do {               \
+        LOG(log_error, logtype_default, a, __VA_ARGS__);   \
+        ret = -1;      \
+        goto cleanup;  \
+    } while (0)
 #define EC_CLEANUP cleanup
 #define EC_EXIT return ret
 
index ae49b460869d41d265649461e86fdcdd3e995095..8c0c21d099bcf77150919189b808b7d16e3ca7bf 100644 (file)
@@ -510,6 +510,39 @@ static int ad_header_read(const char *path _U_, struct adouble *ad, const struct
     return 0;
 }
 
+/* error here means it's not ad ._ adouble:osx file and thus we return 1 */
+int ad_valid_header_osx(const char *path)
+{
+    EC_INIT;
+    int fd;
+    struct adouble      adosx;
+    char                *buf = &adosx.ad_data[0];
+    ssize_t             header_len;
+
+    EC_NEG1( fd = open(path, O_RDONLY) );
+
+    /* read the header */
+    EC_NEG1( header_len = read(fd, buf, AD_DATASZ_OSX) );
+
+    if (header_len < AD_HEADER_LEN)
+        EC_FAIL;
+
+    memcpy(&adosx.ad_magic, buf, sizeof(adosx.ad_magic));
+    memcpy(&adosx.ad_version, buf + ADEDOFF_VERSION, sizeof(adosx.ad_version));
+    adosx.ad_magic = ntohl(adosx.ad_magic);
+    adosx.ad_version = ntohl(adosx.ad_version);
+
+    if ((adosx.ad_magic != AD_MAGIC) || (adosx.ad_version != AD_VERSION2)) {
+        LOG(log_error, logtype_afpd, "ad_valid_header_osx: not an adouble:ox file");
+        EC_FAIL;
+    }
+
+EC_CLEANUP:
+    if (ret != 0)
+        return 1;
+    return 0;
+}
+
 /* Read an ._ file, only uses the resofork, finderinfo is taken from EA */
 static int ad_header_read_osx(const char *path _U_, struct adouble *ad, const struct stat *hst)
 {
index 507bd210e65f268c1d0f9761502f7f2daf693d2d..93ff14781204433dad70f015da298f351c4bf453 100644 (file)
@@ -30,6 +30,7 @@
 #include <arpa/inet.h>
 #include <inttypes.h>
 #include <time.h>
+#include <regex.h>
 
 #include <atalk/afp.h>
 #include <atalk/util.h>
@@ -947,14 +948,10 @@ static int readvolfile(AFPObj *obj, const struct passwd *pwent)
             continue;
         if (STRCMP(secname, ==, INISEC_HOMES)) {
             have_uservol = 1;
-            if (obj->username[0] == 0)
+            if (!obj->uid)
                 /* not an AFP session, but cnid daemon, dbd or ad util */
                 continue;
-            if ((p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir", NULL)) == NULL)
-                continue;
-            strlcpy(tmp, p, MAXPATHLEN);
-            strlcat(tmp, "/", MAXPATHLEN);
-            strlcat(tmp, obj->username, MAXPATHLEN);
+            strlcpy(tmp, pwent->pw_dir, MAXPATHLEN);
             strlcat(tmp, "/", MAXPATHLEN);
             if (p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))
                 strlcat(tmp, p, MAXPATHLEN);
@@ -1190,6 +1187,9 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
     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);
 
@@ -1202,7 +1202,7 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
 
     /* might be a user home, check for that and create a volume if yes */
     if (!have_uservol)
-        EC_FAIL;
+        EC_FAIL_LOG("getvolbypath(\"%s\"): no volume for path", path);
 
     int secnum = iniparser_getnsec(obj->iniconfig);
 
@@ -1213,16 +1213,30 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
     }
 
     if (STRCMP(secname, !=, INISEC_HOMES))
-        EC_FAIL;
-
-    EC_NULL_LOG( basedir = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir", NULL) );
+        EC_FAIL_LOG("getvolbypath(\"%s\"): no volume for path", path);
 
+    EC_NULL_LOG( basedir = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL) );
     LOG(log_debug, logtype_afpd, "getvolbypath: user home section: '%s', basedir: '%s'", secname, basedir);
 
-    if (strncmp(path, basedir, strlen(basedir)) != 0)
-        EC_FAIL;
+    if (regexerr != 0 && (regexerr = regcomp(&reg, basedir, REG_EXTENDED)) != 0) {
+        char errbuf[1024];
+        regerror(regexerr, &reg, errbuf, sizeof(errbuf));
+        printf("error: %s\n", errbuf);
+        EC_FAIL_LOG("getvolbypath(\"%s\"): bad basedir regex: %s", errbuf);
+    }
+
+    if (regexec(&reg, path, 1, match, 0) == REG_NOMATCH)
+        EC_FAIL_LOG("getvolbypath(\"%s\"): no volume for path", path);
+
+    if (match[0].rm_eo - match[0].rm_so > MAXPATHLEN)
+        EC_FAIL_LOG("getvolbypath(\"%s\"): path too long", path);
+
+    strncpy(tmpbuf, path + match[0].rm_so, match[0].rm_eo - match[0].rm_so);
+    tmpbuf[match[0].rm_eo - match[0].rm_so] = 0;
+
+    LOG(log_debug, logtype_afpd, "getvolbypath: basedir regex: '%s', basedir match: \"%s\"",
+        basedir, tmpbuf);
 
-    strlcpy(tmpbuf, basedir, MAXPATHLEN);
     strlcat(tmpbuf, "/", MAXPATHLEN);
 
     p = path + strlen(basedir);
index befa4aa7a7887e7c6b2be6a4cff5701c975f82b8..49590af6d9fe8ba2617d0ad6be390226ed67fd3f 100644 (file)
@@ -474,10 +474,10 @@ static int validupath_ea(VFS_FUNC_ARGS_VALIDUPATH)
 
 #ifndef HAVE_EAFD
     if (name[1] == '_')
-        return 0;
+        return ad_valid_header_osx(name);
 #endif
-    return netatalk_name(name) && strcasecmp(name,".Parent");
-}             
+    return 1;
+}
 
 /* ----------------- */
 static int RF_chown_ea(VFS_FUNC_ARGS_CHOWN)