Mercurial > dovecot > original-hg > dovecot-1.2
changeset 1707:ba70d60987e2 HEAD
We now support checking the password against all defined auth processes and
use the one that matches.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 22 Aug 2003 07:42:13 +0300 |
parents | cdf53841c4af |
children | 0731fc436585 |
files | dovecot-example.conf src/lib-auth/auth-server-request.c |
diffstat | 2 files changed, 139 insertions(+), 42 deletions(-) [+] |
line wrap: on
line diff
--- a/dovecot-example.conf Fri Aug 22 06:52:25 2003 +0300 +++ b/dovecot-example.conf Fri Aug 22 07:42:13 2003 +0300 @@ -337,15 +337,11 @@ ## Authentication processes ## -# You can have multiple processes; each time "auth = xx" is seen, a new -# process definition is started. The point of multiple processes is to be -# able to set stricter permissions to others. For example, plain/PAM -# authentication requires roots, but if you also use digest-md5 authentication -# for some users, you can authenticate them without any privileges in a -# separate auth process. Just remember that only one auth process is asked -# for the password, so you can't have different passwords with different -# processes (unless they have different auth mechanisms, and you're ok with -# having different password for each mechanism). +# You can have multiple authentication processes. With plaintext authentication +# the password is checked against each process, the first one which succeeds is +# used. This is useful if you want to allow both system users (/etc/passwd) +# and virtual users to login without duplicating the system users into virtual +# database. # Executable location #auth_executable = /usr/libexec/dovecot/dovecot-auth @@ -379,7 +375,7 @@ auth default { # Space separated list of wanted authentication mechanisms: # plain digest-md5 anonymous - auth_mechanisms = plain + mechanisms = plain # Where user database is kept: # passwd: /etc/passwd or similiar, using getpwnam() @@ -388,7 +384,7 @@ # vpopmail: vpopmail library # ldap <config path>: LDAP, see doc/dovecot-ldap.conf # pgsql <config path>: a PostgreSQL database, see doc/dovecot-pgsql.conf - auth_userdb = passwd + userdb = passwd # Where password database is kept: # passwd: /etc/passwd or similiar, using getpwnam() @@ -398,34 +394,44 @@ # vpopmail: vpopmail authentication # ldap <config path>: LDAP, see doc/dovecot-ldap.conf # pgsql <config path>: a PostgreSQL database, see doc/dovecot-pgsql.conf - auth_passdb = pam + passdb = pam # User to use for the process. This user needs access to only user and # password databases, nothing else. Only shadow and pam authentication # requires roots, so use something else if possible. Note that passwd # authentication with BSDs internally accesses shadow files, which also # requires roots. - auth_user = root + user = root # Directory where to chroot the process. Most authentication backends don't # work if this is set, and there's no point chrooting if auth_user is root. - #auth_chroot = + #chroot = # Number of authentication processes to create - #auth_count = 1 + #count = 1 } -# digest-md5 authentication process. It requires special MD5 passwords which -# /etc/shadow and PAM doesn't support, so we never need roots to handle it. -# Note that the passwd-file is opened before chrooting and dropping root -# privileges, so it may be 0600-root owned file. +# PAM doesn't provide a way to get uid, gid or home directory. If you don't +# want to use a separate user database (passwd usually), you can use static +# userdb. -#auth digest_md5 { -# auth_mechanisms = digest-md5 -# auth_userdb = passwd-file /etc/passwd.imap -# auth_passdb = passwd-file /etc/passwd.imap -# auth_user = imapauth +#auth onlypam { +# mechanisms = plain +# userdb = static uid=500 gid=500 home=/var/mail/%u +# passdb = pam +# user = dovecot-auth #} -# if you plan to use only passwd-file, you don't need the two auth processes, -# simply set "auth_mechanisms = plain digest-md5" +#auth ldap { +# mechanisms = plain +# userdb = ldap /etc/dovecot-ldap.conf +# passdb = ldap /etc/dovecot-ldap.conf +# user = dovecot-auth +#} + +#auth virtualfile { +# mechanisms = plain digest-md5 +# userdb = passwd-file /etc/passwd.imap +# passdb = passwd-file /etc/passwd.imap +# user = dovecot-auth +#}
--- a/src/lib-auth/auth-server-request.c Fri Aug 22 06:52:25 2003 +0300 +++ b/src/lib-auth/auth-server-request.c Fri Aug 22 07:42:13 2003 +0300 @@ -8,22 +8,63 @@ #include "auth-server-request.h" struct auth_request { - enum auth_mech mech; struct auth_server_connection *conn; + enum auth_mech mech; + enum auth_protocol protocol; + unsigned int id; auth_request_callback_t *callback; void *context; + struct auth_server_connection *next_conn; + unsigned char *plaintext_data; /* for resending to other servers */ + size_t plaintext_data_size; + unsigned int init_sent:1; + unsigned int retrying:1; }; +static int auth_server_send_new_request(struct auth_server_connection *conn, + struct auth_request *request) +{ + struct auth_client_request_new auth_request; + + auth_request.type = AUTH_CLIENT_REQUEST_NEW; + auth_request.id = request->id; + auth_request.protocol = request->protocol; + auth_request.mech = request->mech; + + if (o_stream_send(conn->output, &auth_request, + sizeof(auth_request)) < 0) { + errno = conn->output->stream_errno; + i_warning("Error sending request to auth server: %m"); + auth_server_connection_destroy(conn, TRUE); + return FALSE; + } + + return TRUE; +} + +static struct auth_server_connection * +get_next_plain_server(struct auth_server_connection *conn) +{ + conn = conn->next; + while (conn != NULL) { + if ((conn->available_auth_mechs & AUTH_MECH_PLAIN) != 0) + return conn; + conn = conn->next; + } + return NULL; +} + void auth_server_request_handle_reply(struct auth_server_connection *conn, struct auth_client_request_reply *reply, const unsigned char *data) { struct auth_request *request; + struct auth_server_connection *next; request = hash_lookup(conn->requests, POINTER_CAST(reply->id)); if (request == NULL) { @@ -32,10 +73,49 @@ return; } + switch (reply->result) { + case AUTH_CLIENT_RESULT_SUCCESS: + if (conn == request->conn) + request->next_conn = NULL; + else { + i_assert(request->next_conn == conn); + request->conn = request->next_conn; + request->next_conn = NULL; + } + break; + case AUTH_CLIENT_RESULT_FAILURE: + if (request->plaintext_data == NULL) + break; + + next = get_next_plain_server(conn); + if (next == NULL) + break; + + hash_remove(conn->requests, POINTER_CAST(request->id)); + hash_insert(next->requests, POINTER_CAST(request->id), request); + + if (conn == request->conn) + request->conn = request->next_conn; + + request->next_conn = next; + request->retrying = TRUE; + + auth_server_send_new_request(next, request); + return; + case AUTH_CLIENT_RESULT_CONTINUE: + if (!request->retrying) + break; + + auth_client_request_continue(request, request->plaintext_data, + request->plaintext_data_size); + return; + } + request->callback(request, reply, data, request->context); if (reply->result != AUTH_CLIENT_RESULT_CONTINUE) { hash_remove(conn->requests, POINTER_CAST(request->id)); + i_free(request->plaintext_data); i_free(request); } } @@ -62,15 +142,15 @@ { struct auth_server_connection *conn; struct auth_request *request; - struct auth_client_request_new auth_request; conn = auth_server_connection_find_mech(client, mech, error_r); if (conn == NULL) return NULL; request = i_new(struct auth_request, 1); + request->conn = conn; request->mech = mech; - request->conn = conn; + request->protocol = protocol; request->id = ++client->request_id_counter; if (request->id == 0) { /* wrapped - ID 0 not allowed */ @@ -81,17 +161,8 @@ hash_insert(conn->requests, POINTER_CAST(request->id), request); - /* send request to auth */ - auth_request.type = AUTH_CLIENT_REQUEST_NEW; - auth_request.id = request->id; - auth_request.protocol = protocol; - auth_request.mech = request->mech; - if (o_stream_send(request->conn->output, &auth_request, - sizeof(auth_request)) < 0) { - errno = request->conn->output->stream_errno; - i_warning("Error sending request to auth server: %m"); - auth_server_connection_destroy(request->conn, TRUE); - } + if (!auth_server_send_new_request(conn, request)) + request = NULL; return request; } @@ -100,6 +171,23 @@ { struct auth_client_request_continue auth_request; + if (request->mech == AUTH_MECH_PLAIN && + request->plaintext_data == NULL) { + request->next_conn = get_next_plain_server(request->conn); + if (request->next_conn != NULL) { + /* plaintext authentication - save the data so we can + try it for the next */ + request->plaintext_data = i_malloc(data_size); + memcpy(request->plaintext_data, data, data_size); + request->plaintext_data_size = data_size; + + hash_insert(request->next_conn->requests, + POINTER_CAST(request->id), request); + auth_server_send_new_request(request->next_conn, + request); + } + } + /* send continued request to auth */ auth_request.type = AUTH_CLIENT_REQUEST_CONTINUE; auth_request.id = request->id; @@ -118,8 +206,11 @@ { void *id = POINTER_CAST(request->id); - if (hash_lookup(request->conn->requests, id) != NULL) - hash_remove(request->conn->requests, id); + hash_remove(request->conn->requests, id); + if (request->next_conn != NULL) + hash_remove(request->next_conn->requests, id); + + i_free(request->plaintext_data); i_free(request); }