Skip to content

Commit ff6ce9a

Browse files
committed
Fix bugs in libpq's GSSAPI encryption support.
The critical issue fixed here is that if a GSSAPI-encrypted connection is successfully made, pqsecure_open_gss() cleared conn->allow_ssl_try, as an admittedly-hacky way of preventing us from then trying to tunnel SSL encryption over the already-encrypted connection. The problem with that is that if we abandon the GSSAPI connection because of a failure during authentication, we would not attempt SSL encryption in the next try with the same server. This can lead to unexpected connection failure, or silently getting a non-encrypted connection where an encrypted one is expected. Fortunately, we'd only manage to make a GSSAPI-encrypted connection if both client and server hold valid tickets in the same Kerberos infrastructure, which is a relatively uncommon environment. Nonetheless this is a very nasty bug with potential security consequences. To fix, don't reset the flag, instead adding a check for conn->gssenc being already true when deciding whether to try to initiate SSL. While here, fix some lesser issues in libpq's GSSAPI code: * Use the need_new_connection stanza when dropping an attempted GSSAPI connection, instead of partially duplicating that code. The consequences of this are pretty minor: AFAICS it could only lead to auth_req_received or password_needed remaining set when they shouldn't, which is not too harmful. * Fix pg_GSS_error() to not repeat the "mprefix" it's given multiple times, and to notice any failure return from gss_display_status(). * Avoid gratuitous dependency on NI_MAXHOST in pg_GSS_load_servicename(). Per report from Mikael Gustavsson. Back-patch to v12 where this code was introduced. Discussion: https://postgr.es/m/e5b0b6ed05764324a2f3fe7acfc766d5@smhi.se
1 parent cf61b07 commit ff6ce9a

File tree

3 files changed

+29
-28
lines changed

3 files changed

+29
-28
lines changed

src/interfaces/libpq/fe-connect.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2909,11 +2909,16 @@ PQconnectPoll(PGconn *conn)
29092909
#ifdef USE_SSL
29102910

29112911
/*
2912-
* If SSL is enabled and we haven't already got it running,
2913-
* request it instead of sending the startup message.
2912+
* If SSL is enabled and we haven't already got encryption of
2913+
* some sort running, request SSL instead of sending the
2914+
* startup message.
29142915
*/
29152916
if (conn->allow_ssl_try && !conn->wait_ssl_try &&
2916-
!conn->ssl_in_use)
2917+
!conn->ssl_in_use
2918+
#ifdef ENABLE_GSS
2919+
&& !conn->gssenc
2920+
#endif
2921+
)
29172922
{
29182923
ProtocolVersion pv;
29192924

@@ -3042,6 +3047,7 @@ PQconnectPoll(PGconn *conn)
30423047
}
30433048
/* Otherwise, proceed with normal startup */
30443049
conn->allow_ssl_try = false;
3050+
/* We can proceed using this connection */
30453051
conn->status = CONNECTION_MADE;
30463052
return PGRES_POLLING_WRITING;
30473053
}
@@ -3139,8 +3145,7 @@ PQconnectPoll(PGconn *conn)
31393145
* don't hang up the socket, though.
31403146
*/
31413147
conn->try_gss = false;
3142-
pqDropConnection(conn, true);
3143-
conn->status = CONNECTION_NEEDED;
3148+
need_new_connection = true;
31443149
goto keep_going;
31453150
}
31463151

@@ -3158,6 +3163,7 @@ PQconnectPoll(PGconn *conn)
31583163
}
31593164

31603165
conn->try_gss = false;
3166+
/* We can proceed using this connection */
31613167
conn->status = CONNECTION_MADE;
31623168
return PGRES_POLLING_WRITING;
31633169
}
@@ -3186,8 +3192,7 @@ PQconnectPoll(PGconn *conn)
31863192
* the current connection to do so, though.
31873193
*/
31883194
conn->try_gss = false;
3189-
pqDropConnection(conn, true);
3190-
conn->status = CONNECTION_NEEDED;
3195+
need_new_connection = true;
31913196
goto keep_going;
31923197
}
31933198
return pollres;
@@ -3354,10 +3359,9 @@ PQconnectPoll(PGconn *conn)
33543359
*/
33553360
if (conn->gssenc && conn->gssencmode[0] == 'p')
33563361
{
3357-
/* postmaster expects us to drop the connection */
3362+
/* only retry once */
33583363
conn->try_gss = false;
3359-
pqDropConnection(conn, true);
3360-
conn->status = CONNECTION_NEEDED;
3364+
need_new_connection = true;
33613365
goto keep_going;
33623366
}
33633367
#endif

src/interfaces/libpq/fe-gssapi-common.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,21 @@
2020

2121
/*
2222
* Fetch all errors of a specific type and append to "str".
23+
* Each error string is preceded by a space.
2324
*/
2425
static void
25-
pg_GSS_error_int(PQExpBuffer str, const char *mprefix,
26-
OM_uint32 stat, int type)
26+
pg_GSS_error_int(PQExpBuffer str, OM_uint32 stat, int type)
2727
{
2828
OM_uint32 lmin_s;
2929
gss_buffer_desc lmsg;
3030
OM_uint32 msg_ctx = 0;
3131

3232
do
3333
{
34-
gss_display_status(&lmin_s, stat, type,
35-
GSS_C_NO_OID, &msg_ctx, &lmsg);
36-
appendPQExpBuffer(str, "%s: %s\n", mprefix, (char *) lmsg.value);
34+
if (gss_display_status(&lmin_s, stat, type, GSS_C_NO_OID,
35+
&msg_ctx, &lmsg) != GSS_S_COMPLETE)
36+
break;
37+
appendPQExpBuffer(str, " %s", (char *) lmsg.value);
3738
gss_release_buffer(&lmin_s, &lmsg);
3839
} while (msg_ctx);
3940
}
@@ -46,12 +47,11 @@ pg_GSS_error(const char *mprefix, PGconn *conn,
4647
OM_uint32 maj_stat, OM_uint32 min_stat)
4748
{
4849
resetPQExpBuffer(&conn->errorMessage);
49-
50-
/* Fetch major error codes */
51-
pg_GSS_error_int(&conn->errorMessage, mprefix, maj_stat, GSS_C_GSS_CODE);
52-
53-
/* Add the minor codes as well */
54-
pg_GSS_error_int(&conn->errorMessage, mprefix, min_stat, GSS_C_MECH_CODE);
50+
appendPQExpBuffer(&conn->errorMessage, "%s:", mprefix);
51+
pg_GSS_error_int(&conn->errorMessage, maj_stat, GSS_C_GSS_CODE);
52+
appendPQExpBufferChar(&conn->errorMessage, ':');
53+
pg_GSS_error_int(&conn->errorMessage, min_stat, GSS_C_MECH_CODE);
54+
appendPQExpBufferChar(&conn->errorMessage, '\n');
5555
}
5656

5757
/*
@@ -103,7 +103,7 @@ pg_GSS_load_servicename(PGconn *conn)
103103
* Import service principal name so the proper ticket can be acquired by
104104
* the GSSAPI system.
105105
*/
106-
maxlen = NI_MAXHOST + strlen(conn->krbsrvname) + 2;
106+
maxlen = strlen(conn->krbsrvname) + strlen(host) + 2;
107107
temp_gbuf.value = (char *) malloc(maxlen);
108108
if (!temp_gbuf.value)
109109
{

src/interfaces/libpq/fe-secure-gssapi.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -647,17 +647,14 @@ pqsecure_open_gss(PGconn *conn)
647647
if (output.length == 0)
648648
{
649649
/*
650-
* We're done - hooray! Kind of gross, but we need to disable SSL
651-
* here so that we don't accidentally tunnel one over the other.
650+
* We're done - hooray! Set flag to tell the low-level I/O routines
651+
* to do GSS wrapping/unwrapping.
652652
*/
653-
#ifdef USE_SSL
654-
conn->allow_ssl_try = false;
655-
#endif
653+
conn->gssenc = true;
656654

657655
/* Clean up */
658656
gss_release_cred(&minor, &conn->gcred);
659657
conn->gcred = GSS_C_NO_CREDENTIAL;
660-
conn->gssenc = true;
661658
gss_release_buffer(&minor, &output);
662659

663660
/*

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