]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added auth_master_pass_lookup() and changed auth_master_used_lookup() API.
authorTimo Sirainen <tss@iki.fi>
Mon, 31 Aug 2009 15:37:25 +0000 (11:37 -0400)
committerTimo Sirainen <tss@iki.fi>
Mon, 31 Aug 2009 15:37:25 +0000 (11:37 -0400)
User lookup can now send local/remote IPs and ports to auth process.

--HG--
branch : HEAD

src/lib-auth/auth-master.c
src/lib-auth/auth-master.h
src/lib-storage/mail-storage-service.c
src/lib-storage/mail-storage-service.h
src/lib-storage/mail-user.c

index db1e3a84b153fad0bf311431446858b2c6ed6d05..d30f1d12bbedcc70ec2afe1164c730887f3dc9cc 100644 (file)
@@ -7,6 +7,7 @@
 #include "network.h"
 #include "istream.h"
 #include "ostream.h"
+#include "str.h"
 #include "auth-master.h"
 
 #include <stdlib.h>
@@ -49,11 +50,18 @@ struct auth_master_connection {
 struct auth_master_user_lookup_ctx {
        struct auth_master_connection *conn;
        pool_t pool;
-       const char *user;
        struct auth_user_reply *user_reply;
        int return_value;
 };
 
+struct auth_master_pass_lookup_ctx {
+       struct auth_master_connection *conn;
+       int return_value;
+
+       pool_t pool;
+       const char **fields;
+};
+
 struct auth_master_user_list_ctx {
        struct auth_master_connection *conn;
        pool_t pool;
@@ -162,27 +170,34 @@ static int auth_input_handshake(struct auth_master_connection *conn)
        return 0;
 }
 
+static int parse_reply(struct auth_master_connection *conn,
+                      const char *cmd, const char *const *args,
+                      const char *expected_reply)
+{
+       io_loop_stop(conn->ioloop);
+
+       if (strcmp(cmd, expected_reply) == 0)
+               return 1;
+       if (strcmp(cmd, "NOTFOUND") == 0)
+               return 0;
+       if (strcmp(cmd, "FAIL") == 0) {
+               i_error("Lookup failed: %s",
+                       *args != NULL ? *args : "Internal failure");
+               return -1;
+       }
+       i_error("Unknown reply: %s", cmd);
+       return -1;
+}
+
 static bool auth_user_reply_callback(const char *cmd, const char *const *args,
                                     void *context)
 {
        struct auth_master_user_lookup_ctx *ctx = context;
 
-       io_loop_stop(ctx->conn->ioloop);
-       if (strcmp(cmd, "USER") == 0) {
+       ctx->return_value = parse_reply(ctx->conn, cmd, args, "USER");
+       if (ctx->return_value > 0)
                auth_parse_input(ctx, args);
-               ctx->return_value = 1;
-               return TRUE;
-       }
-       if (strcmp(cmd, "NOTFOUND") == 0) {
-               ctx->return_value = 0;
-               return TRUE;
-       }
-       if (strcmp(cmd, "FAIL") == 0) {
-               i_error("userdb lookup(%s) failed: %s", ctx->user,
-                       *args != NULL ? *args : "Internal failure");
-               return TRUE;
-       }
-       return FALSE;
+       return TRUE;
 }
 
 static bool
@@ -373,14 +388,40 @@ static int auth_master_run_cmd(struct auth_master_connection *conn,
        return 0;
 }
 
+static unsigned int
+auth_master_next_request_id(struct auth_master_connection *conn)
+{
+       if (++conn->request_counter == 0) {
+               /* avoid zero */
+               conn->request_counter++;
+       }
+       return conn->request_counter;
+}
+
+static void
+auth_user_info_export(string_t *str, const struct auth_user_info *info)
+{
+       str_append(str, "service=");
+       str_append(str, info->service);
+
+       if (info->local_ip.family != 0)
+               str_printfa(str, "\tlip=%s", net_ip2addr(&info->local_ip));
+       if (info->local_port != 0)
+               str_printfa(str, "\tlport=%d", info->local_port);
+       if (info->remote_ip.family != 0)
+               str_printfa(str, "\trip=%s", net_ip2addr(&info->remote_ip));
+       if (info->remote_port != 0)
+               str_printfa(str, "\trport=%d", info->remote_port);
+}
+
 int auth_master_user_lookup(struct auth_master_connection *conn,
-                           const char *user, const char *service,
+                           const char *user, const struct auth_user_info *info,
                            pool_t pool, struct auth_user_reply *reply_r)
 {
        struct auth_master_user_lookup_ctx ctx;
-       const char *str;
+       string_t *str;
 
-       if (!is_valid_string(user) || !is_valid_string(service)) {
+       if (!is_valid_string(user) || !is_valid_string(info->service)) {
                /* non-allowed characters, the user can't exist */
                return 0;
        }
@@ -389,26 +430,74 @@ int auth_master_user_lookup(struct auth_master_connection *conn,
        ctx.conn = conn;
        ctx.return_value = -1;
        ctx.pool = pool;
-       ctx.user = user;
        ctx.user_reply = reply_r;
 
-       if (++conn->request_counter == 0) {
-               /* avoid zero */
-               conn->request_counter++;
-       }
-
        conn->reply_callback = auth_user_reply_callback;
        conn->reply_context = &ctx;
 
+       str = t_str_new(128);
+       str_printfa(str, "USER\t%u\t%s\t",
+                   auth_master_next_request_id(conn), user);
+       auth_user_info_export(str, info);
+       str_append_c(str, '\n');
+
        conn->prefix = t_strdup_printf("userdb lookup(%s)", user);
-       str = t_strdup_printf("USER\t%u\t%s\tservice=%s\n",
-                             conn->request_counter, user, service);
-       (void)auth_master_run_cmd(conn, str);
+       (void)auth_master_run_cmd(conn, str_c(str));
        conn->prefix = DEFAULT_USERDB_LOOKUP_PREFIX;
 
        return ctx.return_value;
 }
 
+static bool auth_pass_reply_callback(const char *cmd, const char *const *args,
+                                    void *context)
+{
+       struct auth_master_pass_lookup_ctx *ctx = context;
+       unsigned int i, len;
+
+       ctx->return_value = parse_reply(ctx->conn, cmd, args, "PASS");
+       if (ctx->return_value > 0) {
+               len = str_array_length(args);
+               ctx->fields = p_new(ctx->pool, const char *, len + 1);
+               for (i = 0; i < len; i++)
+                       ctx->fields[i] = p_strdup(ctx->pool, args[i]);
+       }
+       return TRUE;
+}
+
+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_ctx ctx;
+       string_t *str;
+
+       if (!is_valid_string(user) || !is_valid_string(info->service)) {
+               /* non-allowed characters, the user can't exist */
+               return 0;
+       }
+
+       memset(&ctx, 0, sizeof(ctx));
+       ctx.conn = conn;
+       ctx.return_value = -1;
+       ctx.pool = pool;
+
+       conn->reply_callback = auth_pass_reply_callback;
+       conn->reply_context = &ctx;
+
+       str = t_str_new(128);
+       str_printfa(str, "PASS\t%u\t%s\t",
+                   auth_master_next_request_id(conn), user);
+       auth_user_info_export(str, info);
+       str_append_c(str, '\n');
+
+       conn->prefix = t_strdup_printf("passdb lookup(%s)", user);
+       (void)auth_master_run_cmd(conn, str_c(str));
+       conn->prefix = DEFAULT_USERDB_LOOKUP_PREFIX;
+
+       *fields_r = ctx.fields;
+       return ctx.return_value;
+}
+
 static bool
 auth_user_list_reply_callback(const char *cmd, const char *const *args,
                              void *context)
@@ -449,15 +538,10 @@ auth_master_user_list_init(struct auth_master_connection *conn)
        ctx->conn = conn;
        i_array_init(&ctx->users, 128);
 
-       if (++conn->request_counter == 0) {
-               /* avoid zero */
-               conn->request_counter++;
-       }
-
        conn->reply_callback = auth_user_list_reply_callback;
        conn->reply_context = ctx;
 
-       str = t_strdup_printf("LIST\t%u\n", conn->request_counter);
+       str = t_strdup_printf("LIST\t%u\n", auth_master_next_request_id(conn));
        conn->prefix = "userdb list";
        if (auth_master_run_cmd(conn, str) < 0)
                ctx->failed = TRUE;
index 24b6a164c23fbd4997f10a412a50fd0aa594f885..b12043b9e19b81dc43dec8afaefe86769752ecf3 100644 (file)
@@ -1,6 +1,14 @@
 #ifndef AUTH_MASTER_H
 #define AUTH_MASTER_H
 
+#include "network.h"
+
+struct auth_user_info {
+       const char *service;
+       struct ip_addr local_ip, remote_ip;
+       unsigned int local_port, remote_port;
+};
+
 struct auth_user_reply {
        uid_t uid;
        gid_t gid;
@@ -12,10 +20,14 @@ struct auth_master_connection *
 auth_master_init(const char *auth_socket_path, bool debug);
 void auth_master_deinit(struct auth_master_connection **conn);
 
-/* Returns -1 = error, 0 = user not found, 1 = ok */
+/* Do a USER lookup. Returns -1 = error, 0 = user not found, 1 = ok */
 int auth_master_user_lookup(struct auth_master_connection *conn,
-                           const char *user, const char *service,
+                           const char *user, const struct auth_user_info *info,
                            pool_t pool, struct auth_user_reply *reply_r);
+/* 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);
 
 /* Iterate through all users. */
 struct auth_master_user_list_ctx *
index 7046e5676a94ee72b317bb10721281d8604a7d94..714fe69393887696619730bfefbd471b9472cce7 100644 (file)
@@ -149,19 +149,26 @@ user_reply_handle(struct setting_parser_context *set_parser,
 static int
 service_auth_userdb_lookup(struct auth_master_connection *conn,
                           struct setting_parser_context *set_parser,
-                          const char *name,
+                          const char *service_name,
+                          const struct mail_storage_service_input *input,
                           const struct mail_user_settings *user_set,
                           const char **user, const char **system_groups_user_r,
                           const char **error_r)
 {
+       struct auth_user_info info;
        struct auth_user_reply reply;
        const char *system_groups_user, *orig_user = *user;
        unsigned int len;
        pool_t pool;
        int ret;
 
+       memset(&info, 0, sizeof(info));
+       info.service = service_name;
+       info.local_ip = input->local_ip;
+       info.remote_ip = input->remote_ip;
+
        pool = pool_alloconly_create("userdb lookup", 1024);
-       ret = auth_master_user_lookup(conn, *user, name, pool, &reply);
+       ret = auth_master_user_lookup(conn, *user, &info, pool, &reply);
        if (ret > 0) {
                len = reply.chroot == NULL ? 0 : strlen(reply.chroot);
 
@@ -539,7 +546,8 @@ init_user_real(struct master_service *service,
                conn = auth_master_init(user_set->auth_socket_path,
                                        mail_set->mail_debug);
                if (service_auth_userdb_lookup(conn, service->set_parser,
-                                              service->name, user_set, &user,
+                                              service->name, &input,
+                                              user_set, &user,
                                               &system_groups_user,
                                               &error) <= 0)
                        i_fatal("%s", error);
@@ -660,6 +668,12 @@ mail_storage_service_multi_init(struct master_service *service,
        return ctx;
 }
 
+struct auth_master_connection *
+mail_storage_service_multi_get_auth_conn(struct mail_storage_service_multi_ctx *ctx)
+{
+       return ctx->conn;
+}
+
 int mail_storage_service_multi_lookup(struct mail_storage_service_multi_ctx *ctx,
                                      const struct mail_storage_service_input *input,
                                      pool_t pool,
@@ -684,7 +698,7 @@ int mail_storage_service_multi_lookup(struct mail_storage_service_multi_ctx *ctx
        if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0) {
                orig_user = username = user->input.username;
                ret = service_auth_userdb_lookup(ctx->conn, user->set_parser,
-                                                ctx->service->name,
+                                                ctx->service->name, input,
                                                 user->user_set, &username,
                                                 &user->system_groups_user,
                                                 error_r);
index bd631fa2e0421df0c1e020664f7402a172725183..4ed7f3c328d25bb4e55a72ab5abd16fdd1d1f45e 100644 (file)
@@ -39,6 +39,8 @@ struct mail_storage_service_multi_ctx *
 mail_storage_service_multi_init(struct master_service *service,
                                const struct setting_parser_info *set_roots[],
                                enum mail_storage_service_flags flags);
+struct auth_master_connection *
+mail_storage_service_multi_get_auth_conn(struct mail_storage_service_multi_ctx *ctx);
 /* Returns 1 if ok, 0 if user wasn't found, -1 if error. */
 int mail_storage_service_multi_lookup(struct mail_storage_service_multi_ctx *ctx,
                                      const struct mail_storage_service_input *input,
index e5ed351bededf73abb0dea473e33c1faa1f170cb..e9afeac1b7e4c0994aa2a73d1a36cbf8e431f8d0 100644 (file)
@@ -241,10 +241,18 @@ const char *mail_user_home_expand(struct mail_user *user, const char *path)
 
 int mail_user_get_home(struct mail_user *user, const char **home_r)
 {
+       struct auth_user_info info;
        struct auth_user_reply reply;
        pool_t userdb_pool;
        int ret;
 
+       memset(&info, 0, sizeof(info));
+       info.service = "lib-storage";
+       if (user->local_ip != NULL)
+               info.local_ip = *user->local_ip;
+       if (user->remote_ip != NULL)
+               info.remote_ip = *user->remote_ip;
+
        if (user->home_looked_up) {
                *home_r = user->_home;
                return user->_home != NULL ? 1 : 0;
@@ -252,7 +260,7 @@ int mail_user_get_home(struct mail_user *user, const char **home_r)
 
        userdb_pool = pool_alloconly_create("userdb lookup", 512);
        ret = auth_master_user_lookup(auth_master_conn, user->username,
-                                     "lib-storage", userdb_pool, &reply);
+                                     &info, userdb_pool, &reply);
        if (ret < 0)
                *home_r = NULL;
        else {