4 Copyright (C) Simo Sorce 2004-2008
5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2006
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Stefan Metzmacher 2007-2010
8 Copyright (C) Matthias Dieter Wallnöfer 2009-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 * Component: ldb password_hash module
29 * Description: correctly handle AD password changes fields
31 * Author: Andrew Bartlett
32 * Author: Stefan Metzmacher
36 #include "ldb_module.h"
37 #include "libcli/auth/libcli_auth.h"
38 #include "libcli/security/dom_sid.h"
39 #include "system/kerberos.h"
40 #include "auth/kerberos/kerberos.h"
41 #include "dsdb/samdb/samdb.h"
42 #include "dsdb/samdb/ldb_modules/util.h"
43 #include "dsdb/samdb/ldb_modules/password_modules.h"
44 #include "librpc/gen_ndr/ndr_drsblobs.h"
45 #include "lib/crypto/md4.h"
46 #include "param/param.h"
47 #include "lib/krb5_wrap/krb5_samba.h"
48 #include "auth/auth_sam.h"
49 #include "auth/common_auth.h"
50 #include "lib/messaging/messaging.h"
51 #include "lib/param/loadparm.h"
53 #include "lib/crypto/gnutls_helpers.h"
54 #include <gnutls/crypto.h>
56 #include "kdc/db-glue.h"
63 * 1.2.0 is what dpkg-shlibdeps generates, based on used symbols and
65 * https://salsa.debian.org/debian/gpgme/blob/debian/master/debian/libgpgme11.symbols
68 #define MINIMUM_GPGME_VERSION "1.2.0"
74 /* If we have decided there is a reason to work on this request, then
75 * setup all the password hash types correctly.
77 * If we haven't the hashes yet but the password given as plain-text (attributes
78 * 'unicodePwd', 'userPassword' and 'clearTextPassword') we have to check for
79 * the constraints. Once this is done, we calculate the password hashes.
81 * Notice: unlike the real AD which only supports the UTF16 special based
82 * 'unicodePwd' and the UTF8 based 'userPassword' plaintext attribute we
83 * understand also a UTF16 based 'clearTextPassword' one.
84 * The latter is also accessible through LDAP so it can also be set by external
85 * tools and scripts. But be aware that this isn't portable on non SAMBA 4 ADs!
87 * Also when the module receives only the password hashes (possible through
88 * specifying an internal LDB control - for security reasons) some checks are
89 * performed depending on the operation mode (see below) (e.g. if the password
90 * has been in use before if the password memory policy was activated).
92 * Attention: There is a difference between "modify" and "reset" operations
93 * (see MS-ADTS 3.1.1.3.1.5). If the client sends a "add" and "remove"
94 * operation for a password attribute we thread this as a "modify"; if it sends
95 * only a "replace" one we have an (administrative) reset.
97 * Finally, if the administrator has requested that a password history
98 * be maintained, then this should also be written out.
102 /* TODO: [consider always MS-ADTS 3.1.1.3.1.5]
103 * - Check for right connection encryption
106 /* Notice: Definition of "dsdb_control_password_change_status" moved into
110 struct ldb_module *module;
111 struct ldb_request *req;
113 struct ldb_request *dom_req;
114 struct ldb_reply *dom_res;
116 struct ldb_reply *pso_res;
118 struct ldb_reply *search_res;
120 struct ldb_message *update_msg;
122 struct dsdb_control_password_change_status *status;
123 struct dsdb_control_password_change *change;
125 const char **gpg_key_ids;
131 bool update_password;
133 bool pwd_last_set_bypass;
134 bool pwd_last_set_default;
135 bool smartcard_reset;
136 const char **userPassword_schemes;
140 struct setup_password_fields_io {
141 struct ph_context *ac;
143 struct smb_krb5_context *smb_krb5_context;
145 /* info about the user account */
147 uint32_t userAccountControl;
149 const char *sAMAccountName;
150 const char *user_principal_name;
151 const char *displayName; /* full name */
153 uint32_t restrictions;
154 struct dom_sid *account_sid;
158 /* new credentials and old given credentials */
159 struct setup_password_fields_given {
160 const struct ldb_val *cleartext_utf8;
161 const struct ldb_val *cleartext_utf16;
163 struct samr_Password *nt_hash;
166 * The AES256 kerberos key to confirm the previous password was
167 * not reused (for n) and to prove the old password was known
170 * We don't have any old salts, so we won't catch password reuse
171 * if said password was used prior to an account rename and
172 * another password change.
177 /* old credentials */
179 struct samr_Password *nt_hash;
180 uint32_t nt_history_len;
181 struct samr_Password *nt_history;
182 const struct ldb_val *supplemental;
183 struct supplementalCredentialsBlob scb;
186 * The AES256 kerberos key as stored in the DB.
187 * Used to confirm the given password was correct
188 * and in case the previous password was reused.
195 /* generated credentials */
197 struct samr_Password *nt_hash;
198 uint32_t nt_history_len;
199 struct samr_Password *nt_history;
205 struct ldb_val supplemental;
210 static int msg_find_old_and_new_pwd_val(const struct ldb_message *msg,
212 enum ldb_request_type operation,
213 const struct ldb_val **new_val,
214 const struct ldb_val **old_val);
216 static int password_hash_bypass(struct ldb_module *module, struct ldb_request *request)
218 struct ldb_context *ldb = ldb_module_get_ctx(module);
219 const struct ldb_message *msg;
220 struct ldb_message_element *nte;
221 struct ldb_message_element *lme;
222 struct ldb_message_element *nthe;
223 struct ldb_message_element *lmhe;
224 struct ldb_message_element *sce;
227 switch (request->operation) {
229 msg = request->op.add.message;
232 msg = request->op.mod.message;
235 return ldb_next_request(module, request);
238 /* nobody must touch password histories and 'supplementalCredentials' */
240 #define GET_VALUES(el, attr) do { \
241 ret = dsdb_get_expected_new_values(request, \
245 request->operation); \
247 if (ret != LDB_SUCCESS) { \
252 GET_VALUES(nte, "unicodePwd");
255 * Even as Samba continues to ignore the LM hash, and reset it
256 * when practical, we keep the constraint that it must be a 16
257 * byte value if specified.
259 GET_VALUES(lme, "dBCSPwd");
260 GET_VALUES(nthe, "ntPwdHistory");
261 GET_VALUES(lmhe, "lmPwdHistory");
262 GET_VALUES(sce, "supplementalCredentials");
265 #define CHECK_HASH_ELEMENT(e, min, max) do {\
266 if (e && e->num_values) { \
267 unsigned int _count; \
268 if (e->num_values != 1) { \
269 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
270 "num_values != 1"); \
272 if ((e->values[0].length % 16) != 0) { \
273 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
274 "length % 16 != 0"); \
276 _count = e->values[0].length / 16; \
277 if (_count < min) { \
278 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
281 if (_count > max) { \
282 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
288 CHECK_HASH_ELEMENT(nte, 1, 1);
289 CHECK_HASH_ELEMENT(lme, 1, 1);
290 CHECK_HASH_ELEMENT(nthe, 1, INT32_MAX);
291 CHECK_HASH_ELEMENT(lmhe, 1, INT32_MAX);
293 if (sce && sce->num_values) {
294 enum ndr_err_code ndr_err;
295 struct supplementalCredentialsBlob *scb;
296 struct supplementalCredentialsPackage *scpp = NULL;
297 struct supplementalCredentialsPackage *scpk = NULL;
298 struct supplementalCredentialsPackage *scpkn = NULL;
299 struct supplementalCredentialsPackage *scpct = NULL;
300 DATA_BLOB scpbp = data_blob_null;
301 DATA_BLOB scpbk = data_blob_null;
302 DATA_BLOB scpbkn = data_blob_null;
303 DATA_BLOB scpbct = data_blob_null;
307 if (sce->num_values != 1) {
308 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
312 scb = talloc_zero(request, struct supplementalCredentialsBlob);
314 return ldb_module_oom(module);
317 ndr_err = ndr_pull_struct_blob_all(&sce->values[0], scb, scb,
318 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
319 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
321 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
322 "ndr_pull_struct_blob_all");
325 if (scb->sub.num_packages < 2) {
327 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
331 for (i=0; i < scb->sub.num_packages; i++) {
334 subblob = strhex_to_data_blob(scb, scb->sub.packages[i].data);
335 if (subblob.data == NULL) {
337 return ldb_module_oom(module);
340 if (strcmp(scb->sub.packages[i].name, "Packages") == 0) {
343 return ldb_error(ldb,
344 LDB_ERR_CONSTRAINT_VIOLATION,
347 scpp = &scb->sub.packages[i];
351 if (strcmp(scb->sub.packages[i].name, "Primary:Kerberos") == 0) {
354 return ldb_error(ldb,
355 LDB_ERR_CONSTRAINT_VIOLATION,
356 "Primary:Kerberos twice");
358 scpk = &scb->sub.packages[i];
362 if (strcmp(scb->sub.packages[i].name, "Primary:Kerberos-Newer-Keys") == 0) {
365 return ldb_error(ldb,
366 LDB_ERR_CONSTRAINT_VIOLATION,
367 "Primary:Kerberos-Newer-Keys twice");
369 scpkn = &scb->sub.packages[i];
373 if (strcmp(scb->sub.packages[i].name, "Primary:CLEARTEXT") == 0) {
376 return ldb_error(ldb,
377 LDB_ERR_CONSTRAINT_VIOLATION,
378 "Primary:CLEARTEXT twice");
380 scpct = &scb->sub.packages[i];
385 data_blob_free(&subblob);
390 return ldb_error(ldb,
391 LDB_ERR_CONSTRAINT_VIOLATION,
392 "Primary:Packages missing");
397 * If Primary:Kerberos is missing w2k8r2 reboots
398 * when a password is changed.
401 return ldb_error(ldb,
402 LDB_ERR_CONSTRAINT_VIOLATION,
403 "Primary:Kerberos missing");
407 struct package_PackagesBlob *p;
410 p = talloc_zero(scb, struct package_PackagesBlob);
413 return ldb_module_oom(module);
416 ndr_err = ndr_pull_struct_blob(&scpbp, p, p,
417 (ndr_pull_flags_fn_t)ndr_pull_package_PackagesBlob);
418 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
420 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
421 "ndr_pull_struct_blob Packages");
424 if (p->names == NULL) {
426 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
427 "Packages names == NULL");
430 for (n = 0; p->names[n]; n++) {
434 if (scb->sub.num_packages != (n + 1)) {
436 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
437 "Packages num_packages != num_names + 1");
444 struct package_PrimaryKerberosBlob *k;
446 k = talloc_zero(scb, struct package_PrimaryKerberosBlob);
449 return ldb_module_oom(module);
452 ndr_err = ndr_pull_struct_blob(&scpbk, k, k,
453 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
454 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
456 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
457 "ndr_pull_struct_blob PrimaryKerberos");
460 if (k->version != 3) {
462 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
463 "PrimaryKerberos version != 3");
466 if (k->ctr.ctr3.salt.string == NULL) {
468 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
469 "PrimaryKerberos salt == NULL");
472 if (strlen(k->ctr.ctr3.salt.string) == 0) {
474 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
475 "PrimaryKerberos strlen(salt) == 0");
478 if (k->ctr.ctr3.num_keys != 2) {
480 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
481 "PrimaryKerberos num_keys != 2");
484 if (k->ctr.ctr3.num_old_keys > k->ctr.ctr3.num_keys) {
486 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
487 "PrimaryKerberos num_old_keys > num_keys");
490 if (k->ctr.ctr3.keys[0].keytype != ENCTYPE_DES_CBC_MD5) {
492 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
493 "PrimaryKerberos key[0] != DES_CBC_MD5");
495 if (k->ctr.ctr3.keys[1].keytype != ENCTYPE_DES_CBC_CRC) {
497 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
498 "PrimaryKerberos key[1] != DES_CBC_CRC");
501 if (k->ctr.ctr3.keys[0].value_len != 8) {
503 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
504 "PrimaryKerberos key[0] value_len != 8");
506 if (k->ctr.ctr3.keys[1].value_len != 8) {
508 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
509 "PrimaryKerberos key[1] value_len != 8");
512 for (i = 0; i < k->ctr.ctr3.num_old_keys; i++) {
513 if (k->ctr.ctr3.old_keys[i].keytype ==
514 k->ctr.ctr3.keys[i].keytype &&
515 k->ctr.ctr3.old_keys[i].value_len ==
516 k->ctr.ctr3.keys[i].value_len) {
521 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
522 "PrimaryKerberos old_keys type/value_len doesn't match");
529 struct package_PrimaryKerberosBlob *k;
531 k = talloc_zero(scb, struct package_PrimaryKerberosBlob);
534 return ldb_module_oom(module);
537 ndr_err = ndr_pull_struct_blob(&scpbkn, k, k,
538 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
539 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
541 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
542 "ndr_pull_struct_blob PrimaryKerberosNeverKeys");
545 if (k->version != 4) {
547 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
548 "KerberosNerverKeys version != 4");
551 if (k->ctr.ctr4.salt.string == NULL) {
553 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
554 "KerberosNewerKeys salt == NULL");
557 if (strlen(k->ctr.ctr4.salt.string) == 0) {
559 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
560 "KerberosNewerKeys strlen(salt) == 0");
563 if (k->ctr.ctr4.num_keys != 4) {
565 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
566 "KerberosNewerKeys num_keys != 4");
569 if (k->ctr.ctr4.num_old_keys > k->ctr.ctr4.num_keys) {
571 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
572 "KerberosNewerKeys num_old_keys > num_keys");
575 if (k->ctr.ctr4.num_older_keys > k->ctr.ctr4.num_old_keys) {
577 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
578 "KerberosNewerKeys num_older_keys > num_old_keys");
581 if (k->ctr.ctr4.keys[0].keytype != ENCTYPE_AES256_CTS_HMAC_SHA1_96) {
583 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
584 "KerberosNewerKeys key[0] != AES256");
586 if (k->ctr.ctr4.keys[1].keytype != ENCTYPE_AES128_CTS_HMAC_SHA1_96) {
588 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
589 "KerberosNewerKeys key[1] != AES128");
591 if (k->ctr.ctr4.keys[2].keytype != ENCTYPE_DES_CBC_MD5) {
593 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
594 "KerberosNewerKeys key[2] != DES_CBC_MD5");
596 if (k->ctr.ctr4.keys[3].keytype != ENCTYPE_DES_CBC_CRC) {
598 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
599 "KerberosNewerKeys key[3] != DES_CBC_CRC");
602 if (k->ctr.ctr4.keys[0].value_len != 32) {
604 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
605 "KerberosNewerKeys key[0] value_len != 32");
607 if (k->ctr.ctr4.keys[1].value_len != 16) {
609 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
610 "KerberosNewerKeys key[1] value_len != 16");
612 if (k->ctr.ctr4.keys[2].value_len != 8) {
614 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
615 "KerberosNewerKeys key[2] value_len != 8");
617 if (k->ctr.ctr4.keys[3].value_len != 8) {
619 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
620 "KerberosNewerKeys key[3] value_len != 8");
625 * Maybe we can check old and older keys here.
626 * But we need to do some tests, if the old keys
627 * can be taken from the PrimaryKerberos blob
628 * (with only des keys), when the domain was upgraded
636 struct package_PrimaryCLEARTEXTBlob *ct;
638 ct = talloc_zero(scb, struct package_PrimaryCLEARTEXTBlob);
641 return ldb_module_oom(module);
644 ndr_err = ndr_pull_struct_blob(&scpbct, ct, ct,
645 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryCLEARTEXTBlob);
646 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
648 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
649 "ndr_pull_struct_blob PrimaryCLEARTEXT");
652 if ((ct->cleartext.length % 2) != 0) {
654 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
655 "PrimaryCLEARTEXT length % 2 != 0");
661 ndr_err = ndr_push_struct_blob(&blob, scb, scb,
662 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
663 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
665 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
666 "ndr_pull_struct_blob_all");
669 if (sce->values[0].length != blob.length) {
671 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
672 "supplementalCredentialsBlob length differ");
675 if (!mem_equal_const_time(sce->values[0].data, blob.data, blob.length)) {
677 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
678 "supplementalCredentialsBlob memcmp differ");
684 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_bypass - validated\n");
685 return ldb_next_request(module, request);
688 /* Get the NT hash, and fill it in as an entry in the password history,
689 and specify it into io->g.nt_hash */
691 static int setup_nt_fields(struct setup_password_fields_io *io)
693 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
695 if (io->u.store_nt_hash) {
696 io->g.nt_hash = io->n.nt_hash;
699 if (io->ac->status->domain_data.pwdHistoryLength == 0) {
703 /* We might not have an old NT password */
705 if (io->g.nt_hash == NULL) {
707 * If there was not an NT hash specified, then don't
708 * store the NT password history.
710 * While the NTLM code on a Windows DC will cope with
711 * a missing unicodePwd, if it finds a last password
712 * in the ntPwdHistory, even if the bytes are zero ,
713 * it will (quite reasonably) treat it as a valid NT
714 * hash. NTLM logins with the previous password are
715 * allowed for a short time after the password is
716 * changed to allow for password propagation delays.
721 io->g.nt_history = talloc_array(io->ac,
722 struct samr_Password,
723 io->ac->status->domain_data.pwdHistoryLength);
724 if (!io->g.nt_history) {
728 for (i = 0; i < MIN(io->ac->status->domain_data.pwdHistoryLength-1,
729 io->o.nt_history_len); i++) {
730 io->g.nt_history[i+1] = io->o.nt_history[i];
732 io->g.nt_history_len = i + 1;
734 io->g.nt_history[0] = *io->g.nt_hash;
739 static int setup_kerberos_keys(struct setup_password_fields_io *io)
741 struct ldb_context *ldb;
742 krb5_error_code krb5_ret;
743 krb5_principal salt_principal = NULL;
747 krb5_data cleartext_data;
748 uint32_t uac_flags = 0;
750 ldb = ldb_module_get_ctx(io->ac->module);
751 cleartext_data.data = (char *)io->n.cleartext_utf8->data;
752 cleartext_data.length = io->n.cleartext_utf8->length;
754 uac_flags = io->u.userAccountControl & UF_ACCOUNT_TYPE_MASK;
755 krb5_ret = smb_krb5_salt_principal(io->smb_krb5_context->krb5_context,
756 io->ac->status->domain_data.realm,
757 io->u.sAMAccountName,
758 io->u.user_principal_name,
762 ldb_asprintf_errstring(ldb,
763 "setup_kerberos_keys: "
764 "generation of a salting principal failed: %s",
765 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
767 return LDB_ERR_OPERATIONS_ERROR;
771 * create salt from salt_principal
773 krb5_ret = smb_krb5_get_pw_salt(io->smb_krb5_context->krb5_context,
774 salt_principal, &salt_data);
776 krb5_free_principal(io->smb_krb5_context->krb5_context, salt_principal);
778 ldb_asprintf_errstring(ldb,
779 "setup_kerberos_keys: "
780 "generation of krb5_salt failed: %s",
781 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
783 return LDB_ERR_OPERATIONS_ERROR;
786 /* now use the talloced copy of the salt */
787 salt.data = talloc_strndup(io->ac,
788 (char *)salt_data.data,
790 smb_krb5_free_data_contents(io->smb_krb5_context->krb5_context,
792 if (salt.data == NULL) {
795 io->g.salt = salt.data;
796 salt.length = strlen(io->g.salt);
799 * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of
800 * the salt and the cleartext password
802 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
806 ENCTYPE_AES256_CTS_HMAC_SHA1_96,
809 ldb_asprintf_errstring(ldb,
810 "setup_kerberos_keys: "
811 "generation of a aes256-cts-hmac-sha1-96 key failed: %s",
812 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
814 return LDB_ERR_OPERATIONS_ERROR;
816 io->g.aes_256 = data_blob_talloc(io->ac,
818 KRB5_KEY_LENGTH(&key));
819 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
820 if (!io->g.aes_256.data) {
825 * create ENCTYPE_AES128_CTS_HMAC_SHA1_96 key out of
826 * the salt and the cleartext password
828 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
832 ENCTYPE_AES128_CTS_HMAC_SHA1_96,
835 ldb_asprintf_errstring(ldb,
836 "setup_kerberos_keys: "
837 "generation of a aes128-cts-hmac-sha1-96 key failed: %s",
838 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
840 return LDB_ERR_OPERATIONS_ERROR;
842 io->g.aes_128 = data_blob_talloc(io->ac,
844 KRB5_KEY_LENGTH(&key));
845 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
846 if (!io->g.aes_128.data) {
851 * As per RFC-6649 single DES encryption types are no longer considered
852 * secure to be used in Kerberos, we store random keys instead of the
853 * ENCTYPE_DES_CBC_MD5 and ENCTYPE_DES_CBC_CRC keys.
855 io->g.des_md5 = data_blob_talloc(io->ac, NULL, 8);
856 if (!io->g.des_md5.data) {
859 generate_secret_buffer(io->g.des_md5.data, 8);
861 io->g.des_crc = data_blob_talloc(io->ac, NULL, 8);
862 if (!io->g.des_crc.data) {
865 generate_secret_buffer(io->g.des_crc.data, 8);
870 static int setup_kerberos_key_hash(struct setup_password_fields_io *io,
871 struct setup_password_fields_given *g)
873 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
874 krb5_error_code krb5_ret;
877 krb5_data cleartext_data;
879 if (io->ac->search_res == NULL) {
880 /* No old data so nothing to do */
884 if (io->o.salt.data == NULL) {
885 /* We didn't fetch the salt in setup_io(), so nothing to do */
889 salt.data = (char *)io->o.salt.data;
890 salt.length = io->o.salt.length;
892 cleartext_data.data = (char *)g->cleartext_utf8->data;
893 cleartext_data.length = g->cleartext_utf8->length;
896 * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of the salt
897 * and the cleartext password
899 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
903 ENCTYPE_AES256_CTS_HMAC_SHA1_96,
906 ldb_asprintf_errstring(ldb,
907 "setup_kerberos_key_hash: "
908 "generation of a aes256-cts-hmac-sha1-96 key failed: %s",
909 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
911 return LDB_ERR_OPERATIONS_ERROR;
914 g->aes_256 = data_blob_talloc(io->ac,
916 KRB5_KEY_LENGTH(&key));
917 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
918 if (g->aes_256.data == NULL) {
922 talloc_keep_secret(g->aes_256.data);
927 static int setup_primary_kerberos(struct setup_password_fields_io *io,
928 const struct supplementalCredentialsBlob *old_scb,
929 struct package_PrimaryKerberosBlob *pkb)
931 struct ldb_context *ldb;
932 struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3;
933 struct supplementalCredentialsPackage *old_scp = NULL;
934 struct package_PrimaryKerberosBlob _old_pkb;
935 struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL;
937 enum ndr_err_code ndr_err;
939 ldb = ldb_module_get_ctx(io->ac->module);
942 * prepare generation of keys
944 * ENCTYPE_DES_CBC_MD5
945 * ENCTYPE_DES_CBC_CRC
948 pkb3->salt.string = io->g.salt;
950 pkb3->keys = talloc_array(io->ac,
951 struct package_PrimaryKerberosKey3,
957 pkb3->keys[0].keytype = ENCTYPE_DES_CBC_MD5;
958 pkb3->keys[0].value = &io->g.des_md5;
959 pkb3->keys[1].keytype = ENCTYPE_DES_CBC_CRC;
960 pkb3->keys[1].value = &io->g.des_crc;
962 /* initialize the old keys to zero */
963 pkb3->num_old_keys = 0;
964 pkb3->old_keys = NULL;
966 /* if there're no old keys, then we're done */
971 for (i=0; i < old_scb->sub.num_packages; i++) {
972 if (strcmp("Primary:Kerberos", old_scb->sub.packages[i].name) != 0) {
976 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
980 old_scp = &old_scb->sub.packages[i];
983 /* Primary:Kerberos element of supplementalCredentials */
987 blob = strhex_to_data_blob(io->ac, old_scp->data);
992 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
993 ndr_err = ndr_pull_struct_blob(&blob, io->ac, &_old_pkb,
994 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
995 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
996 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
997 ldb_asprintf_errstring(ldb,
998 "setup_primary_kerberos: "
999 "failed to pull old package_PrimaryKerberosBlob: %s",
1001 return LDB_ERR_OPERATIONS_ERROR;
1004 if (_old_pkb.version != 3) {
1005 ldb_asprintf_errstring(ldb,
1006 "setup_primary_kerberos: "
1007 "package_PrimaryKerberosBlob version[%u] expected[3]",
1009 return LDB_ERR_OPERATIONS_ERROR;
1012 old_pkb3 = &_old_pkb.ctr.ctr3;
1015 /* if we didn't found the old keys we're done */
1020 /* fill in the old keys */
1021 pkb3->num_old_keys = old_pkb3->num_keys;
1022 pkb3->old_keys = old_pkb3->keys;
1027 static int setup_primary_kerberos_newer(struct setup_password_fields_io *io,
1028 const struct supplementalCredentialsBlob *old_scb,
1029 struct package_PrimaryKerberosBlob *pkb)
1031 struct ldb_context *ldb;
1032 struct package_PrimaryKerberosCtr4 *pkb4 = &pkb->ctr.ctr4;
1033 struct supplementalCredentialsPackage *old_scp = NULL;
1034 struct package_PrimaryKerberosBlob _old_pkb;
1035 struct package_PrimaryKerberosCtr4 *old_pkb4 = NULL;
1037 enum ndr_err_code ndr_err;
1039 ldb = ldb_module_get_ctx(io->ac->module);
1042 * prepare generation of keys
1044 * ENCTYPE_AES256_CTS_HMAC_SHA1_96
1045 * ENCTYPE_AES128_CTS_HMAC_SHA1_96
1046 * ENCTYPE_DES_CBC_MD5
1047 * ENCTYPE_DES_CBC_CRC
1050 pkb4->salt.string = io->g.salt;
1051 pkb4->default_iteration_count = 4096;
1054 pkb4->keys = talloc_array(io->ac,
1055 struct package_PrimaryKerberosKey4,
1058 return ldb_oom(ldb);
1061 pkb4->keys[0].iteration_count = 4096;
1062 pkb4->keys[0].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
1063 pkb4->keys[0].value = &io->g.aes_256;
1064 pkb4->keys[1].iteration_count = 4096;
1065 pkb4->keys[1].keytype = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
1066 pkb4->keys[1].value = &io->g.aes_128;
1067 pkb4->keys[2].iteration_count = 4096;
1068 pkb4->keys[2].keytype = ENCTYPE_DES_CBC_MD5;
1069 pkb4->keys[2].value = &io->g.des_md5;
1070 pkb4->keys[3].iteration_count = 4096;
1071 pkb4->keys[3].keytype = ENCTYPE_DES_CBC_CRC;
1072 pkb4->keys[3].value = &io->g.des_crc;
1074 /* initialize the old keys to zero */
1075 pkb4->num_old_keys = 0;
1076 pkb4->old_keys = NULL;
1077 pkb4->num_older_keys = 0;
1078 pkb4->older_keys = NULL;
1080 /* if there're no old keys, then we're done */
1085 for (i=0; i < old_scb->sub.num_packages; i++) {
1086 if (strcmp("Primary:Kerberos-Newer-Keys", old_scb->sub.packages[i].name) != 0) {
1090 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
1094 old_scp = &old_scb->sub.packages[i];
1097 /* Primary:Kerberos-Newer-Keys element of supplementalCredentials */
1101 blob = strhex_to_data_blob(io->ac, old_scp->data);
1103 return ldb_oom(ldb);
1106 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
1107 ndr_err = ndr_pull_struct_blob(&blob, io->ac,
1109 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
1110 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1111 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1112 ldb_asprintf_errstring(ldb,
1113 "setup_primary_kerberos_newer: "
1114 "failed to pull old package_PrimaryKerberosBlob: %s",
1116 return LDB_ERR_OPERATIONS_ERROR;
1119 if (_old_pkb.version != 4) {
1120 ldb_asprintf_errstring(ldb,
1121 "setup_primary_kerberos_newer: "
1122 "package_PrimaryKerberosBlob version[%u] expected[4]",
1124 return LDB_ERR_OPERATIONS_ERROR;
1127 old_pkb4 = &_old_pkb.ctr.ctr4;
1130 /* if we didn't found the old keys we're done */
1135 /* fill in the old keys */
1136 pkb4->num_old_keys = old_pkb4->num_keys;
1137 pkb4->old_keys = old_pkb4->keys;
1138 pkb4->num_older_keys = old_pkb4->num_old_keys;
1139 pkb4->older_keys = old_pkb4->old_keys;
1144 static int setup_primary_wdigest(struct setup_password_fields_io *io,
1145 const struct supplementalCredentialsBlob *old_scb,
1146 struct package_PrimaryWDigestBlob *pdb)
1148 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1149 DATA_BLOB sAMAccountName;
1150 DATA_BLOB sAMAccountName_l;
1151 DATA_BLOB sAMAccountName_u;
1152 const char *user_principal_name = io->u.user_principal_name;
1153 DATA_BLOB userPrincipalName;
1154 DATA_BLOB userPrincipalName_l;
1155 DATA_BLOB userPrincipalName_u;
1156 DATA_BLOB netbios_domain;
1157 DATA_BLOB netbios_domain_l;
1158 DATA_BLOB netbios_domain_u;
1159 DATA_BLOB dns_domain;
1160 DATA_BLOB dns_domain_l;
1161 DATA_BLOB dns_domain_u;
1164 DATA_BLOB backslash;
1172 * See 3.1.1.8.11.3.1 WDIGEST_CREDENTIALS Construction
1173 * https://msdn.microsoft.com/en-us/library/cc245680.aspx
1174 * for what precalculated hashes are supposed to be stored...
1176 * I can't reproduce all values which should contain "Digest" as realm,
1177 * am I doing something wrong or is w2k3 just broken...?
1179 * W2K3 fills in following for a user:
1181 * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1182 * sAMAccountName: NewUser2Sam
1183 * userPrincipalName: NewUser2Princ@sub1.w2k3.vmnet1.vm.base
1185 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1186 * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1187 * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1188 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1189 * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1190 * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1191 * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1192 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1193 * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1194 * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1195 * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1196 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1197 * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1198 * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1199 * 221c55284451ae9b3aacaa2a3c86f10f => NewUser2Princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1200 * 74e1be668853d4324d38c07e2acfb8ea => (w2k3 has a bug here!) newuser2princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1201 * e1e244ab7f098e3ae1761be7f9229bbb => NEWUSER2PRINC@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1202 * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1203 * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1204 * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1205 * 31dc704d3640335b2123d4ee28aa1f11 => ??? changes with NewUser2Sam => NewUser1Sam
1206 * 36349f5cecd07320fb3bb0e119230c43 => ??? changes with NewUser2Sam => NewUser1Sam
1207 * 12adf019d037fb535c01fd0608e78d9d => ??? changes with NewUser2Sam => NewUser1Sam
1208 * 6feecf8e724906f3ee1105819c5105a1 => ??? changes with NewUser2Princ => NewUser1Princ
1209 * 6c6911f3de6333422640221b9c51ff1f => ??? changes with NewUser2Princ => NewUser1Princ
1210 * 4b279877e742895f9348ac67a8de2f69 => ??? changes with NewUser2Princ => NewUser1Princ
1211 * db0c6bff069513e3ebb9870d29b57490 => ??? changes with NewUser2Sam => NewUser1Sam
1212 * 45072621e56b1c113a4e04a8ff68cd0e => ??? changes with NewUser2Sam => NewUser1Sam
1213 * 11d1220abc44a9c10cf91ef4a9c1de02 => ??? changes with NewUser2Sam => NewUser1Sam
1215 * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1216 * sAMAccountName: NewUser2Sam
1218 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1219 * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1220 * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1221 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1222 * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1223 * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1224 * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1225 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1226 * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1227 * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1228 * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1229 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1230 * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1231 * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1232 * 8a140d30b6f0a5912735dc1e3bc993b4 => NewUser2Sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1233 * 86d95b2faae6cae4ec261e7fbaccf093 => (here w2k3 is correct) newuser2sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1234 * dfeff1493110220efcdfc6362e5f5450 => NEWUSER2SAM@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1235 * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1236 * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1237 * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1238 * 31dc704d3640335b2123d4ee28aa1f11 => ???M1 changes with NewUser2Sam => NewUser1Sam
1239 * 36349f5cecd07320fb3bb0e119230c43 => ???M1.L changes with newuser2sam => newuser1sam
1240 * 12adf019d037fb535c01fd0608e78d9d => ???M1.U changes with NEWUSER2SAM => NEWUSER1SAM
1241 * 569b4533f2d9e580211dd040e5e360a8 => ???M2 changes with NewUser2Princ => NewUser1Princ
1242 * 52528bddf310a587c5d7e6a9ae2cbb20 => ???M2.L changes with newuser2princ => newuser1princ
1243 * 4f629a4f0361289ca4255ab0f658fcd5 => ???M3 changes with NewUser2Princ => NewUser1Princ (doesn't depend on case of userPrincipal )
1244 * db0c6bff069513e3ebb9870d29b57490 => ???M4 changes with NewUser2Sam => NewUser1Sam
1245 * 45072621e56b1c113a4e04a8ff68cd0e => ???M5 changes with NewUser2Sam => NewUser1Sam (doesn't depend on case of sAMAccountName)
1246 * 11d1220abc44a9c10cf91ef4a9c1de02 => ???M4.U changes with NEWUSER2SAM => NEWUSER1SAM
1250 * sAMAccountName, netbios_domain
1253 .user = &sAMAccountName,
1254 .realm = &netbios_domain,
1257 .user = &sAMAccountName_l,
1258 .realm = &netbios_domain_l,
1261 .user = &sAMAccountName_u,
1262 .realm = &netbios_domain_u,
1265 .user = &sAMAccountName,
1266 .realm = &netbios_domain_u,
1269 .user = &sAMAccountName,
1270 .realm = &netbios_domain_l,
1273 .user = &sAMAccountName_u,
1274 .realm = &netbios_domain_l,
1277 .user = &sAMAccountName_l,
1278 .realm = &netbios_domain_u,
1281 * sAMAccountName, dns_domain
1284 * Windows preserves the case of the DNS domain,
1285 * Samba lower cases the domain at provision time
1286 * This means that for mixed case Domains, the WDigest08 hash
1287 * calculated by Samba differs from that calculated by Windows.
1288 * Until we get a real world use case this will remain a known
1289 * bug, as changing the case could have unforeseen impacts.
1293 .user = &sAMAccountName,
1294 .realm = &dns_domain,
1297 .user = &sAMAccountName_l,
1298 .realm = &dns_domain_l,
1301 .user = &sAMAccountName_u,
1302 .realm = &dns_domain_u,
1305 .user = &sAMAccountName,
1306 .realm = &dns_domain_u,
1309 .user = &sAMAccountName,
1310 .realm = &dns_domain_l,
1313 .user = &sAMAccountName_u,
1314 .realm = &dns_domain_l,
1317 .user = &sAMAccountName_l,
1318 .realm = &dns_domain_u,
1321 * userPrincipalName, no realm
1324 .user = &userPrincipalName,
1328 * NOTE: w2k3 messes this up, if the user has a real userPrincipalName,
1329 * the fallback to the sAMAccountName based userPrincipalName is correct
1331 .user = &userPrincipalName_l,
1334 .user = &userPrincipalName_u,
1337 * nt4dom\sAMAccountName, no realm
1340 .user = &sAMAccountName,
1341 .nt4dom = &netbios_domain
1344 .user = &sAMAccountName_l,
1345 .nt4dom = &netbios_domain_l
1348 .user = &sAMAccountName_u,
1349 .nt4dom = &netbios_domain_u
1353 * the following ones are guessed depending on the technet2 article
1354 * but not reproducible on a w2k3 server
1356 /* sAMAccountName with "Digest" realm */
1358 .user = &sAMAccountName,
1362 .user = &sAMAccountName_l,
1366 .user = &sAMAccountName_u,
1369 /* userPrincipalName with "Digest" realm */
1371 .user = &userPrincipalName,
1375 .user = &userPrincipalName_l,
1379 .user = &userPrincipalName_u,
1382 /* nt4dom\\sAMAccountName with "Digest" realm */
1384 .user = &sAMAccountName,
1385 .nt4dom = &netbios_domain,
1389 .user = &sAMAccountName_l,
1390 .nt4dom = &netbios_domain_l,
1394 .user = &sAMAccountName_u,
1395 .nt4dom = &netbios_domain_u,
1399 int rc = LDB_ERR_OTHER;
1401 /* prepare DATA_BLOB's used in the combinations array */
1402 sAMAccountName = data_blob_string_const(io->u.sAMAccountName);
1403 sAMAccountName_l = data_blob_string_const(strlower_talloc(io->ac, io->u.sAMAccountName));
1404 if (!sAMAccountName_l.data) {
1405 return ldb_oom(ldb);
1407 sAMAccountName_u = data_blob_string_const(strupper_talloc(io->ac, io->u.sAMAccountName));
1408 if (!sAMAccountName_u.data) {
1409 return ldb_oom(ldb);
1412 /* if the user doesn't have a userPrincipalName, create one (with lower case realm) */
1413 if (!user_principal_name) {
1414 user_principal_name = talloc_asprintf(io->ac, "%s@%s",
1415 io->u.sAMAccountName,
1416 io->ac->status->domain_data.dns_domain);
1417 if (!user_principal_name) {
1418 return ldb_oom(ldb);
1421 userPrincipalName = data_blob_string_const(user_principal_name);
1422 userPrincipalName_l = data_blob_string_const(strlower_talloc(io->ac, user_principal_name));
1423 if (!userPrincipalName_l.data) {
1424 return ldb_oom(ldb);
1426 userPrincipalName_u = data_blob_string_const(strupper_talloc(io->ac, user_principal_name));
1427 if (!userPrincipalName_u.data) {
1428 return ldb_oom(ldb);
1431 netbios_domain = data_blob_string_const(io->ac->status->domain_data.netbios_domain);
1432 netbios_domain_l = data_blob_string_const(strlower_talloc(io->ac,
1433 io->ac->status->domain_data.netbios_domain));
1434 if (!netbios_domain_l.data) {
1435 return ldb_oom(ldb);
1437 netbios_domain_u = data_blob_string_const(strupper_talloc(io->ac,
1438 io->ac->status->domain_data.netbios_domain));
1439 if (!netbios_domain_u.data) {
1440 return ldb_oom(ldb);
1443 dns_domain = data_blob_string_const(io->ac->status->domain_data.dns_domain);
1444 dns_domain_l = data_blob_string_const(io->ac->status->domain_data.dns_domain);
1445 dns_domain_u = data_blob_string_const(io->ac->status->domain_data.realm);
1447 digest = data_blob_string_const("Digest");
1449 delim = data_blob_string_const(":");
1450 backslash = data_blob_string_const("\\");
1452 pdb->num_hashes = ARRAY_SIZE(wdigest);
1453 pdb->hashes = talloc_array(io->ac, struct package_PrimaryWDigestHash,
1456 return ldb_oom(ldb);
1459 for (i=0; i < ARRAY_SIZE(wdigest); i++) {
1460 gnutls_hash_hd_t hash_hnd = NULL;
1462 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
1468 if (wdigest[i].nt4dom) {
1469 rc = gnutls_hash(hash_hnd,
1470 wdigest[i].nt4dom->data,
1471 wdigest[i].nt4dom->length);
1473 gnutls_hash_deinit(hash_hnd, NULL);
1474 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1477 rc = gnutls_hash(hash_hnd,
1481 gnutls_hash_deinit(hash_hnd, NULL);
1482 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1486 rc = gnutls_hash(hash_hnd,
1487 wdigest[i].user->data,
1488 wdigest[i].user->length);
1490 gnutls_hash_deinit(hash_hnd, NULL);
1491 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1494 rc = gnutls_hash(hash_hnd, delim.data, delim.length);
1496 gnutls_hash_deinit(hash_hnd, NULL);
1497 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1500 if (wdigest[i].realm) {
1501 rc = gnutls_hash(hash_hnd,
1502 wdigest[i].realm->data,
1503 wdigest[i].realm->length);
1505 gnutls_hash_deinit(hash_hnd, NULL);
1506 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1510 rc = gnutls_hash(hash_hnd, delim.data, delim.length);
1512 gnutls_hash_deinit(hash_hnd, NULL);
1513 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1516 rc = gnutls_hash(hash_hnd,
1517 io->n.cleartext_utf8->data,
1518 io->n.cleartext_utf8->length);
1520 gnutls_hash_deinit(hash_hnd, NULL);
1521 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1525 gnutls_hash_deinit(hash_hnd, pdb->hashes[i].hash);
1533 #define SHA_SALT_PERMITTED_CHARS "abcdefghijklmnopqrstuvwxyz" \
1534 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
1536 #define SHA_SALT_SIZE 16
1537 #define SHA_256_SCHEME "CryptSHA256"
1538 #define SHA_512_SCHEME "CryptSHA512"
1539 #define CRYPT "{CRYPT}"
1540 #define SHA_ID_LEN 3
1541 #define SHA_256_ALGORITHM_ID 5
1542 #define SHA_512_ALGORITHM_ID 6
1543 #define ROUNDS_PARAMETER "rounds="
1546 * Extract the crypt (3) algorithm number and number of hash rounds from the
1547 * supplied scheme string
1549 static bool parse_scheme(const char *scheme, int *algorithm, int *rounds) {
1551 const char *rp = NULL; /* Pointer to the 'rounds=' option */
1552 char digits[21]; /* digits extracted from the rounds option */
1553 int i = 0; /* loop index variable */
1555 if (strncasecmp(SHA_256_SCHEME, scheme, strlen(SHA_256_SCHEME)) == 0) {
1556 *algorithm = SHA_256_ALGORITHM_ID;
1557 } else if (strncasecmp(SHA_512_SCHEME, scheme, strlen(SHA_256_SCHEME))
1559 *algorithm = SHA_512_ALGORITHM_ID;
1564 rp = strcasestr(scheme, ROUNDS_PARAMETER);
1566 /* No options specified, use crypt default number of rounds */
1570 rp += strlen(ROUNDS_PARAMETER);
1571 for (i = 0; isdigit(rp[i]) && i < (sizeof(digits) - 1); i++) {
1575 *rounds = atoi(digits);
1580 * Calculate the password hash specified by scheme, and return it in
1583 static int setup_primary_userPassword_hash(
1585 struct setup_password_fields_io *io,
1587 struct package_PrimaryUserPasswordValue *hash_value)
1589 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1590 const char *salt = NULL; /* Randomly generated salt */
1591 const char *cmd = NULL; /* command passed to crypt */
1592 const char *hash = NULL; /* password hash generated by crypt */
1593 int algorithm = 0; /* crypt hash algorithm number */
1594 int rounds = 0; /* The number of hash rounds */
1595 DATA_BLOB *hash_blob = NULL;
1596 TALLOC_CTX *frame = talloc_stackframe();
1597 #if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT_RN)
1598 struct crypt_data crypt_data = {
1599 .initialized = 0 /* working storage used by crypt */
1603 /* Generate a random password salt */
1604 salt = generate_random_str_list(frame,
1606 SHA_SALT_PERMITTED_CHARS);
1609 return ldb_oom(ldb);
1612 /* determine the hashing algorithm and number of rounds*/
1613 if (!parse_scheme(scheme, &algorithm, &rounds)) {
1614 ldb_asprintf_errstring(
1616 "setup_primary_userPassword: Invalid scheme of [%s] "
1617 "specified for 'password hash userPassword schemes' in "
1621 return LDB_ERR_OPERATIONS_ERROR;
1623 hash_value->scheme = talloc_strdup(ctx, CRYPT);
1624 if (hash_value->scheme == NULL) {
1626 return ldb_oom(ldb);
1628 hash_value->scheme_len = strlen(CRYPT) + 1;
1630 /* generate the id/salt parameter used by crypt */
1632 cmd = talloc_asprintf(frame,
1639 return ldb_oom(ldb);
1642 cmd = talloc_asprintf(frame, "$%d$%s", algorithm, salt);
1645 return ldb_oom(ldb);
1650 * Relies on the assertion that cleartext_utf8->data is a zero
1651 * terminated UTF-8 string
1655 * crypt_r() and crypt() may return a null pointer upon error
1656 * depending on how libcrypt was configured, so we prefer
1657 * crypt_rn() from libcrypt / libxcrypt which always returns
1660 * POSIX specifies returning a null pointer and setting
1663 * RHEL 7 (which does not use libcrypt / libxcrypt) returns a
1664 * non-NULL pointer from crypt_r() on success but (always?)
1665 * sets errno during internal processing in the NSS crypto
1668 * By preferring crypt_rn we avoid the 'return non-NULL but
1669 * set-errno' that we otherwise cannot tell apart from the
1674 #ifdef HAVE_CRYPT_RN
1675 hash = crypt_rn((char *)io->n.cleartext_utf8->data,
1678 sizeof(crypt_data));
1680 hash = crypt_r((char *)io->n.cleartext_utf8->data, cmd, &crypt_data);
1683 * No crypt_r falling back to crypt, which is NOT thread safe
1684 * Thread safety MT-Unsafe race:crypt
1686 hash = crypt((char *)io->n.cleartext_utf8->data, cmd);
1689 * On error, crypt() and crypt_r() may return a null pointer,
1690 * or a pointer to an invalid hash beginning with a '*'.
1692 if (hash == NULL || hash[0] == '*') {
1694 const char *reason = NULL;
1695 if (errno == ERANGE) {
1696 reason = "Password exceeds maximum length allowed for crypt() hashing";
1698 int err = strerror_r(errno, buf, sizeof(buf));
1702 reason = "Unknown error";
1705 ldb_asprintf_errstring(
1707 "setup_primary_userPassword: generation of a %s "
1708 "password hash failed: (%s)",
1712 return LDB_ERR_OPERATIONS_ERROR;
1715 hash_blob = talloc_zero(ctx, DATA_BLOB);
1717 if (hash_blob == NULL) {
1719 return ldb_oom(ldb);
1722 *hash_blob = data_blob_talloc(hash_blob,
1723 (const uint8_t *)hash,
1725 if (hash_blob->data == NULL) {
1727 return ldb_oom(ldb);
1729 hash_value->value = hash_blob;
1735 * Calculate the desired extra password hashes
1737 static int setup_primary_userPassword(
1738 struct setup_password_fields_io *io,
1739 const struct supplementalCredentialsBlob *old_scb,
1740 struct package_PrimaryUserPasswordBlob *p_userPassword_b)
1742 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1743 TALLOC_CTX *frame = talloc_stackframe();
1748 * Save the current nt_hash, use this to determine if the password
1749 * has been changed by windows. Which will invalidate the userPassword
1750 * hash. Note once NTLM-Strong-NOWTF becomes available it should be
1751 * used in preference to the NT password hash
1753 if (io->g.nt_hash == NULL) {
1755 * When the NT hash is not available, we use this field to store
1756 * the first 16 bytes of the AES256 key instead. This allows
1757 * 'samba-tool user' to verify that the user's password is in
1758 * sync with the userPassword package.
1760 uint8_t hash_len = MIN(16, io->g.aes_256.length);
1762 ZERO_STRUCT(p_userPassword_b->current_nt_hash);
1763 memcpy(p_userPassword_b->current_nt_hash.hash,
1767 p_userPassword_b->current_nt_hash = *io->g.nt_hash;
1771 * Determine the number of hashes
1772 * Note: that currently there is no limit on the number of hashes
1773 * no checking is done on the number of schemes specified
1774 * or for uniqueness.
1776 p_userPassword_b->num_hashes = 0;
1777 for (i = 0; io->ac->userPassword_schemes[i]; i++) {
1778 p_userPassword_b->num_hashes++;
1781 p_userPassword_b->hashes
1782 = talloc_array(io->ac,
1783 struct package_PrimaryUserPasswordValue,
1784 p_userPassword_b->num_hashes);
1785 if (p_userPassword_b->hashes == NULL) {
1787 return ldb_oom(ldb);
1790 for (i = 0; io->ac->userPassword_schemes[i]; i++) {
1791 ret = setup_primary_userPassword_hash(
1792 p_userPassword_b->hashes,
1794 io->ac->userPassword_schemes[i],
1795 &p_userPassword_b->hashes[i]);
1796 if (ret != LDB_SUCCESS) {
1806 static int setup_primary_samba_gpg(struct setup_password_fields_io *io,
1807 struct package_PrimarySambaGPGBlob *pgb)
1809 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1812 gpgme_ctx_t ctx = NULL;
1813 size_t num_keys = str_list_length(io->ac->gpg_key_ids);
1814 gpgme_key_t keys[num_keys+1];
1817 gpgme_data_t plain_data = NULL;
1818 gpgme_data_t crypt_data = NULL;
1819 size_t crypt_length = 0;
1820 char *crypt_mem = NULL;
1822 gret = gpgme_new(&ctx);
1823 if (gret != GPG_ERR_NO_ERROR) {
1824 ldb_debug(ldb, LDB_DEBUG_ERROR,
1825 "%s:%s: gret[%u] %s\n",
1826 __location__, __func__,
1827 gret, gpgme_strerror(gret));
1828 return ldb_module_operr(io->ac->module);
1831 gpgme_set_armor(ctx, 1);
1833 gret = gpgme_data_new_from_mem(&plain_data,
1834 (const char *)io->n.cleartext_utf16->data,
1835 io->n.cleartext_utf16->length,
1837 if (gret != GPG_ERR_NO_ERROR) {
1838 ldb_debug(ldb, LDB_DEBUG_ERROR,
1839 "%s:%s: gret[%u] %s\n",
1840 __location__, __func__,
1841 gret, gpgme_strerror(gret));
1843 return ldb_module_operr(io->ac->module);
1845 gret = gpgme_data_new(&crypt_data);
1846 if (gret != GPG_ERR_NO_ERROR) {
1847 ldb_debug(ldb, LDB_DEBUG_ERROR,
1848 "%s:%s: gret[%u] %s\n",
1849 __location__, __func__,
1850 gret, gpgme_strerror(gret));
1851 gpgme_data_release(plain_data);
1853 return ldb_module_operr(io->ac->module);
1856 for (ki = 0; ki < num_keys; ki++) {
1857 const char *key_id = io->ac->gpg_key_ids[ki];
1858 size_t len = strlen(key_id);
1863 ldb_debug(ldb, LDB_DEBUG_FATAL,
1864 "%s:%s: ki[%zu] key_id[%s] strlen < 16, "
1865 "please specify at least the 64bit key id\n",
1866 __location__, __func__,
1868 for (kr = 0; keys[kr] != NULL; kr++) {
1869 gpgme_key_release(keys[kr]);
1871 gpgme_data_release(crypt_data);
1872 gpgme_data_release(plain_data);
1874 return ldb_module_operr(io->ac->module);
1877 gret = gpgme_get_key(ctx, key_id, &keys[ki], 0 /* public key */);
1878 if (gret != GPG_ERR_NO_ERROR) {
1880 if (gpg_err_source(gret) == GPG_ERR_SOURCE_GPGME
1881 && gpg_err_code(gret) == GPG_ERR_EOF) {
1882 ldb_debug(ldb, LDB_DEBUG_ERROR,
1884 "'password hash gpg key ids': "
1885 "Public Key ID [%s] "
1886 "not found in keyring\n",
1890 ldb_debug(ldb, LDB_DEBUG_ERROR,
1891 "%s:%s: ki[%zu] key_id[%s] "
1893 __location__, __func__,
1895 gret, gpgme_strerror(gret));
1897 for (kr = 0; keys[kr] != NULL; kr++) {
1898 gpgme_key_release(keys[kr]);
1900 gpgme_data_release(crypt_data);
1901 gpgme_data_release(plain_data);
1903 return ldb_module_operr(io->ac->module);
1908 gret = gpgme_op_encrypt(ctx, keys,
1909 GPGME_ENCRYPT_ALWAYS_TRUST,
1910 plain_data, crypt_data);
1911 gpgme_data_release(plain_data);
1913 for (kr = 0; keys[kr] != NULL; kr++) {
1914 gpgme_key_release(keys[kr]);
1919 if (gret != GPG_ERR_NO_ERROR) {
1920 ldb_debug(ldb, LDB_DEBUG_ERROR,
1921 "%s:%s: gret[%u] %s\n",
1922 __location__, __func__,
1923 gret, gpgme_strerror(gret));
1924 gpgme_data_release(crypt_data);
1925 return ldb_module_operr(io->ac->module);
1928 crypt_mem = gpgme_data_release_and_get_mem(crypt_data, &crypt_length);
1930 if (crypt_mem == NULL) {
1931 return ldb_module_oom(io->ac->module);
1934 pgb->gpg_blob = data_blob_talloc(io->ac,
1935 (const uint8_t *)crypt_mem,
1937 gpgme_free(crypt_mem);
1940 if (pgb->gpg_blob.data == NULL) {
1941 return ldb_module_oom(io->ac->module);
1945 #else /* ENABLE_GPGME */
1946 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1947 "You configured 'password hash gpg key ids', "
1948 "but GPGME support is missing. (%s:%d)",
1949 __FILE__, __LINE__);
1950 return LDB_ERR_UNWILLING_TO_PERFORM;
1951 #endif /* else ENABLE_GPGME */
1954 #define NUM_PACKAGES 6
1955 static int setup_supplemental_field(struct setup_password_fields_io *io)
1957 struct ldb_context *ldb;
1958 struct supplementalCredentialsBlob scb = {};
1959 struct supplementalCredentialsBlob *old_scb = NULL;
1962 * ( Kerberos-Newer-Keys, Kerberos,
1963 * WDigest, CLEARTEXT, userPassword, SambaGPG)
1965 uint32_t num_names = 0;
1966 const char *names[1+NUM_PACKAGES] = {};
1967 uint32_t num_packages = 0;
1968 struct supplementalCredentialsPackage packages[1+NUM_PACKAGES] = {};
1969 struct supplementalCredentialsPackage *pp = packages;
1971 enum ndr_err_code ndr_err;
1972 bool do_newer_keys = false;
1973 bool do_cleartext = false;
1974 bool do_samba_gpg = false;
1975 struct loadparm_context *lp_ctx = NULL;
1977 ldb = ldb_module_get_ctx(io->ac->module);
1978 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
1979 struct loadparm_context);
1981 if (!io->n.cleartext_utf8) {
1983 * when we don't have a cleartext password
1984 * we can't setup a supplementalCredentials value
1989 /* if there's an old supplementalCredentials blob then use it */
1990 if (io->o.supplemental) {
1991 if (io->o.scb.sub.signature == SUPPLEMENTAL_CREDENTIALS_SIGNATURE) {
1992 old_scb = &io->o.scb;
1994 ldb_debug(ldb, LDB_DEBUG_ERROR,
1995 "setup_supplemental_field: "
1996 "supplementalCredentialsBlob "
1997 "signature[0x%04X] expected[0x%04X]",
1998 io->o.scb.sub.signature,
1999 SUPPLEMENTAL_CREDENTIALS_SIGNATURE);
2002 /* Per MS-SAMR 3.1.1.8.11.6 we create AES keys if our domain functionality level is 2008 or higher */
2007 * The ordering is this
2009 * Primary:Kerberos-Newer-Keys (optional)
2012 * Primary:CLEARTEXT (optional)
2013 * Primary:userPassword
2014 * Primary:SambaGPG (optional)
2016 * And the 'Packages' package is insert before the last
2019 * Note: it's important that Primary:SambaGPG is added as
2020 * the last element. This is the indication that it matches
2021 * the current password. When a password change happens on
2022 * a Windows DC, it will keep the old Primary:SambaGPG value,
2023 * but as the first element.
2025 do_newer_keys = (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2008);
2026 if (do_newer_keys) {
2027 struct package_PrimaryKerberosBlob pknb;
2028 DATA_BLOB pknb_blob;
2031 * setup 'Primary:Kerberos-Newer-Keys' element
2033 names[num_names++] = "Kerberos-Newer-Keys";
2035 ret = setup_primary_kerberos_newer(io, old_scb, &pknb);
2036 if (ret != LDB_SUCCESS) {
2040 ndr_err = ndr_push_struct_blob(
2043 (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
2044 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2045 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2046 ldb_asprintf_errstring(
2048 "setup_supplemental_field: "
2050 "package_PrimaryKerberosNeverBlob: %s",
2052 return LDB_ERR_OPERATIONS_ERROR;
2054 pknb_hexstr = data_blob_hex_string_upper(io->ac, &pknb_blob);
2056 return ldb_oom(ldb);
2058 pp->name = "Primary:Kerberos-Newer-Keys";
2060 pp->data = pknb_hexstr;
2067 * setup 'Primary:Kerberos' element
2069 /* Primary:Kerberos */
2070 struct package_PrimaryKerberosBlob pkb;
2074 names[num_names++] = "Kerberos";
2076 ret = setup_primary_kerberos(io, old_scb, &pkb);
2077 if (ret != LDB_SUCCESS) {
2081 ndr_err = ndr_push_struct_blob(
2084 (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
2085 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2086 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2087 ldb_asprintf_errstring(
2089 "setup_supplemental_field: "
2090 "failed to push package_PrimaryKerberosBlob: %s",
2092 return LDB_ERR_OPERATIONS_ERROR;
2094 pkb_hexstr = data_blob_hex_string_upper(io->ac, &pkb_blob);
2096 return ldb_oom(ldb);
2098 pp->name = "Primary:Kerberos";
2100 pp->data = pkb_hexstr;
2105 if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_ALLOWED) {
2107 * setup 'Primary:WDigest' element
2109 struct package_PrimaryWDigestBlob pdb;
2113 names[num_names++] = "WDigest";
2115 ret = setup_primary_wdigest(io, old_scb, &pdb);
2116 if (ret != LDB_SUCCESS) {
2120 ndr_err = ndr_push_struct_blob(
2123 (ndr_push_flags_fn_t)ndr_push_package_PrimaryWDigestBlob);
2124 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2125 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2126 ldb_asprintf_errstring(
2128 "setup_supplemental_field: "
2129 "failed to push package_PrimaryWDigestBlob: %s",
2131 return LDB_ERR_OPERATIONS_ERROR;
2133 pdb_hexstr = data_blob_hex_string_upper(io->ac, &pdb_blob);
2135 return ldb_oom(ldb);
2137 pp->name = "Primary:WDigest";
2139 pp->data = pdb_hexstr;
2145 * setup 'Primary:CLEARTEXT' element
2147 if (io->ac->status->domain_data.store_cleartext &&
2148 (io->u.userAccountControl & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) {
2149 do_cleartext = true;
2152 struct package_PrimaryCLEARTEXTBlob pcb;
2156 names[num_names++] = "CLEARTEXT";
2158 pcb.cleartext = *io->n.cleartext_utf16;
2160 ndr_err = ndr_push_struct_blob(
2163 (ndr_push_flags_fn_t)ndr_push_package_PrimaryCLEARTEXTBlob);
2164 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2165 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2166 ldb_asprintf_errstring(
2168 "setup_supplemental_field: "
2169 "failed to push package_PrimaryCLEARTEXTBlob: %s",
2171 return LDB_ERR_OPERATIONS_ERROR;
2173 pcb_hexstr = data_blob_hex_string_upper(io->ac, &pcb_blob);
2175 return ldb_oom(ldb);
2177 pp->name = "Primary:CLEARTEXT";
2179 pp->data = pcb_hexstr;
2185 * Don't generate crypt() or similar password for the krbtgt account.
2186 * It's unnecessary, and the length of the cleartext in UTF-8 form
2187 * exceeds the maximum (CRYPT_MAX_PASSPHRASE_SIZE) allowed by crypt().
2189 if (io->ac->userPassword_schemes && !io->u.is_krbtgt) {
2191 * setup 'Primary:userPassword' element
2193 struct package_PrimaryUserPasswordBlob
2195 DATA_BLOB p_userPassword_b_blob;
2196 char *p_userPassword_b_hexstr;
2198 names[num_names++] = "userPassword";
2200 ret = setup_primary_userPassword(io,
2203 if (ret != LDB_SUCCESS) {
2207 ndr_err = ndr_push_struct_blob(
2208 &p_userPassword_b_blob,
2211 (ndr_push_flags_fn_t)
2212 ndr_push_package_PrimaryUserPasswordBlob);
2213 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2214 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2215 ldb_asprintf_errstring(
2217 "setup_supplemental_field: failed to push "
2218 "package_PrimaryUserPasswordBlob: %s",
2220 return LDB_ERR_OPERATIONS_ERROR;
2222 p_userPassword_b_hexstr
2223 = data_blob_hex_string_upper(
2225 &p_userPassword_b_blob);
2226 if (!p_userPassword_b_hexstr) {
2227 return ldb_oom(ldb);
2229 pp->name = "Primary:userPassword";
2231 pp->data = p_userPassword_b_hexstr;
2237 * setup 'Primary:SambaGPG' element
2239 if (io->ac->gpg_key_ids != NULL) {
2240 do_samba_gpg = true;
2243 struct package_PrimarySambaGPGBlob pgb;
2247 names[num_names++] = "SambaGPG";
2249 ret = setup_primary_samba_gpg(io, &pgb);
2250 if (ret != LDB_SUCCESS) {
2254 ndr_err = ndr_push_struct_blob(&pgb_blob, io->ac, &pgb,
2255 (ndr_push_flags_fn_t)ndr_push_package_PrimarySambaGPGBlob);
2256 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2257 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2258 ldb_asprintf_errstring(ldb,
2259 "setup_supplemental_field: failed to "
2260 "push package_PrimarySambaGPGBlob: %s",
2262 return LDB_ERR_OPERATIONS_ERROR;
2264 pgb_hexstr = data_blob_hex_string_upper(io->ac, &pgb_blob);
2266 return ldb_oom(ldb);
2268 pp->name = "Primary:SambaGPG";
2270 pp->data = pgb_hexstr;
2276 * setup 'Packages' element
2279 struct package_PackagesBlob pb;
2284 ndr_err = ndr_push_struct_blob(
2287 (ndr_push_flags_fn_t)ndr_push_package_PackagesBlob);
2288 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2289 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2290 ldb_asprintf_errstring(
2292 "setup_supplemental_field: "
2293 "failed to push package_PackagesBlob: %s",
2295 return LDB_ERR_OPERATIONS_ERROR;
2297 pb_hexstr = data_blob_hex_string_upper(io->ac, &pb_blob);
2299 return ldb_oom(ldb);
2301 pp->name = "Packages";
2303 pp->data = pb_hexstr;
2306 * We don't increment pp so it's pointing to the last package
2311 * setup 'supplementalCredentials' value
2315 * The 'Packages' element needs to be the second last element
2316 * in supplementalCredentials
2318 struct supplementalCredentialsPackage temp;
2319 struct supplementalCredentialsPackage *prev;
2326 scb.sub.signature = SUPPLEMENTAL_CREDENTIALS_SIGNATURE;
2327 scb.sub.num_packages = num_packages;
2328 scb.sub.packages = packages;
2330 ndr_err = ndr_push_struct_blob(
2331 &io->g.supplemental, io->ac,
2333 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
2334 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2335 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2336 ldb_asprintf_errstring(
2338 "setup_supplemental_field: "
2339 "failed to push supplementalCredentialsBlob: %s",
2341 return LDB_ERR_OPERATIONS_ERROR;
2348 static int setup_last_set_field(struct setup_password_fields_io *io)
2350 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2351 const struct ldb_message *msg = NULL;
2352 struct timeval tv = { .tv_sec = 0 };
2353 const struct ldb_val *old_val = NULL;
2354 const struct ldb_val *new_val = NULL;
2357 switch (io->ac->req->operation) {
2359 msg = io->ac->req->op.add.message;
2362 msg = io->ac->req->op.mod.message;
2365 return LDB_ERR_OPERATIONS_ERROR;
2369 if (io->ac->pwd_last_set_bypass) {
2370 struct ldb_message_element *el = NULL;
2374 * This is a message from pdb_samba_dsdb_replace_by_sam()
2376 * We want to ensure there is only one pwdLastSet element, and
2377 * it isn't deleting.
2380 return LDB_ERR_CONSTRAINT_VIOLATION;
2383 for (i = 0; i < msg->num_elements; i++) {
2384 if (ldb_attr_cmp(msg->elements[i].name,
2385 "pwdLastSet") == 0) {
2387 el = &msg->elements[i];
2391 return LDB_ERR_CONSTRAINT_VIOLATION;
2394 if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
2395 return LDB_ERR_CONSTRAINT_VIOLATION;
2398 io->g.last_set = samdb_result_nttime(msg, "pwdLastSet", 0);
2402 ret = msg_find_old_and_new_pwd_val(msg, "pwdLastSet",
2403 io->ac->req->operation,
2404 &new_val, &old_val);
2405 if (ret != LDB_SUCCESS) {
2409 if (old_val != NULL && new_val == NULL) {
2410 ldb_set_errstring(ldb,
2411 "'pwdLastSet' deletion is not allowed!");
2412 return LDB_ERR_UNWILLING_TO_PERFORM;
2415 io->g.last_set = UINT64_MAX;
2416 if (new_val != NULL) {
2417 struct ldb_message *tmp_msg = NULL;
2419 tmp_msg = ldb_msg_new(io->ac);
2420 if (tmp_msg == NULL) {
2421 return ldb_module_oom(io->ac->module);
2424 if (old_val != NULL) {
2425 NTTIME old_last_set = 0;
2427 ret = ldb_msg_add_value(tmp_msg, "oldval",
2429 if (ret != LDB_SUCCESS) {
2433 old_last_set = samdb_result_nttime(tmp_msg,
2436 if (io->u.pwdLastSet != old_last_set) {
2437 return dsdb_module_werror(io->ac->module,
2438 LDB_ERR_NO_SUCH_ATTRIBUTE,
2439 WERR_DS_CANT_REM_MISSING_ATT_VAL,
2440 "setup_last_set_field: old pwdLastSet "
2441 "value not found!");
2445 ret = ldb_msg_add_value(tmp_msg, "newval",
2447 if (ret != LDB_SUCCESS) {
2451 io->g.last_set = samdb_result_nttime(tmp_msg,
2454 } else if (ldb_msg_find_element(msg, "pwdLastSet")) {
2455 ldb_set_errstring(ldb,
2456 "'pwdLastSet' deletion is not allowed!");
2457 return LDB_ERR_UNWILLING_TO_PERFORM;
2458 } else if (io->ac->smartcard_reset) {
2460 * adding UF_SMARTCARD_REQUIRED doesn't update
2461 * pwdLastSet implicitly.
2463 io->ac->update_lastset = false;
2466 /* only 0 or -1 (0xFFFFFFFFFFFFFFFF) are allowed */
2467 switch (io->g.last_set) {
2469 if (!io->ac->pwd_last_set_default) {
2472 if (!io->ac->update_password) {
2477 if (!io->ac->update_password &&
2478 io->u.pwdLastSet != 0 &&
2479 io->u.pwdLastSet != UINT64_MAX)
2482 * Just setting pwdLastSet to -1, while not changing
2483 * any password field has no effect if pwdLastSet
2484 * is already non-zero.
2486 io->ac->update_lastset = false;
2489 /* -1 means set it as now */
2491 io->g.last_set = timeval_to_nttime(&tv);
2494 return dsdb_module_werror(io->ac->module,
2496 WERR_INVALID_PARAMETER,
2497 "setup_last_set_field: "
2498 "pwdLastSet must be 0 or -1 only!");
2501 if (io->ac->req->operation == LDB_ADD) {
2503 * We always need to store the value on add
2509 if (io->g.last_set == io->u.pwdLastSet) {
2511 * Just setting pwdLastSet to 0, is no-op if it's already 0.
2513 io->ac->update_lastset = false;
2519 static int setup_given_passwords(struct setup_password_fields_io *io,
2520 struct setup_password_fields_given *g)
2522 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2524 if (g->cleartext_utf8) {
2525 struct ldb_val *cleartext_utf16_blob;
2527 cleartext_utf16_blob = talloc(io->ac, struct ldb_val);
2528 if (!cleartext_utf16_blob) {
2529 return ldb_oom(ldb);
2531 if (!convert_string_talloc(io->ac,
2533 g->cleartext_utf8->data,
2534 g->cleartext_utf8->length,
2535 &cleartext_utf16_blob->data,
2536 &cleartext_utf16_blob->length)) {
2537 if (g->cleartext_utf8->length != 0) {
2538 talloc_free(cleartext_utf16_blob);
2539 ldb_asprintf_errstring(ldb,
2540 "setup_password_fields: "
2541 "failed to generate UTF16 password from cleartext UTF8 one for user '%s'!",
2542 io->u.sAMAccountName);
2543 return LDB_ERR_CONSTRAINT_VIOLATION;
2545 /* passwords with length "0" are valid! */
2546 cleartext_utf16_blob->data = NULL;
2547 cleartext_utf16_blob->length = 0;
2550 g->cleartext_utf16 = cleartext_utf16_blob;
2551 } else if (g->cleartext_utf16) {
2552 struct ldb_val *cleartext_utf8_blob;
2554 cleartext_utf8_blob = talloc(io->ac, struct ldb_val);
2555 if (!cleartext_utf8_blob) {
2556 return ldb_oom(ldb);
2558 if (!convert_string_talloc(io->ac,
2559 CH_UTF16MUNGED, CH_UTF8,
2560 g->cleartext_utf16->data,
2561 g->cleartext_utf16->length,
2562 &cleartext_utf8_blob->data,
2563 &cleartext_utf8_blob->length)) {
2564 if (g->cleartext_utf16->length != 0) {
2565 /* We must bail out here, the input wasn't even
2566 * a multiple of 2 bytes */
2567 talloc_free(cleartext_utf8_blob);
2568 ldb_asprintf_errstring(ldb,
2569 "setup_password_fields: "
2570 "failed to generate UTF8 password from cleartext UTF 16 one for user '%s' - the latter had odd length (length must be a multiple of 2)!",
2571 io->u.sAMAccountName);
2572 return LDB_ERR_CONSTRAINT_VIOLATION;
2574 /* passwords with length "0" are valid! */
2575 cleartext_utf8_blob->data = NULL;
2576 cleartext_utf8_blob->length = 0;
2579 g->cleartext_utf8 = cleartext_utf8_blob;
2582 if (g->cleartext_utf16) {
2583 struct samr_Password *nt_hash;
2585 nt_hash = talloc(io->ac, struct samr_Password);
2587 return ldb_oom(ldb);
2589 g->nt_hash = nt_hash;
2591 /* compute the new nt hash */
2592 mdfour(nt_hash->hash,
2593 g->cleartext_utf16->data,
2594 g->cleartext_utf16->length);
2598 * We need to build one more hash, so we can compare with what might
2599 * have been stored in the old password (for the LDAP password change)
2601 * We don't have any old salts, so we won't catch password reuse if said
2602 * password was used prior to an account rename and another password
2605 * We don't have to store the 'opaque' (string2key iterations)
2606 * as Heimdal doesn't allow that to be changed.
2608 if (g->cleartext_utf8 != NULL) {
2609 int ret = setup_kerberos_key_hash(io, g);
2610 if (ret != LDB_SUCCESS) {
2618 static int setup_password_fields(struct setup_password_fields_io *io)
2620 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2623 ret = setup_last_set_field(io);
2624 if (ret != LDB_SUCCESS) {
2628 if (!io->ac->update_password) {
2632 if (io->u.is_krbtgt) {
2635 size_t diff = max - min;
2637 struct ldb_val *krbtgt_utf16 = NULL;
2639 if (!io->ac->pwd_reset) {
2640 return dsdb_module_werror(io->ac->module,
2641 LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS,
2642 WERR_DS_ATT_ALREADY_EXISTS,
2643 "Password change on krbtgt not permitted!");
2646 if (io->n.cleartext_utf16 == NULL) {
2647 return dsdb_module_werror(io->ac->module,
2648 LDB_ERR_UNWILLING_TO_PERFORM,
2649 WERR_DS_INVALID_ATTRIBUTE_SYNTAX,
2650 "Password reset on krbtgt requires UTF16!");
2654 * Instead of taking the callers value,
2655 * we just generate a new random value here.
2657 * Include null termination in the array.
2662 generate_random_buffer((uint8_t *)&tmp, sizeof(tmp));
2669 krbtgt_utf16 = talloc_zero(io->ac, struct ldb_val);
2670 if (krbtgt_utf16 == NULL) {
2671 return ldb_oom(ldb);
2674 *krbtgt_utf16 = data_blob_talloc_zero(krbtgt_utf16,
2676 if (krbtgt_utf16->data == NULL) {
2677 return ldb_oom(ldb);
2679 krbtgt_utf16->length = len * 2;
2680 generate_secret_buffer(krbtgt_utf16->data,
2681 krbtgt_utf16->length);
2682 io->n.cleartext_utf16 = krbtgt_utf16;
2685 /* transform the old password (for password changes) */
2686 ret = setup_given_passwords(io, &io->og);
2687 if (ret != LDB_SUCCESS) {
2691 /* transform the new password */
2692 ret = setup_given_passwords(io, &io->n);
2693 if (ret != LDB_SUCCESS) {
2697 if (io->n.cleartext_utf8) {
2698 ret = setup_kerberos_keys(io);
2699 if (ret != LDB_SUCCESS) {
2705 * This relies on setup_kerberos_keys to make a NT-hash-like
2706 * value for password history purposes
2709 ret = setup_nt_fields(io);
2710 if (ret != LDB_SUCCESS) {
2714 ret = setup_supplemental_field(io);
2715 if (ret != LDB_SUCCESS) {
2722 static int setup_smartcard_reset(struct setup_password_fields_io *io)
2724 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2725 struct supplementalCredentialsBlob scb = { .__ndr_size = 0 };
2726 enum ndr_err_code ndr_err;
2728 if (!io->ac->smartcard_reset) {
2732 io->g.nt_hash = talloc(io->ac, struct samr_Password);
2733 if (io->g.nt_hash == NULL) {
2734 return ldb_module_oom(io->ac->module);
2736 generate_secret_buffer(io->g.nt_hash->hash,
2737 sizeof(io->g.nt_hash->hash));
2738 io->g.nt_history_len = 0;
2741 * We take the "old" value and store it
2742 * with num_packages = 0.
2744 * On "add" we have scb.sub.signature == 0, which
2747 * [0000] 00 00 00 00 00 00 00 00 00 00 00 00 00
2749 * On modify it's likely to be scb.sub.signature ==
2750 * SUPPLEMENTAL_CREDENTIALS_SIGNATURE (0x0050), which results in
2753 * [0000] 00 00 00 00 62 00 00 00 00 00 00 00 20 00 20 00
2754 * [0010] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2755 * [0020] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2756 * [0030] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2757 * [0040] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2758 * [0050] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2759 * [0060] 20 00 20 00 20 00 20 00 20 00 20 00 50 00 00
2761 * See https://bugzilla.samba.org/show_bug.cgi?id=11441
2762 * and ndr_{push,pull}_supplementalCredentialsSubBlob().
2765 scb.sub.num_packages = 0;
2768 * setup 'supplementalCredentials' value without packages
2770 ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac,
2772 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
2773 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2774 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2775 ldb_asprintf_errstring(ldb,
2776 "setup_smartcard_reset: "
2777 "failed to push supplementalCredentialsBlob: %s",
2779 return LDB_ERR_OPERATIONS_ERROR;
2782 io->ac->update_password = true;
2786 static int make_error_and_update_badPwdCount(struct setup_password_fields_io *io, WERROR *werror)
2788 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2789 struct ldb_message *mod_msg = NULL;
2790 struct ldb_message *pso_msg = NULL;
2791 struct ldb_message *current = NULL;
2792 NTSTATUS status = NT_STATUS_OK;
2793 int ret; /* The errors we will actually return */
2794 int dbg_ret; /* The errors we can only complain about in logs */
2797 * OK, horrible semantics ahead.
2799 * - We need to abort any existing transaction
2800 * - create a transaction around the badPwdCount update
2801 * - re-open the transaction so the upper layer
2802 * doesn't know what happened.
2804 * This is needed because returning an error to the upper
2805 * layer will cancel the transaction and undo the badPwdCount
2810 * Checking errors here is a bit pointless.
2811 * What can we do if we can't end the transaction?
2813 dbg_ret = ldb_next_del_trans(io->ac->module);
2814 if (dbg_ret != LDB_SUCCESS) {
2815 ldb_debug(ldb, LDB_DEBUG_FATAL,
2816 "Failed to abort transaction prior to update of badPwdCount of %s: %s",
2817 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2818 ldb_errstring(ldb));
2820 * just return the original error
2825 /* Likewise, what should we do if we can't open a new transaction? */
2826 dbg_ret = ldb_next_start_trans(io->ac->module);
2827 if (dbg_ret != LDB_SUCCESS) {
2828 ldb_debug(ldb, LDB_DEBUG_ERROR,
2829 "Failed to open transaction to update badPwdCount of %s: %s",
2830 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2831 ldb_errstring(ldb));
2833 * just return the original error
2839 * Re-read the account details, using the GUID in case the DN
2842 status = authsam_reread_user_logon_data(
2844 io->ac->search_res->message,
2846 if (!NT_STATUS_IS_OK(status)) {
2847 /* The re-read can return account locked out, as well
2848 * as an internal error
2850 goto end_transaction;
2853 /* PSO search result is optional (NULL if no PSO applies) */
2854 if (io->ac->pso_res != NULL) {
2855 pso_msg = io->ac->pso_res->message;
2858 status = dsdb_update_bad_pwd_count(io->ac, ldb,
2860 io->ac->dom_res->message,
2863 if (!NT_STATUS_IS_OK(status)) {
2864 goto end_transaction;
2867 if (mod_msg == NULL) {
2868 goto end_transaction;
2871 dbg_ret = dsdb_module_modify(io->ac->module, mod_msg,
2872 DSDB_FLAG_NEXT_MODULE,
2874 if (dbg_ret != LDB_SUCCESS) {
2875 ldb_debug(ldb, LDB_DEBUG_ERROR,
2876 "Failed to update badPwdCount of %s: %s",
2877 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2878 ldb_errstring(ldb));
2880 * We can only ignore this...
2885 dbg_ret = ldb_next_end_trans(io->ac->module);
2886 if (dbg_ret != LDB_SUCCESS) {
2887 ldb_debug(ldb, LDB_DEBUG_ERROR,
2888 "Failed to close transaction to update badPwdCount of %s: %s",
2889 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2890 ldb_errstring(ldb));
2892 * We can only ignore this...
2896 dbg_ret = ldb_next_start_trans(io->ac->module);
2897 if (dbg_ret != LDB_SUCCESS) {
2898 ldb_debug(ldb, LDB_DEBUG_ERROR,
2899 "Failed to open transaction after update of badPwdCount of %s: %s",
2900 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2901 ldb_errstring(ldb));
2903 * We can only ignore this...
2908 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2909 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
2910 *werror = WERR_ACCOUNT_LOCKED_OUT;
2912 *werror = WERR_INVALID_PASSWORD;
2914 ldb_asprintf_errstring(ldb,
2915 "%08X: %s - check_password_restrictions: "
2916 "The old password specified doesn't match!",
2922 static int check_password_restrictions(struct setup_password_fields_io *io, WERROR *werror)
2924 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2927 struct loadparm_context *lp_ctx =
2928 talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2929 struct loadparm_context);
2930 struct dsdb_encrypted_connection_state *opaque_connection_state =
2931 ldb_get_opaque(ldb,DSDB_OPAQUE_ENCRYPTED_CONNECTION_STATE_NAME);
2933 *werror = WERR_INVALID_PARAMETER;
2935 if (!io->ac->update_password) {
2940 * Prevent update password on an insecure connection.
2941 * The opaque is added in the ldap backend init.
2943 if (opaque_connection_state != NULL &&
2944 !opaque_connection_state->using_encrypted_connection) {
2945 ret = LDB_ERR_UNWILLING_TO_PERFORM;
2946 *werror = WERR_GEN_FAILURE;
2947 ldb_asprintf_errstring(ldb,
2948 "%08X: SvcErr: DSID-031A126C, "
2949 "problem 5003 (WILL_NOT_PERFORM), "
2951 "Password modification over LDAP "
2952 "must be over an encrypted connection",
2953 W_ERROR_V(*werror));
2958 * First check the old password is correct, for password
2959 * changes when this hasn't already been checked by a
2960 * trustworthy layer above
2962 if (!io->ac->pwd_reset && !(io->ac->change
2963 && io->ac->change->old_password_checked == DSDB_PASSWORD_CHECKED_AND_CORRECT)) {
2964 bool hash_checked = false;
2966 * we need the old nt hash given by the client (this
2967 * is for the plaintext over LDAP password change,
2968 * Kpasswd and SAMR supply the control)
2970 if (io->og.nt_hash == NULL && io->og.aes_256.length == 0) {
2971 ldb_asprintf_errstring(ldb,
2972 "check_password_restrictions: "
2973 "You need to provide the old password in order "
2975 return LDB_ERR_UNWILLING_TO_PERFORM;
2979 * First compare the ENCTYPE_AES256_CTS_HMAC_SHA1_96 password and see if we have a match
2982 if (io->og.aes_256.length > 0 && io->o.aes_256.length) {
2983 hash_checked = data_blob_equal_const_time(&io->og.aes_256, &io->o.aes_256);
2986 /* The password modify through the NT hash is encouraged and
2987 has no problems at all */
2988 if (!hash_checked && io->og.nt_hash && io->o.nt_hash) {
2989 hash_checked = mem_equal_const_time(io->og.nt_hash->hash, io->o.nt_hash->hash, 16);
2992 if (!hash_checked) {
2993 return make_error_and_update_badPwdCount(io, werror);
2997 if (io->u.restrictions == 0) {
2998 /* FIXME: Is this right? */
3002 /* Password minimum age: yes, this is a minus. The ages are in negative 100nsec units! */
3003 if ((io->u.pwdLastSet - io->ac->status->domain_data.minPwdAge > io->g.last_set) &&
3006 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3007 *werror = WERR_PASSWORD_RESTRICTION;
3008 ldb_asprintf_errstring(ldb,
3009 "%08X: %s - check_password_restrictions: "
3010 "password is too young to change!",
3017 * Fundamental password checks done by the call
3018 * "samdb_check_password".
3019 * It is also in use by "dcesrv_samr_ValidatePassword".
3021 if (io->n.cleartext_utf8 != NULL) {
3022 enum samr_ValidationStatus vstat;
3023 vstat = samdb_check_password(io->ac, lp_ctx,
3024 io->u.sAMAccountName,
3025 io->u.user_principal_name,
3027 io->n.cleartext_utf8,
3028 io->ac->status->domain_data.pwdProperties,
3029 io->ac->status->domain_data.minPwdLength);
3031 case SAMR_VALIDATION_STATUS_SUCCESS:
3032 /* perfect -> proceed! */
3035 case SAMR_VALIDATION_STATUS_PWD_TOO_SHORT:
3036 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3037 *werror = WERR_PASSWORD_RESTRICTION;
3038 ldb_asprintf_errstring(ldb,
3039 "%08X: %s - check_password_restrictions: "
3040 "the password is too short. It should be equal to or longer than %u characters!",
3043 io->ac->status->domain_data.minPwdLength);
3044 io->ac->status->reject_reason = SAM_PWD_CHANGE_PASSWORD_TOO_SHORT;
3047 case SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH:
3048 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3049 *werror = WERR_PASSWORD_RESTRICTION;
3050 ldb_asprintf_errstring(ldb,
3051 "%08X: %s - check_password_restrictions: "
3052 "the password does not meet the complexity criteria!",
3055 io->ac->status->reject_reason = SAM_PWD_CHANGE_NOT_COMPLEX;
3059 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3060 *werror = WERR_PASSWORD_RESTRICTION;
3061 ldb_asprintf_errstring(ldb,
3062 "%08X: %s - check_password_restrictions: "
3063 "the password doesn't fit due to a miscellaneous restriction!",
3070 if (io->ac->pwd_reset) {
3076 * This check works by using the current Kerberos password to
3077 * make up a password history. We already did the salted hash
3078 * creation to pass the password change check.
3080 * We check the pwdHistoryLength to ensure we honour the
3081 * policy on if the history should be checked
3083 if (io->ac->status->domain_data.pwdHistoryLength > 0
3084 && io->g.aes_256.length && io->o.aes_256.length)
3086 bool equal = data_blob_equal_const_time(&io->g.aes_256,
3089 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3090 *werror = WERR_PASSWORD_RESTRICTION;
3091 ldb_asprintf_errstring(ldb,
3092 "%08X: %s - check_password_restrictions: "
3093 "the password was already used (previous password)!",
3096 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
3101 if (io->n.nt_hash) {
3103 * checks the NT hash password history, against the
3106 for (i = 0; i < io->o.nt_history_len; i++) {
3107 bool pw_cmp = mem_equal_const_time(io->n.nt_hash, io->o.nt_history[i].hash, 16);
3109 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3110 *werror = WERR_PASSWORD_RESTRICTION;
3111 ldb_asprintf_errstring(ldb,
3112 "%08X: %s - check_password_restrictions: "
3113 "the password was already used (in history)!",
3116 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
3123 * This check works by using the old Kerberos passwords
3124 * (old and older) to make up a password history.
3126 * We check the pwdHistoryLength to ensure we honour the
3127 * policy on if the history should be checked
3130 i <= io->o.kvno && i < MIN(3, io->ac->status->domain_data.pwdHistoryLength);
3133 krb5_error_code krb5_ret;
3134 const uint32_t request_kvno = io->o.kvno - i;
3135 DATA_BLOB db_key_blob;
3138 if (io->n.cleartext_utf8 == NULL) {
3140 * No point checking history if we don't have
3141 * a cleartext password.
3146 if (io->ac->search_res == NULL) {
3148 * This is an ADD, no existing history to check
3154 * If this account requires a smartcard for login, we don't
3155 * attempt a comparison with the old password.
3157 if (io->u.userAccountControl & UF_SMARTCARD_REQUIRED) {
3162 * Extract the old ENCTYPE_AES256_CTS_HMAC_SHA1_96 value from
3163 * the supplementalCredentials.
3165 krb5_ret = dsdb_extract_aes_256_key(io->smb_krb5_context->krb5_context,
3167 io->ac->search_res->message,
3168 io->u.userAccountControl,
3169 &request_kvno, /* kvno */
3170 NULL, /* kvno_out */
3173 if (krb5_ret == ENOENT) {
3175 * If there is no old AES hash (perhaps an imported DB with
3176 * just unicodePwd) then we just won't have an old
3177 * password to compare to if there is no NT hash
3180 } else if (krb5_ret) {
3181 ldb_asprintf_errstring(ldb,
3182 "check_password_restrictions: "
3183 "extraction of old[%u - %d = %d] aes256-cts-hmac-sha1-96 key failed: %s",
3184 io->o.kvno, i, io->o.kvno - i,
3185 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
3187 return LDB_ERR_OPERATIONS_ERROR;
3190 /* This is the actual history check */
3191 pw_equal = data_blob_equal_const_time(&io->n.aes_256,
3194 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3195 *werror = WERR_PASSWORD_RESTRICTION;
3196 ldb_asprintf_errstring(ldb,
3197 "%08X: %s - check_password_restrictions: "
3198 "the password was already used (in history)!",
3201 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
3206 /* are all password changes disallowed? */
3207 if (io->ac->status->domain_data.pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
3208 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3209 *werror = WERR_PASSWORD_RESTRICTION;
3210 ldb_asprintf_errstring(ldb,
3211 "%08X: %s - check_password_restrictions: "
3212 "password changes disabled!",
3218 /* can this user change the password? */
3219 if (io->u.userAccountControl & UF_PASSWD_CANT_CHANGE) {
3220 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3221 *werror = WERR_PASSWORD_RESTRICTION;
3222 ldb_asprintf_errstring(ldb,
3223 "%08X: %s - check_password_restrictions: "
3224 "password can't be changed on this account!",
3233 static int check_password_restrictions_and_log(struct setup_password_fields_io *io)
3236 int ret = check_password_restrictions(io, &werror);
3237 struct ph_context *ac = io->ac;
3239 * Password resets are not authentication events, and if the
3240 * upper layer checked the password and supplied the hash
3241 * values as proof, then this is also not an authentication
3242 * even at this layer (already logged). This is to log LDAP
3246 /* Do not record a failure in the auth log below in the success case */
3247 if (ret == LDB_SUCCESS) {
3251 if (ac->pwd_reset == false && ac->change == NULL) {
3252 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3253 struct imessaging_context *msg_ctx;
3254 struct loadparm_context *lp_ctx
3255 = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"),
3256 struct loadparm_context);
3257 NTSTATUS status = werror_to_ntstatus(werror);
3258 const char *domain_name = lpcfg_sam_name(lp_ctx);
3259 void *opaque_remote_address = NULL;
3261 * Forcing this via the NTLM auth structure is not ideal, but
3262 * it is the most practical option right now, and ensures the
3263 * logs are consistent, even if some elements are always NULL.
3265 struct auth_usersupplied_info ui = {
3268 .account_name = io->u.sAMAccountName,
3269 .domain_name = domain_name,
3272 .account_name = io->u.sAMAccountName,
3273 .domain_name = domain_name,
3275 .service_description = "LDAP Password Change",
3276 .auth_description = "LDAP Modify",
3277 .password_type = "plaintext"
3280 opaque_remote_address = ldb_get_opaque(ldb,
3282 if (opaque_remote_address == NULL) {
3283 ldb_asprintf_errstring(ldb,
3284 "Failed to obtain remote address for "
3285 "the LDAP client while changing the "
3287 return LDB_ERR_OPERATIONS_ERROR;
3289 ui.remote_host = talloc_get_type(opaque_remote_address,
3290 struct tsocket_address);
3292 msg_ctx = imessaging_client_init(ac, lp_ctx,
3293 ldb_get_event_context(ldb));
3295 ldb_asprintf_errstring(ldb,
3296 "Failed to generate client messaging context in %s",
3297 lpcfg_imessaging_path(ac, lp_ctx));
3298 return LDB_ERR_OPERATIONS_ERROR;
3300 log_authentication_event(msg_ctx,
3306 io->u.sAMAccountName,
3308 NULL /* client_audit_info */,
3309 NULL /* server_audit_info */);
3315 static int update_final_msg(struct setup_password_fields_io *io)
3317 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
3320 bool update_password = io->ac->update_password;
3321 bool update_scb = io->ac->update_password;
3324 * If we add a user without initial password,
3325 * we need to add replication meta data for
3326 * following attributes:
3332 * If we add a user with initial password or a
3333 * password is changed of an existing user,
3334 * we need to replace the following attributes
3335 * with a forced meta data update, e.g. also
3336 * when updating an empty attribute with an empty value:
3341 * - supplementalCredentials
3344 switch (io->ac->req->operation) {
3346 update_password = true;
3347 el_flags |= DSDB_FLAG_INTERNAL_FORCE_META_DATA;
3350 el_flags |= LDB_FLAG_MOD_REPLACE;
3351 el_flags |= DSDB_FLAG_INTERNAL_FORCE_META_DATA;
3354 return ldb_module_operr(io->ac->module);
3357 if (update_password) {
3358 ret = ldb_msg_add_empty(io->ac->update_msg,
3361 if (ret != LDB_SUCCESS) {
3366 * This wipes any old LM password after any password
3369 * This is the same as the previous default behaviour
3370 * of 'lanman auth = no'
3372 ret = ldb_msg_add_empty(io->ac->update_msg,
3375 if (ret != LDB_SUCCESS) {
3378 ret = ldb_msg_add_empty(io->ac->update_msg,
3381 if (ret != LDB_SUCCESS) {
3385 * This wipes any LM password history after any password
3388 * This is the same as the previous default behaviour
3389 * of 'lanman auth = no'
3391 ret = ldb_msg_add_empty(io->ac->update_msg,
3394 if (ret != LDB_SUCCESS) {
3399 ret = ldb_msg_add_empty(io->ac->update_msg,
3400 "supplementalCredentials",
3402 if (ret != LDB_SUCCESS) {
3406 if (io->ac->update_lastset) {
3407 ret = ldb_msg_add_empty(io->ac->update_msg,
3410 if (ret != LDB_SUCCESS) {
3415 if (io->g.nt_hash != NULL) {
3416 ret = samdb_msg_add_hash(ldb, io->ac,
3420 if (ret != LDB_SUCCESS) {
3425 if (io->g.nt_history_len > 0) {
3426 ret = samdb_msg_add_hashes(ldb, io->ac,
3430 io->g.nt_history_len);
3431 if (ret != LDB_SUCCESS) {
3435 if (io->g.supplemental.length > 0) {
3436 ret = ldb_msg_add_value(io->ac->update_msg,
3437 "supplementalCredentials",
3438 &io->g.supplemental, NULL);
3439 if (ret != LDB_SUCCESS) {
3443 if (io->ac->update_lastset) {
3444 ret = samdb_msg_add_uint64(ldb, io->ac,
3448 if (ret != LDB_SUCCESS) {
3457 * This is intended for use by the "password_hash" module since there
3458 * password changes can be specified through one message element with the
3459 * new password (to set) and another one with the old password (to unset).
3461 * The first which sets a password (new value) can have flags
3462 * (LDB_FLAG_MOD_ADD, LDB_FLAG_MOD_REPLACE) but also none (on "add" operations
3463 * for entries). The latter (old value) has always specified
3464 * LDB_FLAG_MOD_DELETE.
3466 * Returns LDB_ERR_CONSTRAINT_VIOLATION and LDB_ERR_UNWILLING_TO_PERFORM if
3467 * matching message elements are malformed in respect to the set/change rules.
3468 * Otherwise it returns LDB_SUCCESS.
3470 static int msg_find_old_and_new_pwd_val(const struct ldb_message *msg,
3472 enum ldb_request_type operation,
3473 const struct ldb_val **new_val,
3474 const struct ldb_val **old_val)
3485 for (i = 0; i < msg->num_elements; i++) {
3486 if (ldb_attr_cmp(msg->elements[i].name, name) != 0) {
3490 if ((operation == LDB_MODIFY) &&
3491 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_DELETE)) {
3492 /* 0 values are allowed */
3493 if (msg->elements[i].num_values == 1) {
3494 *old_val = &msg->elements[i].values[0];
3495 } else if (msg->elements[i].num_values > 1) {
3496 return LDB_ERR_CONSTRAINT_VIOLATION;
3498 } else if ((operation == LDB_MODIFY) &&
3499 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_REPLACE)) {
3500 if (msg->elements[i].num_values > 0) {
3501 *new_val = &msg->elements[i].values[msg->elements[i].num_values - 1];
3503 return LDB_ERR_UNWILLING_TO_PERFORM;
3506 /* Add operations and LDB_FLAG_MOD_ADD */
3507 if (msg->elements[i].num_values > 0) {
3508 *new_val = &msg->elements[i].values[msg->elements[i].num_values - 1];
3510 return LDB_ERR_CONSTRAINT_VIOLATION;
3518 static int setup_io(struct ph_context *ac,
3519 const struct ldb_message *client_msg,
3520 const struct ldb_message *existing_msg,
3521 struct setup_password_fields_io *io)
3523 const struct ldb_val *quoted_utf16, *old_quoted_utf16, *lm_hash, *old_lm_hash;
3524 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3525 struct loadparm_context *lp_ctx = talloc_get_type(
3526 ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
3527 enum store_nt_hash store_hash_setting =
3528 lpcfg_nt_hash_store(lp_ctx);
3530 const struct ldb_message *info_msg = NULL;
3531 struct dom_sid *account_sid = NULL;
3532 int rodc_krbtgt = 0;
3534 *io = (struct setup_password_fields_io) {};
3536 /* Some operations below require kerberos contexts */
3538 if (existing_msg != NULL) {
3540 * This is a modify operation
3542 info_msg = existing_msg;
3545 * This is an add operation
3547 info_msg = client_msg;
3550 ret = smb_krb5_init_context(ac,
3551 (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm"),
3552 &io->smb_krb5_context);
3556 * In the special case of mit krb5.conf vs heimdal, the includedir
3557 * statement causes ret == 22 (KRB5_CONFIG_BADFORMAT) to be returned.
3558 * We look for this case so that we can give a more instructional
3559 * message to the administrator.
3561 if (ret == KRB5_CONFIG_BADFORMAT || ret == EINVAL) {
3562 ldb_asprintf_errstring(ldb, "Failed to setup krb5_context: %s - "
3563 "This could be due to an invalid krb5 configuration. "
3564 "Please check your system's krb5 configuration is correct.",
3565 error_message(ret));
3567 ldb_asprintf_errstring(ldb, "Failed to setup krb5_context: %s",
3568 error_message(ret));
3570 return LDB_ERR_OPERATIONS_ERROR;
3575 io->u.userAccountControl = ldb_msg_find_attr_as_uint(info_msg,
3576 "userAccountControl", 0);
3577 if (info_msg == existing_msg) {
3579 * We only take pwdLastSet from the existing object
3580 * otherwise we leave it as 0.
3582 * If no attribute is available, e.g. on deleted objects
3583 * we remember that as UINT64_MAX.
3585 io->u.pwdLastSet = samdb_result_nttime(info_msg, "pwdLastSet",
3588 io->u.sAMAccountName = ldb_msg_find_attr_as_string(info_msg,
3589 "sAMAccountName", NULL);
3590 io->u.user_principal_name = ldb_msg_find_attr_as_string(info_msg,
3591 "userPrincipalName", NULL);
3592 io->u.displayName = ldb_msg_find_attr_as_string(info_msg,
3593 "displayName", NULL);
3595 /* Ensure it has an objectSID too */
3596 io->u.account_sid = samdb_result_dom_sid(ac, info_msg, "objectSid");
3597 if (io->u.account_sid != NULL) {
3601 status = dom_sid_split_rid(account_sid, io->u.account_sid, NULL, &rid);
3602 if (NT_STATUS_IS_OK(status)) {
3603 if (rid == DOMAIN_RID_KRBTGT) {
3604 io->u.is_krbtgt = true;
3609 rodc_krbtgt = ldb_msg_find_attr_as_int(info_msg,
3610 "msDS-SecondaryKrbTgtNumber", 0);
3611 if (rodc_krbtgt != 0) {
3612 io->u.is_krbtgt = true;
3615 if (io->u.sAMAccountName == NULL) {
3616 ldb_asprintf_errstring(ldb,
3617 "setup_io: sAMAccountName attribute is missing on %s for attempted password set/change",
3618 ldb_dn_get_linearized(info_msg->dn));
3620 return LDB_ERR_CONSTRAINT_VIOLATION;
3623 if (io->u.userAccountControl & UF_INTERDOMAIN_TRUST_ACCOUNT) {
3624 struct ldb_control *permit_trust = ldb_request_get_control(ac->req,
3625 DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
3627 if (permit_trust == NULL) {
3628 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
3629 ldb_asprintf_errstring(ldb,
3630 "%08X: %s - setup_io: changing the interdomain trust password "
3631 "on %s not allowed via LDAP. Use LSA or NETLOGON",
3632 W_ERROR_V(WERR_ACCESS_DENIED),
3634 ldb_dn_get_linearized(info_msg->dn));
3639 /* Only non-trust accounts have restrictions (possibly this test is the
3640 * wrong way around, but we like to be restrictive if possible */
3641 io->u.restrictions = !(io->u.userAccountControl & UF_TRUST_ACCOUNT_MASK);
3643 if (io->u.is_krbtgt) {
3644 io->u.restrictions = 0;
3645 io->ac->status->domain_data.pwdHistoryLength =
3646 MAX(io->ac->status->domain_data.pwdHistoryLength, 3);
3650 * Machine accounts need the NT hash to operate the NETLOGON
3651 * ServerAuthenticate{,2,3} logic
3653 if (!(io->u.userAccountControl & UF_NORMAL_ACCOUNT)) {
3654 store_hash_setting = NT_HASH_STORE_ALWAYS;
3657 switch (store_hash_setting) {
3658 case NT_HASH_STORE_ALWAYS:
3659 io->u.store_nt_hash = true;
3661 case NT_HASH_STORE_NEVER:
3662 io->u.store_nt_hash = false;
3664 case NT_HASH_STORE_AUTO:
3665 if (lpcfg_ntlm_auth(lp_ctx) == NTLM_AUTH_DISABLED) {
3666 io->u.store_nt_hash = false;
3669 io->u.store_nt_hash = true;
3673 if (ac->userPassword) {
3674 ret = msg_find_old_and_new_pwd_val(client_msg, "userPassword",
3676 &io->n.cleartext_utf8,
3677 &io->og.cleartext_utf8);
3678 if (ret != LDB_SUCCESS) {
3679 ldb_asprintf_errstring(ldb,
3681 "it's only allowed to set the old password once!");
3686 if (io->n.cleartext_utf8 != NULL) {
3687 struct ldb_val *cleartext_utf8_blob;
3690 cleartext_utf8_blob = talloc(io->ac, struct ldb_val);
3691 if (!cleartext_utf8_blob) {
3692 return ldb_oom(ldb);
3695 *cleartext_utf8_blob = *io->n.cleartext_utf8;
3697 /* make sure we have a null terminated string */
3698 p = talloc_strndup(cleartext_utf8_blob,
3699 (const char *)io->n.cleartext_utf8->data,
3700 io->n.cleartext_utf8->length);
3701 if ((p == NULL) && (io->n.cleartext_utf8->length > 0)) {
3702 return ldb_oom(ldb);
3704 cleartext_utf8_blob->data = (uint8_t *)p;
3706 io->n.cleartext_utf8 = cleartext_utf8_blob;
3709 ret = msg_find_old_and_new_pwd_val(client_msg, "clearTextPassword",
3711 &io->n.cleartext_utf16,
3712 &io->og.cleartext_utf16);
3713 if (ret != LDB_SUCCESS) {
3714 ldb_asprintf_errstring(ldb,
3716 "it's only allowed to set the old password once!");
3720 /* this rather strange looking piece of code is there to
3721 handle a ldap client setting a password remotely using the
3722 unicodePwd ldap field. The syntax is that the password is
3723 in UTF-16LE, with a " at either end. Unfortunately the
3724 unicodePwd field is also used to store the nt hashes
3725 internally in Samba, and is used in the nt hash format on
3726 the wire in DRS replication, so we have a single name for
3727 two distinct values. The code below leaves us with a small
3728 chance (less than 1 in 2^32) of a mixup, if someone manages
3729 to create a MD4 hash which starts and ends in 0x22 0x00, as
3730 that would then be treated as a UTF16 password rather than
3733 ret = msg_find_old_and_new_pwd_val(client_msg, "unicodePwd",
3737 if (ret != LDB_SUCCESS) {
3738 ldb_asprintf_errstring(ldb,
3740 "it's only allowed to set the old password once!");
3744 /* Checks and converts the actual "unicodePwd" attribute */
3745 if (!ac->hash_values &&
3747 quoted_utf16->length >= 4 &&
3748 quoted_utf16->data[0] == '"' &&
3749 quoted_utf16->data[1] == 0 &&
3750 quoted_utf16->data[quoted_utf16->length-2] == '"' &&
3751 quoted_utf16->data[quoted_utf16->length-1] == 0) {
3752 struct ldb_val *quoted_utf16_2;
3754 if (io->n.cleartext_utf16) {
3755 /* refuse the change if someone wants to change with
3756 with both UTF16 possibilities at the same time... */
3757 ldb_asprintf_errstring(ldb,
3759 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'clearTextPassword'");
3760 return LDB_ERR_UNWILLING_TO_PERFORM;
3764 * adapt the quoted UTF16 string to be a real
3767 quoted_utf16_2 = talloc(io->ac, struct ldb_val);
3768 if (quoted_utf16_2 == NULL) {
3769 return ldb_oom(ldb);
3772 quoted_utf16_2->data = quoted_utf16->data + 2;
3773 quoted_utf16_2->length = quoted_utf16->length-4;
3774 io->n.cleartext_utf16 = quoted_utf16_2;
3775 io->n.nt_hash = NULL;
3777 } else if (quoted_utf16) {
3778 /* We have only the hash available -> so no plaintext here */
3779 if (!ac->hash_values) {
3780 /* refuse the change if someone wants to change
3781 the hash without control specified... */
3782 ldb_asprintf_errstring(ldb,
3784 "it's not allowed to set the NT hash password directly'");
3785 /* this looks odd but this is what Windows does:
3786 returns "UNWILLING_TO_PERFORM" on wrong
3787 password sets and "CONSTRAINT_VIOLATION" on
3788 wrong password changes. */
3789 if (old_quoted_utf16 == NULL) {
3790 return LDB_ERR_UNWILLING_TO_PERFORM;
3793 return LDB_ERR_CONSTRAINT_VIOLATION;
3796 io->n.nt_hash = talloc(io->ac, struct samr_Password);
3797 if (io->n.nt_hash == NULL) {
3798 return ldb_oom(ldb);
3800 memcpy(io->n.nt_hash->hash, quoted_utf16->data,
3801 MIN(quoted_utf16->length, sizeof(io->n.nt_hash->hash)));
3804 /* Checks and converts the previous "unicodePwd" attribute */
3805 if (!ac->hash_values &&
3807 old_quoted_utf16->length >= 4 &&
3808 old_quoted_utf16->data[0] == '"' &&
3809 old_quoted_utf16->data[1] == 0 &&
3810 old_quoted_utf16->data[old_quoted_utf16->length-2] == '"' &&
3811 old_quoted_utf16->data[old_quoted_utf16->length-1] == 0) {
3812 struct ldb_val *old_quoted_utf16_2;
3814 if (io->og.cleartext_utf16) {
3815 /* refuse the change if someone wants to change with
3816 both UTF16 possibilities at the same time... */
3817 ldb_asprintf_errstring(ldb,
3819 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'clearTextPassword'");
3820 return LDB_ERR_UNWILLING_TO_PERFORM;
3824 * adapt the quoted UTF16 string to be a real
3827 old_quoted_utf16_2 = talloc(io->ac, struct ldb_val);
3828 if (old_quoted_utf16_2 == NULL) {
3829 return ldb_oom(ldb);
3832 old_quoted_utf16_2->data = old_quoted_utf16->data + 2;
3833 old_quoted_utf16_2->length = old_quoted_utf16->length-4;
3835 io->og.cleartext_utf16 = old_quoted_utf16_2;
3836 io->og.nt_hash = NULL;
3837 } else if (old_quoted_utf16) {
3838 /* We have only the hash available -> so no plaintext here */
3839 if (!ac->hash_values) {
3840 /* refuse the change if someone wants to change
3841 the hash without control specified... */
3842 ldb_asprintf_errstring(ldb,
3844 "it's not allowed to set the NT hash password directly'");
3845 return LDB_ERR_UNWILLING_TO_PERFORM;
3848 io->og.nt_hash = talloc(io->ac, struct samr_Password);
3849 if (io->og.nt_hash == NULL) {
3850 return ldb_oom(ldb);
3852 memcpy(io->og.nt_hash->hash, old_quoted_utf16->data,
3853 MIN(old_quoted_utf16->length, sizeof(io->og.nt_hash->hash)));
3856 /* Handles the "dBCSPwd" attribute (LM hash) */
3857 ret = msg_find_old_and_new_pwd_val(client_msg, "dBCSPwd",
3859 &lm_hash, &old_lm_hash);
3860 if (ret != LDB_SUCCESS) {
3861 ldb_asprintf_errstring(ldb,
3863 "it's only allowed to set the old password once!");
3867 if (((lm_hash != NULL) || (old_lm_hash != NULL))) {
3868 /* refuse the change if someone wants to change the LM hash */
3869 ldb_asprintf_errstring(ldb,
3871 "it's not allowed to set the LM hash password (dBCSPwd)'");
3872 return LDB_ERR_UNWILLING_TO_PERFORM;
3876 * Handles the password change control if it's specified. It has the
3877 * precedence and overrides already specified old password values of
3878 * change requests (but that shouldn't happen since the control is
3879 * fully internal and only used in conjunction with replace requests!).
3881 if (ac->change != NULL) {
3882 io->og.nt_hash = NULL;
3885 /* refuse the change if someone wants to change the clear-
3886 text and supply his own hashes at the same time... */
3887 if ((io->n.cleartext_utf8 || io->n.cleartext_utf16)
3888 && (io->n.nt_hash)) {
3889 ldb_asprintf_errstring(ldb,
3891 "it's only allowed to set the password in form of cleartext attributes or as hashes");
3892 return LDB_ERR_UNWILLING_TO_PERFORM;
3895 /* refuse the change if someone wants to change the password
3896 using both plaintext methods (UTF8 and UTF16) at the same time... */
3897 if (io->n.cleartext_utf8 && io->n.cleartext_utf16) {
3898 ldb_asprintf_errstring(ldb,
3900 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
3901 return LDB_ERR_UNWILLING_TO_PERFORM;
3904 /* refuse the change if someone tries to set/change the password by
3905 * any method that would leave us without a password! */
3906 if (io->ac->update_password
3907 && (!io->n.cleartext_utf8) && (!io->n.cleartext_utf16)
3908 && (!io->n.nt_hash)) {
3909 ldb_asprintf_errstring(ldb,
3911 "It's not possible to delete the password (changes using the LAN Manager hash alone could be deactivated)!");
3912 /* on "userPassword" and "clearTextPassword" we've to return
3913 * something different, since these are virtual attributes */
3914 if ((ldb_msg_find_element(client_msg, "userPassword") != NULL) ||
3915 (ldb_msg_find_element(client_msg, "clearTextPassword") != NULL)) {
3916 return LDB_ERR_CONSTRAINT_VIOLATION;
3918 return LDB_ERR_UNWILLING_TO_PERFORM;
3922 * refuse the change if someone wants to compare against a
3923 * plaintext or dsdb_control_password_change at the same time
3924 * for a "password modify" operation...
3926 if ((io->og.cleartext_utf8 || io->og.cleartext_utf16)
3928 ldb_asprintf_errstring(ldb,
3930 "it's only allowed to provide the old password in form of cleartext attributes or as the dsdb_control_password_change");
3931 return LDB_ERR_UNWILLING_TO_PERFORM;
3934 /* refuse the change if someone wants to compare against both
3935 * plaintexts at the same time for a "password modify" operation... */
3936 if (io->og.cleartext_utf8 && io->og.cleartext_utf16) {
3937 ldb_asprintf_errstring(ldb,
3939 "it's only allowed to provide the old cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
3940 return LDB_ERR_UNWILLING_TO_PERFORM;
3943 /* Decides if we have a password modify or password reset operation */
3944 if (ac->req->operation == LDB_ADD) {
3945 /* On "add" we have only "password reset" */
3946 ac->pwd_reset = true;
3947 } else if (ac->req->operation == LDB_MODIFY) {
3948 struct ldb_control *pav_ctrl = NULL;
3949 struct dsdb_control_password_acl_validation *pav = NULL;
3951 pav_ctrl = ldb_request_get_control(ac->req,
3952 DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID);
3953 if (pav_ctrl != NULL) {
3954 pav = talloc_get_type_abort(pav_ctrl->data,
3955 struct dsdb_control_password_acl_validation);
3958 if (pav == NULL && ac->update_password) {
3962 * If the DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID
3963 * control is missing, we require system access!
3965 ok = dsdb_module_am_system(ac->module);
3967 return ldb_module_operr(ac->module);
3973 * We assume what the acl module has validated.
3975 ac->pwd_reset = pav->pwd_reset;
3976 } else if (io->og.cleartext_utf8 || io->og.cleartext_utf16
3979 * If we have an old password specified or the
3980 * dsdb_control_password_change then for sure
3981 * it is a user "password change"
3983 ac->pwd_reset = false;
3985 /* Otherwise we have also here a "password reset" */
3986 ac->pwd_reset = true;
3989 /* this shouldn't happen */
3990 return ldb_operr(ldb);
3993 if (existing_msg != NULL) {
3995 krb5_error_code krb5_ret;
3997 DATA_BLOB salt_blob;
4000 if (ac->pwd_reset) {
4001 /* Get the old password from the database */
4002 status = samdb_result_passwords_no_lockout(ac,
4007 /* Get the old password from the database */
4008 status = samdb_result_passwords(ac,
4014 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
4015 return dsdb_module_werror(ac->module,
4016 LDB_ERR_CONSTRAINT_VIOLATION,
4017 WERR_ACCOUNT_LOCKED_OUT,
4018 "Password change not permitted,"
4019 " account locked out!");
4022 if (!NT_STATUS_IS_OK(status)) {
4024 * This only happens if the database has gone weird,
4025 * not if we are just missing the passwords
4027 return ldb_operr(ldb);
4030 io->o.nt_history_len = samdb_result_hashes(ac, existing_msg,
4033 io->o.supplemental = ldb_msg_find_ldb_val(existing_msg,
4034 "supplementalCredentials");
4036 if (io->o.supplemental != NULL) {
4037 enum ndr_err_code ndr_err;
4039 ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac,
4041 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
4042 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4043 status = ndr_map_error2ntstatus(ndr_err);
4044 ldb_asprintf_errstring(ldb,
4045 "setup_io: failed to pull "
4046 "old supplementalCredentialsBlob: %s",
4048 return LDB_ERR_OPERATIONS_ERROR;
4053 * If this account requires a smartcard for login, we don't
4054 * attempt a comparison with the old password.
4056 if (io->u.userAccountControl & UF_SMARTCARD_REQUIRED) {
4061 * Extract the old ENCTYPE_AES256_CTS_HMAC_SHA1_96
4062 * value from the supplementalCredentials.
4064 krb5_ret = dsdb_extract_aes_256_key(io->smb_krb5_context->krb5_context,
4067 io->u.userAccountControl,
4069 &kvno, /* kvno_out */
4072 if (krb5_ret == ENOENT) {
4074 * If there is no old AES hash (perhaps an imported DB with
4075 * just unicodePwd) then we just won't have an old
4076 * password to compare to if there is no NT hash
4081 ldb_asprintf_errstring(ldb,
4083 "extraction of salt for old aes256-cts-hmac-sha1-96 key failed: %s",
4084 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
4086 return LDB_ERR_OPERATIONS_ERROR;
4089 io->o.salt = salt_blob;
4090 io->o.aes_256 = key_blob;
4097 static struct ph_context *ph_init_context(struct ldb_module *module,
4098 struct ldb_request *req,
4100 bool update_password)
4102 struct ldb_context *ldb;
4103 struct ph_context *ac;
4104 struct loadparm_context *lp_ctx = NULL;
4106 ldb = ldb_module_get_ctx(module);
4108 ac = talloc_zero(req, struct ph_context);
4110 ldb_set_errstring(ldb, "Out of Memory");
4114 ac->module = module;
4116 ac->userPassword = userPassword;
4117 ac->update_password = update_password;
4118 ac->update_lastset = true;
4120 lp_ctx = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"),
4121 struct loadparm_context);
4122 ac->gpg_key_ids = lpcfg_password_hash_gpg_key_ids(lp_ctx);
4123 ac->userPassword_schemes
4124 = lpcfg_password_hash_userpassword_schemes(lp_ctx);
4128 static void ph_apply_controls(struct ph_context *ac)
4130 struct ldb_control *ctrl;
4132 ac->change_status = false;
4133 ctrl = ldb_request_get_control(ac->req,
4134 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID);
4136 ac->change_status = true;
4138 /* Mark the "change status" control as uncritical (done) */
4139 ctrl->critical = false;
4142 ac->hash_values = false;
4143 ctrl = ldb_request_get_control(ac->req,
4144 DSDB_CONTROL_PASSWORD_HASH_VALUES_OID);
4146 ac->hash_values = true;
4148 /* Mark the "hash values" control as uncritical (done) */
4149 ctrl->critical = false;
4152 ctrl = ldb_request_get_control(ac->req,
4153 DSDB_CONTROL_PASSWORD_CHANGE_OLD_PW_CHECKED_OID);
4155 ac->change = talloc_get_type_abort(ctrl->data, struct dsdb_control_password_change);
4157 /* Mark the "change" control as uncritical (done) */
4158 ctrl->critical = false;
4161 ac->pwd_last_set_bypass = false;
4162 ctrl = ldb_request_get_control(ac->req,
4163 DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID);
4165 ac->pwd_last_set_bypass = true;
4167 /* Mark the "bypass pwdLastSet" control as uncritical (done) */
4168 ctrl->critical = false;
4171 ac->pwd_last_set_default = false;
4172 ctrl = ldb_request_get_control(ac->req,
4173 DSDB_CONTROL_PASSWORD_DEFAULT_LAST_SET_OID);
4175 ac->pwd_last_set_default = true;
4177 /* Mark the "bypass pwdLastSet" control as uncritical (done) */
4178 ctrl->critical = false;
4181 ac->smartcard_reset = false;
4182 ctrl = ldb_request_get_control(ac->req,
4183 DSDB_CONTROL_PASSWORD_USER_ACCOUNT_CONTROL_OID);
4185 struct dsdb_control_password_user_account_control *uac = NULL;
4186 uint32_t added_flags = 0;
4188 uac = talloc_get_type_abort(ctrl->data,
4189 struct dsdb_control_password_user_account_control);
4191 added_flags = uac->new_flags & ~uac->old_flags;
4193 if (added_flags & UF_SMARTCARD_REQUIRED) {
4194 ac->smartcard_reset = true;
4197 /* Mark the "smartcard required" control as uncritical (done) */
4198 ctrl->critical = false;
4202 static int ph_op_callback(struct ldb_request *req, struct ldb_reply *ares)
4204 struct ph_context *ac;
4206 ac = talloc_get_type(req->context, struct ph_context);
4209 return ldb_module_done(ac->req, NULL, NULL,
4210 LDB_ERR_OPERATIONS_ERROR);
4213 if (ares->type == LDB_REPLY_REFERRAL) {
4214 return ldb_module_send_referral(ac->req, ares->referral);
4217 if ((ares->error != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
4218 /* On success and trivial errors a status control is being
4219 * added (used for example by the "samdb_set_password" call) */
4220 ldb_reply_add_control(ares,
4221 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
4226 if (ares->error != LDB_SUCCESS) {
4227 return ldb_module_done(ac->req, ares->controls,
4228 ares->response, ares->error);
4231 if (ares->type != LDB_REPLY_DONE) {
4233 return ldb_module_done(ac->req, NULL, NULL,
4234 LDB_ERR_OPERATIONS_ERROR);
4237 return ldb_module_done(ac->req, ares->controls,
4238 ares->response, ares->error);
4241 static int password_hash_add_do_add(struct ph_context *ac);
4242 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares);
4243 static int password_hash_mod_search_self(struct ph_context *ac);
4244 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares);
4245 static int password_hash_mod_do_mod(struct ph_context *ac);
4248 * LDB callback handler for searching for a user's PSO. Once we have all the
4249 * Password Settings that apply to the user, we can continue with the modify
4252 static int get_pso_data_callback(struct ldb_request *req,
4253 struct ldb_reply *ares)
4255 struct ldb_context *ldb = NULL;
4256 struct ph_context *ac = NULL;
4257 bool domain_complexity = true;
4258 bool pso_complexity = true;
4259 struct dsdb_user_pwd_settings *settings = NULL;
4260 int ret = LDB_SUCCESS;
4262 ac = talloc_get_type(req->context, struct ph_context);
4263 ldb = ldb_module_get_ctx(ac->module);
4266 ret = LDB_ERR_OPERATIONS_ERROR;
4269 if (ares->error != LDB_SUCCESS) {
4270 return ldb_module_done(ac->req, ares->controls,
4271 ares->response, ares->error);
4274 switch (ares->type) {
4275 case LDB_REPLY_ENTRY:
4277 /* check status was initialized by the domain query */
4278 if (ac->status == NULL) {
4280 ldb_set_errstring(ldb, "Uninitialized status");
4281 ret = LDB_ERR_OPERATIONS_ERROR;
4286 * use the PSO's values instead of the domain defaults (the PSO
4287 * attributes should always exist, but use the domain default
4288 * values as a fallback).
4290 settings = &ac->status->domain_data;
4291 settings->store_cleartext =
4292 ldb_msg_find_attr_as_bool(ares->message,
4293 "msDS-PasswordReversibleEncryptionEnabled",
4294 settings->store_cleartext);
4296 settings->pwdHistoryLength =
4297 ldb_msg_find_attr_as_uint(ares->message,
4298 "msDS-PasswordHistoryLength",
4299 settings->pwdHistoryLength);
4300 settings->maxPwdAge =
4301 ldb_msg_find_attr_as_int64(ares->message,
4302 "msDS-MaximumPasswordAge",
4303 settings->maxPwdAge);
4304 settings->minPwdAge =
4305 ldb_msg_find_attr_as_int64(ares->message,
4306 "msDS-MinimumPasswordAge",
4307 settings->minPwdAge);
4308 settings->minPwdLength =
4309 ldb_msg_find_attr_as_uint(ares->message,
4310 "msDS-MinimumPasswordLength",
4311 settings->minPwdLength);
4313 (settings->pwdProperties & DOMAIN_PASSWORD_COMPLEX);
4315 ldb_msg_find_attr_as_bool(ares->message,
4316 "msDS-PasswordComplexityEnabled",
4319 /* set or clear the complexity bit if required */
4320 if (pso_complexity && !domain_complexity) {
4321 settings->pwdProperties |= DOMAIN_PASSWORD_COMPLEX;
4322 } else if (domain_complexity && !pso_complexity) {
4323 settings->pwdProperties &= ~DOMAIN_PASSWORD_COMPLEX;
4326 if (ac->pso_res != NULL) {
4327 DBG_ERR("Too many PSO results for %s\n",
4328 ldb_dn_get_linearized(ac->search_res->message->dn));
4329 talloc_free(ac->pso_res);
4332 /* store the PSO result (we may need its lockout settings) */
4333 ac->pso_res = talloc_steal(ac, ares);
4337 case LDB_REPLY_REFERRAL:
4343 case LDB_REPLY_DONE:
4347 * perform the next step of the modify operation (this code
4348 * shouldn't get called in the 'user add' case)
4350 if (ac->req->operation == LDB_MODIFY) {
4351 ret = password_hash_mod_do_mod(ac);
4353 ret = LDB_ERR_OPERATIONS_ERROR;
4359 if (ret != LDB_SUCCESS) {
4360 struct ldb_reply *new_ares;
4362 new_ares = talloc_zero(ac->req, struct ldb_reply);
4363 if (new_ares == NULL) {
4365 return ldb_module_done(ac->req, NULL, NULL,
4366 LDB_ERR_OPERATIONS_ERROR);
4369 new_ares->error = ret;
4370 if ((ret != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
4371 /* On success and trivial errors a status control is being
4372 * added (used for example by the "samdb_set_password" call) */
4373 ldb_reply_add_control(new_ares,
4374 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
4379 return ldb_module_done(ac->req, new_ares->controls,
4380 new_ares->response, new_ares->error);
4387 * Builds and returns a search request to look up the PSO that applies to
4388 * the user in question. Returns NULL if no PSO applies, or could not be found
4390 static struct ldb_request * build_pso_data_request(struct ph_context *ac)
4392 /* attrs[] is returned from this function in
4393 pso_req->op.search.attrs, so it must be static, as
4394 otherwise the compiler can put it on the stack */
4395 static const char * const attrs[] = { "msDS-PasswordComplexityEnabled",
4396 "msDS-PasswordReversibleEncryptionEnabled",
4397 "msDS-PasswordHistoryLength",
4398 "msDS-MaximumPasswordAge",
4399 "msDS-MinimumPasswordAge",
4400 "msDS-MinimumPasswordLength",
4401 "msDS-LockoutThreshold",
4402 "msDS-LockoutObservationWindow",
4404 struct ldb_context *ldb = NULL;
4405 struct ldb_request *pso_req = NULL;
4406 struct ldb_dn *pso_dn = NULL;
4407 TALLOC_CTX *mem_ctx = ac;
4410 ldb = ldb_module_get_ctx(ac->module);
4412 /* if a PSO applies to the user, we need to lookup the PSO as well */
4413 pso_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, ac->search_res->message,
4414 "msDS-ResultantPSO");
4415 if (pso_dn == NULL) {
4419 ret = ldb_build_search_req(&pso_req, ldb, mem_ctx, pso_dn,
4420 LDB_SCOPE_BASE, NULL, attrs, NULL,
4421 ac, get_pso_data_callback,
4424 /* log errors, but continue with the default domain settings */
4425 if (ret != LDB_SUCCESS) {
4426 DBG_ERR("Error %d constructing PSO query for user %s\n", ret,
4427 ldb_dn_get_linearized(ac->search_res->message->dn));
4429 LDB_REQ_SET_LOCATION(pso_req);
4434 static int get_domain_data_callback(struct ldb_request *req,
4435 struct ldb_reply *ares)
4437 struct ldb_context *ldb;
4438 struct ph_context *ac;
4439 struct loadparm_context *lp_ctx;
4440 struct ldb_request *pso_req = NULL;
4441 int ret = LDB_SUCCESS;
4443 ac = talloc_get_type(req->context, struct ph_context);
4444 ldb = ldb_module_get_ctx(ac->module);
4447 ret = LDB_ERR_OPERATIONS_ERROR;
4450 if (ares->error != LDB_SUCCESS) {
4451 return ldb_module_done(ac->req, ares->controls,
4452 ares->response, ares->error);
4455 switch (ares->type) {
4456 case LDB_REPLY_ENTRY:
4457 if (ac->status != NULL) {
4460 ldb_set_errstring(ldb, "Too many results");
4461 ret = LDB_ERR_OPERATIONS_ERROR;
4465 /* Setup the "status" structure (used as control later) */
4466 ac->status = talloc_zero(ac->req,
4467 struct dsdb_control_password_change_status);
4468 if (ac->status == NULL) {
4472 ret = LDB_ERR_OPERATIONS_ERROR;
4476 /* Setup the "domain data" structure */
4477 ac->status->domain_data.pwdProperties =
4478 ldb_msg_find_attr_as_uint(ares->message, "pwdProperties", -1);
4479 ac->status->domain_data.pwdHistoryLength =
4480 ldb_msg_find_attr_as_uint(ares->message, "pwdHistoryLength", -1);
4481 ac->status->domain_data.maxPwdAge =
4482 ldb_msg_find_attr_as_int64(ares->message, "maxPwdAge", -1);
4483 ac->status->domain_data.minPwdAge =
4484 ldb_msg_find_attr_as_int64(ares->message, "minPwdAge", -1);
4485 ac->status->domain_data.minPwdLength =
4486 ldb_msg_find_attr_as_uint(ares->message, "minPwdLength", -1);
4487 ac->status->domain_data.store_cleartext =
4488 ac->status->domain_data.pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT;
4490 /* For a domain DN, this puts things in dotted notation */
4491 /* For builtin domains, this will give details for the host,
4492 * but that doesn't really matter, as it's just used for salt
4493 * and kerberos principals, which don't exist here */
4495 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
4496 struct loadparm_context);
4498 ac->status->domain_data.dns_domain = lpcfg_dnsdomain(lp_ctx);
4499 ac->status->domain_data.realm = lpcfg_realm(lp_ctx);
4500 ac->status->domain_data.netbios_domain = lpcfg_sam_name(lp_ctx);
4502 ac->status->reject_reason = SAM_PWD_CHANGE_NO_ERROR;
4504 if (ac->dom_res != NULL) {
4507 ldb_set_errstring(ldb, "Too many results");
4508 ret = LDB_ERR_OPERATIONS_ERROR;
4512 ac->dom_res = talloc_steal(ac, ares);
4516 case LDB_REPLY_REFERRAL:
4522 case LDB_REPLY_DONE:
4524 /* call the next step */
4525 switch (ac->req->operation) {
4527 ret = password_hash_add_do_add(ac);
4533 * The user may have an optional PSO applied. If so,
4534 * query the PSO to get the Fine-Grained Password Policy
4535 * for the user, before we perform the modify
4537 pso_req = build_pso_data_request(ac);
4538 if (pso_req != NULL) {
4539 ret = ldb_next_request(ac->module, pso_req);
4542 /* no PSO, so we can perform the modify now */
4543 ret = password_hash_mod_do_mod(ac);
4548 ret = LDB_ERR_OPERATIONS_ERROR;
4555 if (ret != LDB_SUCCESS) {
4556 struct ldb_reply *new_ares;
4558 new_ares = talloc_zero(ac->req, struct ldb_reply);
4559 if (new_ares == NULL) {
4561 return ldb_module_done(ac->req, NULL, NULL,
4562 LDB_ERR_OPERATIONS_ERROR);
4565 new_ares->error = ret;
4566 if ((ret != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
4567 /* On success and trivial errors a status control is being
4568 * added (used for example by the "samdb_set_password" call) */
4569 ldb_reply_add_control(new_ares,
4570 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
4575 return ldb_module_done(ac->req, new_ares->controls,
4576 new_ares->response, new_ares->error);
4582 static int build_domain_data_request(struct ph_context *ac)
4584 /* attrs[] is returned from this function in
4585 ac->dom_req->op.search.attrs, so it must be static, as
4586 otherwise the compiler can put it on the stack */
4587 struct ldb_context *ldb;
4588 static const char * const attrs[] = { "pwdProperties",
4594 "lockOutObservationWindow",
4598 ldb = ldb_module_get_ctx(ac->module);
4600 ret = ldb_build_search_req(&ac->dom_req, ldb, ac,
4601 ldb_get_default_basedn(ldb),
4605 ac, get_domain_data_callback,
4607 LDB_REQ_SET_LOCATION(ac->dom_req);
4611 static int password_hash_needed(struct ldb_module *module,
4612 struct ldb_request *req,
4613 struct ph_context **_ac)
4615 struct ldb_context *ldb = ldb_module_get_ctx(module);
4616 const char *operation = NULL;
4617 const struct ldb_message *msg = NULL;
4618 struct ph_context *ac = NULL;
4619 const char *passwordAttrs[] = {
4620 DSDB_PASSWORD_ATTRIBUTES,
4623 const char **a = NULL;
4624 unsigned int attr_cnt = 0;
4625 struct ldb_control *bypass = NULL;
4626 struct ldb_control *uac_ctrl = NULL;
4627 bool userPassword = dsdb_user_password_support(module, req, req);
4628 bool update_password = false;
4629 bool processing_needed = false;
4633 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_needed\n");
4635 switch (req->operation) {
4638 msg = req->op.add.message;
4641 operation = "modify";
4642 msg = req->op.mod.message;
4645 return ldb_next_request(module, req);
4648 if (ldb_dn_is_special(msg->dn)) { /* do not manipulate our control entries */
4649 return ldb_next_request(module, req);
4652 bypass = ldb_request_get_control(req,
4653 DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID);
4654 if (bypass != NULL) {
4655 /* Mark the "bypass" control as uncritical (done) */
4656 bypass->critical = false;
4657 ldb_debug(ldb, LDB_DEBUG_TRACE,
4658 "password_hash_needed(%s) (bypassing)\n",
4660 return password_hash_bypass(module, req);
4663 /* nobody must touch password histories and 'supplementalCredentials' */
4664 if (ldb_msg_find_element(msg, "ntPwdHistory")) {
4665 return LDB_ERR_UNWILLING_TO_PERFORM;
4667 if (ldb_msg_find_element(msg, "lmPwdHistory")) {
4668 return LDB_ERR_UNWILLING_TO_PERFORM;
4670 if (ldb_msg_find_element(msg, "supplementalCredentials")) {
4671 return LDB_ERR_UNWILLING_TO_PERFORM;
4675 * If no part of this touches the 'userPassword' OR 'clearTextPassword'
4676 * OR 'unicodePwd' OR 'dBCSPwd' we don't need to make any changes.
4677 * For password changes/set there should be a 'delete' or a 'modify'
4678 * on these attributes.
4680 for (a = passwordAttrs; *a != NULL; a++) {
4681 if ((!userPassword) && (ldb_attr_cmp(*a, "userPassword") == 0)) {
4685 if (ldb_msg_find_element(msg, *a) != NULL) {
4686 /* MS-ADTS 3.1.1.3.1.5.2 */
4687 if ((ldb_attr_cmp(*a, "userPassword") == 0) &&
4688 (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003)) {
4689 return LDB_ERR_CONSTRAINT_VIOLATION;
4697 update_password = true;
4698 processing_needed = true;
4701 if (ldb_msg_find_element(msg, "pwdLastSet")) {
4702 processing_needed = true;
4705 uac_ctrl = ldb_request_get_control(req,
4706 DSDB_CONTROL_PASSWORD_USER_ACCOUNT_CONTROL_OID);
4707 if (uac_ctrl != NULL) {
4708 struct dsdb_control_password_user_account_control *uac = NULL;
4709 uint32_t added_flags = 0;
4711 uac = talloc_get_type_abort(uac_ctrl->data,
4712 struct dsdb_control_password_user_account_control);
4714 added_flags = uac->new_flags & ~uac->old_flags;
4716 if (added_flags & UF_SMARTCARD_REQUIRED) {
4717 processing_needed = true;
4721 if (!processing_needed) {
4722 return ldb_next_request(module, req);
4725 ac = ph_init_context(module, req, userPassword, update_password);
4727 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
4728 return ldb_operr(ldb);
4730 ph_apply_controls(ac);
4733 * Make a copy in order to apply our modifications
4734 * to the final update
4736 ac->update_msg = ldb_msg_copy_shallow(ac, msg);
4737 if (ac->update_msg == NULL) {
4738 return ldb_oom(ldb);
4742 * Remove all password related attributes.
4744 if (ac->userPassword) {
4745 ldb_msg_remove_attr(ac->update_msg, "userPassword");
4747 ldb_msg_remove_attr(ac->update_msg, "clearTextPassword");
4748 ldb_msg_remove_attr(ac->update_msg, "unicodePwd");
4749 ldb_msg_remove_attr(ac->update_msg, "ntPwdHistory");
4750 ldb_msg_remove_attr(ac->update_msg, "dBCSPwd");
4751 ldb_msg_remove_attr(ac->update_msg, "lmPwdHistory");
4752 ldb_msg_remove_attr(ac->update_msg, "supplementalCredentials");
4753 ldb_msg_remove_attr(ac->update_msg, "pwdLastSet");
4759 static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
4761 struct ldb_context *ldb = ldb_module_get_ctx(module);
4762 struct ph_context *ac = NULL;
4765 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_add\n");
4767 ret = password_hash_needed(module, req, &ac);
4768 if (ret != LDB_SUCCESS) {
4775 /* Make sure we are performing the password set action on a (for us)
4776 * valid object. Those are instances of either "user" and/or
4777 * "inetOrgPerson". Otherwise continue with the submodules. */
4778 if ((!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "user"))
4779 && (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "inetOrgPerson"))) {
4783 if (ldb_msg_find_element(req->op.add.message, "clearTextPassword") != NULL) {
4784 ldb_set_errstring(ldb,
4785 "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
4786 return LDB_ERR_NO_SUCH_ATTRIBUTE;
4789 return ldb_next_request(module, req);
4792 /* get user domain data */
4793 ret = build_domain_data_request(ac);
4794 if (ret != LDB_SUCCESS) {
4798 return ldb_next_request(module, ac->dom_req);
4801 static int password_hash_add_do_add(struct ph_context *ac)
4803 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
4804 struct ldb_request *down_req;
4805 struct setup_password_fields_io io;
4808 /* Prepare the internal data structure containing the passwords */
4809 ret = setup_io(ac, ac->req->op.add.message, NULL, &io);
4810 if (ret != LDB_SUCCESS) {
4814 ret = setup_password_fields(&io);
4815 if (ret != LDB_SUCCESS) {
4819 ret = check_password_restrictions_and_log(&io);
4820 if (ret != LDB_SUCCESS) {
4824 ret = setup_smartcard_reset(&io);
4825 if (ret != LDB_SUCCESS) {
4829 ret = update_final_msg(&io);
4830 if (ret != LDB_SUCCESS) {
4834 ret = ldb_build_add_req(&down_req, ldb, ac,
4839 LDB_REQ_SET_LOCATION(down_req);
4840 if (ret != LDB_SUCCESS) {
4844 return ldb_next_request(ac->module, down_req);
4847 static int password_hash_modify(struct ldb_module *module, struct ldb_request *req)
4849 struct ldb_context *ldb = ldb_module_get_ctx(module);
4850 struct ph_context *ac = NULL;
4851 const char *passwordAttrs[] = {DSDB_PASSWORD_ATTRIBUTES, NULL}, **l;
4852 unsigned int del_attr_cnt, add_attr_cnt, rep_attr_cnt;
4853 struct ldb_message_element *passwordAttr;
4854 struct ldb_message *msg;
4855 struct ldb_request *down_req;
4856 struct ldb_control *restore = NULL;
4860 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_modify\n");
4862 ret = password_hash_needed(module, req, &ac);
4863 if (ret != LDB_SUCCESS) {
4870 /* use a new message structure so that we can modify it */
4871 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
4873 return ldb_oom(ldb);
4876 /* - check for single-valued password attributes
4877 * (if not return "CONSTRAINT_VIOLATION")
4878 * - check that for a password change operation one add and one delete
4880 * (if not return "CONSTRAINT_VIOLATION" or "UNWILLING_TO_PERFORM")
4881 * - check that a password change and a password set operation cannot
4883 * (if not return "UNWILLING_TO_PERFORM")
4884 * - remove all password attributes modifications from the first change
4885 * operation (anything without the passwords) - we will make the real
4886 * modification later */
4890 for (l = passwordAttrs; *l != NULL; l++) {
4891 if ((!ac->userPassword) &&
4892 (ldb_attr_cmp(*l, "userPassword") == 0)) {
4896 while ((passwordAttr = ldb_msg_find_element(msg, *l)) != NULL) {
4897 unsigned int mtype = LDB_FLAG_MOD_TYPE(passwordAttr->flags);
4898 unsigned int nvalues = passwordAttr->num_values;
4900 if (mtype == LDB_FLAG_MOD_DELETE) {
4903 if (mtype == LDB_FLAG_MOD_ADD) {
4906 if (mtype == LDB_FLAG_MOD_REPLACE) {
4909 if ((nvalues != 1) && (mtype == LDB_FLAG_MOD_ADD)) {
4911 ldb_asprintf_errstring(ldb,
4912 "'%s' attribute must have exactly one value on add operations!",
4914 return LDB_ERR_CONSTRAINT_VIOLATION;
4916 if ((nvalues > 1) && (mtype == LDB_FLAG_MOD_DELETE)) {
4918 ldb_asprintf_errstring(ldb,
4919 "'%s' attribute must have zero or one value(s) on delete operations!",
4921 return LDB_ERR_CONSTRAINT_VIOLATION;
4923 ldb_msg_remove_element(msg, passwordAttr);
4926 if ((del_attr_cnt == 0) && (add_attr_cnt > 0)) {
4928 ldb_set_errstring(ldb,
4929 "Only the add action for a password change specified!");
4930 return LDB_ERR_UNWILLING_TO_PERFORM;
4932 if ((del_attr_cnt > 1) || (add_attr_cnt > 1)) {
4934 ldb_set_errstring(ldb,
4935 "Only one delete and one add action for a password change allowed!");
4936 return LDB_ERR_UNWILLING_TO_PERFORM;
4938 if ((rep_attr_cnt > 0) && ((del_attr_cnt > 0) || (add_attr_cnt > 0))) {
4940 ldb_set_errstring(ldb,
4941 "Either a password change or a password set operation is allowed!");
4942 return LDB_ERR_UNWILLING_TO_PERFORM;
4945 restore = ldb_request_get_control(req,
4946 DSDB_CONTROL_RESTORE_TOMBSTONE_OID);
4947 if (restore == NULL) {
4949 * A tombstone reanimation generates a double update
4952 * So we only remove it without the
4953 * DSDB_CONTROL_RESTORE_TOMBSTONE_OID control.
4955 ldb_msg_remove_attr(msg, "pwdLastSet");
4959 /* if there was nothing else to be modified skip to next step */
4960 if (msg->num_elements == 0) {
4961 return password_hash_mod_search_self(ac);
4965 * Now we apply all changes remaining in msg
4966 * and remove them from our final update_msg
4969 for (i = 0; i < msg->num_elements; i++) {
4970 ldb_msg_remove_attr(ac->update_msg,
4971 msg->elements[i].name);
4974 ret = ldb_build_mod_req(&down_req, ldb, ac,
4977 ac, ph_modify_callback,
4979 LDB_REQ_SET_LOCATION(down_req);
4980 if (ret != LDB_SUCCESS) {
4984 return ldb_next_request(module, down_req);
4987 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
4989 struct ph_context *ac;
4991 ac = talloc_get_type(req->context, struct ph_context);
4994 return ldb_module_done(ac->req, NULL, NULL,
4995 LDB_ERR_OPERATIONS_ERROR);
4998 if (ares->type == LDB_REPLY_REFERRAL) {
4999 return ldb_module_send_referral(ac->req, ares->referral);
5002 if (ares->error != LDB_SUCCESS) {
5003 return ldb_module_done(ac->req, ares->controls,
5004 ares->response, ares->error);
5007 if (ares->type != LDB_REPLY_DONE) {
5009 return ldb_module_done(ac->req, NULL, NULL,
5010 LDB_ERR_OPERATIONS_ERROR);
5015 return password_hash_mod_search_self(ac);
5018 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares)
5020 struct ldb_context *ldb;
5021 struct ph_context *ac;
5022 int ret = LDB_SUCCESS;
5024 ac = talloc_get_type(req->context, struct ph_context);
5025 ldb = ldb_module_get_ctx(ac->module);
5028 ret = LDB_ERR_OPERATIONS_ERROR;
5031 if (ares->error != LDB_SUCCESS) {
5032 return ldb_module_done(ac->req, ares->controls,
5033 ares->response, ares->error);
5036 /* we are interested only in the single reply (base search) */
5037 switch (ares->type) {
5038 case LDB_REPLY_ENTRY:
5039 /* Make sure we are performing the password change action on a
5040 * (for us) valid object. Those are instances of either "user"
5041 * and/or "inetOrgPerson". Otherwise continue with the
5043 if ((!ldb_msg_check_string_attribute(ares->message, "objectClass", "user"))
5044 && (!ldb_msg_check_string_attribute(ares->message, "objectClass", "inetOrgPerson"))) {
5047 if (ldb_msg_find_element(ac->req->op.mod.message, "clearTextPassword") != NULL) {
5048 ldb_set_errstring(ldb,
5049 "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
5050 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
5054 ret = ldb_next_request(ac->module, ac->req);
5058 if (ac->search_res != NULL) {
5061 ldb_set_errstring(ldb, "Too many results");
5062 ret = LDB_ERR_OPERATIONS_ERROR;
5066 ac->search_res = talloc_steal(ac, ares);
5070 case LDB_REPLY_REFERRAL:
5071 /* ignore anything else for now */
5076 case LDB_REPLY_DONE:
5079 /* get user domain data */
5080 ret = build_domain_data_request(ac);
5081 if (ret != LDB_SUCCESS) {
5082 return ldb_module_done(ac->req, NULL, NULL, ret);
5085 ret = ldb_next_request(ac->module, ac->dom_req);
5090 if (ret != LDB_SUCCESS) {
5091 return ldb_module_done(ac->req, NULL, NULL, ret);
5097 static int password_hash_mod_search_self(struct ph_context *ac)
5099 struct ldb_context *ldb;
5100 static const char * const attrs[] = { "objectClass",
5101 "userAccountControl",
5102 "msDS-ResultantPSO",
5103 "msDS-User-Account-Control-Computed",
5107 "userPrincipalName",
5109 "supplementalCredentials",
5117 "msDS-KeyVersionNumber",
5118 "msDS-SecondaryKrbTgtNumber",
5120 struct ldb_request *search_req;
5123 ldb = ldb_module_get_ctx(ac->module);
5125 ret = ldb_build_search_req(&search_req, ldb, ac,
5126 ac->req->op.mod.message->dn,
5131 ac, ph_mod_search_callback,
5133 LDB_REQ_SET_LOCATION(search_req);
5134 if (ret != LDB_SUCCESS) {
5138 return ldb_next_request(ac->module, search_req);
5141 static int password_hash_mod_do_mod(struct ph_context *ac)
5143 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
5144 struct ldb_request *mod_req;
5145 struct setup_password_fields_io io;
5148 /* Prepare the internal data structure containing the passwords */
5149 ret = setup_io(ac, ac->req->op.mod.message,
5150 ac->search_res->message, &io);
5151 if (ret != LDB_SUCCESS) {
5155 ret = setup_password_fields(&io);
5156 if (ret != LDB_SUCCESS) {
5160 ret = check_password_restrictions_and_log(&io);
5161 if (ret != LDB_SUCCESS) {
5165 ret = setup_smartcard_reset(&io);
5166 if (ret != LDB_SUCCESS) {
5170 ret = update_final_msg(&io);
5171 if (ret != LDB_SUCCESS) {
5175 ret = ldb_build_mod_req(&mod_req, ldb, ac,
5180 LDB_REQ_SET_LOCATION(mod_req);
5181 if (ret != LDB_SUCCESS) {
5185 return ldb_next_request(ac->module, mod_req);
5188 static const struct ldb_module_ops ldb_password_hash_module_ops = {
5189 .name = "password_hash",
5190 .add = password_hash_add,
5191 .modify = password_hash_modify
5194 int ldb_password_hash_module_init(const char *version)
5197 const char *gversion = NULL;
5198 #endif /* ENABLE_GPGME */
5200 LDB_MODULE_CHECK_VERSION(version);
5204 * Note: this sets a SIGPIPE handler
5205 * if none is active already. See:
5206 * https://www.gnupg.org/documentation/manuals/gpgme/Signal-Handling.html#Signal-Handling
5208 gversion = gpgme_check_version(MINIMUM_GPGME_VERSION);
5209 if (gversion == NULL) {
5210 fprintf(stderr, "%s() in %s version[%s]: "
5211 "gpgme_check_version(%s) not available, "
5212 "gpgme_check_version(NULL) => '%s'\n",
5213 __func__, __FILE__, version,
5214 MINIMUM_GPGME_VERSION, gpgme_check_version(NULL));
5215 return LDB_ERR_UNAVAILABLE;
5217 #endif /* ENABLE_GPGME */
5219 return ldb_register_module(&ldb_password_hash_module_ops);