4 Copyright (c) 2010, Simo Sorce <idra@samba.org>
5 Copyright (c) 2014-2015 Guenther Deschner <gd@samba.org>
6 Copyright (c) 2014-2016 Andreas Schneider <asn@samba.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #define TEVENT_DEPRECATED 1
25 #include "param/param.h"
26 #include "dsdb/samdb/samdb.h"
27 #include "system/kerberos.h"
29 #include <kadm5/kadm_err.h>
31 #include "kdc/sdb_kdb.h"
32 #include "auth/kerberos/kerberos.h"
33 #include "kdc/samba_kdc.h"
34 #include "kdc/pac-glue.h"
35 #include "kdc/db-glue.h"
36 #include "auth/auth.h"
37 #include "kdc/kpasswd_glue.h"
38 #include "auth/auth_sam.h"
40 #include "mit_samba.h"
42 void mit_samba_context_free(struct mit_samba_context
*ctx
)
44 /* free heimdal's krb5_context */
46 krb5_free_context(ctx
->context
);
49 /* then free everything else */
53 int mit_samba_context_init(struct mit_samba_context
**_ctx
)
56 struct mit_samba_context
*ctx
;
57 const char *s4_conf_file
;
59 struct samba_kdc_base_context base_ctx
;
61 ctx
= talloc_zero(NULL
, struct mit_samba_context
);
67 base_ctx
.ev_ctx
= tevent_context_init(ctx
);
68 if (!base_ctx
.ev_ctx
) {
72 tevent_loop_allow_nesting(base_ctx
.ev_ctx
);
73 base_ctx
.lp_ctx
= loadparm_init_global(false);
74 if (!base_ctx
.lp_ctx
) {
79 setup_logging("mitkdc", DEBUG_STDOUT
);
81 /* init s4 configuration */
82 s4_conf_file
= lpcfg_configfile(base_ctx
.lp_ctx
);
84 lpcfg_load(base_ctx
.lp_ctx
, s4_conf_file
);
86 lpcfg_load_default(base_ctx
.lp_ctx
);
89 status
= samba_kdc_setup_db_ctx(ctx
, &base_ctx
, &ctx
->db_ctx
);
90 if (!NT_STATUS_IS_OK(status
)) {
95 /* init heimdal's krb_context and log facilities */
96 ret
= smb_krb5_init_context_basic(ctx
,
107 mit_samba_context_free(ctx
);
114 static krb5_error_code
ks_is_tgs_principal(struct mit_samba_context
*ctx
,
115 krb5_const_principal principal
)
120 p
= smb_krb5_principal_get_comp_string(ctx
, ctx
->context
, principal
, 0);
122 eq
= krb5_princ_size(ctx
->context
, principal
) == 2 &&
123 (strcmp(p
, KRB5_TGS_NAME
) == 0);
130 int mit_samba_generate_salt(krb5_data
*salt
)
137 salt
->data
= malloc(salt
->length
);
138 if (salt
->data
== NULL
) {
142 generate_random_buffer((uint8_t *)salt
->data
, salt
->length
);
147 int mit_samba_generate_random_password(krb5_data
*pwd
)
157 tmp_ctx
= talloc_named(NULL
,
159 "mit_samba_create_principal_password context");
160 if (tmp_ctx
== NULL
) {
164 password
= generate_random_password(tmp_ctx
, pwd
->length
, pwd
->length
);
165 if (password
== NULL
) {
166 talloc_free(tmp_ctx
);
170 pwd
->data
= strdup(password
);
171 talloc_free(tmp_ctx
);
172 if (pwd
->data
== NULL
) {
179 int mit_samba_get_principal(struct mit_samba_context
*ctx
,
180 krb5_const_principal principal
,
182 krb5_db_entry
**_kentry
)
184 struct sdb_entry_ex sentry
= {
187 krb5_db_entry
*kentry
;
191 kentry
= malloc(sizeof(krb5_db_entry
));
192 if (kentry
== NULL
) {
196 if (kflags
& KRB5_KDB_FLAG_CANONICALIZE
) {
197 sflags
|= SDB_F_CANON
;
199 if (kflags
& (KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY
|
200 KRB5_KDB_FLAG_INCLUDE_PAC
)) {
202 * KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY is equal to
205 * We use ANY to also allow AS_REQ for service principal names
206 * This is supported by Windows.
208 sflags
|= SDB_F_GET_ANY
|SDB_F_FOR_AS_REQ
;
209 } else if (ks_is_tgs_principal(ctx
, principal
)) {
210 sflags
|= SDB_F_GET_KRBTGT
;
212 sflags
|= SDB_F_GET_SERVER
|SDB_F_FOR_TGS_REQ
;
215 /* always set this or the created_by data will not be populated by samba's
216 * backend and we will fail to parse the entry later */
217 sflags
|= SDB_F_ADMIN_DATA
;
219 ret
= samba_kdc_fetch(ctx
->context
, ctx
->db_ctx
,
220 principal
, sflags
, 0, &sentry
);
224 case SDB_ERR_NOENTRY
:
225 ret
= KRB5_KDB_NOENTRY
;
227 case SDB_ERR_WRONG_REALM
:
229 * If we have a wrong realm e.g. if we try get a cross forest
230 * ticket, we return a ticket with the correct realm. The KDC
231 * will detect this an return the appropriate return code.
235 case SDB_ERR_NOT_FOUND_HERE
:
236 /* FIXME: RODC support */
241 ret
= sdb_entry_ex_to_kdb_entry_ex(ctx
->context
, &sentry
, kentry
);
243 sdb_free_entry(&sentry
);
254 int mit_samba_get_firstkey(struct mit_samba_context
*ctx
,
255 krb5_db_entry
**_kentry
)
257 struct sdb_entry_ex sentry
= {
260 krb5_db_entry
*kentry
;
263 kentry
= malloc(sizeof(krb5_db_entry
));
264 if (kentry
== NULL
) {
268 ret
= samba_kdc_firstkey(ctx
->context
, ctx
->db_ctx
, &sentry
);
272 case SDB_ERR_NOENTRY
:
274 return KRB5_KDB_NOENTRY
;
275 case SDB_ERR_NOT_FOUND_HERE
:
276 /* FIXME: RODC support */
282 ret
= sdb_entry_ex_to_kdb_entry_ex(ctx
->context
, &sentry
, kentry
);
284 sdb_free_entry(&sentry
);
294 int mit_samba_get_nextkey(struct mit_samba_context
*ctx
,
295 krb5_db_entry
**_kentry
)
297 struct sdb_entry_ex sentry
= {
300 krb5_db_entry
*kentry
;
303 kentry
= malloc(sizeof(krb5_db_entry
));
304 if (kentry
== NULL
) {
308 ret
= samba_kdc_nextkey(ctx
->context
, ctx
->db_ctx
, &sentry
);
312 case SDB_ERR_NOENTRY
:
314 return KRB5_KDB_NOENTRY
;
315 case SDB_ERR_NOT_FOUND_HERE
:
316 /* FIXME: RODC support */
322 ret
= sdb_entry_ex_to_kdb_entry_ex(ctx
->context
, &sentry
, kentry
);
324 sdb_free_entry(&sentry
);
334 int mit_samba_get_pac_data(struct mit_samba_context
*ctx
,
335 krb5_db_entry
*client
,
341 struct samba_kdc_entry
*skdc_entry
;
343 skdc_entry
= talloc_get_type_abort(client
->e_data
,
344 struct samba_kdc_entry
);
346 tmp_ctx
= talloc_named(ctx
, 0, "mit_samba_get_pac_data context");
351 nt_status
= samba_kdc_get_pac_blob(tmp_ctx
, skdc_entry
, &pac_blob
);
352 if (!NT_STATUS_IS_OK(nt_status
)) {
353 talloc_free(tmp_ctx
);
357 data
->data
= (uint8_t *)malloc(pac_blob
->length
);
359 talloc_free(tmp_ctx
);
362 memcpy(data
->data
, pac_blob
->data
, pac_blob
->length
);
363 data
->length
= pac_blob
->length
;
365 talloc_free(tmp_ctx
);
369 int mit_samba_update_pac_data(struct mit_samba_context
*ctx
,
370 krb5_db_entry
*client
,
372 DATA_BLOB
*logon_data
)
375 DATA_BLOB
*logon_blob
;
376 krb5_error_code code
;
380 struct samba_kdc_entry
*skdc_entry
= NULL
;
383 skdc_entry
= talloc_get_type_abort(client
->e_data
,
384 struct samba_kdc_entry
);
387 /* The user account may be set not to want the PAC */
388 if (client
&& !samba_princ_needs_pac(skdc_entry
)) {
392 tmp_ctx
= talloc_named(ctx
, 0, "mit_samba_update_pac_data context");
397 logon_blob
= talloc_zero(tmp_ctx
, DATA_BLOB
);
403 code
= krb5_pac_parse(ctx
->context
,
404 pac_data
->data
, pac_data
->length
, &pac
);
410 /* TODO: An implementation-specific decision will need to be
411 * made as to when to check the KDC pac signature, and how to
412 * untrust untrusted RODCs */
413 nt_status
= samba_kdc_update_pac_blob(tmp_ctx
, ctx
->context
,
414 pac
, logon_blob
, NULL
, NULL
);
415 if (!NT_STATUS_IS_OK(nt_status
)) {
416 DEBUG(0, ("Building PAC failed: %s\n",
417 nt_errstr(nt_status
)));
422 logon_data
->data
= (uint8_t *)malloc(logon_blob
->length
);
423 if (!logon_data
->data
) {
427 memcpy(logon_data
->data
, logon_blob
->data
, logon_blob
->length
);
428 logon_data
->length
= logon_blob
->length
;
433 if (pac
) krb5_pac_free(ctx
->context
, pac
);
434 talloc_free(tmp_ctx
);
438 /* provide header, function is exported but there are no public headers */
440 krb5_error_code
encode_krb5_padata_sequence(krb5_pa_data
*const *rep
, krb5_data
**code
);
442 /* this function allocates 'data' using malloc.
443 * The caller is responsible for freeing it */
444 static void samba_kdc_build_edata_reply(NTSTATUS nt_status
, DATA_BLOB
*e_data
)
446 krb5_error_code ret
= 0;
447 krb5_pa_data pa
, *ppa
= NULL
;
456 pa
.magic
= KV5M_PA_DATA
;
457 pa
.pa_type
= KRB5_PADATA_PW_SALT
;
459 pa
.contents
= malloc(pa
.length
);
464 SIVAL(pa
.contents
, 0, NT_STATUS_V(nt_status
));
465 SIVAL(pa
.contents
, 4, 0);
466 SIVAL(pa
.contents
, 8, 1);
470 ret
= encode_krb5_padata_sequence(&ppa
, &d
);
476 e_data
->data
= (uint8_t *)d
->data
;
477 e_data
->length
= d
->length
;
479 /* free d, not d->data - gd */
485 int mit_samba_check_client_access(struct mit_samba_context
*ctx
,
486 krb5_db_entry
*client
,
487 const char *client_name
,
488 krb5_db_entry
*server
,
489 const char *server_name
,
490 const char *netbios_name
,
491 bool password_change
,
494 struct samba_kdc_entry
*skdc_entry
;
497 skdc_entry
= talloc_get_type(client
->e_data
, struct samba_kdc_entry
);
499 nt_status
= samba_kdc_check_client_access(skdc_entry
,
504 if (!NT_STATUS_IS_OK(nt_status
)) {
505 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NO_MEMORY
)) {
509 samba_kdc_build_edata_reply(nt_status
, e_data
);
511 return samba_kdc_map_policy_err(nt_status
);
517 int mit_samba_check_s4u2proxy(struct mit_samba_context
*ctx
,
518 krb5_db_entry
*kentry
,
519 const char *target_name
,
520 bool is_nt_enterprise_name
)
524 * This is disabled because mit_samba_update_pac_data() does not handle
525 * S4U_DELEGATION_INFO
528 return KRB5KDC_ERR_BADOPTION
;
530 krb5_principal target_principal
;
534 if (is_nt_enterprise_name
) {
535 flags
= KRB5_PRINCIPAL_PARSE_ENTERPRISE
;
538 ret
= krb5_parse_name_flags(ctx
->context
, target_name
,
539 flags
, &target_principal
);
544 ret
= samba_kdc_check_s4u2proxy(ctx
->context
,
549 krb5_free_principal(ctx
->context
, target_principal
);
555 static krb5_error_code
mit_samba_change_pwd_error(krb5_context context
,
557 enum samPwdChangeReason reject_reason
,
558 struct samr_DomInfo1
*dominfo
)
560 krb5_error_code code
= KADM5_PASS_Q_GENERIC
;
562 if (NT_STATUS_EQUAL(result
, NT_STATUS_NO_SUCH_USER
)) {
563 code
= KADM5_BAD_PRINCIPAL
;
564 krb5_set_error_message(context
,
566 "No such user when changing password");
568 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
569 code
= KADM5_PASS_Q_GENERIC
;
570 krb5_set_error_message(context
,
572 "Not permitted to change password");
574 if (NT_STATUS_EQUAL(result
, NT_STATUS_PASSWORD_RESTRICTION
) &&
576 switch (reject_reason
) {
577 case SAM_PWD_CHANGE_PASSWORD_TOO_SHORT
:
578 code
= KADM5_PASS_Q_TOOSHORT
;
579 krb5_set_error_message(context
,
581 "Password too short, password "
582 "must be at least %d characters "
584 dominfo
->min_password_length
);
586 case SAM_PWD_CHANGE_NOT_COMPLEX
:
587 code
= KADM5_PASS_Q_DICT
;
588 krb5_set_error_message(context
,
590 "Password does not meet "
591 "complexity requirements");
593 case SAM_PWD_CHANGE_PWD_IN_HISTORY
:
594 code
= KADM5_PASS_TOOSOON
;
595 krb5_set_error_message(context
,
597 "Password is already in password "
598 "history. New password must not "
599 "match any of your %d previous "
601 dominfo
->password_history_length
);
604 code
= KADM5_PASS_Q_GENERIC
;
605 krb5_set_error_message(context
,
607 "Password change rejected, "
608 "password changes may not be "
609 "permitted on this account, or "
610 "the minimum password age may "
611 "not have elapsed.");
619 int mit_samba_kpasswd_change_password(struct mit_samba_context
*ctx
,
621 krb5_db_entry
*db_entry
)
624 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
627 enum samPwdChangeReason reject_reason
;
628 struct samr_DomInfo1
*dominfo
;
629 const char *error_string
= NULL
;
630 struct auth_user_info_dc
*user_info_dc
;
631 struct samba_kdc_entry
*p
;
632 krb5_error_code code
= 0;
634 #ifdef DEBUG_PASSWORD
635 DEBUG(1,("mit_samba_kpasswd_change_password called with: %s\n", pwd
));
638 tmp_ctx
= talloc_named(ctx
, 0, "mit_samba_kpasswd_change_password");
639 if (tmp_ctx
== NULL
) {
643 p
= (struct samba_kdc_entry
*)db_entry
->e_data
;
645 status
= authsam_make_user_info_dc(tmp_ctx
,
647 lpcfg_netbios_name(ctx
->db_ctx
->lp_ctx
),
648 lpcfg_sam_name(ctx
->db_ctx
->lp_ctx
),
649 lpcfg_sam_dnsname(ctx
->db_ctx
->lp_ctx
),
655 if (!NT_STATUS_IS_OK(status
)) {
656 DEBUG(1,("authsam_make_user_info_dc failed: %s\n",
658 talloc_free(tmp_ctx
);
662 status
= auth_generate_session_info(tmp_ctx
,
666 0, /* session_info_flags */
669 if (!NT_STATUS_IS_OK(status
)) {
670 DEBUG(1,("auth_generate_session_info failed: %s\n",
672 talloc_free(tmp_ctx
);
676 /* password is expected as UTF16 */
678 if (!convert_string_talloc(tmp_ctx
, CH_UTF8
, CH_UTF16
,
680 &password
.data
, &password
.length
)) {
681 DEBUG(1,("convert_string_talloc failed\n"));
682 talloc_free(tmp_ctx
);
686 status
= samdb_kpasswd_change_password(tmp_ctx
,
696 if (!NT_STATUS_IS_OK(status
)) {
697 DEBUG(1,("samdb_kpasswd_change_password failed: %s\n",
699 code
= KADM5_PASS_Q_GENERIC
;
700 krb5_set_error_message(ctx
->context
, code
, "%s", error_string
);
704 if (!NT_STATUS_IS_OK(result
)) {
705 code
= mit_samba_change_pwd_error(ctx
->context
,
712 talloc_free(tmp_ctx
);
717 void mit_samba_zero_bad_password_count(krb5_db_entry
*db_entry
)
719 struct samba_kdc_entry
*p
;
720 struct ldb_dn
*domain_dn
;
722 p
= (struct samba_kdc_entry
*)db_entry
->e_data
;
724 domain_dn
= ldb_get_default_basedn(p
->kdc_db_ctx
->samdb
);
726 authsam_logon_success_accounting(p
->kdc_db_ctx
->samdb
,
733 void mit_samba_update_bad_password_count(krb5_db_entry
*db_entry
)
735 struct samba_kdc_entry
*p
;
737 p
= (struct samba_kdc_entry
*)db_entry
->e_data
;
739 authsam_update_bad_pwd_count(p
->kdc_db_ctx
->samdb
,
741 ldb_get_default_basedn(p
->kdc_db_ctx
->samdb
));