]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm: Added new "auth login" command to simulate an actual client login.
authorTimo Sirainen <tss@iki.fi>
Mon, 7 Sep 2015 18:54:20 +0000 (21:54 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 7 Sep 2015 18:54:20 +0000 (21:54 +0300)
This performs both passdb and userdb lookups and prints their results.

src/doveadm/doveadm-auth.c

index f96f0dcee0b720e80666867cad018991f0e601db..e8cf80c5dc5d50d0a26ab0e3bf2c308b7d3da295 100644 (file)
@@ -5,6 +5,7 @@
 #include "array.h"
 #include "askpass.h"
 #include "base64.h"
+#include "hex-binary.h"
 #include "str.h"
 #include "wildcard-match.h"
 #include "settings-parser.h"
@@ -13,6 +14,8 @@
 #include "auth-client.h"
 #include "auth-master.h"
 #include "auth-server-connection.h"
+#include "master-auth.h"
+#include "master-login-auth.h"
 #include "mail-storage-service.h"
 #include "mail-user.h"
 #include "doveadm.h"
 #include <unistd.h>
 
 struct authtest_input {
+       pool_t pool;
        const char *username;
        const char *password;
        struct auth_user_info info;
        bool success;
+
+       struct auth_client_request *request;
+       struct master_auth_request master_auth_req;
+
+       unsigned int auth_id;
+       unsigned int auth_pid;
+       const char *auth_cookie;
+
 };
 
 static void auth_cmd_help(doveadm_command_t *cmd);
@@ -106,6 +118,12 @@ auth_callback(struct auth_client_request *request ATTR_UNUSED,
 {
        struct authtest_input *input = context;
 
+       input->request = NULL;
+       input->auth_id = auth_client_request_get_id(request);
+       input->auth_pid = auth_client_request_get_server_pid(request);
+       input->auth_cookie = input->pool == NULL ? NULL :
+               p_strdup(input->pool, auth_client_request_get_cookie(request));
+
        if (!io_loop_is_running(current_ioloop))
                return;
 
@@ -155,8 +173,8 @@ static void auth_connected(struct auth_client *client,
        info.remote_port = input->info.remote_port;
        info.initial_resp_base64 = str_c(base64_resp);
 
-       (void)auth_client_request_new(client, &info,
-                                     auth_callback, input);
+       input->request = auth_client_request_new(client, &info,
+                                                auth_callback, input);
 }
 
 static void
@@ -293,6 +311,109 @@ static void cmd_auth_test(int argc, char *argv[])
                doveadm_exit_code = EX_NOPERM;
 }
 
+static void
+master_auth_callback(const char *const *auth_args,
+                    const char *errormsg, void *context)
+{
+       struct authtest_input *input = context;
+       unsigned int i;
+
+       io_loop_stop(current_ioloop);
+       if (errormsg != NULL) {
+               i_error("userdb lookup failed: %s", errormsg);
+               return;
+       }
+       printf("userdb extra fields:\n");
+       for (i = 0; auth_args[i] != NULL; i++)
+               printf("  %s\n", auth_args[i]);
+       input->success = TRUE;
+}
+
+static void
+cmd_auth_master_input(const char *auth_master_socket_path,
+                     struct authtest_input *input)
+{
+       struct master_login_auth *master_auth;
+       struct master_auth_request master_auth_req;
+       buffer_t buf;
+
+       memset(&master_auth_req, 0, sizeof(master_auth_req));
+       master_auth_req.tag = 1;
+       master_auth_req.auth_pid = input->auth_pid;
+       master_auth_req.auth_id = input->auth_id;
+       master_auth_req.client_pid = getpid();
+       master_auth_req.local_ip = input->info.local_ip;
+       master_auth_req.remote_ip = input->info.remote_ip;
+
+       buffer_create_from_data(&buf, master_auth_req.cookie,
+                               sizeof(master_auth_req.cookie));
+       if (strlen(input->auth_cookie) == MASTER_AUTH_COOKIE_SIZE*2)
+               (void)hex_to_binary(input->auth_cookie, &buf);
+
+       input->success = FALSE;
+       master_auth = master_login_auth_init(auth_master_socket_path, FALSE);
+       io_loop_set_running(current_ioloop);
+       master_login_auth_request(master_auth, &master_auth_req,
+                                 master_auth_callback, input);
+       if (io_loop_is_running(current_ioloop))
+               io_loop_run(current_ioloop);
+       master_login_auth_deinit(&master_auth);
+}
+
+static void cmd_auth_login(int argc, char *argv[])
+{
+       const char *auth_login_socket_path, *auth_master_socket_path;
+       struct auth_client *auth_client;
+       struct authtest_input input;
+       int c;
+
+       memset(&input, 0, sizeof(input));
+       input.info.service = "doveadm";
+
+       auth_login_socket_path = t_strconcat(doveadm_settings->base_dir,
+                                            "/auth-login", NULL);
+       auth_master_socket_path = t_strconcat(doveadm_settings->base_dir,
+                                             "/auth-master", NULL);
+       while ((c = getopt(argc, argv, "a:m:x:")) > 0) {
+               switch (c) {
+               case 'a':
+                       auth_login_socket_path = optarg;
+                       break;
+               case 'm':
+                       auth_master_socket_path = optarg;
+                       break;
+               case 'x':
+                       auth_user_info_parse(&input.info, optarg);
+                       break;
+               default:
+                       auth_cmd_help(cmd_auth_login);
+               }
+       }
+
+       if (optind == argc)
+               auth_cmd_help(cmd_auth_login);
+
+       input.pool = pool_alloconly_create("auth login", 256);
+       input.username = argv[optind++];
+       input.password = argv[optind] != NULL ? argv[optind++] :
+               t_askpass("Password: ");
+       if (argv[optind] != NULL)
+                       i_fatal("Unexpected parameter: %s", argv[optind]);
+       /* authenticate */
+       auth_client = auth_client_init(auth_login_socket_path, getpid(), FALSE);
+       auth_client_set_connect_notify(auth_client, auth_connected, &input);
+       if (!auth_client_is_disconnected(auth_client))
+               io_loop_run(current_ioloop);
+       auth_client_set_connect_notify(auth_client, NULL, NULL);
+       /* finish login with userdb lookup */
+       if (input.success)
+               cmd_auth_master_input(auth_master_socket_path, &input);
+       if (!input.success)
+               doveadm_exit_code = EX_NOPERM;
+       auth_client_deinit(&auth_client);
+       pool_unref(&input.pool);
+}
+
 static void cmd_auth_lookup(int argc, char *argv[])
 {
        const char *auth_socket_path = doveadm_settings->auth_socket_path;
@@ -522,6 +643,8 @@ static void cmd_user(int argc, char *argv[])
 struct doveadm_cmd doveadm_cmd_auth[] = {
        { cmd_auth_test, "auth test",
          "[-a <auth socket path>] [-x <auth info>] <user> [<password>]" },
+       { cmd_auth_login, "auth login",
+         "[-a <auth-login socket path>] [-m <auth-master socket path>] [-x <auth info>] <user> [<password>]" },
        { cmd_auth_lookup, "auth lookup",
          "[-a <userdb socket path>] [-x <auth info>] [-f field] <user> [...]" },
        { cmd_auth_cache_flush, "auth cache flush",