From e6b6d1c75cad1739d1880c943c9dc8128f4fe4c4 Mon Sep 17 00:00:00 2001
From: Samay Sharma <smilingsamay@gmail.com>
Date: Tue, 15 Feb 2022 22:28:40 -0800
Subject: [PATCH v2 2/3] Add sample extension to test custom auth provider
 hooks

This change adds a new extension to src/test/modules to
test the custom authentication provider hooks. In this
extension, we use an array to define which users to
authenticate and what passwords to use.
---
 src/test/modules/test_auth_provider/Makefile  | 16 ++++
 .../test_auth_provider/test_auth_provider.c   | 90 +++++++++++++++++++
 2 files changed, 106 insertions(+)
 create mode 100644 src/test/modules/test_auth_provider/Makefile
 create mode 100644 src/test/modules/test_auth_provider/test_auth_provider.c

diff --git a/src/test/modules/test_auth_provider/Makefile b/src/test/modules/test_auth_provider/Makefile
new file mode 100644
index 0000000000..17971a5c7a
--- /dev/null
+++ b/src/test/modules/test_auth_provider/Makefile
@@ -0,0 +1,16 @@
+# src/test/modules/test_auth_provider/Makefile
+
+MODULE_big = test_auth_provider
+OBJS = test_auth_provider.o
+PGFILEDESC = "test_auth_provider - provider to test auth hooks"
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_auth_provider
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_auth_provider/test_auth_provider.c b/src/test/modules/test_auth_provider/test_auth_provider.c
new file mode 100644
index 0000000000..477ef8b2c3
--- /dev/null
+++ b/src/test/modules/test_auth_provider/test_auth_provider.c
@@ -0,0 +1,90 @@
+/* -------------------------------------------------------------------------
+ *
+ * test_auth_provider.c
+ *			example authentication provider plugin		
+ *
+ * Copyright (c) 2022, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		contrib/test_auth_provider/test_auth_provider.c
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+#include "fmgr.h"
+#include "libpq/auth.h"
+#include "libpq/libpq.h"
+
+PG_MODULE_MAGIC;
+
+void _PG_init(void);
+
+static char *get_password_for_user(char *user_name);
+
+/*
+ * List of usernames / passwords to approve. Here we are not
+ * getting passwords from Postgres but from this list. In a more real-life
+ * extension, you can fetch valid credentials and authentication tokens /
+ * passwords from an external authentication provider.
+ */
+char credentials[3][3][50] = {
+	{"bob","alice","carol"},
+	{"bob123","alice123","carol123"}
+};
+
+static int TestAuthenticationCheck(Port *port)
+{
+	char *passwd;
+	int result = STATUS_ERROR;
+	char *real_pass;
+
+	sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
+
+	passwd = recv_password_packet(port);
+	if (passwd == NULL)
+		return STATUS_EOF;
+		
+	real_pass = get_password_for_user(port->user_name);
+	if (real_pass)
+	{
+		if(strcmp(passwd, real_pass) == 0)
+		{
+			result = STATUS_OK;
+		}
+		pfree(real_pass);
+	}
+
+	pfree(passwd);
+
+	return result;
+}
+
+static char *
+get_password_for_user(char *user_name)
+{
+	char *password = NULL;
+	int i;
+	for (i=0; i<3; i++)
+	{
+		if (strcmp(user_name, credentials[0][i]) == 0)
+		{
+			password = pstrdup(credentials[1][i]);
+		}
+	}
+
+	return password;
+}
+
+static const char *TestAuthenticationError(Port *port)
+{
+	char *error_message = (char *)palloc (100);
+	sprintf(error_message, "Test authentication failed for user %s", port->user_name);
+	return error_message;
+}
+
+void
+_PG_init(void)
+{
+	RegisterAuthProvider("test", TestAuthenticationCheck, TestAuthenticationError);
+}
-- 
2.34.1

