Пример #1
0
static struct userdb_module *
passwd_file_preinit(pool_t pool, const char *args)
{
	struct passwd_file_userdb_module *module;
	const char *format = PASSWD_FILE_DEFAULT_USERNAME_FORMAT;
	const char *p;

	if (strncmp(args, "username_format=", 16) == 0) {
		args += 16;
		p = strchr(args, ' ');
		if (p == NULL) {
			format = p_strdup(pool, args);
			args = "";
		} else {
			format = p_strdup_until(pool, args, p);
			args = p + 1;
		}
	}

	if (*args == '\0')
		i_fatal("userdb passwd-file: Missing args");

	module = p_new(pool, struct passwd_file_userdb_module, 1);
	module->pwf = db_passwd_file_init(args, TRUE,
					  global_auth_settings->debug);
	module->username_format = format;
	return &module->module;
}
static int http_request_parse_target(struct http_request_parser *parser)
{
	struct http_message_parser *_parser = &parser->parser;
	const unsigned char *p = parser->parser.cur;

	/* We'll just parse anything up to the first SP or a control char.
	   We could also implement workarounds for buggy HTTP clients and
	   parse anything up to the HTTP-version and return 301 with the
	   target properly encoded (FIXME). */
	while (p < _parser->end && *p > ' ')
		p++;

	/* target is too long when explicit limit is exceeded or when input buffer
	   runs out of space */
	/* FIXME: put limit on full request line rather than target and method
	   separately */
	/* FIXME: is it wise to keep target in stream buffer? It can become very
	   large for some applications, increasing the stream buffer size */
	if ((uoff_t)(p - _parser->cur) > parser->max_target_length ||
		(p == _parser->end && ((uoff_t)(p - _parser->cur) >=
			i_stream_get_max_buffer_size(_parser->input)))) {
		parser->error_code = HTTP_REQUEST_PARSE_ERROR_TARGET_TOO_LONG;
		parser->parser.error = "HTTP request target is too long";
		return -1;
	}
	if (p == _parser->end)
		return 0;
	parser->request_target = p_strdup_until(_parser->msg.pool, _parser->cur, p);
	parser->parser.cur = p;
	return 1;
}
static void
mail_filter_parse_setting(struct mail_user *user, const char *name,
			  const char **socket_path_r, const char **args_r)
{
	const char *value, *p;

	value = mail_user_plugin_getenv(user, name);
	if (value == NULL)
		return;

	p = strchr(value, ' ');
	if (p == NULL) {
		*socket_path_r = p_strdup(user->pool, value);
		*args_r = "";
	} else {
		*socket_path_r = p_strdup_until(user->pool, value, p);
		*args_r = p_strdup(user->pool, p + 1);
	}
	if (**socket_path_r != '/') {
		/* relative to base_dir */
		*socket_path_r = p_strdup_printf(user->pool, "%s/%s",
			user->set->base_dir, *socket_path_r);
	}
	if (user->mail_debug) {
		i_debug("mail_filter: Filtering %s via socket %s",
			name, *socket_path_r);
	}
}
Пример #4
0
const char *p_str_rtrim(pool_t pool, const char *str, const char *chars)
{
	const char *begin, *end;

	str_trim_parse(str, chars, STR_TRIM_RIGHT, &begin, &end);
	if (begin == NULL)
		return "";
	return p_strdup_until(pool, begin, end);
}
static int http_request_parse_method(struct http_request_parser *parser)
{
	const unsigned char *p = parser->parser.cur;

	/* method         = token
	 */
	while (p < parser->parser.end && http_char_is_token(*p))
		p++;

	if ((p - parser->parser.cur) > HTTP_REQUEST_PARSER_MAX_METHOD_LENGTH) {
		parser->error_code = HTTP_REQUEST_PARSE_ERROR_METHOD_TOO_LONG;
		parser->parser.error = "HTTP request method is too long";
		return -1;
	}
	if (p == parser->parser.end)
		return 0;
	parser->request_method =
		p_strdup_until(parser->parser.msg.pool, parser->parser.cur, p);
	parser->parser.cur = p;
	return 1;
}
Пример #6
0
int str_unescape_next(const char **str, const char **unescaped_r)
{
	const char *p;
	char *escaped;
	bool esc_found = FALSE;

	for (p = *str; *p != '\0'; p++) {
		if (*p == '"')
			break;
		else if (*p == '\\') {
			if (p[1] == '\0')
				return -1;
			esc_found = TRUE;
			p++;
		}
	}
	if (*p != '"')
		return -1;
	escaped = p_strdup_until(unsafe_data_stack_pool, *str, p);
	*str = p+1;
	*unescaped_r = !esc_found ? escaped : str_unescape(escaped);
	return 0;
}
Пример #7
0
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;
}
Пример #8
0
static int
maildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
			 const char **value_r)
{
	struct index_mail *mail = (struct index_mail *)_mail;
	struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box;
	const char *path, *fname = NULL, *end, *guid, *uidl, *order;
	struct stat st;

	switch (field) {
	case MAIL_FETCH_GUID:
		/* use GUID from uidlist if it exists */
		i_assert(!_mail->saving);

		if (mail->data.guid != NULL) {
			*value_r = mail->data.guid;
			return 0;
		}

		/* first make sure that we have a refreshed uidlist */
		if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0)
			return -1;

		guid = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
						  MAILDIR_UIDLIST_REC_EXT_GUID);
		if (guid != NULL) {
			if (*guid != '\0') {
				*value_r = mail->data.guid =
					p_strdup(mail->mail.data_pool, guid);
				return 0;
			}

			mail_storage_set_critical(_mail->box->storage,
				"Maildir %s: Corrupted dovecot-uidlist: "
				"UID %u had empty GUID, clearing it",
				mailbox_get_path(_mail->box), _mail->uid);
			maildir_uidlist_unset_ext(mbox->uidlist, _mail->uid,
				MAILDIR_UIDLIST_REC_EXT_GUID);
		}

		/* default to base filename: */
		if (maildir_mail_get_special(_mail, MAIL_FETCH_STORAGE_ID,
					     value_r) < 0)
			return -1;
		mail->data.guid = mail->data.filename;
		return 0;
	case MAIL_FETCH_STORAGE_ID:
		if (mail->data.filename != NULL) {
			*value_r = mail->data.filename;
			return 0;
		}
		if (fname != NULL) {
			/* we came here from MAIL_FETCH_GUID,
			   avoid a second lookup */
		} else if (!_mail->saving) {
			if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0)
				return -1;
		} else {
			path = maildir_save_file_get_path(_mail->transaction,
							  _mail->seq);
			fname = strrchr(path, '/');
			fname = fname != NULL ? fname + 1 : path;
		}
		end = strchr(fname, MAILDIR_INFO_SEP);
		mail->data.filename = end == NULL ?
			p_strdup(mail->mail.data_pool, fname) :
			p_strdup_until(mail->mail.data_pool, fname, end);
		*value_r = mail->data.filename;
		return 0;
	case MAIL_FETCH_UIDL_BACKEND:
		uidl = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
					MAILDIR_UIDLIST_REC_EXT_POP3_UIDL);
		if (uidl == NULL) {
			/* use the default */
			*value_r = "";
		} else if (*uidl == '\0') {
			/* special optimization case: use the base file name */
			return maildir_mail_get_special(_mail,
					MAIL_FETCH_STORAGE_ID, value_r);
		} else {
			*value_r = p_strdup(mail->mail.data_pool, uidl);
		}
		return 0;
	case MAIL_FETCH_POP3_ORDER:
		order = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
					MAILDIR_UIDLIST_REC_EXT_POP3_ORDER);
		if (order == NULL) {
			*value_r = "";
		} else {
			*value_r = p_strdup(mail->mail.data_pool, order);
		}
		return 0;
	case MAIL_FETCH_REFCOUNT:
		if (maildir_mail_stat(_mail, &st) < 0)
			return -1;
		*value_r = p_strdup_printf(mail->mail.data_pool, "%lu",
					   (unsigned long)st.st_nlink);
		return 0;
	default:
		return index_mail_get_special(_mail, field, value_r);
	}
}
Пример #9
0
bool imap_fetch_binary_init(struct imap_fetch_init_context *ctx)
{
	struct imap_fetch_body_data *body;
	const struct imap_arg *list_args;
	unsigned int list_count;
	const char *str, *p, *error;

	i_assert(strncmp(ctx->name, "BINARY", 6) == 0);
	p = ctx->name + 6;

	body = p_new(ctx->pool, struct imap_fetch_body_data, 1);
	body->binary = TRUE;

	if (strncmp(p, ".SIZE", 5) == 0) {
		/* fetch decoded size of the section */
		p += 5;
		body->binary_size = TRUE;
	} else if (strncmp(p, ".PEEK", 5) == 0) {
		p += 5;
	} else {
		ctx->fetch_ctx->flags_update_seen = TRUE;
	}
	if (*p != '[') {
		ctx->error = "Invalid BINARY[..] parameter: Missing '['";
		return FALSE;
	}

	if (imap_arg_get_list_full(&ctx->args[0], &list_args, &list_count)) {
		/* BINARY[HEADER.FIELDS.. (headers list)] */
		if (!imap_arg_get_atom(&ctx->args[1], &str) ||
		    str[0] != ']') {
			ctx->error = "Invalid BINARY[..] parameter: Missing ']'";
			return FALSE;
		}
		if (body_header_fields_parse(ctx, body, p+1,
					     list_args, list_count) < 0)
			return FALSE;
		p = str+1;
		ctx->args += 2;
	} else {
		/* no headers list */
		body->section = p+1;
		p = strchr(body->section, ']');
		if (p == NULL) {
			ctx->error = "Invalid BINARY[..] parameter: Missing ']'";
			return FALSE;
		}
		body->section = p_strdup_until(ctx->pool, body->section, p);
		p++;
	}
	if (imap_msgpart_parse(body->section, &body->msgpart) < 0) {
		ctx->error = "Invalid BINARY[..] section";
		return FALSE;
	}
	imap_msgpart_set_decode_to_binary(body->msgpart);
	ctx->fetch_ctx->fetch_data |=
		imap_msgpart_get_fetch_data(body->msgpart);

	if (!body->binary_size) {
		if (body_parse_partial(body, p, &error) < 0) {
			ctx->error = p_strdup_printf(ctx->pool,
				"Invalid BINARY[..] parameter: %s", error);
			return FALSE;
		}
	}

	/* update the section name for the imap_fetch_add_handler() */
	ctx->name = p_strdup(ctx->pool, get_body_name(body));
	if (body->binary_size) {
		imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_WANT_DEINIT,
				       "0", fetch_binary_size, body);
	} else {
		imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_WANT_DEINIT,
				       "NIL", fetch_body_msgpart, body);
	}
	return TRUE;
}
Пример #10
0
static void
mech_apop_auth_initial(struct auth_request *auth_request,
		       const unsigned char *data, size_t data_size)
{
	struct apop_auth_request *request =
		(struct apop_auth_request *)auth_request;
	const unsigned char *tmp, *end, *username = NULL;
	unsigned long pid, connect_uid, timestamp;
	const char *error;

	/* pop3-login handles sending the challenge and getting the response.
	   Our input here is: <challenge> \0 <username> \0 <response> */

	if (data_size == 0) {
		/* Should never happen */
		auth_request_log_info(auth_request, "apop",
				      "no initial respone");
		auth_request_fail(auth_request);
		return;
	}

	tmp = data;
	end = data + data_size;

	/* get the challenge */
	while (tmp != end && *tmp != '\0')
		tmp++;
	request->challenge = p_strdup_until(request->pool, data, tmp);

	if (tmp != end) {
		/* get the username */
		username = ++tmp;
		while (tmp != end && *tmp != '\0')
			tmp++;
	}

	if (tmp + 1 + 16 != end) {
		/* Should never happen */
		auth_request_log_info(auth_request, "apop", "malformed data");
		auth_request_fail(auth_request);
		return;
	}
	memcpy(request->response_digest, tmp + 1,
	       sizeof(request->response_digest));

	/* the challenge must begin with trusted unique ID. we trust only
	   ourself, so make sure it matches our connection specific UID
	   which we told to client in handshake. Also require a timestamp
	   which is later than this process's start time. */

	if (sscanf(request->challenge, "<%lx.%lx.%lx.",
		   &pid, &connect_uid, &timestamp) != 3 ||
	    connect_uid != auth_request->connect_uid ||
            pid != (unsigned long)getpid() ||
	    (time_t)timestamp < process_start_time) {
		auth_request_log_info(auth_request, "apop",
				      "invalid challenge");
		auth_request_fail(auth_request);
		return;
	}

	if (!auth_request_set_username(auth_request, (const char *)username,
				       &error)) {
		auth_request_log_info(auth_request, "apop", "%s", error);
		auth_request_fail(auth_request);
		return;
	}

	auth_request_lookup_credentials(auth_request, "PLAIN",
					apop_credentials_callback);
}
Пример #11
0
static int
virtual_config_parse_line(struct virtual_parse_context *ctx, const char *line,
                          const char **error_r)
{
    struct mail_user *user = ctx->mbox->storage->storage.user;
    struct virtual_backend_box *bbox;
    const char *p;
    bool no_wildcards = FALSE;

    if (*line == ' ' || *line == '\t') {
        /* continues the previous search rule */
        if (ctx->rule_idx == array_count(&ctx->mbox->backend_boxes)) {
            *error_r = "Search rule without a mailbox";
            return -1;
        }
        while (*line == ' ' || *line == '\t') line++;
        str_append_c(ctx->rule, ' ');
        str_append(ctx->rule, line);
        return 0;
    }
    /* if there is no rule yet, it means we want the previous mailboxes
       to use the rule that comes later */
    if (str_len(ctx->rule) > 0) {
        if (virtual_config_add_rule(ctx, error_r) < 0)
            return -1;
    }
    if (!uni_utf8_str_is_valid(line)) {
        *error_r = t_strdup_printf("Mailbox name not UTF-8: %s",
                                   line);
        return -1;
    }

    /* new mailbox. the search args are added to it later. */
    bbox = p_new(ctx->pool, struct virtual_backend_box, 1);
    bbox->virtual_mbox = ctx->mbox;
    if (strcasecmp(line, "INBOX") == 0)
        line = "INBOX";
    bbox->name = p_strdup(ctx->pool, line);
    switch (bbox->name[0]) {
    case '+':
        bbox->name++;
        bbox->clear_recent = TRUE;
        break;
    case '-':
        bbox->name++;
        bbox->negative_match = TRUE;
        break;
    case '!':
        /* save messages here */
        if (ctx->mbox->save_bbox != NULL) {
            *error_r = "Multiple save mailboxes defined";
            return -1;
        }
        bbox->name++;
        ctx->mbox->save_bbox = bbox;
        no_wildcards = TRUE;
        break;
    }
    if (bbox->name[0] == '/') {
        /* [+-!]/metadata entry:value */
        if ((p = strchr(bbox->name, ':')) == NULL) {
            *error_r = "':' separator missing between metadata entry name and value";
            return -1;
        }
        bbox->metadata_entry = p_strdup_until(ctx->pool, bbox->name, p++);
        bbox->metadata_value = p;
        if (!imap_metadata_verify_entry_name(bbox->metadata_entry, error_r))
            return -1;
        no_wildcards = TRUE;
    }

    if (!no_wildcards &&
            (strchr(bbox->name, '*') != NULL ||
             strchr(bbox->name, '%') != NULL)) {
        bbox->glob = imap_match_init(ctx->pool, bbox->name, TRUE, ctx->sep);
        ctx->have_wildcards = TRUE;
    }
    if (bbox->metadata_entry == NULL) {
        /* now that the prefix characters have been processed,
           find the namespace */
        bbox->ns = strcasecmp(bbox->name, "INBOX") == 0 ?
                   mail_namespace_find_inbox(user->namespaces) :
                   mail_namespace_find(user->namespaces, bbox->name);
        if (bbox->ns == NULL) {
            *error_r = t_strdup_printf("Namespace not found for %s",
                                       bbox->name);
            return -1;
        }
        if (strcmp(bbox->name, ctx->mbox->box.vname) == 0) {
            *error_r = "Virtual mailbox can't point to itself";
            return -1;
        }
        ctx->have_mailbox_defines = TRUE;
    }

    array_append(&ctx->mbox->backend_boxes, &bbox, 1);
    return 0;
}
Пример #12
0
const char *t_strdup_until(const void *start, const void *end)
{
	return p_strdup_until(unsafe_data_stack_pool, start, end);
}
Пример #13
0
static int smtp_parse_ehlo_line(struct smtp_parser *parser,
	const char **key_r, const char *const **params_r)
{
	const unsigned char *pbegin = parser->cur;
	ARRAY_TYPE(const_string) params = ARRAY_INIT;
	const char *param;

	/*
	   ehlo-line      = ehlo-keyword *( SP ehlo-param )
	   ehlo-keyword   = (ALPHA / DIGIT) *(ALPHA / DIGIT / "-")
	                    ; additional syntax of ehlo-params depends on
	                    ; ehlo-keyword
	   ehlo-param     = 1*(%d33-126)
	                    ; any CHAR excluding <SP> and all
	                    ; control characters (US-ASCII 0-31 and 127
	                    ; inclusive)
	 */

	if (parser->cur >= parser->end || !i_isalnum(*parser->cur)) {
		parser->error = "Unexpected character in EHLO keyword";
		return -1;
	}
	parser->cur++;

	while (parser->cur < parser->end &&
		(i_isalnum(*parser->cur) || *parser->cur == '-'))
		parser->cur++;

	if (key_r != NULL)
		*key_r = p_strdup_until(parser->pool, pbegin, parser->cur);

	if (parser->cur >= parser->end) {
		if (params_r != NULL)
			*params_r = p_new(parser->pool, const char *, 1);
		return 1;
	}
	if (*parser->cur != ' ') {
		parser->error = "Unexpected character in EHLO keyword";
		return -1;
	}
	parser->cur++;

	pbegin = parser->cur;
	if (params_r != NULL)
		p_array_init(&params, parser->pool, 32);
	while (parser->cur < parser->end) {
		if (*parser->cur == ' ') {
			if (parser->cur+1 >= parser->end || *(parser->cur+1) == ' ') {
				parser->error = "Missing EHLO parameter after ' '";
				return -1;
			}
			if (params_r != NULL) {
				param = p_strdup_until(parser->pool, pbegin, parser->cur);
				array_append(&params, &param, 1);
			}
			pbegin = parser->cur + 1;
		} else if (!smtp_char_is_ehlo_param(*parser->cur)) {
			parser->error = "Unexpected character in EHLO parameter";
			return -1;
		}
		parser->cur++;
	}

	if (params_r != NULL) {
		array_append_zero(&params);
		*params_r = array_idx(&params, 0);
	}
	return 1;
}
Пример #14
0
const char *message_id_get_next(const char **msgid_p)
{
	const char *msgid = *msgid_p;
	const char *p;
	string_t *str = NULL;
	bool found_at;

	if (*msgid_p == NULL)
		return NULL;

	for (;;) {
		/* skip until '<' */
		while (*msgid != '<') {
			if (*msgid == '\0') {
				*msgid_p = msgid;
				return NULL;
			}
			msgid++;
		}
		msgid++;

		/* check it through quickly to see if it's already normalized */
		p = msgid; found_at = FALSE;
		for (;; p++) {
			if ((unsigned char)*p >= 'A') /* matches most */
				continue;

			if (*p == '@')
				found_at = TRUE;
			if (*p == '>' || *p == '"' || *p == '(' || *p == '[')
				break;

			if (*p == '\0') {
				*msgid_p = p;
				return NULL;
			}
		}

		if (*p == '>') {
			*msgid_p = p+1;
			if (found_at) {
				char *s;

				s = p_strdup_until(unsafe_data_stack_pool,
						   msgid, p);
				strip_lwsp(s);
				return s;
			}
		} else {
			/* ok, do it the slow way */
			*msgid_p = msgid;

			if (str == NULL) {
				/* allocate only once, so we don't leak
				   with multiple invalid message IDs */
				str = t_str_new(256);
			}
			if (get_untokenized_msgid(msgid_p, str))
				return str_c(str);
		}

		/* invalid message id, see if there's another valid one */
		msgid = *msgid_p;
	}
}
Пример #15
0
char *i_strdup_until(const void *str, const void *end)
{
	return p_strdup_until(default_pool, str, end);
}