4 Copyright (C) Simo Sorce 2004-2008
5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2006
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Stefan Metzmacher 2007-2010
8 Copyright (C) Matthias Dieter Wallnöfer 2009-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 * Component: ldb password_hash module
29 * Description: correctly handle AD password changes fields
31 * Author: Andrew Bartlett
32 * Author: Stefan Metzmacher
36 #include "ldb_module.h"
37 #include "libcli/auth/libcli_auth.h"
38 #include "libcli/security/dom_sid.h"
39 #include "system/kerberos.h"
40 #include "auth/kerberos/kerberos.h"
41 #include "dsdb/samdb/samdb.h"
42 #include "dsdb/samdb/ldb_modules/util.h"
43 #include "dsdb/samdb/ldb_modules/password_modules.h"
44 #include "librpc/gen_ndr/ndr_drsblobs.h"
45 #include "../lib/crypto/crypto.h"
46 #include "param/param.h"
47 #include "lib/krb5_wrap/krb5_samba.h"
54 /* If we have decided there is a reason to work on this request, then
55 * setup all the password hash types correctly.
57 * If we haven't the hashes yet but the password given as plain-text (attributes
58 * 'unicodePwd', 'userPassword' and 'clearTextPassword') we have to check for
59 * the constraints. Once this is done, we calculate the password hashes.
61 * Notice: unlike the real AD which only supports the UTF16 special based
62 * 'unicodePwd' and the UTF8 based 'userPassword' plaintext attribute we
63 * understand also a UTF16 based 'clearTextPassword' one.
64 * The latter is also accessible through LDAP so it can also be set by external
65 * tools and scripts. But be aware that this isn't portable on non SAMBA 4 ADs!
67 * Also when the module receives only the password hashes (possible through
68 * specifying an internal LDB control - for security reasons) some checks are
69 * performed depending on the operation mode (see below) (e.g. if the password
70 * has been in use before if the password memory policy was activated).
72 * Attention: There is a difference between "modify" and "reset" operations
73 * (see MS-ADTS 3.1.1.3.1.5). If the client sends a "add" and "remove"
74 * operation for a password attribute we thread this as a "modify"; if it sends
75 * only a "replace" one we have an (administrative) reset.
77 * Finally, if the administrator has requested that a password history
78 * be maintained, then this should also be written out.
82 /* TODO: [consider always MS-ADTS 3.1.1.3.1.5]
83 * - Check for right connection encryption
86 /* Notice: Definition of "dsdb_control_password_change_status" moved into
90 struct ldb_module *module;
91 struct ldb_request *req;
93 struct ldb_request *dom_req;
94 struct ldb_reply *dom_res;
96 struct ldb_reply *search_res;
98 struct ldb_message *update_msg;
100 struct dsdb_control_password_change_status *status;
101 struct dsdb_control_password_change *change;
103 const char **gpg_key_ids;
109 bool update_password;
111 bool pwd_last_set_bypass;
112 bool pwd_last_set_default;
113 bool smartcard_reset;
117 struct setup_password_fields_io {
118 struct ph_context *ac;
120 struct smb_krb5_context *smb_krb5_context;
122 /* infos about the user account */
124 uint32_t userAccountControl;
126 const char *sAMAccountName;
127 const char *user_principal_name;
130 uint32_t restrictions;
133 /* new credentials and old given credentials */
134 struct setup_password_fields_given {
135 const struct ldb_val *cleartext_utf8;
136 const struct ldb_val *cleartext_utf16;
137 struct samr_Password *nt_hash;
138 struct samr_Password *lm_hash;
141 /* old credentials */
143 struct samr_Password *nt_hash;
144 struct samr_Password *lm_hash;
145 uint32_t nt_history_len;
146 struct samr_Password *nt_history;
147 uint32_t lm_history_len;
148 struct samr_Password *lm_history;
149 const struct ldb_val *supplemental;
150 struct supplementalCredentialsBlob scb;
153 /* generated credentials */
155 struct samr_Password *nt_hash;
156 struct samr_Password *lm_hash;
157 uint32_t nt_history_len;
158 struct samr_Password *nt_history;
159 uint32_t lm_history_len;
160 struct samr_Password *lm_history;
166 struct ldb_val supplemental;
171 static int msg_find_old_and_new_pwd_val(const struct ldb_message *msg,
173 enum ldb_request_type operation,
174 const struct ldb_val **new_val,
175 const struct ldb_val **old_val);
177 static int password_hash_bypass(struct ldb_module *module, struct ldb_request *request)
179 struct ldb_context *ldb = ldb_module_get_ctx(module);
180 const struct ldb_message *msg;
181 struct ldb_message_element *nte;
182 struct ldb_message_element *lme;
183 struct ldb_message_element *nthe;
184 struct ldb_message_element *lmhe;
185 struct ldb_message_element *sce;
187 switch (request->operation) {
189 msg = request->op.add.message;
192 msg = request->op.mod.message;
195 return ldb_next_request(module, request);
198 /* nobody must touch password histories and 'supplementalCredentials' */
199 nte = dsdb_get_single_valued_attr(msg, "unicodePwd",
201 lme = dsdb_get_single_valued_attr(msg, "dBCSPwd",
203 nthe = dsdb_get_single_valued_attr(msg, "ntPwdHistory",
205 lmhe = dsdb_get_single_valued_attr(msg, "lmPwdHistory",
207 sce = dsdb_get_single_valued_attr(msg, "supplementalCredentials",
210 #define CHECK_HASH_ELEMENT(e, min, max) do {\
211 if (e && e->num_values) { \
212 unsigned int _count; \
213 if (e->num_values != 1) { \
214 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
215 "num_values != 1"); \
217 if ((e->values[0].length % 16) != 0) { \
218 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
219 "length % 16 != 0"); \
221 _count = e->values[0].length / 16; \
222 if (_count < min) { \
223 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
226 if (_count > max) { \
227 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
233 CHECK_HASH_ELEMENT(nte, 1, 1);
234 CHECK_HASH_ELEMENT(lme, 1, 1);
235 CHECK_HASH_ELEMENT(nthe, 1, INT32_MAX);
236 CHECK_HASH_ELEMENT(lmhe, 1, INT32_MAX);
238 if (sce && sce->num_values) {
239 enum ndr_err_code ndr_err;
240 struct supplementalCredentialsBlob *scb;
241 struct supplementalCredentialsPackage *scpp = NULL;
242 struct supplementalCredentialsPackage *scpk = NULL;
243 struct supplementalCredentialsPackage *scpkn = NULL;
244 struct supplementalCredentialsPackage *scpct = NULL;
245 DATA_BLOB scpbp = data_blob_null;
246 DATA_BLOB scpbk = data_blob_null;
247 DATA_BLOB scpbkn = data_blob_null;
248 DATA_BLOB scpbct = data_blob_null;
252 if (sce->num_values != 1) {
253 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
257 scb = talloc_zero(request, struct supplementalCredentialsBlob);
259 return ldb_module_oom(module);
262 ndr_err = ndr_pull_struct_blob_all(&sce->values[0], scb, scb,
263 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
264 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
265 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
266 "ndr_pull_struct_blob_all");
269 if (scb->sub.num_packages < 2) {
270 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
274 for (i=0; i < scb->sub.num_packages; i++) {
277 subblob = strhex_to_data_blob(scb, scb->sub.packages[i].data);
278 if (subblob.data == NULL) {
279 return ldb_module_oom(module);
282 if (strcmp(scb->sub.packages[i].name, "Packages") == 0) {
284 return ldb_error(ldb,
285 LDB_ERR_CONSTRAINT_VIOLATION,
288 scpp = &scb->sub.packages[i];
292 if (strcmp(scb->sub.packages[i].name, "Primary:Kerberos") == 0) {
294 return ldb_error(ldb,
295 LDB_ERR_CONSTRAINT_VIOLATION,
296 "Primary:Kerberos twice");
298 scpk = &scb->sub.packages[i];
302 if (strcmp(scb->sub.packages[i].name, "Primary:Kerberos-Newer-Keys") == 0) {
304 return ldb_error(ldb,
305 LDB_ERR_CONSTRAINT_VIOLATION,
306 "Primary:Kerberos-Newer-Keys twice");
308 scpkn = &scb->sub.packages[i];
312 if (strcmp(scb->sub.packages[i].name, "Primary:CLEARTEXT") == 0) {
314 return ldb_error(ldb,
315 LDB_ERR_CONSTRAINT_VIOLATION,
316 "Primary:CLEARTEXT twice");
318 scpct = &scb->sub.packages[i];
323 data_blob_free(&subblob);
327 return ldb_error(ldb,
328 LDB_ERR_CONSTRAINT_VIOLATION,
329 "Primary:Packages missing");
334 * If Primary:Kerberos is missing w2k8r2 reboots
335 * when a password is changed.
337 return ldb_error(ldb,
338 LDB_ERR_CONSTRAINT_VIOLATION,
339 "Primary:Kerberos missing");
343 struct package_PackagesBlob *p;
346 p = talloc_zero(scb, struct package_PackagesBlob);
348 return ldb_module_oom(module);
351 ndr_err = ndr_pull_struct_blob(&scpbp, p, p,
352 (ndr_pull_flags_fn_t)ndr_pull_package_PackagesBlob);
353 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
354 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
355 "ndr_pull_struct_blob Packages");
358 if (p->names == NULL) {
359 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
360 "Packages names == NULL");
363 for (n = 0; p->names[n]; n++) {
367 if (scb->sub.num_packages != (n + 1)) {
368 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
369 "Packages num_packages != num_names + 1");
376 struct package_PrimaryKerberosBlob *k;
378 k = talloc_zero(scb, struct package_PrimaryKerberosBlob);
380 return ldb_module_oom(module);
383 ndr_err = ndr_pull_struct_blob(&scpbk, k, k,
384 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
385 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
386 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
387 "ndr_pull_struct_blob PrimaryKerberos");
390 if (k->version != 3) {
391 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
392 "PrimaryKerberos version != 3");
395 if (k->ctr.ctr3.salt.string == NULL) {
396 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
397 "PrimaryKerberos salt == NULL");
400 if (strlen(k->ctr.ctr3.salt.string) == 0) {
401 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
402 "PrimaryKerberos strlen(salt) == 0");
405 if (k->ctr.ctr3.num_keys != 2) {
406 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
407 "PrimaryKerberos num_keys != 2");
410 if (k->ctr.ctr3.num_old_keys > k->ctr.ctr3.num_keys) {
411 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
412 "PrimaryKerberos num_old_keys > num_keys");
415 if (k->ctr.ctr3.keys[0].keytype != ENCTYPE_DES_CBC_MD5) {
416 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
417 "PrimaryKerberos key[0] != DES_CBC_MD5");
419 if (k->ctr.ctr3.keys[1].keytype != ENCTYPE_DES_CBC_CRC) {
420 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
421 "PrimaryKerberos key[1] != DES_CBC_CRC");
424 if (k->ctr.ctr3.keys[0].value_len != 8) {
425 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
426 "PrimaryKerberos key[0] value_len != 8");
428 if (k->ctr.ctr3.keys[1].value_len != 8) {
429 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
430 "PrimaryKerberos key[1] value_len != 8");
433 for (i = 0; i < k->ctr.ctr3.num_old_keys; i++) {
434 if (k->ctr.ctr3.old_keys[i].keytype ==
435 k->ctr.ctr3.keys[i].keytype &&
436 k->ctr.ctr3.old_keys[i].value_len ==
437 k->ctr.ctr3.keys[i].value_len) {
441 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
442 "PrimaryKerberos old_keys type/value_len doesn't match");
449 struct package_PrimaryKerberosBlob *k;
451 k = talloc_zero(scb, struct package_PrimaryKerberosBlob);
453 return ldb_module_oom(module);
456 ndr_err = ndr_pull_struct_blob(&scpbkn, k, k,
457 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
458 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
459 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
460 "ndr_pull_struct_blob PrimaryKerberosNeverKeys");
463 if (k->version != 4) {
464 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
465 "KerberosNerverKeys version != 4");
468 if (k->ctr.ctr4.salt.string == NULL) {
469 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
470 "KerberosNewerKeys salt == NULL");
473 if (strlen(k->ctr.ctr4.salt.string) == 0) {
474 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
475 "KerberosNewerKeys strlen(salt) == 0");
478 if (k->ctr.ctr4.num_keys != 4) {
479 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
480 "KerberosNewerKeys num_keys != 2");
483 if (k->ctr.ctr4.num_old_keys > k->ctr.ctr4.num_keys) {
484 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
485 "KerberosNewerKeys num_old_keys > num_keys");
488 if (k->ctr.ctr4.num_older_keys > k->ctr.ctr4.num_old_keys) {
489 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
490 "KerberosNewerKeys num_older_keys > num_old_keys");
493 if (k->ctr.ctr4.keys[0].keytype != ENCTYPE_AES256_CTS_HMAC_SHA1_96) {
494 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
495 "KerberosNewerKeys key[0] != AES256");
497 if (k->ctr.ctr4.keys[1].keytype != ENCTYPE_AES128_CTS_HMAC_SHA1_96) {
498 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
499 "KerberosNewerKeys key[1] != AES128");
501 if (k->ctr.ctr4.keys[2].keytype != ENCTYPE_DES_CBC_MD5) {
502 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
503 "KerberosNewerKeys key[2] != DES_CBC_MD5");
505 if (k->ctr.ctr4.keys[3].keytype != ENCTYPE_DES_CBC_CRC) {
506 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
507 "KerberosNewerKeys key[3] != DES_CBC_CRC");
510 if (k->ctr.ctr4.keys[0].value_len != 32) {
511 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
512 "KerberosNewerKeys key[0] value_len != 32");
514 if (k->ctr.ctr4.keys[1].value_len != 16) {
515 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
516 "KerberosNewerKeys key[1] value_len != 16");
518 if (k->ctr.ctr4.keys[2].value_len != 8) {
519 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
520 "KerberosNewerKeys key[2] value_len != 8");
522 if (k->ctr.ctr4.keys[3].value_len != 8) {
523 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
524 "KerberosNewerKeys key[3] value_len != 8");
529 * Maybe we can check old and older keys here.
530 * But we need to do some tests, if the old keys
531 * can be taken from the PrimaryKerberos blob
532 * (with only des keys), when the domain was upgraded
540 struct package_PrimaryCLEARTEXTBlob *ct;
542 ct = talloc_zero(scb, struct package_PrimaryCLEARTEXTBlob);
544 return ldb_module_oom(module);
547 ndr_err = ndr_pull_struct_blob(&scpbct, ct, ct,
548 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryCLEARTEXTBlob);
549 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
550 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
551 "ndr_pull_struct_blob PrimaryCLEARTEXT");
554 if ((ct->cleartext.length % 2) != 0) {
555 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
556 "PrimaryCLEARTEXT length % 2 != 0");
562 ndr_err = ndr_push_struct_blob(&blob, scb, scb,
563 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
564 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
565 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
566 "ndr_pull_struct_blob_all");
569 if (sce->values[0].length != blob.length) {
570 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
571 "supplementalCredentialsBlob length differ");
574 if (memcmp(sce->values[0].data, blob.data, blob.length) != 0) {
575 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
576 "supplementalCredentialsBlob memcmp differ");
582 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_bypass - validated\n");
583 return ldb_next_request(module, request);
586 /* Get the NT hash, and fill it in as an entry in the password history,
587 and specify it into io->g.nt_hash */
589 static int setup_nt_fields(struct setup_password_fields_io *io)
591 struct ldb_context *ldb;
594 io->g.nt_hash = io->n.nt_hash;
595 ldb = ldb_module_get_ctx(io->ac->module);
597 if (io->ac->status->domain_data.pwdHistoryLength == 0) {
601 /* We might not have an old NT password */
602 io->g.nt_history = talloc_array(io->ac,
603 struct samr_Password,
604 io->ac->status->domain_data.pwdHistoryLength);
605 if (!io->g.nt_history) {
609 for (i = 0; i < MIN(io->ac->status->domain_data.pwdHistoryLength-1,
610 io->o.nt_history_len); i++) {
611 io->g.nt_history[i+1] = io->o.nt_history[i];
613 io->g.nt_history_len = i + 1;
616 io->g.nt_history[0] = *io->g.nt_hash;
619 * TODO: is this correct?
620 * the simular behavior is correct for the lm history case
622 E_md4hash("", io->g.nt_history[0].hash);
628 /* Get the LANMAN hash, and fill it in as an entry in the password history,
629 and specify it into io->g.lm_hash */
631 static int setup_lm_fields(struct setup_password_fields_io *io)
633 struct ldb_context *ldb;
636 io->g.lm_hash = io->n.lm_hash;
637 ldb = ldb_module_get_ctx(io->ac->module);
639 if (io->ac->status->domain_data.pwdHistoryLength == 0) {
643 /* We might not have an old LM password */
644 io->g.lm_history = talloc_array(io->ac,
645 struct samr_Password,
646 io->ac->status->domain_data.pwdHistoryLength);
647 if (!io->g.lm_history) {
651 for (i = 0; i < MIN(io->ac->status->domain_data.pwdHistoryLength-1,
652 io->o.lm_history_len); i++) {
653 io->g.lm_history[i+1] = io->o.lm_history[i];
655 io->g.lm_history_len = i + 1;
658 io->g.lm_history[0] = *io->g.lm_hash;
660 E_deshash("", io->g.lm_history[0].hash);
666 static int setup_kerberos_keys(struct setup_password_fields_io *io)
668 struct ldb_context *ldb;
669 krb5_error_code krb5_ret;
670 krb5_principal salt_principal;
673 krb5_data cleartext_data;
675 ldb = ldb_module_get_ctx(io->ac->module);
676 cleartext_data.data = (char *)io->n.cleartext_utf8->data;
677 cleartext_data.length = io->n.cleartext_utf8->length;
679 /* Many, many thanks to lukeh@padl.com for this
680 * algorithm, described in his Nov 10 2004 mail to
681 * samba-technical@lists.samba.org */
684 * Determine a salting principal
686 if (io->u.is_computer) {
690 name = strlower_talloc(io->ac, io->u.sAMAccountName);
695 if (name[strlen(name)-1] == '$') {
696 name[strlen(name)-1] = '\0';
699 saltbody = talloc_asprintf(io->ac, "%s.%s", name,
700 io->ac->status->domain_data.dns_domain);
705 krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
707 io->ac->status->domain_data.realm,
708 "host", saltbody, NULL);
709 } else if (io->u.user_principal_name) {
710 char *user_principal_name;
713 user_principal_name = talloc_strdup(io->ac, io->u.user_principal_name);
714 if (!user_principal_name) {
718 p = strchr(user_principal_name, '@');
723 krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
725 io->ac->status->domain_data.realm,
726 user_principal_name, NULL);
728 krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
730 io->ac->status->domain_data.realm,
731 io->u.sAMAccountName, NULL);
734 ldb_asprintf_errstring(ldb,
735 "setup_kerberos_keys: "
736 "generation of a salting principal failed: %s",
737 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
739 return LDB_ERR_OPERATIONS_ERROR;
743 * create salt from salt_principal
745 krb5_ret = smb_krb5_get_pw_salt(io->smb_krb5_context->krb5_context,
746 salt_principal, &salt);
747 krb5_free_principal(io->smb_krb5_context->krb5_context, salt_principal);
749 ldb_asprintf_errstring(ldb,
750 "setup_kerberos_keys: "
751 "generation of krb5_salt failed: %s",
752 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
754 return LDB_ERR_OPERATIONS_ERROR;
756 /* create a talloc copy */
757 io->g.salt = talloc_strndup(io->ac,
760 smb_krb5_free_data_contents(io->smb_krb5_context->krb5_context, &salt);
764 /* now use the talloced copy of the salt */
765 salt.data = discard_const(io->g.salt);
766 salt.length = strlen(io->g.salt);
769 * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of
770 * the salt and the cleartext password
772 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
776 ENCTYPE_AES256_CTS_HMAC_SHA1_96,
779 ldb_asprintf_errstring(ldb,
780 "setup_kerberos_keys: "
781 "generation of a aes256-cts-hmac-sha1-96 key failed: %s",
782 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
784 return LDB_ERR_OPERATIONS_ERROR;
786 io->g.aes_256 = data_blob_talloc(io->ac,
788 KRB5_KEY_LENGTH(&key));
789 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
790 if (!io->g.aes_256.data) {
795 * create ENCTYPE_AES128_CTS_HMAC_SHA1_96 key out of
796 * the salt and the cleartext password
798 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
802 ENCTYPE_AES128_CTS_HMAC_SHA1_96,
805 ldb_asprintf_errstring(ldb,
806 "setup_kerberos_keys: "
807 "generation of a aes128-cts-hmac-sha1-96 key failed: %s",
808 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
810 return LDB_ERR_OPERATIONS_ERROR;
812 io->g.aes_128 = data_blob_talloc(io->ac,
814 KRB5_KEY_LENGTH(&key));
815 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
816 if (!io->g.aes_128.data) {
821 * create ENCTYPE_DES_CBC_MD5 key out of
822 * the salt and the cleartext password
824 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
831 ldb_asprintf_errstring(ldb,
832 "setup_kerberos_keys: "
833 "generation of a des-cbc-md5 key failed: %s",
834 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
836 return LDB_ERR_OPERATIONS_ERROR;
838 io->g.des_md5 = data_blob_talloc(io->ac,
840 KRB5_KEY_LENGTH(&key));
841 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
842 if (!io->g.des_md5.data) {
847 * create ENCTYPE_DES_CBC_CRC key out of
848 * the salt and the cleartext password
850 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
857 ldb_asprintf_errstring(ldb,
858 "setup_kerberos_keys: "
859 "generation of a des-cbc-crc key failed: %s",
860 smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
862 return LDB_ERR_OPERATIONS_ERROR;
864 io->g.des_crc = data_blob_talloc(io->ac,
866 KRB5_KEY_LENGTH(&key));
867 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
868 if (!io->g.des_crc.data) {
875 static int setup_primary_kerberos(struct setup_password_fields_io *io,
876 const struct supplementalCredentialsBlob *old_scb,
877 struct package_PrimaryKerberosBlob *pkb)
879 struct ldb_context *ldb;
880 struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3;
881 struct supplementalCredentialsPackage *old_scp = NULL;
882 struct package_PrimaryKerberosBlob _old_pkb;
883 struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL;
885 enum ndr_err_code ndr_err;
887 ldb = ldb_module_get_ctx(io->ac->module);
890 * prepare generation of keys
892 * ENCTYPE_DES_CBC_MD5
893 * ENCTYPE_DES_CBC_CRC
896 pkb3->salt.string = io->g.salt;
898 pkb3->keys = talloc_array(io->ac,
899 struct package_PrimaryKerberosKey3,
905 pkb3->keys[0].keytype = ENCTYPE_DES_CBC_MD5;
906 pkb3->keys[0].value = &io->g.des_md5;
907 pkb3->keys[1].keytype = ENCTYPE_DES_CBC_CRC;
908 pkb3->keys[1].value = &io->g.des_crc;
910 /* initialize the old keys to zero */
911 pkb3->num_old_keys = 0;
912 pkb3->old_keys = NULL;
914 /* if there're no old keys, then we're done */
919 for (i=0; i < old_scb->sub.num_packages; i++) {
920 if (strcmp("Primary:Kerberos", old_scb->sub.packages[i].name) != 0) {
924 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
928 old_scp = &old_scb->sub.packages[i];
931 /* Primary:Kerberos element of supplementalCredentials */
935 blob = strhex_to_data_blob(io->ac, old_scp->data);
940 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
941 ndr_err = ndr_pull_struct_blob(&blob, io->ac, &_old_pkb,
942 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
943 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
944 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
945 ldb_asprintf_errstring(ldb,
946 "setup_primary_kerberos: "
947 "failed to pull old package_PrimaryKerberosBlob: %s",
949 return LDB_ERR_OPERATIONS_ERROR;
952 if (_old_pkb.version != 3) {
953 ldb_asprintf_errstring(ldb,
954 "setup_primary_kerberos: "
955 "package_PrimaryKerberosBlob version[%u] expected[3]",
957 return LDB_ERR_OPERATIONS_ERROR;
960 old_pkb3 = &_old_pkb.ctr.ctr3;
963 /* if we didn't found the old keys we're done */
968 /* fill in the old keys */
969 pkb3->num_old_keys = old_pkb3->num_keys;
970 pkb3->old_keys = old_pkb3->keys;
975 static int setup_primary_kerberos_newer(struct setup_password_fields_io *io,
976 const struct supplementalCredentialsBlob *old_scb,
977 struct package_PrimaryKerberosBlob *pkb)
979 struct ldb_context *ldb;
980 struct package_PrimaryKerberosCtr4 *pkb4 = &pkb->ctr.ctr4;
981 struct supplementalCredentialsPackage *old_scp = NULL;
982 struct package_PrimaryKerberosBlob _old_pkb;
983 struct package_PrimaryKerberosCtr4 *old_pkb4 = NULL;
985 enum ndr_err_code ndr_err;
987 ldb = ldb_module_get_ctx(io->ac->module);
990 * prepare generation of keys
992 * ENCTYPE_AES256_CTS_HMAC_SHA1_96
993 * ENCTYPE_AES128_CTS_HMAC_SHA1_96
994 * ENCTYPE_DES_CBC_MD5
995 * ENCTYPE_DES_CBC_CRC
998 pkb4->salt.string = io->g.salt;
999 pkb4->default_iteration_count = 4096;
1002 pkb4->keys = talloc_array(io->ac,
1003 struct package_PrimaryKerberosKey4,
1006 return ldb_oom(ldb);
1009 pkb4->keys[0].iteration_count = 4096;
1010 pkb4->keys[0].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
1011 pkb4->keys[0].value = &io->g.aes_256;
1012 pkb4->keys[1].iteration_count = 4096;
1013 pkb4->keys[1].keytype = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
1014 pkb4->keys[1].value = &io->g.aes_128;
1015 pkb4->keys[2].iteration_count = 4096;
1016 pkb4->keys[2].keytype = ENCTYPE_DES_CBC_MD5;
1017 pkb4->keys[2].value = &io->g.des_md5;
1018 pkb4->keys[3].iteration_count = 4096;
1019 pkb4->keys[3].keytype = ENCTYPE_DES_CBC_CRC;
1020 pkb4->keys[3].value = &io->g.des_crc;
1022 /* initialize the old keys to zero */
1023 pkb4->num_old_keys = 0;
1024 pkb4->old_keys = NULL;
1025 pkb4->num_older_keys = 0;
1026 pkb4->older_keys = NULL;
1028 /* if there're no old keys, then we're done */
1033 for (i=0; i < old_scb->sub.num_packages; i++) {
1034 if (strcmp("Primary:Kerberos-Newer-Keys", old_scb->sub.packages[i].name) != 0) {
1038 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
1042 old_scp = &old_scb->sub.packages[i];
1045 /* Primary:Kerberos-Newer-Keys element of supplementalCredentials */
1049 blob = strhex_to_data_blob(io->ac, old_scp->data);
1051 return ldb_oom(ldb);
1054 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
1055 ndr_err = ndr_pull_struct_blob(&blob, io->ac,
1057 (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
1058 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1059 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1060 ldb_asprintf_errstring(ldb,
1061 "setup_primary_kerberos_newer: "
1062 "failed to pull old package_PrimaryKerberosBlob: %s",
1064 return LDB_ERR_OPERATIONS_ERROR;
1067 if (_old_pkb.version != 4) {
1068 ldb_asprintf_errstring(ldb,
1069 "setup_primary_kerberos_newer: "
1070 "package_PrimaryKerberosBlob version[%u] expected[4]",
1072 return LDB_ERR_OPERATIONS_ERROR;
1075 old_pkb4 = &_old_pkb.ctr.ctr4;
1078 /* if we didn't found the old keys we're done */
1083 /* fill in the old keys */
1084 pkb4->num_old_keys = old_pkb4->num_keys;
1085 pkb4->old_keys = old_pkb4->keys;
1086 pkb4->num_older_keys = old_pkb4->num_old_keys;
1087 pkb4->older_keys = old_pkb4->old_keys;
1092 static int setup_primary_wdigest(struct setup_password_fields_io *io,
1093 const struct supplementalCredentialsBlob *old_scb,
1094 struct package_PrimaryWDigestBlob *pdb)
1096 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1097 DATA_BLOB sAMAccountName;
1098 DATA_BLOB sAMAccountName_l;
1099 DATA_BLOB sAMAccountName_u;
1100 const char *user_principal_name = io->u.user_principal_name;
1101 DATA_BLOB userPrincipalName;
1102 DATA_BLOB userPrincipalName_l;
1103 DATA_BLOB userPrincipalName_u;
1104 DATA_BLOB netbios_domain;
1105 DATA_BLOB netbios_domain_l;
1106 DATA_BLOB netbios_domain_u;
1107 DATA_BLOB dns_domain;
1108 DATA_BLOB dns_domain_l;
1109 DATA_BLOB dns_domain_u;
1112 DATA_BLOB backslash;
1121 * http://technet2.microsoft.com/WindowsServer/en/library/717b450c-f4a0-4cc9-86f4-cc0633aae5f91033.mspx?mfr=true
1122 * for what precalculated hashes are supposed to be stored...
1124 * I can't reproduce all values which should contain "Digest" as realm,
1125 * am I doing something wrong or is w2k3 just broken...?
1127 * W2K3 fills in following for a user:
1129 * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1130 * sAMAccountName: NewUser2Sam
1131 * userPrincipalName: NewUser2Princ@sub1.w2k3.vmnet1.vm.base
1133 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1134 * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1135 * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1136 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1137 * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1138 * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1139 * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1140 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1141 * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1142 * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1143 * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1144 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1145 * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1146 * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1147 * 221c55284451ae9b3aacaa2a3c86f10f => NewUser2Princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1148 * 74e1be668853d4324d38c07e2acfb8ea => (w2k3 has a bug here!) newuser2princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1149 * e1e244ab7f098e3ae1761be7f9229bbb => NEWUSER2PRINC@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1150 * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1151 * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1152 * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1153 * 31dc704d3640335b2123d4ee28aa1f11 => ??? changes with NewUser2Sam => NewUser1Sam
1154 * 36349f5cecd07320fb3bb0e119230c43 => ??? changes with NewUser2Sam => NewUser1Sam
1155 * 12adf019d037fb535c01fd0608e78d9d => ??? changes with NewUser2Sam => NewUser1Sam
1156 * 6feecf8e724906f3ee1105819c5105a1 => ??? changes with NewUser2Princ => NewUser1Princ
1157 * 6c6911f3de6333422640221b9c51ff1f => ??? changes with NewUser2Princ => NewUser1Princ
1158 * 4b279877e742895f9348ac67a8de2f69 => ??? changes with NewUser2Princ => NewUser1Princ
1159 * db0c6bff069513e3ebb9870d29b57490 => ??? changes with NewUser2Sam => NewUser1Sam
1160 * 45072621e56b1c113a4e04a8ff68cd0e => ??? changes with NewUser2Sam => NewUser1Sam
1161 * 11d1220abc44a9c10cf91ef4a9c1de02 => ??? changes with NewUser2Sam => NewUser1Sam
1163 * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1164 * sAMAccountName: NewUser2Sam
1166 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1167 * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1168 * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1169 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1170 * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1171 * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1172 * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1173 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1174 * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1175 * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1176 * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1177 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1178 * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1179 * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1180 * 8a140d30b6f0a5912735dc1e3bc993b4 => NewUser2Sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1181 * 86d95b2faae6cae4ec261e7fbaccf093 => (here w2k3 is correct) newuser2sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1182 * dfeff1493110220efcdfc6362e5f5450 => NEWUSER2SAM@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1183 * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1184 * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1185 * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1186 * 31dc704d3640335b2123d4ee28aa1f11 => ???M1 changes with NewUser2Sam => NewUser1Sam
1187 * 36349f5cecd07320fb3bb0e119230c43 => ???M1.L changes with newuser2sam => newuser1sam
1188 * 12adf019d037fb535c01fd0608e78d9d => ???M1.U changes with NEWUSER2SAM => NEWUSER1SAM
1189 * 569b4533f2d9e580211dd040e5e360a8 => ???M2 changes with NewUser2Princ => NewUser1Princ
1190 * 52528bddf310a587c5d7e6a9ae2cbb20 => ???M2.L changes with newuser2princ => newuser1princ
1191 * 4f629a4f0361289ca4255ab0f658fcd5 => ???M3 changes with NewUser2Princ => NewUser1Princ (doesn't depend on case of userPrincipal )
1192 * db0c6bff069513e3ebb9870d29b57490 => ???M4 changes with NewUser2Sam => NewUser1Sam
1193 * 45072621e56b1c113a4e04a8ff68cd0e => ???M5 changes with NewUser2Sam => NewUser1Sam (doesn't depend on case of sAMAccountName)
1194 * 11d1220abc44a9c10cf91ef4a9c1de02 => ???M4.U changes with NEWUSER2SAM => NEWUSER1SAM
1198 * sAMAccountName, netbios_domain
1201 .user = &sAMAccountName,
1202 .realm = &netbios_domain,
1205 .user = &sAMAccountName_l,
1206 .realm = &netbios_domain_l,
1209 .user = &sAMAccountName_u,
1210 .realm = &netbios_domain_u,
1213 .user = &sAMAccountName,
1214 .realm = &netbios_domain_u,
1217 .user = &sAMAccountName,
1218 .realm = &netbios_domain_l,
1221 .user = &sAMAccountName_u,
1222 .realm = &netbios_domain_l,
1225 .user = &sAMAccountName_l,
1226 .realm = &netbios_domain_u,
1229 * sAMAccountName, dns_domain
1232 .user = &sAMAccountName,
1233 .realm = &dns_domain,
1236 .user = &sAMAccountName_l,
1237 .realm = &dns_domain_l,
1240 .user = &sAMAccountName_u,
1241 .realm = &dns_domain_u,
1244 .user = &sAMAccountName,
1245 .realm = &dns_domain_u,
1248 .user = &sAMAccountName,
1249 .realm = &dns_domain_l,
1252 .user = &sAMAccountName_u,
1253 .realm = &dns_domain_l,
1256 .user = &sAMAccountName_l,
1257 .realm = &dns_domain_u,
1260 * userPrincipalName, no realm
1263 .user = &userPrincipalName,
1267 * NOTE: w2k3 messes this up, if the user has a real userPrincipalName,
1268 * the fallback to the sAMAccountName based userPrincipalName is correct
1270 .user = &userPrincipalName_l,
1273 .user = &userPrincipalName_u,
1276 * nt4dom\sAMAccountName, no realm
1279 .user = &sAMAccountName,
1280 .nt4dom = &netbios_domain
1283 .user = &sAMAccountName_l,
1284 .nt4dom = &netbios_domain_l
1287 .user = &sAMAccountName_u,
1288 .nt4dom = &netbios_domain_u
1292 * the following ones are guessed depending on the technet2 article
1293 * but not reproducable on a w2k3 server
1295 /* sAMAccountName with "Digest" realm */
1297 .user = &sAMAccountName,
1301 .user = &sAMAccountName_l,
1305 .user = &sAMAccountName_u,
1308 /* userPrincipalName with "Digest" realm */
1310 .user = &userPrincipalName,
1314 .user = &userPrincipalName_l,
1318 .user = &userPrincipalName_u,
1321 /* nt4dom\\sAMAccountName with "Digest" realm */
1323 .user = &sAMAccountName,
1324 .nt4dom = &netbios_domain,
1328 .user = &sAMAccountName_l,
1329 .nt4dom = &netbios_domain_l,
1333 .user = &sAMAccountName_u,
1334 .nt4dom = &netbios_domain_u,
1339 /* prepare DATA_BLOB's used in the combinations array */
1340 sAMAccountName = data_blob_string_const(io->u.sAMAccountName);
1341 sAMAccountName_l = data_blob_string_const(strlower_talloc(io->ac, io->u.sAMAccountName));
1342 if (!sAMAccountName_l.data) {
1343 return ldb_oom(ldb);
1345 sAMAccountName_u = data_blob_string_const(strupper_talloc(io->ac, io->u.sAMAccountName));
1346 if (!sAMAccountName_u.data) {
1347 return ldb_oom(ldb);
1350 /* if the user doesn't have a userPrincipalName, create one (with lower case realm) */
1351 if (!user_principal_name) {
1352 user_principal_name = talloc_asprintf(io->ac, "%s@%s",
1353 io->u.sAMAccountName,
1354 io->ac->status->domain_data.dns_domain);
1355 if (!user_principal_name) {
1356 return ldb_oom(ldb);
1359 userPrincipalName = data_blob_string_const(user_principal_name);
1360 userPrincipalName_l = data_blob_string_const(strlower_talloc(io->ac, user_principal_name));
1361 if (!userPrincipalName_l.data) {
1362 return ldb_oom(ldb);
1364 userPrincipalName_u = data_blob_string_const(strupper_talloc(io->ac, user_principal_name));
1365 if (!userPrincipalName_u.data) {
1366 return ldb_oom(ldb);
1369 netbios_domain = data_blob_string_const(io->ac->status->domain_data.netbios_domain);
1370 netbios_domain_l = data_blob_string_const(strlower_talloc(io->ac,
1371 io->ac->status->domain_data.netbios_domain));
1372 if (!netbios_domain_l.data) {
1373 return ldb_oom(ldb);
1375 netbios_domain_u = data_blob_string_const(strupper_talloc(io->ac,
1376 io->ac->status->domain_data.netbios_domain));
1377 if (!netbios_domain_u.data) {
1378 return ldb_oom(ldb);
1381 dns_domain = data_blob_string_const(io->ac->status->domain_data.dns_domain);
1382 dns_domain_l = data_blob_string_const(io->ac->status->domain_data.dns_domain);
1383 dns_domain_u = data_blob_string_const(io->ac->status->domain_data.realm);
1385 digest = data_blob_string_const("Digest");
1387 delim = data_blob_string_const(":");
1388 backslash = data_blob_string_const("\\");
1390 pdb->num_hashes = ARRAY_SIZE(wdigest);
1391 pdb->hashes = talloc_array(io->ac, struct package_PrimaryWDigestHash,
1394 return ldb_oom(ldb);
1397 for (i=0; i < ARRAY_SIZE(wdigest); i++) {
1400 if (wdigest[i].nt4dom) {
1401 MD5Update(&md5, wdigest[i].nt4dom->data, wdigest[i].nt4dom->length);
1402 MD5Update(&md5, backslash.data, backslash.length);
1404 MD5Update(&md5, wdigest[i].user->data, wdigest[i].user->length);
1405 MD5Update(&md5, delim.data, delim.length);
1406 if (wdigest[i].realm) {
1407 MD5Update(&md5, wdigest[i].realm->data, wdigest[i].realm->length);
1409 MD5Update(&md5, delim.data, delim.length);
1410 MD5Update(&md5, io->n.cleartext_utf8->data, io->n.cleartext_utf8->length);
1411 MD5Final(pdb->hashes[i].hash, &md5);
1417 static int setup_primary_samba_gpg(struct setup_password_fields_io *io,
1418 struct package_PrimarySambaGPGBlob *pgb)
1420 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1423 gpgme_ctx_t ctx = NULL;
1424 size_t num_keys = str_list_length(io->ac->gpg_key_ids);
1425 gpgme_key_t keys[num_keys+1];
1428 gpgme_data_t plain_data = NULL;
1429 gpgme_data_t crypt_data = NULL;
1430 size_t crypt_length = 0;
1431 char *crypt_mem = NULL;
1433 gret = gpgme_new(&ctx);
1434 if (gret != GPG_ERR_NO_ERROR) {
1435 ldb_debug(ldb, LDB_DEBUG_ERROR,
1436 "%s:%s: gret[%u] %s\n",
1437 __location__, __func__,
1438 gret, gpgme_strerror(gret));
1439 return ldb_module_operr(io->ac->module);
1442 gpgme_set_armor(ctx, 1);
1444 gret = gpgme_data_new_from_mem(&plain_data,
1445 (const char *)io->n.cleartext_utf16->data,
1446 io->n.cleartext_utf16->length,
1448 if (gret != GPG_ERR_NO_ERROR) {
1449 ldb_debug(ldb, LDB_DEBUG_ERROR,
1450 "%s:%s: gret[%u] %s\n",
1451 __location__, __func__,
1452 gret, gpgme_strerror(gret));
1454 return ldb_module_operr(io->ac->module);
1456 gret = gpgme_data_new(&crypt_data);
1457 if (gret != GPG_ERR_NO_ERROR) {
1458 ldb_debug(ldb, LDB_DEBUG_ERROR,
1459 "%s:%s: gret[%u] %s\n",
1460 __location__, __func__,
1461 gret, gpgme_strerror(gret));
1462 gpgme_data_release(plain_data);
1464 return ldb_module_operr(io->ac->module);
1467 for (ki = 0; ki < num_keys; ki++) {
1468 const char *key_id = io->ac->gpg_key_ids[ki];
1469 size_t len = strlen(key_id);
1474 ldb_debug(ldb, LDB_DEBUG_FATAL,
1475 "%s:%s: ki[%zu] key_id[%s] strlen < 16, "
1476 "please specify at least the 64bit key id\n",
1477 __location__, __func__,
1479 for (kr = 0; keys[kr] != NULL; kr++) {
1480 gpgme_key_release(keys[kr]);
1482 gpgme_data_release(crypt_data);
1483 gpgme_data_release(plain_data);
1485 return ldb_module_operr(io->ac->module);
1488 gret = gpgme_get_key(ctx, key_id, &keys[ki], 0 /* public key */);
1489 if (gret != GPG_ERR_NO_ERROR) {
1491 ldb_debug(ldb, LDB_DEBUG_ERROR,
1492 "%s:%s: ki[%zu] key_id[%s] gret[%u] %s\n",
1493 __location__, __func__,
1495 gret, gpgme_strerror(gret));
1496 for (kr = 0; keys[kr] != NULL; kr++) {
1497 gpgme_key_release(keys[kr]);
1499 gpgme_data_release(crypt_data);
1500 gpgme_data_release(plain_data);
1502 return ldb_module_operr(io->ac->module);
1507 gret = gpgme_op_encrypt(ctx, keys,
1508 GPGME_ENCRYPT_ALWAYS_TRUST,
1509 plain_data, crypt_data);
1510 gpgme_data_release(plain_data);
1512 for (kr = 0; keys[kr] != NULL; kr++) {
1513 gpgme_key_release(keys[kr]);
1518 if (gret != GPG_ERR_NO_ERROR) {
1519 ldb_debug(ldb, LDB_DEBUG_ERROR,
1520 "%s:%s: gret[%u] %s\n",
1521 __location__, __func__,
1522 gret, gpgme_strerror(gret));
1523 gpgme_data_release(crypt_data);
1524 return ldb_module_operr(io->ac->module);
1527 crypt_mem = gpgme_data_release_and_get_mem(crypt_data, &crypt_length);
1529 if (crypt_mem == NULL) {
1530 return ldb_module_oom(io->ac->module);
1533 pgb->gpg_blob = data_blob_talloc(io->ac,
1534 (const uint8_t *)crypt_mem,
1536 gpgme_free(crypt_mem);
1539 if (pgb->gpg_blob.data == NULL) {
1540 return ldb_module_oom(io->ac->module);
1544 #else /* ENABLE_GPGME */
1545 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1546 "You configured 'password hash gpg key ids', "
1547 "but GPGME support is missing. (%s:%d)",
1548 __FILE__, __LINE__);
1549 return LDB_ERR_UNWILLING_TO_PERFORM;
1550 #endif /* else ENABLE_GPGME */
1553 static int setup_supplemental_field(struct setup_password_fields_io *io)
1555 struct ldb_context *ldb;
1556 struct supplementalCredentialsBlob scb;
1557 struct supplementalCredentialsBlob *old_scb = NULL;
1558 /* Packages + (Kerberos-Newer-Keys, Kerberos, WDigest, CLEARTEXT, SambaGPG) */
1559 uint32_t num_names = 0;
1560 const char *names[1+5];
1561 uint32_t num_packages = 0;
1562 struct supplementalCredentialsPackage packages[1+5];
1564 struct supplementalCredentialsPackage *pp = NULL;
1565 struct package_PackagesBlob pb;
1568 /* Primary:Kerberos-Newer-Keys */
1569 const char **nkn = NULL;
1570 struct supplementalCredentialsPackage *pkn = NULL;
1571 struct package_PrimaryKerberosBlob pknb;
1572 DATA_BLOB pknb_blob;
1574 /* Primary:Kerberos */
1575 const char **nk = NULL;
1576 struct supplementalCredentialsPackage *pk = NULL;
1577 struct package_PrimaryKerberosBlob pkb;
1580 /* Primary:WDigest */
1581 const char **nd = NULL;
1582 struct supplementalCredentialsPackage *pd = NULL;
1583 struct package_PrimaryWDigestBlob pdb;
1586 /* Primary:CLEARTEXT */
1587 const char **nc = NULL;
1588 struct supplementalCredentialsPackage *pc = NULL;
1589 struct package_PrimaryCLEARTEXTBlob pcb;
1592 /* Primary:SambaGPG */
1593 const char **ng = NULL;
1594 struct supplementalCredentialsPackage *pg = NULL;
1595 struct package_PrimarySambaGPGBlob pgb;
1599 enum ndr_err_code ndr_err;
1601 bool do_newer_keys = false;
1602 bool do_cleartext = false;
1603 bool do_samba_gpg = false;
1605 ZERO_STRUCT(zero16);
1607 ZERO_STRUCT(packages);
1609 ldb = ldb_module_get_ctx(io->ac->module);
1611 if (!io->n.cleartext_utf8) {
1613 * when we don't have a cleartext password
1614 * we can't setup a supplementalCredential value
1619 /* if there's an old supplementaCredentials blob then use it */
1620 if (io->o.supplemental) {
1621 if (io->o.scb.sub.signature == SUPPLEMENTAL_CREDENTIALS_SIGNATURE) {
1622 old_scb = &io->o.scb;
1624 ldb_debug(ldb, LDB_DEBUG_ERROR,
1625 "setup_supplemental_field: "
1626 "supplementalCredentialsBlob "
1627 "signature[0x%04X] expected[0x%04X]",
1628 io->o.scb.sub.signature,
1629 SUPPLEMENTAL_CREDENTIALS_SIGNATURE);
1632 /* Per MS-SAMR 3.1.1.8.11.6 we create AES keys if our domain functionality level is 2008 or higher */
1633 do_newer_keys = (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2008);
1635 if (io->ac->status->domain_data.store_cleartext &&
1636 (io->u.userAccountControl & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) {
1637 do_cleartext = true;
1640 if (io->ac->gpg_key_ids != NULL) {
1641 do_samba_gpg = true;
1645 * The ordering is this
1647 * Primary:Kerberos-Newer-Keys (optional)
1650 * Primary:CLEARTEXT (optional)
1651 * Primary:SambaGPG (optional)
1653 * And the 'Packages' package is insert before the last
1656 * Note: it's important that Primary:SambaGPG is added as
1657 * the last element. This is the indication that it matches
1658 * the current password. When a password change happens on
1659 * a Windows DC, it will keep the old Primary:SambaGPG value,
1660 * but as the first element.
1662 if (do_newer_keys) {
1663 /* Primary:Kerberos-Newer-Keys */
1664 nkn = &names[num_names++];
1665 pkn = &packages[num_packages++];
1668 /* Primary:Kerberos */
1669 nk = &names[num_names++];
1670 pk = &packages[num_packages++];
1672 if (!do_cleartext && !do_samba_gpg) {
1674 pp = &packages[num_packages++];
1677 /* Primary:WDigest */
1678 nd = &names[num_names++];
1679 pd = &packages[num_packages++];
1682 if (!do_samba_gpg) {
1684 pp = &packages[num_packages++];
1687 /* Primary:CLEARTEXT */
1688 nc = &names[num_names++];
1689 pc = &packages[num_packages++];
1694 pp = &packages[num_packages++];
1696 /* Primary:SambaGPG */
1697 ng = &names[num_names++];
1698 pg = &packages[num_packages++];
1703 * setup 'Primary:Kerberos-Newer-Keys' element
1705 *nkn = "Kerberos-Newer-Keys";
1707 ret = setup_primary_kerberos_newer(io, old_scb, &pknb);
1708 if (ret != LDB_SUCCESS) {
1712 ndr_err = ndr_push_struct_blob(&pknb_blob, io->ac,
1714 (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
1715 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1716 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1717 ldb_asprintf_errstring(ldb,
1718 "setup_supplemental_field: "
1719 "failed to push package_PrimaryKerberosNeverBlob: %s",
1721 return LDB_ERR_OPERATIONS_ERROR;
1723 pknb_hexstr = data_blob_hex_string_upper(io->ac, &pknb_blob);
1725 return ldb_oom(ldb);
1727 pkn->name = "Primary:Kerberos-Newer-Keys";
1729 pkn->data = pknb_hexstr;
1733 * setup 'Primary:Kerberos' element
1737 ret = setup_primary_kerberos(io, old_scb, &pkb);
1738 if (ret != LDB_SUCCESS) {
1742 ndr_err = ndr_push_struct_blob(&pkb_blob, io->ac,
1744 (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
1745 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1746 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1747 ldb_asprintf_errstring(ldb,
1748 "setup_supplemental_field: "
1749 "failed to push package_PrimaryKerberosBlob: %s",
1751 return LDB_ERR_OPERATIONS_ERROR;
1753 pkb_hexstr = data_blob_hex_string_upper(io->ac, &pkb_blob);
1755 return ldb_oom(ldb);
1757 pk->name = "Primary:Kerberos";
1759 pk->data = pkb_hexstr;
1762 * setup 'Primary:WDigest' element
1766 ret = setup_primary_wdigest(io, old_scb, &pdb);
1767 if (ret != LDB_SUCCESS) {
1771 ndr_err = ndr_push_struct_blob(&pdb_blob, io->ac,
1773 (ndr_push_flags_fn_t)ndr_push_package_PrimaryWDigestBlob);
1774 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1775 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1776 ldb_asprintf_errstring(ldb,
1777 "setup_supplemental_field: "
1778 "failed to push package_PrimaryWDigestBlob: %s",
1780 return LDB_ERR_OPERATIONS_ERROR;
1782 pdb_hexstr = data_blob_hex_string_upper(io->ac, &pdb_blob);
1784 return ldb_oom(ldb);
1786 pd->name = "Primary:WDigest";
1788 pd->data = pdb_hexstr;
1791 * setup 'Primary:CLEARTEXT' element
1796 pcb.cleartext = *io->n.cleartext_utf16;
1798 ndr_err = ndr_push_struct_blob(&pcb_blob, io->ac,
1800 (ndr_push_flags_fn_t)ndr_push_package_PrimaryCLEARTEXTBlob);
1801 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1802 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1803 ldb_asprintf_errstring(ldb,
1804 "setup_supplemental_field: "
1805 "failed to push package_PrimaryCLEARTEXTBlob: %s",
1807 return LDB_ERR_OPERATIONS_ERROR;
1809 pcb_hexstr = data_blob_hex_string_upper(io->ac, &pcb_blob);
1811 return ldb_oom(ldb);
1813 pc->name = "Primary:CLEARTEXT";
1815 pc->data = pcb_hexstr;
1819 * setup 'Primary:SambaGPG' element
1824 ret = setup_primary_samba_gpg(io, &pgb);
1825 if (ret != LDB_SUCCESS) {
1829 ndr_err = ndr_push_struct_blob(&pgb_blob, io->ac, &pgb,
1830 (ndr_push_flags_fn_t)ndr_push_package_PrimarySambaGPGBlob);
1831 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1832 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1833 ldb_asprintf_errstring(ldb,
1834 "setup_supplemental_field: failed to "
1835 "push package_PrimarySambaGPGBlob: %s",
1837 return LDB_ERR_OPERATIONS_ERROR;
1839 pgb_hexstr = data_blob_hex_string_upper(io->ac, &pgb_blob);
1841 return ldb_oom(ldb);
1843 pg->name = "Primary:SambaGPG";
1845 pg->data = pgb_hexstr;
1849 * setup 'Packages' element
1852 ndr_err = ndr_push_struct_blob(&pb_blob, io->ac,
1854 (ndr_push_flags_fn_t)ndr_push_package_PackagesBlob);
1855 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1856 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1857 ldb_asprintf_errstring(ldb,
1858 "setup_supplemental_field: "
1859 "failed to push package_PackagesBlob: %s",
1861 return LDB_ERR_OPERATIONS_ERROR;
1863 pb_hexstr = data_blob_hex_string_upper(io->ac, &pb_blob);
1865 return ldb_oom(ldb);
1867 pp->name = "Packages";
1869 pp->data = pb_hexstr;
1872 * setup 'supplementalCredentials' value
1875 scb.sub.signature = SUPPLEMENTAL_CREDENTIALS_SIGNATURE;
1876 scb.sub.num_packages = num_packages;
1877 scb.sub.packages = packages;
1879 ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac,
1881 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
1882 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1883 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1884 ldb_asprintf_errstring(ldb,
1885 "setup_supplemental_field: "
1886 "failed to push supplementalCredentialsBlob: %s",
1888 return LDB_ERR_OPERATIONS_ERROR;
1894 static int setup_last_set_field(struct setup_password_fields_io *io)
1896 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1897 const struct ldb_message *msg = NULL;
1898 struct timeval tv = { .tv_sec = 0 };
1899 const struct ldb_val *old_val = NULL;
1900 const struct ldb_val *new_val = NULL;
1903 switch (io->ac->req->operation) {
1905 msg = io->ac->req->op.add.message;
1908 msg = io->ac->req->op.mod.message;
1911 return LDB_ERR_OPERATIONS_ERROR;
1915 if (io->ac->pwd_last_set_bypass) {
1916 struct ldb_message_element *el1 = NULL;
1917 struct ldb_message_element *el2 = NULL;
1920 return LDB_ERR_CONSTRAINT_VIOLATION;
1923 el1 = dsdb_get_single_valued_attr(msg, "pwdLastSet",
1924 io->ac->req->operation);
1926 return LDB_ERR_CONSTRAINT_VIOLATION;
1928 el2 = ldb_msg_find_element(msg, "pwdLastSet");
1930 return LDB_ERR_CONSTRAINT_VIOLATION;
1933 return LDB_ERR_CONSTRAINT_VIOLATION;
1936 io->g.last_set = samdb_result_nttime(msg, "pwdLastSet", 0);
1940 ret = msg_find_old_and_new_pwd_val(msg, "pwdLastSet",
1941 io->ac->req->operation,
1942 &new_val, &old_val);
1943 if (ret != LDB_SUCCESS) {
1947 if (old_val != NULL && new_val == NULL) {
1948 ldb_set_errstring(ldb,
1949 "'pwdLastSet' deletion is not allowed!");
1950 return LDB_ERR_UNWILLING_TO_PERFORM;
1953 io->g.last_set = UINT64_MAX;
1954 if (new_val != NULL) {
1955 struct ldb_message *tmp_msg = NULL;
1957 tmp_msg = ldb_msg_new(io->ac);
1958 if (tmp_msg == NULL) {
1959 return ldb_module_oom(io->ac->module);
1962 if (old_val != NULL) {
1963 NTTIME old_last_set = 0;
1965 ret = ldb_msg_add_value(tmp_msg, "oldval",
1967 if (ret != LDB_SUCCESS) {
1971 old_last_set = samdb_result_nttime(tmp_msg,
1974 if (io->u.pwdLastSet != old_last_set) {
1975 return dsdb_module_werror(io->ac->module,
1976 LDB_ERR_NO_SUCH_ATTRIBUTE,
1977 WERR_DS_CANT_REM_MISSING_ATT_VAL,
1978 "setup_last_set_field: old pwdLastSet "
1979 "value not found!");
1983 ret = ldb_msg_add_value(tmp_msg, "newval",
1985 if (ret != LDB_SUCCESS) {
1989 io->g.last_set = samdb_result_nttime(tmp_msg,
1992 } else if (ldb_msg_find_element(msg, "pwdLastSet")) {
1993 ldb_set_errstring(ldb,
1994 "'pwdLastSet' deletion is not allowed!");
1995 return LDB_ERR_UNWILLING_TO_PERFORM;
1996 } else if (io->ac->smartcard_reset) {
1998 * adding UF_SMARTCARD_REQUIRED doesn't update
1999 * pwdLastSet implicitly.
2001 io->ac->update_lastset = false;
2004 /* only 0 or -1 (0xFFFFFFFFFFFFFFFF) are allowed */
2005 switch (io->g.last_set) {
2007 if (!io->ac->pwd_last_set_default) {
2010 if (!io->ac->update_password) {
2015 if (!io->ac->update_password &&
2016 io->u.pwdLastSet != 0 &&
2017 io->u.pwdLastSet != UINT64_MAX)
2020 * Just setting pwdLastSet to -1, while not changing
2021 * any password field has no effect if pwdLastSet
2022 * is already non-zero.
2024 io->ac->update_lastset = false;
2027 /* -1 means set it as now */
2029 io->g.last_set = timeval_to_nttime(&tv);
2032 return dsdb_module_werror(io->ac->module,
2034 WERR_INVALID_PARAMETER,
2035 "setup_last_set_field: "
2036 "pwdLastSet must be 0 or -1 only!");
2039 if (io->ac->req->operation == LDB_ADD) {
2041 * We always need to store the value on add
2047 if (io->g.last_set == io->u.pwdLastSet) {
2049 * Just setting pwdLastSet to 0, is no-op if it's already 0.
2051 io->ac->update_lastset = false;
2057 static int setup_given_passwords(struct setup_password_fields_io *io,
2058 struct setup_password_fields_given *g)
2060 struct ldb_context *ldb;
2063 ldb = ldb_module_get_ctx(io->ac->module);
2065 if (g->cleartext_utf8) {
2066 struct ldb_val *cleartext_utf16_blob;
2068 cleartext_utf16_blob = talloc(io->ac, struct ldb_val);
2069 if (!cleartext_utf16_blob) {
2070 return ldb_oom(ldb);
2072 if (!convert_string_talloc(io->ac,
2074 g->cleartext_utf8->data,
2075 g->cleartext_utf8->length,
2076 (void *)&cleartext_utf16_blob->data,
2077 &cleartext_utf16_blob->length)) {
2078 if (g->cleartext_utf8->length != 0) {
2079 talloc_free(cleartext_utf16_blob);
2080 ldb_asprintf_errstring(ldb,
2081 "setup_password_fields: "
2082 "failed to generate UTF16 password from cleartext UTF8 one for user '%s'!",
2083 io->u.sAMAccountName);
2084 return LDB_ERR_CONSTRAINT_VIOLATION;
2086 /* passwords with length "0" are valid! */
2087 cleartext_utf16_blob->data = NULL;
2088 cleartext_utf16_blob->length = 0;
2091 g->cleartext_utf16 = cleartext_utf16_blob;
2092 } else if (g->cleartext_utf16) {
2093 struct ldb_val *cleartext_utf8_blob;
2095 cleartext_utf8_blob = talloc(io->ac, struct ldb_val);
2096 if (!cleartext_utf8_blob) {
2097 return ldb_oom(ldb);
2099 if (!convert_string_talloc(io->ac,
2100 CH_UTF16MUNGED, CH_UTF8,
2101 g->cleartext_utf16->data,
2102 g->cleartext_utf16->length,
2103 (void *)&cleartext_utf8_blob->data,
2104 &cleartext_utf8_blob->length)) {
2105 if (g->cleartext_utf16->length != 0) {
2106 /* We must bail out here, the input wasn't even
2107 * a multiple of 2 bytes */
2108 talloc_free(cleartext_utf8_blob);
2109 ldb_asprintf_errstring(ldb,
2110 "setup_password_fields: "
2111 "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)!",
2112 io->u.sAMAccountName);
2113 return LDB_ERR_CONSTRAINT_VIOLATION;
2115 /* passwords with length "0" are valid! */
2116 cleartext_utf8_blob->data = NULL;
2117 cleartext_utf8_blob->length = 0;
2120 g->cleartext_utf8 = cleartext_utf8_blob;
2123 if (g->cleartext_utf16) {
2124 struct samr_Password *nt_hash;
2126 nt_hash = talloc(io->ac, struct samr_Password);
2128 return ldb_oom(ldb);
2130 g->nt_hash = nt_hash;
2132 /* compute the new nt hash */
2133 mdfour(nt_hash->hash,
2134 g->cleartext_utf16->data,
2135 g->cleartext_utf16->length);
2138 if (g->cleartext_utf8) {
2139 struct samr_Password *lm_hash;
2141 lm_hash = talloc(io->ac, struct samr_Password);
2143 return ldb_oom(ldb);
2146 /* compute the new lm hash */
2147 ok = E_deshash((char *)g->cleartext_utf8->data, lm_hash->hash);
2149 g->lm_hash = lm_hash;
2151 talloc_free(lm_hash);
2158 static int setup_password_fields(struct setup_password_fields_io *io)
2160 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2161 struct loadparm_context *lp_ctx =
2162 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2163 struct loadparm_context);
2166 ret = setup_last_set_field(io);
2167 if (ret != LDB_SUCCESS) {
2171 if (!io->ac->update_password) {
2175 /* transform the old password (for password changes) */
2176 ret = setup_given_passwords(io, &io->og);
2177 if (ret != LDB_SUCCESS) {
2181 /* transform the new password */
2182 ret = setup_given_passwords(io, &io->n);
2183 if (ret != LDB_SUCCESS) {
2187 if (io->n.cleartext_utf8) {
2188 ret = setup_kerberos_keys(io);
2189 if (ret != LDB_SUCCESS) {
2194 ret = setup_nt_fields(io);
2195 if (ret != LDB_SUCCESS) {
2199 if (lpcfg_lanman_auth(lp_ctx)) {
2200 ret = setup_lm_fields(io);
2201 if (ret != LDB_SUCCESS) {
2205 io->g.lm_hash = NULL;
2206 io->g.lm_history_len = 0;
2209 ret = setup_supplemental_field(io);
2210 if (ret != LDB_SUCCESS) {
2217 static int setup_smartcard_reset(struct setup_password_fields_io *io)
2219 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2220 struct loadparm_context *lp_ctx = talloc_get_type(
2221 ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
2222 struct supplementalCredentialsBlob scb = { .__ndr_size = 0 };
2223 enum ndr_err_code ndr_err;
2225 if (!io->ac->smartcard_reset) {
2229 io->g.nt_hash = talloc(io->ac, struct samr_Password);
2230 if (io->g.nt_hash == NULL) {
2231 return ldb_module_oom(io->ac->module);
2233 generate_secret_buffer(io->g.nt_hash->hash,
2234 sizeof(io->g.nt_hash->hash));
2235 io->g.nt_history_len = 0;
2237 if (lpcfg_lanman_auth(lp_ctx)) {
2238 io->g.lm_hash = talloc(io->ac, struct samr_Password);
2239 if (io->g.lm_hash == NULL) {
2240 return ldb_module_oom(io->ac->module);
2242 generate_secret_buffer(io->g.lm_hash->hash,
2243 sizeof(io->g.lm_hash->hash));
2245 io->g.lm_hash = NULL;
2247 io->g.lm_history_len = 0;
2250 * We take the "old" value and store it
2251 * with num_packages = 0.
2253 * On "add" we have scb.sub.signature == 0, which
2256 * [0000] 00 00 00 00 00 00 00 00 00 00 00 00 00
2258 * On modify it's likely to be scb.sub.signature ==
2259 * SUPPLEMENTAL_CREDENTIALS_SIGNATURE (0x0050), which results in
2262 * [0000] 00 00 00 00 62 00 00 00 00 00 00 00 20 00 20 00
2263 * [0010] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2264 * [0020] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2265 * [0030] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2266 * [0040] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2267 * [0050] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2268 * [0060] 20 00 20 00 20 00 20 00 20 00 20 00 50 00 00
2270 * See https://bugzilla.samba.org/show_bug.cgi?id=11441
2271 * and ndr_{push,pull}_supplementalCredentialsSubBlob().
2274 scb.sub.num_packages = 0;
2277 * setup 'supplementalCredentials' value without packages
2279 ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac,
2281 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
2282 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2283 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2284 ldb_asprintf_errstring(ldb,
2285 "setup_smartcard_reset: "
2286 "failed to push supplementalCredentialsBlob: %s",
2288 return LDB_ERR_OPERATIONS_ERROR;
2291 io->ac->update_password = true;
2295 static int make_error_and_update_badPwdCount(struct setup_password_fields_io *io)
2297 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2298 struct ldb_message *mod_msg = NULL;
2302 status = dsdb_update_bad_pwd_count(io->ac, ldb,
2303 io->ac->search_res->message,
2304 io->ac->dom_res->message,
2306 if (!NT_STATUS_IS_OK(status)) {
2310 if (mod_msg == NULL) {
2315 * OK, horrible semantics ahead.
2317 * - We need to abort any existing transaction
2318 * - create a transaction arround the badPwdCount update
2319 * - re-open the transaction so the upper layer
2320 * doesn't know what happened.
2322 * This is needed because returning an error to the upper
2323 * layer will cancel the transaction and undo the badPwdCount
2328 * Checking errors here is a bit pointless.
2329 * What can we do if we can't end the transaction?
2331 ret = ldb_next_del_trans(io->ac->module);
2332 if (ret != LDB_SUCCESS) {
2333 ldb_debug(ldb, LDB_DEBUG_FATAL,
2334 "Failed to abort transaction prior to update of badPwdCount of %s: %s",
2335 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2336 ldb_errstring(ldb));
2338 * just return the original error
2343 /* Likewise, what should we do if we can't open a new transaction? */
2344 ret = ldb_next_start_trans(io->ac->module);
2345 if (ret != LDB_SUCCESS) {
2346 ldb_debug(ldb, LDB_DEBUG_ERROR,
2347 "Failed to open transaction to update badPwdCount of %s: %s",
2348 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2349 ldb_errstring(ldb));
2351 * just return the original error
2356 ret = dsdb_module_modify(io->ac->module, mod_msg,
2357 DSDB_FLAG_NEXT_MODULE,
2359 if (ret != LDB_SUCCESS) {
2360 ldb_debug(ldb, LDB_DEBUG_ERROR,
2361 "Failed to update badPwdCount of %s: %s",
2362 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2363 ldb_errstring(ldb));
2365 * We can only ignore this...
2369 ret = ldb_next_end_trans(io->ac->module);
2370 if (ret != LDB_SUCCESS) {
2371 ldb_debug(ldb, LDB_DEBUG_ERROR,
2372 "Failed to close transaction to update badPwdCount of %s: %s",
2373 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2374 ldb_errstring(ldb));
2376 * We can only ignore this...
2380 ret = ldb_next_start_trans(io->ac->module);
2381 if (ret != LDB_SUCCESS) {
2382 ldb_debug(ldb, LDB_DEBUG_ERROR,
2383 "Failed to open transaction after update of badPwdCount of %s: %s",
2384 ldb_dn_get_linearized(io->ac->search_res->message->dn),
2385 ldb_errstring(ldb));
2387 * We can only ignore this...
2392 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2393 ldb_asprintf_errstring(ldb,
2394 "%08X: %s - check_password_restrictions: "
2395 "The old password specified doesn't match!",
2396 W_ERROR_V(WERR_INVALID_PASSWORD),
2401 static int check_password_restrictions(struct setup_password_fields_io *io)
2403 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2405 struct loadparm_context *lp_ctx =
2406 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2407 struct loadparm_context);
2409 if (!io->ac->update_password) {
2413 /* First check the old password is correct, for password changes */
2414 if (!io->ac->pwd_reset) {
2415 bool nt_hash_checked = false;
2417 /* we need the old nt or lm hash given by the client */
2418 if (!io->og.nt_hash && !io->og.lm_hash) {
2419 ldb_asprintf_errstring(ldb,
2420 "check_password_restrictions: "
2421 "You need to provide the old password in order "
2423 return LDB_ERR_UNWILLING_TO_PERFORM;
2426 /* The password modify through the NT hash is encouraged and
2427 has no problems at all */
2428 if (io->og.nt_hash) {
2429 if (!io->o.nt_hash || memcmp(io->og.nt_hash->hash, io->o.nt_hash->hash, 16) != 0) {
2430 return make_error_and_update_badPwdCount(io);
2433 nt_hash_checked = true;
2436 /* But it is also possible to change a password by the LM hash
2437 * alone for compatibility reasons. This check is optional if
2438 * the NT hash was already checked - otherwise it's mandatory.
2439 * (as the SAMR operations request it). */
2440 if (io->og.lm_hash) {
2441 if ((!io->o.lm_hash && !nt_hash_checked)
2442 || (io->o.lm_hash && memcmp(io->og.lm_hash->hash, io->o.lm_hash->hash, 16) != 0)) {
2443 return make_error_and_update_badPwdCount(io);
2448 if (io->u.restrictions == 0) {
2449 /* FIXME: Is this right? */
2453 /* Password minimum age: yes, this is a minus. The ages are in negative 100nsec units! */
2454 if ((io->u.pwdLastSet - io->ac->status->domain_data.minPwdAge > io->g.last_set) &&
2457 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2458 ldb_asprintf_errstring(ldb,
2459 "%08X: %s - check_password_restrictions: "
2460 "password is too young to change!",
2461 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2467 * Fundamental password checks done by the call
2468 * "samdb_check_password".
2469 * It is also in use by "dcesrv_samr_ValidatePassword".
2471 if (io->n.cleartext_utf8 != NULL) {
2472 enum samr_ValidationStatus vstat;
2473 vstat = samdb_check_password(io->ac, lp_ctx,
2474 io->n.cleartext_utf8,
2475 io->ac->status->domain_data.pwdProperties,
2476 io->ac->status->domain_data.minPwdLength);
2478 case SAMR_VALIDATION_STATUS_SUCCESS:
2479 /* perfect -> proceed! */
2482 case SAMR_VALIDATION_STATUS_PWD_TOO_SHORT:
2483 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2484 ldb_asprintf_errstring(ldb,
2485 "%08X: %s - check_password_restrictions: "
2486 "the password is too short. It should be equal or longer than %u characters!",
2487 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2489 io->ac->status->domain_data.minPwdLength);
2490 io->ac->status->reject_reason = SAM_PWD_CHANGE_PASSWORD_TOO_SHORT;
2493 case SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH:
2494 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2495 ldb_asprintf_errstring(ldb,
2496 "%08X: %s - check_password_restrictions: "
2497 "the password does not meet the complexity criteria!",
2498 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2500 io->ac->status->reject_reason = SAM_PWD_CHANGE_NOT_COMPLEX;
2504 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2505 ldb_asprintf_errstring(ldb,
2506 "%08X: %s - check_password_restrictions: "
2507 "the password doesn't fit due to a miscellaneous restriction!",
2508 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2514 if (io->ac->pwd_reset) {
2518 if (io->n.nt_hash) {
2521 /* checks the NT hash password history */
2522 for (i = 0; i < io->o.nt_history_len; i++) {
2523 ret = memcmp(io->n.nt_hash, io->o.nt_history[i].hash, 16);
2525 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2526 ldb_asprintf_errstring(ldb,
2527 "%08X: %s - check_password_restrictions: "
2528 "the password was already used (in history)!",
2529 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2531 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
2537 if (io->n.lm_hash) {
2540 /* checks the LM hash password history */
2541 for (i = 0; i < io->o.lm_history_len; i++) {
2542 ret = memcmp(io->n.lm_hash, io->o.lm_history[i].hash, 16);
2544 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2545 ldb_asprintf_errstring(ldb,
2546 "%08X: %s - check_password_restrictions: "
2547 "the password was already used (in history)!",
2548 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2550 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
2556 /* are all password changes disallowed? */
2557 if (io->ac->status->domain_data.pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
2558 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2559 ldb_asprintf_errstring(ldb,
2560 "%08X: %s - check_password_restrictions: "
2561 "password changes disabled!",
2562 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2567 /* can this user change the password? */
2568 if (io->u.userAccountControl & UF_PASSWD_CANT_CHANGE) {
2569 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2570 ldb_asprintf_errstring(ldb,
2571 "%08X: %s - check_password_restrictions: "
2572 "password can't be changed on this account!",
2573 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2581 static int update_final_msg(struct setup_password_fields_io *io)
2583 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2586 bool update_password = io->ac->update_password;
2587 bool update_scb = io->ac->update_password;
2590 * If we add a user without initial password,
2591 * we need to add replication meta data for
2592 * following attributes:
2598 * If we add a user with initial password or a
2599 * password is changed of an existing user,
2600 * we need to replace the following attributes
2601 * with a forced meta data update, e.g. also
2602 * when updating an empty attribute with an empty value:
2607 * - supplementalCredentials
2610 switch (io->ac->req->operation) {
2612 update_password = true;
2613 el_flags |= DSDB_FLAG_INTERNAL_FORCE_META_DATA;
2616 el_flags |= LDB_FLAG_MOD_REPLACE;
2617 el_flags |= DSDB_FLAG_INTERNAL_FORCE_META_DATA;
2620 return ldb_module_operr(io->ac->module);
2623 if (update_password) {
2624 ret = ldb_msg_add_empty(io->ac->update_msg,
2627 if (ret != LDB_SUCCESS) {
2630 ret = ldb_msg_add_empty(io->ac->update_msg,
2633 if (ret != LDB_SUCCESS) {
2636 ret = ldb_msg_add_empty(io->ac->update_msg,
2639 if (ret != LDB_SUCCESS) {
2642 ret = ldb_msg_add_empty(io->ac->update_msg,
2645 if (ret != LDB_SUCCESS) {