static struct mail_save_context * maildir_save_transaction_init(struct mailbox_transaction_context *t) { struct maildir_mailbox *mbox = (struct maildir_mailbox *)t->box; struct maildir_save_context *ctx; const char *path; pool_t pool; pool = pool_alloconly_create("maildir_save_context", 4096); ctx = p_new(pool, struct maildir_save_context, 1); ctx->ctx.transaction = t; ctx->pool = pool; ctx->mbox = mbox; ctx->trans = t->itrans; ctx->files_tail = &ctx->files; ctx->fd = -1; path = mailbox_get_path(&mbox->box); ctx->tmpdir = p_strconcat(pool, path, "/tmp", NULL); ctx->newdir = p_strconcat(pool, path, "/new", NULL); ctx->curdir = p_strconcat(pool, path, "/cur", NULL); buffer_create_from_const_data(&ctx->keywords_buffer, "", 0); array_create_from_buffer(&ctx->keywords_array, &ctx->keywords_buffer, sizeof(unsigned int)); ctx->last_save_finished = TRUE; return &ctx->ctx; }
int mdbox_storage_create(struct mail_storage *_storage, struct mail_namespace *ns, const char **error_r) { struct mdbox_storage *storage = (struct mdbox_storage *)_storage; const char *dir; storage->set = mail_storage_get_driver_settings(_storage); storage->preallocate_space = storage->set->mdbox_preallocate_space; if (*ns->list->set.mailbox_dir_name == '\0') { *error_r = "mdbox: MAILBOXDIR must not be empty"; return -1; } _storage->unique_root_dir = p_strdup(_storage->pool, ns->list->set.root_dir); dir = mailbox_list_get_root_forced(ns->list, MAILBOX_LIST_PATH_TYPE_DIR); storage->storage_dir = p_strconcat(_storage->pool, dir, "/"MDBOX_GLOBAL_DIR_NAME, NULL); storage->alt_storage_dir = p_strconcat(_storage->pool, ns->list->set.alt_dir, "/"MDBOX_GLOBAL_DIR_NAME, NULL); i_array_init(&storage->open_files, 64); storage->map = mdbox_map_init(storage, ns->list); return dbox_storage_create(_storage, ns, error_r); }
static int fetch_data(struct imap_fetch_context *ctx, const struct imap_fetch_body_data *body, const struct message_size *size) { string_t *str; ctx->cur_name = p_strconcat(ctx->cmd->pool, "[", body->section, "]", NULL); ctx->cur_size = get_send_size(body, size->virtual_size); str = get_prefix(ctx, body, ctx->cur_size); if (o_stream_send(ctx->client->output, str_data(str), str_len(str)) < 0) return -1; if (!ctx->update_partial) { if (message_skip_virtual(ctx->cur_input, body->skip, NULL, FALSE, &ctx->skip_cr) < 0) { fetch_read_error(ctx); return -1; } } else { if (seek_partial(ctx->select_counter, ctx->cur_mail->uid, &last_partial, ctx->cur_input, body->skip, &ctx->skip_cr) < 0) { fetch_read_error(ctx); return -1; } } return fetch_stream(ctx, size); }
static int mbox_storage_create(struct mail_storage *_storage, struct mail_namespace *ns, const char **error_r) { struct mbox_storage *storage = (struct mbox_storage *)_storage; struct stat st; const char *dir; if (master_service_get_client_limit(master_service) > 1) { /* we can't handle locking related problems. */ *error_r = "mbox requires client_limit=1 for service"; return -1; } storage->set = mail_storage_get_driver_settings(_storage); if (mailbox_list_get_root_path(ns->list, MAILBOX_LIST_PATH_TYPE_INDEX, &dir)) { _storage->temp_path_prefix = p_strconcat(_storage->pool, dir, "/", mailbox_list_get_temp_prefix(ns->list), NULL); } if (stat(ns->list->set.root_dir, &st) == 0 && !S_ISDIR(st.st_mode)) { *error_r = t_strdup_printf( "mbox root directory can't be a file: %s " "(http://wiki2.dovecot.org/MailLocation/Mbox)", ns->list->set.root_dir); return -1; } return 0; }
static struct mail_search_arg * arg_new_human_date(struct mail_search_build_context *ctx, enum mail_search_arg_type type, enum mail_search_date_type date_type) { struct mail_search_arg *sarg; const char *value; sarg = mail_search_build_new(ctx, type); if (mail_search_parse_string(ctx->parser, &value) < 0) return NULL; if (mail_parse_human_timestamp(value, &sarg->value.time) < 0) sarg->value.time = (time_t)-1; sarg->value.search_flags = MAIL_SEARCH_ARG_FLAG_USE_TZ; if (sarg->value.time == (time_t)-1) { ctx->_error = p_strconcat(ctx->pool, "Invalid search date parameter: ", value, NULL); return NULL; } sarg->value.date_type = date_type; return sarg; }
static void mailbox_list_index_update_info(struct mailbox_list_index_iterate_context *ctx) { struct mailbox_list_index_node *node = ctx->next_node; struct mailbox *box; p_clear(ctx->info_pool); str_truncate(ctx->path, ctx->parent_len); /* the root directory may have an empty name. in that case we'll still want to insert the separator, so check for non-NULL parent rather than non-empty path. */ if (node->parent != NULL) { str_append_c(ctx->path, mailbox_list_get_hierarchy_sep(ctx->ctx.list)); } str_append(ctx->path, node->name); ctx->info.vname = mailbox_list_get_vname(ctx->ctx.list, str_c(ctx->path)); ctx->info.flags = node->children != NULL ? MAILBOX_CHILDREN : MAILBOX_NOCHILDREN; if (strcmp(ctx->info.vname, "INBOX") != 0) { /* non-INBOX */ ctx->info.vname = p_strdup(ctx->info_pool, ctx->info.vname); } else if (!ctx->prefix_inbox_list) { /* listing INBOX itself */ ctx->info.vname = "INBOX"; if (mail_namespace_is_inbox_noinferiors(ctx->info.ns)) { ctx->info.flags &= ~(MAILBOX_CHILDREN|MAILBOX_NOCHILDREN); ctx->info.flags |= MAILBOX_NOINFERIORS; } } else { /* listing INBOX/INBOX */ ctx->info.vname = p_strconcat(ctx->info_pool, ctx->ctx.list->ns->prefix, "INBOX", NULL); ctx->info.flags |= MAILBOX_NONEXISTENT; } if ((node->flags & MAILBOX_LIST_INDEX_FLAG_NONEXISTENT) != 0) ctx->info.flags |= MAILBOX_NONEXISTENT; else if ((node->flags & MAILBOX_LIST_INDEX_FLAG_NOSELECT) != 0) ctx->info.flags |= MAILBOX_NOSELECT; if ((node->flags & MAILBOX_LIST_INDEX_FLAG_NOINFERIORS) != 0) ctx->info.flags |= MAILBOX_NOINFERIORS; if ((ctx->ctx.flags & (MAILBOX_LIST_ITER_SELECT_SUBSCRIBED | MAILBOX_LIST_ITER_RETURN_SUBSCRIBED)) != 0) { mailbox_list_set_subscription_flags(ctx->ctx.list, ctx->info.vname, &ctx->info.flags); } if ((ctx->ctx.flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0) { box = mailbox_alloc(ctx->ctx.list, ctx->info.vname, 0); mailbox_list_index_status_set_info_flags(box, node->uid, &ctx->info.flags); mailbox_free(&box); } }
static int sieve_dict_storage_init (struct sieve_storage *storage, const char *const *options, enum sieve_error *error_r) { struct sieve_dict_storage *dstorage = (struct sieve_dict_storage *)storage; struct sieve_instance *svinst = storage->svinst; const char *uri = storage->location, *username = NULL; if ( options != NULL ) { while ( *options != NULL ) { const char *option = *options; if ( strncasecmp(option, "user="******"Invalid option `%s'", option); *error_r = SIEVE_ERROR_TEMP_FAILURE; return -1; } options++; } } if ( username == NULL ) { if ( svinst->username == NULL ) { sieve_storage_set_critical(storage, "No username specified"); *error_r = SIEVE_ERROR_TEMP_FAILURE; return -1; } username = svinst->username; } if ( svinst->base_dir == NULL ) { sieve_storage_set_critical(storage, "BUG: Sieve interpreter is initialized without a base_dir"); *error_r = SIEVE_ERROR_TEMP_FAILURE; return -1; } sieve_storage_sys_debug(storage, "user=%s, uri=%s", username, uri); dstorage->uri = p_strdup(storage->pool, uri); dstorage->username = p_strdup(storage->pool, username); storage->location = p_strconcat(storage->pool, SIEVE_DICT_STORAGE_DRIVER_NAME, ":", storage->location, ";user=", username, NULL); return 0; }
static struct mailbox_list *imapdir_list_alloc(void) { struct maildir_mailbox_list *list; pool_t pool; pool = pool_alloconly_create("imapdir list", 1024); list = p_new(pool, struct maildir_mailbox_list, 1); list->list = imapdir_mailbox_list; list->list.pool = pool; list->global_temp_prefix = IMAPDIR_GLOBAL_TEMP_PREFIX; list->temp_prefix = p_strconcat(pool, list->global_temp_prefix, my_hostname, ".", my_pid, ".", NULL); return &list->list; }
static struct mailbox_list *fs_list_alloc(void) { struct fs_mailbox_list *list; pool_t pool; pool = pool_alloconly_create("fs list", 2048); list = p_new(pool, struct fs_mailbox_list, 1); list->list = fs_mailbox_list; list->list.pool = pool; list->temp_prefix = p_strconcat(pool, GLOBAL_TEMP_PREFIX, my_hostname, ".", my_pid, ".", NULL); return &list->list; }
static struct mailbox_list *maildir_list_alloc(void) { struct maildir_mailbox_list *list; pool_t pool; pool = pool_alloconly_create("maildir++ list", 2048); list = p_new(pool, struct maildir_mailbox_list, 1); list->list = maildir_mailbox_list; list->list.pool = pool; list->sep = '.'; list->global_temp_prefix = MAILDIR_GLOBAL_TEMP_PREFIX; list->temp_prefix = p_strconcat(pool, list->global_temp_prefix, my_hostname, ".", my_pid, ".", NULL); return &list->list; }
void testsuite_smtp_init(void) { pool_t pool; testsuite_smtp_pool = pool = pool_alloconly_create("testsuite_smtp", 8192); testsuite_smtp_tmp = p_strconcat (pool, testsuite_tmp_dir_get(), "/smtp", NULL); if ( mkdir(testsuite_smtp_tmp, 0700) < 0 ) { i_fatal("failed to create temporary directory '%s': %m.", testsuite_smtp_tmp); } p_array_init(&testsuite_smtp_messages, pool, 16); }
static bool lda_settings_check(void *_set, pool_t pool, const char **error_r) { struct lda_settings *set = _set; if (*set->hostname == '\0') set->hostname = p_strdup(pool, my_hostdomain()); if (*set->postmaster_address == '\0') { /* check for valid looking fqdn in hostname */ if (strchr(set->hostname, '.') == NULL) { *error_r = "postmaster_address setting not given"; return FALSE; } set->postmaster_address = p_strconcat(pool, "postmaster@", set->hostname, NULL); } return TRUE; }
static int mail_search_build_key_int(struct mail_search_build_context *ctx, struct mail_search_arg *parent, struct mail_search_arg **arg_r) { struct mail_search_arg *sarg; struct mail_search_arg *old_parent = ctx->parent; const char *key; const struct mail_search_register_arg *reg_arg; mail_search_register_fallback_t *fallback; int ret; ctx->parent = parent; if ((ret = mail_search_parse_key(ctx->parser, &key)) <= 0) return ret; if (strcmp(key, MAIL_SEARCH_PARSER_KEY_LIST) == 0) { if (mail_search_build_list(ctx, &sarg) < 0) return -1; if (sarg->value.subargs == NULL) { ctx->_error = "No search parameters inside list"; return -1; } ctx->parent = old_parent; *arg_r = sarg; return 1; } key = t_str_ucase(key); reg_arg = mail_search_register_find(ctx->reg, key); if (reg_arg != NULL) sarg = reg_arg->build(ctx); else if (mail_search_register_get_fallback(ctx->reg, &fallback)) sarg = fallback(ctx, key); else { sarg = NULL; ctx->_error = p_strconcat(ctx->pool, "Unknown argument ", key, NULL); } ctx->parent = old_parent; *arg_r = sarg; return sarg == NULL ? -1 : 1; }
static struct mail_search_arg * imap_search_fallback(struct mail_search_build_context *ctx, const char *key) { struct mail_search_arg *sarg; if (*key == '*' || (*key >= '0' && *key <= '9')) { /* <message-set> */ sarg = mail_search_build_new(ctx, SEARCH_SEQSET); p_array_init(&sarg->value.seqset, ctx->pool, 16); if (imap_seq_set_parse(key, &sarg->value.seqset) < 0) { ctx->_error = "Invalid messageset"; return NULL; } return sarg; } ctx->_error = p_strconcat(ctx->pool, "Unknown argument ", key, NULL); return NULL; }
static struct mail_search_arg * human_search_mailbox(struct mail_search_build_context *ctx) { struct mail_search_arg *sarg; sarg = mail_search_build_str(ctx, SEARCH_MAILBOX); if (sarg == NULL) return NULL; if (strchr(sarg->value.str, '*') != NULL || strchr(sarg->value.str, '%') != NULL) sarg->type = SEARCH_MAILBOX_GLOB; if (!uni_utf8_str_is_valid(sarg->value.str)) { ctx->_error = p_strconcat(ctx->pool, "Mailbox name not valid UTF-8: ", sarg->value.str, NULL); return NULL; } return sarg; }
bool cmd_uid(struct client_command_context *cmd) { struct command *command; const char *cmd_name; /* UID <command> <args> */ cmd_name = imap_parser_read_word(cmd->parser); if (cmd_name == NULL) return FALSE; command = command_find(t_strconcat("UID ", cmd_name, NULL)); if (command == NULL) { client_send_tagline(cmd, t_strconcat( "BAD Unknown UID command ", cmd_name, NULL)); return TRUE; } cmd->name = p_strconcat(cmd->pool, "UID ", cmd_name, NULL); cmd->cmd_flags = command->flags; cmd->func = command->func; cmd->uid = TRUE; return cmd->func(cmd); }
static const char * auth_master_reply_hide_passwords(struct auth_master_connection *conn, const char *str) { char **args, *p, *p2; unsigned int i; if (conn->auth->set->debug_passwords) return str; /* hide all parameters that have "pass" in their key */ args = p_strsplit(pool_datastack_create(), str, "\t"); for (i = 0; args[i] != NULL; i++) { p = strstr(args[i], "pass"); p2 = strchr(args[i], '='); if (p != NULL && p < p2) { *p2 = '\0'; args[i] = p_strconcat(pool_datastack_create(), args[i], "=<hidden>", NULL); } } return t_strarray_join((void *)args, "\t"); }
passwd_file_add(struct passwd_file *pw, const char *username, const char *pass, const char *const *args) { /* args = uid, gid, user info, home dir, shell, extra_fields */ struct passwd_user *pu; const char *extra_fields = NULL; char *user; size_t len; if (hash_table_lookup(pw->users, username) != NULL) { i_error("passwd-file %s: User %s exists more than once", pw->path, username); return; } pu = p_new(pw->pool, struct passwd_user, 1); user = p_strdup(pw->pool, username); len = pass == NULL ? 0 : strlen(pass); if (len > 4 && pass[0] != '{' && pass[0] != '$' && pass[len-1] == ']' && pass[len-4] == '[') { /* password[type] - we're being libpam-pwdfile compatible here. it uses 13 = DES and 34 = MD5. For backwards comaptibility with ourself, we have also 56 = Digest-MD5. */ int num = (pass[len-3] - '0') * 10 + (pass[len-2] - '0'); pass = t_strndup(pass, len-4); if (num == 34) { pu->password = p_strconcat(pw->pool, "{PLAIN-MD5}", pass, NULL); } else if (num == 56) { pu->password = p_strconcat(pw->pool, "{DIGEST-MD5}", pass, NULL); if (strlen(pu->password) != 32 + 12) { i_error("passwd-file %s: User %s " "has invalid password", pw->path, username); return; } } else { pu->password = p_strconcat(pw->pool, "{CRYPT}", pass, NULL); } } else { pu->password = p_strdup(pw->pool, pass); } pu->uid = (uid_t)-1; pu->gid = (gid_t)-1; if (*args == NULL) ; else if (!pw->db->userdb || **args == '\0') { args++; } else { pu->uid = userdb_parse_uid(NULL, *args); if (pu->uid == 0 || pu->uid == (uid_t)-1) { i_error("passwd-file %s: User %s has invalid UID '%s'", pw->path, username, *args); return; } args++; } if (*args == NULL) { if (pw->db->userdb_warn_missing) { i_error("passwd-file %s: User %s is missing " "userdb info", pw->path, username); } /* don't allow userdb lookups */ pu->uid = 0; pu->gid = 0; } else if (!pw->db->userdb || **args == '\0') args++; else { pu->gid = userdb_parse_gid(NULL, *args); if (pu->gid == 0 || pu->gid == (gid_t)-1) { i_error("passwd-file %s: User %s has invalid GID '%s'", pw->path, username, *args); return; } args++; } /* user info */ if (*args != NULL) args++; /* home */ if (*args != NULL) { if (pw->db->userdb) pu->home = p_strdup_empty(pw->pool, *args); args++; } /* shell */ if (*args != NULL) args++; if (*args != NULL && **args == '\0') { /* old format, this field is empty and next field may contain MAIL */ args++; if (*args != NULL && **args != '\0' && pw->db->userdb) { extra_fields = t_strconcat("userdb_mail=", t_strarray_join(args, ":"), NULL); } } else if (*args != NULL) { /* new format, contains a space separated list of extra fields */ extra_fields = t_strarray_join(args, ":"); } if (extra_fields != NULL) { pu->extra_fields = p_strsplit_spaces(pw->pool, extra_fields, " "); } hash_table_insert(pw->users, user, pu); }
struct mail_storage_service_ctx * mail_storage_service_init(struct master_service *service, const struct setting_parser_info *set_roots[], enum mail_storage_service_flags flags) { struct mail_storage_service_ctx *ctx; const char *version; pool_t pool; unsigned int count; version = master_service_get_version_string(service); if (version != NULL && strcmp(version, PACKAGE_VERSION) != 0) { i_fatal("Version mismatch: libdovecot-storage.so is '%s', " "while the running Dovecot binary is '%s'", PACKAGE_VERSION, version); } if ((flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 && getuid() != 0) { /* service { user } isn't root. the permission drop can't be temporary. */ flags &= ~MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP; } (void)umask(0077); io_loop_set_time_moved_callback(current_ioloop, mail_storage_service_time_moved); mail_storage_init(); mail_storage_register_all(); mailbox_list_register_all(); pool = pool_alloconly_create("mail storage service", 2048); ctx = p_new(pool, struct mail_storage_service_ctx, 1); ctx->pool = pool; ctx->service = service; ctx->flags = flags; /* @UNSAFE */ if (set_roots == NULL) count = 0; else for (count = 0; set_roots[count] != NULL; count++) ; ctx->set_roots = p_new(pool, const struct setting_parser_info *, count + 2); ctx->set_roots[0] = &mail_user_setting_parser_info; if (set_roots != NULL) { memcpy(ctx->set_roots + 1, set_roots, sizeof(*ctx->set_roots) * count); } /* do all the global initialization. delay initializing plugins until we drop privileges the first time. */ if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0) { /* note: we may not have read any settings yet, so this logging may still be going to wrong location */ ctx->default_log_prefix = p_strconcat(pool, service->name, ": ", NULL); master_service_init_log(service, ctx->default_log_prefix); } dict_drivers_register_builtin(); return ctx; }
void doveadm_dsync_main(int *_argc, char **_argv[]) { int argc = *_argc; const char *getopt_str; char **argv = *_argv; char **new_argv, *mailbox = NULL, *alt_char = NULL, *username = NULL; char *p, *dup, new_flags[6]; int max_argc, src, dest, i, j; bool flag_f = FALSE, flag_R = FALSE, flag_m, flag_u, flag_C, has_arg; bool dsync_server = FALSE; p = strrchr(argv[0], '/'); if (p == NULL) p = argv[0]; if (strstr(p, "dsync") == NULL) return; /* @UNSAFE: this is called when the "doveadm" binary is called as "dsync" (for backwards compatibility) */ max_argc = argc + 7; new_argv = t_new(char *, max_argc); new_argv[0] = argv[0]; dest = 1; getopt_str = master_service_getopt_string(); /* add global doveadm flags */ for (src = 1; src < argc; src++) { if (argv[src][0] != '-') break; flag_m = FALSE; flag_C = FALSE; has_arg = FALSE; flag_u = FALSE; dup = t_strdup_noconst(argv[src]); for (i = j = 1; argv[src][i] != '\0'; i++) { switch (argv[src][i]) { case 'C': flag_C = TRUE; break; case 'f': flag_f = TRUE; break; case 'R': flag_R = TRUE; break; case 'm': flag_m = TRUE; break; case 'u': flag_u = TRUE; break; default: p = strchr(getopt_str, argv[src][i]); if (p != NULL && p[1] == ':') has_arg = TRUE; dup[j++] = argv[src][i]; break; } } if (j > 1) { dup[j++] = '\0'; new_argv[dest++] = dup; if (has_arg && src+1 < argc) new_argv[dest++] = argv[++src]; } if (flag_m) { if (src+1 == argc) i_fatal("-m missing parameter"); mailbox = argv[++src]; } if (flag_u) { if (src+1 == argc) i_fatal("-u missing parameter"); username = argv[++src]; } if (flag_C) { if (src+1 == argc) i_fatal("-C missing parameter"); alt_char = argv[++src]; } } if (alt_char != NULL) { new_argv[dest++] = "-o"; new_argv[dest++] = p_strconcat(pool_datastack_create(), "dsync_alt_char=", alt_char, NULL); } /* mirror|backup|server */ if (src == argc) i_fatal("Missing mirror or backup parameter"); if (strcmp(argv[src], "sync") == 0 || strcmp(argv[src], "dsync-server") == 0) { /* we're re-executing dsync due to doveconf. "backup" re-exec detection is later. */ return; } if (strcmp(argv[src], "mirror") == 0) new_argv[dest] = "sync"; else if (strcmp(argv[src], "backup") == 0) new_argv[dest] = "backup"; else if (strcmp(argv[src], "server") == 0) { new_argv[dest] = "dsync-server"; dsync_server = TRUE; } else i_fatal("Invalid parameter: %s", argv[src]); src++; dest++; if (src < argc && strncmp(argv[src], "-E", 2) == 0) { /* we're re-executing dsync due to doveconf */ return; } /* dsync flags */ new_flags[0] = '-'; new_flags[1] = 'E'; i = 2; if (!dsync_server) { if (flag_f) new_flags[i++] = 'f'; if (flag_R) new_flags[i++] = 'R'; if (mailbox != NULL) new_flags[i++] = 'm'; } i_assert((unsigned int)i < sizeof(new_flags)); new_flags[i] = '\0'; if (i > 1) { new_argv[dest++] = strdup(new_flags); if (mailbox != NULL) new_argv[dest++] = mailbox; } if (username != NULL) { new_argv[dest++] = "-u"; new_argv[dest++] = username; } /* rest of the parameters */ for (; src < argc; src++) new_argv[dest++] = argv[src]; i_assert(dest < max_argc); new_argv[dest] = NULL; legacy_dsync = TRUE; *_argc = dest; *_argv = new_argv; optind = 1; }
static void fix_base_path(struct mail_user_settings *set, pool_t pool, const char **str) { if (*str != NULL && **str != '\0' && **str != '/') *str = p_strconcat(pool, set->base_dir, "/", *str, NULL); }
static bool client_command_input(struct client_command_context *cmd) { struct client *client = cmd->client; struct command *command; if (cmd->func != NULL) { /* command is being executed - continue it */ if (command_exec(cmd)) { /* command execution was finished */ client_command_free(&cmd); client_add_missing_io(client); return TRUE; } return client_handle_unfinished_cmd(cmd); } if (cmd->tag == NULL) { cmd->tag = imap_parser_read_word(cmd->parser); if (cmd->tag == NULL) return FALSE; /* need more data */ cmd->tag = p_strdup(cmd->pool, cmd->tag); } if (cmd->name == NULL) { cmd->name = imap_parser_read_word(cmd->parser); if (cmd->name == NULL) return FALSE; /* need more data */ /* UID commands are a special case. better to handle them here. */ if (!cmd->uid && strcasecmp(cmd->name, "UID") == 0) { cmd->uid = TRUE; cmd->name = imap_parser_read_word(cmd->parser); if (cmd->name == NULL) return FALSE; /* need more data */ } cmd->name = !cmd->uid ? p_strdup(cmd->pool, cmd->name) : p_strconcat(cmd->pool, "UID ", cmd->name, NULL); imap_refresh_proctitle(); } client->input_skip_line = TRUE; if (cmd->name[0] == '\0') { /* command not given - cmd->func is already NULL. */ } else if ((command = command_find(cmd->name)) != NULL) { cmd->func = command->func; cmd->cmd_flags = command->flags; if (client_command_is_ambiguous(cmd)) { /* do nothing until existing commands are finished */ i_assert(cmd->state == CLIENT_COMMAND_STATE_WAIT_INPUT); cmd->state = CLIENT_COMMAND_STATE_WAIT_UNAMBIGUITY; io_remove(&client->io); return FALSE; } } if (cmd->func == NULL) { /* unknown command */ client_send_command_error(cmd, "Unknown command."); cmd->param_error = TRUE; client_command_free(&cmd); return TRUE; } else { i_assert(!client->disconnected); return client_command_input(cmd); } }
static bool verify_credentials(struct digest_auth_request *request, const unsigned char *credentials, size_t size) { struct md5_context ctx; unsigned char digest[MD5_RESULTLEN]; const char *a1_hex, *a2_hex, *response_hex; int i; /* get the MD5 password */ if (size != MD5_RESULTLEN) { auth_request_log_error(&request->auth_request, AUTH_SUBSYS_MECH, "invalid credentials length"); return FALSE; } /* response = HEX( KD ( HEX(H(A1)), { nonce-value, ":" nc-value, ":", cnonce-value, ":", qop-value, ":", HEX(H(A2)) })) and if authzid is not empty: A1 = { H( { username-value, ":", realm-value, ":", passwd } ), ":", nonce-value, ":", cnonce-value, ":", authzid } else: A1 = { H( { username-value, ":", realm-value, ":", passwd } ), ":", nonce-value, ":", cnonce-value } If the "qop" directive's value is "auth", then A2 is: A2 = { "AUTHENTICATE:", digest-uri-value } If the "qop" value is "auth-int" or "auth-conf" then A2 is: A2 = { "AUTHENTICATE:", digest-uri-value, ":00000000000000000000000000000000" } */ /* A1 */ md5_init(&ctx); md5_update(&ctx, credentials, size); md5_update(&ctx, ":", 1); md5_update(&ctx, request->nonce, strlen(request->nonce)); md5_update(&ctx, ":", 1); md5_update(&ctx, request->cnonce, strlen(request->cnonce)); if (request->authzid != NULL) { md5_update(&ctx, ":", 1); md5_update(&ctx, request->authzid, strlen(request->authzid)); } md5_final(&ctx, digest); a1_hex = binary_to_hex(digest, 16); /* do it twice, first verify the user's response, the second is sent for client as a reply */ for (i = 0; i < 2; i++) { /* A2 */ md5_init(&ctx); if (i == 0) md5_update(&ctx, "AUTHENTICATE:", 13); else md5_update(&ctx, ":", 1); if (request->digest_uri != NULL) { md5_update(&ctx, request->digest_uri, strlen(request->digest_uri)); } if (request->qop == QOP_AUTH_INT || request->qop == QOP_AUTH_CONF) { md5_update(&ctx, ":00000000000000000000000000000000", 33); } md5_final(&ctx, digest); a2_hex = binary_to_hex(digest, 16); /* response */ md5_init(&ctx); md5_update(&ctx, a1_hex, 32); md5_update(&ctx, ":", 1); md5_update(&ctx, request->nonce, strlen(request->nonce)); md5_update(&ctx, ":", 1); md5_update(&ctx, request->nonce_count, strlen(request->nonce_count)); md5_update(&ctx, ":", 1); md5_update(&ctx, request->cnonce, strlen(request->cnonce)); md5_update(&ctx, ":", 1); md5_update(&ctx, request->qop_value, strlen(request->qop_value)); md5_update(&ctx, ":", 1); md5_update(&ctx, a2_hex, 32); md5_final(&ctx, digest); response_hex = binary_to_hex(digest, 16); if (i == 0) { /* verify response */ if (memcmp(response_hex, request->response, 32) != 0) { auth_request_log_info(&request->auth_request, AUTH_SUBSYS_MECH, "password mismatch"); return FALSE; } } else { request->rspauth = p_strconcat(request->pool, "rspauth=", response_hex, NULL); } } return TRUE; }
static void settings_export(struct config_export_context *ctx, const struct setting_parser_info *info, bool parent_unique_deflist, const void *set, const void *change_set) { const struct setting_define *def; const void *value, *default_value, *change_value; void *const *children = NULL, *const *change_children = NULL; unsigned int i, count, count2, prefix_len; const char *str; char *key; bool dump, dump_default = FALSE; for (def = info->defines; def->key != NULL; def++) { value = CONST_PTR_OFFSET(set, def->offset); default_value = info->defaults == NULL ? NULL : CONST_PTR_OFFSET(info->defaults, def->offset); change_value = CONST_PTR_OFFSET(change_set, def->offset); switch (ctx->scope) { case CONFIG_DUMP_SCOPE_ALL: dump_default = TRUE; break; case CONFIG_DUMP_SCOPE_SET: dump_default = *((const char *)change_value) != 0; break; case CONFIG_DUMP_SCOPE_CHANGED: dump_default = FALSE; break; } if (!parent_unique_deflist || (ctx->flags & CONFIG_DUMP_FLAG_HIDE_LIST_DEFAULTS) == 0) { /* .. */ } else if (*((const char *)change_value) == 0 && def->offset != info->type_offset) { /* this is mainly for service {} blocks. if value hasn't changed, it's the default. even if info->defaults has a different value. */ default_value = value; } else { /* value is set explicitly, but we don't know the default here. assume it's not the default. */ dump_default = TRUE; } dump = FALSE; count = 0; str_truncate(ctx->value, 0); switch (def->type) { case SET_BOOL: case SET_SIZE: case SET_UINT: case SET_UINT_OCT: case SET_TIME: case SET_STR_VARS: case SET_STR: case SET_ENUM: if (!config_export_type(ctx->value, value, default_value, def->type, dump_default, &dump)) i_unreached(); break; case SET_DEFLIST: case SET_DEFLIST_UNIQUE: { const ARRAY_TYPE(void_array) *val = value; const ARRAY_TYPE(void_array) *change_val = change_value; if (!array_is_created(val)) break; children = array_get(val, &count); for (i = 0; i < count; i++) { if (i > 0) str_append_c(ctx->value, ' '); setting_export_section_name(ctx->value, def, children[i], i); } change_children = array_get(change_val, &count2); i_assert(count == count2); break; } case SET_STRLIST: { const ARRAY_TYPE(const_string) *val = value; const char *const *strings; if (!array_is_created(val)) break; key = p_strconcat(ctx->pool, str_c(ctx->prefix), def->key, NULL); if (hash_table_lookup(ctx->keys, key) != NULL) { /* already added all of these */ break; } hash_table_insert(ctx->keys, key, key); /* for doveconf -n to see this KEY_LIST */ ctx->callback(key, "", CONFIG_KEY_LIST, ctx->context); strings = array_get(val, &count); i_assert(count % 2 == 0); for (i = 0; i < count; i += 2) { str = p_strdup_printf(ctx->pool, "%s%s%c%s", str_c(ctx->prefix), def->key, SETTINGS_SEPARATOR, strings[i]); ctx->callback(str, strings[i+1], CONFIG_KEY_NORMAL, ctx->context); } count = 0; break; } case SET_ALIAS: break; } if (str_len(ctx->value) > 0 || dump) { key = p_strconcat(ctx->pool, str_c(ctx->prefix), def->key, NULL); if (hash_table_lookup(ctx->keys, key) == NULL) { enum config_key_type type; if (def->offset == info->type_offset && parent_unique_deflist) type = CONFIG_KEY_UNIQUE_KEY; else if (SETTING_TYPE_IS_DEFLIST(def->type)) type = CONFIG_KEY_LIST; else type = CONFIG_KEY_NORMAL; ctx->callback(key, str_c(ctx->value), type, ctx->context); hash_table_insert(ctx->keys, key, key); } } prefix_len = str_len(ctx->prefix); for (i = 0; i < count; i++) { str_append(ctx->prefix, def->key); str_append_c(ctx->prefix, SETTINGS_SEPARATOR); setting_export_section_name(ctx->prefix, def, children[i], i); str_append_c(ctx->prefix, SETTINGS_SEPARATOR); settings_export(ctx, def->list_info, def->type == SET_DEFLIST_UNIQUE, children[i], change_children[i]); str_truncate(ctx->prefix, prefix_len); } } }