static void doveadm_mail_cmd_server_run(struct client_connection *conn, struct doveadm_mail_cmd_context *ctx, const struct mail_storage_service_input *input) { const char *error; int ret; ctx->conn = conn; if (ctx->v.preinit != NULL) ctx->v.preinit(ctx); ret = doveadm_mail_single_user(ctx, input, &error); doveadm_mail_server_flush(); ctx->v.deinit(ctx); doveadm_print_flush(); mail_storage_service_deinit(&ctx->storage_service); if (ret < 0) { i_error("%s: %s", ctx->cmd->name, error); o_stream_nsend(conn->output, "\n-\n", 3); } else if (ret == 0) { o_stream_nsend_str(conn->output, "\n-NOUSER\n"); } else if (ctx->exit_code != 0) { /* maybe not an error, but not a full success either */ o_stream_nsend_str(conn->output, t_strdup_printf("\n-%u\n", ctx->exit_code)); } else { o_stream_nsend(conn->output, "\n+\n", 3); } pool_unref(&ctx->pool); }
static int mdbox_file_metadata_copy(struct dbox_file *file, struct ostream *output) { struct dbox_metadata_header meta_hdr; const char *line; size_t buf_size; int ret; if ((ret = mdbox_file_read_metadata_hdr(file, &meta_hdr)) <= 0) return ret; o_stream_nsend(output, &meta_hdr, sizeof(meta_hdr)); buf_size = i_stream_get_max_buffer_size(file->input); /* use unlimited line length for metadata */ i_stream_set_max_buffer_size(file->input, (size_t)-1); while ((line = i_stream_read_next_line(file->input)) != NULL) { if (*line == '\0') { /* end of metadata */ break; } o_stream_nsend_str(output, line); o_stream_nsend(output, "\n", 1); } i_stream_set_max_buffer_size(file->input, buf_size); if (line == NULL) { dbox_file_set_corrupted(file, "missing end-of-metadata line"); return 0; } o_stream_nsend(output, "\n", 1); return 1; }
static int fetch_body_msgpart(struct imap_fetch_context *ctx, struct mail *mail, struct imap_fetch_body_data *body) { struct imap_msgpart_open_result result; string_t *str; if (mail == NULL) { imap_msgpart_free(&body->msgpart); return 1; } if (imap_msgpart_open(mail, body->msgpart, &result) < 0) { if (!body->binary || mailbox_get_last_mail_error(mail->box) != MAIL_ERROR_INVALIDDATA) return -1; /* tried to do BINARY fetch for a MIME part with broken content */ str = get_prefix(&ctx->state, body, (uoff_t)-1, FALSE); o_stream_nsend(ctx->client->output, str_data(str), str_len(str)); return 1; } ctx->state.cur_input = result.input; ctx->state.cur_size = result.size; ctx->state.cur_size_field = result.size_field; ctx->state.cur_human_name = get_body_human_name(ctx->ctx_pool, body); str = get_prefix(&ctx->state, body, ctx->state.cur_size, result.binary_decoded_input_has_nuls); o_stream_nsend(ctx->client->output, str_data(str), str_len(str)); ctx->state.cont_handler = fetch_stream_continue; return ctx->state.cont_handler(ctx); }
static int mail_index_recreate(struct mail_index *index) { struct mail_index_map *map = index->map; struct ostream *output; unsigned int base_size; const char *path; int ret = 0, fd; i_assert(!MAIL_INDEX_IS_IN_MEMORY(index)); i_assert(map->hdr.indexid == index->indexid); i_assert((map->hdr.flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) == 0); i_assert(index->indexid != 0); fd = mail_index_create_tmp_file(index, index->filepath, &path); if (fd == -1) return -1; output = o_stream_create_fd_file(fd, 0, FALSE); o_stream_cork(output); base_size = I_MIN(map->hdr.base_header_size, sizeof(map->hdr)); o_stream_nsend(output, &map->hdr, base_size); o_stream_nsend(output, CONST_PTR_OFFSET(map->hdr_base, base_size), map->hdr.header_size - base_size); o_stream_nsend(output, map->rec_map->records, map->rec_map->records_count * map->hdr.record_size); o_stream_nflush(output); if (o_stream_nfinish(output) < 0) { mail_index_file_set_syscall_error(index, path, "write()"); ret = -1; } o_stream_destroy(&output); if (ret == 0 && index->fsync_mode != FSYNC_MODE_NEVER) { if (fdatasync(fd) < 0) { mail_index_file_set_syscall_error(index, path, "fdatasync()"); ret = -1; } } if (close(fd) < 0) { mail_index_file_set_syscall_error(index, path, "close()"); ret = -1; } if ((index->flags & MAIL_INDEX_OPEN_FLAG_KEEP_BACKUPS) != 0) (void)mail_index_create_backup(index); if (ret == 0 && rename(path, index->filepath) < 0) { mail_index_set_error(index, "rename(%s, %s) failed: %m", path, index->filepath); ret = -1; } if (ret < 0) i_unlink(path); return ret; }
static void astream_add_body(struct attachment_istream *astream, const struct message_block *block) { struct attachment_istream_part *part = &astream->part; buffer_t *part_buf; size_t new_size; switch (part->state) { case MAIL_ATTACHMENT_STATE_NO: stream_add_data(astream, block->data, block->size); break; case MAIL_ATTACHMENT_STATE_MAYBE: /* we'll write data to in-memory buffer until we reach attachment min_size */ if (part->part_buf == NULL) { part->part_buf = buffer_create_dynamic(default_pool, astream->set.min_size); } part_buf = part->part_buf; new_size = part_buf->used + block->size; if (new_size < astream->set.min_size) { buffer_append(part_buf, block->data, block->size); break; } /* attachment is large enough. we'll first copy the buffered data from memory to temp file */ if (astream_open_output(astream) < 0) { /* failed, fallback to just saving it inline */ part->state = MAIL_ATTACHMENT_STATE_NO; stream_add_data(astream, part_buf->data, part_buf->used); stream_add_data(astream, block->data, block->size); break; } part->state = MAIL_ATTACHMENT_STATE_YES; astream_try_base64_decode(part, part_buf->data, part_buf->used); hash_format_loop(astream->set.hash_format, part_buf->data, part_buf->used); o_stream_nsend(part->temp_output, part_buf->data, part_buf->used); buffer_set_used_size(part_buf, 0); /* fall through to write the new data to temp file */ case MAIL_ATTACHMENT_STATE_YES: astream_try_base64_decode(part, block->data, block->size); hash_format_loop(astream->set.hash_format, block->data, block->size); o_stream_nsend(part->temp_output, block->data, block->size); break; } }
static void client_connection_input(struct client_connection *conn) { const char *line; bool ok = TRUE; int ret; if (!conn->handshaked) { if ((line = i_stream_read_next_line(conn->input)) == NULL) { if (conn->input->eof || conn->input->stream_errno != 0) { client_log_disconnect_error(conn); client_connection_destroy(&conn); } return; } if (!version_string_verify(line, "doveadm-server", DOVEADM_SERVER_PROTOCOL_VERSION_MAJOR)) { i_error("doveadm client not compatible with this server " "(mixed old and new binaries?)"); client_connection_destroy(&conn); return; } conn->handshaked = TRUE; } if (!conn->authenticated) { if ((ret = client_connection_authenticate(conn)) <= 0) { if (ret < 0) { o_stream_nsend(conn->output, "-\n", 2); client_connection_destroy(&conn); } return; } o_stream_nsend(conn->output, "+\n", 2); conn->authenticated = TRUE; } while (ok && !conn->input->closed && (line = i_stream_read_next_line(conn->input)) != NULL) { T_BEGIN { char **args; args = p_strsplit(pool_datastack_create(), line, "\t"); ok = client_handle_command(conn, args); } T_END; } if (conn->input->eof || conn->input->stream_errno != 0 || !ok) client_connection_destroy(&conn); }
static void doveadm_cmd_server_run(struct client_connection *conn, const struct doveadm_cmd *cmd, int argc, char *argv[]) { const char *str = NULL; unsigned int i; i_getopt_reset(); doveadm_exit_code = 0; cmd->cmd(argc, argv); if (doveadm_exit_code == 0) { o_stream_nsend(conn->output, "\n+\n", 3); return; } for (i = 0; i < N_ELEMENTS(exit_code_strings); i++) { if (exit_code_strings[i].code == doveadm_exit_code) { str = exit_code_strings[i].str; break; } } if (str != NULL) { o_stream_nsend_str(conn->output, t_strdup_printf("\n-%s\n", str)); } else { o_stream_nsend_str(conn->output, "\n-\n"); i_error("BUG: Command '%s' returned unknown error code %d", cmd->name, doveadm_exit_code); } }
static void test_compress_file(const char *in_path, const char *out_path) { const struct compression_handler *handler; struct istream *input, *file_input; struct ostream *output, *file_output; int fd_in, fd_out; struct sha1_ctxt sha1; unsigned char output_sha1[SHA1_RESULTLEN], input_sha1[SHA1_RESULTLEN]; const unsigned char *data; size_t size; ssize_t ret; handler = compression_lookup_handler_from_ext(out_path); if (handler == NULL) i_fatal("Can't detect compression algorithm from path %s", out_path); if (handler->create_ostream == NULL) i_fatal("Support not compiled in for %s", handler->name); /* write the compressed output file */ fd_in = open(in_path, O_RDONLY); if (fd_in == -1) i_fatal("open(%s) failed: %m", in_path); fd_out = open(out_path, O_TRUNC | O_CREAT | O_RDWR, 0600); if (fd_out == -1) i_fatal("creat(%s) failed: %m", out_path); sha1_init(&sha1); file_output = o_stream_create_fd_file(fd_out, 0, FALSE); output = handler->create_ostream(file_output, 1); input = i_stream_create_fd_autoclose(&fd_in, IO_BLOCK_SIZE); while (i_stream_read_data(input, &data, &size, 0) > 0) { sha1_loop(&sha1, data, size); o_stream_nsend(output, data, size); i_stream_skip(input, size); } if (o_stream_nfinish(output) < 0) { i_fatal("write(%s) failed: %s", out_path, o_stream_get_error(output)); } i_stream_destroy(&input); o_stream_destroy(&output); o_stream_destroy(&file_output); sha1_result(&sha1, output_sha1); /* verify that we can read the compressed file */ sha1_init(&sha1); file_input = i_stream_create_fd(fd_out, IO_BLOCK_SIZE, FALSE); input = handler->create_istream(file_input, FALSE); while ((ret = i_stream_read_data(input, &data, &size, 0)) > 0) { sha1_loop(&sha1, data, size); i_stream_skip(input, size); } i_stream_destroy(&input); i_stream_destroy(&file_input); sha1_result(&sha1, input_sha1); if (memcmp(input_sha1, output_sha1, sizeof(input_sha1)) != 0) i_fatal("Decompression couldn't get the original input"); i_close_fd(&fd_out); }
void worker_connection_request(struct worker_connection *conn, const struct indexer_request *request, void *context) { i_assert(worker_connection_is_connected(conn)); i_assert(context != NULL); i_assert(request->index || request->optimize); if (conn->request_username == NULL) conn->request_username = i_strdup(request->username); else { i_assert(strcmp(conn->request_username, request->username) == 0); } aqueue_append(conn->request_queue, &context); T_BEGIN { string_t *str = t_str_new(128); str_append_tabescaped(str, request->username); str_append_c(str, '\t'); str_append_tabescaped(str, request->mailbox); str_append_c(str, '\t'); if (request->session_id != NULL) str_append_tabescaped(str, request->session_id); str_printfa(str, "\t%u\t", request->max_recent_msgs); if (request->index) str_append_c(str, 'i'); if (request->optimize) str_append_c(str, 'o'); str_append_c(str, '\n'); o_stream_nsend(conn->output, str_data(str), str_len(str)); } T_END; }
static bool lmtp_client_send_xclient(struct lmtp_client *client) { string_t *str; unsigned int empty_len; if (client->xclient_args == NULL) { /* not supported */ return FALSE; } if (client->xclient_sent) return FALSE; str = t_str_new(64); str_append(str, "XCLIENT"); empty_len = str_len(str); if (client->set.source_ip.family != 0 && str_array_icase_find(client->xclient_args, "ADDR")) str_printfa(str, " ADDR=%s", net_ip2addr(&client->set.source_ip)); if (client->set.source_port != 0 && str_array_icase_find(client->xclient_args, "PORT")) str_printfa(str, " PORT=%u", client->set.source_port); if (client->set.proxy_ttl != 0 && str_array_icase_find(client->xclient_args, "TTL")) str_printfa(str, " TTL=%u", client->set.proxy_ttl); if (client->set.proxy_timeout_secs != 0 && str_array_icase_find(client->xclient_args, "TIMEOUT")) str_printfa(str, " TIMEOUT=%u", client->set.proxy_timeout_secs); if (str_len(str) == empty_len) return FALSE; str_append(str, "\r\n"); o_stream_nsend(client->output, str_data(str), str_len(str)); return TRUE; }
static int fetch_body_msgpart(struct imap_fetch_context *ctx, struct mail *mail, struct imap_fetch_body_data *body) { struct imap_msgpart_open_result result; string_t *str; if (mail == NULL) { imap_msgpart_free(&body->msgpart); return 1; } if (imap_msgpart_open(mail, body->msgpart, &result) < 0) return -1; ctx->state.cur_input = result.input; ctx->state.cur_size = result.size; ctx->state.cur_size_field = result.size_field; ctx->state.cur_human_name = get_body_human_name(ctx->ctx_pool, body); fetch_state_update_stats(ctx, body->msgpart); str = get_prefix(&ctx->state, body, ctx->state.cur_size, result.binary_decoded_input_has_nuls); o_stream_nsend(ctx->client->output, str_data(str), str_len(str)); ctx->state.cont_handler = fetch_stream_continue; return ctx->state.cont_handler(ctx); }
static void client_input(struct client *client) { struct istream *input; struct ostream *output; unsigned char buf[1024]; ssize_t ret; ret = read(STDIN_FILENO, buf, sizeof(buf)); if (ret == 0) { if (client->compressed) { master_service_stop(master_service); return; } /* start compression */ i_info("<Compression started>"); input = i_stream_create_deflate(client->input, TRUE); output = o_stream_create_deflate(client->output, 6); i_stream_unref(&client->input); o_stream_unref(&client->output); client->input = input; client->output = output; client->compressed = TRUE; return; } if (ret < 0) i_fatal("read(stdin) failed: %m"); o_stream_nsend(client->output, buf, ret); }
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_nsend_str(output, key); o_stream_nsend_str(output, "="); while ((p = strchr(value, '\n')) != NULL) { o_stream_nsend(output, value, p-value); o_stream_nsend(output, SETTING_STREAM_LF_CHAR, 1); value = p+1; } o_stream_nsend_str(output, value); o_stream_nsend_str(output, "\n"); }
static int proxy_input_banner(struct imap_client *client, struct ostream *output, const char *line) { const char *const *capabilities = NULL; string_t *str; int ret; if (!str_begins(line, "* OK ")) { client_log_err(&client->common, t_strdup_printf( "proxy: Remote returned invalid banner: %s", str_sanitize(line, 160))); return -1; } str = t_str_new(128); if (str_begins(line + 5, "[CAPABILITY ")) { capabilities = t_strsplit(t_strcut(line + 5 + 12, ']'), " "); if (str_array_icase_find(capabilities, "SASL-IR")) client->proxy_sasl_ir = TRUE; if (str_array_icase_find(capabilities, "LOGINDISABLED")) client->proxy_logindisabled = TRUE; i_free(client->proxy_backend_capability); client->proxy_backend_capability = i_strdup(t_strcut(line + 5 + 12, ']')); if (str_array_icase_find(capabilities, "ID") && !client->common.proxy_not_trusted) { client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_ID; proxy_write_id(client, str); if (client->common.proxy_nopipelining) { /* write login or starttls after I OK */ o_stream_nsend(output, str_data(str), str_len(str)); return 0; } } } if ((ret = proxy_write_starttls(client, str)) < 0) { return -1; } else if (ret == 0) { if (proxy_write_login(client, str) < 0) return -1; } o_stream_nsend(output, str_data(str), str_len(str)); return 0; }
void login_proxy_detach(struct login_proxy *proxy) { struct client *client = proxy->client; const unsigned char *data; size_t size; i_assert(proxy->client_fd == -1); i_assert(proxy->server_input != NULL); i_assert(proxy->server_output != NULL); if (proxy->to != NULL) timeout_remove(&proxy->to); proxy->client_fd = i_stream_get_fd(client->input); proxy->client_input = client->input; proxy->client_output = client->output; i_stream_set_persistent_buffers(client->input, FALSE); o_stream_set_max_buffer_size(client->output, (size_t)-1); o_stream_set_flush_callback(client->output, proxy_client_output, proxy); client->input = NULL; client->output = NULL; /* send all pending client input to proxy */ data = i_stream_get_data(proxy->client_input, &size); if (size != 0) o_stream_nsend(proxy->server_output, data, size); /* from now on, just do dummy proxying */ io_remove(&proxy->server_io); proxy->server_io = io_add(proxy->server_fd, IO_READ, server_input, proxy); proxy->client_io = io_add_istream(proxy->client_input, proxy_client_input, proxy); o_stream_set_flush_callback(proxy->server_output, server_output, proxy); i_stream_destroy(&proxy->server_input); if (proxy->notify_refresh_secs != 0) { proxy->to_notify = timeout_add(proxy->notify_refresh_secs * 1000, login_proxy_notify, proxy); } proxy->callback = NULL; if (login_proxy_ipc_server == NULL) { login_proxy_ipc_server = ipc_server_init(LOGIN_PROXY_IPC_PATH, LOGIN_PROXY_IPC_NAME, login_proxy_ipc_cmd); } DLLIST_REMOVE(&login_proxies_pending, proxy); DLLIST_PREPEND(&login_proxies, proxy); client->fd = -1; client->login_proxy = NULL; }
static int cmd_dsync_server_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) { struct dsync_cmd_context *ctx = (struct dsync_cmd_context *)_ctx; struct dsync_ibc *ibc; struct dsync_brain *brain; string_t *temp_prefix, *state_str = NULL; enum dsync_brain_sync_type sync_type; const char *name; if (_ctx->conn != NULL) { /* doveadm-server connection. start with a success reply. after that follows the regular dsync protocol. */ ctx->fd_in = ctx->fd_out = -1; ctx->input = _ctx->conn->input; ctx->output = _ctx->conn->output; o_stream_nsend(ctx->output, "\n+\n", 3); i_set_failure_prefix("dsync-server(%s): ", user->username); name = i_stream_get_name(ctx->input); } else { /* the log messages go via stderr to the remote dsync, so the names are reversed */ i_set_failure_prefix("dsync-remote(%s): ", user->username); name = "local"; } doveadm_user_init_dsync(user); temp_prefix = t_str_new(64); mail_user_set_get_temp_prefix(temp_prefix, user->set); ibc = cmd_dsync_icb_stream_init(ctx, name, str_c(temp_prefix)); brain = dsync_brain_slave_init(user, ibc, FALSE); io_loop_run(current_ioloop); if (ctx->replicator_notify) { state_str = t_str_new(128); dsync_brain_get_state(brain, state_str); } sync_type = dsync_brain_get_sync_type(brain); if (dsync_brain_deinit(&brain) < 0) _ctx->exit_code = EX_TEMPFAIL; dsync_ibc_deinit(&ibc); if (_ctx->conn != NULL) { /* make sure nothing more is written by the generic doveadm connection code */ o_stream_close(_ctx->conn->output); } if (ctx->replicator_notify && _ctx->exit_code == 0) dsync_replicator_notify(ctx, sync_type, str_c(state_str)); return _ctx->exit_code == 0 ? 0 : -1; }
static int cmd_setmetadata_entry(struct imap_setmetadata_context *ctx, const char *entry_name, const struct imap_arg *entry_value) { struct istream *inputs[2]; struct mail_attribute_value value; string_t *path; int ret; switch (entry_value->type) { case IMAP_ARG_NIL: case IMAP_ARG_ATOM: case IMAP_ARG_STRING: /* we have the value already */ if (ctx->failed) return 1; memset(&value, 0, sizeof(value)); value.value = imap_arg_as_nstring(entry_value); ret = imap_metadata_set(ctx->trans, entry_name, &value); if (ret < 0) { /* delay reporting the failure so we'll finish reading the command input */ ctx->storage_failure = TRUE; ctx->failed = TRUE; } return 1; case IMAP_ARG_LITERAL_SIZE: o_stream_nsend(ctx->cmd->client->output, "+ OK\r\n", 6); o_stream_nflush(ctx->cmd->client->output); o_stream_uncork(ctx->cmd->client->output); o_stream_cork(ctx->cmd->client->output); /* fall through */ case IMAP_ARG_LITERAL_SIZE_NONSYNC: i_free(ctx->entry_name); ctx->entry_name = i_strdup(entry_name); ctx->entry_value_len = imap_arg_as_literal_size(entry_value); inputs[0] = i_stream_create_limit(ctx->cmd->client->input, ctx->entry_value_len); inputs[1] = NULL; path = t_str_new(128); mail_user_set_get_temp_prefix(path, ctx->cmd->client->user->set); ctx->input = i_stream_create_seekable_path(inputs, METADATA_MAX_INMEM_SIZE, str_c(path)); i_stream_set_name(ctx->input, i_stream_get_name(inputs[0])); i_stream_unref(&inputs[0]); return cmd_setmetadata_entry_read_stream(ctx); case IMAP_ARG_LITERAL: case IMAP_ARG_LIST: case IMAP_ARG_EOL: break; } i_unreached(); }
static void client_connection_send_auth_handshake(struct client_connection * conn, int listen_fd) { const char *listen_path; struct stat st; /* we'll have to do this with stat(), because at least in Linux fstat() always returns mode as 0777 */ if (net_getunixname(listen_fd, &listen_path) == 0 && stat(listen_path, &st) == 0 && S_ISSOCK(st.st_mode) && (st.st_mode & 0777) == 0600) { /* no need for client to authenticate */ conn->authenticated = TRUE; o_stream_nsend(conn->output, "+\n", 2); } else { o_stream_nsend(conn->output, "-\n", 2); } }
static void test_write_read_v2(void) { test_begin("test_write_read_v2"); unsigned char payload[IO_BLOCK_SIZE*10]; const unsigned char *ptr; size_t pos = 0, siz; random_fill_weak(payload, IO_BLOCK_SIZE*10); buffer_t *buf = buffer_create_dynamic(default_pool, sizeof(payload)); struct ostream *os = o_stream_create_buffer(buf); struct ostream *os_2 = o_stream_create_encrypt(os, "aes-256-gcm-sha256", test_v1_kp.pub, IO_STREAM_ENC_INTEGRITY_AEAD); o_stream_nsend(os_2, payload, sizeof(payload)); test_assert(o_stream_nfinish(os_2) == 0); if (os_2->stream_errno != 0) i_debug("error: %s", o_stream_get_error(os_2)); o_stream_unref(&os); o_stream_unref(&os_2); struct istream *is = test_istream_create_data(buf->data, buf->used); /* test regression where read fails due to incorrect behaviour when buffer is full before going to decrypt code */ i_stream_set_max_buffer_size(is, 8192); i_stream_read(is); struct istream *is_2 = i_stream_create_decrypt(is, test_v1_kp.priv); size_t offset = 0; test_istream_set_size(is, 0); test_istream_set_allow_eof(is, FALSE); while(i_stream_read_data(is_2, &ptr, &siz, 0)>=0) { if (offset == buf->used) test_istream_set_allow_eof(is, TRUE); else test_istream_set_size(is, ++offset); test_assert_idx(pos + siz <= sizeof(payload), pos); if (pos + siz > sizeof(payload)) break; test_assert_idx(siz == 0 || memcmp(ptr, payload + pos, siz) == 0, pos); i_stream_skip(is_2, siz); pos += siz; } test_assert(is_2->stream_errno == 0); if (is_2->stream_errno != 0) i_debug("error: %s", i_stream_get_error(is_2)); i_stream_unref(&is); i_stream_unref(&is_2); buffer_free(&buf); test_end(); }
static int client_export_iter_session(struct client *client) { struct client_export_cmd *cmd = client->cmd_export; struct mail_session *session = client->mail_session_iter; i_assert(cmd->level == MAIL_EXPORT_LEVEL_SESSION); mail_session_unref(&client->mail_session_iter); if (!cmd->header_sent) { o_stream_nsend_str(client->output, "session\tuser\tip\tservice\tpid\tconnected" "\tlast_update\tnum_cmds" MAIL_STATS_HEADER); cmd->header_sent = TRUE; } for (; session != NULL; session = session->stable_next) { if (client_is_busy(client)) break; if (!mail_export_filter_match_session(&cmd->filter, session)) continue; str_truncate(cmd->str, 0); T_BEGIN { str_append(cmd->str, guid_128_to_string(session->guid)); str_append_c(cmd->str, '\t'); str_append_tabescaped(cmd->str, session->user->name); str_append_c(cmd->str, '\t'); if (session->ip != NULL) { str_append(cmd->str, net_ip2addr(&session->ip->ip)); } str_append_c(cmd->str, '\t'); str_append_tabescaped(cmd->str, session->service); } T_END; str_printfa(cmd->str, "\t%ld", (long)session->pid); str_printfa(cmd->str, "\t%d", !session->disconnected); client_export_timeval(cmd->str, &session->last_update); str_printfa(cmd->str, "\t%u", session->num_cmds); client_export_mail_stats(cmd->str, &session->stats); str_append_c(cmd->str, '\n'); o_stream_nsend(client->output, str_data(cmd->str), str_len(cmd->str)); } if (session != NULL) { client->mail_session_iter = session; mail_session_ref(session); return 0; } return 1; }
static bool cmd_append_send_literal_continue(struct cmd_append_context *ctx) { if (ctx->failed) { /* tagline was already sent, we can abort here */ return FALSE; } o_stream_nsend(ctx->client->output, "+ OK\r\n", 6); o_stream_nflush(ctx->client->output); o_stream_uncork(ctx->client->output); o_stream_cork(ctx->client->output); return TRUE; }
static void test_write_read_v1_short(void) { test_begin("test_write_read_v1_short"); unsigned char payload[1]; const unsigned char *ptr; size_t pos = 0, siz; random_fill_weak(payload, 1); buffer_t *buf = buffer_create_dynamic(default_pool, 64); struct ostream *os = o_stream_create_buffer(buf); struct ostream *os_2 = o_stream_create_encrypt(os, "<unused>", test_v2_kp.pub, IO_STREAM_ENC_VERSION_1); o_stream_nsend(os_2, payload, sizeof(payload)); if (os_2->stream_errno != 0) i_debug("error: %s", o_stream_get_error(os_2)); test_assert(os_2->stream_errno == 0); test_assert(o_stream_nfinish(os_2) == 0); test_assert(os_2->stream_errno == 0); o_stream_unref(&os); o_stream_unref(&os_2); struct istream *is = test_istream_create_data(buf->data, buf->used); struct istream *is_2 = i_stream_create_decrypt(is, test_v2_kp.priv); size_t offset = 0; test_istream_set_allow_eof(is, FALSE); test_istream_set_size(is, 0); while(i_stream_read_data(is_2, &ptr, &siz, 0)>=0) { if (offset == buf->used) test_istream_set_allow_eof(is, TRUE); else test_istream_set_size(is, ++offset); test_assert_idx(pos + siz <= sizeof(payload), pos); if (pos + siz > sizeof(payload)) break; test_assert_idx(siz == 0 || memcmp(ptr, payload + pos, siz) == 0, pos); i_stream_skip(is_2, siz); pos += siz; } test_assert(is_2->stream_errno == 0); i_stream_unref(&is); i_stream_unref(&is_2); buffer_free(&buf); test_end(); }
static void user_callback(enum userdb_result result, struct auth_request *auth_request) { struct auth_master_connection *conn = auth_request->master; string_t *str; const char *value; if (auth_request->userdb_lookup_tempfailed) result = USERDB_RESULT_INTERNAL_FAILURE; if (result == USERDB_RESULT_OK) { if (user_verify_restricted_uid(auth_request) < 0) result = USERDB_RESULT_INTERNAL_FAILURE; } str = t_str_new(128); switch (result) { case USERDB_RESULT_INTERNAL_FAILURE: str_printfa(str, "FAIL\t%u", auth_request->id); if (auth_request->userdb_lookup_tempfailed) { value = auth_fields_find(auth_request->userdb_reply, "reason"); if (value != NULL) str_printfa(str, "\treason=%s", value); } break; case USERDB_RESULT_USER_UNKNOWN: str_printfa(str, "NOTFOUND\t%u", auth_request->id); break; case USERDB_RESULT_OK: str_printfa(str, "USER\t%u\t", auth_request->id); str_append_tabescaped(str, auth_request->user); str_append_c(str, '\t'); auth_fields_append(auth_request->userdb_reply, str, AUTH_FIELD_FLAG_HIDDEN, 0); break; } if (conn->auth->set->debug) { i_debug("userdb out: %s", auth_master_reply_hide_passwords(conn, str_c(str))); } str_append_c(str, '\n'); o_stream_nsend(conn->output, str_data(str), str_len(str)); auth_request_unref(&auth_request); auth_master_connection_unref(&conn); }
static int client_export_iter_command(struct client *client) { struct client_export_cmd *cmd = client->cmd_export; struct mail_command *command = client->mail_cmd_iter; i_assert(cmd->level == MAIL_EXPORT_LEVEL_COMMAND); mail_command_unref(&client->mail_cmd_iter); if (!cmd->header_sent) { o_stream_nsend_str(client->output, "cmd\targs\tsession\tuser\tlast_update"MAIL_STATS_HEADER); cmd->header_sent = TRUE; } for (; command != NULL; command = command->stable_next) { if (client_is_busy(client)) break; if (!mail_export_filter_match_session(&cmd->filter, command->session)) continue; str_truncate(cmd->str, 0); str_append_tabescaped(cmd->str, command->name); str_append_c(cmd->str, '\t'); str_append_tabescaped(cmd->str, command->args); str_append_c(cmd->str, '\t'); T_BEGIN { str_append(cmd->str, guid_128_to_string(command->session->guid)); str_append_c(cmd->str, '\t'); str_append_tabescaped(cmd->str, command->session->user->name); } T_END; client_export_timeval(cmd->str, &command->last_update); client_export_mail_stats(cmd->str, &command->stats); str_append_c(cmd->str, '\n'); o_stream_nsend(client->output, str_data(cmd->str), str_len(cmd->str)); } if (command != NULL) { client->mail_cmd_iter = command; mail_command_ref(command); return 0; } return 1; }
static void pass_callback_finish(struct auth_request *auth_request, enum passdb_result result) { struct auth_master_connection *conn = auth_request->master; string_t *str; str = t_str_new(128); switch (result) { case PASSDB_RESULT_OK: if (auth_request->failed || !auth_request->passdb_success) { str_printfa(str, "FAIL\t%u", auth_request->id); break; } str_printfa(str, "PASS\t%u\tuser="******"NOTFOUND\t%u", auth_request->id); break; case PASSDB_RESULT_NEXT: case PASSDB_RESULT_PASSWORD_MISMATCH: case PASSDB_RESULT_INTERNAL_FAILURE: str_printfa(str, "FAIL\t%u", auth_request->id); break; case PASSDB_RESULT_SCHEME_NOT_AVAILABLE: str_printfa(str, "FAIL\t%u\treason=Configured passdbs don't support credentials lookups", auth_request->id); break; } if (conn->auth->set->debug) i_debug("passdb out: %s", str_c(str)); str_append_c(str, '\n'); o_stream_nsend(conn->output, str_data(str), str_len(str)); auth_request_unref(&auth_request); auth_master_connection_unref(&conn); }
static int proxy_input_banner(struct imap_client *client, struct ostream *output, const char *line) { enum login_proxy_ssl_flags ssl_flags; const char *const *capabilities = NULL; string_t *str; if (strncmp(line, "* OK ", 5) != 0) { client_log_err(&client->common, t_strdup_printf( "proxy: Remote returned invalid banner: %s", str_sanitize(line, 160))); return -1; } str = t_str_new(128); if (strncmp(line + 5, "[CAPABILITY ", 12) == 0) { capabilities = t_strsplit(t_strcut(line + 5 + 12, ']'), " "); if (str_array_icase_find(capabilities, "ID")) proxy_write_id(client, str); if (str_array_icase_find(capabilities, "SASL-IR")) client->proxy_sasl_ir = TRUE; if (str_array_icase_find(capabilities, "LOGINDISABLED")) client->proxy_logindisabled = TRUE; i_free(client->proxy_backend_capability); client->proxy_backend_capability = i_strdup(t_strcut(line + 5 + 12, ']')); } ssl_flags = login_proxy_get_ssl_flags(client->common.login_proxy); if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) != 0) { if (capabilities != NULL && !str_array_icase_find(capabilities, "STARTTLS")) { client_log_err(&client->common, "proxy: Remote doesn't support STARTTLS"); return -1; } str_append(str, "S STARTTLS\r\n"); } else { if (proxy_write_login(client, str) < 0) return -1; } o_stream_nsend(output, str_data(str), str_len(str)); return 0; }
static void lmtp_client_send_rcpts(struct lmtp_client *client) { const struct lmtp_rcpt *rcpt; unsigned int i, count; string_t *str = t_str_new(128); rcpt = array_get(&client->recipients, &count); for (i = client->rcpt_next_send_idx; i < count; i++) { str_truncate(str, 0); str_printfa(str, "RCPT TO:<%s>", rcpt[i].address); if (rcpt->params.dsn_orcpt != NULL) { str_append(str, " ORCPT="); lmtp_append_xtext(str, rcpt->params.dsn_orcpt); } str_append(str, "\r\n"); o_stream_nsend(client->output, str_data(str), str_len(str)); } client->rcpt_next_send_idx = i; }
int squat_uidlist_build_init(struct squat_uidlist *uidlist, struct squat_uidlist_build_context **ctx_r) { struct squat_uidlist_build_context *ctx; int ret; i_assert(!uidlist->building); ret = squat_uidlist_open_or_create(uidlist); if (ret == 0 && lseek(uidlist->fd, uidlist->hdr.used_file_size, SEEK_SET) < 0) { i_error("lseek(%s) failed: %m", uidlist->path); ret = -1; } if (ret < 0) { if (uidlist->file_lock != NULL) file_unlock(&uidlist->file_lock); if (uidlist->dotlock != NULL) file_dotlock_delete(&uidlist->dotlock); return -1; } ctx = i_new(struct squat_uidlist_build_context, 1); ctx->uidlist = uidlist; ctx->output = o_stream_create_fd(uidlist->fd, 0); if (ctx->output->offset == 0) { struct squat_uidlist_file_header hdr; memset(&hdr, 0, sizeof(hdr)); o_stream_nsend(ctx->output, &hdr, sizeof(hdr)); } o_stream_cork(ctx->output); i_array_init(&ctx->lists, 10240); i_array_init(&ctx->block_offsets, 128); i_array_init(&ctx->block_end_indexes, 128); ctx->list_start_idx = uidlist->hdr.count; ctx->build_hdr = uidlist->hdr; uidlist->building = TRUE; *ctx_r = ctx; return 0; }
static int client_export_iter_ip(struct client *client) { struct client_export_cmd *cmd = client->cmd_export; struct mail_ip *ip = client->mail_ip_iter; i_assert(cmd->level == MAIL_EXPORT_LEVEL_IP); mail_ip_unref(&client->mail_ip_iter); if (!cmd->header_sent) { o_stream_nsend_str(client->output, "ip\treset_timestamp\tlast_update" "\tnum_logins\tnum_cmds\tnum_connected_sessions"MAIL_STATS_HEADER); cmd->header_sent = TRUE; } for (; ip != NULL; ip = ip->stable_next) { if (client_is_busy(client)) break; if (!mail_export_filter_match_ip(&cmd->filter, ip)) continue; str_truncate(cmd->str, 0); T_BEGIN { str_append(cmd->str, net_ip2addr(&ip->ip)); } T_END; str_printfa(cmd->str, "\t%ld", (long)ip->reset_timestamp); client_export_timeval(cmd->str, &ip->last_update); str_printfa(cmd->str, "\t%u\t%u\t%u", ip->num_logins, ip->num_cmds, ip->num_connected_sessions); client_export_mail_stats(cmd->str, &ip->stats); str_append_c(cmd->str, '\n'); o_stream_nsend(client->output, str_data(cmd->str), str_len(cmd->str)); } if (ip != NULL) { client->mail_ip_iter = ip; mail_ip_ref(ip); return 0; } return 1; }
static void replicator_send(struct replicator_connection *conn, enum replication_priority priority, const char *data) { unsigned int data_len = strlen(data); if (conn->fd != -1 && o_stream_get_buffer_used_size(conn->output) == 0) { /* we can send data immediately */ o_stream_nsend(conn->output, data, data_len); } else if (conn->queue[priority]->used + data_len >= REPLICATOR_MEMBUF_MAX_SIZE) { /* FIXME: compress duplicates, start writing to file */ } else { /* queue internally to separate queues */ buffer_append(conn->queue[priority], data, data_len); if (conn->output != NULL) o_stream_set_flush_pending(conn->output, TRUE); } }