s3:rpc_server: Initialize array
[Samba.git] / source4 / dsdb / samdb / ldb_modules / password_hash.c
blob1d1267624e2c02f6746ce39484e5e93b72c75833
1 /*
2 ldb database module
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/>.
25 * Name: ldb
27 * Component: ldb password_hash module
29 * Description: correctly handle AD password changes fields
31 * Author: Andrew Bartlett
32 * Author: Stefan Metzmacher
35 #include "includes.h"
36 #include "ldb_errors.h"
37 #include "ldb_module.h"
38 #include "libcli/auth/libcli_auth.h"
39 #include "libcli/security/dom_sid.h"
40 #include "system/kerberos.h"
41 #include "auth/kerberos/kerberos.h"
42 #include "dsdb/gmsa/util.h"
43 #include "dsdb/samdb/samdb.h"
44 #include "dsdb/samdb/ldb_modules/util.h"
45 #include "dsdb/samdb/ldb_modules/password_modules.h"
46 #include "librpc/gen_ndr/ndr_drsblobs.h"
47 #include "lib/crypto/md4.h"
48 #include "param/param.h"
49 #include "lib/krb5_wrap/krb5_samba.h"
50 #include "auth/auth_sam.h"
51 #include "auth/common_auth.h"
52 #include "lib/messaging/messaging.h"
53 #include "lib/param/loadparm.h"
55 #include "lib/crypto/gnutls_helpers.h"
56 #include <gnutls/crypto.h>
58 #include "kdc/db-glue.h"
60 #ifdef ENABLE_GPGME
61 #undef class
62 #include <gpgme.h>
65 * 1.2.0 is what dpkg-shlibdeps generates, based on used symbols and
66 * libgpgme11.symbols
67 * https://salsa.debian.org/debian/gpgme/blob/debian/master/debian/libgpgme11.symbols
70 #define MINIMUM_GPGME_VERSION "1.2.0"
71 #endif
73 #undef strncasecmp
74 #undef strcasecmp
76 /* If we have decided there is a reason to work on this request, then
77 * setup all the password hash types correctly.
79 * If we haven't the hashes yet but the password given as plain-text (attributes
80 * 'unicodePwd', 'userPassword' and 'clearTextPassword') we have to check for
81 * the constraints. Once this is done, we calculate the password hashes.
83 * Notice: unlike the real AD which only supports the UTF16 special based
84 * 'unicodePwd' and the UTF8 based 'userPassword' plaintext attribute we
85 * understand also a UTF16 based 'clearTextPassword' one.
86 * The latter is also accessible through LDAP so it can also be set by external
87 * tools and scripts. But be aware that this isn't portable on non SAMBA 4 ADs!
89 * Also when the module receives only the password hashes (possible through
90 * specifying an internal LDB control - for security reasons) some checks are
91 * performed depending on the operation mode (see below) (e.g. if the password
92 * has been in use before if the password memory policy was activated).
94 * Attention: There is a difference between "modify" and "reset" operations
95 * (see MS-ADTS 3.1.1.3.1.5). If the client sends a "add" and "remove"
96 * operation for a password attribute we thread this as a "modify"; if it sends
97 * only a "replace" one we have an (administrative) reset.
99 * Finally, if the administrator has requested that a password history
100 * be maintained, then this should also be written out.
104 /* TODO: [consider always MS-ADTS 3.1.1.3.1.5]
105 * - Check for right connection encryption
108 /* Notice: Definition of "dsdb_control_password_change_status" moved into
109 * "samdb.h" */
111 struct ph_context {
112 struct ldb_module *module;
113 struct ldb_request *req;
115 struct ldb_request *dom_req;
116 struct ldb_reply *dom_res;
118 struct ldb_reply *pso_res;
120 struct ldb_reply *search_res;
122 struct ldb_message *update_msg;
124 struct dsdb_control_password_change_status *status;
125 struct dsdb_control_password_change *change;
127 const char **gpg_key_ids;
129 bool pwd_reset;
130 bool change_status;
131 bool hash_values;
132 bool userPassword;
133 bool update_password;
134 bool update_lastset;
135 bool pwd_last_set_bypass;
136 bool pwd_last_set_default;
137 bool smartcard_reset;
138 bool kdc_reset_smartcard_account_password;
139 const char **userPassword_schemes;
143 struct setup_password_fields_io {
144 struct ph_context *ac;
146 struct smb_krb5_context *smb_krb5_context;
148 /* info about the user account */
149 struct {
150 uint32_t userAccountControl;
151 NTTIME pwdLastSet;
152 const char *sAMAccountName;
153 const char *user_principal_name;
154 const char *displayName; /* full name */
155 bool is_krbtgt;
156 uint32_t restrictions;
157 struct dom_sid *account_sid;
158 bool store_nt_hash;
159 } u;
161 /* new credentials and old given credentials */
162 struct setup_password_fields_given {
163 const struct ldb_val *cleartext_utf8;
164 const struct ldb_val *cleartext_utf16;
166 struct samr_Password *nt_hash;
169 * The AES256 kerberos key to confirm the previous password was
170 * not reused (for n) and to prove the old password was known
171 * (for og).
173 * We don't have any old salts, so we won't catch password reuse
174 * if said password was used prior to an account rename and
175 * another password change.
177 DATA_BLOB aes_256;
178 } n, og;
180 /* old credentials */
181 struct {
182 struct samr_Password *nt_hash;
183 uint32_t nt_history_len;
184 struct samr_Password *nt_history;
185 const struct ldb_val *supplemental;
186 struct supplementalCredentialsBlob scb;
189 * The AES256 kerberos key as stored in the DB.
190 * Used to confirm the given password was correct
191 * and in case the previous password was reused.
193 DATA_BLOB aes_256;
194 DATA_BLOB salt;
195 uint32_t kvno;
196 } o;
198 /* generated credentials */
199 struct {
200 struct samr_Password *nt_hash;
201 uint32_t nt_history_len;
202 struct samr_Password *nt_history;
203 const char *salt;
204 DATA_BLOB aes_256;
205 DATA_BLOB aes_128;
206 DATA_BLOB des_md5;
207 DATA_BLOB des_crc;
208 struct ldb_val supplemental;
209 NTTIME last_set;
210 } g;
213 static int msg_find_old_and_new_pwd_val(const struct ldb_message *msg,
214 const char *name,
215 enum ldb_request_type operation,
216 const struct ldb_val **new_val,
217 const struct ldb_val **old_val);
219 static int password_hash_bypass(struct ldb_module *module, struct ldb_request *request)
221 struct ldb_context *ldb = ldb_module_get_ctx(module);
222 const struct ldb_message *msg;
223 struct ldb_message_element *nte;
224 struct ldb_message_element *lme;
225 struct ldb_message_element *nthe;
226 struct ldb_message_element *lmhe;
227 struct ldb_message_element *sce;
228 int ret;
230 switch (request->operation) {
231 case LDB_ADD:
232 msg = request->op.add.message;
233 break;
234 case LDB_MODIFY:
235 msg = request->op.mod.message;
236 break;
237 default:
238 return ldb_next_request(module, request);
241 /* nobody must touch password histories and 'supplementalCredentials' */
243 #define GET_VALUES(el, attr) do { \
244 ret = dsdb_get_expected_new_values(request, \
245 msg, \
246 attr, \
247 &el, \
248 request->operation); \
250 if (ret != LDB_SUCCESS) { \
251 return ret; \
253 } while(0)
255 GET_VALUES(nte, "unicodePwd");
258 * Even as Samba continues to ignore the LM hash, and reset it
259 * when practical, we keep the constraint that it must be a 16
260 * byte value if specified.
262 GET_VALUES(lme, "dBCSPwd");
263 GET_VALUES(nthe, "ntPwdHistory");
264 GET_VALUES(lmhe, "lmPwdHistory");
265 GET_VALUES(sce, "supplementalCredentials");
267 #undef GET_VALUES
268 #define CHECK_HASH_ELEMENT(e, min, max) do {\
269 if (e && e->num_values) { \
270 unsigned int _count; \
271 if (e->num_values != 1) { \
272 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
273 "num_values != 1"); \
275 if ((e->values[0].length % 16) != 0) { \
276 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
277 "length % 16 != 0"); \
279 _count = e->values[0].length / 16; \
280 if (_count < min) { \
281 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
282 "count < min"); \
284 if (_count > max) { \
285 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
286 "count > max"); \
289 } while (0)
291 CHECK_HASH_ELEMENT(nte, 1, 1);
292 CHECK_HASH_ELEMENT(lme, 1, 1);
293 CHECK_HASH_ELEMENT(nthe, 1, INT32_MAX);
294 CHECK_HASH_ELEMENT(lmhe, 1, INT32_MAX);
296 if (sce && sce->num_values) {
297 enum ndr_err_code ndr_err;
298 struct supplementalCredentialsBlob *scb;
299 struct supplementalCredentialsPackage *scpp = NULL;
300 struct supplementalCredentialsPackage *scpk = NULL;
301 struct supplementalCredentialsPackage *scpkn = NULL;
302 struct supplementalCredentialsPackage *scpct = NULL;
303 DATA_BLOB scpbp = data_blob_null;
304 DATA_BLOB scpbk = data_blob_null;
305 DATA_BLOB scpbkn = data_blob_null;
306 DATA_BLOB scpbct = data_blob_null;
307 DATA_BLOB blob;
308 uint32_t i;
310 if (sce->num_values != 1) {
311 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
312 "num_values != 1");
315 scb = talloc_zero(request, struct supplementalCredentialsBlob);
316 if (!scb) {
317 return ldb_module_oom(module);
320 ndr_err = ndr_pull_struct_blob_all(&sce->values[0], scb, scb,
321 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
322 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
323 talloc_free(scb);
324 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
325 "ndr_pull_struct_blob_all");
328 if (scb->sub.num_packages < 2) {
329 talloc_free(scb);
330 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
331 "num_packages < 2");
334 for (i=0; i < scb->sub.num_packages; i++) {
335 DATA_BLOB subblob;
337 subblob = strhex_to_data_blob(scb, scb->sub.packages[i].data);
338 if (subblob.data == NULL) {
339 talloc_free(scb);
340 return ldb_module_oom(module);
343 if (strcmp(scb->sub.packages[i].name, "Packages") == 0) {
344 if (scpp) {
345 talloc_free(scb);
346 return ldb_error(ldb,
347 LDB_ERR_CONSTRAINT_VIOLATION,
348 "Packages twice");
350 scpp = &scb->sub.packages[i];
351 scpbp = subblob;
352 continue;
354 if (strcmp(scb->sub.packages[i].name, "Primary:Kerberos") == 0) {
355 if (scpk) {
356 talloc_free(scb);
357 return ldb_error(ldb,
358 LDB_ERR_CONSTRAINT_VIOLATION,
359 "Primary:Kerberos twice");
361 scpk = &scb->sub.packages[i];
362 scpbk = subblob;
363 continue;
365 if (strcmp(scb->sub.packages[i].name, "Primary:Kerberos-Newer-Keys") == 0) {
366 if (scpkn) {
367 talloc_free(scb);
368 return ldb_error(ldb,
369 LDB_ERR_CONSTRAINT_VIOLATION,
370 "Primary:Kerberos-Newer-Keys twice");
372 scpkn = &scb->sub.packages[i];
373 scpbkn = subblob;
374 continue;
376 if (strcmp(scb->sub.packages[i].name, "Primary:CLEARTEXT") == 0) {
377 if (scpct) {
378 talloc_free(scb);
379 return ldb_error(ldb,
380 LDB_ERR_CONSTRAINT_VIOLATION,
381 "Primary:CLEARTEXT twice");
383 scpct = &scb->sub.packages[i];
384 scpbct = subblob;
385 continue;
388 data_blob_free(&subblob);
391 if (scpp == NULL) {
392 talloc_free(scb);
393 return ldb_error(ldb,
394 LDB_ERR_CONSTRAINT_VIOLATION,
395 "Primary:Packages missing");
398 if (scpk == NULL) {
400 * If Primary:Kerberos is missing w2k8r2 reboots
401 * when a password is changed.
403 talloc_free(scb);
404 return ldb_error(ldb,
405 LDB_ERR_CONSTRAINT_VIOLATION,
406 "Primary:Kerberos missing");
409 if (scpp) {
410 struct package_PackagesBlob *p;
411 uint32_t n;
413 p = talloc_zero(scb, struct package_PackagesBlob);
414 if (p == NULL) {
415 talloc_free(scb);
416 return ldb_module_oom(module);
419 ndr_err = ndr_pull_struct_blob(&scpbp, p, p,
420 (ndr_pull_flags_fn_t)ndr_pull_package_PackagesBlob);
421 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
422 talloc_free(scb);
423 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
424 "ndr_pull_struct_blob Packages");
427 if (p->names == NULL) {
428 talloc_free(scb);
429 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
430 "Packages names == NULL");
433 for (n = 0; p->names[n]; n++) {
434 /* noop */
437 if (scb->sub.num_packages != (n + 1)) {
438 talloc_free(scb);
439 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
440 "Packages num_packages != num_names + 1");
443 talloc_free(p);
446 if (scpk) {
447 struct package_PrimaryKerberosBlob *k;
449 k = talloc_zero(scb, struct package_PrimaryKerberosBlob);
450 if (k == NULL) {
451 talloc_free(scb);
452 return ldb_module_oom(module);
455 ndr_err = ndr_pull_struct_blob(&scpbk, k, k,
456 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
457 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
458 talloc_free(scb);
459 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
460 "ndr_pull_struct_blob PrimaryKerberos");
463 if (k->version != 3) {
464 talloc_free(scb);
465 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
466 "PrimaryKerberos version != 3");
469 if (k->ctr.ctr3.salt.string == NULL) {
470 talloc_free(scb);
471 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
472 "PrimaryKerberos salt == NULL");
475 if (strlen(k->ctr.ctr3.salt.string) == 0) {
476 talloc_free(scb);
477 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
478 "PrimaryKerberos strlen(salt) == 0");
481 if (k->ctr.ctr3.num_keys != 2) {
482 talloc_free(scb);
483 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
484 "PrimaryKerberos num_keys != 2");
487 if (k->ctr.ctr3.num_old_keys > k->ctr.ctr3.num_keys) {
488 talloc_free(scb);
489 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
490 "PrimaryKerberos num_old_keys > num_keys");
493 if (k->ctr.ctr3.keys[0].keytype != ENCTYPE_DES_CBC_MD5) {
494 talloc_free(scb);
495 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
496 "PrimaryKerberos key[0] != DES_CBC_MD5");
498 if (k->ctr.ctr3.keys[1].keytype != ENCTYPE_DES_CBC_CRC) {
499 talloc_free(scb);
500 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
501 "PrimaryKerberos key[1] != DES_CBC_CRC");
504 if (k->ctr.ctr3.keys[0].value_len != 8) {
505 talloc_free(scb);
506 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
507 "PrimaryKerberos key[0] value_len != 8");
509 if (k->ctr.ctr3.keys[1].value_len != 8) {
510 talloc_free(scb);
511 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
512 "PrimaryKerberos key[1] value_len != 8");
515 for (i = 0; i < k->ctr.ctr3.num_old_keys; i++) {
516 if (k->ctr.ctr3.old_keys[i].keytype ==
517 k->ctr.ctr3.keys[i].keytype &&
518 k->ctr.ctr3.old_keys[i].value_len ==
519 k->ctr.ctr3.keys[i].value_len) {
520 continue;
523 talloc_free(scb);
524 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
525 "PrimaryKerberos old_keys type/value_len doesn't match");
528 talloc_free(k);
531 if (scpkn) {
532 struct package_PrimaryKerberosBlob *k;
534 k = talloc_zero(scb, struct package_PrimaryKerberosBlob);
535 if (k == NULL) {
536 talloc_free(scb);
537 return ldb_module_oom(module);
540 ndr_err = ndr_pull_struct_blob(&scpbkn, k, k,
541 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
542 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
543 talloc_free(scb);
544 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
545 "ndr_pull_struct_blob PrimaryKerberosNewerKeys");
548 if (k->version != 4) {
549 talloc_free(scb);
550 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
551 "KerberosNewerKeys version != 4");
554 if (k->ctr.ctr4.salt.string == NULL) {
555 talloc_free(scb);
556 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
557 "KerberosNewerKeys salt == NULL");
560 if (strlen(k->ctr.ctr4.salt.string) == 0) {
561 talloc_free(scb);
562 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
563 "KerberosNewerKeys strlen(salt) == 0");
566 if (k->ctr.ctr4.num_keys != 4) {
567 talloc_free(scb);
568 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
569 "KerberosNewerKeys num_keys != 4");
572 if (k->ctr.ctr4.num_old_keys > k->ctr.ctr4.num_keys) {
573 talloc_free(scb);
574 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
575 "KerberosNewerKeys num_old_keys > num_keys");
578 if (k->ctr.ctr4.num_older_keys > k->ctr.ctr4.num_old_keys) {
579 talloc_free(scb);
580 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
581 "KerberosNewerKeys num_older_keys > num_old_keys");
584 if (k->ctr.ctr4.keys[0].keytype != ENCTYPE_AES256_CTS_HMAC_SHA1_96) {
585 talloc_free(scb);
586 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
587 "KerberosNewerKeys key[0] != AES256");
589 if (k->ctr.ctr4.keys[1].keytype != ENCTYPE_AES128_CTS_HMAC_SHA1_96) {
590 talloc_free(scb);
591 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
592 "KerberosNewerKeys key[1] != AES128");
594 if (k->ctr.ctr4.keys[2].keytype != ENCTYPE_DES_CBC_MD5) {
595 talloc_free(scb);
596 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
597 "KerberosNewerKeys key[2] != DES_CBC_MD5");
599 if (k->ctr.ctr4.keys[3].keytype != ENCTYPE_DES_CBC_CRC) {
600 talloc_free(scb);
601 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
602 "KerberosNewerKeys key[3] != DES_CBC_CRC");
605 if (k->ctr.ctr4.keys[0].value_len != 32) {
606 talloc_free(scb);
607 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
608 "KerberosNewerKeys key[0] value_len != 32");
610 if (k->ctr.ctr4.keys[1].value_len != 16) {
611 talloc_free(scb);
612 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
613 "KerberosNewerKeys key[1] value_len != 16");
615 if (k->ctr.ctr4.keys[2].value_len != 8) {
616 talloc_free(scb);
617 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
618 "KerberosNewerKeys key[2] value_len != 8");
620 if (k->ctr.ctr4.keys[3].value_len != 8) {
621 talloc_free(scb);
622 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
623 "KerberosNewerKeys key[3] value_len != 8");
627 * TODO:
628 * Maybe we can check old and older keys here.
629 * But we need to do some tests, if the old keys
630 * can be taken from the PrimaryKerberos blob
631 * (with only des keys), when the domain was upgraded
632 * from w2k3 to w2k8.
635 talloc_free(k);
638 if (scpct) {
639 struct package_PrimaryCLEARTEXTBlob *ct;
641 ct = talloc_zero(scb, struct package_PrimaryCLEARTEXTBlob);
642 if (ct == NULL) {
643 talloc_free(scb);
644 return ldb_module_oom(module);
647 ndr_err = ndr_pull_struct_blob(&scpbct, ct, ct,
648 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryCLEARTEXTBlob);
649 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
650 talloc_free(scb);
651 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
652 "ndr_pull_struct_blob PrimaryCLEARTEXT");
655 if ((ct->cleartext.length % 2) != 0) {
656 talloc_free(scb);
657 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
658 "PrimaryCLEARTEXT length % 2 != 0");
661 talloc_free(ct);
664 ndr_err = ndr_push_struct_blob(&blob, scb, scb,
665 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
666 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
667 talloc_free(scb);
668 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
669 "ndr_push_struct_blob");
672 if (sce->values[0].length != blob.length) {
673 talloc_free(scb);
674 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
675 "supplementalCredentialsBlob length differ");
678 if (!mem_equal_const_time(sce->values[0].data, blob.data, blob.length)) {
679 talloc_free(scb);
680 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
681 "supplementalCredentialsBlob memcmp differ");
684 talloc_free(scb);
687 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_bypass - validated\n");
688 return ldb_next_request(module, request);
691 /* Get the NT hash, and fill it in as an entry in the password history,
692 and specify it into io->g.nt_hash */
694 static int setup_nt_fields(struct setup_password_fields_io *io)
696 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
697 uint32_t i;
698 if (io->u.store_nt_hash) {
699 io->g.nt_hash = io->n.nt_hash;
702 if (io->ac->status->domain_data.pwdHistoryLength == 0) {
703 return LDB_SUCCESS;
706 /* We might not have an old NT password */
708 if (io->g.nt_hash == NULL) {
710 * If there was not an NT hash specified, then don't
711 * store the NT password history.
713 * While the NTLM code on a Windows DC will cope with
714 * a missing unicodePwd, if it finds a last password
715 * in the ntPwdHistory, even if the bytes are zero ,
716 * it will (quite reasonably) treat it as a valid NT
717 * hash. NTLM logins with the previous password are
718 * allowed for a short time after the password is
719 * changed to allow for password propagation delays.
721 return LDB_SUCCESS;
724 io->g.nt_history = talloc_array(io->ac,
725 struct samr_Password,
726 io->ac->status->domain_data.pwdHistoryLength);
727 if (!io->g.nt_history) {
728 return ldb_oom(ldb);
731 for (i = 0; i < MIN(io->ac->status->domain_data.pwdHistoryLength-1,
732 io->o.nt_history_len); i++) {
733 io->g.nt_history[i+1] = io->o.nt_history[i];
735 io->g.nt_history_len = i + 1;
737 io->g.nt_history[0] = *io->g.nt_hash;
739 return LDB_SUCCESS;
742 static int setup_kerberos_keys(struct setup_password_fields_io *io)
744 struct ldb_context *ldb;
745 krb5_error_code krb5_ret;
746 krb5_principal salt_principal = NULL;
747 krb5_data salt_data;
748 krb5_data salt;
749 krb5_keyblock key;
750 krb5_data cleartext_data;
751 uint32_t uac_flags = 0;
753 ldb = ldb_module_get_ctx(io->ac->module);
754 cleartext_data.data = (char *)io->n.cleartext_utf8->data;
755 cleartext_data.length = io->n.cleartext_utf8->length;
757 uac_flags = io->u.userAccountControl & UF_ACCOUNT_TYPE_MASK;
758 krb5_ret = smb_krb5_salt_principal(io->smb_krb5_context->krb5_context,
759 io->ac->status->domain_data.realm,
760 io->u.sAMAccountName,
761 io->u.user_principal_name,
762 uac_flags,
763 &salt_principal);
764 if (krb5_ret) {
765 ldb_asprintf_errstring(ldb,
766 "setup_kerberos_keys: "
767 "generation of a salting principal failed: %s",
768 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
769 krb5_ret, io->ac));
770 return LDB_ERR_OPERATIONS_ERROR;
774 * create salt from salt_principal
776 krb5_ret = smb_krb5_get_pw_salt(io->smb_krb5_context->krb5_context,
777 salt_principal, &salt_data);
779 krb5_free_principal(io->smb_krb5_context->krb5_context, salt_principal);
780 if (krb5_ret) {
781 ldb_asprintf_errstring(ldb,
782 "setup_kerberos_keys: "
783 "generation of krb5_salt failed: %s",
784 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
785 krb5_ret, io->ac));
786 return LDB_ERR_OPERATIONS_ERROR;
789 /* now use the talloced copy of the salt */
790 salt.data = talloc_strndup(io->ac,
791 (char *)salt_data.data,
792 salt_data.length);
793 smb_krb5_free_data_contents(io->smb_krb5_context->krb5_context,
794 &salt_data);
795 if (salt.data == NULL) {
796 return ldb_oom(ldb);
798 io->g.salt = salt.data;
799 salt.length = strlen(io->g.salt);
802 * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of
803 * the salt and the cleartext password
805 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
806 NULL,
807 &salt,
808 &cleartext_data,
809 ENCTYPE_AES256_CTS_HMAC_SHA1_96,
810 &key);
811 if (krb5_ret) {
812 ldb_asprintf_errstring(ldb,
813 "setup_kerberos_keys: "
814 "generation of a aes256-cts-hmac-sha1-96 key failed: %s",
815 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
816 krb5_ret, io->ac));
817 return LDB_ERR_OPERATIONS_ERROR;
819 io->g.aes_256 = data_blob_talloc(io->ac,
820 KRB5_KEY_DATA(&key),
821 KRB5_KEY_LENGTH(&key));
822 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
823 if (!io->g.aes_256.data) {
824 return ldb_oom(ldb);
828 * create ENCTYPE_AES128_CTS_HMAC_SHA1_96 key out of
829 * the salt and the cleartext password
831 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
832 NULL,
833 &salt,
834 &cleartext_data,
835 ENCTYPE_AES128_CTS_HMAC_SHA1_96,
836 &key);
837 if (krb5_ret) {
838 ldb_asprintf_errstring(ldb,
839 "setup_kerberos_keys: "
840 "generation of a aes128-cts-hmac-sha1-96 key failed: %s",
841 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
842 krb5_ret, io->ac));
843 return LDB_ERR_OPERATIONS_ERROR;
845 io->g.aes_128 = data_blob_talloc(io->ac,
846 KRB5_KEY_DATA(&key),
847 KRB5_KEY_LENGTH(&key));
848 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
849 if (!io->g.aes_128.data) {
850 return ldb_oom(ldb);
854 * As per RFC-6649 single DES encryption types are no longer considered
855 * secure to be used in Kerberos, we store random keys instead of the
856 * ENCTYPE_DES_CBC_MD5 and ENCTYPE_DES_CBC_CRC keys.
858 io->g.des_md5 = data_blob_talloc(io->ac, NULL, 8);
859 if (!io->g.des_md5.data) {
860 return ldb_oom(ldb);
862 generate_secret_buffer(io->g.des_md5.data, 8);
864 io->g.des_crc = data_blob_talloc(io->ac, NULL, 8);
865 if (!io->g.des_crc.data) {
866 return ldb_oom(ldb);
868 generate_secret_buffer(io->g.des_crc.data, 8);
870 return LDB_SUCCESS;
873 static int setup_kerberos_key_hash(struct setup_password_fields_io *io,
874 struct setup_password_fields_given *g)
876 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
877 krb5_error_code krb5_ret;
878 krb5_data salt;
879 krb5_keyblock key;
880 krb5_data cleartext_data;
882 if (io->ac->search_res == NULL) {
883 /* No old data so nothing to do */
884 return LDB_SUCCESS;
887 if (io->o.salt.data == NULL) {
888 /* We didn't fetch the salt in setup_io(), so nothing to do */
889 return LDB_SUCCESS;
892 salt.data = (char *)io->o.salt.data;
893 salt.length = io->o.salt.length;
895 cleartext_data.data = (char *)g->cleartext_utf8->data;
896 cleartext_data.length = g->cleartext_utf8->length;
899 * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of the salt
900 * and the cleartext password
902 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
903 NULL,
904 &salt,
905 &cleartext_data,
906 ENCTYPE_AES256_CTS_HMAC_SHA1_96,
907 &key);
908 if (krb5_ret) {
909 ldb_asprintf_errstring(ldb,
910 "setup_kerberos_key_hash: "
911 "generation of a aes256-cts-hmac-sha1-96 key failed: %s",
912 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
913 krb5_ret, io->ac));
914 return LDB_ERR_OPERATIONS_ERROR;
917 g->aes_256 = data_blob_talloc(io->ac,
918 KRB5_KEY_DATA(&key),
919 KRB5_KEY_LENGTH(&key));
920 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
921 if (g->aes_256.data == NULL) {
922 return ldb_oom(ldb);
925 talloc_keep_secret(g->aes_256.data);
927 return LDB_SUCCESS;
930 static int setup_primary_kerberos(struct setup_password_fields_io *io,
931 const struct supplementalCredentialsBlob *old_scb,
932 struct package_PrimaryKerberosBlob *pkb)
934 struct ldb_context *ldb;
935 struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3;
936 struct supplementalCredentialsPackage *old_scp = NULL;
937 struct package_PrimaryKerberosBlob _old_pkb;
938 struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL;
939 uint32_t i;
940 enum ndr_err_code ndr_err;
942 ldb = ldb_module_get_ctx(io->ac->module);
945 * prepare generation of keys
947 * ENCTYPE_DES_CBC_MD5
948 * ENCTYPE_DES_CBC_CRC
950 pkb->version = 3;
951 pkb3->salt.string = io->g.salt;
952 pkb3->num_keys = 2;
953 pkb3->keys = talloc_array(io->ac,
954 struct package_PrimaryKerberosKey3,
955 pkb3->num_keys);
956 if (!pkb3->keys) {
957 return ldb_oom(ldb);
960 pkb3->keys[0].keytype = ENCTYPE_DES_CBC_MD5;
961 pkb3->keys[0].value = &io->g.des_md5;
962 pkb3->keys[1].keytype = ENCTYPE_DES_CBC_CRC;
963 pkb3->keys[1].value = &io->g.des_crc;
965 /* initialize the old keys to zero */
966 pkb3->num_old_keys = 0;
967 pkb3->old_keys = NULL;
969 /* if there're no old keys, then we're done */
970 if (!old_scb) {
971 return LDB_SUCCESS;
974 for (i=0; i < old_scb->sub.num_packages; i++) {
975 if (strcmp("Primary:Kerberos", old_scb->sub.packages[i].name) != 0) {
976 continue;
979 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
980 continue;
983 old_scp = &old_scb->sub.packages[i];
984 break;
986 /* Primary:Kerberos element of supplementalCredentials */
987 if (old_scp) {
988 DATA_BLOB blob;
990 blob = strhex_to_data_blob(io->ac, old_scp->data);
991 if (!blob.data) {
992 return ldb_oom(ldb);
995 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
996 ndr_err = ndr_pull_struct_blob(&blob, io->ac, &_old_pkb,
997 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
998 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
999 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1000 ldb_asprintf_errstring(ldb,
1001 "setup_primary_kerberos: "
1002 "failed to pull old package_PrimaryKerberosBlob: %s",
1003 nt_errstr(status));
1004 return LDB_ERR_OPERATIONS_ERROR;
1007 if (_old_pkb.version != 3) {
1008 ldb_asprintf_errstring(ldb,
1009 "setup_primary_kerberos: "
1010 "package_PrimaryKerberosBlob version[%u] expected[3]",
1011 _old_pkb.version);
1012 return LDB_ERR_OPERATIONS_ERROR;
1015 old_pkb3 = &_old_pkb.ctr.ctr3;
1018 /* if we didn't find the old keys we're done */
1019 if (!old_pkb3) {
1020 return LDB_SUCCESS;
1023 /* fill in the old keys */
1024 pkb3->num_old_keys = old_pkb3->num_keys;
1025 pkb3->old_keys = old_pkb3->keys;
1027 return LDB_SUCCESS;
1030 static int setup_primary_kerberos_newer(struct setup_password_fields_io *io,
1031 const struct supplementalCredentialsBlob *old_scb,
1032 struct package_PrimaryKerberosBlob *pkb)
1034 struct ldb_context *ldb;
1035 struct package_PrimaryKerberosCtr4 *pkb4 = &pkb->ctr.ctr4;
1036 struct supplementalCredentialsPackage *old_scp = NULL;
1037 struct package_PrimaryKerberosBlob _old_pkb;
1038 struct package_PrimaryKerberosCtr4 *old_pkb4 = NULL;
1039 uint32_t i;
1040 enum ndr_err_code ndr_err;
1042 ldb = ldb_module_get_ctx(io->ac->module);
1045 * prepare generation of keys
1047 * ENCTYPE_AES256_CTS_HMAC_SHA1_96
1048 * ENCTYPE_AES128_CTS_HMAC_SHA1_96
1049 * ENCTYPE_DES_CBC_MD5
1050 * ENCTYPE_DES_CBC_CRC
1052 pkb->version = 4;
1053 pkb4->salt.string = io->g.salt;
1054 pkb4->default_iteration_count = 4096;
1055 pkb4->num_keys = 4;
1057 pkb4->keys = talloc_array(io->ac,
1058 struct package_PrimaryKerberosKey4,
1059 pkb4->num_keys);
1060 if (!pkb4->keys) {
1061 return ldb_oom(ldb);
1064 pkb4->keys[0].iteration_count = 4096;
1065 pkb4->keys[0].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
1066 pkb4->keys[0].value = &io->g.aes_256;
1067 pkb4->keys[1].iteration_count = 4096;
1068 pkb4->keys[1].keytype = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
1069 pkb4->keys[1].value = &io->g.aes_128;
1070 pkb4->keys[2].iteration_count = 4096;
1071 pkb4->keys[2].keytype = ENCTYPE_DES_CBC_MD5;
1072 pkb4->keys[2].value = &io->g.des_md5;
1073 pkb4->keys[3].iteration_count = 4096;
1074 pkb4->keys[3].keytype = ENCTYPE_DES_CBC_CRC;
1075 pkb4->keys[3].value = &io->g.des_crc;
1077 /* initialize the old keys to zero */
1078 pkb4->num_old_keys = 0;
1079 pkb4->old_keys = NULL;
1080 pkb4->num_older_keys = 0;
1081 pkb4->older_keys = NULL;
1083 /* if there're no old keys, then we're done */
1084 if (!old_scb) {
1085 return LDB_SUCCESS;
1088 for (i=0; i < old_scb->sub.num_packages; i++) {
1089 if (strcmp("Primary:Kerberos-Newer-Keys", old_scb->sub.packages[i].name) != 0) {
1090 continue;
1093 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
1094 continue;
1097 old_scp = &old_scb->sub.packages[i];
1098 break;
1100 /* Primary:Kerberos-Newer-Keys element of supplementalCredentials */
1101 if (old_scp) {
1102 DATA_BLOB blob;
1104 blob = strhex_to_data_blob(io->ac, old_scp->data);
1105 if (!blob.data) {
1106 return ldb_oom(ldb);
1109 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
1110 ndr_err = ndr_pull_struct_blob(&blob, io->ac,
1111 &_old_pkb,
1112 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
1113 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1114 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1115 ldb_asprintf_errstring(ldb,
1116 "setup_primary_kerberos_newer: "
1117 "failed to pull old package_PrimaryKerberosBlob: %s",
1118 nt_errstr(status));
1119 return LDB_ERR_OPERATIONS_ERROR;
1122 if (_old_pkb.version != 4) {
1123 ldb_asprintf_errstring(ldb,
1124 "setup_primary_kerberos_newer: "
1125 "package_PrimaryKerberosBlob version[%u] expected[4]",
1126 _old_pkb.version);
1127 return LDB_ERR_OPERATIONS_ERROR;
1130 old_pkb4 = &_old_pkb.ctr.ctr4;
1133 /* if we didn't find the old keys we're done */
1134 if (!old_pkb4) {
1135 return LDB_SUCCESS;
1138 /* fill in the old keys */
1139 pkb4->num_old_keys = old_pkb4->num_keys;
1140 pkb4->old_keys = old_pkb4->keys;
1141 pkb4->num_older_keys = old_pkb4->num_old_keys;
1142 pkb4->older_keys = old_pkb4->old_keys;
1144 return LDB_SUCCESS;
1147 static int setup_primary_wdigest(struct setup_password_fields_io *io,
1148 const struct supplementalCredentialsBlob *old_scb,
1149 struct package_PrimaryWDigestBlob *pdb)
1151 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1152 DATA_BLOB sAMAccountName;
1153 DATA_BLOB sAMAccountName_l;
1154 DATA_BLOB sAMAccountName_u;
1155 const char *user_principal_name = io->u.user_principal_name;
1156 DATA_BLOB userPrincipalName;
1157 DATA_BLOB userPrincipalName_l;
1158 DATA_BLOB userPrincipalName_u;
1159 DATA_BLOB netbios_domain;
1160 DATA_BLOB netbios_domain_l;
1161 DATA_BLOB netbios_domain_u;
1162 DATA_BLOB dns_domain;
1163 DATA_BLOB dns_domain_l;
1164 DATA_BLOB dns_domain_u;
1165 DATA_BLOB digest;
1166 DATA_BLOB delim;
1167 DATA_BLOB backslash;
1168 uint8_t i;
1169 struct {
1170 DATA_BLOB *user;
1171 DATA_BLOB *realm;
1172 DATA_BLOB *nt4dom;
1173 } wdigest[] = {
1175 * See 3.1.1.8.11.3.1 WDIGEST_CREDENTIALS Construction
1176 * https://msdn.microsoft.com/en-us/library/cc245680.aspx
1177 * for what precalculated hashes are supposed to be stored...
1179 * I can't reproduce all values which should contain "Digest" as realm,
1180 * am I doing something wrong or is w2k3 just broken...?
1182 * W2K3 fills in following for a user:
1184 * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1185 * sAMAccountName: NewUser2Sam
1186 * userPrincipalName: NewUser2Princ@sub1.w2k3.vmnet1.vm.base
1188 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1189 * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1190 * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1191 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1192 * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1193 * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1194 * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1195 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1196 * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1197 * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1198 * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1199 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1200 * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1201 * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1202 * 221c55284451ae9b3aacaa2a3c86f10f => NewUser2Princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1203 * 74e1be668853d4324d38c07e2acfb8ea => (w2k3 has a bug here!) newuser2princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1204 * e1e244ab7f098e3ae1761be7f9229bbb => NEWUSER2PRINC@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1205 * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1206 * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1207 * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1208 * 31dc704d3640335b2123d4ee28aa1f11 => ??? changes with NewUser2Sam => NewUser1Sam
1209 * 36349f5cecd07320fb3bb0e119230c43 => ??? changes with NewUser2Sam => NewUser1Sam
1210 * 12adf019d037fb535c01fd0608e78d9d => ??? changes with NewUser2Sam => NewUser1Sam
1211 * 6feecf8e724906f3ee1105819c5105a1 => ??? changes with NewUser2Princ => NewUser1Princ
1212 * 6c6911f3de6333422640221b9c51ff1f => ??? changes with NewUser2Princ => NewUser1Princ
1213 * 4b279877e742895f9348ac67a8de2f69 => ??? changes with NewUser2Princ => NewUser1Princ
1214 * db0c6bff069513e3ebb9870d29b57490 => ??? changes with NewUser2Sam => NewUser1Sam
1215 * 45072621e56b1c113a4e04a8ff68cd0e => ??? changes with NewUser2Sam => NewUser1Sam
1216 * 11d1220abc44a9c10cf91ef4a9c1de02 => ??? changes with NewUser2Sam => NewUser1Sam
1218 * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1219 * sAMAccountName: NewUser2Sam
1221 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1222 * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1223 * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1224 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1225 * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1226 * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1227 * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1228 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1229 * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1230 * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1231 * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1232 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1233 * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1234 * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1235 * 8a140d30b6f0a5912735dc1e3bc993b4 => NewUser2Sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1236 * 86d95b2faae6cae4ec261e7fbaccf093 => (here w2k3 is correct) newuser2sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1237 * dfeff1493110220efcdfc6362e5f5450 => NEWUSER2SAM@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1238 * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1239 * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1240 * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1241 * 31dc704d3640335b2123d4ee28aa1f11 => ???M1 changes with NewUser2Sam => NewUser1Sam
1242 * 36349f5cecd07320fb3bb0e119230c43 => ???M1.L changes with newuser2sam => newuser1sam
1243 * 12adf019d037fb535c01fd0608e78d9d => ???M1.U changes with NEWUSER2SAM => NEWUSER1SAM
1244 * 569b4533f2d9e580211dd040e5e360a8 => ???M2 changes with NewUser2Princ => NewUser1Princ
1245 * 52528bddf310a587c5d7e6a9ae2cbb20 => ???M2.L changes with newuser2princ => newuser1princ
1246 * 4f629a4f0361289ca4255ab0f658fcd5 => ???M3 changes with NewUser2Princ => NewUser1Princ (doesn't depend on case of userPrincipal )
1247 * db0c6bff069513e3ebb9870d29b57490 => ???M4 changes with NewUser2Sam => NewUser1Sam
1248 * 45072621e56b1c113a4e04a8ff68cd0e => ???M5 changes with NewUser2Sam => NewUser1Sam (doesn't depend on case of sAMAccountName)
1249 * 11d1220abc44a9c10cf91ef4a9c1de02 => ???M4.U changes with NEWUSER2SAM => NEWUSER1SAM
1253 * sAMAccountName, netbios_domain
1256 .user = &sAMAccountName,
1257 .realm = &netbios_domain,
1260 .user = &sAMAccountName_l,
1261 .realm = &netbios_domain_l,
1264 .user = &sAMAccountName_u,
1265 .realm = &netbios_domain_u,
1268 .user = &sAMAccountName,
1269 .realm = &netbios_domain_u,
1272 .user = &sAMAccountName,
1273 .realm = &netbios_domain_l,
1276 .user = &sAMAccountName_u,
1277 .realm = &netbios_domain_l,
1280 .user = &sAMAccountName_l,
1281 .realm = &netbios_domain_u,
1284 * sAMAccountName, dns_domain
1286 * TODO:
1287 * Windows preserves the case of the DNS domain,
1288 * Samba lower cases the domain at provision time
1289 * This means that for mixed case Domains, the WDigest08 hash
1290 * calculated by Samba differs from that calculated by Windows.
1291 * Until we get a real world use case this will remain a known
1292 * bug, as changing the case could have unforeseen impacts.
1296 .user = &sAMAccountName,
1297 .realm = &dns_domain,
1300 .user = &sAMAccountName_l,
1301 .realm = &dns_domain_l,
1304 .user = &sAMAccountName_u,
1305 .realm = &dns_domain_u,
1308 .user = &sAMAccountName,
1309 .realm = &dns_domain_u,
1312 .user = &sAMAccountName,
1313 .realm = &dns_domain_l,
1316 .user = &sAMAccountName_u,
1317 .realm = &dns_domain_l,
1320 .user = &sAMAccountName_l,
1321 .realm = &dns_domain_u,
1324 * userPrincipalName, no realm
1327 .user = &userPrincipalName,
1331 * NOTE: w2k3 messes this up, if the user has a real userPrincipalName,
1332 * the fallback to the sAMAccountName based userPrincipalName is correct
1334 .user = &userPrincipalName_l,
1337 .user = &userPrincipalName_u,
1340 * nt4dom\sAMAccountName, no realm
1343 .user = &sAMAccountName,
1344 .nt4dom = &netbios_domain
1347 .user = &sAMAccountName_l,
1348 .nt4dom = &netbios_domain_l
1351 .user = &sAMAccountName_u,
1352 .nt4dom = &netbios_domain_u
1356 * the following ones are guessed depending on the technet2 article
1357 * but not reproducible on a w2k3 server
1359 /* sAMAccountName with "Digest" realm */
1361 .user = &sAMAccountName,
1362 .realm = &digest
1365 .user = &sAMAccountName_l,
1366 .realm = &digest
1369 .user = &sAMAccountName_u,
1370 .realm = &digest
1372 /* userPrincipalName with "Digest" realm */
1374 .user = &userPrincipalName,
1375 .realm = &digest
1378 .user = &userPrincipalName_l,
1379 .realm = &digest
1382 .user = &userPrincipalName_u,
1383 .realm = &digest
1385 /* nt4dom\\sAMAccountName with "Digest" realm */
1387 .user = &sAMAccountName,
1388 .nt4dom = &netbios_domain,
1389 .realm = &digest
1392 .user = &sAMAccountName_l,
1393 .nt4dom = &netbios_domain_l,
1394 .realm = &digest
1397 .user = &sAMAccountName_u,
1398 .nt4dom = &netbios_domain_u,
1399 .realm = &digest
1402 int rc = LDB_ERR_OTHER;
1404 /* prepare DATA_BLOB's used in the combinations array */
1405 sAMAccountName = data_blob_string_const(io->u.sAMAccountName);
1406 sAMAccountName_l = data_blob_string_const(strlower_talloc(io->ac, io->u.sAMAccountName));
1407 if (!sAMAccountName_l.data) {
1408 return ldb_oom(ldb);
1410 sAMAccountName_u = data_blob_string_const(strupper_talloc(io->ac, io->u.sAMAccountName));
1411 if (!sAMAccountName_u.data) {
1412 return ldb_oom(ldb);
1415 /* if the user doesn't have a userPrincipalName, create one (with lower case realm) */
1416 if (!user_principal_name) {
1417 user_principal_name = talloc_asprintf(io->ac, "%s@%s",
1418 io->u.sAMAccountName,
1419 io->ac->status->domain_data.dns_domain);
1420 if (!user_principal_name) {
1421 return ldb_oom(ldb);
1424 userPrincipalName = data_blob_string_const(user_principal_name);
1425 userPrincipalName_l = data_blob_string_const(strlower_talloc(io->ac, user_principal_name));
1426 if (!userPrincipalName_l.data) {
1427 return ldb_oom(ldb);
1429 userPrincipalName_u = data_blob_string_const(strupper_talloc(io->ac, user_principal_name));
1430 if (!userPrincipalName_u.data) {
1431 return ldb_oom(ldb);
1434 netbios_domain = data_blob_string_const(io->ac->status->domain_data.netbios_domain);
1435 netbios_domain_l = data_blob_string_const(strlower_talloc(io->ac,
1436 io->ac->status->domain_data.netbios_domain));
1437 if (!netbios_domain_l.data) {
1438 return ldb_oom(ldb);
1440 netbios_domain_u = data_blob_string_const(strupper_talloc(io->ac,
1441 io->ac->status->domain_data.netbios_domain));
1442 if (!netbios_domain_u.data) {
1443 return ldb_oom(ldb);
1446 dns_domain = data_blob_string_const(io->ac->status->domain_data.dns_domain);
1447 dns_domain_l = data_blob_string_const(io->ac->status->domain_data.dns_domain);
1448 dns_domain_u = data_blob_string_const(io->ac->status->domain_data.realm);
1450 digest = data_blob_string_const("Digest");
1452 delim = data_blob_string_const(":");
1453 backslash = data_blob_string_const("\\");
1455 pdb->num_hashes = ARRAY_SIZE(wdigest);
1456 pdb->hashes = talloc_array(io->ac, struct package_PrimaryWDigestHash,
1457 pdb->num_hashes);
1458 if (!pdb->hashes) {
1459 return ldb_oom(ldb);
1462 for (i=0; i < ARRAY_SIZE(wdigest); i++) {
1463 gnutls_hash_hd_t hash_hnd = NULL;
1465 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
1466 if (rc < 0) {
1467 rc = ldb_oom(ldb);
1468 goto out;
1471 if (wdigest[i].nt4dom) {
1472 rc = gnutls_hash(hash_hnd,
1473 wdigest[i].nt4dom->data,
1474 wdigest[i].nt4dom->length);
1475 if (rc < 0) {
1476 gnutls_hash_deinit(hash_hnd, NULL);
1477 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1478 goto out;
1480 rc = gnutls_hash(hash_hnd,
1481 backslash.data,
1482 backslash.length);
1483 if (rc < 0) {
1484 gnutls_hash_deinit(hash_hnd, NULL);
1485 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1486 goto out;
1489 rc = gnutls_hash(hash_hnd,
1490 wdigest[i].user->data,
1491 wdigest[i].user->length);
1492 if (rc < 0) {
1493 gnutls_hash_deinit(hash_hnd, NULL);
1494 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1495 goto out;
1497 rc = gnutls_hash(hash_hnd, delim.data, delim.length);
1498 if (rc < 0) {
1499 gnutls_hash_deinit(hash_hnd, NULL);
1500 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1501 goto out;
1503 if (wdigest[i].realm) {
1504 rc = gnutls_hash(hash_hnd,
1505 wdigest[i].realm->data,
1506 wdigest[i].realm->length);
1507 if (rc < 0) {
1508 gnutls_hash_deinit(hash_hnd, NULL);
1509 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1510 goto out;
1513 rc = gnutls_hash(hash_hnd, delim.data, delim.length);
1514 if (rc < 0) {
1515 gnutls_hash_deinit(hash_hnd, NULL);
1516 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1517 goto out;
1519 rc = gnutls_hash(hash_hnd,
1520 io->n.cleartext_utf8->data,
1521 io->n.cleartext_utf8->length);
1522 if (rc < 0) {
1523 gnutls_hash_deinit(hash_hnd, NULL);
1524 rc = LDB_ERR_UNWILLING_TO_PERFORM;
1525 goto out;
1528 gnutls_hash_deinit(hash_hnd, pdb->hashes[i].hash);
1531 rc = LDB_SUCCESS;
1532 out:
1533 return rc;
1536 #define SHA_SALT_PERMITTED_CHARS "abcdefghijklmnopqrstuvwxyz" \
1537 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
1538 "0123456789./"
1539 #define SHA_SALT_SIZE 16
1540 #define SHA_256_SCHEME "CryptSHA256"
1541 #define SHA_512_SCHEME "CryptSHA512"
1542 #define CRYPT "{CRYPT}"
1543 #define SHA_ID_LEN 3
1544 #define SHA_256_ALGORITHM_ID 5
1545 #define SHA_512_ALGORITHM_ID 6
1546 #define ROUNDS_PARAMETER "rounds="
1549 * Extract the crypt (3) algorithm number and number of hash rounds from the
1550 * supplied scheme string
1552 static bool parse_scheme(const char *scheme, int *algorithm, int *rounds) {
1554 const char *rp = NULL; /* Pointer to the 'rounds=' option */
1555 char digits[21]; /* digits extracted from the rounds option */
1556 int i = 0; /* loop index variable */
1558 if (strncasecmp(SHA_256_SCHEME, scheme, strlen(SHA_256_SCHEME)) == 0) {
1559 *algorithm = SHA_256_ALGORITHM_ID;
1560 } else if (strncasecmp(SHA_512_SCHEME, scheme, strlen(SHA_256_SCHEME))
1561 == 0) {
1562 *algorithm = SHA_512_ALGORITHM_ID;
1563 } else {
1564 return false;
1567 rp = strcasestr(scheme, ROUNDS_PARAMETER);
1568 if (rp == NULL) {
1569 /* No options specified, use crypt default number of rounds */
1570 *rounds = 0;
1571 return true;
1573 rp += strlen(ROUNDS_PARAMETER);
1574 for (i = 0; isdigit(rp[i]) && i < (sizeof(digits) - 1); i++) {
1575 digits[i] = rp[i];
1577 digits[i] = '\0';
1578 *rounds = atoi(digits);
1579 return true;
1583 * Calculate the password hash specified by scheme, and return it in
1584 * hash_value
1586 static int setup_primary_userPassword_hash(
1587 TALLOC_CTX *ctx,
1588 struct setup_password_fields_io *io,
1589 const char* scheme,
1590 struct package_PrimaryUserPasswordValue *hash_value)
1592 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1593 const char *salt = NULL; /* Randomly generated salt */
1594 const char *cmd = NULL; /* command passed to crypt */
1595 const char *hash = NULL; /* password hash generated by crypt */
1596 int algorithm = 0; /* crypt hash algorithm number */
1597 int rounds = 0; /* The number of hash rounds */
1598 DATA_BLOB *hash_blob = NULL;
1599 TALLOC_CTX *frame = talloc_stackframe();
1600 #if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT_RN)
1601 struct crypt_data crypt_data = {
1602 .initialized = 0 /* working storage used by crypt */
1604 #endif
1606 /* Generate a random password salt */
1607 salt = generate_random_str_list(frame,
1608 SHA_SALT_SIZE,
1609 SHA_SALT_PERMITTED_CHARS);
1610 if (salt == NULL) {
1611 TALLOC_FREE(frame);
1612 return ldb_oom(ldb);
1615 /* determine the hashing algorithm and number of rounds*/
1616 if (!parse_scheme(scheme, &algorithm, &rounds)) {
1617 ldb_asprintf_errstring(
1618 ldb,
1619 "setup_primary_userPassword: Invalid scheme of [%s] "
1620 "specified for 'password hash userPassword schemes' in "
1621 "samba.conf",
1622 scheme);
1623 TALLOC_FREE(frame);
1624 return LDB_ERR_OPERATIONS_ERROR;
1626 hash_value->scheme = talloc_strdup(ctx, CRYPT);
1627 if (hash_value->scheme == NULL) {
1628 TALLOC_FREE(frame);
1629 return ldb_oom(ldb);
1631 hash_value->scheme_len = strlen(CRYPT) + 1;
1633 /* generate the id/salt parameter used by crypt */
1634 if (rounds) {
1635 cmd = talloc_asprintf(frame,
1636 "$%d$rounds=%d$%s",
1637 algorithm,
1638 rounds,
1639 salt);
1640 if (cmd == NULL) {
1641 TALLOC_FREE(frame);
1642 return ldb_oom(ldb);
1644 } else {
1645 cmd = talloc_asprintf(frame, "$%d$%s", algorithm, salt);
1646 if (cmd == NULL) {
1647 TALLOC_FREE(frame);
1648 return ldb_oom(ldb);
1653 * Relies on the assertion that cleartext_utf8->data is a zero
1654 * terminated UTF-8 string
1658 * crypt_r() and crypt() may return a null pointer upon error
1659 * depending on how libcrypt was configured, so we prefer
1660 * crypt_rn() from libcrypt / libxcrypt which always returns
1661 * NULL on error.
1663 * POSIX specifies returning a null pointer and setting
1664 * errno.
1666 * RHEL 7 (which does not use libcrypt / libxcrypt) returns a
1667 * non-NULL pointer from crypt_r() on success but (always?)
1668 * sets errno during internal processing in the NSS crypto
1669 * subsystem.
1671 * By preferring crypt_rn we avoid the 'return non-NULL but
1672 * set-errno' that we otherwise cannot tell apart from the
1673 * RHEL 7 behaviour.
1675 errno = 0;
1677 #ifdef HAVE_CRYPT_RN
1678 hash = crypt_rn((char *)io->n.cleartext_utf8->data,
1679 cmd,
1680 &crypt_data,
1681 sizeof(crypt_data));
1682 #elif HAVE_CRYPT_R
1683 hash = crypt_r((char *)io->n.cleartext_utf8->data, cmd, &crypt_data);
1684 #else
1686 * No crypt_r falling back to crypt, which is NOT thread safe
1687 * Thread safety MT-Unsafe race:crypt
1689 hash = crypt((char *)io->n.cleartext_utf8->data, cmd);
1690 #endif
1692 * On error, crypt() and crypt_r() may return a null pointer,
1693 * or a pointer to an invalid hash beginning with a '*'.
1695 if (hash == NULL || hash[0] == '*') {
1696 char buf[1024];
1697 const char *reason = NULL;
1698 if (errno == ERANGE) {
1699 reason = "Password exceeds maximum length allowed for crypt() hashing";
1700 } else {
1701 int err = strerror_r(errno, buf, sizeof(buf));
1702 if (err == 0) {
1703 reason = buf;
1704 } else {
1705 reason = "Unknown error";
1708 ldb_asprintf_errstring(
1709 ldb,
1710 "setup_primary_userPassword: generation of a %s "
1711 "password hash failed: (%s)",
1712 scheme,
1713 reason);
1714 TALLOC_FREE(frame);
1715 return LDB_ERR_OPERATIONS_ERROR;
1718 hash_blob = talloc_zero(ctx, DATA_BLOB);
1720 if (hash_blob == NULL) {
1721 TALLOC_FREE(frame);
1722 return ldb_oom(ldb);
1725 *hash_blob = data_blob_talloc(hash_blob,
1726 (const uint8_t *)hash,
1727 strlen(hash));
1728 if (hash_blob->data == NULL) {
1729 TALLOC_FREE(frame);
1730 return ldb_oom(ldb);
1732 hash_value->value = hash_blob;
1733 TALLOC_FREE(frame);
1734 return LDB_SUCCESS;
1738 * Calculate the desired extra password hashes
1740 static int setup_primary_userPassword(
1741 struct setup_password_fields_io *io,
1742 const struct supplementalCredentialsBlob *old_scb,
1743 struct package_PrimaryUserPasswordBlob *p_userPassword_b)
1745 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1746 TALLOC_CTX *frame = talloc_stackframe();
1747 int i;
1748 int ret;
1751 * Save the current nt_hash, use this to determine if the password
1752 * has been changed by windows. Which will invalidate the userPassword
1753 * hash. Note once NTLM-Strong-NOWTF becomes available it should be
1754 * used in preference to the NT password hash
1756 if (io->g.nt_hash == NULL) {
1758 * When the NT hash is not available, we use this field to store
1759 * the first 16 bytes of the AES256 key instead. This allows
1760 * 'samba-tool user' to verify that the user's password is in
1761 * sync with the userPassword package.
1763 uint8_t hash_len = MIN(16, io->g.aes_256.length);
1765 ZERO_STRUCT(p_userPassword_b->current_nt_hash);
1766 memcpy(p_userPassword_b->current_nt_hash.hash,
1767 io->g.aes_256.data,
1768 hash_len);
1769 } else {
1770 p_userPassword_b->current_nt_hash = *io->g.nt_hash;
1774 * Determine the number of hashes
1775 * Note: that currently there is no limit on the number of hashes
1776 * no checking is done on the number of schemes specified
1777 * or for uniqueness.
1779 p_userPassword_b->num_hashes = 0;
1780 for (i = 0; io->ac->userPassword_schemes[i]; i++) {
1781 p_userPassword_b->num_hashes++;
1784 p_userPassword_b->hashes
1785 = talloc_array(io->ac,
1786 struct package_PrimaryUserPasswordValue,
1787 p_userPassword_b->num_hashes);
1788 if (p_userPassword_b->hashes == NULL) {
1789 TALLOC_FREE(frame);
1790 return ldb_oom(ldb);
1793 for (i = 0; io->ac->userPassword_schemes[i]; i++) {
1794 ret = setup_primary_userPassword_hash(
1795 p_userPassword_b->hashes,
1797 io->ac->userPassword_schemes[i],
1798 &p_userPassword_b->hashes[i]);
1799 if (ret != LDB_SUCCESS) {
1800 TALLOC_FREE(frame);
1801 return ret;
1804 TALLOC_FREE(frame);
1805 return LDB_SUCCESS;
1809 static int setup_primary_samba_gpg(struct setup_password_fields_io *io,
1810 struct package_PrimarySambaGPGBlob *pgb)
1812 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1813 #ifdef ENABLE_GPGME
1814 gpgme_error_t gret;
1815 gpgme_ctx_t ctx = NULL;
1816 size_t num_keys = str_list_length(io->ac->gpg_key_ids);
1817 gpgme_key_t keys[num_keys+1];
1818 size_t ki = 0;
1819 size_t kr = 0;
1820 gpgme_data_t plain_data = NULL;
1821 gpgme_data_t crypt_data = NULL;
1822 size_t crypt_length = 0;
1823 char *crypt_mem = NULL;
1825 gret = gpgme_new(&ctx);
1826 if (gret != GPG_ERR_NO_ERROR) {
1827 ldb_debug(ldb, LDB_DEBUG_ERROR,
1828 "%s:%s: gret[%u] %s\n",
1829 __location__, __func__,
1830 gret, gpgme_strerror(gret));
1831 return ldb_module_operr(io->ac->module);
1834 gpgme_set_armor(ctx, 1);
1836 gret = gpgme_data_new_from_mem(&plain_data,
1837 (const char *)io->n.cleartext_utf16->data,
1838 io->n.cleartext_utf16->length,
1839 0 /* no copy */);
1840 if (gret != GPG_ERR_NO_ERROR) {
1841 ldb_debug(ldb, LDB_DEBUG_ERROR,
1842 "%s:%s: gret[%u] %s\n",
1843 __location__, __func__,
1844 gret, gpgme_strerror(gret));
1845 gpgme_release(ctx);
1846 return ldb_module_operr(io->ac->module);
1848 gret = gpgme_data_new(&crypt_data);
1849 if (gret != GPG_ERR_NO_ERROR) {
1850 ldb_debug(ldb, LDB_DEBUG_ERROR,
1851 "%s:%s: gret[%u] %s\n",
1852 __location__, __func__,
1853 gret, gpgme_strerror(gret));
1854 gpgme_data_release(plain_data);
1855 gpgme_release(ctx);
1856 return ldb_module_operr(io->ac->module);
1859 for (ki = 0; ki < num_keys; ki++) {
1860 const char *key_id = io->ac->gpg_key_ids[ki];
1861 size_t len = strlen(key_id);
1863 keys[ki] = NULL;
1865 if (len < 16) {
1866 ldb_debug(ldb, LDB_DEBUG_FATAL,
1867 "%s:%s: ki[%zu] key_id[%s] strlen < 16, "
1868 "please specify at least the 64bit key id\n",
1869 __location__, __func__,
1870 ki, key_id);
1871 for (kr = 0; keys[kr] != NULL; kr++) {
1872 gpgme_key_release(keys[kr]);
1874 gpgme_data_release(crypt_data);
1875 gpgme_data_release(plain_data);
1876 gpgme_release(ctx);
1877 return ldb_module_operr(io->ac->module);
1880 gret = gpgme_get_key(ctx, key_id, &keys[ki], 0 /* public key */);
1881 if (gret != GPG_ERR_NO_ERROR) {
1882 keys[ki] = NULL;
1883 if (gpg_err_source(gret) == GPG_ERR_SOURCE_GPGME
1884 && gpg_err_code(gret) == GPG_ERR_EOF) {
1885 ldb_debug(ldb, LDB_DEBUG_ERROR,
1886 "Invalid "
1887 "'password hash gpg key ids': "
1888 "Public Key ID [%s] "
1889 "not found in keyring\n",
1890 key_id);
1892 } else {
1893 ldb_debug(ldb, LDB_DEBUG_ERROR,
1894 "%s:%s: ki[%zu] key_id[%s] "
1895 "gret[%u] %s\n",
1896 __location__, __func__,
1897 ki, key_id,
1898 gret, gpgme_strerror(gret));
1900 for (kr = 0; keys[kr] != NULL; kr++) {
1901 gpgme_key_release(keys[kr]);
1903 gpgme_data_release(crypt_data);
1904 gpgme_data_release(plain_data);
1905 gpgme_release(ctx);
1906 return ldb_module_operr(io->ac->module);
1909 keys[ki] = NULL;
1911 gret = gpgme_op_encrypt(ctx, keys,
1912 GPGME_ENCRYPT_ALWAYS_TRUST,
1913 plain_data, crypt_data);
1914 gpgme_data_release(plain_data);
1915 plain_data = NULL;
1916 for (kr = 0; keys[kr] != NULL; kr++) {
1917 gpgme_key_release(keys[kr]);
1918 keys[kr] = NULL;
1920 gpgme_release(ctx);
1921 ctx = NULL;
1922 if (gret != GPG_ERR_NO_ERROR) {
1923 ldb_debug(ldb, LDB_DEBUG_ERROR,
1924 "%s:%s: gret[%u] %s\n",
1925 __location__, __func__,
1926 gret, gpgme_strerror(gret));
1927 gpgme_data_release(crypt_data);
1928 return ldb_module_operr(io->ac->module);
1931 crypt_mem = gpgme_data_release_and_get_mem(crypt_data, &crypt_length);
1932 crypt_data = NULL;
1933 if (crypt_mem == NULL) {
1934 return ldb_module_oom(io->ac->module);
1937 pgb->gpg_blob = data_blob_talloc(io->ac,
1938 (const uint8_t *)crypt_mem,
1939 crypt_length);
1940 gpgme_free(crypt_mem);
1941 crypt_mem = NULL;
1942 crypt_length = 0;
1943 if (pgb->gpg_blob.data == NULL) {
1944 return ldb_module_oom(io->ac->module);
1947 return LDB_SUCCESS;
1948 #else /* ENABLE_GPGME */
1949 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1950 "You configured 'password hash gpg key ids', "
1951 "but GPGME support is missing. (%s:%d)",
1952 __FILE__, __LINE__);
1953 return LDB_ERR_UNWILLING_TO_PERFORM;
1954 #endif /* else ENABLE_GPGME */
1957 #define NUM_PACKAGES 6
1958 static int setup_supplemental_field(struct setup_password_fields_io *io)
1960 struct ldb_context *ldb;
1961 struct supplementalCredentialsBlob scb = {};
1962 struct supplementalCredentialsBlob *old_scb = NULL;
1964 * Packages +
1965 * ( Kerberos-Newer-Keys, Kerberos,
1966 * WDigest, CLEARTEXT, userPassword, SambaGPG)
1968 uint32_t num_names = 0;
1969 const char *names[1+NUM_PACKAGES] = {};
1970 uint32_t num_packages = 0;
1971 struct supplementalCredentialsPackage packages[1+NUM_PACKAGES] = {};
1972 struct supplementalCredentialsPackage *pp = packages;
1973 int ret;
1974 enum ndr_err_code ndr_err;
1975 bool do_newer_keys = false;
1976 bool do_cleartext = false;
1977 bool do_samba_gpg = false;
1978 struct loadparm_context *lp_ctx = NULL;
1980 ldb = ldb_module_get_ctx(io->ac->module);
1981 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
1982 struct loadparm_context);
1984 if (!io->n.cleartext_utf8) {
1986 * when we don't have a cleartext password
1987 * we can't setup a supplementalCredentials value
1989 return LDB_SUCCESS;
1992 /* if there's an old supplementalCredentials blob then use it */
1993 if (io->o.supplemental) {
1994 if (io->o.scb.sub.signature == SUPPLEMENTAL_CREDENTIALS_SIGNATURE) {
1995 old_scb = &io->o.scb;
1996 } else {
1997 ldb_debug(ldb, LDB_DEBUG_ERROR,
1998 "setup_supplemental_field: "
1999 "supplementalCredentialsBlob "
2000 "signature[0x%04X] expected[0x%04X]",
2001 io->o.scb.sub.signature,
2002 SUPPLEMENTAL_CREDENTIALS_SIGNATURE);
2005 /* Per MS-SAMR 3.1.1.8.11.6 we create AES keys if our domain functionality level is 2008 or higher */
2010 * The ordering is this
2012 * Primary:Kerberos-Newer-Keys (optional)
2013 * Primary:Kerberos
2014 * Primary:WDigest
2015 * Primary:CLEARTEXT (optional)
2016 * Primary:userPassword
2017 * Primary:SambaGPG (optional)
2019 * And the 'Packages' package is insert before the last
2020 * other package.
2022 * Note: it's important that Primary:SambaGPG is added as
2023 * the last element. This is the indication that it matches
2024 * the current password. When a password change happens on
2025 * a Windows DC, it will keep the old Primary:SambaGPG value,
2026 * but as the first element.
2028 do_newer_keys = (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2008);
2029 if (do_newer_keys) {
2030 struct package_PrimaryKerberosBlob pknb;
2031 DATA_BLOB pknb_blob;
2032 char *pknb_hexstr;
2034 * setup 'Primary:Kerberos-Newer-Keys' element
2036 names[num_names++] = "Kerberos-Newer-Keys";
2038 ret = setup_primary_kerberos_newer(io, old_scb, &pknb);
2039 if (ret != LDB_SUCCESS) {
2040 return ret;
2043 ndr_err = ndr_push_struct_blob(
2044 &pknb_blob, io->ac,
2045 &pknb,
2046 (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
2047 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2048 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2049 ldb_asprintf_errstring(
2050 ldb,
2051 "setup_supplemental_field: "
2052 "failed to push "
2053 "package_PrimaryKerberosNeverBlob: %s",
2054 nt_errstr(status));
2055 return LDB_ERR_OPERATIONS_ERROR;
2057 pknb_hexstr = data_blob_hex_string_upper(io->ac, &pknb_blob);
2058 if (!pknb_hexstr) {
2059 return ldb_oom(ldb);
2061 pp->name = "Primary:Kerberos-Newer-Keys";
2062 pp->reserved = 1;
2063 pp->data = pknb_hexstr;
2064 pp++;
2065 num_packages++;
2070 * setup 'Primary:Kerberos' element
2072 /* Primary:Kerberos */
2073 struct package_PrimaryKerberosBlob pkb;
2074 DATA_BLOB pkb_blob;
2075 char *pkb_hexstr;
2077 names[num_names++] = "Kerberos";
2079 ret = setup_primary_kerberos(io, old_scb, &pkb);
2080 if (ret != LDB_SUCCESS) {
2081 return ret;
2084 ndr_err = ndr_push_struct_blob(
2085 &pkb_blob, io->ac,
2086 &pkb,
2087 (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
2088 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2089 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2090 ldb_asprintf_errstring(
2091 ldb,
2092 "setup_supplemental_field: "
2093 "failed to push package_PrimaryKerberosBlob: %s",
2094 nt_errstr(status));
2095 return LDB_ERR_OPERATIONS_ERROR;
2097 pkb_hexstr = data_blob_hex_string_upper(io->ac, &pkb_blob);
2098 if (!pkb_hexstr) {
2099 return ldb_oom(ldb);
2101 pp->name = "Primary:Kerberos";
2102 pp->reserved = 1;
2103 pp->data = pkb_hexstr;
2104 pp++;
2105 num_packages++;
2108 if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_ALLOWED) {
2110 * setup 'Primary:WDigest' element
2112 struct package_PrimaryWDigestBlob pdb;
2113 DATA_BLOB pdb_blob;
2114 char *pdb_hexstr;
2116 names[num_names++] = "WDigest";
2118 ret = setup_primary_wdigest(io, old_scb, &pdb);
2119 if (ret != LDB_SUCCESS) {
2120 return ret;
2123 ndr_err = ndr_push_struct_blob(
2124 &pdb_blob, io->ac,
2125 &pdb,
2126 (ndr_push_flags_fn_t)ndr_push_package_PrimaryWDigestBlob);
2127 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2128 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2129 ldb_asprintf_errstring(
2130 ldb,
2131 "setup_supplemental_field: "
2132 "failed to push package_PrimaryWDigestBlob: %s",
2133 nt_errstr(status));
2134 return LDB_ERR_OPERATIONS_ERROR;
2136 pdb_hexstr = data_blob_hex_string_upper(io->ac, &pdb_blob);
2137 if (!pdb_hexstr) {
2138 return ldb_oom(ldb);
2140 pp->name = "Primary:WDigest";
2141 pp->reserved = 1;
2142 pp->data = pdb_hexstr;
2143 pp++;
2144 num_packages++;
2148 * setup 'Primary:CLEARTEXT' element
2150 if (io->ac->status->domain_data.store_cleartext &&
2151 (io->u.userAccountControl & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) {
2152 do_cleartext = true;
2154 if (do_cleartext) {
2155 struct package_PrimaryCLEARTEXTBlob pcb;
2156 DATA_BLOB pcb_blob;
2157 char *pcb_hexstr;
2159 names[num_names++] = "CLEARTEXT";
2161 pcb.cleartext = *io->n.cleartext_utf16;
2163 ndr_err = ndr_push_struct_blob(
2164 &pcb_blob, io->ac,
2165 &pcb,
2166 (ndr_push_flags_fn_t)ndr_push_package_PrimaryCLEARTEXTBlob);
2167 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2168 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2169 ldb_asprintf_errstring(
2170 ldb,
2171 "setup_supplemental_field: "
2172 "failed to push package_PrimaryCLEARTEXTBlob: %s",
2173 nt_errstr(status));
2174 return LDB_ERR_OPERATIONS_ERROR;
2176 pcb_hexstr = data_blob_hex_string_upper(io->ac, &pcb_blob);
2177 if (!pcb_hexstr) {
2178 return ldb_oom(ldb);
2180 pp->name = "Primary:CLEARTEXT";
2181 pp->reserved = 1;
2182 pp->data = pcb_hexstr;
2183 pp++;
2184 num_packages++;
2188 * Don't generate crypt() or similar password for the krbtgt account.
2189 * It's unnecessary, and the length of the cleartext in UTF-8 form
2190 * exceeds the maximum (CRYPT_MAX_PASSPHRASE_SIZE) allowed by crypt().
2192 if (io->ac->userPassword_schemes && !io->u.is_krbtgt) {
2194 * setup 'Primary:userPassword' element
2196 struct package_PrimaryUserPasswordBlob
2197 p_userPassword_b;
2198 DATA_BLOB p_userPassword_b_blob;
2199 char *p_userPassword_b_hexstr;
2201 names[num_names++] = "userPassword";
2203 ret = setup_primary_userPassword(io,
2204 old_scb,
2205 &p_userPassword_b);
2206 if (ret != LDB_SUCCESS) {
2207 return ret;
2210 ndr_err = ndr_push_struct_blob(
2211 &p_userPassword_b_blob,
2212 io->ac,
2213 &p_userPassword_b,
2214 (ndr_push_flags_fn_t)
2215 ndr_push_package_PrimaryUserPasswordBlob);
2216 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2217 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2218 ldb_asprintf_errstring(
2219 ldb,
2220 "setup_supplemental_field: failed to push "
2221 "package_PrimaryUserPasswordBlob: %s",
2222 nt_errstr(status));
2223 return LDB_ERR_OPERATIONS_ERROR;
2225 p_userPassword_b_hexstr
2226 = data_blob_hex_string_upper(
2227 io->ac,
2228 &p_userPassword_b_blob);
2229 if (!p_userPassword_b_hexstr) {
2230 return ldb_oom(ldb);
2232 pp->name = "Primary:userPassword";
2233 pp->reserved = 1;
2234 pp->data = p_userPassword_b_hexstr;
2235 pp++;
2236 num_packages++;
2240 * setup 'Primary:SambaGPG' element
2242 if (io->ac->gpg_key_ids != NULL) {
2243 do_samba_gpg = true;
2245 if (do_samba_gpg) {
2246 struct package_PrimarySambaGPGBlob pgb;
2247 DATA_BLOB pgb_blob;
2248 char *pgb_hexstr;
2250 names[num_names++] = "SambaGPG";
2252 ret = setup_primary_samba_gpg(io, &pgb);
2253 if (ret != LDB_SUCCESS) {
2254 return ret;
2257 ndr_err = ndr_push_struct_blob(&pgb_blob, io->ac, &pgb,
2258 (ndr_push_flags_fn_t)ndr_push_package_PrimarySambaGPGBlob);
2259 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2260 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2261 ldb_asprintf_errstring(ldb,
2262 "setup_supplemental_field: failed to "
2263 "push package_PrimarySambaGPGBlob: %s",
2264 nt_errstr(status));
2265 return LDB_ERR_OPERATIONS_ERROR;
2267 pgb_hexstr = data_blob_hex_string_upper(io->ac, &pgb_blob);
2268 if (!pgb_hexstr) {
2269 return ldb_oom(ldb);
2271 pp->name = "Primary:SambaGPG";
2272 pp->reserved = 1;
2273 pp->data = pgb_hexstr;
2274 pp++;
2275 num_packages++;
2279 * setup 'Packages' element
2282 struct package_PackagesBlob pb;
2283 DATA_BLOB pb_blob;
2284 char *pb_hexstr;
2286 pb.names = names;
2287 ndr_err = ndr_push_struct_blob(
2288 &pb_blob, io->ac,
2289 &pb,
2290 (ndr_push_flags_fn_t)ndr_push_package_PackagesBlob);
2291 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2292 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2293 ldb_asprintf_errstring(
2294 ldb,
2295 "setup_supplemental_field: "
2296 "failed to push package_PackagesBlob: %s",
2297 nt_errstr(status));
2298 return LDB_ERR_OPERATIONS_ERROR;
2300 pb_hexstr = data_blob_hex_string_upper(io->ac, &pb_blob);
2301 if (!pb_hexstr) {
2302 return ldb_oom(ldb);
2304 pp->name = "Packages";
2305 pp->reserved = 2;
2306 pp->data = pb_hexstr;
2307 num_packages++;
2309 * We don't increment pp so it's pointing to the last package
2314 * setup 'supplementalCredentials' value
2318 * The 'Packages' element needs to be the second last element
2319 * in supplementalCredentials
2321 struct supplementalCredentialsPackage temp;
2322 struct supplementalCredentialsPackage *prev;
2324 prev = pp-1;
2325 temp = *prev;
2326 *prev = *pp;
2327 *pp = temp;
2329 scb.sub.signature = SUPPLEMENTAL_CREDENTIALS_SIGNATURE;
2330 scb.sub.num_packages = num_packages;
2331 scb.sub.packages = packages;
2333 ndr_err = ndr_push_struct_blob(
2334 &io->g.supplemental, io->ac,
2335 &scb,
2336 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
2337 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2338 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2339 ldb_asprintf_errstring(
2340 ldb,
2341 "setup_supplemental_field: "
2342 "failed to push supplementalCredentialsBlob: %s",
2343 nt_errstr(status));
2344 return LDB_ERR_OPERATIONS_ERROR;
2348 return LDB_SUCCESS;
2351 static int setup_last_set_field(struct setup_password_fields_io *io)
2353 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2354 const struct ldb_message *msg = NULL;
2355 const struct ldb_val *old_val = NULL;
2356 const struct ldb_val *new_val = NULL;
2357 int ret;
2358 bool ok;
2360 switch (io->ac->req->operation) {
2361 case LDB_ADD:
2362 msg = io->ac->req->op.add.message;
2363 break;
2364 case LDB_MODIFY:
2365 msg = io->ac->req->op.mod.message;
2366 break;
2367 default:
2368 return LDB_ERR_OPERATIONS_ERROR;
2369 break;
2372 if (io->ac->pwd_last_set_bypass) {
2373 struct ldb_message_element *el = NULL;
2374 size_t i;
2375 size_t count = 0;
2377 * This is a message from pdb_samba_dsdb_replace_by_sam()
2379 * We want to ensure there is only one pwdLastSet element, and
2380 * it isn't deleting.
2382 if (msg == NULL) {
2383 return LDB_ERR_CONSTRAINT_VIOLATION;
2386 for (i = 0; i < msg->num_elements; i++) {
2387 if (ldb_attr_cmp(msg->elements[i].name,
2388 "pwdLastSet") == 0) {
2389 count++;
2390 el = &msg->elements[i];
2393 if (count != 1) {
2394 return LDB_ERR_CONSTRAINT_VIOLATION;
2397 if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
2398 return LDB_ERR_CONSTRAINT_VIOLATION;
2401 io->g.last_set = samdb_result_nttime(msg, "pwdLastSet", 0);
2402 return LDB_SUCCESS;
2405 ret = msg_find_old_and_new_pwd_val(msg, "pwdLastSet",
2406 io->ac->req->operation,
2407 &new_val, &old_val);
2408 if (ret != LDB_SUCCESS) {
2409 return ret;
2412 if (old_val != NULL && new_val == NULL) {
2413 ldb_set_errstring(ldb,
2414 "'pwdLastSet' deletion is not allowed!");
2415 return LDB_ERR_UNWILLING_TO_PERFORM;
2418 io->g.last_set = UINT64_MAX;
2419 if (new_val != NULL) {
2420 struct ldb_message *tmp_msg = NULL;
2422 tmp_msg = ldb_msg_new(io->ac);
2423 if (tmp_msg == NULL) {
2424 return ldb_module_oom(io->ac->module);
2427 if (old_val != NULL) {
2428 NTTIME old_last_set = 0;
2430 ret = ldb_msg_add_value(tmp_msg, "oldval",
2431 old_val, NULL);
2432 if (ret != LDB_SUCCESS) {
2433 return ret;
2436 old_last_set = samdb_result_nttime(tmp_msg,
2437 "oldval",
2439 if (io->u.pwdLastSet != old_last_set) {
2440 return dsdb_module_werror(io->ac->module,
2441 LDB_ERR_NO_SUCH_ATTRIBUTE,
2442 WERR_DS_CANT_REM_MISSING_ATT_VAL,
2443 "setup_last_set_field: old pwdLastSet "
2444 "value not found!");
2448 ret = ldb_msg_add_value(tmp_msg, "newval",
2449 new_val, NULL);
2450 if (ret != LDB_SUCCESS) {
2451 return ret;
2454 io->g.last_set = samdb_result_nttime(tmp_msg,
2455 "newval",
2457 } else if (ldb_msg_find_element(msg, "pwdLastSet")) {
2458 ldb_set_errstring(ldb,
2459 "'pwdLastSet' deletion is not allowed!");
2460 return LDB_ERR_UNWILLING_TO_PERFORM;
2461 } else if (io->ac->smartcard_reset) {
2463 * adding UF_SMARTCARD_REQUIRED doesn't update
2464 * pwdLastSet implicitly.
2466 io->ac->update_lastset = false;
2469 /* only 0 or -1 (0xFFFFFFFFFFFFFFFF) are allowed */
2470 switch (io->g.last_set) {
2471 case 0:
2472 if (!io->ac->pwd_last_set_default) {
2473 break;
2475 if (!io->ac->update_password) {
2476 break;
2478 FALL_THROUGH;
2479 case UINT64_MAX:
2480 if (!io->ac->update_password &&
2481 io->u.pwdLastSet != 0 &&
2482 io->u.pwdLastSet != UINT64_MAX)
2485 * Just setting pwdLastSet to -1, while not changing
2486 * any password field has no effect if pwdLastSet
2487 * is already non-zero.
2489 io->ac->update_lastset = false;
2490 break;
2492 /* -1 means set it as now */
2493 ok = dsdb_gmsa_current_time(ldb, &io->g.last_set);
2494 if (!ok) {
2495 return LDB_ERR_OPERATIONS_ERROR;
2497 break;
2498 default:
2499 return dsdb_module_werror(io->ac->module,
2500 LDB_ERR_OTHER,
2501 WERR_INVALID_PARAMETER,
2502 "setup_last_set_field: "
2503 "pwdLastSet must be 0 or -1 only!");
2506 if (io->ac->req->operation == LDB_ADD) {
2508 * We always need to store the value on add
2509 * operations.
2511 return LDB_SUCCESS;
2514 if (io->g.last_set == io->u.pwdLastSet) {
2516 * Just setting pwdLastSet to 0, is no-op if it's already 0.
2518 io->ac->update_lastset = false;
2521 return LDB_SUCCESS;
2524 static int setup_given_passwords(struct setup_password_fields_io *io,
2525 struct setup_password_fields_given *g)
2527 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2529 if (g->cleartext_utf8) {
2530 struct ldb_val *cleartext_utf16_blob;
2532 cleartext_utf16_blob = talloc(io->ac, struct ldb_val);
2533 if (!cleartext_utf16_blob) {
2534 return ldb_oom(ldb);
2536 if (!convert_string_talloc(io->ac,
2537 CH_UTF8, CH_UTF16,
2538 g->cleartext_utf8->data,
2539 g->cleartext_utf8->length,
2540 &cleartext_utf16_blob->data,
2541 &cleartext_utf16_blob->length)) {
2542 if (g->cleartext_utf8->length != 0) {
2543 talloc_free(cleartext_utf16_blob);
2544 ldb_asprintf_errstring(ldb,
2545 "setup_password_fields: "
2546 "failed to generate UTF16 password from cleartext UTF8 one for user '%s'!",
2547 io->u.sAMAccountName);
2548 return LDB_ERR_CONSTRAINT_VIOLATION;
2549 } else {
2550 /* passwords with length "0" are valid! */
2551 cleartext_utf16_blob->data = NULL;
2552 cleartext_utf16_blob->length = 0;
2555 g->cleartext_utf16 = cleartext_utf16_blob;
2556 } else if (g->cleartext_utf16) {
2557 struct ldb_val *cleartext_utf8_blob;
2559 cleartext_utf8_blob = talloc(io->ac, struct ldb_val);
2560 if (!cleartext_utf8_blob) {
2561 return ldb_oom(ldb);
2563 if (!convert_string_talloc(io->ac,
2564 CH_UTF16MUNGED, CH_UTF8,
2565 g->cleartext_utf16->data,
2566 g->cleartext_utf16->length,
2567 &cleartext_utf8_blob->data,
2568 &cleartext_utf8_blob->length)) {
2569 if (g->cleartext_utf16->length != 0) {
2570 /* We must bail out here, the input wasn't even
2571 * a multiple of 2 bytes */
2572 talloc_free(cleartext_utf8_blob);
2573 ldb_asprintf_errstring(ldb,
2574 "setup_password_fields: "
2575 "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)!",
2576 io->u.sAMAccountName);
2577 return LDB_ERR_CONSTRAINT_VIOLATION;
2578 } else {
2579 /* passwords with length "0" are valid! */
2580 cleartext_utf8_blob->data = NULL;
2581 cleartext_utf8_blob->length = 0;
2584 g->cleartext_utf8 = cleartext_utf8_blob;
2587 if (g->cleartext_utf16) {
2588 struct samr_Password *nt_hash;
2590 nt_hash = talloc(io->ac, struct samr_Password);
2591 if (!nt_hash) {
2592 return ldb_oom(ldb);
2594 g->nt_hash = nt_hash;
2596 /* compute the new nt hash */
2597 mdfour(nt_hash->hash,
2598 g->cleartext_utf16->data,
2599 g->cleartext_utf16->length);
2603 * We need to build one more hash, so we can compare with what might
2604 * have been stored in the old password (for the LDAP password change)
2606 * We don't have any old salts, so we won't catch password reuse if said
2607 * password was used prior to an account rename and another password
2608 * change.
2610 * We don't have to store the 'opaque' (string2key iterations)
2611 * as Heimdal doesn't allow that to be changed.
2613 if (g->cleartext_utf8 != NULL) {
2614 int ret = setup_kerberos_key_hash(io, g);
2615 if (ret != LDB_SUCCESS) {
2616 return ret;
2620 return LDB_SUCCESS;
2623 static int setup_password_fields(struct setup_password_fields_io *io)
2625 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2626 bool prepare_random;
2628 int ret;
2630 ret = setup_last_set_field(io);
2631 if (ret != LDB_SUCCESS) {
2632 return ret;
2635 if (!io->ac->update_password && !io->ac->smartcard_reset) {
2636 return LDB_SUCCESS;
2639 if (io->u.is_krbtgt) {
2640 if (!io->ac->pwd_reset) {
2641 return dsdb_module_werror(io->ac->module,
2642 LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS,
2643 WERR_DS_ATT_ALREADY_EXISTS,
2644 "Password change on krbtgt not permitted!");
2647 if (io->n.cleartext_utf16 == NULL) {
2648 return dsdb_module_werror(io->ac->module,
2649 LDB_ERR_UNWILLING_TO_PERFORM,
2650 WERR_DS_INVALID_ATTRIBUTE_SYNTAX,
2651 "Password reset on krbtgt requires UTF16!");
2655 prepare_random = io->u.is_krbtgt || io->ac->smartcard_reset ||
2656 io->ac->kdc_reset_smartcard_account_password;
2659 * krbtgt, smartcard reset (on addition of
2660 * UF_SMARTCARD_REQUIRED) and KDC-triggered rollover (for
2661 * ResetSmartCardAccountPassword) need random passwords for
2662 * all supported keys
2664 if (prepare_random) {
2665 size_t min = 196;
2666 size_t max = 255;
2667 size_t diff = max - min;
2668 size_t len = max;
2669 struct ldb_val *krbtgt_utf16 = NULL;
2672 * Instead of taking the callers value,
2673 * we just generate a new random value here.
2675 * Include null termination in the array.
2677 if (diff > 0) {
2678 size_t tmp;
2680 generate_random_buffer((uint8_t *)&tmp, sizeof(tmp));
2682 tmp %= diff;
2684 len = min + tmp;
2687 krbtgt_utf16 = talloc_zero(io->ac, struct ldb_val);
2688 if (krbtgt_utf16 == NULL) {
2689 return ldb_oom(ldb);
2692 *krbtgt_utf16 = data_blob_talloc_zero(krbtgt_utf16,
2693 (len+1)*2);
2694 if (krbtgt_utf16->data == NULL) {
2695 return ldb_oom(ldb);
2697 krbtgt_utf16->length = len * 2;
2698 generate_secret_buffer(krbtgt_utf16->data,
2699 krbtgt_utf16->length);
2700 io->n.cleartext_utf16 = krbtgt_utf16;
2703 /* transform the old password (for password changes) */
2704 ret = setup_given_passwords(io, &io->og);
2705 if (ret != LDB_SUCCESS) {
2706 return ret;
2709 /* transform the new password */
2710 ret = setup_given_passwords(io, &io->n);
2711 if (ret != LDB_SUCCESS) {
2712 return ret;
2715 if (io->n.cleartext_utf8) {
2716 ret = setup_kerberos_keys(io);
2717 if (ret != LDB_SUCCESS) {
2718 return ret;
2723 * This relies on setup_kerberos_keys to make a NT-hash-like
2724 * value for password history purposes
2727 ret = setup_nt_fields(io);
2728 if (ret != LDB_SUCCESS) {
2729 return ret;
2732 ret = setup_supplemental_field(io);
2733 if (ret != LDB_SUCCESS) {
2734 return ret;
2737 return LDB_SUCCESS;
2740 static int setup_smartcard_reset(struct setup_password_fields_io *io)
2743 if (!io->ac->smartcard_reset) {
2744 return LDB_SUCCESS;
2748 * We must not keep the old password history otherwise the
2749 * password will not appear to have been randomised until the
2750 * 60min window is over
2752 io->g.nt_history_len = 0;
2755 * The password has been randomly set earlier, but now we need
2756 * to declare this a password update so that the change is
2757 * made (this ensures that the other rules about updates are
2758 * skipped in case, which is the setting of
2759 * UF_SMARTCARD_REQUIRED on an account)
2762 io->ac->update_password = true;
2763 return LDB_SUCCESS;
2766 static int make_error_and_update_badPwdCount(struct setup_password_fields_io *io, WERROR *werror)
2768 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2769 struct ldb_message *mod_msg = NULL;
2770 struct ldb_message *pso_msg = NULL;
2771 struct ldb_message *current = NULL;
2772 NTSTATUS status = NT_STATUS_OK;
2773 int ret; /* The errors we will actually return */
2774 int dbg_ret; /* The errors we can only complain about in logs */
2777 * OK, horrible semantics ahead.
2779 * - We need to abort any existing transaction
2780 * - create a transaction around the badPwdCount update
2781 * - re-open the transaction so the upper layer
2782 * doesn't know what happened.
2784 * This is needed because returning an error to the upper
2785 * layer will cancel the transaction and undo the badPwdCount
2786 * update.
2790 * Checking errors here is a bit pointless.
2791 * What can we do if we can't end the transaction?
2793 dbg_ret = ldb_next_del_trans(io->ac->module);
2794 if (dbg_ret != LDB_SUCCESS) {
2795 ldb_debug(ldb, LDB_DEBUG_FATAL,
2796 "Failed to abort transaction prior to update of badPwdCount of %s: %s",
2797 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2798 ldb_errstring(ldb));
2800 * just return the original error
2802 goto done;
2805 /* Likewise, what should we do if we can't open a new transaction? */
2806 dbg_ret = ldb_next_start_trans(io->ac->module);
2807 if (dbg_ret != LDB_SUCCESS) {
2808 ldb_debug(ldb, LDB_DEBUG_ERROR,
2809 "Failed to open transaction to update badPwdCount of %s: %s",
2810 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2811 ldb_errstring(ldb));
2813 * just return the original error
2815 goto done;
2819 * Re-read the account details, using the GUID in case the DN
2820 * is being changed.
2822 status = authsam_reread_user_logon_data(
2823 ldb, io->ac,
2824 io->ac->search_res->message,
2825 &current);
2826 if (!NT_STATUS_IS_OK(status)) {
2827 /* The re-read can return account locked out, as well
2828 * as an internal error
2830 goto end_transaction;
2833 /* PSO search result is optional (NULL if no PSO applies) */
2834 if (io->ac->pso_res != NULL) {
2835 pso_msg = io->ac->pso_res->message;
2838 status = dsdb_update_bad_pwd_count(io->ac, ldb,
2839 current,
2840 io->ac->dom_res->message,
2841 pso_msg,
2842 &mod_msg);
2843 if (!NT_STATUS_IS_OK(status)) {
2844 goto end_transaction;
2847 if (mod_msg == NULL) {
2848 goto end_transaction;
2851 dbg_ret = dsdb_module_modify(io->ac->module, mod_msg,
2852 DSDB_FLAG_NEXT_MODULE,
2853 io->ac->req);
2854 if (dbg_ret != LDB_SUCCESS) {
2855 ldb_debug(ldb, LDB_DEBUG_ERROR,
2856 "Failed to update badPwdCount of %s: %s",
2857 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2858 ldb_errstring(ldb));
2860 * We can only ignore this...
2864 end_transaction:
2865 dbg_ret = ldb_next_end_trans(io->ac->module);
2866 if (dbg_ret != LDB_SUCCESS) {
2867 ldb_debug(ldb, LDB_DEBUG_ERROR,
2868 "Failed to close transaction to update badPwdCount of %s: %s",
2869 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2870 ldb_errstring(ldb));
2872 * We can only ignore this...
2876 dbg_ret = ldb_next_start_trans(io->ac->module);
2877 if (dbg_ret != LDB_SUCCESS) {
2878 ldb_debug(ldb, LDB_DEBUG_ERROR,
2879 "Failed to open transaction after update of badPwdCount of %s: %s",
2880 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2881 ldb_errstring(ldb));
2883 * We can only ignore this...
2887 done:
2888 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2889 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
2890 *werror = WERR_ACCOUNT_LOCKED_OUT;
2891 } else {
2892 *werror = WERR_INVALID_PASSWORD;
2894 ldb_asprintf_errstring(ldb,
2895 "%08X: %s - check_password_restrictions: "
2896 "The old password specified doesn't match!",
2897 W_ERROR_V(*werror),
2898 ldb_strerror(ret));
2899 return ret;
2902 static int check_password_restrictions(struct setup_password_fields_io *io, WERROR *werror)
2904 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2905 int ret;
2906 uint32_t i;
2907 struct loadparm_context *lp_ctx =
2908 talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2909 struct loadparm_context);
2910 struct dsdb_encrypted_connection_state *opaque_connection_state =
2911 ldb_get_opaque(ldb,DSDB_OPAQUE_ENCRYPTED_CONNECTION_STATE_NAME);
2913 *werror = WERR_INVALID_PARAMETER;
2915 if (!io->ac->update_password) {
2916 return LDB_SUCCESS;
2920 * Prevent update password on an insecure connection.
2921 * The opaque is added in the ldap backend init.
2923 if (opaque_connection_state != NULL &&
2924 !opaque_connection_state->using_encrypted_connection) {
2925 ret = LDB_ERR_UNWILLING_TO_PERFORM;
2926 *werror = WERR_GEN_FAILURE;
2927 ldb_asprintf_errstring(ldb,
2928 "%08X: SvcErr: DSID-031A126C, "
2929 "problem 5003 (WILL_NOT_PERFORM), "
2930 "data 0\n"
2931 "Password modification over LDAP "
2932 "must be over an encrypted connection",
2933 W_ERROR_V(*werror));
2934 return ret;
2937 /* Do not apply restrictions on a KDC-issued rollover (eg ResetSmartCardAccountPassword) */
2938 if (io->ac->kdc_reset_smartcard_account_password) {
2939 return LDB_SUCCESS;
2943 * First check the old password is correct, for password
2944 * changes when this hasn't already been checked by a
2945 * trustworthy layer above
2947 if (!io->ac->pwd_reset && !(io->ac->change
2948 && io->ac->change->old_password_checked == DSDB_PASSWORD_CHECKED_AND_CORRECT)) {
2949 bool hash_checked = false;
2951 * we need the old nt hash given by the client (this
2952 * is for the plaintext over LDAP password change,
2953 * Kpasswd and SAMR supply the control)
2955 if (io->og.nt_hash == NULL && io->og.aes_256.length == 0) {
2956 ldb_asprintf_errstring(ldb,
2957 "check_password_restrictions: "
2958 "You need to provide the old password in order "
2959 "to change it!");
2960 return LDB_ERR_UNWILLING_TO_PERFORM;
2964 * First compare the ENCTYPE_AES256_CTS_HMAC_SHA1_96 password and see if we have a match
2967 if (io->og.aes_256.length > 0 && io->o.aes_256.length) {
2968 hash_checked = data_blob_equal_const_time(&io->og.aes_256, &io->o.aes_256);
2971 /* The password modify through the NT hash is encouraged and
2972 has no problems at all */
2973 if (!hash_checked && io->og.nt_hash && io->o.nt_hash) {
2974 hash_checked = mem_equal_const_time(io->og.nt_hash->hash, io->o.nt_hash->hash, 16);
2977 if (!hash_checked) {
2978 return make_error_and_update_badPwdCount(io, werror);
2983 * There is no restriction on a smartcard_reset update, even
2984 * if a password was specified, as it is randomised in this
2985 * module.
2987 if (io->ac->smartcard_reset) {
2988 return LDB_SUCCESS;
2992 * Only non-trust accounts have restrictions.
2994 * This is where a krbtgt random password set will also exit, as
2995 * io->u.restrictions = 0 is called earlier.
2997 if (io->u.restrictions == 0) {
2998 return LDB_SUCCESS;
3001 /* Password minimum age: yes, this is a minus. The ages are in negative 100nsec units! */
3002 if ((io->u.pwdLastSet - io->ac->status->domain_data.minPwdAge > io->g.last_set) &&
3003 !io->ac->pwd_reset)
3005 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3006 *werror = WERR_PASSWORD_RESTRICTION;
3007 ldb_asprintf_errstring(ldb,
3008 "%08X: %s - check_password_restrictions: "
3009 "password is too young to change!",
3010 W_ERROR_V(*werror),
3011 ldb_strerror(ret));
3012 return ret;
3016 * Fundamental password checks done by the call
3017 * "samdb_check_password".
3018 * It is also in use by "dcesrv_samr_ValidatePassword".
3020 if (io->n.cleartext_utf8 != NULL) {
3021 enum samr_ValidationStatus vstat;
3022 vstat = samdb_check_password(io->ac, lp_ctx,
3023 io->u.sAMAccountName,
3024 io->u.user_principal_name,
3025 io->u.displayName,
3026 io->n.cleartext_utf8,
3027 io->ac->status->domain_data.pwdProperties,
3028 io->ac->status->domain_data.minPwdLength);
3029 switch (vstat) {
3030 case SAMR_VALIDATION_STATUS_SUCCESS:
3031 /* perfect -> proceed! */
3032 break;
3034 case SAMR_VALIDATION_STATUS_PWD_TOO_SHORT:
3035 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3036 *werror = WERR_PASSWORD_RESTRICTION;
3037 ldb_asprintf_errstring(ldb,
3038 "%08X: %s - check_password_restrictions: "
3039 "the password is too short. It should be equal to or longer than %u characters!",
3040 W_ERROR_V(*werror),
3041 ldb_strerror(ret),
3042 io->ac->status->domain_data.minPwdLength);
3043 io->ac->status->reject_reason = SAM_PWD_CHANGE_PASSWORD_TOO_SHORT;
3044 return ret;
3046 case SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH:
3047 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3048 *werror = WERR_PASSWORD_RESTRICTION;
3049 ldb_asprintf_errstring(ldb,
3050 "%08X: %s - check_password_restrictions: "
3051 "the password does not meet the complexity criteria!",
3052 W_ERROR_V(*werror),
3053 ldb_strerror(ret));
3054 io->ac->status->reject_reason = SAM_PWD_CHANGE_NOT_COMPLEX;
3055 return ret;
3057 default:
3058 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3059 *werror = WERR_PASSWORD_RESTRICTION;
3060 ldb_asprintf_errstring(ldb,
3061 "%08X: %s - check_password_restrictions: "
3062 "the password doesn't fit due to a miscellaneous restriction!",
3063 W_ERROR_V(*werror),
3064 ldb_strerror(ret));
3065 return ret;
3069 if (io->ac->pwd_reset) {
3070 *werror = WERR_OK;
3071 return LDB_SUCCESS;
3075 * This check works by using the current Kerberos password to
3076 * make up a password history. We already did the salted hash
3077 * creation to pass the password change check.
3079 * We check the pwdHistoryLength to ensure we honour the
3080 * policy on if the history should be checked
3082 if (io->ac->status->domain_data.pwdHistoryLength > 0
3083 && io->g.aes_256.length && io->o.aes_256.length)
3085 bool equal = data_blob_equal_const_time(&io->g.aes_256,
3086 &io->o.aes_256);
3087 if (equal) {
3088 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3089 *werror = WERR_PASSWORD_RESTRICTION;
3090 ldb_asprintf_errstring(ldb,
3091 "%08X: %s - check_password_restrictions: "
3092 "the password was already used (previous password)!",
3093 W_ERROR_V(*werror),
3094 ldb_strerror(ret));
3095 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
3096 return ret;
3100 if (io->n.nt_hash) {
3102 * checks the NT hash password history, against the
3103 * generated NT hash
3105 for (i = 0; i < io->o.nt_history_len; i++) {
3106 bool pw_cmp = mem_equal_const_time(io->n.nt_hash, io->o.nt_history[i].hash, 16);
3107 if (pw_cmp) {
3108 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3109 *werror = WERR_PASSWORD_RESTRICTION;
3110 ldb_asprintf_errstring(ldb,
3111 "%08X: %s - check_password_restrictions: "
3112 "the password was already used (in history)!",
3113 W_ERROR_V(*werror),
3114 ldb_strerror(ret));
3115 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
3116 return ret;
3122 * This check works by using the old Kerberos passwords
3123 * (old and older) to make up a password history.
3125 * We check the pwdHistoryLength to ensure we honour the
3126 * policy on if the history should be checked
3128 for (i = 1;
3129 i <= io->o.kvno && i < MIN(3, io->ac->status->domain_data.pwdHistoryLength);
3130 i++)
3132 krb5_error_code krb5_ret;
3133 const uint32_t request_kvno = io->o.kvno - i;
3134 DATA_BLOB db_key_blob;
3135 bool pw_equal;
3137 if (io->n.cleartext_utf8 == NULL) {
3139 * No point checking history if we don't have
3140 * a cleartext password.
3142 break;
3145 if (io->ac->search_res == NULL) {
3147 * This is an ADD, no existing history to check
3149 break;
3153 * If this account requires a smartcard for login, we don't
3154 * attempt a comparison with the old password.
3156 if (io->u.userAccountControl & UF_SMARTCARD_REQUIRED) {
3157 break;
3161 * Extract the old ENCTYPE_AES256_CTS_HMAC_SHA1_96 value from
3162 * the supplementalCredentials.
3164 krb5_ret = dsdb_extract_aes_256_key(io->smb_krb5_context->krb5_context,
3165 io->ac,
3166 ldb,
3167 io->ac->search_res->message,
3168 io->u.userAccountControl,
3169 &request_kvno, /* kvno */
3170 NULL, /* kvno_out */
3171 &db_key_blob,
3172 NULL); /* salt */
3173 if (krb5_ret == ENOENT) {
3175 * If there is no old AES hash (perhaps an imported DB with
3176 * just unicodePwd) then we just won't have an old
3177 * password to compare to if there is no NT hash
3179 break;
3180 } else if (krb5_ret) {
3181 ldb_asprintf_errstring(ldb,
3182 "check_password_restrictions: "
3183 "extraction of old[%u - %d = %d] aes256-cts-hmac-sha1-96 key failed: %s",
3184 io->o.kvno, i, io->o.kvno - i,
3185 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
3186 krb5_ret, io->ac));
3187 return LDB_ERR_OPERATIONS_ERROR;
3190 /* This is the actual history check */
3191 pw_equal = data_blob_equal_const_time(&io->n.aes_256,
3192 &db_key_blob);
3193 if (pw_equal) {
3194 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3195 *werror = WERR_PASSWORD_RESTRICTION;
3196 ldb_asprintf_errstring(ldb,
3197 "%08X: %s - check_password_restrictions: "
3198 "the password was already used (in history)!",
3199 W_ERROR_V(*werror),
3200 ldb_strerror(ret));
3201 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
3202 return ret;
3206 /* are all password changes disallowed? */
3207 if (io->ac->status->domain_data.pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
3208 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3209 *werror = WERR_PASSWORD_RESTRICTION;
3210 ldb_asprintf_errstring(ldb,
3211 "%08X: %s - check_password_restrictions: "
3212 "password changes disabled!",
3213 W_ERROR_V(*werror),
3214 ldb_strerror(ret));
3215 return ret;
3218 /* can this user change the password? */
3219 if (io->u.userAccountControl & UF_PASSWD_CANT_CHANGE) {
3220 ret = LDB_ERR_CONSTRAINT_VIOLATION;
3221 *werror = WERR_PASSWORD_RESTRICTION;
3222 ldb_asprintf_errstring(ldb,
3223 "%08X: %s - check_password_restrictions: "
3224 "password can't be changed on this account!",
3225 W_ERROR_V(*werror),
3226 ldb_strerror(ret));
3227 return ret;
3230 return LDB_SUCCESS;
3233 static int check_password_restrictions_and_log(struct setup_password_fields_io *io)
3235 WERROR werror;
3236 int ret = check_password_restrictions(io, &werror);
3237 struct ph_context *ac = io->ac;
3239 * Password resets are not authentication events, and if the
3240 * upper layer checked the password and supplied the hash
3241 * values as proof, then this is also not an authentication
3242 * even at this layer (already logged). This is to log LDAP
3243 * password changes.
3246 /* Do not record a failure in the auth log below in the success case */
3247 if (ret == LDB_SUCCESS) {
3248 werror = WERR_OK;
3251 if (ac->pwd_reset == false && ac->change == NULL) {
3252 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3253 struct imessaging_context *msg_ctx;
3254 struct loadparm_context *lp_ctx
3255 = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"),
3256 struct loadparm_context);
3257 NTSTATUS status = werror_to_ntstatus(werror);
3258 const char *domain_name = lpcfg_sam_name(lp_ctx);
3259 void *opaque_remote_address = NULL;
3261 * Forcing this via the NTLM auth structure is not ideal, but
3262 * it is the most practical option right now, and ensures the
3263 * logs are consistent, even if some elements are always NULL.
3265 struct auth_usersupplied_info ui = {
3266 .was_mapped = true,
3267 .client = {
3268 .account_name = io->u.sAMAccountName,
3269 .domain_name = domain_name,
3271 .mapped = {
3272 .account_name = io->u.sAMAccountName,
3273 .domain_name = domain_name,
3275 .service_description = "LDAP Password Change",
3276 .auth_description = "LDAP Modify",
3277 .password_type = "plaintext"
3280 opaque_remote_address = ldb_get_opaque(ldb,
3281 "remoteAddress");
3282 if (opaque_remote_address == NULL) {
3283 ldb_asprintf_errstring(ldb,
3284 "Failed to obtain remote address for "
3285 "the LDAP client while changing the "
3286 "password");
3287 return LDB_ERR_OPERATIONS_ERROR;
3289 ui.remote_host = talloc_get_type(opaque_remote_address,
3290 struct tsocket_address);
3292 msg_ctx = imessaging_client_init(ac, lp_ctx,
3293 ldb_get_event_context(ldb));
3294 if (!msg_ctx) {
3295 ldb_asprintf_errstring(ldb,
3296 "Failed to generate client messaging context in %s",
3297 lpcfg_imessaging_path(ac, lp_ctx));
3298 return LDB_ERR_OPERATIONS_ERROR;
3300 log_authentication_event(msg_ctx,
3301 lp_ctx,
3302 NULL,
3303 &ui,
3304 status,
3305 domain_name,
3306 io->u.sAMAccountName,
3307 io->u.account_sid,
3308 NULL /* client_audit_info */,
3309 NULL /* server_audit_info */);
3312 return ret;
3315 static int update_final_msg(struct setup_password_fields_io *io)
3317 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
3318 int ret;
3319 int el_flags = 0;
3320 bool update_password = io->ac->update_password;
3321 bool update_scb = io->ac->update_password;
3324 * If we add a user without initial password,
3325 * we need to add replication meta data for
3326 * following attributes:
3327 * - unicodePwd
3328 * - dBCSPwd
3329 * - ntPwdHistory
3330 * - lmPwdHistory
3332 * If we add a user with initial password or a
3333 * password is changed of an existing user,
3334 * we need to replace the following attributes
3335 * with a forced meta data update, e.g. also
3336 * when updating an empty attribute with an empty value:
3337 * - unicodePwd
3338 * - dBCSPwd
3339 * - ntPwdHistory
3340 * - lmPwdHistory
3341 * - supplementalCredentials
3344 switch (io->ac->req->operation) {
3345 case LDB_ADD:
3346 update_password = true;
3347 el_flags |= DSDB_FLAG_INTERNAL_FORCE_META_DATA;
3348 break;
3349 case LDB_MODIFY:
3350 el_flags |= LDB_FLAG_MOD_REPLACE;
3351 el_flags |= DSDB_FLAG_INTERNAL_FORCE_META_DATA;
3352 break;
3353 default:
3354 return ldb_module_operr(io->ac->module);
3357 if (update_password) {
3358 ret = ldb_msg_add_empty(io->ac->update_msg,
3359 "unicodePwd",
3360 el_flags, NULL);
3361 if (ret != LDB_SUCCESS) {
3362 return ret;
3366 * This wipes any old LM password after any password
3367 * update operation.
3369 * This is the same as the previous default behaviour
3370 * of 'lanman auth = no'
3372 ret = ldb_msg_add_empty(io->ac->update_msg,
3373 "dBCSPwd",
3374 el_flags, NULL);
3375 if (ret != LDB_SUCCESS) {
3376 return ret;
3378 ret = ldb_msg_add_empty(io->ac->update_msg,
3379 "ntPwdHistory",
3380 el_flags, NULL);
3381 if (ret != LDB_SUCCESS) {
3382 return ret;
3385 * This wipes any LM password history after any password
3386 * update operation.
3388 * This is the same as the previous default behaviour
3389 * of 'lanman auth = no'
3391 ret = ldb_msg_add_empty(io->ac->update_msg,
3392 "lmPwdHistory",
3393 el_flags, NULL);
3394 if (ret != LDB_SUCCESS) {
3395 return ret;
3398 if (update_scb) {
3399 ret = ldb_msg_add_empty(io->ac->update_msg,
3400 "supplementalCredentials",
3401 el_flags, NULL);
3402 if (ret != LDB_SUCCESS) {
3403 return ret;
3406 if (io->ac->update_lastset) {
3407 ret = ldb_msg_add_empty(io->ac->update_msg,
3408 "pwdLastSet",
3409 el_flags, NULL);
3410 if (ret != LDB_SUCCESS) {
3411 return ret;
3415 if (io->g.nt_hash != NULL) {
3416 ret = samdb_msg_add_hash(ldb, io->ac,
3417 io->ac->update_msg,
3418 "unicodePwd",
3419 io->g.nt_hash);
3420 if (ret != LDB_SUCCESS) {
3421 return ret;
3425 if (io->g.nt_history_len > 0) {
3426 ret = samdb_msg_add_hashes(ldb, io->ac,
3427 io->ac->update_msg,
3428 "ntPwdHistory",
3429 io->g.nt_history,
3430 io->g.nt_history_len);
3431 if (ret != LDB_SUCCESS) {
3432 return ret;
3435 if (io->g.supplemental.length > 0) {
3436 ret = ldb_msg_add_value(io->ac->update_msg,
3437 "supplementalCredentials",
3438 &io->g.supplemental, NULL);
3439 if (ret != LDB_SUCCESS) {
3440 return ret;
3443 if (io->ac->update_lastset) {
3444 ret = samdb_msg_add_uint64(ldb, io->ac,
3445 io->ac->update_msg,
3446 "pwdLastSet",
3447 io->g.last_set);
3448 if (ret != LDB_SUCCESS) {
3449 return ret;
3453 return LDB_SUCCESS;
3457 * This is intended for use by the "password_hash" module since there
3458 * password changes can be specified through one message element with the
3459 * new password (to set) and another one with the old password (to unset).
3461 * The first which sets a password (new value) can have flags
3462 * (LDB_FLAG_MOD_ADD, LDB_FLAG_MOD_REPLACE) but also none (on "add" operations
3463 * for entries). The latter (old value) has always specified
3464 * LDB_FLAG_MOD_DELETE.
3466 * Returns LDB_ERR_CONSTRAINT_VIOLATION and LDB_ERR_UNWILLING_TO_PERFORM if
3467 * matching message elements are malformed in respect to the set/change rules.
3468 * Otherwise it returns LDB_SUCCESS.
3470 static int msg_find_old_and_new_pwd_val(const struct ldb_message *msg,
3471 const char *name,
3472 enum ldb_request_type operation,
3473 const struct ldb_val **new_val,
3474 const struct ldb_val **old_val)
3476 unsigned int i;
3478 *new_val = NULL;
3479 *old_val = NULL;
3481 if (msg == NULL) {
3482 return LDB_SUCCESS;
3485 for (i = 0; i < msg->num_elements; i++) {
3486 if (ldb_attr_cmp(msg->elements[i].name, name) != 0) {
3487 continue;
3490 if ((operation == LDB_MODIFY) &&
3491 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_DELETE)) {
3492 /* 0 values are allowed */
3493 if (msg->elements[i].num_values == 1) {
3494 *old_val = &msg->elements[i].values[0];
3495 } else if (msg->elements[i].num_values > 1) {
3496 return LDB_ERR_CONSTRAINT_VIOLATION;
3498 } else if ((operation == LDB_MODIFY) &&
3499 (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_REPLACE)) {
3500 if (msg->elements[i].num_values > 0) {
3501 *new_val = &msg->elements[i].values[msg->elements[i].num_values - 1];
3502 } else {
3503 return LDB_ERR_UNWILLING_TO_PERFORM;
3505 } else {
3506 /* Add operations and LDB_FLAG_MOD_ADD */
3507 if (msg->elements[i].num_values > 0) {
3508 *new_val = &msg->elements[i].values[msg->elements[i].num_values - 1];
3509 } else {
3510 return LDB_ERR_CONSTRAINT_VIOLATION;
3515 return LDB_SUCCESS;
3518 static int setup_io(struct ph_context *ac,
3519 const struct ldb_message *client_msg,
3520 const struct ldb_message *existing_msg,
3521 struct setup_password_fields_io *io)
3523 const struct ldb_val *quoted_utf16, *old_quoted_utf16, *lm_hash, *old_lm_hash;
3524 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3525 struct loadparm_context *lp_ctx = talloc_get_type(
3526 ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
3527 enum store_nt_hash store_hash_setting =
3528 lpcfg_nt_hash_store(lp_ctx);
3529 int ret;
3530 const struct ldb_message *info_msg = NULL;
3531 struct dom_sid *account_sid = NULL;
3532 int rodc_krbtgt = 0;
3534 *io = (struct setup_password_fields_io) {};
3536 /* Some operations below require kerberos contexts */
3538 if (existing_msg != NULL) {
3540 * This is a modify operation
3542 info_msg = existing_msg;
3543 } else {
3545 * This is an add operation
3547 info_msg = client_msg;
3550 ret = smb_krb5_init_context(ac,
3551 (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm"),
3552 &io->smb_krb5_context);
3554 if (ret != 0) {
3556 * In the special case of mit krb5.conf vs heimdal, the includedir
3557 * statement causes ret == 22 (KRB5_CONFIG_BADFORMAT) to be returned.
3558 * We look for this case so that we can give a more instructional
3559 * message to the administrator.
3561 if (ret == KRB5_CONFIG_BADFORMAT || ret == EINVAL) {
3562 ldb_asprintf_errstring(ldb, "Failed to setup krb5_context: %s - "
3563 "This could be due to an invalid krb5 configuration. "
3564 "Please check your system's krb5 configuration is correct.",
3565 error_message(ret));
3566 } else {
3567 ldb_asprintf_errstring(ldb, "Failed to setup krb5_context: %s",
3568 error_message(ret));
3570 return LDB_ERR_OPERATIONS_ERROR;
3573 io->ac = ac;
3575 io->u.userAccountControl = ldb_msg_find_attr_as_uint(info_msg,
3576 "userAccountControl", 0);
3577 if (info_msg == existing_msg) {
3579 * We only take pwdLastSet from the existing object
3580 * otherwise we leave it as 0.
3582 * If no attribute is available, e.g. on deleted objects
3583 * we remember that as UINT64_MAX.
3585 io->u.pwdLastSet = samdb_result_nttime(info_msg, "pwdLastSet",
3586 UINT64_MAX);
3588 io->u.sAMAccountName = ldb_msg_find_attr_as_string(info_msg,
3589 "sAMAccountName", NULL);
3590 io->u.user_principal_name = ldb_msg_find_attr_as_string(info_msg,
3591 "userPrincipalName", NULL);
3592 io->u.displayName = ldb_msg_find_attr_as_string(info_msg,
3593 "displayName", NULL);
3595 /* Ensure it has an objectSID too */
3596 io->u.account_sid = samdb_result_dom_sid(ac, info_msg, "objectSid");
3597 if (io->u.account_sid != NULL) {
3598 NTSTATUS status;
3599 uint32_t rid = 0;
3601 status = dom_sid_split_rid(account_sid, io->u.account_sid, NULL, &rid);
3602 if (NT_STATUS_IS_OK(status)) {
3603 if (rid == DOMAIN_RID_KRBTGT) {
3604 io->u.is_krbtgt = true;
3609 rodc_krbtgt = ldb_msg_find_attr_as_int(info_msg,
3610 "msDS-SecondaryKrbTgtNumber", 0);
3611 if (rodc_krbtgt != 0) {
3612 io->u.is_krbtgt = true;
3615 if (io->u.sAMAccountName == NULL) {
3616 ldb_asprintf_errstring(ldb,
3617 "setup_io: sAMAccountName attribute is missing on %s for attempted password set/change",
3618 ldb_dn_get_linearized(info_msg->dn));
3620 return LDB_ERR_CONSTRAINT_VIOLATION;
3623 if (io->u.userAccountControl & UF_INTERDOMAIN_TRUST_ACCOUNT) {
3624 struct ldb_control *permit_trust = ldb_request_get_control(ac->req,
3625 DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
3627 if (permit_trust == NULL) {
3628 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
3629 ldb_asprintf_errstring(ldb,
3630 "%08X: %s - setup_io: changing the interdomain trust password "
3631 "on %s not allowed via LDAP. Use LSA or NETLOGON",
3632 W_ERROR_V(WERR_ACCESS_DENIED),
3633 ldb_strerror(ret),
3634 ldb_dn_get_linearized(info_msg->dn));
3635 return ret;
3639 /* Only non-trust accounts have restrictions (possibly this test is the
3640 * wrong way around, but we like to be restrictive if possible */
3641 io->u.restrictions = !(io->u.userAccountControl & UF_TRUST_ACCOUNT_MASK);
3643 if (io->u.is_krbtgt) {
3644 io->u.restrictions = 0;
3645 io->ac->status->domain_data.pwdHistoryLength =
3646 MAX(io->ac->status->domain_data.pwdHistoryLength, 3);
3650 * Machine accounts need the NT hash to operate the NETLOGON
3651 * ServerAuthenticate{,2,3} logic
3653 if (!(io->u.userAccountControl & UF_NORMAL_ACCOUNT)) {
3654 store_hash_setting = NT_HASH_STORE_ALWAYS;
3657 switch (store_hash_setting) {
3658 case NT_HASH_STORE_ALWAYS:
3659 io->u.store_nt_hash = true;
3660 break;
3661 case NT_HASH_STORE_NEVER:
3662 io->u.store_nt_hash = false;
3663 break;
3664 case NT_HASH_STORE_AUTO:
3665 if (lpcfg_ntlm_auth(lp_ctx) == NTLM_AUTH_DISABLED) {
3666 io->u.store_nt_hash = false;
3667 break;
3669 io->u.store_nt_hash = true;
3670 break;
3673 if (ac->userPassword) {
3674 ret = msg_find_old_and_new_pwd_val(client_msg, "userPassword",
3675 ac->req->operation,
3676 &io->n.cleartext_utf8,
3677 &io->og.cleartext_utf8);
3678 if (ret != LDB_SUCCESS) {
3679 ldb_asprintf_errstring(ldb,
3680 "setup_io: "
3681 "it's only allowed to set the old password once!");
3682 return ret;
3686 if (io->n.cleartext_utf8 != NULL) {
3687 struct ldb_val *cleartext_utf8_blob;
3688 char *p;
3690 cleartext_utf8_blob = talloc(io->ac, struct ldb_val);
3691 if (!cleartext_utf8_blob) {
3692 return ldb_oom(ldb);
3695 *cleartext_utf8_blob = *io->n.cleartext_utf8;
3697 /* make sure we have a null terminated string */
3698 p = talloc_strndup(cleartext_utf8_blob,
3699 (const char *)io->n.cleartext_utf8->data,
3700 io->n.cleartext_utf8->length);
3701 if ((p == NULL) && (io->n.cleartext_utf8->length > 0)) {
3702 return ldb_oom(ldb);
3704 cleartext_utf8_blob->data = (uint8_t *)p;
3706 io->n.cleartext_utf8 = cleartext_utf8_blob;
3709 ret = msg_find_old_and_new_pwd_val(client_msg, "clearTextPassword",
3710 ac->req->operation,
3711 &io->n.cleartext_utf16,
3712 &io->og.cleartext_utf16);
3713 if (ret != LDB_SUCCESS) {
3714 ldb_asprintf_errstring(ldb,
3715 "setup_io: "
3716 "it's only allowed to set the old password once!");
3717 return ret;
3720 /* this rather strange looking piece of code is there to
3721 handle a ldap client setting a password remotely using the
3722 unicodePwd ldap field. The syntax is that the password is
3723 in UTF-16LE, with a " at either end. Unfortunately the
3724 unicodePwd field is also used to store the nt hashes
3725 internally in Samba, and is used in the nt hash format on
3726 the wire in DRS replication, so we have a single name for
3727 two distinct values. The code below leaves us with a small
3728 chance (less than 1 in 2^32) of a mixup, if someone manages
3729 to create a MD4 hash which starts and ends in 0x22 0x00, as
3730 that would then be treated as a UTF16 password rather than
3731 a nthash */
3733 ret = msg_find_old_and_new_pwd_val(client_msg, "unicodePwd",
3734 ac->req->operation,
3735 &quoted_utf16,
3736 &old_quoted_utf16);
3737 if (ret != LDB_SUCCESS) {
3738 ldb_asprintf_errstring(ldb,
3739 "setup_io: "
3740 "it's only allowed to set the old password once!");
3741 return ret;
3744 /* Checks and converts the actual "unicodePwd" attribute */
3745 if (!ac->hash_values &&
3746 quoted_utf16 &&
3747 quoted_utf16->length >= 4 &&
3748 quoted_utf16->data[0] == '"' &&
3749 quoted_utf16->data[1] == 0 &&
3750 quoted_utf16->data[quoted_utf16->length-2] == '"' &&
3751 quoted_utf16->data[quoted_utf16->length-1] == 0) {
3752 struct ldb_val *quoted_utf16_2;
3754 if (io->n.cleartext_utf16) {
3755 /* refuse the change if someone wants to change with
3756 both UTF16 possibilities at the same time... */
3757 ldb_asprintf_errstring(ldb,
3758 "setup_io: "
3759 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'clearTextPassword'");
3760 return LDB_ERR_UNWILLING_TO_PERFORM;
3764 * adapt the quoted UTF16 string to be a real
3765 * cleartext one
3767 quoted_utf16_2 = talloc(io->ac, struct ldb_val);
3768 if (quoted_utf16_2 == NULL) {
3769 return ldb_oom(ldb);
3772 quoted_utf16_2->data = quoted_utf16->data + 2;
3773 quoted_utf16_2->length = quoted_utf16->length-4;
3774 io->n.cleartext_utf16 = quoted_utf16_2;
3775 io->n.nt_hash = NULL;
3777 } else if (quoted_utf16) {
3778 /* We have only the hash available -> so no plaintext here */
3779 if (!ac->hash_values) {
3780 /* refuse the change if someone wants to change
3781 the hash without control specified... */
3782 ldb_asprintf_errstring(ldb,
3783 "setup_io: "
3784 "it's not allowed to set the NT hash password directly'");
3785 /* this looks odd but this is what Windows does:
3786 returns "UNWILLING_TO_PERFORM" on wrong
3787 password sets and "CONSTRAINT_VIOLATION" on
3788 wrong password changes. */
3789 if (old_quoted_utf16 == NULL) {
3790 return LDB_ERR_UNWILLING_TO_PERFORM;
3793 return LDB_ERR_CONSTRAINT_VIOLATION;
3796 io->n.nt_hash = talloc(io->ac, struct samr_Password);
3797 if (io->n.nt_hash == NULL) {
3798 return ldb_oom(ldb);
3800 memcpy(io->n.nt_hash->hash, quoted_utf16->data,
3801 MIN(quoted_utf16->length, sizeof(io->n.nt_hash->hash)));
3804 /* Checks and converts the previous "unicodePwd" attribute */
3805 if (!ac->hash_values &&
3806 old_quoted_utf16 &&
3807 old_quoted_utf16->length >= 4 &&
3808 old_quoted_utf16->data[0] == '"' &&
3809 old_quoted_utf16->data[1] == 0 &&
3810 old_quoted_utf16->data[old_quoted_utf16->length-2] == '"' &&
3811 old_quoted_utf16->data[old_quoted_utf16->length-1] == 0) {
3812 struct ldb_val *old_quoted_utf16_2;
3814 if (io->og.cleartext_utf16) {
3815 /* refuse the change if someone wants to change with
3816 both UTF16 possibilities at the same time... */
3817 ldb_asprintf_errstring(ldb,
3818 "setup_io: "
3819 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'clearTextPassword'");
3820 return LDB_ERR_UNWILLING_TO_PERFORM;
3824 * adapt the quoted UTF16 string to be a real
3825 * cleartext one
3827 old_quoted_utf16_2 = talloc(io->ac, struct ldb_val);
3828 if (old_quoted_utf16_2 == NULL) {
3829 return ldb_oom(ldb);
3832 old_quoted_utf16_2->data = old_quoted_utf16->data + 2;
3833 old_quoted_utf16_2->length = old_quoted_utf16->length-4;
3835 io->og.cleartext_utf16 = old_quoted_utf16_2;
3836 io->og.nt_hash = NULL;
3837 } else if (old_quoted_utf16) {
3838 /* We have only the hash available -> so no plaintext here */
3839 if (!ac->hash_values) {
3840 /* refuse the change if someone wants to change
3841 the hash without control specified... */
3842 ldb_asprintf_errstring(ldb,
3843 "setup_io: "
3844 "it's not allowed to set the NT hash password directly'");
3845 return LDB_ERR_UNWILLING_TO_PERFORM;
3848 io->og.nt_hash = talloc(io->ac, struct samr_Password);
3849 if (io->og.nt_hash == NULL) {
3850 return ldb_oom(ldb);
3852 memcpy(io->og.nt_hash->hash, old_quoted_utf16->data,
3853 MIN(old_quoted_utf16->length, sizeof(io->og.nt_hash->hash)));
3856 /* Handles the "dBCSPwd" attribute (LM hash) */
3857 ret = msg_find_old_and_new_pwd_val(client_msg, "dBCSPwd",
3858 ac->req->operation,
3859 &lm_hash, &old_lm_hash);
3860 if (ret != LDB_SUCCESS) {
3861 ldb_asprintf_errstring(ldb,
3862 "setup_io: "
3863 "it's only allowed to set the old password once!");
3864 return ret;
3867 if (((lm_hash != NULL) || (old_lm_hash != NULL))) {
3868 /* refuse the change if someone wants to change the LM hash */
3869 ldb_asprintf_errstring(ldb,
3870 "setup_io: "
3871 "it's not allowed to set the LM hash password (dBCSPwd)'");
3872 return LDB_ERR_UNWILLING_TO_PERFORM;
3876 * Handles the password change control if it's specified. It has the
3877 * precedence and overrides already specified old password values of
3878 * change requests (but that shouldn't happen since the control is
3879 * fully internal and only used in conjunction with replace requests!).
3881 if (ac->change != NULL) {
3882 io->og.nt_hash = NULL;
3885 /* refuse the change if someone wants to change the clear-
3886 text and supply his own hashes at the same time... */
3887 if ((io->n.cleartext_utf8 || io->n.cleartext_utf16)
3888 && (io->n.nt_hash)) {
3889 ldb_asprintf_errstring(ldb,
3890 "setup_io: "
3891 "it's only allowed to set the password in form of cleartext attributes or as hashes");
3892 return LDB_ERR_UNWILLING_TO_PERFORM;
3895 /* refuse the change if someone wants to change the password
3896 using both plaintext methods (UTF8 and UTF16) at the same time... */
3897 if (io->n.cleartext_utf8 && io->n.cleartext_utf16) {
3898 ldb_asprintf_errstring(ldb,
3899 "setup_io: "
3900 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
3901 return LDB_ERR_UNWILLING_TO_PERFORM;
3904 /* refuse the change if someone tries to set/change the password by
3905 * any method that would leave us without a password! */
3906 if (io->ac->update_password
3907 && (!io->n.cleartext_utf8) && (!io->n.cleartext_utf16)
3908 && (!io->n.nt_hash)) {
3909 ldb_asprintf_errstring(ldb,
3910 "setup_io: "
3911 "It's not possible to delete the password (changes using the LAN Manager hash alone could be deactivated)!");
3912 /* on "userPassword" and "clearTextPassword" we've to return
3913 * something different, since these are virtual attributes */
3914 if ((ldb_msg_find_element(client_msg, "userPassword") != NULL) ||
3915 (ldb_msg_find_element(client_msg, "clearTextPassword") != NULL)) {
3916 return LDB_ERR_CONSTRAINT_VIOLATION;
3918 return LDB_ERR_UNWILLING_TO_PERFORM;
3922 * refuse the change if someone wants to compare against a
3923 * plaintext or dsdb_control_password_change at the same time
3924 * for a "password modify" operation...
3926 if ((io->og.cleartext_utf8 || io->og.cleartext_utf16)
3927 && ac->change) {
3928 ldb_asprintf_errstring(ldb,
3929 "setup_io: "
3930 "it's only allowed to provide the old password in form of cleartext attributes or as the dsdb_control_password_change");
3931 return LDB_ERR_UNWILLING_TO_PERFORM;
3934 /* refuse the change if someone wants to compare against both
3935 * plaintexts at the same time for a "password modify" operation... */
3936 if (io->og.cleartext_utf8 && io->og.cleartext_utf16) {
3937 ldb_asprintf_errstring(ldb,
3938 "setup_io: "
3939 "it's only allowed to provide the old cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
3940 return LDB_ERR_UNWILLING_TO_PERFORM;
3943 /* Decides if we have a password modify or password reset operation */
3944 if (ac->req->operation == LDB_ADD) {
3945 /* On "add" we have only "password reset" */
3946 ac->pwd_reset = true;
3947 } else if (ac->req->operation == LDB_MODIFY) {
3948 struct ldb_control *pav_ctrl = NULL;
3949 struct dsdb_control_password_acl_validation *pav = NULL;
3951 pav_ctrl = ldb_request_get_control(ac->req,
3952 DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID);
3953 if (pav_ctrl != NULL) {
3954 pav = talloc_get_type_abort(pav_ctrl->data,
3955 struct dsdb_control_password_acl_validation);
3958 if (pav == NULL && ac->update_password) {
3959 bool ok;
3962 * If the DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID
3963 * control is missing, we require system access!
3965 ok = dsdb_have_system_access(
3966 ac->module,
3967 ac->req,
3968 SYSTEM_CONTROL_KEEP_CRITICAL);
3969 if (!ok) {
3970 return ldb_module_operr(ac->module);
3974 if (pav != NULL) {
3976 * We assume what the acl module has validated.
3978 ac->pwd_reset = pav->pwd_reset;
3979 } else if (io->og.cleartext_utf8 || io->og.cleartext_utf16
3980 || ac->change) {
3982 * If we have an old password specified or the
3983 * dsdb_control_password_change then for sure
3984 * it is a user "password change"
3986 ac->pwd_reset = false;
3987 } else {
3988 /* Otherwise we have also here a "password reset" */
3989 ac->pwd_reset = true;
3991 } else {
3992 /* this shouldn't happen */
3993 return ldb_operr(ldb);
3996 if (existing_msg != NULL) {
3997 NTSTATUS status;
3998 krb5_error_code krb5_ret;
3999 DATA_BLOB key_blob;
4000 DATA_BLOB salt_blob;
4001 uint32_t kvno;
4003 if (ac->pwd_reset) {
4004 /* Get the old password from the database */
4005 status = samdb_result_passwords_no_lockout(ac,
4006 lp_ctx,
4007 existing_msg,
4008 &io->o.nt_hash);
4009 } else {
4010 /* Get the old password from the database */
4011 status = samdb_result_passwords(ac,
4012 lp_ctx,
4013 existing_msg,
4014 &io->o.nt_hash);
4017 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
4018 return dsdb_module_werror(ac->module,
4019 LDB_ERR_CONSTRAINT_VIOLATION,
4020 WERR_ACCOUNT_LOCKED_OUT,
4021 "Password change not permitted,"
4022 " account locked out!");
4025 if (!NT_STATUS_IS_OK(status)) {
4027 * This only happens if the database has gone weird,
4028 * not if we are just missing the passwords
4030 return ldb_operr(ldb);
4033 io->o.nt_history_len = samdb_result_hashes(ac, existing_msg,
4034 "ntPwdHistory",
4035 &io->o.nt_history);
4036 io->o.supplemental = ldb_msg_find_ldb_val(existing_msg,
4037 "supplementalCredentials");
4039 if (io->o.supplemental != NULL) {
4040 enum ndr_err_code ndr_err;
4042 ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac,
4043 &io->o.scb,
4044 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
4045 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4046 status = ndr_map_error2ntstatus(ndr_err);
4047 ldb_asprintf_errstring(ldb,
4048 "setup_io: failed to pull "
4049 "old supplementalCredentialsBlob: %s",
4050 nt_errstr(status));
4051 return LDB_ERR_OPERATIONS_ERROR;
4056 * If this account requires a smartcard for login, we don't
4057 * attempt a comparison with the old password.
4059 if (io->u.userAccountControl & UF_SMARTCARD_REQUIRED) {
4060 return LDB_SUCCESS;
4064 * Extract the old ENCTYPE_AES256_CTS_HMAC_SHA1_96
4065 * value from the supplementalCredentials.
4067 krb5_ret = dsdb_extract_aes_256_key(io->smb_krb5_context->krb5_context,
4068 io->ac,
4069 ldb,
4070 existing_msg,
4071 io->u.userAccountControl,
4072 NULL, /* kvno */
4073 &kvno, /* kvno_out */
4074 &key_blob,
4075 &salt_blob);
4076 if (krb5_ret == ENOENT) {
4078 * If there is no old AES hash (perhaps an imported DB with
4079 * just unicodePwd) then we just won't have an old
4080 * password to compare to if there is no NT hash
4082 return LDB_SUCCESS;
4084 if (krb5_ret) {
4085 ldb_asprintf_errstring(ldb,
4086 "setup_io: "
4087 "extraction of salt for old aes256-cts-hmac-sha1-96 key failed: %s",
4088 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
4089 krb5_ret, io->ac));
4090 return LDB_ERR_OPERATIONS_ERROR;
4093 io->o.salt = salt_blob;
4094 io->o.aes_256 = key_blob;
4095 io->o.kvno = kvno;
4098 return LDB_SUCCESS;
4101 static struct ph_context *ph_init_context(struct ldb_module *module,
4102 struct ldb_request *req,
4103 bool userPassword,
4104 bool update_password)
4106 struct ldb_context *ldb;
4107 struct ph_context *ac;
4108 struct loadparm_context *lp_ctx = NULL;
4110 ldb = ldb_module_get_ctx(module);
4112 ac = talloc_zero(req, struct ph_context);
4113 if (ac == NULL) {
4114 ldb_set_errstring(ldb, "Out of Memory");
4115 return NULL;
4118 ac->module = module;
4119 ac->req = req;
4120 ac->userPassword = userPassword;
4121 ac->update_password = update_password;
4122 ac->update_lastset = true;
4124 lp_ctx = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"),
4125 struct loadparm_context);
4126 ac->gpg_key_ids = lpcfg_password_hash_gpg_key_ids(lp_ctx);
4127 ac->userPassword_schemes
4128 = lpcfg_password_hash_userpassword_schemes(lp_ctx);
4129 return ac;
4132 static void ph_apply_controls(struct ph_context *ac)
4134 struct ldb_control *ctrl;
4136 ac->change_status = false;
4137 ctrl = ldb_request_get_control(ac->req,
4138 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID);
4139 if (ctrl != NULL) {
4140 ac->change_status = true;
4142 /* Mark the "change status" control as uncritical (done) */
4143 ctrl->critical = false;
4146 ac->hash_values = false;
4147 ctrl = ldb_request_get_control(ac->req,
4148 DSDB_CONTROL_PASSWORD_HASH_VALUES_OID);
4149 if (ctrl != NULL) {
4150 ac->hash_values = true;
4152 /* Mark the "hash values" control as uncritical (done) */
4153 ctrl->critical = false;
4156 ctrl = ldb_request_get_control(ac->req,
4157 DSDB_CONTROL_PASSWORD_CHANGE_OLD_PW_CHECKED_OID);
4158 if (ctrl != NULL) {
4159 ac->change = talloc_get_type_abort(ctrl->data, struct dsdb_control_password_change);
4161 /* Mark the "change" control as uncritical (done) */
4162 ctrl->critical = false;
4165 ac->pwd_last_set_bypass = false;
4166 ctrl = ldb_request_get_control(ac->req,
4167 DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID);
4168 if (ctrl != NULL) {
4169 ac->pwd_last_set_bypass = true;
4171 /* Mark the "bypass pwdLastSet" control as uncritical (done) */
4172 ctrl->critical = false;
4175 ac->pwd_last_set_default = false;
4176 ctrl = ldb_request_get_control(ac->req,
4177 DSDB_CONTROL_PASSWORD_DEFAULT_LAST_SET_OID);
4178 if (ctrl != NULL) {
4179 ac->pwd_last_set_default = true;
4181 /* Mark the "bypass pwdLastSet" control as uncritical (done) */
4182 ctrl->critical = false;
4185 ac->smartcard_reset = false;
4186 ctrl = ldb_request_get_control(ac->req,
4187 DSDB_CONTROL_PASSWORD_USER_ACCOUNT_CONTROL_OID);
4188 if (ctrl != NULL) {
4189 struct dsdb_control_password_user_account_control *uac = NULL;
4190 uint32_t added_flags = 0;
4192 uac = talloc_get_type_abort(ctrl->data,
4193 struct dsdb_control_password_user_account_control);
4195 added_flags = uac->new_flags & ~uac->old_flags;
4197 if (added_flags & UF_SMARTCARD_REQUIRED) {
4198 ac->smartcard_reset = true;
4201 /* Mark the "smartcard required" control as uncritical (done) */
4202 ctrl->critical = false;
4205 ac->kdc_reset_smartcard_account_password = false;
4206 ctrl = ldb_request_get_control(ac->req,
4207 DSDB_CONTROL_PASSWORD_KDC_RESET_SMARTCARD_ACCOUNT_PASSWORD);
4208 if (ctrl != NULL) {
4209 ac->kdc_reset_smartcard_account_password = true;
4211 /* Mark KDC running ResetSmartCardAccountPassword control as uncritical (done) */
4212 ctrl->critical = false;
4217 static int ph_op_callback(struct ldb_request *req, struct ldb_reply *ares)
4219 struct ph_context *ac;
4221 ac = talloc_get_type(req->context, struct ph_context);
4223 if (!ares) {
4224 return ldb_module_done(ac->req, NULL, NULL,
4225 LDB_ERR_OPERATIONS_ERROR);
4228 if (ares->type == LDB_REPLY_REFERRAL) {
4229 return ldb_module_send_referral(ac->req, ares->referral);
4232 if ((ares->error != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
4233 /* On success and trivial errors a status control is being
4234 * added (used for example by the "samdb_set_password" call) */
4235 ldb_reply_add_control(ares,
4236 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
4237 false,
4238 ac->status);
4241 if (ares->error != LDB_SUCCESS) {
4242 return ldb_module_done(ac->req, ares->controls,
4243 ares->response, ares->error);
4246 if (ares->type != LDB_REPLY_DONE) {
4247 talloc_free(ares);
4248 return ldb_module_done(ac->req, NULL, NULL,
4249 LDB_ERR_OPERATIONS_ERROR);
4252 return ldb_module_done(ac->req, ares->controls,
4253 ares->response, ares->error);
4256 static int password_hash_add_do_add(struct ph_context *ac);
4257 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares);
4258 static int password_hash_mod_search_self(struct ph_context *ac);
4259 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares);
4260 static int password_hash_mod_do_mod(struct ph_context *ac);
4263 * LDB callback handler for searching for a user's PSO. Once we have all the
4264 * Password Settings that apply to the user, we can continue with the modify
4265 * operation
4267 static int get_pso_data_callback(struct ldb_request *req,
4268 struct ldb_reply *ares)
4270 struct ldb_context *ldb = NULL;
4271 struct ph_context *ac = NULL;
4272 bool domain_complexity = true;
4273 bool pso_complexity = true;
4274 struct dsdb_user_pwd_settings *settings = NULL;
4275 int ret = LDB_SUCCESS;
4277 ac = talloc_get_type(req->context, struct ph_context);
4278 ldb = ldb_module_get_ctx(ac->module);
4280 if (!ares) {
4281 ret = LDB_ERR_OPERATIONS_ERROR;
4282 goto done;
4284 if (ares->error != LDB_SUCCESS) {
4285 return ldb_module_done(ac->req, ares->controls,
4286 ares->response, ares->error);
4289 switch (ares->type) {
4290 case LDB_REPLY_ENTRY:
4292 /* check status was initialized by the domain query */
4293 if (ac->status == NULL) {
4294 talloc_free(ares);
4295 ldb_set_errstring(ldb, "Uninitialized status");
4296 ret = LDB_ERR_OPERATIONS_ERROR;
4297 goto done;
4301 * use the PSO's values instead of the domain defaults (the PSO
4302 * attributes should always exist, but use the domain default
4303 * values as a fallback).
4305 settings = &ac->status->domain_data;
4306 settings->store_cleartext =
4307 ldb_msg_find_attr_as_bool(ares->message,
4308 "msDS-PasswordReversibleEncryptionEnabled",
4309 settings->store_cleartext);
4311 settings->pwdHistoryLength =
4312 ldb_msg_find_attr_as_uint(ares->message,
4313 "msDS-PasswordHistoryLength",
4314 settings->pwdHistoryLength);
4315 settings->maxPwdAge =
4316 ldb_msg_find_attr_as_int64(ares->message,
4317 "msDS-MaximumPasswordAge",
4318 settings->maxPwdAge);
4319 settings->minPwdAge =
4320 ldb_msg_find_attr_as_int64(ares->message,
4321 "msDS-MinimumPasswordAge",
4322 settings->minPwdAge);
4323 settings->minPwdLength =
4324 ldb_msg_find_attr_as_uint(ares->message,
4325 "msDS-MinimumPasswordLength",
4326 settings->minPwdLength);
4327 domain_complexity =
4328 (settings->pwdProperties & DOMAIN_PASSWORD_COMPLEX);
4329 pso_complexity =
4330 ldb_msg_find_attr_as_bool(ares->message,
4331 "msDS-PasswordComplexityEnabled",
4332 domain_complexity);
4334 /* set or clear the complexity bit if required */
4335 if (pso_complexity && !domain_complexity) {
4336 settings->pwdProperties |= DOMAIN_PASSWORD_COMPLEX;
4337 } else if (domain_complexity && !pso_complexity) {
4338 settings->pwdProperties &= ~DOMAIN_PASSWORD_COMPLEX;
4341 if (ac->pso_res != NULL) {
4342 DBG_ERR("Too many PSO results for %s\n",
4343 ldb_dn_get_linearized(ac->search_res->message->dn));
4344 talloc_free(ac->pso_res);
4347 /* store the PSO result (we may need its lockout settings) */
4348 ac->pso_res = talloc_steal(ac, ares);
4349 ret = LDB_SUCCESS;
4350 break;
4352 case LDB_REPLY_REFERRAL:
4353 /* ignore */
4354 talloc_free(ares);
4355 ret = LDB_SUCCESS;
4356 break;
4358 case LDB_REPLY_DONE:
4359 talloc_free(ares);
4362 * perform the next step of the modify operation (this code
4363 * shouldn't get called in the 'user add' case)
4365 if (ac->req->operation == LDB_MODIFY) {
4366 ret = password_hash_mod_do_mod(ac);
4367 } else {
4368 ret = LDB_ERR_OPERATIONS_ERROR;
4370 break;
4373 done:
4374 if (ret != LDB_SUCCESS) {
4375 struct ldb_reply *new_ares;
4377 new_ares = talloc_zero(ac->req, struct ldb_reply);
4378 if (new_ares == NULL) {
4379 ldb_oom(ldb);
4380 return ldb_module_done(ac->req, NULL, NULL,
4381 LDB_ERR_OPERATIONS_ERROR);
4384 new_ares->error = ret;
4385 if ((ret != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
4386 /* On success and trivial errors a status control is being
4387 * added (used for example by the "samdb_set_password" call) */
4388 ldb_reply_add_control(new_ares,
4389 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
4390 false,
4391 ac->status);
4394 return ldb_module_done(ac->req, new_ares->controls,
4395 new_ares->response, new_ares->error);
4398 return LDB_SUCCESS;
4402 * Builds and returns a search request to look up the PSO that applies to
4403 * the user in question. Returns NULL if no PSO applies, or could not be found
4405 static struct ldb_request * build_pso_data_request(struct ph_context *ac)
4407 /* attrs[] is returned from this function in
4408 pso_req->op.search.attrs, so it must be static, as
4409 otherwise the compiler can put it on the stack */
4410 static const char * const attrs[] = { "msDS-PasswordComplexityEnabled",
4411 "msDS-PasswordReversibleEncryptionEnabled",
4412 "msDS-PasswordHistoryLength",
4413 "msDS-MaximumPasswordAge",
4414 "msDS-MinimumPasswordAge",
4415 "msDS-MinimumPasswordLength",
4416 "msDS-LockoutThreshold",
4417 "msDS-LockoutObservationWindow",
4418 NULL };
4419 struct ldb_context *ldb = NULL;
4420 struct ldb_request *pso_req = NULL;
4421 struct ldb_dn *pso_dn = NULL;
4422 TALLOC_CTX *mem_ctx = ac;
4423 int ret;
4425 ldb = ldb_module_get_ctx(ac->module);
4427 /* if a PSO applies to the user, we need to lookup the PSO as well */
4428 pso_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, ac->search_res->message,
4429 "msDS-ResultantPSO");
4430 if (pso_dn == NULL) {
4431 return NULL;
4434 ret = ldb_build_search_req(&pso_req, ldb, mem_ctx, pso_dn,
4435 LDB_SCOPE_BASE, NULL, attrs, NULL,
4436 ac, get_pso_data_callback,
4437 ac->dom_req);
4439 /* log errors, but continue with the default domain settings */
4440 if (ret != LDB_SUCCESS) {
4441 DBG_ERR("Error %d constructing PSO query for user %s\n", ret,
4442 ldb_dn_get_linearized(ac->search_res->message->dn));
4444 LDB_REQ_SET_LOCATION(pso_req);
4445 return pso_req;
4449 static int get_domain_data_callback(struct ldb_request *req,
4450 struct ldb_reply *ares)
4452 struct ldb_context *ldb;
4453 struct ph_context *ac;
4454 struct loadparm_context *lp_ctx;
4455 struct ldb_request *pso_req = NULL;
4456 int ret = LDB_SUCCESS;
4458 ac = talloc_get_type(req->context, struct ph_context);
4459 ldb = ldb_module_get_ctx(ac->module);
4461 if (!ares) {
4462 ret = LDB_ERR_OPERATIONS_ERROR;
4463 goto done;
4465 if (ares->error != LDB_SUCCESS) {
4466 return ldb_module_done(ac->req, ares->controls,
4467 ares->response, ares->error);
4470 switch (ares->type) {
4471 case LDB_REPLY_ENTRY:
4472 if (ac->status != NULL) {
4473 talloc_free(ares);
4475 ldb_set_errstring(ldb, "Too many results");
4476 ret = LDB_ERR_OPERATIONS_ERROR;
4477 goto done;
4480 /* Setup the "status" structure (used as control later) */
4481 ac->status = talloc_zero(ac->req,
4482 struct dsdb_control_password_change_status);
4483 if (ac->status == NULL) {
4484 talloc_free(ares);
4486 ldb_oom(ldb);
4487 ret = LDB_ERR_OPERATIONS_ERROR;
4488 goto done;
4491 /* Setup the "domain data" structure */
4492 ac->status->domain_data.pwdProperties =
4493 ldb_msg_find_attr_as_uint(ares->message, "pwdProperties", -1);
4494 ac->status->domain_data.pwdHistoryLength =
4495 ldb_msg_find_attr_as_uint(ares->message, "pwdHistoryLength", -1);
4496 ac->status->domain_data.maxPwdAge =
4497 ldb_msg_find_attr_as_int64(ares->message, "maxPwdAge", -1);
4498 ac->status->domain_data.minPwdAge =
4499 ldb_msg_find_attr_as_int64(ares->message, "minPwdAge", -1);
4500 ac->status->domain_data.minPwdLength =
4501 ldb_msg_find_attr_as_uint(ares->message, "minPwdLength", -1);
4502 ac->status->domain_data.store_cleartext =
4503 ac->status->domain_data.pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT;
4505 /* For a domain DN, this puts things in dotted notation */
4506 /* For builtin domains, this will give details for the host,
4507 * but that doesn't really matter, as it's just used for salt
4508 * and kerberos principals, which don't exist here */
4510 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
4511 struct loadparm_context);
4513 ac->status->domain_data.dns_domain = lpcfg_dnsdomain(lp_ctx);
4514 ac->status->domain_data.realm = lpcfg_realm(lp_ctx);
4515 ac->status->domain_data.netbios_domain = lpcfg_sam_name(lp_ctx);
4517 ac->status->reject_reason = SAM_PWD_CHANGE_NO_ERROR;
4519 if (ac->dom_res != NULL) {
4520 talloc_free(ares);
4522 ldb_set_errstring(ldb, "Too many results");
4523 ret = LDB_ERR_OPERATIONS_ERROR;
4524 goto done;
4527 ac->dom_res = talloc_steal(ac, ares);
4528 ret = LDB_SUCCESS;
4529 break;
4531 case LDB_REPLY_REFERRAL:
4532 /* ignore */
4533 talloc_free(ares);
4534 ret = LDB_SUCCESS;
4535 break;
4537 case LDB_REPLY_DONE:
4538 talloc_free(ares);
4539 /* call the next step */
4540 switch (ac->req->operation) {
4541 case LDB_ADD:
4542 ret = password_hash_add_do_add(ac);
4543 break;
4545 case LDB_MODIFY:
4548 * The user may have an optional PSO applied. If so,
4549 * query the PSO to get the Fine-Grained Password Policy
4550 * for the user, before we perform the modify
4552 pso_req = build_pso_data_request(ac);
4553 if (pso_req != NULL) {
4554 ret = ldb_next_request(ac->module, pso_req);
4555 } else {
4557 /* no PSO, so we can perform the modify now */
4558 ret = password_hash_mod_do_mod(ac);
4560 break;
4562 default:
4563 ret = LDB_ERR_OPERATIONS_ERROR;
4564 break;
4566 break;
4569 done:
4570 if (ret != LDB_SUCCESS) {
4571 struct ldb_reply *new_ares;
4573 new_ares = talloc_zero(ac->req, struct ldb_reply);
4574 if (new_ares == NULL) {
4575 ldb_oom(ldb);
4576 return ldb_module_done(ac->req, NULL, NULL,
4577 LDB_ERR_OPERATIONS_ERROR);
4580 new_ares->error = ret;
4581 if ((ret != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
4582 /* On success and trivial errors a status control is being
4583 * added (used for example by the "samdb_set_password" call) */
4584 ldb_reply_add_control(new_ares,
4585 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
4586 false,
4587 ac->status);
4590 return ldb_module_done(ac->req, new_ares->controls,
4591 new_ares->response, new_ares->error);
4594 return LDB_SUCCESS;
4597 static int build_domain_data_request(struct ph_context *ac)
4599 /* attrs[] is returned from this function in
4600 ac->dom_req->op.search.attrs, so it must be static, as
4601 otherwise the compiler can put it on the stack */
4602 struct ldb_context *ldb;
4603 static const char * const attrs[] = { "pwdProperties",
4604 "pwdHistoryLength",
4605 "maxPwdAge",
4606 "minPwdAge",
4607 "minPwdLength",
4608 "lockoutThreshold",
4609 "lockOutObservationWindow",
4610 NULL };
4611 int ret;
4613 ldb = ldb_module_get_ctx(ac->module);
4615 ret = ldb_build_search_req(&ac->dom_req, ldb, ac,
4616 ldb_get_default_basedn(ldb),
4617 LDB_SCOPE_BASE,
4618 NULL, attrs,
4619 NULL,
4620 ac, get_domain_data_callback,
4621 ac->req);
4622 LDB_REQ_SET_LOCATION(ac->dom_req);
4623 return ret;
4626 static int password_hash_needed(struct ldb_module *module,
4627 struct ldb_request *req,
4628 struct ph_context **_ac)
4630 struct ldb_context *ldb = ldb_module_get_ctx(module);
4631 const char *operation = NULL;
4632 const struct ldb_message *msg = NULL;
4633 struct ph_context *ac = NULL;
4634 const char *passwordAttrs[] = {
4635 DSDB_PASSWORD_ATTRIBUTES,
4636 NULL
4638 const char **a = NULL;
4639 unsigned int attr_cnt = 0;
4640 struct ldb_control *bypass = NULL;
4641 struct ldb_control *uac_ctrl = NULL;
4642 bool userPassword = dsdb_user_password_support(module, req, req);
4643 bool update_password = false;
4644 bool processing_needed = false;
4646 *_ac = NULL;
4648 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_needed\n");
4650 switch (req->operation) {
4651 case LDB_ADD:
4652 operation = "add";
4653 msg = req->op.add.message;
4654 break;
4655 case LDB_MODIFY:
4656 operation = "modify";
4657 msg = req->op.mod.message;
4658 break;
4659 default:
4660 return ldb_next_request(module, req);
4663 if (ldb_dn_is_special(msg->dn)) { /* do not manipulate our control entries */
4664 return ldb_next_request(module, req);
4667 bypass = ldb_request_get_control(req,
4668 DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID);
4669 if (bypass != NULL) {
4670 /* Mark the "bypass" control as uncritical (done) */
4671 bypass->critical = false;
4672 ldb_debug(ldb, LDB_DEBUG_TRACE,
4673 "password_hash_needed(%s) (bypassing)\n",
4674 operation);
4675 return password_hash_bypass(module, req);
4678 /* nobody must touch password histories and 'supplementalCredentials' */
4679 if (ldb_msg_find_element(msg, "ntPwdHistory")) {
4680 return LDB_ERR_UNWILLING_TO_PERFORM;
4682 if (ldb_msg_find_element(msg, "lmPwdHistory")) {
4683 return LDB_ERR_UNWILLING_TO_PERFORM;
4685 if (ldb_msg_find_element(msg, "supplementalCredentials")) {
4686 return LDB_ERR_UNWILLING_TO_PERFORM;
4690 * If no part of this touches the 'userPassword' OR 'clearTextPassword'
4691 * OR 'unicodePwd' OR 'dBCSPwd' we don't need to make any changes.
4692 * For password changes/set there should be a 'delete' or a 'modify'
4693 * on these attributes.
4695 for (a = passwordAttrs; *a != NULL; a++) {
4696 if ((!userPassword) && (ldb_attr_cmp(*a, "userPassword") == 0)) {
4697 continue;
4700 if (ldb_msg_find_element(msg, *a) != NULL) {
4701 /* MS-ADTS 3.1.1.3.1.5.2 */
4702 if ((ldb_attr_cmp(*a, "userPassword") == 0) &&
4703 (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003)) {
4704 return LDB_ERR_CONSTRAINT_VIOLATION;
4707 ++attr_cnt;
4711 if (attr_cnt > 0) {
4712 update_password = true;
4713 processing_needed = true;
4716 if (ldb_msg_find_element(msg, "pwdLastSet")) {
4717 processing_needed = true;
4720 uac_ctrl = ldb_request_get_control(req,
4721 DSDB_CONTROL_PASSWORD_USER_ACCOUNT_CONTROL_OID);
4722 if (uac_ctrl != NULL) {
4723 struct dsdb_control_password_user_account_control *uac = NULL;
4724 uint32_t added_flags = 0;
4726 uac = talloc_get_type_abort(uac_ctrl->data,
4727 struct dsdb_control_password_user_account_control);
4729 added_flags = uac->new_flags & ~uac->old_flags;
4731 if (added_flags & UF_SMARTCARD_REQUIRED) {
4732 processing_needed = true;
4736 if (!processing_needed) {
4737 return ldb_next_request(module, req);
4740 ac = ph_init_context(module, req, userPassword, update_password);
4741 if (!ac) {
4742 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
4743 return ldb_operr(ldb);
4745 ph_apply_controls(ac);
4748 * Make a copy in order to apply our modifications
4749 * to the final update
4751 ac->update_msg = ldb_msg_copy_shallow(ac, msg);
4752 if (ac->update_msg == NULL) {
4753 return ldb_oom(ldb);
4756 dsdb_remove_password_related_attrs(ac->update_msg, ac->userPassword);
4758 *_ac = ac;
4759 return LDB_SUCCESS;
4762 static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
4764 struct ldb_context *ldb = ldb_module_get_ctx(module);
4765 struct ph_context *ac = NULL;
4766 int ret;
4768 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_add\n");
4770 ret = password_hash_needed(module, req, &ac);
4771 if (ret != LDB_SUCCESS) {
4772 return ret;
4774 if (ac == NULL) {
4775 return ret;
4778 /* Make sure we are performing the password set action on a (for us)
4779 * valid object. Those are instances of either "user" and/or
4780 * "inetOrgPerson". Otherwise continue with the submodules. */
4781 if ((!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "user"))
4782 && (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "inetOrgPerson"))) {
4784 TALLOC_FREE(ac);
4786 if (ldb_msg_find_element(req->op.add.message, "clearTextPassword") != NULL) {
4787 ldb_set_errstring(ldb,
4788 "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
4789 return LDB_ERR_NO_SUCH_ATTRIBUTE;
4792 return ldb_next_request(module, req);
4795 /* get user domain data */
4796 ret = build_domain_data_request(ac);
4797 if (ret != LDB_SUCCESS) {
4798 return ret;
4801 return ldb_next_request(module, ac->dom_req);
4804 static int password_hash_add_do_add(struct ph_context *ac)
4806 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
4807 struct ldb_request *down_req;
4808 struct setup_password_fields_io io;
4809 int ret;
4811 /* Prepare the internal data structure containing the passwords */
4812 ret = setup_io(ac, ac->req->op.add.message, NULL, &io);
4813 if (ret != LDB_SUCCESS) {
4814 return ret;
4817 ret = setup_password_fields(&io);
4818 if (ret != LDB_SUCCESS) {
4819 return ret;
4822 ret = check_password_restrictions_and_log(&io);
4823 if (ret != LDB_SUCCESS) {
4824 return ret;
4827 ret = setup_smartcard_reset(&io);
4828 if (ret != LDB_SUCCESS) {
4829 return ret;
4832 ret = update_final_msg(&io);
4833 if (ret != LDB_SUCCESS) {
4834 return ret;
4837 ret = ldb_build_add_req(&down_req, ldb, ac,
4838 ac->update_msg,
4839 ac->req->controls,
4840 ac, ph_op_callback,
4841 ac->req);
4842 LDB_REQ_SET_LOCATION(down_req);
4843 if (ret != LDB_SUCCESS) {
4844 return ret;
4847 return ldb_next_request(ac->module, down_req);
4850 static int password_hash_modify(struct ldb_module *module, struct ldb_request *req)
4852 struct ldb_context *ldb = ldb_module_get_ctx(module);
4853 struct ph_context *ac = NULL;
4854 const char *passwordAttrs[] = {DSDB_PASSWORD_ATTRIBUTES, NULL}, **l;
4855 unsigned int del_attr_cnt, add_attr_cnt, rep_attr_cnt;
4856 struct ldb_message_element *passwordAttr;
4857 struct ldb_message *msg;
4858 struct ldb_request *down_req;
4859 struct ldb_control *restore = NULL;
4860 int ret;
4861 unsigned int i = 0;
4863 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_modify\n");
4865 ret = password_hash_needed(module, req, &ac);
4866 if (ret != LDB_SUCCESS) {
4867 return ret;
4869 if (ac == NULL) {
4870 return ret;
4873 /* use a new message structure so that we can modify it */
4874 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
4875 if (msg == NULL) {
4876 return ldb_oom(ldb);
4879 /* - check for single-valued password attributes
4880 * (if not return "CONSTRAINT_VIOLATION")
4881 * - check that for a password change operation one add and one delete
4882 * operation exists
4883 * (if not return "CONSTRAINT_VIOLATION" or "UNWILLING_TO_PERFORM")
4884 * - check that a password change and a password set operation cannot
4885 * be mixed
4886 * (if not return "UNWILLING_TO_PERFORM")
4887 * - remove all password attributes modifications from the first change
4888 * operation (anything without the passwords) - we will make the real
4889 * modification later */
4890 del_attr_cnt = 0;
4891 add_attr_cnt = 0;
4892 rep_attr_cnt = 0;
4893 for (l = passwordAttrs; *l != NULL; l++) {
4894 if ((!ac->userPassword) &&
4895 (ldb_attr_cmp(*l, "userPassword") == 0)) {
4896 continue;
4899 while ((passwordAttr = ldb_msg_find_element(msg, *l)) != NULL) {
4900 unsigned int mtype = LDB_FLAG_MOD_TYPE(passwordAttr->flags);
4901 unsigned int nvalues = passwordAttr->num_values;
4903 if (mtype == LDB_FLAG_MOD_DELETE) {
4904 ++del_attr_cnt;
4906 if (mtype == LDB_FLAG_MOD_ADD) {
4907 ++add_attr_cnt;
4909 if (mtype == LDB_FLAG_MOD_REPLACE) {
4910 ++rep_attr_cnt;
4912 if ((nvalues != 1) && (mtype == LDB_FLAG_MOD_ADD)) {
4913 talloc_free(ac);
4914 ldb_asprintf_errstring(ldb,
4915 "'%s' attribute must have exactly one value on add operations!",
4916 *l);
4917 return LDB_ERR_CONSTRAINT_VIOLATION;
4919 if ((nvalues > 1) && (mtype == LDB_FLAG_MOD_DELETE)) {
4920 talloc_free(ac);
4921 ldb_asprintf_errstring(ldb,
4922 "'%s' attribute must have zero or one value(s) on delete operations!",
4923 *l);
4924 return LDB_ERR_CONSTRAINT_VIOLATION;
4926 ldb_msg_remove_element(msg, passwordAttr);
4929 if ((del_attr_cnt == 0) && (add_attr_cnt > 0)) {
4930 talloc_free(ac);
4931 ldb_set_errstring(ldb,
4932 "Only the add action for a password change specified!");
4933 return LDB_ERR_UNWILLING_TO_PERFORM;
4935 if ((del_attr_cnt > 1) || (add_attr_cnt > 1)) {
4936 talloc_free(ac);
4937 ldb_set_errstring(ldb,
4938 "Only one delete and one add action for a password change allowed!");
4939 return LDB_ERR_UNWILLING_TO_PERFORM;
4941 if ((rep_attr_cnt > 0) && ((del_attr_cnt > 0) || (add_attr_cnt > 0))) {
4942 talloc_free(ac);
4943 ldb_set_errstring(ldb,
4944 "Either a password change or a password set operation is allowed!");
4945 return LDB_ERR_UNWILLING_TO_PERFORM;
4948 restore = ldb_request_get_control(req,
4949 DSDB_CONTROL_RESTORE_TOMBSTONE_OID);
4950 if (restore == NULL) {
4952 * A tombstone reanimation generates a double update
4953 * of pwdLastSet.
4955 * So we only remove it without the
4956 * DSDB_CONTROL_RESTORE_TOMBSTONE_OID control.
4958 ldb_msg_remove_attr(msg, "pwdLastSet");
4962 /* if there was nothing else to be modified skip to next step */
4963 if (msg->num_elements == 0) {
4964 return password_hash_mod_search_self(ac);
4968 * Now we apply all changes remaining in msg
4969 * and remove them from our final update_msg
4972 for (i = 0; i < msg->num_elements; i++) {
4973 ldb_msg_remove_attr(ac->update_msg,
4974 msg->elements[i].name);
4977 ret = ldb_build_mod_req(&down_req, ldb, ac,
4978 msg,
4979 req->controls,
4980 ac, ph_modify_callback,
4981 req);
4982 LDB_REQ_SET_LOCATION(down_req);
4983 if (ret != LDB_SUCCESS) {
4984 return ret;
4987 return ldb_next_request(module, down_req);
4990 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
4992 struct ph_context *ac;
4994 ac = talloc_get_type(req->context, struct ph_context);
4996 if (!ares) {
4997 return ldb_module_done(ac->req, NULL, NULL,
4998 LDB_ERR_OPERATIONS_ERROR);
5001 if (ares->type == LDB_REPLY_REFERRAL) {
5002 return ldb_module_send_referral(ac->req, ares->referral);
5005 if (ares->error != LDB_SUCCESS) {
5006 return ldb_module_done(ac->req, ares->controls,
5007 ares->response, ares->error);
5010 if (ares->type != LDB_REPLY_DONE) {
5011 talloc_free(ares);
5012 return ldb_module_done(ac->req, NULL, NULL,
5013 LDB_ERR_OPERATIONS_ERROR);
5016 talloc_free(ares);
5018 return password_hash_mod_search_self(ac);
5021 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares)
5023 struct ldb_context *ldb;
5024 struct ph_context *ac;
5025 int ret = LDB_SUCCESS;
5027 ac = talloc_get_type(req->context, struct ph_context);
5028 ldb = ldb_module_get_ctx(ac->module);
5030 if (!ares) {
5031 ret = LDB_ERR_OPERATIONS_ERROR;
5032 goto done;
5034 if (ares->error != LDB_SUCCESS) {
5035 return ldb_module_done(ac->req, ares->controls,
5036 ares->response, ares->error);
5039 /* we are interested only in the single reply (base search) */
5040 switch (ares->type) {
5041 case LDB_REPLY_ENTRY:
5042 /* Make sure we are performing the password change action on a
5043 * (for us) valid object. Those are instances of either "user"
5044 * and/or "inetOrgPerson". Otherwise continue with the
5045 * submodules. */
5046 if ((!ldb_msg_check_string_attribute(ares->message, "objectClass", "user"))
5047 && (!ldb_msg_check_string_attribute(ares->message, "objectClass", "inetOrgPerson"))) {
5048 talloc_free(ares);
5050 if (ldb_msg_find_element(ac->req->op.mod.message, "clearTextPassword") != NULL) {
5051 ldb_set_errstring(ldb,
5052 "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
5053 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
5054 goto done;
5057 ret = ldb_next_request(ac->module, ac->req);
5058 goto done;
5061 if (ac->search_res != NULL) {
5062 talloc_free(ares);
5064 ldb_set_errstring(ldb, "Too many results");
5065 ret = LDB_ERR_OPERATIONS_ERROR;
5066 goto done;
5069 ac->search_res = talloc_steal(ac, ares);
5070 ret = LDB_SUCCESS;
5071 break;
5073 case LDB_REPLY_REFERRAL:
5074 /* ignore anything else for now */
5075 talloc_free(ares);
5076 ret = LDB_SUCCESS;
5077 break;
5079 case LDB_REPLY_DONE:
5080 talloc_free(ares);
5082 /* get user domain data */
5083 ret = build_domain_data_request(ac);
5084 if (ret != LDB_SUCCESS) {
5085 return ldb_module_done(ac->req, NULL, NULL, ret);
5088 ret = ldb_next_request(ac->module, ac->dom_req);
5089 break;
5092 done:
5093 if (ret != LDB_SUCCESS) {
5094 return ldb_module_done(ac->req, NULL, NULL, ret);
5097 return LDB_SUCCESS;
5100 static int password_hash_mod_search_self(struct ph_context *ac)
5102 struct ldb_context *ldb;
5103 static const char * const attrs[] = { "objectClass",
5104 "userAccountControl",
5105 "msDS-ResultantPSO",
5106 "msDS-User-Account-Control-Computed",
5107 "pwdLastSet",
5108 "sAMAccountName",
5109 "objectSid",
5110 "userPrincipalName",
5111 "displayName",
5112 "supplementalCredentials",
5113 "lmPwdHistory",
5114 "ntPwdHistory",
5115 "dBCSPwd",
5116 "unicodePwd",
5117 "badPasswordTime",
5118 "badPwdCount",
5119 "lockoutTime",
5120 "msDS-KeyVersionNumber",
5121 "msDS-SecondaryKrbTgtNumber",
5122 NULL };
5123 struct ldb_request *search_req;
5124 int ret;
5126 ldb = ldb_module_get_ctx(ac->module);
5128 ret = ldb_build_search_req(&search_req, ldb, ac,
5129 ac->req->op.mod.message->dn,
5130 LDB_SCOPE_BASE,
5131 "(objectclass=*)",
5132 attrs,
5133 NULL,
5134 ac, ph_mod_search_callback,
5135 ac->req);
5136 LDB_REQ_SET_LOCATION(search_req);
5137 if (ret != LDB_SUCCESS) {
5138 return ret;
5141 return ldb_next_request(ac->module, search_req);
5144 static int password_hash_mod_do_mod(struct ph_context *ac)
5146 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
5147 struct ldb_request *mod_req;
5148 struct setup_password_fields_io io;
5149 int ret;
5151 /* Prepare the internal data structure containing the passwords */
5152 ret = setup_io(ac, ac->req->op.mod.message,
5153 ac->search_res->message, &io);
5154 if (ret != LDB_SUCCESS) {
5155 return ret;
5158 ret = setup_password_fields(&io);
5159 if (ret != LDB_SUCCESS) {
5160 return ret;
5163 ret = check_password_restrictions_and_log(&io);
5164 if (ret != LDB_SUCCESS) {
5165 return ret;
5168 ret = setup_smartcard_reset(&io);
5169 if (ret != LDB_SUCCESS) {
5170 return ret;
5173 ret = update_final_msg(&io);
5174 if (ret != LDB_SUCCESS) {
5175 return ret;
5178 ret = ldb_build_mod_req(&mod_req, ldb, ac,
5179 ac->update_msg,
5180 ac->req->controls,
5181 ac, ph_op_callback,
5182 ac->req);
5183 LDB_REQ_SET_LOCATION(mod_req);
5184 if (ret != LDB_SUCCESS) {
5185 return ret;
5188 return ldb_next_request(ac->module, mod_req);
5191 static const struct ldb_module_ops ldb_password_hash_module_ops = {
5192 .name = "password_hash",
5193 .add = password_hash_add,
5194 .modify = password_hash_modify
5197 int ldb_password_hash_module_init(const char *version)
5199 #ifdef ENABLE_GPGME
5200 const char *gversion = NULL;
5201 #endif /* ENABLE_GPGME */
5203 LDB_MODULE_CHECK_VERSION(version);
5205 #ifdef ENABLE_GPGME
5207 * Note: this sets a SIGPIPE handler
5208 * if none is active already. See:
5209 * https://www.gnupg.org/documentation/manuals/gpgme/Signal-Handling.html#Signal-Handling
5211 gversion = gpgme_check_version(MINIMUM_GPGME_VERSION);
5212 if (gversion == NULL) {
5213 fprintf(stderr, "%s() in %s version[%s]: "
5214 "gpgme_check_version(%s) not available, "
5215 "gpgme_check_version(NULL) => '%s'\n",
5216 __func__, __FILE__, version,
5217 MINIMUM_GPGME_VERSION, gpgme_check_version(NULL));
5218 return LDB_ERR_UNAVAILABLE;
5220 #endif /* ENABLE_GPGME */
5222 return ldb_register_module(&ldb_password_hash_module_ops);