/*
 * poc-passfilelookup.c
 *
 * PoC for PQpassfileLookup(): a client that connects through a local
 * tunnel looks up the password under the REAL server's host and port
 * (the entry that already exists in the passfile), then connects to
 * the tunnel's local port passing that password explicitly.
 *
 * Compile:  cc poc-passfilelookup.c -o poc-passfilelookup -lpq
 * Usage:    poc-passfilelookup REALHOST REALPORT DBNAME USER LOCALPORT
 *
 * The passfile is not named here: passing NULL makes the lookup use
 * PGPASSFILE or ~/.pgpass, exactly as a connection would.
 */
#include <stdio.h>
#include <stdlib.h>

#include "libpq-fe.h"

int
main(int argc, char *argv[])
{
	char	   *password;
	PGconn	   *conn;
	PGresult   *res;

	if (argc != 6)
	{
		fprintf(stderr, "usage: %s REALHOST REALPORT DBNAME USER LOCALPORT\n",
				argv[0]);
		return 2;
	}

	/* Step 1: look up the password under the REAL host and port. */
	password = PQpassfileLookup(argv[1], argv[2], argv[3], argv[4], NULL);
	if (password == NULL)
	{
		fprintf(stderr, "no password found for %s:%s:%s:%s\n",
				argv[1], argv[2], argv[3], argv[4]);
		return 1;
	}
	printf("PQpassfileLookup(\"%s\", \"%s\", \"%s\", \"%s\", NULL) = \"%s\"\n",
		   argv[1], argv[2], argv[3], argv[4], password);

	/* Step 2: connect to the LOCAL tunnel port with that password. */
	{
		const char *keywords[] = {"host", "port", "dbname", "user",
		"password", NULL};
		const char *values[] = {"127.0.0.1", argv[5], argv[3], argv[4],
		password, NULL};

		conn = PQconnectdbParams(keywords, values, 0);
	}
	PQfreemem(password);

	if (PQstatus(conn) != CONNECTION_OK)
	{
		fprintf(stderr, "connection failed: %s", PQerrorMessage(conn));
		PQfinish(conn);
		return 1;
	}

	res = PQexec(conn, "select current_user");
	if (PQresultStatus(res) == PGRES_TUPLES_OK)
		printf("connected to 127.0.0.1:%s as %s -> OK\n",
			   argv[5], PQgetvalue(res, 0, 0));

	PQclear(res);
	PQfinish(conn);
	return 0;
}
