Esempio n. 1
0
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;
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
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;
}
Esempio n. 5
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;
}
Esempio n. 6
0
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);
	}
}
Esempio n. 7
0
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;
}
Esempio n. 8
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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);
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
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;
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
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");
}
Esempio n. 18
0
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);
}
Esempio n. 19
0
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;
}
Esempio n. 20
0
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;
}
Esempio n. 21
0
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);
}
Esempio n. 22
0
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);
	}
}
Esempio n. 23
0
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;
}
Esempio n. 24
0
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);
		}
	}
}