[dovecot-cvs] dovecot/src/auth db-passwd-file.c, 1.12, 1.13 db-passwd-file.h, 1.5, 1.6 passdb-passwd-file.c, 1.18, 1.19 userdb-passwd-file.c, 1.14, 1.15

cras at dovecot.org cras at dovecot.org
Fri Jul 22 15:42:59 EEST 2005


Update of /var/lib/cvs/dovecot/src/auth
In directory talvi:/tmp/cvs-serv24394

Modified Files:
	db-passwd-file.c db-passwd-file.h passdb-passwd-file.c 
	userdb-passwd-file.c 
Log Message:
Added support for variables in passwd-file path.



Index: db-passwd-file.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/db-passwd-file.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- db-passwd-file.c	12 Jul 2005 12:58:47 -0000	1.12
+++ db-passwd-file.c	22 Jul 2005 12:42:57 -0000	1.13
@@ -11,6 +11,7 @@
 #include "istream.h"
 #include "hash.h"
 #include "str.h"
+#include "var-expand.h"
 
 #include <stdlib.h>
 #include <unistd.h>
@@ -120,7 +121,21 @@
 	hash_insert(pw->users, pu->user_realm, pu);
 }
 
-static void passwd_file_open(struct passwd_file *pw)
+static struct passwd_file *
+passwd_file_new(struct db_passwd_file *db, const char *expanded_path)
+{
+	struct passwd_file *pw;
+
+	pw = i_new(struct passwd_file, 1);
+	pw->db = db;
+	pw->path = i_strdup(expanded_path);
+	pw->fd = -1;
+
+	hash_insert(db->files, pw->path, pw);
+	return pw;
+}
+
+static int passwd_file_open(struct passwd_file *pw)
 {
 	struct istream *input;
 	const char *const *args;
@@ -129,11 +144,16 @@
 	int fd;
 
 	fd = open(pw->path, O_RDONLY);
-	if (fd == -1)
-		i_fatal("passwd-file %s: Can't open file: %m", pw->path);
+	if (fd == -1) {
+		i_error("passwd-file %s: Can't open file: %m", pw->path);
+		return FALSE;
+	}
 
-	if (fstat(fd, &st) != 0)
-		i_fatal("passwd-file %s: fstat() failed: %m", pw->path);
+	if (fstat(fd, &st) != 0) {
+		i_error("passwd-file %s: fstat() failed: %m", pw->path);
+		(void)close(fd);
+		return FALSE;
+	}
 
 	pw->fd = fd;
 	pw->stamp = st.st_mtime;
@@ -153,11 +173,12 @@
 			/* at least two fields */
 			const char *no_args = NULL;
 			passwd_file_add(pw, args[0], args[1],
-					pw->userdb ? args+2 : &no_args);
+					pw->db->userdb ? args+2 : &no_args);
 		}
 		t_pop();
 	}
 	i_stream_unref(input);
+	return TRUE;
 }
 
 static void passwd_file_close(struct passwd_file *pw)
@@ -178,51 +199,157 @@
 	}
 }
 
-static void passwd_file_sync(struct passwd_file *pw)
+static void passwd_file_free(struct passwd_file *pw)
+{
+	hash_remove(pw->db->files, pw->path);
+
+	passwd_file_close(pw);
+	i_free(pw->path);
+	i_free(pw);
+}
+
+static int passwd_file_sync(struct passwd_file *pw)
 {
 	struct stat st;
 
-	if (stat(pw->path, &st) < 0)
-		i_fatal("passwd-file %s: stat() failed: %m", pw->path);
+	if (stat(pw->path, &st) < 0) {
+		/* with variables don't give hard errors, or errors about
+		   nonexisting files */
+		if (errno != ENOENT)
+			i_error("passwd-file %s: stat() failed: %m", pw->path);
+
+		passwd_file_free(pw);
+		return FALSE;
+	}
 
 	if (st.st_mtime != pw->stamp) {
 		passwd_file_close(pw);
-		passwd_file_open(pw);
+		return passwd_file_open(pw);
 	}
+	return TRUE;
 }
 
-struct passwd_file *db_passwd_file_parse(const char *path, int userdb)
+struct db_passwd_file *db_passwd_file_parse(const char *path, int userdb)
 {
-	struct passwd_file *pw;
+	struct db_passwd_file *db;
+	const char *p;
+	int percents = FALSE;
 
-	pw = i_new(struct passwd_file, 1);
-	pw->refcount = 1;
-	pw->path = i_strdup(path);
-	pw->userdb = userdb;
+	db = i_new(struct db_passwd_file, 1);
+	db->refcount = 1;
+	db->userdb = userdb;
+	db->files = hash_create(default_pool, default_pool, 100,
+				str_hash, (hash_cmp_callback_t *)strcmp);
 
-	passwd_file_open(pw);
-	return pw;
+	for (p = path; *p != '\0'; p++) {
+		if (*p == '%' && p[1] != '\0') {
+			p++;
+			switch (var_get_key(p)) {
+			case 'd':
+				db->domain_var = TRUE;
+				db->vars = TRUE;
+				break;
+			case '%':
+				percents = TRUE;
+				break;
+			default:
+				db->vars = TRUE;
+				break;
+			}
+		}
+	}
+
+	if (percents && !db->vars) {
+		/* just extra escaped % chars. remove them. */
+		struct var_expand_table empty_table[1];
+		string_t *dest;
+
+		empty_table[0].key = '\0';
+		dest = t_str_new(256);
+		var_expand(dest, path, empty_table);
+		path = str_c(dest);
+	}
+
+	db->path = i_strdup(path);
+
+	if (!db->vars) {
+		/* no variables, open the file immediately */
+		db->default_file = passwd_file_new(db, path);
+		if (!passwd_file_open(db->default_file))
+			exit(FATAL_DEFAULT);
+	}
+	return db;
 }
 
-void db_passwd_file_unref(struct passwd_file *pw)
+void db_passwd_file_unref(struct db_passwd_file *db)
 {
-	if (--pw->refcount == 0) {
-		passwd_file_close(pw);
-		i_free(pw->path);
-		i_free(pw);
+	struct hash_iterate_context *iter;
+	void *key, *value;
+
+	if (--db->refcount == 0) {
+		iter = hash_iterate_init(db->files);
+		while (hash_iterate(iter, &key, &value))
+			passwd_file_free(value);
+		hash_iterate_deinit(iter);
+
+		hash_destroy(db->files);
+		i_free(db->path);
+		i_free(db);
 	}
 }
 
+static const char *path_fix(const char *path)
+{
+	const char *p;
+
+	p = strchr(path, '/');
+	if (p == NULL)
+		return path;
+
+	/* most likely this is an invalid request. just cut off the '/' and
+	   everything after it. */
+	return t_strdup_until(path, p);
+}
+
 struct passwd_user *
-db_passwd_file_lookup(struct passwd_file *pw, struct auth_request *request)
+db_passwd_file_lookup(struct db_passwd_file *db, struct auth_request *request)
 {
+	struct passwd_file *pw;
 	struct passwd_user *pu;
 
-	passwd_file_sync(pw);
+	if (!db->vars)
+		pw = db->default_file;
+	else {
+		const struct var_expand_table *table;
+		string_t *dest;
 
-	pu = hash_lookup(pw->users, request->user);
+		t_push();
+
+		table = auth_request_get_var_expand_table(request, path_fix);
+		dest = t_str_new(256);
+		var_expand(dest, db->path, table);
+
+		pw = hash_lookup(db->files, str_c(dest));
+		if (pw == NULL) {
+			/* doesn't exist yet. create lookup for it. */
+			pw = passwd_file_new(db, str_c(dest));
+		}
+
+		t_pop();
+	}
+
+	if (!passwd_file_sync(pw)) {
+		auth_request_log_info(request, "passwd-file",
+				      "no passwd file");
+		return NULL;
+	}
+
+	t_push();
+	pu = hash_lookup(pw->users, !db->domain_var ? request->user :
+			 t_strcut(request->user, '@'));
 	if (pu == NULL)
                 auth_request_log_info(request, "passwd-file", "unknown user");
+	t_pop();
 
 	return pu;
 }

Index: db-passwd-file.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/db-passwd-file.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- db-passwd-file.h	31 May 2004 18:57:25 -0000	1.5
+++ db-passwd-file.h	22 Jul 2005 12:42:57 -0000	1.6
@@ -15,24 +15,35 @@
 };
 
 struct passwd_file {
-	int refcount;
+        struct db_passwd_file *db;
 	pool_t pool;
 
 	char *path;
 	time_t stamp;
 	int fd;
-	int userdb;
 
 	struct hash_table *users;
 };
 
-extern struct passwd_file *userdb_pwf;
-extern struct passwd_file *passdb_pwf;
+struct db_passwd_file {
+	int refcount;
+
+	char *path;
+	struct hash_table *files;
+        struct passwd_file *default_file;
+
+	unsigned int domain_var:1;
+	unsigned int vars:1;
+	unsigned int userdb:1;
+};
+
+extern struct db_passwd_file *userdb_pwf;
+extern struct db_passwd_file *passdb_pwf;
 
 struct passwd_user *
-db_passwd_file_lookup(struct passwd_file *pw, struct auth_request *request);
+db_passwd_file_lookup(struct db_passwd_file *db, struct auth_request *request);
 
-struct passwd_file *db_passwd_file_parse(const char *path, int userdb);
-void db_passwd_file_unref(struct passwd_file *pw);
+struct db_passwd_file *db_passwd_file_parse(const char *path, int userdb);
+void db_passwd_file_unref(struct db_passwd_file *db);
 
 #endif

Index: passdb-passwd-file.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/passdb-passwd-file.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- passdb-passwd-file.c	12 Jul 2005 12:58:47 -0000	1.18
+++ passdb-passwd-file.c	22 Jul 2005 12:42:57 -0000	1.19
@@ -8,7 +8,7 @@
 #include "password-scheme.h"
 #include "db-passwd-file.h"
 
-struct passwd_file *passdb_pwf = NULL;
+struct db_passwd_file *passdb_pwf = NULL;
 
 static void
 passwd_file_verify_plain(struct auth_request *request, const char *password,
@@ -24,10 +24,6 @@
 		return;
 	}
 
-	/* we use case-sensitive lookups. otherwise we'd have to update
-	   request->user to pu->user */
-	i_assert(strcmp(request->user, pu->user_realm) == 0);
-
 	crypted_pass = pu->password;
 	scheme = password_get_scheme(&crypted_pass);
 	if (scheme == NULL) scheme = "CRYPT";

Index: userdb-passwd-file.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/userdb-passwd-file.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- userdb-passwd-file.c	12 Jul 2005 12:58:47 -0000	1.14
+++ userdb-passwd-file.c	22 Jul 2005 12:42:57 -0000	1.15
@@ -8,7 +8,7 @@
 #include "userdb.h"
 #include "db-passwd-file.h"
 
-struct passwd_file *userdb_pwf = NULL;
+struct db_passwd_file *userdb_pwf = NULL;
 
 static void passwd_file_lookup(struct auth_request *auth_request,
 			       userdb_callback_t *callback)
@@ -42,7 +42,8 @@
 
 		/* resync */
 		userdb_pwf->userdb = TRUE;
-                userdb_pwf->stamp = 0;
+		if (userdb_pwf->default_file != NULL)
+			userdb_pwf->default_file->stamp = 0;
 	} else {
 		userdb_pwf = db_passwd_file_parse(args, TRUE);
 	}



More information about the dovecot-cvs mailing list