krb5: decorate PrincipalNameAttrs with krb5_pac
Add krb5_pac to PrincipalNameAttrs to avoid needing to re-parse it each time gss_get_name_attribute() is called.
This commit is contained in:
@@ -5,4 +5,5 @@
|
||||
--sequence=ETYPE-INFO
|
||||
--sequence=ETYPE-INFO2
|
||||
--preserve-binary=KDC-REQ-BODY
|
||||
--decorate=PrincipalNameAttrs:void:pac?:::
|
||||
--decorate=Principal:PrincipalNameAttrs:nameattrs?
|
||||
|
@@ -169,6 +169,7 @@ static get_name_attr_f get_realm;
|
||||
static get_name_attr_f get_ncomps;
|
||||
static get_name_attr_f get_peer_realm;
|
||||
static get_name_attr_f get_pac;
|
||||
static get_name_attr_f get_pac_buffer;
|
||||
static get_name_attr_f get_authz_data;
|
||||
static get_name_attr_f get_ticket_authz_data;
|
||||
static get_name_attr_f get_authenticator_authz_data;
|
||||
@@ -210,16 +211,16 @@ static struct krb5_name_attrs {
|
||||
{ NB("peer-realm"), get_peer_realm, NULL, NULL, 1, 1 },
|
||||
{ NB("ticket-authz-data#pac"), get_pac, NULL, NULL, 1, 1 },
|
||||
{ NM(""), get_pac, NULL, NULL, 1, 0 },
|
||||
{ NM("logon-info"), get_pac, NULL, NULL, 1, 0 },
|
||||
{ NM("credentials-info"), get_pac, NULL, NULL, 1, 0 },
|
||||
{ NM("server-checksum"), get_pac, NULL, NULL, 1, 0 },
|
||||
{ NM("privsvr-checksum"), get_pac, NULL, NULL, 1, 0 },
|
||||
{ NM("client-info"), get_pac, NULL, NULL, 1, 0 },
|
||||
{ NM("delegation-info"), get_pac, NULL, NULL, 1, 0 },
|
||||
{ NM("upn-dns-info"), get_pac, NULL, NULL, 1, 0 },
|
||||
{ NM("ticket-checksum"), get_pac, NULL, NULL, 1, 0 },
|
||||
{ NM("attributes-info"), get_pac, NULL, NULL, 1, 0 },
|
||||
{ NM("requestor-sid"), get_pac, NULL, NULL, 1, 0 },
|
||||
{ NM("logon-info"), get_pac_buffer, NULL, NULL, 1, 0 },
|
||||
{ NM("credentials-info"), get_pac_buffer, NULL, NULL, 1, 0 },
|
||||
{ NM("server-checksum"), get_pac_buffer, NULL, NULL, 1, 0 },
|
||||
{ NM("privsvr-checksum"), get_pac_buffer, NULL, NULL, 1, 0 },
|
||||
{ NM("client-info"), get_pac_buffer, NULL, NULL, 1, 0 },
|
||||
{ NM("delegation-info"), get_pac_buffer, NULL, NULL, 1, 0 },
|
||||
{ NM("upn-dns-info"), get_pac_buffer, NULL, NULL, 1, 0 },
|
||||
{ NM("ticket-checksum"), get_pac_buffer, NULL, NULL, 1, 0 },
|
||||
{ NM("attributes-info"), get_pac_buffer, NULL, NULL, 1, 0 },
|
||||
{ NM("requestor-sid"), get_pac_buffer, NULL, NULL, 1, 0 },
|
||||
{ NB("ticket-authz-data#kdc-issued"),
|
||||
get_ticket_authz_data, NULL, NULL, 1, 1 },
|
||||
{ NB("ticket-authz-data"),
|
||||
@@ -686,29 +687,69 @@ get_pac(OM_uint32 *minor_status,
|
||||
{
|
||||
krb5_error_code kret;
|
||||
krb5_context context;
|
||||
krb5_data data, pac_data;
|
||||
krb5_data suffix;
|
||||
krb5_data data;
|
||||
PrincipalNameAttrs *nameattrs = name->nameattrs;
|
||||
PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
|
||||
EncTicketPart *ticket = NULL;
|
||||
|
||||
krb5_data_zero(&data);
|
||||
krb5_data_zero(&pac_data);
|
||||
|
||||
if (src) switch (src->element) {
|
||||
case choice_PrincipalNameAttrSrc_enc_ticket_part:
|
||||
ticket = &src->u.enc_ticket_part;
|
||||
break;
|
||||
case choice_PrincipalNameAttrSrc_enc_kdc_rep_part:
|
||||
default:
|
||||
return GSS_S_UNAVAILABLE;
|
||||
}
|
||||
if (src == NULL ||
|
||||
src->element != choice_PrincipalNameAttrSrc_enc_ticket_part)
|
||||
return GSS_S_UNAVAILABLE;
|
||||
|
||||
ticket = &src->u.enc_ticket_part;
|
||||
|
||||
if (prefix->length || !authenticated || !ticket)
|
||||
return GSS_S_UNAVAILABLE;
|
||||
|
||||
GSSAPI_KRB5_INIT(&context);
|
||||
|
||||
*authenticated = nameattrs->pac_verified;
|
||||
if (complete)
|
||||
*complete = 1;
|
||||
|
||||
kret = _krb5_get_ad(context, ticket->authorization_data,
|
||||
NULL, KRB5_AUTHDATA_WIN2K_PAC,
|
||||
value ? &data : NULL);
|
||||
|
||||
if (value) {
|
||||
value->length = data.length;
|
||||
value->value = data.data;
|
||||
}
|
||||
|
||||
*minor_status = kret;
|
||||
if (kret == ENOENT)
|
||||
return GSS_S_UNAVAILABLE;
|
||||
return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
static OM_uint32
|
||||
get_pac_buffer(OM_uint32 *minor_status,
|
||||
const CompositePrincipal *name,
|
||||
gss_const_buffer_t prefix,
|
||||
gss_const_buffer_t attr,
|
||||
gss_const_buffer_t frag,
|
||||
int *authenticated,
|
||||
int *complete,
|
||||
gss_buffer_t value,
|
||||
gss_buffer_t display_value,
|
||||
int *more)
|
||||
{
|
||||
krb5_error_code kret;
|
||||
krb5_context context;
|
||||
krb5_data data;
|
||||
PrincipalNameAttrs *nameattrs = name->nameattrs;
|
||||
krb5_data suffix;
|
||||
|
||||
krb5_data_zero(&data);
|
||||
|
||||
if (prefix->length || !authenticated ||
|
||||
!nameattrs || !nameattrs->pac)
|
||||
return GSS_S_UNAVAILABLE;
|
||||
|
||||
GSSAPI_KRB5_INIT(&context);
|
||||
|
||||
if (ATTR_EQ_PREFIX(attr, "urn:mspac:")) {
|
||||
suffix.length = attr->length - (sizeof("urn:mspac:") - 1);
|
||||
suffix.data = (char *)attr->value + sizeof("urn:mspac:") - 1;
|
||||
@@ -716,37 +757,20 @@ get_pac(OM_uint32 *minor_status,
|
||||
suffix.length = frag->length - sizeof("pac-") - 1;
|
||||
suffix.data = (char *)frag->value + sizeof("pac-") - 1;
|
||||
} else
|
||||
krb5_data_zero(&suffix); /* ticket-authz-data#pac */
|
||||
return GSS_S_UNAVAILABLE; /* should not be reached */
|
||||
|
||||
*authenticated = nameattrs->pac_verified;
|
||||
if (complete)
|
||||
*complete = 1;
|
||||
|
||||
kret = _krb5_get_ad(context, ticket->authorization_data,
|
||||
NULL, KRB5_AUTHDATA_WIN2K_PAC, &pac_data);
|
||||
if (kret == 0 && suffix.length) {
|
||||
krb5_pac pac;
|
||||
kret = _krb5_pac_get_buffer_by_name(context, nameattrs->pac, &suffix,
|
||||
value ? &data : NULL);
|
||||
|
||||
kret = krb5_pac_parse(context, pac_data.data, pac_data.length, &pac);
|
||||
if (kret == 0) {
|
||||
kret = _krb5_pac_get_buffer_by_name(context, pac, &suffix,
|
||||
value ? &data : NULL);
|
||||
krb5_pac_free(context, pac);
|
||||
}
|
||||
|
||||
if (value) {
|
||||
value->length = data.length;
|
||||
value->value = data.data;
|
||||
krb5_data_zero(&data);
|
||||
}
|
||||
} else if (kret == 0 && value) {
|
||||
value->length = pac_data.length;
|
||||
value->value = pac_data.data;
|
||||
krb5_data_zero(&pac_data);
|
||||
if (value) {
|
||||
value->length = data.length;
|
||||
value->value = data.data;
|
||||
}
|
||||
|
||||
krb5_data_free(&pac_data);
|
||||
krb5_data_free(&data);
|
||||
*minor_status = kret;
|
||||
if (kret == ENOENT)
|
||||
return GSS_S_UNAVAILABLE;
|
||||
@@ -1083,6 +1107,10 @@ get_canonical_name(OM_uint32 *minor_status,
|
||||
kret = _krb5_principalname2krb5_principal(context, &p,
|
||||
kdcrep->sname,
|
||||
kdcrep->srealm);
|
||||
} else if (nameattrs && nameattrs->pac &&
|
||||
(_krb5_pac_get_canon_principal(context, nameattrs->pac, &p)) == 0) {
|
||||
if (authenticated)
|
||||
*authenticated = nameattrs->pac_verified;
|
||||
} else if (ticket) {
|
||||
krb5_data data;
|
||||
krb5_pac pac = NULL;
|
||||
|
@@ -1998,3 +1998,41 @@ _krb5_kdc_pac_sign_ticket(krb5_context context,
|
||||
krb5_data_free(&rspac);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for krb5_copy_principal(), because the krb5_pac
|
||||
* in nameattrs lacks a copy constructor (not being an ASN.1 type)
|
||||
*/
|
||||
|
||||
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
|
||||
_krb5_pac_copy(krb5_context context, krb5_pac in, krb5_pac *out)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_pac p;
|
||||
|
||||
*out = NULL;
|
||||
|
||||
ret = krb5_pac_parse(context, in->data.data, in->data.length, &p);
|
||||
if (ret == 0 && in->ticket_sign_data.data)
|
||||
ret = krb5_data_copy(&p->ticket_sign_data, in->ticket_sign_data.data,
|
||||
in->ticket_sign_data.length);
|
||||
|
||||
if (ret == 0 && in->upn_princ)
|
||||
ret = krb5_copy_principal(context, in->upn_princ, &p->upn_princ);
|
||||
p->upn_flags = in->upn_flags;
|
||||
if (ret == 0 && in->canon_princ)
|
||||
ret = krb5_copy_principal(context, in->canon_princ, &p->canon_princ);
|
||||
if (ret == 0 && in->sid.data)
|
||||
ret = krb5_data_copy(&p->sid, in->sid.data, in->sid.length);
|
||||
|
||||
p->pac_attributes = in->pac_attributes;
|
||||
|
||||
if (ret) {
|
||||
krb5_pac_free(context, p);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*out = p;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -102,10 +102,13 @@ KRB5_LIB_FUNCTION void KRB5_LIB_CALL
|
||||
krb5_free_principal(krb5_context context,
|
||||
krb5_principal p)
|
||||
{
|
||||
if(p){
|
||||
free_Principal(p);
|
||||
free(p);
|
||||
}
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
if (p->nameattrs)
|
||||
krb5_pac_free(context, p->nameattrs->pac);
|
||||
free_Principal(p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -926,12 +929,25 @@ krb5_copy_principal(krb5_context context,
|
||||
krb5_principal *outprinc)
|
||||
{
|
||||
krb5_principal p = malloc(sizeof(*p));
|
||||
krb5_error_code ret;
|
||||
|
||||
if (p == NULL)
|
||||
return krb5_enomem(context);
|
||||
if(copy_Principal(inprinc, p)) {
|
||||
free(p);
|
||||
return krb5_enomem(context);
|
||||
}
|
||||
if (inprinc->nameattrs && inprinc->nameattrs->pac) {
|
||||
krb5_pac pac;
|
||||
|
||||
ret = _krb5_pac_copy(context, inprinc->nameattrs->pac, &pac);
|
||||
if (ret) {
|
||||
krb5_free_principal(context, p);
|
||||
return ret;
|
||||
}
|
||||
heim_assert(p->nameattrs, "nameattrs uninitialized");
|
||||
p->nameattrs->pac = pac;
|
||||
}
|
||||
*outprinc = p;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1080,9 +1080,11 @@ krb5_rd_req_ctx(krb5_context context,
|
||||
} else if (ret2 != ENOENT)
|
||||
ret = ret2;
|
||||
}
|
||||
krb5_pac_free(context, pac);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
krb5_pac_free(context, pac);
|
||||
goto out;
|
||||
}
|
||||
o->ticket->client->nameattrs->pac = pac;
|
||||
} else
|
||||
ret = 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user