bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch/* max. length of input lines (URLs) */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch/* Disconnect client after idling this many milliseconds */
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch#define IMAP_URLAUTH_WORKER_PROTOCOL_MAJOR_VERSION 2
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#define IMAP_URLAUTH_WORKER_PROTOCOL_MINOR_VERSION 0
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct mail_storage_service_user *service_user;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* settings: */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const struct imap_urlauth_worker_settings *set;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic struct mail_storage_service_ctx *storage_service;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_destroy(struct client *client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_abort(struct client *client, const char *reason);
4fa772eefd5a22a597601488be44997e788cb60dStephan Boschstatic int client_run_url(struct client *client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_input(struct client *client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic bool client_handle_input(struct client *client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int client_output(struct client *client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_ctrl_input(struct client *client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_worker_refresh_proctitle(void)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct client *client = imap_urlauth_worker_clients;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(title, client->mail_user->username);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_idle_timeout(struct client *client)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Session closed for inactivity in reading our output");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* always use nonblocking I/O */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->access_anonymous = TRUE; /* default until overridden */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->ctrl_io = io_add(fd, IO_READ, client_ctrl_input, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST_PREPEND(&imap_urlauth_worker_clients, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic struct client *
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschclient_create_standalone(const char *access_user,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *access_applications,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* always use nonblocking I/O */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (access_user != NULL && *access_user != '\0')
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *apps = access_applications;
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->input = i_stream_create_fd(fd_in, MAX_INBUF_SIZE);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->output = o_stream_create_fd(fd_out, (size_t)-1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->io = io_add(fd_in, IO_READ, client_input, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch o_stream_set_flush_callback(client->output, client_output, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST_PREPEND(&imap_urlauth_worker_clients, client);
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("imap-urlauth[%s](%s): ",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_abort(struct client *client, const char *reason)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_destroy(struct client *client)
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("imap-urlauth[%s](%s): ",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* deinitialize url */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST_REMOVE(&imap_urlauth_worker_clients, client);
33a80622828063f5be6f743855d5273fabe8ae58Timo Sirainen fd_close_maybe_stdio(&client->fd_in, &client->fd_out);
eb318ea05532d2e54ed3bfc89bc15dcf1adae838Timo Sirainen mail_storage_service_user_unref(&client->service_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch array_foreach_modifiable(&client->access_apps, app)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch master_service_client_connection_destroyed(master_service);
4fa772eefd5a22a597601488be44997e788cb60dStephan Boschstatic int client_run_url(struct client *client)
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody while (i_stream_read_more(client->msg_part_input, &data, &size) > 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((ret = o_stream_send(client->output, data, size)) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (o_stream_get_buffer_used_size(client->output) >= 4096) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((ret = o_stream_flush(client->output)) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschclient_send_line(struct client *client, const char *fmt, ...)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(ret < 0 || (size_t)ret == str_len(str));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschclient_fetch_urlpart(struct client *client, const char *url,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char **bpstruct_r, bool *binary_with_nuls_r,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = imap_urlauth_fetch(client->urlauth_ctx, url,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch error = t_strdup_printf("Failed to fetch URLAUTH \"%s\": %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* don't leak info about existence/accessibility
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch of mailboxes */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((url_flags & IMAP_URLAUTH_FETCH_FLAG_BINARY) != 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_msgpart_url_set_decode_to_binary(client->url);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((url_flags & IMAP_URLAUTH_FETCH_FLAG_BODYPARTSTRUCTURE) != 0) {
2d72e8492960794037a1ca90df34f7ab2a170a81Timo Sirainen ret = imap_msgpart_url_get_bodypartstructure(client->url,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Failed to read URLAUTH \"%s\": %s", url, error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* if requested, read the message part the URL points to */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((url_flags & IMAP_URLAUTH_FETCH_FLAG_BODY) != 0 ||
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (url_flags & IMAP_URLAUTH_FETCH_FLAG_BINARY) != 0) {
2d72e8492960794037a1ca90df34f7ab2a170a81Timo Sirainen ret = imap_msgpart_url_read_part(client->url, &mpresult, &error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Failed to read URLAUTH \"%s\": %s", url, error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *binary_with_nuls_r = mpresult.binary_decoded_input_has_nuls;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int client_fetch_url(struct client *client, const char *url,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* fetch URL */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = client_fetch_urlpart(client, url, url_flags, &bpstruct,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* fetch failed */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* don't send error details to anonymous users: just to be sure
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch that no information about the target user account is unduly
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->access_anonymous || errormsg == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* fetch failed badly */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Session aborted: Fatal failure while fetching URL");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(response, str_tabescape(bpstruct));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("Fetched URLAUTH yielded BODYPARTSTRUCTURE (%s)",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* return content */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->msg_part_size == 0 || client->msg_part_input == NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_send_line(client, "%s", str_c(response));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("Fetched URLAUTH yielded empty result");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* actual content */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_printfa(response, "\t%"PRIuUOFF_T, client->msg_part_size);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_send_line(client, "%s", str_c(response));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("Fetched URLAUTH yielded %"PRIuUOFF_T" bytes "
9008daea438f0e389b37aabbbde62a1f02725e32Timo Sirainen "Session aborted: Fatal failure while transferring URL");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* URL not finished */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch o_stream_set_flush_pending(client->output, TRUE);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschclient_handle_command(struct client *client, const char *cmd,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *args, const char **error_r)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* "URL"["\tbody"]["\tbinary"]["\tbpstruct"]"\t"<url>:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch fetch URL (meta)data */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch url_flags |= IMAP_URLAUTH_FETCH_FLAG_BODYPARTSTRUCTURE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = client_fetch_url(client, url, url_flags);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* "END": unselect current user (closes worker) */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *error_r = "END: Invalid number of parameters";
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (void)o_stream_send_str(client->ctrl_output, "FINISHED\n");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *error_r = t_strconcat("Unknown or inappropriate command: ", cmd, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschclient_handle_user_command(struct client *client, const char *cmd,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *args, const char **error_r)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* "USER\t"<username> */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* check command syntax */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *error_r = t_strconcat("Unknown or inappropriate command: ",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *error_r = "USER: Invalid number of parameters";
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* lookup user */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("Looking up user %s", input.username);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = mail_storage_service_lookup_next(storage_service, &input,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("Failed to lookup user %s: %s", input.username, error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Session aborted: Failed to lookup user");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else if (ret == 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("User %s doesn't exist", input.username);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* drop privileges */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch set = mail_storage_service_user_get_set(user)[1];
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (settings_var_expand(&imap_urlauth_worker_setting_parser_info, set,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen "Session aborted: Failed to expand settings: %s", error));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("Found user account `%s' on behalf of user `%s'",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* initialize urlauth context */
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen i_error("imap_urlauth_host setting is not configured for user %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Session aborted: URLAUTH not configured");
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch config.access_service = client->access_service;
6541da94741ea43514cdac3dd2ebbcf839ffb783Stephan Bosch config.access_anonymous = client->access_anonymous;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (const void *)array_get(&client->access_apps, &count);
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen client->urlauth_ctx = imap_urlauth_init(client->mail_user, &config);
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch i_debug("Providing access to user account `%s' on behalf of user `%s' "
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch "using service `%s'", mail_user->username, client->access_user,
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("imap-urlauth[%s](%s->%s): ",
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen my_pid, client->access_user, mail_user->username);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic bool client_handle_input(struct client *client)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* we're still processing a URL. wait until it's
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* disconnected */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (void)o_stream_send_str(client->ctrl_output, "DISCONNECTED\n");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* line too long, kill it */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Session aborted: Input line too long");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while ((line = i_stream_next_line(client->input)) != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *args = t_strsplit_tabescaped(line);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = client_handle_user_command(client, cmd, args, &error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = client_handle_command(client, cmd, args, &error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Session aborted: Unexpected input");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_input(struct client *client)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int client_output(struct client *client)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (void)o_stream_send_str(client->ctrl_output, "DISCONNECTED\n");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->url == NULL && client->waiting_input) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* client got destroyed */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* url not finished yet */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* data still in output buffer, get back here to add IO */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* unexpectedly disconnected */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else if (ret < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("fd_read() returned invalid byte 0x%2x", data);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->fd_in == -1 || client->fd_out == -1) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("Handshake is missing a file descriptor");
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi i_stream_create_fd(client->fd_ctrl, MAX_INBUF_SIZE);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->ctrl_output = o_stream_create_fd(client->fd_ctrl, (size_t)-1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_ctrl_input(struct client *client)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->fd_in == -1 || client->fd_out == -1) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((ret = client_ctrl_read_fds(client)) <= 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* disconnected */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* line too long, kill it */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Control session aborted: Input line too long");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((line = i_stream_next_line(client->ctrl_input)) == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (!version_string_verify(line, "imap-urlauth-worker",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch IMAP_URLAUTH_WORKER_PROTOCOL_MAJOR_VERSION)) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth-worker client not compatible with this server "
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Control session aborted: Version mismatch");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (o_stream_send_str(client->ctrl_output, "OK\n") < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Control session aborted: Unexpected input");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((line = i_stream_next_line(client->ctrl_input)) == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (*args == NULL || strcmp(*args, "ACCESS") != 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("Invalid control command: %s", str_sanitize(line, 80));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Control session aborted: Invalid command");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("Invalid ACCESS command: %s", str_sanitize(line, 80));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Control session aborted: Invalid command");
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("imap-urlauth[%s](%s): ",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* apps=<access-application>[,<access-application,...] */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else if (strncasecmp(*args, "apps=", 5) == 0 &&
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *apps = t_strsplit(*args+5, ",");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("Invalid ACCESS parameter: %s", str_sanitize(*args, 80));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Control session aborted: Invalid command");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (o_stream_send_str(client->ctrl_output, "OK\n") < 0) {
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->input = i_stream_create_fd(client->fd_in, MAX_INBUF_SIZE);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->output = o_stream_create_fd(client->fd_out, (size_t)-1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->io = io_add(client->fd_in, IO_READ, client_input, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch o_stream_set_flush_callback(client->output, client_output, client);
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch i_debug("Worker activated for access by user `%s' using service `%s'",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* do nothing */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void main_stdio_run(const char *access_user,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *access_applications)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch access_user = access_user != NULL ? access_user : getenv("USER");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (void)client_create_standalone(access_user, access_applications,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_connected(struct master_service_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch master_service_client_connection_accept(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch static const struct setting_parser_info *set_roots[] = {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch enum mail_storage_service_flags storage_service_flags =
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch service_flags |= MASTER_SERVICE_FLAG_STANDALONE |
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch service_flags |= MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch master_service = master_service_init("imap-urlauth-worker", service_flags,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while ((c = master_getopt(master_service)) > 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_fatal_status(EX_USAGE, "Unknown argument: %s", argv[optind]);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch t_strdup_printf("imap-urlauth[%s]: ", my_pid));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch master_service_set_die_callback(master_service, imap_urlauth_worker_die);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* fake that we're running, so we know if client was destroyed
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while handling its initial input */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch main_stdio_run(access_user, array_idx(&access_apps,0));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch master_service_run(master_service, client_connected);