changeset 3171:8a3b57385eca HEAD

Added state variable for auth_request and several assertions to make sure the state is always valid. Fixed assert crash when a user having cached passdb entry expired tried to authenticate.
author Timo Sirainen <tss@iki.fi>
date Sat, 05 Mar 2005 13:48:13 +0200
parents 42e1e9dbf19e
children b951764080cc
files src/auth/auth-request-handler.c src/auth/auth-request.c src/auth/auth-request.h src/auth/passdb-blocking.c src/auth/passdb-cache.c src/auth/passdb-cache.h
diffstat 6 files changed, 59 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/auth-request-handler.c	Sat Mar 05 12:25:09 2005 +0200
+++ b/src/auth/auth-request-handler.c	Sat Mar 05 13:48:13 2005 +0200
@@ -384,6 +384,10 @@
         struct auth_request_handler *handler = request->context;
 	string_t *reply;
 
+	i_assert(request->state == AUTH_REQUEST_STATE_USERDB);
+
+	request->state = AUTH_REQUEST_STATE_FINISHED;
+
 	reply = t_str_new(256);
 	if (handler->prepend_connect_uid)
 		str_printfa(reply, "%u\t", request->connect_uid);
@@ -422,7 +426,8 @@
 	auth_request_ref(request);
 	auth_request_handler_remove(handler, request);
 
-	if (!request->successful) {
+	if (request->state != AUTH_REQUEST_STATE_FINISHED ||
+	    !request->successful) {
 		i_error("Master requested unfinished authentication request "
 			"%u.%u", handler->client_pid, client_id);
 		str_printfa(reply, "NOTFOUND\t%u", id);
@@ -431,6 +436,7 @@
 		/* the request isn't being referenced anywhere anymore,
 		   so we can do a bit of kludging.. replace the request's
 		   old client_id with master's id. */
+		request->state = AUTH_REQUEST_STATE_USERDB;
 		request->id = id;
 		request->context = handler;
 
@@ -449,6 +455,7 @@
 	size /= sizeof(*auth_request);
 
 	for (i = 0; i < size; i++) {
+		i_assert(auth_request[i]->state == AUTH_REQUEST_STATE_FINISHED);
 		auth_request[i]->callback(auth_request[i],
 					  AUTH_CLIENT_RESULT_FAILURE, NULL, 0);
 		auth_request_unref(auth_request[i]);
--- a/src/auth/auth-request.c	Sat Mar 05 12:25:09 2005 +0200
+++ b/src/auth/auth-request.c	Sat Mar 05 13:48:13 2005 +0200
@@ -23,6 +23,7 @@
 	struct auth_request *request;
 
 	request = mech->auth_new();
+	request->state = AUTH_REQUEST_STATE_NEW;
 
 	request->refcount = 1;
 	request->created = ioloop_time;
@@ -37,9 +38,9 @@
 void auth_request_success(struct auth_request *request,
 			  const void *data, size_t data_size)
 {
-	i_assert(!request->finished);
-	request->finished = TRUE;
+	i_assert(request->state == AUTH_REQUEST_STATE_MECH_CONTINUE);
 
+	request->state = AUTH_REQUEST_STATE_FINISHED;
 	request->successful = TRUE;
 	request->callback(request, AUTH_CLIENT_RESULT_SUCCESS,
 			  data, data_size);
@@ -47,9 +48,9 @@
 
 void auth_request_fail(struct auth_request *request)
 {
-	i_assert(!request->finished);
-	request->finished = TRUE;
+	i_assert(request->state == AUTH_REQUEST_STATE_MECH_CONTINUE);
 
+	request->state = AUTH_REQUEST_STATE_FINISHED;
 	request->callback(request, AUTH_CLIENT_RESULT_FAILURE, NULL, 0);
 }
 
@@ -89,12 +90,17 @@
 void auth_request_initial(struct auth_request *request,
 			  const unsigned char *data, size_t data_size)
 {
+	i_assert(request->state == AUTH_REQUEST_STATE_NEW);
+
+	request->state = AUTH_REQUEST_STATE_MECH_CONTINUE;
 	request->mech->auth_initial(request, data, data_size);
 }
 
 void auth_request_continue(struct auth_request *request,
 			   const unsigned char *data, size_t data_size)
 {
+	i_assert(request->state == AUTH_REQUEST_STATE_MECH_CONTINUE);
+
 	request->mech->auth_continue(request, data, data_size);
 }
 
@@ -149,7 +155,10 @@
 					struct auth_request *request)
 {
 	const char *cache_key;
-	int expired;
+
+	i_assert(request->state == AUTH_REQUEST_STATE_PASSDB);
+
+	request->state = AUTH_REQUEST_STATE_MECH_CONTINUE;
 
         auth_request_save_cache(request, result);
 
@@ -161,7 +170,7 @@
 		   expired record. */
 		if (passdb_cache_verify_plain(request, cache_key,
 					      request->mech_password,
-					      &result, &expired)) {
+					      &result, TRUE)) {
 			request->private_callback.verify_plain(result, request);
 			safe_memset(request->mech_password, 0,
 				    strlen(request->mech_password));
@@ -193,7 +202,8 @@
 	struct passdb_module *passdb = request->auth->passdb;
 	enum passdb_result result;
 	const char *cache_key;
-	int expired;
+
+	i_assert(request->state == AUTH_REQUEST_STATE_MECH_CONTINUE);
 
 	request->mech_password = p_strdup(request->pool, password);
 	request->private_callback.verify_plain = callback;
@@ -201,12 +211,14 @@
 	cache_key = passdb_cache == NULL ? NULL : passdb->cache_key;
 	if (cache_key != NULL) {
 		if (passdb_cache_verify_plain(request, cache_key, password,
-					      &result, &expired) && !expired) {
+					      &result, FALSE)) {
 			callback(result, request);
 			return;
 		}
 	}
 
+	request->state = AUTH_REQUEST_STATE_PASSDB;
+
 	if (passdb->blocking)
 		passdb_blocking_verify_plain(request);
 	else {
@@ -220,8 +232,10 @@
 					      struct auth_request *request)
 {
 	const char *cache_key, *scheme;
-	int expired;
 
+	i_assert(request->state == AUTH_REQUEST_STATE_PASSDB);
+
+	request->state = AUTH_REQUEST_STATE_MECH_CONTINUE;
         auth_request_save_cache(request, result);
 
 	if (request->passdb_password != NULL) {
@@ -237,7 +251,7 @@
 		   expired record. */
 		if (passdb_cache_lookup_credentials(request, cache_key,
 						    &credentials, &scheme,
-						    &expired)) {
+						    TRUE)) {
 			passdb_handle_credentials(credentials != NULL ?
 				PASSDB_RESULT_OK : PASSDB_RESULT_USER_UNKNOWN,
 				request->credentials, credentials, scheme,
@@ -257,13 +271,13 @@
 {
 	struct passdb_module *passdb = request->auth->passdb;
 	const char *cache_key, *result, *scheme;
-	int expired;
+
+	i_assert(request->state == AUTH_REQUEST_STATE_MECH_CONTINUE);
 
 	cache_key = passdb_cache == NULL ? NULL : passdb->cache_key;
 	if (cache_key != NULL) {
 		if (passdb_cache_lookup_credentials(request, cache_key,
-						    &result, &scheme,
-						    &expired) && !expired) {
+						    &result, &scheme, FALSE)) {
 			passdb_handle_credentials(result != NULL ?
 						  PASSDB_RESULT_OK :
 						  PASSDB_RESULT_USER_UNKNOWN,
@@ -273,6 +287,7 @@
 		}
 	}
 
+	request->state = AUTH_REQUEST_STATE_PASSDB;
 	request->credentials = credentials;
 	request->private_callback.lookup_credentials = callback;
 
--- a/src/auth/auth-request.h	Sat Mar 05 12:25:09 2005 +0200
+++ b/src/auth/auth-request.h	Sat Mar 05 13:48:13 2005 +0200
@@ -8,10 +8,19 @@
 
 struct auth_client_connection;
 
+enum auth_request_state {
+	AUTH_REQUEST_STATE_NEW,
+	AUTH_REQUEST_STATE_PASSDB,
+	AUTH_REQUEST_STATE_MECH_CONTINUE,
+	AUTH_REQUEST_STATE_FINISHED,
+	AUTH_REQUEST_STATE_USERDB
+};
+
 struct auth_request {
 	int refcount;
 
 	pool_t pool;
+        enum auth_request_state state;
 	char *user;
 	char *mech_password; /* set if verify_plain() is called */
 	char *passdb_password; /* set after password lookup if successful */
@@ -40,7 +49,6 @@
 
 	unsigned int successful:1;
 	unsigned int internal_failure:1;
-	unsigned int finished:1;
 	unsigned int delayed_failure:1;
 	unsigned int accept_input:1;
 	unsigned int no_failure_delay:1;
--- a/src/auth/passdb-blocking.c	Sat Mar 05 12:25:09 2005 +0200
+++ b/src/auth/passdb-blocking.c	Sat Mar 05 13:48:13 2005 +0200
@@ -87,6 +87,8 @@
 {
 	string_t *str;
 
+	i_assert(request->extra_fields == NULL);
+
 	str = t_str_new(64);
 	str_append(str, "PASSV\t");
 	str_append(str, request->mech_password);
@@ -118,6 +120,8 @@
 {
 	string_t *str;
 
+	i_assert(request->extra_fields == NULL);
+
 	str = t_str_new(64);
 	str_printfa(str, "PASSL\t%d\t", request->credentials);
 	auth_request_export(request, str);
--- a/src/auth/passdb-cache.c	Sat Mar 05 12:25:09 2005 +0200
+++ b/src/auth/passdb-cache.c	Sat Mar 05 13:48:13 2005 +0200
@@ -34,17 +34,17 @@
 
 int passdb_cache_verify_plain(struct auth_request *request, const char *key,
 			      const char *password,
-			      enum passdb_result *result_r, int *expired_r)
+			      enum passdb_result *result_r, int use_expired)
 {
 	const char *value, *cached_pw, *scheme, *const *list;
-	int ret;
+	int ret, expired;
 
 	if (passdb_cache == NULL)
 		return FALSE;
 
 	/* value = password \t ... */
-	value = auth_cache_lookup(passdb_cache, request, key, expired_r);
-	if (value == NULL)
+	value = auth_cache_lookup(passdb_cache, request, key, &expired);
+	if (value == NULL || (expired && !use_expired))
 		return FALSE;
 
 	if (*value == '\0') {
@@ -76,15 +76,16 @@
 
 int passdb_cache_lookup_credentials(struct auth_request *request,
 				    const char *key, const char **result_r,
-				    const char **scheme_r, int *expired_r)
+				    const char **scheme_r, int use_expired)
 {
 	const char *value, *const *list;
+	int expired;
 
 	if (passdb_cache == NULL)
 		return FALSE;
 
-	value = auth_cache_lookup(passdb_cache, request, key, expired_r);
-	if (value == NULL)
+	value = auth_cache_lookup(passdb_cache, request, key, &expired);
+	if (value == NULL || (expired && !use_expired))
 		return FALSE;
 
 	if (*value == '\0') {
--- a/src/auth/passdb-cache.h	Sat Mar 05 12:25:09 2005 +0200
+++ b/src/auth/passdb-cache.h	Sat Mar 05 13:48:13 2005 +0200
@@ -8,10 +8,10 @@
 
 int passdb_cache_verify_plain(struct auth_request *request, const char *key,
 			      const char *password,
-			      enum passdb_result *result_r, int *expired_r);
+			      enum passdb_result *result_r, int use_expired);
 int passdb_cache_lookup_credentials(struct auth_request *request,
 				    const char *key, const char **result_r,
-				    const char **scheme_r, int *expired_r);
+				    const char **scheme_r, int use_expired);
 
 void passdb_cache_init(void);
 void passdb_cache_deinit(void);