Пример #1
0
bool passdb_cache_lookup_credentials(struct auth_request *request,
				     const char *key, const char **password_r,
				     const char **scheme_r,
				     enum passdb_result *result_r,
				     bool use_expired)
{
	const char *value, *const *list;
	struct auth_cache_node *node;
	bool neg_expired;

	if (passdb_cache == NULL)
		return FALSE;

	if (!passdb_cache_lookup(request, key, use_expired,
				 &node, &value, &neg_expired))
		return FALSE;

	if (*value == '\0') {
		/* negative cache entry */
		*result_r = PASSDB_RESULT_USER_UNKNOWN;
		*password_r = NULL;
		*scheme_r = NULL;
		return TRUE;
	}

	list = t_strsplit_tab(value);
	auth_request_set_fields(request, list + 1, NULL);

	*result_r = PASSDB_RESULT_OK;
	*password_r = *list[0] == '\0' ? NULL : list[0];
	*scheme_r = password_get_scheme(password_r);
	i_assert(*scheme_r != NULL || *password_r == NULL);
	return TRUE;
}
Пример #2
0
static void
credentials_checkpassword_callback(struct auth_request *request,
				   enum db_checkpassword_status status,
				   const char *const *extra_fields,
				   lookup_credentials_callback_t *callback)
{
	const char *scheme, *crypted_pass = NULL;
	unsigned int i;

	switch (status) {
	case DB_CHECKPASSWORD_STATUS_INTERNAL_FAILURE:
		callback(PASSDB_RESULT_INTERNAL_FAILURE, NULL, 0, request);
		return;
	case DB_CHECKPASSWORD_STATUS_FAILURE:
		callback(PASSDB_RESULT_USER_UNKNOWN, NULL, 0, request);
		return;
	case DB_CHECKPASSWORD_STATUS_OK:
		break;
	}
	for (i = 0; extra_fields[i] != NULL; i++) {
		if (strncmp(extra_fields[i], "password=", 9) == 0)
			crypted_pass = extra_fields[i]+9;
		else if (extra_fields[i][0] != '\0') {
			auth_request_set_field_keyvalue(request,
							extra_fields[i], NULL);
		}
	}
	scheme = password_get_scheme(&crypted_pass);
	if (scheme == NULL)
		scheme = request->credentials_scheme;

	passdb_handle_credentials(PASSDB_RESULT_OK, crypted_pass, scheme,
				  callback, request);
}
Пример #3
0
bool passdb_cache_verify_plain(struct auth_request *request, const char *key,
			       const char *password,
			       enum passdb_result *result_r, bool use_expired)
{
	const char *value, *cached_pw, *scheme, *const *list;
	struct auth_cache_node *node;
	int ret;
	bool neg_expired;

	if (passdb_cache == NULL || key == NULL)
		return FALSE;

	if (!passdb_cache_lookup(request, key, use_expired,
				 &node, &value, &neg_expired))
		return FALSE;

	if (*value == '\0') {
		/* negative cache entry */
		auth_request_log_unknown_user(request, AUTH_SUBSYS_DB);
		*result_r = PASSDB_RESULT_USER_UNKNOWN;
		return TRUE;
	}

	list = t_strsplit_tab(value);

	cached_pw = list[0];
	if (*cached_pw == '\0') {
		/* NULL password */
		auth_request_log_info(request, AUTH_SUBSYS_DB,
				      "Cached NULL password access");
		ret = 1;
	} else {
		scheme = password_get_scheme(&cached_pw);
		i_assert(scheme != NULL);

		ret = auth_request_password_verify(request, password, cached_pw,
						   scheme, AUTH_SUBSYS_DB);

		if (ret == 0 && (node->last_success || neg_expired)) {
			/* a) the last authentication was successful. assume
			   that the password was changed and cache is expired.
			   b) negative TTL reached, use it for password
			   mismatches too. */
			node->last_success = FALSE;
			return FALSE;
		}
	}
	node->last_success = ret > 0;

	/* save the extra_fields only after we know we're using the
	   cached data */
	auth_request_set_fields(request, list + 1, NULL);

	*result_r = ret > 0 ? PASSDB_RESULT_OK :
		PASSDB_RESULT_PASSWORD_MISMATCH;
	return TRUE;
}
Пример #4
0
static void
vpopmail_verify_plain(struct auth_request *request, const char *password,
		      verify_plain_callback_t *callback)
{
	enum passdb_result result;
	const char *scheme, *tmp_pass;
	char *crypted_pass;
	bool cleartext = FALSE;
	int ret;

	crypted_pass = vpopmail_password_lookup(request, &cleartext, &result);
	if (crypted_pass == NULL) {
		callback(result, request);
		return;
	}
	tmp_pass = crypted_pass;

	if (cleartext)
		scheme = "CLEARTEXT";
	else {
		scheme = password_get_scheme(&tmp_pass);
		if (scheme == NULL)
			scheme = request->passdb->passdb->default_pass_scheme;
	}

	ret = auth_request_password_verify(request, password, tmp_pass,
					   scheme, AUTH_SUBSYS_DB);
	safe_memset(crypted_pass, 0, strlen(crypted_pass));

	if (ret <= 0) {
		callback(PASSDB_RESULT_PASSWORD_MISMATCH, request);
		return;
	}

#ifdef POP_AUTH_OPEN_RELAY
	if (strcasecmp(request->service, "POP3") == 0 ||
	    strcasecmp(request->service, "IMAP") == 0) {
		const char *host = net_ip2addr(&request->remote_ip);
		/* vpopmail 5.4 does not understand IPv6 */
		if (host[0] != '\0' && IPADDR_IS_V4(&request->remote_ip)) {
			/* use putenv() directly rather than env_put() which
			   would leak memory every time we got here. use a
			   static buffer for putenv() as SUSv2 requirements
			   would otherwise corrupt our environment later. */
			static char ip_env[256];

			i_snprintf(ip_env, sizeof(ip_env),
				   "TCPREMOTEIP=%s", host);
			putenv(ip_env);
			open_smtp_relay();
		}
	}
#endif

	callback(PASSDB_RESULT_OK, request);
}
Пример #5
0
static void
ldap_lookup_finish(struct auth_request *auth_request,
		   struct passdb_ldap_request *ldap_request,
		   LDAPMessage *res)
{
	enum passdb_result passdb_result;
	const char *password = NULL, *scheme;
	int ret;

	if (res == NULL) {
		passdb_result = PASSDB_RESULT_INTERNAL_FAILURE;
	} else if (ldap_request->entries == 0) {
		passdb_result = PASSDB_RESULT_USER_UNKNOWN;
		auth_request_log_info(auth_request, "ldap",
				      "unknown user");
	} else if (ldap_request->entries > 1) {
		auth_request_log_error(auth_request, "ldap",
			"pass_filter matched multiple objects, aborting");
		passdb_result = PASSDB_RESULT_INTERNAL_FAILURE;
	} else if (auth_request->passdb_password == NULL &&
		   !auth_fields_exists(auth_request->extra_fields, "nopassword")) {
		auth_request_log_info(auth_request, "ldap",
			"No password returned (and no nopassword)");
		passdb_result = PASSDB_RESULT_PASSWORD_MISMATCH;
	} else {
		/* passdb_password may change on the way,
		   so we'll need to strdup. */
		password = t_strdup(auth_request->passdb_password);
		passdb_result = PASSDB_RESULT_OK;
	}

	scheme = password_get_scheme(&password);
	/* auth_request_set_field() sets scheme */
	i_assert(password == NULL || scheme != NULL);

	if (auth_request->credentials_scheme != NULL) {
		passdb_handle_credentials(passdb_result, password, scheme,
			ldap_request->callback.lookup_credentials,
			auth_request);
	} else {
		if (password != NULL) {
			ret = auth_request_password_verify(auth_request,
					auth_request->mech_password,
					password, scheme, "ldap");
			passdb_result = ret > 0 ? PASSDB_RESULT_OK :
				PASSDB_RESULT_PASSWORD_MISMATCH;
		}

		ldap_request->callback.verify_plain(passdb_result,
						    auth_request);
	}
}
Пример #6
0
static void passdb_dict_lookup_pass(struct passdb_dict_request *dict_request)
{
	struct auth_request *auth_request = dict_request->auth_request;
	struct passdb_module *_module = auth_request->passdb->passdb;
	struct dict_passdb_module *module =
		(struct dict_passdb_module *)_module;
	string_t *key;
	const char *password = NULL, *scheme = NULL;
	enum passdb_result passdb_result;
	int ret;

	key = t_str_new(512);
	str_append(key, DICT_PATH_SHARED);
	var_expand(key, module->conn->set.password_key,
		   auth_request_get_var_expand_table(auth_request, NULL));

	if (*module->conn->set.password_key == '\0') {
		auth_request_log_error(auth_request, "dict",
				       "password_key not specified");
		passdb_result = PASSDB_RESULT_INTERNAL_FAILURE;
	} else {
		passdb_result = passdb_dict_lookup_key(auth_request, module,
						       str_c(key));
	}

	if (passdb_result == PASSDB_RESULT_OK) {
		/* passdb_password may change on the way,
		   so we'll need to strdup. */
		password = t_strdup(auth_request->passdb_password);
		scheme = password_get_scheme(&password);
		/* auth_request_set_field() sets scheme */
		i_assert(password == NULL || scheme != NULL);
	}

	if (auth_request->credentials_scheme != NULL) {
		passdb_handle_credentials(passdb_result, password, scheme,
			dict_request->callback.lookup_credentials,
			auth_request);
	} else {
		if (password != NULL) {
			ret = auth_request_password_verify(auth_request,
					auth_request->mech_password,
					password, scheme, "dict");
			passdb_result = ret > 0 ? PASSDB_RESULT_OK :
				PASSDB_RESULT_PASSWORD_MISMATCH;
		}

		dict_request->callback.verify_plain(passdb_result,
						    auth_request);
	}
}
Пример #7
0
static void passdb_dict_lookup_pass(struct passdb_dict_request *dict_request)
{
    struct auth_request *auth_request = dict_request->auth_request;
    struct passdb_module *_module = auth_request->passdb->passdb;
    struct dict_passdb_module *module =
        (struct dict_passdb_module *)_module;
    const char *password = NULL, *scheme = NULL;
    enum passdb_result passdb_result;
    int ret;

    if (array_count(&module->conn->set.passdb_fields) == 0 &&
            array_count(&module->conn->set.parsed_passdb_objects) == 0) {
        auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
                               "No passdb_objects or passdb_fields specified");
        passdb_result = PASSDB_RESULT_INTERNAL_FAILURE;
    } else {
        passdb_result = passdb_dict_lookup_key(auth_request, module);
    }

    if (passdb_result == PASSDB_RESULT_OK) {
        /* passdb_password may change on the way,
           so we'll need to strdup. */
        password = t_strdup(auth_request->passdb_password);
        scheme = password_get_scheme(&password);
        /* auth_request_set_field() sets scheme */
        i_assert(password == NULL || scheme != NULL);
    }

    if (auth_request->credentials_scheme != NULL) {
        passdb_handle_credentials(passdb_result, password, scheme,
                                  dict_request->callback.lookup_credentials,
                                  auth_request);
    } else {
        if (password != NULL) {
            ret = auth_request_password_verify(auth_request,
                                               auth_request->mech_password,
                                               password, scheme, AUTH_SUBSYS_DB);
            passdb_result = ret > 0 ? PASSDB_RESULT_OK :
                            PASSDB_RESULT_PASSWORD_MISMATCH;
        }

        dict_request->callback.verify_plain(passdb_result,
                                            auth_request);
    }
}
Пример #8
0
static enum passdb_result
static_save_fields(struct auth_request *request, const char **password_r,
		   const char **scheme_r)
{
	struct static_passdb_module *module =
		(struct static_passdb_module *)request->passdb->passdb;
	const char *error;

	*password_r = NULL;
	*scheme_r = NULL;

	auth_request_log_debug(request, AUTH_SUBSYS_DB, "lookup");
	if (passdb_template_export(module->tmpl, request, &error) < 0) {
		auth_request_log_error(request, AUTH_SUBSYS_DB,
			"Failed to expand template: %s", error);
		return PASSDB_RESULT_INTERNAL_FAILURE;
	}

	if (module->static_password_tmpl != NULL) {
		if (t_auth_request_var_expand(module->static_password_tmpl,
				request, NULL, password_r, &error) <= 0) {
			auth_request_log_error(request, AUTH_SUBSYS_DB,
				"Failed to expand password=%s: %s",
				module->static_password_tmpl, error);
			return PASSDB_RESULT_INTERNAL_FAILURE;
		}
	} else if (auth_fields_exists(request->extra_fields, "nopassword")) {
		*password_r = "";
	} else {
		auth_request_log_info(request, AUTH_SUBSYS_DB,
			"No password returned (and no nopassword)");
		return PASSDB_RESULT_PASSWORD_MISMATCH;
	}

	*scheme_r = password_get_scheme(password_r);

	if (*scheme_r == NULL)
		*scheme_r = STATIC_PASS_SCHEME;

	auth_request_set_field(request, "password",
			       *password_r, *scheme_r);

	return PASSDB_RESULT_OK;
}
Пример #9
0
static void
auth_checkpassword_callback(struct auth_request *request,
			    enum db_checkpassword_status status,
			    const char *const *extra_fields,
			    verify_plain_callback_t *callback)
{
	const char *scheme, *crypted_pass = NULL;
	unsigned int i;

	switch (status) {
	case DB_CHECKPASSWORD_STATUS_INTERNAL_FAILURE:
		callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
		return;
	case DB_CHECKPASSWORD_STATUS_FAILURE:
		callback(PASSDB_RESULT_PASSWORD_MISMATCH, request);
		return;
	case DB_CHECKPASSWORD_STATUS_OK:
		break;
	}
	for (i = 0; extra_fields[i] != NULL; i++) {
		if (strncmp(extra_fields[i], "password="******"password",
					       crypted_pass, scheme);
		} else {
			auth_request_log_error(request, AUTH_SUBSYS_DB,
				"password field returned without {scheme} prefix");
		}
	}
	callback(PASSDB_RESULT_OK, request);
}
Пример #10
0
bool passdb_cache_lookup_credentials(struct auth_request *request,
				     const char *key, const char **password_r,
				     const char **scheme_r,
				     enum passdb_result *result_r,
				     bool use_expired)
{
	const char *value, *const *list;
	struct auth_cache_node *node;
	bool expired, neg_expired;

	if (passdb_cache == NULL)
		return FALSE;

	value = auth_cache_lookup(passdb_cache, request, key, &node,
				  &expired, &neg_expired);
	if (value == NULL || (expired && !use_expired)) {
		auth_request_log_debug(request, AUTH_SUBSYS_DB,
				       value == NULL ? "cache miss" :
				       "cache expired");
		return FALSE;
	}
	passdb_cache_log_hit(request, value);

	if (*value == '\0') {
		/* negative cache entry */
		*result_r = PASSDB_RESULT_USER_UNKNOWN;
		*password_r = NULL;
		*scheme_r = NULL;
		return TRUE;
	}

	list = t_strsplit_tab(value);
	auth_request_set_fields(request, list + 1, NULL);

	*result_r = PASSDB_RESULT_OK;
	*password_r = *list[0] == '\0' ? NULL : list[0];
	*scheme_r = password_get_scheme(password_r);
	i_assert(*scheme_r != NULL || *password_r == NULL);
	return TRUE;
}
Пример #11
0
static void passwd_file_save_results(struct auth_request *request,
                                     const struct passwd_user *pu,
                                     const char **crypted_pass_r,
                                     const char **scheme_r)
{
    const struct var_expand_table *table;
    const char *key, *value;
    string_t *str;
    char **p;

    *crypted_pass_r = pu->password != NULL ? pu->password : "";
    *scheme_r = password_get_scheme(crypted_pass_r);
    if (*scheme_r == NULL)
        *scheme_r = request->passdb->passdb->default_pass_scheme;

    /* save the password so cache can use it */
    auth_request_set_field(request, "password",
                           *crypted_pass_r, *scheme_r);

    if (pu->extra_fields != NULL) {
        str = t_str_new(512);
        table = auth_request_get_var_expand_table(request, NULL);

        for (p = pu->extra_fields; *p != NULL; p++) {
            value = strchr(*p, '=');
            if (value != NULL) {
                key = t_strdup_until(*p, value);
                str_truncate(str, 0);
                auth_request_var_expand_with_table(str, value + 1,
                                                   request, table, NULL);
                value = str_c(str);
            } else {
                key = *p;
                value = "";
            }
            auth_request_set_field(request, key, value, NULL);
        }
    }
}
Пример #12
0
static bool lookup_credentials_callback(const char *reply, void *context)
{
	struct auth_request *request = context;
	enum passdb_result result;
	const char *password = NULL, *scheme = NULL;

	result = auth_worker_reply_parse(request, reply);
	if (result == PASSDB_RESULT_OK && request->passdb_password != NULL) {
		password = request->passdb_password;
		scheme = password_get_scheme(&password);
		if (scheme == NULL) {
			auth_request_log_error(request, AUTH_SUBSYS_DB,
				"Received reply from worker without "
				"password scheme");
			result = PASSDB_RESULT_INTERNAL_FAILURE;
		}
	}

	passdb_handle_credentials(result, password, scheme,
				  auth_request_lookup_credentials_callback,
				  request);
	auth_request_unref(&request);
	return TRUE;
}
Пример #13
0
static void sql_query_callback(struct sql_result *result,
			       struct passdb_sql_request *sql_request)
{
	struct auth_request *auth_request = sql_request->auth_request;
	struct passdb_module *_module = auth_request->passdb->passdb;
	struct sql_passdb_module *module = (struct sql_passdb_module *)_module;
	enum passdb_result passdb_result;
	const char *password, *scheme;
	int ret;

	passdb_result = PASSDB_RESULT_INTERNAL_FAILURE;
	password = NULL;

	ret = sql_result_next_row(result);
	if (ret >= 0)
		db_sql_success(module->conn);
	if (ret < 0) {
		if (!module->conn->default_password_query) {
			auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
					       "Password query failed: %s",
					       sql_result_get_error(result));
		} else {
			auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
				"Password query failed: %s "
				"(using built-in default password_query: %s)",
				sql_result_get_error(result),
				module->conn->set.password_query);
		}
	} else if (ret == 0) {
		auth_request_log_unknown_user(auth_request, AUTH_SUBSYS_DB);
		passdb_result = PASSDB_RESULT_USER_UNKNOWN;
	} else {
		sql_query_save_results(result, sql_request);

		/* Note that we really want to check if the password field is
		   found. Just checking if password is set isn't enough,
		   because with proxies we might want to return NULL as
		   password. */
		if (sql_result_find_field(result, "password") < 0 &&
		    sql_result_find_field(result, "password_noscheme") < 0) {
			auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
				"Password query must return a field named "
				"'password'");
		} else if (sql_result_next_row(result) > 0) {
			auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
				"Password query returned multiple matches");
		} else if (auth_request->passdb_password == NULL &&
			   !auth_fields_exists(auth_request->extra_fields, "nopassword") &&
			   !auth_fields_exists(auth_request->extra_fields, "noauthenticate")) {
			auth_request_log_info(auth_request, AUTH_SUBSYS_DB,
				"Empty password returned without nopassword");
			passdb_result = PASSDB_RESULT_PASSWORD_MISMATCH;
		} else {
			/* passdb_password may change on the way,
			   so we'll need to strdup. */
			password = t_strdup(auth_request->passdb_password);
			passdb_result = PASSDB_RESULT_OK;
		}
	}

	scheme = password_get_scheme(&password);
	/* auth_request_set_field() sets scheme */
	i_assert(password == NULL || scheme != NULL);

	if (auth_request->credentials_scheme != NULL) {
		passdb_handle_credentials(passdb_result, password, scheme,
			sql_request->callback.lookup_credentials,
			auth_request);
		auth_request_unref(&auth_request);
		return;
	}

	/* verify plain */
	if (password == NULL) {
		sql_request->callback.verify_plain(passdb_result, auth_request);
		auth_request_unref(&auth_request);
		return;
	}

	ret = auth_request_password_verify(auth_request,
					   auth_request->mech_password,
					   password, scheme, AUTH_SUBSYS_DB);

	sql_request->callback.verify_plain(ret > 0 ? PASSDB_RESULT_OK :
					   PASSDB_RESULT_PASSWORD_MISMATCH,
					   auth_request);
	auth_request_unref(&auth_request);
}