static void dbox_file_copy_metadata(struct dbox_file *file, struct ostream *output, bool *have_guid_r) { const char *line; uoff_t prev_offset = file->input->v_offset; *have_guid_r = FALSE; while ((line = i_stream_read_next_line(file->input)) != NULL) { if (*line == DBOX_METADATA_OLDV1_SPACE || *line == '\0') { /* end of metadata */ return; } if (*line < 32) { /* broken - possibly a new pre-magic block */ i_stream_seek(file->input, prev_offset); return; } if (*line == DBOX_METADATA_VIRTUAL_SIZE) { /* it may be wrong - recreate it */ continue; } if (*line == DBOX_METADATA_GUID) *have_guid_r = TRUE; o_stream_send_str(output, line); o_stream_send_str(output, "\n"); } }
static void test_ostream_multiplex_simple(void) { test_begin("ostream multiplex (simple)"); const unsigned char expected[] = { '\x00','\x00','\x00','\x00','\x05','\x68','\x65', '\x6c','\x6c','\x6f','\x01','\x00','\x00','\x00', '\x05','\x77','\x6f','\x72','\x6c','\x64' }; buffer_t *result = t_str_new(64); struct ostream *os = test_ostream_create(result); struct ostream *os2 = o_stream_create_multiplex(os, (size_t)-1); struct ostream *os3 = o_stream_multiplex_add_channel(os2, 1); test_assert(o_stream_send_str(os2, "hello") == 5); test_assert(o_stream_send_str(os3, "world") == 5); o_stream_unref(&os3); o_stream_unref(&os2); o_stream_unref(&os); test_assert(sizeof(expected) == result->used); test_assert(memcmp(result->data, expected, I_MIN(sizeof(expected), result->used)) == 0); test_end(); }
void testsuite_result_print (const struct sieve_runtime_env *renv) { struct ostream *out; out = o_stream_create_fd(1, 0, FALSE); o_stream_send_str(out, "\n--"); sieve_result_print(_testsuite_result, renv->scriptenv, out, NULL); o_stream_send_str(out, "--\n\n"); o_stream_destroy(&out); }
static void lmtp_client_send_handshake(struct lmtp_client *client) { switch (client->protocol) { case LMTP_CLIENT_PROTOCOL_LMTP: o_stream_send_str(client->output, t_strdup_printf("LHLO %s\r\n", client->set.my_hostname)); break; case LMTP_CLIENT_PROTOCOL_SMTP: o_stream_send_str(client->output, t_strdup_printf("EHLO %s\r\n", client->set.my_hostname)); break; } }
static int client_input_notify(struct doveadm_connection *client, const char *const *args) { struct replicator_user *user; /* <username> <flags> <state> */ if (str_array_length(args) < 3) { i_error("%s: NOTIFY: Invalid parameters", client->conn.name); return -1; } user = replicator_queue_add(client->queue, args[0], REPLICATION_PRIORITY_NONE); if (args[1][0] == 'f') user->last_full_sync = ioloop_time; user->last_fast_sync = ioloop_time; user->last_update = ioloop_time; if (args[2][0] != '\0') { i_free(user->state); user->state = i_strdup(args[2]); } o_stream_send_str(client->conn.output, "+\n"); return 0; }
static int client_output(struct client *client) { if (o_stream_flush(client->output) < 0) { if (client->ctrl_output != NULL) (void)o_stream_send_str(client->ctrl_output, "DISCONNECTED\n"); client_destroy(client); return 1; } timeout_reset(client->to_idle); if (client->url != NULL) { if (client_run_url(client) < 0) { client_destroy(client); return 1; } if (client->url == NULL && client->waiting_input) { if (!client_handle_input(client)) { /* client got destroyed */ return 1; } } } if (client->url != NULL) { /* url not finished yet */ return 0; } else if (client->io == NULL) { /* data still in output buffer, get back here to add IO */ return 0; } else { return 1; } }
static void auth_worker_send_reply(struct auth_worker_client *client, string_t *str) { if (shutdown_request) o_stream_send_str(client->output, "SHUTDOWN\n"); o_stream_send(client->output, str_data(str), str_len(str)); }
void auth_client_send_cancel(struct auth_client *client, unsigned int id) { const char *str = t_strdup_printf("CANCEL\t%u\n", id); if (o_stream_send_str(client->conn->output, str) < 0) i_error("Error sending request to auth server: %m"); }
static int lmtp_client_data_next(struct lmtp_client *client, const char *line) { struct lmtp_rcpt *rcpt; unsigned int i, count; rcpt = array_get_modifiable(&client->recipients, &count); for (i = client->rcpt_next_data_idx; i < count; i++) { if (rcpt[i].failed) { /* already called rcpt_to_callback with failure */ continue; } client->rcpt_next_data_idx = i + 1; rcpt[i].failed = line[0] != '2'; rcpt[i].data_callback(!rcpt[i].failed, line, rcpt[i].context); if (client->protocol == LMTP_CLIENT_PROTOCOL_LMTP) break; } if (client->rcpt_next_data_idx < count) return 0; o_stream_send_str(client->output, "QUIT\r\n"); lmtp_client_close(client); return -1; }
static int write_from_line(struct mbox_save_context *ctx, time_t received_date, const char *from_envelope) { int ret; T_BEGIN { const char *line; if (from_envelope == NULL) { struct mail_storage *storage = &ctx->mbox->storage->storage; from_envelope = strchr(storage->user->username, '@') != NULL ? storage->user->username : t_strconcat(storage->user->username, "@", my_hostdomain(), NULL); } else if (*from_envelope == '\0') { /* can't write empty envelope */ from_envelope = "MAILER-DAEMON"; } /* save in local timezone, no matter what it was given with */ line = mbox_from_create(from_envelope, received_date); if ((ret = o_stream_send_str(ctx->output, line)) < 0) write_error(ctx); } T_END; return ret; }
static int master_input_cache_flush(struct auth_master_connection *conn, const char *args) { const char *const *list; unsigned int count; /* <id> [<user> [<user> [..]] */ list = t_strsplit_tab(args); if (list[0] == NULL) { i_error("BUG: doveadm sent broken CACHE-FLUSH"); return FALSE; } if (passdb_cache == NULL) { /* cache disabled */ count = 0; } else if (list[1] == NULL) { /* flush the whole cache */ count = auth_cache_clear(passdb_cache); } else { count = auth_cache_clear_users(passdb_cache, list+1); } (void)o_stream_send_str(conn->output, t_strdup_printf("OK\t%s\t%u\n", list[0], count)); return TRUE; }
static int client_handle_command(struct client *client, const char *cmd, const char *const *args, const char **error_r) { int ret; *error_r = NULL; /* "URL"["\tbody"]["\tbinary"]["\tbpstruct"]"\t"<url>: fetch URL (meta)data */ if (strcmp(cmd, "URL") == 0) { enum imap_urlauth_fetch_flags url_flags = 0; const char *url; if (*args == NULL) { *error_r = "URL: Missing URL parameter"; return -1; } url = *args; args++; while (*args != NULL) { if (strcasecmp(*args, "body") == 0) url_flags |= IMAP_URLAUTH_FETCH_FLAG_BODY; else if (strcasecmp(*args, "binary") == 0) url_flags |= IMAP_URLAUTH_FETCH_FLAG_BINARY; else if (strcasecmp(*args, "bpstruct") == 0) url_flags |= IMAP_URLAUTH_FETCH_FLAG_BODYPARTSTRUCTURE; args++; } if (url_flags == 0) url_flags = IMAP_URLAUTH_FETCH_FLAG_BODY; T_BEGIN { ret = client_fetch_url(client, url, url_flags); } T_END; return ret; } /* "END": unselect current user (closes worker) */ if (strcmp(cmd, "END") == 0) { if (args[0] != NULL) { *error_r = "END: Invalid number of parameters"; return -1; } client->finished = TRUE; if (client->ctrl_output != NULL) (void)o_stream_send_str(client->ctrl_output, "FINISHED\n"); client_destroy(client); return 0; } *error_r = t_strconcat("Unknown or inappropriate command: ", cmd, NULL); return -1; }
static void config_request_output(const char *key, const char *value, enum config_key_type type ATTR_UNUSED, void *context) { struct ostream *output = context; const char *p; o_stream_send_str(output, key); o_stream_send_str(output, "="); while ((p = strchr(value, '\n')) != NULL) { o_stream_send(output, value, p-value); o_stream_send(output, SETTING_STREAM_LF_CHAR, 1); value = p+1; } o_stream_send_str(output, value); o_stream_send_str(output, "\n"); }
static bool client_handle_input(struct client *client) { const char *line, *cmd, *error; int ret; if (client->url != NULL || client->to_delay != NULL) { /* we're still processing a URL. wait until it's finished. */ io_remove(&client->io); client->io = NULL; client->waiting_input = TRUE; return TRUE; } if (client->io == NULL) { client->io = io_add(client->fd_in, IO_READ, client_input, client); } client->waiting_input = FALSE; timeout_reset(client->to_idle); switch (i_stream_read(client->input)) { case -1: /* disconnected */ if (client->ctrl_output != NULL) (void)o_stream_send_str(client->ctrl_output, "DISCONNECTED\n"); client_destroy(client); return FALSE; case -2: /* line too long, kill it */ client_abort(client, "Session aborted: Input line too long"); return FALSE; } while ((line = i_stream_next_line(client->input)) != NULL) { const char *const *args = t_strsplit_tabescaped(line); if (args[0] == NULL) continue; cmd = args[0]; args++; if (client->mail_user == NULL) ret = client_handle_user_command(client, cmd, args, &error); else ret = client_handle_command(client, cmd, args, &error); if (ret <= 0) { if (ret == 0) break; i_error("Client input error: %s", error); client_abort(client, "Session aborted: Unexpected input"); return FALSE; } } return TRUE; }
static int client_input_remove(struct doveadm_connection *client, const char *const *args) { struct replicator_user *user; /* <username> */ if (str_array_length(args) != 1) { i_error("%s: REMOVE: Invalid parameters", client->conn.name); return -1; } user = replicator_queue_lookup(client->queue, args[0]); if (user == NULL) o_stream_send_str(client->conn.output, "-User not found\n"); else { replicator_queue_remove(client->queue, &user); o_stream_send_str(client->conn.output, "+\n"); } return 0; }
static void lmtp_client_send_rcpts(struct lmtp_client *client) { const struct lmtp_rcpt *rcpt; unsigned int i, count; rcpt = array_get(&client->recipients, &count); for (i = client->rcpt_next_send_idx; i < count; i++) { o_stream_send_str(client->output, t_strdup_printf("RCPT TO:<%s>\r\n", rcpt[i].address)); } client->rcpt_next_send_idx = i; }
static int client_input_replicate(struct doveadm_connection *client, const char *const *args) { struct replicator_queue_iter *iter; struct replicator_user *user; const char *usermask; enum replication_priority priority; unsigned int match_count; /* <priority> <username>|<mask> */ if (str_array_length(args) != 2) { i_error("%s: REPLICATE: Invalid parameters", client->conn.name); return -1; } if (replication_priority_parse(args[0], &priority) < 0) { o_stream_send_str(client->conn.output, "-Invalid priority\n"); return 0; } usermask = args[1]; if (strchr(usermask, '*') == NULL && strchr(usermask, '?') == NULL) { replicator_queue_add(client->queue, usermask, priority); o_stream_send_str(client->conn.output, "+1\n"); return 0; } match_count = 0; iter = replicator_queue_iter_init(client->queue); while ((user = replicator_queue_iter_next(iter)) != NULL) { if (!wildcard_match(user->username, usermask)) continue; replicator_queue_add(client->queue, user->username, priority); match_count++; } replicator_queue_iter_deinit(&iter); o_stream_send_str(client->conn.output, t_strdup_printf("+%u\n", match_count)); return 0; }
static int lmtp_client_send_data_cmd(struct lmtp_client *client) { if (client->rcpt_next_receive_idx < array_count(&client->recipients)) return 0; if (client->global_fail_string != NULL || !client->rcpt_to_successes) { lmtp_client_fail(client, client->global_fail_string); return -1; } else { client->input_state++; o_stream_send_str(client->output, "DATA\r\n"); return 0; } }
static void client_send_sendalive_if_needed(struct client *client) { time_t now, last_io; if (o_stream_get_buffer_used_size(client->output) != 0) return; now = time(NULL); last_io = I_MAX(client->last_input, client->last_output); if (now - last_io > MAIL_STORAGE_STAYALIVE_SECS) { o_stream_send_str(client->output, "* OK Hang in there..\r\n"); o_stream_flush(client->output); client->last_output = now; } }
int auth_server_connection_connect(struct auth_server_connection *conn) { const char *handshake; int fd; i_assert(!conn->connected); i_assert(conn->fd == -1); conn->last_connect = ioloop_time; timeout_remove(&conn->to); /* max. 1 second wait here. */ fd = net_connect_unix_with_retries(conn->client->auth_socket_path, 1000); if (fd == -1) { if (errno == EACCES) { i_error("auth: %s", eacces_error_get("connect", conn->client->auth_socket_path)); } else { i_error("auth: connect(%s) failed: %m", conn->client->auth_socket_path); } return -1; } conn->fd = fd; conn->io = io_add(fd, IO_READ, auth_server_connection_input, conn); conn->input = i_stream_create_fd(fd, AUTH_SERVER_CONN_MAX_LINE_LENGTH); conn->output = o_stream_create_fd(fd, (size_t)-1); conn->connected = TRUE; handshake = t_strdup_printf("VERSION\t%u\t%u\nCPID\t%u\n", AUTH_CLIENT_PROTOCOL_MAJOR_VERSION, AUTH_CLIENT_PROTOCOL_MINOR_VERSION, conn->client->client_pid); if (o_stream_send_str(conn->output, handshake) < 0) { i_warning("Error sending handshake to auth server: %s", o_stream_get_error(conn->output)); auth_server_connection_disconnect(conn, o_stream_get_error(conn->output)); return -1; } conn->to = timeout_add(AUTH_HANDSHAKE_TIMEOUT, auth_client_handshake_timeout, conn); return 0; }
static int client_handle_request(struct client *client, struct http_request *request) { string_t *str = t_str_new(128); if (strcmp(request->method, "GET") != 0) { o_stream_send_str(client->conn.output, "HTTP/1.1 501 Not Implemented\r\nAllow: GET\r\n\r\n"); return 0; } str_append(str, "HTTP/1.1 200 OK\r\n"); str_printfa(str, "Date: %s\r\n", http_date_create(ioloop_time)); str_printfa(str, "Content-Length: %d\r\n", (int)strlen(request->target_raw)); str_append(str, "Content-Type: text/plain\r\n"); str_append(str, "\r\n"); str_append(str, request->target_raw); o_stream_send(client->conn.output, str_data(str), str_len(str)); return 0; }
static int imap_hibernate_client_input_args(struct connection *conn, const char *const *args, int fd, pool_t pool) { struct imap_hibernate_client *client = (struct imap_hibernate_client *)conn; struct imap_client_state state; const char *error; if (imap_hibernate_client_parse_input(args, pool, &state, &error) < 0) { i_error("Failed to parse client input: %s", error); o_stream_send_str(conn->output, t_strdup_printf( "-Failed to parse client input: %s\n", error)); return -1; } client->imap_client = imap_client_create(fd, &state); /* the transferred imap client fd is now counted as the client. */ client->imap_client_created = TRUE; return state.have_notify_fd ? 0 : 1; }
static int acllist_append(struct acl_backend_vfile *backend, struct ostream *output, const char *vname) { struct acl_object *aclobj; struct acl_object_list_iter *iter; struct acl_rights rights; struct acl_backend_vfile_acllist acllist; const char *name; int ret; name = mail_namespace_get_storage_name(backend->backend.list->ns, vname); acl_cache_flush(backend->backend.cache, name); aclobj = acl_object_init_from_name(&backend->backend, name); iter = acl_object_list_init(aclobj); while ((ret = acl_object_list_next(iter, &rights)) > 0) { if (acl_rights_has_nonowner_lookup_changes(&rights)) break; } acl_object_list_deinit(&iter); if (acl_backend_vfile_object_get_mtime(aclobj, &acllist.mtime) < 0) ret = -1; if (ret > 0) { acllist.name = p_strdup(backend->acllist_pool, name); array_append(&backend->acllist, &acllist, 1); T_BEGIN { const char *line; line = t_strdup_printf("%s %s\n", dec2str(acllist.mtime), name); o_stream_send_str(output, line); } T_END; }
int subsfile_set_subscribed(struct mailbox_list *list, const char *path, const char *temp_prefix, const char *name, bool set) { const struct mail_storage_settings *mail_set = list->mail_set; struct dotlock_settings dotlock_set; struct dotlock *dotlock; const char *line, *origin; struct istream *input; struct ostream *output; int fd_in, fd_out; mode_t mode; gid_t gid; bool found, changed = FALSE, failed = FALSE; if (strcasecmp(name, "INBOX") == 0) name = "INBOX"; memset(&dotlock_set, 0, sizeof(dotlock_set)); dotlock_set.use_excl_lock = mail_set->dotlock_use_excl; dotlock_set.nfs_flush = mail_set->mail_nfs_storage; dotlock_set.temp_prefix = temp_prefix; dotlock_set.timeout = SUBSCRIPTION_FILE_LOCK_TIMEOUT; dotlock_set.stale_timeout = SUBSCRIPTION_FILE_CHANGE_TIMEOUT; mailbox_list_get_permissions(list, NULL, &mode, &gid, &origin); fd_out = file_dotlock_open_group(&dotlock_set, path, 0, mode, gid, origin, &dotlock); if (fd_out == -1 && errno == ENOENT) { /* directory hasn't been created yet. */ if (mailbox_list_create_parent_dir(list, NULL, path) < 0) return -1; fd_out = file_dotlock_open_group(&dotlock_set, path, 0, mode, gid, origin, &dotlock); } if (fd_out == -1) { if (errno == EAGAIN) { mailbox_list_set_error(list, MAIL_ERROR_TEMP, "Timeout waiting for subscription file lock"); } else { subswrite_set_syscall_error(list, "file_dotlock_open()", path); } return -1; } fd_in = nfs_safe_open(path, O_RDONLY); if (fd_in == -1 && errno != ENOENT) { subswrite_set_syscall_error(list, "open()", path); (void)file_dotlock_delete(&dotlock); return -1; } input = fd_in == -1 ? NULL : i_stream_create_fd(fd_in, list->mailbox_name_max_length+1, TRUE); output = o_stream_create_fd_file(fd_out, 0, FALSE); o_stream_cork(output); found = FALSE; while ((line = next_line(list, path, input, &failed, FALSE)) != NULL) { if (strcmp(line, name) == 0) { found = TRUE; if (!set) { changed = TRUE; continue; } } (void)o_stream_send_str(output, line); (void)o_stream_send(output, "\n", 1); } if (!failed && set && !found) { /* append subscription */ line = t_strconcat(name, "\n", NULL); (void)o_stream_send_str(output, line); changed = TRUE; } if (changed && !failed) { if (o_stream_flush(output) < 0) { subswrite_set_syscall_error(list, "write()", path); failed = TRUE; } else if (mail_set->parsed_fsync_mode != FSYNC_MODE_NEVER) { if (fsync(fd_out) < 0) { subswrite_set_syscall_error(list, "fsync()", path); failed = TRUE; } } } if (input != NULL) i_stream_destroy(&input); o_stream_destroy(&output); if (failed || !changed) { if (file_dotlock_delete(&dotlock) < 0) { subswrite_set_syscall_error(list, "file_dotlock_delete()", path); failed = TRUE; } } else { enum dotlock_replace_flags flags = DOTLOCK_REPLACE_FLAG_VERIFY_OWNER; if (file_dotlock_replace(&dotlock, flags) < 0) { subswrite_set_syscall_error(list, "file_dotlock_replace()", path); failed = TRUE; } } return failed ? -1 : (changed ? 1 : 0); }
static void test_iostream_proxy_simple(void) { size_t bytes; test_begin("iostream_proxy"); int sfdl[2]; int sfdr[2]; int counter; test_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sfdl) == 0); test_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sfdr) == 0); fd_set_nonblock(sfdl[0], TRUE); fd_set_nonblock(sfdl[1], TRUE); fd_set_nonblock(sfdr[0], TRUE); fd_set_nonblock(sfdr[1], TRUE); struct ioloop *ioloop = io_loop_create(); struct istream *left_in = i_stream_create_fd(sfdl[1], IO_BLOCK_SIZE); struct ostream *left_out = o_stream_create_fd(sfdl[1], IO_BLOCK_SIZE); struct istream *right_in = i_stream_create_fd(sfdr[1], IO_BLOCK_SIZE); struct ostream *right_out = o_stream_create_fd(sfdr[1], IO_BLOCK_SIZE); struct iostream_proxy *proxy; proxy = iostream_proxy_create(left_in, left_out, right_in, right_out); i_stream_unref(&left_in); o_stream_unref(&left_out); i_stream_unref(&right_in); o_stream_unref(&right_out); iostream_proxy_set_completion_callback(proxy, completed, &counter); iostream_proxy_start(proxy); left_in = i_stream_create_fd(sfdl[0], IO_BLOCK_SIZE); left_out = o_stream_create_fd(sfdl[0], IO_BLOCK_SIZE); right_in = i_stream_create_fd(sfdr[0], IO_BLOCK_SIZE); right_out = o_stream_create_fd(sfdr[0], IO_BLOCK_SIZE); test_assert(proxy != NULL); test_assert(o_stream_send_str(left_out, "hello, world") > 0); o_stream_flush(left_out); o_stream_unref(&left_out); test_assert(shutdown(sfdl[0], SHUT_WR) == 0); counter = 1; io_loop_run(ioloop); i_stream_read(right_in); test_assert(strcmp((const char*)i_stream_get_data(right_in, &bytes), "hello, world") == 0); i_stream_skip(right_in, bytes); test_assert(o_stream_send_str(right_out, "hello, world") > 0); o_stream_flush(right_out); o_stream_unref(&right_out); test_assert(shutdown(sfdr[0], SHUT_WR) == 0); counter = 1; io_loop_run(ioloop); i_stream_read(left_in); test_assert(strcmp((const char*)i_stream_get_data(left_in, &bytes), "hello, world") == 0); i_stream_skip(left_in, bytes); iostream_proxy_unref(&proxy); io_loop_destroy(&ioloop); i_stream_unref(&left_in); i_stream_unref(&right_in); /* close fd */ close(sfdl[0]); close(sfdl[1]); close(sfdr[0]); close(sfdr[1]); test_end(); }
static void client_ctrl_input(struct client *client) { const char *const *args; const char *line; int ret; timeout_reset(client->to_idle); if (client->fd_in == -1 || client->fd_out == -1) { if ((ret = client_ctrl_read_fds(client)) <= 0) { if (ret < 0) client_abort(client, "FD Transfer failed"); return; } } switch (i_stream_read(client->ctrl_input)) { case -1: /* disconnected */ client_destroy(client); return; case -2: /* line too long, kill it */ client_abort(client, "Control session aborted: Input line too long"); return; } if (!client->version_received) { if ((line = i_stream_next_line(client->ctrl_input)) == NULL) return; if (!version_string_verify(line, "imap-urlauth-worker", IMAP_URLAUTH_WORKER_PROTOCOL_MAJOR_VERSION)) { i_error("imap-urlauth-worker client not compatible with this server " "(mixed old and new binaries?) %s", line); client_abort(client, "Control session aborted: Version mismatch"); return; } client->version_received = TRUE; if (o_stream_send_str(client->ctrl_output, "OK\n") < 0) { client_destroy(client); return; } } if (client->access_received) { client_abort(client, "Control session aborted: Unexpected input"); return; } if ((line = i_stream_next_line(client->ctrl_input)) == NULL) return; args = t_strsplit_tabescaped(line); if (*args == NULL || strcmp(*args, "ACCESS") != 0) { i_error("Invalid control command: %s", str_sanitize(line, 80)); client_abort(client, "Control session aborted: Invalid command"); return; } args++; if (*args == NULL) { i_error("Invalid ACCESS command: %s", str_sanitize(line, 80)); client_abort(client, "Control session aborted: Invalid command"); return; } i_assert(client->access_user == NULL); if (**args != '\0') { client->access_user = i_strdup(*args); client->access_anonymous = FALSE; } else { client->access_user = i_strdup("anonymous"); client->access_anonymous = TRUE; } i_set_failure_prefix("imap-urlauth[%s](%s): ", my_pid, client->access_user); args++; while (*args != NULL) { /* debug */ if (strcasecmp(*args, "debug") == 0) { client->debug = TRUE; /* apps=<access-application>[,<access-application,...] */ } else if (strncasecmp(*args, "apps=", 5) == 0 && (*args)[5] != '\0') { const char *const *apps = t_strsplit(*args+5, ","); while (*apps != NULL) { char *app = i_strdup(*apps); array_append(&client->access_apps, &app, 1); if (client->debug) { i_debug("User %s has URLAUTH %s access", client->access_user, app); } apps++; } } else { i_error("Invalid ACCESS parameter: %s", str_sanitize(*args, 80)); client_abort(client, "Control session aborted: Invalid command"); return; } args++; } client->access_received = TRUE; if (o_stream_send_str(client->ctrl_output, "OK\n") < 0) { client_destroy(client); return; } client->input = i_stream_create_fd(client->fd_in, MAX_INBUF_SIZE, FALSE); client->output = o_stream_create_fd(client->fd_out, (size_t)-1, FALSE); client->io = io_add(client->fd_in, IO_READ, client_input, client); o_stream_set_flush_callback(client->output, client_output, client); if (client->debug) { i_debug("Worker activated for access by user %s", client->access_user); } }
static int imap_hibernate_client_input_line(struct connection *conn, const char *line) { struct imap_hibernate_client *client = (struct imap_hibernate_client *)conn; int fd = -1, ret; if (!conn->version_received) { if (connection_verify_version(conn, t_strsplit_tabescaped(line)) < 0) return -1; conn->version_received = TRUE; return 1; } if (client->imap_client == NULL) { char *const *args; pool_t pool; fd = i_stream_unix_get_read_fd(conn->input); if (fd == -1) { i_error("IMAP client fd not received"); return -1; } pool = pool_alloconly_create("client cmd", 1024); args = p_strsplit_tabescaped(pool, line); ret = imap_hibernate_client_input_args(conn, (void *)args, fd, pool); if (ret >= 0 && client->debug) i_debug("Create client with input: %s", line); pool_unref(&pool); } else { fd = i_stream_unix_get_read_fd(conn->input); if (fd == -1) { i_error("IMAP notify fd not received (input: %s)", line); ret = -1; } else if (line[0] != '\0') { i_error("Expected empty notify fd line from client, but got: %s", line); o_stream_send_str(conn->output, "Expected empty notify fd line"); ret = -1; } else { imap_client_add_notify_fd(client->imap_client, fd); ret = 1; } } if (ret < 0) { if (client->imap_client != NULL) imap_client_destroy(&client->imap_client, NULL); if (fd != -1) i_close_fd(&fd); return -1; } else if (ret == 0) { /* still need to read another fd */ i_stream_unix_set_read_fd(conn->input); o_stream_send_str(conn->output, "+\n"); return 1; } else { /* finished - always disconnect the hibernate client afterwards */ o_stream_send_str(conn->output, "+\n"); imap_client_create_finish(client->imap_client); return -1; } }
static inline void _trace_line_print_empty (const struct sieve_runtime_env *renv) { o_stream_send_str(renv->trace->stream, "\n"); }
static int config_connection_request(struct config_connection *conn, const char *const *args) { struct config_export_context *ctx; struct master_service_settings_output output; struct config_filter filter; const char *path, *error, *module = ""; /* [<args>] */ memset(&filter, 0, sizeof(filter)); for (; *args != NULL; args++) { if (strncmp(*args, "service=", 8) == 0) filter.service = *args + 8; else if (strncmp(*args, "module=", 7) == 0) module = *args + 7; else if (strncmp(*args, "lname=", 6) == 0) filter.local_name = *args + 6; else if (strncmp(*args, "lip=", 4) == 0) { if (net_addr2ip(*args + 4, &filter.local_net) == 0) { filter.local_bits = IPADDR_IS_V4(&filter.local_net) ? 32 : 128; } } else if (strncmp(*args, "rip=", 4) == 0) { if (net_addr2ip(*args + 4, &filter.remote_net) == 0) { filter.remote_bits = IPADDR_IS_V4(&filter.remote_net) ? 32 : 128; } } } if (strcmp(module, "master") == 0) { /* master reads configuration only when reloading settings */ path = master_service_get_config_path(master_service); if (config_parse_file(path, TRUE, "", &error) <= 0) { o_stream_send_str(conn->output, t_strconcat("ERROR ", error, "\n", NULL)); config_connection_destroy(conn); return -1; } } o_stream_cork(conn->output); ctx = config_export_init(module, CONFIG_DUMP_SCOPE_SET, 0, config_request_output, conn->output); config_export_by_filter(ctx, &filter); config_export_get_output(ctx, &output); if (output.specific_services != NULL) { const char *const *s; for (s = output.specific_services; *s != NULL; s++) { o_stream_send_str(conn->output, t_strdup_printf("service=%s\t", *s)); } } if (output.service_uses_local) o_stream_send_str(conn->output, "service-uses-local\t"); if (output.service_uses_remote) o_stream_send_str(conn->output, "service-uses-remote\t"); if (output.used_local) o_stream_send_str(conn->output, "used-local\t"); if (output.used_remote) o_stream_send_str(conn->output, "used-remote\t"); o_stream_send_str(conn->output, "\n"); if (config_export_finish(&ctx) < 0) { config_connection_destroy(conn); return -1; } o_stream_send_str(conn->output, "\n"); o_stream_uncork(conn->output); return 0; }
int subsfile_set_subscribed(struct mailbox_list *list, const char *path, const char *temp_prefix, const char *name, bool set) { const struct mail_storage_settings *mail_set = list->mail_set; struct dotlock_settings dotlock_set; struct dotlock *dotlock; struct mailbox_permissions perm; const char *line, *dir, *fname, *escaped_name; struct istream *input = NULL; struct ostream *output; int fd_in, fd_out; enum mailbox_list_path_type type; bool found, changed = FALSE, failed = FALSE; unsigned int version = 2; if (strcasecmp(name, "INBOX") == 0) name = "INBOX"; memset(&dotlock_set, 0, sizeof(dotlock_set)); dotlock_set.use_excl_lock = mail_set->dotlock_use_excl; dotlock_set.nfs_flush = mail_set->mail_nfs_storage; dotlock_set.temp_prefix = temp_prefix; dotlock_set.timeout = SUBSCRIPTION_FILE_LOCK_TIMEOUT; dotlock_set.stale_timeout = SUBSCRIPTION_FILE_CHANGE_TIMEOUT; mailbox_list_get_root_permissions(list, &perm); fd_out = file_dotlock_open_group(&dotlock_set, path, 0, perm.file_create_mode, perm.file_create_gid, perm.file_create_gid_origin, &dotlock); if (fd_out == -1 && errno == ENOENT) { /* directory hasn't been created yet. */ type = list->set.control_dir != NULL ? MAILBOX_LIST_PATH_TYPE_CONTROL : MAILBOX_LIST_PATH_TYPE_DIR; fname = strrchr(path, '/'); if (fname != NULL) { dir = t_strdup_until(path, fname); if (mailbox_list_mkdir_root(list, dir, type) < 0) return -1; } fd_out = file_dotlock_open_group(&dotlock_set, path, 0, perm.file_create_mode, perm.file_create_gid, perm.file_create_gid_origin, &dotlock); } if (fd_out == -1) { if (errno == EAGAIN) { mailbox_list_set_error(list, MAIL_ERROR_TEMP, "Timeout waiting for subscription file lock"); } else { subswrite_set_syscall_error(list, "file_dotlock_open()", path); } return -1; } fd_in = nfs_safe_open(path, O_RDONLY); if (fd_in == -1 && errno != ENOENT) { subswrite_set_syscall_error(list, "open()", path); file_dotlock_delete(&dotlock); return -1; } if (fd_in != -1) { input = i_stream_create_fd_autoclose(&fd_in, list->mailbox_name_max_length+1); i_stream_set_return_partial_line(input, TRUE); subsfile_list_read_header(list, input, &version); } found = FALSE; output = o_stream_create_fd_file(fd_out, 0, FALSE); o_stream_cork(output); if (version >= 2) o_stream_send_str(output, version2_header); if (version < 2 || name[0] == '\0') escaped_name = name; else { const char *const *tmp; char separators[2]; string_t *str = t_str_new(64); separators[0] = mailbox_list_get_hierarchy_sep(list); separators[1] = '\0'; tmp = t_strsplit(name, separators); str_append_tabescaped(str, *tmp); for (tmp++; *tmp != NULL; tmp++) { str_append_c(str, '\t'); str_append_tabescaped(str, *tmp); } escaped_name = str_c(str); } if (input != NULL) { while ((line = next_line(list, path, input, &failed, FALSE)) != NULL) { if (strcmp(line, escaped_name) == 0) { found = TRUE; if (!set) { changed = TRUE; continue; } } o_stream_nsend_str(output, line); o_stream_nsend(output, "\n", 1); } i_stream_destroy(&input); } if (!failed && set && !found) { /* append subscription */ line = t_strconcat(escaped_name, "\n", NULL); o_stream_nsend_str(output, line); changed = TRUE; } if (changed && !failed) { if (o_stream_nfinish(output) < 0) { subswrite_set_syscall_error(list, "write()", path); failed = TRUE; } else if (mail_set->parsed_fsync_mode != FSYNC_MODE_NEVER) { if (fsync(fd_out) < 0) { subswrite_set_syscall_error(list, "fsync()", path); failed = TRUE; } } } else { o_stream_ignore_last_errors(output); } o_stream_destroy(&output); if (failed || !changed) { if (file_dotlock_delete(&dotlock) < 0) { subswrite_set_syscall_error(list, "file_dotlock_delete()", path); failed = TRUE; } } else { enum dotlock_replace_flags flags = DOTLOCK_REPLACE_FLAG_VERIFY_OWNER; if (file_dotlock_replace(&dotlock, flags) < 0) { subswrite_set_syscall_error(list, "file_dotlock_replace()", path); failed = TRUE; } } return failed ? -1 : (changed ? 1 : 0); }