Example #1
0
static void acl_mailbox_fail_not_found(struct mailbox *box)
{
	int ret;

	ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_LOOKUP);
	if (ret > 0) {
		mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
				       MAIL_ERRSTR_NO_PERMISSION);
	} else if (ret == 0) {
		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
				T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
	}
}
Example #2
0
static int pop3c_mail_get_received_date(struct mail *_mail, time_t *date_r)
{
	mail_storage_set_error(_mail->box->storage, MAIL_ERROR_NOTPOSSIBLE,
			       "POP3 has no received date");
	*date_r = (time_t)-1;
	return -1;
}
Example #3
0
static int do_hardlink(struct maildir_mailbox *mbox, const char *path,
		       struct hardlink_ctx *ctx)
{
	int ret;

	if (mbox->storage->storage.set->mail_nfs_storage)
		ret = nfs_safe_link(path, ctx->dest_path, FALSE);
	else
		ret = link(path, ctx->dest_path);
	if (ret < 0) {
		if (errno == ENOENT)
			return 0;

		if (ENOQUOTA(errno)) {
			mail_storage_set_error(&mbox->storage->storage,
				MAIL_ERROR_NOQUOTA, MAIL_ERRSTR_NO_QUOTA);
			return -1;
		}

		/* we could handle the EEXIST condition by changing the
		   filename, but it practically never happens so just fallback
		   to standard copying for the rare cases when it does. */
		if (errno == EACCES || ECANTLINK(errno) || errno == EEXIST)
			return 1;

		mail_storage_set_critical(&mbox->storage->storage,
					  "link(%s, %s) failed: %m",
					  path, ctx->dest_path);
		return -1;
	}

	ctx->success = TRUE;
	return 1;
}
Example #4
0
int tfsignature_extract(struct mailbox_transaction_context *t,
		      struct mail *mail, const char **signature)
{
	const char *const *signatures;

	signatures = get_mail_headers(mail, tfsignature_hdr);

	if (!signatures || !signatures[0]) {
		if (!tfsignature_nosig_ignore) {
			mail_storage_set_error(t->box->storage,
					       ME(NOTPOSSIBLE)
					       "antispam signature not found");
			return -1;
		} else {
			*signature = NULL;
			return 0;
		}
	}

	while (signatures[1])
		signatures++;

	*signature = signatures[0];

	return 0;
}
static int acl_have_attribute_rights(struct mailbox *box)
{
	int ret;

	/* RFC 5464:

	   When the ACL extension [RFC4314] is present, users can only set and
	   retrieve private or shared mailbox annotations on a mailbox on which
	   they have the "l" right and any one of the "r", "s", "w", "i", or "p"
	   rights.
	*/
	ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_LOOKUP);
	if (ret <= 0) {
		if (ret < 0)
			return -1;
		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
				T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
		return -1;
	}

	if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_READ) > 0)
		return 0;
	if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_SEEN) > 0)
		return 0;
	if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE) > 0)
		return 0;
	if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_INSERT) > 0)
		return 0;
	if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_POST) > 0)
		return 0;
	return -1;
}
Example #6
0
static int
sieve_attribute_set_default(struct mail_storage *storage,
			    struct sieve_storage *svstorage,
			    const struct mail_attribute_value *value)
{
	const unsigned char *data;
	size_t size;
	ssize_t ret;
	char type;

	if (value->value != NULL) {
		type = value->value[0];
	} else if (value->value_stream != NULL) {
		ret = i_stream_read_data(value->value_stream, &data, &size, 0);
		if (ret == -1) {
			mail_storage_set_critical(storage, "read(%s) failed: %m",
				i_stream_get_name(value->value_stream));
			return -1;
		}
		i_assert(ret > 0);
		type = data[0];
	} else {
		type = MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_SCRIPT;
	}
	if (type == MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_LINK)
		return sieve_attribute_set_active(storage, svstorage, value);
	if (type == MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_SCRIPT)
		return sieve_attribute_set_active_script(storage, svstorage, value);
	mail_storage_set_error(storage, MAIL_ERROR_PARAMS,
			       "Invalid value for default sieve attribute");
	return -1;
}
Example #7
0
static int
fts_transaction_commit(struct mailbox_transaction_context *t,
		       struct mail_transaction_commit_changes *changes_r)
{
	struct fts_transaction_context *ft = FTS_CONTEXT(t);
	struct fts_mailbox *fbox = FTS_CONTEXT(t->box);
	struct mailbox *box = t->box;
	bool autoindex;
	int ret = 0;

	autoindex = ft->mails_saved &&
		mail_user_plugin_getenv(box->storage->user,
					"fts_autoindex") != NULL;

	if (fts_transaction_end(t) < 0) {
		mail_storage_set_error(t->box->storage, MAIL_ERROR_TEMP,
				       "FTS transaction commit failed");
		ret = -1;
	}
	if (fbox->module_ctx.super.transaction_commit(t, changes_r) < 0)
		ret = -1;
	if (ret < 0)
		return -1;

	if (autoindex)
		fts_queue_index(box);
	return 0;
}
static int
acl_mailbox_rename(struct mailbox *src, struct mailbox *dest)
{
	struct acl_mailbox *abox = ACL_CONTEXT(src);
	int ret;

	/* renaming requires rights to delete the old mailbox */
	ret = acl_mailbox_right_lookup(src, ACL_STORAGE_RIGHT_DELETE);
	if (ret <= 0) {
		if (ret == 0)
			acl_mailbox_fail_not_found(src);
		return -1;
	}

	/* and create the new one under the parent mailbox */
	T_BEGIN {
		ret = acl_mailbox_list_have_right(dest->list, dest->name, TRUE,
						ACL_STORAGE_RIGHT_CREATE, NULL);
	} T_END;

	if (ret <= 0) {
		if (ret == 0) {
			/* Note that if the mailbox didn't have LOOKUP
			   permission, this now reveals to user the mailbox's
			   existence. Can't help it. */
			mail_storage_set_error(src->storage, MAIL_ERROR_PERM,
					       MAIL_ERRSTR_NO_PERMISSION);
		} else {
			mail_storage_set_internal_error(src->storage);
		}
		return -1;
	}

	return abox->module_ctx.super.rename_box(src, dest);
}
static int
acl_mailbox_create(struct mailbox *box, const struct mailbox_update *update,
		   bool directory)
{
	struct acl_mailbox *abox = ACL_CONTEXT(box);
	int ret;

	/* we're looking up CREATE permission from our parent's rights */
	ret = acl_mailbox_list_have_right(box->list, box->name, TRUE,
					  ACL_STORAGE_RIGHT_CREATE, NULL);
	if (ret <= 0) {
		if (ret < 0) {
			mail_storage_set_internal_error(box->storage);
			return -1;
		}
		/* Note that if user didn't have LOOKUP permission to parent
		   mailbox, this may reveal the mailbox's existence to user.
		   Can't help it. */
		mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
				       MAIL_ERRSTR_NO_PERMISSION);
		return -1;
	}

	/* ignore ACLs in this mailbox until creation is complete, because
	   super.create() may call e.g. mailbox_open() which will fail since
	   we haven't yet copied ACLs to this mailbox. */
	abox->skip_acl_checks = TRUE;
	ret = abox->module_ctx.super.create_box(box, update, directory);
	abox->skip_acl_checks = FALSE;
	if (ret == 0)
		acl_mailbox_copy_acls_from_parent(box);
	return ret;
}
Example #10
0
static int
index_storage_get_dict(struct mailbox *box, enum mail_attribute_type type,
		       struct dict **dict_r, const char **mailbox_prefix_r)
{
	struct mail_storage *storage = box->storage;
	struct mail_namespace *ns;
	struct mailbox_metadata metadata;
	struct dict_settings set;
	const char *error;

	if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0)
		return -1;
	*mailbox_prefix_r = guid_128_to_string(metadata.guid);

	ns = mailbox_get_namespace(box);
	if (type == MAIL_ATTRIBUTE_TYPE_PRIVATE) {
		/* private attributes are stored in user's own dict */
		return index_storage_get_user_dict(storage, storage->user, dict_r);
	} else if (ns->user == ns->owner) {
		/* user owns the mailbox. shared attributes are stored in
		   the same dict. */
		return index_storage_get_user_dict(storage, storage->user, dict_r);
	} else if (ns->owner != NULL) {
		/* accessing shared attribute of a shared mailbox.
		   use the owner's dict. */
		return index_storage_get_user_dict(storage, ns->owner, dict_r);
	}

	/* accessing shared attributes of a public mailbox. no user owns it,
	   so use the storage's dict. */
	if (storage->_shared_attr_dict != NULL) {
		*dict_r = storage->_shared_attr_dict;
		return 0;
	}
	if (*storage->set->mail_attribute_dict == '\0') {
		mail_storage_set_error(storage, MAIL_ERROR_NOTPOSSIBLE,
				       "Mailbox attributes not enabled");
		return -1;
	}
	if (storage->shared_attr_dict_failed) {
		mail_storage_set_internal_error(storage);
		return -1;
	}

	memset(&set, 0, sizeof(set));
	set.username = storage->user->username;
	set.base_dir = storage->user->set->base_dir;
	if (mail_user_get_home(storage->user, &set.home_dir) <= 0)
		set.home_dir = NULL;
	if (dict_init_full(storage->set->mail_attribute_dict, &set,
			   &storage->_shared_attr_dict, &error) < 0) {
		mail_storage_set_critical(storage,
			"mail_attribute_dict: dict_init(%s) failed: %s",
			storage->set->mail_attribute_dict, error);
		storage->shared_attr_dict_failed = TRUE;
		return -1;
	}
	*dict_r = storage->_shared_attr_dict;
	return 0;
}
Example #11
0
static int
mbox_mailbox_create(struct mailbox *box, const struct mailbox_update *update,
		    bool directory)
{
	int fd, ret;

	if (directory &&
	    (box->list->props & MAILBOX_LIST_PROP_NO_NOSELECT) == 0)
		return 0;

	if (box->inbox_any) {
		if (create_inbox(box) < 0)
			return -1;
	} else {
		/* create the mbox file */
		ret = mailbox_create_fd(box, box->path,
					O_RDWR | O_CREAT | O_EXCL, &fd);
		if (ret < 0)
			return -1;
		if (ret == 0) {
			mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
					       "Mailbox already exists");
			return -1;
		}
		(void)close(fd);
	}
	return update == NULL ? 0 : mbox_mailbox_update(box, update);
}
Example #12
0
static int create_inbox(struct mailbox *box)
{
	const char *inbox_path;
	int fd;

	inbox_path = mailbox_get_path(box);

	fd = open(inbox_path, O_RDWR | O_CREAT | O_EXCL, 0660);
	if (fd == -1 && errno == EACCES) {
		/* try again with increased privileges */
		(void)restrict_access_use_priv_gid();
		fd = open(inbox_path, O_RDWR | O_CREAT | O_EXCL, 0660);
		restrict_access_drop_priv_gid();
	}
	if (fd != -1) {
		i_close_fd(&fd);
		return 0;
	} else if (errno == EACCES) {
		mail_storage_set_critical(box->storage, "%s",
			mail_error_create_eacces_msg("open", inbox_path));
		return -1;
	} else if (errno == EEXIST) {
		mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
				       "Mailbox already exists");
		return -1;
	} else {
		mail_storage_set_critical(box->storage,
			"open(%s, O_CREAT) failed: %m", inbox_path);
		return -1;
	}
}
Example #13
0
static int
pop3_migration_get_special(struct mail *_mail, enum mail_fetch_field field,
			   const char **value_r)
{
	struct mail_private *mail = (struct mail_private *)_mail;
	union mail_module_context *mmail = POP3_MIGRATION_MAIL_CONTEXT(mail);
	struct pop3_migration_mailbox *mbox = POP3_MIGRATION_CONTEXT(_mail->box);
	struct imap_msg_map map_key, *map;

	if (field == MAIL_FETCH_UIDL_BACKEND ||
	    field == MAIL_FETCH_POP3_ORDER) {
		if (mbox->uidl_sync_failed ||
		    pop3_migration_uidl_sync(_mail->box) < 0) {
			mbox->uidl_sync_failed = TRUE;
			mail_storage_set_error(_mail->box->storage,
					       MAIL_ERROR_TEMP,
					       "POP3 UIDLs couldn't be synced");
			return -1;
		}

		memset(&map_key, 0, sizeof(map_key));
		map_key.uid = _mail->uid;
		map = array_bsearch(&mbox->imap_msg_map, &map_key,
				    imap_msg_map_uid_cmp);
		if (map != NULL && map->pop3_uidl != NULL) {
			if (field == MAIL_FETCH_UIDL_BACKEND)
				*value_r = map->pop3_uidl;
			else
				*value_r = t_strdup_printf("%u", map->pop3_seq);
			return 0;
		}
		/* not found from POP3 server, fallback to default */
	}
	return mmail->super.get_special(_mail, field, value_r);
}
Example #14
0
static int
sieve_attribute_get_sieve(struct mail_storage *storage, const char *key,
			  struct mail_attribute_value *value_r)
{
	struct sieve_storage *svstorage;
	struct sieve_script *script;
	const char *scriptname, *errstr;
	int ret;

	if ((ret = mail_sieve_user_init(storage->user, &svstorage)) <= 0)
		return ret;

	if (strcmp(key, MAILBOX_ATTRIBUTE_SIEVE_DEFAULT) == 0)
		return sieve_attribute_get_default(storage, svstorage, value_r);
	if (strncmp(key, MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES,
		    strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES)) != 0)
		return 0;
	if ((value_r->flags & MAIL_ATTRIBUTE_VALUE_FLAG_INT_STREAMS) == 0) {
		mail_storage_set_error(storage, MAIL_ERROR_PARAMS,
			"Sieve attributes are available only as streams");
		return -1;
	}
	scriptname = key + strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES);
	script = sieve_storage_open_script(svstorage, scriptname, NULL);
	if ((ret=sieve_attribute_retrieve_script
		(storage, svstorage, script, FALSE, value_r, &errstr)) < 0) {
		mail_storage_set_critical(storage,
			"Failed to access sieve script '%s': %s",
			scriptname, errstr);
	}
	return ret;
}
Example #15
0
static int
mbox_mailbox_create(struct mailbox *box, const struct mailbox_update *update,
		    bool directory)
{
	int fd, ret;

	if ((ret = index_storage_mailbox_create(box, directory)) <= 0)
		return ret;

	if (box->inbox_any) {
		if (create_inbox(box) < 0)
			return -1;
	} else {
		/* create the mbox file */
		ret = mailbox_create_fd(box, mailbox_get_path(box),
					O_RDWR | O_CREAT | O_EXCL, &fd);
		if (ret < 0)
			return -1;
		if (ret == 0) {
			mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
					       "Mailbox already exists");
			return -1;
		}
		i_close_fd(&fd);
	}
	return update == NULL ? 0 : mbox_mailbox_update(box, update);
}
Example #16
0
static int
index_storage_get_user_dict(struct mail_storage *err_storage,
			    struct mail_user *user, struct dict **dict_r)
{
	struct dict_settings dict_set;
	struct mail_namespace *ns;
	struct mail_storage *attr_storage;
	const char *error;

	if (user->_attr_dict != NULL) {
		*dict_r = user->_attr_dict;
		return 0;
	}
	if (user->attr_dict_failed) {
		mail_storage_set_internal_error(err_storage);
		return -1;
	}

	ns = mail_user_find_attribute_namespace(user);
	if (ns == NULL) {
		/* probably never happens? */
		mail_storage_set_error(err_storage, MAIL_ERROR_NOTPOSSIBLE,
			"Mailbox attributes not available for this mailbox");
		return -1;
	}
	attr_storage = mail_namespace_get_default_storage(ns);

	if (*attr_storage->set->mail_attribute_dict == '\0') {
		mail_storage_set_error(err_storage, MAIL_ERROR_NOTPOSSIBLE,
				       "Mailbox attributes not enabled");
		return -1;
	}

	memset(&dict_set, 0, sizeof(dict_set));
	dict_set.username = user->username;
	dict_set.base_dir = user->set->base_dir;
	if (dict_init(attr_storage->set->mail_attribute_dict, &dict_set,
		      &user->_attr_dict, &error) < 0) {
		mail_storage_set_critical(err_storage,
			"mail_attribute_dict: dict_init(%s) failed: %s",
			attr_storage->set->mail_attribute_dict, error);
		user->attr_dict_failed = TRUE;
		return -1;
	}
	*dict_r = user->_attr_dict;
	return 0;
}
Example #17
0
int pop3c_sync_get_uidls(struct pop3c_mailbox *mbox)
{
	ARRAY_TYPE(const_string) uidls;
	struct istream *input;
	const char *error, *cline;
	char *line, *p;
	unsigned int seq, line_seq;

	if (mbox->msg_uidls != NULL)
		return 0;
	if ((pop3c_client_get_capabilities(mbox->client) &
	     POP3C_CAPABILITY_UIDL) == 0) {
		mail_storage_set_error(mbox->box.storage,
				       MAIL_ERROR_NOTPOSSIBLE,
				       "UIDLs not supported by server");
		return -1;
	}

	if (pop3c_client_cmd_stream(mbox->client, "UIDL\r\n",
				    &input, &error) < 0) {
		mail_storage_set_critical(mbox->box.storage,
					  "UIDL failed: %s", error);
		return -1;
	}

	mbox->uidl_pool = pool_alloconly_create("POP3 UIDLs", 1024*32);
	p_array_init(&uidls, mbox->uidl_pool, 64); seq = 0;
	while ((line = i_stream_read_next_line(input)) != NULL) {
		seq++;
		p = strchr(line, ' ');
		if (p == NULL) {
			mail_storage_set_critical(mbox->box.storage,
				"Invalid UIDL line: %s", line);
			break;
		}
		*p++ = '\0';
		if (str_to_uint(line, &line_seq) < 0 || line_seq != seq) {
			mail_storage_set_critical(mbox->box.storage,
				"Unexpected UIDL seq: %s != %u", line, seq);
			break;
		}

		cline = p_strdup(mbox->uidl_pool, p);
		array_append(&uidls, &cline, 1);
	}
	i_stream_destroy(&input);
	if (line != NULL) {
		pool_unref(&mbox->uidl_pool);
		return -1;
	}
	if (seq == 0) {
		/* make msg_uidls non-NULL */
		array_append_zero(&uidls);
	}
	mbox->msg_uidls = array_idx(&uidls, 0);
	mbox->msg_count = seq;
	return 0;
}
Example #18
0
static int maildir_create_tmp(struct maildir_mailbox *mbox, const char *dir,
			      const char **fname_r)
{
	struct mailbox *box = &mbox->box;
	const struct mailbox_permissions *perm = mailbox_get_permissions(box);
	unsigned int prefix_len;
	const char *tmp_fname;
	string_t *path;
	mode_t old_mask;
	int fd;

	path = t_str_new(256);
	str_append(path, dir);
	str_append_c(path, '/');
	prefix_len = str_len(path);

	do {
		tmp_fname = maildir_filename_generate();
		str_truncate(path, prefix_len);
		str_append(path, tmp_fname);

		/* the generated filename is unique. the only reason why it
		   might return an existing filename is if the time moved
		   backwards. so we'll use O_EXCL anyway, although it's mostly
		   useless. */
		old_mask = umask(0777 & ~perm->file_create_mode);
		fd = open(str_c(path),
			  O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0777);
		umask(old_mask);
	} while (fd == -1 && errno == EEXIST);

	*fname_r = tmp_fname;
	if (fd == -1) {
		if (ENOQUOTA(errno)) {
			mail_storage_set_error(box->storage,
				MAIL_ERROR_NOQUOTA, MAIL_ERRSTR_NO_QUOTA);
		} else {
			mail_storage_set_critical(box->storage,
				"open(%s) failed: %m", str_c(path));
		}
	} else if (perm->file_create_gid != (gid_t)-1) {
		if (fchown(fd, (uid_t)-1, perm->file_create_gid) < 0) {
			if (errno == EPERM) {
				mail_storage_set_critical(box->storage, "%s",
					eperm_error_get_chgrp("fchown",
						str_c(path),
						perm->file_create_gid,
						perm->file_create_gid_origin));
			} else {
				mail_storage_set_critical(box->storage,
					"fchown(%s) failed: %m", str_c(path));
			}
		}
	}

	return fd;
}
static int acl_attribute_get_acl(struct mailbox *box, const char *key,
				 struct mail_attribute_value *value_r)
{
	struct acl_object *aclobj = acl_mailbox_get_aclobj(box);
	struct acl_object_list_iter *iter;
	struct acl_rights rights, wanted_rights;
	const char *id;
	int ret;

	memset(value_r, 0, sizeof(*value_r));

	if (!box->storage->user->dsyncing) {
		mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
				       MAIL_ERRSTR_NO_PERMISSION);
		return -1;
	}
	/* set last_change for all ACL objects, even if they don't exist
	   (because they could have been removed by the last change, and dsync
	   can use this information) */
	(void)acl_object_last_changed(aclobj, &value_r->last_change);

	memset(&wanted_rights, 0, sizeof(wanted_rights));
	id = key + strlen(MAILBOX_ATTRIBUTE_PREFIX_ACL);
	if (acl_identifier_parse(id, &wanted_rights) < 0) {
		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
				       t_strdup_printf("Invalid ID: %s", id));
		return -1;
	}

	iter = acl_object_list_init(aclobj);
	while ((ret = acl_object_list_next(iter, &rights)) > 0) {
		if (!rights.global &&
		    rights.id_type == wanted_rights.id_type &&
		    null_strcmp(rights.identifier, wanted_rights.identifier) == 0) {
			value_r->value = acl_rights_export(&rights);
			break;
		}
	}
	if (ret < 0)
		mail_storage_set_internal_error(box->storage);
	acl_object_list_deinit(&iter);
	return ret;
}
Example #20
0
static int
mbox_mailbox_get_guid(struct mbox_mailbox *mbox, guid_128_t guid_r)
{
	const char *errstr;

	if (mail_index_is_in_memory(mbox->box.index)) {
		errstr = "Mailbox GUIDs are not permanent without index files";
		if (mbox->storage->set->mbox_min_index_size != 0) {
			errstr = t_strconcat(errstr,
				" (mbox_min_index_size is non-zero)", NULL);
		}
		mail_storage_set_error(mbox->box.storage,
				       MAIL_ERROR_NOTPOSSIBLE, errstr);
		return -1;
	}
	if (mbox_sync_header_refresh(mbox) < 0)
		return -1;

	if (!guid_128_is_empty(mbox->mbox_hdr.mailbox_guid)) {
		/* we have the GUID */
	} else if (mbox_file_open(mbox) < 0)
		return -1;
	else if (mbox->backend_readonly) {
		mail_storage_set_error(mbox->box.storage, MAIL_ERROR_PERM,
			"Can't set mailbox GUID to a read-only mailbox");
		return -1;
	} else {
		/* create another mailbox and sync  */
		struct mailbox *box2;
		struct mbox_mailbox *mbox2;
		int ret;

		i_assert(mbox->mbox_lock_type == F_UNLCK);
		box2 = mailbox_alloc(mbox->box.list, mbox->box.vname, 0);
		ret = mailbox_sync(box2, 0);
		mbox2 = (struct mbox_mailbox *)box2;
		memcpy(guid_r, mbox2->mbox_hdr.mailbox_guid, GUID_128_SIZE);
		mailbox_free(&box2);
		return ret;
	}
	memcpy(guid_r, mbox->mbox_hdr.mailbox_guid, GUID_128_SIZE);
	return 0;
}
Example #21
0
void virtual_box_copy_error(struct mailbox *dest, struct mailbox *src)
{
	const char *name, *str;
	enum mail_error error;

	name = get_user_visible_mailbox_name(src);
	str = mail_storage_get_last_error(src->storage, &error);

	str = t_strdup_printf("%s (for backend mailbox %s)", str, name);
	mail_storage_set_error(dest->storage, error, str);
}
Example #22
0
static int
pop3c_mail_get_stream(struct mail *_mail, bool get_body,
		      struct message_size *hdr_size,
		      struct message_size *body_size, struct istream **stream_r)
{
	struct index_mail *mail = (struct index_mail *)_mail;
	struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
	enum pop3c_capability capa;
	const char *name, *cmd, *error;
	struct istream *input;

	if (get_body && mail->data.stream != NULL) {
		name = i_stream_get_name(mail->data.stream);
		if (strncmp(name, "RETR", 4) == 0) {
			/* we've fetched the body */
		} else if (strncmp(name, "TOP", 3) == 0) {
			/* we've fetched the header, but we need the body
			   now too */
			index_mail_close_streams(mail);
		} else {
			i_panic("Unexpected POP3 stream name: %s", name);
		}
	}

	if (mail->data.stream == NULL) {
		capa = pop3c_client_get_capabilities(mbox->client);
		if (get_body || (capa & POP3C_CAPABILITY_TOP) == 0) {
			cmd = t_strdup_printf("RETR %u\r\n", _mail->seq);
			get_body = TRUE;
		} else {
			cmd = t_strdup_printf("TOP %u 0\r\n", _mail->seq);
		}
		if (pop3c_client_cmd_stream(mbox->client, cmd,
					    &input, &error) < 0) {
			mail_storage_set_error(mbox->box.storage,
				!pop3c_client_is_connected(mbox->client) ?
				MAIL_ERROR_TEMP : MAIL_ERROR_EXPUNGED, error);
			return -1;
		}
		mail->data.stream = input;
		if (mail->mail.v.istream_opened != NULL) {
			if (mail->mail.v.istream_opened(_mail,
							&mail->data.stream) < 0) {
				index_mail_close_streams(mail);
				return -1;
			}
		}
		i_stream_set_name(mail->data.stream, t_strcut(cmd, '\r'));
		if (get_body)
			pop3c_mail_cache_size(mail);
	}
	return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
}
Example #23
0
static void
mail_copy_set_failed(struct mail_save_context *ctx, struct mail *mail,
		     const char *func)
{
	const char *errstr;
	enum mail_error error;

	if (ctx->transaction->box->storage == mail->box->storage)
		return;

	errstr = mail_storage_get_last_error(mail->box->storage, &error);
	mail_storage_set_error(ctx->transaction->box->storage, error,
			       t_strdup_printf("%s (%s)", errstr, func));
}
Example #24
0
void mbox_set_syscall_error(struct mbox_mailbox *mbox, const char *function)
{
	i_assert(function != NULL);

	if (ENOQUOTA(errno)) {
		mail_storage_set_error(&mbox->storage->storage,
			MAIL_ERROR_NOQUOTA, MAIL_ERRSTR_NO_QUOTA);
	} else {
		const char *toobig_error = errno != EFBIG ? "" :
			" (process was started with ulimit -f limit)";
		mailbox_set_critical(&mbox->box,
			"%s failed with mbox: %m%s", function, toobig_error);
	}
}
Example #25
0
int mailbox_keywords_create(struct mailbox *box, const char *const keywords[],
			    struct mail_keywords **keywords_r)
{
	const char *error, *empty_keyword_list = NULL;

	i_assert(box->opened);

	if (keywords == NULL)
		keywords = &empty_keyword_list;
	if (!mailbox_keywords_are_valid(box, keywords, &error)) {
		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS, error);
		return -1;
	}

	*keywords_r = mail_index_keywords_create(box->index, keywords);
	return 0;
}
Example #26
0
static int
mbox_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
{
	struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;

	if (mail_index_is_in_memory(box->index)) {
		mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
			"Mailbox GUIDs are not permanent without index files");
		return -1;
	}
	if (mail_guid_128_is_empty(mbox->mbox_hdr.mailbox_guid)) {
		if (mailbox_sync(&mbox->box, 0) < 0)
			return -1;
	}
	memcpy(guid, mbox->mbox_hdr.mailbox_guid, MAIL_GUID_128_SIZE);
	return 0;
}
Example #27
0
int mbox_set_syscall_error(struct mbox_mailbox *mbox, const char *function)
{
	i_assert(function != NULL);

	if (ENOSPACE(errno)) {
		mail_storage_set_error(&mbox->storage->storage,
			MAIL_ERROR_NOSPACE, MAIL_ERRSTR_NO_SPACE);
	} else {
		const char *toobig_error = errno != EFBIG ? "" :
			" (process was started with ulimit -f limit)";
		mail_storage_set_critical(&mbox->storage->storage,
					  "%s failed with mbox file %s: %m%s",
					  function, mbox->box.path,
					  toobig_error);
	}
	return -1;
}
Example #28
0
static void
index_sort_program_set_mail_failed(struct mail_search_sort_program *program,
				   struct mail *mail)
{
	switch (mailbox_get_last_mail_error(mail->box)) {
	case MAIL_ERROR_EXPUNGED:
		break;
	case MAIL_ERROR_LOOKUP_ABORTED:
		/* just change the error message */
		i_assert(program->slow_mails_left == 0);
		mail_storage_set_error(program->t->box->storage, MAIL_ERROR_LIMIT,
			"Requested sort would have taken too long.");
		/* fall through */
	default:
		program->failed = TRUE;
		break;
	}
}
Example #29
0
int mbox_file_seek(struct mbox_mailbox *mbox, struct mail_index_view *view,
		   uint32_t seq, bool *deleted_r)
{
	uoff_t offset;
	int ret;

	ret = mbox_file_lookup_offset(mbox, view, seq, &offset);
	if (ret <= 0) {
		*deleted_r = ret < 0;
		return ret;
	}
	*deleted_r = FALSE;

	if (istream_raw_mbox_seek(mbox->mbox_stream, offset) < 0) {
		if (offset == 0) {
			mbox->invalid_mbox_file = TRUE;
			mail_storage_set_error(&mbox->storage->storage,
				MAIL_ERROR_NOTPOSSIBLE,
				"Mailbox isn't a valid mbox file");
			return -1;
		}

		if (mbox->mbox_hdr.dirty_flag != 0)
			return 0;

		mail_storage_set_critical(&mbox->storage->storage,
			"Cached message offset %s is invalid for mbox file %s",
			dec2str(offset), mailbox_get_path(&mbox->box));
		mbox->mbox_hdr.dirty_flag = 1;
		mbox->mbox_broken_offsets = TRUE;
		return 0;
	}

	if (mbox->mbox_hdr.dirty_flag != 0) {
		/* we're dirty - make sure this is the correct mail */
		if (!mbox_sync_parse_match_mail(mbox, view, seq))
			return 0;

		ret = istream_raw_mbox_seek(mbox->mbox_stream, offset);
		i_assert(ret == 0);
	}

	return 1;
}
Example #30
0
static int zlib_mail_save_finish(struct mail_save_context *ctx)
{
	struct mailbox *box = ctx->transaction->box;
	union mailbox_module_context *zbox = ZLIB_CONTEXT(box);
	struct istream *input;

	if (zbox->super.save_finish(ctx) < 0)
		return -1;

	if (mail_get_stream(ctx->dest_mail, NULL, NULL, &input) < 0)
		return -1;

	if (compression_detect_handler(input) != NULL) {
		mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
			"Saving mails compressed by client isn't supported");
		return -1;
	}
	return 0;
}