1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray * All rights reserved.
5b528cefcSMark Murray *
6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray * modification, are permitted provided that the following conditions
8b528cefcSMark Murray * are met:
9b528cefcSMark Murray *
10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray *
13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray * documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray *
17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray * may be used to endorse or promote products derived from this software
19b528cefcSMark Murray * without specific prior written permission.
20b528cefcSMark Murray *
21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray * SUCH DAMAGE.
32b528cefcSMark Murray */
33b528cefcSMark Murray
34b528cefcSMark Murray #include "kdc_locl.h"
35b528cefcSMark Murray
36c19800e8SDoug Rabson struct timeval _kdc_now;
37b528cefcSMark Murray
385e9cd1aeSAssar Westerlund krb5_error_code
_kdc_db_fetch(krb5_context context,krb5_kdc_configuration * config,krb5_const_principal principal,unsigned flags,krb5uint32 * kvno_ptr,HDB ** db,hdb_entry_ex ** h)39c19800e8SDoug Rabson _kdc_db_fetch(krb5_context context,
40c19800e8SDoug Rabson krb5_kdc_configuration *config,
41c19800e8SDoug Rabson krb5_const_principal principal,
42c19800e8SDoug Rabson unsigned flags,
43*ae771770SStanislav Sedov krb5uint32 *kvno_ptr,
44c19800e8SDoug Rabson HDB **db,
45c19800e8SDoug Rabson hdb_entry_ex **h)
46b528cefcSMark Murray {
47c19800e8SDoug Rabson hdb_entry_ex *ent;
48*ae771770SStanislav Sedov krb5_error_code ret = HDB_ERR_NOENTRY;
49b528cefcSMark Murray int i;
50*ae771770SStanislav Sedov unsigned kvno = 0;
51*ae771770SStanislav Sedov
52*ae771770SStanislav Sedov if (kvno_ptr) {
53*ae771770SStanislav Sedov kvno = *kvno_ptr;
54*ae771770SStanislav Sedov flags |= HDB_F_KVNO_SPECIFIED;
55*ae771770SStanislav Sedov }
565e9cd1aeSAssar Westerlund
57c19800e8SDoug Rabson ent = calloc (1, sizeof (*ent));
58c19800e8SDoug Rabson if (ent == NULL) {
59*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
605e9cd1aeSAssar Westerlund return ENOMEM;
61c19800e8SDoug Rabson }
62b528cefcSMark Murray
63c19800e8SDoug Rabson for(i = 0; i < config->num_db; i++) {
64*ae771770SStanislav Sedov krb5_principal enterprise_principal = NULL;
65*ae771770SStanislav Sedov if (!(config->db[i]->hdb_capability_flags & HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL)
66*ae771770SStanislav Sedov && principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
67*ae771770SStanislav Sedov if (principal->name.name_string.len != 1) {
68*ae771770SStanislav Sedov ret = KRB5_PARSE_MALFORMED;
69*ae771770SStanislav Sedov krb5_set_error_message(context, ret,
70*ae771770SStanislav Sedov "malformed request: "
71*ae771770SStanislav Sedov "enterprise name with %d name components",
72*ae771770SStanislav Sedov principal->name.name_string.len);
73*ae771770SStanislav Sedov free(ent);
74*ae771770SStanislav Sedov return ret;
75*ae771770SStanislav Sedov }
76*ae771770SStanislav Sedov ret = krb5_parse_name(context, principal->name.name_string.val[0],
77*ae771770SStanislav Sedov &enterprise_principal);
78*ae771770SStanislav Sedov if (ret) {
79*ae771770SStanislav Sedov free(ent);
80*ae771770SStanislav Sedov return ret;
81*ae771770SStanislav Sedov }
82*ae771770SStanislav Sedov
83*ae771770SStanislav Sedov principal = enterprise_principal;
84*ae771770SStanislav Sedov }
85*ae771770SStanislav Sedov
86c19800e8SDoug Rabson ret = config->db[i]->hdb_open(context, config->db[i], O_RDONLY, 0);
87b528cefcSMark Murray if (ret) {
88*ae771770SStanislav Sedov const char *msg = krb5_get_error_message(context, ret);
89*ae771770SStanislav Sedov kdc_log(context, config, 0, "Failed to open database: %s", msg);
90*ae771770SStanislav Sedov krb5_free_error_message(context, msg);
91b528cefcSMark Murray continue;
92b528cefcSMark Murray }
93*ae771770SStanislav Sedov
94*ae771770SStanislav Sedov ret = config->db[i]->hdb_fetch_kvno(context,
95c19800e8SDoug Rabson config->db[i],
96c19800e8SDoug Rabson principal,
97c19800e8SDoug Rabson flags | HDB_F_DECRYPT,
98*ae771770SStanislav Sedov kvno,
99c19800e8SDoug Rabson ent);
100*ae771770SStanislav Sedov
101*ae771770SStanislav Sedov krb5_free_principal(context, enterprise_principal);
102*ae771770SStanislav Sedov
103c19800e8SDoug Rabson config->db[i]->hdb_close(context, config->db[i]);
1045e9cd1aeSAssar Westerlund if(ret == 0) {
105c19800e8SDoug Rabson if (db)
106c19800e8SDoug Rabson *db = config->db[i];
1075e9cd1aeSAssar Westerlund *h = ent;
1085e9cd1aeSAssar Westerlund return 0;
1095e9cd1aeSAssar Westerlund }
110b528cefcSMark Murray }
111b528cefcSMark Murray free(ent);
112*ae771770SStanislav Sedov krb5_set_error_message(context, ret,
113*ae771770SStanislav Sedov "no such entry found in hdb");
114*ae771770SStanislav Sedov return ret;
115b528cefcSMark Murray }
1165e9cd1aeSAssar Westerlund
1175e9cd1aeSAssar Westerlund void
_kdc_free_ent(krb5_context context,hdb_entry_ex * ent)118c19800e8SDoug Rabson _kdc_free_ent(krb5_context context, hdb_entry_ex *ent)
1195e9cd1aeSAssar Westerlund {
1205e9cd1aeSAssar Westerlund hdb_free_entry (context, ent);
1215e9cd1aeSAssar Westerlund free (ent);
1225e9cd1aeSAssar Westerlund }
1235e9cd1aeSAssar Westerlund
124c19800e8SDoug Rabson /*
125c19800e8SDoug Rabson * Use the order list of preferred encryption types and sort the
126c19800e8SDoug Rabson * available keys and return the most preferred key.
127c19800e8SDoug Rabson */
128c19800e8SDoug Rabson
129c19800e8SDoug Rabson krb5_error_code
_kdc_get_preferred_key(krb5_context context,krb5_kdc_configuration * config,hdb_entry_ex * h,const char * name,krb5_enctype * enctype,Key ** key)130c19800e8SDoug Rabson _kdc_get_preferred_key(krb5_context context,
131c19800e8SDoug Rabson krb5_kdc_configuration *config,
132c19800e8SDoug Rabson hdb_entry_ex *h,
133c19800e8SDoug Rabson const char *name,
134c19800e8SDoug Rabson krb5_enctype *enctype,
135c19800e8SDoug Rabson Key **key)
136c19800e8SDoug Rabson {
137c19800e8SDoug Rabson krb5_error_code ret;
138c19800e8SDoug Rabson int i;
139c19800e8SDoug Rabson
140*ae771770SStanislav Sedov if (config->use_strongest_server_key) {
141*ae771770SStanislav Sedov const krb5_enctype *p = krb5_kerberos_enctypes(context);
142c19800e8SDoug Rabson
143c19800e8SDoug Rabson for (i = 0; p[i] != ETYPE_NULL; i++) {
144c19800e8SDoug Rabson if (krb5_enctype_valid(context, p[i]) != 0)
145c19800e8SDoug Rabson continue;
146c19800e8SDoug Rabson ret = hdb_enctype2key(context, &h->entry, p[i], key);
147*ae771770SStanislav Sedov if (ret != 0)
148*ae771770SStanislav Sedov continue;
149*ae771770SStanislav Sedov if (enctype != NULL)
150c19800e8SDoug Rabson *enctype = p[i];
151c19800e8SDoug Rabson return 0;
152c19800e8SDoug Rabson }
153*ae771770SStanislav Sedov } else {
154*ae771770SStanislav Sedov *key = NULL;
155*ae771770SStanislav Sedov
156*ae771770SStanislav Sedov for (i = 0; i < h->entry.keys.len; i++) {
157*ae771770SStanislav Sedov if (krb5_enctype_valid(context, h->entry.keys.val[i].key.keytype)
158*ae771770SStanislav Sedov != 0)
159*ae771770SStanislav Sedov continue;
160*ae771770SStanislav Sedov ret = hdb_enctype2key(context, &h->entry,
161*ae771770SStanislav Sedov h->entry.keys.val[i].key.keytype, key);
162*ae771770SStanislav Sedov if (ret != 0)
163*ae771770SStanislav Sedov continue;
164*ae771770SStanislav Sedov if (enctype != NULL)
165*ae771770SStanislav Sedov *enctype = (*key)->key.keytype;
166*ae771770SStanislav Sedov return 0;
167*ae771770SStanislav Sedov }
168c19800e8SDoug Rabson }
169c19800e8SDoug Rabson
170*ae771770SStanislav Sedov krb5_set_error_message(context, EINVAL,
171*ae771770SStanislav Sedov "No valid kerberos key found for %s", name);
172*ae771770SStanislav Sedov return EINVAL; /* XXX */
173c19800e8SDoug Rabson }
174c19800e8SDoug Rabson
175