Skip to content

Commit b3a5bf7

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 d379659 commit b3a5bf7

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
@@ -2814,11 +2814,16 @@ PQconnectPoll(PGconn *conn)
28142814
#ifdef USE_SSL
28152815

28162816
/*
2817-
* If SSL is enabled and we haven't already got it running,
2818-
* request it instead of sending the startup message.
2817+
* If SSL is enabled and we haven't already got encryption of
2818+
* some sort running, request SSL instead of sending the
2819+
* startup message.
28192820
*/
28202821
if (conn->allow_ssl_try && !conn->wait_ssl_try &&
2821-
!conn->ssl_in_use)
2822+
!conn->ssl_in_use
2823+
#ifdef ENABLE_GSS
2824+
&& !conn->gssenc
2825+
#endif
2826+
)
28222827
{
28232828
ProtocolVersion pv;
28242829

@@ -2947,6 +2952,7 @@ PQconnectPoll(PGconn *conn)
29472952
}
29482953
/* Otherwise, proceed with normal startup */
29492954
conn->allow_ssl_try = false;
2955+
/* We can proceed using this connection */
29502956
conn->status = CONNECTION_MADE;
29512957
return PGRES_POLLING_WRITING;
29522958
}
@@ -3044,8 +3050,7 @@ PQconnectPoll(PGconn *conn)
30443050
* don't hang up the socket, though.
30453051
*/
30463052
conn->try_gss = false;
3047-
pqDropConnection(conn, true);
3048-
conn->status = CONNECTION_NEEDED;
3053+
need_new_connection = true;
30493054
goto keep_going;
30503055
}
30513056

@@ -3063,6 +3068,7 @@ PQconnectPoll(PGconn *conn)
30633068
}
30643069

30653070
conn->try_gss = false;
3071+
/* We can proceed using this connection */
30663072
conn->status = CONNECTION_MADE;
30673073
return PGRES_POLLING_WRITING;
30683074
}
@@ -3091,8 +3097,7 @@ PQconnectPoll(PGconn *conn)
30913097
* the current connection to do so, though.
30923098
*/
30933099
conn->try_gss = false;
3094-
pqDropConnection(conn, true);
3095-
conn->status = CONNECTION_NEEDED;
3100+
need_new_connection = true;
30963101
goto keep_going;
30973102
}
30983103
return pollres;
@@ -3263,10 +3268,9 @@ PQconnectPoll(PGconn *conn)
32633268
*/
32643269
if (conn->gssenc && conn->gssencmode[0] == 'p')
32653270
{
3266-
/* postmaster expects us to drop the connection */
3271+
/* only retry once */
32673272
conn->try_gss = false;
3268-
pqDropConnection(conn, true);
3269-
conn->status = CONNECTION_NEEDED;
3273+
need_new_connection = true;
32703274
goto keep_going;
32713275
}
32723276
#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