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"
30 #include <kadm5/kadm_err.h>
32 #include "kdc/sdb_kdb.h"
33 #include "auth/kerberos/kerberos.h"
34 #include "auth/kerberos/pac_utils.h"
35 #include "kdc/samba_kdc.h"
36 #include "kdc/pac-glue.h"
37 #include "kdc/db-glue.h"
38 #include "auth/auth.h"
39 #include "kdc/kpasswd_glue.h"
40 #include "auth/auth_sam.h"
42 #include "mit_samba.h"
45 #define DBGC_CLASS DBGC_KERBEROS
47 void mit_samba_context_free(struct mit_samba_context
*ctx
)
49 /* free heimdal's krb5_context */
51 krb5_free_context(ctx
->context
);
54 /* then free everything else */
59 * Implemant a callback to log to the MIT KDC log facility
61 * http://web.mit.edu/kerberos/krb5-devel/doc/plugindev/general.html#logging-from-kdc-and-kadmind-plugin-modules
63 static void mit_samba_debug(void *private_ptr
, int msg_level
, const char *msg
)
71 com_err("", is_error
, "%s", msg
);
74 int mit_samba_context_init(struct mit_samba_context
**_ctx
)
77 struct mit_samba_context
*ctx
;
78 const char *s4_conf_file
;
80 struct samba_kdc_base_context base_ctx
;
82 ctx
= talloc_zero(NULL
, struct mit_samba_context
);
88 base_ctx
.ev_ctx
= tevent_context_init(ctx
);
89 if (!base_ctx
.ev_ctx
) {
93 tevent_loop_allow_nesting(base_ctx
.ev_ctx
);
94 base_ctx
.lp_ctx
= loadparm_init_global(false);
95 if (!base_ctx
.lp_ctx
) {
100 debug_set_callback(NULL
, mit_samba_debug
);
102 /* init s4 configuration */
103 s4_conf_file
= lpcfg_configfile(base_ctx
.lp_ctx
);
104 if (s4_conf_file
!= NULL
) {
105 char *p
= talloc_strdup(ctx
, s4_conf_file
);
110 lpcfg_load(base_ctx
.lp_ctx
, p
);
113 lpcfg_load_default(base_ctx
.lp_ctx
);
116 status
= samba_kdc_setup_db_ctx(ctx
, &base_ctx
, &ctx
->db_ctx
);
117 if (!NT_STATUS_IS_OK(status
)) {
122 /* init heimdal's krb_context and log facilities */
123 ret
= smb_krb5_init_context_basic(ctx
,
134 mit_samba_context_free(ctx
);
141 static krb5_error_code
ks_is_tgs_principal(struct mit_samba_context
*ctx
,
142 krb5_const_principal principal
)
147 p
= smb_krb5_principal_get_comp_string(ctx
, ctx
->context
, principal
, 0);
149 eq
= krb5_princ_size(ctx
->context
, principal
) == 2 &&
150 (strcmp(p
, KRB5_TGS_NAME
) == 0);
157 int mit_samba_generate_salt(krb5_data
*salt
)
164 salt
->data
= malloc(salt
->length
);
165 if (salt
->data
== NULL
) {
169 generate_random_buffer((uint8_t *)salt
->data
, salt
->length
);
174 int mit_samba_generate_random_password(krb5_data
*pwd
)
184 tmp_ctx
= talloc_named(NULL
,
186 "mit_samba_create_principal_password context");
187 if (tmp_ctx
== NULL
) {
191 password
= generate_random_password(tmp_ctx
, pwd
->length
, pwd
->length
);
192 if (password
== NULL
) {
193 talloc_free(tmp_ctx
);
197 pwd
->data
= strdup(password
);
198 talloc_free(tmp_ctx
);
199 if (pwd
->data
== NULL
) {
206 int mit_samba_get_principal(struct mit_samba_context
*ctx
,
207 krb5_const_principal principal
,
209 krb5_db_entry
**_kentry
)
211 struct sdb_entry sentry
= {};
212 krb5_db_entry
*kentry
;
215 krb5_principal referral_principal
= NULL
;
217 kentry
= calloc(1, sizeof(krb5_db_entry
));
218 if (kentry
== NULL
) {
222 #if KRB5_KDB_API_VERSION >= 10
224 * The MIT KDC code that wants the canonical name in all lookups, and
225 * takes care to canonicalize only when appropriate.
227 sflags
|= SDB_F_FORCE_CANON
;
230 #if KRB5_KDB_DAL_MAJOR_VERSION >= 9
231 if (kflags
& KRB5_KDB_FLAG_REFERRAL_OK
) {
232 sflags
|= SDB_F_CANON
;
235 if (kflags
& KRB5_KDB_FLAG_CLIENT
) {
236 sflags
|= SDB_F_GET_CLIENT
;
238 if (!(kflags
& KRB5_KDB_FLAG_REFERRAL_OK
)) {
239 sflags
|= SDB_F_FOR_AS_REQ
;
242 int equal
= smb_krb5_principal_is_tgs(ctx
->context
, principal
);
248 sflags
|= SDB_F_GET_KRBTGT
;
250 sflags
|= SDB_F_GET_SERVER
;
252 if (!(kflags
& KRB5_KDB_FLAG_REFERRAL_OK
)) {
253 sflags
|= SDB_F_FOR_TGS_REQ
;
257 #else /* KRB5_KDB_DAL_MAJOR_VERSION < 9 */
258 if (kflags
& KRB5_KDB_FLAG_CANONICALIZE
) {
259 sflags
|= SDB_F_CANON
;
261 if (kflags
& (KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY
|
262 KRB5_KDB_FLAG_INCLUDE_PAC
)) {
264 * KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY is equal to
267 * We use ANY to also allow AS_REQ for service principal names
268 * This is supported by Windows.
270 sflags
|= SDB_F_GET_ANY
|SDB_F_FOR_AS_REQ
;
272 int equal
= smb_krb5_principal_is_tgs(ctx
->context
, principal
);
278 sflags
|= SDB_F_GET_KRBTGT
;
280 sflags
|= SDB_F_GET_SERVER
|SDB_F_FOR_TGS_REQ
;
283 #endif /* KRB5_KDB_DAL_MAJOR_VERSION */
285 /* always set this or the created_by data will not be populated by samba's
286 * backend and we will fail to parse the entry later */
287 sflags
|= SDB_F_ADMIN_DATA
;
290 fetch_referral_principal
:
291 ret
= samba_kdc_fetch(ctx
->context
, ctx
->db_ctx
,
292 principal
, sflags
, 0, &sentry
);
296 case SDB_ERR_NOENTRY
:
297 ret
= KRB5_KDB_NOENTRY
;
299 case SDB_ERR_WRONG_REALM
: {
300 char *dest_realm
= NULL
;
301 const char *our_realm
= lpcfg_realm(ctx
->db_ctx
->lp_ctx
);
303 if (sflags
& SDB_F_FOR_AS_REQ
) {
305 * If this is a request for a TGT, we are done. The KDC
306 * will return the correct error to the client.
312 if (referral_principal
!= NULL
) {
313 sdb_entry_free(&sentry
);
314 ret
= KRB5_KDB_NOENTRY
;
319 * We get a TGS request
321 * cifs/dc7.SAMBA2008R2.EXAMPLE.COM@ADDOM.SAMBA.EXAMPLE.COM
323 * to our DC for the realm
325 * ADDOM.SAMBA.EXAMPLE.COM
327 * We look up if we have and entry in the database and get an
328 * entry with the pricipal:
330 * cifs/dc7.SAMBA2008R2.EXAMPLE.COM@SAMBA2008R2.EXAMPLE.COM
332 * and the error: SDB_ERR_WRONG_REALM.
334 * In the case of a TGS-REQ we need to return a referral ticket
335 * fo the next trust hop to the client. This ticket will have
336 * the following principal:
338 * krbtgt/SAMBA2008R2.EXAMPLE.COM@ADDOM.SAMBA.EXAMPLE.COM
340 * We just redo the lookup in the database with the referral
341 * principal and return success.
343 dest_realm
= smb_krb5_principal_get_realm(
344 ctx
, ctx
->context
, sentry
.principal
);
345 sdb_entry_free(&sentry
);
346 if (dest_realm
== NULL
) {
347 ret
= KRB5_KDB_NOENTRY
;
351 ret
= smb_krb5_make_principal(ctx
->context
,
357 TALLOC_FREE(dest_realm
);
362 principal
= referral_principal
;
363 goto fetch_referral_principal
;
365 case SDB_ERR_NOT_FOUND_HERE
:
366 /* FIXME: RODC support */
371 ret
= sdb_entry_to_krb5_db_entry(ctx
->context
, &sentry
, kentry
);
373 sdb_entry_free(&sentry
);
376 krb5_free_principal(ctx
->context
, referral_principal
);
377 referral_principal
= NULL
;
387 int mit_samba_get_firstkey(struct mit_samba_context
*ctx
,
388 krb5_db_entry
**_kentry
)
390 struct sdb_entry sentry
= {};
391 krb5_db_entry
*kentry
;
394 kentry
= malloc(sizeof(krb5_db_entry
));
395 if (kentry
== NULL
) {
399 ret
= samba_kdc_firstkey(ctx
->context
, ctx
->db_ctx
, &sentry
);
403 case SDB_ERR_NOENTRY
:
405 return KRB5_KDB_NOENTRY
;
406 case SDB_ERR_NOT_FOUND_HERE
:
407 /* FIXME: RODC support */
413 ret
= sdb_entry_to_krb5_db_entry(ctx
->context
, &sentry
, kentry
);
415 sdb_entry_free(&sentry
);
425 int mit_samba_get_nextkey(struct mit_samba_context
*ctx
,
426 krb5_db_entry
**_kentry
)
428 struct sdb_entry sentry
= {};
429 krb5_db_entry
*kentry
;
432 kentry
= malloc(sizeof(krb5_db_entry
));
433 if (kentry
== NULL
) {
437 ret
= samba_kdc_nextkey(ctx
->context
, ctx
->db_ctx
, &sentry
);
441 case SDB_ERR_NOENTRY
:
443 return KRB5_KDB_NOENTRY
;
444 case SDB_ERR_NOT_FOUND_HERE
:
445 /* FIXME: RODC support */
451 ret
= sdb_entry_to_krb5_db_entry(ctx
->context
, &sentry
, kentry
);
453 sdb_entry_free(&sentry
);
463 int mit_samba_get_pac(struct mit_samba_context
*smb_ctx
,
464 krb5_context context
,
466 krb5_db_entry
*client
,
467 krb5_db_entry
*server
,
468 krb5_keyblock
*replaced_reply_key
,
472 DATA_BLOB
*logon_info_blob
= NULL
;
473 DATA_BLOB
*upn_dns_info_blob
= NULL
;
474 DATA_BLOB
*cred_ndr
= NULL
;
475 DATA_BLOB
**cred_ndr_ptr
= NULL
;
476 DATA_BLOB cred_blob
= data_blob_null
;
477 DATA_BLOB
*pcred_blob
= NULL
;
478 DATA_BLOB
*pac_attrs_blob
= NULL
;
479 DATA_BLOB
*requester_sid_blob
= NULL
;
481 krb5_error_code code
;
482 struct samba_kdc_entry
*skdc_entry
;
484 enum samba_asserted_identity asserted_identity
=
485 (flags
& KRB5_KDB_FLAG_PROTOCOL_TRANSITION
) ?
486 SAMBA_ASSERTED_IDENTITY_SERVICE
:
487 SAMBA_ASSERTED_IDENTITY_AUTHENTICATION_AUTHORITY
;
489 skdc_entry
= talloc_get_type_abort(client
->e_data
,
490 struct samba_kdc_entry
);
492 tmp_ctx
= talloc_named(smb_ctx
,
494 "mit_samba_get_pac_data_blobs context");
495 if (tmp_ctx
== NULL
) {
499 /* Check if we have a PREAUTH key */
500 if (replaced_reply_key
!= NULL
) {
501 cred_ndr_ptr
= &cred_ndr
;
504 is_krbtgt
= ks_is_tgs_principal(smb_ctx
, server
->princ
);
506 nt_status
= samba_kdc_get_pac_blobs(tmp_ctx
,
512 is_krbtgt
? &pac_attrs_blob
: NULL
,
513 PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY
,
514 is_krbtgt
? &requester_sid_blob
: NULL
);
515 if (!NT_STATUS_IS_OK(nt_status
)) {
516 talloc_free(tmp_ctx
);
517 if (NT_STATUS_EQUAL(nt_status
,
518 NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
524 if (replaced_reply_key
!= NULL
&& cred_ndr
!= NULL
) {
525 code
= samba_kdc_encrypt_pac_credentials(context
,
531 talloc_free(tmp_ctx
);
534 pcred_blob
= &cred_blob
;
537 code
= samba_make_krb5_pac(context
,
546 talloc_free(tmp_ctx
);
550 #if KRB5_KDB_DAL_MAJOR_VERSION < 9
551 krb5_error_code
mit_samba_reget_pac(struct mit_samba_context
*ctx
,
552 krb5_context context
,
554 krb5_const_principal client_principal
,
555 krb5_db_entry
*client
,
556 krb5_db_entry
*server
,
557 krb5_db_entry
*krbtgt
,
558 krb5_keyblock
*krbtgt_keyblock
,
562 krb5_error_code code
;
563 struct samba_kdc_entry
*client_skdc_entry
= NULL
;
564 struct samba_kdc_entry
*krbtgt_skdc_entry
= NULL
;
565 struct samba_kdc_entry
*server_skdc_entry
= NULL
;
566 krb5_principal delegated_proxy_principal
= NULL
;
567 krb5_pac new_pac
= NULL
;
568 bool is_in_db
= false;
569 bool is_untrusted
= false;
570 uint32_t flags
= SAMBA_KDC_FLAG_SKIP_PAC_BUFFER
;
572 /* Create a memory context early so code can use talloc_stackframe() */
573 tmp_ctx
= talloc_named(ctx
, 0, "mit_samba_reget_pac context");
574 if (tmp_ctx
== NULL
) {
578 if (client
!= NULL
) {
580 talloc_get_type_abort(client
->e_data
,
581 struct samba_kdc_entry
);
584 if (server
== NULL
) {
590 talloc_get_type_abort(server
->e_data
,
591 struct samba_kdc_entry
);
593 if (krbtgt
== NULL
) {
598 talloc_get_type_abort(krbtgt
->e_data
,
599 struct samba_kdc_entry
);
601 code
= samba_krbtgt_is_in_db(krbtgt_skdc_entry
,
609 flags
|= SAMBA_KDC_FLAG_KRBTGT_IS_UNTRUSTED
;
613 flags
|= SAMBA_KDC_FLAG_KRBTGT_IN_DB
;
617 if (kdc_flags
& KRB5_KDB_FLAG_PROTOCOL_TRANSITION
) {
618 flags
|= SAMBA_KDC_FLAG_PROTOCOL_TRANSITION
;
621 if (kdc_flags
& KRB5_KDB_FLAG_CONSTRAINED_DELEGATION
) {
622 flags
|= SAMBA_KDC_FLAG_CONSTRAINED_DELEGATION
;
623 delegated_proxy_principal
= discard_const(client_principal
);
626 /* Build an updated PAC */
627 code
= krb5_pac_init(context
, &new_pac
);
632 code
= samba_kdc_update_pac(tmp_ctx
,
634 krbtgt_skdc_entry
->kdc_db_ctx
->samdb
,
640 delegated_proxy_principal
,
644 krb5_pac_free(context
, new_pac
);
645 if (code
== ENODATA
) {
646 krb5_pac_free(context
, *pac
);
653 /* We now replace the pac */
654 krb5_pac_free(context
, *pac
);
658 talloc_free(tmp_ctx
);
662 krb5_error_code
mit_samba_update_pac(struct mit_samba_context
*ctx
,
663 krb5_context context
,
665 krb5_db_entry
*client
,
666 krb5_db_entry
*server
,
667 krb5_db_entry
*krbtgt
,
671 TALLOC_CTX
*tmp_ctx
= NULL
;
672 krb5_error_code code
;
673 struct samba_kdc_entry
*client_skdc_entry
= NULL
;
674 struct samba_kdc_entry
*server_skdc_entry
= NULL
;
675 struct samba_kdc_entry
*krbtgt_skdc_entry
= NULL
;
676 bool is_in_db
= false;
677 bool is_untrusted
= false;
678 uint32_t flags
= SAMBA_KDC_FLAG_SKIP_PAC_BUFFER
;
680 /* Create a memory context early so code can use talloc_stackframe() */
681 tmp_ctx
= talloc_named(ctx
, 0, "mit_samba_update_pac context");
682 if (tmp_ctx
== NULL
) {
686 if (client
!= NULL
) {
688 talloc_get_type_abort(client
->e_data
,
689 struct samba_kdc_entry
);
692 if (krbtgt
== NULL
) {
697 talloc_get_type_abort(krbtgt
->e_data
,
698 struct samba_kdc_entry
);
701 talloc_get_type_abort(server
->e_data
,
702 struct samba_kdc_entry
);
705 * If the krbtgt was generated by an RODC, and we are not that
706 * RODC, then we need to regenerate the PAC - we can't trust
707 * it, and confirm that the RODC was permitted to print this ticket
709 * Because of the samba_kdc_validate_pac_blob() step we can be
710 * sure that the record in 'client' or 'server' matches the SID in the
713 code
= samba_krbtgt_is_in_db(krbtgt_skdc_entry
,
721 flags
|= SAMBA_KDC_FLAG_KRBTGT_IS_UNTRUSTED
;
725 flags
|= SAMBA_KDC_FLAG_KRBTGT_IN_DB
;
729 if (kdc_flags
& KRB5_KDB_FLAG_CONSTRAINED_DELEGATION
) {
730 flags
|= SAMBA_KDC_FLAG_CONSTRAINED_DELEGATION
;
733 code
= samba_kdc_update_pac(tmp_ctx
,
735 krbtgt_skdc_entry
->kdc_db_ctx
->samdb
,
745 if (code
== ENODATA
) {
747 * We can't tell the KDC to not issue a PAC. It will
748 * just return the newly allocated empty PAC.
755 talloc_free(tmp_ctx
);
760 /* provide header, function is exported but there are no public headers */
762 krb5_error_code
encode_krb5_padata_sequence(krb5_pa_data
*const *rep
, krb5_data
**code
);
764 /* this function allocates 'data' using malloc.
765 * The caller is responsible for freeing it */
766 static void samba_kdc_build_edata_reply(NTSTATUS nt_status
, DATA_BLOB
*e_data
)
768 krb5_error_code ret
= 0;
769 krb5_pa_data pa
, *ppa
[2];
778 pa
.magic
= KV5M_PA_DATA
;
779 pa
.pa_type
= KRB5_PADATA_PW_SALT
;
781 pa
.contents
= malloc(pa
.length
);
786 SIVAL(pa
.contents
, 0, NT_STATUS_V(nt_status
));
787 SIVAL(pa
.contents
, 4, 0);
788 SIVAL(pa
.contents
, 8, 1);
793 ret
= encode_krb5_padata_sequence(ppa
, &d
);
799 e_data
->data
= (uint8_t *)d
->data
;
800 e_data
->length
= d
->length
;
802 /* free d, not d->data - gd */
808 int mit_samba_check_client_access(struct mit_samba_context
*ctx
,
809 krb5_db_entry
*client
,
810 const char *client_name
,
811 krb5_db_entry
*server
,
812 const char *server_name
,
813 const char *netbios_name
,
814 bool password_change
,
817 struct samba_kdc_entry
*skdc_entry
;
820 skdc_entry
= talloc_get_type(client
->e_data
, struct samba_kdc_entry
);
822 nt_status
= samba_kdc_check_client_access(skdc_entry
,
827 if (!NT_STATUS_IS_OK(nt_status
)) {
828 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NO_MEMORY
)) {
832 samba_kdc_build_edata_reply(nt_status
, e_data
);
834 return samba_kdc_map_policy_err(nt_status
);
840 int mit_samba_check_s4u2proxy(struct mit_samba_context
*ctx
,
841 const krb5_db_entry
*server
,
842 krb5_const_principal target_principal
)
844 #if KRB5_KDB_DAL_MAJOR_VERSION < 9
845 return KRB5KDC_ERR_BADOPTION
;
847 struct samba_kdc_entry
*server_skdc_entry
=
848 talloc_get_type_abort(server
->e_data
, struct samba_kdc_entry
);
849 krb5_error_code code
;
851 code
= samba_kdc_check_s4u2proxy(ctx
->context
,
860 krb5_error_code
mit_samba_check_allowed_to_delegate_from(
861 struct mit_samba_context
*ctx
,
862 krb5_const_principal client_principal
,
863 krb5_const_principal server_principal
,
865 const krb5_db_entry
*proxy
)
867 #if KRB5_KDB_DAL_MAJOR_VERSION < 8
868 return KRB5KDC_ERR_POLICY
;
870 struct samba_kdc_entry
*proxy_skdc_entry
=
871 talloc_get_type_abort(proxy
->e_data
, struct samba_kdc_entry
);
872 krb5_error_code code
;
874 code
= samba_kdc_check_s4u2proxy_rbcd(ctx
->context
,
885 static krb5_error_code
mit_samba_change_pwd_error(krb5_context context
,
887 enum samPwdChangeReason reject_reason
,
888 struct samr_DomInfo1
*dominfo
)
890 krb5_error_code code
= KADM5_PASS_Q_GENERIC
;
892 if (NT_STATUS_EQUAL(result
, NT_STATUS_NO_SUCH_USER
)) {
893 code
= KADM5_BAD_PRINCIPAL
;
894 krb5_set_error_message(context
,
896 "No such user when changing password");
898 if (NT_STATUS_EQUAL(result
, NT_STATUS_ACCESS_DENIED
)) {
899 code
= KADM5_PASS_Q_GENERIC
;
900 krb5_set_error_message(context
,
902 "Not permitted to change password");
904 if (NT_STATUS_EQUAL(result
, NT_STATUS_PASSWORD_RESTRICTION
) &&
906 switch (reject_reason
) {
907 case SAM_PWD_CHANGE_PASSWORD_TOO_SHORT
:
908 code
= KADM5_PASS_Q_TOOSHORT
;
909 krb5_set_error_message(context
,
911 "Password too short, password "
912 "must be at least %d characters "
914 dominfo
->min_password_length
);
916 case SAM_PWD_CHANGE_NOT_COMPLEX
:
917 code
= KADM5_PASS_Q_DICT
;
918 krb5_set_error_message(context
,
920 "Password does not meet "
921 "complexity requirements");
923 case SAM_PWD_CHANGE_PWD_IN_HISTORY
:
924 code
= KADM5_PASS_TOOSOON
;
925 krb5_set_error_message(context
,
927 "Password is already in password "
928 "history. New password must not "
929 "match any of your %d previous "
931 dominfo
->password_history_length
);
934 code
= KADM5_PASS_Q_GENERIC
;
935 krb5_set_error_message(context
,
937 "Password change rejected, "
938 "password changes may not be "
939 "permitted on this account, or "
940 "the minimum password age may "
941 "not have elapsed.");
949 int mit_samba_kpasswd_change_password(struct mit_samba_context
*ctx
,
951 krb5_db_entry
*db_entry
)
954 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
957 enum samPwdChangeReason reject_reason
;
958 struct samr_DomInfo1
*dominfo
;
959 const char *error_string
= NULL
;
960 struct auth_user_info_dc
*user_info_dc
;
961 struct samba_kdc_entry
*p
=
962 talloc_get_type_abort(db_entry
->e_data
, struct samba_kdc_entry
);
963 krb5_error_code code
= 0;
965 #ifdef DEBUG_PASSWORD
966 DEBUG(1,("mit_samba_kpasswd_change_password called with: %s\n", pwd
));
969 tmp_ctx
= talloc_named(ctx
, 0, "mit_samba_kpasswd_change_password");
970 if (tmp_ctx
== NULL
) {
974 status
= samba_kdc_get_user_info_from_db(p
,
977 if (!NT_STATUS_IS_OK(status
)) {
978 DEBUG(1,("samba_kdc_get_user_info_from_db failed: %s\n",
980 talloc_free(tmp_ctx
);
984 status
= auth_generate_session_info(tmp_ctx
,
988 0, /* session_info_flags */
991 if (!NT_STATUS_IS_OK(status
)) {
992 DEBUG(1,("auth_generate_session_info failed: %s\n",
994 talloc_free(tmp_ctx
);
998 /* password is expected as UTF16 */
1000 if (!convert_string_talloc(tmp_ctx
, CH_UTF8
, CH_UTF16
,
1002 &password
.data
, &password
.length
)) {
1003 DEBUG(1,("convert_string_talloc failed\n"));
1004 talloc_free(tmp_ctx
);
1008 status
= samdb_kpasswd_change_password(tmp_ctx
,
1009 ctx
->db_ctx
->lp_ctx
,
1010 ctx
->db_ctx
->ev_ctx
,
1017 if (!NT_STATUS_IS_OK(status
)) {
1018 DEBUG(1,("samdb_kpasswd_change_password failed: %s\n",
1019 nt_errstr(status
)));
1020 code
= KADM5_PASS_Q_GENERIC
;
1021 krb5_set_error_message(ctx
->context
, code
, "%s", error_string
);
1025 if (!NT_STATUS_IS_OK(result
)) {
1026 code
= mit_samba_change_pwd_error(ctx
->context
,
1033 talloc_free(tmp_ctx
);
1038 void mit_samba_zero_bad_password_count(krb5_db_entry
*db_entry
)
1040 struct netr_SendToSamBase
*send_to_sam
= NULL
;
1041 struct samba_kdc_entry
*p
=
1042 talloc_get_type_abort(db_entry
->e_data
, struct samba_kdc_entry
);
1043 struct ldb_dn
*domain_dn
;
1045 domain_dn
= ldb_get_default_basedn(p
->kdc_db_ctx
->samdb
);
1047 authsam_logon_success_accounting(p
->kdc_db_ctx
->samdb
,
1052 /* TODO: RODC support */
1056 void mit_samba_update_bad_password_count(krb5_db_entry
*db_entry
)
1058 struct samba_kdc_entry
*p
=
1059 talloc_get_type_abort(db_entry
->e_data
, struct samba_kdc_entry
);
1061 authsam_update_bad_pwd_count(p
->kdc_db_ctx
->samdb
,
1063 ldb_get_default_basedn(p
->kdc_db_ctx
->samdb
));
1066 bool mit_samba_princ_needs_pac(krb5_db_entry
*db_entry
)
1068 struct samba_kdc_entry
*skdc_entry
=
1069 talloc_get_type_abort(db_entry
->e_data
, struct samba_kdc_entry
);
1071 return samba_princ_needs_pac(skdc_entry
);