Increase buffer size for GSSAPI exchanges

Kerberos ticket may include additional authorization data (AD)
information. With MIT Kerberos 1.21 a minimal PAC AD is included.
In Active Directory or FreeIPA environments where a full PAC AD is
available, the size of Kerberos ticket may be up to 64Kb.

Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
Alexander Bokovoy 2024-03-01 13:58:41 +02:00
parent 47c232b881
commit 8e3b84789d
3 changed files with 52 additions and 12 deletions

View File

@ -89,6 +89,7 @@ typedef struct client { /* Connection Information: */
FLAG confirmed; /* confirm state */
CLIENTSTATE cState; /* state needing confirmation */
char cOption; /* option initiating the confirmation */
size_t tokenSize; /* buffer size for GSSAPI token */
} CONSCLIENT;
extern void Replay(CONSENT *, CONSFILE *, unsigned short);

View File

@ -1964,13 +1964,19 @@ int
AttemptGSSAPI(CONSCLIENT *pCL)
{
int nr, ret = 0;
char buf[1024];
char *buf = NULL;
gss_buffer_desc sendtok, recvtok, dbuf;
gss_ctx_id_t gssctx = GSS_C_NO_CONTEXT;
OM_uint32 stmaj, stmin, mctx, dmin;
gss_name_t user = 0;
if ((nr = FileRead(pCL->fd, buf, sizeof(buf))) <= 0) {
buf = malloc(pCL->tokenSize);
if (buf == NULL) {
Error("Unable to allocate a buffer for GSSAPI token");
return -1;
}
if ((nr = FileRead(pCL->fd, buf, pCL->tokenSize)) <= 0) {
free(buf);
return nr;
}
recvtok.value = buf;
@ -2009,6 +2015,8 @@ AttemptGSSAPI(CONSCLIENT *pCL)
Error("GSSAPI didn't work, %*s", dbuf.length, dbuf.value);
ret = -1;
}
free(buf);
return ret;
}
#endif
@ -3097,12 +3105,31 @@ DoClientRead(GRPENT *pGE, CONSCLIENT *pCLServing)
}
#endif
#if HAVE_GSSAPI
#define MAX_GSSAPI_TOKSIZE 64*1024
} else if (pCLServing->iState == S_IDENT &&
strcmp(pcCmd, "gssapi") == 0) {
FileWrite(pCLServing->fd, FLAGFALSE, "ok\r\n", -1);
/* Change the I/O mode right away, we'll do the read
* and accept when the select gets back to us */
pCLServing->ioState = INGSSACCEPT;
if (pcArgs == (char *)0) {
FileWrite(pCLServing->fd, FLAGFALSE,
"gssapi requires argument\r\n", -1);
} else {
FileWrite(pCLServing->fd, FLAGFALSE, "ok\r\n", -1);
/* Read the token size but limit it to 64K,
* that's practical limit for GSSAPI krb5 mechanism.
*
* The client connection will be rejected for large
* requests as server will not be able to parse
* incomplete ASN.1 but this is intentional. */
pCLServing->tokenSize = (size_t) strtol(pcArgs, NULL, 10);
if (pCLServing->tokenSize > MAX_GSSAPI_TOKSIZE) {
FileWrite(pCLServing->fd, FLAGFALSE,
"gssapi token size too large\r\n", -1);
pCLServing->tokenSize = MAX_GSSAPI_TOKSIZE;
}
/* Change the I/O mode right away, we'll do the read
* and accept when the select gets back to us */
pCLServing->ioState = INGSSACCEPT;
}
#endif
} else if (pCLServing->iState == S_IDENT &&
strcmp(pcCmd, "login") == 0) {

View File

@ -167,11 +167,12 @@ AttemptSSL(CONSFILE *pcf)
#endif
#if HAVE_GSSAPI
#define MAX_GSSAPI_TOKSIZE 64*1024
gss_name_t gss_server_name = GSS_C_NO_NAME;
gss_ctx_id_t secctx = GSS_C_NO_CONTEXT;
gss_buffer_desc mytok = GSS_C_EMPTY_BUFFER;
int
size_t
CanGetGSSContext(const char *servername)
{
char namestr[128];
@ -208,18 +209,22 @@ CanGetGSSContext(const char *servername)
}
int
AttemptGSSAPI(CONSFILE *pcf)
AttemptGSSAPI(CONSFILE *pcf, size_t toksize)
{
OM_uint32 stmaj, stmin;
gss_buffer_desc servertok;
char buf[1024];
char *buf = NULL;
int nr;
int ret;
buf = malloc(toksize);
if (buf == NULL) {
return -1;
}
FileSetQuoteIAC(pcf, FLAGFALSE);
FileWrite(pcf, FLAGFALSE, mytok.value, mytok.length);
FileSetQuoteIAC(pcf, FLAGTRUE);
nr = FileRead(pcf, buf, sizeof(buf));
nr = FileRead(pcf, buf, toksize);
servertok.length = nr;
servertok.value = buf;
@ -233,6 +238,7 @@ AttemptGSSAPI(CONSFILE *pcf)
ret = (stmaj == GSS_S_COMPLETE);
gss_release_name(&stmin, &gss_server_name);
free(buf);
return ret;
}
#endif
@ -1586,7 +1592,7 @@ DoCmds(char *master, char *pports, int cmdi)
char *pcopy;
char *serverName;
#if HAVE_GSSAPI
int toksize;
size_t toksize;
#endif
if ((pcopy = ports = StrDup(pports)) == (char *)0)
@ -1671,10 +1677,16 @@ DoCmds(char *master, char *pports, int cmdi)
#endif
#if HAVE_GSSAPI
if ((toksize = CanGetGSSContext(server)) > 0) {
if (toksize > MAX_GSSAPI_TOKSIZE) {
Error("Maximum support GSSAPI token size is %lu, "
"GSSAPI context creation reported %lu. "
"Server will reject authentication.",
MAX_GSSAPI_TOKSIZE, toksize);
}
FilePrint(pcf, FLAGFALSE, "gssapi %d\r\n", toksize);
t = ReadReply(pcf, FLAGFALSE);
if (strcmp(t, "ok\r\n") == 0) {
if (AttemptGSSAPI(pcf)) {
if (AttemptGSSAPI(pcf, toksize)) {
goto gssapi_logged_me_in;
}
}