2 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
37 name_type_ok(krb5_context context
,
38 krb5_kdc_configuration
*config
,
39 krb5_const_principal principal
)
41 int nt
= krb5_principal_get_type(context
, principal
);
43 if (!krb5_principal_is_krbtgt(context
, principal
))
45 if (nt
== KRB5_NT_SRV_INST
|| nt
== KRB5_NT_UNKNOWN
)
47 if (config
->strict_nametypes
== 0)
52 struct timeval _kdc_now
;
54 static krb5_error_code
55 synthesize_hdb_close(krb5_context context
, struct HDB
*db
)
63 * Synthesize an HDB entry suitable for PKINIT and only PKINIT.
65 static krb5_error_code
66 synthesize_client(krb5_context context
,
67 krb5_kdc_configuration
*config
,
68 krb5_const_principal princ
,
76 /* Hope this works! */
77 null_db
.hdb_destroy
= synthesize_hdb_close
;
78 null_db
.hdb_close
= synthesize_hdb_close
;
82 ret
= (e
= calloc(1, sizeof(*e
))) ? 0 : krb5_enomem(context
);
84 e
->entry
.flags
.client
= 1;
85 e
->entry
.flags
.immutable
= 1;
86 e
->entry
.flags
.virtual = 1;
87 e
->entry
.flags
.synthetic
= 1;
88 e
->entry
.flags
.do_not_store
= 1;
90 e
->entry
.keys
.len
= 0;
91 e
->entry
.keys
.val
= NULL
;
92 e
->entry
.created_by
.time
= time(NULL
);
93 e
->entry
.modified_by
= NULL
;
94 e
->entry
.valid_start
= NULL
;
95 e
->entry
.valid_end
= NULL
;
96 e
->entry
.pw_end
= NULL
;
97 e
->entry
.etypes
= NULL
;
98 e
->entry
.generation
= NULL
;
99 e
->entry
.extensions
= NULL
;
102 ret
= (e
->entry
.max_renew
= calloc(1, sizeof(*e
->entry
.max_renew
))) ?
103 0 : krb5_enomem(context
);
105 ret
= (e
->entry
.max_life
= calloc(1, sizeof(*e
->entry
.max_life
))) ?
106 0 : krb5_enomem(context
);
108 ret
= krb5_copy_principal(context
, princ
, &e
->entry
.principal
);
110 ret
= krb5_copy_principal(context
, princ
, &e
->entry
.created_by
.principal
);
113 * We can't check OCSP in the TGS path, so we can't let tickets for
114 * synthetic principals live very long.
116 *(e
->entry
.max_renew
) = config
->synthetic_clients_max_renew
;
117 *(e
->entry
.max_life
) = config
->synthetic_clients_max_life
;
120 hdb_free_entry(context
, e
);
126 _kdc_db_fetch(krb5_context context
,
127 krb5_kdc_configuration
*config
,
128 krb5_const_principal principal
,
130 krb5uint32
*kvno_ptr
,
134 hdb_entry_ex
*ent
= NULL
;
135 krb5_error_code ret
= HDB_ERR_NOENTRY
;
138 krb5_principal enterprise_principal
= NULL
;
139 krb5_const_principal princ
;
143 if (!name_type_ok(context
, config
, principal
))
144 return HDB_ERR_NOENTRY
;
146 flags
|= HDB_F_DECRYPT
;
147 if (kvno_ptr
!= NULL
&& *kvno_ptr
!= 0) {
149 flags
|= HDB_F_KVNO_SPECIFIED
;
151 flags
|= HDB_F_ALL_KVNOS
;
154 ent
= calloc(1, sizeof (*ent
));
156 return krb5_enomem(context
);
158 if (principal
->name
.name_type
== KRB5_NT_ENTERPRISE_PRINCIPAL
) {
159 if (principal
->name
.name_string
.len
!= 1) {
160 ret
= KRB5_PARSE_MALFORMED
;
161 krb5_set_error_message(context
, ret
,
162 "malformed request: "
163 "enterprise name with %d name components",
164 principal
->name
.name_string
.len
);
167 ret
= krb5_parse_name(context
, principal
->name
.name_string
.val
[0],
168 &enterprise_principal
);
173 for (i
= 0; i
< config
->num_db
; i
++) {
174 HDB
*curdb
= config
->db
[i
];
179 ret
= curdb
->hdb_open(context
, curdb
, O_RDONLY
, 0);
181 const char *msg
= krb5_get_error_message(context
, ret
);
182 kdc_log(context
, config
, 0, "Failed to open database: %s", msg
);
183 krb5_free_error_message(context
, msg
);
188 if (!(curdb
->hdb_capability_flags
& HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL
) && enterprise_principal
)
189 princ
= enterprise_principal
;
191 ret
= hdb_fetch_kvno(context
, curdb
, princ
, flags
, 0, 0, kvno
, ent
);
192 curdb
->hdb_close(context
, curdb
);
194 if (ret
== HDB_ERR_NOENTRY
)
195 continue; /* Check the other databases */
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.
208 case HDB_ERR_WRONG_REALM
:
211 * the ent->entry.principal just contains hints for the client
212 * to retry. This is important for enterprise principal routing
219 case HDB_ERR_NOENTRY
:
222 if ((flags
& HDB_F_GET_CLIENT
) && (flags
& HDB_F_SYNTHETIC_OK
) &&
223 config
->synthetic_clients
) {
224 ret
= synthesize_client(context
, config
, principal
, db
, h
);
226 krb5_set_error_message(context
, ret
, "could not synthesize "
227 "HDB client principal entry");
228 ret
= HDB_ERR_NOENTRY
;
229 krb5_prepend_error_message(context
, ret
, "no such entry found in hdb");
232 krb5_set_error_message(context
, ret
, "no such entry found in hdb");
243 krb5_free_principal(context
, enterprise_principal
);
249 _kdc_free_ent(krb5_context context
, hdb_entry_ex
*ent
)
251 hdb_free_entry (context
, ent
);
256 * Use the order list of preferred encryption types and sort the
257 * available keys and return the most preferred key.
261 _kdc_get_preferred_key(krb5_context context
,
262 krb5_kdc_configuration
*config
,
265 krb5_enctype
*enctype
,
271 if (config
->use_strongest_server_key
) {
272 const krb5_enctype
*p
= krb5_kerberos_enctypes(context
);
274 for (i
= 0; p
[i
] != (krb5_enctype
)ETYPE_NULL
; i
++) {
275 if (krb5_enctype_valid(context
, p
[i
]) != 0 &&
276 !_kdc_is_weak_exception(h
->entry
.principal
, p
[i
]))
278 ret
= hdb_enctype2key(context
, &h
->entry
, NULL
, p
[i
], key
);
288 for (i
= 0; i
< h
->entry
.keys
.len
; i
++) {
289 if (krb5_enctype_valid(context
, h
->entry
.keys
.val
[i
].key
.keytype
) != 0 &&
290 !_kdc_is_weak_exception(h
->entry
.principal
, h
->entry
.keys
.val
[i
].key
.keytype
))
292 ret
= hdb_enctype2key(context
, &h
->entry
, NULL
,
293 h
->entry
.keys
.val
[i
].key
.keytype
, key
);
297 *enctype
= (*key
)->key
.keytype
;
302 krb5_set_error_message(context
, EINVAL
,
303 "No valid kerberos key found for %s", name
);
304 return EINVAL
; /* XXX */