xref: /freebsd/crypto/heimdal/kdc/misc.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
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