Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : *
17 : * 3. Neither the name of the Institute nor the names of its contributors
18 : * may be used to endorse or promote products derived from this software
19 : * without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 : * SUCH DAMAGE.
32 : */
33 :
34 : #include "kdc_locl.h"
35 :
36 : static int
37 214130 : name_type_ok(krb5_context context,
38 : krb5_kdc_configuration *config,
39 : krb5_const_principal principal)
40 : {
41 214130 : int nt = krb5_principal_get_type(context, principal);
42 :
43 214130 : if (!krb5_principal_is_krbtgt(context, principal))
44 89494 : return 1;
45 124636 : if (nt == KRB5_NT_SRV_INST || nt == KRB5_NT_UNKNOWN)
46 124636 : return 1;
47 0 : if (config->strict_nametypes == 0)
48 0 : return 1;
49 0 : return 0;
50 : }
51 :
52 : struct timeval _kdc_now;
53 :
54 : static krb5_error_code
55 0 : synthesize_hdb_close(krb5_context context, struct HDB *db)
56 : {
57 : (void) context;
58 : (void) db;
59 0 : return 0;
60 : }
61 :
62 : /*
63 : * Synthesize an HDB entry suitable for PKINIT and GSS preauth.
64 : */
65 : static krb5_error_code
66 0 : synthesize_client(krb5_context context,
67 : krb5_kdc_configuration *config,
68 : krb5_const_principal princ,
69 : HDB **db,
70 : hdb_entry **h)
71 : {
72 : static HDB null_db;
73 : krb5_error_code ret;
74 : hdb_entry *e;
75 :
76 : /* Hope this works! */
77 0 : null_db.hdb_destroy = synthesize_hdb_close;
78 0 : null_db.hdb_close = synthesize_hdb_close;
79 0 : if (db)
80 0 : *db = &null_db;
81 :
82 0 : ret = (e = calloc(1, sizeof(*e))) ? 0 : krb5_enomem(context);
83 0 : if (ret == 0) {
84 0 : e->flags.client = 1;
85 0 : e->flags.immutable = 1;
86 0 : e->flags.virtual = 1;
87 0 : e->flags.synthetic = 1;
88 0 : e->flags.do_not_store = 1;
89 0 : e->kvno = 1;
90 0 : e->keys.len = 0;
91 0 : e->keys.val = NULL;
92 0 : e->created_by.time = time(NULL);
93 0 : e->modified_by = NULL;
94 0 : e->valid_start = NULL;
95 0 : e->valid_end = NULL;
96 0 : e->pw_end = NULL;
97 0 : e->etypes = NULL;
98 0 : e->generation = NULL;
99 0 : e->extensions = NULL;
100 : }
101 0 : if (ret == 0)
102 0 : ret = (e->max_renew = calloc(1, sizeof(*e->max_renew))) ?
103 0 : 0 : krb5_enomem(context);
104 0 : if (ret == 0)
105 0 : ret = (e->max_life = calloc(1, sizeof(*e->max_life))) ?
106 0 : 0 : krb5_enomem(context);
107 0 : if (ret == 0)
108 0 : ret = krb5_copy_principal(context, princ, &e->principal);
109 0 : if (ret == 0)
110 0 : ret = krb5_copy_principal(context, princ, &e->created_by.principal);
111 0 : if (ret == 0) {
112 : /*
113 : * We can't check OCSP in the TGS path, so we can't let tickets for
114 : * synthetic principals live very long.
115 : */
116 0 : *(e->max_renew) = config->synthetic_clients_max_renew;
117 0 : *(e->max_life) = config->synthetic_clients_max_life;
118 0 : *h = e;
119 0 : } else if (e) {
120 0 : hdb_free_entry(context, &null_db, e);
121 : }
122 0 : return ret;
123 : }
124 :
125 : KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
126 214130 : _kdc_db_fetch(krb5_context context,
127 : krb5_kdc_configuration *config,
128 : krb5_const_principal principal,
129 : unsigned flags,
130 : krb5uint32 *kvno_ptr,
131 : HDB **db,
132 : hdb_entry **h)
133 : {
134 214130 : hdb_entry *ent = NULL;
135 214130 : krb5_error_code ret = HDB_ERR_NOENTRY;
136 : int i;
137 214130 : unsigned kvno = 0;
138 214130 : krb5_principal enterprise_principal = NULL;
139 : krb5_const_principal princ;
140 :
141 214130 : *h = NULL;
142 :
143 214130 : if (!name_type_ok(context, config, principal))
144 0 : return HDB_ERR_NOENTRY;
145 :
146 214130 : flags |= HDB_F_DECRYPT;
147 214130 : if (kvno_ptr != NULL && *kvno_ptr != 0) {
148 38489 : kvno = *kvno_ptr;
149 38489 : flags |= HDB_F_KVNO_SPECIFIED;
150 : } else {
151 175641 : flags |= HDB_F_ALL_KVNOS;
152 : }
153 :
154 214130 : ent = calloc(1, sizeof (*ent));
155 214130 : if (ent == NULL)
156 0 : return krb5_enomem(context);
157 :
158 214130 : if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
159 2668 : if (principal->name.name_string.len != 1) {
160 6 : ret = KRB5_PARSE_MALFORMED;
161 6 : krb5_set_error_message(context, ret,
162 : "malformed request: "
163 : "enterprise name with %d name components",
164 : principal->name.name_string.len);
165 6 : goto out;
166 : }
167 2662 : ret = krb5_parse_name(context, principal->name.name_string.val[0],
168 : &enterprise_principal);
169 2662 : if (ret)
170 0 : goto out;
171 : }
172 :
173 215674 : for (i = 0; i < config->num_db; i++) {
174 214124 : HDB *curdb = config->db[i];
175 :
176 214124 : if (db)
177 214124 : *db = curdb;
178 :
179 214124 : ret = curdb->hdb_open(context, curdb, O_RDONLY, 0);
180 214124 : if (ret) {
181 0 : const char *msg = krb5_get_error_message(context, ret);
182 0 : kdc_log(context, config, 0, "Failed to open database: %s", msg);
183 0 : krb5_free_error_message(context, msg);
184 0 : continue;
185 : }
186 :
187 214124 : princ = principal;
188 214124 : if (!(curdb->hdb_capability_flags & HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL) && enterprise_principal)
189 0 : princ = enterprise_principal;
190 :
191 214124 : ret = hdb_fetch_kvno(context, curdb, princ, flags, 0, 0, kvno, ent);
192 214124 : curdb->hdb_close(context, curdb);
193 :
194 214124 : if (ret == HDB_ERR_NOENTRY)
195 1550 : continue; /* Check the other databases */
196 :
197 : /*
198 : * This is really important, because errors like
199 : * HDB_ERR_NOT_FOUND_HERE (used to indicate to Samba that
200 : * the RODC on which this code is running does not have
201 : * the key we need, and so a proxy to the KDC is required)
202 : * have specific meaning, and need to be propogated up.
203 : */
204 212574 : break;
205 : }
206 :
207 214124 : switch (ret) {
208 209547 : case HDB_ERR_WRONG_REALM:
209 : case 0:
210 : /*
211 : * the ent->entry.principal just contains hints for the client
212 : * to retry. This is important for enterprise principal routing
213 : * between trusts.
214 : */
215 209547 : *h = ent;
216 209547 : ent = NULL;
217 209547 : break;
218 :
219 1550 : case HDB_ERR_NOENTRY:
220 1550 : if (db)
221 1550 : *db = NULL;
222 1550 : if ((flags & HDB_F_GET_CLIENT) && (flags & HDB_F_SYNTHETIC_OK) &&
223 : config->synthetic_clients) {
224 0 : ret = synthesize_client(context, config, principal, db, h);
225 0 : if (ret) {
226 0 : krb5_set_error_message(context, ret, "could not synthesize "
227 : "HDB client principal entry");
228 0 : ret = HDB_ERR_NOENTRY;
229 0 : krb5_prepend_error_message(context, ret, "no such entry found in hdb");
230 : }
231 : } else {
232 1550 : krb5_set_error_message(context, ret, "no such entry found in hdb");
233 : }
234 1550 : break;
235 :
236 3027 : default:
237 3027 : if (db)
238 3027 : *db = NULL;
239 3027 : break;
240 : }
241 :
242 214130 : out:
243 214130 : krb5_free_principal(context, enterprise_principal);
244 214130 : free(ent);
245 214130 : return ret;
246 : }
247 :
248 : KDC_LIB_FUNCTION void KDC_LIB_CALL
249 209547 : _kdc_free_ent(krb5_context context, HDB *db, hdb_entry *ent)
250 : {
251 209547 : hdb_free_entry (context, db, ent);
252 209547 : free (ent);
253 209547 : }
254 :
255 : /*
256 : * Use the order list of preferred encryption types and sort the
257 : * available keys and return the most preferred key.
258 : */
259 :
260 : krb5_error_code
261 92825 : _kdc_get_preferred_key(krb5_context context,
262 : krb5_kdc_configuration *config,
263 : hdb_entry *h,
264 : const char *name,
265 : krb5_enctype *enctype,
266 : Key **key)
267 : {
268 : krb5_error_code ret;
269 : int i;
270 :
271 92825 : if (config->use_strongest_server_key) {
272 92825 : const krb5_enctype *p = krb5_kerberos_enctypes(context);
273 :
274 151470 : for (i = 0; p[i] != ETYPE_NULL; i++) {
275 151306 : if (krb5_enctype_valid(context, p[i]) != 0 &&
276 0 : !_kdc_is_weak_exception(h->principal, p[i]))
277 0 : continue;
278 151306 : ret = hdb_enctype2key(context, h, NULL, p[i], key);
279 151306 : if (ret != 0)
280 58645 : continue;
281 92661 : if (enctype != NULL)
282 19503 : *enctype = p[i];
283 92661 : return 0;
284 : }
285 : } else {
286 0 : *key = NULL;
287 :
288 0 : for (i = 0; i < h->keys.len; i++) {
289 0 : if (krb5_enctype_valid(context, h->keys.val[i].key.keytype) != 0 &&
290 0 : !_kdc_is_weak_exception(h->principal, h->keys.val[i].key.keytype))
291 0 : continue;
292 0 : ret = hdb_enctype2key(context, h, NULL,
293 0 : h->keys.val[i].key.keytype, key);
294 0 : if (ret != 0)
295 0 : continue;
296 0 : if (enctype != NULL)
297 0 : *enctype = (*key)->key.keytype;
298 0 : return 0;
299 : }
300 : }
301 :
302 164 : krb5_set_error_message(context, ret = KRB5KDC_ERR_ETYPE_NOSUPP,
303 : "No valid kerberos key found for %s", name);
304 164 : return ret;
305 : }
306 :
307 : krb5_error_code
308 69912 : _kdc_verify_checksum(krb5_context context,
309 : krb5_crypto crypto,
310 : krb5_key_usage usage,
311 : const krb5_data *data,
312 : Checksum *cksum)
313 : {
314 : krb5_error_code ret;
315 :
316 69912 : ret = krb5_verify_checksum(context, crypto, usage,
317 : data->data, data->length,
318 : cksum);
319 69912 : if (ret == KRB5_PROG_SUMTYPE_NOSUPP)
320 2 : ret = KRB5KDC_ERR_SUMTYPE_NOSUPP;
321 :
322 69912 : return ret;
323 : }
324 :
325 : /*
326 : * Returns TRUE if a PAC should be included in ticket authorization data.
327 : *
328 : * Per [MS-KILE] 3.3.5.3, PACs are always included for TGTs; for service
329 : * tickets, policy is governed by whether the client explicitly requested
330 : * a PAC be omitted when requesting a TGT, or if the no-auth-data-reqd
331 : * flag is set on the service principal entry.
332 : */
333 :
334 : krb5_boolean
335 35728 : _kdc_include_pac_p(astgs_request_t r)
336 : {
337 35728 : return TRUE;
338 : }
339 :
340 : /*
341 : * Notify the HDB backend and KDC plugin of the audited event.
342 : */
343 :
344 : krb5_error_code
345 71023 : _kdc_audit_request(astgs_request_t r)
346 : {
347 : krb5_error_code ret;
348 : struct HDB *hdb;
349 :
350 71023 : ret = _kdc_plugin_audit(r);
351 142046 : if (ret == 0 &&
352 142046 : (hdb = r->clientdb ? r->clientdb : r->config->db[0]) &&
353 71023 : hdb->hdb_audit)
354 71023 : ret = hdb->hdb_audit(r->context, hdb, r->client, (hdb_request_t)r);
355 :
356 71023 : return ret;
357 : }
|