</para>
<para>
- クライアントが<productname>Pgpool-II</productname>に接続する際の認証用のパスワードを管理するのが<filename>pool_passwd</filename>ファイルです(詳細は<xref linkend="guc-pool-passwd">をご覧ください。)<filename>pool_passwd</filename>に登録されるパスワードは、<productname>PostgreSQL</productname>に登録されるパスワードと一致している必要があります。<productname>PostgreSQL</productname>に登録されたパスワードを変更しても、<filename>pool_passwd</filename>のパスワードは自動変更されないことに注意してください。<link linkend="auth-scram">scram-shar-256認証</link>と<link linkend="auth-md5">MD5認証</link>では、<filename>pool_passwd</filename>にユーザ名とパスワードを登録するのが必須ですが、<link linkend="auth-password">clear text password認証</link>では必須ではありません。このため、<filename>pool_passwd</filename>のパスワードの保守を避けたい場合には、<link linkend="auth-password">clear text password認証</link>の検討をお勧めします。
+ クライアントが<productname>Pgpool-II</productname>に接続する際の認証用のパスワードを管理するのが<filename>pool_passwd</filename>ファイルです(詳細は<xref linkend="guc-pool-passwd">をご覧ください。)
+ <filename>pool_passwd</filename>に登録されるパスワードは、<productname>PostgreSQL</productname>に登録されるパスワードと一致している必要があります。
+ <productname>PostgreSQL</productname>に登録されたパスワードを変更しても、<filename>pool_passwd</filename>のパスワードは自動変更されないことに注意してください。
+ <link linkend="auth-scram">scram-shar-256認証</link>と<link linkend="auth-md5">MD5認証</link>では、<filename>pool_passwd</filename>にユーザ名とパスワードを登録するのが必須ですが、<link linkend="auth-password">clear text password認証</link>、あるいは<xref linkend="guc-allow-clear-text-frontend-auth">が有効である場合では必須ではありません。
+ このため、<filename>pool_passwd</filename>のパスワードの保守を避けたい場合には、<link linkend="auth-password">clear text password認証</link>あるいは<xref linkend="guc-allow-clear-text-frontend-auth">の検討をお勧めします。
</para>
<sect1 id="auth-pool-hba-conf">
<!--
The following subsections describe the authentication methods in more detail.
-->
- 以下の小節では、認証方式について詳細に説明します。
+ 以下の小節では、<filename>pool_hba.conf</filename>で指定する認証方式について詳細に説明します。
</para>
<sect2 id="auth-trust">
そのため、<productname>Pgpool-II</productname>の<literal>md5</literal>認証は<xref linkend="guc-pool-passwd">認証ファイルを使ってサポートしています。
</para>
- <note>
- <para>
- <!--
- If <productname>Pgpool-II</productname> is operated in raw
- mode or there's only 1 backend configured, you don't need to
- setup <xref linkend="guc-pool-passwd">.
- -->
- <productname>Pgpool-II</productname>をrawモードで使用している場合、あるいはバックエンドが1つしかない場合は、<xref linkend="guc-pool-passwd">を設定する必要はありません。
- </para>
- </note>
-
<sect3 id="md5-authentication-file-format">
<!--
<title>Authentication file format</title>
must contain the user password in either plain text
<literal>md5</literal> or <literal>AES</literal> encrypted format.
-->
- <literal>md5</literal>認証を使用するには、<xref linkend="guc-pool-passwd">認証ファイルに平文、<literal>md5</literal>または<literal>AES</literal>暗号化形式のいずれかのユーザのパスワード
+ <literal>md5</literal>認証を使用するには、<xref linkend="guc-pool-passwd">認証ファイルに平文、<literal>AES</literal>、<literal>md5</literal>暗号化形式のいずれかのユーザのパスワード
が含まれている必要があります。
</para>
<para>
-->
<literal>pool_passwd</literal>ファイルは以下の形式の行を含みます。
<programlisting>
- "username:plain_text_passwd"
+ "username:TEXT_plain_text_passwd"
+ </programlisting>
+ <programlisting>
+ "username:AES_encrypted_passwd"
</programlisting>
<programlisting>
- "username:encrypted_passwd"
+ "username:md5_encrypted_passwd"
</programlisting>
+ (実際には、"TEXT"、"AES"、"md5"の後の"_"は存在しません。)
</para>
</sect3>
-->
2. <filename>pool_hba.conf</filename>にmd5認証のエントリを作成します。
詳細については<xref linkend="auth-pool-hba-conf">を参照してください。
+ <filename>pool_hba.conf</filename>を有効にしない場合は、<productname>PostgreSQL</productname>の<filename>pg_hba.conf</filename>でmd5認証が指定されていることを確認してください。
</para>
<para>
<!--
<literal>SCRAM</literal>認証を使用する場合、<xref linkend="guc-pool-passwd">認証ファイルは平文もしくは<literal>AES</literal>暗号化ファーマットのユーザパスワードを含んでる必要があります。
<programlisting>
- "username:plain_text_passwd"
+ "username:TEXT_plain_text_passwd"
</programlisting>
<programlisting>
"username:AES_encrypted_passwd"
</programlisting>
+ (実際には、"TEXT"あるいは"AES"の後の"_"は存在しません。)
<note>
<para>
<!--
-->
2- <filename>pool_hba.conf</filename>に適切なscram-sha-256エントリを追加します。
詳細は<xref linkend="auth-pool-hba-conf">を参照してください。
+ <filename>pool_hba.conf</filename>を有効にしない場合は、<productname>PostgreSQL</productname>の<filename>pg_hba.conf</filename>でscram-sha-256認証が指定されていることを確認してください。
</para>
<para>
<!--
To enable PAM authentication, you need to create a service-configuration
file for <productname>Pgpool-II</productname> in the system's
PAM configuration directory (which is usually at <literal>"/etc/pam.d"</literal>).
- A sample service-configuration file is installed as
- <filename>"share/pgpool-II/pgpool.pam"</filename> under the install directory.
-->
PAM認証を有効にするには、<productname>Pgpool-II</productname>のサービス設定ファイルをシステムのPAM設定ディレクトリ(通常は<literal>"/etc/pam.d"</literal>にあります)に作成しなければなりません。
- サービス設定ファイルのサンプルはインストールディレクトリ下に<literal>"share/pgpool-II/pgpool.pam"</literal>としてインストールされています。
</para>
<note>
authentication</link> require that the user name and the password
have been already registered on <filename>pool_passwd</filename>,
while <link linkend="auth-password">clear text password
- authentication</link> does not require that. Therefore, if you want
- to avoid maintaining the <filename>pool_passwd</filename>, it would
- be worth to check <link linkend="auth-password">clear text password
- authentication</link>.
+ authentication</link>
+ or <xref linkend="guc-allow-clear-text-frontend-auth"> does not
+ require that. Therefore, if you want to avoid maintaining
+ the <filename>pool_passwd</filename>, it would be worth to
+ check <link linkend="auth-password">clear text password
+ authentication</link>
+ or <xref linkend="guc-allow-clear-text-frontend-auth">.
</para>
<sect1 id="auth-pool-hba-conf">
<sect1 id="auth-methods">
<title>Authentication Methods</title>
<para>
- The following subsections describe the authentication methods in more detail.
+ The following subsections describe the authentication methods
+ specified by <filename>pool_hba.conf</filename> in more detail.
</para>
<sect2 id="auth-trust">
<xref linkend="guc-pool-passwd"> authentication file.
</para>
- <note>
- <para>
- If <productname>Pgpool-II</productname> is operated in raw
- mode or there's only 1 backend configured, you don't need to
- setup <xref linkend="guc-pool-passwd">.
- </para>
- </note>
-
<sect3 id="md5-authentication-file-format">
<title>Authentication file format</title>
<para>
To use the <literal>md5</literal> authentication
- <xref linkend="guc-pool-passwd"> authentication file
- must contain the user password in either plain text
- <literal>md5</literal> or <literal>AES</literal> encrypted format.
+ <xref linkend="guc-pool-passwd"> authentication file must contain
+ the user password in either plain text, <literal>AES</literal>
+ or <literal>md5</literal> encrypted format.
</para>
<para>
The <xref linkend="guc-pool-passwd"> file should contain lines in the following format:
<programlisting>
- "username:plain_text_passwd"
+ "username:TEXT_plain_text_passwd"
+ </programlisting>
+ <programlisting>
+ "username:AES_encrypted_passwd"
</programlisting>
<programlisting>
- "username:encrypted_passwd"
+ "username:md5_encrypted_passwd"
</programlisting>
+ (Actually "_" after "TEXT", "AES" or "md5" does not exist.)
</para>
</sect3>
<para>
2- Add an appropriate md5 entry to <filename>pool_hba.conf</filename>.
See <xref linkend="auth-pool-hba-conf"> for more details.
+ If <filename>pool_hba.conf</filename> is not enabled, make sure
+ that md5 authentication is specified
+ in <filename>pg_hba.conf</filename>
+ of <productname>PostgreSQL</productname>.
</para>
<para>
3- After changing md5 password (in both pool_passwd
or <literal>AES</literal> encrypted format.
<programlisting>
- "username:plain_text_passwd"
+ "username:TEXT_plain_text_passwd"
</programlisting>
<programlisting>
"username:AES_encrypted_passwd"
</programlisting>
+ (Actually "_" after "TEXT" or "AES" does not exist.)
<note>
<para>
<literal>md5</literal> type user passwords in
<para>
2- Add an appropriate scram-sha-256 entry to <filename>pool_hba.conf</filename>.
See <xref linkend="auth-pool-hba-conf"> for more details.
+ If <filename>pool_hba.conf</filename> is not enabled, make sure that md5 authentication is specified in <filename>pg_hba.conf</filename> of <productname>PostgreSQL</productname>.
</para>
<para>
3- After changing SCRAM password (in both pool_passwd
<para>
To enable PAM authentication, you need to create a service-configuration
- file for <productname>Pgpool-II</productname> in the system's
+ file named for <productname>Pgpool-II</productname> in the system's
PAM configuration directory (which is usually at <literal>"/etc/pam.d"</literal>).
- A sample service-configuration file is installed as
- <filename>"share/pgpool-II/pgpool.pam"</filename> under the install directory.
</para>
<note>
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2020 PgPool Global Development Group
+ * Copyright (c) 2003-2025 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
#include "auth/md5.h"
#include <unistd.h>
-#ifdef HAVE_CRYPT_H
-#include <crypt.h>
-#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
static POOL_STATUS pool_send_backend_key_data(POOL_CONNECTION * frontend, int pid, int key, int protoMajor);
static int do_clear_text_password(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor);
static void pool_send_auth_fail(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * cp);
-static int do_crypt(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor);
static int do_md5(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor,
char *storedPassword, PasswordType passwordType);
-static int do_md5_single_backend(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor);
static void send_md5auth_request(POOL_CONNECTION * frontend, int protoMajor, char *salt);
static int read_password_packet(POOL_CONNECTION * frontend, int protoMajor, char *password, int *pwdSize);
static int send_password_packet(POOL_CONNECTION * backend, int protoMajor, char *password);
}
}
- /* crypt authentication? */
- else if (authkind == AUTH_REQ_CRYPT)
- {
- for (i = 0; i < NUM_BACKENDS; i++)
- {
- if (!VALID_BACKEND(i))
- continue;
-
- ereport(DEBUG1,
- (errmsg("authentication backend"),
- errdetail("trying crypt authentication")));
-
- authkind = do_crypt(CONNECTION(cp, i), frontend, 0, protoMajor);
-
- if (authkind < 0)
- {
- pool_send_auth_fail(frontend, cp);
- ereport(ERROR,
- (errmsg("failed to authenticate with backend"),
- errdetail("do_crypt_text_password failed in slot %d", i)));
- }
- }
- }
-
/* md5 authentication? */
else if (authkind == AUTH_REQ_MD5)
{
/*
* check if we can use md5 authentication.
*/
- if (!RAW_MODE && NUM_BACKENDS > 1)
+ if (get_auth_password(MAIN(cp), frontend, 0,
+ &password, &passwordType) == false)
{
- if (get_auth_password(MAIN(cp), frontend, 0,
- &password, &passwordType) == false)
+ /*
+ * We do not have any password, we can still get the password
+ * from client using plain text authentication if it is
+ * allowed by user
+ */
+ if (frontend->pool_hba == NULL && pool_config->allow_clear_text_frontend_auth)
{
- /*
- * We do not have any password, we can still get the password
- * from client using plain text authentication if it is
- * allowed by user
- */
- if (frontend->pool_hba == NULL && pool_config->allow_clear_text_frontend_auth)
+ ereport(LOG,
+ (errmsg("using clear text authentication with frontend"),
+ errdetail("backend will still use md5 auth"),
+ errhint("you can disable this behavior by setting allow_clear_text_frontend_auth to off")));
+ authenticate_frontend_clear_text(frontend);
+ /* now check again if we have a password now */
+ if (get_auth_password(MAIN(cp), frontend, 0,
+ &password, &passwordType) == false)
{
- ereport(LOG,
- (errmsg("using clear text authentication with frontend"),
- errdetail("backend will still use md5 auth"),
- errhint("you can disable this behavior by setting allow_clear_text_frontend_auth to off")));
- authenticate_frontend_clear_text(frontend);
- /* now check again if we have a password now */
- if (get_auth_password(MAIN(cp), frontend, 0,
- &password, &passwordType) == false)
- {
- ereport(ERROR,
- (errmsg("failed to authenticate with backend using md5"),
- errdetail("unable to get the password")));
- }
+ ereport(ERROR,
+ (errmsg("failed to authenticate with backend using md5"),
+ errdetail("unable to get the password")));
}
}
- /* we have a password to use, validate the password type */
- if (passwordType != PASSWORD_TYPE_PLAINTEXT && passwordType != PASSWORD_TYPE_MD5
- && passwordType != PASSWORD_TYPE_AES)
- {
- ereport(ERROR,
- (errmsg("failed to authenticate with backend using md5"),
- errdetail("valid password not found")));
- }
+ }
+ /* we have a password to use, validate the password type */
+ if (passwordType != PASSWORD_TYPE_PLAINTEXT && passwordType != PASSWORD_TYPE_MD5
+ && passwordType != PASSWORD_TYPE_AES)
+ {
+ ereport(ERROR,
+ (errmsg("failed to authenticate with backend using md5"),
+ errdetail("valid password not found")));
}
for (i = 0; i < NUM_BACKENDS; i++)
do_clear_text_password(MAIN(cp), frontend, 1, protoMajor);
break;
- case AUTH_REQ_CRYPT:
- /* crypt password */
- do_crypt(MAIN(cp), frontend, 1, protoMajor);
- break;
-
case AUTH_REQ_MD5:
/* md5 password */
authenticate_frontend_md5(MAIN(cp), frontend, 1, protoMajor);
break;
+
case AUTH_REQ_SASL:
/* SCRAM */
authenticate_frontend_SCRAM(MAIN(cp), frontend, 1);
break;
+
default:
ereport(ERROR,
(errmsg("authentication failed"),
char *pwd = NULL;
int kind;
PasswordType passwordType = PASSWORD_TYPE_UNKNOWN;
+ bool rtn;
if (reauth && frontend->frontend_authenticated)
{
return 0;
}
- if (get_auth_password(backend, frontend, reauth, &pwd, &passwordType) == false)
+ rtn = get_auth_password(backend, frontend, reauth, &pwd, &passwordType);
+
+ /*
+ * If pool_hba.conf == "password", we should already have frontend
+ * password. When reauth, we want the password, rather than
+ * backend->password, which is returned by get_auth_password() if
+ * pool_passwd does not have an entry for the user.
+ */
+ if (reauth && rtn && frontend->passwordMapping == NULL &&
+ frontend->pwd_size > 0 &&
+ frontend->passwordType == PASSWORD_TYPE_PLAINTEXT)
+ {
+ pwd = frontend->password;
+ passwordType = frontend->passwordType;
+ }
+
+ else if (!rtn || frontend->pwd_size == 0)
{
/*
* We do not have any password, we can still get the password
authenticate_frontend_clear_text(frontend);
/* now check again if we have a password now */
-
- if (get_auth_password(backend, frontend, reauth, &pwd, &passwordType) == false)
+ if (get_auth_password(backend, frontend, 0, &pwd, &passwordType) == false)
{
ereport(FATAL,
(return_code(2),
return kind;
}
-/*
- * perform crypt authentication
- */
-static int
-do_crypt(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor)
-{
- char salt[2];
- static int size;
- static char password[MAX_PASSWORD_SIZE];
- char response;
- int kind;
- int len;
-
- if (!reauth)
- {
- /* read salt */
- pool_read(backend, salt, sizeof(salt));
- }
- else
- {
- memcpy(salt, backend->salt, sizeof(salt));
- }
-
- /* main? */
- if (IS_MAIN_NODE_ID(backend->db_node_id))
- {
- pool_write(frontend, "R", 1); /* authentication */
- if (protoMajor == PROTO_MAJOR_V3)
- {
- len = htonl(10);
- pool_write(frontend, &len, sizeof(len));
- }
- kind = htonl(4); /* crypt authentication */
- pool_write(frontend, &kind, sizeof(kind)); /* indicating crypt
- * authentication */
- pool_write_and_flush(frontend, salt, sizeof(salt)); /* salt */
-
- /* read password packet */
- if (protoMajor == PROTO_MAJOR_V2)
- {
- pool_read(frontend, &size, sizeof(size));
- }
- else
- {
- char k;
-
- pool_read(frontend, &k, sizeof(k));
- if (k != 'p')
- {
- ereport(ERROR,
- (errmsg("crypt authentication failed"),
- errdetail("invalid password packet. Packet does not starts with \"p\"")));
- }
- pool_read(frontend, &size, sizeof(size));
- }
-
- if ((ntohl(size) - 4) > sizeof(password))
- {
- ereport(ERROR,
- (errmsg("crypt authentication failed"),
- errdetail("password is too long, password size is %d", ntohl(size) - 4)));
- }
-
- pool_read(frontend, password, ntohl(size) - 4);
- }
-
- /* connection reusing? */
- if (reauth)
- {
- ereport(DEBUG1,
- (errmsg("performing crypt authentication"),
- errdetail("size: %d saved_size: %d", (ntohl(size) - 4), backend->pwd_size)));
-
- if ((ntohl(size) - 4) != backend->pwd_size)
- ereport(ERROR,
- (errmsg("crypt authentication failed"),
- errdetail("password size does not match")));
-
-
- if (memcmp(password, backend->password, backend->pwd_size) != 0)
- ereport(ERROR,
- (errmsg("crypt authentication failed"),
- errdetail("password does not match")));
-
- return 0;
- }
-
- /* send password packet to backend */
- if (protoMajor == PROTO_MAJOR_V3)
- pool_write(backend, "p", 1);
- pool_write(backend, &size, sizeof(size));
- pool_write_and_flush(backend, password, ntohl(size) - 4);
- pool_read(backend, &response, sizeof(response));
-
- if (response != 'R')
- {
- if (response == 'E') /* Backend has thrown an error instead */
- {
- char *message = NULL;
-
- if (pool_extract_error_message(false, backend, protoMajor, false, &message) == 1)
- {
- ereport(ERROR,
- (errmsg("crypt authentication failed"),
- errdetail("%s", message ? message : "backend throws authentication error")));
- }
- if (message)
- pfree(message);
- }
- ereport(ERROR,
- (errmsg("crypt authentication failed"),
- errdetail("invalid packet from backend. backend does not return R while processing clear text password authentication")));
- }
-
- if (protoMajor == PROTO_MAJOR_V3)
- {
- pool_read(backend, &len, sizeof(len));
-
- if (ntohl(len) != 8)
- ereport(ERROR,
- (errmsg("crypt authentication failed"),
- errdetail("invalid packet from backend. incorrect authentication packet size (%d)", ntohl(len))));
- }
-
- /* expect to read "Authentication OK" response. kind should be 0... */
- pool_read(backend, &kind, sizeof(kind));
-
- /* if authenticated, save info */
- if (kind == 0)
- {
- int msglen;
-
- pool_write(frontend, "R", 1);
-
- if (protoMajor == PROTO_MAJOR_V3)
- {
- msglen = htonl(8);
- pool_write(frontend, &msglen, sizeof(msglen));
- }
-
- msglen = htonl(0);
- pool_write_and_flush(frontend, &msglen, sizeof(msglen));
-
- backend->auth_kind = 4;
- backend->pwd_size = ntohl(size) - 4;
- memcpy(backend->password, password, backend->pwd_size);
- memcpy(backend->salt, salt, sizeof(salt));
- }
- return kind;
-}
-
/*
* Do the SCRAM authentication with the frontend using the stored
* password in the pool_passwd file.
PasswordType storedPasswordType = PASSWORD_TYPE_UNKNOWN;
char *storedPassword = NULL;
- if (RAW_MODE || NUM_BACKENDS == 1)
- {
- if (backend)
- do_md5_single_backend(backend, frontend, reauth, protoMajor);
- return; /* This will be handled later */
- }
-
if (get_auth_password(backend, frontend, reauth,&storedPassword, &storedPasswordType) == false)
{
ereport(FATAL,
}
/*
- * perform MD5 authentication
+ * Get user's password from various sources. Firstly try pool_passwd and
+ * return it if the user's password is there. If reauth == 0 (first time the
+ * user connect to pgpool) and the password is in frontend, return it. If
+ * reauth != 0 (reuse connection pool) and the password is in backendm return
+ * it.
*/
-static int
-do_md5_single_backend(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor)
-{
- char salt[4];
- static int size;
- static char password[MAX_PASSWORD_SIZE];
- int kind;
-
- if (!reauth)
- {
- /* read salt from backend */
- pool_read(backend, salt, sizeof(salt));
- ereport(DEBUG1,
- (errmsg("performing md5 authentication"),
- errdetail("DB node id: %d salt: %hhx%hhx%hhx%hhx", backend->db_node_id,
- salt[0], salt[1], salt[2], salt[3])));
- }
- else
- {
- /* Use the saved salt */
- memcpy(salt, backend->salt, sizeof(salt));
- }
-
- /* Send md5 auth request to frontend */
- send_md5auth_request(frontend, protoMajor, salt);
-
- /* Read password packet */
- read_password_packet(frontend, protoMajor, password, &size);
-
- /* connection reusing? compare it with saved password */
- if (reauth)
- {
- if (backend->passwordType != PASSWORD_TYPE_MD5)
- ereport(ERROR,
- (errmsg("md5 authentication failed"),
- errdetail("invalid password type")));
-
- if (size != backend->pwd_size)
- ereport(ERROR,
- (errmsg("md5 authentication failed"),
- errdetail("password does not match")));
-
- if (memcmp(password, backend->password, backend->pwd_size) != 0)
- ereport(ERROR,
- (errmsg("md5 authentication failed"),
- errdetail("password does not match")));
- return 0;
- }
- else
- {
- /* Send password packet to backend and receive auth response */
- kind = send_password_packet(backend, protoMajor, password);
- if (kind < 0)
- ereport(ERROR,
- (errmsg("md5 authentication failed"),
- errdetail("backend replied with invalid kind")));
-
- /* If authenticated, reply back to frontend and save info */
- if (kind == AUTH_REQ_OK)
- {
- send_auth_ok(frontend, protoMajor);
- backend->passwordType = PASSWORD_TYPE_MD5;
- backend->auth_kind = AUTH_REQ_MD5;
- backend->pwd_size = size;
- memcpy(backend->password, password, backend->pwd_size);
- memcpy(backend->salt, salt, sizeof(salt));
- }
- }
- return kind;
-}
-
static bool
get_auth_password(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth,
char **password, PasswordType *passwordType)
* check if we have password stored in the frontend connection. that
* could come by using the clear text auth
*/
- if (frontend->pwd_size > 0 && frontend->passwordType == PASSWORD_TYPE_PLAINTEXT)
+ if (!reauth &&
+ frontend->pwd_size > 0 && frontend->passwordType == PASSWORD_TYPE_PLAINTEXT)
{
*password = frontend->password;
*passwordType = frontend->passwordType;
char encbuf[POOL_PASSWD_LEN + 1];
char *pool_passwd = NULL;
- if (RAW_MODE || NUM_BACKENDS == 1)
- return do_md5_single_backend(backend, frontend, reauth, protoMajor);
-
if (passwordType == PASSWORD_TYPE_AES)
{
/*
* already received the password from frontend using the clear text
* auth, we may not need to authenticate it
*/
- if (pool_config->allow_clear_text_frontend_auth &&
- frontend->auth_kind == AUTH_REQ_PASSWORD &&
+ if ((pool_config->allow_clear_text_frontend_auth ||
+ frontend->auth_kind == AUTH_REQ_PASSWORD) &&
frontend->pwd_size > 0 &&
frontend->passwordType == PASSWORD_TYPE_PLAINTEXT)
{
* already received the password from frontend using the clear text
* auth, we may not need to authenticate it
*/
- if (pool_config->allow_clear_text_frontend_auth &&
- frontend->auth_kind == AUTH_REQ_PASSWORD &&
+ if ((pool_config->allow_clear_text_frontend_auth ||
+ frontend->auth_kind == AUTH_REQ_PASSWORD) &&
frontend->pwd_size > 0 &&
frontend->passwordType == PASSWORD_TYPE_PLAINTEXT)
{
#%PAM-1.0
-auth required pam_permit.so
-account required pam_permit.so
+# create your own PAM configurations
--- /dev/null
+username,pool_hba.conf,allow_clear_text_frontend_auth,pool_passwd,pg_hba.conf,expected,comment
+scram1,scram,off,AES,scram,ok,
+scram2,scram,off,AES,md5,ok,
+scram3,scram,off,AES,password,ok,
+scram4,scram,off,AES,pam,ok,
+scram5,scram,off,AES,ldap,ok,
+scram6,scram,off,md5,scram,fail,
+scram7,scram,off,md5,md5,fail,
+scram8,scram,off,md5,password,fail,
+scram9,scram,off,md5,pam,fail,
+scram10,scram,off,md5,ldap,fail,
+scram11,scram,off,text,scram,ok,
+scram12,scram,off,text,md5,ok,
+scram13,scram,off,text,password,ok,
+scram14,scram,off,text,pam,ok,
+scram15,scram,off,text,ldap,ok,
+scram16,scram,off,off,scram,fail,
+scram17,scram,off,off,md5,fail,
+scram18,scram,off,off,password,fail,
+scram19,scram,off,off,pam,fail,
+scram20,scram,off,off,ldap,fail,
+md51,md5,off,AES,scram,ok,
+md52,md5,off,AES,md5,ok,
+md53,md5,off,AES,password,ok,
+md54,md5,off,AES,pam,ok,
+md55,md5,off,AES,ldap,ok,
+md56,md5,off,md5,scram,fail,
+md57,md5,off,md5,md5,ok,
+md58,md5,off,md5,password,fail,
+md59,md5,off,md5,pam,fail,
+md510,md5,off,md5,ldap,fail,
+md511,md5,off,text,scram,ok,
+md512,md5,off,text,md5,ok,
+md513,md5,off,text,password,ok,
+md514,md5,off,text,pam,ok,
+md515,md5,off,text,ldap,ok,
+md516,md5,off,off,scram,fail,
+md517,md5,off,off,md5,fail,
+md518,md5,off,off,password,fail,
+md519,md5,off,off,pam,fail,
+md520,md5,off,off,ldap,fail,
+p1,password,off,AES,scram,ok,
+p2,password,off,AES,md5,ok,
+p3,password,off,AES,password,ok,
+p4,password,off,AES,pam,ok,
+p5,password,off,AES,ldap,ok,
+p6,password,off,md5,scram,fail,
+p7,password,off,md5,md5,ok,
+p8,password,off,md5,password,fail,
+p9,password,off,md5,pam,fail,
+p10,password,off,md5,ldap,fail,
+p11,password,off,text,scram,ok,
+p12,password,off,text,md5,ok,
+p13,password,off,text,password,ok,
+p14,password,off,text,pam,ok,
+p15,password,off,text,ldap,ok,
+p16,password,off,off,scram,ok,
+p17,password,off,off,md5,ok,
+p18,password,off,off,password,ok,
+p19,password,off,off,pam,ok,
+p20,password,off,off,ldap,ok,
+o1,off,on,off,scram,ok,
+o2,off,on,off,md5,ok,
+o3,off,on,off,password,ok,
+o4,off,on,off,pam,ok,
+o5,off,on,off,ldap,ok,
+o6,off,off,AES,scram,ok,
+o7,off,off,AES,md5,ok,
+o8,off,off,AES,password,ok,
+o9,off,off,AES,pam,ok,
+o10,off,off,AES,ldap,ok,
+o11,off,off,md5,scram,fail,
+o12,off,off,md5,md5,ok,
+o13,off,off,md5,password,fail,
+o14,off,off,md5,pam,fail,
+o15,off,off,md5,ldap,fail,
+o16,off,off,text,scram,ok,
+o17,off,off,text,md5,ok,
+o18,off,off,text,password,ok,
+o19,off,off,text,pam,ok,
+o20,off,off,text,ldap,ok,
+o21,off,off,off,scram,fail,
+o22,off,off,off,md5,fail,
+o23,off,off,off,password,ok,
+o24,off,off,off,pam,ok,
+o25,off,off,off,ldap,ok,
+pam1,pam,off,AES,scram,ok,
+pam2,pam,off,AES,md5,ok,
+pam3,pam,off,AES,password,ok,
+pam4,pam,off,AES,pam,ok,
+pam5,pam,off,AES,ldap,ok,
+pam6,pam,off,md5,scram,fail,
+pam7,pam,off,md5,md5,ok,
+pam8,pam,off,md5,password,fail,
+pam9,pam,off,md5,pam,fail,
+pam10,pam,off,md5,ldap,fail,
+pam11,pam,off,text,scram,ok,
+pam12,pam,off,text,md5,ok,
+pam13,pam,off,text,password,ok,
+pam14,pam,off,text,pam,ok,
+pam15,pam,off,text,ldap,ok,
+pam16,pam,off,off,scram,fail,
+pam17,pam,off,off,md5,fail,
+pam18,pam,off,off,password,fail,
+pam19,pam,off,off,pam,fail,
+pam20,pam,off,off,ldap,fail,
+ldap1,ldap,off,AES,scram,ok,
+ldap2,ldap,off,AES,md5,ok,
+ldap3,ldap,off,AES,password,ok,
+ldap4,ldap,off,AES,pam,ok,
+ldap5,ldap,off,AES,ldap,ok,
+ldap6,ldap,off,md5,scram,fail,
+ldap7,ldap,off,md5,md5,ok,
+ldap8,ldap,off,md5,password,fail,
+ldap9,ldap,off,md5,pam,fail,
+ldap10,ldap,off,md5,ldap,fail,
+ldap11,ldap,off,text,scram,ok,
+ldap12,ldap,off,text,md5,ok,
+ldap13,ldap,off,text,password,ok,
+ldap14,ldap,off,text,pam,ok,
+ldap15,ldap,off,text,ldap,ok,
+ldap16,ldap,off,off,scram,fail,
+ldap17,ldap,off,off,md5,fail,
+ldap18,ldap,off,off,password,fail,
+ldap19,ldap,off,off,pam,fail,
+ldap20,ldap,off,off,ldap,fail,
--- /dev/null
+#! /usr/bin/bash
+# Create input file for ldapadd command to stdout.
+# Users' list must be provided from stdin.
+if [ $# -ne 0 ];then
+ echo "usage: $0"
+ exit 1
+fi
+
+while read username
+do
+ cat <<EOF
+dn: uid=$username,ou=people,dc=nodomain
+cn: $username
+sn: $username
+objectClass: inetOrgPerson
+objectClass: simpleSecurityObject
+userPassword: $username
+
+EOF
+done
--- /dev/null
+#! /usr/bin/bash
+# Create input file (newusers_input.txt) for newusers command.
+# Users' list must be provided as $1.
+if [ $# -ne 1 ];then
+ echo "usage: $0 pam_users_list_file"
+ exit 1
+fi
+
+USERS=newusers_input.txt
+
+spec=$1
+
+cp /dev/null $USERS
+cat $spec|while read username
+do
+ echo "$username:$username::::/nonexistent:/usr/sbin/nologin" >> $USERS
+done
--- /dev/null
+#! /usr/bin/bash
+# read users list from stdin and perform ldapdelete command.
+PASSWORD=ldapadmin
+set -e
+while read i
+do
+ ldapdelete -x -w $PASSWORD -D cn=admin,dc=nodomain uid=$i,ou=people,dc=nodomain
+done
--- /dev/null
+#! /usr/bin/bash
+# read users list from stdin and perform userdel command.
+set -e
+while read i
+do
+ /usr/sbin/userdel $i
+done
--- /dev/null
+#! /usr/bin/bash
+# List up user names used in the LDAP authentication test.
+# The result is put to stdout.
+spec=client_auth_2node.csv
+IFS=","
+cat $spec|while read line
+do
+ set $line
+ if [ $1 != 'username' ];then
+ username=$1
+ pool_hba=$2
+ pg_hba=$5
+ if [ $pool_hba = "ldap" -o $pg_hba = "ldap" ];then
+ echo $username
+ fi
+ fi
+done
--- /dev/null
+#! /usr/bin/bash
+# List up user names used in the PAM authentication test.
+spec=client_auth_2node.csv
+IFS=","
+cat $spec|while read line
+do
+ set $line
+ if [ $1 != 'username' ];then
+ username=$1
+ pool_hba=$2
+ pg_hba=$5
+ if [ $pool_hba = "pam" -o $pg_hba = "pam" ];then
+ echo $username
+ fi
+ fi
+done
--- /dev/null
+scram4
+scram9
+scram14
+scram19
+md54
+md59
+md514
+md519
+p4
+p9
+p14
+p19
+o4
+o9
+o14
+o19
+o24
+pam1
+pam2
+pam3
+pam4
+pam5
+pam6
+pam7
+pam8
+pam9
+pam10
+pam11
+pam12
+pam13
+pam14
+pam15
+pam16
+pam17
+pam18
+pam19
+pam20
+ldap4
+ldap9
+ldap14
+ldap19
--- /dev/null
+#!/usr/bin/bash
+#-------------------------------------------------------------------
+# test script for client authentication
+#
+
+# This test is only valid with PostgreSQL 10 or later.
+if [ $PGVERSION -le 9 ];then
+ echo "all tests skipped due to PostgreSQL version: $PGVERSION"
+ exit 0
+fi
+
+# --------------------------------------------------------------------
+# PAM authentication tests are not performed by default. In order to
+# test PAM authentication (both frontend and backend), run following
+# scripts here (040.client_auth).
+#
+# Create pam users list.
+# $ ./list_pam_user.sh > pam_users.txt
+#
+# Create input file for newusers command.
+# The result file is newusers_input.txt.
+# $ ./create_pam_user.sh pam_users.txt
+#
+# Finally run newusers command as root.
+# the users are not allowed to login (login shell is /usr/sbin/nologin)
+# /usr/sbin/newusers newusers_input.txt
+#
+# Note that newusers just ignore users that are already registered in
+# the system. So it is harmless to generate new newusers_input.txt and
+# run newusers command. It will happily register new users.
+#
+# Then set the environment variable DO_PAM_TEST to "true".
+#
+if [ "$DO_PAM_TEST" != "true" ];then
+ echo "all pam tests will be skipped"
+fi
+# --------------------------------------------------------------------
+# LDAP authentication tests are not performed by default. In order to
+# test LDAP authentication (both frontend and backend), run following
+# scripts here (040.client_auth). The procedure below assumes that
+# LDAP server is created on localhost, with LDAP admin name is
+# "admin", domain is "nodomain".
+#
+# To create LDAP ldif file, run:
+# $ cat client_auth_2node.csv|./list_ldap_user.sh|./create_ldap_user.sh > ldap_users.ldif
+#
+# Then run ldapadd command.
+# ldapadd -x -D cn=admin,dc=nodomain -W -f ldap_users.ldif
+#
+# Set the environment variable DO_LDAP_TEST to "true".
+#
+if [ "$DO_LDAP_TEST" != "true" ];then
+ echo "all ldap tests will be skipped"
+fi
+# --------------------------------------------------------------------
+# Function declarations
+
+# create user
+# $1: username
+# $2: "scram", "md5", "password", "pam" or "ldap".
+# If "password" is specified, encryption method becomes 'scram-sha-256'.
+function add_user()
+{
+ createuser $1
+ if [ $2 = "scram" ];then
+ psql -c "SET password_encryption = 'scram-sha-256'; ALTER USER $1 WITH ENCRYPTED PASSWORD '$1'"
+ elif [ $2 = "md5" ];then
+ psql -c "SET password_encryption = 'md5'; ALTER USER $1 WITH ENCRYPTED PASSWORD '$1'"
+ elif [ $2 = "password" ];then
+ psql -c "SET password_encryption = 'scram-sha-256'; ALTER USER $1 WITH ENCRYPTED PASSWORD '$1'"
+ elif [ "$DO_PAM_TEST" = "true" -a $2 = "pam" ];then
+ psql -c "SET password_encryption = 'scram-sha-256'; ALTER USER $1 WITH ENCRYPTED PASSWORD '$1'"
+ elif [ "$DO_PAM_TEST" != "true" -a $2 = "pam" ];then
+ echo "do nothing because DO_PAM_TEST is not true and auth method is pam"
+ elif [ "$DO_LDAP_TEST" = "true" -a $2 = "ldap" ];then
+ psql -c "SET password_encryption = 'scram-sha-256'; ALTER USER $1 WITH ENCRYPTED PASSWORD '$1'"
+ elif [ "$DO_LDAP_TEST" != "true" -a $2 = "ldap" ];then
+ echo "do nothing because DO_LDAP_TEST is not true and auth method is ldap"
+ else
+ echo "wrong auth method \"$2\" for add_user $1"
+ exit 1
+ fi
+}
+
+# create pool_hba.conf entry
+# $1: username
+# $2: auth method for pool_hba.conf
+# "scram", "md5" or "password"
+# $3: pgpool major version first digit (e.g. "4")
+function add_pool_hba()
+{
+ # "scram-sha-256" is only supported in pgpool version 4.0 or later
+ if [ $3 -gt 3 -a $2 = "scram" ];then
+ echo "host all $1 127.0.0.1/32 scram-sha-256" >> $POOL_HBA
+ echo "host all $1 ::1/128 scram-sha-256" >> $POOL_HBA
+ elif [ $2 = "md5" ];then
+ echo "host all $1 127.0.0.1/32 md5" >> $POOL_HBA
+ echo "host all $1 ::1/128 md5" >> $POOL_HBA
+ elif [ "$DO_PAM_TEST" = "true" -a $2 = "pam" ];then
+ echo "host all $1 127.0.0.1/32 pam" >> $POOL_HBA
+ echo "host all $1 ::1/128 pam" >> $POOL_HBA
+ elif [ "$DO_PAM_TEST" != "true" -a $2 = "pam" ];then
+ echo "do nothing because DO_PAM_TEST is not true and auth method is pam"
+ elif [ "$DO_LDAP_TEST" = "true" -a $2 = "ldap" ];then
+ echo "host all $1 127.0.0.1/32 ldap ldapserver=localhost ldapbasedn="dc=nodomain" ldapsearchattribute=uid" >> $POOL_HBA
+ echo "host all $1 ::1/128 ldap ldapserver=localhost ldapbasedn="dc=nodomain" ldapsearchattribute=uid" >> $POOL_HBA
+ elif [ "$DO_LDAP_TEST" != "true" -a $2 = "ldap" ];then
+ echo "do nothing because DO_LDAP_TEST is not true and auth method is ldap"
+ # "password" is only supported in pgpool version 4.0 or later
+ elif [ $3 -gt 3 -a $2 = "password" ];then
+ echo "host all $1 127.0.0.1/32 password" >> $POOL_HBA
+ echo "host all $1 ::1/128 password" >> $POOL_HBA
+ else
+ echo "skip adding to pool_hba.conf"
+ fi
+}
+
+# create pool_passwd entry
+# $1: username (also password)
+# $2: encryption method (AES, md5 or text)
+# $3: pgpool major version first digit (e.g. "4")
+function add_pool_passwd()
+{
+ # "AES" is only supported in pgpool version 4.0 or later
+ if [ $3 -gt 3 -a $2 = "AES" ];then
+ echo $1|$PG_ENC -m -f $PGPOOL_CONF -u $1 $1
+ elif [ $2 = "md5" ];then
+ echo $1|$PG_MD5 -m -f $PGPOOL_CONF -u $1 $1
+ # "text" is only supported in pgpool version 4.0 or later
+ elif [ $3 -gt 3 -a $2 = "text" ];then
+ if [ $3 -gt 3 ];then
+ echo "$1:TEXT$1" >> $POOL_PASSWD
+ else
+ echo "$1:$1" >> $POOL_PASSWD
+ fi
+ else
+ echo "skip adding to pool_passwd"
+ fi
+}
+
+# create pg_hba.conf entry
+# $1: username
+# $2: "scram", "md5", "password" or "pam".
+function add_pg_hba()
+{
+ for i in data0 data1
+ do
+ if [ ! -d $i ];then
+ continue
+ fi
+
+ PG_HBA=$i/pg_hba.conf
+ if [ $2 = "scram" ];then
+ echo "host all $1 127.0.0.1/32 scram-sha-256" >> $PG_HBA
+ echo "host all $1 ::1/128 scram-sha-256" >> $PG_HBA
+ echo "local all $1 scram-sha-256" >> $PG_HBA
+ elif [ $2 = "md5" ];then
+ echo "host all $1 127.0.0.1/32 md5" >> $PG_HBA
+ echo "host all $1 ::1/128 md5" >> $PG_HBA
+ echo "local all $1 md5" >> $PG_HBA
+ elif [ $2 = "password" ];then
+ echo "host all $1 127.0.0.1/32 password" >> $PG_HBA
+ echo "host all $1 ::1/128 password" >> $PG_HBA
+ echo "local all $1 password" >> $PG_HBA
+ elif [ "$DO_PAM_TEST" = "true" -a $2 = "pam" ];then
+ echo "host all $1 127.0.0.1/32 pam" >> $PG_HBA
+ echo "host all $1 ::1/128 pam" >> $PG_HBA
+ echo "local all $1 pam" >> $PG_HBA
+ elif [ "$DO_PAM_TEST" != "true" -a $2 = "pam" ];then
+ echo "do nothing because DO_PAM_TEST is not true and auth method is pam"
+ elif [ "$DO_LDAP_TEST" = "true" -a $2 = "ldap" ];then
+ echo "host all $1 127.0.0.1/32 ldap ldapserver=localhost ldapbasedn="dc=nodomain" ldapsearchattribute=uid" >> $PG_HBA
+ echo "host all $1 ::1/128 ldap ldapserver=localhost ldapbasedn="dc=nodomain" ldapsearchattribute=uid" >> $PG_HBA
+ echo "local all $1 ldap ldapserver=localhost ldapbasedn="dc=nodomain" ldapsearchattribute=uid" >> $PG_HBA
+ elif [ "$DO_LDAP_TEST" != "true" -a $2 = "ldap" ];then
+ echo "do nothing because DO_LDAP_TEST is not true and auth method is ldap"
+ else
+ echo "wrong auth method \"$2\" for add_pg_hba $1"
+ exit 1
+ fi
+ done
+}
+
+# create pgpass entry
+# $1: username
+function add_pgpass()
+{
+ echo "127.0.0.1:$PGPORT:$PGDATABASE:$1:$1" >> pgpass
+ echo "127.0.0.1:$PGPORT:$PGDATABASE:$1:$1foo" >> pgpasswrong
+}
+
+# Perform actual tests
+# $1: test spec csv file
+# $2: number of PostgreSQL nodes
+# $3: clustering mode
+function do_auth
+{
+ rm -fr $TESTDIR
+ mkdir $TESTDIR
+ cd $TESTDIR
+
+ cp /dev/null $failed_usernames
+ mode=$3
+
+ # create test environment
+ echo -n "creating test environment..."
+ $PGPOOL_SETUP -m $mode -n $2 || exit 1
+ #$PGPOOL_SETUP -m $mode -n 1 || exit 1
+ echo "done."
+
+ source ./bashrc.ports
+ export PGPORT=$PGPOOL_PORT
+ export PGDATABASE=test
+
+ # Set max_init_children to 1 to make sure we reuse the
+ # connection to test wrong password rejection
+ echo "num_init_children = 1" >> etc/pgpool.conf
+
+ PGPOOL_CONF=etc/pgpool.conf
+ POOL_HBA=etc/pool_hba.conf
+ if [ ! -f $POOL_HBA ];then
+ cp ../../../../../sample/pool_hba.conf.sample $POOL_HBA
+ fi
+ POOL_PASSWD=etc/pool_passwd
+
+ #
+ # replace trust auth for all users with superuser in pg_hba.conf
+ for i in data0 data1
+ do
+ if [ ! -d $i ];then
+ continue
+ fi
+
+ sed -i "s/local *all *all *trust/local all $superuser trust/" $i/pg_hba.conf
+ sed -i "s/host *all *all *all *trust/host all $superuser all trust/" $i/pg_hba.conf
+ done
+
+ #
+ # replace trust auth for all users with superuser in pool_hba.conf
+ sed -i "s@host all all 127.0.0.1/32 trust@host all $superuser all trust@" $POOL_HBA
+ sed -i "s@host all all ::1/128 trust@host all $superuser ::1/128 trust@" $POOL_HBA
+
+ # set up pgpass
+ cp /dev/null pgpass
+ chmod 0600 pgpass
+ cp /dev/null pgpasswrong
+ chmod 0600 pgpasswrong
+
+ # pgpool.conf opt
+ cp /dev/null $PGPOOL_CONF_OPT
+# echo "include pgpool.conf.opt" >> etc/pgpool.conf
+ # add last line marker to pgpool.conf
+ echo "#last" >> etc/pgpool.conf
+
+ # start pgpool
+ ./startall
+ wait_for_pgpool_startup
+
+ IFS=","
+
+ #
+ # setup each user
+ #
+ cat $spec|while read line
+ do
+ set $line
+ if [ $1 = 'username' ];then
+ echo "skip title row"
+ else
+ username=$1
+ echo "==== $username ===="
+ pool_hba=$2
+ allow_clear=$3
+ pool_passwd=$4
+ pg_hba=$5
+ expected=$6
+
+ add_user $username $pg_hba
+ add_pool_hba $username $pool_hba $PGPOOL_VERSION_DIGIT
+ add_pool_passwd $username $pool_passwd $PGPOOL_VERSION_DIGIT
+ add_pg_hba $username $pg_hba
+ add_pgpass $username
+ fi
+ done
+ ./shutdownall
+
+ #
+ # do auth tests
+ #
+ cat $spec|while read line
+ do
+ set $line
+ username=$1
+ echo "==== $username ===="
+ pool_hba=$2
+ allow_clear=$3
+ pool_passwd=$4
+ pg_hba=$5
+ expected=$6
+
+ if [ $1 = 'username' ];then
+ echo "skip tile row"
+ elif [ "$DO_PAM_TEST" != "true" ] && [ $pool_hba = "pam" -o $pg_hba = "pam" ];then
+ echo "skip pam test"
+ elif [ "$DO_LDAP_TEST" != "true" ] && [ $pool_hba = "ldap" -o $pg_hba = "ldap" ];then
+ echo "skip ldap test"
+ else
+ cp $PGPOOL_CONF_OPT $PGPOOL_CONF_OPT.old
+ if [ $pool_hba = "scram" -o $pool_hba = "md5" -o $pool_hba = "password" -o $pool_hba = "pam" -o $pool_hba = "ldap" ];then
+ echo "enable_pool_hba = on" > $PGPOOL_CONF_OPT
+ last=`tail -1 etc/pgpool.conf`
+ if [ "$last" != "#last" ];then
+ # remove the last line if it's not a marker
+ echo "remove the last line in pgpool.conf because \"$last\""
+ sed -i '$d' etc/pgpool.conf
+ fi
+ cat $PGPOOL_CONF_OPT >> etc/pgpool.conf
+ echo "add \"`cat $PGPOOL_CONF_OPT`\""
+ else
+ if [ $allow_clear = "off" ];then
+ cp /dev/null $PGPOOL_CONF_OPT
+ else
+ echo "allow_clear_text_frontend_auth = on" > $PGPOOL_CONF_OPT
+ fi
+ last=`tail -1 etc/pgpool.conf`
+ if [ $last != "#last" ];then
+ # remove the last line if it's not a marker
+ echo "remove the last line in pgpool.conf because \"$last\""
+ sed -i '$d' etc/pgpool.conf
+ fi
+ cat $PGPOOL_CONF_OPT >> etc/pgpool.conf
+ echo "add \"`cat $PGPOOL_CONF_OPT`\""
+ fi
+
+ # if pgpool.conf.opt was changed, restart pgpool
+ cmp $PGPOOL_CONF_OPT $PGPOOL_CONF_OPT.old
+ if [ $? != 0 ];then
+ ./shutdownall
+ ./startall
+ wait_for_pgpool_startup
+ fi
+
+ result=""
+ PGPASSFILE=pgpass $PSQL -h 127.0.0.1 -U $username -c "SELECT user" >/dev/null 2>&1
+ rtn=$?
+ if [ $expected = "ok" ];then
+ echo -n "checking $username auth expecting success..."
+ if [ $rtn = 0 ];then
+ echo "ok."
+ echo -n "checking $username auth expecting success in reauth..."
+ PGPASSFILE=pgpass $PSQL -h 127.0.0.1 -U $username -c "SELECT user" >/dev/null 2>&1
+ if [ $? != 0 ];then
+ echo "$username: password verification on reauth failed."
+ else
+ # reauth was Ok.
+ echo "ok."
+ echo -n "$username: try with wrong password expecting rejected..."
+ PGPASSFILE=pgpasswrong $PSQL -h 127.0.0.1 -U $username -c "SELECT user">/dev/null 2>&1
+ if [ $? = 0 ];then
+ echo "$username: wrong password verification failed."
+ echo "$mode $num_backends $username" >> $unexpected_passwd_verifi
+ else
+ echo "ok."
+ result=ok
+ fi
+ fi
+ else
+ echo "$username: password verification failed."
+ fi
+ else # expecting fail
+ echo -n "checking $username auth expecting failure..."
+ if [ $rtn != 0 ];then
+ echo "ok."
+ result=ok
+ else
+ # make sure that wrong password is rejected
+ PGPASSFILE=pgpasswrong $PSQL -h 127.0.0.1 -U $username -c "SELECT user">/dev/null 2>&1
+ if [ $? = 0 ];then
+ echo "$username: unexpected successfull password verification"
+ echo "$mode $num_backends $username" >> $unexpected_passwd_verifi
+ else
+ # maybe this test case should have been "ok", not "fail"?
+ echo "$username: while expecting fail, wrong password was rejected but proper password was accepted"
+ fi
+ fi
+ fi
+
+ if [ "$result" != "ok" ];then
+ echo -n " $username" >> $failed_usernames
+ fi
+ fi
+ done
+
+ ./shutdownall
+ cd ..
+
+ if [ -s $failed_usernames ];then
+ echo "failed tests:"
+ cat $failed_usernames
+ echo
+ fi
+}
+
+#
+#----------------------------------------
+# Misc preparations
+
+# pgpool major version first digit (e.g. "4")
+PGPOOL_VERSION_DIGIT=`echo $PGPOOL_VERSION|awk '{print $3}'|sed 's/\([1-9]\).*$/\1/'`
+failed_usernames=/tmp/failed_usernames
+failed_modes=/tmp/failed_modes
+unexpected_passwd_verifi=/tmp/unexpected_passwd_verificatio
+total_failed_usernames=/tmp/total_failed_usernames
+trap "rm $failed_usernames $failed_modes $unexpected_passwd_verifi $total_failed_usernames" EXIT
+cp /dev/null $failed_usernames
+cp /dev/null $failed_modes
+cp /dev/null $unexpected_passwd_verifi
+cp /dev/null $total_failed_usernames
+
+source $TESTLIBS
+TESTDIR=testdir
+PSQL=$PGBIN/psql
+PG_ENC=$PGPOOL_INSTALL_DIR/bin/pg_enc
+PG_MD5=$PGPOOL_INSTALL_DIR/bin/pg_md5
+export CREATEUSER=$PGBIN/createuser
+superuser=`whoami`
+PGPOOL_CONF_OPT=etc/pgpool.conf.opt
+# .pgpoolkey
+export PGPOOLKEYFILE=`pwd`/pgpoolkey
+echo "secret" > $PGPOOLKEYFILE
+chmod 0600 $PGPOOLKEYFILE
+#
+#----------------------------------------
+# Test execution starts here
+
+# pgpool_setup does not create a replication environment for logical
+# replication mode and slony mode, which makes the test failed
+# horribly because PostgreSQL roles are not replicated. Therefore we
+# skip the tests for these modes.
+
+for mode in s r i n
+#for mode in s r i n l y
+do
+ echo "==== testing mode: $mode ==="
+ anyfail=""
+ spec=../client_auth_2node.csv
+ num_backends=2
+ do_auth $spec $num_backends $mode
+ if [ -s $failed_usernames ];then
+ anyfail="yes"
+ echo "$mode $num_backends `cat $failed_usernames`" >> $total_failed_usernames
+ fi
+
+ if [ -n "$anyfail" ];then
+ echo -n "$mode " >> $failed_modes
+ fi
+done
+
+if [ -s $unexpected_passwd_verifi ];then
+ echo
+ echo "IMPORTANT: unexpected successful password verfication found:"
+ cat $unexpected_passwd_verifi
+fi
+
+if [ -s $failed_modes ];then
+ echo
+ echo "failed mode: `cat $failed_modes`"
+ echo
+ echo "failed tests:"
+ cat $total_failed_usernames
+ exit 1
+fi
+
+exit 0