diff --git a/src/managesieve/main.c b/src/managesieve/main.c index 43e89ce074fb6945bb8ee5b029b4ea14edcf6a89..b244f007027d9fc4762b60b3c11d21bd6de2e029 100644 --- a/src/managesieve/main.c +++ b/src/managesieve/main.c @@ -12,6 +12,7 @@ #include "base64.h" #include "process-title.h" #include "restrict-access.h" +#include "time-util.h" #include "settings.h" #include "master-interface.h" #include "master-service-settings.h" @@ -21,6 +22,7 @@ #include "mail-user.h" #include "mail-storage-service.h" +#include "managesieve-quote.h" #include "managesieve-common.h" #include "managesieve-commands.h" #include "managesieve-capabilities.h" @@ -142,7 +144,7 @@ static void client_logged_in(struct client *client) static int client_create_from_input(const struct mail_storage_service_input *input, int fd_in, int fd_out, const buffer_t *input_buf, - const char **error_r) + const char **client_error_r, const char **error_r) { struct mail_storage_service_input service_input; struct mail_user *mail_user; @@ -150,6 +152,9 @@ client_create_from_input(const struct mail_storage_service_input *input, struct managesieve_settings *set; struct event *event; + *client_error_r = NULL; + *error_r = NULL; + event = event_create(NULL); event_add_category(event, &event_category_managesieve); event_add_fields(event, (const struct event_add_field []){ @@ -177,7 +182,8 @@ client_create_from_input(const struct mail_storage_service_input *input, verbose_proctitle = TRUE; if (client_create(fd_in, fd_out, input->session_id, - event, mail_user, set, &client, error_r) < 0) { + event, mail_user, set, + &client, client_error_r, error_r) < 0) { settings_free(set); mail_user_unref(&mail_user); event_unref(&event); @@ -196,7 +202,7 @@ client_create_from_input(const struct mail_storage_service_input *input, static void main_stdio_run(const char *username) { struct mail_storage_service_input input; - const char *value, *error, *input_base64; + const char *value, *client_error, *error, *input_base64; buffer_t *input_buf; i_zero(&input); @@ -216,7 +222,7 @@ static void main_stdio_run(const char *username) NULL : t_base64_decode_str(input_base64)); if (client_create_from_input(&input, STDIN_FILENO, STDOUT_FILENO, - input_buf, &error) < 0) + input_buf, &client_error, &error) < 0) i_fatal("%s", error); } @@ -224,10 +230,9 @@ static void login_request_finished(const struct login_server_request *request, const char *username, const char *const *extra_fields) { -#define MSG_BYE_INTERNAL_ERROR "BYE \""CRITICAL_MSG"\"\r\n" struct mail_storage_service_input input; enum login_request_flags flags = request->auth_req.flags; - const char *error; + const char *client_error, *error; buffer_t input_buf; i_zero(&input); @@ -245,11 +250,21 @@ login_request_finished(const struct login_server_request *request, buffer_create_from_const_data(&input_buf, request->data, request->auth_req.data_size); if (client_create_from_input(&input, request->fd, request->fd, - &input_buf, &error) < 0) { + &input_buf, &client_error, &error) < 0) { + string_t *byemsg; int fd = request->fd; - if (write(fd, MSG_BYE_INTERNAL_ERROR, - strlen(MSG_BYE_INTERNAL_ERROR)) < 0) { + if (client_error == NULL) { + client_error = t_strflocaltime(CRITICAL_MSG_STAMP, + ioloop_time); + } + + byemsg = t_str_new(256); + str_append(byemsg, "BYE "); + managesieve_quote_append_string(byemsg, client_error, FALSE); + str_append(byemsg, "\r\n"); + + if (write(fd, str_data(byemsg), str_len(byemsg)) < 0) { if (errno != EAGAIN && errno != EPIPE) i_error("write(client) failed: %m"); } diff --git a/src/managesieve/managesieve-client.c b/src/managesieve/managesieve-client.c index 3a23226fbeb23bab2305c1004b6341979c36bb38..ec7b8de16c11949c025f9ac5a08674c8d7d2e598 100644 --- a/src/managesieve/managesieve-client.c +++ b/src/managesieve/managesieve-client.c @@ -61,50 +61,50 @@ static void client_idle_timeout(struct client *client) } } -static struct sieve_storage * -client_get_storage(struct sieve_instance *svinst, struct event *event, - struct mail_user *user, int fd_out) +static int +client_get_storage(struct sieve_instance *svinst, struct mail_user *user, + struct sieve_storage **storage_r, + const char **client_error_r, const char **error_r) { struct sieve_storage *storage; enum sieve_error error_code; - const char *errormsg, *byemsg; - /* Open personal script storage */ + *storage_r = NULL; + /* Open personal script storage */ if (sieve_storage_create_personal(svinst, user, SIEVE_STORAGE_FLAG_READWRITE, &storage, &error_code) < 0) { switch (error_code) { case SIEVE_ERROR_NOT_POSSIBLE: - byemsg = "BYE \"Sieve processing is disabled for this user.\"\r\n"; - errormsg = "Failed to open Sieve storage: " + *client_error_r = + "Sieve processing is disabled for this user"; + *error_r = "Failed to open Sieve storage: " "Sieve is disabled for this user"; break; case SIEVE_ERROR_NOT_FOUND: - byemsg = "BYE \"This user cannot manage personal Sieve scripts.\"\r\n"; - errormsg = "Failed to open Sieve storage: " - "Personal script storage disabled or not found."; + *client_error_r = + "This user cannot manage personal Sieve scripts"; + *error_r = "Failed to open Sieve storage: " + "Personal script storage disabled or not found"; break; default: - byemsg = t_strflocaltime( - "BYE \""CRITICAL_MSG_STAMP"\"\r\n", ioloop_time); - errormsg = "Failed to open Sieve storage."; - } - - if (write(fd_out, byemsg, strlen(byemsg)) < 0) { - if (errno != EAGAIN && errno != EPIPE) - e_error(event, "write(client) failed: %m"); + *client_error_r = t_strflocaltime(CRITICAL_MSG_STAMP, + ioloop_time); + *error_r = "Failed to open Sieve storage."; } - i_fatal("%s", errormsg); + return -1; } - return storage; + *storage_r = storage; + return 0; } int client_create(int fd_in, int fd_out, const char *session_id, struct event *event, struct mail_user *user, const struct managesieve_settings *set, - struct client **client_r, const char **error_r) + struct client **client_r, const char **client_error_r, + const char **error_r) { struct client *client; struct sieve_environment svenv; @@ -112,6 +112,8 @@ int client_create(int fd_in, int fd_out, const char *session_id, struct sieve_storage *storage; pool_t pool; + *client_error_r = NULL; + *error_r = NULL; *client_r = NULL; *error_r = NULL; @@ -132,7 +134,9 @@ int client_create(int fd_in, int fd_out, const char *session_id, /* Get Sieve storage */ - storage = client_get_storage(svinst, event, user, fd_out); + if (client_get_storage(svinst, user, &storage, + client_error_r, error_r) < 0) + return -1; /* always use nonblocking I/O */ net_set_nonblock(fd_in, TRUE); diff --git a/src/managesieve/managesieve-client.h b/src/managesieve/managesieve-client.h index c06ccb50fd59480fb560e84994ee75e1bc716b63..03f13c2f14905ab3b4c4330165beb61951e40e89 100644 --- a/src/managesieve/managesieve-client.h +++ b/src/managesieve/managesieve-client.h @@ -94,7 +94,8 @@ extern unsigned int managesieve_client_count; int client_create(int fd_in, int fd_out, const char *session_id, struct event *event, struct mail_user *user, const struct managesieve_settings *set, - struct client **client_r, const char **error_r); + struct client **client_r, const char **client_error_r, + const char **error_r); void client_create_finish(struct client *client); void client_destroy(struct client *client, const char *reason);