Line data Source code
1 : /*
2 : * Copyright (c) 1999-2001, 2003, PADL Software Pty Ltd.
3 : * Copyright (c) 2004-2009, Andrew Bartlett <abartlet@samba.org>.
4 : * Copyright (c) 2004, Stefan Metzmacher <metze@samba.org>
5 : * All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : *
11 : * 1. Redistributions of source code must retain the above copyright
12 : * notice, this list of conditions and the following disclaimer.
13 : *
14 : * 2. Redistributions in binary form must reproduce the above copyright
15 : * notice, this list of conditions and the following disclaimer in the
16 : * documentation and/or other materials provided with the distribution.
17 : *
18 : * 3. Neither the name of PADL Software nor the names of its contributors
19 : * may be used to endorse or promote products derived from this software
20 : * without specific prior written permission.
21 : *
22 : * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
23 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 : * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
26 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 : * SUCH DAMAGE.
33 : */
34 :
35 : #include "includes.h"
36 : #include "kdc/kdc-glue.h"
37 : #include "kdc/db-glue.h"
38 : #include "kdc/pac-glue.h"
39 : #include "auth/auth_sam.h"
40 : #include "auth/common_auth.h"
41 : #include "auth/authn_policy.h"
42 : #include <ldb.h>
43 : #include "sdb.h"
44 : #include "sdb_hdb.h"
45 : #include "dsdb/samdb/samdb.h"
46 : #include "param/param.h"
47 : #include "../lib/tsocket/tsocket.h"
48 : #include "librpc/gen_ndr/ndr_winbind_c.h"
49 : #include "lib/messaging/irpc.h"
50 : #include "hdb.h"
51 : #include <kdc-audit.h>
52 : #include <kdc-plugin.h>
53 :
54 : #undef DBGC_CLASS
55 : #define DBGC_CLASS DBGC_KERBEROS
56 :
57 313941 : static krb5_error_code hdb_samba4_open(krb5_context context, HDB *db, int flags, mode_t mode)
58 : {
59 313941 : if (db->hdb_master_key_set) {
60 0 : krb5_error_code ret = HDB_ERR_NOENTRY;
61 0 : krb5_warnx(context, "hdb_samba4_open: use of a master key incompatible with LDB\n");
62 0 : krb5_set_error_message(context, ret, "hdb_samba4_open: use of a master key incompatible with LDB\n");
63 0 : return ret;
64 : }
65 :
66 303799 : return 0;
67 : }
68 :
69 313941 : static krb5_error_code hdb_samba4_close(krb5_context context, HDB *db)
70 : {
71 313941 : return 0;
72 : }
73 :
74 0 : static krb5_error_code hdb_samba4_lock(krb5_context context, HDB *db, int operation)
75 : {
76 0 : return 0;
77 : }
78 :
79 0 : static krb5_error_code hdb_samba4_unlock(krb5_context context, HDB *db)
80 : {
81 0 : return 0;
82 : }
83 :
84 0 : static krb5_error_code hdb_samba4_rename(krb5_context context, HDB *db, const char *new_name)
85 : {
86 0 : return HDB_ERR_DB_INUSE;
87 : }
88 :
89 0 : static krb5_error_code hdb_samba4_store(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
90 : {
91 0 : return HDB_ERR_DB_INUSE;
92 : }
93 :
94 : /*
95 : * If we ever want kadmin to work fast, we might try and reopen the
96 : * ldb with LDB_NOSYNC
97 : */
98 0 : static krb5_error_code hdb_samba4_set_sync(krb5_context context, struct HDB *db, int set_sync)
99 : {
100 0 : return 0;
101 : }
102 :
103 313571 : static void hdb_samba4_free_entry_context(krb5_context context, struct HDB *db, hdb_entry *entry)
104 : {
105 : /*
106 : * This function is now called for every HDB entry, not just those with
107 : * 'context' set, so we have to check that the context is not NULL.
108 : */
109 313571 : if (entry->context != NULL) {
110 10142 : struct samba_kdc_entry *skdc_entry =
111 307111 : talloc_get_type_abort(entry->context,
112 : struct samba_kdc_entry);
113 :
114 : /* this function is called only from hdb_free_entry().
115 : * Make sure we neutralize the destructor or we will
116 : * get a double free later when hdb_free_entry() will
117 : * try to call free_hdb_entry() */
118 307111 : entry->context = NULL;
119 307111 : skdc_entry->kdc_entry = NULL;
120 307111 : TALLOC_FREE(skdc_entry);
121 : }
122 313571 : }
123 :
124 0 : static krb5_error_code hdb_samba4_fetch_fast_cookie(krb5_context context,
125 : struct samba_kdc_db_context *kdc_db_ctx,
126 : hdb_entry *entry)
127 : {
128 0 : DBG_ERR("Looked up HDB entry for unsupported FX-COOKIE.\n");
129 0 : return HDB_ERR_NOENTRY;
130 : }
131 :
132 314031 : static krb5_error_code hdb_samba4_fetch_kvno(krb5_context context, HDB *db,
133 : krb5_const_principal principal,
134 : unsigned flags,
135 : krb5_kvno kvno,
136 : hdb_entry *entry)
137 : {
138 10142 : struct samba_kdc_db_context *kdc_db_ctx;
139 314031 : struct sdb_entry sentry = {};
140 10142 : krb5_error_code code, ret;
141 10142 : uint32_t sflags;
142 :
143 314031 : kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
144 : struct samba_kdc_db_context);
145 :
146 314031 : if (flags & HDB_F_GET_FAST_COOKIE) {
147 0 : return hdb_samba4_fetch_fast_cookie(context,
148 : kdc_db_ctx,
149 : entry);
150 : }
151 :
152 314031 : sflags = (flags & SDB_F_HDB_MASK);
153 :
154 314031 : ret = samba_kdc_fetch(context,
155 : kdc_db_ctx,
156 : principal,
157 : sflags,
158 : kvno,
159 : &sentry);
160 314031 : switch (ret) {
161 297429 : case 0:
162 297429 : code = 0;
163 297429 : break;
164 1690 : case SDB_ERR_WRONG_REALM:
165 : /*
166 : * If SDB_ERR_WRONG_REALM is returned we need to process the
167 : * sdb_entry to fill the principal in the HDB entry.
168 : */
169 1690 : code = HDB_ERR_WRONG_REALM;
170 1690 : break;
171 1750 : case SDB_ERR_NOENTRY:
172 1750 : return HDB_ERR_NOENTRY;
173 3020 : case SDB_ERR_NOT_FOUND_HERE:
174 3020 : return HDB_ERR_NOT_FOUND_HERE;
175 0 : default:
176 0 : return ret;
177 : }
178 :
179 309261 : ret = sdb_entry_to_hdb_entry(context, &sentry, entry);
180 309261 : sdb_entry_free(&sentry);
181 :
182 309261 : if (code == 0) {
183 307571 : code = ret;
184 : }
185 :
186 299119 : return code;
187 : }
188 :
189 68 : static krb5_error_code hdb_samba4_kpasswd_fetch_kvno(krb5_context context, HDB *db,
190 : krb5_const_principal _principal,
191 : unsigned flags,
192 : krb5_kvno _kvno,
193 : hdb_entry *entry)
194 : {
195 68 : struct samba_kdc_db_context *kdc_db_ctx = NULL;
196 0 : krb5_error_code ret;
197 68 : krb5_principal kpasswd_principal = NULL;
198 :
199 68 : kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
200 : struct samba_kdc_db_context);
201 :
202 68 : ret = smb_krb5_make_principal(context, &kpasswd_principal,
203 : lpcfg_realm(kdc_db_ctx->lp_ctx),
204 : "kadmin", "changepw",
205 : NULL);
206 68 : if (ret) {
207 0 : return ret;
208 : }
209 68 : smb_krb5_principal_set_type(context, kpasswd_principal, KRB5_NT_SRV_INST);
210 :
211 : /*
212 : * For the kpasswd service, always ensure we get the latest kvno. This
213 : * also means we (correctly) refuse RODC-issued tickets.
214 : */
215 68 : flags &= ~HDB_F_KVNO_SPECIFIED;
216 :
217 : /* Don't bother looking up a client or krbtgt. */
218 68 : flags &= ~(HDB_F_GET_CLIENT|HDB_F_GET_KRBTGT);
219 :
220 68 : ret = hdb_samba4_fetch_kvno(context, db,
221 : kpasswd_principal,
222 : flags,
223 : 0,
224 : entry);
225 :
226 68 : krb5_free_principal(context, kpasswd_principal);
227 68 : return ret;
228 : }
229 :
230 0 : static krb5_error_code hdb_samba4_firstkey(krb5_context context, HDB *db, unsigned flags,
231 : hdb_entry *entry)
232 : {
233 0 : struct samba_kdc_db_context *kdc_db_ctx;
234 0 : struct sdb_entry sentry = {};
235 0 : krb5_error_code ret;
236 :
237 0 : kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
238 : struct samba_kdc_db_context);
239 :
240 0 : ret = samba_kdc_firstkey(context, kdc_db_ctx, &sentry);
241 0 : switch (ret) {
242 0 : case 0:
243 0 : break;
244 0 : case SDB_ERR_WRONG_REALM:
245 0 : return HDB_ERR_WRONG_REALM;
246 0 : case SDB_ERR_NOENTRY:
247 0 : return HDB_ERR_NOENTRY;
248 0 : case SDB_ERR_NOT_FOUND_HERE:
249 0 : return HDB_ERR_NOT_FOUND_HERE;
250 0 : default:
251 0 : return ret;
252 : }
253 :
254 0 : ret = sdb_entry_to_hdb_entry(context, &sentry, entry);
255 0 : sdb_entry_free(&sentry);
256 0 : return ret;
257 : }
258 :
259 0 : static krb5_error_code hdb_samba4_nextkey(krb5_context context, HDB *db, unsigned flags,
260 : hdb_entry *entry)
261 : {
262 0 : struct samba_kdc_db_context *kdc_db_ctx;
263 0 : struct sdb_entry sentry = {};
264 0 : krb5_error_code ret;
265 :
266 0 : kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
267 : struct samba_kdc_db_context);
268 :
269 0 : ret = samba_kdc_nextkey(context, kdc_db_ctx, &sentry);
270 0 : switch (ret) {
271 0 : case 0:
272 0 : break;
273 0 : case SDB_ERR_WRONG_REALM:
274 0 : return HDB_ERR_WRONG_REALM;
275 0 : case SDB_ERR_NOENTRY:
276 0 : return HDB_ERR_NOENTRY;
277 0 : case SDB_ERR_NOT_FOUND_HERE:
278 0 : return HDB_ERR_NOT_FOUND_HERE;
279 0 : default:
280 0 : return ret;
281 : }
282 :
283 0 : ret = sdb_entry_to_hdb_entry(context, &sentry, entry);
284 0 : sdb_entry_free(&sentry);
285 0 : return ret;
286 : }
287 :
288 0 : static krb5_error_code hdb_samba4_nextkey_panic(krb5_context context, HDB *db,
289 : unsigned flags,
290 : hdb_entry *entry)
291 : {
292 0 : DBG_ERR("Attempt to iterate kpasswd keytab => PANIC\n");
293 0 : smb_panic("hdb_samba4_nextkey_panic: Attempt to iterate kpasswd keytab");
294 : }
295 :
296 68 : static krb5_error_code hdb_samba4_destroy(krb5_context context, HDB *db)
297 : {
298 68 : talloc_free(db);
299 68 : return 0;
300 : }
301 :
302 : static krb5_error_code
303 146 : hdb_samba4_check_constrained_delegation(krb5_context context, HDB *db,
304 : hdb_entry *entry,
305 : krb5_const_principal target_principal)
306 : {
307 146 : struct samba_kdc_db_context *kdc_db_ctx = NULL;
308 146 : struct samba_kdc_entry *skdc_entry = NULL;
309 :
310 146 : kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
311 : struct samba_kdc_db_context);
312 146 : skdc_entry = talloc_get_type_abort(entry->context,
313 : struct samba_kdc_entry);
314 :
315 146 : return samba_kdc_check_s4u2proxy(context, kdc_db_ctx,
316 : skdc_entry,
317 : target_principal);
318 : }
319 :
320 : static krb5_error_code
321 136 : hdb_samba4_check_rbcd(krb5_context context, HDB *db,
322 : const hdb_entry *client_krbtgt,
323 : const hdb_entry *client,
324 : const hdb_entry *device_krbtgt,
325 : const hdb_entry *device,
326 : krb5_const_principal server_principal,
327 : krb5_const_pac header_pac,
328 : krb5_const_pac device_pac,
329 : const hdb_entry *proxy)
330 : {
331 136 : struct samba_kdc_db_context *kdc_db_ctx = NULL;
332 136 : struct samba_kdc_entry *client_skdc_entry = NULL;
333 136 : const struct samba_kdc_entry *client_krbtgt_skdc_entry = NULL;
334 136 : struct samba_kdc_entry *proxy_skdc_entry = NULL;
335 136 : const struct auth_user_info_dc *client_info = NULL;
336 136 : const struct auth_user_info_dc *device_info = NULL;
337 136 : struct samba_kdc_entry_pac client_pac_entry = {};
338 136 : struct auth_claims auth_claims = {};
339 136 : TALLOC_CTX *mem_ctx = NULL;
340 0 : krb5_error_code code;
341 :
342 136 : kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
343 : struct samba_kdc_db_context);
344 136 : client_skdc_entry = talloc_get_type_abort(client->context,
345 : struct samba_kdc_entry);
346 136 : client_krbtgt_skdc_entry = talloc_get_type_abort(client_krbtgt->context,
347 : struct samba_kdc_entry);
348 136 : proxy_skdc_entry = talloc_get_type_abort(proxy->context,
349 : struct samba_kdc_entry);
350 :
351 136 : mem_ctx = talloc_new(kdc_db_ctx);
352 136 : if (mem_ctx == NULL) {
353 0 : return ENOMEM;
354 : }
355 :
356 136 : client_pac_entry = samba_kdc_entry_pac(header_pac,
357 : client_skdc_entry,
358 136 : samba_kdc_entry_is_trust(client_krbtgt_skdc_entry));
359 :
360 136 : code = samba_kdc_get_user_info_dc(mem_ctx,
361 : context,
362 : kdc_db_ctx->samdb,
363 : client_pac_entry,
364 : &client_info,
365 : NULL /* resource_groups_out */);
366 136 : if (code != 0) {
367 0 : goto out;
368 : }
369 :
370 136 : code = samba_kdc_get_claims_data(mem_ctx,
371 : context,
372 : kdc_db_ctx->samdb,
373 : client_pac_entry,
374 : &auth_claims.user_claims);
375 136 : if (code) {
376 0 : goto out;
377 : }
378 :
379 136 : if (device != NULL) {
380 90 : struct samba_kdc_entry *device_skdc_entry = NULL;
381 90 : const struct samba_kdc_entry *device_krbtgt_skdc_entry = NULL;
382 90 : struct samba_kdc_entry_pac device_pac_entry = {};
383 :
384 90 : device_skdc_entry = talloc_get_type_abort(device->context,
385 : struct samba_kdc_entry);
386 :
387 90 : if (device_krbtgt != NULL) {
388 90 : device_krbtgt_skdc_entry = talloc_get_type_abort(device_krbtgt->context,
389 : struct samba_kdc_entry);
390 : }
391 :
392 90 : device_pac_entry = samba_kdc_entry_pac(device_pac,
393 : device_skdc_entry,
394 90 : samba_kdc_entry_is_trust(device_krbtgt_skdc_entry));
395 :
396 90 : code = samba_kdc_get_user_info_dc(mem_ctx,
397 : context,
398 : kdc_db_ctx->samdb,
399 : device_pac_entry,
400 : &device_info,
401 : NULL /* resource_groups_out */);
402 90 : if (code) {
403 0 : goto out;
404 : }
405 :
406 90 : code = samba_kdc_get_claims_data(mem_ctx,
407 : context,
408 : kdc_db_ctx->samdb,
409 : device_pac_entry,
410 : &auth_claims.device_claims);
411 90 : if (code) {
412 0 : goto out;
413 : }
414 : }
415 :
416 136 : code = samba_kdc_check_s4u2proxy_rbcd(context,
417 : kdc_db_ctx,
418 136 : client->principal,
419 : server_principal,
420 : client_info,
421 : device_info,
422 : auth_claims,
423 : proxy_skdc_entry);
424 136 : out:
425 136 : talloc_free(mem_ctx);
426 136 : return code;
427 : }
428 :
429 : static krb5_error_code
430 47 : hdb_samba4_check_pkinit_ms_upn_match(krb5_context context, HDB *db,
431 : hdb_entry *entry,
432 : krb5_const_principal certificate_principal)
433 : {
434 0 : struct samba_kdc_db_context *kdc_db_ctx;
435 0 : struct samba_kdc_entry *skdc_entry;
436 0 : krb5_error_code ret;
437 :
438 47 : kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
439 : struct samba_kdc_db_context);
440 47 : skdc_entry = talloc_get_type_abort(entry->context,
441 : struct samba_kdc_entry);
442 :
443 47 : ret = samba_kdc_check_pkinit_ms_upn_match(context, kdc_db_ctx,
444 : skdc_entry,
445 : certificate_principal);
446 47 : switch (ret) {
447 45 : case 0:
448 45 : break;
449 0 : case SDB_ERR_WRONG_REALM:
450 0 : ret = HDB_ERR_WRONG_REALM;
451 0 : break;
452 0 : case SDB_ERR_NOENTRY:
453 0 : ret = HDB_ERR_NOENTRY;
454 0 : break;
455 0 : case SDB_ERR_NOT_FOUND_HERE:
456 0 : ret = HDB_ERR_NOT_FOUND_HERE;
457 0 : break;
458 2 : default:
459 2 : break;
460 : }
461 :
462 47 : return ret;
463 : }
464 :
465 : static krb5_error_code
466 950 : hdb_samba4_check_client_matches_target_service(krb5_context context, HDB *db,
467 : hdb_entry *client_entry,
468 : hdb_entry *server_target_entry)
469 : {
470 0 : struct samba_kdc_entry *skdc_client_entry
471 950 : = talloc_get_type_abort(client_entry->context,
472 : struct samba_kdc_entry);
473 0 : struct samba_kdc_entry *skdc_server_target_entry
474 950 : = talloc_get_type_abort(server_target_entry->context,
475 : struct samba_kdc_entry);
476 :
477 950 : return samba_kdc_check_client_matches_target_service(context,
478 : skdc_client_entry,
479 : skdc_server_target_entry);
480 : }
481 :
482 8 : static void reset_bad_password_netlogon(TALLOC_CTX *mem_ctx,
483 : struct samba_kdc_db_context *kdc_db_ctx,
484 : struct netr_SendToSamBase *send_to_sam)
485 : {
486 0 : struct dcerpc_binding_handle *irpc_handle;
487 0 : struct winbind_SendToSam req;
488 8 : struct tevent_req *subreq = NULL;
489 :
490 8 : irpc_handle = irpc_binding_handle_by_name(mem_ctx, kdc_db_ctx->msg_ctx,
491 : "winbind_server",
492 : &ndr_table_winbind);
493 :
494 8 : if (irpc_handle == NULL) {
495 0 : DBG_ERR("No winbind_server running!\n");
496 0 : return;
497 : }
498 :
499 8 : req.in.message = *send_to_sam;
500 :
501 : /*
502 : * This seem to rely on the current IRPC implementation,
503 : * which delivers the message in the _send function.
504 : *
505 : * TODO: we need a ONE_WAY IRPC handle and register
506 : * a callback and wait for it to be triggered!
507 : */
508 8 : subreq = dcerpc_winbind_SendToSam_r_send(mem_ctx, kdc_db_ctx->ev_ctx,
509 : irpc_handle, &req);
510 :
511 : /* we aren't interested in a reply */
512 8 : TALLOC_FREE(subreq);
513 : }
514 :
515 : #define SAMBA_HDB_AUTHN_AUDIT_INFO_OBJ "samba:authn_audit_info_obj"
516 : #define SAMBA_HDB_CLIENT_AUDIT_INFO "samba:client_audit_info"
517 : #define SAMBA_HDB_SERVER_AUDIT_INFO "samba:server_audit_info"
518 :
519 : #define SAMBA_HDB_NT_STATUS_OBJ "samba:nt_status_obj"
520 : #define SAMBA_HDB_NT_STATUS "samba:nt_status"
521 :
522 : struct hdb_audit_info_obj {
523 : struct authn_audit_info *audit_info;
524 : };
525 :
526 567 : static void hdb_audit_info_obj_dealloc(void *ptr)
527 : {
528 567 : struct hdb_audit_info_obj *audit_info_obj = ptr;
529 :
530 567 : if (audit_info_obj == NULL) {
531 0 : return;
532 : }
533 :
534 567 : TALLOC_FREE(audit_info_obj->audit_info);
535 : }
536 :
537 : /*
538 : * Set talloc-allocated auditing information of the KDC request. On success,
539 : * ‘audit_info’ is invalidated and may no longer be used by the caller.
540 : */
541 567 : static krb5_error_code hdb_samba4_set_steal_audit_info(astgs_request_t r,
542 : const char *key,
543 : struct authn_audit_info *audit_info)
544 : {
545 567 : struct hdb_audit_info_obj *audit_info_obj = NULL;
546 :
547 567 : audit_info_obj = kdc_object_alloc(sizeof (*audit_info_obj),
548 : SAMBA_HDB_AUTHN_AUDIT_INFO_OBJ,
549 : hdb_audit_info_obj_dealloc);
550 567 : if (audit_info_obj == NULL) {
551 0 : return ENOMEM;
552 : }
553 :
554 : /*
555 : * Steal a handle to the audit information onto the NULL context —
556 : * Heimdal will be responsible for the deallocation of the object.
557 : */
558 567 : audit_info_obj->audit_info = talloc_steal(NULL, audit_info);
559 :
560 567 : heim_audit_setkv_object((heim_svc_req_desc)r, key, audit_info_obj);
561 567 : heim_release(audit_info_obj);
562 :
563 567 : return 0;
564 : }
565 :
566 : /*
567 : * Set talloc-allocated client auditing information of the KDC request. On
568 : * success, ‘client_audit_info’ is invalidated and may no longer be used by the
569 : * caller.
570 : */
571 397 : krb5_error_code hdb_samba4_set_steal_client_audit_info(astgs_request_t r,
572 : struct authn_audit_info *client_audit_info)
573 : {
574 397 : return hdb_samba4_set_steal_audit_info(r,
575 : SAMBA_HDB_CLIENT_AUDIT_INFO,
576 : client_audit_info);
577 : }
578 :
579 31354 : static const struct authn_audit_info *hdb_samba4_get_client_audit_info(hdb_request_t r)
580 : {
581 31354 : const struct hdb_audit_info_obj *audit_info_obj = NULL;
582 :
583 32524 : audit_info_obj = heim_audit_getkv((heim_svc_req_desc)r, SAMBA_HDB_CLIENT_AUDIT_INFO);
584 31354 : if (audit_info_obj == NULL) {
585 29790 : return NULL;
586 : }
587 :
588 394 : return audit_info_obj->audit_info;
589 : }
590 :
591 : /*
592 : * Set talloc-allocated server auditing information of the KDC request. On
593 : * success, ‘server_audit_info’ is invalidated and may no longer be used by the
594 : * caller.
595 : */
596 170 : krb5_error_code hdb_samba4_set_steal_server_audit_info(astgs_request_t r,
597 : struct authn_audit_info *server_audit_info)
598 : {
599 170 : return hdb_samba4_set_steal_audit_info(r,
600 : SAMBA_HDB_SERVER_AUDIT_INFO,
601 : server_audit_info);
602 : }
603 :
604 83883 : static const struct authn_audit_info *hdb_samba4_get_server_audit_info(hdb_request_t r)
605 : {
606 83883 : const struct hdb_audit_info_obj *audit_info_obj = NULL;
607 :
608 86711 : audit_info_obj = heim_audit_getkv((heim_svc_req_desc)r, SAMBA_HDB_SERVER_AUDIT_INFO);
609 83883 : if (audit_info_obj == NULL) {
610 80885 : return NULL;
611 : }
612 :
613 170 : return audit_info_obj->audit_info;
614 : }
615 :
616 : struct hdb_ntstatus_obj {
617 : NTSTATUS status;
618 : krb5_error_code current_error;
619 : };
620 :
621 : /*
622 : * Add an NTSTATUS code to a Kerberos request. ‘error’ is the error value we
623 : * want to return to the client. When it comes time to generating the error
624 : * request, we shall compare this error value to whatever error we are about to
625 : * return; if the two match, we shall replace the ‘e-data’ field in the reply
626 : * with the NTSTATUS code.
627 : */
628 112 : krb5_error_code hdb_samba4_set_ntstatus(astgs_request_t r,
629 : const NTSTATUS status,
630 : const krb5_error_code error)
631 : {
632 112 : struct hdb_ntstatus_obj *status_obj = NULL;
633 :
634 112 : status_obj = kdc_object_alloc(sizeof (*status_obj),
635 : SAMBA_HDB_NT_STATUS_OBJ,
636 : NULL);
637 112 : if (status_obj == NULL) {
638 0 : return ENOMEM;
639 : }
640 :
641 112 : *status_obj = (struct hdb_ntstatus_obj) {
642 : .status = status,
643 : .current_error = error,
644 : };
645 :
646 112 : heim_audit_setkv_object((heim_svc_req_desc)r, SAMBA_HDB_NT_STATUS, status_obj);
647 112 : heim_release(status_obj);
648 :
649 112 : return 0;
650 : }
651 :
652 115 : static krb5_error_code hdb_samba4_make_nt_status_edata(const NTSTATUS status,
653 : const uint32_t flags,
654 : krb5_data *edata_out)
655 : {
656 115 : const uint32_t status_code = NT_STATUS_V(status);
657 115 : const uint32_t zero = 0;
658 0 : KERB_ERROR_DATA error_data;
659 0 : krb5_data e_data;
660 :
661 0 : krb5_error_code ret;
662 0 : size_t size;
663 :
664 : /* The raw KERB-ERR-TYPE-EXTENDED structure. */
665 0 : uint8_t data[12];
666 :
667 115 : PUSH_LE_U32(data, 0, status_code);
668 115 : PUSH_LE_U32(data, 4, zero);
669 115 : PUSH_LE_U32(data, 8, flags);
670 :
671 115 : e_data = (krb5_data) {
672 : .data = &data,
673 : .length = sizeof(data),
674 : };
675 :
676 115 : error_data = (KERB_ERROR_DATA) {
677 : .data_type = kERB_ERR_TYPE_EXTENDED,
678 : .data_value = &e_data,
679 : };
680 :
681 115 : ASN1_MALLOC_ENCODE(KERB_ERROR_DATA,
682 : edata_out->data, edata_out->length,
683 : &error_data,
684 : &size, ret);
685 115 : if (ret) {
686 0 : return ret;
687 : }
688 115 : if (size != edata_out->length) {
689 : /* Internal ASN.1 encoder error */
690 0 : krb5_data_free(edata_out);
691 0 : return KRB5KRB_ERR_GENERIC;
692 : }
693 :
694 115 : return 0;
695 : }
696 :
697 115 : static krb5_error_code hdb_samba4_set_edata_from_ntstatus(hdb_request_t r, const NTSTATUS status)
698 : {
699 115 : const KDC_REQ *req = kdc_request_get_req((astgs_request_t)r);
700 115 : krb5_error_code ret = 0;
701 0 : krb5_data e_data;
702 115 : uint32_t flags = 1;
703 :
704 115 : if (req->msg_type == krb_tgs_req) {
705 : /* This flag is used to indicate a TGS-REQ. */
706 63 : flags |= 2;
707 : }
708 :
709 115 : ret = hdb_samba4_make_nt_status_edata(status, flags, &e_data);
710 115 : if (ret) {
711 0 : return ret;
712 : }
713 :
714 115 : ret = kdc_request_set_e_data((astgs_request_t)r, e_data);
715 115 : if (ret) {
716 0 : krb5_data_free(&e_data);
717 : }
718 :
719 115 : return ret;
720 : }
721 :
722 86512 : static NTSTATUS hdb_samba4_get_ntstatus(hdb_request_t r)
723 : {
724 86512 : struct hdb_ntstatus_obj *status_obj = NULL;
725 :
726 86512 : status_obj = heim_audit_getkv((heim_svc_req_desc)r, SAMBA_HDB_NT_STATUS);
727 86512 : if (status_obj == NULL) {
728 86400 : return NT_STATUS_OK;
729 : }
730 :
731 112 : if (r->error_code != status_obj->current_error) {
732 : /*
733 : * The error code has changed from what we expect. Consider the
734 : * NTSTATUS to be invalidated.
735 : */
736 0 : return NT_STATUS_OK;
737 : }
738 :
739 112 : return status_obj->status;
740 : }
741 :
742 52529 : static krb5_error_code hdb_samba4_tgs_audit(const struct samba_kdc_db_context *kdc_db_ctx,
743 : const hdb_entry *entry,
744 : hdb_request_t r)
745 : {
746 52529 : TALLOC_CTX *frame = talloc_stackframe();
747 52529 : const struct authn_audit_info *server_audit_info = NULL;
748 52529 : struct tsocket_address *remote_host = NULL;
749 52529 : struct samba_kdc_entry *client_entry = NULL;
750 52529 : struct dom_sid sid_buf = {};
751 52529 : const char *account_name = NULL;
752 52529 : const char *domain_name = NULL;
753 52529 : const struct dom_sid *sid = NULL;
754 52529 : size_t sa_socklen = 0;
755 52529 : NTSTATUS auth_status = NT_STATUS_OK;
756 52529 : krb5_error_code ret = 0;
757 52529 : krb5_error_code final_ret = 0;
758 :
759 : /* Have we got a status code indicating an error? */
760 52529 : auth_status = hdb_samba4_get_ntstatus(r);
761 52529 : if (!NT_STATUS_IS_OK(auth_status)) {
762 : /*
763 : * Include this status code in the ‘e-data’ field of the reply.
764 : */
765 63 : ret = hdb_samba4_set_edata_from_ntstatus(r, auth_status);
766 63 : if (ret) {
767 0 : final_ret = ret;
768 : }
769 52466 : } else if (entry == NULL) {
770 2988 : auth_status = NT_STATUS_NO_SUCH_USER;
771 49478 : } else if (r->error_code) {
772 : /*
773 : * Don’t include a status code in the reply. Just log the
774 : * request as being unsuccessful.
775 : */
776 233 : auth_status = NT_STATUS_UNSUCCESSFUL;
777 : }
778 :
779 52529 : switch (r->addr->sa_family) {
780 52529 : case AF_INET:
781 52529 : sa_socklen = sizeof(struct sockaddr_in);
782 52529 : break;
783 : #ifdef HAVE_IPV6
784 0 : case AF_INET6:
785 0 : sa_socklen = sizeof(struct sockaddr_in6);
786 0 : break;
787 : #endif
788 : }
789 :
790 52529 : ret = tsocket_address_bsd_from_sockaddr(frame, r->addr,
791 : sa_socklen,
792 : &remote_host);
793 52529 : if (ret != 0) {
794 0 : remote_host = NULL;
795 : /* Ignore the error. */
796 : }
797 :
798 52529 : server_audit_info = hdb_samba4_get_server_audit_info(r);
799 :
800 52529 : if (entry != NULL) {
801 49541 : client_entry = talloc_get_type_abort(entry->context,
802 : struct samba_kdc_entry);
803 :
804 49541 : ret = samdb_result_dom_sid_buf(client_entry->msg, "objectSid", &sid_buf);
805 49541 : if (ret) {
806 : /* Ignore the error. */
807 : } else {
808 49541 : sid = &sid_buf;
809 : }
810 :
811 49541 : account_name = ldb_msg_find_attr_as_string(client_entry->msg, "sAMAccountName", NULL);
812 49541 : domain_name = lpcfg_sam_name(kdc_db_ctx->lp_ctx);
813 : }
814 :
815 52529 : log_authz_event(kdc_db_ctx->msg_ctx,
816 52529 : kdc_db_ctx->lp_ctx,
817 : remote_host,
818 : NULL /* local */,
819 : server_audit_info,
820 52529 : r->sname,
821 : "TGS-REQ with Ticket-Granting Ticket",
822 : domain_name,
823 : account_name,
824 : sid,
825 52529 : lpcfg_netbios_name(kdc_db_ctx->lp_ctx),
826 : krb5_kdc_get_time(),
827 : auth_status);
828 :
829 52529 : talloc_free(frame);
830 52529 : if (final_ret) {
831 0 : r->error_code = final_ret;
832 : }
833 52529 : return final_ret;
834 : }
835 :
836 104689 : static krb5_error_code hdb_samba4_audit(krb5_context context,
837 : HDB *db,
838 : hdb_entry *entry,
839 : hdb_request_t r)
840 : {
841 104689 : struct samba_kdc_db_context *kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
842 : struct samba_kdc_db_context);
843 104689 : struct ldb_dn *domain_dn = ldb_get_default_basedn(kdc_db_ctx->samdb);
844 104689 : heim_object_t auth_details_obj = NULL;
845 104689 : const char *auth_details = NULL;
846 104689 : char *etype_str = NULL;
847 104689 : heim_object_t hdb_auth_status_obj = NULL;
848 3413 : int hdb_auth_status;
849 104689 : heim_object_t pa_type_obj = NULL;
850 104689 : const char *pa_type = NULL;
851 3413 : struct auth_usersupplied_info ui;
852 104689 : size_t sa_socklen = 0;
853 104689 : const KDC_REQ *req = kdc_request_get_req((astgs_request_t)r);
854 104689 : krb5_error_code final_ret = 0;
855 3413 : NTSTATUS edata_status;
856 :
857 104689 : if (req->msg_type == krb_tgs_req) {
858 52529 : return hdb_samba4_tgs_audit(kdc_db_ctx, entry, r);
859 : }
860 :
861 52160 : if (r->error_code == KRB5KDC_ERR_PREAUTH_REQUIRED) {
862 : /* Let’s not log PREAUTH_REQUIRED errors. */
863 17592 : return 0;
864 : }
865 :
866 33983 : edata_status = hdb_samba4_get_ntstatus(r);
867 :
868 33983 : hdb_auth_status_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_AUTH_EVENT);
869 33983 : if (hdb_auth_status_obj == NULL) {
870 : /* No status code found, so just return. */
871 2180 : return 0;
872 : }
873 :
874 31803 : hdb_auth_status = heim_number_get_int(hdb_auth_status_obj);
875 :
876 31803 : pa_type_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_PA_NAME);
877 31803 : if (pa_type_obj != NULL) {
878 30739 : pa_type = heim_string_get_utf8(pa_type_obj);
879 : }
880 :
881 31803 : auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_PKINIT_CLIENT_CERT);
882 31803 : if (auth_details_obj != NULL) {
883 45 : auth_details = heim_string_get_utf8(auth_details_obj);
884 : } else {
885 31758 : auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_GSS_INITIATOR);
886 31758 : if (auth_details_obj != NULL) {
887 0 : auth_details = heim_string_get_utf8(auth_details_obj);
888 : } else {
889 31758 : heim_object_t etype_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_PA_ETYPE);
890 31758 : if (etype_obj != NULL) {
891 30497 : int etype = heim_number_get_int(etype_obj);
892 :
893 30497 : krb5_error_code ret = krb5_enctype_to_string(r->context, etype, &etype_str);
894 30497 : if (ret == 0) {
895 30497 : auth_details = etype_str;
896 : } else {
897 0 : auth_details = "unknown enctype";
898 : }
899 : }
900 : }
901 : }
902 :
903 : /*
904 : * Forcing this via the NTLM auth structure is not ideal, but
905 : * it is the most practical option right now, and ensures the
906 : * logs are consistent, even if some elements are always NULL.
907 : */
908 32973 : ui = (struct auth_usersupplied_info) {
909 : .was_mapped = true,
910 : .client = {
911 31803 : .account_name = r->cname,
912 : .domain_name = NULL,
913 : },
914 : .service_description = "Kerberos KDC",
915 : .auth_description = "Unknown Auth Description",
916 : .password_type = auth_details,
917 31803 : .logon_id = generate_random_u64(),
918 : };
919 :
920 31803 : switch (r->addr->sa_family) {
921 31803 : case AF_INET:
922 31803 : sa_socklen = sizeof(struct sockaddr_in);
923 31803 : break;
924 : #ifdef HAVE_IPV6
925 0 : case AF_INET6:
926 0 : sa_socklen = sizeof(struct sockaddr_in6);
927 0 : break;
928 : #endif
929 : }
930 :
931 31803 : switch (hdb_auth_status) {
932 31354 : default:
933 : {
934 31354 : TALLOC_CTX *frame = talloc_stackframe();
935 31354 : struct samba_kdc_entry *p = talloc_get_type_abort(entry->context,
936 : struct samba_kdc_entry);
937 1170 : struct dom_sid *sid
938 31354 : = samdb_result_dom_sid(frame, p->msg, "objectSid");
939 1170 : const char *account_name
940 31354 : = ldb_msg_find_attr_as_string(p->msg, "sAMAccountName", NULL);
941 31354 : const char *domain_name = lpcfg_sam_name(p->kdc_db_ctx->lp_ctx);
942 1170 : struct tsocket_address *remote_host;
943 31354 : const char *auth_description = NULL;
944 31354 : const struct authn_audit_info *client_audit_info = NULL;
945 31354 : const struct authn_audit_info *server_audit_info = NULL;
946 1170 : NTSTATUS status;
947 1170 : int ret;
948 31354 : bool rwdc_fallback = false;
949 :
950 31354 : ret = tsocket_address_bsd_from_sockaddr(frame, r->addr,
951 : sa_socklen,
952 : &remote_host);
953 31354 : if (ret != 0) {
954 0 : ui.remote_host = NULL;
955 : } else {
956 31354 : ui.remote_host = remote_host;
957 : }
958 :
959 31354 : ui.mapped.account_name = account_name;
960 31354 : ui.mapped.domain_name = domain_name;
961 :
962 31354 : if (pa_type != NULL) {
963 30739 : auth_description = talloc_asprintf(frame,
964 : "%s Pre-authentication",
965 : pa_type);
966 30739 : if (auth_description == NULL) {
967 0 : auth_description = pa_type;
968 : }
969 : } else {
970 615 : auth_description = "Unknown Pre-authentication";
971 : }
972 31354 : ui.auth_description = auth_description;
973 :
974 31354 : if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_AUTHORIZED) {
975 30310 : struct netr_SendToSamBase *send_to_sam = NULL;
976 :
977 : /*
978 : * TODO: We could log the AS-REQ authorization success here as
979 : * well. However before we do that, we need to pass
980 : * in the PAC here or re-calculate it.
981 : */
982 30310 : status = authsam_logon_success_accounting(kdc_db_ctx->samdb, p->msg,
983 : domain_dn, true, frame, &send_to_sam);
984 30310 : if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
985 0 : edata_status = status;
986 :
987 0 : r->error_code = final_ret = KRB5KDC_ERR_CLIENT_REVOKED;
988 0 : rwdc_fallback = kdc_db_ctx->rodc;
989 30310 : } else if (!NT_STATUS_IS_OK(status)) {
990 0 : r->error_code = final_ret = KRB5KDC_ERR_CLIENT_REVOKED;
991 0 : rwdc_fallback = kdc_db_ctx->rodc;
992 : } else {
993 30310 : if (r->error_code == KRB5KDC_ERR_NEVER_VALID) {
994 1 : edata_status = status = NT_STATUS_TIME_DIFFERENCE_AT_DC;
995 : } else {
996 30309 : status = krb5_to_nt_status(r->error_code);
997 : }
998 :
999 30310 : if (kdc_db_ctx->rodc && send_to_sam != NULL) {
1000 8 : reset_bad_password_netlogon(frame, kdc_db_ctx, send_to_sam);
1001 : }
1002 : }
1003 :
1004 : /* This is the final success */
1005 1044 : } else if (hdb_auth_status == KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY) {
1006 : /*
1007 : * This was only a pre-authentication success,
1008 : * but we didn't reach the final
1009 : * KDC_AUTH_EVENT_CLIENT_AUTHORIZED,
1010 : * so consult the error code.
1011 : */
1012 0 : if (r->error_code == 0) {
1013 0 : DBG_ERR("ERROR: VALIDATED_LONG_TERM_KEY "
1014 : "with error=0 => INTERNAL_ERROR\n");
1015 0 : status = NT_STATUS_INTERNAL_ERROR;
1016 0 : r->error_code = final_ret = KRB5KRB_ERR_GENERIC;
1017 0 : } else if (!NT_STATUS_IS_OK(p->reject_status)) {
1018 0 : status = p->reject_status;
1019 : } else {
1020 0 : status = krb5_to_nt_status(r->error_code);
1021 : }
1022 1044 : } else if (hdb_auth_status == KDC_AUTH_EVENT_PREAUTH_SUCCEEDED) {
1023 : /*
1024 : * This was only a pre-authentication success,
1025 : * but we didn't reach the final
1026 : * KDC_AUTH_EVENT_CLIENT_AUTHORIZED,
1027 : * so consult the error code.
1028 : */
1029 0 : if (r->error_code == 0) {
1030 0 : DBG_ERR("ERROR: PREAUTH_SUCCEEDED "
1031 : "with error=0 => INTERNAL_ERROR\n");
1032 0 : status = NT_STATUS_INTERNAL_ERROR;
1033 0 : r->error_code = final_ret = KRB5KRB_ERR_GENERIC;
1034 0 : } else if (!NT_STATUS_IS_OK(p->reject_status)) {
1035 0 : status = p->reject_status;
1036 : } else {
1037 0 : status = krb5_to_nt_status(r->error_code);
1038 : }
1039 1044 : } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_FOUND) {
1040 : /*
1041 : * We found the client principal,
1042 : * but we didn’t reach the final
1043 : * KDC_AUTH_EVENT_CLIENT_AUTHORIZED,
1044 : * so consult the error code.
1045 : */
1046 635 : if (r->error_code == 0) {
1047 0 : DBG_ERR("ERROR: CLIENT_FOUND "
1048 : "with error=0 => INTERNAL_ERROR\n");
1049 0 : status = NT_STATUS_INTERNAL_ERROR;
1050 0 : r->error_code = final_ret = KRB5KRB_ERR_GENERIC;
1051 635 : } else if (!NT_STATUS_IS_OK(p->reject_status)) {
1052 45 : status = p->reject_status;
1053 : } else {
1054 590 : status = krb5_to_nt_status(r->error_code);
1055 : }
1056 409 : } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_TIME_SKEW) {
1057 10 : status = NT_STATUS_TIME_DIFFERENCE_AT_DC;
1058 399 : } else if (hdb_auth_status == KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY) {
1059 267 : status = authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn);
1060 267 : if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
1061 2 : edata_status = status;
1062 :
1063 2 : r->error_code = final_ret = KRB5KDC_ERR_CLIENT_REVOKED;
1064 : } else {
1065 265 : status = NT_STATUS_WRONG_PASSWORD;
1066 : }
1067 267 : rwdc_fallback = kdc_db_ctx->rodc;
1068 132 : } else if (hdb_auth_status == KDC_AUTH_EVENT_HISTORIC_LONG_TERM_KEY) {
1069 : /*
1070 : * The pre-authentication succeeds with a password
1071 : * from the password history, so we don't
1072 : * update the badPwdCount, but still return
1073 : * PREAUTH_FAILED and need to forward to
1074 : * a RWDC in order to produce an authoritative
1075 : * response for the client.
1076 : */
1077 130 : status = NT_STATUS_WRONG_PASSWORD;
1078 130 : rwdc_fallback = kdc_db_ctx->rodc;
1079 2 : } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_LOCKED_OUT) {
1080 0 : edata_status = status = NT_STATUS_ACCOUNT_LOCKED_OUT;
1081 0 : rwdc_fallback = kdc_db_ctx->rodc;
1082 2 : } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED) {
1083 2 : if (pa_type != NULL && strncmp(pa_type, "PK-INIT", strlen("PK-INIT")) == 0) {
1084 2 : status = NT_STATUS_PKINIT_NAME_MISMATCH;
1085 : } else {
1086 0 : status = NT_STATUS_ACCOUNT_RESTRICTION;
1087 : }
1088 2 : rwdc_fallback = kdc_db_ctx->rodc;
1089 0 : } else if (hdb_auth_status == KDC_AUTH_EVENT_PREAUTH_FAILED) {
1090 0 : if (pa_type != NULL && strncmp(pa_type, "PK-INIT", strlen("PK-INIT")) == 0) {
1091 0 : status = NT_STATUS_PKINIT_FAILURE;
1092 : } else {
1093 0 : status = NT_STATUS_GENERIC_COMMAND_FAILED;
1094 : }
1095 0 : rwdc_fallback = kdc_db_ctx->rodc;
1096 : } else {
1097 0 : DBG_ERR("Unhandled hdb_auth_status=%d => INTERNAL_ERROR\n",
1098 : hdb_auth_status);
1099 0 : status = NT_STATUS_INTERNAL_ERROR;
1100 0 : r->error_code = final_ret = KRB5KRB_ERR_GENERIC;
1101 : }
1102 :
1103 31354 : if (!NT_STATUS_IS_OK(edata_status)) {
1104 0 : krb5_error_code code;
1105 :
1106 52 : code = hdb_samba4_set_edata_from_ntstatus(r, edata_status);
1107 52 : if (code) {
1108 0 : r->error_code = final_ret = code;
1109 : }
1110 : }
1111 :
1112 31354 : if (rwdc_fallback) {
1113 : /*
1114 : * Forward the request to an RWDC in order
1115 : * to give an authoritative answer to the client.
1116 : */
1117 20 : auth_description = talloc_asprintf(frame,
1118 : "%s,Forward-To-RWDC",
1119 : ui.auth_description);
1120 20 : if (auth_description != NULL) {
1121 20 : ui.auth_description = auth_description;
1122 : }
1123 20 : final_ret = HDB_ERR_NOT_FOUND_HERE;
1124 : }
1125 :
1126 31354 : client_audit_info = hdb_samba4_get_client_audit_info(r);
1127 31354 : server_audit_info = hdb_samba4_get_server_audit_info(r);
1128 :
1129 31354 : log_authentication_event(kdc_db_ctx->msg_ctx,
1130 : kdc_db_ctx->lp_ctx,
1131 31354 : &r->tv_start,
1132 : &ui,
1133 : status,
1134 : domain_name,
1135 : account_name,
1136 : sid,
1137 : client_audit_info,
1138 : server_audit_info);
1139 31354 : if (final_ret == KRB5KRB_ERR_GENERIC && socket_wrapper_enabled()) {
1140 : /*
1141 : * If we're running under make test
1142 : * just panic
1143 : */
1144 0 : DBG_ERR("Unexpected situation => PANIC\n");
1145 0 : smb_panic("hdb_samba4_audit: Unexpected situation");
1146 : }
1147 31354 : TALLOC_FREE(frame);
1148 31354 : break;
1149 : }
1150 449 : case KDC_AUTH_EVENT_CLIENT_UNKNOWN:
1151 : {
1152 0 : struct tsocket_address *remote_host;
1153 0 : int ret;
1154 449 : TALLOC_CTX *frame = talloc_stackframe();
1155 449 : ret = tsocket_address_bsd_from_sockaddr(frame, r->addr,
1156 : sa_socklen,
1157 : &remote_host);
1158 449 : if (ret != 0) {
1159 0 : ui.remote_host = NULL;
1160 : } else {
1161 449 : ui.remote_host = remote_host;
1162 : }
1163 :
1164 449 : if (pa_type == NULL) {
1165 449 : pa_type = "AS-REQ";
1166 : }
1167 :
1168 449 : ui.auth_description = pa_type;
1169 :
1170 : /* Note this is not forwarded to an RWDC */
1171 :
1172 449 : log_authentication_event(kdc_db_ctx->msg_ctx,
1173 : kdc_db_ctx->lp_ctx,
1174 449 : &r->tv_start,
1175 : &ui,
1176 449 : NT_STATUS_NO_SUCH_USER,
1177 : NULL, NULL,
1178 : NULL,
1179 : NULL /* client_audit_info */,
1180 : NULL /* server_audit_info */);
1181 449 : TALLOC_FREE(frame);
1182 449 : break;
1183 : }
1184 : }
1185 :
1186 31803 : free(etype_str);
1187 :
1188 31803 : return final_ret;
1189 : }
1190 :
1191 : /* This interface is to be called by the KDC and libnet_keytab_dump,
1192 : * which is expecting Samba calling conventions.
1193 : * It is also called by a wrapper (hdb_samba4_create) from the
1194 : * kpasswdd -> krb5 -> keytab_hdb -> hdb code */
1195 :
1196 161 : NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx,
1197 : krb5_context context, struct HDB **db)
1198 : {
1199 161 : struct samba_kdc_db_context *kdc_db_ctx = NULL;
1200 8 : NTSTATUS nt_status;
1201 :
1202 161 : if (hdb_interface_version != HDB_INTERFACE_VERSION) {
1203 0 : krb5_set_error_message(context, EINVAL, "Heimdal HDB interface version mismatch between build-time and run-time libraries!");
1204 0 : return NT_STATUS_ERROR_DS_INCOMPATIBLE_VERSION;
1205 : }
1206 :
1207 161 : *db = talloc_zero(base_ctx, HDB);
1208 161 : if (!*db) {
1209 0 : krb5_set_error_message(context, ENOMEM, "talloc_zero: out of memory");
1210 0 : return NT_STATUS_NO_MEMORY;
1211 : }
1212 :
1213 161 : (*db)->hdb_master_key_set = 0;
1214 161 : (*db)->hdb_db = NULL;
1215 161 : (*db)->hdb_capability_flags = HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL;
1216 :
1217 161 : nt_status = samba_kdc_setup_db_ctx(*db, base_ctx, &kdc_db_ctx);
1218 161 : if (!NT_STATUS_IS_OK(nt_status)) {
1219 0 : talloc_free(*db);
1220 0 : return nt_status;
1221 : }
1222 161 : (*db)->hdb_db = kdc_db_ctx;
1223 :
1224 161 : (*db)->hdb_dbc = NULL;
1225 161 : (*db)->hdb_open = hdb_samba4_open;
1226 161 : (*db)->hdb_close = hdb_samba4_close;
1227 161 : (*db)->hdb_free_entry_context = hdb_samba4_free_entry_context;
1228 161 : (*db)->hdb_fetch_kvno = hdb_samba4_fetch_kvno;
1229 161 : (*db)->hdb_store = hdb_samba4_store;
1230 161 : (*db)->hdb_firstkey = hdb_samba4_firstkey;
1231 161 : (*db)->hdb_nextkey = hdb_samba4_nextkey;
1232 161 : (*db)->hdb_lock = hdb_samba4_lock;
1233 161 : (*db)->hdb_unlock = hdb_samba4_unlock;
1234 161 : (*db)->hdb_set_sync = hdb_samba4_set_sync;
1235 161 : (*db)->hdb_rename = hdb_samba4_rename;
1236 : /* we don't implement these, as we are not a lockable database */
1237 161 : (*db)->hdb__get = NULL;
1238 161 : (*db)->hdb__put = NULL;
1239 : /* kadmin should not be used for deletes - use other tools instead */
1240 161 : (*db)->hdb__del = NULL;
1241 161 : (*db)->hdb_destroy = hdb_samba4_destroy;
1242 :
1243 161 : (*db)->hdb_audit = hdb_samba4_audit;
1244 161 : (*db)->hdb_check_constrained_delegation = hdb_samba4_check_constrained_delegation;
1245 161 : (*db)->hdb_check_rbcd = hdb_samba4_check_rbcd;
1246 161 : (*db)->hdb_check_pkinit_ms_upn_match = hdb_samba4_check_pkinit_ms_upn_match;
1247 161 : (*db)->hdb_check_client_matches_target_service = hdb_samba4_check_client_matches_target_service;
1248 :
1249 161 : return NT_STATUS_OK;
1250 : }
1251 :
1252 68 : NTSTATUS hdb_samba4_kpasswd_create_kdc(struct samba_kdc_base_context *base_ctx,
1253 : krb5_context context, struct HDB **db)
1254 : {
1255 0 : NTSTATUS nt_status;
1256 :
1257 68 : nt_status = hdb_samba4_create_kdc(base_ctx, context, db);
1258 68 : if (!NT_STATUS_IS_OK(nt_status)) {
1259 0 : return nt_status;
1260 : }
1261 :
1262 68 : (*db)->hdb_fetch_kvno = hdb_samba4_kpasswd_fetch_kvno;
1263 68 : (*db)->hdb_firstkey = hdb_samba4_nextkey_panic;
1264 68 : (*db)->hdb_nextkey = hdb_samba4_nextkey_panic;
1265 :
1266 68 : return NT_STATUS_OK;
1267 : }
|