diff src/auth/passdb-pgsql.c @ 1296:a9ac5865daf8 HEAD

Whops, forgot to add.
author Timo Sirainen <tss@iki.fi>
date Fri, 14 Mar 2003 21:28:59 +0200
parents
children 7cde19dbe754
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/auth/passdb-pgsql.c	Fri Mar 14 21:28:59 2003 +0200
@@ -0,0 +1,173 @@
+/* Copyright (C) 2003 Alex Howansky, Timo Sirainen */
+
+#include "config.h"
+#undef HAVE_CONFIG_H
+
+#ifdef PASSDB_PGSQL
+
+#include "common.h"
+#include "str.h"
+#include "var-expand.h"
+#include "password-scheme.h"
+#include "db-pgsql.h"
+#include "passdb.h"
+
+#include <libpq-fe.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct passdb_pgsql_connection {
+	struct pgsql_connection *conn;
+};
+
+struct passdb_pgsql_request {
+	struct pgsql_request request;
+
+	enum passdb_credentials credentials;
+	union {
+		verify_plain_callback_t *verify_plain;
+                lookup_credentials_callback_t *lookup_credentials;
+	} callback;
+
+	char password[1];
+};
+
+static struct passdb_pgsql_connection *passdb_pgsql_conn;
+
+static void pgsql_handle_request(struct pgsql_connection *conn,
+				 struct pgsql_request *request, PGresult *res)
+{
+	struct passdb_pgsql_request *pgsql_request =
+		(struct passdb_pgsql_request *) request;
+	struct auth_request *auth_request = request->context;
+	const char *user, *password, *scheme;
+	int ret = 0;
+
+	user = auth_request->user;
+	password = NULL;
+
+	if (res != NULL) {
+		if (PQntuples(res) == 0) {
+			if (verbose)
+				i_info("pgsql(%s): Unknown user", user);
+		} else if (PQntuples(res) > 1) {
+			i_error("pgsql(%s): Multiple matches for user", user);
+		} else if (PQnfields(res) != 1) {
+			i_error("pgsql(%s): Password query returned "
+				"more than one field", user);
+		} else {
+			password = t_strdup(PQgetvalue(res, 0, 0));
+		}
+	}
+
+	scheme = password_get_scheme(&password);
+	if (scheme == NULL) {
+		scheme = conn->set.default_pass_scheme;
+		i_assert(scheme != NULL);
+	}
+
+	if (pgsql_request->credentials != -1) {
+		passdb_handle_credentials(pgsql_request->credentials,
+			user, password, scheme,
+			pgsql_request->callback.lookup_credentials,
+			auth_request);
+		return;
+	}
+
+	/* verify plain */
+	if (password == NULL) {
+		pgsql_request->callback.verify_plain(PASSDB_RESULT_USER_UNKNOWN,
+						     auth_request);
+		return;
+	}
+
+	ret = password_verify(pgsql_request->password, password,
+			      scheme, user);
+	if (ret < 0)
+		i_error("pgsql(%s): Unknown password scheme %s", user, scheme);
+	else if (ret == 0) {
+		if (verbose)
+			i_info("pgsql(%s): Password mismatch", user);
+	}
+
+	pgsql_request->callback.verify_plain(ret > 0 ? PASSDB_RESULT_OK :
+					     PASSDB_RESULT_PASSWORD_MISMATCH,
+					     auth_request);
+}
+
+static void pgsql_lookup_pass(struct auth_request *auth_request,
+			      struct pgsql_request *pgsql_request)
+{
+	struct pgsql_connection *conn = passdb_pgsql_conn->conn;
+	const char *query;
+	string_t *str;
+
+	str = t_str_new(512);
+	var_expand(str, conn->set.password_query, auth_request->user, NULL);
+	query = str_c(str);
+
+	pgsql_request->callback = pgsql_handle_request;
+	pgsql_request->context = auth_request;
+
+	if (db_pgsql_is_valid_username(conn, auth_request->user))
+		db_pgsql_query(conn, query, pgsql_request);
+	else {
+		if (verbose) {
+			i_error("pgsql(%s): Invalid username",
+				auth_request->user);
+		}
+		pgsql_handle_request(conn, pgsql_request, NULL);
+	}
+}
+
+static void
+pgsql_verify_plain(struct auth_request *request, const char *password,
+		   verify_plain_callback_t *callback)
+{
+	struct passdb_pgsql_request *pgsql_request;
+
+	pgsql_request = i_malloc(sizeof(struct passdb_pgsql_request) +
+				 strlen(password));
+	pgsql_request->credentials = -1;
+	pgsql_request->callback.verify_plain = callback;
+	strcpy(pgsql_request->password, password);
+
+	pgsql_lookup_pass(request, &pgsql_request->request);
+}
+
+static void pgsql_lookup_credentials(struct auth_request *request,
+				     enum passdb_credentials credentials,
+				     lookup_credentials_callback_t *callback)
+{
+	struct passdb_pgsql_request *pgsql_request;
+
+	pgsql_request = i_new(struct passdb_pgsql_request, 1);
+	pgsql_request->credentials = credentials;
+	pgsql_request->callback.lookup_credentials = callback;
+
+        pgsql_lookup_pass(request, &pgsql_request->request);
+}
+
+static void passdb_pgsql_init(const char *args)
+{
+	struct pgsql_connection *conn;
+
+	passdb_pgsql_conn = i_new(struct passdb_pgsql_connection, 1);
+	passdb_pgsql_conn->conn = conn = db_pgsql_init(args);
+}
+
+static void passdb_pgsql_deinit(void)
+{
+	db_pgsql_unref(passdb_pgsql_conn->conn);
+	i_free(passdb_pgsql_conn);
+}
+
+struct passdb_module passdb_pgsql = {
+	passdb_pgsql_init,
+	passdb_pgsql_deinit,
+
+	pgsql_verify_plain,
+	pgsql_lookup_credentials
+};
+
+#endif