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
	 Luke Howard
					Luke Howard