]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-master: Allow userdb to return postlogin socket path.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Sun, 23 Jul 2017 09:32:38 +0000 (12:32 +0300)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Mon, 14 Aug 2017 08:19:59 +0000 (11:19 +0300)
Returning "postlogin=socketpath" as userdb extra field overrides the
postlogin socket path in the service { executable } parameter.

src/lib-master/master-login.c

index 800e206e1b9ccf43b8361d237ba2fb8e753f5ebf..f694ad018e4eb3bd57b2adf69ec875928f94c355 100644 (file)
@@ -40,6 +40,7 @@ struct master_login_postlogin {
        struct timeout *to;
        string_t *input;
        char *username;
+       char *socket_path;
 };
 
 struct master_login {
@@ -231,13 +232,13 @@ static void master_login_postlogin_free(struct master_login_postlogin *pl)
        if (close(pl->fd) < 0)
                i_error("close(postlogin) failed: %m");
        str_free(&pl->input);
+       i_free(pl->socket_path);
        i_free(pl->username);
        i_free(pl);
 }
 
 static void master_login_postlogin_input(struct master_login_postlogin *pl)
 {
-       struct master_login *login = pl->client->conn->login;
        char buf[1024];
        const char **auth_args, **p;
        size_t len;
@@ -263,11 +264,10 @@ static void master_login_postlogin_input(struct master_login_postlogin *pl)
                        if (errno == EAGAIN)
                                return;
 
-                       i_error("fd_read(%s) failed: %m",
-                               login->postlogin_socket_path);
+                       i_error("fd_read(%s) failed: %m", pl->socket_path);
                } else if (str_len(pl->input) > 0) {
                        i_error("fd_read(%s) failed: disconnected",
-                               login->postlogin_socket_path);
+                               pl->socket_path);
                } else {
                        i_info("Post-login script denied access to user %s",
                               pl->username);
@@ -287,17 +287,16 @@ static void master_login_postlogin_input(struct master_login_postlogin *pl)
 
 static void master_login_postlogin_timeout(struct master_login_postlogin *pl)
 {
-       struct master_login *login = pl->client->conn->login;
-
        i_error("%s: Timeout waiting for post-login script to finish, aborting",
-               login->postlogin_socket_path);
+               pl->socket_path);
 
        master_login_client_free(&pl->client);
        master_login_postlogin_free(pl);
 }
 
 static int master_login_postlogin(struct master_login_client *client,
-                                 const char *const *auth_args)
+                                 const char *const *auth_args,
+                                 const char *socket_path)
 {
        struct master_login *login = client->conn->login;
        struct master_login_postlogin *pl;
@@ -306,10 +305,10 @@ static int master_login_postlogin(struct master_login_client *client,
        int fd;
        ssize_t ret;
 
-       fd = net_connect_unix_with_retries(login->postlogin_socket_path, 1000);
+       fd = net_connect_unix_with_retries(socket_path, 1000);
        if (fd == -1) {
                i_error("net_connect_unix(%s) failed: %m%s",
-                       login->postlogin_socket_path, errno != EAGAIN ? "" :
+                       socket_path, errno != EAGAIN ? "" :
                        " - http://wiki2.dovecot.org/SocketUnavailable");
                return -1;
        }
@@ -326,11 +325,9 @@ static int master_login_postlogin(struct master_login_client *client,
        ret = fd_send(fd, client->fd, str_data(str), str_len(str));
        if (ret != (ssize_t)str_len(str)) {
                if (ret < 0) {
-                       i_error("write(%s) failed: %m",
-                               login->postlogin_socket_path);
+                       i_error("write(%s) failed: %m", socket_path);
                } else {
-                       i_error("write(%s) failed: partial write",
-                               login->postlogin_socket_path);
+                       i_error("write(%s) failed: partial write", socket_path);
                }
                i_close_fd(&fd);
                return -1;
@@ -340,6 +337,7 @@ static int master_login_postlogin(struct master_login_client *client,
        pl = i_new(struct master_login_postlogin, 1);
        pl->client = client;
        pl->username = i_strdup(auth_args[0]);
+       pl->socket_path = i_strdup(socket_path);
        pl->fd = fd;
        pl->io = io_add(fd, IO_READ, master_login_postlogin_input, pl);
        pl->to = timeout_add(login->postlogin_timeout_secs * 1000,
@@ -348,6 +346,16 @@ static int master_login_postlogin(struct master_login_client *client,
        return 0;
 }
 
+static const char *
+auth_args_find_postlogin_socket(const char *const *auth_args)
+{
+       for (unsigned int i = 0; auth_args[i] != NULL; i++) {
+               if (strncmp(auth_args[i], "postlogin=", 10) == 0)
+                       return auth_args[i]+10;
+       }
+       return NULL;
+}
+
 static void
 master_login_auth_callback(const char *const *auth_args, const char *errormsg,
                           void *context)
@@ -355,6 +363,7 @@ master_login_auth_callback(const char *const *auth_args, const char *errormsg,
        struct master_login_client *client = context;
        struct master_login_connection *conn = client->conn;
        struct master_auth_reply reply;
+       const char *postlogin_socket_path;
 
        i_zero(&reply);
        reply.tag = client->auth_req.tag;
@@ -375,7 +384,11 @@ master_login_auth_callback(const char *const *auth_args, const char *errormsg,
        i_set_failure_prefix("%s(%s): ", client->conn->login->service->name,
                             auth_args[0]);
 
-       if (conn->login->postlogin_socket_path == NULL)
+       postlogin_socket_path = auth_args_find_postlogin_socket(auth_args);
+       if (postlogin_socket_path == NULL)
+               postlogin_socket_path = conn->login->postlogin_socket_path;
+
+       if (postlogin_socket_path == NULL)
                master_login_auth_finish(client, auth_args);
        else {
                /* we've sent the reply. the connection is no longer needed,
@@ -385,7 +398,8 @@ master_login_auth_callback(const char *const *auth_args, const char *errormsg,
                master_login_conn_unref(&conn);
 
                /* execute post-login scripts before finishing auth */
-               if (master_login_postlogin(client, auth_args) < 0)
+               if (master_login_postlogin(client, auth_args,
+                                          postlogin_socket_path) < 0)
                        master_login_client_free(&client);
        }
 }