On 11/05/2007 15:57, Timo Sirainen wrote:
On Fri, 2007-04-20 at 14:00 +0100, John Robinson wrote:
I'm trying to add "virtual" mailboxes to a system. Real users with different uids own domains. Each domain has a passwd-file passdb. I don't want to use this passwd-file for the userdb, because I want to fix the home, mail and uid/gid settings. Can I use the static userdb in a less static manner, e.g.
userdb static { args = uid=%{owner of /vmail/%d} gid=%{gid of /vmail/%d} home=/vmail/%d/users/%u mail=mbox:/vmail/%d/users/%u/mail:INBOX=/vmail/%d/users/%u/INBOX }
Hmm. You could always use a checkpassword script which does everything, but the above does look like it could be useful. I'm just not sure what would be the best way to implement it so that it would be useful for other kinds of configurations too..
One possibility would be to set "uid_file=/vmail/%d gid_file=/vmail/%d". I guess that would be good. Added to TODO, but I'm not sure when I get around to implementing it.
Something like the attached? It applies cleanly to 1.0.0, I've tested it lightly and it appears to work. My testing was to use passdb pam with userdb static { args = uid_file=/home/%u gid_file=/home/%u home=/home/%u }. It's perhaps not perfect: it doesn't complain if you set both uid and uid_file, ditto gid and gid_file, and it doesn't do any sanity checks on the result of the expansion[1]. Cheers, John. [1] Use uid_file=/vmail/%d and login with domain ../etc/passwd and you end up looking at /etc/passwd. I don't know whether this matters: it's only doing a stat(), hopefully dovecot won't let you check mail as root, and anyway presumably the user has already had their password checked by now, and someone logging in as foo@../etc/passwd or whatever would have failed a password check. diff -urN --exclude='*~' dovecot-1.0.0.orig/src/auth/userdb-static.c dovecot-1.0.0-semistatic/src/auth/userdb-static.c --- dovecot-1.0.0.orig/src/auth/userdb-static.c 2007-03-21 20:01:56.000000000 +0000 +++ dovecot-1.0.0-semistatic/src/auth/userdb-static.c 2007-05-15 02:46:32.000000000 +0100 @@ -10,6 +10,8 @@ #include "userdb.h" #include <stdlib.h> +#include <unistd.h> +#include <sys/stat.h> struct static_context { userdb_callback_t *callback, *old_callback; @@ -33,8 +35,10 @@ const struct var_expand_table *table; struct auth_stream_reply *reply; string_t *str; - const char *const *args, *value; + const char *const *args, *key, *value; unsigned int i, count; + bool ok = TRUE; + struct stat fileinfo; t_push(); str = t_str_new(256); @@ -46,17 +50,39 @@ args = array_get(&module->template, &count); i_assert((count % 2) == 0); for (i = 0; i < count; i += 2) { + key = args[i]; if (args[i+1] == NULL) value = NULL; else { str_truncate(str, 0); var_expand(str, args[i+1], table); value = str_c(str); + if (strcasecmp(key, "uid_file") == 0) { + if (stat(value, &fileinfo) != 0) { + ok = FALSE; + auth_request_log_info(auth_request, "static-userdb", + "Can't stat uid_file %s: %s", + value, strerror(errno)); + } else { + key = "uid"; + value = dec2str(fileinfo.st_uid); + } + } else if (strcasecmp(key, "gid_file") == 0) { + if (stat(value, &fileinfo) != 0) { + ok = FALSE; + auth_request_log_info(auth_request, "static-userdb", + "Can't stat gid_file %s: %s", + value, strerror(errno)); + } else { + key = "gid"; + value = dec2str(fileinfo.st_gid); + } + } } - auth_stream_reply_add(reply, args[i], value); + auth_stream_reply_add(reply, key, value); } - callback(USERDB_RESULT_OK, reply, auth_request); + callback((ok ? USERDB_RESULT_OK : USERDB_RESULT_INTERNAL_FAILURE), reply, auth_request); t_pop(); } @@ -131,11 +157,14 @@ const char *const *tmp, *key, *value; uid_t uid; gid_t gid; + bool uid_file; + bool gid_file; module = p_new(auth_userdb->auth->pool, struct static_userdb_module, 1); uid = (uid_t)-1; gid = (gid_t)-1; + uid_file = gid_file = FALSE; tmp = t_strsplit_spaces(args, " "); ARRAY_CREATE(&module->template, auth_userdb->auth->pool, @@ -165,6 +194,10 @@ value); } value = dec2str(gid); + } else if (strcasecmp(key, "uid_file") == 0) { + uid_file = TRUE; + } else if (strcasecmp(key, "gid_file") == 0) { + gid_file = TRUE; } else if (strcmp(key, "allow_all_users") == 0) { module->allow_all_users = value == NULL || strcasecmp(value, "yes") == 0; @@ -180,9 +213,9 @@ } t_pop(); - if (uid == (uid_t)-1) + if ((uid == (uid_t)-1) && !uid_file) i_fatal("static userdb: uid missing"); - if (gid == (gid_t)-1) + if ((gid == (gid_t)-1) && !gid_file) i_fatal("static userdb: gid missing"); return &module->module; }