Skip to content

Commit 4bbf110

Browse files
committed
Add libpq connection parameter "scram_channel_binding"
This parameter can be used to enforce the channel binding type used during a SCRAM authentication. This can be useful to check code paths where an invalid channel binding type is used by a client and will be even more useful to allow testing other channel binding types when they are added. The default value is tls-unique, which is what RFC 5802 specifies. Clients can optionally specify an empty value, which has as effect to not use channel binding and use SCRAM-SHA-256 as chosen SASL mechanism. More tests for SCRAM and channel binding are added to the SSL test suite. Author: Author: Michael Paquier <michael.paquier@gmail.com>
1 parent ab9e0e7 commit 4bbf110

File tree

7 files changed

+69
-9
lines changed

7 files changed

+69
-9
lines changed

doc/src/sgml/libpq.sgml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,30 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
12221222
</listitem>
12231223
</varlistentry>
12241224

1225+
<varlistentry id="libpq-scram-channel-binding" xreflabel="scram_channel_binding">
1226+
<term><literal>scram_channel_binding</literal></term>
1227+
<listitem>
1228+
<para>
1229+
Specifies the channel binding type to use with SCRAM authentication.
1230+
The list of channel binding types supported by server are listed in
1231+
<xref linkend="sasl-authentication"/>. An empty value specifies that
1232+
the client will not use channel binding. The default value is
1233+
<literal>tls-unique</literal>.
1234+
</para>
1235+
1236+
<para>
1237+
Channel binding is only supported on SSL connections. If the
1238+
connection is not using SSL, then this setting is ignored.
1239+
</para>
1240+
1241+
<para>
1242+
This parameter is mainly intended for protocol testing. In normal
1243+
use, there should not be a need to choose a channel binding type other
1244+
than the default one.
1245+
</para>
1246+
</listitem>
1247+
</varlistentry>
1248+
12251249
<varlistentry id="libpq-connect-sslmode" xreflabel="sslmode">
12261250
<term><literal>sslmode</literal></term>
12271251
<listitem>

src/interfaces/libpq/fe-auth-scram.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ pg_fe_scram_init(const char *username,
9393
const char *password,
9494
bool ssl_in_use,
9595
const char *sasl_mechanism,
96+
const char *channel_binding_type,
9697
char *tls_finished_message,
9798
size_t tls_finished_len)
9899
{
@@ -112,17 +113,14 @@ pg_fe_scram_init(const char *username,
112113
state->tls_finished_message = tls_finished_message;
113114
state->tls_finished_len = tls_finished_len;
114115
state->sasl_mechanism = strdup(sasl_mechanism);
116+
state->channel_binding_type = channel_binding_type;
117+
115118
if (!state->sasl_mechanism)
116119
{
117120
free(state);
118121
return NULL;
119122
}
120123

121-
/*
122-
* Store channel binding type. Only one type is currently supported.
123-
*/
124-
state->channel_binding_type = SCRAM_CHANNEL_BINDING_TLS_UNIQUE;
125-
126124
/* Normalize the password with SASLprep, if possible */
127125
rc = pg_saslprep(password, &prep_password);
128126
if (rc == SASLPREP_OOM)
@@ -375,6 +373,15 @@ build_client_first_message(fe_scram_state *state, PQExpBuffer errormessage)
375373
Assert(state->ssl_in_use);
376374
appendPQExpBuffer(&buf, "p=%s", state->channel_binding_type);
377375
}
376+
else if (state->channel_binding_type == NULL ||
377+
strlen(state->channel_binding_type) == 0)
378+
{
379+
/*
380+
* Client has chosen to not show to server that it supports channel
381+
* binding.
382+
*/
383+
appendPQExpBuffer(&buf, "n");
384+
}
378385
else if (state->ssl_in_use)
379386
{
380387
/*
@@ -493,6 +500,9 @@ build_client_final_message(fe_scram_state *state, PQExpBuffer errormessage)
493500

494501
free(cbind_input);
495502
}
503+
else if (state->channel_binding_type == NULL ||
504+
strlen(state->channel_binding_type) == 0)
505+
appendPQExpBuffer(&buf, "c=biws"); /* base64 of "n,," */
496506
else if (state->ssl_in_use)
497507
appendPQExpBuffer(&buf, "c=eSws"); /* base64 of "y,," */
498508
else

src/interfaces/libpq/fe-auth.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -528,11 +528,13 @@ pg_SASL_init(PGconn *conn, int payloadlen)
528528

529529
/*
530530
* Select the mechanism to use. Pick SCRAM-SHA-256-PLUS over anything
531-
* else. Pick SCRAM-SHA-256 if nothing else has already been picked.
532-
* If we add more mechanisms, a more refined priority mechanism might
533-
* become necessary.
531+
* else if a channel binding type is set. Pick SCRAM-SHA-256 if
532+
* nothing else has already been picked. If we add more mechanisms, a
533+
* more refined priority mechanism might become necessary.
534534
*/
535535
if (conn->ssl_in_use &&
536+
conn->scram_channel_binding &&
537+
strlen(conn->scram_channel_binding) > 0 &&
536538
strcmp(mechanism_buf.data, SCRAM_SHA256_PLUS_NAME) == 0)
537539
selected_mechanism = SCRAM_SHA256_PLUS_NAME;
538540
else if (strcmp(mechanism_buf.data, SCRAM_SHA256_NAME) == 0 &&
@@ -591,6 +593,7 @@ pg_SASL_init(PGconn *conn, int payloadlen)
591593
password,
592594
conn->ssl_in_use,
593595
selected_mechanism,
596+
conn->scram_channel_binding,
594597
tls_finished,
595598
tls_finished_len);
596599
if (!conn->sasl_state)

src/interfaces/libpq/fe-auth.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ extern void *pg_fe_scram_init(const char *username,
2727
const char *password,
2828
bool ssl_in_use,
2929
const char *sasl_mechanism,
30+
const char *channel_binding_type,
3031
char *tls_finished_message,
3132
size_t tls_finished_len);
3233
extern void pg_fe_scram_free(void *opaq);

src/interfaces/libpq/fe-connect.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
7171
#endif
7272

7373
#include "common/ip.h"
74+
#include "common/scram-common.h"
7475
#include "mb/pg_wchar.h"
7576
#include "port/pg_bswap.h"
7677

@@ -122,6 +123,7 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
122123
#define DefaultOption ""
123124
#define DefaultAuthtype ""
124125
#define DefaultTargetSessionAttrs "any"
126+
#define DefaultSCRAMChannelBinding SCRAM_CHANNEL_BINDING_TLS_UNIQUE
125127
#ifdef USE_SSL
126128
#define DefaultSSLMode "prefer"
127129
#else
@@ -262,6 +264,11 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
262264
"TCP-Keepalives-Count", "", 10, /* strlen(INT32_MAX) == 10 */
263265
offsetof(struct pg_conn, keepalives_count)},
264266

267+
{"scram_channel_binding", NULL, DefaultSCRAMChannelBinding, NULL,
268+
"SCRAM-Channel-Binding", "D",
269+
21, /* sizeof("tls-server-end-point") == 21 */
270+
offsetof(struct pg_conn, scram_channel_binding)},
271+
265272
/*
266273
* ssl options are allowed even without client SSL support because the
267274
* client can still handle SSL modes "disable" and "allow". Other
@@ -3469,6 +3476,8 @@ freePGconn(PGconn *conn)
34693476
free(conn->keepalives_interval);
34703477
if (conn->keepalives_count)
34713478
free(conn->keepalives_count);
3479+
if (conn->scram_channel_binding)
3480+
free(conn->scram_channel_binding);
34723481
if (conn->sslmode)
34733482
free(conn->sslmode);
34743483
if (conn->sslcert)

src/interfaces/libpq/libpq-int.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ struct pg_conn
349349
* retransmits */
350350
char *keepalives_count; /* maximum number of TCP keepalive
351351
* retransmits */
352+
char *scram_channel_binding; /* SCRAM channel binding type */
352353
char *sslmode; /* SSL mode (require,prefer,allow,disable) */
353354
char *sslcompression; /* SSL compression (0 or 1) */
354355
char *sslkey; /* client key filename */

src/test/ssl/t/002_scram.pl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use warnings;
55
use PostgresNode;
66
use TestLib;
7-
use Test::More tests => 1;
7+
use Test::More tests => 4;
88
use ServerSetup;
99
use File::Copy;
1010

@@ -34,5 +34,17 @@
3434
$common_connstr =
3535
"user=ssltestuser dbname=trustdb sslmode=require hostaddr=$SERVERHOSTADDR";
3636

37+
# Default settings
3738
test_connect_ok($common_connstr, '',
3839
"SCRAM authentication with default channel binding");
40+
41+
# Channel binding settings
42+
test_connect_ok($common_connstr,
43+
"scram_channel_binding=tls-unique",
44+
"SCRAM authentication with tls-unique as channel binding");
45+
test_connect_ok($common_connstr,
46+
"scram_channel_binding=''",
47+
"SCRAM authentication without channel binding");
48+
test_connect_fails($common_connstr,
49+
"scram_channel_binding=not-exists",
50+
"SCRAM authentication with invalid channel binding");

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy