示例#1
0
static int fts_filter_stopwords_read_list(struct fts_filter_stopwords *filter,
					  const char **error_r)
{
	struct istream *input;
	const char *line, **words, *path;
	int ret = 0;

	path = t_strdup_printf(STOPWORDS_FILE_FORMAT,
			       filter->stopwords_dir, filter->lang->name);

	input = i_stream_create_file(path, IO_BLOCK_SIZE);
	while ((line = i_stream_read_next_line(input)) != NULL) T_BEGIN {
		line = t_strcut(line, STOPWORDS_COMMENT_CHAR1);
		line = t_strcut(line, STOPWORDS_COMMENT_CHAR2);

		words = t_strsplit_spaces(line, " \t");
		for (; *words != NULL; words++) {
			const char *word = p_strdup(filter->pool, *words);
			hash_table_insert(filter->stopwords, word, word);
		}
	} T_END;

	if (input->stream_errno != 0) {
		*error_r = t_strdup_printf("Failed to read stopword list %s: %s",
					   path, i_stream_get_error(input));
		ret = -1;
	}
	i_stream_destroy(&input);
	return ret;
}
static const struct var_expand_table *
get_var_expand_table(struct master_service *service,
		     struct mail_storage_service_user *user,
		     const struct mail_storage_service_input *input,
		     const struct mail_storage_service_privileges *priv)
{
	static struct var_expand_table static_tab[] = {
		{ 'u', NULL, "user" },
		{ 'n', NULL, "username" },
		{ 'd', NULL, "domain" },
		{ 's', NULL, "service" },
		{ 'l', NULL, "lip" },
		{ 'r', NULL, "rip" },
		{ 'p', NULL, "pid" },
		{ 'i', NULL, "uid" },
		{ '\0', NULL, "gid" },
		{ '\0', NULL, "session" },
		{ '\0', NULL, "auth_user" },
		{ '\0', NULL, "auth_username" },
		{ '\0', NULL, "auth_domain" },
		{ '\0', NULL, NULL }
	};
	struct var_expand_table *tab;

	tab = t_malloc(sizeof(static_tab));
	memcpy(tab, static_tab, sizeof(static_tab));

	tab[0].value = input->username;
	tab[1].value = t_strcut(input->username, '@');
	tab[2].value = strchr(input->username, '@');
	if (tab[2].value != NULL) tab[2].value++;
	tab[3].value = service->name;
	tab[4].value = net_ip2addr(&input->local_ip);
	tab[5].value = net_ip2addr(&input->remote_ip);
	tab[6].value = my_pid;
	tab[7].value = priv == NULL ? NULL :
		dec2str(priv->uid == (uid_t)-1 ? geteuid() : priv->uid);
	tab[8].value = priv == NULL ? NULL :
		dec2str(priv->gid == (gid_t)-1 ? getegid() : priv->gid);
	tab[9].value = input->session_id;
	if (user == NULL || user->auth_user == NULL) {
		tab[10].value = tab[0].value;
		tab[11].value = tab[1].value;
		tab[12].value = tab[2].value;
	} else {
		tab[10].value = user->auth_user;
		tab[11].value = t_strcut(user->auth_user, '@');
		tab[12].value = strchr(user->auth_user, '@');
	}
	return tab;
}
示例#3
0
static void passwd_file_iterate_next(struct userdb_iterate_context *_ctx)
{
    struct passwd_file_userdb_iterate_context *ctx =
        (struct passwd_file_userdb_iterate_context *)_ctx;
    const char *line, *p;

    if (ctx->input == NULL)
        line = NULL;
    else {
        while ((line = i_stream_read_next_line(ctx->input)) != NULL) {
            if (*line == '\0' || *line == ':' || *line == '#')
                continue; /* no username or comment */
            if (ctx->skip_passdb_entries &&
                    ((p = strchr(line, ':')) == NULL ||
                     strchr(p+1, ':') == NULL)) {
                /* only passdb info */
                continue;
            }
            break;
        }
        if (line == NULL && ctx->input->stream_errno != 0) {
            i_error("read(%s) failed: %m", ctx->path);
            _ctx->failed = TRUE;
        }
    }
    if (line == NULL)
        _ctx->callback(NULL, _ctx->context);
    else T_BEGIN {
        _ctx->callback(t_strcut(line, ':'), _ctx->context);
    } T_END;
}
示例#4
0
static void
stats_metric_settings_to_query(const struct stats_metric_settings *set,
			       struct event_filter_query *query_r)
{
	i_zero(query_r);

	/* generate fields for event filter */
	if (array_is_created(&set->filter)) {
		struct event_filter_field *filter_fields;
		const char *const *filters;
		unsigned int i, count;

		filters = array_get(&set->filter, &count);
		i_assert(count % 2 == 0);
		count /= 2;

		filter_fields = t_new(struct event_filter_field, count + 1);
		for (i = 0; i < count; i++) {
			filter_fields[i].key = filters[i*2];
			filter_fields[i].value = filters[i*2+1];
		}
		query_r->fields = filter_fields;
	}

	/* add query to the event filter */
	query_r->categories = t_strsplit_spaces(set->categories, " ");
	query_r->name = set->event_name;
	query_r->source_filename = t_strcut(set->source_location, ':');
	query_r->source_linenum = set->parsed_source_linenum;
}
示例#5
0
文件: sysinfo-get.c 项目: bdraco/core
static const char *distro_get(void)
{
	static const char *files[] = {
		"", "/etc/redhat-release",
		"", "/etc/SuSE-release",
		"", "/etc/mandriva-release",
		"", "/etc/fedora-release",
		"", "/etc/sourcemage-release",
		"", "/etc/slackware-version",
		"", "/etc/gentoo-release",
		"Debian ", "/etc/debian_version",
		NULL
	};
	const char *name;
	unsigned int i;

	if (lsb_distro_get("/etc/lsb-release", &name))
		return name;
	for (i = 0; files[i] != NULL; i += 2) {
		if (readfile(files[i+1], &name)) {
			return t_strconcat(files[i], t_strcut(name, '\n'),
					   NULL);
		}
	}
	return "";
}
示例#6
0
static bool
maildir_expunge_is_valid_guid(struct maildir_index_sync_context *ctx,
			      uint32_t uid, const char *filename,
			      guid_128_t expunged_guid_128)
{
	guid_128_t guid_128;
	const char *guid;

	if (guid_128_is_empty(expunged_guid_128)) {
		/* no GUID associated with expunge */
		return TRUE;
	}

	T_BEGIN {
		guid = maildir_uidlist_lookup_ext(ctx->mbox->uidlist, uid,
						  MAILDIR_UIDLIST_REC_EXT_GUID);
		if (guid == NULL)
			guid = t_strcut(filename, ':');
		mail_generate_guid_128_hash(guid, guid_128);
	} T_END;

	if (memcmp(guid_128, expunged_guid_128, sizeof(guid_128)) == 0)
		return TRUE;

	mail_storage_set_critical(&ctx->mbox->storage->storage,
		"Mailbox %s: Expunged GUID mismatch for UID %u: %s vs %s",
		ctx->mbox->box.vname, ctx->uid,
		guid_128_to_string(guid_128),
		guid_128_to_string(expunged_guid_128));
	return FALSE;
}
示例#7
0
static void
client_send_login_reply(struct imap_client *client, string_t *str,
			const char *line)
{
	const char *capability;
	bool tagged_capability;

	capability = client->proxy_backend_capability;
	tagged_capability = strncasecmp(line, "[CAPABILITY ", 12) == 0;
	if (tagged_capability)
		capability = t_strcut(line + 12, ']');

	if (client->client_ignores_capability_resp_code && capability != NULL) {
		/* client has used CAPABILITY command, so it didn't understand
		   the capabilities in the banner. send the backend's untagged
		   CAPABILITY reply and hope that the client understands it */
		str_printfa(str, "* CAPABILITY %s\r\n", capability);
	}
	str_append(str, client->cmd_tag);
	str_append(str, " OK ");
	if (!client->client_ignores_capability_resp_code &&
	    !tagged_capability && capability != NULL) {
		str_printfa(str, "[CAPABILITY %s] ", capability);
		if (*line == '[') {
			/* we need to send the capability.
			   skip over this resp-code */
			while (*line != ']' && *line != '\0')
				line++;
			if (*line == ' ') line++;
		}
	}
	str_append(str, line);
	str_append(str, "\r\n");
}
示例#8
0
static int
cmd_user_input(const char *auth_socket_path, const struct authtest_input *input,
	       const char *show_field, bool userdb)
{
	const char *lookup_name = userdb ? "userdb lookup" : "passdb lookup";
	struct auth_master_connection *conn;
	pool_t pool;
	const char *username, *const *fields, *p;
	int ret;

	if (auth_socket_path == NULL) {
		auth_socket_path = t_strconcat(doveadm_settings->base_dir,
					       "/auth-userdb", NULL);
	}

	pool = pool_alloconly_create("auth master lookup", 1024);

	conn = auth_master_init(auth_socket_path, 0);
	if (userdb) {
		ret = auth_master_user_lookup(conn, input->username, &input->info,
					      pool, &username, &fields);
	} else {
		ret = auth_master_pass_lookup(conn, input->username, &input->info,
					      pool, &fields);
	}
	if (ret < 0) {
		if (fields[0] == NULL)
			i_error("%s failed for %s", lookup_name, input->username);
		else {
			i_error("%s failed for %s: %s", lookup_name,
				input->username, fields[0]);
		}
	} else if (ret == 0) {
		fprintf(show_field == NULL ? stdout : stderr,
			"%s: user %s doesn't exist\n", lookup_name,
			input->username);
	} else if (show_field != NULL) {
		unsigned int show_field_len = strlen(show_field);

		for (; *fields; fields++) {
			if (strncmp(*fields, show_field, show_field_len) == 0 &&
			    (*fields)[show_field_len] == '=')
				printf("%s\n", *fields + show_field_len + 1);
		}
	} else {
		printf("%s: %s\n", userdb ? "userdb" : "passdb", input->username);

		for (; *fields; fields++) {
			p = strchr(*fields, '=');
			if (p == NULL)
				printf("  %-10s\n", *fields);
			else {
				printf("  %-10s: %s\n",
				       t_strcut(*fields, '='), p + 1);
			}
		}
	}
	auth_master_deinit(&conn);
	return ret;
}
示例#9
0
static void
login_host_callback(const struct ip_addr *ip, const char *errormsg,
		    void *context)
{
	struct login_host_request *request = context;
	struct director *dir = request->conn->dir;
	const char *line, *line_params;
	unsigned int secs;

	if (ip != NULL) {
		secs = dir->set->director_user_expire / 2;
		line = t_strdup_printf("%s\thost=%s\tproxy_refresh=%u",
				       request->line, net_ip2addr(ip), secs);
	} else {
		if (strncmp(request->line, "OK\t", 3) == 0)
			line_params = request->line + 3;
		else if (strncmp(request->line, "PASS\t", 5) == 0)
			line_params = request->line + 5;
		else
			i_panic("BUG: Unexpected line: %s", request->line);

		i_error("director: User %s host lookup failed: %s",
			request->username, errormsg);
		line = t_strconcat("FAIL\t", t_strcut(line_params, '\t'),
				   "\ttemp", NULL);
	}
	login_connection_send_line(request->conn, line);

	login_connection_unref(&request->conn);
	i_free(request->username);
	i_free(request->line);
	i_free(request);
}
示例#10
0
static int proxy_input_banner(struct imap_client *client,
			      struct ostream *output, const char *line)
{
	const char *const *capabilities = NULL;
	string_t *str;
	int ret;

	if (!str_begins(line, "* OK ")) {
		client_log_err(&client->common, t_strdup_printf(
			"proxy: Remote returned invalid banner: %s",
			str_sanitize(line, 160)));
		return -1;
	}

	str = t_str_new(128);
	if (str_begins(line + 5, "[CAPABILITY ")) {
		capabilities = t_strsplit(t_strcut(line + 5 + 12, ']'), " ");
		if (str_array_icase_find(capabilities, "SASL-IR"))
			client->proxy_sasl_ir = TRUE;
		if (str_array_icase_find(capabilities, "LOGINDISABLED"))
			client->proxy_logindisabled = TRUE;
		i_free(client->proxy_backend_capability);
		client->proxy_backend_capability =
			i_strdup(t_strcut(line + 5 + 12, ']'));
		if (str_array_icase_find(capabilities, "ID") &&
		    !client->common.proxy_not_trusted) {
			client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_ID;
			proxy_write_id(client, str);
			if (client->common.proxy_nopipelining) {
				/* write login or starttls after I OK */
				o_stream_nsend(output, str_data(str), str_len(str));
				return 0;
			}
		}
	}

	if ((ret = proxy_write_starttls(client, str)) < 0) {
		return -1;
	} else if (ret == 0) {
		if (proxy_write_login(client, str) < 0)
			return -1;
	}

	o_stream_nsend(output, str_data(str), str_len(str));
	return 0;
}
示例#11
0
static int proxy_input_banner(struct imap_client *client,
			      struct ostream *output, const char *line)
{
	enum login_proxy_ssl_flags ssl_flags;
	const char *const *capabilities = NULL;
	string_t *str;

	if (strncmp(line, "* OK ", 5) != 0) {
		client_log_err(&client->common, t_strdup_printf(
			"proxy: Remote returned invalid banner: %s",
			str_sanitize(line, 160)));
		return -1;
	}

	str = t_str_new(128);
	if (strncmp(line + 5, "[CAPABILITY ", 12) == 0) {
		capabilities = t_strsplit(t_strcut(line + 5 + 12, ']'), " ");
		if (str_array_icase_find(capabilities, "ID"))
			proxy_write_id(client, str);
		if (str_array_icase_find(capabilities, "SASL-IR"))
			client->proxy_sasl_ir = TRUE;
		if (str_array_icase_find(capabilities, "LOGINDISABLED"))
			client->proxy_logindisabled = TRUE;
		i_free(client->proxy_backend_capability);
		client->proxy_backend_capability =
			i_strdup(t_strcut(line + 5 + 12, ']'));
	}

	ssl_flags = login_proxy_get_ssl_flags(client->common.login_proxy);
	if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) != 0) {
		if (capabilities != NULL &&
		    !str_array_icase_find(capabilities, "STARTTLS")) {
			client_log_err(&client->common,
				"proxy: Remote doesn't support STARTTLS");
			return -1;
		}
		str_append(str, "S STARTTLS\r\n");
	} else {
		if (proxy_write_login(client, str) < 0)
			return -1;
	}

	o_stream_nsend(output, str_data(str), str_len(str));
	return 0;
}
示例#12
0
static bool
proxy_client_worker_next_msg_get(struct proxy_client_dsync_worker *worker,
                                 const struct proxy_client_request *request,
                                 const char *line)
{
    enum dsync_msg_get_result result = DSYNC_MSG_GET_RESULT_FAILED;
    const char *p, *error;
    uint32_t uid;

    p_clear(worker->msg_get_pool);
    switch (line[0]) {
    case '1':
        /* ok */
        if (line[1] != '\t')
            break;
        line += 2;

        if ((p = strchr(line, '\t')) == NULL)
            break;
        uid = strtoul(t_strcut(line, '\t'), NULL, 10);
        line = p + 1;

        if (uid != request->uid) {
            i_error("msg-get returned invalid uid: %u != %u",
                    uid, request->uid);
            proxy_client_fail(worker);
            return FALSE;
        }

        if (dsync_proxy_msg_static_import(worker->msg_get_pool,
                                          line, &worker->msg_get_data,
                                          &error) < 0) {
            i_error("Invalid msg-get static input: %s", error);
            proxy_client_fail(worker);
            return FALSE;
        }
        worker->msg_get_data.input =
            i_stream_create_dot(worker->input, FALSE);
        i_stream_set_destroy_callback(worker->msg_get_data.input,
                                      proxy_client_worker_msg_get_done,
                                      worker);
        io_remove(&worker->io);
        result = DSYNC_MSG_GET_RESULT_SUCCESS;
        break;
    case '0':
        /* expunged */
        result = DSYNC_MSG_GET_RESULT_EXPUNGED;
        break;
    default:
        /* failure */
        break;
    }

    request->callback.get(result, &worker->msg_get_data, request->context);
    return worker->io != NULL && worker->msg_get_data.input == NULL;
}
示例#13
0
static void auth_server_connection_input(struct auth_server_connection *conn)
{
	struct istream *input;
	const char *line, *error;
	int ret;

	switch (i_stream_read(conn->input)) {
	case 0:
		return;
	case -1:
		/* disconnected */
		error = conn->input->stream_errno != 0 ?
			strerror(conn->input->stream_errno) : "EOF";
		auth_server_connection_reconnect(conn, error);
		return;
	case -2:
		/* buffer full - can't happen unless auth is buggy */
		i_error("BUG: Auth server sent us more than %d bytes of data",
			AUTH_SERVER_CONN_MAX_LINE_LENGTH);
		auth_server_connection_disconnect(conn, "buffer full");
		return;
	}

	if (!conn->version_received) {
		line = i_stream_next_line(conn->input);
		if (line == NULL)
			return;

		/* make sure the major version matches */
		if (strncmp(line, "VERSION\t", 8) != 0 ||
		    !str_uint_equals(t_strcut(line + 8, '\t'),
				     AUTH_CLIENT_PROTOCOL_MAJOR_VERSION)) {
			i_error("Authentication server not compatible with "
				"this client (mixed old and new binaries?)");
			auth_server_connection_disconnect(conn,
				"incompatible server");
			return;
		}
		conn->version_received = TRUE;
	}

	input = conn->input;
	i_stream_ref(input);
	while ((line = i_stream_next_line(input)) != NULL && !input->closed) {
		T_BEGIN {
			ret = auth_server_connection_input_line(conn, line);
		} T_END;

		if (ret < 0) {
			auth_server_connection_disconnect(conn, t_strdup_printf(
				"Received broken input: %s", line));
			break;
		}
	}
	i_stream_unref(&input);
}
示例#14
0
static int
cmd_user_input(struct auth_master_connection *conn,
	       const struct authtest_input *input,
	       const char *show_field, bool userdb)
{
	const char *lookup_name = userdb ? "userdb lookup" : "passdb lookup";
	pool_t pool;
	const char *updated_username = NULL, *const *fields, *p;
	int ret;

	pool = pool_alloconly_create("auth master lookup", 1024);

	if (userdb) {
		ret = auth_master_user_lookup(conn, input->username, &input->info,
					      pool, &updated_username, &fields);
	} else {
		ret = auth_master_pass_lookup(conn, input->username, &input->info,
					      pool, &fields);
	}
	if (ret < 0) {
		if (fields[0] == NULL)
			i_error("%s failed for %s", lookup_name, input->username);
		else {
			i_error("%s failed for %s: %s", lookup_name,
				input->username, fields[0]);
		}
		ret = -1;
	} else if (ret == 0) {
		fprintf(show_field == NULL ? stdout : stderr,
			"%s: user %s doesn't exist\n", lookup_name,
			input->username);
	} else if (show_field != NULL) {
		unsigned int show_field_len = strlen(show_field);

		for (; *fields; fields++) {
			if (strncmp(*fields, show_field, show_field_len) == 0 &&
			    (*fields)[show_field_len] == '=')
				printf("%s\n", *fields + show_field_len + 1);
		}
	} else {
		printf("%s: %s\n", userdb ? "userdb" : "passdb", input->username);

		if (updated_username != NULL)
			printf("  %-10s: %s\n", "user", updated_username);
		for (; *fields; fields++) {
			p = strchr(*fields, '=');
			if (p == NULL)
				printf("  %-10s\n", *fields);
			else {
				printf("  %-10s: %s\n",
				       t_strcut(*fields, '='), p + 1);
			}
		}
	}
	return ret;
}
示例#15
0
bool password_scheme_is_alias(const char *scheme1, const char *scheme2)
{
	const struct password_scheme *s1 = NULL, *s2 = NULL;

	if (*scheme1 == '\0' || *scheme2 == '\0')
		return FALSE;

	scheme1 = t_strcut(scheme1, '.');
	scheme2 = t_strcut(scheme2, '.');

	if (strcasecmp(scheme1, scheme2) == 0)
		return TRUE;

	s1 = hash_table_lookup(password_schemes, scheme1);
	s2 = hash_table_lookup(password_schemes, scheme2);

	/* if they've the same generate function, they're equivalent */
	return s1 != NULL && s2 != NULL &&
		s1->password_generate == s2->password_generate;
}
示例#16
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);
}
static void
get_var_expand_users(struct var_expand_table *tab, const char *user)
{
	unsigned int i;

	tab[0].value = user;
	tab[1].value = t_strcut(user, '@');
	tab[2].value = strchr(user, '@');
	if (tab[2].value != NULL) tab[2].value++;

	for (i = 0; i < 3; i++)
		tab[i].value = str_sanitize(tab[i].value, 80);
}
示例#18
0
static void env_put_extra_fields(const char *extra_fields)
{
	const char *const *tmp;
	const char *key, *p;

	for (tmp = t_strsplit(extra_fields, "\t"); *tmp != NULL; tmp++) {
		key = t_str_ucase(t_strcut(*tmp, '='));
		p = strchr(*tmp, '=');
		if (p == NULL)
			env_put(t_strconcat(key, "=1", NULL));
		else
			env_put(t_strconcat(key, p, NULL));
	}
}
示例#19
0
文件: sysinfo-get.c 项目: bdraco/core
static const char *filesystem_get(const char *mail_location)
{
	struct mountpoint mp;
	const char *path;

	path = strchr(mail_location, ':');
	if (path == NULL)
		path = mail_location;
	else
		path = t_strcut(path + 1, ':');
	if (*path == '~') {
		/* we don't know where users' home dirs are */
		return "";
	}
	path = t_strcut(path, '%');
	if (strlen(path) <= 1)
		return "";

	/* all in all it seems we can support only /<path>/%u style location */
	if (mountpoint_get(path, pool_datastack_create(), &mp) < 0)
		return "";
	return mp.type == NULL ? "" : mp.type;
}
const char *mail_storage_service_fields_var_expand(const char *data,
						   const char *const *fields)
{
	const char *field_name = t_strcut(data, ':');
	unsigned int i, field_name_len;

	if (fields == NULL)
		return field_get_default(data);

	field_name_len = strlen(field_name);
	for (i = 0; fields[i] != NULL; i++) {
		if (strncmp(fields[i], field_name, field_name_len) == 0 &&
		    fields[i][field_name_len] == '=')
			return fields[i] + field_name_len+1;
	}
	return field_get_default(data);
}
示例#21
0
文件: acl-backend.c 项目: bdraco/core
struct acl_backend *
acl_backend_init(const char *data, struct mailbox_list *list,
		 const char *acl_username, const char *const *groups,
		 bool owner)
{
	struct mail_user *user = mailbox_list_get_user(list);
	struct acl_backend *backend;
	unsigned int i, group_count;

	if (user->mail_debug) {
		i_debug("acl: initializing backend with data: %s", data);
		i_debug("acl: acl username = %s", acl_username);
		i_debug("acl: owner = %d", owner ? 1 : 0);
	}

	group_count = str_array_length(groups);

	if (strncmp(data, "vfile:", 6) == 0)
		data += 6;
	else if (strcmp(data, "vfile") == 0)
		data = "";
	else
		i_fatal("Unknown ACL backend: %s", t_strcut(data, ':'));

	backend = acl_backend_vfile.alloc();
	backend->debug = user->mail_debug;
	backend->v = acl_backend_vfile;
	backend->list = list;
	backend->username = p_strdup(backend->pool, acl_username);
	backend->owner = owner;
	backend->globals_only =
		mail_user_plugin_getenv_bool(user, "acl_globals_only");

	if (group_count > 0) {
		backend->group_count = group_count;
		backend->groups =
			p_new(backend->pool, const char *, group_count);
		for (i = 0; i < group_count; i++) {
			backend->groups[i] = p_strdup(backend->pool, groups[i]);
			if (user->mail_debug)
				i_debug("acl: group added: %s", groups[i]);
		}
		i_qsort(backend->groups, group_count, sizeof(const char *),
			i_strcmp_p);
	}
示例#22
0
static void
login_host_callback(const struct ip_addr *ip, const char *hostname,
		    const char *errormsg, void *context)
{
	struct login_host_request *request = context;
	struct director *dir = request->conn->dir;
	const char *line, *line_params;
	unsigned int secs;

	if (ip == NULL) {
		if (strncmp(request->line, "OK\t", 3) == 0)
			line_params = request->line + 3;
		else if (strncmp(request->line, "PASS\t", 5) == 0)
			line_params = request->line + 5;
		else
			i_panic("BUG: Unexpected line: %s", request->line);

		i_error("director: User %s host lookup failed: %s",
			request->username, errormsg);
		line = t_strconcat("FAIL\t", t_strcut(line_params, '\t'),
				   "\ttemp", NULL);
	} else if (request->director_proxy_maybe &&
		   login_host_request_is_self(request, ip)) {
		line = request->line;
	} else {
		string_t *str = t_str_new(64);

		secs = dir->set->director_user_expire / 2;
		str_printfa(str, "%s\tproxy_refresh=%u\t", request->line, secs);
		if (hostname == NULL || hostname[0] == '\0')
			str_printfa(str, "host=%s", net_ip2addr(ip));
		else {
			str_printfa(str, "host=%s\thostip=%s",
				    hostname, net_ip2addr(ip));
		}
		line = str_c(str);
	}
	login_connection_send_line(request->conn, line);

	login_connection_unref(&request->conn);
	i_free(request->username);
	i_free(request->line);
	i_free(request);
}
示例#23
0
static void auth_worker_send_reply(struct auth_worker_client *client,
				   struct auth_request *request,
				   string_t *str)
{
	time_t cmd_duration = time(NULL) - client->cmd_start;
	const char *p;

	if (worker_restart_request)
		o_stream_nsend_str(client->output, "RESTART\n");
	o_stream_nsend(client->output, str_data(str), str_len(str));
	if (o_stream_nfinish(client->output) < 0 && request != NULL &&
	    cmd_duration > AUTH_WORKER_WARN_DISCONNECTED_LONG_CMD_SECS) {
		p = strchr(str_c(str), '\t');
		p = p == NULL ? "BUG" : t_strcut(p+1, '\t');

		i_warning("Auth master disconnected us while handling "
			  "request for %s for %ld secs (result=%s)",
			  request->user, (long)cmd_duration, p);
	}
}
示例#24
0
static int
master_service_apply_config_overrides(struct master_service *service,
				      struct setting_parser_context *parser,
				      const char **error_r)
{
	const char *const *overrides;
	unsigned int i, count;

	overrides = array_get(&service->config_overrides, &count);
	for (i = 0; i < count; i++) {
		if (settings_parse_line(parser, overrides[i]) < 0) {
			*error_r = t_strdup_printf(
				"Invalid -o parameter %s: %s", overrides[i],
				settings_parser_get_error(parser));
			return -1;
		}
		settings_parse_set_key_expandeded(parser, service->set_pool,
						  t_strcut(overrides[i], '='));
	}
	return 0;
}
示例#25
0
static void proxy_write_id(struct imap_client *client, string_t *str)
{
	i_assert(client->common.proxy_ttl > 1);

	str_append(str, "I ID (");
	if (client->common.client_id != NULL &&
	    str_len(client->common.client_id) > 0) {
		str_append_str(str, client->common.client_id);
		str_append_c(str, ' ');
	}
	str_printfa(str, "\"x-session-id\" \"%s\" "
		    "\"x-originating-ip\" \"%s\" "
		    "\"x-originating-port\" \"%u\" "
		    "\"x-connected-ip\" \"%s\" "
		    "\"x-connected-port\" \"%u\" "
		    "\"x-proxy-ttl\" \"%u\"",
		    client_get_session_id(&client->common),
		    net_ip2addr(&client->common.ip),
		    client->common.remote_port,
		    net_ip2addr(&client->common.local_ip),
		    client->common.local_port,
		    client->common.proxy_ttl - 1);

	/* append any forward_ variables to request */
	for(const char *const *ptr = client->common.auth_passdb_args; *ptr != NULL; ptr++) {
		if (strncasecmp(*ptr, "forward_", 8) == 0) {
			const char *key = t_strconcat("x-forward-",
						      t_strcut((*ptr)+8, '='),
						      NULL);
			const char *val = i_strchr_to_next(*ptr, '=');
			str_append_c(str, ' ');
			imap_append_string(str, key);
			str_append_c(str, ' ');
			imap_append_nstring(str, val);
		}
	}

	str_append(str, ")\r\n");
}
示例#26
0
文件: sysinfo-get.c 项目: bdraco/core
static bool lsb_distro_get(const char *path, const char **name_r)
{
	const char *data, *const *p, *str, *end;

	if (!readfile(path, &data))
		return FALSE;

	for (p = t_strsplit(data, "\n"); *p != NULL; p++) {
		if (strncmp(*p, "DISTRIB_DESCRIPTION=", 20) == 0)
			break;
	}
	if (*p == NULL)
		return FALSE;

	str = t_strcut(*p + 20, '\n');
	if (*str != '"')
		*name_r = str;
	else {
		end = strrchr(++str, '"');
		*name_r = str_unescape(p_strdup_until(unsafe_data_stack_pool,
						      str, end));
	}
	return TRUE;
}
示例#27
0
文件: script.c 项目: zatsepin/core
static bool client_exec_script(struct master_service_connection *conn)
{
	ARRAY_TYPE(const_string) envs;
	const char *const *args;
	string_t *input;
	void *buf;
	size_t prev_size, scanpos;
	bool header_complete = FALSE, noreply = FALSE;
	ssize_t ret;
	int status;
	pid_t pid;

	net_set_nonblock(conn->fd, FALSE);
	input = t_buffer_create(IO_BLOCK_SIZE);

	/* Input contains:

	   VERSION .. <lf>
	   [alarm=<secs> <lf>]
	   "noreply" | "-" (or anything really) <lf>

	   arg 1 <lf>
	   arg 2 <lf>
	   ...
	   <lf>
	   DATA

	   This is quite a horrible protocol. If alarm is specified, it MUST be
	   before "noreply". If "noreply" isn't given, something other string
	   (typically "-") must be given which is eaten away.
	*/		
	alarm(SCRIPT_READ_TIMEOUT_SECS);
	scanpos = 1;
	while (!header_complete) {
		const unsigned char *pos, *end;

		prev_size = input->used;
		buf = buffer_append_space_unsafe(input, IO_BLOCK_SIZE);

		/* peek in socket input buffer */
		ret = recv(conn->fd, buf, IO_BLOCK_SIZE, MSG_PEEK);
		if (ret <= 0) {
			buffer_set_used_size(input, prev_size);
			if (strchr(str_c(input), '\n') != NULL)
				script_verify_version(t_strcut(str_c(input), '\n'));

			if (ret < 0)
				i_fatal("recv(MSG_PEEK) failed: %m");

			i_fatal("recv(MSG_PEEK) failed: disconnected");
		}

		/* scan for final \n\n */
		pos = CONST_PTR_OFFSET(input->data, scanpos);
		end = CONST_PTR_OFFSET(input->data, prev_size + ret);
		for (; pos < end; pos++) {
			if (pos[-1] == '\n' && pos[0] == '\n') {
				header_complete = TRUE;
				pos++;
				break;
			}
		}
		scanpos = pos - (const unsigned char *)input->data;

		/* read data for real (up to and including \n\n) */
		ret = recv(conn->fd, buf, scanpos-prev_size, 0);
		if (prev_size+ret != scanpos) {
			if (ret < 0)
				i_fatal("recv() failed: %m");
			if (ret == 0)
				i_fatal("recv() failed: disconnected");
			i_fatal("recv() failed: size of definitive recv() differs from peek");
		}
		buffer_set_used_size(input, scanpos);
	}
	alarm(0);

	/* drop the last two LFs */
	buffer_set_used_size(input, scanpos-2);

	args = t_strsplit(str_c(input), "\n");
	script_verify_version(*args); args++;
	t_array_init(&envs, 16);
	if (*args != NULL) {
		const char *p;

		if (str_begins(*args, "alarm=")) {
			unsigned int seconds;
			if (str_to_uint(*args + 6, &seconds) < 0)
				i_fatal("invalid alarm option");
			alarm(seconds);
			args++;
		}
		while (str_begins(*args, "env_")) {
			const char *envname, *env;

			env = t_str_tabunescape(*args+4);
			p = strchr(env, '=');
			if (p == NULL)
				i_fatal("invalid environment variable");
			envname = t_strdup_until(*args+4, p);

			if (str_array_find(accepted_envs, envname))
				array_append(&envs, &env, 1);
			args++;
		}
		if (strcmp(*args, "noreply") == 0) {
			noreply = TRUE;
		}
		if (**args == '\0')
			i_fatal("empty options");
		args++;
	}
	array_append_zero(&envs);

	if (noreply) {
		/* no need to fork and check exit status */
		exec_child(conn, args, array_idx(&envs, 0));
		i_unreached();
	}

	if ((pid = fork()) == (pid_t)-1) {
		i_error("fork() failed: %m");
		return FALSE;
	}

	if (pid == 0) {
		/* child */
		exec_child(conn, args, array_idx(&envs, 0));
		i_unreached();
	}

	/* parent */

	/* check script exit status */
	if (waitpid(pid, &status, 0) < 0) {
		i_error("waitpid() failed: %m");
		return FALSE;
	} else if (WIFEXITED(status)) {
		ret = WEXITSTATUS(status);
		if (ret != 0) {
			i_error("Script terminated abnormally, exit status %d", (int)ret);
			return FALSE;
		}
	} else if (WIFSIGNALED(status)) {
		i_error("Script terminated abnormally, signal %d", WTERMSIG(status));
		return FALSE;
	} else if (WIFSTOPPED(status)) {
		i_fatal("Script stopped, signal %d", WSTOPSIG(status));
		return FALSE;
	} else {
		i_fatal("Script terminated abnormally, return status %d", status);
		return FALSE;
	}
	return TRUE;
}
示例#28
0
static void master_login_auth_input(struct master_login_auth *auth)
{
	const char *line;
	bool ret;

	switch (i_stream_read(auth->input)) {
	case 0:
		return;
	case -1:
		/* disconnected. stop accepting new connections, because in
		   default configuration we no longer have permissions to
		   connect back to auth-master */
		master_service_stop_new_connections(master_service);
		master_login_auth_disconnect(auth);
		return;
	case -2:
		/* buffer full */
		i_error("Auth server sent us too long line");
		master_login_auth_disconnect(auth);
		return;
	}

	if (!auth->version_received) {
		line = i_stream_next_line(auth->input);
		if (line == NULL)
			return;

		/* make sure the major version matches */
		if (strncmp(line, "VERSION\t", 8) != 0 ||
		    !str_uint_equals(t_strcut(line + 8, '\t'),
				     AUTH_MASTER_PROTOCOL_MAJOR_VERSION)) {
			i_error("Authentication server not compatible with "
				"master process (mixed old and new binaries?)");
			master_login_auth_disconnect(auth);
			return;
		}
		auth->version_received = TRUE;
	}
	if (!auth->spid_received) {
		line = i_stream_next_line(auth->input);
		if (line == NULL)
			return;

		if (strncmp(line, "SPID\t", 5) != 0 ||
		    str_to_pid(line + 5, &auth->auth_server_pid) < 0) {
			i_error("Authentication server didn't "
				"send valid SPID as expected: %s", line);
			master_login_auth_disconnect(auth);
			return;
		}
		auth->spid_received = TRUE;
		master_login_auth_check_spids(auth);
	}

	auth->refcount++;
	while ((line = i_stream_next_line(auth->input)) != NULL) {
		if (strncmp(line, "USER\t", 5) == 0)
			ret = master_login_auth_input_user(auth, line + 5);
		else if (strncmp(line, "NOTFOUND\t", 9) == 0)
			ret = master_login_auth_input_notfound(auth, line + 9);
		else if (strncmp(line, "FAIL\t", 5) == 0)
			ret = master_login_auth_input_fail(auth, line + 5);
		else
			ret = TRUE;

		if (!ret || auth->input == NULL) {
			master_login_auth_disconnect(auth);
			break;
		}
	}
	master_login_auth_unref(&auth);
}
示例#29
0
static void auth_input_line(const char *line, void *context)
{
	struct login_connection *conn = context;
	struct login_host_request *request, temp_request;
	const char *const *args, *line_params, *username = NULL, *tag = "";
	bool proxy = FALSE, host = FALSE;

	if (line == NULL) {
		/* auth connection died -> kill also this login connection */
		login_connection_deinit(&conn);
		return;
	}
	if (conn->type != LOGIN_CONNECTION_TYPE_USERDB &&
	    strncmp(line, "OK\t", 3) == 0)
		line_params = line + 3;
	else if (conn->type == LOGIN_CONNECTION_TYPE_USERDB &&
		 strncmp(line, "PASS\t", 5) == 0)
		line_params = line + 5;
	else {
		login_connection_send_line(conn, line);
		return;
	}

	/* OK <id> [<parameters>] */
	args = t_strsplit_tab(line_params);
	if (*args != NULL) {
		/* we should always get here, but in case we don't just
		   forward as-is and let login process handle the error. */
		args++;
	}

	memset(&temp_request, 0, sizeof(temp_request));
	for (; *args != NULL; args++) {
		if (strncmp(*args, "proxy", 5) == 0 &&
		    ((*args)[5] == '=' || (*args)[5] == '\0'))
			proxy = TRUE;
		else if (strncmp(*args, "host=", 5) == 0)
			host = TRUE;
		else if (strncmp(*args, "lip=", 4) == 0) {
			if (net_addr2ip((*args) + 4, &temp_request.local_ip) < 0)
				i_error("auth sent invalid lip field: %s", (*args) + 6);
		} else if (strncmp(*args, "lport=", 6) == 0) {
			if (str_to_uint((*args) + 6, &temp_request.local_port) < 0)
				i_error("auth sent invalid lport field: %s", (*args) + 6);
		} else if (strncmp(*args, "port=", 5) == 0) {
			if (str_to_uint((*args) + 5, &temp_request.dest_port) < 0)
				i_error("auth sent invalid port field: %s", (*args) + 6);
		} else if (strncmp(*args, "destuser="******"director_tag=", 13) == 0)
			tag = *args + 13;
		else if (strncmp(*args, "director_proxy_maybe", 20) == 0 &&
			 ((*args)[20] == '=' || (*args)[20] == '\0'))
			temp_request.director_proxy_maybe = TRUE;
		else if (strncmp(*args, "user=", 5) == 0) {
			if (username == NULL)
				username = *args + 5;
		}
	}
	if ((!proxy && !temp_request.director_proxy_maybe) ||
	    host || username == NULL) {
		login_connection_send_line(conn, line);
		return;
	}
	if (*conn->dir->set->master_user_separator != '\0') {
		/* with master user logins we still want to use only the
		   login username */
		username = t_strcut(username,
				    *conn->dir->set->master_user_separator);
	}

	/* we need to add the host. the lookup might be asynchronous */
	request = i_new(struct login_host_request, 1);
	*request = temp_request;
	request->conn = conn;
	request->line = i_strdup(line);
	request->username = i_strdup(username);

	conn->refcount++;
	director_request(conn->dir, username, tag, login_host_callback, request);
}
static int set_line(struct mail_storage_service_ctx *ctx,
		    struct mail_storage_service_user *user,
		    const char *line)
{
	struct setting_parser_context *set_parser = user->set_parser;
	bool mail_debug;
	const char *key, *orig_key, *append_value = NULL;
	unsigned int len;
	int ret;

	mail_debug = mail_user_set_get_mail_debug(user->user_info,
						  user->user_set);
	if (strchr(line, '=') == NULL)
		line = t_strconcat(line, "=yes", NULL);
	orig_key = key = t_strcut(line, '=');

	len = strlen(key);
	if (len > 0 && key[len-1] == '+') {
		/* key+=value */
		append_value = line + len + 1;
		key = t_strndup(key, len-1);
	}

	if (!settings_parse_is_valid_key(set_parser, key)) {
		/* assume it's a plugin setting */
		key = t_strconcat("plugin/", key, NULL);
		line = t_strconcat("plugin/", line, NULL);
	}

	if (master_service_set_has_config_override(ctx->service, key)) {
		/* this setting was already overridden with -o parameter */
		if (mail_debug) {
			i_debug("Ignoring overridden (-o) userdb setting: %s",
				key);
		}
		return 1;
	}

	if (append_value != NULL) {
		const void *value;
		enum setting_type type;

		value = settings_parse_get_value(set_parser, key, &type);
		if (type == SET_STR) {
			const char *const *strp = value;

			line = t_strdup_printf("%s=%s%s",
					       key, *strp, append_value);
		} else {
			i_error("Ignoring %s userdb setting. "
				"'+' can only be used for strings.", orig_key);
		}
	}

	ret = settings_parse_line(set_parser, line);
	if (mail_debug && ret >= 0) {
		if (strstr(key, "pass") != NULL) {
			/* possibly a password field (e.g. imapc_password).
			   hide the value. */
			line = t_strconcat(key, "=<hidden>", NULL);
		}
		i_debug(ret == 0 ?
			"Unknown userdb setting: %s" :
			"Added userdb setting: %s", line);
	}
	return ret;
}