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 krb5_fulladdr *, 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 krb5_fulladdr *, const krb5_fulladdr *, kdc_realm_t *, 152 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 krb5_fulladdr *, 157 kdc_realm_t *, krb5_data ** ); 158 /* dispatch.c */ 159 void 160 dispatch (void *, 161 const krb5_fulladdr *, 162 const krb5_fulladdr *, 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 krb5_fulladdr *local_addr, 319 const krb5_fulladdr *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 krb5_fulladdr *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 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