]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: Fixes to destroying pending async userdb requests at deinit.
authorTimo Sirainen <tss@iki.fi>
Wed, 2 Jun 2010 15:48:55 +0000 (16:48 +0100)
committerTimo Sirainen <tss@iki.fi>
Wed, 2 Jun 2010 15:48:55 +0000 (16:48 +0100)
--HG--
branch : HEAD

src/auth/auth-master-connection.c
src/auth/auth-master-connection.h
src/auth/auth-request-handler.c
src/auth/auth-request-handler.h
src/auth/auth-request.c
src/auth/auth-request.h

index 33245ff07ca5160c43c5f6c44ec41e1a74bc925a..bf16b69346c6de99a02814a7f04393596d0710e6 100644 (file)
@@ -3,6 +3,7 @@
 #include "auth-common.h"
 #include "array.h"
 #include "hash.h"
+#include "llist.h"
 #include "str.h"
 #include "strescape.h"
 #include "str-sanitize.h"
 #define MAX_INBUF_SIZE 1024
 #define MAX_OUTBUF_SIZE (1024*50)
 
+struct auth_request_list {
+       struct auth_request_list *prev, *next;
+
+       struct auth_request *auth_request;
+};
+
 struct master_userdb_request {
        struct auth_master_connection *conn;
        unsigned int id;
@@ -116,6 +123,7 @@ master_input_auth_request(struct auth_master_connection *conn, const char *args,
                          const char **error_r)
 {
        struct auth_request *auth_request;
+       struct auth_request_list *request_list;
        const char *const *list, *name, *arg;
        unsigned int id;
 
@@ -129,9 +137,14 @@ master_input_auth_request(struct auth_master_connection *conn, const char *args,
 
        auth_request = auth_request_new_dummy();
        auth_request->id = id;
-       auth_request->context = conn;
+       auth_request->master = conn;
        auth_master_connection_ref(conn);
 
+       request_list = p_new(auth_request->pool, struct auth_request_list, 1);
+       request_list->auth_request = auth_request;
+       DLLIST_PREPEND(&conn->requests, request_list);
+       auth_request->context = request_list;
+
        if (!auth_request_set_username(auth_request, list[1], error_r)) {
                *request_r = auth_request;
                return 0;
@@ -152,8 +165,9 @@ master_input_auth_request(struct auth_master_connection *conn, const char *args,
 
        if (auth_request->service == NULL) {
                i_error("BUG: Master sent %s request without service", cmd);
-               auth_master_connection_unref(&conn);
+               DLLIST_REMOVE(&conn->requests, request_list);
                auth_request_unref(&auth_request);
+               auth_master_connection_unref(&conn);
                return -1;
        }
 
@@ -166,7 +180,8 @@ static void
 user_callback(enum userdb_result result,
              struct auth_request *auth_request)
 {
-       struct auth_master_connection *conn = auth_request->context;
+       struct auth_master_connection *conn = auth_request->master;
+       struct auth_request_list *list = auth_request->context;
        struct auth_stream_reply *reply = auth_request->userdb_reply;
        string_t *str;
        const char *value;
@@ -198,6 +213,8 @@ user_callback(enum userdb_result result,
 
        str_append_c(str, '\n');
        (void)o_stream_send(conn->output, str_data(str), str_len(str));
+
+       DLLIST_REMOVE(&conn->requests, list);
        auth_request_unref(&auth_request);
        auth_master_connection_unref(&conn);
 }
@@ -229,7 +246,8 @@ pass_callback(enum passdb_result result,
              size_t size ATTR_UNUSED,
              struct auth_request *auth_request)
 {
-       struct auth_master_connection *conn = auth_request->context;
+       struct auth_master_connection *conn = auth_request->master;
+       struct auth_request_list *list = auth_request->context;
        struct auth_stream_reply *reply = auth_request->extra_fields;
        string_t *str;
 
@@ -257,6 +275,8 @@ pass_callback(enum passdb_result result,
 
        str_append_c(str, '\n');
        (void)o_stream_send(conn->output, str_data(str), str_len(str));
+
+       DLLIST_REMOVE(&conn->requests, list);
        auth_request_unref(&auth_request);
        auth_master_connection_unref(&conn);
 }
@@ -512,6 +532,7 @@ void auth_master_connection_destroy(struct auth_master_connection **_conn)
 {
         struct auth_master_connection *conn = *_conn;
         struct auth_master_connection *const *masters;
+       struct auth_request_list *list;
        unsigned int idx;
 
        *_conn = NULL;
@@ -519,6 +540,9 @@ void auth_master_connection_destroy(struct auth_master_connection **_conn)
                return;
        conn->destroyed = TRUE;
 
+       for (list = conn->requests; list != NULL; list = list->next)
+               list->auth_request->destroyed = TRUE;
+
        array_foreach(&auth_master_connections, masters) {
                if (*masters == conn) {
                        idx = array_foreach_idx(&auth_master_connections,
index 26d2b7266b4d8b44a8c9c33cfd4d40b59500ac7f..b0bc9aaab6ff560acff9a6fb4d002a9cbf1bedaa 100644 (file)
@@ -12,6 +12,8 @@ struct auth_master_connection {
        struct ostream *output;
        struct io *io;
 
+       struct auth_request_list *requests;
+
        unsigned int version_received:1;
        unsigned int destroyed:1;
        unsigned int userdb_only:1;
index feb292f97090da55101dc8ab15268787c908d198..13d8b884ae00d683da72604b73cd82290175fdc3 100644 (file)
@@ -74,6 +74,7 @@ static void auth_request_handler_unref(struct auth_request_handler **_handler)
        while (hash_table_iterate(iter, &key, &value)) {
                struct auth_request *auth_request = value;
 
+               auth_request->destroyed = TRUE;
                auth_request_unref(&auth_request);
        }
        hash_table_iterate_deinit(&iter);
@@ -97,11 +98,6 @@ void auth_request_handler_destroy(struct auth_request_handler **_handler)
        auth_request_handler_unref(&handler);
 }
 
-bool auth_request_handler_is_destroyed(struct auth_request_handler *handler)
-{
-       return handler->destroyed;
-}
-
 void auth_request_handler_set(struct auth_request_handler *handler,
                              unsigned int connect_uid,
                              unsigned int client_pid)
index 2391282327fc5fe71c9c05608114909eea742f32..515b3a8267a7e750864364e16f2c0921e3e07d92 100644 (file)
@@ -25,8 +25,6 @@ auth_request_handler_create(auth_request_callback_t *callback, void *context,
 #endif
 void auth_request_handler_destroy(struct auth_request_handler **handler);
 
-bool auth_request_handler_is_destroyed(struct auth_request_handler *handler);
-
 void auth_request_handler_set(struct auth_request_handler *handler,
                              unsigned int connect_uid,
                              unsigned int client_pid);
index b6ba7d3ac64c864e71a62df90fc2224fb5144bae..b3b4fb8d35451a22c4e79967b0a0267ae643c7bc 100644 (file)
@@ -390,7 +390,7 @@ auth_request_handle_passdb_callback(enum passdb_result *result,
                            strlen(request->passdb_password));
        }
 
-       if (auth_request_handler_is_destroyed(request->handler)) {
+       if (request->destroyed) {
                /* the passdb may have been freed already. this request won't
                   be sent anywhere anyway, so just fail it immediately. */
                *result = PASSDB_RESULT_INTERNAL_FAILURE;
@@ -742,6 +742,14 @@ void auth_request_userdb_callback(enum userdb_result result,
 {
        struct userdb_module *userdb = request->userdb->userdb;
 
+       if (request->destroyed) {
+               /* the userdb may have been freed already. this request won't
+                  be sent anywhere anyway, so just fail it immediately. */
+               request->private_callback.
+                       userdb(USERDB_RESULT_INTERNAL_FAILURE, request);
+               return;
+       }
+
        if (result != USERDB_RESULT_OK && request->userdb->next != NULL) {
                /* try next userdb. */
                if (result == USERDB_RESULT_INTERNAL_FAILURE)
index ed9d00f420b19576dbe9ab28959e2e58ef3e9ca8..db23030273752127663cbb28642f1ddbf5797fef 100644 (file)
@@ -108,6 +108,7 @@ struct auth_request {
        unsigned int userdb_lookup:1;
        unsigned int userdb_lookup_failed:1;
        unsigned int secured:1;
+       unsigned int destroyed:1;
 
        /* ... mechanism specific data ... */
 };