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/crypto.h"
46 #include "param/param.h"
47 #include "lib/krb5_wrap/krb5_samba.h"
48 #include "auth/common_auth.h"
49 #include "lib/messaging/messaging.h"
56 /* If we have decided there is a reason to work on this request, then
57 * setup all the password hash types correctly.
59 * If we haven't the hashes yet but the password given as plain-text (attributes
60 * 'unicodePwd', 'userPassword' and 'clearTextPassword') we have to check for
61 * the constraints. Once this is done, we calculate the password hashes.
63 * Notice: unlike the real AD which only supports the UTF16 special based
64 * 'unicodePwd' and the UTF8 based 'userPassword' plaintext attribute we
65 * understand also a UTF16 based 'clearTextPassword' one.
66 * The latter is also accessible through LDAP so it can also be set by external
67 * tools and scripts. But be aware that this isn't portable on non SAMBA 4 ADs!
69 * Also when the module receives only the password hashes (possible through
70 * specifying an internal LDB control - for security reasons) some checks are
71 * performed depending on the operation mode (see below) (e.g. if the password
72 * has been in use before if the password memory policy was activated).
74 * Attention: There is a difference between "modify" and "reset" operations
75 * (see MS-ADTS 3.1.1.3.1.5). If the client sends a "add" and "remove"
76 * operation for a password attribute we thread this as a "modify"; if it sends
77 * only a "replace" one we have an (administrative) reset.
79 * Finally, if the administrator has requested that a password history
80 * be maintained, then this should also be written out.
84 /* TODO: [consider always MS-ADTS 3.1.1.3.1.5]
85 * - Check for right connection encryption
88 /* Notice: Definition of "dsdb_control_password_change_status" moved into
92 struct ldb_module *module;
93 struct ldb_request *req;
95 struct ldb_request *dom_req;
96 struct ldb_reply *dom_res;
98 struct ldb_reply *pso_res;
100 struct ldb_reply *search_res;
102 struct ldb_message *update_msg;
104 struct dsdb_control_password_change_status *status;
105 struct dsdb_control_password_change *change;
107 const char **gpg_key_ids;
113 bool update_password;
115 bool pwd_last_set_bypass;
116 bool pwd_last_set_default;
117 bool smartcard_reset;
118 const char **userPassword_schemes;
122 struct setup_password_fields_io {
123 struct ph_context *ac;
125 struct smb_krb5_context *smb_krb5_context;
127 /* info about the user account */
129 uint32_t userAccountControl;
131 const char *sAMAccountName;
132 const char *user_principal_name;
135 uint32_t restrictions;
136 struct dom_sid *account_sid;
139 /* new credentials and old given credentials */
140 struct setup_password_fields_given {
141 const struct ldb_val *cleartext_utf8;
142 const struct ldb_val *cleartext_utf16;
143 struct samr_Password *nt_hash;
144 struct samr_Password *lm_hash;
147 /* old credentials */
149 struct samr_Password *nt_hash;
150 struct samr_Password *lm_hash;
151 uint32_t nt_history_len;
152 struct samr_Password *nt_history;
153 uint32_t lm_history_len;
154 struct samr_Password *lm_history;
155 const struct ldb_val *supplemental;
156 struct supplementalCredentialsBlob scb;
159 /* generated credentials */
161 struct samr_Password *nt_hash;
162 struct samr_Password *lm_hash;
163 uint32_t nt_history_len;
164 struct samr_Password *nt_history;
165 uint32_t lm_history_len;
166 struct samr_Password *lm_history;
172 struct ldb_val supplemental;
177 static int msg_find_old_and_new_pwd_val(const struct ldb_message *msg,
179 enum ldb_request_type operation,
180 const struct ldb_val **new_val,
181 const struct ldb_val **old_val);
183 static int password_hash_bypass(struct ldb_module *module, struct ldb_request *request)
185 struct ldb_context *ldb = ldb_module_get_ctx(module);
186 const struct ldb_message *msg;
187 struct ldb_message_element *nte;
188 struct ldb_message_element *lme;
189 struct ldb_message_element *nthe;
190 struct ldb_message_element *lmhe;
191 struct ldb_message_element *sce;
193 switch (request->operation) {
195 msg = request->op.add.message;
198 msg = request->op.mod.message;
201 return ldb_next_request(module, request);
204 /* nobody must touch password histories and 'supplementalCredentials' */
205 nte = dsdb_get_single_valued_attr(msg, "unicodePwd",
207 lme = dsdb_get_single_valued_attr(msg, "dBCSPwd",
209 nthe = dsdb_get_single_valued_attr(msg, "ntPwdHistory",
211 lmhe = dsdb_get_single_valued_attr(msg, "lmPwdHistory",
213 sce = dsdb_get_single_valued_attr(msg, "supplementalCredentials",
216 #define CHECK_HASH_ELEMENT(e, min, max) do {\
217 if (e && e->num_values) { \
218 unsigned int _count; \
219 if (e->num_values != 1) { \
220 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
221 "num_values != 1"); \
223 if ((e->values[0].length % 16) != 0) { \
224 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
225 "length % 16 != 0"); \
227 _count = e->values[0].length / 16; \
228 if (_count < min) { \
229 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
232 if (_count > max) { \
233 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
239 CHECK_HASH_ELEMENT(nte, 1, 1);
240 CHECK_HASH_ELEMENT(lme, 1, 1);
241 CHECK_HASH_ELEMENT(nthe, 1, INT32_MAX);
242 CHECK_HASH_ELEMENT(lmhe, 1, INT32_MAX);
244 if (sce && sce->num_values) {
245 enum ndr_err_code ndr_err;
246 struct supplementalCredentialsBlob *scb;
247 struct supplementalCredentialsPackage *scpp = NULL;
248 struct supplementalCredentialsPackage *scpk = NULL;
249 struct supplementalCredentialsPackage *scpkn = NULL;
250 struct supplementalCredentialsPackage *scpct = NULL;
251 DATA_BLOB scpbp = data_blob_null;
252 DATA_BLOB scpbk = data_blob_null;
253 DATA_BLOB scpbkn = data_blob_null;
254 DATA_BLOB scpbct = data_blob_null;
258 if (sce->num_values != 1) {
259 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
263 scb = talloc_zero(request, struct supplementalCredentialsBlob);
265 return ldb_module_oom(module);
268 ndr_err = ndr_pull_struct_blob_all(&sce->values[0], scb, scb,
269 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
270 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
271 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
272 "ndr_pull_struct_blob_all");
275 if (scb->sub.num_packages < 2) {
276 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
280 for (i=0; i < scb->sub.num_packages; i++) {
283 subblob = strhex_to_data_blob(scb, scb->sub.packages[i].data);
284 if (subblob.data == NULL) {
285 return ldb_module_oom(module);
288 if (strcmp(scb->sub.packages[i].name, "Packages") == 0) {
290 return ldb_error(ldb,
291 LDB_ERR_CONSTRAINT_VIOLATION,
294 scpp = &scb->sub.packages[i];
298 if (strcmp(scb->sub.packages[i].name, "Primary:Kerberos") == 0) {
300 return ldb_error(ldb,
301 LDB_ERR_CONSTRAINT_VIOLATION,
302 "Primary:Kerberos twice");
304 scpk = &scb->sub.packages[i];
308 if (strcmp(scb->sub.packages[i].name, "Primary:Kerberos-Newer-Keys") == 0) {
310 return ldb_error(ldb,
311 LDB_ERR_CONSTRAINT_VIOLATION,
312 "Primary:Kerberos-Newer-Keys twice");
314 scpkn = &scb->sub.packages[i];
318 if (strcmp(scb->sub.packages[i].name, "Primary:CLEARTEXT") == 0) {
320 return ldb_error(ldb,
321 LDB_ERR_CONSTRAINT_VIOLATION,
322 "Primary:CLEARTEXT twice");
324 scpct = &scb->sub.packages[i];
329 data_blob_free(&subblob);
333 return ldb_error(ldb,
334 LDB_ERR_CONSTRAINT_VIOLATION,
335 "Primary:Packages missing");
340 * If Primary:Kerberos is missing w2k8r2 reboots
341 * when a password is changed.
343 return ldb_error(ldb,
344 LDB_ERR_CONSTRAINT_VIOLATION,
345 "Primary:Kerberos missing");
349 struct package_PackagesBlob *p;
352 p = talloc_zero(scb, struct package_PackagesBlob);
354 return ldb_module_oom(module);
357 ndr_err = ndr_pull_struct_blob(&scpbp, p, p,
358 (ndr_pull_flags_fn_t)ndr_pull_package_PackagesBlob);
359 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
360 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
361 "ndr_pull_struct_blob Packages");
364 if (p->names == NULL) {
365 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
366 "Packages names == NULL");
369 for (n = 0; p->names[n]; n++) {
373 if (scb->sub.num_packages != (n + 1)) {
374 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
375 "Packages num_packages != num_names + 1");
382 struct package_PrimaryKerberosBlob *k;
384 k = talloc_zero(scb, struct package_PrimaryKerberosBlob);
386 return ldb_module_oom(module);
389 ndr_err = ndr_pull_struct_blob(&scpbk, k, k,
390 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
391 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
392 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
393 "ndr_pull_struct_blob PrimaryKerberos");
396 if (k->version != 3) {
397 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
398 "PrimaryKerberos version != 3");
401 if (k->ctr.ctr3.salt.string == NULL) {
402 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
403 "PrimaryKerberos salt == NULL");
406 if (strlen(k->ctr.ctr3.salt.string) == 0) {
407 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
408 "PrimaryKerberos strlen(salt) == 0");
411 if (k->ctr.ctr3.num_keys != 2) {
412 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
413 "PrimaryKerberos num_keys != 2");
416 if (k->ctr.ctr3.num_old_keys > k->ctr.ctr3.num_keys) {
417 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
418 "PrimaryKerberos num_old_keys > num_keys");
421 if (k->ctr.ctr3.keys[0].keytype != ENCTYPE_DES_CBC_MD5) {
422 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
423 "PrimaryKerberos key[0] != DES_CBC_MD5");
425 if (k->ctr.ctr3.keys[1].keytype != ENCTYPE_DES_CBC_CRC) {
426 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
427 "PrimaryKerberos key[1] != DES_CBC_CRC");
430 if (k->ctr.ctr3.keys[0].value_len != 8) {
431 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
432 "PrimaryKerberos key[0] value_len != 8");
434 if (k->ctr.ctr3.keys[1].value_len != 8) {
435 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
436 "PrimaryKerberos key[1] value_len != 8");
439 for (i = 0; i < k->ctr.ctr3.num_old_keys; i++) {
440 if (k->ctr.ctr3.old_keys[i].keytype ==
441 k->ctr.ctr3.keys[i].keytype &&
442 k->ctr.ctr3.old_keys[i].value_len ==
443 k->ctr.ctr3.keys[i].value_len) {
447 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
448 "PrimaryKerberos old_keys type/value_len doesn't match");
455 struct package_PrimaryKerberosBlob *k;
457 k = talloc_zero(scb, struct package_PrimaryKerberosBlob);
459 return ldb_module_oom(module);
462 ndr_err = ndr_pull_struct_blob(&scpbkn, k, k,
463 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
464 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
465 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
466 "ndr_pull_struct_blob PrimaryKerberosNeverKeys");
469 if (k->version != 4) {
470 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
471 "KerberosNerverKeys version != 4");
474 if (k->ctr.ctr4.salt.string == NULL) {
475 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
476 "KerberosNewerKeys salt == NULL");
479 if (strlen(k->ctr.ctr4.salt.string) == 0) {
480 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
481 "KerberosNewerKeys strlen(salt) == 0");
484 if (k->ctr.ctr4.num_keys != 4) {
485 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
486 "KerberosNewerKeys num_keys != 2");
489 if (k->ctr.ctr4.num_old_keys > k->ctr.ctr4.num_keys) {
490 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
491 "KerberosNewerKeys num_old_keys > num_keys");
494 if (k->ctr.ctr4.num_older_keys > k->ctr.ctr4.num_old_keys) {
495 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
496 "KerberosNewerKeys num_older_keys > num_old_keys");
499 if (k->ctr.ctr4.keys[0].keytype != ENCTYPE_AES256_CTS_HMAC_SHA1_96) {
500 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
501 "KerberosNewerKeys key[0] != AES256");
503 if (k->ctr.ctr4.keys[1].keytype != ENCTYPE_AES128_CTS_HMAC_SHA1_96) {
504 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
505 "KerberosNewerKeys key[1] != AES128");
507 if (k->ctr.ctr4.keys[2].keytype != ENCTYPE_DES_CBC_MD5) {
508 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
509 "KerberosNewerKeys key[2] != DES_CBC_MD5");
511 if (k->ctr.ctr4.keys[3].keytype != ENCTYPE_DES_CBC_CRC) {
512 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
513 "KerberosNewerKeys key[3] != DES_CBC_CRC");
516 if (k->ctr.ctr4.keys[0].value_len != 32) {
517 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
518 "KerberosNewerKeys key[0] value_len != 32");
520 if (k->ctr.ctr4.keys[1].value_len != 16) {
521 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
522 "KerberosNewerKeys key[1] value_len != 16");
524 if (k->ctr.ctr4.keys[2].value_len != 8) {
525 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
526 "KerberosNewerKeys key[2] value_len != 8");
528 if (k->ctr.ctr4.keys[3].value_len != 8) {
529 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
530 "KerberosNewerKeys key[3] value_len != 8");
535 * Maybe we can check old and older keys here.
536 * But we need to do some tests, if the old keys
537 * can be taken from the PrimaryKerberos blob
538 * (with only des keys), when the domain was upgraded
546 struct package_PrimaryCLEARTEXTBlob *ct;
548 ct = talloc_zero(scb, struct package_PrimaryCLEARTEXTBlob);
550 return ldb_module_oom(module);
553 ndr_err = ndr_pull_struct_blob(&scpbct, ct, ct,
554 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryCLEARTEXTBlob);
555 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
556 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
557 "ndr_pull_struct_blob PrimaryCLEARTEXT");
560 if ((ct->cleartext.length % 2) != 0) {
561 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
562 "PrimaryCLEARTEXT length % 2 != 0");
568 ndr_err = ndr_push_struct_blob(&blob, scb, scb,
569 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
570 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
571 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
572 "ndr_pull_struct_blob_all");
575 if (sce->values[0].length != blob.length) {
576 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
577 "supplementalCredentialsBlob length differ");
580 if (memcmp(sce->values[0].data, blob.data, blob.length) != 0) {
581 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
582 "supplementalCredentialsBlob memcmp differ");
588 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_bypass - validated\n");
589 return ldb_next_request(module, request);
592 /* Get the NT hash, and fill it in as an entry in the password history,
593 and specify it into io->g.nt_hash */
595 static int setup_nt_fields(struct setup_password_fields_io *io)
597 struct ldb_context *ldb;
600 io->g.nt_hash = io->n.nt_hash;
601 ldb = ldb_module_get_ctx(io->ac->module);
603 if (io->ac->status->domain_data.pwdHistoryLength == 0) {
607 /* We might not have an old NT password */
608 io->g.nt_history = talloc_array(io->ac,
609 struct samr_Password,
610 io->ac->status->domain_data.pwdHistoryLength);
611 if (!io->g.nt_history) {
615 for (i = 0; i < MIN(io->ac->status->domain_data.pwdHistoryLength-1,
616 io->o.nt_history_len); i++) {
617 io->g.nt_history[i+1] = io->o.nt_history[i];
619 io->g.nt_history_len = i + 1;
622 io->g.nt_history[0] = *io->g.nt_hash;
625 * TODO: is this correct?
626 * the simular behavior is correct for the lm history case
628 E_md4hash("", io->g.nt_history[0].hash);
634 /* Get the LANMAN hash, and fill it in as an entry in the password history,
635 and specify it into io->g.lm_hash */
637 static int setup_lm_fields(struct setup_password_fields_io *io)
639 struct ldb_context *ldb;
642 io->g.lm_hash = io->n.lm_hash;
643 ldb = ldb_module_get_ctx(io->ac->module);
645 if (io->ac->status->domain_data.pwdHistoryLength == 0) {
649 /* We might not have an old LM password */
650 io->g.lm_history = talloc_array(io->ac,
651 struct samr_Password,
652 io->ac->status->domain_data.pwdHistoryLength);
653 if (!io->g.lm_history) {
657 for (i = 0; i < MIN(io->ac->status->domain_data.pwdHistoryLength-1,
658 io->o.lm_history_len); i++) {
659 io->g.lm_history[i+1] = io->o.lm_history[i];
661 io->g.lm_history_len = i + 1;
664 io->g.lm_history[0] = *io->g.lm_hash;
666 E_deshash("", io->g.lm_history[0].hash);
672 static int setup_kerberos_keys(struct setup_password_fields_io *io)
674 struct ldb_context *ldb;
675 krb5_error_code krb5_ret;
676 char *salt_principal = NULL;
677 char *salt_data = NULL;
680 krb5_data cleartext_data;
682 ldb = ldb_module_get_ctx(io->ac->module);
683 cleartext_data.data = (char *)io->n.cleartext_utf8->data;
684 cleartext_data.length = io->n.cleartext_utf8->length;
686 krb5_ret = smb_krb5_salt_principal(io->ac->status->domain_data.realm,
687 io->u.sAMAccountName,
688 io->u.user_principal_name,
693 ldb_asprintf_errstring(ldb,
694 "setup_kerberos_keys: "
695 "generation of a salting principal failed: %s",
696 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
698 return LDB_ERR_OPERATIONS_ERROR;
702 * create salt from salt_principal
704 krb5_ret = smb_krb5_salt_principal2data(io->smb_krb5_context->krb5_context,
705 salt_principal, io->ac, &salt_data);
707 ldb_asprintf_errstring(ldb,
708 "setup_kerberos_keys: "
709 "generation of krb5_salt failed: %s",
710 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
712 return LDB_ERR_OPERATIONS_ERROR;
714 io->g.salt = salt_data;
716 /* now use the talloced copy of the salt */
717 salt.data = discard_const(io->g.salt);
718 salt.length = strlen(io->g.salt);
721 * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of
722 * the salt and the cleartext password
724 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
728 ENCTYPE_AES256_CTS_HMAC_SHA1_96,
731 ldb_asprintf_errstring(ldb,
732 "setup_kerberos_keys: "
733 "generation of a aes256-cts-hmac-sha1-96 key failed: %s",
734 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
736 return LDB_ERR_OPERATIONS_ERROR;
738 io->g.aes_256 = data_blob_talloc(io->ac,
740 KRB5_KEY_LENGTH(&key));
741 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
742 if (!io->g.aes_256.data) {
747 * create ENCTYPE_AES128_CTS_HMAC_SHA1_96 key out of
748 * the salt and the cleartext password
750 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
754 ENCTYPE_AES128_CTS_HMAC_SHA1_96,
757 ldb_asprintf_errstring(ldb,
758 "setup_kerberos_keys: "
759 "generation of a aes128-cts-hmac-sha1-96 key failed: %s",
760 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
762 return LDB_ERR_OPERATIONS_ERROR;
764 io->g.aes_128 = data_blob_talloc(io->ac,
766 KRB5_KEY_LENGTH(&key));
767 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
768 if (!io->g.aes_128.data) {
773 * create ENCTYPE_DES_CBC_MD5 key out of
774 * the salt and the cleartext password
776 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
783 ldb_asprintf_errstring(ldb,
784 "setup_kerberos_keys: "
785 "generation of a des-cbc-md5 key failed: %s",
786 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
788 return LDB_ERR_OPERATIONS_ERROR;
790 io->g.des_md5 = data_blob_talloc(io->ac,
792 KRB5_KEY_LENGTH(&key));
793 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
794 if (!io->g.des_md5.data) {
799 * create ENCTYPE_DES_CBC_CRC 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,
809 ldb_asprintf_errstring(ldb,
810 "setup_kerberos_keys: "
811 "generation of a des-cbc-crc key failed: %s",
812 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
814 return LDB_ERR_OPERATIONS_ERROR;
816 io->g.des_crc = 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.des_crc.data) {
827 static int setup_primary_kerberos(struct setup_password_fields_io *io,
828 const struct supplementalCredentialsBlob *old_scb,
829 struct package_PrimaryKerberosBlob *pkb)
831 struct ldb_context *ldb;
832 struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3;
833 struct supplementalCredentialsPackage *old_scp = NULL;
834 struct package_PrimaryKerberosBlob _old_pkb;
835 struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL;
837 enum ndr_err_code ndr_err;
839 ldb = ldb_module_get_ctx(io->ac->module);
842 * prepare generation of keys
844 * ENCTYPE_DES_CBC_MD5
845 * ENCTYPE_DES_CBC_CRC
848 pkb3->salt.string = io->g.salt;
850 pkb3->keys = talloc_array(io->ac,
851 struct package_PrimaryKerberosKey3,
857 pkb3->keys[0].keytype = ENCTYPE_DES_CBC_MD5;
858 pkb3->keys[0].value = &io->g.des_md5;
859 pkb3->keys[1].keytype = ENCTYPE_DES_CBC_CRC;
860 pkb3->keys[1].value = &io->g.des_crc;
862 /* initialize the old keys to zero */
863 pkb3->num_old_keys = 0;
864 pkb3->old_keys = NULL;
866 /* if there're no old keys, then we're done */
871 for (i=0; i < old_scb->sub.num_packages; i++) {
872 if (strcmp("Primary:Kerberos", old_scb->sub.packages[i].name) != 0) {
876 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
880 old_scp = &old_scb->sub.packages[i];
883 /* Primary:Kerberos element of supplementalCredentials */
887 blob = strhex_to_data_blob(io->ac, old_scp->data);
892 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
893 ndr_err = ndr_pull_struct_blob(&blob, io->ac, &_old_pkb,
894 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
895 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
896 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
897 ldb_asprintf_errstring(ldb,
898 "setup_primary_kerberos: "
899 "failed to pull old package_PrimaryKerberosBlob: %s",
901 return LDB_ERR_OPERATIONS_ERROR;
904 if (_old_pkb.version != 3) {
905 ldb_asprintf_errstring(ldb,
906 "setup_primary_kerberos: "
907 "package_PrimaryKerberosBlob version[%u] expected[3]",
909 return LDB_ERR_OPERATIONS_ERROR;
912 old_pkb3 = &_old_pkb.ctr.ctr3;
915 /* if we didn't found the old keys we're done */
920 /* fill in the old keys */
921 pkb3->num_old_keys = old_pkb3->num_keys;
922 pkb3->old_keys = old_pkb3->keys;
927 static int setup_primary_kerberos_newer(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_PrimaryKerberosCtr4 *pkb4 = &pkb->ctr.ctr4;
933 struct supplementalCredentialsPackage *old_scp = NULL;
934 struct package_PrimaryKerberosBlob _old_pkb;
935 struct package_PrimaryKerberosCtr4 *old_pkb4 = NULL;
937 enum ndr_err_code ndr_err;
939 ldb = ldb_module_get_ctx(io->ac->module);
942 * prepare generation of keys
944 * ENCTYPE_AES256_CTS_HMAC_SHA1_96
945 * ENCTYPE_AES128_CTS_HMAC_SHA1_96
946 * ENCTYPE_DES_CBC_MD5
947 * ENCTYPE_DES_CBC_CRC
950 pkb4->salt.string = io->g.salt;
951 pkb4->default_iteration_count = 4096;
954 pkb4->keys = talloc_array(io->ac,
955 struct package_PrimaryKerberosKey4,
961 pkb4->keys[0].iteration_count = 4096;
962 pkb4->keys[0].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
963 pkb4->keys[0].value = &io->g.aes_256;
964 pkb4->keys[1].iteration_count = 4096;
965 pkb4->keys[1].keytype = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
966 pkb4->keys[1].value = &io->g.aes_128;
967 pkb4->keys[2].iteration_count = 4096;
968 pkb4->keys[2].keytype = ENCTYPE_DES_CBC_MD5;
969 pkb4->keys[2].value = &io->g.des_md5;
970 pkb4->keys[3].iteration_count = 4096;
971 pkb4->keys[3].keytype = ENCTYPE_DES_CBC_CRC;
972 pkb4->keys[3].value = &io->g.des_crc;
974 /* initialize the old keys to zero */
975 pkb4->num_old_keys = 0;
976 pkb4->old_keys = NULL;
977 pkb4->num_older_keys = 0;
978 pkb4->older_keys = NULL;
980 /* if there're no old keys, then we're done */
985 for (i=0; i < old_scb->sub.num_packages; i++) {
986 if (strcmp("Primary:Kerberos-Newer-Keys", old_scb->sub.packages[i].name) != 0) {
990 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
994 old_scp = &old_scb->sub.packages[i];
997 /* Primary:Kerberos-Newer-Keys element of supplementalCredentials */
1001 blob = strhex_to_data_blob(io->ac, old_scp->data);
1003 return ldb_oom(ldb);
1006 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
1007 ndr_err = ndr_pull_struct_blob(&blob, io->ac,
1009 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
1010 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1011 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1012 ldb_asprintf_errstring(ldb,
1013 "setup_primary_kerberos_newer: "
1014 "failed to pull old package_PrimaryKerberosBlob: %s",
1016 return LDB_ERR_OPERATIONS_ERROR;
1019 if (_old_pkb.version != 4) {
1020 ldb_asprintf_errstring(ldb,
1021 "setup_primary_kerberos_newer: "
1022 "package_PrimaryKerberosBlob version[%u] expected[4]",
1024 return LDB_ERR_OPERATIONS_ERROR;
1027 old_pkb4 = &_old_pkb.ctr.ctr4;
1030 /* if we didn't found the old keys we're done */
1035 /* fill in the old keys */
1036 pkb4->num_old_keys = old_pkb4->num_keys;
1037 pkb4->old_keys = old_pkb4->keys;
1038 pkb4->num_older_keys = old_pkb4->num_old_keys;
1039 pkb4->older_keys = old_pkb4->old_keys;
1044 static int setup_primary_wdigest(struct setup_password_fields_io *io,
1045 const struct supplementalCredentialsBlob *old_scb,
1046 struct package_PrimaryWDigestBlob *pdb)
1048 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1049 DATA_BLOB sAMAccountName;
1050 DATA_BLOB sAMAccountName_l;
1051 DATA_BLOB sAMAccountName_u;
1052 const char *user_principal_name = io->u.user_principal_name;
1053 DATA_BLOB userPrincipalName;
1054 DATA_BLOB userPrincipalName_l;
1055 DATA_BLOB userPrincipalName_u;
1056 DATA_BLOB netbios_domain;
1057 DATA_BLOB netbios_domain_l;
1058 DATA_BLOB netbios_domain_u;
1059 DATA_BLOB dns_domain;
1060 DATA_BLOB dns_domain_l;
1061 DATA_BLOB dns_domain_u;
1064 DATA_BLOB backslash;
1072 * See 3.1.1.8.11.3.1 WDIGEST_CREDENTIALS Construction
1073 * https://msdn.microsoft.com/en-us/library/cc245680.aspx
1074 * for what precalculated hashes are supposed to be stored...
1076 * I can't reproduce all values which should contain "Digest" as realm,
1077 * am I doing something wrong or is w2k3 just broken...?
1079 * W2K3 fills in following for a user:
1081 * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1082 * sAMAccountName: NewUser2Sam
1083 * userPrincipalName: NewUser2Princ@sub1.w2k3.vmnet1.vm.base
1085 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1086 * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1087 * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1088 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1089 * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1090 * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1091 * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1092 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1093 * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1094 * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1095 * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1096 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1097 * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1098 * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1099 * 221c55284451ae9b3aacaa2a3c86f10f => NewUser2Princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1100 * 74e1be668853d4324d38c07e2acfb8ea => (w2k3 has a bug here!) newuser2princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1101 * e1e244ab7f098e3ae1761be7f9229bbb => NEWUSER2PRINC@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1102 * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1103 * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1104 * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1105 * 31dc704d3640335b2123d4ee28aa1f11 => ??? changes with NewUser2Sam => NewUser1Sam
1106 * 36349f5cecd07320fb3bb0e119230c43 => ??? changes with NewUser2Sam => NewUser1Sam
1107 * 12adf019d037fb535c01fd0608e78d9d => ??? changes with NewUser2Sam => NewUser1Sam
1108 * 6feecf8e724906f3ee1105819c5105a1 => ??? changes with NewUser2Princ => NewUser1Princ
1109 * 6c6911f3de6333422640221b9c51ff1f => ??? changes with NewUser2Princ => NewUser1Princ
1110 * 4b279877e742895f9348ac67a8de2f69 => ??? changes with NewUser2Princ => NewUser1Princ
1111 * db0c6bff069513e3ebb9870d29b57490 => ??? changes with NewUser2Sam => NewUser1Sam
1112 * 45072621e56b1c113a4e04a8ff68cd0e => ??? changes with NewUser2Sam => NewUser1Sam
1113 * 11d1220abc44a9c10cf91ef4a9c1de02 => ??? changes with NewUser2Sam => NewUser1Sam
1115 * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1116 * sAMAccountName: NewUser2Sam
1118 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1119 * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1120 * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1121 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1122 * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1123 * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1124 * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1125 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1126 * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1127 * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1128 * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1129 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1130 * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1131 * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1132 * 8a140d30b6f0a5912735dc1e3bc993b4 => NewUser2Sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1133 * 86d95b2faae6cae4ec261e7fbaccf093 => (here w2k3 is correct) newuser2sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1134 * dfeff1493110220efcdfc6362e5f5450 => NEWUSER2SAM@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1135 * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1136 * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1137 * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1138 * 31dc704d3640335b2123d4ee28aa1f11 => ???M1 changes with NewUser2Sam => NewUser1Sam
1139 * 36349f5cecd07320fb3bb0e119230c43 => ???M1.L changes with newuser2sam => newuser1sam
1140 * 12adf019d037fb535c01fd0608e78d9d => ???M1.U changes with NEWUSER2SAM => NEWUSER1SAM
1141 * 569b4533f2d9e580211dd040e5e360a8 => ???M2 changes with NewUser2Princ => NewUser1Princ
1142 * 52528bddf310a587c5d7e6a9ae2cbb20 => ???M2.L changes with newuser2princ => newuser1princ
1143 * 4f629a4f0361289ca4255ab0f658fcd5 => ???M3 changes with NewUser2Princ => NewUser1Princ (doesn't depend on case of userPrincipal )
1144 * db0c6bff069513e3ebb9870d29b57490 => ???M4 changes with NewUser2Sam => NewUser1Sam
1145 * 45072621e56b1c113a4e04a8ff68cd0e => ???M5 changes with NewUser2Sam => NewUser1Sam (doesn't depend on case of sAMAccountName)
1146 * 11d1220abc44a9c10cf91ef4a9c1de02 => ???M4.U changes with NEWUSER2SAM => NEWUSER1SAM
1150 * sAMAccountName, netbios_domain
1153 .user = &sAMAccountName,
1154 .realm = &netbios_domain,
1157 .user = &sAMAccountName_l,
1158 .realm = &netbios_domain_l,
1161 .user = &sAMAccountName_u,
1162 .realm = &netbios_domain_u,
1165 .user = &sAMAccountName,
1166 .realm = &netbios_domain_u,
1169 .user = &sAMAccountName,
1170 .realm = &netbios_domain_l,
1173 .user = &sAMAccountName_u,
1174 .realm = &netbios_domain_l,
1177 .user = &sAMAccountName_l,
1178 .realm = &netbios_domain_u,
1181 * sAMAccountName, dns_domain
1184 * Windows preserves the case of the DNS domain,
1185 * Samba lower cases the domain at provision time
1186 * This means that for mixed case Domains, the WDigest08 hash
1187 * calculated by Samba differs from that calculated by Windows.
1188 * Until we get a real world use case this will remain a known
1189 * bug, as changing the case could have unforeseen impacts.
1193 .user = &sAMAccountName,
1194 .realm = &dns_domain,
1197 .user = &sAMAccountName_l,
1198 .realm = &dns_domain_l,
1201 .user = &sAMAccountName_u,
1202 .realm = &dns_domain_u,
1205 .user = &sAMAccountName,
1206 .realm = &dns_domain_u,
1209 .user = &sAMAccountName,
1210 .realm = &dns_domain_l,
1213 .user = &sAMAccountName_u,
1214 .realm = &dns_domain_l,
1217 .user = &sAMAccountName_l,
1218 .realm = &dns_domain_u,
1221 * userPrincipalName, no realm
1224 .user = &userPrincipalName,
1228 * NOTE: w2k3 messes this up, if the user has a real userPrincipalName,
1229 * the fallback to the sAMAccountName based userPrincipalName is correct
1231 .user = &userPrincipalName_l,
1234 .user = &userPrincipalName_u,
1237 * nt4dom\sAMAccountName, no realm
1240 .user = &sAMAccountName,
1241 .nt4dom = &netbios_domain
1244 .user = &sAMAccountName_l,
1245 .nt4dom = &netbios_domain_l
1248 .user = &sAMAccountName_u,
1249 .nt4dom = &netbios_domain_u
1253 * the following ones are guessed depending on the technet2 article
1254 * but not reproducable on a w2k3 server
1256 /* sAMAccountName with "Digest" realm */
1258 .user = &sAMAccountName,
1262 .user = &sAMAccountName_l,
1266 .user = &sAMAccountName_u,
1269 /* userPrincipalName with "Digest" realm */
1271 .user = &userPrincipalName,
1275 .user = &userPrincipalName_l,
1279 .user = &userPrincipalName_u,
1282 /* nt4dom\\sAMAccountName with "Digest" realm */
1284 .user = &sAMAccountName,
1285 .nt4dom = &netbios_domain,
1289 .user = &sAMAccountName_l,
1290 .nt4dom = &netbios_domain_l,
1294 .user = &sAMAccountName_u,
1295 .nt4dom = &netbios_domain_u,
1300 /* prepare DATA_BLOB's used in the combinations array */
1301 sAMAccountName = data_blob_string_const(io->u.sAMAccountName);
1302 sAMAccountName_l = data_blob_string_const(strlower_talloc(io->ac, io->u.sAMAccountName));
1303 if (!sAMAccountName_l.data) {
1304 return ldb_oom(ldb);
1306 sAMAccountName_u = data_blob_string_const(strupper_talloc(io->ac, io->u.sAMAccountName));
1307 if (!sAMAccountName_u.data) {
1308 return ldb_oom(ldb);
1311 /* if the user doesn't have a userPrincipalName, create one (with lower case realm) */
1312 if (!user_principal_name) {
1313 user_principal_name = talloc_asprintf(io->ac, "%s@%s",
1314 io->u.sAMAccountName,
1315 io->ac->status->domain_data.dns_domain);
1316 if (!user_principal_name) {
1317 return ldb_oom(ldb);
1320 userPrincipalName = data_blob_string_const(user_principal_name);
1321 userPrincipalName_l = data_blob_string_const(strlower_talloc(io->ac, user_principal_name));
1322 if (!userPrincipalName_l.data) {
1323 return ldb_oom(ldb);
1325 userPrincipalName_u = data_blob_string_const(strupper_talloc(io->ac, user_principal_name));
1326 if (!userPrincipalName_u.data) {
1327 return ldb_oom(ldb);
1330 netbios_domain = data_blob_string_const(io->ac->status->domain_data.netbios_domain);
1331 netbios_domain_l = data_blob_string_const(strlower_talloc(io->ac,
1332 io->ac->status->domain_data.netbios_domain));
1333 if (!netbios_domain_l.data) {
1334 return ldb_oom(ldb);
1336 netbios_domain_u = data_blob_string_const(strupper_talloc(io->ac,
1337 io->ac->status->domain_data.netbios_domain));
1338 if (!netbios_domain_u.data) {
1339 return ldb_oom(ldb);
1342 dns_domain = data_blob_string_const(io->ac->status->domain_data.dns_domain);
1343 dns_domain_l = data_blob_string_const(io->ac->status->domain_data.dns_domain);
1344 dns_domain_u = data_blob_string_const(io->ac->status->domain_data.realm);
1346 digest = data_blob_string_const("Digest");
1348 delim = data_blob_string_const(":");
1349 backslash = data_blob_string_const("\\");
1351 pdb->num_hashes = ARRAY_SIZE(wdigest);
1352 pdb->hashes = talloc_array(io->ac, struct package_PrimaryWDigestHash,
1355 return ldb_oom(ldb);
1358 for (i=0; i < ARRAY_SIZE(wdigest); i++) {
1361 if (wdigest[i].nt4dom) {
1362 MD5Update(&md5, wdigest[i].nt4dom->data, wdigest[i].nt4dom->length);
1363 MD5Update(&md5, backslash.data, backslash.length);
1365 MD5Update(&md5, wdigest[i].user->data, wdigest[i].user->length);
1366 MD5Update(&md5, delim.data, delim.length);
1367 if (wdigest[i].realm) {
1368 MD5Update(&md5, wdigest[i].realm->data, wdigest[i].realm->length);
1370 MD5Update(&md5, delim.data, delim.length);
1371 MD5Update(&md5, io->n.cleartext_utf8->data, io->n.cleartext_utf8->length);
1372 MD5Final(pdb->hashes[i].hash, &md5);
1378 #define SHA_SALT_PERMITTED_CHARS "abcdefghijklmnopqrstuvwxyz" \
1379 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
1381 #define SHA_SALT_SIZE 16
1382 #define SHA_256_SCHEME "CryptSHA256"
1383 #define SHA_512_SCHEME "CryptSHA512"
1384 #define CRYPT "{CRYPT}"
1385 #define SHA_ID_LEN 3
1386 #define SHA_256_ALGORITHM_ID 5
1387 #define SHA_512_ALGORITHM_ID 6
1388 #define ROUNDS_PARAMETER "rounds="
1391 * Extract the crypt (3) algorithm number and number of hash rounds from the
1392 * supplied scheme string
1394 static bool parse_scheme(const char *scheme, int *algorithm, int *rounds) {
1396 const char *rp = NULL; /* Pointer to the 'rounds=' option */
1397 char digits[21]; /* digits extracted from the rounds option */
1398 int i = 0; /* loop index variable */
1400 if (strncasecmp(SHA_256_SCHEME, scheme, strlen(SHA_256_SCHEME)) == 0) {
1401 *algorithm = SHA_256_ALGORITHM_ID;
1402 } else if (strncasecmp(SHA_512_SCHEME, scheme, strlen(SHA_256_SCHEME))
1404 *algorithm = SHA_512_ALGORITHM_ID;
1409 rp = strcasestr(scheme, ROUNDS_PARAMETER);
1411 /* No options specified, use crypt default number of rounds */
1415 rp += strlen(ROUNDS_PARAMETER);
1416 for (i = 0; isdigit(rp[i]) && i < (sizeof(digits) - 1); i++) {
1420 *rounds = atoi(digits);
1425 * Calculate the password hash specified by scheme, and return it in
1428 static int setup_primary_userPassword_hash(
1430 struct setup_password_fields_io *io,
1432 struct package_PrimaryUserPasswordValue *hash_value)
1434 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1435 const char *salt = NULL; /* Randomly generated salt */
1436 const char *cmd = NULL; /* command passed to crypt */
1437 const char *hash = NULL; /* password hash generated by crypt */
1438 int algorithm = 0; /* crypt hash algorithm number */
1439 int rounds = 0; /* The number of hash rounds */
1440 DATA_BLOB *hash_blob = NULL;
1441 TALLOC_CTX *frame = talloc_stackframe();
1443 struct crypt_data crypt_data; /* working storage used by crypt */
1446 /* Genrate a random password salt */
1447 salt = generate_random_str_list(frame,
1449 SHA_SALT_PERMITTED_CHARS);
1452 return ldb_oom(ldb);
1455 /* determine the hashing algoritm and number of rounds*/
1456 if (!parse_scheme(scheme, &algorithm, &rounds)) {
1457 ldb_asprintf_errstring(
1459 "setup_primary_userPassword: Invalid scheme of [%s] "
1460 "specified for 'password hash userPassword schemes' in "
1464 return LDB_ERR_OPERATIONS_ERROR;
1466 hash_value->scheme = talloc_strdup(ctx, CRYPT);
1467 hash_value->scheme_len = strlen(CRYPT) + 1;
1469 /* generate the id/salt parameter used by crypt */
1471 cmd = talloc_asprintf(frame,
1477 cmd = talloc_asprintf(frame, "$%d$%s", algorithm, salt);
1481 * Relies on the assertion that cleartext_utf8->data is a zero
1482 * terminated UTF-8 string
1485 hash = crypt_r((char *)io->n.cleartext_utf8->data, cmd, &crypt_data);
1488 * No crypt_r falling back to crypt, which is NOT thread safe
1489 * Thread safety MT-Unsafe race:crypt
1491 hash = crypt((char *)io->n.cleartext_utf8->data, cmd);
1495 int err = strerror_r(errno, buf, sizeof(buf));
1497 strlcpy(buf, "Unknown error", sizeof(buf)-1);
1499 ldb_asprintf_errstring(
1501 "setup_primary_userPassword: generation of a %s "
1502 "password hash failed: (%s)",
1506 return LDB_ERR_OPERATIONS_ERROR;
1509 hash_blob = talloc_zero(ctx, DATA_BLOB);
1511 if (hash_blob == NULL) {
1513 return ldb_oom(ldb);
1516 *hash_blob = data_blob_talloc(hash_blob,
1517 (const uint8_t *)hash,
1519 if (hash_blob->data == NULL) {
1521 return ldb_oom(ldb);
1523 hash_value->value = hash_blob;
1529 * Calculate the desired extra password hashes
1531 static int setup_primary_userPassword(
1532 struct setup_password_fields_io *io,
1533 const struct supplementalCredentialsBlob *old_scb,
1534 struct package_PrimaryUserPasswordBlob *p_userPassword_b)
1536 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1537 TALLOC_CTX *frame = talloc_stackframe();
1542 * Save the current nt_hash, use this to determine if the password
1543 * has been changed by windows. Which will invalidate the userPassword
1544 * hash. Note once NTLM-Strong-NOWTF becomes available it should be
1545 * used in preference to the NT password hash
1547 if (io->g.nt_hash == NULL) {
1548 ldb_asprintf_errstring(ldb,
1549 "No NT Hash, unable to calculate userPassword hashes");
1550 return LDB_ERR_UNWILLING_TO_PERFORM;
1552 p_userPassword_b->current_nt_hash = *io->g.nt_hash;
1555 * Determine the number of hashes
1556 * Note: that currently there is no limit on the number of hashes
1557 * no checking is done on the number of schemes specified
1558 * or for uniqueness.
1560 p_userPassword_b->num_hashes = 0;
1561 for (i = 0; io->ac->userPassword_schemes[i]; i++) {
1562 p_userPassword_b->num_hashes++;
1565 p_userPassword_b->hashes
1566 = talloc_array(io->ac,
1567 struct package_PrimaryUserPasswordValue,
1568 p_userPassword_b->num_hashes);
1569 if (p_userPassword_b->hashes == NULL) {
1571 return ldb_oom(ldb);
1574 for (i = 0; io->ac->userPassword_schemes[i]; i++) {
1575 ret = setup_primary_userPassword_hash(
1576 p_userPassword_b->hashes,
1578 io->ac->userPassword_schemes[i],
1579 &p_userPassword_b->hashes[i]);
1580 if (ret != LDB_SUCCESS) {
1589 static int setup_primary_samba_gpg(struct setup_password_fields_io *io,
1590 struct package_PrimarySambaGPGBlob *pgb)
1592 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1595 gpgme_ctx_t ctx = NULL;
1596 size_t num_keys = str_list_length(io->ac->gpg_key_ids);
1597 gpgme_key_t keys[num_keys+1];
1600 gpgme_data_t plain_data = NULL;
1601 gpgme_data_t crypt_data = NULL;
1602 size_t crypt_length = 0;
1603 char *crypt_mem = NULL;
1605 gret = gpgme_new(&ctx);
1606 if (gret != GPG_ERR_NO_ERROR) {
1607 ldb_debug(ldb, LDB_DEBUG_ERROR,
1608 "%s:%s: gret[%u] %s\n",
1609 __location__, __func__,
1610 gret, gpgme_strerror(gret));
1611 return ldb_module_operr(io->ac->module);
1614 gpgme_set_armor(ctx, 1);
1616 gret = gpgme_data_new_from_mem(&plain_data,
1617 (const char *)io->n.cleartext_utf16->data,
1618 io->n.cleartext_utf16->length,
1620 if (gret != GPG_ERR_NO_ERROR) {
1621 ldb_debug(ldb, LDB_DEBUG_ERROR,
1622 "%s:%s: gret[%u] %s\n",
1623 __location__, __func__,
1624 gret, gpgme_strerror(gret));
1626 return ldb_module_operr(io->ac->module);
1628 gret = gpgme_data_new(&crypt_data);
1629 if (gret != GPG_ERR_NO_ERROR) {
1630 ldb_debug(ldb, LDB_DEBUG_ERROR,
1631 "%s:%s: gret[%u] %s\n",
1632 __location__, __func__,
1633 gret, gpgme_strerror(gret));
1634 gpgme_data_release(plain_data);
1636 return ldb_module_operr(io->ac->module);
1639 for (ki = 0; ki < num_keys; ki++) {
1640 const char *key_id = io->ac->gpg_key_ids[ki];
1641 size_t len = strlen(key_id);
1646 ldb_debug(ldb, LDB_DEBUG_FATAL,
1647 "%s:%s: ki[%zu] key_id[%s] strlen < 16, "
1648 "please specify at least the 64bit key id\n",
1649 __location__, __func__,
1651 for (kr = 0; keys[kr] != NULL; kr++) {
1652 gpgme_key_release(keys[kr]);
1654 gpgme_data_release(crypt_data);
1655 gpgme_data_release(plain_data);
1657 return ldb_module_operr(io->ac->module);
1660 gret = gpgme_get_key(ctx, key_id, &keys[ki], 0 /* public key */);
1661 if (gret != GPG_ERR_NO_ERROR) {
1663 if (gpg_err_source(gret) == GPG_ERR_SOURCE_GPGME
1664 && gpg_err_code(gret) == GPG_ERR_EOF) {
1665 ldb_debug(ldb, LDB_DEBUG_ERROR,
1667 "'password hash gpg key ids': "
1668 "Public Key ID [%s] "
1669 "not found in keyring\n",
1673 ldb_debug(ldb, LDB_DEBUG_ERROR,
1674 "%s:%s: ki[%zu] key_id[%s] "
1676 __location__, __func__,
1678 gret, gpgme_strerror(gret));
1680 for (kr = 0; keys[kr] != NULL; kr++) {
1681 gpgme_key_release(keys[kr]);
1683 gpgme_data_release(crypt_data);
1684 gpgme_data_release(plain_data);
1686 return ldb_module_operr(io->ac->module);
1691 gret = gpgme_op_encrypt(ctx, keys,
1692 GPGME_ENCRYPT_ALWAYS_TRUST,
1693 plain_data, crypt_data);
1694 gpgme_data_release(plain_data);
1696 for (kr = 0; keys[kr] != NULL; kr++) {
1697 gpgme_key_release(keys[kr]);
1702 if (gret != GPG_ERR_NO_ERROR) {
1703 ldb_debug(ldb, LDB_DEBUG_ERROR,
1704 "%s:%s: gret[%u] %s\n",
1705 __location__, __func__,
1706 gret, gpgme_strerror(gret));
1707 gpgme_data_release(crypt_data);
1708 return ldb_module_operr(io->ac->module);
1711 crypt_mem = gpgme_data_release_and_get_mem(crypt_data, &crypt_length);
1713 if (crypt_mem == NULL) {
1714 return ldb_module_oom(io->ac->module);
1717 pgb->gpg_blob = data_blob_talloc(io->ac,
1718 (const uint8_t *)crypt_mem,
1720 gpgme_free(crypt_mem);
1723 if (pgb->gpg_blob.data == NULL) {
1724 return ldb_module_oom(io->ac->module);
1728 #else /* ENABLE_GPGME */
1729 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1730 "You configured 'password hash gpg key ids', "
1731 "but GPGME support is missing. (%s:%d)",
1732 __FILE__, __LINE__);
1733 return LDB_ERR_UNWILLING_TO_PERFORM;
1734 #endif /* else ENABLE_GPGME */
1737 #define NUM_PACKAGES 6
1738 static int setup_supplemental_field(struct setup_password_fields_io *io)
1740 struct ldb_context *ldb;
1741 struct supplementalCredentialsBlob scb;
1742 struct supplementalCredentialsBlob *old_scb = NULL;
1745 * ( Kerberos-Newer-Keys, Kerberos,
1746 * WDigest, CLEARTEXT, userPassword, SambaGPG)
1748 uint32_t num_names = 0;
1749 const char *names[1+NUM_PACKAGES];
1750 uint32_t num_packages = 0;
1751 struct supplementalCredentialsPackage packages[1+NUM_PACKAGES];
1752 struct supplementalCredentialsPackage *pp = packages;
1754 enum ndr_err_code ndr_err;
1755 bool do_newer_keys = false;
1756 bool do_cleartext = false;
1757 bool do_samba_gpg = false;
1760 ZERO_STRUCT(packages);
1762 ldb = ldb_module_get_ctx(io->ac->module);
1764 if (!io->n.cleartext_utf8) {
1766 * when we don't have a cleartext password
1767 * we can't setup a supplementalCredential value
1772 /* if there's an old supplementaCredentials blob then use it */
1773 if (io->o.supplemental) {
1774 if (io->o.scb.sub.signature == SUPPLEMENTAL_CREDENTIALS_SIGNATURE) {
1775 old_scb = &io->o.scb;
1777 ldb_debug(ldb, LDB_DEBUG_ERROR,
1778 "setup_supplemental_field: "
1779 "supplementalCredentialsBlob "
1780 "signature[0x%04X] expected[0x%04X]",
1781 io->o.scb.sub.signature,
1782 SUPPLEMENTAL_CREDENTIALS_SIGNATURE);
1785 /* Per MS-SAMR 3.1.1.8.11.6 we create AES keys if our domain functionality level is 2008 or higher */
1790 * The ordering is this
1792 * Primary:Kerberos-Newer-Keys (optional)
1795 * Primary:CLEARTEXT (optional)
1796 * Primary:userPassword
1797 * Primary:SambaGPG (optional)
1799 * And the 'Packages' package is insert before the last
1802 * Note: it's important that Primary:SambaGPG is added as
1803 * the last element. This is the indication that it matches
1804 * the current password. When a password change happens on
1805 * a Windows DC, it will keep the old Primary:SambaGPG value,
1806 * but as the first element.
1808 do_newer_keys = (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2008);
1809 if (do_newer_keys) {
1810 struct package_PrimaryKerberosBlob pknb;
1811 DATA_BLOB pknb_blob;
1814 * setup 'Primary:Kerberos-Newer-Keys' element
1816 names[num_names++] = "Kerberos-Newer-Keys";
1818 ret = setup_primary_kerberos_newer(io, old_scb, &pknb);
1819 if (ret != LDB_SUCCESS) {
1823 ndr_err = ndr_push_struct_blob(
1826 (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
1827 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1828 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1829 ldb_asprintf_errstring(
1831 "setup_supplemental_field: "
1833 "package_PrimaryKerberosNeverBlob: %s",
1835 return LDB_ERR_OPERATIONS_ERROR;
1837 pknb_hexstr = data_blob_hex_string_upper(io->ac, &pknb_blob);
1839 return ldb_oom(ldb);
1841 pp->name = "Primary:Kerberos-Newer-Keys";
1843 pp->data = pknb_hexstr;
1850 * setup 'Primary:Kerberos' element
1852 /* Primary:Kerberos */
1853 struct package_PrimaryKerberosBlob pkb;
1857 names[num_names++] = "Kerberos";
1859 ret = setup_primary_kerberos(io, old_scb, &pkb);
1860 if (ret != LDB_SUCCESS) {
1864 ndr_err = ndr_push_struct_blob(
1867 (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
1868 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1869 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1870 ldb_asprintf_errstring(
1872 "setup_supplemental_field: "
1873 "failed to push package_PrimaryKerberosBlob: %s",
1875 return LDB_ERR_OPERATIONS_ERROR;
1877 pkb_hexstr = data_blob_hex_string_upper(io->ac, &pkb_blob);
1879 return ldb_oom(ldb);
1881 pp->name = "Primary:Kerberos";
1883 pp->data = pkb_hexstr;
1890 * setup 'Primary:WDigest' element
1892 struct package_PrimaryWDigestBlob pdb;
1896 names[num_names++] = "WDigest";
1898 ret = setup_primary_wdigest(io, old_scb, &pdb);
1899 if (ret != LDB_SUCCESS) {
1903 ndr_err = ndr_push_struct_blob(
1906 (ndr_push_flags_fn_t)ndr_push_package_PrimaryWDigestBlob);
1907 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1908 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1909 ldb_asprintf_errstring(
1911 "setup_supplemental_field: "
1912 "failed to push package_PrimaryWDigestBlob: %s",
1914 return LDB_ERR_OPERATIONS_ERROR;
1916 pdb_hexstr = data_blob_hex_string_upper(io->ac, &pdb_blob);
1918 return ldb_oom(ldb);
1920 pp->name = "Primary:WDigest";
1922 pp->data = pdb_hexstr;
1928 * setup 'Primary:CLEARTEXT' element
1930 if (io->ac->status->domain_data.store_cleartext &&
1931 (io->u.userAccountControl & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) {
1932 do_cleartext = true;
1935 struct package_PrimaryCLEARTEXTBlob pcb;
1939 names[num_names++] = "CLEARTEXT";
1941 pcb.cleartext = *io->n.cleartext_utf16;
1943 ndr_err = ndr_push_struct_blob(
1946 (ndr_push_flags_fn_t)ndr_push_package_PrimaryCLEARTEXTBlob);
1947 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1948 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1949 ldb_asprintf_errstring(
1951 "setup_supplemental_field: "
1952 "failed to push package_PrimaryCLEARTEXTBlob: %s",
1954 return LDB_ERR_OPERATIONS_ERROR;
1956 pcb_hexstr = data_blob_hex_string_upper(io->ac, &pcb_blob);
1958 return ldb_oom(ldb);
1960 pp->name = "Primary:CLEARTEXT";
1962 pp->data = pcb_hexstr;
1967 if (io->ac->userPassword_schemes) {
1969 * setup 'Primary:userPassword' element
1971 struct package_PrimaryUserPasswordBlob
1973 DATA_BLOB p_userPassword_b_blob;
1974 char *p_userPassword_b_hexstr;
1976 names[num_names++] = "userPassword";
1978 ret = setup_primary_userPassword(io,
1981 if (ret != LDB_SUCCESS) {
1985 ndr_err = ndr_push_struct_blob(
1986 &p_userPassword_b_blob,
1989 (ndr_push_flags_fn_t)
1990 ndr_push_package_PrimaryUserPasswordBlob);
1991 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1992 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1993 ldb_asprintf_errstring(
1995 "setup_supplemental_field: failed to push "
1996 "package_PrimaryUserPasswordBlob: %s",
1998 return LDB_ERR_OPERATIONS_ERROR;
2000 p_userPassword_b_hexstr
2001 = data_blob_hex_string_upper(
2003 &p_userPassword_b_blob);
2004 if (!p_userPassword_b_hexstr) {
2005 return ldb_oom(ldb);
2007 pp->name = "Primary:userPassword";
2009 pp->data = p_userPassword_b_hexstr;
2015 * setup 'Primary:SambaGPG' element
2017 if (io->ac->gpg_key_ids != NULL) {
2018 do_samba_gpg = true;
2021 struct package_PrimarySambaGPGBlob pgb;
2025 names[num_names++] = "SambaGPG";
2027 ret = setup_primary_samba_gpg(io, &pgb);
2028 if (ret != LDB_SUCCESS) {
2032 ndr_err = ndr_push_struct_blob(&pgb_blob, io->ac, &pgb,
2033 (ndr_push_flags_fn_t)ndr_push_package_PrimarySambaGPGBlob);
2034 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2035 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2036 ldb_asprintf_errstring(ldb,
2037 "setup_supplemental_field: failed to "
2038 "push package_PrimarySambaGPGBlob: %s",
2040 return LDB_ERR_OPERATIONS_ERROR;
2042 pgb_hexstr = data_blob_hex_string_upper(io->ac, &pgb_blob);
2044 return ldb_oom(ldb);
2046 pp->name = "Primary:SambaGPG";
2048 pp->data = pgb_hexstr;
2054 * setup 'Packages' element
2057 struct package_PackagesBlob pb;
2062 ndr_err = ndr_push_struct_blob(
2065 (ndr_push_flags_fn_t)ndr_push_package_PackagesBlob);
2066 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2067 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2068 ldb_asprintf_errstring(
2070 "setup_supplemental_field: "
2071 "failed to push package_PackagesBlob: %s",
2073 return LDB_ERR_OPERATIONS_ERROR;
2075 pb_hexstr = data_blob_hex_string_upper(io->ac, &pb_blob);
2077 return ldb_oom(ldb);
2079 pp->name = "Packages";
2081 pp->data = pb_hexstr;
2084 * We don't increment pp so it's pointing to the last package
2089 * setup 'supplementalCredentials' value
2093 * The 'Packages' element needs to be the second last element
2094 * in supplementalCredentials
2096 struct supplementalCredentialsPackage temp;
2097 struct supplementalCredentialsPackage *prev;
2105 scb.sub.signature = SUPPLEMENTAL_CREDENTIALS_SIGNATURE;
2106 scb.sub.num_packages = num_packages;
2107 scb.sub.packages = packages;
2109 ndr_err = ndr_push_struct_blob(
2110 &io->g.supplemental, io->ac,
2112 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
2113 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2114 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2115 ldb_asprintf_errstring(
2117 "setup_supplemental_field: "
2118 "failed to push supplementalCredentialsBlob: %s",
2120 return LDB_ERR_OPERATIONS_ERROR;
2127 static int setup_last_set_field(struct setup_password_fields_io *io)
2129 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2130 const struct ldb_message *msg = NULL;
2131 struct timeval tv = { .tv_sec = 0 };
2132 const struct ldb_val *old_val = NULL;
2133 const struct ldb_val *new_val = NULL;
2136 switch (io->ac->req->operation) {
2138 msg = io->ac->req->op.add.message;
2141 msg = io->ac->req->op.mod.message;
2144 return LDB_ERR_OPERATIONS_ERROR;
2148 if (io->ac->pwd_last_set_bypass) {
2149 struct ldb_message_element *el1 = NULL;
2150 struct ldb_message_element *el2 = NULL;
2153 return LDB_ERR_CONSTRAINT_VIOLATION;
2156 el1 = dsdb_get_single_valued_attr(msg, "pwdLastSet",
2157 io->ac->req->operation);
2159 return LDB_ERR_CONSTRAINT_VIOLATION;
2161 el2 = ldb_msg_find_element(msg, "pwdLastSet");
2163 return LDB_ERR_CONSTRAINT_VIOLATION;
2166 return LDB_ERR_CONSTRAINT_VIOLATION;
2169 io->g.last_set = samdb_result_nttime(msg, "pwdLastSet", 0);
2173 ret = msg_find_old_and_new_pwd_val(msg, "pwdLastSet",
2174 io->ac->req->operation,
2175 &new_val, &old_val);
2176 if (ret != LDB_SUCCESS) {
2180 if (old_val != NULL && new_val == NULL) {
2181 ldb_set_errstring(ldb,
2182 "'pwdLastSet' deletion is not allowed!");
2183 return LDB_ERR_UNWILLING_TO_PERFORM;
2186 io->g.last_set = UINT64_MAX;
2187 if (new_val != NULL) {
2188 struct ldb_message *tmp_msg = NULL;
2190 tmp_msg = ldb_msg_new(io->ac);
2191 if (tmp_msg == NULL) {
2192 return ldb_module_oom(io->ac->module);
2195 if (old_val != NULL) {
2196 NTTIME old_last_set = 0;
2198 ret = ldb_msg_add_value(tmp_msg, "oldval",
2200 if (ret != LDB_SUCCESS) {
2204 old_last_set = samdb_result_nttime(tmp_msg,
2207 if (io->u.pwdLastSet != old_last_set) {
2208 return dsdb_module_werror(io->ac->module,
2209 LDB_ERR_NO_SUCH_ATTRIBUTE,
2210 WERR_DS_CANT_REM_MISSING_ATT_VAL,
2211 "setup_last_set_field: old pwdLastSet "
2212 "value not found!");
2216 ret = ldb_msg_add_value(tmp_msg, "newval",
2218 if (ret != LDB_SUCCESS) {
2222 io->g.last_set = samdb_result_nttime(tmp_msg,
2225 } else if (ldb_msg_find_element(msg, "pwdLastSet")) {
2226 ldb_set_errstring(ldb,
2227 "'pwdLastSet' deletion is not allowed!");
2228 return LDB_ERR_UNWILLING_TO_PERFORM;
2229 } else if (io->ac->smartcard_reset) {
2231 * adding UF_SMARTCARD_REQUIRED doesn't update
2232 * pwdLastSet implicitly.
2234 io->ac->update_lastset = false;
2237 /* only 0 or -1 (0xFFFFFFFFFFFFFFFF) are allowed */
2238 switch (io->g.last_set) {
2240 if (!io->ac->pwd_last_set_default) {
2243 if (!io->ac->update_password) {
2248 if (!io->ac->update_password &&
2249 io->u.pwdLastSet != 0 &&
2250 io->u.pwdLastSet != UINT64_MAX)
2253 * Just setting pwdLastSet to -1, while not changing
2254 * any password field has no effect if pwdLastSet
2255 * is already non-zero.
2257 io->ac->update_lastset = false;
2260 /* -1 means set it as now */
2262 io->g.last_set = timeval_to_nttime(&tv);
2265 return dsdb_module_werror(io->ac->module,
2267 WERR_INVALID_PARAMETER,
2268 "setup_last_set_field: "
2269 "pwdLastSet must be 0 or -1 only!");
2272 if (io->ac->req->operation == LDB_ADD) {
2274 * We always need to store the value on add
2280 if (io->g.last_set == io->u.pwdLastSet) {
2282 * Just setting pwdLastSet to 0, is no-op if it's already 0.
2284 io->ac->update_lastset = false;
2290 static int setup_given_passwords(struct setup_password_fields_io *io,
2291 struct setup_password_fields_given *g)
2293 struct ldb_context *ldb;
2296 ldb = ldb_module_get_ctx(io->ac->module);
2298 if (g->cleartext_utf8) {
2299 struct ldb_val *cleartext_utf16_blob;
2301 cleartext_utf16_blob = talloc(io->ac, struct ldb_val);
2302 if (!cleartext_utf16_blob) {
2303 return ldb_oom(ldb);
2305 if (!convert_string_talloc(io->ac,
2307 g->cleartext_utf8->data,
2308 g->cleartext_utf8->length,
2309 (void *)&cleartext_utf16_blob->data,
2310 &cleartext_utf16_blob->length)) {
2311 if (g->cleartext_utf8->length != 0) {
2312 talloc_free(cleartext_utf16_blob);
2313 ldb_asprintf_errstring(ldb,
2314 "setup_password_fields: "
2315 "failed to generate UTF16 password from cleartext UTF8 one for user '%s'!",
2316 io->u.sAMAccountName);
2317 return LDB_ERR_CONSTRAINT_VIOLATION;
2319 /* passwords with length "0" are valid! */
2320 cleartext_utf16_blob->data = NULL;
2321 cleartext_utf16_blob->length = 0;
2324 g->cleartext_utf16 = cleartext_utf16_blob;
2325 } else if (g->cleartext_utf16) {
2326 struct ldb_val *cleartext_utf8_blob;
2328 cleartext_utf8_blob = talloc(io->ac, struct ldb_val);
2329 if (!cleartext_utf8_blob) {
2330 return ldb_oom(ldb);
2332 if (!convert_string_talloc(io->ac,
2333 CH_UTF16MUNGED, CH_UTF8,
2334 g->cleartext_utf16->data,
2335 g->cleartext_utf16->length,
2336 (void *)&cleartext_utf8_blob->data,
2337 &cleartext_utf8_blob->length)) {
2338 if (g->cleartext_utf16->length != 0) {
2339 /* We must bail out here, the input wasn't even
2340 * a multiple of 2 bytes */
2341 talloc_free(cleartext_utf8_blob);
2342 ldb_asprintf_errstring(ldb,
2343 "setup_password_fields: "
2344 "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)!",
2345 io->u.sAMAccountName);
2346 return LDB_ERR_CONSTRAINT_VIOLATION;
2348 /* passwords with length "0" are valid! */
2349 cleartext_utf8_blob->data = NULL;
2350 cleartext_utf8_blob->length = 0;
2353 g->cleartext_utf8 = cleartext_utf8_blob;
2356 if (g->cleartext_utf16) {
2357 struct samr_Password *nt_hash;
2359 nt_hash = talloc(io->ac, struct samr_Password);
2361 return ldb_oom(ldb);
2363 g->nt_hash = nt_hash;
2365 /* compute the new nt hash */
2366 mdfour(nt_hash->hash,
2367 g->cleartext_utf16->data,
2368 g->cleartext_utf16->length);
2371 if (g->cleartext_utf8) {
2372 struct samr_Password *lm_hash;
2374 lm_hash = talloc(io->ac, struct samr_Password);
2376 return ldb_oom(ldb);
2379 /* compute the new lm hash */
2380 ok = E_deshash((char *)g->cleartext_utf8->data, lm_hash->hash);
2382 g->lm_hash = lm_hash;
2384 talloc_free(lm_hash);
2391 static int setup_password_fields(struct setup_password_fields_io *io)
2393 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2394 struct loadparm_context *lp_ctx =
2395 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2396 struct loadparm_context);
2399 ret = setup_last_set_field(io);
2400 if (ret != LDB_SUCCESS) {
2404 if (!io->ac->update_password) {
2408 /* transform the old password (for password changes) */
2409 ret = setup_given_passwords(io, &io->og);
2410 if (ret != LDB_SUCCESS) {
2414 /* transform the new password */
2415 ret = setup_given_passwords(io, &io->n);
2416 if (ret != LDB_SUCCESS) {
2420 if (io->n.cleartext_utf8) {
2421 ret = setup_kerberos_keys(io);
2422 if (ret != LDB_SUCCESS) {
2427 ret = setup_nt_fields(io);
2428 if (ret != LDB_SUCCESS) {
2432 if (lpcfg_lanman_auth(lp_ctx)) {
2433 ret = setup_lm_fields(io);
2434 if (ret != LDB_SUCCESS) {
2438 io->g.lm_hash = NULL;
2439 io->g.lm_history_len = 0;
2442 ret = setup_supplemental_field(io);
2443 if (ret != LDB_SUCCESS) {
2450 static int setup_smartcard_reset(struct setup_password_fields_io *io)
2452 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2453 struct loadparm_context *lp_ctx = talloc_get_type(
2454 ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
2455 struct supplementalCredentialsBlob scb = { .__ndr_size = 0 };
2456 enum ndr_err_code ndr_err;
2458 if (!io->ac->smartcard_reset) {
2462 io->g.nt_hash = talloc(io->ac, struct samr_Password);
2463 if (io->g.nt_hash == NULL) {
2464 return ldb_module_oom(io->ac->module);
2466 generate_secret_buffer(io->g.nt_hash->hash,
2467 sizeof(io->g.nt_hash->hash));
2468 io->g.nt_history_len = 0;
2470 if (lpcfg_lanman_auth(lp_ctx)) {
2471 io->g.lm_hash = talloc(io->ac, struct samr_Password);
2472 if (io->g.lm_hash == NULL) {
2473 return ldb_module_oom(io->ac->module);
2475 generate_secret_buffer(io->g.lm_hash->hash,
2476 sizeof(io->g.lm_hash->hash));
2478 io->g.lm_hash = NULL;
2480 io->g.lm_history_len = 0;
2483 * We take the "old" value and store it
2484 * with num_packages = 0.
2486 * On "add" we have scb.sub.signature == 0, which
2489 * [0000] 00 00 00 00 00 00 00 00 00 00 00 00 00
2491 * On modify it's likely to be scb.sub.signature ==
2492 * SUPPLEMENTAL_CREDENTIALS_SIGNATURE (0x0050), which results in
2495 * [0000] 00 00 00 00 62 00 00 00 00 00 00 00 20 00 20 00
2496 * [0010] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2497 * [0020] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2498 * [0030] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2499 * [0040] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2500 * [0050] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2501 * [0060] 20 00 20 00 20 00 20 00 20 00 20 00 50 00 00
2503 * See https://bugzilla.samba.org/show_bug.cgi?id=11441
2504 * and ndr_{push,pull}_supplementalCredentialsSubBlob().
2507 scb.sub.num_packages = 0;
2510 * setup 'supplementalCredentials' value without packages
2512 ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac,
2514 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
2515 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2516 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2517 ldb_asprintf_errstring(ldb,
2518 "setup_smartcard_reset: "
2519 "failed to push supplementalCredentialsBlob: %s",
2521 return LDB_ERR_OPERATIONS_ERROR;
2524 io->ac->update_password = true;
2528 static int make_error_and_update_badPwdCount(struct setup_password_fields_io *io, WERROR *werror)
2530 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2531 struct ldb_message *mod_msg = NULL;
2532 struct ldb_message *pso_msg = NULL;
2536 /* PSO search result is optional (NULL if no PSO applies) */
2537 if (io->ac->pso_res != NULL) {
2538 pso_msg = io->ac->pso_res->message;
2541 status = dsdb_update_bad_pwd_count(io->ac, ldb,
2542 io->ac->search_res->message,
2543 io->ac->dom_res->message,
2546 if (!NT_STATUS_IS_OK(status)) {
2550 if (mod_msg == NULL) {
2555 * OK, horrible semantics ahead.
2557 * - We need to abort any existing transaction
2558 * - create a transaction arround the badPwdCount update
2559 * - re-open the transaction so the upper layer
2560 * doesn't know what happened.
2562 * This is needed because returning an error to the upper
2563 * layer will cancel the transaction and undo the badPwdCount
2568 * Checking errors here is a bit pointless.
2569 * What can we do if we can't end the transaction?
2571 ret = ldb_next_del_trans(io->ac->module);
2572 if (ret != LDB_SUCCESS) {
2573 ldb_debug(ldb, LDB_DEBUG_FATAL,
2574 "Failed to abort transaction prior to update of badPwdCount of %s: %s",
2575 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2576 ldb_errstring(ldb));
2578 * just return the original error
2583 /* Likewise, what should we do if we can't open a new transaction? */
2584 ret = ldb_next_start_trans(io->ac->module);
2585 if (ret != LDB_SUCCESS) {
2586 ldb_debug(ldb, LDB_DEBUG_ERROR,
2587 "Failed to open transaction to update badPwdCount of %s: %s",
2588 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2589 ldb_errstring(ldb));
2591 * just return the original error
2596 ret = dsdb_module_modify(io->ac->module, mod_msg,
2597 DSDB_FLAG_NEXT_MODULE,
2599 if (ret != LDB_SUCCESS) {
2600 ldb_debug(ldb, LDB_DEBUG_ERROR,
2601 "Failed to update badPwdCount of %s: %s",
2602 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2603 ldb_errstring(ldb));
2605 * We can only ignore this...
2609 ret = ldb_next_end_trans(io->ac->module);
2610 if (ret != LDB_SUCCESS) {
2611 ldb_debug(ldb, LDB_DEBUG_ERROR,
2612 "Failed to close transaction to update badPwdCount of %s: %s",
2613 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2614 ldb_errstring(ldb));
2616 * We can only ignore this...
2620 ret = ldb_next_start_trans(io->ac->module);
2621 if (ret != LDB_SUCCESS) {
2622 ldb_debug(ldb, LDB_DEBUG_ERROR,
2623 "Failed to open transaction after update of badPwdCount of %s: %s",
2624 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2625 ldb_errstring(ldb));
2627 * We can only ignore this...
2632 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2633 *werror = WERR_INVALID_PASSWORD;
2634 ldb_asprintf_errstring(ldb,
2635 "%08X: %s - check_password_restrictions: "
2636 "The old password specified doesn't match!",
2642 static int check_password_restrictions(struct setup_password_fields_io *io, WERROR *werror)
2644 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2646 struct loadparm_context *lp_ctx =
2647 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2648 struct loadparm_context);
2650 *werror = WERR_INVALID_PARAMETER;
2652 if (!io->ac->update_password) {
2656 /* First check the old password is correct, for password changes */
2657 if (!io->ac->pwd_reset) {
2658 bool nt_hash_checked = false;
2660 /* we need the old nt or lm hash given by the client */
2661 if (!io->og.nt_hash && !io->og.lm_hash) {
2662 ldb_asprintf_errstring(ldb,
2663 "check_password_restrictions: "
2664 "You need to provide the old password in order "
2666 return LDB_ERR_UNWILLING_TO_PERFORM;
2669 /* The password modify through the NT hash is encouraged and
2670 has no problems at all */
2671 if (io->og.nt_hash) {
2672 if (!io->o.nt_hash || memcmp(io->og.nt_hash->hash, io->o.nt_hash->hash, 16) != 0) {
2673 return make_error_and_update_badPwdCount(io, werror);
2676 nt_hash_checked = true;
2679 /* But it is also possible to change a password by the LM hash
2680 * alone for compatibility reasons. This check is optional if
2681 * the NT hash was already checked - otherwise it's mandatory.
2682 * (as the SAMR operations request it). */
2683 if (io->og.lm_hash) {
2684 if ((!io->o.lm_hash && !nt_hash_checked)
2685 || (io->o.lm_hash && memcmp(io->og.lm_hash->hash, io->o.lm_hash->hash, 16) != 0)) {
2686 return make_error_and_update_badPwdCount(io, werror);
2691 if (io->u.restrictions == 0) {
2692 /* FIXME: Is this right? */
2696 /* Password minimum age: yes, this is a minus. The ages are in negative 100nsec units! */
2697 if ((io->u.pwdLastSet - io->ac->status->domain_data.minPwdAge > io->g.last_set) &&
2700 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2701 *werror = WERR_PASSWORD_RESTRICTION;
2702 ldb_asprintf_errstring(ldb,
2703 "%08X: %s - check_password_restrictions: "
2704 "password is too young to change!",
2711 * Fundamental password checks done by the call
2712 * "samdb_check_password".
2713 * It is also in use by "dcesrv_samr_ValidatePassword".
2715 if (io->n.cleartext_utf8 != NULL) {
2716 enum samr_ValidationStatus vstat;
2717 vstat = samdb_check_password(io->ac, lp_ctx,
2718 io->n.cleartext_utf8,
2719 io->ac->status->domain_data.pwdProperties,
2720 io->ac->status->domain_data.minPwdLength);
2722 case SAMR_VALIDATION_STATUS_SUCCESS:
2723 /* perfect -> proceed! */
2726 case SAMR_VALIDATION_STATUS_PWD_TOO_SHORT:
2727 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2728 *werror = WERR_PASSWORD_RESTRICTION;
2729 ldb_asprintf_errstring(ldb,
2730 "%08X: %s - check_password_restrictions: "
2731 "the password is too short. It should be equal or longer than %u characters!",
2734 io->ac->status->domain_data.minPwdLength);
2735 io->ac->status->reject_reason = SAM_PWD_CHANGE_PASSWORD_TOO_SHORT;
2738 case SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH:
2739 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2740 *werror = WERR_PASSWORD_RESTRICTION;
2741 ldb_asprintf_errstring(ldb,
2742 "%08X: %s - check_password_restrictions: "
2743 "the password does not meet the complexity criteria!",
2746 io->ac->status->reject_reason = SAM_PWD_CHANGE_NOT_COMPLEX;
2750 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2751 *werror = WERR_PASSWORD_RESTRICTION;
2752 ldb_asprintf_errstring(ldb,
2753 "%08X: %s - check_password_restrictions: "
2754 "the password doesn't fit due to a miscellaneous restriction!",
2761 if (io->ac->pwd_reset) {
2766 if (io->n.nt_hash) {
2769 /* checks the NT hash password history */
2770 for (i = 0; i < io->o.nt_history_len; i++) {
2771 ret = memcmp(io->n.nt_hash, io->o.nt_history[i].hash, 16);
2773 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2774 *werror = WERR_PASSWORD_RESTRICTION;
2775 ldb_asprintf_errstring(ldb,
2776 "%08X: %s - check_password_restrictions: "
2777 "the password was already used (in history)!",
2780 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
2786 if (io->n.lm_hash) {
2789 /* checks the LM hash password history */
2790 for (i = 0; i < io->o.lm_history_len; i++) {
2791 ret = memcmp(io->n.lm_hash, io->o.lm_history[i].hash, 16);
2793 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2794 *werror = WERR_PASSWORD_RESTRICTION;
2795 ldb_asprintf_errstring(ldb,
2796 "%08X: %s - check_password_restrictions: "
2797 "the password was already used (in history)!",
2800 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
2806 /* are all password changes disallowed? */
2807 if (io->ac->status->domain_data.pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
2808 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2809 *werror = WERR_PASSWORD_RESTRICTION;
2810 ldb_asprintf_errstring(ldb,
2811 "%08X: %s - check_password_restrictions: "
2812 "password changes disabled!",
2818 /* can this user change the password? */
2819 if (io->u.userAccountControl & UF_PASSWD_CANT_CHANGE) {
2820 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2821 *werror = WERR_PASSWORD_RESTRICTION;
2822 ldb_asprintf_errstring(ldb,
2823 "%08X: %s - check_password_restrictions: "
2824 "password can't be changed on this account!",
2833 static int check_password_restrictions_and_log(struct setup_password_fields_io *io)
2836 int ret = check_password_restrictions(io, &werror);
2837 struct ph_context *ac = io->ac;
2839 * Password resets are not authentication events, and if the
2840 * upper layer checked the password and supplied the hash
2841 * values as proof, then this is also not an authentication
2842 * even at this layer (already logged). This is to log LDAP
2846 /* Do not record a failure in the auth log below in the success case */
2847 if (ret == LDB_SUCCESS) {
2851 if (ac->pwd_reset == false && ac->change == NULL) {
2852 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2853 struct imessaging_context *msg_ctx;
2854 struct loadparm_context *lp_ctx
2855 = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"),
2856 struct loadparm_context);
2857 NTSTATUS status = werror_to_ntstatus(werror);
2858 const char *domain_name = lpcfg_sam_name(lp_ctx);
2859 void *opaque_remote_address = NULL;
2861 * Forcing this via the NTLM auth structure is not ideal, but
2862 * it is the most practical option right now, and ensures the
2863 * logs are consistent, even if some elements are always NULL.
2865 struct auth_usersupplied_info ui = {
2866 .mapped_state = true,
2869 .account_name = io->u.sAMAccountName,
2870 .domain_name = domain_name,
2873 .account_name = io->u.sAMAccountName,
2874 .domain_name = domain_name,
2876 .service_description = "LDAP Password Change",
2877 .auth_description = "LDAP Modify",
2878 .password_type = "plaintext"
2881 opaque_remote_address = ldb_get_opaque(ldb,
2883 if (opaque_remote_address == NULL) {
2884 ldb_asprintf_errstring(ldb,
2885 "Failed to obtain remote address for "
2886 "the LDAP client while changing the "
2888 return LDB_ERR_OPERATIONS_ERROR;
2890 ui.remote_host = talloc_get_type(opaque_remote_address,
2891 struct tsocket_address);
2893 msg_ctx = imessaging_client_init(ac, lp_ctx,
2894 ldb_get_event_context(ldb));
2896 ldb_asprintf_errstring(ldb,
2897 "Failed to generate client messaging context in %s",
2898 lpcfg_imessaging_path(ac, lp_ctx));
2899 return LDB_ERR_OPERATIONS_ERROR;
2901 log_authentication_event(msg_ctx,
2907 io->u.sAMAccountName,
2915 static int update_final_msg(struct setup_password_fields_io *io)
2917 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2920 bool update_password = io->ac->update_password;
2921 bool update_scb = io->ac->update_password;
2924 * If we add a user without initial password,
2925 * we need to add replication meta data for
2926 * following attributes:
2932 * If we add a user with initial password or a
2933 * password is changed of an existing user,
2934 * we need to replace the following attributes
2935 * with a forced meta data update, e.g. also
2936 * when updating an empty attribute with an empty value:
2941 * - supplementalCredentials
2944 switch (io->ac->req->operation) {
2946 update_password = true;
2947 el_flags |= DSDB_FLAG_INTERNAL_FORCE_META_DATA;
2950 el_flags |= LDB_FLAG_MOD_REPLACE;
2951 el_flags |= DSDB_FLAG_INTERNAL_FORCE_META_DATA;
2954 return ldb_module_operr(io->ac->module);
2957 if (update_password) {
2958 ret = ldb_msg_add_empty(io->ac->update_msg,
2961 if (ret != LDB_SUCCESS) {
2964 ret = ldb_msg_add_empty(io->ac->update_msg,
2967 if (ret != LDB_SUCCESS) {
2970 ret = ldb_msg_add_empty(io->ac->update_msg,
2973 if (ret != LDB_SUCCESS) {
2976 ret = ldb_msg_add_empty(io->ac->update_msg,
2979 if (ret != LDB_SUCCESS) {
2984 ret = ldb_msg_add_empty(io->ac->update_msg,
2985 "supplementalCredentials",
2987 if (ret != LDB_SUCCESS) {
2991 if (io->ac->update_lastset) {
2992 ret = ldb_msg_add_empty(io->ac->update_msg,
2995 if (ret != LDB_SUCCESS) {
3000 if (io->g.nt_hash != NULL) {
3001 ret = samdb_msg_add_hash(ldb, io->ac,
3005 if (ret != LDB_SUCCESS) {
3009 if (io->g.lm_hash != NULL) {
3010 ret = samdb_msg_add_hash(ldb, io->ac,
3014 if (ret != LDB_SUCCESS) {
3018 if (io->g.nt_history_len > 0) {
3019 ret = samdb_msg_add_hashes(ldb, io->ac,
3023 io->g.nt_history_len);
3024 if (ret != LDB_SUCCESS) {
3028 if (io->g.lm_history_len > 0) {
3029 ret = samdb_msg_add_hashes(ldb, io->ac,
3033 io->g.lm_history_len);
3034 if (ret != LDB_SUCCESS) {
3038 if (io->g.supplemental.length > 0) {
3039 ret = ldb_msg_add_value(io->ac->update_msg,
3040 "supplementalCredentials",
3041 &io->g.supplemental, NULL);
3042 if (ret != LDB_SUCCESS) {
3046 if (io->ac->update_lastset) {
3047 ret = samdb_msg_add_uint64(ldb, io->ac,
3051 if (ret != LDB_SUCCESS) {
3060 * This is intended for use by the "password_hash" module since there
3061 * password changes can be specified through one message element with the
3062 * new password (to set) and another one with the old password (to unset).
3064 * The first which sets a password (new value) can have flags
3065 * (LDB_FLAG_MOD_ADD, LDB_FLAG_MOD_REPLACE) but also none (on "add" operations
3066 * for entries). The latter (old value) has always specified
3067 * LDB_FLAG_MOD_DELETE.
3069 * Returns LDB_ERR_CONSTRAINT_VIOLATION and LDB_ERR_UNWILLING_TO_PERFORM if
3070 * matching message elements are malformed in respect to the set/change rules.
3071 * Otherwise it returns LDB_SUCCESS.
3073 static int msg_find_old_and_new_pwd_val(const struct ldb_message *msg,
3075 enum ldb_request_type operation,
3076 const struct ldb_val **new_val,
3077 const struct ldb_val **old_val)
3088 for (i = 0; i < msg->num_elements; i++) {
3089 if (ldb_attr_cmp(msg->elements[i].name, name) != 0) {
3093 if ((operation == LDB_MODIFY) &&
3094 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_DELETE)) {
3095 /* 0 values are allowed */
3096 if (msg->elements[i].num_values == 1) {
3097 *old_val = &msg->elements[i].values[0];
3098 } else if (msg->elements[i].num_values > 1) {
3099 return LDB_ERR_CONSTRAINT_VIOLATION;
3101 } else if ((operation == LDB_MODIFY) &&
3102 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_REPLACE)) {
3103 if (msg->elements[i].num_values > 0) {
3104 *new_val = &msg->elements[i].values[msg->elements[i].num_values - 1];
3106 return LDB_ERR_UNWILLING_TO_PERFORM;
3109 /* Add operations and LDB_FLAG_MOD_ADD */
3110 if (msg->elements[i].num_values > 0) {
3111 *new_val = &msg->elements[i].values[msg->elements[i].num_values - 1];
3113 return LDB_ERR_CONSTRAINT_VIOLATION;
3121 static int setup_io(struct ph_context *ac,
3122 const struct ldb_message *client_msg,
3123 const struct ldb_message *existing_msg,
3124 struct setup_password_fields_io *io)
3126 const struct ldb_val *quoted_utf16, *old_quoted_utf16, *lm_hash, *old_lm_hash;
3127 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3128 struct loadparm_context *lp_ctx = talloc_get_type(
3129 ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
3131 const struct ldb_message *info_msg = NULL;
3132 struct dom_sid *account_sid = NULL;
3133 int rodc_krbtgt = 0;
3137 /* Some operations below require kerberos contexts */
3139 if (existing_msg != NULL) {
3141 * This is a modify operation
3143 info_msg = existing_msg;
3146 * This is an add operation
3148 info_msg = client_msg;
3151 ret = smb_krb5_init_context(ac,
3152 (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm"),
3153 &io->smb_krb5_context);
3157 * In the special case of mit krb5.conf vs heimdal, the includedir
3158 * statement causes ret == 22 (KRB5_CONFIG_BADFORMAT) to be returned.
3159 * We look for this case so that we can give a more instructional
3160 * message to the administrator.
3162 if (ret == KRB5_CONFIG_BADFORMAT || ret == EINVAL) {
3163 ldb_asprintf_errstring(ldb, "Failed to setup krb5_context: %s - "
3164 "This could be due to an invalid krb5 configuration. "
3165 "Please check your system's krb5 configuration is correct.",
3166 error_message(ret));
3168 ldb_asprintf_errstring(ldb, "Failed to setup krb5_context: %s",
3169 error_message(ret));
3171 return LDB_ERR_OPERATIONS_ERROR;
3176 io->u.userAccountControl = ldb_msg_find_attr_as_uint(info_msg,
3177 "userAccountControl", 0);
3178 if (info_msg == existing_msg) {
3180 * We only take pwdLastSet from the existing object
3181 * otherwise we leave it as 0.
3183 * If no attribute is available, e.g. on deleted objects
3184 * we remember that as UINT64_MAX.
3186 io->u.pwdLastSet = samdb_result_nttime(info_msg, "pwdLastSet",
3189 io->u.sAMAccountName = ldb_msg_find_attr_as_string(info_msg,
3190 "sAMAccountName", NULL);
3191 io->u.user_principal_name = ldb_msg_find_attr_as_string(info_msg,
3192 "userPrincipalName", NULL);
3193 io->u.is_computer = ldb_msg_check_string_attribute(info_msg, "objectClass", "computer");
3195 /* Ensure it has an objectSID too */
3196 io->u.account_sid = samdb_result_dom_sid(ac, info_msg, "objectSid");
3197 if (io->u.account_sid != NULL) {
3201 status = dom_sid_split_rid(account_sid, io->u.account_sid, NULL, &rid);
3202 if (NT_STATUS_IS_OK(status)) {
3203 if (rid == DOMAIN_RID_KRBTGT) {
3204 io->u.is_krbtgt = true;
3209 rodc_krbtgt = ldb_msg_find_attr_as_int(info_msg,
3210 "msDS-SecondaryKrbTgtNumber", 0);
3211 if (rodc_krbtgt != 0) {
3212 io->u.is_krbtgt = true;
3215 if (io->u.sAMAccountName == NULL) {
3216 ldb_asprintf_errstring(ldb,
3217 "setup_io: sAMAccountName attribute is missing on %s for attempted password set/change",
3218 ldb_dn_get_linearized(info_msg->dn));
3220 return LDB_ERR_CONSTRAINT_VIOLATION;
3223 if (io->u.userAccountControl & UF_INTERDOMAIN_TRUST_ACCOUNT) {
3224 struct ldb_control *permit_trust = ldb_request_get_control(ac->req,
3225 DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
3227 if (permit_trust == NULL) {
3228 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
3229 ldb_asprintf_errstring(ldb,
3230 "%08X: %s - setup_io: changing the interdomain trust password "
3231 "on %s not allowed via LDAP. Use LSA or NETLOGON",
3232 W_ERROR_V(WERR_ACCESS_DENIED),
3234 ldb_dn_get_linearized(info_msg->dn));
3239 /* Only non-trust accounts have restrictions (possibly this test is the
3240 * wrong way around, but we like to be restrictive if possible */
3241 io->u.restrictions = !(io->u.userAccountControl & UF_TRUST_ACCOUNT_MASK);
3243 if (io->u.is_krbtgt) {
3244 io->u.restrictions = 0;
3245 io->ac->status->domain_data.pwdHistoryLength =
3246 MAX(io->ac->status->domain_data.pwdHistoryLength, 3);
3249 if (ac->userPassword) {
3250 ret = msg_find_old_and_new_pwd_val(client_msg, "userPassword",
3252 &io->n.cleartext_utf8,
3253 &io->og.cleartext_utf8);
3254 if (ret != LDB_SUCCESS) {
3255 ldb_asprintf_errstring(ldb,
3257 "it's only allowed to set the old password once!");
3262 if (io->n.cleartext_utf8 != NULL) {
3263 struct ldb_val *cleartext_utf8_blob;
3266 cleartext_utf8_blob = talloc(io->ac, struct ldb_val);
3267 if (!cleartext_utf8_blob) {
3268 return ldb_oom(ldb);
3271 *cleartext_utf8_blob = *io->n.cleartext_utf8;
3273 /* make sure we have a null terminated string */
3274 p = talloc_strndup(cleartext_utf8_blob,
3275 (const char *)io->n.cleartext_utf8->data,
3276 io->n.cleartext_utf8->length);
3277 if ((p == NULL) && (io->n.cleartext_utf8->length > 0)) {
3278 return ldb_oom(ldb);
3280 cleartext_utf8_blob->data = (uint8_t *)p;
3282 io->n.cleartext_utf8 = cleartext_utf8_blob;
3285 ret = msg_find_old_and_new_pwd_val(client_msg, "clearTextPassword",
3287 &io->n.cleartext_utf16,
3288 &io->og.cleartext_utf16);
3289 if (ret != LDB_SUCCESS) {
3290 ldb_asprintf_errstring(ldb,
3292 "it's only allowed to set the old password once!");
3296 /* this rather strange looking piece of code is there to
3297 handle a ldap client setting a password remotely using the
3298 unicodePwd ldap field. The syntax is that the password is
3299 in UTF-16LE, with a " at either end. Unfortunately the
3300 unicodePwd field is also used to store the nt hashes
3301 internally in Samba, and is used in the nt hash format on
3302 the wire in DRS replication, so we have a single name for
3303 two distinct values. The code below leaves us with a small
3304 chance (less than 1 in 2^32) of a mixup, if someone manages
3305 to create a MD4 hash which starts and ends in 0x22 0x00, as
3306 that would then be treated as a UTF16 password rather than
3309 ret = msg_find_old_and_new_pwd_val(client_msg, "unicodePwd",
3313 if (ret != LDB_SUCCESS) {
3314 ldb_asprintf_errstring(ldb,
3316 "it's only allowed to set the old password once!");
3320 /* Checks and converts the actual "unicodePwd" attribute */
3321 if (!ac->hash_values &&
3323 quoted_utf16->length >= 4 &&
3324 quoted_utf16->data[0] == '"' &&
3325 quoted_utf16->data[1] == 0 &&
3326 quoted_utf16->data[quoted_utf16->length-2] == '"' &&
3327 quoted_utf16->data[quoted_utf16->length-1] == 0) {
3328 struct ldb_val *quoted_utf16_2;
3330 if (io->n.cleartext_utf16) {
3331 /* refuse the change if someone wants to change with
3332 with both UTF16 possibilities at the same time... */
3333 ldb_asprintf_errstring(ldb,
3335 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'clearTextPassword'");
3336 return LDB_ERR_UNWILLING_TO_PERFORM;
3340 * adapt the quoted UTF16 string to be a real
3343 quoted_utf16_2 = talloc(io->ac, struct ldb_val);
3344 if (quoted_utf16_2 == NULL) {
3345 return ldb_oom(ldb);
3348 quoted_utf16_2->data = quoted_utf16->data + 2;
3349 quoted_utf16_2->length = quoted_utf16->length-4;
3350 io->n.cleartext_utf16 = quoted_utf16_2;
3351 io->n.nt_hash = NULL;
3353 } else if (quoted_utf16) {
3354 /* We have only the hash available -> so no plaintext here */
3355 if (!ac->hash_values) {
3356 /* refuse the change if someone wants to change
3357 the hash without control specified... */
3358 ldb_asprintf_errstring(ldb,
3360 "it's not allowed to set the NT hash password directly'");
3361 /* this looks odd but this is what Windows does:
3362 returns "UNWILLING_TO_PERFORM" on wrong
3363 password sets and "CONSTRAINT_VIOLATION" on
3364 wrong password changes. */
3365 if (old_quoted_utf16 == NULL) {
3366 return LDB_ERR_UNWILLING_TO_PERFORM;
3369 return LDB_ERR_CONSTRAINT_VIOLATION;
3372 io->n.nt_hash = talloc(io->ac, struct samr_Password);
3373 memcpy(io->n.nt_hash->hash, quoted_utf16->data,
3374 MIN(quoted_utf16->length, sizeof(io->n.nt_hash->hash)));
3377 /* Checks and converts the previous "unicodePwd" attribute */
3378 if (!ac->hash_values &&
3380 old_quoted_utf16->length >= 4 &&
3381 old_quoted_utf16->data[0] == '"' &&
3382 old_quoted_utf16->data[1] == 0 &&
3383 old_quoted_utf16->data[old_quoted_utf16->length-2] == '"' &&
3384 old_quoted_utf16->data[old_quoted_utf16->length-1] == 0) {
3385 struct ldb_val *old_quoted_utf16_2;
3387 if (io->og.cleartext_utf16) {
3388 /* refuse the change if someone wants to change with
3389 both UTF16 possibilities at the same time... */
3390 ldb_asprintf_errstring(ldb,
3392 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'clearTextPassword'");
3393 return LDB_ERR_UNWILLING_TO_PERFORM;
3397 * adapt the quoted UTF16 string to be a real
3400 old_quoted_utf16_2 = talloc(io->ac, struct ldb_val);
3401 if (old_quoted_utf16_2 == NULL) {
3402 return ldb_oom(ldb);
3405 old_quoted_utf16_2->data = old_quoted_utf16->data + 2;
3406 old_quoted_utf16_2->length = old_quoted_utf16->length-4;
3408 io->og.cleartext_utf16 = old_quoted_utf16_2;
3409 io->og.nt_hash = NULL;
3410 } else if (old_quoted_utf16) {
3411 /* We have only the hash available -> so no plaintext here */
3412 if (!ac->hash_values) {
3413 /* refuse the change if someone wants to change
3414 the hash without control specified... */
3415 ldb_asprintf_errstring(ldb,
3417 "it's not allowed to set the NT hash password directly'");
3418 return LDB_ERR_UNWILLING_TO_PERFORM;
3421 io->og.nt_hash = talloc(io->ac, struct samr_Password);
3422 memcpy(io->og.nt_hash->hash, old_quoted_utf16->data,
3423 MIN(old_quoted_utf16->length, sizeof(io->og.nt_hash->hash)));
3426 /* Handles the "dBCSPwd" attribute (LM hash) */
3427 io->n.lm_hash = NULL; io->og.lm_hash = NULL;
3428 ret = msg_find_old_and_new_pwd_val(client_msg, "dBCSPwd",
3430 &lm_hash, &old_lm_hash);
3431 if (ret != LDB_SUCCESS) {
3432 ldb_asprintf_errstring(ldb,
3434 "it's only allowed to set the old password once!");
3438 if (((lm_hash != NULL) || (old_lm_hash != NULL)) && (!ac->hash_values)) {
3439 /* refuse the change if someone wants to change the hash
3440 without control specified... */
3441 ldb_asprintf_errstring(ldb,
3443 "it's not allowed to set the LM hash password directly'");
3444 return LDB_ERR_UNWILLING_TO_PERFORM;
3447 if (lpcfg_lanman_auth(lp_ctx) && (lm_hash != NULL)) {
3448 io->n.lm_hash = talloc(io->ac, struct samr_Password);
3449 memcpy(io->n.lm_hash->hash, lm_hash->data, MIN(lm_hash->length,
3450 sizeof(io->n.lm_hash->hash)));
3452 if (lpcfg_lanman_auth(lp_ctx) && (old_lm_hash != NULL)) {
3453 io->og.lm_hash = talloc(io->ac, struct samr_Password);
3454 memcpy(io->og.lm_hash->hash, old_lm_hash->data, MIN(old_lm_hash->length,
3455 sizeof(io->og.lm_hash->hash)));
3459 * Handles the password change control if it's specified. It has the
3460 * precedance and overrides already specified old password values of
3461 * change requests (but that shouldn't happen since the control is
3462 * fully internal and only used in conjunction with replace requests!).
3464 if (ac->change != NULL) {
3465 io->og.nt_hash = NULL;
3466 if (ac->change->old_nt_pwd_hash != NULL) {
3467 io->og.nt_hash = talloc_memdup(io->ac,
3468 ac->change->old_nt_pwd_hash,
3469 sizeof(struct samr_Password));
3471 io->og.lm_hash = NULL;
3472 if (lpcfg_lanman_auth(lp_ctx) && (ac->change->old_lm_pwd_hash != NULL)) {
3473 io->og.lm_hash = talloc_memdup(io->ac,
3474 ac->change->old_lm_pwd_hash,
3475 sizeof(struct samr_Password));
3479 /* refuse the change if someone wants to change the clear-
3480 text and supply his own hashes at the same time... */
3481 if ((io->n.cleartext_utf8 || io->n.cleartext_utf16)
3482 && (io->n.nt_hash || io->n.lm_hash)) {
3483 ldb_asprintf_errstring(ldb,
3485 "it's only allowed to set the password in form of cleartext attributes or as hashes");
3486 return LDB_ERR_UNWILLING_TO_PERFORM;
3489 /* refuse the change if someone wants to change the password
3490 using both plaintext methods (UTF8 and UTF16) at the same time... */
3491 if (io->n.cleartext_utf8 && io->n.cleartext_utf16) {
3492 ldb_asprintf_errstring(ldb,
3494 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
3495 return LDB_ERR_UNWILLING_TO_PERFORM;
3498 /* refuse the change if someone tries to set/change the password by
3499 * the lanman hash alone and we've deactivated that mechanism. This
3500 * would end in an account without any password! */
3501 if (io->ac->update_password
3502 && (!io->n.cleartext_utf8) && (!io->n.cleartext_utf16)
3503 && (!io->n.nt_hash) && (!io->n.lm_hash)) {
3504 ldb_asprintf_errstring(ldb,
3506 "It's not possible to delete the password (changes using the LAN Manager hash alone could be deactivated)!");
3507 /* on "userPassword" and "clearTextPassword" we've to return
3508 * something different, since these are virtual attributes */
3509 if ((ldb_msg_find_element(client_msg, "userPassword") != NULL) ||
3510 (ldb_msg_find_element(client_msg, "clearTextPassword") != NULL)) {
3511 return LDB_ERR_CONSTRAINT_VIOLATION;
3513 return LDB_ERR_UNWILLING_TO_PERFORM;
3516 /* refuse the change if someone wants to compare against a plaintext
3517 or hash at the same time for a "password modify" operation... */
3518 if ((io->og.cleartext_utf8 || io->og.cleartext_utf16)
3519 && (io->og.nt_hash || io->og.lm_hash)) {
3520 ldb_asprintf_errstring(ldb,
3522 "it's only allowed to provide the old password in form of cleartext attributes or as hashes");
3523 return LDB_ERR_UNWILLING_TO_PERFORM;
3526 /* refuse the change if someone wants to compare against both
3527 * plaintexts at the same time for a "password modify" operation... */
3528 if (io->og.cleartext_utf8 && io->og.cleartext_utf16) {
3529 ldb_asprintf_errstring(ldb,
3531 "it's only allowed to provide the old cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
3532 return LDB_ERR_UNWILLING_TO_PERFORM;
3535 /* Decides if we have a password modify or password reset operation */
3536 if (ac->req->operation == LDB_ADD) {
3537 /* On "add" we have only "password reset" */
3538 ac->pwd_reset = true;
3539 } else if (ac->req->operation == LDB_MODIFY) {
3540 struct ldb_control *pav_ctrl = NULL;
3541 struct dsdb_control_password_acl_validation *pav = NULL;
3543 pav_ctrl = ldb_request_get_control(ac->req,
3544 DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID);
3545 if (pav_ctrl != NULL) {
3546 pav = talloc_get_type_abort(pav_ctrl->data,
3547 struct dsdb_control_password_acl_validation);
3550 if (pav == NULL && ac->update_password) {
3554 * If the DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID
3555 * control is missing, we require system access!
3557 ok = dsdb_module_am_system(ac->module);
3559 return ldb_module_operr(ac->module);
3565 * We assume what the acl module has validated.
3567 ac->pwd_reset = pav->pwd_reset;
3568 } else if (io->og.cleartext_utf8 || io->og.cleartext_utf16
3569 || io->og.nt_hash || io->og.lm_hash) {
3570 /* If we have an old password specified then for sure it
3571 * is a user "password change" */
3572 ac->pwd_reset = false;
3574 /* Otherwise we have also here a "password reset" */
3575 ac->pwd_reset = true;
3578 /* this shouldn't happen */
3579 return ldb_operr(ldb);
3582 if (io->u.is_krbtgt) {
3585 size_t diff = max - min;
3587 struct ldb_val *krbtgt_utf16 = NULL;
3589 if (!ac->pwd_reset) {
3590 return dsdb_module_werror(ac->module,
3591 LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS,
3592 WERR_DS_ATT_ALREADY_EXISTS,
3593 "Password change on krbtgt not permitted!");
3596 if (io->n.cleartext_utf16 == NULL) {
3597 return dsdb_module_werror(ac->module,
3598 LDB_ERR_UNWILLING_TO_PERFORM,
3599 WERR_DS_INVALID_ATTRIBUTE_SYNTAX,
3600 "Password reset on krbtgt requires UTF16!");
3604 * Instead of taking the callers value,
3605 * we just generate a new random value here.
3607 * Include null termination in the array.
3612 generate_random_buffer((uint8_t *)&tmp, sizeof(tmp));
3619 krbtgt_utf16 = talloc_zero(io->ac, struct ldb_val);
3620 if (krbtgt_utf16 == NULL) {
3621 return ldb_oom(ldb);
3624 *krbtgt_utf16 = data_blob_talloc_zero(krbtgt_utf16,
3626 if (krbtgt_utf16->data == NULL) {
3627 return ldb_oom(ldb);
3629 krbtgt_utf16->length = len * 2;
3630 generate_secret_buffer(krbtgt_utf16->data,
3631 krbtgt_utf16->length);
3632 io->n.cleartext_utf16 = krbtgt_utf16;
3635 if (existing_msg != NULL) {
3638 if (ac->pwd_reset) {
3639 /* Get the old password from the database */
3640 status = samdb_result_passwords_no_lockout(ac,
3646 /* Get the old password from the database */
3647 status = samdb_result_passwords(ac,
3654 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
3655 return dsdb_module_werror(ac->module,
3656 LDB_ERR_CONSTRAINT_VIOLATION,
3657 WERR_ACCOUNT_LOCKED_OUT,
3658 "Password change not permitted,"
3659 " account locked out!");
3662 if (!NT_STATUS_IS_OK(status)) {
3664 * This only happens if the database has gone weird,
3665 * not if we are just missing the passwords
3667 return ldb_operr(ldb);
3670 io->o.nt_history_len = samdb_result_hashes(ac, existing_msg,
3673 io->o.lm_history_len = samdb_result_hashes(ac, existing_msg,
3676 io->o.supplemental = ldb_msg_find_ldb_val(existing_msg,
3677 "supplementalCredentials");
3679 if (io->o.supplemental != NULL) {
3680 enum ndr_err_code ndr_err;
3682 ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac,
3684 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
3685 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3686 status = ndr_map_error2ntstatus(ndr_err);
3687 ldb_asprintf_errstring(ldb,
3688 "setup_io: failed to pull "
3689 "old supplementalCredentialsBlob: %s",
3691 return LDB_ERR_OPERATIONS_ERROR;
3699 static struct ph_context *ph_init_context(struct ldb_module *module,
3700 struct ldb_request *req,
3702 bool update_password)
3704 struct ldb_context *ldb;
3705 struct ph_context *ac;
3706 struct loadparm_context *lp_ctx = NULL;
3708 ldb = ldb_module_get_ctx(module);
3710 ac = talloc_zero(req, struct ph_context);
3712 ldb_set_errstring(ldb, "Out of Memory");
3716 ac->module = module;
3718 ac->userPassword = userPassword;
3719 ac->update_password = update_password;
3720 ac->update_lastset = true;
3722 lp_ctx = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"),
3723 struct loadparm_context);
3724 ac->gpg_key_ids = lpcfg_password_hash_gpg_key_ids(lp_ctx);
3725 ac->userPassword_schemes
3726 = lpcfg_password_hash_userpassword_schemes(lp_ctx);
3730 static void ph_apply_controls(struct ph_context *ac)
3732 struct ldb_control *ctrl;
3734 ac->change_status = false;
3735 ctrl = ldb_request_get_control(ac->req,
3736 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID);
3738 ac->change_status = true;
3740 /* Mark the "change status" control as uncritical (done) */
3741 ctrl->critical = false;
3744 ac->hash_values = false;
3745 ctrl = ldb_request_get_control(ac->req,
3746 DSDB_CONTROL_PASSWORD_HASH_VALUES_OID);
3748 ac->hash_values = true;
3750 /* Mark the "hash values" control as uncritical (done) */
3751 ctrl->critical = false;
3754 ctrl = ldb_request_get_control(ac->req,
3755 DSDB_CONTROL_PASSWORD_CHANGE_OID);
3757 ac->change = (struct dsdb_control_password_change *) ctrl->data;
3759 /* Mark the "change" control as uncritical (done) */
3760 ctrl->critical = false;
3763 ac->pwd_last_set_bypass = false;
3764 ctrl = ldb_request_get_control(ac->req,
3765 DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID);
3767 ac->pwd_last_set_bypass = true;
3769 /* Mark the "bypass pwdLastSet" control as uncritical (done) */
3770 ctrl->critical = false;
3773 ac->pwd_last_set_default = false;
3774 ctrl = ldb_request_get_control(ac->req,
3775 DSDB_CONTROL_PASSWORD_DEFAULT_LAST_SET_OID);
3777 ac->pwd_last_set_default = true;
3779 /* Mark the "bypass pwdLastSet" control as uncritical (done) */
3780 ctrl->critical = false;
3783 ac->smartcard_reset = false;
3784 ctrl = ldb_request_get_control(ac->req,
3785 DSDB_CONTROL_PASSWORD_USER_ACCOUNT_CONTROL_OID);
3787 struct dsdb_control_password_user_account_control *uac = NULL;
3788 uint32_t added_flags = 0;
3790 uac = talloc_get_type_abort(ctrl->data,
3791 struct dsdb_control_password_user_account_control);
3793 added_flags = uac->new_flags & ~uac->old_flags;
3795 if (added_flags & UF_SMARTCARD_REQUIRED) {
3796 ac->smartcard_reset = true;
3799 /* Mark the "smartcard required" control as uncritical (done) */
3800 ctrl->critical = false;
3804 static int ph_op_callback(struct ldb_request *req, struct ldb_reply *ares)
3806 struct ph_context *ac;
3808 ac = talloc_get_type(req->context, struct ph_context);
3811 return ldb_module_done(ac->req, NULL, NULL,
3812 LDB_ERR_OPERATIONS_ERROR);
3815 if (ares->type == LDB_REPLY_REFERRAL) {
3816 return ldb_module_send_referral(ac->req, ares->referral);
3819 if ((ares->error != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
3820 /* On success and trivial errors a status control is being
3821 * added (used for example by the "samdb_set_password" call) */
3822 ldb_reply_add_control(ares,
3823 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
3828 if (ares->error != LDB_SUCCESS) {
3829 return ldb_module_done(ac->req, ares->controls,
3830 ares->response, ares->error);
3833 if (ares->type != LDB_REPLY_DONE) {
3835 return ldb_module_done(ac->req, NULL, NULL,
3836 LDB_ERR_OPERATIONS_ERROR);
3839 return ldb_module_done(ac->req, ares->controls,
3840 ares->response, ares->error);
3843 static int password_hash_add_do_add(struct ph_context *ac);
3844 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares);
3845 static int password_hash_mod_search_self(struct ph_context *ac);
3846 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares);
3847 static int password_hash_mod_do_mod(struct ph_context *ac);
3850 * LDB callback handler for searching for a user's PSO. Once we have all the
3851 * Password Settings that apply to the user, we can continue with the modify
3854 static int get_pso_data_callback(struct ldb_request *req,
3855 struct ldb_reply *ares)
3857 struct ldb_context *ldb = NULL;
3858 struct ph_context *ac = NULL;
3859 bool domain_complexity = true;
3860 bool pso_complexity = true;
3861 struct dsdb_user_pwd_settings *settings = NULL;
3862 int ret = LDB_SUCCESS;
3864 ac = talloc_get_type(req->context, struct ph_context);
3865 ldb = ldb_module_get_ctx(ac->module);
3868 ret = LDB_ERR_OPERATIONS_ERROR;
3871 if (ares->error != LDB_SUCCESS) {
3872 return ldb_module_done(ac->req, ares->controls,
3873 ares->response, ares->error);
3876 switch (ares->type) {
3877 case LDB_REPLY_ENTRY:
3879 /* check status was initialized by the domain query */
3880 if (ac->status == NULL) {
3882 ldb_set_errstring(ldb, "Uninitialized status");
3883 ret = LDB_ERR_OPERATIONS_ERROR;
3888 * use the PSO's values instead of the domain defaults (the PSO
3889 * attributes should always exist, but use the domain default
3890 * values as a fallback).
3892 settings = &ac->status->domain_data;
3893 settings->store_cleartext =
3894 ldb_msg_find_attr_as_bool(ares->message,
3895 "msDS-PasswordReversibleEncryptionEnabled",
3896 settings->store_cleartext);
3898 settings->pwdHistoryLength =
3899 ldb_msg_find_attr_as_uint(ares->message,
3900 "msDS-PasswordHistoryLength",
3901 settings->pwdHistoryLength);
3902 settings->maxPwdAge =
3903 ldb_msg_find_attr_as_int64(ares->message,
3904 "msDS-MaximumPasswordAge",
3905 settings->maxPwdAge);
3906 settings->minPwdAge =
3907 ldb_msg_find_attr_as_int64(ares->message,
3908 "msDS-MinimumPasswordAge",
3909 settings->minPwdAge);
3910 settings->minPwdLength =
3911 ldb_msg_find_attr_as_uint(ares->message,
3912 "msDS-MinimumPasswordLength",
3913 settings->minPwdLength);
3915 (settings->pwdProperties & DOMAIN_PASSWORD_COMPLEX);
3917 ldb_msg_find_attr_as_bool(ares->message,
3918 "msDS-PasswordComplexityEnabled",
3921 /* set or clear the complexity bit if required */
3922 if (pso_complexity && !domain_complexity) {
3923 settings->pwdProperties |= DOMAIN_PASSWORD_COMPLEX;
3924 } else if (domain_complexity && !pso_complexity) {
3925 settings->pwdProperties &= ~DOMAIN_PASSWORD_COMPLEX;
3928 if (ac->pso_res != NULL) {
3929 DBG_ERR("Too many PSO results for %s",
3930 ldb_dn_get_linearized(ac->search_res->message->dn));
3931 talloc_free(ac->pso_res);
3934 /* store the PSO result (we may need its lockout settings) */
3935 ac->pso_res = talloc_steal(ac, ares);
3939 case LDB_REPLY_REFERRAL:
3945 case LDB_REPLY_DONE:
3949 * perform the next step of the modify operation (this code
3950 * shouldn't get called in the 'user add' case)
3952 if (ac->req->operation == LDB_MODIFY) {
3953 ret = password_hash_mod_do_mod(ac);
3955 ret = LDB_ERR_OPERATIONS_ERROR;
3961 if (ret != LDB_SUCCESS) {
3962 struct ldb_reply *new_ares;
3964 new_ares = talloc_zero(ac->req, struct ldb_reply);
3965 if (new_ares == NULL) {
3967 return ldb_module_done(ac->req, NULL, NULL,
3968 LDB_ERR_OPERATIONS_ERROR);
3971 new_ares->error = ret;
3972 if ((ret != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
3973 /* On success and trivial errors a status control is being
3974 * added (used for example by the "samdb_set_password" call) */
3975 ldb_reply_add_control(new_ares,
3976 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
3981 return ldb_module_done(ac->req, new_ares->controls,
3982 new_ares->response, new_ares->error);
3989 * Builds and returns a search request to lookup up the PSO that applies to
3990 * the user in question. Returns NULL if no PSO applies, or could not be found
3992 static struct ldb_request * build_pso_data_request(struct ph_context *ac)
3994 /* attrs[] is returned from this function in
3995 pso_req->op.search.attrs, so it must be static, as
3996 otherwise the compiler can put it on the stack */
3997 static const char * const attrs[] = { "msDS-PasswordComplexityEnabled",
3998 "msDS-PasswordReversibleEncryptionEnabled",
3999 "msDS-PasswordHistoryLength",
4000 "msDS-MaximumPasswordAge",
4001 "msDS-MinimumPasswordAge",
4002 "msDS-MinimumPasswordLength",
4003 "msDS-LockoutThreshold",
4004 "msDS-LockoutObservationWindow",
4006 struct ldb_context *ldb = NULL;
4007 struct ldb_request *pso_req = NULL;
4008 struct ldb_dn *pso_dn = NULL;
4009 TALLOC_CTX *mem_ctx = ac;
4012 ldb = ldb_module_get_ctx(ac->module);
4014 /* if a PSO applies to the user, we need to lookup the PSO as well */
4015 pso_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, ac->search_res->message,
4016 "msDS-ResultantPSO");
4017 if (pso_dn == NULL) {
4021 ret = ldb_build_search_req(&pso_req, ldb, mem_ctx, pso_dn,
4022 LDB_SCOPE_BASE, NULL, attrs, NULL,
4023 ac, get_pso_data_callback,
4026 /* log errors, but continue with the default domain settings */
4027 if (ret != LDB_SUCCESS) {
4028 DBG_ERR("Error %d constructing PSO query for user %s", ret,
4029 ldb_dn_get_linearized(ac->search_res->message->dn));
4031 LDB_REQ_SET_LOCATION(pso_req);
4036 static int get_domain_data_callback(struct ldb_request *req,
4037 struct ldb_reply *ares)
4039 struct ldb_context *ldb;
4040 struct ph_context *ac;
4041 struct loadparm_context *lp_ctx;
4042 struct ldb_request *pso_req = NULL;
4043 int ret = LDB_SUCCESS;
4045 ac = talloc_get_type(req->context, struct ph_context);
4046 ldb = ldb_module_get_ctx(ac->module);
4049 ret = LDB_ERR_OPERATIONS_ERROR;
4052 if (ares->error != LDB_SUCCESS) {
4053 return ldb_module_done(ac->req, ares->controls,
4054 ares->response, ares->error);
4057 switch (ares->type) {
4058 case LDB_REPLY_ENTRY:
4059 if (ac->status != NULL) {
4062 ldb_set_errstring(ldb, "Too many results");
4063 ret = LDB_ERR_OPERATIONS_ERROR;
4067 /* Setup the "status" structure (used as control later) */
4068 ac->status = talloc_zero(ac->req,
4069 struct dsdb_control_password_change_status);
4070 if (ac->status == NULL) {
4074 ret = LDB_ERR_OPERATIONS_ERROR;
4078 /* Setup the "domain data" structure */
4079 ac->status->domain_data.pwdProperties =
4080 ldb_msg_find_attr_as_uint(ares->message, "pwdProperties", -1);
4081 ac->status->domain_data.pwdHistoryLength =
4082 ldb_msg_find_attr_as_uint(ares->message, "pwdHistoryLength", -1);
4083 ac->status->domain_data.maxPwdAge =
4084 ldb_msg_find_attr_as_int64(ares->message, "maxPwdAge", -1);
4085 ac->status->domain_data.minPwdAge =
4086 ldb_msg_find_attr_as_int64(ares->message, "minPwdAge", -1);
4087 ac->status->domain_data.minPwdLength =
4088 ldb_msg_find_attr_as_uint(ares->message, "minPwdLength", -1);
4089 ac->status->domain_data.store_cleartext =
4090 ac->status->domain_data.pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT;
4092 /* For a domain DN, this puts things in dotted notation */
4093 /* For builtin domains, this will give details for the host,
4094 * but that doesn't really matter, as it's just used for salt
4095 * and kerberos principals, which don't exist here */
4097 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
4098 struct loadparm_context);
4100 ac->status->domain_data.dns_domain = lpcfg_dnsdomain(lp_ctx);
4101 ac->status->domain_data.realm = lpcfg_realm(lp_ctx);
4102 ac->status->domain_data.netbios_domain = lpcfg_sam_name(lp_ctx);
4104 ac->status->reject_reason = SAM_PWD_CHANGE_NO_ERROR;
4106 if (ac->dom_res != NULL) {
4109 ldb_set_errstring(ldb, "Too many results");
4110 ret = LDB_ERR_OPERATIONS_ERROR;
4114 ac->dom_res = talloc_steal(ac, ares);
4118 case LDB_REPLY_REFERRAL:
4124 case LDB_REPLY_DONE:
4126 /* call the next step */
4127 switch (ac->req->operation) {
4129 ret = password_hash_add_do_add(ac);
4135 * The user may have an optional PSO applied. If so,
4136 * query the PSO to get the Fine-Grained Password Policy
4137 * for the user, before we perform the modify
4139 pso_req = build_pso_data_request(ac);
4140 if (pso_req != NULL) {
4141 ret = ldb_next_request(ac->module, pso_req);
4144 /* no PSO, so we can perform the modify now */
4145 ret = password_hash_mod_do_mod(ac);
4150 ret = LDB_ERR_OPERATIONS_ERROR;
4157 if (ret != LDB_SUCCESS) {
4158 struct ldb_reply *new_ares;
4160 new_ares = talloc_zero(ac->req, struct ldb_reply);
4161 if (new_ares == NULL) {
4163 return ldb_module_done(ac->req, NULL, NULL,
4164 LDB_ERR_OPERATIONS_ERROR);
4167 new_ares->error = ret;
4168 if ((ret != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
4169 /* On success and trivial errors a status control is being
4170 * added (used for example by the "samdb_set_password" call) */
4171 ldb_reply_add_control(new_ares,
4172 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
4177 return ldb_module_done(ac->req, new_ares->controls,
4178 new_ares->response, new_ares->error);
4184 static int build_domain_data_request(struct ph_context *ac)
4186 /* attrs[] is returned from this function in
4187 ac->dom_req->op.search.attrs, so it must be static, as
4188 otherwise the compiler can put it on the stack */
4189 struct ldb_context *ldb;
4190 static const char * const attrs[] = { "pwdProperties",
4196 "lockOutObservationWindow",
4200 ldb = ldb_module_get_ctx(ac->module);
4202 ret = ldb_build_search_req(&ac->dom_req, ldb, ac,
4203 ldb_get_default_basedn(ldb),
4207 ac, get_domain_data_callback,
4209 LDB_REQ_SET_LOCATION(ac->dom_req);
4213 static int password_hash_needed(struct ldb_module *module,
4214 struct ldb_request *req,
4215 struct ph_context **_ac)
4217 struct ldb_context *ldb = ldb_module_get_ctx(module);
4218 const char *operation = NULL;
4219 const struct ldb_message *msg = NULL;
4220 struct ph_context *ac = NULL;
4221 const char *passwordAttrs[] = {
4222 DSDB_PASSWORD_ATTRIBUTES,
4225 const char **a = NULL;
4226 unsigned int attr_cnt = 0;
4227 struct ldb_control *bypass = NULL;
4228 struct ldb_control *uac_ctrl = NULL;
4229 bool userPassword = dsdb_user_password_support(module, req, req);
4230 bool update_password = false;
4231 bool processing_needed = false;
4235 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_needed\n");
4237 switch (req->operation) {
4240 msg = req->op.add.message;
4243 operation = "modify";
4244 msg = req->op.mod.message;
4247 return ldb_next_request(module, req);
4250 if (ldb_dn_is_special(msg->dn)) { /* do not manipulate our control entries */
4251 return ldb_next_request(module, req);
4254 bypass = ldb_request_get_control(req,
4255 DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID);
4256 if (bypass != NULL) {
4257 /* Mark the "bypass" control as uncritical (done) */
4258 bypass->critical = false;
4259 ldb_debug(ldb, LDB_DEBUG_TRACE,
4260 "password_hash_needed(%s) (bypassing)\n",
4262 return password_hash_bypass(module, req);
4265 /* nobody must touch password histories and 'supplementalCredentials' */
4266 if (ldb_msg_find_element(msg, "ntPwdHistory")) {
4267 return LDB_ERR_UNWILLING_TO_PERFORM;
4269 if (ldb_msg_find_element(msg, "lmPwdHistory")) {
4270 return LDB_ERR_UNWILLING_TO_PERFORM;
4272 if (ldb_msg_find_element(msg, "supplementalCredentials")) {
4273 return LDB_ERR_UNWILLING_TO_PERFORM;
4277 * If no part of this touches the 'userPassword' OR 'clearTextPassword'
4278 * OR 'unicodePwd' OR 'dBCSPwd' we don't need to make any changes.
4279 * For password changes/set there should be a 'delete' or a 'modify'
4280 * on these attributes.
4282 for (a = passwordAttrs; *a != NULL; a++) {
4283 if ((!userPassword) && (ldb_attr_cmp(*a, "userPassword") == 0)) {
4287 if (ldb_msg_find_element(msg, *a) != NULL) {
4288 /* MS-ADTS 3.1.1.3.1.5.2 */
4289 if ((ldb_attr_cmp(*a, "userPassword") == 0) &&
4290 (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003)) {
4291 return LDB_ERR_CONSTRAINT_VIOLATION;
4299 update_password = true;
4300 processing_needed = true;
4303 if (ldb_msg_find_element(msg, "pwdLastSet")) {
4304 processing_needed = true;
4307 uac_ctrl = ldb_request_get_control(req,
4308 DSDB_CONTROL_PASSWORD_USER_ACCOUNT_CONTROL_OID);
4309 if (uac_ctrl != NULL) {
4310 struct dsdb_control_password_user_account_control *uac = NULL;
4311 uint32_t added_flags = 0;
4313 uac = talloc_get_type_abort(uac_ctrl->data,
4314 struct dsdb_control_password_user_account_control);
4316 added_flags = uac->new_flags & ~uac->old_flags;
4318 if (added_flags & UF_SMARTCARD_REQUIRED) {
4319 processing_needed = true;
4323 if (!processing_needed) {
4324 return ldb_next_request(module, req);
4327 ac = ph_init_context(module, req, userPassword, update_password);
4329 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
4330 return ldb_operr(ldb);
4332 ph_apply_controls(ac);
4335 * Make a copy in order to apply our modifications
4336 * to the final update
4338 ac->update_msg = ldb_msg_copy_shallow(ac, msg);
4339 if (ac->update_msg == NULL) {
4340 return ldb_oom(ldb);
4344 * Remove all password related attributes.
4346 if (ac->userPassword) {
4347 ldb_msg_remove_attr(ac->update_msg, "userPassword");
4349 ldb_msg_remove_attr(ac->update_msg, "clearTextPassword");
4350 ldb_msg_remove_attr(ac->update_msg, "unicodePwd");
4351 ldb_msg_remove_attr(ac->update_msg, "ntPwdHistory");
4352 ldb_msg_remove_attr(ac->update_msg, "dBCSPwd");
4353 ldb_msg_remove_attr(ac->update_msg, "lmPwdHistory");
4354 ldb_msg_remove_attr(ac->update_msg, "supplementalCredentials");
4355 ldb_msg_remove_attr(ac->update_msg, "pwdLastSet");
4361 static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
4363 struct ldb_context *ldb = ldb_module_get_ctx(module);
4364 struct ph_context *ac = NULL;
4367 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_add\n");
4369 ret = password_hash_needed(module, req, &ac);
4370 if (ret != LDB_SUCCESS) {
4377 /* Make sure we are performing the password set action on a (for us)
4378 * valid object. Those are instances of either "user" and/or
4379 * "inetOrgPerson". Otherwise continue with the submodules. */
4380 if ((!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "user"))
4381 && (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "inetOrgPerson"))) {
4385 if (ldb_msg_find_element(req->op.add.message, "clearTextPassword") != NULL) {
4386 ldb_set_errstring(ldb,
4387 "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
4388 return LDB_ERR_NO_SUCH_ATTRIBUTE;
4391 return ldb_next_request(module, req);
4394 /* get user domain data */
4395 ret = build_domain_data_request(ac);
4396 if (ret != LDB_SUCCESS) {
4400 return ldb_next_request(module, ac->dom_req);
4403 static int password_hash_add_do_add(struct ph_context *ac)
4405 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
4406 struct ldb_request *down_req;
4407 struct setup_password_fields_io io;
4410 /* Prepare the internal data structure containing the passwords */
4411 ret = setup_io(ac, ac->req->op.add.message, NULL, &io);
4412 if (ret != LDB_SUCCESS) {
4416 ret = setup_password_fields(&io);
4417 if (ret != LDB_SUCCESS) {
4421 ret = check_password_restrictions_and_log(&io);
4422 if (ret != LDB_SUCCESS) {
4426 ret = setup_smartcard_reset(&io);
4427 if (ret != LDB_SUCCESS) {
4431 ret = update_final_msg(&io);
4432 if (ret != LDB_SUCCESS) {
4436 ret = ldb_build_add_req(&down_req, ldb, ac,
4441 LDB_REQ_SET_LOCATION(down_req);
4442 if (ret != LDB_SUCCESS) {
4446 return ldb_next_request(ac->module, down_req);
4449 static int password_hash_modify(struct ldb_module *module, struct ldb_request *req)
4451 struct ldb_context *ldb = ldb_module_get_ctx(module);
4452 struct ph_context *ac = NULL;
4453 const char *passwordAttrs[] = {DSDB_PASSWORD_ATTRIBUTES, NULL}, **l;
4454 unsigned int del_attr_cnt, add_attr_cnt, rep_attr_cnt;
4455 struct ldb_message_element *passwordAttr;
4456 struct ldb_message *msg;
4457 struct ldb_request *down_req;
4458 struct ldb_control *restore = NULL;
4462 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_modify\n");
4464 ret = password_hash_needed(module, req, &ac);
4465 if (ret != LDB_SUCCESS) {
4472 /* use a new message structure so that we can modify it */
4473 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
4475 return ldb_oom(ldb);
4478 /* - check for single-valued password attributes
4479 * (if not return "CONSTRAINT_VIOLATION")
4480 * - check that for a password change operation one add and one delete
4482 * (if not return "CONSTRAINT_VIOLATION" or "UNWILLING_TO_PERFORM")
4483 * - check that a password change and a password set operation cannot
4485 * (if not return "UNWILLING_TO_PERFORM")
4486 * - remove all password attributes modifications from the first change
4487 * operation (anything without the passwords) - we will make the real
4488 * modification later */
4492 for (l = passwordAttrs; *l != NULL; l++) {
4493 if ((!ac->userPassword) &&
4494 (ldb_attr_cmp(*l, "userPassword") == 0)) {
4498 while ((passwordAttr = ldb_msg_find_element(msg, *l)) != NULL) {
4499 unsigned int mtype = LDB_FLAG_MOD_TYPE(passwordAttr->flags);
4500 unsigned int nvalues = passwordAttr->num_values;
4502 if (mtype == LDB_FLAG_MOD_DELETE) {
4505 if (mtype == LDB_FLAG_MOD_ADD) {
4508 if (mtype == LDB_FLAG_MOD_REPLACE) {
4511 if ((nvalues != 1) && (mtype == LDB_FLAG_MOD_ADD)) {
4513 ldb_asprintf_errstring(ldb,
4514 "'%s' attribute must have exactly one value on add operations!",
4516 return LDB_ERR_CONSTRAINT_VIOLATION;
4518 if ((nvalues > 1) && (mtype == LDB_FLAG_MOD_DELETE)) {
4520 ldb_asprintf_errstring(ldb,
4521 "'%s' attribute must have zero or one value(s) on delete operations!",
4523 return LDB_ERR_CONSTRAINT_VIOLATION;
4525 ldb_msg_remove_element(msg, passwordAttr);
4528 if ((del_attr_cnt == 0) && (add_attr_cnt > 0)) {
4530 ldb_set_errstring(ldb,
4531 "Only the add action for a password change specified!");
4532 return LDB_ERR_UNWILLING_TO_PERFORM;
4534 if ((del_attr_cnt > 1) || (add_attr_cnt > 1)) {
4536 ldb_set_errstring(ldb,
4537 "Only one delete and one add action for a password change allowed!");
4538 return LDB_ERR_UNWILLING_TO_PERFORM;
4540 if ((rep_attr_cnt > 0) && ((del_attr_cnt > 0) || (add_attr_cnt > 0))) {
4542 ldb_set_errstring(ldb,
4543 "Either a password change or a password set operation is allowed!");
4544 return LDB_ERR_UNWILLING_TO_PERFORM;
4547 restore = ldb_request_get_control(req,
4548 DSDB_CONTROL_RESTORE_TOMBSTONE_OID);
4549 if (restore == NULL) {
4551 * A tomstone reanimation generates a double update
4554 * So we only remove it without the
4555 * DSDB_CONTROL_RESTORE_TOMBSTONE_OID control.
4557 ldb_msg_remove_attr(msg, "pwdLastSet");
4561 /* if there was nothing else to be modified skip to next step */
4562 if (msg->num_elements == 0) {
4563 return password_hash_mod_search_self(ac);
4567 * Now we apply all changes remaining in msg
4568 * and remove them from our final update_msg
4571 for (i = 0; i < msg->num_elements; i++) {
4572 ldb_msg_remove_attr(ac->update_msg,
4573 msg->elements[i].name);
4576 ret = ldb_build_mod_req(&down_req, ldb, ac,
4579 ac, ph_modify_callback,
4581 LDB_REQ_SET_LOCATION(down_req);
4582 if (ret != LDB_SUCCESS) {
4586 return ldb_next_request(module, down_req);
4589 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
4591 struct ph_context *ac;
4593 ac = talloc_get_type(req->context, struct ph_context);
4596 return ldb_module_done(ac->req, NULL, NULL,
4597 LDB_ERR_OPERATIONS_ERROR);
4600 if (ares->type == LDB_REPLY_REFERRAL) {
4601 return ldb_module_send_referral(ac->req, ares->referral);
4604 if (ares->error != LDB_SUCCESS) {
4605 return ldb_module_done(ac->req, ares->controls,
4606 ares->response, ares->error);
4609 if (ares->type != LDB_REPLY_DONE) {
4611 return ldb_module_done(ac->req, NULL, NULL,
4612 LDB_ERR_OPERATIONS_ERROR);
4617 return password_hash_mod_search_self(ac);
4620 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares)
4622 struct ldb_context *ldb;
4623 struct ph_context *ac;
4624 int ret = LDB_SUCCESS;
4626 ac = talloc_get_type(req->context, struct ph_context);
4627 ldb = ldb_module_get_ctx(ac->module);
4630 ret = LDB_ERR_OPERATIONS_ERROR;
4633 if (ares->error != LDB_SUCCESS) {
4634 return ldb_module_done(ac->req, ares->controls,
4635 ares->response, ares->error);
4638 /* we are interested only in the single reply (base search) */
4639 switch (ares->type) {
4640 case LDB_REPLY_ENTRY:
4641 /* Make sure we are performing the password change action on a
4642 * (for us) valid object. Those are instances of either "user"
4643 * and/or "inetOrgPerson". Otherwise continue with the
4645 if ((!ldb_msg_check_string_attribute(ares->message, "objectClass", "user"))
4646 && (!ldb_msg_check_string_attribute(ares->message, "objectClass", "inetOrgPerson"))) {
4649 if (ldb_msg_find_element(ac->req->op.mod.message, "clearTextPassword") != NULL) {
4650 ldb_set_errstring(ldb,
4651 "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
4652 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
4656 ret = ldb_next_request(ac->module, ac->req);
4660 if (ac->search_res != NULL) {
4663 ldb_set_errstring(ldb, "Too many results");
4664 ret = LDB_ERR_OPERATIONS_ERROR;
4668 ac->search_res = talloc_steal(ac, ares);
4672 case LDB_REPLY_REFERRAL:
4673 /* ignore anything else for now */
4678 case LDB_REPLY_DONE:
4681 /* get user domain data */
4682 ret = build_domain_data_request(ac);
4683 if (ret != LDB_SUCCESS) {
4684 return ldb_module_done(ac->req, NULL, NULL, ret);
4687 ret = ldb_next_request(ac->module, ac->dom_req);
4692 if (ret != LDB_SUCCESS) {
4693 return ldb_module_done(ac->req, NULL, NULL, ret);
4699 static int password_hash_mod_search_self(struct ph_context *ac)
4701 struct ldb_context *ldb;
4702 static const char * const attrs[] = { "objectClass",
4703 "userAccountControl",
4704 "msDS-ResultantPSO",
4705 "msDS-User-Account-Control-Computed",
4709 "userPrincipalName",
4710 "supplementalCredentials",
4718 "msDS-SecondaryKrbTgtNumber",
4720 struct ldb_request *search_req;
4723 ldb = ldb_module_get_ctx(ac->module);
4725 ret = ldb_build_search_req(&search_req, ldb, ac,
4726 ac->req->op.mod.message->dn,
4731 ac, ph_mod_search_callback,
4733 LDB_REQ_SET_LOCATION(search_req);
4734 if (ret != LDB_SUCCESS) {
4738 return ldb_next_request(ac->module, search_req);
4741 static int password_hash_mod_do_mod(struct ph_context *ac)
4743 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
4744 struct ldb_request *mod_req;
4745 struct setup_password_fields_io io;
4748 /* Prepare the internal data structure containing the passwords */
4749 ret = setup_io(ac, ac->req->op.mod.message,
4750 ac->search_res->message, &io);
4751 if (ret != LDB_SUCCESS) {
4755 ret = setup_password_fields(&io);
4756 if (ret != LDB_SUCCESS) {
4760 ret = check_password_restrictions_and_log(&io);
4761 if (ret != LDB_SUCCESS) {
4765 ret = setup_smartcard_reset(&io);
4766 if (ret != LDB_SUCCESS) {
4770 ret = update_final_msg(&io);
4771 if (ret != LDB_SUCCESS) {
4775 ret = ldb_build_mod_req(&mod_req, ldb, ac,
4780 LDB_REQ_SET_LOCATION(mod_req);
4781 if (ret != LDB_SUCCESS) {
4785 return ldb_next_request(ac->module, mod_req);
4788 static const struct ldb_module_ops ldb_password_hash_module_ops = {
4789 .name = "password_hash",
4790 .add = password_hash_add,
4791 .modify = password_hash_modify
4794 int ldb_password_hash_module_init(const char *version)
4797 const char *gversion = NULL;
4798 #endif /* ENABLE_GPGME */
4800 LDB_MODULE_CHECK_VERSION(version);
4804 * Note: this sets a SIGPIPE handler
4805 * if none is active already. See:
4806 * https://www.gnupg.org/documentation/manuals/gpgme/Signal-Handling.html#Signal-Handling
4808 gversion = gpgme_check_version(GPGME_VERSION);
4809 if (gversion == NULL) {
4810 fprintf(stderr, "%s() in %s version[%s]: "
4811 "gpgme_check_version(%s) not available, "
4812 "gpgme_check_version(NULL) => '%s'\n",
4813 __func__, __FILE__, version,
4814 GPGME_VERSION, gpgme_check_version(NULL));
4815 return LDB_ERR_UNAVAILABLE;
4817 #endif /* ENABLE_GPGME */
4819 return ldb_register_module(&ldb_password_hash_module_ops);