Esempio n. 1
0
static int
imap_master_client_parse_input(const char *const *args, pool_t pool,
			       struct mail_storage_service_input *input_r,
			       struct imap_master_input *master_input_r,
			       const char **error_r)
{
	const char *key, *value;
	unsigned int peer_dev_major = 0, peer_dev_minor = 0;

	i_zero(input_r);
	i_zero(master_input_r);
	master_input_r->client_input = buffer_create_dynamic(pool, 64);
	master_input_r->client_output = buffer_create_dynamic(pool, 16);
	master_input_r->state = buffer_create_dynamic(pool, 512);

	input_r->module = input_r->service = "imap";
	/* we never want to do userdb lookup again when restoring the client.
	   we have the userdb_fields cached already. */
	input_r->flags_override_remove = MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;

	if (args[0] == NULL) {
		*error_r = "Missing username in input";
		return -1;
	}
	input_r->username = args[0];

	for (args++; *args != NULL; args++) {
		value = strchr(*args, '=');
		if (value != NULL)
			key = t_strdup_until(*args, value++);
		else {
			key = *args;
			value = "";
		}
		if (strcmp(key, "lip") == 0) {
			if (net_addr2ip(value, &input_r->local_ip) < 0) {
				*error_r = t_strdup_printf(
					"Invalid lip value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "rip") == 0) {
			if (net_addr2ip(value, &input_r->remote_ip) < 0) {
				*error_r = t_strdup_printf(
					"Invalid rip value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "peer_dev_major") == 0) {
			if (str_to_uint(value, &peer_dev_major) < 0) {
				*error_r = t_strdup_printf(
					"Invalid peer_dev_major value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "peer_dev_minor") == 0) {
			if (str_to_uint(value, &peer_dev_minor) < 0) {
				*error_r = t_strdup_printf(
					"Invalid peer_dev_minor value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "peer_ino") == 0) {
			if (str_to_ino(value, &master_input_r->peer_ino) < 0) {
				*error_r = t_strdup_printf(
					"Invalid peer_ino value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "session") == 0) {
			input_r->session_id = value;
		} else if (strcmp(key, "session_created") == 0) {
			if (str_to_time(value, &input_r->session_create_time) < 0) {
				*error_r = t_strdup_printf(
					"Invalid session_created value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "userdb_fields") == 0) {
			input_r->userdb_fields =
				t_strsplit_tabescaped(value);
		} else if (strcmp(key, "client_input") == 0) {
			if (base64_decode(value, strlen(value), NULL,
					  master_input_r->client_input) < 0) {
				*error_r = t_strdup_printf(
					"Invalid client_input base64 value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "client_output") == 0) {
			if (base64_decode(value, strlen(value), NULL,
					  master_input_r->client_output) < 0) {
				*error_r = t_strdup_printf(
					"Invalid client_output base64 value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "state") == 0) {
			if (base64_decode(value, strlen(value), NULL,
					  master_input_r->state) < 0) {
				*error_r = t_strdup_printf(
					"Invalid state base64 value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "tag") == 0) {
			master_input_r->tag = t_strdup(value);
		} else if (strcmp(key, "bad-done") == 0) {
			master_input_r->state_import_bad_idle_done = TRUE;
		} else if (strcmp(key, "idle-continue") == 0) {
			master_input_r->state_import_idle_continue = TRUE;
		}
	}
	if (peer_dev_major != 0 || peer_dev_minor != 0) {
		master_input_r->peer_dev =
			makedev(peer_dev_major, peer_dev_minor);
	}
	return 0;
}
Esempio n. 2
0
static uint32_t
mailbox_uidvalidity_next_rescan(struct mailbox_list *list, const char *path)
{
	DIR *d;
	struct dirent *dp;
	const char *fname, *dir, *prefix, *tmp;
	char *endp;
	unsigned int i, prefix_len;
	uint32_t cur_value, min_value, max_value;
	mode_t old_mask;
	int fd;

	fname = strrchr(path, '/');
	if (fname == NULL) {
		dir = ".";
		fname = path;
	} else {
		dir = t_strdup_until(path, fname);
		fname++;
	}

	d = opendir(dir);
	if (d == NULL) {
		i_error("opendir(%s) failed: %m", dir);
		return mailbox_uidvalidity_next_fallback();
	}
	prefix = t_strconcat(fname, ".", NULL);
	prefix_len = strlen(prefix);

	/* just in case there happens to be multiple matching uidvalidity
	   files, track the min/max values. use the max value and delete the
	   min value file. */
	max_value = 0; min_value = (uint32_t)-1;
	while ((dp = readdir(d)) != NULL) {
		if (strncmp(dp->d_name, prefix, prefix_len) == 0) {
			cur_value = strtoul(dp->d_name + prefix_len, &endp, 16);
			if (*endp == '\0') {
				if (min_value > cur_value)
					min_value = cur_value;
				if (max_value < cur_value)
					max_value = cur_value;
			}
		}
	}
	if (closedir(d) < 0)
		i_error("closedir(%s) failed: %m", dir);

	if (max_value == 0) {
		/* no uidvalidity files. create one. */
		for (i = 0; i < RETRY_COUNT; i++) {
			cur_value = mailbox_uidvalidity_next_fallback();
			tmp = t_strdup_printf("%s.%08x", path, cur_value);
			/* the file is empty, don't bother with permissions */
			old_mask = umask(0);
			fd = open(tmp, O_RDWR | O_CREAT | O_EXCL, 0444);
			umask(old_mask);
			if (fd != -1 || errno != EEXIST)
				break;
			/* already exists. although it's quite unlikely we'll
			   hit this race condition. more likely we'll create
			   a duplicate file.. */
		}
		if (fd == -1) {
			i_error("creat(%s) failed: %m", tmp);
			return cur_value;
		}
		i_close_fd(&fd);
		mailbox_uidvalidity_write(list, path, cur_value);
		return cur_value;
	}
	if (min_value != max_value) {
		/* duplicate uidvalidity files, delete the oldest */
		tmp = t_strdup_printf("%s.%08x", path, min_value);
		if (unlink(tmp) < 0 && errno != ENOENT)
			i_error("unlink(%s) failed: %m", tmp);
	}

	cur_value = max_value;
	if (mailbox_uidvalidity_rename(path, &cur_value, TRUE) < 0)
		return mailbox_uidvalidity_next_fallback();
	mailbox_uidvalidity_write(list, path, cur_value);
	return cur_value;
}
Esempio n. 3
0
		uint64_t *value_r ATTR_UNUSED, uint64_t *limit_r ATTR_UNUSED)
{
#if defined(EXT_RQUOTAVERS) && defined(GRPQUOTA)
	struct getquota_rslt result;
	ext_getquota_args args;
	struct timeval timeout;
	enum clnt_stat call_status;
	CLIENT *cl;
	struct fs_quota_mountpoint *mount = root->mount;
	const char *host;
	char *path;

	path = strchr(mount->device_path, ':');
	i_assert(path != NULL);

	host = t_strdup_until(mount->device_path, path);
	path++;

	if (root->root.quota->set->debug) {
		i_debug("quota-fs: host=%s, path=%s, gid=%s, %s",
			host, path, dec2str(root->gid),
			bytes ? "bytes" : "files");
	}

	/* clnt_create() polls for a while to establish a connection */
	cl = clnt_create(host, RQUOTAPROG, EXT_RQUOTAVERS, "udp");
	if (cl == NULL) {
		i_error("quota-fs: could not contact RPC service on %s (group)",
			host);
		return -1;
	}
Esempio n. 4
0
static int do_rquota_user(struct fs_quota_root *root, bool bytes,
			  uint64_t *value_r, uint64_t *limit_r)
{
	struct getquota_rslt result;
	struct getquota_args args;
	struct timeval timeout;
	enum clnt_stat call_status;
	CLIENT *cl;
	struct fs_quota_mountpoint *mount = root->mount;
	const char *host;
	char *path;

	path = strchr(mount->device_path, ':');
	i_assert(path != NULL);

	host = t_strdup_until(mount->device_path, path);
	path++;

	/* For NFSv4, we send the filesystem path without initial /. Server
	   prepends proper NFS pseudoroot automatically and uses this for
	   detection of NFSv4 mounts. */
	if (strcmp(root->mount->type, "nfs4") == 0) {
		while (*path == '/')
			path++;
	}

	if (root->root.quota->set->debug) {
		i_debug("quota-fs: host=%s, path=%s, uid=%s, %s",
			host, path, dec2str(root->uid),
			bytes ? "bytes" : "files");
	}

	/* clnt_create() polls for a while to establish a connection */
	cl = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp");
	if (cl == NULL) {
		i_error("quota-fs: could not contact RPC service on %s",
			host);
		return -1;
	}

	/* Establish some RPC credentials */
	auth_destroy(cl->cl_auth);
	cl->cl_auth = authunix_create_default();

	/* make the rquota call on the remote host */
	args.gqa_pathp = path;
	args.gqa_uid = root->uid;

	timeout.tv_sec = RQUOTA_GETQUOTA_TIMEOUT_SECS;
	timeout.tv_usec = 0;
	call_status = clnt_call(cl, RQUOTAPROC_GETQUOTA,
				(xdrproc_t)xdr_getquota_args, (char *)&args,
				(xdrproc_t)xdr_getquota_rslt, (char *)&result,
				timeout);
	
	/* the result has been deserialized, let the client go */
	auth_destroy(cl->cl_auth);
	clnt_destroy(cl);

	if (call_status != RPC_SUCCESS) {
		const char *rpc_error_msg = clnt_sperrno(call_status);

		i_error("quota-fs: remote rquota call failed: %s",
			rpc_error_msg);
		return -1;
	}

	switch (result.status) {
	case Q_OK: {
		rquota_get_result(&result.getquota_rslt_u.gqr_rquota, bytes,
				  value_r, limit_r);
		if (root->root.quota->set->debug) {
			i_debug("quota-fs: uid=%s, value=%llu, limit=%llu",
				dec2str(root->uid),
				(unsigned long long)*value_r,
				(unsigned long long)*limit_r);
		}
		return 1;
	}
	case Q_NOQUOTA:
		if (root->root.quota->set->debug) {
			i_debug("quota-fs: uid=%s, limit=unlimited",
				dec2str(root->uid));
		}
		return 1;
	case Q_EPERM:
		i_error("quota-fs: permission denied to rquota service");
		return -1;
	default:
		i_error("quota-fs: unrecognized status code (%d) "
			"from rquota service", result.status);
		return -1;
	}
}
Esempio n. 5
0
static int
shared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
		      const char **error_r)
{
	struct shared_storage *storage = (struct shared_storage *)_storage;
	struct mail_storage *storage_class;
	const char *driver, *p;
	char *wildcardp, key;
	bool have_username;

	/* location must begin with the actual mailbox driver */
	p = strchr(ns->set->location, ':');
	if (p == NULL) {
		*error_r = "Shared mailbox location not prefixed with driver";
		return -1;
	}
	driver = t_strdup_until(ns->set->location, p);
	storage->location = p_strdup(_storage->pool, ns->set->location);
	storage->unexpanded_location =
		p_strdup(_storage->pool, ns->unexpanded_set->location);
	storage->storage_class_name = p_strdup(_storage->pool, driver);

	storage_class = mail_user_get_storage_class(_storage->user, driver);
	if (storage_class != NULL)
		_storage->class_flags = storage_class->class_flags;
	else if (strcmp(driver, "auto") != 0) {
		*error_r = t_strconcat("Unknown shared storage driver: ",
				       driver, NULL);
		return -1;
	}

	wildcardp = strchr(ns->prefix, '%');
	if (wildcardp == NULL) {
		*error_r = "Shared namespace prefix doesn't contain %";
		return -1;
	}
	storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);

	have_username = FALSE;
	for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
		if (*p != '%')
			continue;

		key = p[1];
		if (key == 'u' || key == 'n')
			have_username = TRUE;
		else if (key != '%' && key != 'd')
			break;
	}
	if (*p != '\0') {
		*error_r = "Shared namespace prefix contains unknown variables";
		return -1;
	}
	if (!have_username) {
		*error_r = "Shared namespace prefix doesn't contain %u or %n";
		return -1;
	}
	if (p[-1] != mail_namespace_get_sep(ns) &&
	    (ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
			  NAMESPACE_FLAG_LIST_CHILDREN)) != 0) {
		*error_r = "Shared namespace prefix doesn't end with hierarchy separator";
		return -1;
	}

	/* truncate prefix after the above checks are done, so they can log
	   the full prefix in error conditions */
	*wildcardp = '\0';
	ns->prefix_len = strlen(ns->prefix);
	return 0;
}
Esempio n. 6
0
static void lmtp_address_translate(struct client *client, const char **address)
{
	const char *transpos = client->lmtp_set->lmtp_address_translate;
	const char *p, *nextstr, *addrpos = *address;
	unsigned int len;
	string_t *username, *domain, *dest = NULL;

	if (*transpos == '\0')
		return;

	username = t_str_new(64);
	domain = t_str_new(64);

	/* check that string matches up to the first '%' */
	p = strchr(transpos, '%');
	if (p == NULL)
		len = strlen(transpos);
	else
		len = p-transpos;
	if (strncmp(transpos, addrpos, len) != 0)
		return;
	transpos += len;
	addrpos += len;

	while (*transpos != '\0') {
		switch (transpos[1]) {
		case 'n':
		case 'u':
			dest = username;
			break;
		case 'd':
			dest = domain;
			break;
		default:
			return;
		}
		transpos += 2;

		/* find where the next string starts */
		if (*transpos == '\0') {
			str_append(dest, addrpos);
			break;
		}
		p = strchr(transpos, '%');
		if (p == NULL)
			nextstr = transpos;
		else
			nextstr = t_strdup_until(transpos, p);
		p = strstr(addrpos, nextstr);
		if (p == NULL)
			return;
		str_append_n(dest, addrpos, p-addrpos);

		len = strlen(nextstr);
		transpos += len;
		addrpos = p + len;
	}
	str_append_c(username, '@');
	if (domain != NULL)
		str_append_str(username, domain);
	*address = str_c(username);
}
Esempio n. 7
0
static int
imap_hibernate_client_parse_input(const char *const *args, pool_t pool,
				  struct imap_client_state *state_r,
				  const char **error_r)
{
	const char *key, *value;
	unsigned int peer_dev_major = 0, peer_dev_minor = 0;

	memset(state_r, 0, sizeof(*state_r));
	if (args[0] == NULL) {
		*error_r = "Missing username in input";
		return -1;
	}
	state_r->username = args[0]; args++;
	if (args[0] == NULL) {
		*error_r = "Missing mail_log_prefix in input";
		return -1;
	}
	state_r->mail_log_prefix = args[0]; args++;

	for (; *args != NULL; args++) {
		value = strchr(*args, '=');
		if (value != NULL)
			key = t_strdup_until(*args, value++);
		else {
			key = *args;
			value = "";
		}
		if (strcmp(key, "lip") == 0) {
			if (net_addr2ip(value, &state_r->local_ip) < 0) {
				*error_r = t_strdup_printf(
					"Invalid lip value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "rip") == 0) {
			if (net_addr2ip(value, &state_r->remote_ip) < 0) {
				*error_r = t_strdup_printf(
					"Invalid rip value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "peer_dev_major") == 0) {
			if (str_to_uint(value, &peer_dev_major) < 0) {
				*error_r = t_strdup_printf(
					"Invalid peer_dev_major value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "peer_dev_minor") == 0) {
			if (str_to_uint(value, &peer_dev_minor) < 0) {
				*error_r = t_strdup_printf(
					"Invalid peer_dev_minor value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "peer_ino") == 0) {
			if (str_to_ino(value, &state_r->peer_ino) < 0) {
				*error_r = t_strdup_printf(
					"Invalid peer_ino value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "uid") == 0) {
			if (str_to_uid(value, &state_r->uid) < 0) {
				*error_r = t_strdup_printf(
					"Invalid uid value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "gid") == 0) {
			if (str_to_gid(value, &state_r->gid) < 0) {
				*error_r = t_strdup_printf(
					"Invalid gid value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "stats") == 0) {
			state_r->stats = value;
		} else if (strcmp(key, "idle-cmd") == 0) {
			state_r->idle_cmd = TRUE;
		} else if (strcmp(key, "session") == 0) {
			state_r->session_id = value;
		} else if (strcmp(key, "session_created") == 0) {
			if (str_to_time(value, &state_r->session_created) < 0) {
				*error_r = t_strdup_printf(
					"Invalid session_created value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "userdb_fields") == 0) {
			state_r->userdb_fields = value;
		} else if (strcmp(key, "notify_fd") == 0) {
			state_r->have_notify_fd = TRUE;
		} else if (strcmp(key, "idle_notify_interval") == 0) {
			if (str_to_uint(value, &state_r->imap_idle_notify_interval) < 0) {
				*error_r = t_strdup_printf(
					"Invalid idle_notify_interval value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "tag") == 0) {
			state_r->tag = i_strdup(value);
		} else if (strcmp(key, "state") == 0) {
			buffer_t *state_buf;

			state_buf = buffer_create_dynamic(pool, 1024);
			if (base64_decode(value, strlen(value), NULL,
					  state_buf) < 0) {
				*error_r = t_strdup_printf(
					"Invalid state base64 value: %s", value);
				return -1;
			}
			state_r->state = state_buf->data;
			state_r->state_size = state_buf->used;
		}
	}
	if (state_r->tag == NULL) {
		*error_r = "Missing tag";
		return -1;
	}
	if (peer_dev_major != 0 || peer_dev_minor != 0)
		state_r->peer_dev = makedev(peer_dev_major, peer_dev_minor);
	return 0;
}
Esempio n. 8
0
int dbox_file_fix(struct dbox_file *file, uoff_t start_offset)
{
	struct ostream *output;
	const char *dir, *p, *temp_path, *broken_path;
	bool deleted;
	int fd, ret;

	i_assert(dbox_file_is_open(file));

	p = strrchr(file->cur_path, '/');
	i_assert(p != NULL);
	dir = t_strdup_until(file->cur_path, p);

	temp_path = t_strdup_printf("%s/%s", dir, dbox_generate_tmp_filename());
	fd = file->storage->v.file_create_fd(file, temp_path, FALSE);
	if (fd == -1)
		return -1;

	output = o_stream_create_fd_file(fd, 0, FALSE);
	ret = dbox_file_fix_write_stream(file, start_offset, temp_path, output);
	o_stream_unref(&output);
	if (close(fd) < 0) {
		mail_storage_set_critical(&file->storage->storage,
					  "close(%s) failed: %m", temp_path);
		ret = -1;
	}
	if (ret < 0) {
		if (unlink(temp_path) < 0) {
			mail_storage_set_critical(&file->storage->storage,
				"unlink(%s) failed: %m", temp_path);
		}
		return -1;
	}
	/* keep a copy of the original file in case someone wants to look
	   at it */
	broken_path = t_strconcat(file->cur_path,
				  DBOX_MAIL_FILE_BROKEN_COPY_SUFFIX, NULL);
	if (link(file->cur_path, broken_path) < 0) {
		mail_storage_set_critical(&file->storage->storage,
					  "link(%s, %s) failed: %m",
					  file->cur_path, broken_path);
	} else {
		i_warning("dbox: Copy of the broken file saved to %s",
			  broken_path);
	}
	if (rename(temp_path, file->cur_path) < 0) {
		mail_storage_set_critical(&file->storage->storage,
					  "rename(%s, %s) failed: %m",
					  temp_path, file->cur_path);
		return -1;
	}

	/* file was successfully recreated - reopen it */
	dbox_file_close(file);
	if (dbox_file_open(file, &deleted) <= 0) {
		mail_storage_set_critical(&file->storage->storage,
			"dbox_file_fix(%s): reopening file failed",
			file->cur_path);
		return -1;
	}
	return 0;
}
Esempio n. 9
0
static void client_auth_parse_args(struct client *client,
				   const char *const *args,
				   struct client_auth_reply *reply_r)
{
	const char *key, *value, *p;

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

	for (; *args != NULL; args++) {
		p = strchr(*args, '=');
		if (p == NULL) {
			key = *args;
			value = "";
		} else {
			key = t_strdup_until(*args, p);
			value = p + 1;
		}
		if (strcmp(key, "nologin") == 0)
			reply_r->nologin = TRUE;
		else if (strcmp(key, "proxy") == 0)
			reply_r->proxy = TRUE;
		else if (strcmp(key, "temp") == 0)
			reply_r->temp = TRUE;
		else if (strcmp(key, "authz") == 0)
			reply_r->authz_failure = TRUE;
		else if (strcmp(key, "user_disabled") == 0)
			client->auth_user_disabled = TRUE;
		else if (strcmp(key, "pass_expired") == 0)
			client->auth_pass_expired = TRUE;
		else if (strcmp(key, "reason") == 0)
			reply_r->reason = value;
		else if (strcmp(key, "host") == 0)
			reply_r->host = value;
		else if (strcmp(key, "hostip") == 0)
			reply_r->hostip = value;
		else if (strcmp(key, "source_ip") == 0)
			reply_r->source_ip = value;
		else if (strcmp(key, "port") == 0) {
			if (net_str2port(value, &reply_r->port) < 0) {
				i_error("Auth service returned invalid "
					"port number: %s", value);
			}
		} else if (strcmp(key, "destuser") == 0)
			reply_r->destuser = value;
		else if (strcmp(key, "pass") == 0)
			reply_r->password = value;
		else if (strcmp(key, "proxy_timeout") == 0) {
			if (str_to_uint(value, &reply_r->proxy_timeout_msecs) < 0) {
				i_error("BUG: Auth service returned invalid "
					"proxy_timeout value: %s", value);
			}
			reply_r->proxy_timeout_msecs *= 1000;
		} else if (strcmp(key, "proxy_refresh") == 0) {
			if (str_to_uint(value, &reply_r->proxy_refresh_secs) < 0) {
				i_error("BUG: Auth service returned invalid "
					"proxy_refresh value: %s", value);
			}
		} else if (strcmp(key, "proxy_mech") == 0)
			reply_r->proxy_mech = value;
		else if (strcmp(key, "proxy_nopipelining") == 0)
			reply_r->proxy_nopipelining = TRUE;
		else if (strcmp(key, "master") == 0)
			reply_r->master_user = value;
		else if (strcmp(key, "ssl") == 0) {
			reply_r->ssl_flags |= PROXY_SSL_FLAG_YES;
			if (strcmp(value, "any-cert") == 0)
				reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
			if (reply_r->port == 0)
				reply_r->port = login_binary->default_ssl_port;
		} else if (strcmp(key, "starttls") == 0) {
			reply_r->ssl_flags |= PROXY_SSL_FLAG_YES |
				PROXY_SSL_FLAG_STARTTLS;
			if (strcmp(value, "any-cert") == 0)
				reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
		} else if (strcmp(key, "user") == 0 ||
			   strcmp(key, "postlogin_socket") == 0) {
			/* already handled in sasl-server.c */
		} else if (client->set->auth_debug)
			i_debug("Ignoring unknown passdb extra field: %s", key);
	}
	if (reply_r->port == 0)
		reply_r->port = login_binary->default_port;

	if (reply_r->destuser == NULL)
		reply_r->destuser = client->virtual_user;
}
Esempio n. 10
0
static int ATTR_NULL(2) ATTR_NOWARN_UNUSED_RESULT
mbox_dotlock_privileged_op(struct mbox_mailbox *mbox,
                           struct dotlock_settings *set,
                           enum mbox_dotlock_op op)
{
    const char *box_path, *dir, *fname;
    int ret = -1, orig_dir_fd, orig_errno;

    orig_dir_fd = open(".", O_RDONLY);
    if (orig_dir_fd == -1) {
        mail_storage_set_critical(&mbox->storage->storage,
                                  "open(.) failed: %m");
        return -1;
    }

    /* allow dotlocks to be created only for files we can read while we're
       unprivileged. to make sure there are no race conditions we first
       have to chdir to the mbox file's directory and then use relative
       paths. unless this is done, users could:
        - create *.lock files to any directory writable by the
          privileged group
        - DoS other users by dotlocking their mailboxes infinitely
    */
    box_path = mailbox_get_path(&mbox->box);
    fname = strrchr(box_path, '/');
    if (fname == NULL) {
        /* already relative */
        fname = box_path;
    } else {
        dir = t_strdup_until(box_path, fname);
        if (chdir(dir) < 0) {
            mail_storage_set_critical(&mbox->storage->storage,
                                      "chdir(%s) failed: %m", dir);
            i_close_fd(&orig_dir_fd);
            return -1;
        }
        fname++;
    }
    if (op == MBOX_DOTLOCK_OP_LOCK) {
        if (access(fname, R_OK) < 0) {
            mail_storage_set_critical(&mbox->storage->storage,
                                      "access(%s) failed: %m", box_path);
            i_close_fd(&orig_dir_fd);
            return -1;
        }
    }

    if (restrict_access_use_priv_gid() < 0) {
        i_close_fd(&orig_dir_fd);
        return -1;
    }

    switch (op) {
    case MBOX_DOTLOCK_OP_LOCK:
        /* we're now privileged - avoid doing as much as possible */
        ret = file_dotlock_create(set, fname, 0, &mbox->mbox_dotlock);
        if (ret > 0)
            mbox->mbox_used_privileges = TRUE;
        else if (ret < 0 && errno == EACCES) {
            const char *errmsg =
                eacces_error_get_creating("file_dotlock_create",
                                          fname);
            mail_storage_set_critical(&mbox->storage->storage,
                                      "%s", errmsg);
        } else {
            mbox_set_syscall_error(mbox, "file_dotlock_create()");
        }
        break;
    case MBOX_DOTLOCK_OP_UNLOCK:
        /* we're now privileged - avoid doing as much as possible */
        ret = file_dotlock_delete(&mbox->mbox_dotlock);
        if (ret < 0)
            mbox_set_syscall_error(mbox, "file_dotlock_delete()");
        mbox->mbox_used_privileges = FALSE;
        break;
    case MBOX_DOTLOCK_OP_TOUCH:
        ret = file_dotlock_touch(mbox->mbox_dotlock);
        if (ret < 0)
            mbox_set_syscall_error(mbox, "file_dotlock_touch()");
        break;
    }

    orig_errno = errno;
    restrict_access_drop_priv_gid();

    if (fchdir(orig_dir_fd) < 0) {
        mail_storage_set_critical(&mbox->storage->storage,
                                  "fchdir() failed: %m");
    }
    i_close_fd(&orig_dir_fd);
    errno = orig_errno;
    return ret;
}
Esempio n. 11
0
static int sis_try_deduplicate(const char *rootdir, const char *fname)
{
	const char *p, *hash, *hashdir, *path, *hashes_dir, *hashes_path;
	struct stat st;
	ino_t inode;
	int ret;

	/* fname should be in <hash>-<guid> format */
	p = strchr(fname, '-');
	i_assert(p != NULL);

	hash = t_strdup_until(fname, p);
	hashdir = sis_get_dir(rootdir, hash);
	path = t_strdup_printf("%s/%s", hashdir, fname);

	hashes_dir = t_strconcat(hashdir, "/", HASH_DIR_NAME, NULL);
	hashes_path = t_strconcat(hashes_dir, "/", hash, NULL);
	if (link(path, hashes_path) == 0) {
		/* first file with this hash. we're done */
		return 0;
	}
	if (errno == ENOENT) {
		/* either path was already deleted or hashes dir
		   doesn't exist */
		if (mkdir(hashes_dir, 0700) < 0) {
			if (errno == EEXIST)
				return 0;
			i_error("mkdir(%s) failed: %m", hashes_dir);
			return -1;
		}
		/* try again */
		if (link(path, hashes_path) == 0 || errno == ENOENT)
			return 0;
	}
	if (errno != EEXIST) {
		i_error("link(%s, %s) failed: %m", path, hashes_path);
		return -1;
	}

	/* need to do a byte-by-byte comparison. but check first if someone
	   else already had deduplicated the file. */
	if (stat(path, &st) < 0) {
		if (errno == ENOENT) {
			/* just got deleted */
			return 0;
		}
		i_error("stat(%s) failed: %m", path);
		return -1;
	}
	if (st.st_nlink > 1) {
		/* already deduplicated */
		return 0;
	}

	ret = file_contents_equal(path, hashes_path, &inode);
	if (ret < 0) {
		if (errno == ENOENT) {
			/* either path or hashes_path was deleted. */
			return sis_try_deduplicate(rootdir, fname);
		}
		return -1;
	}
	if (ret > 0) {
		/* equal, replace with hard link */
		ret = hardlink_replace(hashes_path, path, inode);
		if (ret > 0)
			return 0;
		else if (ret < 0)
			return -1;
		/* too many hard links or inode changed */
	}

	/* replace hashes link with this  */
	return hardlink_replace(path, hashes_path, st.st_ino) < 0 ? -1 : 0;
}
static bool ext_enotify_option_parse
(struct sieve_enotify_env *nenv, const char *option, bool name_only,
	const char **opt_name_r, const char **opt_value_r)
{
	const char *p = option;

	/* "<optionname>=<value>".
	 *
	 * l-d = ALPHA / DIGIT
	 * l-d-p = l-d / "." / "-" / "_"
	 * optionname = l-d *l-d-p
	 * value = *(%x01-09 / %x0B-0C / %x0E-FF)
	 */

	/*
	 * Parse option name
	 *
	 * optionname = l-d *l-d-p
	 */

	/* Explicitly report empty option as such */
	if ( *p == '\0' ) {
		sieve_enotify_error(nenv, "empty option specified");
		return FALSE;
	}

	/* l-d = ALPHA / DIGIT */
	if ( i_isalnum(*p) ) {
		p++;

		/* l-d-p = l-d / "." / "-" / "_" */
		while ( i_isalnum(*p) || *p == '.' || *p == '-' || *p == '_' )
			p++;
	}

	/* Parsing must end at '=' and we must parse at least one character */
	if ( *p != '=' || p == option ) {
		sieve_enotify_error(nenv, "invalid option name specified in option '%s'",
				str_sanitize(option, 80));
		return FALSE;
	}

	/* Assign option name */
	if ( opt_name_r != NULL )
		*opt_name_r = t_strdup_until(option, p);

	/* Skip '=' */
	p++;

	/* Exit now if only the option name is of interest */
	if ( name_only )
		return TRUE;

	/*
	 * Parse option value
	 */

	/* value = *(%x01-09 / %x0B-0C / %x0E-FF) */
	while ( *p != '\0' && *p != 0x0A && *p != 0x0D )
		p++;

	/* Parse must end at end of string */
	if ( *p != '\0' ) {
		sieve_enotify_error(nenv,
			"notify command: invalid option value specified in option '%s'",
				str_sanitize(option, 80));
		return FALSE;
	}

	/* Assign option value */
	if ( opt_value_r != NULL )
		*opt_value_r = p;

	return TRUE;
}
Esempio n. 13
0
static void client_auth_parse_args(struct client *client,
				   const char *const *args,
				   struct client_auth_reply *reply_r)
{
	const char *key, *value, *p;

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

	for (; *args != NULL; args++) {
		p = strchr(*args, '=');
		if (p == NULL) {
			key = *args;
			value = "";
		} else {
			key = t_strdup_until(*args, p);
			value = p + 1;
		}
		if (strcmp(key, "nologin") == 0)
			reply_r->nologin = TRUE;
		else if (strcmp(key, "proxy") == 0)
			reply_r->proxy = TRUE;
		else if (strcmp(key, "temp") == 0)
			reply_r->temp = TRUE;
		else if (strcmp(key, "authz") == 0)
			reply_r->authz_failure = TRUE;
		else if (strcmp(key, "user_disabled") == 0)
			client->auth_user_disabled = TRUE;
		else if (strcmp(key, "pass_expired") == 0)
			client->auth_pass_expired = TRUE;
		else if (strcmp(key, "reason") == 0)
			reply_r->reason = value;
		else if (strcmp(key, "host") == 0)
			reply_r->host = value;
		else if (strcmp(key, "hostip") == 0)
			reply_r->hostip = value;
		else if (strcmp(key, "port") == 0)
			reply_r->port = atoi(value);
		else if (strcmp(key, "destuser") == 0)
			reply_r->destuser = value;
		else if (strcmp(key, "pass") == 0)
			reply_r->password = value;
		else if (strcmp(key, "proxy_timeout") == 0)
			reply_r->proxy_timeout_msecs = 1000*atoi(value);
		else if (strcmp(key, "proxy_refresh") == 0)
			reply_r->proxy_refresh_secs = atoi(value);
		else if (strcmp(key, "master") == 0)
			reply_r->master_user = value;
		else if (strcmp(key, "ssl") == 0) {
			reply_r->ssl_flags |= PROXY_SSL_FLAG_YES;
			if (strcmp(value, "any-cert") == 0)
				reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
			if (reply_r->port == 0)
				reply_r->port = login_binary->default_ssl_port;
		} else if (strcmp(key, "starttls") == 0) {
			reply_r->ssl_flags |= PROXY_SSL_FLAG_YES |
				PROXY_SSL_FLAG_STARTTLS;
			if (strcmp(value, "any-cert") == 0)
				reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
		} else if (strcmp(key, "user") == 0) {
			/* already handled in login-common */
		} else if (client->set->auth_debug)
			i_debug("Ignoring unknown passdb extra field: %s", key);
	}
	if (reply_r->port == 0)
		reply_r->port = login_binary->default_port;

	if (reply_r->destuser == NULL)
		reply_r->destuser = client->virtual_user;
}
Esempio n. 14
0
static void client_connected(struct master_service_connection *conn)
{
	enum mail_storage_service_flags flags =
		MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS;
	string_t *instr, *keys;
	const char **args, *key, *value, *error, *version_line, *data_line;
	struct mail_storage_service_ctx *service_ctx;
	struct mail_storage_service_input input;
	struct mail_storage_service_user *user;
	char buf[1024];
	unsigned int i, socket_count;
	int fd = -1;
	ssize_t ret;

	alarm(SCRIPT_LOGIN_READ_TIMEOUT_SECS);

	net_set_nonblock(conn->fd, FALSE);
	instr = t_str_new(1024);
	ret = fd_read(conn->fd, buf, sizeof(buf), &fd);
	while (ret > 0) {
		str_append_n(instr, buf, ret);
		if (buf[ret-1] == '\n' &&
		    strchr(str_c(instr), '\n')[1] != '\0') {
			str_truncate(instr, str_len(instr)-1);
			break;
		}

		ret = read(conn->fd, buf, sizeof(buf));
	}

	version_line = str_c(instr);
	data_line = strchr(version_line, '\n');
	if (data_line != NULL)
		version_line = t_strdup_until(version_line, data_line++);
	else
		version_line = NULL;

	if (ret > 0 || version_line != NULL) {
		if (version_line == NULL ||
		    !version_string_verify(version_line, "script-login",
				SCRIPT_LOGIN_PROTOCOL_VERSION_MAJOR)) {
			i_fatal("Client not compatible with this binary "
				"(connecting to wrong socket?)");
		}
	}

	if (ret <= 0) {
		if (ret < 0)
			i_fatal("read() failed: %m");
		else
			i_fatal("read() failed: disconnected");
	}
	if (fd == -1)
		i_fatal("client fd not received");

	/* put everything to environment */
	env_clean();
	keys = t_str_new(256);
	args = t_strsplit(data_line, "\t");

	if (str_array_length(args) < 3)
		i_fatal("Missing input fields");

	i = 0;
	memset(&input, 0, sizeof(input));
	input.module = "mail"; /* need to get mail_uid, mail_gid */
	input.service = "script-login";
	(void)net_addr2ip(args[i++], &input.local_ip);
	(void)net_addr2ip(args[i++], &input.remote_ip);
	input.username = args[i++];
	input.userdb_fields = args + i;

	env_put(t_strconcat("LOCAL_IP=", net_ip2addr(&input.local_ip), NULL));
	env_put(t_strconcat("IP=", net_ip2addr(&input.remote_ip), NULL));
	env_put(t_strconcat("USER="******"%s ", key);
		}
	}
	env_put(t_strconcat(ENV_USERDB_KEYS"=", str_c(keys), NULL));

	master_service_init_log(master_service,
		t_strdup_printf("script-login(%s): ", input.username));

	service_ctx = mail_storage_service_init(master_service, NULL, flags);
	if (mail_storage_service_lookup(service_ctx, &input, &user, &error) <= 0)
		i_fatal("%s", error);
	mail_storage_service_restrict_setenv(service_ctx, user);

	if (drop_privileges)
		restrict_access_by_env(getenv("HOME"), TRUE);

	if (dup2(fd, STDIN_FILENO) < 0)
		i_fatal("dup2() failed: %m");
	if (dup2(fd, STDOUT_FILENO) < 0)
		i_fatal("dup2() failed: %m");
	if (conn->fd != SCRIPT_COMM_FD) {
		if (dup2(conn->fd, SCRIPT_COMM_FD) < 0)
			i_fatal("dup2() failed: %m");
	}

	/* close all listener sockets */
	socket_count = master_service_get_socket_count(master_service);
	for (i = 0; i < socket_count; i++) {
		if (close(MASTER_LISTEN_FD_FIRST + i) < 0)
			i_error("close(listener) failed: %m");
	}
	if (close(MASTER_STATUS_FD) < 0)
		i_error("close(status) failed: %m");

	execvp_const(exec_args[0], exec_args);
}
Esempio n. 15
0
static int mcht_matches_match_key
(struct sieve_match_context *mctx, const char *val, size_t val_size,
	const char *key, size_t key_size)
{
	const struct sieve_comparator *cmp = mctx->comparator;
	struct sieve_match_values *mvalues;
	string_t *mvalue = NULL, *mchars = NULL;
	string_t *section, *subsection;
	const char *vend, *kend, *vp, *kp, *wp, *pvp;
	bool backtrack = FALSE; /* TRUE: match of '?'-connected sections failed */
	char wcard = '\0';      /* Current wildcard */
	char next_wcard = '\0'; /* Next  widlcard */
	unsigned int key_offset = 0;

	if ( cmp->def == NULL || cmp->def->char_match == NULL )
		return 0;

	/* Key sections */
	section = t_str_new(32);    /* Section (after beginning or *) */
	subsection = t_str_new(32); /* Sub-section (after ?) */

	/* Mark end of value and key */
	vend = (const char *) val + val_size;
	kend = (const char *) key + key_size;

	/* Initialize pointers */
	vp = val;                   /* Value pointer */
	kp = key;                   /* Key pointer */
	wp = key;                   /* Wildcard (key) pointer */

	/* Start match values list if requested */
	if ( (mvalues = sieve_match_values_start(mctx->runenv)) != NULL ) {
		/* Skip ${0} for now; added when match succeeds */
		sieve_match_values_add(mvalues, NULL);

		mvalue = t_str_new(32);     /* Match value (*) */
		mchars = t_str_new(32);     /* Match characters (.?..?.??) */
	}

	/* Match the pattern:
	 *   <pattern> = <section>*<section>*<section>...
	 *   <section> = <sub-section>?<sub-section>?<sub-section>...
	 *
	 * Escape sequences \? and \* need special attention.
	 */

	debug_printf("=== Start ===\n");
	debug_printf("  key:   %s\n", t_strdup_until(key, kend));
	debug_printf("  value: %s\n", t_strdup_until(val, vend));

	/* Loop until either key or value ends */
	while (kp < kend && vp < vend ) {
		const char *needle, *nend;

		if ( !backtrack ) {
			/* Search the next '*' wildcard in the key string */

			wcard = next_wcard;

			/* Find the needle to look for in the string */
			key_offset = 0;
			for (;;) {
				next_wcard = _scan_key_section(section, &wp, kend);

				if ( wcard == '\0' || str_len(section) > 0 )
					break;

				if ( next_wcard == '*' ) {
					break;
				}

				if ( wp < kend )
					wp++;
				else
					break;
				key_offset++;
			}

			debug_printf("found wildcard '%c' at pos [%d]\n",
				next_wcard, (int) (wp-key));

			if ( mvalues != NULL )
				str_truncate(mvalue, 0);
		} else {
			/* Backtracked; '*' wildcard is retained */
			debug_printf("backtracked");
			backtrack = FALSE;
		}

		/* Determine what we are looking for */
		needle = str_c(section);
		nend = PTR_OFFSET(needle, str_len(section));

		debug_printf("  section needle:  '%s'\n", t_strdup_until(needle, nend));
		debug_printf("  section key:     '%s'\n", t_strdup_until(kp, kend));
		debug_printf("  section remnant: '%s'\n", t_strdup_until(wp, kend));
		debug_printf("  value remnant:   '%s'\n", t_strdup_until(vp, vend));
		debug_printf("  key offset:      %d\n", key_offset);

		pvp = vp;
		if ( next_wcard == '\0' ) {
			if ( wcard == '\0' ) {
				/* No current wildcard; match needs to happen right at the beginning */
				debug_printf("next_wcard = NULL && wcard = NUL; needle should be equal to value.\n");

				if ( (vend - vp) != (nend - needle) ||
					!cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) {
					debug_printf("  key not equal to value\n");
					break;
				}

			} else {
				const char *qp, *qend;

				/* No more wildcards; find the needle substring at the end of string */
				debug_printf("next_wcard = NUL; must find needle at end\n");

				/* Check if the value is still large enough */
				if ( vend - str_len(section) < vp ) {
					debug_printf("  wont match: value is too short\n");
					break;
				}

				/* Move value pointer to where the needle should be */
				vp = PTR_OFFSET(vend, -str_len(section));

				/* Record match values */
				qend = vp;
				qp = vp - key_offset;

				if ( mvalues != NULL )
					str_append_n(mvalue, pvp, qp-pvp);

				/* Compare needle to end of value string */
				if ( !cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) {
					debug_printf("  match at end failed\n");
					break;
				}

				/* Add match values */
				if ( mvalues != NULL ) {
					/* Append '*' match value */
					sieve_match_values_add(mvalues, mvalue);

					/* Append any initial '?' match values */
					for ( ; qp < qend; qp++ )
						sieve_match_values_add_char(mvalues, *qp);
				}
			}

			/* Finish match */
			kp = kend;
			vp = vend;

			debug_printf("  matched end of value\n");
			break;
		} else {
			/* Next wildcard found; match needle before next wildcard */

			const char *prv = NULL; /* Stored value pointer for backtrack */
			const char *prk = NULL; /* Stored key pointer for backtrack */
			const char *prw = NULL; /* Stored wildcard pointer for backtrack */
			const char *chars;

			/* Reset '?' match values */
			if ( mvalues != NULL )
				str_truncate(mchars, 0);

			if ( wcard == '\0' ) {
				/* No current wildcard; match needs to happen right at the beginning */
				debug_printf("wcard = NUL; needle should be found at the beginning.\n");
				debug_printf("  begin needle: '%s'\n", t_strdup_until(needle, nend));
				debug_printf("  begin value:  '%s'\n", t_strdup_until(vp, vend));

				if ( !cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) {
					debug_printf("  failed to find needle at beginning\n");
					break;
				}

			} else {
				/* Current wildcard present; match needle between current and next wildcard */
				debug_printf("wcard != NUL; must find needle at an offset (>= %d).\n",
					key_offset);

				/* Match may happen at any offset (>= key offset): find substring */
				vp += key_offset;
				if ( (vp >= vend) || !_string_find(cmp, &vp, vend, &needle, nend) ) {
					debug_printf("  failed to find needle at an offset\n");
					break;
				}

				prv = vp - str_len(section);
				prk = kp;
				prw = wp;

				/* Append match values */
				if ( mvalues != NULL ) {
					const char *qend = vp - str_len(section);
					const char *qp = qend - key_offset;

					/* Append '*' match value */
					str_append_n(mvalue, pvp, qp-pvp);

					/* Append any initial '?' match values (those that caused the key
					 * offset.
					 */
					for ( ; qp < qend; qp++ )
						str_append_c(mchars, *qp);
				}
			}

			/* Update wildcard and key pointers for next wildcard scan */
			if ( wp < kend ) wp++;
			kp = wp;

			/* Scan successive '?' wildcards */
			while ( next_wcard == '?' ) {
				debug_printf("next_wcard = '?'; need to match arbitrary character\n");

				/* Add match value */
				if ( mvalues != NULL )
					str_append_c(mchars, *vp);

				vp++;

				/* Scan for next '?' wildcard */
				next_wcard = _scan_key_section(subsection, &wp, kend);
				debug_printf("found next wildcard '%c' at pos [%d] (fixed match)\n",
					next_wcard, (int) (wp-key));

				/* Determine what we are looking for */
				needle = str_c(subsection);
				nend = PTR_OFFSET(needle, str_len(subsection));

				debug_printf("  sub key:       '%s'\n", t_strdup_until(needle, nend));
				debug_printf("  value remnant: '%s'\n", vp <= vend ? t_strdup_until(vp, vend) : "");

				/* Try matching the needle at fixed position */
				if ( (needle == nend && next_wcard == '\0' && vp < vend ) ||
					!cmp->def->char_match(cmp, &vp, vend, &needle, nend) ) {

					/* Match failed: now we have a problem. We need to backtrack to the previous
					 * '*' wildcard occurrence and start scanning for the next possible match.
					 */

					debug_printf("  failed fixed match\n");

					/* Start backtrack */
					if ( prv != NULL && prv + 1 < vend ) {
						/* Restore pointers */
						vp = prv;
						kp = prk;
						wp = prw;

						/* Skip forward one value character to scan the next possible match */
						if ( mvalues != NULL )
							str_append_c(mvalue, *vp);
						vp++;

						/* Set wildcard state appropriately */
						wcard = '*';
						next_wcard = '?';

						/* Backtrack */
						backtrack = TRUE;

						debug_printf("  BACKTRACK\n");
					}

					/* Break '?' wildcard scanning loop */
					break;
				}

				/* Update wildcard and key pointers for next wildcard scan */
				if ( wp < kend ) wp++;
				kp = wp;
			}

			if ( !backtrack ) {
				unsigned int i;

				if ( next_wcard == '?' ) {
					debug_printf("failed to match '?'\n");
					break;
				}

				if ( mvalues != NULL ) {
					if ( prv != NULL )
						sieve_match_values_add(mvalues, mvalue);

					chars = (const char *) str_data(mchars);

					for ( i = 0; i < str_len(mchars); i++ ) {
						sieve_match_values_add_char(mvalues, chars[i]);
					}
				}

				if ( next_wcard != '*' ) {
					debug_printf("failed to match at end of string\n");
					break;
				}
			}
		}

		/* Check whether string ends in a wildcard
		 * (avoid scanning the rest of the string)
		 */
		if ( kp == kend && next_wcard == '*' ) {
			/* Add the rest of the string as match value */
			if ( mvalues != NULL ) {
				str_truncate(mvalue, 0);
				str_append_n(mvalue, vp, vend-vp);
				sieve_match_values_add(mvalues, mvalue);
			}

			/* Finish match */
			kp = kend;
			vp = vend;

			debug_printf("key ends with '*'\n");
			break;
		}

		debug_printf("== Loop ==\n");
	}

	/* Eat away a trailing series of *s */
	if ( vp == vend ) {
		while ( kp < kend && *kp == '*' ) kp++;
	}

	/* By definition, the match is only successful if both value and key pattern
	 * are exhausted.
	 */

	debug_printf("=== Finish ===\n");
	debug_printf("  result: %s\n", (kp == kend && vp == vend) ? "true" : "false");

	if (kp == kend && vp == vend) {
		/* Activate new match values after successful match */
		if ( mvalues != NULL ) {
			/* Set ${0} */
			string_t *matched = str_new_const(pool_datastack_create(), val, val_size);
			sieve_match_values_set(mvalues, 0, matched);

			/* Commit new match values */
			sieve_match_values_commit(mctx->runenv, &mvalues);
		}
		return 1;
	}

	/* No match; drop collected match values */
	sieve_match_values_abort(&mvalues);
	return 0;
}
Esempio n. 16
0
static int
fs_crypt_init(struct fs *_fs, const char *args, const
	      struct fs_settings *set)
{
	struct crypt_fs *fs = (struct crypt_fs *)_fs;
	const char *enc_algo, *set_prefix;
	const char *p, *arg, *value, *error, *parent_name, *parent_args;
	const char *public_key_path = "", *private_key_path = "", *password = "";

	random_init();
	if (!dcrypt_initialize("openssl", NULL, &error))
		i_fatal("dcrypt_initialize(): %s", error);

	/* [algo=<s>:][set_prefix=<n>:][public_key_path=<s>:]
	   [private_key_path=<s>:[password=<s>:]]<parent fs> */
	set_prefix = "mail_crypt_global";
	enc_algo = "aes-256-gcm-sha256";
	for (;;) {
		p = strchr(args, ':');
		if (p == NULL) {
			fs_set_error(_fs, "Missing parameters");
			return -1;
		}
		arg = t_strdup_until(args, p);
		if ((value = strchr(arg, '=')) == NULL)
			break;
		arg = t_strdup_until(arg, value++);
		args = p+1;

		if (strcmp(arg, "algo") == 0)
			enc_algo = value;
		else if (strcmp(arg, "set_prefix") == 0)
			set_prefix = value;
		else if (strcmp(arg, "public_key_path") == 0)
			public_key_path = value;
		else if (strcmp(arg, "private_key_path") == 0)
			private_key_path = value;
		else if (strcmp(arg, "password") == 0)
			password = value;
		else {
			fs_set_error(_fs, "Invalid parameter '%s'", arg);
			return -1;
		}
	}

	parent_args = strchr(args, ':');
	if (parent_args == NULL) {
		parent_name = args;
		parent_args = "";
	} else {
		parent_name = t_strdup_until(args, parent_args);
		parent_args++;
	}
	if (fs_init(parent_name, parent_args, set, &_fs->parent, &error) < 0) {
		fs_set_error(_fs, "%s: %s", parent_name, error);
		return -1;
	}
	fs->enc_algo = i_strdup(enc_algo);
	fs->set_prefix = i_strdup(set_prefix);
	fs->public_key_path = i_strdup_empty(public_key_path);
	fs->private_key_path = i_strdup_empty(private_key_path);
	fs->password = i_strdup_empty(password);
	return 0;
}
Esempio n. 17
0
static void driver_mysql_parse_connect_string(struct mysql_db *db,
					      const char *connect_string)
{
	const char *const *args, *name, *value;
	const char **field;

	db->ssl_cipher = "HIGH";
	db->ssl_verify_server_cert = 0; /* FIXME: change to 1 for v2.3 */

	args = t_strsplit_spaces(connect_string, " ");
	for (; *args != NULL; args++) {
		value = strchr(*args, '=');
		if (value == NULL) {
			i_fatal("mysql: Missing value in connect string: %s",
				*args);
		}
		name = t_strdup_until(*args, value);
		value++;

		field = NULL;
		if (strcmp(name, "host") == 0 ||
		    strcmp(name, "hostaddr") == 0)
			field = &db->host;
		else if (strcmp(name, "user") == 0)
			field = &db->user;
		else if (strcmp(name, "password") == 0)
			field = &db->password;
		else if (strcmp(name, "dbname") == 0)
			field = &db->dbname;
		else if (strcmp(name, "port") == 0)
			db->port = atoi(value);
		else if (strcmp(name, "client_flags") == 0)
			db->client_flags = atoi(value);
		else if (strcmp(name, "ssl_cert") == 0)
			field = &db->ssl_cert;
		else if (strcmp(name, "ssl_key") == 0)
			field = &db->ssl_key;
		else if (strcmp(name, "ssl_ca") == 0)
			field = &db->ssl_ca;
		else if (strcmp(name, "ssl_ca_path") == 0)
			field = &db->ssl_ca_path;
		else if (strcmp(name, "ssl_cipher") == 0)
			field = &db->ssl_cipher;
		else if (strcmp(name, "ssl_verify_server_cert") == 0) {
			if (strcmp(value, "yes") == 0)
				db->ssl_verify_server_cert = 1;
			else if (strcmp(value, "no") == 0)
				db->ssl_verify_server_cert = 0;
			else
				i_fatal("mysql: Invalid boolean: %s", value);
		} else if (strcmp(name, "option_file") == 0)
			field = &db->option_file;
		else if (strcmp(name, "option_group") == 0)
			field = &db->option_group;
		else
			i_fatal("mysql: Unknown connect string: %s", name);

		if (field != NULL)
			*field = p_strdup(db->pool, value);
	}

	if (db->host == NULL)
		i_fatal("mysql: No hosts given in connect string");

	db->mysql = mysql_init(NULL);
	if (db->mysql == NULL)
		i_fatal("mysql_init() failed");
}