Re: [Dovecot] Semi-static userdb...?

2007-07-02 Thread Timo Sirainen
On Tue, 2007-05-15 at 12:24 +0300, Timo Sirainen wrote:
 On 15.5.2007, at 5.16, John Robinson wrote:
 
  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?
 
 Otherwise it's OK, but I'd want it to work with all userdbs. Looks  
 like the code doesn't currently support doing that in any easy way.  
 With passdbs it'd have been easy to use auth_request_set_field(). I  
 guess I'll add a similar auth_request_add_userdb_field() for CVS HEAD.

Added uidgid_file to v1.1 tree:
http://hg.dovecot.org/dovecot/rev/f7cdede45a88


signature.asc
Description: This is a digitally signed message part


Re: [Dovecot] Semi-static userdb...?

2007-05-15 Thread Timo Sirainen

On 15.5.2007, at 5.16, John Robinson wrote:

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?


Otherwise it's OK, but I'd want it to work with all userdbs. Looks  
like the code doesn't currently support doing that in any easy way.  
With passdbs it'd have been easy to use auth_request_set_field(). I  
guess I'll add a similar auth_request_add_userdb_field() for CVS HEAD.


[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 [EMAIL PROTECTED]/etc/ 
passwd or whatever would have failed a password check.


Right.

Hmm. Although this makes me think about deliver.. If using PAM/ 
checkpassword and userdb static, Dovecot can't verify that the user  
exists. Now if the username or domain contains ../ in it, the %n and % 
d variables in mail location will contain ../ also, which could mean  
that deliver can write to locations where it's not ever supposed to  
be writing anything.


I think the main problem is that username validations and  
translations are done only for authentications, not for deliver's  
userdb lookups. I guess I'll have to change this. After that '/' will  
be in invalid character list by default.



+   auth_request_log_info(auth_request, 
static-userdb,
+ Can't stat uid_file %s: 
%s,
+ value, strerror(errno));


Instead of %s strerror() you can use %m which does the same.





PGP.sig
Description: This is a digitally signed message part


Re: [Dovecot] Semi-static userdb...?

2007-05-14 Thread John Robinson

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 [EMAIL PROTECTED]/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.0 
+
+++ dovecot-1.0.0-semistatic/src/auth/userdb-static.c   2007-05-15 
02:46:32.0 +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,  );