Skip to content

Commit 13f3655

Browse files
committed
Don't assume GSSAPI result strings are null-terminated.
Our uses of gss_display_status() and gss_display_name() assumed that the gss_buffer_desc strings returned by those functions are null-terminated. It appears that they generally are, given the lack of field complaints up to now. However, the available documentation does not promise this, and some man pages for gss_display_status() show examples that rely on the gss_buffer_desc.length field instead of expecting null termination. Also, we now have a report that on some implementations, clang's address sanitizer is of the opinion that the byte after the specified length is undefined. Hence, change the code to rely on the length field instead. This might well be cosmetic rather than fixing any real bug, but it's hard to be sure, so back-patch to all supported branches. While here, also back-patch the v12 changes that made pg_GSS_error deal honestly with multiple messages available from gss_display_status. Per report from Sudheer H R. Discussion: https://postgr.es/m/5372B6D4-8276-42C0-B8FB-BD0918826FC3@tekenlight.com
1 parent b961bdf commit 13f3655

File tree

3 files changed

+25
-14
lines changed

3 files changed

+25
-14
lines changed

src/backend/libpq/auth.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,7 @@ pg_GSS_checkauth(Port *port)
11931193
min_stat,
11941194
lmin_s;
11951195
gss_buffer_desc gbuf;
1196+
char *princ;
11961197

11971198
/*
11981199
* Get the name of the user that authenticated, and compare it to the pg
@@ -1206,18 +1207,27 @@ pg_GSS_checkauth(Port *port)
12061207
return STATUS_ERROR;
12071208
}
12081209

1210+
/*
1211+
* gbuf.value might not be null-terminated, so turn it into a regular
1212+
* null-terminated string.
1213+
*/
1214+
princ = palloc(gbuf.length + 1);
1215+
memcpy(princ, gbuf.value, gbuf.length);
1216+
princ[gbuf.length] = '\0';
1217+
gss_release_buffer(&lmin_s, &gbuf);
1218+
12091219
/*
12101220
* Copy the original name of the authenticated principal into our backend
12111221
* memory for display later.
12121222
*/
1213-
port->gss->princ = MemoryContextStrdup(TopMemoryContext, gbuf.value);
1223+
port->gss->princ = MemoryContextStrdup(TopMemoryContext, princ);
12141224

12151225
/*
12161226
* Split the username at the realm separator
12171227
*/
1218-
if (strchr(gbuf.value, '@'))
1228+
if (strchr(princ, '@'))
12191229
{
1220-
char *cp = strchr(gbuf.value, '@');
1230+
char *cp = strchr(princ, '@');
12211231

12221232
/*
12231233
* If we are not going to include the realm in the username that is
@@ -1244,7 +1254,7 @@ pg_GSS_checkauth(Port *port)
12441254
elog(DEBUG2,
12451255
"GSSAPI realm (%s) and configured realm (%s) don't match",
12461256
cp, port->hba->krb_realm);
1247-
gss_release_buffer(&lmin_s, &gbuf);
1257+
pfree(princ);
12481258
return STATUS_ERROR;
12491259
}
12501260
}
@@ -1253,15 +1263,14 @@ pg_GSS_checkauth(Port *port)
12531263
{
12541264
elog(DEBUG2,
12551265
"GSSAPI did not return realm but realm matching was requested");
1256-
1257-
gss_release_buffer(&lmin_s, &gbuf);
1266+
pfree(princ);
12581267
return STATUS_ERROR;
12591268
}
12601269

1261-
ret = check_usermap(port->hba->usermap, port->user_name, gbuf.value,
1270+
ret = check_usermap(port->hba->usermap, port->user_name, princ,
12621271
pg_krb_caseins_users);
12631272

1264-
gss_release_buffer(&lmin_s, &gbuf);
1273+
pfree(princ);
12651274

12661275
return ret;
12671276
}

src/backend/libpq/be-gssapi-common.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ pg_GSS_error_int(char *s, size_t len, OM_uint32 stat, int type)
2929
OM_uint32 lmin_s,
3030
msg_ctx = 0;
3131

32-
s[0] = '\0'; /* just in case gss_display_status fails */
33-
3432
do
3533
{
3634
if (gss_display_status(&lmin_s, stat, type, GSS_C_NO_OID,
@@ -43,16 +41,19 @@ pg_GSS_error_int(char *s, size_t len, OM_uint32 stat, int type)
4341
i++;
4442
}
4543
if (i < len)
46-
strlcpy(s + i, gmsg.value, len - i);
44+
memcpy(s + i, gmsg.value, Min(len - i, gmsg.length));
4745
i += gmsg.length;
4846
gss_release_buffer(&lmin_s, &gmsg);
4947
}
5048
while (msg_ctx);
5149

52-
if (i >= len)
50+
/* add nul termination */
51+
if (i < len)
52+
s[i] = '\0';
53+
else
5354
{
5455
elog(COMMERROR, "incomplete GSS error report");
55-
s[len - 1] = '\0'; /* ensure string is nul-terminated */
56+
s[len - 1] = '\0';
5657
}
5758
}
5859

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ pg_GSS_error_int(PQExpBuffer str, OM_uint32 stat, int type)
3434
if (gss_display_status(&lmin_s, stat, type, GSS_C_NO_OID,
3535
&msg_ctx, &lmsg) != GSS_S_COMPLETE)
3636
break;
37-
appendPQExpBuffer(str, " %s", (char *) lmsg.value);
37+
appendPQExpBufferChar(str, ' ');
38+
appendBinaryPQExpBuffer(str, lmsg.value, lmsg.length);
3839
gss_release_buffer(&lmin_s, &lmsg);
3940
} while (msg_ctx);
4041
}

0 commit comments

Comments
 (0)