1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* kdc/kdc_util.h */
3 /*
4 * Portions Copyright (C) 2007 Apple Inc.
5 * Copyright 1990, 2007, 2014 by the Massachusetts Institute of Technology.
6 *
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
11 *
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
25 *
26 *
27 * Declarations for policy.c
28 */
29
30 #ifndef __KRB5_KDC_UTIL__
31 #define __KRB5_KDC_UTIL__
32
33 #include <krb5/kdcpreauth_plugin.h>
34 #include "kdb.h"
35 #include "net-server.h"
36 #include "realm_data.h"
37 #include "reqstate.h"
38
39 krb5_boolean krb5_is_tgs_principal (krb5_const_principal);
40 krb5_boolean is_cross_tgs_principal(krb5_const_principal);
41 krb5_boolean is_local_tgs_principal(krb5_const_principal);
42 krb5_error_code
43 add_to_transited (krb5_data *,
44 krb5_data *,
45 krb5_principal,
46 krb5_principal,
47 krb5_principal);
48 krb5_error_code
49 compress_transited (krb5_data *,
50 krb5_principal,
51 krb5_data *);
52 krb5_error_code
53 fetch_last_req_info (krb5_db_entry *, krb5_last_req_entry ***);
54
55 krb5_error_code
56 kdc_convert_key (krb5_keyblock *, krb5_keyblock *, int);
57 krb5_error_code
58 kdc_process_tgs_req (kdc_realm_t *, krb5_kdc_req *,
59 const struct sockaddr *,
60 krb5_data *,
61 krb5_ticket **,
62 krb5_db_entry **krbtgt_ptr,
63 krb5_keyblock **, krb5_keyblock **,
64 krb5_pa_data **pa_tgs_req);
65
66 krb5_error_code
67 kdc_get_server_key (krb5_context, krb5_ticket *, unsigned int,
68 krb5_boolean match_enctype,
69 krb5_db_entry **, krb5_keyblock **, krb5_kvno *);
70
71 krb5_error_code
72 get_first_current_key(krb5_context context, krb5_db_entry *entry,
73 krb5_keyblock *key_out);
74
75 krb5_error_code
76 get_local_tgt(krb5_context context, const krb5_data *realm,
77 krb5_db_entry *candidate, krb5_db_entry **alias_out,
78 krb5_db_entry **storage_out, krb5_keyblock *kb_out);
79
80 krb5_error_code
81 validate_as_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry *,
82 krb5_db_entry *, krb5_timestamp,
83 const char **, krb5_pa_data ***);
84
85 krb5_error_code
86 check_tgs_constraints(kdc_realm_t *realm, krb5_kdc_req *request,
87 krb5_db_entry *server, krb5_ticket *ticket, krb5_pac pac,
88 const krb5_ticket *stkt, krb5_pac stkt_pac,
89 krb5_db_entry *stkt_server, krb5_timestamp kdc_time,
90 krb5_pa_s4u_x509_user *s4u_x509_user,
91 krb5_db_entry *s4u2self_client,
92 krb5_boolean is_crossrealm, krb5_boolean is_referral,
93 const char **status, krb5_pa_data ***e_data);
94
95 krb5_error_code
96 check_tgs_policy(kdc_realm_t *realm, krb5_kdc_req *request,
97 krb5_db_entry *server, krb5_ticket *ticket,
98 krb5_pac pac, const krb5_ticket *stkt, krb5_pac stkt_pac,
99 krb5_principal stkt_pac_client, krb5_db_entry *stkt_server,
100 krb5_timestamp kdc_time, krb5_boolean is_crossrealm,
101 krb5_boolean is_referral, const char **status,
102 krb5_pa_data ***e_data);
103
104 krb5_flags
105 get_ticket_flags(krb5_flags reqflags, krb5_db_entry *client,
106 krb5_db_entry *server, krb5_enc_tkt_part *header_enc);
107
108 krb5_error_code
109 check_indicators(krb5_context context, krb5_db_entry *server,
110 krb5_data *const *indicators);
111
112 int
113 fetch_asn1_field (unsigned char *, unsigned int, unsigned int, krb5_data *);
114
115 krb5_enctype
116 select_session_keytype (krb5_context context, krb5_db_entry *server,
117 int nktypes, krb5_enctype *ktypes);
118
119 void limit_string (char *name);
120
121 char *ktypes2str(krb5_enctype *ktype, int nktypes);
122
123 char *rep_etypes2str(krb5_kdc_rep *rep);
124
125 /* authind.c */
126 krb5_boolean
127 authind_contains(krb5_data *const *indicators, const char *ind);
128
129 krb5_error_code
130 authind_add(krb5_context context, const char *ind, krb5_data ***indicators);
131
132 krb5_error_code
133 authind_extract(krb5_context context, krb5_authdata **authdata,
134 krb5_data ***indicators);
135
136 /* cammac.c */
137 krb5_error_code
138 cammac_create(krb5_context context, krb5_enc_tkt_part *enc_tkt_reply,
139 krb5_keyblock *server_key, krb5_db_entry *tgt,
140 krb5_keyblock *tgt_key, krb5_authdata **contents,
141 krb5_authdata ***cammac_out);
142
143 krb5_boolean
144 cammac_check_kdcver(krb5_context context, krb5_cammac *cammac,
145 krb5_enc_tkt_part *enc_tkt, krb5_db_entry *tgt,
146 krb5_keyblock *tgt_key);
147
148 /* do_as_req.c */
149 void
150 process_as_req (krb5_kdc_req *, krb5_data *,
151 const struct sockaddr *, const struct sockaddr *,
152 kdc_realm_t *, verto_ctx *, loop_respond_fn, void *);
153
154 /* do_tgs_req.c */
155 krb5_error_code
156 process_tgs_req (krb5_kdc_req *, krb5_data *, const struct sockaddr *,
157 kdc_realm_t *, krb5_data ** );
158 /* dispatch.c */
159 void
160 dispatch (void *,
161 const struct sockaddr *,
162 const struct sockaddr *,
163 krb5_data *,
164 int,
165 verto_ctx *,
166 loop_respond_fn,
167 void *);
168
169 void
170 kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...)
171 #if !defined(__cplusplus) && (__GNUC__ > 2)
172 __attribute__((__format__(__printf__, 3, 4)))
173 #endif
174 ;
175
176 /* kdc_preauth.c */
177 krb5_boolean
178 enctype_requires_etype_info_2(krb5_enctype enctype);
179
180 const char *
181 missing_required_preauth (krb5_db_entry *client,
182 krb5_db_entry *server,
183 krb5_enc_tkt_part *enc_tkt_reply);
184 typedef void (*kdc_hint_respond_fn)(void *arg);
185 void
186 get_preauth_hint_list(krb5_kdc_req *request,
187 krb5_kdcpreauth_rock rock, krb5_pa_data ***e_data_out,
188 kdc_hint_respond_fn respond, void *arg);
189 void
190 load_preauth_plugins(struct server_handle * handle, krb5_context context,
191 verto_ctx *ctx);
192 void
193 unload_preauth_plugins(krb5_context context);
194
195 typedef void (*kdc_preauth_respond_fn)(void *arg, krb5_error_code code);
196
197 void
198 check_padata(krb5_context context, krb5_kdcpreauth_rock rock,
199 krb5_data *req_pkt, krb5_kdc_req *request,
200 krb5_enc_tkt_part *enc_tkt_reply, void **padata_context,
201 krb5_pa_data ***e_data, krb5_boolean *typed_e_data,
202 kdc_preauth_respond_fn respond, void *state);
203
204 krb5_error_code
205 return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
206 krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply,
207 krb5_keyblock *encrypting_key, void **padata_context);
208
209 void
210 free_padata_context(krb5_context context, void *padata_context);
211
212 /* kdc_preauth_ec.c */
213 krb5_error_code
214 kdcpreauth_encrypted_challenge_initvt(krb5_context context, int maj_ver,
215 int min_ver, krb5_plugin_vtable vtable);
216
217 /* kdc_preauth_enctsc.c */
218 krb5_error_code
219 kdcpreauth_encrypted_timestamp_initvt(krb5_context context, int maj_ver,
220 int min_ver, krb5_plugin_vtable vtable);
221
222 /* kdc_authdata.c */
223 krb5_error_code
224 load_authdata_plugins(krb5_context context);
225 krb5_error_code
226 unload_authdata_plugins(krb5_context context);
227
228 krb5_error_code
229 get_auth_indicators(krb5_context context, krb5_enc_tkt_part *enc_tkt,
230 krb5_db_entry *local_tgt, krb5_keyblock *local_tgt_key,
231 krb5_data ***indicators_out);
232
233 krb5_error_code
234 handle_authdata(kdc_realm_t *realm, unsigned int flags, krb5_db_entry *client,
235 krb5_db_entry *server, krb5_db_entry *subject_server,
236 krb5_db_entry *local_tgt, krb5_keyblock *local_tgt_key,
237 krb5_keyblock *client_key, krb5_keyblock *server_key,
238 krb5_keyblock *header_key, krb5_keyblock *replaced_reply_key,
239 krb5_data *req_pkt, krb5_kdc_req *request,
240 krb5_const_principal altcprinc, krb5_pac subject_pac,
241 krb5_enc_tkt_part *enc_tkt_request,
242 krb5_data ***auth_indicators,
243 krb5_enc_tkt_part *enc_tkt_reply);
244
245 /* replay.c */
246 krb5_error_code kdc_init_lookaside(krb5_context context);
247 krb5_boolean kdc_check_lookaside (krb5_context, krb5_data *, krb5_data **);
248 void kdc_insert_lookaside (krb5_context, krb5_data *, krb5_data *);
249 void kdc_remove_lookaside (krb5_context kcontext, krb5_data *);
250 void kdc_free_lookaside(krb5_context);
251
252 /* kdc_util.c */
253 void reset_for_hangup(void *);
254
255 krb5_error_code
256 pac_privsvr_key(krb5_context context, krb5_db_entry *server,
257 const krb5_keyblock *tgt_key, krb5_keyblock **key_out);
258
259 krb5_error_code
260 get_verified_pac(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
261 krb5_db_entry *server, krb5_keyblock *server_key,
262 krb5_db_entry *tgt, krb5_keyblock *tgt_key,
263 krb5_pac *pac_out);
264
265 krb5_error_code
266 get_pac_princ_with_realm(krb5_context context, krb5_pac pac,
267 krb5_principal *princ_out,
268 krb5_timestamp *authtime_out);
269
270 krb5_boolean
271 include_pac_p(krb5_context context, krb5_kdc_req *request);
272
273 krb5_error_code
274 return_enc_padata(krb5_context context,
275 krb5_data *req_pkt, krb5_kdc_req *request,
276 krb5_keyblock *reply_key,
277 krb5_db_entry *server,
278 krb5_enc_kdc_rep_part *reply_encpart,
279 krb5_boolean is_referral);
280
281 krb5_error_code
282 kdc_process_s4u2self_req(krb5_context context, krb5_kdc_req *request,
283 const krb5_db_entry *server,
284 krb5_keyblock *tgs_subkey, krb5_keyblock *tgs_session,
285 krb5_pa_s4u_x509_user **s4u2self_req,
286 krb5_db_entry **princ_ptr, const char **status);
287
288 krb5_error_code
289 s4u2self_forwardable(krb5_context context, krb5_db_entry *server,
290 krb5_flags *tktflags);
291
292 krb5_error_code
293 kdc_make_s4u2self_rep (krb5_context context,
294 krb5_keyblock *tgs_subkey,
295 krb5_keyblock *tgs_session,
296 krb5_pa_s4u_x509_user *req_s4u_user,
297 krb5_kdc_rep *reply,
298 krb5_enc_kdc_rep_part *reply_encpart);
299
300 krb5_error_code
301 kdc_check_transited_list(krb5_context context, const krb5_data *trans,
302 const krb5_data *realm1, const krb5_data *realm2);
303
304 void
305 kdc_get_ticket_endtime(kdc_realm_t *realm, krb5_timestamp now,
306 krb5_timestamp endtime, krb5_timestamp till,
307 krb5_db_entry *client, krb5_db_entry *server,
308 krb5_timestamp *out_endtime);
309
310 void
311 kdc_get_ticket_renewtime(kdc_realm_t *realm, krb5_kdc_req *request,
312 krb5_enc_tkt_part *tgt, krb5_db_entry *client,
313 krb5_db_entry *server, krb5_flags *tktflags,
314 krb5_ticket_times *times);
315
316 void
317 log_as_req(krb5_context context,
318 const struct sockaddr *local_addr,
319 const struct sockaddr *remote_addr,
320 krb5_kdc_req *request, krb5_kdc_rep *reply,
321 krb5_db_entry *client, const char *cname,
322 krb5_db_entry *server, const char *sname,
323 krb5_timestamp authtime,
324 const char *status, krb5_error_code errcode, const char *emsg);
325 void
326 log_tgs_req(krb5_context ctx, const struct sockaddr *from,
327 krb5_kdc_req *request, krb5_kdc_rep *reply,
328 krb5_principal cprinc, krb5_principal sprinc,
329 krb5_principal altcprinc,
330 krb5_timestamp authtime,
331 unsigned int c_flags,
332 const char *status, krb5_error_code errcode, const char *emsg);
333 void
334 log_tgs_badtrans(krb5_context ctx, krb5_principal cprinc,
335 krb5_principal sprinc, krb5_data *trcont,
336 krb5_error_code errcode);
337
338 void
339 log_tgs_alt_tgt(krb5_context context, krb5_principal p);
340
341 krb5_boolean
342 is_client_db_alias(krb5_context context, const krb5_db_entry *entry,
343 krb5_const_principal princ);
344
345 /* FAST*/
346 enum krb5_fast_kdc_flags {
347 KRB5_FAST_REPLY_KEY_USED = 0x1,
348 KRB5_FAST_REPLY_KEY_REPLACED = 0x02
349 };
350
351 /*
352 * If *requestptr contains FX_FAST padata, compute the armor key, verify the
353 * checksum over checksummed_data, decode the FAST request, and substitute
354 * *requestptr with the inner request. Set the armor_key, cookie, and
355 * fast_options fields in state. state->cookie will be set for a non-FAST
356 * request if it contains FX_COOKIE padata. If inner_body_out is non-NULL, set
357 * *inner_body_out to a copy of the encoded inner body, or to NULL if the
358 * request is not a FAST request.
359 */
360 krb5_error_code
361 kdc_find_fast (krb5_kdc_req **requestptr, krb5_data *checksummed_data,
362 krb5_keyblock *tgs_subkey, krb5_keyblock *tgs_session,
363 struct kdc_request_state *state, krb5_data **inner_body_out);
364
365 krb5_error_code
366 kdc_fast_response_handle_padata (struct kdc_request_state *state,
367 krb5_kdc_req *request,
368 krb5_kdc_rep *rep,
369 krb5_enctype enctype);
370 krb5_error_code
371 kdc_fast_handle_error (krb5_context context,
372 struct kdc_request_state *state,
373 krb5_kdc_req *request,
374 krb5_pa_data **in_padata, krb5_error *err,
375 krb5_data **fast_edata_out);
376
377 krb5_error_code kdc_fast_handle_reply_key(struct kdc_request_state *state,
378 krb5_keyblock *existing_key,
379 krb5_keyblock **out_key);
380
381
382 krb5_boolean
383 kdc_fast_hide_client(struct kdc_request_state *state);
384
385 krb5_error_code
386 kdc_handle_protected_negotiation( krb5_context context,
387 krb5_data *req_pkt, krb5_kdc_req *request,
388 const krb5_keyblock *reply_key,
389 krb5_pa_data ***out_enc_padata);
390
391 krb5_error_code
392 kdc_fast_read_cookie(krb5_context context, struct kdc_request_state *state,
393 krb5_kdc_req *req, krb5_db_entry *local_tgt,
394 krb5_keyblock *local_tgt_key);
395
396 krb5_boolean kdc_fast_search_cookie(struct kdc_request_state *state,
397 krb5_preauthtype pa_type, krb5_data *out);
398
399 krb5_error_code kdc_fast_set_cookie(struct kdc_request_state *state,
400 krb5_preauthtype pa_type,
401 const krb5_data *data);
402
403 krb5_error_code
404 kdc_fast_make_cookie(krb5_context context, struct kdc_request_state *state,
405 krb5_db_entry *local_tgt, krb5_keyblock *local_tgt_key,
406 krb5_const_principal client_princ,
407 krb5_pa_data **cookie_out);
408
409 krb5_error_code
410 kdc_add_pa_pac_options(krb5_context context, krb5_kdc_req *request,
411 krb5_pa_data ***out_enc_padata);
412
413 krb5_error_code
414 kdc_get_pa_pac_options(krb5_context context, krb5_pa_data **in_padata,
415 krb5_pa_pac_options **pac_options_out);
416
417 krb5_error_code
418 kdc_get_pa_pac_rbcd(krb5_context context, krb5_pa_data **in_padata,
419 krb5_boolean *supported);
420
421 /* Information handle for kdcpreauth callbacks. All pointers are aliases. */
422 struct krb5_kdcpreauth_rock_st {
423 krb5_kdc_req *request;
424 krb5_data *inner_body;
425 krb5_db_entry *client;
426 krb5_db_entry *local_tgt;
427 krb5_keyblock *local_tgt_key;
428 krb5_key_data *client_key;
429 krb5_keyblock *client_keyblock;
430 struct kdc_request_state *rstate;
431 verto_ctx *vctx;
432 krb5_data ***auth_indicators;
433 krb5_boolean send_freshness_token;
434 krb5_boolean replaced_reply_key;
435 };
436
437 #define isflagset(flagfield, flag) (flagfield & (flag))
438 #define setflag(flagfield, flag) (flagfield |= (flag))
439 #define clear(flagfield, flag) (flagfield &= ~(flag))
440
441 #ifndef min
442 #define min(a, b) ((a) < (b) ? (a) : (b))
443 #define max(a, b) ((a) > (b) ? (a) : (b))
444 #endif
445
446 #define ts_min(a, b) (ts_after(a, b) ? (b) : (a))
447
448 #define ADDRTYPE2FAMILY(X) \
449 ((X) == ADDRTYPE_INET6 ? AF_INET6 : (X) == ADDRTYPE_INET ? AF_INET : -1)
450
451 /* RFC 4120: KRB5KDC_ERR_KEY_TOO_WEAK
452 * RFC 4556: KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED */
453 #define KRB5KDC_ERR_KEY_TOO_WEAK KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED
454 /* TGS-REQ options where the service can be a non-TGS principal */
455
456 #define NON_TGT_OPTION (KDC_OPT_FORWARDED | KDC_OPT_PROXY | KDC_OPT_RENEW | \
457 KDC_OPT_VALIDATE)
458
459 /* TGS-REQ options which are not compatible with referrals */
460 #define NO_REFERRAL_OPTION (NON_TGT_OPTION | KDC_OPT_ENC_TKT_IN_SKEY)
461
462 /* Options incompatible with AS and S4U2Self requests */
463 #define AS_INVALID_OPTIONS (NO_REFERRAL_OPTION | KDC_OPT_CNAME_IN_ADDL_TKT)
464
465 /*
466 * Mask of KDC options that request the corresponding ticket flag with
467 * the same number. Some of these are invalid for AS-REQs, but
468 * validate_as_request() takes care of that. KDC_OPT_RENEWABLE isn't
469 * here because it needs special handling in
470 * kdc_get_ticket_renewtime().
471 *
472 * According to RFC 4120 section 3.1.3 the following AS-REQ options
473 * request their corresponding ticket flags if local policy allows:
474 *
475 * KDC_OPT_FORWARDABLE KDC_OPT_ALLOW_POSTDATE
476 * KDC_OPT_POSTDATED KDC_OPT_PROXIABLE
477 * KDC_OPT_RENEWABLE
478 *
479 * RFC 1510 section A.6 shows pseudocode indicating that the following
480 * TGS-REQ options request their corresponding ticket flags if local
481 * policy allows:
482 *
483 * KDC_OPT_FORWARDABLE KDC_OPT_FORWARDED
484 * KDC_OPT_PROXIABLE KDC_OPT_PROXY
485 * KDC_OPT_POSTDATED KDC_OPT_RENEWABLE
486 *
487 * The above list omits KDC_OPT_ALLOW_POSTDATE, but RFC 4120 section
488 * 5.4.1 says the TGS also handles it.
489 *
490 * RFC 6112 makes KDC_OPT_REQUEST_ANONYMOUS the same bit number as
491 * TKT_FLG_ANONYMOUS.
492 */
493 #define OPTS_COMMON_FLAGS_MASK \
494 (KDC_OPT_FORWARDABLE | KDC_OPT_FORWARDED | \
495 KDC_OPT_PROXIABLE | KDC_OPT_PROXY | \
496 KDC_OPT_ALLOW_POSTDATE | KDC_OPT_POSTDATED | \
497 KDC_OPT_REQUEST_ANONYMOUS)
498
499 /* Copy KDC options that request the corresponding ticket flags. */
500 #define OPTS2FLAGS(x) (x & OPTS_COMMON_FLAGS_MASK)
501
502 /*
503 * Mask of ticket flags for the TGS to propagate from a ticket to a
504 * derivative ticket.
505 *
506 * RFC 4120 section 2.1 says the following flags are carried forward
507 * from an initial ticket to derivative tickets:
508 *
509 * TKT_FLG_PRE_AUTH
510 * TKT_FLG_HW_AUTH
511 *
512 * RFC 4120 section 2.6 says TKT_FLG_FORWARDED is carried forward to
513 * derivative tickets. Proxy tickets are basically identical to
514 * forwarded tickets except that a TGT may never be proxied, therefore
515 * tickets derived from proxy tickets should have TKT_FLAG_PROXY set.
516 * RFC 4120 and RFC 1510 apparently have an accidental omission in not
517 * requiring that tickets derived from a proxy ticket have
518 * TKT_FLG_PROXY set. Previous code also omitted this behavior.
519 *
520 * RFC 6112 section 4.2 implies that TKT_FLG_ANONYMOUS must be
521 * propagated from an anonymous ticket to derivative tickets.
522 */
523 #define TGS_COPIED_FLAGS_MASK \
524 (TKT_FLG_FORWARDED | TKT_FLG_PROXY | \
525 TKT_FLG_PRE_AUTH | TKT_FLG_HW_AUTH | \
526 TKT_FLG_ANONYMOUS)
527
528 /* Copy appropriate header ticket flags to new ticket. */
529 #define COPY_TKT_FLAGS(x) (x & TGS_COPIED_FLAGS_MASK)
530
531 int check_anon(kdc_realm_t *realm, krb5_principal client,
532 krb5_principal server);
533 int errcode_to_protocol(krb5_error_code code);
534
535 char *data2string(krb5_data *d);
536
537 /* Return the current key version of entry, or 0 if it has no keys. */
538 static inline krb5_kvno
current_kvno(krb5_db_entry * entry)539 current_kvno(krb5_db_entry *entry)
540 {
541 return (entry->n_key_data == 0) ? 0 : entry->key_data[0].key_data_kvno;
542 }
543
544 /* MS-PAC section 2.9 */
545 struct pac_s4u_delegation_info {
546 char *proxy_target;
547 uint32_t transited_services_length;
548 char **transited_services;
549 };
550
551 /* Leaves room for one additional service. */
552 krb5_error_code
553 ndr_dec_delegation_info(krb5_data *data,
554 struct pac_s4u_delegation_info **res);
555
556 krb5_error_code
557 ndr_enc_delegation_info(struct pac_s4u_delegation_info *in,
558 krb5_data *out);
559
560 void ndr_free_delegation_info(struct pac_s4u_delegation_info *in);
561
562 #endif /* __KRB5_KDC_UTIL__ */
563