gss: Add way to set authenticator authz-data
Now we can set Authenticator authorization-data with gss_set_name_attribute().
This commit is contained in:
		 Nicolas Williams
					Nicolas Williams
				
			
				
					committed by
					
						 Luke Howard
						Luke Howard
					
				
			
			
				
	
			
			
			 Luke Howard
						Luke Howard
					
				
			
						parent
						
							fe11481cc5
						
					
				
				
					commit
					c2e3c5b66e
				
			| @@ -476,10 +476,11 @@ PrincipalNameAttrs ::= SEQUENCE { | ||||
|         -- True if the PAC was verified | ||||
|         pac-verified        [5]     BOOLEAN, | ||||
|         -- True if any AD-KDC-ISSUEDs in the Ticket were validated | ||||
|         kdc-issued-verified [6]     BOOLEAN | ||||
|         kdc-issued-verified [6]     BOOLEAN, | ||||
|         -- TODO: Add requested attributes, for gss_set_name_attribute(), which | ||||
|         --       should cause corresponding authz-data elements to be added to | ||||
|         --       any TGS-REQ or to the AP-REQ's Authenticator as appropriate. | ||||
|         want-ad             [7]     AuthorizationData OPTIONAL | ||||
| } | ||||
| -- This is our type for exported composite name tokens for GSS [RFC6680]. | ||||
| -- It's the same as Principal (below) as decorated with (see krb5.opt file and | ||||
|   | ||||
| @@ -385,7 +385,7 @@ LDADD = libgssapi.la \ | ||||
| 	$(LIB_roken) | ||||
|  | ||||
| test_names_LDADD = $(LDADD) $(top_builddir)/lib/asn1/libasn1.la | ||||
| test_context_LDADD = $(LDADD) $(top_builddir)/lib/wind/libwind.la | ||||
| test_context_LDADD = $(LDADD) $(top_builddir)/lib/asn1/libasn1.la $(top_builddir)/lib/wind/libwind.la | ||||
|  | ||||
| # gss | ||||
|  | ||||
|   | ||||
| @@ -33,6 +33,12 @@ | ||||
|  | ||||
| #include "gsskrb5_locl.h" | ||||
|  | ||||
| static OM_uint32 | ||||
| gsskrb5_set_authorization_data(OM_uint32 *, | ||||
|                                krb5_context, | ||||
|                                krb5_auth_context, | ||||
|                                gss_const_name_t); | ||||
|  | ||||
| /* | ||||
|  * copy the addresses from `input_chan_bindings' (if any) to | ||||
|  * the auth context `ac' | ||||
| @@ -418,6 +424,11 @@ init_auth | ||||
|     if (ret) | ||||
| 	goto failure; | ||||
|  | ||||
|     ret = gsskrb5_set_authorization_data(minor_status, context, | ||||
|                                          ctx->auth_context, name); | ||||
|     if (ret) | ||||
| 	goto failure; | ||||
|  | ||||
|     ctx->endtime = ctx->kcred->times.endtime; | ||||
|  | ||||
|     ret = _gss_DES3_get_mic_compat(minor_status, ctx, context); | ||||
| @@ -977,3 +988,31 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_init_sec_context | ||||
|     return ret; | ||||
|  | ||||
| } | ||||
|  | ||||
| static OM_uint32 | ||||
| gsskrb5_set_authorization_data(OM_uint32 *minor_status, | ||||
|                                krb5_context context, | ||||
|                                krb5_auth_context auth_context, | ||||
|                                gss_const_name_t gn) | ||||
| { | ||||
|     const CompositePrincipal *name = (const void *)gn; | ||||
|     AuthorizationData *ad; | ||||
|     krb5_error_code kret = 0; | ||||
|     size_t i; | ||||
|  | ||||
|     if (name->nameattrs == NULL || name->nameattrs->want_ad == NULL) | ||||
|         return GSS_S_COMPLETE; | ||||
|  | ||||
|     ad = name->nameattrs->want_ad; | ||||
|     for (i = 0; kret == 0 && i < ad->len; i++) { | ||||
|         kret = krb5_auth_con_add_AuthorizationData(context, auth_context, | ||||
|                                                    ad->val[0].ad_type, | ||||
|                                                    &ad->val[0].ad_data); | ||||
|     } | ||||
|  | ||||
|     if (kret) { | ||||
|         *minor_status = kret; | ||||
|         return GSS_S_FAILURE; | ||||
|     } | ||||
|     return GSS_S_COMPLETE; | ||||
| } | ||||
|   | ||||
| @@ -172,6 +172,7 @@ static get_name_attr_f get_pac; | ||||
| 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; | ||||
| static set_name_attr_f set_authenticator_authz_data; | ||||
| static get_name_attr_f get_transited; | ||||
| static get_name_attr_f get_canonical_name; | ||||
|  | ||||
| @@ -209,7 +210,8 @@ static struct krb5_name_attrs { | ||||
|     { NB("ticket-authz-data"), | ||||
|          get_ticket_authz_data, NULL, NULL, 1, 1 }, | ||||
|     { NB("authenticator-authz-data"), | ||||
|          get_authenticator_authz_data, NULL, NULL, 1, 1 }, | ||||
|          get_authenticator_authz_data, | ||||
|          set_authenticator_authz_data, NULL, 1, 1 }, | ||||
|     { NB("authz-data"),     get_authz_data,  NULL, NULL, 1, 1 }, | ||||
|     { NB("transit-path"),   get_transited,   NULL, NULL, 1, 1 }, | ||||
|     { NB("canonical-name"), get_canonical_name, NULL, NULL, 1, 1 }, | ||||
| @@ -922,6 +924,62 @@ get_authenticator_authz_data(OM_uint32 *minor_status, | ||||
|     return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; | ||||
| } | ||||
|  | ||||
| static OM_uint32 | ||||
| set_authenticator_authz_data(OM_uint32 *minor_status, | ||||
|                              CompositePrincipal *name, | ||||
|                              gss_const_buffer_t prefix, | ||||
|                              gss_const_buffer_t attr, | ||||
|                              gss_const_buffer_t frag, | ||||
|                              int complete, | ||||
|                              gss_buffer_t value) | ||||
| { | ||||
|     AuthorizationDataElement e; | ||||
|     krb5_error_code kret; | ||||
|     size_t sz; | ||||
|  | ||||
|     if (!value) | ||||
|         return GSS_S_CALL_INACCESSIBLE_READ; | ||||
|     if (frag->length && | ||||
|         !ATTR_EQ(frag, "if-relevant")) | ||||
|         return GSS_S_UNAVAILABLE; | ||||
|  | ||||
|     if ((name->nameattrs == NULL && | ||||
|         (name->nameattrs = calloc(1, sizeof(*name->nameattrs))) == NULL) || | ||||
|         (name->nameattrs->want_ad == NULL && | ||||
|          (name->nameattrs->want_ad = | ||||
|           calloc(1, sizeof(*name->nameattrs->want_ad))) == NULL)) { | ||||
|         *minor_status = ENOMEM; | ||||
|         return GSS_S_FAILURE; | ||||
|     } | ||||
|  | ||||
|     memset(&e, 0, sizeof(e)); | ||||
|     kret = decode_AuthorizationDataElement(value->value, value->length, &e, | ||||
|                                            &sz); | ||||
|     if (kret == 0) { | ||||
|         if (frag->length) { | ||||
|             AuthorizationData ir; | ||||
|  | ||||
|             ir.len = 0; | ||||
|             ir.val = NULL; | ||||
|             kret = add_AuthorizationData(&ir, &e); | ||||
|             free_AuthorizationDataElement(&e); | ||||
|             if (kret == 0) { | ||||
|                 e.ad_type = KRB5_AUTHDATA_IF_RELEVANT; | ||||
|                 ASN1_MALLOC_ENCODE(AuthorizationData, e.ad_data.data, | ||||
|                                    e.ad_data.length, &ir, &sz, kret); | ||||
|                 kret = add_AuthorizationData(name->nameattrs->want_ad, &e); | ||||
|             } | ||||
|             free_AuthorizationData(&ir); | ||||
|         } else { | ||||
|             kret = add_AuthorizationData(name->nameattrs->want_ad, &e); | ||||
|             free_AuthorizationDataElement(&e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     *minor_status = kret; | ||||
|     return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; | ||||
| } | ||||
|  | ||||
| static OM_uint32 | ||||
| get_transited(OM_uint32 *minor_status, | ||||
|               const CompositePrincipal *name, | ||||
|   | ||||
| @@ -56,6 +56,7 @@ static char *localname_string; | ||||
| static char *client_name; | ||||
| static char *client_password; | ||||
| static char *localname_string; | ||||
| static char *on_behalf_of_string; | ||||
| static int dns_canon_flag = -1; | ||||
| static int mutual_auth_flag = 0; | ||||
| static int dce_style_flag = 0; | ||||
| @@ -294,6 +295,31 @@ loop(gss_OID mechoid, | ||||
|     if (GSS_ERROR(maj_stat)) | ||||
| 	err(1, "import name creds failed with: %d", maj_stat); | ||||
|  | ||||
|     if (on_behalf_of_string) { | ||||
|         AuthorizationDataElement e; | ||||
|         gss_buffer_desc attr, value; | ||||
|         int32_t kret; | ||||
|         size_t sz; | ||||
|  | ||||
|         memset(&e, 0, sizeof(e)); | ||||
|         e.ad_type = KRB5_AUTHDATA_ON_BEHALF_OF; | ||||
|         e.ad_data.length = strlen(on_behalf_of_string); | ||||
|         e.ad_data.data = on_behalf_of_string; | ||||
|         ASN1_MALLOC_ENCODE(AuthorizationDataElement, value.value, value.length, | ||||
|                            &e, &sz, kret); | ||||
|         if (kret) | ||||
|             errx(1, "Could not encode AD-ON-BEHALF-OF AuthorizationDataElement"); | ||||
|         attr.value = | ||||
|             GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authenticator-authz-data"; | ||||
|         attr.length = | ||||
|             sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authenticator-authz-data") - 1; | ||||
|         maj_stat = gss_set_name_attribute(&min_stat, gss_target_name, 1, &attr, | ||||
|                                           &value); | ||||
|         if (maj_stat != GSS_S_COMPLETE) | ||||
|             errx(1, "gss_set_name_attribute() failed with: %s", | ||||
|                  gssapi_err(maj_stat, min_stat, GSS_KRB5_MECHANISM)); | ||||
|     } | ||||
|  | ||||
|     input_token.length = 0; | ||||
|     input_token.value = NULL; | ||||
|  | ||||
| @@ -457,6 +483,24 @@ loop(gss_OID mechoid, | ||||
| 	errx(1, "mech mismatch"); | ||||
|     *actual_mech = actual_mech_server; | ||||
|  | ||||
|     if (on_behalf_of_string) { | ||||
|         gss_buffer_desc attr, value; | ||||
|  | ||||
|         attr.value = | ||||
|             GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authz-data#580"; | ||||
|         attr.length = | ||||
|             sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authz-data#580") - 1; | ||||
|         maj_stat = gss_get_name_attribute(&min_stat, src_name, &attr, NULL, | ||||
|                                           NULL, &value, NULL, NULL); | ||||
|         if (maj_stat != GSS_S_COMPLETE) | ||||
|             errx(1, "gss_get_name_attribute(authz-data#580) failed with %s", | ||||
|                  gssapi_err(maj_stat, min_stat, GSS_KRB5_MECHANISM)); | ||||
|  | ||||
|         if (value.length != strlen(on_behalf_of_string) || | ||||
|             strncmp(value.value, on_behalf_of_string, | ||||
|                     strlen(on_behalf_of_string)) != 0) | ||||
|             errx(1, "AD-ON-BEHALF-OF did not match"); | ||||
|     } | ||||
|     if (localname_string) { | ||||
|         gss_buffer_desc lname; | ||||
|  | ||||
| @@ -865,6 +909,8 @@ static struct getargs args[] = { | ||||
|     {"server-time-offset",	0, arg_integer,	&server_time_offset, "time", NULL }, | ||||
|     {"max-loops",	0, arg_integer,	&max_loops, "time", NULL }, | ||||
|     {"token-split",	0, arg_integer, &token_split, "bytes", NULL }, | ||||
|     {"on-behalf-of",	0, arg_string, &on_behalf_of_string, "principal", | ||||
|         "send authenticator authz-data AD-ON-BEHALF-OF" }, | ||||
|     {"version",	0,	arg_flag,	&version_flag, "print version", NULL }, | ||||
|     {"verbose",	'v',	arg_flag,	&verbose_flag, "verbose", NULL }, | ||||
|     {"help",	0,	arg_flag,	&help_flag,  NULL, NULL } | ||||
|   | ||||
| @@ -23,6 +23,8 @@ EXPORTS | ||||
| 	krb5_appdefault_time | ||||
| 	krb5_append_addresses | ||||
| 	krb5_auth_con_addflags | ||||
| 	krb5_auth_con_add_AuthorizationData | ||||
| 	krb5_auth_con_add_AuthorizationDataIfRelevant | ||||
| 	krb5_auth_con_free | ||||
| 	krb5_auth_con_genaddrs | ||||
| 	krb5_auth_con_generatelocalsubkey | ||||
|   | ||||
| @@ -24,6 +24,8 @@ HEIMDAL_KRB5_2.0 { | ||||
| 		krb5_appdefault_time; | ||||
| 		krb5_append_addresses; | ||||
| 		krb5_auth_con_addflags; | ||||
| 		krb5_auth_con_add_AuthorizationData; | ||||
| 		krb5_auth_con_add_AuthorizationDataIfRelevant; | ||||
| 		krb5_auth_con_free; | ||||
| 		krb5_auth_con_genaddrs; | ||||
| 		krb5_auth_con_generatelocalsubkey; | ||||
|   | ||||
| @@ -245,6 +245,14 @@ for mech in krb5 krb5iov spnego spnegoiov; do | ||||
| 		{ eval "$testfailed"; } | ||||
| done | ||||
|  | ||||
| echo "======test authz-data (krb5)" | ||||
| ${context} --mech-type=krb5 \ | ||||
|     --mutual \ | ||||
|     --wrapunwrap \ | ||||
|     --on-behalf-of=foo@BAR.TEST.H5L.SE \ | ||||
|     --name-type=hostbased-service host@lucid.test.h5l.se || | ||||
|     { eval "$testfailed"; } | ||||
|  | ||||
| echo "======dce-style" | ||||
| for mech in krb5 krb5iov spnego; do | ||||
| 	iov="" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user