Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f179d5e

Browse files
committed
Add support for using SSL client certificates to authenticate to the
database (only for SSL connections, obviously).
1 parent 3c486fb commit f179d5e

File tree

6 files changed

+120
-14
lines changed

6 files changed

+120
-14
lines changed

doc/src/sgml/client-auth.sgml

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.111 2008/11/18 13:10:20 petere Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.112 2008/11/20 11:48:26 mha Exp $ -->
22

33
<chapter id="client-authentication">
44
<title>Client Authentication</title>
@@ -387,6 +387,16 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
387387
</listitem>
388388
</varlistentry>
389389

390+
<varlistentry>
391+
<term><literal>cert</></term>
392+
<listitem>
393+
<para>
394+
Authenticate using SSL client certificates. See
395+
<xref linkend="auth-cert"> for details.
396+
</para>
397+
</listitem>
398+
</varlistentry>
399+
390400
<varlistentry>
391401
<term><literal>pam</></term>
392402
<listitem>
@@ -1114,6 +1124,25 @@ ldapserver=ldap.example.net prefix="cn=" suffix="dc=example, dc=net"
11141124

11151125
</sect2>
11161126

1127+
<sect2 id="auth-cert">
1128+
<title>Certificate authentication</title>
1129+
1130+
<indexterm zone="auth-cert">
1131+
<primary>Certificate</primary>
1132+
</indexterm>
1133+
1134+
<para>
1135+
This authentication method uses SSL client certificates to perform
1136+
authentication. It is therefore only available for SSL connections.
1137+
When using this authentication method, the server will require that
1138+
the client provide a certificate. No password prompt will be sent
1139+
to the client. The <literal>cn</literal> attribute of the certificate
1140+
will be matched with the username the user is trying to log in as,
1141+
and if they match the login will be allowed. Username mapping can be
1142+
used if the usernames don't match.
1143+
</para>
1144+
</sect2>
1145+
11171146
<sect2 id="auth-pam">
11181147
<title>PAM authentication</title>
11191148

doc/src/sgml/runtime.sgml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.421 2008/11/20 09:29:35 mha Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.422 2008/11/20 11:48:26 mha Exp $ -->
22

33
<chapter Id="runtime">
44
<title>Operating System Environment</title>
@@ -1674,11 +1674,9 @@ $ <userinput>kill -INT `head -1 /usr/local/pgsql/data/postmaster.pid`</userinput
16741674
</para>
16751675

16761676
<para>
1677-
<productname>PostgreSQL</> currently does not support authentication
1678-
using client certificates, since it cannot differentiate between
1679-
different users. As long as the user holds any certificate issued
1680-
by a trusted CA it will be accepted, regardless of what account the
1681-
user is trying to connect with.
1677+
You can use the authentication method <literal>cert</> to use the
1678+
client certificate for authenticating users. See
1679+
<xref linkend="auth-cert"> for details.
16821680
</para>
16831681
</sect2>
16841682

src/backend/libpq/auth.c

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.172 2008/11/20 09:29:36 mha Exp $
11+
* $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.173 2008/11/20 11:48:26 mha Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -113,6 +113,14 @@ ULONG(*__ldap_start_tls_sA) (
113113
static int CheckLDAPAuth(Port *port);
114114
#endif /* USE_LDAP */
115115

116+
/*----------------------------------------------------------------
117+
* Cert authentication
118+
*----------------------------------------------------------------
119+
*/
120+
#ifdef USE_SSL
121+
static int CheckCertAuth(Port *port);
122+
#endif
123+
116124

117125
/*----------------------------------------------------------------
118126
* Kerberos and GSSAPI GUCs
@@ -431,6 +439,14 @@ ClientAuthentication(Port *port)
431439
#endif
432440
break;
433441

442+
case uaCert:
443+
#ifdef USE_SSL
444+
status = CheckCertAuth(port);
445+
#else
446+
Assert(false);
447+
#endif
448+
break;
449+
434450
case uaTrust:
435451
status = STATUS_OK;
436452
break;
@@ -2120,3 +2136,28 @@ CheckLDAPAuth(Port *port)
21202136
}
21212137
#endif /* USE_LDAP */
21222138

2139+
2140+
/*----------------------------------------------------------------
2141+
* SSL client certificate authentication
2142+
*----------------------------------------------------------------
2143+
*/
2144+
#ifdef USE_SSL
2145+
static int
2146+
CheckCertAuth(Port *port)
2147+
{
2148+
Assert(port->ssl);
2149+
2150+
/* Make sure we have received a username in the certificate */
2151+
if (port->peer_cn == NULL ||
2152+
strlen(port->peer_cn) <= 0)
2153+
{
2154+
ereport(LOG,
2155+
(errmsg("Certificate login failed for user \"%s\": client certificate contains no username",
2156+
port->user_name)));
2157+
return STATUS_ERROR;
2158+
}
2159+
2160+
/* Just pass the certificate CN to the usermap check */
2161+
return check_usermap(port->hba->usermap, port->user_name, port->peer_cn, false);
2162+
}
2163+
#endif

src/backend/libpq/hba.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.173 2008/11/20 09:29:36 mha Exp $
13+
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.174 2008/11/20 11:48:26 mha Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -858,6 +858,12 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
858858
parsedline->auth_method = uaLDAP;
859859
#else
860860
unsupauth = "ldap";
861+
#endif
862+
else if (strcmp(token, "cert") == 0)
863+
#ifdef USE_SSL
864+
parsedline->auth_method = uaCert;
865+
#else
866+
unsupauth = "cert";
861867
#endif
862868
else
863869
{
@@ -893,6 +899,17 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
893899
return false;
894900
}
895901

902+
if (parsedline->conntype != ctHostSSL &&
903+
parsedline->auth_method == uaCert)
904+
{
905+
ereport(LOG,
906+
(errcode(ERRCODE_CONFIG_FILE_ERROR),
907+
errmsg("cert authentication is only supported on hostssl connections"),
908+
errcontext("line %d of configuration file \"%s\"",
909+
line_num, HbaFileName)));
910+
return false;
911+
}
912+
896913
/* Parse remaining arguments */
897914
while ((line_item = lnext(line_item)) != NULL)
898915
{
@@ -923,8 +940,9 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
923940
if (parsedline->auth_method != uaIdent &&
924941
parsedline->auth_method != uaKrb5 &&
925942
parsedline->auth_method != uaGSS &&
926-
parsedline->auth_method != uaSSPI)
927-
INVALID_AUTH_OPTION("map", "ident, krb5, gssapi and sspi");
943+
parsedline->auth_method != uaSSPI &&
944+
parsedline->auth_method != uaCert)
945+
INVALID_AUTH_OPTION("map", "ident, krb5, gssapi, sspi and cert");
928946
parsedline->usermap = pstrdup(c);
929947
}
930948
else if (strcmp(token, "clientcert") == 0)
@@ -957,7 +975,18 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
957975
parsedline->clientcert = true;
958976
}
959977
else
978+
{
979+
if (parsedline->auth_method == uaCert)
980+
{
981+
ereport(LOG,
982+
(errcode(ERRCODE_CONFIG_FILE_ERROR),
983+
errmsg("clientcert can not be set to 0 when using \"cert\" authentication"),
984+
errcontext("line %d of configuration file \"%s\"",
985+
line_num, HbaFileName)));
986+
return false;
987+
}
960988
parsedline->clientcert = false;
989+
}
961990
}
962991
else if (strcmp(token, "pamservice") == 0)
963992
{
@@ -1021,6 +1050,14 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
10211050
{
10221051
MANDATORY_AUTH_ARG(parsedline->ldapserver, "ldapserver", "ldap");
10231052
}
1053+
1054+
/*
1055+
* Enforce any parameters implied by other settings.
1056+
*/
1057+
if (parsedline->auth_method == uaCert)
1058+
{
1059+
parsedline->clientcert = true;
1060+
}
10241061

10251062
return true;
10261063
}

src/backend/libpq/pg_hba.conf.sample

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
# an IP address and netmask in separate columns to specify the set of hosts.
3636
#
3737
# METHOD can be "trust", "reject", "md5", "crypt", "password", "gss", "sspi",
38-
# "krb5", "ident", "pam" or "ldap". Note that "password" sends passwords
38+
# "krb5", "ident", "pam", "ldap" or "cert". Note that "password" sends passwords
3939
# in clear text; "md5" is preferred since it sends encrypted passwords.
4040
#
4141
# OPTIONS are a set of options for the authentication in the format

src/include/libpq/hba.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Interface to hba.c
55
*
66
*
7-
* $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.52 2008/11/20 09:29:36 mha Exp $
7+
* $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.53 2008/11/20 11:48:26 mha Exp $
88
*
99
*-------------------------------------------------------------------------
1010
*/
@@ -26,7 +26,8 @@ typedef enum UserAuth
2626
uaGSS,
2727
uaSSPI,
2828
uaPAM,
29-
uaLDAP
29+
uaLDAP,
30+
uaCert
3031
} UserAuth;
3132

3233
typedef enum ConnType

0 commit comments

Comments
 (0)