Fix S4U2Self KDC crash when anon is restricted

In validate_as_request(), when enforcing restrict_anonymous_to_tgt,
use client.princ instead of request->client; the latter is NULL when
validating S4U2Self requests.

CVE-2016-3120:

In MIT krb5 1.9 and later, an authenticated attacker can cause krb5kdc
to dereference a null pointer if the restrict_anonymous_to_tgt option
is set to true, by making an S4U2Self request.

  CVSSv2 Vector: AV:N/AC:H/Au:S/C:N/I:N/A:C/E:H/RL:OF/RC:C

ticket: 8458 (new)
target_version: 1.14-next
target_version: 1.13-next
concat_authorization_data(krb5_context context,
                          krb5_authdata **first, krb5_authdata **second,
                          krb5_authdata ***output)
{
    register int i, j;
    register krb5_authdata **ptr, **retdata;

    /* count up the entries */
    i = 0;
    if (first)
        for (ptr = first; *ptr; ptr++)
            i++;
    if (second)
        for (ptr = second; *ptr; ptr++)
            i++;

    retdata = (krb5_authdata **)malloc((i+1)*sizeof(*retdata));
    if (!retdata)
        return ENOMEM;
    retdata[i] = 0;                     /* null-terminated array */
    for (i = 0, j = 0, ptr = first; j < 2 ; ptr = second, j++)
        while (ptr && *ptr) {
            /* now walk & copy */
            retdata[i] = (krb5_authdata *)malloc(sizeof(*retdata[i]));
            if (!retdata[i]) {
                krb5_free_authdata(context, retdata);
                return ENOMEM;
            }
            *retdata[i] = **ptr;
            if (!(retdata[i]->contents =
                  (krb5_octet *)malloc(retdata[i]->length))) {
                free(retdata[i]);
                retdata[i] = 0;
                krb5_free_authdata(context, retdata);
                return ENOMEM;
            }
            memcpy(retdata[i]->contents, (*ptr)->contents, retdata[i]->length);

            ptr++;
            i++;
        }
    *output = retdata;
    return 0;
}

concat_authorization_data(krb5_context context,
                          krb5_authdata **first, krb5_authdata **second,
                          krb5_authdata ***output)
{
    register int i, j;
    register krb5_authdata **ptr, **retdata;

    /* count up the entries */
    i = 0;
    if (first)
        for (ptr = first; *ptr; ptr++)
            i++;
    if (second)
        for (ptr = second; *ptr; ptr++)
            i++;

    retdata = (krb5_authdata **)malloc((i+1)*sizeof(*retdata));
    if (!retdata)
        return ENOMEM;
    retdata[i] = 0;                     /* null-terminated array */
    for (i = 0, j = 0, ptr = first; j < 2 ; ptr = second, j++)
        while (ptr && *ptr) {
            /* now walk & copy */
            retdata[i] = (krb5_authdata *)malloc(sizeof(*retdata[i]));
            if (!retdata[i]) {
                krb5_free_authdata(context, retdata);
                return ENOMEM;
            }
            *retdata[i] = **ptr;
            if (!(retdata[i]->contents =
                  (krb5_octet *)malloc(retdata[i]->length))) {
                free(retdata[i]);
                retdata[i] = 0;
                krb5_free_authdata(context, retdata);
                return ENOMEM;
            }
            memcpy(retdata[i]->contents, (*ptr)->contents, retdata[i]->length);

            ptr++;
            i++;
        }
    *output = retdata;
    return 0;
}
