====================
* NEW: afpd: static generated AFP signature stored in afp_signature.conf,
cf man 5 afp_signature.conf
+* NEW: afpd: clustering support: new per volume option "cnidserver".
* FIX: afpd: prevent security attack guessing valid server accounts. afpd
now returns error -5023 for unknown users, as does AppleFileServer.
{
DIR* startdir;
- if (NULL == (cdb = cnid_open (path, 0, cnid_type, 0)) ) {
+ if (NULL == (cdb = cnid_open (path, 0, cnid_type, 0, NULL, NULL)) ) {
fprintf (stderr, "ERROR: cannot open CNID database in '%s'\n", path);
fprintf (stderr, "ERROR: check the logs for reasons, aborting\n");
return -1;
# [preexec:cmd] [root_preexec:cmd] [postexec:cmd] [root_postexec:cmd] \
# [allowed_hosts:IPv4 address[/IPv4 netmask bits]] \
# [denied_hosts:IPv4 address[/IPv4 netmask bits]] \
+# ... more, see below ...
#
# name: volume name. it can't include the ':' character
#
# OR with the client requested perm
#
# dbpath:path -> store the database stuff in the following path.
+# cnidserver:server[:port]
+# -> Query this servername or IP address (default:localhost)
+# and port (default: 4700) for CNIDs. Only used with
+# CNID backend "dbd". This option here overrides any
+# setting from afpd.conf:cnidserver.
# password:password -> set a volume password (8 characters max)
# cnidscheme:scheme -> set the cnid scheme for the volume,
# default is [:DEFAULT_CNID_SCHEME:]
/*
- * $Id: volume.c,v 1.121 2010-03-01 05:05:46 didg Exp $
+ * $Id: volume.c,v 1.122 2010-03-31 09:47:32 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#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 */
+
#ifdef FORCE_UIDGID
#warning UIDGID
#include "uid.h"
-#define VOLOPT_FORCEUID 19 /* force uid for username x */
-#define VOLOPT_FORCEGID 20 /* force gid for group x */
+#define VOLOPT_FORCEUID 19 /* force uid for username x */
+#define VOLOPT_FORCEGID 20 /* force gid for group x */
#endif /* FORCE_UIDGID */
-#define VOLOPT_UMASK 21
+#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_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 28 /* <== IMPORTANT !!!!!! */
-#define VOLOPT_NUM (VOLOPT_MAX + 1)
+#define VOLOPT_MAX 31 /* <== IMPORTANT !!!!!! */
+#define VOLOPT_NUM (VOLOPT_MAX + 1)
#define VOLPASSLEN 8
#define VOLOPT_DEFAULT ":DEFAULT:"
p = strtok(NULL, ",");
}
+ } else if (optionok(tmp, "cnidserver:", val)) {
+ setoption(options, save, VOLOPT_CNIDSERVER, val);
+
+ char *p = strrchr(val + 1, ':');
+ if (p) {
+ *p = 0;
+ setoption(options, save, VOLOPT_CNIDPORT, p);
+ }
+
+ LOG(log_debug, logtype_afpd, "CNID Server for volume '%s': %s:%s",
+ volname, val + 1, p ? p + 1 : Cnid_port);
+
} else if (optionok(tmp, "dbpath:", val)) {
setoption(options, save, VOLOPT_DBPATH, val);
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;
volume->v_cnidscheme = strdup(DEFAULT_CNID_SCHEME);
LOG(log_info, logtype_afpd, "Volume %s use CNID scheme %s.", volume->v_path, volume->v_cnidscheme);
}
- if (volume->v_dbpath)
- volume->v_cdb = cnid_open (volume->v_dbpath, volume->v_umask, volume->v_cnidscheme, flags);
- else
- volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, volume->v_cnidscheme, flags);
+
+ LOG(log_info, logtype_afpd, "%s:%s", volume->v_cnidserver, volume->v_cnidport);
+
+ volume->v_cdb = cnid_open(volume->v_dbpath ? volume->v_dbpath : volume->v_path,
+ volume->v_umask,
+ volume->v_cnidscheme,
+ flags,
+ volume->v_cnidserver ? volume->v_cnidserver : Cnid_srv,
+ volume->v_cnidport ? volume->v_cnidport : Cnid_port);
if (!volume->v_cdb) {
flags |= CNID_FLAG_MEMORY;
LOG(log_error, logtype_afpd, "Reopen volume %s using in memory temporary CNID DB.", volume->v_path);
- volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, "tdb", flags);
+ volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, "tdb", flags, NULL, NULL);
#ifdef SERVERTEXT
/* kill ourself with SIGUSR2 aka msg pending */
if (volume->v_cdb) {
if (!(volume->v_flags & AFPVOL_RO)) {
handle_special_folders( volume );
- savevolinfo(volume, Cnid_srv, Cnid_port);
+ savevolinfo(volume,
+ volume->v_cnidserver ? volume->v_cnidserver : Cnid_srv,
+ volume->v_cnidport ? volume->v_cnidport : Cnid_port);
}
/*
/*
- * $Id: cnid.h,v 1.14 2009-11-28 13:09:25 didg Exp $
+ * $Id: cnid.h,v 1.15 2010-03-31 09:47:32 franklahm Exp $
*
* Copyright (c) 2003 the Netatalk Team
* Copyright (c) 2003 Rafal Lewczuk <rlewczuk@pronet.pl>
};
typedef struct _cnid_db cnid_db;
+/*
+ * Consolidation of args passedn from main cnid_open to modules cnid_XXX_open, so
+ * that it's easier to add aditional args as required.
+ */
+struct cnid_open_args {
+ const char *dir;
+ mode_t mask;
+ uint32_t flags;
+ const char *cnidserver; /* for dbd */
+ const char *cnidport; /* for dbd */
+};
+
/*
* CNID module - represents particular CNID implementation
*/
struct _cnid_module {
char *name;
struct list_head db_list; /* CNID modules are also stored on a bidirectional list. */
- struct _cnid_db *(*cnid_open)(const char *dir, mode_t mask, u_int32_t flags);
+ struct _cnid_db *(*cnid_open)(struct cnid_open_args *args);
u_int32_t flags; /* Flags describing some CNID backend aspects. */
};
void cnid_register(struct _cnid_module *module);
/* This function opens a CNID database for selected volume. */
-struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int flags);
+struct _cnid_db *cnid_open(const char *volpath,
+ mode_t mask,
+ char *type,
+ int flags,
+ const char *cnidsrv, /* Only for dbd */
+ const char *cnidport); /* Only for dbd */
cnid_t cnid_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
char *name, const size_t len, cnid_t hint);
/*
* $Log: cnid.h,v $
- * Revision 1.14 2009-11-28 13:09:25 didg
+ * Revision 1.15 2010-03-31 09:47:32 franklahm
+ * clustering support: new per volume option cnidserver
+ *
+ * Revision 1.14 2009/11/28 13:09:25 didg
* guard against confused DB returning junk values
*
* Revision 1.13 2009/11/24 12:18:19 didg
typedef struct CNID_private {
u_int32_t magic;
char db_dir[MAXPATHLEN + 1]; /* Database directory without /.AppleDB appended */
+ char *cnidserver;
+ char *cnidport;
int fd; /* File descriptor to cnid_dbd */
char stamp[ADEDLEN_PRIVSYN]; /* db timestamp */
char *client_stamp;
/*
- * $Id: volume.h,v 1.15 2010-02-19 10:51:59 franklahm Exp $
+ * $Id: volume.h,v 1.16 2010-03-31 09:47:32 franklahm Exp $
*
* Copyright (c) 1990,1994 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
char *v_password;
char *v_cnidscheme;
char *v_dbpath;
+ char *v_cnidserver;
+ char *v_cnidport;
int v_hide; /* new volume wait until old volume is closed */
int v_new; /* volume deleted but there's a new one with the same name */
int v_deleted; /* volume open but deleted in new config file */
/* cnid_open.c */
extern struct _cnid_module cnid_cdb_module;
-extern struct _cnid_db *cnid_cdb_open (const char *, mode_t, u_int32_t flags);
+extern struct _cnid_db *cnid_cdb_open (struct cnid_open_args *args);
/* cnid_close.c */
extern void cnid_cdb_close (struct _cnid_db *);
/*
- * $Id: cnid_cdb_open.c,v 1.4 2009-11-24 12:18:19 didg Exp $
+
+ * $Id: cnid_cdb_open.c,v 1.5 2010-03-31 09:47:32 franklahm Exp $
*
* Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
* All Rights Reserved. See COPYRIGHT.
}
/* --------------- */
-struct _cnid_db *cnid_cdb_open(const char *dir, mode_t mask, u_int32_t flags _U_)
+struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args)
{
struct stat st;
char path[MAXPATHLEN + 1];
static int first = 0;
int rc;
- if (!dir || *dir == 0) {
+ if (!args->dir || *args->dir == 0) {
return NULL;
}
/* this checks .AppleDB.
We need space for dir + '/' + DBHOMELEN + '/' + DBLEN */
- if ((len = strlen(dir)) > (MAXPATHLEN - DBHOMELEN - DBLEN - 2)) {
- LOG(log_error, logtype_default, "cnid_open: Pathname too large: %s", dir);
+ if ((len = strlen(args->dir)) > (MAXPATHLEN - DBHOMELEN - DBLEN - 2)) {
+ LOG(log_error, logtype_default, "cnid_open: Pathname too large: %s", args->dir);
return NULL;
}
- if ((cdb = cnid_cdb_new(dir)) == NULL) {
+ if ((cdb = cnid_cdb_new(args->dir)) == NULL) {
LOG(log_error, logtype_default, "cnid_open: Unable to allocate memory for database");
return NULL;
}
cdb->_private = (void *) db;
db->magic = CNID_DB_MAGIC;
- strcpy(path, dir);
+ strcpy(path, args->dir);
if (path[len - 1] != '/') {
strcat(path, "/");
len++;
}
strcpy(path + len, DBHOME);
- if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~mask) < 0)) {
+ if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~args->mask) < 0)) {
LOG(log_error, logtype_default, "cnid_open: DBHOME mkdir failed for %s", path);
goto fail_adouble;
}
}
/* Open the database environment. */
- if ((rc = db->dbenv->open(db->dbenv, path, DBOPTIONS, 0666 & ~mask)) != 0) {
+ if ((rc = db->dbenv->open(db->dbenv, path, DBOPTIONS, 0666 & ~args->mask)) != 0) {
LOG(log_error, logtype_default, "cnid_open: dbenv->open (rw) of %s failed: %s", path, db_strerror(rc));
/* FIXME: This should probably go. Even if it worked, any use for a read-only DB? Didier? */
if (rc == DB_RUNRECOVERY) {
/* We can't get a full transactional environment, so multi-access
* is out of the question. Let's assume a read-only environment,
* and try to at least get a shared memory pool. */
- if ((rc = db->dbenv->open(db->dbenv, path, DB_INIT_MPOOL, 0666 & ~mask)) != 0) {
+ if ((rc = db->dbenv->open(db->dbenv, path, DB_INIT_MPOOL, 0666 & ~args->mask)) != 0) {
/* Nope, not a MPOOL, either. Last-ditch effort: we'll try to
* open the environment with no flags. */
- if ((rc = db->dbenv->open(db->dbenv, path, 0, 0666 & ~mask)) != 0) {
+ if ((rc = db->dbenv->open(db->dbenv, path, 0, 0666 & ~args->mask)) != 0) {
LOG(log_error, logtype_default, "cnid_open: dbenv->open of %s failed: %s", path, db_strerror(rc));
goto fail_lock;
}
goto fail_appinit;
}
- if ((rc = my_open(db->db_cnid, DBCNID, DBCNID, DB_BTREE, open_flag, 0666 & ~mask)) != 0) {
+ if ((rc = my_open(db->db_cnid, DBCNID, DBCNID, DB_BTREE, open_flag, 0666 & ~args->mask)) != 0) {
LOG(log_error, logtype_default, "cnid_open: Failed to open dev/ino database: %s",
db_strerror(rc));
goto fail_appinit;
goto fail_appinit;
}
- if ((rc = my_open(db->db_didname, DBCNID, DBDIDNAME, DB_BTREE, open_flag, 0666 & ~mask))) {
+ if ((rc = my_open(db->db_didname, DBCNID, DBDIDNAME, DB_BTREE, open_flag, 0666 & ~args->mask))) {
LOG(log_error, logtype_default, "cnid_open: Failed to open did/name database: %s",
db_strerror(rc));
goto fail_appinit;
goto fail_appinit;
}
- if ((rc = my_open(db->db_devino, DBCNID, DBDEVINO, DB_BTREE, open_flag, 0666 & ~mask)) != 0) {
+ if ((rc = my_open(db->db_devino, DBCNID, DBDEVINO, DB_BTREE, open_flag, 0666 & ~args->mask)) != 0) {
LOG(log_error, logtype_default, "cnid_open: Failed to open devino database: %s",
db_strerror(rc));
goto fail_appinit;
/*
- * $Id: cnid.c,v 1.12 2009-12-08 22:33:33 didg Exp $
+ * $Id: cnid.c,v 1.13 2010-03-31 09:47:32 franklahm Exp $
*
* Copyright (c) 2003 the Netatalk Team
* Copyright (c) 2003 Rafal Lewczuk <rlewczuk@pronet.pl>
}
/* Opens CNID database using particular back-end */
-struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int flags)
+struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int flags,
+ const char *cnidsrv, const char *cnidport)
{
struct _cnid_db *db;
cnid_module *mod = NULL;
struct list_head *ptr;
uid_t uid = -1;
gid_t gid = -1;
-
+
list_for_each(ptr, &modules) {
if (0 == strcmp(list_entry(ptr, cnid_module, db_list)->name, type)) {
mod = list_entry(ptr, cnid_module, db_list);
}
}
- db = mod->cnid_open(volpath, mask, flags);
+ struct cnid_open_args args = {volpath, mask, flags, cnidsrv, cnidport};
+ db = mod->cnid_open(&args);
if ((mod->flags & CNID_FLAG_SETUID) && !(flags & CNID_FLAG_MEMORY)) {
seteuid(0);
/*
- * $Id: cnid_dbd.c,v 1.16 2010-01-21 14:14:49 didg Exp $
+ * $Id: cnid_dbd.c,v 1.17 2010-03-31 09:47:32 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
}
/* ----------- */
-extern char *Cnid_srv;
-extern char *Cnid_port;
-
#define MAX_DELAY 40
/* *MUST* be < afp tickle or it's never triggered (got EINTR first) */
int len;
struct iovec iov[2];
- LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s", db->db_dir, Cnid_srv, Cnid_port);
+ LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s",
+ db->db_dir, db->cnidserver, db->cnidport);
- if ((fd = tsock_getfd(Cnid_srv, Cnid_port)) < 0)
+ if ((fd = tsock_getfd(db->cnidserver, db->cnidport)) < 0)
return -1;
len = strlen(db->db_dir);
}
/* ---------------------- */
-struct _cnid_db *cnid_dbd_open(const char *dir, mode_t mask _U_, u_int32_t flags _U_)
+struct _cnid_db *cnid_dbd_open(struct cnid_open_args *args)
{
CNID_private *db = NULL;
struct _cnid_db *cdb = NULL;
- if (!dir) {
+ if (!args->dir) {
return NULL;
}
- if ((cdb = cnid_dbd_new(dir)) == NULL) {
+ if ((cdb = cnid_dbd_new(args->dir)) == NULL) {
LOG(log_error, logtype_cnid, "cnid_open: Unable to allocate memory for database");
return NULL;
}
/* We keep a copy of the directory in the db structure so that we can
transparently reconnect later. */
- strcpy(db->db_dir, dir);
+ strcpy(db->db_dir, args->dir);
db->magic = CNID_DB_MAGIC;
db->fd = -1;
+ db->cnidserver = strdup(args->cnidserver);
+ db->cnidport = strdup(args->cnidport);
LOG(log_debug, logtype_cnid, "cnid_dbd_open: Finished initializing cnid dbd module for volume '%s'", db->db_dir);
/*
- * $Id: cnid_dbd.h,v 1.5 2009-11-24 12:18:19 didg Exp $
+ * $Id: cnid_dbd.h,v 1.6 2010-03-31 09:47:32 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
#include <atalk/cnid.h>
extern struct _cnid_module cnid_dbd_module;
-extern struct _cnid_db *cnid_dbd_open (const char *, mode_t, u_int32_t flags);
+extern struct _cnid_db *cnid_dbd_open (struct cnid_open_args *args);
extern void cnid_dbd_close (struct _cnid_db *);
extern cnid_t cnid_dbd_add (struct _cnid_db *, const struct stat *, const cnid_t,
char *, const size_t, cnid_t);
/*
- * $Id: cnid_last.c,v 1.4 2009-11-24 12:18:20 didg Exp $
+ * $Id: cnid_last.c,v 1.5 2010-03-31 09:47:32 franklahm Exp $
*
* Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
* All Rights Reserved. See COPYRIGHT.
return cdb;
}
-struct _cnid_db *cnid_last_open(const char *dir, mode_t mask _U_, u_int32_t flags _U_)
+struct _cnid_db *cnid_last_open(struct cnid_open_args *args)
{
struct _cnid_db *cdb;
- if (!dir) {
+ if (!args->dir) {
return NULL;
}
- if ((cdb = cnid_last_new(dir)) == NULL) {
+ if ((cdb = cnid_last_new(args->dir)) == NULL) {
LOG(log_error, logtype_default, "cnid_open: Unable to allocate memory for database");
return NULL;
}
};
extern struct _cnid_module cnid_last_module;
-extern struct _cnid_db *cnid_last_open (const char *, mode_t, u_int32_t flags);
+extern struct _cnid_db *cnid_last_open (struct cnid_open_args *args);
extern void cnid_last_close (struct _cnid_db *);
extern cnid_t cnid_last_add (struct _cnid_db *, const struct stat *, const cnid_t,
char *, const size_t, cnid_t);
/* cnid_open.c */
extern struct _cnid_module cnid_tdb_module;
-extern struct _cnid_db *cnid_tdb_open (const char *, mode_t, u_int32_t flags);
+extern struct _cnid_db *cnid_tdb_open (struct cnid_open_args *args);
/* cnid_close.c */
extern void cnid_tdb_close (struct _cnid_db *);
/*
- * $Id: cnid_tdb_open.c,v 1.7 2009-11-24 15:44:56 didg Exp $
+ * $Id: cnid_tdb_open.c,v 1.8 2010-03-31 09:47:32 franklahm Exp $
*
* Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
* All Rights Reserved. See COPYRIGHT.
}
/* ---------------------------- */
-struct _cnid_db *cnid_tdb_open(const char *dir, mode_t mask, u_int32_t flags)
+struct _cnid_db *cnid_tdb_open(struct cnid_open_args *args)
{
struct stat st;
struct _cnid_db *cdb;
int hash_size = 131071;
int tdb_flags = 0;
- if (!dir) {
+ if (!args->dir) {
/* note: dir and path are not used for in memory db */
return NULL;
}
- if ((len = strlen(dir)) > (MAXPATHLEN - DBLEN - 1)) {
- LOG(log_error, logtype_default, "tdb_open: Pathname too large: %s", dir);
+ if ((len = strlen(args->dir)) > (MAXPATHLEN - DBLEN - 1)) {
+ LOG(log_error, logtype_default, "tdb_open: Pathname too large: %s", args->dir);
return NULL;
}
- if ((cdb = cnid_tdb_new(dir)) == NULL) {
+ if ((cdb = cnid_tdb_new(args->dir)) == NULL) {
LOG(log_error, logtype_default, "tdb_open: Unable to allocate memory for tdb");
return NULL;
}
- strcpy(path, dir);
+ strcpy(path, args->dir);
if (path[len - 1] != '/') {
strcat(path, "/");
len++;
}
strcpy(path + len, DBHOME);
- if (!(flags & CNID_FLAG_MEMORY)) {
- if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~mask) < 0)) {
+ if (!(args->flags & CNID_FLAG_MEMORY)) {
+ if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~args->mask) < 0)) {
LOG(log_error, logtype_default, "tdb_open: DBHOME mkdir failed for %s", path);
goto fail;
}
path[len + DBHOMELEN] = '\0';
strcat(path, DBCNID);
- db->tdb_cnid = tdb_open(path, hash_size, tdb_flags , O_RDWR | O_CREAT, 0666 & ~mask);
+ db->tdb_cnid = tdb_open(path, hash_size, tdb_flags , O_RDWR | O_CREAT, 0666 & ~args->mask);
if (!db->tdb_cnid) {
LOG(log_error, logtype_default, "tdb_open: unable to open tdb", path);
goto fail;