]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-auth-client: auth-master - Make asynchronous userdb and passdb lookups available
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sat, 3 Mar 2018 00:20:29 +0000 (01:20 +0100)
committerStephan Bosch <stephan.bosch@open-xchange.com>
Wed, 27 Aug 2025 14:17:02 +0000 (16:17 +0200)
src/lib-auth-client/auth-master.c
src/lib-auth-client/auth-master.h

index e1cfd8dc54db4c3a57c0ec4bf834c0a7aa6feb94..de62dbe6f34b8b295a639af48b9f9faf7dcc7f30 100644 (file)
@@ -678,14 +678,16 @@ void auth_master_wait(struct auth_master_connection *conn)
  */
 
 struct auth_master_lookup {
-       struct auth_master_connection *conn;
+       struct auth_master_request *req;
        struct event *event;
        const char *user;
        const char *expected_reply;
-       int return_value;
 
        pool_t pool;
        const char **fields;
+
+       void (*finished)(struct auth_master_lookup *lookup,
+                        int result, const char *const *fields);
 };
 
 static bool is_valid_string(const char *str)
@@ -870,7 +872,7 @@ auth_lookup_reply_callback(const struct auth_master_reply *reply,
                lookup->fields[0] = p_strdup(lookup->pool, reply->errormsg);
                e_debug(lookup->event, "auth %s error: %s",
                        lookup->expected_reply, reply->errormsg);
-               lookup->return_value = -1;
+               lookup->finished(lookup, -1, lookup->fields);
                return 1;
        }
        i_assert(reply->reply != NULL);
@@ -911,7 +913,8 @@ auth_lookup_reply_callback(const struct auth_master_reply *reply,
                                lookup->expected_reply);
                }
        }
-       lookup->return_value = result;
+
+       lookup->finished(lookup, result, lookup->fields);
        return 1;
 }
 
@@ -923,6 +926,9 @@ auth_lookup_reply_callback(const struct auth_master_reply *reply,
 
 struct auth_master_pass_lookup {
        struct auth_master_lookup lookup;
+
+       auth_master_pass_lookup_callback_t *callback;
+       void *context;
 };
 
 struct auth_master_pass_lookup_ctx {
@@ -940,21 +946,10 @@ auth_master_pass_lookup_callback(struct auth_master_pass_lookup_ctx *ctx,
        ctx->fields = p_strarray_dup(ctx->pool, fields);
 }
 
-static void
-auth_master_pass_lookup_finished(struct auth_master_lookup *_lookup,
-                                int result, const char *const *fields,
-                                struct auth_master_pass_lookup_ctx *ctx);
-static struct auth_master_request *
-auth_master_pass_lookup_start(struct auth_master_pass_lookup *lookup,
-                             struct auth_master_connection *conn,
-                             const char *user,
-                             const struct auth_user_info *info);
-
 int auth_master_pass_lookup(struct auth_master_connection *conn,
                            const char *user, const struct auth_user_info *info,
                            pool_t pool, const char *const **fields_r)
 {
-       struct auth_master_pass_lookup lookup;
        struct auth_master_request *req;
 
        if (!is_valid_string(user) || !is_valid_string(info->protocol)) {
@@ -972,28 +967,30 @@ int auth_master_pass_lookup(struct auth_master_connection *conn,
                .result = -1,
        };
 
-       i_zero(&lookup);
-       lookup.lookup.pool = pool;
-
-       req = auth_master_pass_lookup_start(&lookup, conn, user, info);
+       req = auth_master_pass_lookup_async(conn, user, info,
+                                           auth_master_pass_lookup_callback,
+                                           &ctx);
        (void)auth_master_request_wait(req);
 
-       auth_master_pass_lookup_finished(&lookup.lookup,
-                                        lookup.lookup.return_value,
-                                        lookup.lookup.fields, &ctx);
-       event_unref(&lookup.lookup.event);
-
        *fields_r = ctx.fields != NULL ? ctx.fields :
                p_new(pool, const char *, 1);
        return ctx.result;
+}
 
+static void
+auth_master_pass_lookup_destroyed(struct auth_master_pass_lookup *lookup)
+{
+       event_unref(&lookup->lookup.event);
+       pool_unref(&lookup->lookup.pool);
 }
 
 static void
 auth_master_pass_lookup_finished(struct auth_master_lookup *_lookup,
-                                int result, const char *const *fields,
-                                struct auth_master_pass_lookup_ctx *ctx)
+                                int result, const char *const *fields)
 {
+       struct auth_master_pass_lookup *lookup =
+               container_of(_lookup, struct auth_master_pass_lookup, lookup);
+
        if (result <= 0) {
                struct event_passthrough *e =
                        event_create_passthrough(_lookup->event)->
@@ -1014,20 +1011,39 @@ auth_master_pass_lookup_finished(struct auth_master_lookup *_lookup,
                        (fields == NULL ? "" : t_strarray_join(fields, " ")));
        }
 
-       auth_master_pass_lookup_callback(ctx, result, fields);
+       lookup->callback(lookup->context, result, fields);
 }
 
-static struct auth_master_request *
-auth_master_pass_lookup_start(struct auth_master_pass_lookup *lookup,
-                             struct auth_master_connection *conn,
+#undef auth_master_pass_lookup_async
+struct auth_master_request *
+auth_master_pass_lookup_async(struct auth_master_connection *conn,
                              const char *user,
-                             const struct auth_user_info *info)
+                             const struct auth_user_info *info,
+                             auth_master_pass_lookup_callback_t *callback,
+                             void *context)
 {
        struct auth_master_request *req;
+       struct auth_master_pass_lookup *lookup;
+       pool_t pool;
        string_t *args;
 
-       lookup->lookup.conn = conn;
-       lookup->lookup.return_value = -1;
+       pool = pool_alloconly_create("auth_master_pass_lookup", 1024);
+       lookup = p_new(pool, struct auth_master_pass_lookup, 1);
+       lookup->lookup.pool = pool;
+       lookup->lookup.finished = auth_master_pass_lookup_finished;
+       lookup->callback = callback;
+       lookup->context = context;
+
+       if (!is_valid_string(user) || !is_valid_string(info->protocol)) {
+               /* non-allowed characters, the user can't exist */
+               req = auth_master_request_invalid(conn,
+                       auth_lookup_reply_callback, &lookup->lookup);
+               auth_master_request_add_destroy_callback(req,
+                       auth_master_pass_lookup_destroyed, lookup);
+               lookup->lookup.req = req;
+               return req;
+       }
+
        lookup->lookup.expected_reply = "PASS";
        lookup->lookup.user = user;
 
@@ -1048,6 +1064,9 @@ auth_master_pass_lookup_start(struct auth_master_pass_lookup *lookup,
                                  auth_lookup_reply_callback, &lookup->lookup);
 
        auth_master_request_set_event(req, lookup->lookup.event);
+       auth_master_request_add_destroy_callback(req,
+               auth_master_pass_lookup_destroyed, lookup);
+       lookup->lookup.req = req;
 
        return req;
 }
@@ -1060,6 +1079,9 @@ auth_master_pass_lookup_start(struct auth_master_pass_lookup *lookup,
 
 struct auth_master_user_lookup {
        struct auth_master_lookup lookup;
+
+       auth_master_user_lookup_callback_t *callback;
+       void *context;
 };
 
 struct auth_master_user_lookup_ctx {
@@ -1070,16 +1092,6 @@ struct auth_master_user_lookup_ctx {
        const char *const *fields;
 };
 
-static void
-auth_master_user_lookup_finished(struct auth_master_lookup *_lookup,
-                                int result, const char *const *fields,
-                                struct auth_master_user_lookup_ctx *ctx);
-struct auth_master_request *
-auth_master_user_lookup_start(struct auth_master_user_lookup *lookup,
-                             struct auth_master_connection *conn,
-                             const char *user,
-                             const struct auth_user_info *info);
-
 static void
 auth_master_user_lookup_callback(struct auth_master_user_lookup_ctx *ctx,
                                 int result, const char *username,
@@ -1095,7 +1107,6 @@ int auth_master_user_lookup(struct auth_master_connection *conn,
                            pool_t pool, const char **username_r,
                            const char *const **fields_r)
 {
-       struct auth_master_user_lookup lookup;
        struct auth_master_request *req;
 
        if (!is_valid_string(user) || !is_valid_string(info->protocol)) {
@@ -1114,28 +1125,30 @@ int auth_master_user_lookup(struct auth_master_connection *conn,
                .result = -1,
        };
 
-       i_zero(&lookup);
-       lookup.lookup.pool = pool;
-
-       req = auth_master_user_lookup_start(&lookup, conn, user, info);
+       req = auth_master_user_lookup_async(conn, user, info,
+                                           auth_master_user_lookup_callback,
+                                           &ctx);
        (void)auth_master_request_wait(req);
 
-       auth_master_user_lookup_finished(&lookup.lookup,
-                                        lookup.lookup.return_value,
-                                        lookup.lookup.fields, &ctx);
-       event_unref(&lookup.lookup.event);
-
        *username_r = ctx.username;
        *fields_r = ctx.fields != NULL ? ctx.fields :
                p_new(pool, const char *, 1);
        return ctx.result;
 }
 
+static void
+auth_master_user_lookup_destroyed(struct auth_master_user_lookup *lookup)
+{
+       event_unref(&lookup->lookup.event);
+       pool_unref(&lookup->lookup.pool);
+}
+
 static void
 auth_master_user_lookup_finished(struct auth_master_lookup *_lookup,
-                                int result, const char *const *fields,
-                                struct auth_master_user_lookup_ctx *ctx)
+                                int result, const char *const *fields)
 {
+       struct auth_master_user_lookup *lookup =
+               container_of(_lookup, struct auth_master_user_lookup, lookup);
        const char *username = NULL;
 
        if (result <= 0 || fields[0] == NULL) {
@@ -1167,20 +1180,39 @@ auth_master_user_lookup_finished(struct auth_master_lookup *_lookup,
                        username, t_strarray_join(fields, " "));
        }
 
-       auth_master_user_lookup_callback(ctx, result, username, fields);
+       lookup->callback(lookup->context, result, username, fields);
 }
 
+#undef auth_master_user_lookup_async
 struct auth_master_request *
-auth_master_user_lookup_start(struct auth_master_user_lookup *lookup,
-                             struct auth_master_connection *conn,
+auth_master_user_lookup_async(struct auth_master_connection *conn,
                              const char *user,
-                             const struct auth_user_info *info)
+                             const struct auth_user_info *info,
+                             auth_master_user_lookup_callback_t *callback,
+                             void *context)
 {
        struct auth_master_request *req;
+       struct auth_master_user_lookup *lookup;
+       pool_t pool;
        string_t *args;
 
-       lookup->lookup.conn = conn;
-       lookup->lookup.return_value = -1;
+       pool = pool_alloconly_create("auth_master_user_lookup", 1024);
+       lookup = p_new(pool, struct auth_master_user_lookup, 1);
+       lookup->lookup.pool = pool;
+       lookup->lookup.finished = auth_master_user_lookup_finished;
+       lookup->callback = callback;
+       lookup->context = context;
+
+       if (!is_valid_string(user) || !is_valid_string(info->protocol)) {
+               /* non-allowed characters, the user can't exist */
+               req = auth_master_request_invalid(conn,
+                       auth_lookup_reply_callback, &lookup->lookup);
+               auth_master_request_add_destroy_callback(req,
+                       auth_master_user_lookup_destroyed, lookup);
+               lookup->lookup.req = req;
+               return req;
+       }
+
        lookup->lookup.expected_reply = "USER";
        lookup->lookup.user = user;
 
@@ -1201,6 +1233,9 @@ auth_master_user_lookup_start(struct auth_master_user_lookup *lookup,
                                  auth_lookup_reply_callback, &lookup->lookup);
 
        auth_master_request_set_event(req, lookup->lookup.event);
+       auth_master_request_add_destroy_callback(req,
+               auth_master_user_lookup_destroyed, lookup);
+       lookup->lookup.req = req;
 
        return req;
 }
index 449a6855e3d7ea895486a4ec1279b2ef04ac9f7c..1e82cc7c83119cca0c717b930c8a0377a0684bd2 100644 (file)
@@ -110,11 +110,28 @@ struct auth_user_info {
  * PassDB
  */
 
+typedef void
+auth_master_pass_lookup_callback_t(void *context, int result,
+                                  const char *const *fields);
+
 /* Do a PASS lookup (the actual password isn't returned). */
 int auth_master_pass_lookup(struct auth_master_connection *conn,
                            const char *user, const struct auth_user_info *info,
                            pool_t pool, const char *const **fields_r);
 
+/* Do an asynchronous PASS lookup. */
+struct auth_master_request *
+auth_master_pass_lookup_async(struct auth_master_connection *conn,
+                             const char *user,
+                             const struct auth_user_info *info,
+                             auth_master_pass_lookup_callback_t *callback,
+                             void *context);
+#define auth_master_pass_lookup_async(conn, user, info, callback, context) \
+       auth_master_pass_lookup_async(conn, user, info + \
+               CALLBACK_TYPECHECK(callback, void (*)(typeof(context), \
+                                  int result, const char *const *fields)), \
+               (auth_master_pass_lookup_callback_t *)callback, context)
+
 /*
  * UserDB
  */
@@ -127,6 +144,11 @@ struct auth_user_reply {
        bool anonymous:1;
 };
 
+typedef void
+auth_master_user_lookup_callback_t(void *context, int result,
+                                  const char *username,
+                                  const char *const *fields);
+
 /* Do a USER lookup. Returns -2 = user-specific error, -1 = internal error,
    0 = user not found, 1 = ok. When returning -1 and fields[0] isn't NULL, it
    contains an error message that should be shown to user. */
@@ -135,6 +157,20 @@ int auth_master_user_lookup(struct auth_master_connection *conn,
                            pool_t pool, const char **username_r,
                            const char *const **fields_r);
 
+/* Do an asynchronous USER lookup. */
+struct auth_master_request *
+auth_master_user_lookup_async(struct auth_master_connection *conn,
+                             const char *user,
+                             const struct auth_user_info *info,
+                             auth_master_user_lookup_callback_t *callback,
+                             void *context);
+#define auth_master_user_lookup_async(conn, user, info, callback, context) \
+       auth_master_user_lookup_async(conn, user, info +  \
+               CALLBACK_TYPECHECK(callback, void (*)(typeof(context), \
+                                  int result, const char *username, \
+                                  const char *const *fields)), \
+               (auth_master_user_lookup_callback_t *)callback, context)
+
 /* Parse userdb extra fields into auth_user_reply structure. */
 int auth_user_fields_parse(const char *const *fields, pool_t pool,
                           struct auth_user_reply *reply_r, const char **error_r);