[winpr,sspi] refactor kerberos_rd_tgt_token
the function was quite complex, split it up into multiple subfunctions: * kerberos_rd_tgt_req * kerberos_rd_tgt_req_tag2 * kerberos_rd_tgt_req_tag3 * kerberos_rd_tgt_rep
This commit is contained in:
parent
ab31eb7a50
commit
b253e6ba0a
@ -659,116 +659,189 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL append(char* dst, size_t dstSize, const char* src)
|
||||
{
|
||||
const size_t dlen = strnlen(dst, dstSize);
|
||||
const size_t slen = strlen(src);
|
||||
if (dlen + slen >= dstSize)
|
||||
return FALSE;
|
||||
if (!strncat(dst, src, slen))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL kerberos_rd_tgt_req_tag2(WinPrAsn1Decoder* dec, char* buf, size_t len)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
WinPrAsn1Decoder seq = { 0 };
|
||||
|
||||
/* server-name [2] PrincipalName (SEQUENCE) */
|
||||
if (!WinPrAsn1DecReadSequence(dec, &seq))
|
||||
goto end;
|
||||
|
||||
/* name-type [0] INTEGER */
|
||||
BOOL error = FALSE;
|
||||
WinPrAsn1_INTEGER val = 0;
|
||||
if (!WinPrAsn1DecReadContextualInteger(&seq, 0, &error, &val))
|
||||
goto end;
|
||||
|
||||
/* name-string [1] SEQUENCE OF GeneralString */
|
||||
if (!WinPrAsn1DecReadContextualSequence(&seq, 1, &error, dec))
|
||||
goto end;
|
||||
|
||||
WinPrAsn1_tag tag = 0;
|
||||
BOOL first = TRUE;
|
||||
while (WinPrAsn1DecPeekTag(dec, &tag))
|
||||
{
|
||||
char* lstr = NULL;
|
||||
if (!WinPrAsn1DecReadGeneralString(dec, &lstr))
|
||||
goto end;
|
||||
|
||||
if (!first)
|
||||
{
|
||||
if (!append(buf, len, "/"))
|
||||
goto end;
|
||||
}
|
||||
first = FALSE;
|
||||
|
||||
if (!append(buf, len, lstr))
|
||||
goto end;
|
||||
free(lstr);
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL kerberos_rd_tgt_req_tag3(WinPrAsn1Decoder* dec, char* buf, size_t len)
|
||||
{
|
||||
/* realm [3] Realm */
|
||||
BOOL rc = FALSE;
|
||||
WinPrAsn1_STRING str = NULL;
|
||||
if (!WinPrAsn1DecReadGeneralString(dec, &str))
|
||||
goto end;
|
||||
|
||||
if (!append(buf, len, "@"))
|
||||
goto end;
|
||||
if (!append(buf, len, str))
|
||||
goto end;
|
||||
|
||||
rc = TRUE;
|
||||
end:
|
||||
free(str);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL kerberos_rd_tgt_req(WinPrAsn1Decoder* dec, char** target)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
|
||||
if (!target)
|
||||
return FALSE;
|
||||
*target = NULL;
|
||||
|
||||
wStream s = WinPrAsn1DecGetStream(dec);
|
||||
const size_t len = Stream_Length(&s);
|
||||
if (len == 0)
|
||||
return TRUE;
|
||||
|
||||
WinPrAsn1Decoder dec2 = { 0 };
|
||||
WinPrAsn1_tagId tag = 0;
|
||||
if (WinPrAsn1DecReadContextualTag(dec, &tag, &dec2) == 0)
|
||||
return FALSE;
|
||||
|
||||
char* buf = calloc(len + 1, sizeof(char));
|
||||
if (!buf)
|
||||
return FALSE;
|
||||
|
||||
/* We expect ASN1 context tag values 2 or 3.
|
||||
*
|
||||
* In case we got value 2 an (optional) context tag value 3 might follow.
|
||||
*/
|
||||
BOOL checkForTag3 = TRUE;
|
||||
if (tag == 2)
|
||||
{
|
||||
rc = kerberos_rd_tgt_req_tag2(&dec2, buf, len);
|
||||
if (rc)
|
||||
{
|
||||
const size_t res = WinPrAsn1DecReadContextualTag(dec, &tag, dec);
|
||||
if (res == 0)
|
||||
checkForTag3 = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkForTag3)
|
||||
{
|
||||
if (tag == 3)
|
||||
rc = kerberos_rd_tgt_req_tag3(&dec2, buf, len);
|
||||
else
|
||||
rc = FALSE;
|
||||
}
|
||||
|
||||
end:
|
||||
if (rc)
|
||||
*target = buf;
|
||||
else
|
||||
free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL kerberos_rd_tgt_rep(WinPrAsn1Decoder* dec, krb5_data* ticket)
|
||||
{
|
||||
if (!ticket)
|
||||
return FALSE;
|
||||
|
||||
/* ticket [2] Ticket */
|
||||
WinPrAsn1Decoder asnTicket = { 0 };
|
||||
WinPrAsn1_tagId tag = 0;
|
||||
if (WinPrAsn1DecReadContextualTag(dec, &tag, &asnTicket) == 0)
|
||||
return FALSE;
|
||||
|
||||
if (tag != 2)
|
||||
return FALSE;
|
||||
|
||||
wStream s = WinPrAsn1DecGetStream(&asnTicket);
|
||||
ticket->data = Stream_BufferAs(&s, char);
|
||||
ticket->length = Stream_Length(&s);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL kerberos_rd_tgt_token(const sspi_gss_data* token, char** target, krb5_data* ticket)
|
||||
{
|
||||
WinPrAsn1Decoder dec;
|
||||
WinPrAsn1Decoder dec2;
|
||||
BOOL error = 0;
|
||||
WinPrAsn1_tagId tag = 0;
|
||||
WinPrAsn1_INTEGER val = 0;
|
||||
size_t len = 0;
|
||||
wStream s;
|
||||
char* buf = NULL;
|
||||
char* str = NULL;
|
||||
|
||||
WINPR_ASSERT(token);
|
||||
|
||||
WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)token->data, token->length);
|
||||
if (target)
|
||||
*target = NULL;
|
||||
|
||||
WinPrAsn1Decoder der = { 0 };
|
||||
WinPrAsn1Decoder_InitMem(&der, WINPR_ASN1_DER, (BYTE*)token->data, token->length);
|
||||
|
||||
/* KERB-TGT-REQUEST (SEQUENCE) */
|
||||
if (!WinPrAsn1DecReadSequence(&dec, &dec2))
|
||||
WinPrAsn1Decoder seq = { 0 };
|
||||
if (!WinPrAsn1DecReadSequence(&der, &seq))
|
||||
return FALSE;
|
||||
dec = dec2;
|
||||
|
||||
/* pvno [0] INTEGER */
|
||||
if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val) || val != 5)
|
||||
if (!WinPrAsn1DecReadContextualInteger(&seq, 0, &error, &val) || val != 5)
|
||||
return FALSE;
|
||||
|
||||
/* msg-type [1] INTEGER */
|
||||
if (!WinPrAsn1DecReadContextualInteger(&dec, 1, &error, &val))
|
||||
if (!WinPrAsn1DecReadContextualInteger(&seq, 1, &error, &val))
|
||||
return FALSE;
|
||||
|
||||
if (val == KRB_TGT_REQ)
|
||||
switch (val)
|
||||
{
|
||||
if (!target)
|
||||
return FALSE;
|
||||
*target = NULL;
|
||||
|
||||
s = WinPrAsn1DecGetStream(&dec);
|
||||
len = Stream_Length(&s);
|
||||
if (len == 0)
|
||||
return TRUE;
|
||||
|
||||
buf = malloc(len);
|
||||
if (!buf)
|
||||
return FALSE;
|
||||
|
||||
*buf = 0;
|
||||
*target = buf;
|
||||
|
||||
if (!WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2))
|
||||
goto fail;
|
||||
|
||||
if (tag == 2)
|
||||
{
|
||||
WinPrAsn1Decoder seq;
|
||||
/* server-name [2] PrincipalName (SEQUENCE) */
|
||||
if (!WinPrAsn1DecReadSequence(&dec2, &seq))
|
||||
goto fail;
|
||||
|
||||
/* name-type [0] INTEGER */
|
||||
if (!WinPrAsn1DecReadContextualInteger(&seq, 0, &error, &val))
|
||||
goto fail;
|
||||
|
||||
/* name-string [1] SEQUENCE OF GeneralString */
|
||||
if (!WinPrAsn1DecReadContextualSequence(&seq, 1, &error, &dec2))
|
||||
goto fail;
|
||||
|
||||
while (WinPrAsn1DecPeekTag(&dec2, &tag))
|
||||
{
|
||||
if (!WinPrAsn1DecReadGeneralString(&dec2, &str))
|
||||
goto fail;
|
||||
|
||||
if (buf != *target)
|
||||
*buf++ = '/';
|
||||
buf = stpcpy(buf, str);
|
||||
free(str);
|
||||
}
|
||||
|
||||
if (!WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* realm [3] Realm */
|
||||
if (tag != 3 || !WinPrAsn1DecReadGeneralString(&dec2, &str))
|
||||
goto fail;
|
||||
|
||||
*buf++ = '@';
|
||||
strcpy(buf, str);
|
||||
free(str);
|
||||
return TRUE;
|
||||
case KRB_TGT_REQ:
|
||||
return kerberos_rd_tgt_req(&seq, target);
|
||||
case KRB_TGT_REP:
|
||||
return kerberos_rd_tgt_rep(&seq, ticket);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else if (val == KRB_TGT_REP)
|
||||
{
|
||||
if (!ticket)
|
||||
return FALSE;
|
||||
|
||||
/* ticket [2] Ticket */
|
||||
if (!WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2) || tag != 2)
|
||||
return FALSE;
|
||||
|
||||
s = WinPrAsn1DecGetStream(&dec2);
|
||||
ticket->data = Stream_BufferAs(&s, char);
|
||||
ticket->length = Stream_Length(&s);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
fail:
|
||||
free(buf);
|
||||
if (target)
|
||||
*target = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user