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