1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/krb/srv_dec_tkt.c */
3 /*
4 * Copyright 2006, 2008 by the Massachusetts Institute of Technology.
5 * All Rights Reserved.
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 /*
28 * Server decrypt ticket via keytab or keyblock.
29 *
30 * Different from krb5_rd_req_decoded. (krb5/src/lib/krb5/krb/rd_req_dec.c)
31 * - No krb5_principal_compare or KRB5KRB_AP_ERR_BADMATCH error.
32 * - No replay cache processing.
33 * - No skew checking or KRB5KRB_AP_ERR_SKEW error.
34 * - No address checking or KRB5KRB_AP_ERR_BADADDR error.
35 * - No time validation.
36 * - No permitted enctype validation or KRB5_NOPERM_ETYPE error.
37 * - Does not free ticket->enc_part2 on error.
38 */
39
40 #include <k5-int.h>
41
42 #ifndef LEAN_CLIENT
43 static krb5_error_code
decrypt_ticket_keyblock(krb5_context context,const krb5_keyblock * key,krb5_ticket * ticket)44 decrypt_ticket_keyblock(krb5_context context, const krb5_keyblock *key,
45 krb5_ticket *ticket)
46 {
47 krb5_error_code retval;
48 krb5_data *realm;
49 krb5_transited *trans;
50
51 retval = krb5_decrypt_tkt_part(context, key, ticket);
52 if (retval)
53 goto done;
54
55 trans = &ticket->enc_part2->transited;
56 realm = &ticket->enc_part2->client->realm;
57 if (trans->tr_contents.data && *trans->tr_contents.data) {
58 retval = krb5_check_transited_list(context, &trans->tr_contents,
59 realm, &ticket->server->realm);
60 goto done;
61 }
62
63 if (ticket->enc_part2->flags & TKT_FLG_INVALID) { /* ie, KDC_OPT_POSTDATED */
64 retval = KRB5KRB_AP_ERR_TKT_INVALID;
65 goto done;
66 }
67
68 done:
69 return retval;
70 }
71
72
73 krb5_error_code KRB5_CALLCONV
krb5_server_decrypt_ticket_keytab(krb5_context context,const krb5_keytab keytab,krb5_ticket * ticket)74 krb5_server_decrypt_ticket_keytab(krb5_context context,
75 const krb5_keytab keytab,
76 krb5_ticket *ticket)
77 {
78 krb5_error_code retval;
79 krb5_keytab_entry ktent;
80
81 if (keytab->ops->start_seq_get == NULL) {
82 retval = krb5_kt_get_entry(context, keytab,
83 ticket->server,
84 ticket->enc_part.kvno,
85 ticket->enc_part.enctype, &ktent);
86 if (retval == 0) {
87 retval = decrypt_ticket_keyblock(context, &ktent.key, ticket);
88
89 (void) krb5_free_keytab_entry_contents(context, &ktent);
90 }
91 } else {
92 krb5_error_code code;
93 krb5_kt_cursor cursor;
94
95 retval = krb5_kt_start_seq_get(context, keytab, &cursor);
96 if (retval != 0)
97 goto map_error;
98
99 retval = KRB5_KT_NOTFOUND;
100 while ((code = krb5_kt_next_entry(context, keytab,
101 &ktent, &cursor)) == 0) {
102 if (ktent.key.enctype != ticket->enc_part.enctype) {
103 (void) krb5_free_keytab_entry_contents(context, &ktent);
104 continue;
105 }
106
107 retval = decrypt_ticket_keyblock(context, &ktent.key, ticket);
108 if (retval == 0) {
109 krb5_principal tmp;
110
111 retval = krb5_copy_principal(context, ktent.principal, &tmp);
112 if (retval == 0) {
113 krb5_free_principal(context, ticket->server);
114 ticket->server = tmp;
115 }
116 (void) krb5_free_keytab_entry_contents(context, &ktent);
117 break;
118 }
119 (void) krb5_free_keytab_entry_contents(context, &ktent);
120 }
121
122 code = krb5_kt_end_seq_get(context, keytab, &cursor);
123 if (code != 0)
124 retval = code;
125 }
126
127 map_error:
128 switch (retval) {
129 case KRB5_KT_KVNONOTFOUND:
130 case KRB5_KT_NOTFOUND:
131 case KRB5KRB_AP_ERR_BAD_INTEGRITY:
132 retval = KRB5KRB_AP_WRONG_PRINC;
133 break;
134 default:
135 break;
136 }
137
138 return retval;
139 }
140 #endif /* LEAN_CLIENT */
141