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
+#include
+#include
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;
}