xref: /freebsd/crypto/krb5/src/lib/krb5/krb/srv_dec_tkt.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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