# HG changeset patch # User Timo Sirainen # Date 1500802358 -10800 # Node ID 7ae7c3c159d1f704975fd2f6016f4aadc54a8d5a # Parent 55bd9d8ca7ceb647ae595de65e377a334a27d68b lib-master: Allow userdb to return postlogin socket path. Returning "postlogin=socketpath" as userdb extra field overrides the postlogin socket path in the service { executable } parameter. diff -r 55bd9d8ca7ce -r 7ae7c3c159d1 src/lib-master/master-login.c --- a/src/lib-master/master-login.c Wed Aug 09 13:23:36 2017 +0300 +++ b/src/lib-master/master-login.c Sun Jul 23 12:32:38 2017 +0300 @@ -40,6 +40,7 @@ struct timeout *to; string_t *input; char *username; + char *socket_path; }; struct master_login { @@ -231,13 +232,13 @@ 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 @@ 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_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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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_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); } }