/*
- * $Id: volume.c,v 1.51.2.7.2.33.2.16 2009-01-13 01:05:53 didg Exp $
+ * $Id: volume.c,v 1.51.2.7.2.33.2.24 2009-03-26 11:53:32 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#define VOLOPT_FORCEUID 19 /* force uid for username x */
#define VOLOPT_FORCEGID 20 /* force gid for group x */
-#define VOLOPT_UMASK 21
-#define VOLOPT_DFLTPERM 22
-#else
-#define VOLOPT_UMASK 19
-#define VOLOPT_DFLTPERM 20
#endif /* FORCE_UIDGID */
+#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_MAX (VOLOPT_DFLTPERM +1)
#define VOLOPT_NUM (VOLOPT_MAX + 1)
} else if (optionok(tmp, "umask:", val)) {
options[VOLOPT_UMASK].i_value = (int)strtol(val +1, NULL, 8);
+ } else if (optionok(tmp, "dperm:", val)) {
+ options[VOLOPT_DPERM].i_value = (int)strtol(val+1, NULL, 8);
+ } else if (optionok(tmp, "fperm:", val)) {
+ options[VOLOPT_FPERM].i_value = (int)strtol(val+1, NULL, 8);
} else if (optionok(tmp, "perm:", val)) {
options[VOLOPT_DFLTPERM].i_value = (int)strtol(val+1, NULL, 8);
} else if (optionok(tmp, "mapchars:",val)) {
} else if (optionok(tmp, "postexec:", val)) {
setoption(options, save, VOLOPT_POSTEXEC, val);
+ } else if (optionok(tmp, "allowed_hosts:", val)) {
+ setoption(options, save, VOLOPT_ALLOWED_HOSTS, val);
+
+ } else if (optionok(tmp, "denied_hosts:", val)) {
+ setoption(options, save, VOLOPT_DENIED_HOSTS, val);
+
} else {
/* ignore unknown options */
LOG(log_debug, logtype_afpd, "ignoring unknown volume option: %s", tmp);
/* -----------------
* FIXME should be define elsewhere
*/
+static int netatalk_name(const char *name)
+{
+ return strcasecmp(name,".AppleDB") &&
+ strcasecmp(name,".AppleDouble") &&
+ strcasecmp(name,".AppleDesktop");
+}
+
static int validupath_adouble(const struct vol *vol, const char *name)
{
return (vol->v_flags & AFPVOL_USEDOTS) ?
- strcasecmp(name,".AppleDB") &&
- strcasecmp(name,".AppleDouble") &&
- strcasecmp(name,".AppleDesktop") &&
- strcasecmp(name,".Parent")
- : name[0] != '.';
+ netatalk_name(name) && strcasecmp(name,".Parent"): name[0] != '.';
}
/* ----------------- */
static int validupath_osx(const struct vol *vol _U_, const char *name)
{
- return strncasecmp(name,".Apple", 6) && strncasecmp(name,"._", 2);
+ return strncmp(name,"._", 2) && (
+ (vol->v_flags & AFPVOL_USEDOTS) ? netatalk_name(name): name[0] != '.');
}
/* ---------------- */
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;
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;
initvoladouble(volume);
volume->v_next = Volumes;
int c;
p = buf;
- while ((EOF != ( c = getc( fp )) ) && ( size > 0 )) {
+ while ((EOF != ( c = getc( fp )) ) && ( size > 1 )) {
if ( c == '\n' || c == '\r' ) {
+ if (p != buf && *(p -1) == '\\') {
+ p--;
+ size++;
+ continue;
+ }
*p++ = '\n';
break;
} else {
return 0;
}
+static int hostaccessvol(type, volname, args, obj)
+int type;
+char *volname;
+const char *args;
+const AFPObj *obj;
+{
+ char buf[MAXPATHLEN + 1], *p, *b;
+ DSI *dsi = obj->handle;
+
+ if (!args)
+ return -1;
+
+ strlcpy(buf, args, sizeof(buf));
+ if ((p = strtok_r(buf, ",", &b)) == NULL) /* nothing, return okay */
+ return -1;
+
+ while (p) {
+ if (obj->proto == AFPPROTO_DSI) {
+ struct in_addr mask, net;
+ char *net_char, *mask_char;
+ int mask_int;
+
+ net_char = strtok(p, "/");
+ mask_char = strtok(NULL,"/");
+ if (mask_char == NULL) {
+ mask_int = 32;
+ } else {
+ mask_int = atoi(mask_char);
+ }
+
+ // convert the integer netmask to a bitmask in network order
+ mask.s_addr = htonl(-1 - ((1 << (32 - mask_int)) - 1));
+ net.s_addr = inet_addr(net_char) & mask.s_addr;
+
+ if ((dsi->client.sin_addr.s_addr & mask.s_addr) == net.s_addr) {
+ if (type == VOLOPT_DENIED_HOSTS)
+ LOG(log_info, logtype_afpd, "AFP access denied for client IP '%s' to volume '%s' by denied list",
+ inet_ntoa(dsi->client.sin_addr), volname);
+ return 1;
+ }
+ }
+ p = strtok_r(NULL, ",", &b);
+ }
+ if (type == VOLOPT_ALLOWED_HOSTS)
+ LOG(log_info, logtype_afpd, "AFP access denied for client IP '%s' to volume '%s', not in allowed list",
+ inet_ntoa(dsi->client.sin_addr), volname);
+ return 0;
+}
+
static void setextmap( ext, type, creator, user)
char *ext, *type, *creator;
int user;
allow -> either no list (-1), or in list (1)
deny -> either no list (-1), or not in list (0) */
if (accessvol(options[VOLOPT_ALLOW].c_value, obj->username) &&
- (accessvol(options[VOLOPT_DENY].c_value, obj->username) < 1)) {
+ (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
LOG(log_debug, logtype_afpd,"Error writing .volinfo file: buffer too small, %s", buf);
- if (write( fd, buf, strlen(buf)) < 0) {
+ if (write( fd, buf, strlen(buf)) < 0 || ftruncate(fd, strlen(buf)) < 0 ) {
LOG(log_debug, logtype_afpd,"Error writing .volinfo file: %s", strerror(errno));
- goto done;
}
- ftruncate(fd, strlen(buf));
-done:
lock.l_type = F_UNLCK;
fcntl(fd, F_SETLK, &lock);
close (fd);