static struct mail_log_group_changes * mail_log_action_get_group(struct mail_log_transaction_context *lt, enum mail_log_event event, const char *data) { struct mail_log_group_changes *group; unsigned int i, count; if (!array_is_created(<->group_changes)) p_array_init(<->group_changes, lt->pool, 8); group = array_get_modifiable(<->group_changes, &count); for (i = 0; i < count; i++) { if (group[i].event == event && null_strcmp(data, group[i].data) == 0) return &group[i]; } group = array_append_space(<->group_changes); group->event = event; group->data = p_strdup(lt->pool, data); return group; }
static struct mail_search_arg * imap_search_uid(struct mail_search_build_context *ctx) { struct mail_search_arg *sarg; /* <message set> */ sarg = mail_search_build_str(ctx, SEARCH_UIDSET); if (sarg == NULL) return NULL; p_array_init(&sarg->value.seqset, ctx->pool, 16); if (strcmp(sarg->value.str, "$") == 0) { /* SEARCHRES: delay initialization */ } else { if (imap_seq_set_parse(sarg->value.str, &sarg->value.seqset) < 0) { ctx->_error = "Invalid UID messageset"; return NULL; } } return sarg; }
int index_transaction_commit(struct mailbox_transaction_context *t, struct mail_transaction_commit_changes *changes_r) { struct mailbox *box = t->box; struct mail_index_transaction *itrans = t->itrans; struct mail_index_transaction_commit_result result; int ret; memset(changes_r, 0, sizeof(*changes_r)); changes_r->pool = pool_alloconly_create(MEMPOOL_GROWING "transaction changes", 512); p_array_init(&changes_r->saved_uids, changes_r->pool, 32); t->changes = changes_r; ret = mail_index_transaction_commit_full(&itrans, &result); t = NULL; if (ret < 0 && mail_index_is_deleted(box->index)) mailbox_set_deleted(box); changes_r->ignored_modseq_changes = result.ignored_modseq_changes; return ret; }
void auth_fields_add(struct auth_fields *fields, const char *key, const char *value, enum auth_field_flags flags) { struct auth_field *field; unsigned int idx; i_assert(*key != '\0'); i_assert(strchr(key, '\t') == NULL && strchr(key, '\n') == NULL); if (!auth_fields_find_idx(fields, key, &idx)) { if (!array_is_created(&fields->fields)) p_array_init(&fields->fields, fields->pool, 16); field = array_append_space(&fields->fields); field->key = p_strdup(fields->pool, key); } else { auth_fields_snapshot_preserve(fields); field = array_idx_modifiable(&fields->fields, idx); } field->value = p_strdup_empty(fields->pool, value); field->flags = flags | AUTH_FIELD_FLAG_CHANGED; }
void imap_parser_reset(struct imap_parser *parser) { p_clear(parser->pool); parser->line_size = 0; p_array_init(&parser->root_list, parser->pool, LIST_INIT_COUNT); parser->cur_list = &parser->root_list; parser->list_arg = NULL; parser->cur_type = ARG_PARSE_NONE; parser->cur_pos = 0; parser->cur_resp_text = FALSE; parser->str_first_escape = 0; parser->literal_size = 0; parser->error = NULL; parser->literal_skip_crlf = FALSE; parser->eol = FALSE; parser->args_added_extra_eol = FALSE; parser->literal_size_return = FALSE; }
struct passdb_template *passdb_template_build(pool_t pool, const char *args) { struct passdb_template *tmpl; const char *const *tmp, *key, *value; tmpl = p_new(pool, struct passdb_template, 1); tmp = t_strsplit_spaces(args, " "); p_array_init(&tmpl->args, pool, str_array_length(tmp)); for (; *tmp != NULL; tmp++) { value = strchr(*tmp, '='); if (value == NULL) key = *tmp; else key = t_strdup_until(*tmp, value++); key = p_strdup(pool, key); value = p_strdup(pool, value); array_append(&tmpl->args, &key, 1); array_append(&tmpl->args, &value, 1); } return tmpl; }
struct lmtp_client * lmtp_client_init(const struct lmtp_client_settings *set, lmtp_finish_callback_t *finish_callback, void *context) { struct lmtp_client *client; pool_t pool; i_assert(*set->mail_from == '<'); i_assert(*set->my_hostname != '\0'); pool = pool_alloconly_create("lmtp client", 512); client = p_new(pool, struct lmtp_client, 1); client->refcount = 1; client->pool = pool; client->set.mail_from = p_strdup(pool, set->mail_from); client->set.my_hostname = p_strdup(pool, set->my_hostname); client->set.dns_client_socket_path = p_strdup(pool, set->dns_client_socket_path); client->finish_callback = finish_callback; client->finish_context = context; client->fd = -1; p_array_init(&client->recipients, pool, 16); return client; }
struct client * client_create(int fd, bool ssl, pool_t pool, const struct master_service_connection *conn, const struct login_settings *set, const struct master_service_ssl_settings *ssl_set, void **other_sets) { struct client *client; i_assert(fd != -1); client = login_binary->client_vfuncs->alloc(pool); client->v = *login_binary->client_vfuncs; if (client->v.auth_send_challenge == NULL) client->v.auth_send_challenge = client_auth_send_challenge; if (client->v.auth_parse_response == NULL) client->v.auth_parse_response = client_auth_parse_response; client->created = ioloop_time; client->refcount = 1; client->pool = pool; client->set = set; client->ssl_set = ssl_set; p_array_init(&client->module_contexts, client->pool, 5); client->fd = fd; client->tls = ssl; client->local_ip = conn->local_ip; client->local_port = conn->local_port; client->ip = conn->remote_ip; client->remote_port = conn->remote_port; client->real_local_ip = conn->real_local_ip; client->real_local_port = conn->real_local_port; client->real_remote_ip = conn->real_remote_ip; client->real_remote_port = conn->real_remote_port; client->listener_name = p_strdup(client->pool, conn->name); client->trusted = client_is_trusted(client); client->secured = ssl || client->trusted || net_ip_compare(&conn->real_remote_ip, &conn->real_local_ip); client->proxy_ttl = LOGIN_PROXY_TTL; if (last_client == NULL) last_client = client; DLLIST_PREPEND(&clients, client); clients_count++; client->to_disconnect = timeout_add(CLIENT_LOGIN_TIMEOUT_MSECS, client_idle_disconnect_timeout, client); client_open_streams(client); hook_client_allocated(client); client->v.create(client, other_sets); if (auth_client_is_connected(auth_client)) client_notify_auth_ready(client); else client_set_auth_waiting(client); login_refresh_proctitle(); return client; }
static bool parse_x_keywords_real(struct mbox_sync_mail_context *ctx, struct message_header_line *hdr) { struct mailbox *box = &ctx->sync_ctx->mbox->box; ARRAY_TYPE(keyword_indexes) keyword_list; const unsigned int *list; string_t *keyword; size_t keyword_start; unsigned int i, idx, count; size_t pos; if (array_is_created(&ctx->mail.keywords)) return FALSE; /* duplicate header, delete */ /* read keyword indexes to temporary array first */ keyword = t_str_new(128); t_array_init(&keyword_list, 16); for (pos = 0; pos < hdr->full_value_len; ) { if (IS_LWSP_LF(hdr->full_value[pos])) { pos++; continue; } /* read the keyword string */ keyword_start = pos; for (; pos < hdr->full_value_len; pos++) { if (IS_LWSP_LF(hdr->full_value[pos])) break; } str_truncate(keyword, 0); str_append_n(keyword, hdr->full_value + keyword_start, pos - keyword_start); if (!mail_index_keyword_lookup(box->index, str_c(keyword), &idx)) { /* keyword wasn't found. that means the sent mail originally contained X-Keywords header. Delete it. */ return FALSE; } /* check that the keyword isn't already added there. we don't want duplicates. */ list = array_get(&keyword_list, &count); for (i = 0; i < count; i++) { if (list[i] == idx) break; } if (i == count) array_append(&keyword_list, &idx, 1); } /* once we know how many keywords there are, we can allocate the array from mail_keyword_pool without wasting memory. */ if (array_count(&keyword_list) > 0) { p_array_init(&ctx->mail.keywords, ctx->sync_ctx->mail_keyword_pool, array_count(&keyword_list)); array_append_array(&ctx->mail.keywords, &keyword_list); } ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] = str_len(ctx->header); parse_trailing_whitespace(ctx, hdr); return TRUE; }
static int dsync_connect_tcp(struct dsync_cmd_context *ctx, const struct mail_storage_settings *mail_set, const char *target, bool ssl, const char **error_r) { struct doveadm_server *server; struct server_connection *conn; struct ioloop *ioloop; string_t *cmd; const char *error; server = p_new(ctx->ctx.pool, struct doveadm_server, 1); server->name = p_strdup(ctx->ctx.pool, target); if (ssl) { if (dsync_init_ssl_ctx(ctx, mail_set, &error) < 0) { *error_r = t_strdup_printf( "Couldn't initialize SSL context: %s", error); return -1; } server->ssl_ctx = ctx->ssl_ctx; } p_array_init(&server->connections, ctx->ctx.pool, 1); p_array_init(&server->queue, ctx->ctx.pool, 1); ioloop = io_loop_create(); if (server_connection_create(server, &conn) < 0) { *error_r = "Couldn't create server connection"; return -1; } /* <flags> <username> <command> [<args>] */ cmd = t_str_new(256); if (doveadm_debug) str_append_c(cmd, 'D'); str_append_c(cmd, '\t'); str_append_tabescaped(cmd, ctx->ctx.cur_username); str_append(cmd, "\tdsync-server\t-u"); str_append_tabescaped(cmd, ctx->ctx.cur_username); if (ctx->replicator_notify) str_append(cmd, "\t-U"); str_append_c(cmd, '\n'); ctx->tcp_conn = conn; server_connection_cmd(conn, str_c(cmd), dsync_connected_callback, ctx); io_loop_run(ioloop); ctx->tcp_conn = NULL; if (array_count(&server->connections) > 0) server_connection_destroy(&conn); io_loop_destroy(&ioloop); if (ctx->error != NULL) { *error_r = ctx->error; ctx->error = NULL; return -1; } ctx->run_type = DSYNC_RUN_TYPE_STREAM; return 0; }
int master_service_settings_read(struct master_service *service, const struct master_service_settings_input *input, struct master_service_settings_output *output_r, const char **error_r) { ARRAY(const struct setting_parser_info *) all_roots; const struct setting_parser_info *tmp_root; struct setting_parser_context *parser; struct istream *istream; const char *path = NULL, *error; void **sets; unsigned int i; int ret, fd = -1; time_t now, timeout; bool use_environment, retry; memset(output_r, 0, sizeof(*output_r)); if (getenv("DOVECONF_ENV") == NULL && (service->flags & MASTER_SERVICE_FLAG_NO_CONFIG_SETTINGS) == 0) { retry = service->config_fd != -1; for (;;) { fd = master_service_open_config(service, input, &path, error_r); if (fd == -1) { if (errno == EACCES) output_r->permission_denied = TRUE; return -1; } if (config_send_request(service, input, fd, path, error_r) == 0) break; i_close_fd(&fd); if (!retry) { config_exec_fallback(service, input); return -1; } /* config process died, retry connecting */ retry = FALSE; } } if (service->set_pool != NULL) { if (service->set_parser != NULL) settings_parser_deinit(&service->set_parser); p_clear(service->set_pool); } else { service->set_pool = pool_alloconly_create("master service settings", 16384); } p_array_init(&all_roots, service->set_pool, 8); tmp_root = &master_service_setting_parser_info; array_append(&all_roots, &tmp_root, 1); if (service->want_ssl_settings) { tmp_root = &master_service_ssl_setting_parser_info; array_append(&all_roots, &tmp_root, 1); } if (input->roots != NULL) { for (i = 0; input->roots[i] != NULL; i++) array_append(&all_roots, &input->roots[i], 1); } parser = settings_parser_init_list(service->set_pool, array_idx(&all_roots, 0), array_count(&all_roots), SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS); if (fd != -1) { istream = i_stream_create_fd(fd, (size_t)-1); now = time(NULL); timeout = now + CONFIG_READ_TIMEOUT_SECS; do { alarm(timeout - now); ret = config_read_reply_header(istream, path, service->set_pool, input, output_r, error_r); if (ret == 0) { ret = settings_parse_stream_read(parser, istream); if (ret < 0) *error_r = settings_parser_get_error(parser); } alarm(0); if (ret <= 0) break; /* most likely timed out, but just in case some other signal was delivered early check if we need to continue */ now = time(NULL); } while (now < timeout); i_stream_unref(&istream); if (ret != 0) { if (ret > 0) { *error_r = t_strdup_printf( "Timeout reading config from %s", path); } i_close_fd(&fd); config_exec_fallback(service, input); settings_parser_deinit(&parser); return -1; } if ((service->flags & MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN) != 0 && service->config_fd == -1 && input->config_path == NULL) service->config_fd = fd; else i_close_fd(&fd); use_environment = FALSE; } else { use_environment = TRUE; } if (use_environment || service->keep_environment) { if (settings_parse_environ(parser) < 0) { *error_r = t_strdup(settings_parser_get_error(parser)); settings_parser_deinit(&parser); return -1; } } if (array_is_created(&service->config_overrides)) { if (master_service_apply_config_overrides(service, parser, error_r) < 0) { settings_parser_deinit(&parser); return -1; } } if (!settings_parser_check(parser, service->set_pool, &error)) { *error_r = t_strdup_printf("Invalid settings: %s", error); settings_parser_deinit(&parser); return -1; } sets = settings_parser_get_list(parser); service->set = sets[0]; service->set_parser = parser; if (service->set->version_ignore && (service->flags & MASTER_SERVICE_FLAG_STANDALONE) != 0) { /* running standalone. we want to ignore plugin versions. */ service->version_string = NULL; } if (service->set->shutdown_clients) master_service_set_die_with_master(master_service, TRUE); /* if we change any settings afterwards, they're in expanded form. especially all settings from userdb are already expanded. */ settings_parse_set_expanded(service->set_parser, TRUE); return 0; }
bool sieve_extensions_init(struct sieve_instance *svinst) { unsigned int i; struct sieve_extension_registry *ext_reg = p_new(svinst->pool, struct sieve_extension_registry, 1); struct sieve_extension *ext; svinst->ext_reg = ext_reg; sieve_extension_registry_init(svinst); sieve_capability_registry_init(svinst); /* Preloaded 'extensions' */ ext_reg->comparator_extension = sieve_extension_register(svinst, &comparator_extension, TRUE); ext_reg->match_type_extension = sieve_extension_register(svinst, &match_type_extension, TRUE); ext_reg->address_part_extension = sieve_extension_register(svinst, &address_part_extension, TRUE); p_array_init(&ext_reg->preloaded_extensions, svinst->pool, 5); array_append(&ext_reg->preloaded_extensions, &ext_reg->comparator_extension, 1); array_append(&ext_reg->preloaded_extensions, &ext_reg->match_type_extension, 1); array_append(&ext_reg->preloaded_extensions, &ext_reg->address_part_extension, 1); /* Pre-load dummy extensions */ for ( i = 0; i < sieve_dummy_extensions_count; i++ ) { if ( (ext=_sieve_extension_register (svinst, sieve_dummy_extensions[i], TRUE, FALSE)) == NULL ) return FALSE; ext->dummy = TRUE; } /* Pre-load core extensions */ for ( i = 0; i < sieve_core_extensions_count; i++ ) { if ( sieve_extension_register (svinst, sieve_core_extensions[i], TRUE) == NULL ) return FALSE; } /* Pre-load extra extensions */ for ( i = 0; i < sieve_extra_extensions_count; i++ ) { if ( sieve_extension_register (svinst, sieve_extra_extensions[i], FALSE) == NULL ) return FALSE; } /* Register deprecated extensions */ for ( i = 0; i < sieve_deprecated_extensions_count; i++ ) { if ( sieve_extension_register (svinst, sieve_deprecated_extensions[i], FALSE) == NULL ) return FALSE; } #ifdef HAVE_SIEVE_UNFINISHED /* Register unfinished extensions */ for ( i = 0; i < sieve_unfinished_extensions_count; i++ ) { if ( sieve_extension_register (svinst, sieve_unfinished_extensions[i], FALSE) == NULL ) return FALSE; } #endif /* More extensions can be added through plugins */ return TRUE; }
struct client *client_create(int fd_in, int fd_out, const char *session_id, struct mail_user *user, struct mail_storage_service_user *service_user, const struct imap_settings *set) { const struct mail_storage_settings *mail_set; struct client *client; const char *ident; pool_t pool; bool explicit_capability = FALSE; /* always use nonblocking I/O */ net_set_nonblock(fd_in, TRUE); net_set_nonblock(fd_out, TRUE); pool = pool_alloconly_create("imap client", 2048); client = p_new(pool, struct client, 1); client->pool = pool; client->v = imap_client_vfuncs; client->set = set; client->service_user = service_user; client->session_id = p_strdup(pool, session_id); client->fd_in = fd_in; client->fd_out = fd_out; client->input = i_stream_create_fd(fd_in, set->imap_max_line_length, FALSE); client->output = o_stream_create_fd(fd_out, (size_t)-1, FALSE); o_stream_set_no_error_handling(client->output, TRUE); i_stream_set_name(client->input, "<imap client>"); o_stream_set_name(client->output, "<imap client>"); o_stream_set_flush_callback(client->output, client_output, client); p_array_init(&client->module_contexts, client->pool, 5); client->io = io_add_istream(client->input, client_input, client); client->last_input = ioloop_time; client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS, client_idle_timeout, client); client->command_pool = pool_alloconly_create(MEMPOOL_GROWING"client command", 1024*2); client->user = user; client->notify_count_changes = TRUE; client->notify_flag_changes = TRUE; mail_namespaces_set_storage_callbacks(user->namespaces, &mail_storage_callbacks, client); client->capability_string = str_new(client->pool, sizeof(CAPABILITY_STRING)+64); if (*set->imap_capability == '\0') str_append(client->capability_string, CAPABILITY_STRING); else if (*set->imap_capability != '+') { explicit_capability = TRUE; str_append(client->capability_string, set->imap_capability); } else { str_append(client->capability_string, CAPABILITY_STRING); str_append_c(client->capability_string, ' '); str_append(client->capability_string, set->imap_capability + 1); } if (user->fuzzy_search && !explicit_capability) { /* Enable FUZZY capability only when it actually has a chance of working */ str_append(client->capability_string, " SEARCH=FUZZY"); } mail_set = mail_user_set_get_storage_set(user); if (mail_set->mailbox_list_index && !explicit_capability) { /* NOTIFY is enabled only when mailbox list indexes are enabled, although even that doesn't necessarily guarantee it always */ str_append(client->capability_string, " NOTIFY"); } if (*set->imap_urlauth_host != '\0' && *mail_set->mail_attribute_dict != '\0') { /* Enable URLAUTH capability only when dict is configured correctly */ client_init_urlauth(client); if (!explicit_capability) str_append(client->capability_string, " URLAUTH URLAUTH=BINARY"); } if (set->imap_metadata && *mail_set->mail_attribute_dict != '\0') { client->imap_metadata_enabled = TRUE; if (!explicit_capability) str_append(client->capability_string, " METADATA"); } if (!explicit_capability && user_has_special_use_mailboxes(user)) { /* Advertise SPECIAL-USE only if there are actually some SPECIAL-USE flags in mailbox configuration. */ str_append(client->capability_string, " SPECIAL-USE"); } ident = mail_user_get_anvil_userip_ident(client->user); if (ident != NULL) { master_service_anvil_send(master_service, t_strconcat( "CONNECT\t", my_pid, "\timap/", ident, "\n", NULL)); client->anvil_sent = TRUE; } imap_client_count++; DLLIST_PREPEND(&imap_clients, client); if (hook_client_created != NULL) hook_client_created(&client); imap_refresh_proctitle(); return client; }
static int smtp_parse_ehlo_line(struct smtp_parser *parser, const char **key_r, const char *const **params_r) { const unsigned char *pbegin = parser->cur; ARRAY_TYPE(const_string) params = ARRAY_INIT; const char *param; /* ehlo-line = ehlo-keyword *( SP ehlo-param ) ehlo-keyword = (ALPHA / DIGIT) *(ALPHA / DIGIT / "-") ; additional syntax of ehlo-params depends on ; ehlo-keyword ehlo-param = 1*(%d33-126) ; any CHAR excluding <SP> and all ; control characters (US-ASCII 0-31 and 127 ; inclusive) */ if (parser->cur >= parser->end || !i_isalnum(*parser->cur)) { parser->error = "Unexpected character in EHLO keyword"; return -1; } parser->cur++; while (parser->cur < parser->end && (i_isalnum(*parser->cur) || *parser->cur == '-')) parser->cur++; if (key_r != NULL) *key_r = p_strdup_until(parser->pool, pbegin, parser->cur); if (parser->cur >= parser->end) { if (params_r != NULL) *params_r = p_new(parser->pool, const char *, 1); return 1; } if (*parser->cur != ' ') { parser->error = "Unexpected character in EHLO keyword"; return -1; } parser->cur++; pbegin = parser->cur; if (params_r != NULL) p_array_init(¶ms, parser->pool, 32); while (parser->cur < parser->end) { if (*parser->cur == ' ') { if (parser->cur+1 >= parser->end || *(parser->cur+1) == ' ') { parser->error = "Missing EHLO parameter after ' '"; return -1; } if (params_r != NULL) { param = p_strdup_until(parser->pool, pbegin, parser->cur); array_append(¶ms, ¶m, 1); } pbegin = parser->cur + 1; } else if (!smtp_char_is_ehlo_param(*parser->cur)) { parser->error = "Unexpected character in EHLO parameter"; return -1; } parser->cur++; } if (params_r != NULL) { array_append_zero(¶ms); *params_r = array_idx(¶ms, 0); } return 1; }