4 Copyright (C) Simo Sorce 2004-2008
5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2006
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Stefan Metzmacher 2007-2010
8 Copyright (C) Matthias Dieter Wallnöfer 2009-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 * Component: ldb password_hash module
29 * Description: correctly handle AD password changes fields
31 * Author: Andrew Bartlett
32 * Author: Stefan Metzmacher
36 #include "ldb_module.h"
37 #include "libcli/auth/libcli_auth.h"
38 #include "libcli/security/dom_sid.h"
39 #include "system/kerberos.h"
40 #include "auth/kerberos/kerberos.h"
41 #include "dsdb/samdb/samdb.h"
42 #include "dsdb/samdb/ldb_modules/util.h"
43 #include "dsdb/samdb/ldb_modules/password_modules.h"
44 #include "librpc/gen_ndr/ndr_drsblobs.h"
45 #include "lib/crypto/md4.h"
46 #include "param/param.h"
47 #include "lib/krb5_wrap/krb5_samba.h"
48 #include "auth/common_auth.h"
49 #include "lib/messaging/messaging.h"
50 #include "lib/param/loadparm.h"
52 #include "lib/crypto/gnutls_helpers.h"
53 #include <gnutls/crypto.h>
60 * 1.2.0 is what dpkg-shlibdeps generates, based on used symbols and
62 * https://salsa.debian.org/debian/gpgme/blob/debian/master/debian/libgpgme11.symbols
65 #define MINIMUM_GPGME_VERSION "1.2.0"
71 /* If we have decided there is a reason to work on this request, then
72 * setup all the password hash types correctly.
74 * If we haven't the hashes yet but the password given as plain-text (attributes
75 * 'unicodePwd', 'userPassword' and 'clearTextPassword') we have to check for
76 * the constraints. Once this is done, we calculate the password hashes.
78 * Notice: unlike the real AD which only supports the UTF16 special based
79 * 'unicodePwd' and the UTF8 based 'userPassword' plaintext attribute we
80 * understand also a UTF16 based 'clearTextPassword' one.
81 * The latter is also accessible through LDAP so it can also be set by external
82 * tools and scripts. But be aware that this isn't portable on non SAMBA 4 ADs!
84 * Also when the module receives only the password hashes (possible through
85 * specifying an internal LDB control - for security reasons) some checks are
86 * performed depending on the operation mode (see below) (e.g. if the password
87 * has been in use before if the password memory policy was activated).
89 * Attention: There is a difference between "modify" and "reset" operations
90 * (see MS-ADTS 3.1.1.3.1.5). If the client sends a "add" and "remove"
91 * operation for a password attribute we thread this as a "modify"; if it sends
92 * only a "replace" one we have an (administrative) reset.
94 * Finally, if the administrator has requested that a password history
95 * be maintained, then this should also be written out.
99 /* TODO: [consider always MS-ADTS 3.1.1.3.1.5]
100 * - Check for right connection encryption
103 /* Notice: Definition of "dsdb_control_password_change_status" moved into
107 struct ldb_module
*module
;
108 struct ldb_request
*req
;
110 struct ldb_request
*dom_req
;
111 struct ldb_reply
*dom_res
;
113 struct ldb_reply
*pso_res
;
115 struct ldb_reply
*search_res
;
117 struct ldb_message
*update_msg
;
119 struct dsdb_control_password_change_status
*status
;
120 struct dsdb_control_password_change
*change
;
122 const char **gpg_key_ids
;
128 bool update_password
;
130 bool pwd_last_set_bypass
;
131 bool pwd_last_set_default
;
132 bool smartcard_reset
;
133 const char **userPassword_schemes
;
137 struct setup_password_fields_io
{
138 struct ph_context
*ac
;
140 struct smb_krb5_context
*smb_krb5_context
;
142 /* info about the user account */
144 uint32_t userAccountControl
;
146 const char *sAMAccountName
;
147 const char *user_principal_name
;
148 const char *displayName
; /* full name */
150 uint32_t restrictions
;
151 struct dom_sid
*account_sid
;
154 /* new credentials and old given credentials */
155 struct setup_password_fields_given
{
156 const struct ldb_val
*cleartext_utf8
;
157 const struct ldb_val
*cleartext_utf16
;
158 struct samr_Password
*nt_hash
;
159 struct samr_Password
*lm_hash
;
162 /* old credentials */
164 struct samr_Password
*nt_hash
;
165 struct samr_Password
*lm_hash
;
166 uint32_t nt_history_len
;
167 struct samr_Password
*nt_history
;
168 uint32_t lm_history_len
;
169 struct samr_Password
*lm_history
;
170 const struct ldb_val
*supplemental
;
171 struct supplementalCredentialsBlob scb
;
174 /* generated credentials */
176 struct samr_Password
*nt_hash
;
177 struct samr_Password
*lm_hash
;
178 uint32_t nt_history_len
;
179 struct samr_Password
*nt_history
;
180 uint32_t lm_history_len
;
181 struct samr_Password
*lm_history
;
187 struct ldb_val supplemental
;
192 static int msg_find_old_and_new_pwd_val(const struct ldb_message
*msg
,
194 enum ldb_request_type operation
,
195 const struct ldb_val
**new_val
,
196 const struct ldb_val
**old_val
);
198 static int password_hash_bypass(struct ldb_module
*module
, struct ldb_request
*request
)
200 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
201 const struct ldb_message
*msg
;
202 struct ldb_message_element
*nte
;
203 struct ldb_message_element
*lme
;
204 struct ldb_message_element
*nthe
;
205 struct ldb_message_element
*lmhe
;
206 struct ldb_message_element
*sce
;
208 switch (request
->operation
) {
210 msg
= request
->op
.add
.message
;
213 msg
= request
->op
.mod
.message
;
216 return ldb_next_request(module
, request
);
219 /* nobody must touch password histories and 'supplementalCredentials' */
220 nte
= dsdb_get_single_valued_attr(msg
, "unicodePwd",
222 lme
= dsdb_get_single_valued_attr(msg
, "dBCSPwd",
224 nthe
= dsdb_get_single_valued_attr(msg
, "ntPwdHistory",
226 lmhe
= dsdb_get_single_valued_attr(msg
, "lmPwdHistory",
228 sce
= dsdb_get_single_valued_attr(msg
, "supplementalCredentials",
231 #define CHECK_HASH_ELEMENT(e, min, max) do {\
232 if (e && e->num_values) { \
233 unsigned int _count; \
234 if (e->num_values != 1) { \
235 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
236 "num_values != 1"); \
238 if ((e->values[0].length % 16) != 0) { \
239 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
240 "length % 16 != 0"); \
242 _count = e->values[0].length / 16; \
243 if (_count < min) { \
244 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
247 if (_count > max) { \
248 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
254 CHECK_HASH_ELEMENT(nte
, 1, 1);
255 CHECK_HASH_ELEMENT(lme
, 1, 1);
256 CHECK_HASH_ELEMENT(nthe
, 1, INT32_MAX
);
257 CHECK_HASH_ELEMENT(lmhe
, 1, INT32_MAX
);
259 if (sce
&& sce
->num_values
) {
260 enum ndr_err_code ndr_err
;
261 struct supplementalCredentialsBlob
*scb
;
262 struct supplementalCredentialsPackage
*scpp
= NULL
;
263 struct supplementalCredentialsPackage
*scpk
= NULL
;
264 struct supplementalCredentialsPackage
*scpkn
= NULL
;
265 struct supplementalCredentialsPackage
*scpct
= NULL
;
266 DATA_BLOB scpbp
= data_blob_null
;
267 DATA_BLOB scpbk
= data_blob_null
;
268 DATA_BLOB scpbkn
= data_blob_null
;
269 DATA_BLOB scpbct
= data_blob_null
;
273 if (sce
->num_values
!= 1) {
274 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
278 scb
= talloc_zero(request
, struct supplementalCredentialsBlob
);
280 return ldb_module_oom(module
);
283 ndr_err
= ndr_pull_struct_blob_all(&sce
->values
[0], scb
, scb
,
284 (ndr_pull_flags_fn_t
)ndr_pull_supplementalCredentialsBlob
);
285 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
286 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
287 "ndr_pull_struct_blob_all");
290 if (scb
->sub
.num_packages
< 2) {
291 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
295 for (i
=0; i
< scb
->sub
.num_packages
; i
++) {
298 subblob
= strhex_to_data_blob(scb
, scb
->sub
.packages
[i
].data
);
299 if (subblob
.data
== NULL
) {
300 return ldb_module_oom(module
);
303 if (strcmp(scb
->sub
.packages
[i
].name
, "Packages") == 0) {
305 return ldb_error(ldb
,
306 LDB_ERR_CONSTRAINT_VIOLATION
,
309 scpp
= &scb
->sub
.packages
[i
];
313 if (strcmp(scb
->sub
.packages
[i
].name
, "Primary:Kerberos") == 0) {
315 return ldb_error(ldb
,
316 LDB_ERR_CONSTRAINT_VIOLATION
,
317 "Primary:Kerberos twice");
319 scpk
= &scb
->sub
.packages
[i
];
323 if (strcmp(scb
->sub
.packages
[i
].name
, "Primary:Kerberos-Newer-Keys") == 0) {
325 return ldb_error(ldb
,
326 LDB_ERR_CONSTRAINT_VIOLATION
,
327 "Primary:Kerberos-Newer-Keys twice");
329 scpkn
= &scb
->sub
.packages
[i
];
333 if (strcmp(scb
->sub
.packages
[i
].name
, "Primary:CLEARTEXT") == 0) {
335 return ldb_error(ldb
,
336 LDB_ERR_CONSTRAINT_VIOLATION
,
337 "Primary:CLEARTEXT twice");
339 scpct
= &scb
->sub
.packages
[i
];
344 data_blob_free(&subblob
);
348 return ldb_error(ldb
,
349 LDB_ERR_CONSTRAINT_VIOLATION
,
350 "Primary:Packages missing");
355 * If Primary:Kerberos is missing w2k8r2 reboots
356 * when a password is changed.
358 return ldb_error(ldb
,
359 LDB_ERR_CONSTRAINT_VIOLATION
,
360 "Primary:Kerberos missing");
364 struct package_PackagesBlob
*p
;
367 p
= talloc_zero(scb
, struct package_PackagesBlob
);
369 return ldb_module_oom(module
);
372 ndr_err
= ndr_pull_struct_blob(&scpbp
, p
, p
,
373 (ndr_pull_flags_fn_t
)ndr_pull_package_PackagesBlob
);
374 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
375 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
376 "ndr_pull_struct_blob Packages");
379 if (p
->names
== NULL
) {
380 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
381 "Packages names == NULL");
384 for (n
= 0; p
->names
[n
]; n
++) {
388 if (scb
->sub
.num_packages
!= (n
+ 1)) {
389 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
390 "Packages num_packages != num_names + 1");
397 struct package_PrimaryKerberosBlob
*k
;
399 k
= talloc_zero(scb
, struct package_PrimaryKerberosBlob
);
401 return ldb_module_oom(module
);
404 ndr_err
= ndr_pull_struct_blob(&scpbk
, k
, k
,
405 (ndr_pull_flags_fn_t
)ndr_pull_package_PrimaryKerberosBlob
);
406 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
407 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
408 "ndr_pull_struct_blob PrimaryKerberos");
411 if (k
->version
!= 3) {
412 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
413 "PrimaryKerberos version != 3");
416 if (k
->ctr
.ctr3
.salt
.string
== NULL
) {
417 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
418 "PrimaryKerberos salt == NULL");
421 if (strlen(k
->ctr
.ctr3
.salt
.string
) == 0) {
422 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
423 "PrimaryKerberos strlen(salt) == 0");
426 if (k
->ctr
.ctr3
.num_keys
!= 2) {
427 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
428 "PrimaryKerberos num_keys != 2");
431 if (k
->ctr
.ctr3
.num_old_keys
> k
->ctr
.ctr3
.num_keys
) {
432 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
433 "PrimaryKerberos num_old_keys > num_keys");
436 if (k
->ctr
.ctr3
.keys
[0].keytype
!= ENCTYPE_DES_CBC_MD5
) {
437 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
438 "PrimaryKerberos key[0] != DES_CBC_MD5");
440 if (k
->ctr
.ctr3
.keys
[1].keytype
!= ENCTYPE_DES_CBC_CRC
) {
441 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
442 "PrimaryKerberos key[1] != DES_CBC_CRC");
445 if (k
->ctr
.ctr3
.keys
[0].value_len
!= 8) {
446 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
447 "PrimaryKerberos key[0] value_len != 8");
449 if (k
->ctr
.ctr3
.keys
[1].value_len
!= 8) {
450 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
451 "PrimaryKerberos key[1] value_len != 8");
454 for (i
= 0; i
< k
->ctr
.ctr3
.num_old_keys
; i
++) {
455 if (k
->ctr
.ctr3
.old_keys
[i
].keytype
==
456 k
->ctr
.ctr3
.keys
[i
].keytype
&&
457 k
->ctr
.ctr3
.old_keys
[i
].value_len
==
458 k
->ctr
.ctr3
.keys
[i
].value_len
) {
462 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
463 "PrimaryKerberos old_keys type/value_len doesn't match");
470 struct package_PrimaryKerberosBlob
*k
;
472 k
= talloc_zero(scb
, struct package_PrimaryKerberosBlob
);
474 return ldb_module_oom(module
);
477 ndr_err
= ndr_pull_struct_blob(&scpbkn
, k
, k
,
478 (ndr_pull_flags_fn_t
)ndr_pull_package_PrimaryKerberosBlob
);
479 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
480 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
481 "ndr_pull_struct_blob PrimaryKerberosNeverKeys");
484 if (k
->version
!= 4) {
485 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
486 "KerberosNerverKeys version != 4");
489 if (k
->ctr
.ctr4
.salt
.string
== NULL
) {
490 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
491 "KerberosNewerKeys salt == NULL");
494 if (strlen(k
->ctr
.ctr4
.salt
.string
) == 0) {
495 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
496 "KerberosNewerKeys strlen(salt) == 0");
499 if (k
->ctr
.ctr4
.num_keys
!= 4) {
500 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
501 "KerberosNewerKeys num_keys != 2");
504 if (k
->ctr
.ctr4
.num_old_keys
> k
->ctr
.ctr4
.num_keys
) {
505 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
506 "KerberosNewerKeys num_old_keys > num_keys");
509 if (k
->ctr
.ctr4
.num_older_keys
> k
->ctr
.ctr4
.num_old_keys
) {
510 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
511 "KerberosNewerKeys num_older_keys > num_old_keys");
514 if (k
->ctr
.ctr4
.keys
[0].keytype
!= ENCTYPE_AES256_CTS_HMAC_SHA1_96
) {
515 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
516 "KerberosNewerKeys key[0] != AES256");
518 if (k
->ctr
.ctr4
.keys
[1].keytype
!= ENCTYPE_AES128_CTS_HMAC_SHA1_96
) {
519 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
520 "KerberosNewerKeys key[1] != AES128");
522 if (k
->ctr
.ctr4
.keys
[2].keytype
!= ENCTYPE_DES_CBC_MD5
) {
523 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
524 "KerberosNewerKeys key[2] != DES_CBC_MD5");
526 if (k
->ctr
.ctr4
.keys
[3].keytype
!= ENCTYPE_DES_CBC_CRC
) {
527 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
528 "KerberosNewerKeys key[3] != DES_CBC_CRC");
531 if (k
->ctr
.ctr4
.keys
[0].value_len
!= 32) {
532 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
533 "KerberosNewerKeys key[0] value_len != 32");
535 if (k
->ctr
.ctr4
.keys
[1].value_len
!= 16) {
536 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
537 "KerberosNewerKeys key[1] value_len != 16");
539 if (k
->ctr
.ctr4
.keys
[2].value_len
!= 8) {
540 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
541 "KerberosNewerKeys key[2] value_len != 8");
543 if (k
->ctr
.ctr4
.keys
[3].value_len
!= 8) {
544 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
545 "KerberosNewerKeys key[3] value_len != 8");
550 * Maybe we can check old and older keys here.
551 * But we need to do some tests, if the old keys
552 * can be taken from the PrimaryKerberos blob
553 * (with only des keys), when the domain was upgraded
561 struct package_PrimaryCLEARTEXTBlob
*ct
;
563 ct
= talloc_zero(scb
, struct package_PrimaryCLEARTEXTBlob
);
565 return ldb_module_oom(module
);
568 ndr_err
= ndr_pull_struct_blob(&scpbct
, ct
, ct
,
569 (ndr_pull_flags_fn_t
)ndr_pull_package_PrimaryCLEARTEXTBlob
);
570 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
571 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
572 "ndr_pull_struct_blob PrimaryCLEARTEXT");
575 if ((ct
->cleartext
.length
% 2) != 0) {
576 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
577 "PrimaryCLEARTEXT length % 2 != 0");
583 ndr_err
= ndr_push_struct_blob(&blob
, scb
, scb
,
584 (ndr_push_flags_fn_t
)ndr_push_supplementalCredentialsBlob
);
585 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
586 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
587 "ndr_pull_struct_blob_all");
590 if (sce
->values
[0].length
!= blob
.length
) {
591 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
592 "supplementalCredentialsBlob length differ");
595 if (memcmp(sce
->values
[0].data
, blob
.data
, blob
.length
) != 0) {
596 return ldb_error(ldb
, LDB_ERR_CONSTRAINT_VIOLATION
,
597 "supplementalCredentialsBlob memcmp differ");
603 ldb_debug(ldb
, LDB_DEBUG_TRACE
, "password_hash_bypass - validated\n");
604 return ldb_next_request(module
, request
);
607 /* Get the NT hash, and fill it in as an entry in the password history,
608 and specify it into io->g.nt_hash */
610 static int setup_nt_fields(struct setup_password_fields_io
*io
)
612 struct ldb_context
*ldb
;
615 io
->g
.nt_hash
= io
->n
.nt_hash
;
616 ldb
= ldb_module_get_ctx(io
->ac
->module
);
618 if (io
->ac
->status
->domain_data
.pwdHistoryLength
== 0) {
622 /* We might not have an old NT password */
623 io
->g
.nt_history
= talloc_array(io
->ac
,
624 struct samr_Password
,
625 io
->ac
->status
->domain_data
.pwdHistoryLength
);
626 if (!io
->g
.nt_history
) {
630 for (i
= 0; i
< MIN(io
->ac
->status
->domain_data
.pwdHistoryLength
-1,
631 io
->o
.nt_history_len
); i
++) {
632 io
->g
.nt_history
[i
+1] = io
->o
.nt_history
[i
];
634 io
->g
.nt_history_len
= i
+ 1;
637 io
->g
.nt_history
[0] = *io
->g
.nt_hash
;
640 * TODO: is this correct?
641 * the simular behavior is correct for the lm history case
643 E_md4hash("", io
->g
.nt_history
[0].hash
);
649 /* Get the LANMAN hash, and fill it in as an entry in the password history,
650 and specify it into io->g.lm_hash */
652 static int setup_lm_fields(struct setup_password_fields_io
*io
)
654 struct ldb_context
*ldb
;
657 io
->g
.lm_hash
= io
->n
.lm_hash
;
658 ldb
= ldb_module_get_ctx(io
->ac
->module
);
660 if (io
->ac
->status
->domain_data
.pwdHistoryLength
== 0) {
664 /* We might not have an old LM password */
665 io
->g
.lm_history
= talloc_array(io
->ac
,
666 struct samr_Password
,
667 io
->ac
->status
->domain_data
.pwdHistoryLength
);
668 if (!io
->g
.lm_history
) {
672 for (i
= 0; i
< MIN(io
->ac
->status
->domain_data
.pwdHistoryLength
-1,
673 io
->o
.lm_history_len
); i
++) {
674 io
->g
.lm_history
[i
+1] = io
->o
.lm_history
[i
];
676 io
->g
.lm_history_len
= i
+ 1;
679 io
->g
.lm_history
[0] = *io
->g
.lm_hash
;
681 E_deshash("", io
->g
.lm_history
[0].hash
);
687 static int setup_kerberos_keys(struct setup_password_fields_io
*io
)
689 struct ldb_context
*ldb
;
690 krb5_error_code krb5_ret
;
691 krb5_principal salt_principal
= NULL
;
695 krb5_data cleartext_data
;
696 uint32_t uac_flags
= 0;
698 ldb
= ldb_module_get_ctx(io
->ac
->module
);
699 cleartext_data
.data
= (char *)io
->n
.cleartext_utf8
->data
;
700 cleartext_data
.length
= io
->n
.cleartext_utf8
->length
;
702 uac_flags
= io
->u
.userAccountControl
& UF_ACCOUNT_TYPE_MASK
;
703 krb5_ret
= smb_krb5_salt_principal(io
->smb_krb5_context
->krb5_context
,
704 io
->ac
->status
->domain_data
.realm
,
705 io
->u
.sAMAccountName
,
706 io
->u
.user_principal_name
,
710 ldb_asprintf_errstring(ldb
,
711 "setup_kerberos_keys: "
712 "generation of a salting principal failed: %s",
713 smb_get_krb5_error_message(io
->smb_krb5_context
->krb5_context
,
715 return LDB_ERR_OPERATIONS_ERROR
;
719 * create salt from salt_principal
721 krb5_ret
= smb_krb5_get_pw_salt(io
->smb_krb5_context
->krb5_context
,
722 salt_principal
, &salt_data
);
724 krb5_free_principal(io
->smb_krb5_context
->krb5_context
, salt_principal
);
726 ldb_asprintf_errstring(ldb
,
727 "setup_kerberos_keys: "
728 "generation of krb5_salt failed: %s",
729 smb_get_krb5_error_message(io
->smb_krb5_context
->krb5_context
,
731 return LDB_ERR_OPERATIONS_ERROR
;
734 /* now use the talloced copy of the salt */
735 salt
.data
= talloc_strndup(io
->ac
,
736 (char *)salt_data
.data
,
738 io
->g
.salt
= salt
.data
;
739 salt
.length
= strlen(io
->g
.salt
);
741 smb_krb5_free_data_contents(io
->smb_krb5_context
->krb5_context
,
745 * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of
746 * the salt and the cleartext password
748 krb5_ret
= smb_krb5_create_key_from_string(io
->smb_krb5_context
->krb5_context
,
752 ENCTYPE_AES256_CTS_HMAC_SHA1_96
,
755 ldb_asprintf_errstring(ldb
,
756 "setup_kerberos_keys: "
757 "generation of a aes256-cts-hmac-sha1-96 key failed: %s",
758 smb_get_krb5_error_message(io
->smb_krb5_context
->krb5_context
,
760 return LDB_ERR_OPERATIONS_ERROR
;
762 io
->g
.aes_256
= data_blob_talloc(io
->ac
,
764 KRB5_KEY_LENGTH(&key
));
765 krb5_free_keyblock_contents(io
->smb_krb5_context
->krb5_context
, &key
);
766 if (!io
->g
.aes_256
.data
) {
771 * create ENCTYPE_AES128_CTS_HMAC_SHA1_96 key out of
772 * the salt and the cleartext password
774 krb5_ret
= smb_krb5_create_key_from_string(io
->smb_krb5_context
->krb5_context
,
778 ENCTYPE_AES128_CTS_HMAC_SHA1_96
,
781 ldb_asprintf_errstring(ldb
,
782 "setup_kerberos_keys: "
783 "generation of a aes128-cts-hmac-sha1-96 key failed: %s",
784 smb_get_krb5_error_message(io
->smb_krb5_context
->krb5_context
,
786 return LDB_ERR_OPERATIONS_ERROR
;
788 io
->g
.aes_128
= data_blob_talloc(io
->ac
,
790 KRB5_KEY_LENGTH(&key
));
791 krb5_free_keyblock_contents(io
->smb_krb5_context
->krb5_context
, &key
);
792 if (!io
->g
.aes_128
.data
) {
797 * As per RFC-6649 single DES encryption types are no longer considered
798 * secure to be used in Kerberos, we store random keys instead of the
799 * ENCTYPE_DES_CBC_MD5 and ENCTYPE_DES_CBC_CRC keys.
801 io
->g
.des_md5
= data_blob_talloc(io
->ac
, NULL
, 8);
802 if (!io
->g
.des_md5
.data
) {
805 generate_secret_buffer(io
->g
.des_md5
.data
, 8);
807 io
->g
.des_crc
= data_blob_talloc(io
->ac
, NULL
, 8);
808 if (!io
->g
.des_crc
.data
) {
811 generate_secret_buffer(io
->g
.des_crc
.data
, 8);
816 static int setup_primary_kerberos(struct setup_password_fields_io
*io
,
817 const struct supplementalCredentialsBlob
*old_scb
,
818 struct package_PrimaryKerberosBlob
*pkb
)
820 struct ldb_context
*ldb
;
821 struct package_PrimaryKerberosCtr3
*pkb3
= &pkb
->ctr
.ctr3
;
822 struct supplementalCredentialsPackage
*old_scp
= NULL
;
823 struct package_PrimaryKerberosBlob _old_pkb
;
824 struct package_PrimaryKerberosCtr3
*old_pkb3
= NULL
;
826 enum ndr_err_code ndr_err
;
828 ldb
= ldb_module_get_ctx(io
->ac
->module
);
831 * prepare generation of keys
833 * ENCTYPE_DES_CBC_MD5
834 * ENCTYPE_DES_CBC_CRC
837 pkb3
->salt
.string
= io
->g
.salt
;
839 pkb3
->keys
= talloc_array(io
->ac
,
840 struct package_PrimaryKerberosKey3
,
846 pkb3
->keys
[0].keytype
= ENCTYPE_DES_CBC_MD5
;
847 pkb3
->keys
[0].value
= &io
->g
.des_md5
;
848 pkb3
->keys
[1].keytype
= ENCTYPE_DES_CBC_CRC
;
849 pkb3
->keys
[1].value
= &io
->g
.des_crc
;
851 /* initialize the old keys to zero */
852 pkb3
->num_old_keys
= 0;
853 pkb3
->old_keys
= NULL
;
855 /* if there're no old keys, then we're done */
860 for (i
=0; i
< old_scb
->sub
.num_packages
; i
++) {
861 if (strcmp("Primary:Kerberos", old_scb
->sub
.packages
[i
].name
) != 0) {
865 if (!old_scb
->sub
.packages
[i
].data
|| !old_scb
->sub
.packages
[i
].data
[0]) {
869 old_scp
= &old_scb
->sub
.packages
[i
];
872 /* Primary:Kerberos element of supplementalCredentials */
876 blob
= strhex_to_data_blob(io
->ac
, old_scp
->data
);
881 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
882 ndr_err
= ndr_pull_struct_blob(&blob
, io
->ac
, &_old_pkb
,
883 (ndr_pull_flags_fn_t
)ndr_pull_package_PrimaryKerberosBlob
);
884 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
885 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
886 ldb_asprintf_errstring(ldb
,
887 "setup_primary_kerberos: "
888 "failed to pull old package_PrimaryKerberosBlob: %s",
890 return LDB_ERR_OPERATIONS_ERROR
;
893 if (_old_pkb
.version
!= 3) {
894 ldb_asprintf_errstring(ldb
,
895 "setup_primary_kerberos: "
896 "package_PrimaryKerberosBlob version[%u] expected[3]",
898 return LDB_ERR_OPERATIONS_ERROR
;
901 old_pkb3
= &_old_pkb
.ctr
.ctr3
;
904 /* if we didn't found the old keys we're done */
909 /* fill in the old keys */
910 pkb3
->num_old_keys
= old_pkb3
->num_keys
;
911 pkb3
->old_keys
= old_pkb3
->keys
;
916 static int setup_primary_kerberos_newer(struct setup_password_fields_io
*io
,
917 const struct supplementalCredentialsBlob
*old_scb
,
918 struct package_PrimaryKerberosBlob
*pkb
)
920 struct ldb_context
*ldb
;
921 struct package_PrimaryKerberosCtr4
*pkb4
= &pkb
->ctr
.ctr4
;
922 struct supplementalCredentialsPackage
*old_scp
= NULL
;
923 struct package_PrimaryKerberosBlob _old_pkb
;
924 struct package_PrimaryKerberosCtr4
*old_pkb4
= NULL
;
926 enum ndr_err_code ndr_err
;
928 ldb
= ldb_module_get_ctx(io
->ac
->module
);
931 * prepare generation of keys
933 * ENCTYPE_AES256_CTS_HMAC_SHA1_96
934 * ENCTYPE_AES128_CTS_HMAC_SHA1_96
935 * ENCTYPE_DES_CBC_MD5
936 * ENCTYPE_DES_CBC_CRC
939 pkb4
->salt
.string
= io
->g
.salt
;
940 pkb4
->default_iteration_count
= 4096;
943 pkb4
->keys
= talloc_array(io
->ac
,
944 struct package_PrimaryKerberosKey4
,
950 pkb4
->keys
[0].iteration_count
= 4096;
951 pkb4
->keys
[0].keytype
= ENCTYPE_AES256_CTS_HMAC_SHA1_96
;
952 pkb4
->keys
[0].value
= &io
->g
.aes_256
;
953 pkb4
->keys
[1].iteration_count
= 4096;
954 pkb4
->keys
[1].keytype
= ENCTYPE_AES128_CTS_HMAC_SHA1_96
;
955 pkb4
->keys
[1].value
= &io
->g
.aes_128
;
956 pkb4
->keys
[2].iteration_count
= 4096;
957 pkb4
->keys
[2].keytype
= ENCTYPE_DES_CBC_MD5
;
958 pkb4
->keys
[2].value
= &io
->g
.des_md5
;
959 pkb4
->keys
[3].iteration_count
= 4096;
960 pkb4
->keys
[3].keytype
= ENCTYPE_DES_CBC_CRC
;
961 pkb4
->keys
[3].value
= &io
->g
.des_crc
;
963 /* initialize the old keys to zero */
964 pkb4
->num_old_keys
= 0;
965 pkb4
->old_keys
= NULL
;
966 pkb4
->num_older_keys
= 0;
967 pkb4
->older_keys
= NULL
;
969 /* if there're no old keys, then we're done */
974 for (i
=0; i
< old_scb
->sub
.num_packages
; i
++) {
975 if (strcmp("Primary:Kerberos-Newer-Keys", old_scb
->sub
.packages
[i
].name
) != 0) {
979 if (!old_scb
->sub
.packages
[i
].data
|| !old_scb
->sub
.packages
[i
].data
[0]) {
983 old_scp
= &old_scb
->sub
.packages
[i
];
986 /* Primary:Kerberos-Newer-Keys element of supplementalCredentials */
990 blob
= strhex_to_data_blob(io
->ac
, old_scp
->data
);
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
,
998 (ndr_pull_flags_fn_t
)ndr_pull_package_PrimaryKerberosBlob
);
999 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1000 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1001 ldb_asprintf_errstring(ldb
,
1002 "setup_primary_kerberos_newer: "
1003 "failed to pull old package_PrimaryKerberosBlob: %s",
1005 return LDB_ERR_OPERATIONS_ERROR
;
1008 if (_old_pkb
.version
!= 4) {
1009 ldb_asprintf_errstring(ldb
,
1010 "setup_primary_kerberos_newer: "
1011 "package_PrimaryKerberosBlob version[%u] expected[4]",
1013 return LDB_ERR_OPERATIONS_ERROR
;
1016 old_pkb4
= &_old_pkb
.ctr
.ctr4
;
1019 /* if we didn't found the old keys we're done */
1024 /* fill in the old keys */
1025 pkb4
->num_old_keys
= old_pkb4
->num_keys
;
1026 pkb4
->old_keys
= old_pkb4
->keys
;
1027 pkb4
->num_older_keys
= old_pkb4
->num_old_keys
;
1028 pkb4
->older_keys
= old_pkb4
->old_keys
;
1033 static int setup_primary_wdigest(struct setup_password_fields_io
*io
,
1034 const struct supplementalCredentialsBlob
*old_scb
,
1035 struct package_PrimaryWDigestBlob
*pdb
)
1037 struct ldb_context
*ldb
= ldb_module_get_ctx(io
->ac
->module
);
1038 DATA_BLOB sAMAccountName
;
1039 DATA_BLOB sAMAccountName_l
;
1040 DATA_BLOB sAMAccountName_u
;
1041 const char *user_principal_name
= io
->u
.user_principal_name
;
1042 DATA_BLOB userPrincipalName
;
1043 DATA_BLOB userPrincipalName_l
;
1044 DATA_BLOB userPrincipalName_u
;
1045 DATA_BLOB netbios_domain
;
1046 DATA_BLOB netbios_domain_l
;
1047 DATA_BLOB netbios_domain_u
;
1048 DATA_BLOB dns_domain
;
1049 DATA_BLOB dns_domain_l
;
1050 DATA_BLOB dns_domain_u
;
1053 DATA_BLOB backslash
;
1061 * See 3.1.1.8.11.3.1 WDIGEST_CREDENTIALS Construction
1062 * https://msdn.microsoft.com/en-us/library/cc245680.aspx
1063 * for what precalculated hashes are supposed to be stored...
1065 * I can't reproduce all values which should contain "Digest" as realm,
1066 * am I doing something wrong or is w2k3 just broken...?
1068 * W2K3 fills in following for a user:
1070 * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1071 * sAMAccountName: NewUser2Sam
1072 * userPrincipalName: NewUser2Princ@sub1.w2k3.vmnet1.vm.base
1074 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1075 * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1076 * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1077 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1078 * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1079 * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1080 * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1081 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1082 * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1083 * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1084 * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1085 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1086 * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1087 * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1088 * 221c55284451ae9b3aacaa2a3c86f10f => NewUser2Princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1089 * 74e1be668853d4324d38c07e2acfb8ea => (w2k3 has a bug here!) newuser2princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1090 * e1e244ab7f098e3ae1761be7f9229bbb => NEWUSER2PRINC@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1091 * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1092 * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1093 * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1094 * 31dc704d3640335b2123d4ee28aa1f11 => ??? changes with NewUser2Sam => NewUser1Sam
1095 * 36349f5cecd07320fb3bb0e119230c43 => ??? changes with NewUser2Sam => NewUser1Sam
1096 * 12adf019d037fb535c01fd0608e78d9d => ??? changes with NewUser2Sam => NewUser1Sam
1097 * 6feecf8e724906f3ee1105819c5105a1 => ??? changes with NewUser2Princ => NewUser1Princ
1098 * 6c6911f3de6333422640221b9c51ff1f => ??? changes with NewUser2Princ => NewUser1Princ
1099 * 4b279877e742895f9348ac67a8de2f69 => ??? changes with NewUser2Princ => NewUser1Princ
1100 * db0c6bff069513e3ebb9870d29b57490 => ??? changes with NewUser2Sam => NewUser1Sam
1101 * 45072621e56b1c113a4e04a8ff68cd0e => ??? changes with NewUser2Sam => NewUser1Sam
1102 * 11d1220abc44a9c10cf91ef4a9c1de02 => ??? changes with NewUser2Sam => NewUser1Sam
1104 * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1105 * sAMAccountName: NewUser2Sam
1107 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1108 * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1109 * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1110 * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1111 * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1112 * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1113 * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1114 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1115 * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1116 * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1117 * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1118 * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1119 * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1120 * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1121 * 8a140d30b6f0a5912735dc1e3bc993b4 => NewUser2Sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1122 * 86d95b2faae6cae4ec261e7fbaccf093 => (here w2k3 is correct) newuser2sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1123 * dfeff1493110220efcdfc6362e5f5450 => NEWUSER2SAM@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1124 * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1125 * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1126 * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1127 * 31dc704d3640335b2123d4ee28aa1f11 => ???M1 changes with NewUser2Sam => NewUser1Sam
1128 * 36349f5cecd07320fb3bb0e119230c43 => ???M1.L changes with newuser2sam => newuser1sam
1129 * 12adf019d037fb535c01fd0608e78d9d => ???M1.U changes with NEWUSER2SAM => NEWUSER1SAM
1130 * 569b4533f2d9e580211dd040e5e360a8 => ???M2 changes with NewUser2Princ => NewUser1Princ
1131 * 52528bddf310a587c5d7e6a9ae2cbb20 => ???M2.L changes with newuser2princ => newuser1princ
1132 * 4f629a4f0361289ca4255ab0f658fcd5 => ???M3 changes with NewUser2Princ => NewUser1Princ (doesn't depend on case of userPrincipal )
1133 * db0c6bff069513e3ebb9870d29b57490 => ???M4 changes with NewUser2Sam => NewUser1Sam
1134 * 45072621e56b1c113a4e04a8ff68cd0e => ???M5 changes with NewUser2Sam => NewUser1Sam (doesn't depend on case of sAMAccountName)
1135 * 11d1220abc44a9c10cf91ef4a9c1de02 => ???M4.U changes with NEWUSER2SAM => NEWUSER1SAM
1139 * sAMAccountName, netbios_domain
1142 .user
= &sAMAccountName
,
1143 .realm
= &netbios_domain
,
1146 .user
= &sAMAccountName_l
,
1147 .realm
= &netbios_domain_l
,
1150 .user
= &sAMAccountName_u
,
1151 .realm
= &netbios_domain_u
,
1154 .user
= &sAMAccountName
,
1155 .realm
= &netbios_domain_u
,
1158 .user
= &sAMAccountName
,
1159 .realm
= &netbios_domain_l
,
1162 .user
= &sAMAccountName_u
,
1163 .realm
= &netbios_domain_l
,
1166 .user
= &sAMAccountName_l
,
1167 .realm
= &netbios_domain_u
,
1170 * sAMAccountName, dns_domain
1173 * Windows preserves the case of the DNS domain,
1174 * Samba lower cases the domain at provision time
1175 * This means that for mixed case Domains, the WDigest08 hash
1176 * calculated by Samba differs from that calculated by Windows.
1177 * Until we get a real world use case this will remain a known
1178 * bug, as changing the case could have unforeseen impacts.
1182 .user
= &sAMAccountName
,
1183 .realm
= &dns_domain
,
1186 .user
= &sAMAccountName_l
,
1187 .realm
= &dns_domain_l
,
1190 .user
= &sAMAccountName_u
,
1191 .realm
= &dns_domain_u
,
1194 .user
= &sAMAccountName
,
1195 .realm
= &dns_domain_u
,
1198 .user
= &sAMAccountName
,
1199 .realm
= &dns_domain_l
,
1202 .user
= &sAMAccountName_u
,
1203 .realm
= &dns_domain_l
,
1206 .user
= &sAMAccountName_l
,
1207 .realm
= &dns_domain_u
,
1210 * userPrincipalName, no realm
1213 .user
= &userPrincipalName
,
1217 * NOTE: w2k3 messes this up, if the user has a real userPrincipalName,
1218 * the fallback to the sAMAccountName based userPrincipalName is correct
1220 .user
= &userPrincipalName_l
,
1223 .user
= &userPrincipalName_u
,
1226 * nt4dom\sAMAccountName, no realm
1229 .user
= &sAMAccountName
,
1230 .nt4dom
= &netbios_domain
1233 .user
= &sAMAccountName_l
,
1234 .nt4dom
= &netbios_domain_l
1237 .user
= &sAMAccountName_u
,
1238 .nt4dom
= &netbios_domain_u
1242 * the following ones are guessed depending on the technet2 article
1243 * but not reproducable on a w2k3 server
1245 /* sAMAccountName with "Digest" realm */
1247 .user
= &sAMAccountName
,
1251 .user
= &sAMAccountName_l
,
1255 .user
= &sAMAccountName_u
,
1258 /* userPrincipalName with "Digest" realm */
1260 .user
= &userPrincipalName
,
1264 .user
= &userPrincipalName_l
,
1268 .user
= &userPrincipalName_u
,
1271 /* nt4dom\\sAMAccountName with "Digest" realm */
1273 .user
= &sAMAccountName
,
1274 .nt4dom
= &netbios_domain
,
1278 .user
= &sAMAccountName_l
,
1279 .nt4dom
= &netbios_domain_l
,
1283 .user
= &sAMAccountName_u
,
1284 .nt4dom
= &netbios_domain_u
,
1288 int rc
= LDB_ERR_OTHER
;
1290 /* prepare DATA_BLOB's used in the combinations array */
1291 sAMAccountName
= data_blob_string_const(io
->u
.sAMAccountName
);
1292 sAMAccountName_l
= data_blob_string_const(strlower_talloc(io
->ac
, io
->u
.sAMAccountName
));
1293 if (!sAMAccountName_l
.data
) {
1294 return ldb_oom(ldb
);
1296 sAMAccountName_u
= data_blob_string_const(strupper_talloc(io
->ac
, io
->u
.sAMAccountName
));
1297 if (!sAMAccountName_u
.data
) {
1298 return ldb_oom(ldb
);
1301 /* if the user doesn't have a userPrincipalName, create one (with lower case realm) */
1302 if (!user_principal_name
) {
1303 user_principal_name
= talloc_asprintf(io
->ac
, "%s@%s",
1304 io
->u
.sAMAccountName
,
1305 io
->ac
->status
->domain_data
.dns_domain
);
1306 if (!user_principal_name
) {
1307 return ldb_oom(ldb
);
1310 userPrincipalName
= data_blob_string_const(user_principal_name
);
1311 userPrincipalName_l
= data_blob_string_const(strlower_talloc(io
->ac
, user_principal_name
));
1312 if (!userPrincipalName_l
.data
) {
1313 return ldb_oom(ldb
);
1315 userPrincipalName_u
= data_blob_string_const(strupper_talloc(io
->ac
, user_principal_name
));
1316 if (!userPrincipalName_u
.data
) {
1317 return ldb_oom(ldb
);
1320 netbios_domain
= data_blob_string_const(io
->ac
->status
->domain_data
.netbios_domain
);
1321 netbios_domain_l
= data_blob_string_const(strlower_talloc(io
->ac
,
1322 io
->ac
->status
->domain_data
.netbios_domain
));
1323 if (!netbios_domain_l
.data
) {
1324 return ldb_oom(ldb
);
1326 netbios_domain_u
= data_blob_string_const(strupper_talloc(io
->ac
,
1327 io
->ac
->status
->domain_data
.netbios_domain
));
1328 if (!netbios_domain_u
.data
) {
1329 return ldb_oom(ldb
);
1332 dns_domain
= data_blob_string_const(io
->ac
->status
->domain_data
.dns_domain
);
1333 dns_domain_l
= data_blob_string_const(io
->ac
->status
->domain_data
.dns_domain
);
1334 dns_domain_u
= data_blob_string_const(io
->ac
->status
->domain_data
.realm
);
1336 digest
= data_blob_string_const("Digest");
1338 delim
= data_blob_string_const(":");
1339 backslash
= data_blob_string_const("\\");
1341 pdb
->num_hashes
= ARRAY_SIZE(wdigest
);
1342 pdb
->hashes
= talloc_array(io
->ac
, struct package_PrimaryWDigestHash
,
1345 return ldb_oom(ldb
);
1348 for (i
=0; i
< ARRAY_SIZE(wdigest
); i
++) {
1349 gnutls_hash_hd_t hash_hnd
= NULL
;
1351 rc
= gnutls_hash_init(&hash_hnd
, GNUTLS_DIG_MD5
);
1357 if (wdigest
[i
].nt4dom
) {
1358 rc
= gnutls_hash(hash_hnd
,
1359 wdigest
[i
].nt4dom
->data
,
1360 wdigest
[i
].nt4dom
->length
);
1362 gnutls_hash_deinit(hash_hnd
, NULL
);
1363 rc
= LDB_ERR_UNWILLING_TO_PERFORM
;
1366 rc
= gnutls_hash(hash_hnd
,
1370 gnutls_hash_deinit(hash_hnd
, NULL
);
1371 rc
= LDB_ERR_UNWILLING_TO_PERFORM
;
1375 rc
= gnutls_hash(hash_hnd
,
1376 wdigest
[i
].user
->data
,
1377 wdigest
[i
].user
->length
);
1379 gnutls_hash_deinit(hash_hnd
, NULL
);
1380 rc
= LDB_ERR_UNWILLING_TO_PERFORM
;
1383 rc
= gnutls_hash(hash_hnd
, delim
.data
, delim
.length
);
1385 gnutls_hash_deinit(hash_hnd
, NULL
);
1386 rc
= LDB_ERR_UNWILLING_TO_PERFORM
;
1389 if (wdigest
[i
].realm
) {
1390 rc
= gnutls_hash(hash_hnd
,
1391 wdigest
[i
].realm
->data
,
1392 wdigest
[i
].realm
->length
);
1394 gnutls_hash_deinit(hash_hnd
, NULL
);
1395 rc
= LDB_ERR_UNWILLING_TO_PERFORM
;
1399 rc
= gnutls_hash(hash_hnd
, delim
.data
, delim
.length
);
1401 gnutls_hash_deinit(hash_hnd
, NULL
);
1402 rc
= LDB_ERR_UNWILLING_TO_PERFORM
;
1405 rc
= gnutls_hash(hash_hnd
,
1406 io
->n
.cleartext_utf8
->data
,
1407 io
->n
.cleartext_utf8
->length
);
1409 gnutls_hash_deinit(hash_hnd
, NULL
);
1410 rc
= LDB_ERR_UNWILLING_TO_PERFORM
;
1414 gnutls_hash_deinit(hash_hnd
, pdb
->hashes
[i
].hash
);
1422 #define SHA_SALT_PERMITTED_CHARS "abcdefghijklmnopqrstuvwxyz" \
1423 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
1425 #define SHA_SALT_SIZE 16
1426 #define SHA_256_SCHEME "CryptSHA256"
1427 #define SHA_512_SCHEME "CryptSHA512"
1428 #define CRYPT "{CRYPT}"
1429 #define SHA_ID_LEN 3
1430 #define SHA_256_ALGORITHM_ID 5
1431 #define SHA_512_ALGORITHM_ID 6
1432 #define ROUNDS_PARAMETER "rounds="
1435 * Extract the crypt (3) algorithm number and number of hash rounds from the
1436 * supplied scheme string
1438 static bool parse_scheme(const char *scheme
, int *algorithm
, int *rounds
) {
1440 const char *rp
= NULL
; /* Pointer to the 'rounds=' option */
1441 char digits
[21]; /* digits extracted from the rounds option */
1442 int i
= 0; /* loop index variable */
1444 if (strncasecmp(SHA_256_SCHEME
, scheme
, strlen(SHA_256_SCHEME
)) == 0) {
1445 *algorithm
= SHA_256_ALGORITHM_ID
;
1446 } else if (strncasecmp(SHA_512_SCHEME
, scheme
, strlen(SHA_256_SCHEME
))
1448 *algorithm
= SHA_512_ALGORITHM_ID
;
1453 rp
= strcasestr(scheme
, ROUNDS_PARAMETER
);
1455 /* No options specified, use crypt default number of rounds */
1459 rp
+= strlen(ROUNDS_PARAMETER
);
1460 for (i
= 0; isdigit(rp
[i
]) && i
< (sizeof(digits
) - 1); i
++) {
1464 *rounds
= atoi(digits
);
1469 * Calculate the password hash specified by scheme, and return it in
1472 static int setup_primary_userPassword_hash(
1474 struct setup_password_fields_io
*io
,
1476 struct package_PrimaryUserPasswordValue
*hash_value
)
1478 struct ldb_context
*ldb
= ldb_module_get_ctx(io
->ac
->module
);
1479 const char *salt
= NULL
; /* Randomly generated salt */
1480 const char *cmd
= NULL
; /* command passed to crypt */
1481 const char *hash
= NULL
; /* password hash generated by crypt */
1482 int algorithm
= 0; /* crypt hash algorithm number */
1483 int rounds
= 0; /* The number of hash rounds */
1484 DATA_BLOB
*hash_blob
= NULL
;
1485 TALLOC_CTX
*frame
= talloc_stackframe();
1486 #if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT_RN)
1487 struct crypt_data crypt_data
= {
1488 .initialized
= 0 /* working storage used by crypt */
1492 /* Genrate a random password salt */
1493 salt
= generate_random_str_list(frame
,
1495 SHA_SALT_PERMITTED_CHARS
);
1498 return ldb_oom(ldb
);
1501 /* determine the hashing algoritm and number of rounds*/
1502 if (!parse_scheme(scheme
, &algorithm
, &rounds
)) {
1503 ldb_asprintf_errstring(
1505 "setup_primary_userPassword: Invalid scheme of [%s] "
1506 "specified for 'password hash userPassword schemes' in "
1510 return LDB_ERR_OPERATIONS_ERROR
;
1512 hash_value
->scheme
= talloc_strdup(ctx
, CRYPT
);
1513 hash_value
->scheme_len
= strlen(CRYPT
) + 1;
1515 /* generate the id/salt parameter used by crypt */
1517 cmd
= talloc_asprintf(frame
,
1523 cmd
= talloc_asprintf(frame
, "$%d$%s", algorithm
, salt
);
1527 * Relies on the assertion that cleartext_utf8->data is a zero
1528 * terminated UTF-8 string
1532 * crypt_r() and crypt() may return a null pointer upon error
1533 * depending on how libcrypt was configured, so we prefer
1534 * crypt_rn() from libcrypt / libxcrypt which always returns
1537 * POSIX specifies returning a null pointer and setting
1540 * RHEL 7 (which does not use libcrypt / libxcrypt) returns a
1541 * non-NULL pointer from crypt_r() on success but (always?)
1542 * sets errno during internal processing in the NSS crypto
1545 * By preferring crypt_rn we avoid the 'return non-NULL but
1546 * set-errno' that we otherwise cannot tell apart from the
1551 #ifdef HAVE_CRYPT_RN
1552 hash
= crypt_rn((char *)io
->n
.cleartext_utf8
->data
,
1555 sizeof(crypt_data
));
1557 hash
= crypt_r((char *)io
->n
.cleartext_utf8
->data
, cmd
, &crypt_data
);
1560 * No crypt_r falling back to crypt, which is NOT thread safe
1561 * Thread safety MT-Unsafe race:crypt
1563 hash
= crypt((char *)io
->n
.cleartext_utf8
->data
, cmd
);
1566 * On error, crypt() and crypt_r() may return a null pointer,
1567 * or a pointer to an invalid hash beginning with a '*'.
1569 if (hash
== NULL
|| hash
[0] == '*') {
1571 const char *reason
= NULL
;
1572 if (errno
== ERANGE
) {
1573 reason
= "Password exceeds maximum length allowed for crypt() hashing";
1575 int err
= strerror_r(errno
, buf
, sizeof(buf
));
1579 reason
= "Unknown error";
1582 ldb_asprintf_errstring(
1584 "setup_primary_userPassword: generation of a %s "
1585 "password hash failed: (%s)",
1589 return LDB_ERR_OPERATIONS_ERROR
;
1592 hash_blob
= talloc_zero(ctx
, DATA_BLOB
);
1594 if (hash_blob
== NULL
) {
1596 return ldb_oom(ldb
);
1599 *hash_blob
= data_blob_talloc(hash_blob
,
1600 (const uint8_t *)hash
,
1602 if (hash_blob
->data
== NULL
) {
1604 return ldb_oom(ldb
);
1606 hash_value
->value
= hash_blob
;
1612 * Calculate the desired extra password hashes
1614 static int setup_primary_userPassword(
1615 struct setup_password_fields_io
*io
,
1616 const struct supplementalCredentialsBlob
*old_scb
,
1617 struct package_PrimaryUserPasswordBlob
*p_userPassword_b
)
1619 struct ldb_context
*ldb
= ldb_module_get_ctx(io
->ac
->module
);
1620 TALLOC_CTX
*frame
= talloc_stackframe();
1625 * Save the current nt_hash, use this to determine if the password
1626 * has been changed by windows. Which will invalidate the userPassword
1627 * hash. Note once NTLM-Strong-NOWTF becomes available it should be
1628 * used in preference to the NT password hash
1630 if (io
->g
.nt_hash
== NULL
) {
1631 ldb_asprintf_errstring(ldb
,
1632 "No NT Hash, unable to calculate userPassword hashes");
1633 return LDB_ERR_UNWILLING_TO_PERFORM
;
1635 p_userPassword_b
->current_nt_hash
= *io
->g
.nt_hash
;
1638 * Determine the number of hashes
1639 * Note: that currently there is no limit on the number of hashes
1640 * no checking is done on the number of schemes specified
1641 * or for uniqueness.
1643 p_userPassword_b
->num_hashes
= 0;
1644 for (i
= 0; io
->ac
->userPassword_schemes
[i
]; i
++) {
1645 p_userPassword_b
->num_hashes
++;
1648 p_userPassword_b
->hashes
1649 = talloc_array(io
->ac
,
1650 struct package_PrimaryUserPasswordValue
,
1651 p_userPassword_b
->num_hashes
);
1652 if (p_userPassword_b
->hashes
== NULL
) {
1654 return ldb_oom(ldb
);
1657 for (i
= 0; io
->ac
->userPassword_schemes
[i
]; i
++) {
1658 ret
= setup_primary_userPassword_hash(
1659 p_userPassword_b
->hashes
,
1661 io
->ac
->userPassword_schemes
[i
],
1662 &p_userPassword_b
->hashes
[i
]);
1663 if (ret
!= LDB_SUCCESS
) {
1672 static int setup_primary_samba_gpg(struct setup_password_fields_io
*io
,
1673 struct package_PrimarySambaGPGBlob
*pgb
)
1675 struct ldb_context
*ldb
= ldb_module_get_ctx(io
->ac
->module
);
1678 gpgme_ctx_t ctx
= NULL
;
1679 size_t num_keys
= str_list_length(io
->ac
->gpg_key_ids
);
1680 gpgme_key_t keys
[num_keys
+1];
1683 gpgme_data_t plain_data
= NULL
;
1684 gpgme_data_t crypt_data
= NULL
;
1685 size_t crypt_length
= 0;
1686 char *crypt_mem
= NULL
;
1688 gret
= gpgme_new(&ctx
);
1689 if (gret
!= GPG_ERR_NO_ERROR
) {
1690 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1691 "%s:%s: gret[%u] %s\n",
1692 __location__
, __func__
,
1693 gret
, gpgme_strerror(gret
));
1694 return ldb_module_operr(io
->ac
->module
);
1697 gpgme_set_armor(ctx
, 1);
1699 gret
= gpgme_data_new_from_mem(&plain_data
,
1700 (const char *)io
->n
.cleartext_utf16
->data
,
1701 io
->n
.cleartext_utf16
->length
,
1703 if (gret
!= GPG_ERR_NO_ERROR
) {
1704 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1705 "%s:%s: gret[%u] %s\n",
1706 __location__
, __func__
,
1707 gret
, gpgme_strerror(gret
));
1709 return ldb_module_operr(io
->ac
->module
);
1711 gret
= gpgme_data_new(&crypt_data
);
1712 if (gret
!= GPG_ERR_NO_ERROR
) {
1713 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1714 "%s:%s: gret[%u] %s\n",
1715 __location__
, __func__
,
1716 gret
, gpgme_strerror(gret
));
1717 gpgme_data_release(plain_data
);
1719 return ldb_module_operr(io
->ac
->module
);
1722 for (ki
= 0; ki
< num_keys
; ki
++) {
1723 const char *key_id
= io
->ac
->gpg_key_ids
[ki
];
1724 size_t len
= strlen(key_id
);
1729 ldb_debug(ldb
, LDB_DEBUG_FATAL
,
1730 "%s:%s: ki[%zu] key_id[%s] strlen < 16, "
1731 "please specify at least the 64bit key id\n",
1732 __location__
, __func__
,
1734 for (kr
= 0; keys
[kr
] != NULL
; kr
++) {
1735 gpgme_key_release(keys
[kr
]);
1737 gpgme_data_release(crypt_data
);
1738 gpgme_data_release(plain_data
);
1740 return ldb_module_operr(io
->ac
->module
);
1743 gret
= gpgme_get_key(ctx
, key_id
, &keys
[ki
], 0 /* public key */);
1744 if (gret
!= GPG_ERR_NO_ERROR
) {
1746 if (gpg_err_source(gret
) == GPG_ERR_SOURCE_GPGME
1747 && gpg_err_code(gret
) == GPG_ERR_EOF
) {
1748 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1750 "'password hash gpg key ids': "
1751 "Public Key ID [%s] "
1752 "not found in keyring\n",
1756 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1757 "%s:%s: ki[%zu] key_id[%s] "
1759 __location__
, __func__
,
1761 gret
, gpgme_strerror(gret
));
1763 for (kr
= 0; keys
[kr
] != NULL
; kr
++) {
1764 gpgme_key_release(keys
[kr
]);
1766 gpgme_data_release(crypt_data
);
1767 gpgme_data_release(plain_data
);
1769 return ldb_module_operr(io
->ac
->module
);
1774 gret
= gpgme_op_encrypt(ctx
, keys
,
1775 GPGME_ENCRYPT_ALWAYS_TRUST
,
1776 plain_data
, crypt_data
);
1777 gpgme_data_release(plain_data
);
1779 for (kr
= 0; keys
[kr
] != NULL
; kr
++) {
1780 gpgme_key_release(keys
[kr
]);
1785 if (gret
!= GPG_ERR_NO_ERROR
) {
1786 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1787 "%s:%s: gret[%u] %s\n",
1788 __location__
, __func__
,
1789 gret
, gpgme_strerror(gret
));
1790 gpgme_data_release(crypt_data
);
1791 return ldb_module_operr(io
->ac
->module
);
1794 crypt_mem
= gpgme_data_release_and_get_mem(crypt_data
, &crypt_length
);
1796 if (crypt_mem
== NULL
) {
1797 return ldb_module_oom(io
->ac
->module
);
1800 pgb
->gpg_blob
= data_blob_talloc(io
->ac
,
1801 (const uint8_t *)crypt_mem
,
1803 gpgme_free(crypt_mem
);
1806 if (pgb
->gpg_blob
.data
== NULL
) {
1807 return ldb_module_oom(io
->ac
->module
);
1811 #else /* ENABLE_GPGME */
1812 ldb_debug_set(ldb
, LDB_DEBUG_FATAL
,
1813 "You configured 'password hash gpg key ids', "
1814 "but GPGME support is missing. (%s:%d)",
1815 __FILE__
, __LINE__
);
1816 return LDB_ERR_UNWILLING_TO_PERFORM
;
1817 #endif /* else ENABLE_GPGME */
1820 #define NUM_PACKAGES 6
1821 static int setup_supplemental_field(struct setup_password_fields_io
*io
)
1823 struct ldb_context
*ldb
;
1824 struct supplementalCredentialsBlob scb
;
1825 struct supplementalCredentialsBlob
*old_scb
= NULL
;
1828 * ( Kerberos-Newer-Keys, Kerberos,
1829 * WDigest, CLEARTEXT, userPassword, SambaGPG)
1831 uint32_t num_names
= 0;
1832 const char *names
[1+NUM_PACKAGES
];
1833 uint32_t num_packages
= 0;
1834 struct supplementalCredentialsPackage packages
[1+NUM_PACKAGES
];
1835 struct supplementalCredentialsPackage
*pp
= packages
;
1837 enum ndr_err_code ndr_err
;
1838 bool do_newer_keys
= false;
1839 bool do_cleartext
= false;
1840 bool do_samba_gpg
= false;
1841 struct loadparm_context
*lp_ctx
= NULL
;
1844 ZERO_STRUCT(packages
);
1846 ldb
= ldb_module_get_ctx(io
->ac
->module
);
1847 lp_ctx
= talloc_get_type(ldb_get_opaque(ldb
, "loadparm"),
1848 struct loadparm_context
);
1850 if (!io
->n
.cleartext_utf8
) {
1852 * when we don't have a cleartext password
1853 * we can't setup a supplementalCredential value
1858 /* if there's an old supplementaCredentials blob then use it */
1859 if (io
->o
.supplemental
) {
1860 if (io
->o
.scb
.sub
.signature
== SUPPLEMENTAL_CREDENTIALS_SIGNATURE
) {
1861 old_scb
= &io
->o
.scb
;
1863 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1864 "setup_supplemental_field: "
1865 "supplementalCredentialsBlob "
1866 "signature[0x%04X] expected[0x%04X]",
1867 io
->o
.scb
.sub
.signature
,
1868 SUPPLEMENTAL_CREDENTIALS_SIGNATURE
);
1871 /* Per MS-SAMR 3.1.1.8.11.6 we create AES keys if our domain functionality level is 2008 or higher */
1876 * The ordering is this
1878 * Primary:Kerberos-Newer-Keys (optional)
1881 * Primary:CLEARTEXT (optional)
1882 * Primary:userPassword
1883 * Primary:SambaGPG (optional)
1885 * And the 'Packages' package is insert before the last
1888 * Note: it's important that Primary:SambaGPG is added as
1889 * the last element. This is the indication that it matches
1890 * the current password. When a password change happens on
1891 * a Windows DC, it will keep the old Primary:SambaGPG value,
1892 * but as the first element.
1894 do_newer_keys
= (dsdb_functional_level(ldb
) >= DS_DOMAIN_FUNCTION_2008
);
1895 if (do_newer_keys
) {
1896 struct package_PrimaryKerberosBlob pknb
;
1897 DATA_BLOB pknb_blob
;
1900 * setup 'Primary:Kerberos-Newer-Keys' element
1902 names
[num_names
++] = "Kerberos-Newer-Keys";
1904 ret
= setup_primary_kerberos_newer(io
, old_scb
, &pknb
);
1905 if (ret
!= LDB_SUCCESS
) {
1909 ndr_err
= ndr_push_struct_blob(
1912 (ndr_push_flags_fn_t
)ndr_push_package_PrimaryKerberosBlob
);
1913 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1914 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1915 ldb_asprintf_errstring(
1917 "setup_supplemental_field: "
1919 "package_PrimaryKerberosNeverBlob: %s",
1921 return LDB_ERR_OPERATIONS_ERROR
;
1923 pknb_hexstr
= data_blob_hex_string_upper(io
->ac
, &pknb_blob
);
1925 return ldb_oom(ldb
);
1927 pp
->name
= "Primary:Kerberos-Newer-Keys";
1929 pp
->data
= pknb_hexstr
;
1936 * setup 'Primary:Kerberos' element
1938 /* Primary:Kerberos */
1939 struct package_PrimaryKerberosBlob pkb
;
1943 names
[num_names
++] = "Kerberos";
1945 ret
= setup_primary_kerberos(io
, old_scb
, &pkb
);
1946 if (ret
!= LDB_SUCCESS
) {
1950 ndr_err
= ndr_push_struct_blob(
1953 (ndr_push_flags_fn_t
)ndr_push_package_PrimaryKerberosBlob
);
1954 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1955 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1956 ldb_asprintf_errstring(
1958 "setup_supplemental_field: "
1959 "failed to push package_PrimaryKerberosBlob: %s",
1961 return LDB_ERR_OPERATIONS_ERROR
;
1963 pkb_hexstr
= data_blob_hex_string_upper(io
->ac
, &pkb_blob
);
1965 return ldb_oom(ldb
);
1967 pp
->name
= "Primary:Kerberos";
1969 pp
->data
= pkb_hexstr
;
1974 if (lpcfg_weak_crypto(lp_ctx
) == SAMBA_WEAK_CRYPTO_ALLOWED
) {
1976 * setup 'Primary:WDigest' element
1978 struct package_PrimaryWDigestBlob pdb
;
1982 names
[num_names
++] = "WDigest";
1984 ret
= setup_primary_wdigest(io
, old_scb
, &pdb
);
1985 if (ret
!= LDB_SUCCESS
) {
1989 ndr_err
= ndr_push_struct_blob(
1992 (ndr_push_flags_fn_t
)ndr_push_package_PrimaryWDigestBlob
);
1993 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1994 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1995 ldb_asprintf_errstring(
1997 "setup_supplemental_field: "
1998 "failed to push package_PrimaryWDigestBlob: %s",
2000 return LDB_ERR_OPERATIONS_ERROR
;
2002 pdb_hexstr
= data_blob_hex_string_upper(io
->ac
, &pdb_blob
);
2004 return ldb_oom(ldb
);
2006 pp
->name
= "Primary:WDigest";
2008 pp
->data
= pdb_hexstr
;
2014 * setup 'Primary:CLEARTEXT' element
2016 if (io
->ac
->status
->domain_data
.store_cleartext
&&
2017 (io
->u
.userAccountControl
& UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED
)) {
2018 do_cleartext
= true;
2021 struct package_PrimaryCLEARTEXTBlob pcb
;
2025 names
[num_names
++] = "CLEARTEXT";
2027 pcb
.cleartext
= *io
->n
.cleartext_utf16
;
2029 ndr_err
= ndr_push_struct_blob(
2032 (ndr_push_flags_fn_t
)ndr_push_package_PrimaryCLEARTEXTBlob
);
2033 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2034 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2035 ldb_asprintf_errstring(
2037 "setup_supplemental_field: "
2038 "failed to push package_PrimaryCLEARTEXTBlob: %s",
2040 return LDB_ERR_OPERATIONS_ERROR
;
2042 pcb_hexstr
= data_blob_hex_string_upper(io
->ac
, &pcb_blob
);
2044 return ldb_oom(ldb
);
2046 pp
->name
= "Primary:CLEARTEXT";
2048 pp
->data
= pcb_hexstr
;
2054 * Don't generate crypt() or similar password for the krbtgt account.
2055 * It's unnecessary, and the length of the cleartext in UTF-8 form
2056 * exceeds the maximum (CRYPT_MAX_PASSPHRASE_SIZE) allowed by crypt().
2058 if (io
->ac
->userPassword_schemes
&& !io
->u
.is_krbtgt
) {
2060 * setup 'Primary:userPassword' element
2062 struct package_PrimaryUserPasswordBlob
2064 DATA_BLOB p_userPassword_b_blob
;
2065 char *p_userPassword_b_hexstr
;
2067 names
[num_names
++] = "userPassword";
2069 ret
= setup_primary_userPassword(io
,
2072 if (ret
!= LDB_SUCCESS
) {
2076 ndr_err
= ndr_push_struct_blob(
2077 &p_userPassword_b_blob
,
2080 (ndr_push_flags_fn_t
)
2081 ndr_push_package_PrimaryUserPasswordBlob
);
2082 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2083 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2084 ldb_asprintf_errstring(
2086 "setup_supplemental_field: failed to push "
2087 "package_PrimaryUserPasswordBlob: %s",
2089 return LDB_ERR_OPERATIONS_ERROR
;
2091 p_userPassword_b_hexstr
2092 = data_blob_hex_string_upper(
2094 &p_userPassword_b_blob
);
2095 if (!p_userPassword_b_hexstr
) {
2096 return ldb_oom(ldb
);
2098 pp
->name
= "Primary:userPassword";
2100 pp
->data
= p_userPassword_b_hexstr
;
2106 * setup 'Primary:SambaGPG' element
2108 if (io
->ac
->gpg_key_ids
!= NULL
) {
2109 do_samba_gpg
= true;
2112 struct package_PrimarySambaGPGBlob pgb
;
2116 names
[num_names
++] = "SambaGPG";
2118 ret
= setup_primary_samba_gpg(io
, &pgb
);
2119 if (ret
!= LDB_SUCCESS
) {
2123 ndr_err
= ndr_push_struct_blob(&pgb_blob
, io
->ac
, &pgb
,
2124 (ndr_push_flags_fn_t
)ndr_push_package_PrimarySambaGPGBlob
);
2125 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2126 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2127 ldb_asprintf_errstring(ldb
,
2128 "setup_supplemental_field: failed to "
2129 "push package_PrimarySambaGPGBlob: %s",
2131 return LDB_ERR_OPERATIONS_ERROR
;
2133 pgb_hexstr
= data_blob_hex_string_upper(io
->ac
, &pgb_blob
);
2135 return ldb_oom(ldb
);
2137 pp
->name
= "Primary:SambaGPG";
2139 pp
->data
= pgb_hexstr
;
2145 * setup 'Packages' element
2148 struct package_PackagesBlob pb
;
2153 ndr_err
= ndr_push_struct_blob(
2156 (ndr_push_flags_fn_t
)ndr_push_package_PackagesBlob
);
2157 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2158 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2159 ldb_asprintf_errstring(
2161 "setup_supplemental_field: "
2162 "failed to push package_PackagesBlob: %s",
2164 return LDB_ERR_OPERATIONS_ERROR
;
2166 pb_hexstr
= data_blob_hex_string_upper(io
->ac
, &pb_blob
);
2168 return ldb_oom(ldb
);
2170 pp
->name
= "Packages";
2172 pp
->data
= pb_hexstr
;
2175 * We don't increment pp so it's pointing to the last package
2180 * setup 'supplementalCredentials' value
2184 * The 'Packages' element needs to be the second last element
2185 * in supplementalCredentials
2187 struct supplementalCredentialsPackage temp
;
2188 struct supplementalCredentialsPackage
*prev
;
2196 scb
.sub
.signature
= SUPPLEMENTAL_CREDENTIALS_SIGNATURE
;
2197 scb
.sub
.num_packages
= num_packages
;
2198 scb
.sub
.packages
= packages
;
2200 ndr_err
= ndr_push_struct_blob(
2201 &io
->g
.supplemental
, io
->ac
,
2203 (ndr_push_flags_fn_t
)ndr_push_supplementalCredentialsBlob
);
2204 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2205 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2206 ldb_asprintf_errstring(
2208 "setup_supplemental_field: "
2209 "failed to push supplementalCredentialsBlob: %s",
2211 return LDB_ERR_OPERATIONS_ERROR
;
2218 static int setup_last_set_field(struct setup_password_fields_io
*io
)
2220 struct ldb_context
*ldb
= ldb_module_get_ctx(io
->ac
->module
);
2221 const struct ldb_message
*msg
= NULL
;
2222 struct timeval tv
= { .tv_sec
= 0 };
2223 const struct ldb_val
*old_val
= NULL
;
2224 const struct ldb_val
*new_val
= NULL
;
2227 switch (io
->ac
->req
->operation
) {
2229 msg
= io
->ac
->req
->op
.add
.message
;
2232 msg
= io
->ac
->req
->op
.mod
.message
;
2235 return LDB_ERR_OPERATIONS_ERROR
;
2239 if (io
->ac
->pwd_last_set_bypass
) {
2240 struct ldb_message_element
*el1
= NULL
;
2241 struct ldb_message_element
*el2
= NULL
;
2244 return LDB_ERR_CONSTRAINT_VIOLATION
;
2247 el1
= dsdb_get_single_valued_attr(msg
, "pwdLastSet",
2248 io
->ac
->req
->operation
);
2250 return LDB_ERR_CONSTRAINT_VIOLATION
;
2252 el2
= ldb_msg_find_element(msg
, "pwdLastSet");
2254 return LDB_ERR_CONSTRAINT_VIOLATION
;
2257 return LDB_ERR_CONSTRAINT_VIOLATION
;
2260 io
->g
.last_set
= samdb_result_nttime(msg
, "pwdLastSet", 0);
2264 ret
= msg_find_old_and_new_pwd_val(msg
, "pwdLastSet",
2265 io
->ac
->req
->operation
,
2266 &new_val
, &old_val
);
2267 if (ret
!= LDB_SUCCESS
) {
2271 if (old_val
!= NULL
&& new_val
== NULL
) {
2272 ldb_set_errstring(ldb
,
2273 "'pwdLastSet' deletion is not allowed!");
2274 return LDB_ERR_UNWILLING_TO_PERFORM
;
2277 io
->g
.last_set
= UINT64_MAX
;
2278 if (new_val
!= NULL
) {
2279 struct ldb_message
*tmp_msg
= NULL
;
2281 tmp_msg
= ldb_msg_new(io
->ac
);
2282 if (tmp_msg
== NULL
) {
2283 return ldb_module_oom(io
->ac
->module
);
2286 if (old_val
!= NULL
) {
2287 NTTIME old_last_set
= 0;
2289 ret
= ldb_msg_add_value(tmp_msg
, "oldval",
2291 if (ret
!= LDB_SUCCESS
) {
2295 old_last_set
= samdb_result_nttime(tmp_msg
,
2298 if (io
->u
.pwdLastSet
!= old_last_set
) {
2299 return dsdb_module_werror(io
->ac
->module
,
2300 LDB_ERR_NO_SUCH_ATTRIBUTE
,
2301 WERR_DS_CANT_REM_MISSING_ATT_VAL
,
2302 "setup_last_set_field: old pwdLastSet "
2303 "value not found!");
2307 ret
= ldb_msg_add_value(tmp_msg
, "newval",
2309 if (ret
!= LDB_SUCCESS
) {
2313 io
->g
.last_set
= samdb_result_nttime(tmp_msg
,
2316 } else if (ldb_msg_find_element(msg
, "pwdLastSet")) {
2317 ldb_set_errstring(ldb
,
2318 "'pwdLastSet' deletion is not allowed!");
2319 return LDB_ERR_UNWILLING_TO_PERFORM
;
2320 } else if (io
->ac
->smartcard_reset
) {
2322 * adding UF_SMARTCARD_REQUIRED doesn't update
2323 * pwdLastSet implicitly.
2325 io
->ac
->update_lastset
= false;
2328 /* only 0 or -1 (0xFFFFFFFFFFFFFFFF) are allowed */
2329 switch (io
->g
.last_set
) {
2331 if (!io
->ac
->pwd_last_set_default
) {
2334 if (!io
->ac
->update_password
) {
2339 if (!io
->ac
->update_password
&&
2340 io
->u
.pwdLastSet
!= 0 &&
2341 io
->u
.pwdLastSet
!= UINT64_MAX
)
2344 * Just setting pwdLastSet to -1, while not changing
2345 * any password field has no effect if pwdLastSet
2346 * is already non-zero.
2348 io
->ac
->update_lastset
= false;
2351 /* -1 means set it as now */
2353 io
->g
.last_set
= timeval_to_nttime(&tv
);
2356 return dsdb_module_werror(io
->ac
->module
,
2358 WERR_INVALID_PARAMETER
,
2359 "setup_last_set_field: "
2360 "pwdLastSet must be 0 or -1 only!");
2363 if (io
->ac
->req
->operation
== LDB_ADD
) {
2365 * We always need to store the value on add
2371 if (io
->g
.last_set
== io
->u
.pwdLastSet
) {
2373 * Just setting pwdLastSet to 0, is no-op if it's already 0.
2375 io
->ac
->update_lastset
= false;
2381 static int setup_given_passwords(struct setup_password_fields_io
*io
,
2382 struct setup_password_fields_given
*g
)
2384 struct ldb_context
*ldb
;
2387 ldb
= ldb_module_get_ctx(io
->ac
->module
);
2389 if (g
->cleartext_utf8
) {
2390 struct ldb_val
*cleartext_utf16_blob
;
2392 cleartext_utf16_blob
= talloc(io
->ac
, struct ldb_val
);
2393 if (!cleartext_utf16_blob
) {
2394 return ldb_oom(ldb
);
2396 if (!convert_string_talloc(io
->ac
,
2398 g
->cleartext_utf8
->data
,
2399 g
->cleartext_utf8
->length
,
2400 (void *)&cleartext_utf16_blob
->data
,
2401 &cleartext_utf16_blob
->length
)) {
2402 if (g
->cleartext_utf8
->length
!= 0) {
2403 talloc_free(cleartext_utf16_blob
);
2404 ldb_asprintf_errstring(ldb
,
2405 "setup_password_fields: "
2406 "failed to generate UTF16 password from cleartext UTF8 one for user '%s'!",
2407 io
->u
.sAMAccountName
);
2408 return LDB_ERR_CONSTRAINT_VIOLATION
;
2410 /* passwords with length "0" are valid! */
2411 cleartext_utf16_blob
->data
= NULL
;
2412 cleartext_utf16_blob
->length
= 0;
2415 g
->cleartext_utf16
= cleartext_utf16_blob
;
2416 } else if (g
->cleartext_utf16
) {
2417 struct ldb_val
*cleartext_utf8_blob
;
2419 cleartext_utf8_blob
= talloc(io
->ac
, struct ldb_val
);
2420 if (!cleartext_utf8_blob
) {
2421 return ldb_oom(ldb
);
2423 if (!convert_string_talloc(io
->ac
,
2424 CH_UTF16MUNGED
, CH_UTF8
,
2425 g
->cleartext_utf16
->data
,
2426 g
->cleartext_utf16
->length
,
2427 (void *)&cleartext_utf8_blob
->data
,
2428 &cleartext_utf8_blob
->length
)) {
2429 if (g
->cleartext_utf16
->length
!= 0) {
2430 /* We must bail out here, the input wasn't even
2431 * a multiple of 2 bytes */
2432 talloc_free(cleartext_utf8_blob
);
2433 ldb_asprintf_errstring(ldb
,
2434 "setup_password_fields: "
2435 "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)!",
2436 io
->u
.sAMAccountName
);
2437 return LDB_ERR_CONSTRAINT_VIOLATION
;
2439 /* passwords with length "0" are valid! */
2440 cleartext_utf8_blob
->data
= NULL
;
2441 cleartext_utf8_blob
->length
= 0;
2444 g
->cleartext_utf8
= cleartext_utf8_blob
;
2447 if (g
->cleartext_utf16
) {
2448 struct samr_Password
*nt_hash
;
2450 nt_hash
= talloc(io
->ac
, struct samr_Password
);
2452 return ldb_oom(ldb
);
2454 g
->nt_hash
= nt_hash
;
2456 /* compute the new nt hash */
2457 mdfour(nt_hash
->hash
,
2458 g
->cleartext_utf16
->data
,
2459 g
->cleartext_utf16
->length
);
2462 if (g
->cleartext_utf8
) {
2463 struct samr_Password
*lm_hash
;
2465 lm_hash
= talloc(io
->ac
, struct samr_Password
);
2467 return ldb_oom(ldb
);
2470 /* compute the new lm hash */
2471 ok
= E_deshash((char *)g
->cleartext_utf8
->data
, lm_hash
->hash
);
2473 g
->lm_hash
= lm_hash
;
2475 talloc_free(lm_hash
);
2482 static int setup_password_fields(struct setup_password_fields_io
*io
)
2484 struct ldb_context
*ldb
= ldb_module_get_ctx(io
->ac
->module
);
2485 struct loadparm_context
*lp_ctx
=
2486 talloc_get_type(ldb_get_opaque(ldb
, "loadparm"),
2487 struct loadparm_context
);
2490 ret
= setup_last_set_field(io
);
2491 if (ret
!= LDB_SUCCESS
) {
2495 if (!io
->ac
->update_password
) {
2499 /* transform the old password (for password changes) */
2500 ret
= setup_given_passwords(io
, &io
->og
);
2501 if (ret
!= LDB_SUCCESS
) {
2505 /* transform the new password */
2506 ret
= setup_given_passwords(io
, &io
->n
);
2507 if (ret
!= LDB_SUCCESS
) {
2511 if (io
->n
.cleartext_utf8
) {
2512 ret
= setup_kerberos_keys(io
);
2513 if (ret
!= LDB_SUCCESS
) {
2518 ret
= setup_nt_fields(io
);
2519 if (ret
!= LDB_SUCCESS
) {
2523 if (lpcfg_lanman_auth(lp_ctx
)) {
2524 ret
= setup_lm_fields(io
);
2525 if (ret
!= LDB_SUCCESS
) {
2529 io
->g
.lm_hash
= NULL
;
2530 io
->g
.lm_history_len
= 0;
2533 ret
= setup_supplemental_field(io
);
2534 if (ret
!= LDB_SUCCESS
) {
2541 static int setup_smartcard_reset(struct setup_password_fields_io
*io
)
2543 struct ldb_context
*ldb
= ldb_module_get_ctx(io
->ac
->module
);
2544 struct loadparm_context
*lp_ctx
= talloc_get_type(
2545 ldb_get_opaque(ldb
, "loadparm"), struct loadparm_context
);
2546 struct supplementalCredentialsBlob scb
= { .__ndr_size
= 0 };
2547 enum ndr_err_code ndr_err
;
2549 if (!io
->ac
->smartcard_reset
) {
2553 io
->g
.nt_hash
= talloc(io
->ac
, struct samr_Password
);
2554 if (io
->g
.nt_hash
== NULL
) {
2555 return ldb_module_oom(io
->ac
->module
);
2557 generate_secret_buffer(io
->g
.nt_hash
->hash
,
2558 sizeof(io
->g
.nt_hash
->hash
));
2559 io
->g
.nt_history_len
= 0;
2561 if (lpcfg_lanman_auth(lp_ctx
)) {
2562 io
->g
.lm_hash
= talloc(io
->ac
, struct samr_Password
);
2563 if (io
->g
.lm_hash
== NULL
) {
2564 return ldb_module_oom(io
->ac
->module
);
2566 generate_secret_buffer(io
->g
.lm_hash
->hash
,
2567 sizeof(io
->g
.lm_hash
->hash
));
2569 io
->g
.lm_hash
= NULL
;
2571 io
->g
.lm_history_len
= 0;
2574 * We take the "old" value and store it
2575 * with num_packages = 0.
2577 * On "add" we have scb.sub.signature == 0, which
2580 * [0000] 00 00 00 00 00 00 00 00 00 00 00 00 00
2582 * On modify it's likely to be scb.sub.signature ==
2583 * SUPPLEMENTAL_CREDENTIALS_SIGNATURE (0x0050), which results in
2586 * [0000] 00 00 00 00 62 00 00 00 00 00 00 00 20 00 20 00
2587 * [0010] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2588 * [0020] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2589 * [0030] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2590 * [0040] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2591 * [0050] 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00
2592 * [0060] 20 00 20 00 20 00 20 00 20 00 20 00 50 00 00
2594 * See https://bugzilla.samba.org/show_bug.cgi?id=11441
2595 * and ndr_{push,pull}_supplementalCredentialsSubBlob().
2598 scb
.sub
.num_packages
= 0;
2601 * setup 'supplementalCredentials' value without packages
2603 ndr_err
= ndr_push_struct_blob(&io
->g
.supplemental
, io
->ac
,
2605 (ndr_push_flags_fn_t
)ndr_push_supplementalCredentialsBlob
);
2606 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2607 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2608 ldb_asprintf_errstring(ldb
,
2609 "setup_smartcard_reset: "
2610 "failed to push supplementalCredentialsBlob: %s",
2612 return LDB_ERR_OPERATIONS_ERROR
;
2615 io
->ac
->update_password
= true;
2619 static int make_error_and_update_badPwdCount(struct setup_password_fields_io
*io
, WERROR
*werror
)
2621 struct ldb_context
*ldb
= ldb_module_get_ctx(io
->ac
->module
);
2622 struct ldb_message
*mod_msg
= NULL
;
2623 struct ldb_message
*pso_msg
= NULL
;
2627 /* PSO search result is optional (NULL if no PSO applies) */
2628 if (io
->ac
->pso_res
!= NULL
) {
2629 pso_msg
= io
->ac
->pso_res
->message
;
2632 status
= dsdb_update_bad_pwd_count(io
->ac
, ldb
,
2633 io
->ac
->search_res
->message
,
2634 io
->ac
->dom_res
->message
,
2637 if (!NT_STATUS_IS_OK(status
)) {
2641 if (mod_msg
== NULL
) {
2646 * OK, horrible semantics ahead.
2648 * - We need to abort any existing transaction
2649 * - create a transaction arround the badPwdCount update
2650 * - re-open the transaction so the upper layer
2651 * doesn't know what happened.
2653 * This is needed because returning an error to the upper
2654 * layer will cancel the transaction and undo the badPwdCount
2659 * Checking errors here is a bit pointless.
2660 * What can we do if we can't end the transaction?
2662 ret
= ldb_next_del_trans(io
->ac
->module
);
2663 if (ret
!= LDB_SUCCESS
) {
2664 ldb_debug(ldb
, LDB_DEBUG_FATAL
,
2665 "Failed to abort transaction prior to update of badPwdCount of %s: %s",
2666 ldb_dn_get_linearized(io
->ac
->search_res
->message
->dn
),
2667 ldb_errstring(ldb
));
2669 * just return the original error
2674 /* Likewise, what should we do if we can't open a new transaction? */
2675 ret
= ldb_next_start_trans(io
->ac
->module
);
2676 if (ret
!= LDB_SUCCESS
) {
2677 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
2678 "Failed to open transaction to update badPwdCount of %s: %s",
2679 ldb_dn_get_linearized(io
->ac
->search_res
->message
->dn
),
2680 ldb_errstring(ldb
));
2682 * just return the original error
2687 ret
= dsdb_module_modify(io
->ac
->module
, mod_msg
,
2688 DSDB_FLAG_NEXT_MODULE
,
2690 if (ret
!= LDB_SUCCESS
) {
2691 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
2692 "Failed to update badPwdCount of %s: %s",
2693 ldb_dn_get_linearized(io
->ac
->search_res
->message
->dn
),
2694 ldb_errstring(ldb
));
2696 * We can only ignore this...
2700 ret
= ldb_next_end_trans(io
->ac
->module
);
2701 if (ret
!= LDB_SUCCESS
) {
2702 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
2703 "Failed to close transaction to update badPwdCount of %s: %s",
2704 ldb_dn_get_linearized(io
->ac
->search_res
->message
->dn
),
2705 ldb_errstring(ldb
));
2707 * We can only ignore this...
2711 ret
= ldb_next_start_trans(io
->ac
->module
);
2712 if (ret
!= LDB_SUCCESS
) {
2713 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
2714 "Failed to open transaction after update of badPwdCount of %s: %s",
2715 ldb_dn_get_linearized(io
->ac
->search_res
->message
->dn
),
2716 ldb_errstring(ldb
));
2718 * We can only ignore this...
2723 ret
= LDB_ERR_CONSTRAINT_VIOLATION
;
2724 *werror
= WERR_INVALID_PASSWORD
;
2725 ldb_asprintf_errstring(ldb
,
2726 "%08X: %s - check_password_restrictions: "
2727 "The old password specified doesn't match!",
2733 static int check_password_restrictions(struct setup_password_fields_io
*io
, WERROR
*werror
)
2735 struct ldb_context
*ldb
= ldb_module_get_ctx(io
->ac
->module
);
2737 struct loadparm_context
*lp_ctx
=
2738 talloc_get_type(ldb_get_opaque(ldb
, "loadparm"),
2739 struct loadparm_context
);
2741 *werror
= WERR_INVALID_PARAMETER
;
2743 if (!io
->ac
->update_password
) {
2747 /* First check the old password is correct, for password changes */
2748 if (!io
->ac
->pwd_reset
) {
2749 bool nt_hash_checked
= false;
2751 /* we need the old nt or lm hash given by the client */
2752 if (!io
->og
.nt_hash
&& !io
->og
.lm_hash
) {
2753 ldb_asprintf_errstring(ldb
,
2754 "check_password_restrictions: "
2755 "You need to provide the old password in order "
2757 return LDB_ERR_UNWILLING_TO_PERFORM
;
2760 /* The password modify through the NT hash is encouraged and
2761 has no problems at all */
2762 if (io
->og
.nt_hash
) {
2763 if (!io
->o
.nt_hash
|| memcmp(io
->og
.nt_hash
->hash
, io
->o
.nt_hash
->hash
, 16) != 0) {
2764 return make_error_and_update_badPwdCount(io
, werror
);
2767 nt_hash_checked
= true;
2770 /* But it is also possible to change a password by the LM hash
2771 * alone for compatibility reasons. This check is optional if
2772 * the NT hash was already checked - otherwise it's mandatory.
2773 * (as the SAMR operations request it). */
2774 if (io
->og
.lm_hash
) {
2775 if ((!io
->o
.lm_hash
&& !nt_hash_checked
)
2776 || (io
->o
.lm_hash
&& memcmp(io
->og
.lm_hash
->hash
, io
->o
.lm_hash
->hash
, 16) != 0)) {
2777 return make_error_and_update_badPwdCount(io
, werror
);
2782 if (io
->u
.restrictions
== 0) {
2783 /* FIXME: Is this right? */
2787 /* Password minimum age: yes, this is a minus. The ages are in negative 100nsec units! */
2788 if ((io
->u
.pwdLastSet
- io
->ac
->status
->domain_data
.minPwdAge
> io
->g
.last_set
) &&
2791 ret
= LDB_ERR_CONSTRAINT_VIOLATION
;
2792 *werror
= WERR_PASSWORD_RESTRICTION
;
2793 ldb_asprintf_errstring(ldb
,
2794 "%08X: %s - check_password_restrictions: "
2795 "password is too young to change!",
2802 * Fundamental password checks done by the call
2803 * "samdb_check_password".
2804 * It is also in use by "dcesrv_samr_ValidatePassword".
2806 if (io
->n
.cleartext_utf8
!= NULL
) {
2807 enum samr_ValidationStatus vstat
;
2808 vstat
= samdb_check_password(io
->ac
, lp_ctx
,
2809 io
->u
.sAMAccountName
,
2810 io
->u
.user_principal_name
,
2812 io
->n
.cleartext_utf8
,
2813 io
->ac
->status
->domain_data
.pwdProperties
,
2814 io
->ac
->status
->domain_data
.minPwdLength
);
2816 case SAMR_VALIDATION_STATUS_SUCCESS
:
2817 /* perfect -> proceed! */
2820 case SAMR_VALIDATION_STATUS_PWD_TOO_SHORT
:
2821 ret
= LDB_ERR_CONSTRAINT_VIOLATION
;
2822 *werror
= WERR_PASSWORD_RESTRICTION
;
2823 ldb_asprintf_errstring(ldb
,
2824 "%08X: %s - check_password_restrictions: "
2825 "the password is too short. It should be equal or longer than %u characters!",
2828 io
->ac
->status
->domain_data
.minPwdLength
);
2829 io
->ac
->status
->reject_reason
= SAM_PWD_CHANGE_PASSWORD_TOO_SHORT
;
2832 case SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH
:
2833 ret
= LDB_ERR_CONSTRAINT_VIOLATION
;
2834 *werror
= WERR_PASSWORD_RESTRICTION
;
2835 ldb_asprintf_errstring(ldb
,
2836 "%08X: %s - check_password_restrictions: "
2837 "the password does not meet the complexity criteria!",
2840 io
->ac
->status
->reject_reason
= SAM_PWD_CHANGE_NOT_COMPLEX
;
2844 ret
= LDB_ERR_CONSTRAINT_VIOLATION
;
2845 *werror
= WERR_PASSWORD_RESTRICTION
;
2846 ldb_asprintf_errstring(ldb
,
2847 "%08X: %s - check_password_restrictions: "
2848 "the password doesn't fit due to a miscellaneous restriction!",
2855 if (io
->ac
->pwd_reset
) {
2860 if (io
->n
.nt_hash
) {
2863 /* checks the NT hash password history */
2864 for (i
= 0; i
< io
->o
.nt_history_len
; i
++) {
2865 ret
= memcmp(io
->n
.nt_hash
, io
->o
.nt_history
[i
].hash
, 16);
2867 ret
= LDB_ERR_CONSTRAINT_VIOLATION
;
2868 *werror
= WERR_PASSWORD_RESTRICTION
;
2869 ldb_asprintf_errstring(ldb
,
2870 "%08X: %s - check_password_restrictions: "
2871 "the password was already used (in history)!",
2874 io
->ac
->status
->reject_reason
= SAM_PWD_CHANGE_PWD_IN_HISTORY
;
2880 if (io
->n
.lm_hash
) {
2883 /* checks the LM hash password history */
2884 for (i
= 0; i
< io
->o
.lm_history_len
; i
++) {
2885 ret
= memcmp(io
->n
.lm_hash
, io
->o
.lm_history
[i
].hash
, 16);
2887 ret
= LDB_ERR_CONSTRAINT_VIOLATION
;
2888 *werror
= WERR_PASSWORD_RESTRICTION
;
2889 ldb_asprintf_errstring(ldb
,
2890 "%08X: %s - check_password_restrictions: "
2891 "the password was already used (in history)!",
2894 io
->ac
->status
->reject_reason
= SAM_PWD_CHANGE_PWD_IN_HISTORY
;
2900 /* are all password changes disallowed? */
2901 if (io
->ac
->status
->domain_data
.pwdProperties
& DOMAIN_REFUSE_PASSWORD_CHANGE
) {
2902 ret
= LDB_ERR_CONSTRAINT_VIOLATION
;
2903 *werror
= WERR_PASSWORD_RESTRICTION
;
2904 ldb_asprintf_errstring(ldb
,
2905 "%08X: %s - check_password_restrictions: "
2906 "password changes disabled!",
2912 /* can this user change the password? */
2913 if (io
->u
.userAccountControl
& UF_PASSWD_CANT_CHANGE
) {
2914 ret
= LDB_ERR_CONSTRAINT_VIOLATION
;
2915 *werror
= WERR_PASSWORD_RESTRICTION
;
2916 ldb_asprintf_errstring(ldb
,
2917 "%08X: %s - check_password_restrictions: "
2918 "password can't be changed on this account!",
2927 static int check_password_restrictions_and_log(struct setup_password_fields_io
*io
)
2930 int ret
= check_password_restrictions(io
, &werror
);
2931 struct ph_context
*ac
= io
->ac
;
2933 * Password resets are not authentication events, and if the
2934 * upper layer checked the password and supplied the hash
2935 * values as proof, then this is also not an authentication
2936 * even at this layer (already logged). This is to log LDAP
2940 /* Do not record a failure in the auth log below in the success case */
2941 if (ret
== LDB_SUCCESS
) {
2945 if (ac
->pwd_reset
== false && ac
->change
== NULL
) {
2946 struct ldb_context
*ldb
= ldb_module_get_ctx(ac
->module
);
2947 struct imessaging_context
*msg_ctx
;
2948 struct loadparm_context
*lp_ctx
2949 = talloc_get_type_abort(ldb_get_opaque(ldb
, "loadparm"),
2950 struct loadparm_context
);
2951 NTSTATUS status
= werror_to_ntstatus(werror
);
2952 const char *domain_name
= lpcfg_sam_name(lp_ctx
);
2953 void *opaque_remote_address
= NULL
;
2955 * Forcing this via the NTLM auth structure is not ideal, but
2956 * it is the most practical option right now, and ensures the
2957 * logs are consistent, even if some elements are always NULL.
2959 struct auth_usersupplied_info ui
= {
2960 .mapped_state
= true,
2963 .account_name
= io
->u
.sAMAccountName
,
2964 .domain_name
= domain_name
,
2967 .account_name
= io
->u
.sAMAccountName
,
2968 .domain_name
= domain_name
,
2970 .service_description
= "LDAP Password Change",
2971 .auth_description
= "LDAP Modify",
2972 .password_type
= "plaintext"
2975 opaque_remote_address
= ldb_get_opaque(ldb
,
2977 if (opaque_remote_address
== NULL
) {
2978 ldb_asprintf_errstring(ldb
,
2979 "Failed to obtain remote address for "
2980 "the LDAP client while changing the "
2982 return LDB_ERR_OPERATIONS_ERROR
;
2984 ui
.remote_host
= talloc_get_type(opaque_remote_address
,
2985 struct tsocket_address
);
2987 msg_ctx
= imessaging_client_init(ac
, lp_ctx
,
2988 ldb_get_event_context(ldb
));
2990 ldb_asprintf_errstring(ldb
,
2991 "Failed to generate client messaging context in %s",
2992 lpcfg_imessaging_path(ac
, lp_ctx
));
2993 return LDB_ERR_OPERATIONS_ERROR
;
2995 log_authentication_event(msg_ctx
,
3001 io
->u
.sAMAccountName
,
3008 static int update_final_msg(struct setup_password_fields_io
*io
)
3010 struct ldb_context
*ldb
= ldb_module_get_ctx(io
->ac
->module
);
3013 bool update_password
= io
->ac
->update_password
;
3014 bool update_scb
= io
->ac
->update_password
;
3017 * If we add a user without initial password,
3018 * we need to add replication meta data for
3019 * following attributes:
3025 * If we add a user with initial password or a
3026 * password is changed of an existing user,
3027 * we need to replace the following attributes
3028 * with a forced meta data update, e.g. also
3029 * when updating an empty attribute with an empty value:
3034 * - supplementalCredentials
3037 switch (io
->ac
->req
->operation
) {
3039 update_password
= true;
3040 el_flags
|= DSDB_FLAG_INTERNAL_FORCE_META_DATA
;
3043 el_flags
|= LDB_FLAG_MOD_REPLACE
;
3044 el_flags
|= DSDB_FLAG_INTERNAL_FORCE_META_DATA
;
3047 return ldb_module_operr(io
->ac
->module
);
3050 if (update_password
) {
3051 ret
= ldb_msg_add_empty(io
->ac
->update_msg
,
3054 if (ret
!= LDB_SUCCESS
) {
3057 ret
= ldb_msg_add_empty(io
->ac
->update_msg
,
3060 if (ret
!= LDB_SUCCESS
) {
3063 ret
= ldb_msg_add_empty(io
->ac
->update_msg
,
3066 if (ret
!= LDB_SUCCESS
) {
3069 ret
= ldb_msg_add_empty(io
->ac
->update_msg
,
3072 if (ret
!= LDB_SUCCESS
) {
3077 ret
= ldb_msg_add_empty(io
->ac
->update_msg
,
3078 "supplementalCredentials",
3080 if (ret
!= LDB_SUCCESS
) {
3084 if (io
->ac
->update_lastset
) {
3085 ret
= ldb_msg_add_empty(io
->ac
->update_msg
,
3088 if (ret
!= LDB_SUCCESS
) {
3093 if (io
->g
.nt_hash
!= NULL
) {
3094 ret
= samdb_msg_add_hash(ldb
, io
->ac
,
3098 if (ret
!= LDB_SUCCESS
) {
3102 if (io
->g
.lm_hash
!= NULL
) {
3103 ret
= samdb_msg_add_hash(ldb
, io
->ac
,
3107 if (ret
!= LDB_SUCCESS
) {
3111 if (io
->g
.nt_history_len
> 0) {
3112 ret
= samdb_msg_add_hashes(ldb
, io
->ac
,
3116 io
->g
.nt_history_len
);
3117 if (ret
!= LDB_SUCCESS
) {
3121 if (io
->g
.lm_history_len
> 0) {
3122 ret
= samdb_msg_add_hashes(ldb
, io
->ac
,
3126 io
->g
.lm_history_len
);
3127 if (ret
!= LDB_SUCCESS
) {
3131 if (io
->g
.supplemental
.length
> 0) {
3132 ret
= ldb_msg_add_value(io
->ac
->update_msg
,
3133 "supplementalCredentials",
3134 &io
->g
.supplemental
, NULL
);
3135 if (ret
!= LDB_SUCCESS
) {
3139 if (io
->ac
->update_lastset
) {
3140 ret
= samdb_msg_add_uint64(ldb
, io
->ac
,
3144 if (ret
!= LDB_SUCCESS
) {
3153 * This is intended for use by the "password_hash" module since there
3154 * password changes can be specified through one message element with the
3155 * new password (to set) and another one with the old password (to unset).
3157 * The first which sets a password (new value) can have flags
3158 * (LDB_FLAG_MOD_ADD, LDB_FLAG_MOD_REPLACE) but also none (on "add" operations
3159 * for entries). The latter (old value) has always specified
3160 * LDB_FLAG_MOD_DELETE.
3162 * Returns LDB_ERR_CONSTRAINT_VIOLATION and LDB_ERR_UNWILLING_TO_PERFORM if
3163 * matching message elements are malformed in respect to the set/change rules.
3164 * Otherwise it returns LDB_SUCCESS.
3166 static int msg_find_old_and_new_pwd_val(const struct ldb_message
*msg
,
3168 enum ldb_request_type operation
,
3169 const struct ldb_val
**new_val
,
3170 const struct ldb_val
**old_val
)
3181 for (i
= 0; i
< msg
->num_elements
; i
++) {
3182 if (ldb_attr_cmp(msg
->elements
[i
].name
, name
) != 0) {
3186 if ((operation
== LDB_MODIFY
) &&
3187 (LDB_FLAG_MOD_TYPE(msg
->elements
[i
].flags
) == LDB_FLAG_MOD_DELETE
)) {
3188 /* 0 values are allowed */
3189 if (msg
->elements
[i
].num_values
== 1) {
3190 *old_val
= &msg
->elements
[i
].values
[0];
3191 } else if (msg
->elements
[i
].num_values
> 1) {
3192 return LDB_ERR_CONSTRAINT_VIOLATION
;
3194 } else if ((operation
== LDB_MODIFY
) &&
3195 (LDB_FLAG_MOD_TYPE(msg
->elements
[i
].flags
) == LDB_FLAG_MOD_REPLACE
)) {
3196 if (msg
->elements
[i
].num_values
> 0) {
3197 *new_val
= &msg
->elements
[i
].values
[msg
->elements
[i
].num_values
- 1];
3199 return LDB_ERR_UNWILLING_TO_PERFORM
;
3202 /* Add operations and LDB_FLAG_MOD_ADD */
3203 if (msg
->elements
[i
].num_values
> 0) {
3204 *new_val
= &msg
->elements
[i
].values
[msg
->elements
[i
].num_values
- 1];
3206 return LDB_ERR_CONSTRAINT_VIOLATION
;
3214 static int setup_io(struct ph_context
*ac
,
3215 const struct ldb_message
*client_msg
,
3216 const struct ldb_message
*existing_msg
,
3217 struct setup_password_fields_io
*io
)
3219 const struct ldb_val
*quoted_utf16
, *old_quoted_utf16
, *lm_hash
, *old_lm_hash
;
3220 struct ldb_context
*ldb
= ldb_module_get_ctx(ac
->module
);
3221 struct loadparm_context
*lp_ctx
= talloc_get_type(
3222 ldb_get_opaque(ldb
, "loadparm"), struct loadparm_context
);
3224 const struct ldb_message
*info_msg
= NULL
;
3225 struct dom_sid
*account_sid
= NULL
;
3226 int rodc_krbtgt
= 0;
3230 /* Some operations below require kerberos contexts */
3232 if (existing_msg
!= NULL
) {
3234 * This is a modify operation
3236 info_msg
= existing_msg
;
3239 * This is an add operation
3241 info_msg
= client_msg
;
3244 ret
= smb_krb5_init_context(ac
,
3245 (struct loadparm_context
*)ldb_get_opaque(ldb
, "loadparm"),
3246 &io
->smb_krb5_context
);
3250 * In the special case of mit krb5.conf vs heimdal, the includedir
3251 * statement causes ret == 22 (KRB5_CONFIG_BADFORMAT) to be returned.
3252 * We look for this case so that we can give a more instructional
3253 * message to the administrator.
3255 if (ret
== KRB5_CONFIG_BADFORMAT
|| ret
== EINVAL
) {
3256 ldb_asprintf_errstring(ldb
, "Failed to setup krb5_context: %s - "
3257 "This could be due to an invalid krb5 configuration. "
3258 "Please check your system's krb5 configuration is correct.",
3259 error_message(ret
));
3261 ldb_asprintf_errstring(ldb
, "Failed to setup krb5_context: %s",
3262 error_message(ret
));
3264 return LDB_ERR_OPERATIONS_ERROR
;
3269 io
->u
.userAccountControl
= ldb_msg_find_attr_as_uint(info_msg
,
3270 "userAccountControl", 0);
3271 if (info_msg
== existing_msg
) {
3273 * We only take pwdLastSet from the existing object
3274 * otherwise we leave it as 0.
3276 * If no attribute is available, e.g. on deleted objects
3277 * we remember that as UINT64_MAX.
3279 io
->u
.pwdLastSet
= samdb_result_nttime(info_msg
, "pwdLastSet",
3282 io
->u
.sAMAccountName
= ldb_msg_find_attr_as_string(info_msg
,
3283 "sAMAccountName", NULL
);
3284 io
->u
.user_principal_name
= ldb_msg_find_attr_as_string(info_msg
,
3285 "userPrincipalName", NULL
);
3286 io
->u
.displayName
= ldb_msg_find_attr_as_string(info_msg
,
3287 "displayName", NULL
);
3289 /* Ensure it has an objectSID too */
3290 io
->u
.account_sid
= samdb_result_dom_sid(ac
, info_msg
, "objectSid");
3291 if (io
->u
.account_sid
!= NULL
) {
3295 status
= dom_sid_split_rid(account_sid
, io
->u
.account_sid
, NULL
, &rid
);
3296 if (NT_STATUS_IS_OK(status
)) {
3297 if (rid
== DOMAIN_RID_KRBTGT
) {
3298 io
->u
.is_krbtgt
= true;
3303 rodc_krbtgt
= ldb_msg_find_attr_as_int(info_msg
,
3304 "msDS-SecondaryKrbTgtNumber", 0);
3305 if (rodc_krbtgt
!= 0) {
3306 io
->u
.is_krbtgt
= true;
3309 if (io
->u
.sAMAccountName
== NULL
) {
3310 ldb_asprintf_errstring(ldb
,
3311 "setup_io: sAMAccountName attribute is missing on %s for attempted password set/change",
3312 ldb_dn_get_linearized(info_msg
->dn
));
3314 return LDB_ERR_CONSTRAINT_VIOLATION
;
3317 if (io
->u
.userAccountControl
& UF_INTERDOMAIN_TRUST_ACCOUNT
) {
3318 struct ldb_control
*permit_trust
= ldb_request_get_control(ac
->req
,
3319 DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID
);
3321 if (permit_trust
== NULL
) {
3322 ret
= LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
;
3323 ldb_asprintf_errstring(ldb
,
3324 "%08X: %s - setup_io: changing the interdomain trust password "
3325 "on %s not allowed via LDAP. Use LSA or NETLOGON",
3326 W_ERROR_V(WERR_ACCESS_DENIED
),
3328 ldb_dn_get_linearized(info_msg
->dn
));
3333 /* Only non-trust accounts have restrictions (possibly this test is the
3334 * wrong way around, but we like to be restrictive if possible */
3335 io
->u
.restrictions
= !(io
->u
.userAccountControl
& UF_TRUST_ACCOUNT_MASK
);
3337 if (io
->u
.is_krbtgt
) {
3338 io
->u
.restrictions
= 0;
3339 io
->ac
->status
->domain_data
.pwdHistoryLength
=
3340 MAX(io
->ac
->status
->domain_data
.pwdHistoryLength
, 3);
3343 if (ac
->userPassword
) {
3344 ret
= msg_find_old_and_new_pwd_val(client_msg
, "userPassword",
3346 &io
->n
.cleartext_utf8
,
3347 &io
->og
.cleartext_utf8
);
3348 if (ret
!= LDB_SUCCESS
) {
3349 ldb_asprintf_errstring(ldb
,
3351 "it's only allowed to set the old password once!");
3356 if (io
->n
.cleartext_utf8
!= NULL
) {
3357 struct ldb_val
*cleartext_utf8_blob
;
3360 cleartext_utf8_blob
= talloc(io
->ac
, struct ldb_val
);
3361 if (!cleartext_utf8_blob
) {
3362 return ldb_oom(ldb
);
3365 *cleartext_utf8_blob
= *io
->n
.cleartext_utf8
;
3367 /* make sure we have a null terminated string */
3368 p
= talloc_strndup(cleartext_utf8_blob
,
3369 (const char *)io
->n
.cleartext_utf8
->data
,
3370 io
->n
.cleartext_utf8
->length
);
3371 if ((p
== NULL
) && (io
->n
.cleartext_utf8
->length
> 0)) {
3372 return ldb_oom(ldb
);
3374 cleartext_utf8_blob
->data
= (uint8_t *)p
;
3376 io
->n
.cleartext_utf8
= cleartext_utf8_blob
;
3379 ret
= msg_find_old_and_new_pwd_val(client_msg
, "clearTextPassword",
3381 &io
->n
.cleartext_utf16
,
3382 &io
->og
.cleartext_utf16
);
3383 if (ret
!= LDB_SUCCESS
) {
3384 ldb_asprintf_errstring(ldb
,
3386 "it's only allowed to set the old password once!");
3390 /* this rather strange looking piece of code is there to
3391 handle a ldap client setting a password remotely using the
3392 unicodePwd ldap field. The syntax is that the password is
3393 in UTF-16LE, with a " at either end. Unfortunately the
3394 unicodePwd field is also used to store the nt hashes
3395 internally in Samba, and is used in the nt hash format on
3396 the wire in DRS replication, so we have a single name for
3397 two distinct values. The code below leaves us with a small
3398 chance (less than 1 in 2^32) of a mixup, if someone manages
3399 to create a MD4 hash which starts and ends in 0x22 0x00, as
3400 that would then be treated as a UTF16 password rather than
3403 ret
= msg_find_old_and_new_pwd_val(client_msg
, "unicodePwd",
3407 if (ret
!= LDB_SUCCESS
) {
3408 ldb_asprintf_errstring(ldb
,
3410 "it's only allowed to set the old password once!");
3414 /* Checks and converts the actual "unicodePwd" attribute */
3415 if (!ac
->hash_values
&&
3417 quoted_utf16
->length
>= 4 &&
3418 quoted_utf16
->data
[0] == '"' &&
3419 quoted_utf16
->data
[1] == 0 &&
3420 quoted_utf16
->data
[quoted_utf16
->length
-2] == '"' &&
3421 quoted_utf16
->data
[quoted_utf16
->length
-1] == 0) {
3422 struct ldb_val
*quoted_utf16_2
;
3424 if (io
->n
.cleartext_utf16
) {
3425 /* refuse the change if someone wants to change with
3426 with both UTF16 possibilities at the same time... */
3427 ldb_asprintf_errstring(ldb
,
3429 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'clearTextPassword'");
3430 return LDB_ERR_UNWILLING_TO_PERFORM
;
3434 * adapt the quoted UTF16 string to be a real
3437 quoted_utf16_2
= talloc(io
->ac
, struct ldb_val
);
3438 if (quoted_utf16_2
== NULL
) {
3439 return ldb_oom(ldb
);
3442 quoted_utf16_2
->data
= quoted_utf16
->data
+ 2;
3443 quoted_utf16_2
->length
= quoted_utf16
->length
-4;
3444 io
->n
.cleartext_utf16
= quoted_utf16_2
;
3445 io
->n
.nt_hash
= NULL
;
3447 } else if (quoted_utf16
) {
3448 /* We have only the hash available -> so no plaintext here */
3449 if (!ac
->hash_values
) {
3450 /* refuse the change if someone wants to change
3451 the hash without control specified... */
3452 ldb_asprintf_errstring(ldb
,
3454 "it's not allowed to set the NT hash password directly'");
3455 /* this looks odd but this is what Windows does:
3456 returns "UNWILLING_TO_PERFORM" on wrong
3457 password sets and "CONSTRAINT_VIOLATION" on
3458 wrong password changes. */
3459 if (old_quoted_utf16
== NULL
) {
3460 return LDB_ERR_UNWILLING_TO_PERFORM
;
3463 return LDB_ERR_CONSTRAINT_VIOLATION
;
3466 io
->n
.nt_hash
= talloc(io
->ac
, struct samr_Password
);
3467 memcpy(io
->n
.nt_hash
->hash
, quoted_utf16
->data
,
3468 MIN(quoted_utf16
->length
, sizeof(io
->n
.nt_hash
->hash
)));
3471 /* Checks and converts the previous "unicodePwd" attribute */
3472 if (!ac
->hash_values
&&
3474 old_quoted_utf16
->length
>= 4 &&
3475 old_quoted_utf16
->data
[0] == '"' &&
3476 old_quoted_utf16
->data
[1] == 0 &&
3477 old_quoted_utf16
->data
[old_quoted_utf16
->length
-2] == '"' &&
3478 old_quoted_utf16
->data
[old_quoted_utf16
->length
-1] == 0) {
3479 struct ldb_val
*old_quoted_utf16_2
;
3481 if (io
->og
.cleartext_utf16
) {
3482 /* refuse the change if someone wants to change with
3483 both UTF16 possibilities at the same time... */
3484 ldb_asprintf_errstring(ldb
,
3486 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'clearTextPassword'");
3487 return LDB_ERR_UNWILLING_TO_PERFORM
;
3491 * adapt the quoted UTF16 string to be a real
3494 old_quoted_utf16_2
= talloc(io
->ac
, struct ldb_val
);
3495 if (old_quoted_utf16_2
== NULL
) {
3496 return ldb_oom(ldb
);
3499 old_quoted_utf16_2
->data
= old_quoted_utf16
->data
+ 2;
3500 old_quoted_utf16_2
->length
= old_quoted_utf16
->length
-4;
3502 io
->og
.cleartext_utf16
= old_quoted_utf16_2
;
3503 io
->og
.nt_hash
= NULL
;
3504 } else if (old_quoted_utf16
) {
3505 /* We have only the hash available -> so no plaintext here */
3506 if (!ac
->hash_values
) {
3507 /* refuse the change if someone wants to change
3508 the hash without control specified... */
3509 ldb_asprintf_errstring(ldb
,
3511 "it's not allowed to set the NT hash password directly'");
3512 return LDB_ERR_UNWILLING_TO_PERFORM
;
3515 io
->og
.nt_hash
= talloc(io
->ac
, struct samr_Password
);
3516 memcpy(io
->og
.nt_hash
->hash
, old_quoted_utf16
->data
,
3517 MIN(old_quoted_utf16
->length
, sizeof(io
->og
.nt_hash
->hash
)));
3520 /* Handles the "dBCSPwd" attribute (LM hash) */
3521 io
->n
.lm_hash
= NULL
; io
->og
.lm_hash
= NULL
;
3522 ret
= msg_find_old_and_new_pwd_val(client_msg
, "dBCSPwd",
3524 &lm_hash
, &old_lm_hash
);
3525 if (ret
!= LDB_SUCCESS
) {
3526 ldb_asprintf_errstring(ldb
,
3528 "it's only allowed to set the old password once!");
3532 if (((lm_hash
!= NULL
) || (old_lm_hash
!= NULL
)) && (!ac
->hash_values
)) {
3533 /* refuse the change if someone wants to change the hash
3534 without control specified... */
3535 ldb_asprintf_errstring(ldb
,
3537 "it's not allowed to set the LM hash password directly'");
3538 return LDB_ERR_UNWILLING_TO_PERFORM
;
3541 if (lpcfg_lanman_auth(lp_ctx
) && (lm_hash
!= NULL
)) {
3542 io
->n
.lm_hash
= talloc(io
->ac
, struct samr_Password
);
3543 memcpy(io
->n
.lm_hash
->hash
, lm_hash
->data
, MIN(lm_hash
->length
,
3544 sizeof(io
->n
.lm_hash
->hash
)));
3546 if (lpcfg_lanman_auth(lp_ctx
) && (old_lm_hash
!= NULL
)) {
3547 io
->og
.lm_hash
= talloc(io
->ac
, struct samr_Password
);
3548 memcpy(io
->og
.lm_hash
->hash
, old_lm_hash
->data
, MIN(old_lm_hash
->length
,
3549 sizeof(io
->og
.lm_hash
->hash
)));
3553 * Handles the password change control if it's specified. It has the
3554 * precedance and overrides already specified old password values of
3555 * change requests (but that shouldn't happen since the control is
3556 * fully internal and only used in conjunction with replace requests!).
3558 if (ac
->change
!= NULL
) {
3559 io
->og
.nt_hash
= NULL
;
3560 if (ac
->change
->old_nt_pwd_hash
!= NULL
) {
3561 io
->og
.nt_hash
= talloc_memdup(io
->ac
,
3562 ac
->change
->old_nt_pwd_hash
,
3563 sizeof(struct samr_Password
));
3565 io
->og
.lm_hash
= NULL
;
3566 if (lpcfg_lanman_auth(lp_ctx
) && (ac
->change
->old_lm_pwd_hash
!= NULL
)) {
3567 io
->og
.lm_hash
= talloc_memdup(io
->ac
,
3568 ac
->change
->old_lm_pwd_hash
,
3569 sizeof(struct samr_Password
));
3573 /* refuse the change if someone wants to change the clear-
3574 text and supply his own hashes at the same time... */
3575 if ((io
->n
.cleartext_utf8
|| io
->n
.cleartext_utf16
)
3576 && (io
->n
.nt_hash
|| io
->n
.lm_hash
)) {
3577 ldb_asprintf_errstring(ldb
,
3579 "it's only allowed to set the password in form of cleartext attributes or as hashes");
3580 return LDB_ERR_UNWILLING_TO_PERFORM
;
3583 /* refuse the change if someone wants to change the password
3584 using both plaintext methods (UTF8 and UTF16) at the same time... */
3585 if (io
->n
.cleartext_utf8
&& io
->n
.cleartext_utf16
) {
3586 ldb_asprintf_errstring(ldb
,
3588 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
3589 return LDB_ERR_UNWILLING_TO_PERFORM
;
3592 /* refuse the change if someone tries to set/change the password by
3593 * the lanman hash alone and we've deactivated that mechanism. This
3594 * would end in an account without any password! */
3595 if (io
->ac
->update_password
3596 && (!io
->n
.cleartext_utf8
) && (!io
->n
.cleartext_utf16
)
3597 && (!io
->n
.nt_hash
) && (!io
->n
.lm_hash
)) {
3598 ldb_asprintf_errstring(ldb
,
3600 "It's not possible to delete the password (changes using the LAN Manager hash alone could be deactivated)!");
3601 /* on "userPassword" and "clearTextPassword" we've to return
3602 * something different, since these are virtual attributes */
3603 if ((ldb_msg_find_element(client_msg
, "userPassword") != NULL
) ||
3604 (ldb_msg_find_element(client_msg
, "clearTextPassword") != NULL
)) {
3605 return LDB_ERR_CONSTRAINT_VIOLATION
;
3607 return LDB_ERR_UNWILLING_TO_PERFORM
;
3610 /* refuse the change if someone wants to compare against a plaintext
3611 or hash at the same time for a "password modify" operation... */
3612 if ((io
->og
.cleartext_utf8
|| io
->og
.cleartext_utf16
)
3613 && (io
->og
.nt_hash
|| io
->og
.lm_hash
)) {
3614 ldb_asprintf_errstring(ldb
,
3616 "it's only allowed to provide the old password in form of cleartext attributes or as hashes");
3617 return LDB_ERR_UNWILLING_TO_PERFORM
;
3620 /* refuse the change if someone wants to compare against both
3621 * plaintexts at the same time for a "password modify" operation... */
3622 if (io
->og
.cleartext_utf8
&& io
->og
.cleartext_utf16
) {
3623 ldb_asprintf_errstring(ldb
,
3625 "it's only allowed to provide the old cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
3626 return LDB_ERR_UNWILLING_TO_PERFORM
;
3629 /* Decides if we have a password modify or password reset operation */
3630 if (ac
->req
->operation
== LDB_ADD
) {
3631 /* On "add" we have only "password reset" */
3632 ac
->pwd_reset
= true;
3633 } else if (ac
->req
->operation
== LDB_MODIFY
) {
3634 struct ldb_control
*pav_ctrl
= NULL
;
3635 struct dsdb_control_password_acl_validation
*pav
= NULL
;
3637 pav_ctrl
= ldb_request_get_control(ac
->req
,
3638 DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID
);
3639 if (pav_ctrl
!= NULL
) {
3640 pav
= talloc_get_type_abort(pav_ctrl
->data
,
3641 struct dsdb_control_password_acl_validation
);
3644 if (pav
== NULL
&& ac
->update_password
) {
3648 * If the DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID
3649 * control is missing, we require system access!
3651 ok
= dsdb_module_am_system(ac
->module
);
3653 return ldb_module_operr(ac
->module
);
3659 * We assume what the acl module has validated.
3661 ac
->pwd_reset
= pav
->pwd_reset
;
3662 } else if (io
->og
.cleartext_utf8
|| io
->og
.cleartext_utf16
3663 || io
->og
.nt_hash
|| io
->og
.lm_hash
) {
3664 /* If we have an old password specified then for sure it
3665 * is a user "password change" */
3666 ac
->pwd_reset
= false;
3668 /* Otherwise we have also here a "password reset" */
3669 ac
->pwd_reset
= true;
3672 /* this shouldn't happen */
3673 return ldb_operr(ldb
);
3676 if (io
->u
.is_krbtgt
) {
3679 size_t diff
= max
- min
;
3681 struct ldb_val
*krbtgt_utf16
= NULL
;
3683 if (!ac
->pwd_reset
) {
3684 return dsdb_module_werror(ac
->module
,
3685 LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS
,
3686 WERR_DS_ATT_ALREADY_EXISTS
,
3687 "Password change on krbtgt not permitted!");
3690 if (io
->n
.cleartext_utf16
== NULL
) {
3691 return dsdb_module_werror(ac
->module
,
3692 LDB_ERR_UNWILLING_TO_PERFORM
,
3693 WERR_DS_INVALID_ATTRIBUTE_SYNTAX
,
3694 "Password reset on krbtgt requires UTF16!");
3698 * Instead of taking the callers value,
3699 * we just generate a new random value here.
3701 * Include null termination in the array.
3706 generate_random_buffer((uint8_t *)&tmp
, sizeof(tmp
));
3713 krbtgt_utf16
= talloc_zero(io
->ac
, struct ldb_val
);
3714 if (krbtgt_utf16
== NULL
) {
3715 return ldb_oom(ldb
);
3718 *krbtgt_utf16
= data_blob_talloc_zero(krbtgt_utf16
,
3720 if (krbtgt_utf16
->data
== NULL
) {
3721 return ldb_oom(ldb
);
3723 krbtgt_utf16
->length
= len
* 2;
3724 generate_secret_buffer(krbtgt_utf16
->data
,
3725 krbtgt_utf16
->length
);
3726 io
->n
.cleartext_utf16
= krbtgt_utf16
;
3729 if (existing_msg
!= NULL
) {
3732 if (ac
->pwd_reset
) {
3733 /* Get the old password from the database */
3734 status
= samdb_result_passwords_no_lockout(ac
,
3740 /* Get the old password from the database */
3741 status
= samdb_result_passwords(ac
,
3748 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCOUNT_LOCKED_OUT
)) {
3749 return dsdb_module_werror(ac
->module
,
3750 LDB_ERR_CONSTRAINT_VIOLATION
,
3751 WERR_ACCOUNT_LOCKED_OUT
,
3752 "Password change not permitted,"
3753 " account locked out!");
3756 if (!NT_STATUS_IS_OK(status
)) {
3758 * This only happens if the database has gone weird,
3759 * not if we are just missing the passwords
3761 return ldb_operr(ldb
);
3764 io
->o
.nt_history_len
= samdb_result_hashes(ac
, existing_msg
,
3767 io
->o
.lm_history_len
= samdb_result_hashes(ac
, existing_msg
,
3770 io
->o
.supplemental
= ldb_msg_find_ldb_val(existing_msg
,
3771 "supplementalCredentials");
3773 if (io
->o
.supplemental
!= NULL
) {
3774 enum ndr_err_code ndr_err
;
3776 ndr_err
= ndr_pull_struct_blob_all(io
->o
.supplemental
, io
->ac
,
3778 (ndr_pull_flags_fn_t
)ndr_pull_supplementalCredentialsBlob
);
3779 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3780 status
= ndr_map_error2ntstatus(ndr_err
);
3781 ldb_asprintf_errstring(ldb
,
3782 "setup_io: failed to pull "
3783 "old supplementalCredentialsBlob: %s",
3785 return LDB_ERR_OPERATIONS_ERROR
;
3793 static struct ph_context
*ph_init_context(struct ldb_module
*module
,
3794 struct ldb_request
*req
,
3796 bool update_password
)
3798 struct ldb_context
*ldb
;
3799 struct ph_context
*ac
;
3800 struct loadparm_context
*lp_ctx
= NULL
;
3802 ldb
= ldb_module_get_ctx(module
);
3804 ac
= talloc_zero(req
, struct ph_context
);
3806 ldb_set_errstring(ldb
, "Out of Memory");
3810 ac
->module
= module
;
3812 ac
->userPassword
= userPassword
;
3813 ac
->update_password
= update_password
;
3814 ac
->update_lastset
= true;
3816 lp_ctx
= talloc_get_type_abort(ldb_get_opaque(ldb
, "loadparm"),
3817 struct loadparm_context
);
3818 ac
->gpg_key_ids
= lpcfg_password_hash_gpg_key_ids(lp_ctx
);
3819 ac
->userPassword_schemes
3820 = lpcfg_password_hash_userpassword_schemes(lp_ctx
);
3824 static void ph_apply_controls(struct ph_context
*ac
)
3826 struct ldb_control
*ctrl
;
3828 ac
->change_status
= false;
3829 ctrl
= ldb_request_get_control(ac
->req
,
3830 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID
);
3832 ac
->change_status
= true;
3834 /* Mark the "change status" control as uncritical (done) */
3835 ctrl
->critical
= false;
3838 ac
->hash_values
= false;
3839 ctrl
= ldb_request_get_control(ac
->req
,
3840 DSDB_CONTROL_PASSWORD_HASH_VALUES_OID
);
3842 ac
->hash_values
= true;
3844 /* Mark the "hash values" control as uncritical (done) */
3845 ctrl
->critical
= false;
3848 ctrl
= ldb_request_get_control(ac
->req
,
3849 DSDB_CONTROL_PASSWORD_CHANGE_OID
);
3851 ac
->change
= (struct dsdb_control_password_change
*) ctrl
->data
;
3853 /* Mark the "change" control as uncritical (done) */
3854 ctrl
->critical
= false;
3857 ac
->pwd_last_set_bypass
= false;
3858 ctrl
= ldb_request_get_control(ac
->req
,
3859 DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID
);
3861 ac
->pwd_last_set_bypass
= true;
3863 /* Mark the "bypass pwdLastSet" control as uncritical (done) */
3864 ctrl
->critical
= false;
3867 ac
->pwd_last_set_default
= false;
3868 ctrl
= ldb_request_get_control(ac
->req
,
3869 DSDB_CONTROL_PASSWORD_DEFAULT_LAST_SET_OID
);
3871 ac
->pwd_last_set_default
= true;
3873 /* Mark the "bypass pwdLastSet" control as uncritical (done) */
3874 ctrl
->critical
= false;
3877 ac
->smartcard_reset
= false;
3878 ctrl
= ldb_request_get_control(ac
->req
,
3879 DSDB_CONTROL_PASSWORD_USER_ACCOUNT_CONTROL_OID
);
3881 struct dsdb_control_password_user_account_control
*uac
= NULL
;
3882 uint32_t added_flags
= 0;
3884 uac
= talloc_get_type_abort(ctrl
->data
,
3885 struct dsdb_control_password_user_account_control
);
3887 added_flags
= uac
->new_flags
& ~uac
->old_flags
;
3889 if (added_flags
& UF_SMARTCARD_REQUIRED
) {
3890 ac
->smartcard_reset
= true;
3893 /* Mark the "smartcard required" control as uncritical (done) */
3894 ctrl
->critical
= false;
3898 static int ph_op_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
3900 struct ph_context
*ac
;
3902 ac
= talloc_get_type(req
->context
, struct ph_context
);
3905 return ldb_module_done(ac
->req
, NULL
, NULL
,
3906 LDB_ERR_OPERATIONS_ERROR
);
3909 if (ares
->type
== LDB_REPLY_REFERRAL
) {
3910 return ldb_module_send_referral(ac
->req
, ares
->referral
);
3913 if ((ares
->error
!= LDB_ERR_OPERATIONS_ERROR
) && (ac
->change_status
)) {
3914 /* On success and trivial errors a status control is being
3915 * added (used for example by the "samdb_set_password" call) */
3916 ldb_reply_add_control(ares
,
3917 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID
,
3922 if (ares
->error
!= LDB_SUCCESS
) {
3923 return ldb_module_done(ac
->req
, ares
->controls
,
3924 ares
->response
, ares
->error
);
3927 if (ares
->type
!= LDB_REPLY_DONE
) {
3929 return ldb_module_done(ac
->req
, NULL
, NULL
,
3930 LDB_ERR_OPERATIONS_ERROR
);
3933 return ldb_module_done(ac
->req
, ares
->controls
,
3934 ares
->response
, ares
->error
);
3937 static int password_hash_add_do_add(struct ph_context
*ac
);
3938 static int ph_modify_callback(struct ldb_request
*req
, struct ldb_reply
*ares
);
3939 static int password_hash_mod_search_self(struct ph_context
*ac
);
3940 static int ph_mod_search_callback(struct ldb_request
*req
, struct ldb_reply
*ares
);
3941 static int password_hash_mod_do_mod(struct ph_context
*ac
);
3944 * LDB callback handler for searching for a user's PSO. Once we have all the
3945 * Password Settings that apply to the user, we can continue with the modify
3948 static int get_pso_data_callback(struct ldb_request
*req
,
3949 struct ldb_reply
*ares
)
3951 struct ldb_context
*ldb
= NULL
;
3952 struct ph_context
*ac
= NULL
;
3953 bool domain_complexity
= true;
3954 bool pso_complexity
= true;
3955 struct dsdb_user_pwd_settings
*settings
= NULL
;
3956 int ret
= LDB_SUCCESS
;
3958 ac
= talloc_get_type(req
->context
, struct ph_context
);
3959 ldb
= ldb_module_get_ctx(ac
->module
);
3962 ret
= LDB_ERR_OPERATIONS_ERROR
;
3965 if (ares
->error
!= LDB_SUCCESS
) {
3966 return ldb_module_done(ac
->req
, ares
->controls
,
3967 ares
->response
, ares
->error
);
3970 switch (ares
->type
) {
3971 case LDB_REPLY_ENTRY
:
3973 /* check status was initialized by the domain query */
3974 if (ac
->status
== NULL
) {
3976 ldb_set_errstring(ldb
, "Uninitialized status");
3977 ret
= LDB_ERR_OPERATIONS_ERROR
;
3982 * use the PSO's values instead of the domain defaults (the PSO
3983 * attributes should always exist, but use the domain default
3984 * values as a fallback).
3986 settings
= &ac
->status
->domain_data
;
3987 settings
->store_cleartext
=
3988 ldb_msg_find_attr_as_bool(ares
->message
,
3989 "msDS-PasswordReversibleEncryptionEnabled",
3990 settings
->store_cleartext
);
3992 settings
->pwdHistoryLength
=
3993 ldb_msg_find_attr_as_uint(ares
->message
,
3994 "msDS-PasswordHistoryLength",
3995 settings
->pwdHistoryLength
);
3996 settings
->maxPwdAge
=
3997 ldb_msg_find_attr_as_int64(ares
->message
,
3998 "msDS-MaximumPasswordAge",
3999 settings
->maxPwdAge
);
4000 settings
->minPwdAge
=
4001 ldb_msg_find_attr_as_int64(ares
->message
,
4002 "msDS-MinimumPasswordAge",
4003 settings
->minPwdAge
);
4004 settings
->minPwdLength
=
4005 ldb_msg_find_attr_as_uint(ares
->message
,
4006 "msDS-MinimumPasswordLength",
4007 settings
->minPwdLength
);
4009 (settings
->pwdProperties
& DOMAIN_PASSWORD_COMPLEX
);
4011 ldb_msg_find_attr_as_bool(ares
->message
,
4012 "msDS-PasswordComplexityEnabled",
4015 /* set or clear the complexity bit if required */
4016 if (pso_complexity
&& !domain_complexity
) {
4017 settings
->pwdProperties
|= DOMAIN_PASSWORD_COMPLEX
;
4018 } else if (domain_complexity
&& !pso_complexity
) {
4019 settings
->pwdProperties
&= ~DOMAIN_PASSWORD_COMPLEX
;
4022 if (ac
->pso_res
!= NULL
) {
4023 DBG_ERR("Too many PSO results for %s",
4024 ldb_dn_get_linearized(ac
->search_res
->message
->dn
));
4025 talloc_free(ac
->pso_res
);
4028 /* store the PSO result (we may need its lockout settings) */
4029 ac
->pso_res
= talloc_steal(ac
, ares
);
4033 case LDB_REPLY_REFERRAL
:
4039 case LDB_REPLY_DONE
:
4043 * perform the next step of the modify operation (this code
4044 * shouldn't get called in the 'user add' case)
4046 if (ac
->req
->operation
== LDB_MODIFY
) {
4047 ret
= password_hash_mod_do_mod(ac
);
4049 ret
= LDB_ERR_OPERATIONS_ERROR
;
4055 if (ret
!= LDB_SUCCESS
) {
4056 struct ldb_reply
*new_ares
;
4058 new_ares
= talloc_zero(ac
->req
, struct ldb_reply
);
4059 if (new_ares
== NULL
) {
4061 return ldb_module_done(ac
->req
, NULL
, NULL
,
4062 LDB_ERR_OPERATIONS_ERROR
);
4065 new_ares
->error
= ret
;
4066 if ((ret
!= LDB_ERR_OPERATIONS_ERROR
) && (ac
->change_status
)) {
4067 /* On success and trivial errors a status control is being
4068 * added (used for example by the "samdb_set_password" call) */
4069 ldb_reply_add_control(new_ares
,
4070 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID
,
4075 return ldb_module_done(ac
->req
, new_ares
->controls
,
4076 new_ares
->response
, new_ares
->error
);
4083 * Builds and returns a search request to lookup up the PSO that applies to
4084 * the user in question. Returns NULL if no PSO applies, or could not be found
4086 static struct ldb_request
* build_pso_data_request(struct ph_context
*ac
)
4088 /* attrs[] is returned from this function in
4089 pso_req->op.search.attrs, so it must be static, as
4090 otherwise the compiler can put it on the stack */
4091 static const char * const attrs
[] = { "msDS-PasswordComplexityEnabled",
4092 "msDS-PasswordReversibleEncryptionEnabled",
4093 "msDS-PasswordHistoryLength",
4094 "msDS-MaximumPasswordAge",
4095 "msDS-MinimumPasswordAge",
4096 "msDS-MinimumPasswordLength",
4097 "msDS-LockoutThreshold",
4098 "msDS-LockoutObservationWindow",
4100 struct ldb_context
*ldb
= NULL
;
4101 struct ldb_request
*pso_req
= NULL
;
4102 struct ldb_dn
*pso_dn
= NULL
;
4103 TALLOC_CTX
*mem_ctx
= ac
;
4106 ldb
= ldb_module_get_ctx(ac
->module
);
4108 /* if a PSO applies to the user, we need to lookup the PSO as well */
4109 pso_dn
= ldb_msg_find_attr_as_dn(ldb
, mem_ctx
, ac
->search_res
->message
,
4110 "msDS-ResultantPSO");
4111 if (pso_dn
== NULL
) {
4115 ret
= ldb_build_search_req(&pso_req
, ldb
, mem_ctx
, pso_dn
,
4116 LDB_SCOPE_BASE
, NULL
, attrs
, NULL
,
4117 ac
, get_pso_data_callback
,
4120 /* log errors, but continue with the default domain settings */
4121 if (ret
!= LDB_SUCCESS
) {
4122 DBG_ERR("Error %d constructing PSO query for user %s", ret
,
4123 ldb_dn_get_linearized(ac
->search_res
->message
->dn
));
4125 LDB_REQ_SET_LOCATION(pso_req
);
4130 static int get_domain_data_callback(struct ldb_request
*req
,
4131 struct ldb_reply
*ares
)
4133 struct ldb_context
*ldb
;
4134 struct ph_context
*ac
;
4135 struct loadparm_context
*lp_ctx
;
4136 struct ldb_request
*pso_req
= NULL
;
4137 int ret
= LDB_SUCCESS
;
4139 ac
= talloc_get_type(req
->context
, struct ph_context
);
4140 ldb
= ldb_module_get_ctx(ac
->module
);
4143 ret
= LDB_ERR_OPERATIONS_ERROR
;
4146 if (ares
->error
!= LDB_SUCCESS
) {
4147 return ldb_module_done(ac
->req
, ares
->controls
,
4148 ares
->response
, ares
->error
);
4151 switch (ares
->type
) {
4152 case LDB_REPLY_ENTRY
:
4153 if (ac
->status
!= NULL
) {
4156 ldb_set_errstring(ldb
, "Too many results");
4157 ret
= LDB_ERR_OPERATIONS_ERROR
;
4161 /* Setup the "status" structure (used as control later) */
4162 ac
->status
= talloc_zero(ac
->req
,
4163 struct dsdb_control_password_change_status
);
4164 if (ac
->status
== NULL
) {
4168 ret
= LDB_ERR_OPERATIONS_ERROR
;
4172 /* Setup the "domain data" structure */
4173 ac
->status
->domain_data
.pwdProperties
=
4174 ldb_msg_find_attr_as_uint(ares
->message
, "pwdProperties", -1);
4175 ac
->status
->domain_data
.pwdHistoryLength
=
4176 ldb_msg_find_attr_as_uint(ares
->message
, "pwdHistoryLength", -1);
4177 ac
->status
->domain_data
.maxPwdAge
=
4178 ldb_msg_find_attr_as_int64(ares
->message
, "maxPwdAge", -1);
4179 ac
->status
->domain_data
.minPwdAge
=
4180 ldb_msg_find_attr_as_int64(ares
->message
, "minPwdAge", -1);
4181 ac
->status
->domain_data
.minPwdLength
=
4182 ldb_msg_find_attr_as_uint(ares
->message
, "minPwdLength", -1);
4183 ac
->status
->domain_data
.store_cleartext
=
4184 ac
->status
->domain_data
.pwdProperties
& DOMAIN_PASSWORD_STORE_CLEARTEXT
;
4186 /* For a domain DN, this puts things in dotted notation */
4187 /* For builtin domains, this will give details for the host,
4188 * but that doesn't really matter, as it's just used for salt
4189 * and kerberos principals, which don't exist here */
4191 lp_ctx
= talloc_get_type(ldb_get_opaque(ldb
, "loadparm"),
4192 struct loadparm_context
);
4194 ac
->status
->domain_data
.dns_domain
= lpcfg_dnsdomain(lp_ctx
);
4195 ac
->status
->domain_data
.realm
= lpcfg_realm(lp_ctx
);
4196 ac
->status
->domain_data
.netbios_domain
= lpcfg_sam_name(lp_ctx
);
4198 ac
->status
->reject_reason
= SAM_PWD_CHANGE_NO_ERROR
;
4200 if (ac
->dom_res
!= NULL
) {
4203 ldb_set_errstring(ldb
, "Too many results");
4204 ret
= LDB_ERR_OPERATIONS_ERROR
;
4208 ac
->dom_res
= talloc_steal(ac
, ares
);
4212 case LDB_REPLY_REFERRAL
:
4218 case LDB_REPLY_DONE
:
4220 /* call the next step */
4221 switch (ac
->req
->operation
) {
4223 ret
= password_hash_add_do_add(ac
);
4229 * The user may have an optional PSO applied. If so,
4230 * query the PSO to get the Fine-Grained Password Policy
4231 * for the user, before we perform the modify
4233 pso_req
= build_pso_data_request(ac
);
4234 if (pso_req
!= NULL
) {
4235 ret
= ldb_next_request(ac
->module
, pso_req
);
4238 /* no PSO, so we can perform the modify now */
4239 ret
= password_hash_mod_do_mod(ac
);
4244 ret
= LDB_ERR_OPERATIONS_ERROR
;
4251 if (ret
!= LDB_SUCCESS
) {
4252 struct ldb_reply
*new_ares
;
4254 new_ares
= talloc_zero(ac
->req
, struct ldb_reply
);
4255 if (new_ares
== NULL
) {
4257 return ldb_module_done(ac
->req
, NULL
, NULL
,
4258 LDB_ERR_OPERATIONS_ERROR
);
4261 new_ares
->error
= ret
;
4262 if ((ret
!= LDB_ERR_OPERATIONS_ERROR
) && (ac
->change_status
)) {
4263 /* On success and trivial errors a status control is being
4264 * added (used for example by the "samdb_set_password" call) */
4265 ldb_reply_add_control(new_ares
,
4266 DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID
,
4271 return ldb_module_done(ac
->req
, new_ares
->controls
,
4272 new_ares
->response
, new_ares
->error
);
4278 static int build_domain_data_request(struct ph_context
*ac
)
4280 /* attrs[] is returned from this function in
4281 ac->dom_req->op.search.attrs, so it must be static, as
4282 otherwise the compiler can put it on the stack */
4283 struct ldb_context
*ldb
;
4284 static const char * const attrs
[] = { "pwdProperties",
4290 "lockOutObservationWindow",
4294 ldb
= ldb_module_get_ctx(ac
->module
);
4296 ret
= ldb_build_search_req(&ac
->dom_req
, ldb
, ac
,
4297 ldb_get_default_basedn(ldb
),
4301 ac
, get_domain_data_callback
,
4303 LDB_REQ_SET_LOCATION(ac
->dom_req
);
4307 static int password_hash_needed(struct ldb_module
*module
,
4308 struct ldb_request
*req
,
4309 struct ph_context
**_ac
)
4311 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
4312 const char *operation
= NULL
;
4313 const struct ldb_message
*msg
= NULL
;
4314 struct ph_context
*ac
= NULL
;
4315 const char *passwordAttrs
[] = {
4316 DSDB_PASSWORD_ATTRIBUTES
,
4319 const char **a
= NULL
;
4320 unsigned int attr_cnt
= 0;
4321 struct ldb_control
*bypass
= NULL
;
4322 struct ldb_control
*uac_ctrl
= NULL
;
4323 bool userPassword
= dsdb_user_password_support(module
, req
, req
);
4324 bool update_password
= false;
4325 bool processing_needed
= false;
4329 ldb_debug(ldb
, LDB_DEBUG_TRACE
, "password_hash_needed\n");
4331 switch (req
->operation
) {
4334 msg
= req
->op
.add
.message
;
4337 operation
= "modify";
4338 msg
= req
->op
.mod
.message
;
4341 return ldb_next_request(module
, req
);
4344 if (ldb_dn_is_special(msg
->dn
)) { /* do not manipulate our control entries */
4345 return ldb_next_request(module
, req
);
4348 bypass
= ldb_request_get_control(req
,
4349 DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID
);
4350 if (bypass
!= NULL
) {
4351 /* Mark the "bypass" control as uncritical (done) */
4352 bypass
->critical
= false;
4353 ldb_debug(ldb
, LDB_DEBUG_TRACE
,
4354 "password_hash_needed(%s) (bypassing)\n",
4356 return password_hash_bypass(module
, req
);
4359 /* nobody must touch password histories and 'supplementalCredentials' */
4360 if (ldb_msg_find_element(msg
, "ntPwdHistory")) {
4361 return LDB_ERR_UNWILLING_TO_PERFORM
;
4363 if (ldb_msg_find_element(msg
, "lmPwdHistory")) {
4364 return LDB_ERR_UNWILLING_TO_PERFORM
;
4366 if (ldb_msg_find_element(msg
, "supplementalCredentials")) {
4367 return LDB_ERR_UNWILLING_TO_PERFORM
;
4371 * If no part of this touches the 'userPassword' OR 'clearTextPassword'
4372 * OR 'unicodePwd' OR 'dBCSPwd' we don't need to make any changes.
4373 * For password changes/set there should be a 'delete' or a 'modify'
4374 * on these attributes.
4376 for (a
= passwordAttrs
; *a
!= NULL
; a
++) {
4377 if ((!userPassword
) && (ldb_attr_cmp(*a
, "userPassword") == 0)) {
4381 if (ldb_msg_find_element(msg
, *a
) != NULL
) {
4382 /* MS-ADTS 3.1.1.3.1.5.2 */
4383 if ((ldb_attr_cmp(*a
, "userPassword") == 0) &&
4384 (dsdb_functional_level(ldb
) < DS_DOMAIN_FUNCTION_2003
)) {
4385 return LDB_ERR_CONSTRAINT_VIOLATION
;
4393 update_password
= true;
4394 processing_needed
= true;
4397 if (ldb_msg_find_element(msg
, "pwdLastSet")) {
4398 processing_needed
= true;
4401 uac_ctrl
= ldb_request_get_control(req
,
4402 DSDB_CONTROL_PASSWORD_USER_ACCOUNT_CONTROL_OID
);
4403 if (uac_ctrl
!= NULL
) {
4404 struct dsdb_control_password_user_account_control
*uac
= NULL
;
4405 uint32_t added_flags
= 0;
4407 uac
= talloc_get_type_abort(uac_ctrl
->data
,
4408 struct dsdb_control_password_user_account_control
);
4410 added_flags
= uac
->new_flags
& ~uac
->old_flags
;
4412 if (added_flags
& UF_SMARTCARD_REQUIRED
) {
4413 processing_needed
= true;
4417 if (!processing_needed
) {
4418 return ldb_next_request(module
, req
);
4421 ac
= ph_init_context(module
, req
, userPassword
, update_password
);
4423 DEBUG(0,(__location__
": %s\n", ldb_errstring(ldb
)));
4424 return ldb_operr(ldb
);
4426 ph_apply_controls(ac
);
4429 * Make a copy in order to apply our modifications
4430 * to the final update
4432 ac
->update_msg
= ldb_msg_copy_shallow(ac
, msg
);
4433 if (ac
->update_msg
== NULL
) {
4434 return ldb_oom(ldb
);
4438 * Remove all password related attributes.
4440 if (ac
->userPassword
) {
4441 ldb_msg_remove_attr(ac
->update_msg
, "userPassword");
4443 ldb_msg_remove_attr(ac
->update_msg
, "clearTextPassword");
4444 ldb_msg_remove_attr(ac
->update_msg
, "unicodePwd");
4445 ldb_msg_remove_attr(ac
->update_msg
, "ntPwdHistory");
4446 ldb_msg_remove_attr(ac
->update_msg
, "dBCSPwd");
4447 ldb_msg_remove_attr(ac
->update_msg
, "lmPwdHistory");
4448 ldb_msg_remove_attr(ac
->update_msg
, "supplementalCredentials");
4449 ldb_msg_remove_attr(ac
->update_msg
, "pwdLastSet");
4455 static int password_hash_add(struct ldb_module
*module
, struct ldb_request
*req
)
4457 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
4458 struct ph_context
*ac
= NULL
;
4461 ldb_debug(ldb
, LDB_DEBUG_TRACE
, "password_hash_add\n");
4463 ret
= password_hash_needed(module
, req
, &ac
);
4464 if (ret
!= LDB_SUCCESS
) {
4471 /* Make sure we are performing the password set action on a (for us)
4472 * valid object. Those are instances of either "user" and/or
4473 * "inetOrgPerson". Otherwise continue with the submodules. */
4474 if ((!ldb_msg_check_string_attribute(req
->op
.add
.message
, "objectClass", "user"))
4475 && (!ldb_msg_check_string_attribute(req
->op
.add
.message
, "objectClass", "inetOrgPerson"))) {
4479 if (ldb_msg_find_element(req
->op
.add
.message
, "clearTextPassword") != NULL
) {
4480 ldb_set_errstring(ldb
,
4481 "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
4482 return LDB_ERR_NO_SUCH_ATTRIBUTE
;
4485 return ldb_next_request(module
, req
);
4488 /* get user domain data */
4489 ret
= build_domain_data_request(ac
);
4490 if (ret
!= LDB_SUCCESS
) {
4494 return ldb_next_request(module
, ac
->dom_req
);
4497 static int password_hash_add_do_add(struct ph_context
*ac
)
4499 struct ldb_context
*ldb
= ldb_module_get_ctx(ac
->module
);
4500 struct ldb_request
*down_req
;
4501 struct setup_password_fields_io io
;
4504 /* Prepare the internal data structure containing the passwords */
4505 ret
= setup_io(ac
, ac
->req
->op
.add
.message
, NULL
, &io
);
4506 if (ret
!= LDB_SUCCESS
) {
4510 ret
= setup_password_fields(&io
);
4511 if (ret
!= LDB_SUCCESS
) {
4515 ret
= check_password_restrictions_and_log(&io
);
4516 if (ret
!= LDB_SUCCESS
) {
4520 ret
= setup_smartcard_reset(&io
);
4521 if (ret
!= LDB_SUCCESS
) {
4525 ret
= update_final_msg(&io
);
4526 if (ret
!= LDB_SUCCESS
) {
4530 ret
= ldb_build_add_req(&down_req
, ldb
, ac
,
4535 LDB_REQ_SET_LOCATION(down_req
);
4536 if (ret
!= LDB_SUCCESS
) {
4540 return ldb_next_request(ac
->module
, down_req
);
4543 static int password_hash_modify(struct ldb_module
*module
, struct ldb_request
*req
)
4545 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
4546 struct ph_context
*ac
= NULL
;
4547 const char *passwordAttrs
[] = {DSDB_PASSWORD_ATTRIBUTES
, NULL
}, **l
;
4548 unsigned int del_attr_cnt
, add_attr_cnt
, rep_attr_cnt
;
4549 struct ldb_message_element
*passwordAttr
;
4550 struct ldb_message
*msg
;
4551 struct ldb_request
*down_req
;
4552 struct ldb_control
*restore
= NULL
;
4556 ldb_debug(ldb
, LDB_DEBUG_TRACE
, "password_hash_modify\n");
4558 ret
= password_hash_needed(module
, req
, &ac
);
4559 if (ret
!= LDB_SUCCESS
) {
4566 /* use a new message structure so that we can modify it */
4567 msg
= ldb_msg_copy_shallow(ac
, req
->op
.mod
.message
);
4569 return ldb_oom(ldb
);
4572 /* - check for single-valued password attributes
4573 * (if not return "CONSTRAINT_VIOLATION")
4574 * - check that for a password change operation one add and one delete
4576 * (if not return "CONSTRAINT_VIOLATION" or "UNWILLING_TO_PERFORM")
4577 * - check that a password change and a password set operation cannot
4579 * (if not return "UNWILLING_TO_PERFORM")
4580 * - remove all password attributes modifications from the first change
4581 * operation (anything without the passwords) - we will make the real
4582 * modification later */
4586 for (l
= passwordAttrs
; *l
!= NULL
; l
++) {
4587 if ((!ac
->userPassword
) &&
4588 (ldb_attr_cmp(*l
, "userPassword") == 0)) {
4592 while ((passwordAttr
= ldb_msg_find_element(msg
, *l
)) != NULL
) {
4593 unsigned int mtype
= LDB_FLAG_MOD_TYPE(passwordAttr
->flags
);
4594 unsigned int nvalues
= passwordAttr
->num_values
;
4596 if (mtype
== LDB_FLAG_MOD_DELETE
) {
4599 if (mtype
== LDB_FLAG_MOD_ADD
) {
4602 if (mtype
== LDB_FLAG_MOD_REPLACE
) {
4605 if ((nvalues
!= 1) && (mtype
== LDB_FLAG_MOD_ADD
)) {
4607 ldb_asprintf_errstring(ldb
,
4608 "'%s' attribute must have exactly one value on add operations!",
4610 return LDB_ERR_CONSTRAINT_VIOLATION
;
4612 if ((nvalues
> 1) && (mtype
== LDB_FLAG_MOD_DELETE
)) {
4614 ldb_asprintf_errstring(ldb
,
4615 "'%s' attribute must have zero or one value(s) on delete operations!",
4617 return LDB_ERR_CONSTRAINT_VIOLATION
;
4619 ldb_msg_remove_element(msg
, passwordAttr
);
4622 if ((del_attr_cnt
== 0) && (add_attr_cnt
> 0)) {
4624 ldb_set_errstring(ldb
,
4625 "Only the add action for a password change specified!");
4626 return LDB_ERR_UNWILLING_TO_PERFORM
;
4628 if ((del_attr_cnt
> 1) || (add_attr_cnt
> 1)) {
4630 ldb_set_errstring(ldb
,
4631 "Only one delete and one add action for a password change allowed!");
4632 return LDB_ERR_UNWILLING_TO_PERFORM
;
4634 if ((rep_attr_cnt
> 0) && ((del_attr_cnt
> 0) || (add_attr_cnt
> 0))) {
4636 ldb_set_errstring(ldb
,
4637 "Either a password change or a password set operation is allowed!");
4638 return LDB_ERR_UNWILLING_TO_PERFORM
;
4641 restore
= ldb_request_get_control(req
,
4642 DSDB_CONTROL_RESTORE_TOMBSTONE_OID
);
4643 if (restore
== NULL
) {
4645 * A tomstone reanimation generates a double update
4648 * So we only remove it without the
4649 * DSDB_CONTROL_RESTORE_TOMBSTONE_OID control.
4651 ldb_msg_remove_attr(msg
, "pwdLastSet");
4655 /* if there was nothing else to be modified skip to next step */
4656 if (msg
->num_elements
== 0) {
4657 return password_hash_mod_search_self(ac
);
4661 * Now we apply all changes remaining in msg
4662 * and remove them from our final update_msg
4665 for (i
= 0; i
< msg
->num_elements
; i
++) {
4666 ldb_msg_remove_attr(ac
->update_msg
,
4667 msg
->elements
[i
].name
);
4670 ret
= ldb_build_mod_req(&down_req
, ldb
, ac
,
4673 ac
, ph_modify_callback
,
4675 LDB_REQ_SET_LOCATION(down_req
);
4676 if (ret
!= LDB_SUCCESS
) {
4680 return ldb_next_request(module
, down_req
);
4683 static int ph_modify_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
4685 struct ph_context
*ac
;
4687 ac
= talloc_get_type(req
->context
, struct ph_context
);
4690 return ldb_module_done(ac
->req
, NULL
, NULL
,
4691 LDB_ERR_OPERATIONS_ERROR
);
4694 if (ares
->type
== LDB_REPLY_REFERRAL
) {
4695 return ldb_module_send_referral(ac
->req
, ares
->referral
);
4698 if (ares
->error
!= LDB_SUCCESS
) {
4699 return ldb_module_done(ac
->req
, ares
->controls
,
4700 ares
->response
, ares
->error
);
4703 if (ares
->type
!= LDB_REPLY_DONE
) {
4705 return ldb_module_done(ac
->req
, NULL
, NULL
,
4706 LDB_ERR_OPERATIONS_ERROR
);
4711 return password_hash_mod_search_self(ac
);
4714 static int ph_mod_search_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
4716 struct ldb_context
*ldb
;
4717 struct ph_context
*ac
;
4718 int ret
= LDB_SUCCESS
;
4720 ac
= talloc_get_type(req
->context
, struct ph_context
);
4721 ldb
= ldb_module_get_ctx(ac
->module
);
4724 ret
= LDB_ERR_OPERATIONS_ERROR
;
4727 if (ares
->error
!= LDB_SUCCESS
) {
4728 return ldb_module_done(ac
->req
, ares
->controls
,
4729 ares
->response
, ares
->error
);
4732 /* we are interested only in the single reply (base search) */
4733 switch (ares
->type
) {
4734 case LDB_REPLY_ENTRY
:
4735 /* Make sure we are performing the password change action on a
4736 * (for us) valid object. Those are instances of either "user"
4737 * and/or "inetOrgPerson". Otherwise continue with the
4739 if ((!ldb_msg_check_string_attribute(ares
->message
, "objectClass", "user"))
4740 && (!ldb_msg_check_string_attribute(ares
->message
, "objectClass", "inetOrgPerson"))) {
4743 if (ldb_msg_find_element(ac
->req
->op
.mod
.message
, "clearTextPassword") != NULL
) {
4744 ldb_set_errstring(ldb
,
4745 "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
4746 ret
= LDB_ERR_NO_SUCH_ATTRIBUTE
;
4750 ret
= ldb_next_request(ac
->module
, ac
->req
);
4754 if (ac
->search_res
!= NULL
) {
4757 ldb_set_errstring(ldb
, "Too many results");
4758 ret
= LDB_ERR_OPERATIONS_ERROR
;
4762 ac
->search_res
= talloc_steal(ac
, ares
);
4766 case LDB_REPLY_REFERRAL
:
4767 /* ignore anything else for now */
4772 case LDB_REPLY_DONE
:
4775 /* get user domain data */
4776 ret
= build_domain_data_request(ac
);
4777 if (ret
!= LDB_SUCCESS
) {
4778 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
4781 ret
= ldb_next_request(ac
->module
, ac
->dom_req
);
4786 if (ret
!= LDB_SUCCESS
) {
4787 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
4793 static int password_hash_mod_search_self(struct ph_context
*ac
)
4795 struct ldb_context
*ldb
;
4796 static const char * const attrs
[] = { "objectClass",
4797 "userAccountControl",
4798 "msDS-ResultantPSO",
4799 "msDS-User-Account-Control-Computed",
4803 "userPrincipalName",
4805 "supplementalCredentials",
4813 "msDS-SecondaryKrbTgtNumber",
4815 struct ldb_request
*search_req
;
4818 ldb
= ldb_module_get_ctx(ac
->module
);
4820 ret
= ldb_build_search_req(&search_req
, ldb
, ac
,
4821 ac
->req
->op
.mod
.message
->dn
,
4826 ac
, ph_mod_search_callback
,
4828 LDB_REQ_SET_LOCATION(search_req
);
4829 if (ret
!= LDB_SUCCESS
) {
4833 return ldb_next_request(ac
->module
, search_req
);
4836 static int password_hash_mod_do_mod(struct ph_context
*ac
)
4838 struct ldb_context
*ldb
= ldb_module_get_ctx(ac
->module
);
4839 struct ldb_request
*mod_req
;
4840 struct setup_password_fields_io io
;
4843 /* Prepare the internal data structure containing the passwords */
4844 ret
= setup_io(ac
, ac
->req
->op
.mod
.message
,
4845 ac
->search_res
->message
, &io
);
4846 if (ret
!= LDB_SUCCESS
) {
4850 ret
= setup_password_fields(&io
);
4851 if (ret
!= LDB_SUCCESS
) {
4855 ret
= check_password_restrictions_and_log(&io
);
4856 if (ret
!= LDB_SUCCESS
) {
4860 ret
= setup_smartcard_reset(&io
);
4861 if (ret
!= LDB_SUCCESS
) {
4865 ret
= update_final_msg(&io
);
4866 if (ret
!= LDB_SUCCESS
) {
4870 ret
= ldb_build_mod_req(&mod_req
, ldb
, ac
,
4875 LDB_REQ_SET_LOCATION(mod_req
);
4876 if (ret
!= LDB_SUCCESS
) {
4880 return ldb_next_request(ac
->module
, mod_req
);
4883 static const struct ldb_module_ops ldb_password_hash_module_ops
= {
4884 .name
= "password_hash",
4885 .add
= password_hash_add
,
4886 .modify
= password_hash_modify
4889 int ldb_password_hash_module_init(const char *version
)
4892 const char *gversion
= NULL
;
4893 #endif /* ENABLE_GPGME */
4895 LDB_MODULE_CHECK_VERSION(version
);
4899 * Note: this sets a SIGPIPE handler
4900 * if none is active already. See:
4901 * https://www.gnupg.org/documentation/manuals/gpgme/Signal-Handling.html#Signal-Handling
4903 gversion
= gpgme_check_version(MINIMUM_GPGME_VERSION
);
4904 if (gversion
== NULL
) {
4905 fprintf(stderr
, "%s() in %s version[%s]: "
4906 "gpgme_check_version(%s) not available, "
4907 "gpgme_check_version(NULL) => '%s'\n",
4908 __func__
, __FILE__
, version
,
4909 MINIMUM_GPGME_VERSION
, gpgme_check_version(NULL
));
4910 return LDB_ERR_UNAVAILABLE
;
4912 #endif /* ENABLE_GPGME */
4914 return ldb_register_module(&ldb_password_hash_module_ops
);