Line data Source code
1 : /*
2 : * Copyright (c) 2021 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : *
17 : * 3. Neither the name of the Institute nor the names of its contributors
18 : * may be used to endorse or promote products derived from this software
19 : * without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 : * SUCH DAMAGE.
32 : */
33 :
34 : #include "gsskrb5_locl.h"
35 :
36 : /*
37 : * (Not-yet-)Standard name attributes for Kerberos MNs,
38 : * GSS_KRB5_NAME_ATTRIBUTE_BASE_URN + "...".
39 : *
40 : * I.e., "urn:ietf:kerberos:nameattr-...". (XXX Register this URN namespace
41 : * with IANA.)
42 : *
43 : * Note that we do use URN fragments.
44 : *
45 : * Specific attributes below the base URN:
46 : *
47 : * - name access attributes:
48 : * - "realm" -> realm of name
49 : * - "name-ncomp" -> count of name components
50 : * - "name-ncomp#<digit>" -> name component N (0 <= N <= 9)
51 : *
52 : * Ticket and Authenticator access attributes:
53 : *
54 : * - "transit-path" -> encoding of the transited path
55 : * - "authenticator-authz-data" -> encoding of all of the authz-data from
56 : * the AP-REQ's Authenticator
57 : * - "ticket-authz-data" -> encoding of all of the authz-data from
58 : * the AP-REQ's Ticket
59 : * - "ticket-authz-data#pac" -> the PAC
60 : * - "authz-data#<N>" -> encoding of all of a specific auth-data
61 : * element type N (e.g., 2, meaning
62 : * AD-INTENDED-FOR-SERVER)
63 : *
64 : * Misc. attributes:
65 : *
66 : * - "peer-realm" -> name of peer's realm (if this is an MN
67 : * resulting for establishing a security
68 : * context)
69 : * - "canonical-name" -> exported name token and RFC1964 display
70 : * syntax of the name's canonical name
71 : *
72 : * Compatibility with MIT:
73 : *
74 : * - "urn:mspac:" -> the PAC and its individual info buffers
75 : *
76 : * TODO:
77 : *
78 : * - Add some sort of display syntax for transit path
79 : * - Add support for URN q-components or attribute prefixes to specify
80 : * alternative raw and/or display value encodings (JSON?)
81 : * - Add support for attributes for accessing other parts of the Ticket / KDC
82 : * reply enc-parts, like auth times
83 : * - Add support for getting PAC logon fields, including SIDs (one at a time)
84 : * - Add support for CAMMAC?
85 : */
86 :
87 : static int
88 0 : attr_eq(gss_const_buffer_t attr, const char *aname, size_t aname_len, \
89 : int prefix_check)
90 : {
91 0 : if (attr->length < aname_len)
92 0 : return 0;
93 :
94 0 : if (strncmp((char *)attr->value, aname, aname_len) != 0)
95 0 : return 0;
96 :
97 0 : return prefix_check || attr->length == aname_len;
98 : }
99 :
100 : #define ATTR_EQ(a, an) (attr_eq(a, an, sizeof(an) - 1, FALSE))
101 : #define ATTR_EQ_PREFIX(a, an) (attr_eq(a, an, sizeof(an) - 1, TRUE))
102 :
103 : /* Split attribute into prefix, suffix, and fragment. See RFC6680. */
104 : static void
105 0 : split_attr(gss_const_buffer_t orig,
106 : gss_buffer_t prefix,
107 : gss_buffer_t attr,
108 : gss_buffer_t frag,
109 : int *is_urn)
110 : {
111 0 : char *last = NULL;
112 0 : char *p = orig->value;
113 :
114 0 : *attr = *orig;
115 0 : prefix->value = orig->value;
116 0 : prefix->length = 0;
117 0 : frag->length = 0;
118 0 : frag->value = NULL;
119 :
120 : /* FIXME We don't have a memrchr() in lib/roken */
121 0 : for (p = memchr(p, ' ', orig->length);
122 0 : p;
123 0 : p = memchr(p + 1, ' ', orig->length)) {
124 0 : last = p;
125 0 : prefix->length = last - (const char *)orig->value;
126 0 : attr->value = last + 1;
127 0 : attr->length = orig->length - (prefix->length + 1);
128 : }
129 0 : if (prefix->length == 0)
130 0 : prefix->value = NULL;
131 :
132 0 : if ((*is_urn = (strncmp(attr->value, "urn:", sizeof("urn:") - 1) == 0)) &&
133 0 : (p = memchr((char *)attr->value + 1, '#', attr->length - 1))) {
134 0 : frag->value = ++p;
135 0 : frag->length = attr->length - (p - (const char *)attr->value);
136 0 : attr->length = --p - (const char *)attr->value;
137 : }
138 0 : }
139 :
140 : typedef OM_uint32 get_name_attr_f(OM_uint32 *,
141 : const CompositePrincipal *,
142 : gss_const_buffer_t,
143 : gss_const_buffer_t,
144 : gss_const_buffer_t,
145 : int *,
146 : int *,
147 : gss_buffer_t,
148 : gss_buffer_t,
149 : int *);
150 :
151 : typedef OM_uint32 set_name_attr_f(OM_uint32 *,
152 : CompositePrincipal *,
153 : gss_const_buffer_t,
154 : gss_const_buffer_t,
155 : gss_const_buffer_t,
156 : int,
157 : gss_buffer_t);
158 :
159 : typedef OM_uint32 del_name_attr_f(OM_uint32 *,
160 : CompositePrincipal *,
161 : gss_const_buffer_t,
162 : gss_const_buffer_t,
163 : gss_const_buffer_t);
164 : typedef get_name_attr_f *get_name_attr_fp;
165 : typedef set_name_attr_f *set_name_attr_fp;
166 : typedef del_name_attr_f *del_name_attr_fp;
167 :
168 : static get_name_attr_f get_realm;
169 : static get_name_attr_f get_ncomps;
170 : static get_name_attr_f get_peer_realm;
171 : static get_name_attr_f get_pac;
172 : static get_name_attr_f get_pac_buffer;
173 : static get_name_attr_f get_authz_data;
174 : static get_name_attr_f get_ticket_authz_data;
175 : static get_name_attr_f get_authenticator_authz_data;
176 : static set_name_attr_f set_authenticator_authz_data;
177 : static get_name_attr_f get_transited;
178 : static get_name_attr_f get_canonical_name;
179 :
180 : #define NB(n) \
181 : GSS_KRB5_NAME_ATTRIBUTE_BASE_URN n, n, \
182 : sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN n) - 1, \
183 : sizeof(n) - 1
184 : #define NM(n) \
185 : "urn:mspac:" n, n, sizeof("urn:mspac:" n) - 1, sizeof(n) - 1
186 :
187 : static struct krb5_name_attrs {
188 : const char *fullname;
189 : const char *name;
190 : size_t fullnamelen;
191 : size_t namelen;
192 : get_name_attr_fp getter;
193 : set_name_attr_fp setter;
194 : del_name_attr_fp deleter;
195 : unsigned int indicate:1;
196 : unsigned int is_krb5_name_attr_urn:1;
197 : } name_attrs[] = {
198 : /* XXX We should sort these so we can binary search them */
199 : { NB("realm"), get_realm, NULL, NULL, 1, 1 },
200 : { NB("name-ncomp"), get_ncomps, NULL, NULL, 1, 1 },
201 : { NB("name-ncomp#0"), get_ncomps, NULL, NULL, 1, 1 },
202 : { NB("name-ncomp#1"), get_ncomps, NULL, NULL, 1, 1 },
203 : { NB("name-ncomp#2"), get_ncomps, NULL, NULL, 1, 1 },
204 : { NB("name-ncomp#3"), get_ncomps, NULL, NULL, 1, 1 },
205 : { NB("name-ncomp#4"), get_ncomps, NULL, NULL, 1, 1 },
206 : { NB("name-ncomp#5"), get_ncomps, NULL, NULL, 1, 1 },
207 : { NB("name-ncomp#6"), get_ncomps, NULL, NULL, 1, 1 },
208 : { NB("name-ncomp#7"), get_ncomps, NULL, NULL, 1, 1 },
209 : { NB("name-ncomp#8"), get_ncomps, NULL, NULL, 1, 1 },
210 : { NB("name-ncomp#9"), get_ncomps, NULL, NULL, 1, 1 },
211 : { NB("peer-realm"), get_peer_realm, NULL, NULL, 1, 1 },
212 : { NB("ticket-authz-data#pac"), get_pac, NULL, NULL, 1, 1 },
213 : { NM(""), get_pac, NULL, NULL, 1, 0 },
214 : { NM("logon-info"), get_pac_buffer, NULL, NULL, 1, 0 },
215 : { NM("credentials-info"), get_pac_buffer, NULL, NULL, 1, 0 },
216 : { NM("server-checksum"), get_pac_buffer, NULL, NULL, 1, 0 },
217 : { NM("privsvr-checksum"), get_pac_buffer, NULL, NULL, 1, 0 },
218 : { NM("client-info"), get_pac_buffer, NULL, NULL, 1, 0 },
219 : { NM("delegation-info"), get_pac_buffer, NULL, NULL, 1, 0 },
220 : { NM("upn-dns-info"), get_pac_buffer, NULL, NULL, 1, 0 },
221 : { NM("ticket-checksum"), get_pac_buffer, NULL, NULL, 1, 0 },
222 : { NM("attributes-info"), get_pac_buffer, NULL, NULL, 1, 0 },
223 : { NM("requestor-sid"), get_pac_buffer, NULL, NULL, 1, 0 },
224 : { NB("ticket-authz-data#kdc-issued"),
225 : get_ticket_authz_data, NULL, NULL, 1, 1 },
226 : { NB("ticket-authz-data"),
227 : get_ticket_authz_data, NULL, NULL, 1, 1 },
228 : { NB("authenticator-authz-data"),
229 : get_authenticator_authz_data,
230 : set_authenticator_authz_data, NULL, 1, 1 },
231 : { NB("authz-data"), get_authz_data, NULL, NULL, 1, 1 },
232 : { NB("transit-path"), get_transited, NULL, NULL, 1, 1 },
233 : { NB("canonical-name"), get_canonical_name, NULL, NULL, 1, 1 },
234 : };
235 :
236 : OM_uint32 GSSAPI_CALLCONV
237 0 : _gsskrb5_get_name_attribute(OM_uint32 *minor_status,
238 : gss_name_t name,
239 : gss_buffer_t original_attr,
240 : int *authenticated,
241 : int *complete,
242 : gss_buffer_t value,
243 : gss_buffer_t display_value,
244 : int *more)
245 : {
246 0 : gss_buffer_desc prefix, attr, suffix, frag;
247 0 : size_t i;
248 0 : int is_krb5_name_attr_urn = 0;
249 0 : int is_urn = 0;
250 :
251 0 : *minor_status = 0;
252 0 : if (authenticated)
253 0 : *authenticated = 0;
254 0 : if (complete)
255 0 : *complete = 0;
256 0 : if (more)
257 0 : *more = 0;
258 0 : if (value) {
259 0 : value->length = 0;
260 0 : value->value = NULL;
261 : }
262 0 : if (display_value) {
263 0 : display_value->length = 0;
264 0 : display_value->value = NULL;
265 : }
266 :
267 0 : suffix.value = NULL;
268 0 : suffix.length = 0;
269 :
270 0 : split_attr(original_attr, &prefix, &attr, &frag, &is_urn);
271 :
272 0 : if (prefix.length || !is_urn)
273 0 : return GSS_S_UNAVAILABLE;
274 :
275 0 : is_krb5_name_attr_urn =
276 0 : ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN);
277 0 : if (is_krb5_name_attr_urn) {
278 0 : suffix.value =
279 0 : (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1;
280 0 : suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1);
281 : }
282 :
283 0 : for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) {
284 0 : if (!name_attrs[i].getter)
285 0 : continue;
286 0 : if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) {
287 0 : if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0))
288 0 : continue;
289 0 : } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) {
290 0 : if (!attr_eq(&attr, name_attrs[i].fullname, name_attrs[i].fullnamelen, 0))
291 0 : continue;
292 : } else
293 0 : continue;
294 :
295 0 : return name_attrs[i].getter(minor_status,
296 : (const CompositePrincipal *)name,
297 : &prefix, &attr, &frag, authenticated,
298 : complete, value, display_value, more);
299 : }
300 0 : return GSS_S_UNAVAILABLE;
301 : }
302 :
303 : OM_uint32 GSSAPI_CALLCONV
304 0 : _gsskrb5_set_name_attribute(OM_uint32 *minor_status,
305 : gss_name_t name,
306 : int complete,
307 : gss_buffer_t original_attr,
308 : gss_buffer_t value)
309 : {
310 0 : gss_buffer_desc prefix, attr, suffix, frag;
311 0 : size_t i;
312 0 : int is_krb5_name_attr_urn = 0;
313 0 : int is_urn = 0;
314 :
315 0 : *minor_status = 0;
316 :
317 0 : suffix.value = NULL;
318 0 : suffix.length = 0;
319 :
320 0 : split_attr(original_attr, &prefix, &attr, &frag, &is_urn);
321 :
322 0 : if (prefix.length || !is_urn)
323 0 : return GSS_S_UNAVAILABLE;
324 :
325 0 : is_krb5_name_attr_urn =
326 0 : ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN);
327 0 : if (is_krb5_name_attr_urn) {
328 0 : suffix.value =
329 0 : (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1;
330 0 : suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1);
331 : }
332 :
333 0 : for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) {
334 0 : if (!name_attrs[i].setter)
335 0 : continue;
336 0 : if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) {
337 0 : if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0))
338 0 : continue;
339 0 : } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) {
340 0 : if (!attr_eq(&attr, name_attrs[i].name, name_attrs[i].namelen, 0))
341 0 : continue;
342 : } else
343 0 : continue;
344 :
345 0 : return name_attrs[i].setter(minor_status, (CompositePrincipal *)name,
346 : &prefix, &attr, &frag, complete, value);
347 : }
348 0 : return GSS_S_UNAVAILABLE;
349 : }
350 :
351 : OM_uint32 GSSAPI_CALLCONV
352 0 : _gsskrb5_delete_name_attribute(OM_uint32 *minor_status,
353 : gss_name_t name,
354 : gss_buffer_t original_attr)
355 : {
356 0 : gss_buffer_desc prefix, attr, suffix, frag;
357 0 : size_t i;
358 0 : int is_krb5_name_attr_urn = 0;
359 0 : int is_urn = 0;
360 :
361 0 : *minor_status = 0;
362 :
363 0 : suffix.value = NULL;
364 0 : suffix.length = 0;
365 :
366 0 : split_attr(original_attr, &prefix, &attr, &frag, &is_urn);
367 :
368 0 : if (prefix.length || !is_urn)
369 0 : return GSS_S_UNAVAILABLE;
370 :
371 0 : is_krb5_name_attr_urn =
372 0 : ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN);
373 0 : if (is_krb5_name_attr_urn) {
374 0 : suffix.value =
375 0 : (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1;
376 0 : suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1);
377 : }
378 :
379 0 : for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) {
380 0 : if (!name_attrs[i].deleter)
381 0 : continue;
382 0 : if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) {
383 0 : if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0))
384 0 : continue;
385 0 : } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) {
386 0 : if (!attr_eq(&attr, name_attrs[i].fullname, name_attrs[i].fullnamelen, 0))
387 0 : continue;
388 : } else
389 0 : continue;
390 :
391 0 : return name_attrs[i].deleter(minor_status, (CompositePrincipal *)name,
392 : &prefix, &attr, &frag);
393 : }
394 0 : return GSS_S_UNAVAILABLE;
395 : }
396 :
397 : OM_uint32 GSSAPI_CALLCONV
398 0 : _gsskrb5_inquire_name(OM_uint32 *minor_status,
399 : gss_name_t name,
400 : int *name_is_MN,
401 : gss_OID *MN_mech,
402 : gss_buffer_set_t *attrs)
403 : {
404 0 : gss_buffer_desc prefix, attr, frag, a;
405 0 : OM_uint32 major = GSS_S_UNAVAILABLE;
406 0 : size_t i;
407 0 : int authenticated, is_urn;
408 :
409 0 : *minor_status = 0;
410 0 : if (name_is_MN)
411 0 : *name_is_MN = 1;
412 0 : if (MN_mech)
413 0 : *MN_mech = GSS_KRB5_MECHANISM;
414 0 : if (name == GSS_C_NO_NAME)
415 0 : return GSS_S_CALL_INACCESSIBLE_READ;
416 0 : if (attrs == NULL)
417 0 : return GSS_S_CALL_INACCESSIBLE_WRITE;
418 :
419 0 : for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) {
420 0 : if (!name_attrs[i].indicate)
421 0 : continue;
422 0 : a.value = (void *)(uintptr_t)name_attrs[i].fullname;
423 0 : a.length = name_attrs[i].fullnamelen;
424 0 : split_attr(&a, &prefix, &attr, &frag, &is_urn);
425 0 : major = name_attrs[i].getter(minor_status,
426 : (const CompositePrincipal *)name,
427 : &prefix, &attr, &frag, &authenticated,
428 : NULL, NULL, NULL, NULL);
429 0 : if (major == GSS_S_UNAVAILABLE)
430 0 : continue;
431 0 : if (major != GSS_S_COMPLETE)
432 0 : break;
433 0 : major = gss_add_buffer_set_member(minor_status, &a, attrs);
434 : }
435 0 : if (major == GSS_S_UNAVAILABLE)
436 0 : major = GSS_S_COMPLETE;
437 0 : return major;
438 : }
439 :
440 : OM_uint32 GSSAPI_CALLCONV
441 0 : _gsskrb5_display_name_ext(OM_uint32 *minor_status,
442 : gss_name_t name,
443 : gss_OID display_as_name_type,
444 : gss_buffer_t display_name)
445 : {
446 0 : krb5_const_principal p = (void *)name;
447 0 : char *s = NULL;
448 :
449 0 : *minor_status = 0;
450 0 : if (display_name == NULL)
451 0 : return GSS_S_CALL_INACCESSIBLE_WRITE;
452 0 : display_name->length = 0;
453 0 : display_name->value = NULL;
454 :
455 0 : if (gss_oid_equal(display_as_name_type, GSS_C_NT_USER_NAME)) {
456 0 : if (p->name.name_string.len != 1)
457 0 : return GSS_S_UNAVAILABLE;
458 0 : return _gsskrb5_localname(minor_status, name, GSS_KRB5_MECHANISM,
459 : display_name);
460 : }
461 0 : if (!gss_oid_equal(display_as_name_type, GSS_C_NT_HOSTBASED_SERVICE) ||
462 0 : p->name.name_string.len != 2 ||
463 0 : strchr(p->name.name_string.val[0], '@') ||
464 0 : strchr(p->name.name_string.val[1], '.') == NULL)
465 0 : return GSS_S_UNAVAILABLE;
466 0 : if (asprintf(&s, "%s@%s", p->name.name_string.val[0],
467 0 : p->name.name_string.val[1]) == -1 || s == NULL) {
468 0 : *minor_status = ENOMEM;
469 0 : return GSS_S_FAILURE;
470 : }
471 0 : display_name->length = strlen(s);
472 0 : display_name->value = s;
473 0 : return GSS_S_COMPLETE;
474 : }
475 :
476 : OM_uint32 GSSAPI_CALLCONV
477 0 : _gsskrb5_export_name_composite(OM_uint32 *minor_status,
478 : gss_name_t name,
479 : gss_buffer_t exported_name)
480 : {
481 0 : krb5_error_code kret;
482 0 : gss_buffer_desc inner = GSS_C_EMPTY_BUFFER;
483 0 : unsigned char *buf;
484 0 : size_t sz;
485 :
486 0 : if (name == NULL)
487 0 : return GSS_S_CALL_INACCESSIBLE_READ;
488 0 : if (exported_name == NULL)
489 0 : return GSS_S_CALL_INACCESSIBLE_WRITE;
490 :
491 0 : ASN1_MALLOC_ENCODE(CompositePrincipal, inner.value, inner.length,
492 : (void *)name, &sz, kret);
493 0 : if (kret != 0) {
494 0 : *minor_status = kret;
495 0 : return GSS_S_FAILURE;
496 : }
497 :
498 0 : exported_name->length = 10 + inner.length + GSS_KRB5_MECHANISM->length;
499 0 : exported_name->value = malloc(exported_name->length);
500 0 : if (exported_name->value == NULL) {
501 0 : free(inner.value);
502 0 : *minor_status = ENOMEM;
503 0 : return GSS_S_FAILURE;
504 : }
505 :
506 : /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */
507 :
508 0 : buf = exported_name->value;
509 0 : buf[0] = 0x04;
510 0 : buf[1] = 0x02;
511 0 : buf[2] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff;
512 0 : buf[3] = (GSS_KRB5_MECHANISM->length + 2) & 0xff;
513 0 : buf[4] = 0x06;
514 0 : buf[5] = (GSS_KRB5_MECHANISM->length) & 0xFF;
515 :
516 0 : memcpy(buf + 6, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length);
517 0 : buf += 6 + GSS_KRB5_MECHANISM->length;
518 :
519 0 : buf[0] = (inner.length >> 24) & 0xff;
520 0 : buf[1] = (inner.length >> 16) & 0xff;
521 0 : buf[2] = (inner.length >> 8) & 0xff;
522 0 : buf[3] = (inner.length) & 0xff;
523 0 : buf += 4;
524 :
525 0 : memcpy(buf, inner.value, inner.length);
526 0 : free(inner.value);
527 :
528 0 : *minor_status = 0;
529 0 : return GSS_S_COMPLETE;
530 : }
531 :
532 : #define CHECK_ENOMEM(v, dv) \
533 : do { \
534 : if (((v) && !(v)->value) || ((dv) && !(dv)->value)) { \
535 : if ((v) && (v)->value) { \
536 : free((v)->value); \
537 : (v)->length = 0; \
538 : (v)->value = NULL; \
539 : } \
540 : *minor_status = ENOMEM; \
541 : return GSS_S_FAILURE; \
542 : } \
543 : } while (0)
544 :
545 : static OM_uint32
546 0 : get_realm(OM_uint32 *minor_status,
547 : const CompositePrincipal *name,
548 : gss_const_buffer_t prefix,
549 : gss_const_buffer_t attr,
550 : gss_const_buffer_t frag,
551 : int *authenticated,
552 : int *complete,
553 : gss_buffer_t value,
554 : gss_buffer_t display_value,
555 : int *more)
556 : {
557 0 : PrincipalNameAttrs *nameattrs = name->nameattrs;
558 :
559 0 : if (prefix->length || frag->length || !name->realm)
560 0 : return GSS_S_UNAVAILABLE;
561 0 : if (authenticated && nameattrs && nameattrs->authenticated)
562 0 : *authenticated = 1;
563 0 : if (complete)
564 0 : *complete = 1;
565 0 : if (value && (value->value = strdup(name->realm)))
566 0 : value->length = strlen(name->realm);
567 0 : if (display_value && (display_value->value = strdup(name->realm)))
568 0 : display_value->length = strlen(name->realm);
569 0 : CHECK_ENOMEM(value, display_value);
570 0 : return GSS_S_COMPLETE;
571 : }
572 :
573 : static OM_uint32
574 0 : get_ncomps(OM_uint32 *minor_status,
575 : const CompositePrincipal *name,
576 : gss_const_buffer_t prefix,
577 : gss_const_buffer_t attr,
578 : gss_const_buffer_t frag,
579 : int *authenticated,
580 : int *complete,
581 : gss_buffer_t value,
582 : gss_buffer_t display_value,
583 : int *more)
584 : {
585 0 : PrincipalNameAttrs *nameattrs = name->nameattrs;
586 0 : int n = -1;
587 :
588 0 : if (authenticated && nameattrs && nameattrs->authenticated)
589 0 : *authenticated = 1;
590 0 : if (complete)
591 0 : *complete = 1;
592 :
593 0 : if (frag->length == 1 &&
594 0 : ((const char *)frag->value)[0] >= '0' &&
595 0 : ((const char *)frag->value)[0] <= '9') {
596 0 : n = ((const char *)frag->value)[0] - '0';
597 0 : } else if (frag->length == sizeof("all") - 1 &&
598 0 : strncmp(frag->value, "all", sizeof("all") - 1) == 0) {
599 0 : if (!more || *more < -1 || *more == 0 || *more > CHAR_MAX ||
600 0 : *more > (int)name->name.name_string.len) {
601 0 : *minor_status = EINVAL;
602 0 : return GSS_S_UNAVAILABLE;
603 : }
604 0 : if (*more == -1) {
605 0 : *more = name->name.name_string.len - 1;
606 0 : n = 0;
607 : } else {
608 0 : n = name->name.name_string.len - *more;
609 0 : (*more)--;
610 : }
611 : }
612 :
613 0 : if (frag->length == 0) {
614 0 : char *s = NULL;
615 :
616 : /* Outut count of components */
617 0 : if (value && (value->value = malloc(sizeof(size_t)))) {
618 0 : *((size_t *)value->value) = name->name.name_string.len;
619 0 : value->length = sizeof(size_t);
620 : }
621 0 : if (display_value &&
622 0 : asprintf(&s, "%u", (unsigned int)name->name.name_string.len) > 0) {
623 0 : display_value->value = s;
624 0 : display_value->length = strlen(display_value->value);
625 : }
626 : } else {
627 : /*
628 : * Output a component. The value and the display value are the same in
629 : * this case.
630 : */
631 0 : if (n < 0 || n >= name->name.name_string.len) {
632 0 : *minor_status = EINVAL;
633 0 : return GSS_S_UNAVAILABLE;
634 : }
635 0 : if (value && (value->value = strdup(name->name.name_string.val[n])))
636 0 : value->length = strlen(name->name.name_string.val[n]);
637 0 : if (display_value &&
638 0 : (display_value->value = strdup(name->name.name_string.val[n])))
639 0 : display_value->length = strlen(name->name.name_string.val[n]);
640 : }
641 :
642 0 : CHECK_ENOMEM(value, display_value);
643 0 : return GSS_S_COMPLETE;
644 : }
645 :
646 : static OM_uint32
647 0 : get_peer_realm(OM_uint32 *minor_status,
648 : const CompositePrincipal *name,
649 : gss_const_buffer_t prefix,
650 : gss_const_buffer_t attr,
651 : gss_const_buffer_t frag,
652 : int *authenticated,
653 : int *complete,
654 : gss_buffer_t value,
655 : gss_buffer_t display_value,
656 : int *more)
657 : {
658 0 : PrincipalNameAttrs *nameattrs = name->nameattrs;
659 :
660 0 : if (prefix->length || frag->length || !nameattrs || !nameattrs->peer_realm)
661 0 : return GSS_S_UNAVAILABLE;
662 0 : if (authenticated)
663 0 : *authenticated = 1;
664 0 : if (complete)
665 0 : *complete = 1;
666 0 : if (value && (value->value = strdup(nameattrs->peer_realm[0])))
667 0 : value->length = strlen(value->value);
668 0 : if (display_value &&
669 0 : (display_value->value = strdup(nameattrs->peer_realm[0])))
670 0 : display_value->length = strlen(display_value->value);
671 :
672 0 : CHECK_ENOMEM(value, display_value);
673 0 : return GSS_S_COMPLETE;
674 : }
675 :
676 : static OM_uint32
677 0 : get_pac(OM_uint32 *minor_status,
678 : const CompositePrincipal *name,
679 : gss_const_buffer_t prefix,
680 : gss_const_buffer_t attr,
681 : gss_const_buffer_t frag,
682 : int *authenticated,
683 : int *complete,
684 : gss_buffer_t value,
685 : gss_buffer_t display_value,
686 : int *more)
687 : {
688 0 : krb5_error_code kret;
689 0 : krb5_context context;
690 0 : krb5_data data;
691 0 : PrincipalNameAttrs *nameattrs = name->nameattrs;
692 0 : PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
693 0 : EncTicketPart *ticket = NULL;
694 :
695 0 : krb5_data_zero(&data);
696 :
697 0 : if (src == NULL ||
698 0 : src->element != choice_PrincipalNameAttrSrc_enc_ticket_part)
699 0 : return GSS_S_UNAVAILABLE;
700 :
701 0 : ticket = &src->u.enc_ticket_part;
702 :
703 0 : if (prefix->length || !authenticated || !ticket)
704 0 : return GSS_S_UNAVAILABLE;
705 :
706 0 : GSSAPI_KRB5_INIT(&context);
707 :
708 0 : *authenticated = nameattrs->pac_verified;
709 0 : if (complete)
710 0 : *complete = 1;
711 :
712 0 : kret = _krb5_get_ad(context, ticket->authorization_data,
713 : NULL, KRB5_AUTHDATA_WIN2K_PAC,
714 : value ? &data : NULL);
715 :
716 0 : if (value) {
717 0 : value->length = data.length;
718 0 : value->value = data.data;
719 : }
720 :
721 0 : *minor_status = kret;
722 0 : if (kret == ENOENT)
723 0 : return GSS_S_UNAVAILABLE;
724 0 : return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
725 : }
726 :
727 : static OM_uint32
728 0 : get_pac_buffer(OM_uint32 *minor_status,
729 : const CompositePrincipal *name,
730 : gss_const_buffer_t prefix,
731 : gss_const_buffer_t attr,
732 : gss_const_buffer_t frag,
733 : int *authenticated,
734 : int *complete,
735 : gss_buffer_t value,
736 : gss_buffer_t display_value,
737 : int *more)
738 : {
739 0 : krb5_error_code kret;
740 0 : krb5_context context;
741 0 : krb5_data data;
742 0 : PrincipalNameAttrs *nameattrs = name->nameattrs;
743 0 : krb5_data suffix;
744 :
745 0 : krb5_data_zero(&data);
746 :
747 0 : if (prefix->length || !authenticated ||
748 0 : !nameattrs || !nameattrs->pac)
749 0 : return GSS_S_UNAVAILABLE;
750 :
751 0 : GSSAPI_KRB5_INIT(&context);
752 :
753 0 : if (ATTR_EQ_PREFIX(attr, "urn:mspac:")) {
754 0 : suffix.length = attr->length - (sizeof("urn:mspac:") - 1);
755 0 : suffix.data = (char *)attr->value + sizeof("urn:mspac:") - 1;
756 0 : } else if (ATTR_EQ_PREFIX(frag, "pac-")) {
757 0 : suffix.length = frag->length - sizeof("pac-") - 1;
758 0 : suffix.data = (char *)frag->value + sizeof("pac-") - 1;
759 : } else
760 0 : return GSS_S_UNAVAILABLE; /* should not be reached */
761 :
762 0 : *authenticated = nameattrs->pac_verified;
763 0 : if (complete)
764 0 : *complete = 1;
765 :
766 0 : kret = _krb5_pac_get_buffer_by_name(context, nameattrs->pac, &suffix,
767 : value ? &data : NULL);
768 :
769 0 : if (value) {
770 0 : value->length = data.length;
771 0 : value->value = data.data;
772 : }
773 :
774 0 : *minor_status = kret;
775 0 : if (kret == ENOENT)
776 0 : return GSS_S_UNAVAILABLE;
777 0 : return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
778 : }
779 :
780 : static OM_uint32
781 0 : get_authz_data(OM_uint32 *minor_status,
782 : const CompositePrincipal *name,
783 : gss_const_buffer_t prefix,
784 : gss_const_buffer_t attr,
785 : gss_const_buffer_t frag,
786 : int *authenticated,
787 : int *complete,
788 : gss_buffer_t value,
789 : gss_buffer_t display_value,
790 : int *more)
791 : {
792 0 : krb5_error_code kret = 0;
793 0 : PrincipalNameAttrs *nameattrs = name->nameattrs;
794 0 : PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
795 0 : EncTicketPart *ticket = NULL;
796 0 : krb5_context context;
797 0 : krb5_data data;
798 0 : char s[22];
799 0 : char *end;
800 0 : int64_t n;
801 :
802 0 : if (src) switch (src->element) {
803 0 : case choice_PrincipalNameAttrSrc_enc_ticket_part:
804 0 : ticket = &src->u.enc_ticket_part;
805 0 : break;
806 0 : case choice_PrincipalNameAttrSrc_enc_kdc_rep_part:
807 : default:
808 0 : return GSS_S_UNAVAILABLE;
809 : }
810 :
811 0 : if (!nameattrs || !frag->length || frag->length > sizeof(s) - 1)
812 0 : return GSS_S_UNAVAILABLE;
813 :
814 : /* Output a specific AD element from the ticket or authenticator */
815 0 : krb5_data_zero(&data);
816 0 : memcpy(s, frag->value, frag->length);
817 0 : s[frag->length] = '\0';
818 0 : errno = 0;
819 0 : n = strtoll(s, &end, 10);
820 0 : if (end[0] == '\0' && (errno || n > INT_MAX || n < INT_MIN)) {
821 0 : *minor_status = ERANGE;
822 0 : return GSS_S_UNAVAILABLE;
823 : }
824 0 : if (end[0] != '\0') {
825 0 : *minor_status = EINVAL;
826 0 : return GSS_S_UNAVAILABLE;
827 : }
828 :
829 0 : if (authenticated)
830 0 : *authenticated = 0;
831 0 : if (complete)
832 0 : *complete = 1;
833 :
834 0 : GSSAPI_KRB5_INIT(&context);
835 :
836 0 : kret = ENOENT;
837 0 : if (ticket && ticket->authorization_data) {
838 0 : kret = _krb5_get_ad(context, ticket->authorization_data,
839 : NULL, n, value ? &data : NULL);
840 :
841 : /* If it's from the ticket, it _may_ be authenticated: */
842 0 : if (kret == 0 && authenticated) {
843 0 : if (n == KRB5_AUTHDATA_KDC_ISSUED)
844 0 : *authenticated = nameattrs->kdc_issued_verified;
845 0 : else if (n == KRB5_AUTHDATA_WIN2K_PAC)
846 0 : *authenticated = nameattrs->pac_verified;
847 : }
848 : }
849 0 : if (kret == ENOENT && nameattrs->authenticator_ad &&
850 0 : n != KRB5_AUTHDATA_KDC_ISSUED &&
851 0 : n != KRB5_AUTHDATA_WIN2K_PAC) {
852 0 : kret = _krb5_get_ad(context, nameattrs->authenticator_ad,
853 : NULL, n, value ? &data : NULL);
854 : }
855 :
856 0 : if (value) {
857 0 : value->length = data.length;
858 0 : value->value = data.data;
859 : }
860 0 : *minor_status = kret;
861 0 : if (kret == ENOENT)
862 0 : return GSS_S_UNAVAILABLE;
863 0 : return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
864 : }
865 :
866 : static OM_uint32
867 0 : get_ticket_authz_data(OM_uint32 *minor_status,
868 : const CompositePrincipal *name,
869 : gss_const_buffer_t prefix,
870 : gss_const_buffer_t attr,
871 : gss_const_buffer_t frag,
872 : int *authenticated,
873 : int *complete,
874 : gss_buffer_t value,
875 : gss_buffer_t display_value,
876 : int *more)
877 : {
878 0 : krb5_error_code kret = 0;
879 0 : PrincipalNameAttrs *nameattrs = name->nameattrs;
880 0 : PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
881 0 : EncTicketPart *ticket = NULL;
882 0 : size_t sz;
883 :
884 0 : if (src) switch (src->element) {
885 0 : case choice_PrincipalNameAttrSrc_enc_ticket_part:
886 0 : ticket = &src->u.enc_ticket_part;
887 0 : break;
888 0 : case choice_PrincipalNameAttrSrc_enc_kdc_rep_part:
889 : default:
890 0 : return GSS_S_UNAVAILABLE;
891 : }
892 :
893 0 : if (!ticket)
894 0 : return GSS_S_UNAVAILABLE;
895 :
896 0 : if (complete)
897 0 : *complete = 1;
898 :
899 0 : if (frag->length == sizeof("kdc-issued") - 1 &&
900 0 : strncmp(frag->value, "kdc-issued", sizeof("kdc-issued") - 1) == 0) {
901 0 : krb5_context context;
902 0 : krb5_data data;
903 :
904 0 : GSSAPI_KRB5_INIT(&context);
905 0 : if (authenticated)
906 0 : *authenticated = nameattrs->kdc_issued_verified;
907 :
908 0 : kret = _krb5_get_ad(context, ticket->authorization_data,
909 : NULL, KRB5_AUTHDATA_KDC_ISSUED,
910 : value ? &data : NULL);
911 0 : if (value) {
912 0 : value->length = data.length;
913 0 : value->value = data.data;
914 : }
915 0 : if (kret == ENOENT)
916 0 : return GSS_S_UNAVAILABLE;
917 0 : *minor_status = kret;
918 0 : return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
919 0 : } else if (frag->length) {
920 0 : return GSS_S_UNAVAILABLE;
921 : }
922 :
923 : /* Just because it's in the Ticket doesn't make it authenticated */
924 0 : if (authenticated)
925 0 : *authenticated = 0;
926 :
927 0 : if (value) {
928 0 : ASN1_MALLOC_ENCODE(AuthorizationData, value->value, value->length,
929 : ticket->authorization_data, &sz, kret);
930 0 : *minor_status = kret;
931 : }
932 0 : return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
933 : }
934 :
935 : static OM_uint32
936 0 : get_authenticator_authz_data(OM_uint32 *minor_status,
937 : const CompositePrincipal *name,
938 : gss_const_buffer_t prefix,
939 : gss_const_buffer_t attr,
940 : gss_const_buffer_t frag,
941 : int *authenticated,
942 : int *complete,
943 : gss_buffer_t value,
944 : gss_buffer_t display_value,
945 : int *more)
946 : {
947 0 : krb5_error_code kret = 0;
948 0 : PrincipalNameAttrs *nameattrs = name->nameattrs;
949 0 : size_t sz;
950 :
951 0 : if (!nameattrs || !nameattrs->authenticator_ad)
952 0 : return GSS_S_UNAVAILABLE;
953 0 : if (authenticated)
954 0 : *authenticated = 0;
955 0 : if (complete)
956 0 : *complete = 1;
957 :
958 0 : if (value) {
959 0 : ASN1_MALLOC_ENCODE(AuthorizationData, value->value, value->length,
960 : nameattrs->authenticator_ad, &sz, kret);
961 0 : *minor_status = kret;
962 : }
963 0 : return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
964 : }
965 :
966 : static OM_uint32
967 0 : set_authenticator_authz_data(OM_uint32 *minor_status,
968 : CompositePrincipal *name,
969 : gss_const_buffer_t prefix,
970 : gss_const_buffer_t attr,
971 : gss_const_buffer_t frag,
972 : int complete,
973 : gss_buffer_t value)
974 : {
975 0 : AuthorizationDataElement e;
976 0 : krb5_error_code kret;
977 0 : size_t sz;
978 :
979 0 : if (!value)
980 0 : return GSS_S_CALL_INACCESSIBLE_READ;
981 0 : if (frag->length &&
982 0 : !ATTR_EQ(frag, "if-relevant"))
983 0 : return GSS_S_UNAVAILABLE;
984 :
985 0 : if ((name->nameattrs == NULL &&
986 0 : (name->nameattrs = calloc(1, sizeof(*name->nameattrs))) == NULL) ||
987 0 : (name->nameattrs->want_ad == NULL &&
988 0 : (name->nameattrs->want_ad =
989 0 : calloc(1, sizeof(*name->nameattrs->want_ad))) == NULL)) {
990 0 : *minor_status = ENOMEM;
991 0 : return GSS_S_FAILURE;
992 : }
993 :
994 0 : memset(&e, 0, sizeof(e));
995 0 : kret = decode_AuthorizationDataElement(value->value, value->length, &e,
996 : &sz);
997 0 : if (kret == 0) {
998 0 : if (frag->length) {
999 0 : AuthorizationData ir;
1000 :
1001 0 : ir.len = 0;
1002 0 : ir.val = NULL;
1003 0 : kret = add_AuthorizationData(&ir, &e);
1004 0 : free_AuthorizationDataElement(&e);
1005 0 : if (kret == 0) {
1006 0 : e.ad_type = KRB5_AUTHDATA_IF_RELEVANT;
1007 0 : ASN1_MALLOC_ENCODE(AuthorizationData, e.ad_data.data,
1008 : e.ad_data.length, &ir, &sz, kret);
1009 0 : kret = add_AuthorizationData(name->nameattrs->want_ad, &e);
1010 : }
1011 0 : free_AuthorizationData(&ir);
1012 : } else {
1013 0 : kret = add_AuthorizationData(name->nameattrs->want_ad, &e);
1014 0 : free_AuthorizationDataElement(&e);
1015 : }
1016 : }
1017 :
1018 0 : *minor_status = kret;
1019 0 : return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
1020 : }
1021 :
1022 : static OM_uint32
1023 0 : get_transited(OM_uint32 *minor_status,
1024 : const CompositePrincipal *name,
1025 : gss_const_buffer_t prefix,
1026 : gss_const_buffer_t attr,
1027 : gss_const_buffer_t frag,
1028 : int *authenticated,
1029 : int *complete,
1030 : gss_buffer_t value,
1031 : gss_buffer_t display_value,
1032 : int *more)
1033 : {
1034 0 : krb5_error_code kret = 0;
1035 0 : PrincipalNameAttrs *nameattrs = name->nameattrs;
1036 0 : PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
1037 0 : EncTicketPart *ticket = NULL;
1038 0 : size_t sz;
1039 :
1040 0 : if (src) switch (src->element) {
1041 0 : case choice_PrincipalNameAttrSrc_enc_kdc_rep_part:
1042 0 : break;
1043 0 : case choice_PrincipalNameAttrSrc_enc_ticket_part:
1044 0 : ticket = &src->u.enc_ticket_part;
1045 0 : break;
1046 0 : default:
1047 0 : return GSS_S_UNAVAILABLE;
1048 : }
1049 :
1050 0 : if (!nameattrs && !ticket)
1051 0 : return GSS_S_UNAVAILABLE;
1052 0 : if (nameattrs && !nameattrs->transited && !ticket)
1053 0 : return GSS_S_UNAVAILABLE;
1054 :
1055 0 : if (authenticated)
1056 0 : *authenticated = 1;
1057 0 : if (complete)
1058 0 : *complete = 1;
1059 :
1060 0 : if (value && ticket)
1061 0 : ASN1_MALLOC_ENCODE(TransitedEncoding, value->value, value->length,
1062 : &ticket->transited, &sz, kret);
1063 0 : else if (value && nameattrs->transited)
1064 0 : ASN1_MALLOC_ENCODE(TransitedEncoding, value->value, value->length,
1065 : nameattrs->transited, &sz, kret);
1066 0 : *minor_status = kret;
1067 0 : return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
1068 : }
1069 :
1070 : static OM_uint32
1071 0 : get_canonical_name(OM_uint32 *minor_status,
1072 : const CompositePrincipal *name,
1073 : gss_const_buffer_t prefix,
1074 : gss_const_buffer_t attr,
1075 : gss_const_buffer_t frag,
1076 : int *authenticated,
1077 : int *complete,
1078 : gss_buffer_t value,
1079 : gss_buffer_t display_value,
1080 : int *more)
1081 : {
1082 0 : krb5_error_code kret = 0;
1083 0 : PrincipalNameAttrs *nameattrs = name->nameattrs;
1084 0 : PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
1085 0 : krb5_principal p = NULL;
1086 0 : krb5_context context;
1087 0 : EncTicketPart *ticket = NULL;
1088 0 : EncKDCRepPart *kdcrep = NULL;
1089 :
1090 0 : if (src) switch (src->element) {
1091 0 : case choice_PrincipalNameAttrSrc_enc_kdc_rep_part:
1092 0 : kdcrep = &src->u.enc_kdc_rep_part;
1093 0 : break;
1094 0 : case choice_PrincipalNameAttrSrc_enc_ticket_part:
1095 0 : ticket = &src->u.enc_ticket_part;
1096 0 : break;
1097 0 : default:
1098 0 : return GSS_S_UNAVAILABLE;
1099 : }
1100 :
1101 0 : GSSAPI_KRB5_INIT(&context);
1102 :
1103 0 : if (authenticated)
1104 0 : *authenticated = 1;
1105 0 : if (complete)
1106 0 : *complete = 1;
1107 :
1108 0 : if (kdcrep) {
1109 0 : kret = _krb5_principalname2krb5_principal(context, &p,
1110 : kdcrep->sname,
1111 : kdcrep->srealm);
1112 0 : } else if (nameattrs && nameattrs->pac &&
1113 0 : (_krb5_pac_get_canon_principal(context, nameattrs->pac, &p)) == 0) {
1114 0 : if (authenticated)
1115 0 : *authenticated = nameattrs->pac_verified;
1116 0 : } else if (ticket) {
1117 0 : krb5_data data;
1118 0 : krb5_pac pac = NULL;
1119 :
1120 0 : krb5_data_zero(&data);
1121 :
1122 : /* Use canonical name from PAC if available */
1123 0 : kret = _krb5_get_ad(context, ticket->authorization_data,
1124 : NULL, KRB5_AUTHDATA_WIN2K_PAC, &data);
1125 0 : if (kret == 0)
1126 0 : kret = krb5_pac_parse(context, data.data, data.length, &pac);
1127 0 : if (kret == 0)
1128 0 : kret = _krb5_pac_get_canon_principal(context, pac, &p);
1129 0 : if (kret == 0 && authenticated)
1130 0 : *authenticated = nameattrs->pac_verified;
1131 0 : else if (kret == ENOENT)
1132 0 : kret = _krb5_principalname2krb5_principal(context, &p,
1133 : ticket->cname,
1134 : ticket->crealm);
1135 :
1136 0 : krb5_data_free(&data);
1137 0 : krb5_pac_free(context, pac);
1138 : } else
1139 0 : return GSS_S_UNAVAILABLE;
1140 0 : if (kret == 0 && value) {
1141 0 : OM_uint32 major;
1142 : /*
1143 : * Value is exported name token (exported composite name token
1144 : * should also work).
1145 : */
1146 0 : major = _gsskrb5_export_name(minor_status, (gss_name_t)p, value);
1147 0 : if (major != GSS_S_COMPLETE) {
1148 0 : krb5_free_principal(context, p);
1149 0 : return major;
1150 : }
1151 : }
1152 0 : if (kret == 0 && display_value) {
1153 : /* Display value is principal name display form */
1154 0 : kret = krb5_unparse_name(context, p,
1155 0 : (char **)&display_value->value);
1156 0 : if (kret == 0)
1157 0 : display_value->length = strlen(display_value->value);
1158 : }
1159 :
1160 0 : krb5_free_principal(context, p);
1161 0 : if (kret) {
1162 0 : if (value) {
1163 0 : free(value->value);
1164 0 : value->length = 0;
1165 0 : value->value = NULL;
1166 : }
1167 0 : *minor_status = kret;
1168 0 : return GSS_S_UNAVAILABLE;
1169 : }
1170 0 : return GSS_S_COMPLETE;
1171 : }
|