krb5_wrap: Rename kerberos_free_data_contents()
[samba.git] / source4 / dsdb / samdb / ldb_modules / password_hash.c
1 /* 
2    ldb database module
3
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
9
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.
14    
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.
19    
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/>.
22 */
23
24 /*
25  *  Name: ldb
26  *
27  *  Component: ldb password_hash module
28  *
29  *  Description: correctly handle AD password changes fields
30  *
31  *  Author: Andrew Bartlett
32  *  Author: Stefan Metzmacher
33  */
34
35 #include "includes.h"
36 #include "ldb_module.h"
37 #include "libcli/auth/libcli_auth.h"
38 #include "system/kerberos.h"
39 #include "auth/kerberos/kerberos.h"
40 #include "dsdb/samdb/samdb.h"
41 #include "dsdb/samdb/ldb_modules/util.h"
42 #include "dsdb/samdb/ldb_modules/password_modules.h"
43 #include "librpc/gen_ndr/ndr_drsblobs.h"
44 #include "../lib/crypto/crypto.h"
45 #include "param/param.h"
46 #include "lib/krb5_wrap/krb5_samba.h"
47
48 #ifdef ENABLE_GPGME
49 #undef class
50 #include <gpgme.h>
51 #endif
52
53 /* If we have decided there is a reason to work on this request, then
54  * setup all the password hash types correctly.
55  *
56  * If we haven't the hashes yet but the password given as plain-text (attributes
57  * 'unicodePwd', 'userPassword' and 'clearTextPassword') we have to check for
58  * the constraints. Once this is done, we calculate the password hashes.
59  *
60  * Notice: unlike the real AD which only supports the UTF16 special based
61  * 'unicodePwd' and the UTF8 based 'userPassword' plaintext attribute we
62  * understand also a UTF16 based 'clearTextPassword' one.
63  * The latter is also accessible through LDAP so it can also be set by external
64  * tools and scripts. But be aware that this isn't portable on non SAMBA 4 ADs!
65  *
66  * Also when the module receives only the password hashes (possible through
67  * specifying an internal LDB control - for security reasons) some checks are
68  * performed depending on the operation mode (see below) (e.g. if the password
69  * has been in use before if the password memory policy was activated).
70  *
71  * Attention: There is a difference between "modify" and "reset" operations
72  * (see MS-ADTS 3.1.1.3.1.5). If the client sends a "add" and "remove"
73  * operation for a password attribute we thread this as a "modify"; if it sends
74  * only a "replace" one we have an (administrative) reset.
75  *
76  * Finally, if the administrator has requested that a password history
77  * be maintained, then this should also be written out.
78  *
79  */
80
81 /* TODO: [consider always MS-ADTS 3.1.1.3.1.5]
82  * - Check for right connection encryption
83  */
84
85 /* Notice: Definition of "dsdb_control_password_change_status" moved into
86  * "samdb.h" */
87
88 struct ph_context {
89         struct ldb_module *module;
90         struct ldb_request *req;
91
92         struct ldb_request *dom_req;
93         struct ldb_reply *dom_res;
94
95         struct ldb_reply *search_res;
96
97         struct ldb_message *update_msg;
98
99         struct dsdb_control_password_change_status *status;
100         struct dsdb_control_password_change *change;
101
102         const char **gpg_key_ids;
103
104         bool pwd_reset;
105         bool change_status;
106         bool hash_values;
107         bool userPassword;
108         bool update_password;
109         bool update_lastset;
110         bool pwd_last_set_bypass;
111         bool pwd_last_set_default;
112         bool smartcard_reset;
113 };
114
115
116 struct setup_password_fields_io {
117         struct ph_context *ac;
118
119         struct smb_krb5_context *smb_krb5_context;
120
121         /* infos about the user account */
122         struct {
123                 uint32_t userAccountControl;
124                 NTTIME pwdLastSet;
125                 const char *sAMAccountName;
126                 const char *user_principal_name;
127                 bool is_computer;
128                 uint32_t restrictions;
129         } u;
130
131         /* new credentials and old given credentials */
132         struct setup_password_fields_given {
133                 const struct ldb_val *cleartext_utf8;
134                 const struct ldb_val *cleartext_utf16;
135                 struct samr_Password *nt_hash;
136                 struct samr_Password *lm_hash;
137         } n, og;
138
139         /* old credentials */
140         struct {
141                 struct samr_Password *nt_hash;
142                 struct samr_Password *lm_hash;
143                 uint32_t nt_history_len;
144                 struct samr_Password *nt_history;
145                 uint32_t lm_history_len;
146                 struct samr_Password *lm_history;
147                 const struct ldb_val *supplemental;
148                 struct supplementalCredentialsBlob scb;
149         } o;
150
151         /* generated credentials */
152         struct {
153                 struct samr_Password *nt_hash;
154                 struct samr_Password *lm_hash;
155                 uint32_t nt_history_len;
156                 struct samr_Password *nt_history;
157                 uint32_t lm_history_len;
158                 struct samr_Password *lm_history;
159                 const char *salt;
160                 DATA_BLOB aes_256;
161                 DATA_BLOB aes_128;
162                 DATA_BLOB des_md5;
163                 DATA_BLOB des_crc;
164                 struct ldb_val supplemental;
165                 NTTIME last_set;
166         } g;
167 };
168
169 static int msg_find_old_and_new_pwd_val(const struct ldb_message *msg,
170                                         const char *name,
171                                         enum ldb_request_type operation,
172                                         const struct ldb_val **new_val,
173                                         const struct ldb_val **old_val);
174
175 static int password_hash_bypass(struct ldb_module *module, struct ldb_request *request)
176 {
177         struct ldb_context *ldb = ldb_module_get_ctx(module);
178         const struct ldb_message *msg;
179         struct ldb_message_element *nte;
180         struct ldb_message_element *lme;
181         struct ldb_message_element *nthe;
182         struct ldb_message_element *lmhe;
183         struct ldb_message_element *sce;
184
185         switch (request->operation) {
186         case LDB_ADD:
187                 msg = request->op.add.message;
188                 break;
189         case LDB_MODIFY:
190                 msg = request->op.mod.message;
191                 break;
192         default:
193                 return ldb_next_request(module, request);
194         }
195
196         /* nobody must touch password histories and 'supplementalCredentials' */
197         nte = dsdb_get_single_valued_attr(msg, "unicodePwd",
198                                           request->operation);
199         lme = dsdb_get_single_valued_attr(msg, "dBCSPwd",
200                                           request->operation);
201         nthe = dsdb_get_single_valued_attr(msg, "ntPwdHistory",
202                                            request->operation);
203         lmhe = dsdb_get_single_valued_attr(msg, "lmPwdHistory",
204                                            request->operation);
205         sce = dsdb_get_single_valued_attr(msg, "supplementalCredentials",
206                                           request->operation);
207
208 #define CHECK_HASH_ELEMENT(e, min, max) do {\
209         if (e && e->num_values) { \
210                 unsigned int _count; \
211                 if (e->num_values != 1) { \
212                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
213                                          "num_values != 1"); \
214                 } \
215                 if ((e->values[0].length % 16) != 0) { \
216                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
217                                          "length % 16 != 0"); \
218                 } \
219                 _count = e->values[0].length / 16; \
220                 if (_count < min) { \
221                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
222                                          "count < min"); \
223                 } \
224                 if (_count > max) { \
225                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
226                                          "count > max"); \
227                 } \
228         } \
229 } while (0)
230
231         CHECK_HASH_ELEMENT(nte, 1, 1);
232         CHECK_HASH_ELEMENT(lme, 1, 1);
233         CHECK_HASH_ELEMENT(nthe, 1, INT32_MAX);
234         CHECK_HASH_ELEMENT(lmhe, 1, INT32_MAX);
235
236         if (sce && sce->num_values) {
237                 enum ndr_err_code ndr_err;
238                 struct supplementalCredentialsBlob *scb;
239                 struct supplementalCredentialsPackage *scpp = NULL;
240                 struct supplementalCredentialsPackage *scpk = NULL;
241                 struct supplementalCredentialsPackage *scpkn = NULL;
242                 struct supplementalCredentialsPackage *scpct = NULL;
243                 DATA_BLOB scpbp = data_blob_null;
244                 DATA_BLOB scpbk = data_blob_null;
245                 DATA_BLOB scpbkn = data_blob_null;
246                 DATA_BLOB scpbct = data_blob_null;
247                 DATA_BLOB blob;
248                 uint32_t i;
249
250                 if (sce->num_values != 1) {
251                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
252                                          "num_values != 1");
253                 }
254
255                 scb = talloc_zero(request, struct supplementalCredentialsBlob);
256                 if (!scb) {
257                         return ldb_module_oom(module);
258                 }
259
260                 ndr_err = ndr_pull_struct_blob_all(&sce->values[0], scb, scb,
261                                 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
262                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
263                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
264                                          "ndr_pull_struct_blob_all");
265                 }
266
267                 if (scb->sub.num_packages < 2) {
268                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
269                                          "num_packages < 2");
270                 }
271
272                 for (i=0; i < scb->sub.num_packages; i++) {
273                         DATA_BLOB subblob;
274
275                         subblob = strhex_to_data_blob(scb, scb->sub.packages[i].data);
276                         if (subblob.data == NULL) {
277                                 return ldb_module_oom(module);
278                         }
279
280                         if (strcmp(scb->sub.packages[i].name, "Packages") == 0) {
281                                 if (scpp) {
282                                         return ldb_error(ldb,
283                                                          LDB_ERR_CONSTRAINT_VIOLATION,
284                                                          "Packages twice");
285                                 }
286                                 scpp = &scb->sub.packages[i];
287                                 scpbp = subblob;
288                                 continue;
289                         }
290                         if (strcmp(scb->sub.packages[i].name, "Primary:Kerberos") == 0) {
291                                 if (scpk) {
292                                         return ldb_error(ldb,
293                                                          LDB_ERR_CONSTRAINT_VIOLATION,
294                                                          "Primary:Kerberos twice");
295                                 }
296                                 scpk = &scb->sub.packages[i];
297                                 scpbk = subblob;
298                                 continue;
299                         }
300                         if (strcmp(scb->sub.packages[i].name, "Primary:Kerberos-Newer-Keys") == 0) {
301                                 if (scpkn) {
302                                         return ldb_error(ldb,
303                                                          LDB_ERR_CONSTRAINT_VIOLATION,
304                                                          "Primary:Kerberos-Newer-Keys twice");
305                                 }
306                                 scpkn = &scb->sub.packages[i];
307                                 scpbkn = subblob;
308                                 continue;
309                         }
310                         if (strcmp(scb->sub.packages[i].name, "Primary:CLEARTEXT") == 0) {
311                                 if (scpct) {
312                                         return ldb_error(ldb,
313                                                          LDB_ERR_CONSTRAINT_VIOLATION,
314                                                          "Primary:CLEARTEXT twice");
315                                 }
316                                 scpct = &scb->sub.packages[i];
317                                 scpbct = subblob;
318                                 continue;
319                         }
320
321                         data_blob_free(&subblob);
322                 }
323
324                 if (scpp == NULL) {
325                         return ldb_error(ldb,
326                                          LDB_ERR_CONSTRAINT_VIOLATION,
327                                          "Primary:Packages missing");
328                 }
329
330                 if (scpk == NULL) {
331                         /*
332                          * If Primary:Kerberos is missing w2k8r2 reboots
333                          * when a password is changed.
334                          */
335                         return ldb_error(ldb,
336                                          LDB_ERR_CONSTRAINT_VIOLATION,
337                                          "Primary:Kerberos missing");
338                 }
339
340                 if (scpp) {
341                         struct package_PackagesBlob *p;
342                         uint32_t n;
343
344                         p = talloc_zero(scb, struct package_PackagesBlob);
345                         if (p == NULL) {
346                                 return ldb_module_oom(module);
347                         }
348
349                         ndr_err = ndr_pull_struct_blob(&scpbp, p, p,
350                                         (ndr_pull_flags_fn_t)ndr_pull_package_PackagesBlob);
351                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
352                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
353                                                  "ndr_pull_struct_blob Packages");
354                         }
355
356                         if (p->names == NULL) {
357                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
358                                                  "Packages names == NULL");
359                         }
360
361                         for (n = 0; p->names[n]; n++) {
362                                 /* noop */
363                         }
364
365                         if (scb->sub.num_packages != (n + 1)) {
366                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
367                                                  "Packages num_packages != num_names + 1");
368                         }
369
370                         talloc_free(p);
371                 }
372
373                 if (scpk) {
374                         struct package_PrimaryKerberosBlob *k;
375
376                         k = talloc_zero(scb, struct package_PrimaryKerberosBlob);
377                         if (k == NULL) {
378                                 return ldb_module_oom(module);
379                         }
380
381                         ndr_err = ndr_pull_struct_blob(&scpbk, k, k,
382                                         (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
383                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
384                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
385                                                  "ndr_pull_struct_blob PrimaryKerberos");
386                         }
387
388                         if (k->version != 3) {
389                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
390                                                  "PrimaryKerberos version != 3");
391                         }
392
393                         if (k->ctr.ctr3.salt.string == NULL) {
394                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
395                                                  "PrimaryKerberos salt == NULL");
396                         }
397
398                         if (strlen(k->ctr.ctr3.salt.string) == 0) {
399                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
400                                                  "PrimaryKerberos strlen(salt) == 0");
401                         }
402
403                         if (k->ctr.ctr3.num_keys != 2) {
404                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
405                                                  "PrimaryKerberos num_keys != 2");
406                         }
407
408                         if (k->ctr.ctr3.num_old_keys > k->ctr.ctr3.num_keys) {
409                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
410                                                  "PrimaryKerberos num_old_keys > num_keys");
411                         }
412
413                         if (k->ctr.ctr3.keys[0].keytype != ENCTYPE_DES_CBC_MD5) {
414                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
415                                                  "PrimaryKerberos key[0] != DES_CBC_MD5");
416                         }
417                         if (k->ctr.ctr3.keys[1].keytype != ENCTYPE_DES_CBC_CRC) {
418                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
419                                                  "PrimaryKerberos key[1] != DES_CBC_CRC");
420                         }
421
422                         if (k->ctr.ctr3.keys[0].value_len != 8) {
423                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
424                                                  "PrimaryKerberos key[0] value_len != 8");
425                         }
426                         if (k->ctr.ctr3.keys[1].value_len != 8) {
427                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
428                                                  "PrimaryKerberos key[1] value_len != 8");
429                         }
430
431                         for (i = 0; i < k->ctr.ctr3.num_old_keys; i++) {
432                                 if (k->ctr.ctr3.old_keys[i].keytype ==
433                                     k->ctr.ctr3.keys[i].keytype &&
434                                     k->ctr.ctr3.old_keys[i].value_len ==
435                                     k->ctr.ctr3.keys[i].value_len) {
436                                         continue;
437                                 }
438
439                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
440                                                  "PrimaryKerberos old_keys type/value_len doesn't match");
441                         }
442
443                         talloc_free(k);
444                 }
445
446                 if (scpkn) {
447                         struct package_PrimaryKerberosBlob *k;
448
449                         k = talloc_zero(scb, struct package_PrimaryKerberosBlob);
450                         if (k == NULL) {
451                                 return ldb_module_oom(module);
452                         }
453
454                         ndr_err = ndr_pull_struct_blob(&scpbkn, k, k,
455                                         (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
456                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
457                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
458                                                  "ndr_pull_struct_blob PrimaryKerberosNeverKeys");
459                         }
460
461                         if (k->version != 4) {
462                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
463                                                  "KerberosNerverKeys version != 4");
464                         }
465
466                         if (k->ctr.ctr4.salt.string == NULL) {
467                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
468                                                  "KerberosNewerKeys salt == NULL");
469                         }
470
471                         if (strlen(k->ctr.ctr4.salt.string) == 0) {
472                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
473                                                  "KerberosNewerKeys strlen(salt) == 0");
474                         }
475
476                         if (k->ctr.ctr4.num_keys != 4) {
477                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
478                                                  "KerberosNewerKeys num_keys != 2");
479                         }
480
481                         if (k->ctr.ctr4.num_old_keys > k->ctr.ctr4.num_keys) {
482                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
483                                                  "KerberosNewerKeys num_old_keys > num_keys");
484                         }
485
486                         if (k->ctr.ctr4.num_older_keys > k->ctr.ctr4.num_old_keys) {
487                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
488                                                  "KerberosNewerKeys num_older_keys > num_old_keys");
489                         }
490
491                         if (k->ctr.ctr4.keys[0].keytype != ENCTYPE_AES256_CTS_HMAC_SHA1_96) {
492                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
493                                                  "KerberosNewerKeys key[0] != AES256");
494                         }
495                         if (k->ctr.ctr4.keys[1].keytype != ENCTYPE_AES128_CTS_HMAC_SHA1_96) {
496                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
497                                                  "KerberosNewerKeys key[1] != AES128");
498                         }
499                         if (k->ctr.ctr4.keys[2].keytype != ENCTYPE_DES_CBC_MD5) {
500                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
501                                                  "KerberosNewerKeys key[2] != DES_CBC_MD5");
502                         }
503                         if (k->ctr.ctr4.keys[3].keytype != ENCTYPE_DES_CBC_CRC) {
504                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
505                                                  "KerberosNewerKeys key[3] != DES_CBC_CRC");
506                         }
507
508                         if (k->ctr.ctr4.keys[0].value_len != 32) {
509                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
510                                                  "KerberosNewerKeys key[0] value_len != 32");
511                         }
512                         if (k->ctr.ctr4.keys[1].value_len != 16) {
513                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
514                                                  "KerberosNewerKeys key[1] value_len != 16");
515                         }
516                         if (k->ctr.ctr4.keys[2].value_len != 8) {
517                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
518                                                  "KerberosNewerKeys key[2] value_len != 8");
519                         }
520                         if (k->ctr.ctr4.keys[3].value_len != 8) {
521                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
522                                                  "KerberosNewerKeys key[3] value_len != 8");
523                         }
524
525                         /*
526                          * TODO:
527                          * Maybe we can check old and older keys here.
528                          * But we need to do some tests, if the old keys
529                          * can be taken from the PrimaryKerberos blob
530                          * (with only des keys), when the domain was upgraded
531                          * from w2k3 to w2k8.
532                          */
533
534                         talloc_free(k);
535                 }
536
537                 if (scpct) {
538                         struct package_PrimaryCLEARTEXTBlob *ct;
539
540                         ct = talloc_zero(scb, struct package_PrimaryCLEARTEXTBlob);
541                         if (ct == NULL) {
542                                 return ldb_module_oom(module);
543                         }
544
545                         ndr_err = ndr_pull_struct_blob(&scpbct, ct, ct,
546                                         (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryCLEARTEXTBlob);
547                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
548                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
549                                                  "ndr_pull_struct_blob PrimaryCLEARTEXT");
550                         }
551
552                         if ((ct->cleartext.length % 2) != 0) {
553                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
554                                                  "PrimaryCLEARTEXT length % 2 != 0");
555                         }
556
557                         talloc_free(ct);
558                 }
559
560                 ndr_err = ndr_push_struct_blob(&blob, scb, scb,
561                                 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
562                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
563                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
564                                          "ndr_pull_struct_blob_all");
565                 }
566
567                 if (sce->values[0].length != blob.length) {
568                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
569                                          "supplementalCredentialsBlob length differ");
570                 }
571
572                 if (memcmp(sce->values[0].data, blob.data, blob.length) != 0) {
573                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
574                                          "supplementalCredentialsBlob memcmp differ");
575                 }
576
577                 talloc_free(scb);
578         }
579
580         ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_bypass - validated\n");
581         return ldb_next_request(module, request);
582 }
583
584 /* Get the NT hash, and fill it in as an entry in the password history, 
585    and specify it into io->g.nt_hash */
586
587 static int setup_nt_fields(struct setup_password_fields_io *io)
588 {
589         struct ldb_context *ldb;
590         uint32_t i;
591
592         io->g.nt_hash = io->n.nt_hash;
593         ldb = ldb_module_get_ctx(io->ac->module);
594
595         if (io->ac->status->domain_data.pwdHistoryLength == 0) {
596                 return LDB_SUCCESS;
597         }
598
599         /* We might not have an old NT password */
600         io->g.nt_history = talloc_array(io->ac,
601                                         struct samr_Password,
602                                         io->ac->status->domain_data.pwdHistoryLength);
603         if (!io->g.nt_history) {
604                 return ldb_oom(ldb);
605         }
606
607         for (i = 0; i < MIN(io->ac->status->domain_data.pwdHistoryLength-1,
608                             io->o.nt_history_len); i++) {
609                 io->g.nt_history[i+1] = io->o.nt_history[i];
610         }
611         io->g.nt_history_len = i + 1;
612
613         if (io->g.nt_hash) {
614                 io->g.nt_history[0] = *io->g.nt_hash;
615         } else {
616                 /* 
617                  * TODO: is this correct?
618                  * the simular behavior is correct for the lm history case
619                  */
620                 E_md4hash("", io->g.nt_history[0].hash);
621         }
622
623         return LDB_SUCCESS;
624 }
625
626 /* Get the LANMAN hash, and fill it in as an entry in the password history, 
627    and specify it into io->g.lm_hash */
628
629 static int setup_lm_fields(struct setup_password_fields_io *io)
630 {
631         struct ldb_context *ldb;
632         uint32_t i;
633
634         io->g.lm_hash = io->n.lm_hash;
635         ldb = ldb_module_get_ctx(io->ac->module);
636
637         if (io->ac->status->domain_data.pwdHistoryLength == 0) {
638                 return LDB_SUCCESS;
639         }
640
641         /* We might not have an old LM password */
642         io->g.lm_history = talloc_array(io->ac,
643                                         struct samr_Password,
644                                         io->ac->status->domain_data.pwdHistoryLength);
645         if (!io->g.lm_history) {
646                 return ldb_oom(ldb);
647         }
648
649         for (i = 0; i < MIN(io->ac->status->domain_data.pwdHistoryLength-1,
650                             io->o.lm_history_len); i++) {
651                 io->g.lm_history[i+1] = io->o.lm_history[i];
652         }
653         io->g.lm_history_len = i + 1;
654
655         if (io->g.lm_hash) {
656                 io->g.lm_history[0] = *io->g.lm_hash;
657         } else {
658                 E_deshash("", io->g.lm_history[0].hash);
659         }
660
661         return LDB_SUCCESS;
662 }
663
664 static int setup_kerberos_keys(struct setup_password_fields_io *io)
665 {
666         struct ldb_context *ldb;
667         krb5_error_code krb5_ret;
668         krb5_principal salt_principal;
669         krb5_data salt;
670         krb5_keyblock key;
671         krb5_data cleartext_data;
672
673         ldb = ldb_module_get_ctx(io->ac->module);
674         cleartext_data.data = (char *)io->n.cleartext_utf8->data;
675         cleartext_data.length = io->n.cleartext_utf8->length;
676
677         /* Many, many thanks to lukeh@padl.com for this
678          * algorithm, described in his Nov 10 2004 mail to
679          * samba-technical@lists.samba.org */
680
681         /*
682          * Determine a salting principal
683          */
684         if (io->u.is_computer) {
685                 char *name;
686                 char *saltbody;
687
688                 name = strlower_talloc(io->ac, io->u.sAMAccountName);
689                 if (!name) {
690                         return ldb_oom(ldb);
691                 }
692
693                 if (name[strlen(name)-1] == '$') {
694                         name[strlen(name)-1] = '\0';
695                 }
696
697                 saltbody = talloc_asprintf(io->ac, "%s.%s", name,
698                                            io->ac->status->domain_data.dns_domain);
699                 if (!saltbody) {
700                         return ldb_oom(ldb);
701                 }
702                 
703                 krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
704                                                &salt_principal,
705                                                io->ac->status->domain_data.realm,
706                                                "host", saltbody, NULL);
707         } else if (io->u.user_principal_name) {
708                 char *user_principal_name;
709                 char *p;
710
711                 user_principal_name = talloc_strdup(io->ac, io->u.user_principal_name);
712                 if (!user_principal_name) {
713                         return ldb_oom(ldb);
714                 }
715
716                 p = strchr(user_principal_name, '@');
717                 if (p) {
718                         p[0] = '\0';
719                 }
720
721                 krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
722                                                &salt_principal,
723                                                io->ac->status->domain_data.realm,
724                                                user_principal_name, NULL);
725         } else {
726                 krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
727                                                &salt_principal,
728                                                io->ac->status->domain_data.realm,
729                                                io->u.sAMAccountName, NULL);
730         }
731         if (krb5_ret) {
732                 ldb_asprintf_errstring(ldb,
733                                        "setup_kerberos_keys: "
734                                        "generation of a salting principal failed: %s",
735                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
736                                                                   krb5_ret, io->ac));
737                 return LDB_ERR_OPERATIONS_ERROR;
738         }
739
740         /*
741          * create salt from salt_principal
742          */
743         krb5_ret = smb_krb5_get_pw_salt(io->smb_krb5_context->krb5_context,
744                                     salt_principal, &salt);
745         krb5_free_principal(io->smb_krb5_context->krb5_context, salt_principal);
746         if (krb5_ret) {
747                 ldb_asprintf_errstring(ldb,
748                                        "setup_kerberos_keys: "
749                                        "generation of krb5_salt failed: %s",
750                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
751                                                                   krb5_ret, io->ac));
752                 return LDB_ERR_OPERATIONS_ERROR;
753         }
754         /* create a talloc copy */
755         io->g.salt = talloc_strndup(io->ac,
756                                     (char *)salt.data,
757                                     salt.length);
758         smb_krb5_free_data_contents(io->smb_krb5_context->krb5_context, &salt);
759         if (!io->g.salt) {
760                 return ldb_oom(ldb);
761         }
762         /* now use the talloced copy of the salt */
763         salt.data       = discard_const(io->g.salt);
764         salt.length     = strlen(io->g.salt);
765
766         /*
767          * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of
768          * the salt and the cleartext password
769          */
770         krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
771                                                    NULL,
772                                                    &salt,
773                                                    &cleartext_data,
774                                                    ENCTYPE_AES256_CTS_HMAC_SHA1_96,
775                                                    &key);
776         if (krb5_ret) {
777                 ldb_asprintf_errstring(ldb,
778                                        "setup_kerberos_keys: "
779                                        "generation of a aes256-cts-hmac-sha1-96 key failed: %s",
780                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
781                                                                   krb5_ret, io->ac));
782                 return LDB_ERR_OPERATIONS_ERROR;
783         }
784         io->g.aes_256 = data_blob_talloc(io->ac,
785                                          KRB5_KEY_DATA(&key),
786                                          KRB5_KEY_LENGTH(&key));
787         krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
788         if (!io->g.aes_256.data) {
789                 return ldb_oom(ldb);
790         }
791
792         /*
793          * create ENCTYPE_AES128_CTS_HMAC_SHA1_96 key out of
794          * the salt and the cleartext password
795          */
796         krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
797                                                    NULL,
798                                                    &salt,
799                                                    &cleartext_data,
800                                                    ENCTYPE_AES128_CTS_HMAC_SHA1_96,
801                                                    &key);
802         if (krb5_ret) {
803                 ldb_asprintf_errstring(ldb,
804                                        "setup_kerberos_keys: "
805                                        "generation of a aes128-cts-hmac-sha1-96 key failed: %s",
806                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
807                                                                   krb5_ret, io->ac));
808                 return LDB_ERR_OPERATIONS_ERROR;
809         }
810         io->g.aes_128 = data_blob_talloc(io->ac,
811                                          KRB5_KEY_DATA(&key),
812                                          KRB5_KEY_LENGTH(&key));
813         krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
814         if (!io->g.aes_128.data) {
815                 return ldb_oom(ldb);
816         }
817
818         /*
819          * create ENCTYPE_DES_CBC_MD5 key out of
820          * the salt and the cleartext password
821          */
822         krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
823                                                    NULL,
824                                                    &salt,
825                                                    &cleartext_data,
826                                                    ENCTYPE_DES_CBC_MD5,
827                                                    &key);
828         if (krb5_ret) {
829                 ldb_asprintf_errstring(ldb,
830                                        "setup_kerberos_keys: "
831                                        "generation of a des-cbc-md5 key failed: %s",
832                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
833                                                                   krb5_ret, io->ac));
834                 return LDB_ERR_OPERATIONS_ERROR;
835         }
836         io->g.des_md5 = data_blob_talloc(io->ac,
837                                          KRB5_KEY_DATA(&key),
838                                          KRB5_KEY_LENGTH(&key));
839         krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
840         if (!io->g.des_md5.data) {
841                 return ldb_oom(ldb);
842         }
843
844         /*
845          * create ENCTYPE_DES_CBC_CRC key out of
846          * the salt and the cleartext password
847          */
848         krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
849                                                    NULL,
850                                                    &salt,
851                                                    &cleartext_data,
852                                                    ENCTYPE_DES_CBC_CRC,
853                                                    &key);
854         if (krb5_ret) {
855                 ldb_asprintf_errstring(ldb,
856                                        "setup_kerberos_keys: "
857                                        "generation of a des-cbc-crc key failed: %s",
858                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
859                                                                   krb5_ret, io->ac));
860                 return LDB_ERR_OPERATIONS_ERROR;
861         }
862         io->g.des_crc = data_blob_talloc(io->ac,
863                                          KRB5_KEY_DATA(&key),
864                                          KRB5_KEY_LENGTH(&key));
865         krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
866         if (!io->g.des_crc.data) {
867                 return ldb_oom(ldb);
868         }
869
870         return LDB_SUCCESS;
871 }
872
873 static int setup_primary_kerberos(struct setup_password_fields_io *io,
874                                   const struct supplementalCredentialsBlob *old_scb,
875                                   struct package_PrimaryKerberosBlob *pkb)
876 {
877         struct ldb_context *ldb;
878         struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3;
879         struct supplementalCredentialsPackage *old_scp = NULL;
880         struct package_PrimaryKerberosBlob _old_pkb;
881         struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL;
882         uint32_t i;
883         enum ndr_err_code ndr_err;
884
885         ldb = ldb_module_get_ctx(io->ac->module);
886
887         /*
888          * prepare generation of keys
889          *
890          * ENCTYPE_DES_CBC_MD5
891          * ENCTYPE_DES_CBC_CRC
892          */
893         pkb->version            = 3;
894         pkb3->salt.string       = io->g.salt;
895         pkb3->num_keys          = 2;
896         pkb3->keys              = talloc_array(io->ac,
897                                                struct package_PrimaryKerberosKey3,
898                                                pkb3->num_keys);
899         if (!pkb3->keys) {
900                 return ldb_oom(ldb);
901         }
902
903         pkb3->keys[0].keytype   = ENCTYPE_DES_CBC_MD5;
904         pkb3->keys[0].value     = &io->g.des_md5;
905         pkb3->keys[1].keytype   = ENCTYPE_DES_CBC_CRC;
906         pkb3->keys[1].value     = &io->g.des_crc;
907
908         /* initialize the old keys to zero */
909         pkb3->num_old_keys      = 0;
910         pkb3->old_keys          = NULL;
911
912         /* if there're no old keys, then we're done */
913         if (!old_scb) {
914                 return LDB_SUCCESS;
915         }
916
917         for (i=0; i < old_scb->sub.num_packages; i++) {
918                 if (strcmp("Primary:Kerberos", old_scb->sub.packages[i].name) != 0) {
919                         continue;
920                 }
921
922                 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
923                         continue;
924                 }
925
926                 old_scp = &old_scb->sub.packages[i];
927                 break;
928         }
929         /* Primary:Kerberos element of supplementalCredentials */
930         if (old_scp) {
931                 DATA_BLOB blob;
932
933                 blob = strhex_to_data_blob(io->ac, old_scp->data);
934                 if (!blob.data) {
935                         return ldb_oom(ldb);
936                 }
937
938                 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
939                 ndr_err = ndr_pull_struct_blob(&blob, io->ac, &_old_pkb,
940                                                (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
941                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
942                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
943                         ldb_asprintf_errstring(ldb,
944                                                "setup_primary_kerberos: "
945                                                "failed to pull old package_PrimaryKerberosBlob: %s",
946                                                nt_errstr(status));
947                         return LDB_ERR_OPERATIONS_ERROR;
948                 }
949
950                 if (_old_pkb.version != 3) {
951                         ldb_asprintf_errstring(ldb,
952                                                "setup_primary_kerberos: "
953                                                "package_PrimaryKerberosBlob version[%u] expected[3]",
954                                                _old_pkb.version);
955                         return LDB_ERR_OPERATIONS_ERROR;
956                 }
957
958                 old_pkb3 = &_old_pkb.ctr.ctr3;
959         }
960
961         /* if we didn't found the old keys we're done */
962         if (!old_pkb3) {
963                 return LDB_SUCCESS;
964         }
965
966         /* fill in the old keys */
967         pkb3->num_old_keys      = old_pkb3->num_keys;
968         pkb3->old_keys          = old_pkb3->keys;
969
970         return LDB_SUCCESS;
971 }
972
973 static int setup_primary_kerberos_newer(struct setup_password_fields_io *io,
974                                         const struct supplementalCredentialsBlob *old_scb,
975                                         struct package_PrimaryKerberosBlob *pkb)
976 {
977         struct ldb_context *ldb;
978         struct package_PrimaryKerberosCtr4 *pkb4 = &pkb->ctr.ctr4;
979         struct supplementalCredentialsPackage *old_scp = NULL;
980         struct package_PrimaryKerberosBlob _old_pkb;
981         struct package_PrimaryKerberosCtr4 *old_pkb4 = NULL;
982         uint32_t i;
983         enum ndr_err_code ndr_err;
984
985         ldb = ldb_module_get_ctx(io->ac->module);
986
987         /*
988          * prepare generation of keys
989          *
990          * ENCTYPE_AES256_CTS_HMAC_SHA1_96
991          * ENCTYPE_AES128_CTS_HMAC_SHA1_96
992          * ENCTYPE_DES_CBC_MD5
993          * ENCTYPE_DES_CBC_CRC
994          */
995         pkb->version                    = 4;
996         pkb4->salt.string               = io->g.salt;
997         pkb4->default_iteration_count   = 4096;
998         pkb4->num_keys                  = 4;
999
1000         pkb4->keys = talloc_array(io->ac,
1001                                   struct package_PrimaryKerberosKey4,
1002                                   pkb4->num_keys);
1003         if (!pkb4->keys) {
1004                 return ldb_oom(ldb);
1005         }
1006
1007         pkb4->keys[0].iteration_count   = 4096;
1008         pkb4->keys[0].keytype           = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
1009         pkb4->keys[0].value             = &io->g.aes_256;
1010         pkb4->keys[1].iteration_count   = 4096;
1011         pkb4->keys[1].keytype           = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
1012         pkb4->keys[1].value             = &io->g.aes_128;
1013         pkb4->keys[2].iteration_count   = 4096;
1014         pkb4->keys[2].keytype           = ENCTYPE_DES_CBC_MD5;
1015         pkb4->keys[2].value             = &io->g.des_md5;
1016         pkb4->keys[3].iteration_count   = 4096;
1017         pkb4->keys[3].keytype           = ENCTYPE_DES_CBC_CRC;
1018         pkb4->keys[3].value             = &io->g.des_crc;
1019
1020         /* initialize the old keys to zero */
1021         pkb4->num_old_keys      = 0;
1022         pkb4->old_keys          = NULL;
1023         pkb4->num_older_keys    = 0;
1024         pkb4->older_keys        = NULL;
1025
1026         /* if there're no old keys, then we're done */
1027         if (!old_scb) {
1028                 return LDB_SUCCESS;
1029         }
1030
1031         for (i=0; i < old_scb->sub.num_packages; i++) {
1032                 if (strcmp("Primary:Kerberos-Newer-Keys", old_scb->sub.packages[i].name) != 0) {
1033                         continue;
1034                 }
1035
1036                 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
1037                         continue;
1038                 }
1039
1040                 old_scp = &old_scb->sub.packages[i];
1041                 break;
1042         }
1043         /* Primary:Kerberos-Newer-Keys element of supplementalCredentials */
1044         if (old_scp) {
1045                 DATA_BLOB blob;
1046
1047                 blob = strhex_to_data_blob(io->ac, old_scp->data);
1048                 if (!blob.data) {
1049                         return ldb_oom(ldb);
1050                 }
1051
1052                 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
1053                 ndr_err = ndr_pull_struct_blob(&blob, io->ac,
1054                                                &_old_pkb,
1055                                                (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
1056                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1057                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1058                         ldb_asprintf_errstring(ldb,
1059                                                "setup_primary_kerberos_newer: "
1060                                                "failed to pull old package_PrimaryKerberosBlob: %s",
1061                                                nt_errstr(status));
1062                         return LDB_ERR_OPERATIONS_ERROR;
1063                 }
1064
1065                 if (_old_pkb.version != 4) {
1066                         ldb_asprintf_errstring(ldb,
1067                                                "setup_primary_kerberos_newer: "
1068                                                "package_PrimaryKerberosBlob version[%u] expected[4]",
1069                                                _old_pkb.version);
1070                         return LDB_ERR_OPERATIONS_ERROR;
1071                 }
1072
1073                 old_pkb4 = &_old_pkb.ctr.ctr4;
1074         }
1075
1076         /* if we didn't found the old keys we're done */
1077         if (!old_pkb4) {
1078                 return LDB_SUCCESS;
1079         }
1080
1081         /* fill in the old keys */
1082         pkb4->num_old_keys      = old_pkb4->num_keys;
1083         pkb4->old_keys          = old_pkb4->keys;
1084         pkb4->num_older_keys    = old_pkb4->num_old_keys;
1085         pkb4->older_keys        = old_pkb4->old_keys;
1086
1087         return LDB_SUCCESS;
1088 }
1089
1090 static int setup_primary_wdigest(struct setup_password_fields_io *io,
1091                                  const struct supplementalCredentialsBlob *old_scb,
1092                                  struct package_PrimaryWDigestBlob *pdb)
1093 {
1094         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1095         DATA_BLOB sAMAccountName;
1096         DATA_BLOB sAMAccountName_l;
1097         DATA_BLOB sAMAccountName_u;
1098         const char *user_principal_name = io->u.user_principal_name;
1099         DATA_BLOB userPrincipalName;
1100         DATA_BLOB userPrincipalName_l;
1101         DATA_BLOB userPrincipalName_u;
1102         DATA_BLOB netbios_domain;
1103         DATA_BLOB netbios_domain_l;
1104         DATA_BLOB netbios_domain_u;
1105         DATA_BLOB dns_domain;
1106         DATA_BLOB dns_domain_l;
1107         DATA_BLOB dns_domain_u;
1108         DATA_BLOB digest;
1109         DATA_BLOB delim;
1110         DATA_BLOB backslash;
1111         uint8_t i;
1112         struct {
1113                 DATA_BLOB *user;
1114                 DATA_BLOB *realm;
1115                 DATA_BLOB *nt4dom;
1116         } wdigest[] = {
1117         /*
1118          * See
1119          * http://technet2.microsoft.com/WindowsServer/en/library/717b450c-f4a0-4cc9-86f4-cc0633aae5f91033.mspx?mfr=true
1120          * for what precalculated hashes are supposed to be stored...
1121          *
1122          * I can't reproduce all values which should contain "Digest" as realm,
1123          * am I doing something wrong or is w2k3 just broken...?
1124          *
1125          * W2K3 fills in following for a user:
1126          *
1127          * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1128          * sAMAccountName: NewUser2Sam
1129          * userPrincipalName: NewUser2Princ@sub1.w2k3.vmnet1.vm.base
1130          *
1131          * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1132          * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1133          * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1134          * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1135          * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1136          * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1137          * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1138          * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1139          * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1140          * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1141          * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1142          * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1143          * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1144          * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1145          * 221c55284451ae9b3aacaa2a3c86f10f => NewUser2Princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1146          * 74e1be668853d4324d38c07e2acfb8ea => (w2k3 has a bug here!) newuser2princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1147          * e1e244ab7f098e3ae1761be7f9229bbb => NEWUSER2PRINC@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1148          * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1149          * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1150          * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1151          * 31dc704d3640335b2123d4ee28aa1f11 => ??? changes with NewUser2Sam => NewUser1Sam
1152          * 36349f5cecd07320fb3bb0e119230c43 => ??? changes with NewUser2Sam => NewUser1Sam
1153          * 12adf019d037fb535c01fd0608e78d9d => ??? changes with NewUser2Sam => NewUser1Sam
1154          * 6feecf8e724906f3ee1105819c5105a1 => ??? changes with NewUser2Princ => NewUser1Princ
1155          * 6c6911f3de6333422640221b9c51ff1f => ??? changes with NewUser2Princ => NewUser1Princ
1156          * 4b279877e742895f9348ac67a8de2f69 => ??? changes with NewUser2Princ => NewUser1Princ
1157          * db0c6bff069513e3ebb9870d29b57490 => ??? changes with NewUser2Sam => NewUser1Sam
1158          * 45072621e56b1c113a4e04a8ff68cd0e => ??? changes with NewUser2Sam => NewUser1Sam
1159          * 11d1220abc44a9c10cf91ef4a9c1de02 => ??? changes with NewUser2Sam => NewUser1Sam
1160          *
1161          * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1162          * sAMAccountName: NewUser2Sam
1163          *
1164          * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1165          * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1166          * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1167          * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1168          * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1169          * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1170          * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1171          * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1172          * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1173          * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1174          * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1175          * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1176          * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1177          * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1178          * 8a140d30b6f0a5912735dc1e3bc993b4 => NewUser2Sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1179          * 86d95b2faae6cae4ec261e7fbaccf093 => (here w2k3 is correct) newuser2sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1180          * dfeff1493110220efcdfc6362e5f5450 => NEWUSER2SAM@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1181          * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1182          * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1183          * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1184          * 31dc704d3640335b2123d4ee28aa1f11 => ???M1   changes with NewUser2Sam => NewUser1Sam
1185          * 36349f5cecd07320fb3bb0e119230c43 => ???M1.L changes with newuser2sam => newuser1sam
1186          * 12adf019d037fb535c01fd0608e78d9d => ???M1.U changes with NEWUSER2SAM => NEWUSER1SAM
1187          * 569b4533f2d9e580211dd040e5e360a8 => ???M2   changes with NewUser2Princ => NewUser1Princ
1188          * 52528bddf310a587c5d7e6a9ae2cbb20 => ???M2.L changes with newuser2princ => newuser1princ
1189          * 4f629a4f0361289ca4255ab0f658fcd5 => ???M3 changes with NewUser2Princ => NewUser1Princ (doesn't depend on case of userPrincipal )
1190          * db0c6bff069513e3ebb9870d29b57490 => ???M4 changes with NewUser2Sam => NewUser1Sam
1191          * 45072621e56b1c113a4e04a8ff68cd0e => ???M5 changes with NewUser2Sam => NewUser1Sam (doesn't depend on case of sAMAccountName)
1192          * 11d1220abc44a9c10cf91ef4a9c1de02 => ???M4.U changes with NEWUSER2SAM => NEWUSER1SAM
1193          */
1194
1195         /*
1196          * sAMAccountName, netbios_domain
1197          */
1198                 {
1199                 .user   = &sAMAccountName,
1200                 .realm  = &netbios_domain,
1201                 },
1202                 {
1203                 .user   = &sAMAccountName_l,
1204                 .realm  = &netbios_domain_l,
1205                 },
1206                 {
1207                 .user   = &sAMAccountName_u,
1208                 .realm  = &netbios_domain_u,
1209                 },
1210                 {
1211                 .user   = &sAMAccountName,
1212                 .realm  = &netbios_domain_u,
1213                 },
1214                 {
1215                 .user   = &sAMAccountName,
1216                 .realm  = &netbios_domain_l,
1217                 },
1218                 {
1219                 .user   = &sAMAccountName_u,
1220                 .realm  = &netbios_domain_l,
1221                 },
1222                 {
1223                 .user   = &sAMAccountName_l,
1224                 .realm  = &netbios_domain_u,
1225                 },
1226         /* 
1227          * sAMAccountName, dns_domain
1228          */
1229                 {
1230                 .user   = &sAMAccountName,
1231                 .realm  = &dns_domain,
1232                 },
1233                 {
1234                 .user   = &sAMAccountName_l,
1235                 .realm  = &dns_domain_l,
1236                 },
1237                 {
1238                 .user   = &sAMAccountName_u,
1239                 .realm  = &dns_domain_u,
1240                 },
1241                 {
1242                 .user   = &sAMAccountName,
1243                 .realm  = &dns_domain_u,
1244                 },
1245                 {
1246                 .user   = &sAMAccountName,
1247                 .realm  = &dns_domain_l,
1248                 },
1249                 {
1250                 .user   = &sAMAccountName_u,
1251                 .realm  = &dns_domain_l,
1252                 },
1253                 {
1254                 .user   = &sAMAccountName_l,
1255                 .realm  = &dns_domain_u,
1256                 },
1257         /* 
1258          * userPrincipalName, no realm
1259          */
1260                 {
1261                 .user   = &userPrincipalName,
1262                 },
1263                 {
1264                 /* 
1265                  * NOTE: w2k3 messes this up, if the user has a real userPrincipalName,
1266                  *       the fallback to the sAMAccountName based userPrincipalName is correct
1267                  */
1268                 .user   = &userPrincipalName_l,
1269                 },
1270                 {
1271                 .user   = &userPrincipalName_u,
1272                 },
1273         /* 
1274          * nt4dom\sAMAccountName, no realm
1275          */
1276                 {
1277                 .user   = &sAMAccountName,
1278                 .nt4dom = &netbios_domain
1279                 },
1280                 {
1281                 .user   = &sAMAccountName_l,
1282                 .nt4dom = &netbios_domain_l
1283                 },
1284                 {
1285                 .user   = &sAMAccountName_u,
1286                 .nt4dom = &netbios_domain_u
1287                 },
1288
1289         /*
1290          * the following ones are guessed depending on the technet2 article
1291          * but not reproducable on a w2k3 server
1292          */
1293         /* sAMAccountName with "Digest" realm */
1294                 {
1295                 .user   = &sAMAccountName,
1296                 .realm  = &digest
1297                 },
1298                 {
1299                 .user   = &sAMAccountName_l,
1300                 .realm  = &digest
1301                 },
1302                 {
1303                 .user   = &sAMAccountName_u,
1304                 .realm  = &digest
1305                 },
1306         /* userPrincipalName with "Digest" realm */
1307                 {
1308                 .user   = &userPrincipalName,
1309                 .realm  = &digest
1310                 },
1311                 {
1312                 .user   = &userPrincipalName_l,
1313                 .realm  = &digest
1314                 },
1315                 {
1316                 .user   = &userPrincipalName_u,
1317                 .realm  = &digest
1318                 },
1319         /* nt4dom\\sAMAccountName with "Digest" realm */
1320                 {
1321                 .user   = &sAMAccountName,
1322                 .nt4dom = &netbios_domain,
1323                 .realm  = &digest
1324                 },
1325                 {
1326                 .user   = &sAMAccountName_l,
1327                 .nt4dom = &netbios_domain_l,
1328                 .realm  = &digest
1329                 },
1330                 {
1331                 .user   = &sAMAccountName_u,
1332                 .nt4dom = &netbios_domain_u,
1333                 .realm  = &digest
1334                 },
1335         };
1336
1337         /* prepare DATA_BLOB's used in the combinations array */
1338         sAMAccountName          = data_blob_string_const(io->u.sAMAccountName);
1339         sAMAccountName_l        = data_blob_string_const(strlower_talloc(io->ac, io->u.sAMAccountName));
1340         if (!sAMAccountName_l.data) {
1341                 return ldb_oom(ldb);
1342         }
1343         sAMAccountName_u        = data_blob_string_const(strupper_talloc(io->ac, io->u.sAMAccountName));
1344         if (!sAMAccountName_u.data) {
1345                 return ldb_oom(ldb);
1346         }
1347
1348         /* if the user doesn't have a userPrincipalName, create one (with lower case realm) */
1349         if (!user_principal_name) {
1350                 user_principal_name = talloc_asprintf(io->ac, "%s@%s",
1351                                                       io->u.sAMAccountName,
1352                                                       io->ac->status->domain_data.dns_domain);
1353                 if (!user_principal_name) {
1354                         return ldb_oom(ldb);
1355                 }       
1356         }
1357         userPrincipalName       = data_blob_string_const(user_principal_name);
1358         userPrincipalName_l     = data_blob_string_const(strlower_talloc(io->ac, user_principal_name));
1359         if (!userPrincipalName_l.data) {
1360                 return ldb_oom(ldb);
1361         }
1362         userPrincipalName_u     = data_blob_string_const(strupper_talloc(io->ac, user_principal_name));
1363         if (!userPrincipalName_u.data) {
1364                 return ldb_oom(ldb);
1365         }
1366
1367         netbios_domain          = data_blob_string_const(io->ac->status->domain_data.netbios_domain);
1368         netbios_domain_l        = data_blob_string_const(strlower_talloc(io->ac,
1369                                                                          io->ac->status->domain_data.netbios_domain));
1370         if (!netbios_domain_l.data) {
1371                 return ldb_oom(ldb);
1372         }
1373         netbios_domain_u        = data_blob_string_const(strupper_talloc(io->ac,
1374                                                                          io->ac->status->domain_data.netbios_domain));
1375         if (!netbios_domain_u.data) {
1376                 return ldb_oom(ldb);
1377         }
1378
1379         dns_domain              = data_blob_string_const(io->ac->status->domain_data.dns_domain);
1380         dns_domain_l            = data_blob_string_const(io->ac->status->domain_data.dns_domain);
1381         dns_domain_u            = data_blob_string_const(io->ac->status->domain_data.realm);
1382
1383         digest                  = data_blob_string_const("Digest");
1384
1385         delim                   = data_blob_string_const(":");
1386         backslash               = data_blob_string_const("\\");
1387
1388         pdb->num_hashes = ARRAY_SIZE(wdigest);
1389         pdb->hashes     = talloc_array(io->ac, struct package_PrimaryWDigestHash,
1390                                        pdb->num_hashes);
1391         if (!pdb->hashes) {
1392                 return ldb_oom(ldb);
1393         }
1394
1395         for (i=0; i < ARRAY_SIZE(wdigest); i++) {
1396                 MD5_CTX md5;
1397                 MD5Init(&md5);
1398                 if (wdigest[i].nt4dom) {
1399                         MD5Update(&md5, wdigest[i].nt4dom->data, wdigest[i].nt4dom->length);
1400                         MD5Update(&md5, backslash.data, backslash.length);
1401                 }
1402                 MD5Update(&md5, wdigest[i].user->data, wdigest[i].user->length);
1403                 MD5Update(&md5, delim.data, delim.length);
1404                 if (wdigest[i].realm) {
1405                         MD5Update(&md5, wdigest[i].realm->data, wdigest[i].realm->length);
1406                 }
1407                 MD5Update(&md5, delim.data, delim.length);
1408                 MD5Update(&md5, io->n.cleartext_utf8->data, io->n.cleartext_utf8->length);
1409                 MD5Final(pdb->hashes[i].hash, &md5);
1410         }
1411
1412         return LDB_SUCCESS;
1413 }
1414
1415 static int setup_primary_samba_gpg(struct setup_password_fields_io *io,
1416                                    struct package_PrimarySambaGPGBlob *pgb)
1417 {
1418         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1419 #ifdef ENABLE_GPGME
1420         gpgme_error_t gret;
1421         gpgme_ctx_t ctx = NULL;
1422         size_t num_keys = str_list_length(io->ac->gpg_key_ids);
1423         gpgme_key_t keys[num_keys+1];
1424         size_t ki = 0;
1425         size_t kr = 0;
1426         gpgme_data_t plain_data = NULL;
1427         gpgme_data_t crypt_data = NULL;
1428         size_t crypt_length = 0;
1429         char *crypt_mem = NULL;
1430
1431         gret = gpgme_new(&ctx);
1432         if (gret != GPG_ERR_NO_ERROR) {
1433                 ldb_debug(ldb, LDB_DEBUG_ERROR,
1434                           "%s:%s: gret[%u] %s\n",
1435                           __location__, __func__,
1436                           gret, gpgme_strerror(gret));
1437                 return ldb_module_operr(io->ac->module);
1438         }
1439
1440         gpgme_set_armor(ctx, 1);
1441
1442         gret = gpgme_data_new_from_mem(&plain_data,
1443                                        (const char *)io->n.cleartext_utf16->data,
1444                                        io->n.cleartext_utf16->length,
1445                                        0 /* no copy */);
1446         if (gret != GPG_ERR_NO_ERROR) {
1447                 ldb_debug(ldb, LDB_DEBUG_ERROR,
1448                           "%s:%s: gret[%u] %s\n",
1449                           __location__, __func__,
1450                           gret, gpgme_strerror(gret));
1451                 gpgme_release(ctx);
1452                 return ldb_module_operr(io->ac->module);
1453         }
1454         gret = gpgme_data_new(&crypt_data);
1455         if (gret != GPG_ERR_NO_ERROR) {
1456                 ldb_debug(ldb, LDB_DEBUG_ERROR,
1457                           "%s:%s: gret[%u] %s\n",
1458                           __location__, __func__,
1459                           gret, gpgme_strerror(gret));
1460                 gpgme_data_release(plain_data);
1461                 gpgme_release(ctx);
1462                 return ldb_module_operr(io->ac->module);
1463         }
1464
1465         for (ki = 0; ki < num_keys; ki++) {
1466                 const char *key_id = io->ac->gpg_key_ids[ki];
1467                 size_t len = strlen(key_id);
1468
1469                 keys[ki] = NULL;
1470
1471                 if (len < 16) {
1472                         ldb_debug(ldb, LDB_DEBUG_FATAL,
1473                                   "%s:%s: ki[%zu] key_id[%s] strlen < 16, "
1474                                   "please specifiy at least the 64bit key id\n",
1475                                   __location__, __func__,
1476                                   ki, key_id);
1477                         for (kr = 0; keys[kr] != NULL; kr++) {
1478                                 gpgme_key_release(keys[kr]);
1479                         }
1480                         gpgme_data_release(crypt_data);
1481                         gpgme_data_release(plain_data);
1482                         gpgme_release(ctx);
1483                         return ldb_module_operr(io->ac->module);
1484                 }
1485
1486                 gret = gpgme_get_key(ctx, key_id, &keys[ki], 0 /* public key */);
1487                 if (gret != GPG_ERR_NO_ERROR) {
1488                         keys[ki] = NULL;
1489                         ldb_debug(ldb, LDB_DEBUG_ERROR,
1490                                   "%s:%s: ki[%zu] key_id[%s] gret[%u] %s\n",
1491                                   __location__, __func__,
1492                                   ki, key_id,
1493                                   gret, gpgme_strerror(gret));
1494                         for (kr = 0; keys[kr] != NULL; kr++) {
1495                                 gpgme_key_release(keys[kr]);
1496                         }
1497                         gpgme_data_release(crypt_data);
1498                         gpgme_data_release(plain_data);
1499                         gpgme_release(ctx);
1500                         return ldb_module_operr(io->ac->module);
1501                 }
1502         }
1503         keys[ki] = NULL;
1504
1505         gret = gpgme_op_encrypt(ctx, keys,
1506                                 GPGME_ENCRYPT_ALWAYS_TRUST,
1507                                 plain_data, crypt_data);
1508         gpgme_data_release(plain_data);
1509         plain_data = NULL;
1510         for (kr = 0; keys[kr] != NULL; kr++) {
1511                 gpgme_key_release(keys[kr]);
1512                 keys[kr] = NULL;
1513         }
1514         gpgme_release(ctx);
1515         ctx = NULL;
1516         if (gret != GPG_ERR_NO_ERROR) {
1517                 ldb_debug(ldb, LDB_DEBUG_ERROR,
1518                           "%s:%s: gret[%u] %s\n",
1519                           __location__, __func__,
1520                           gret, gpgme_strerror(gret));
1521                 gpgme_data_release(crypt_data);
1522                 return ldb_module_operr(io->ac->module);
1523         }
1524
1525         crypt_mem = gpgme_data_release_and_get_mem(crypt_data, &crypt_length);
1526         crypt_data = NULL;
1527         if (crypt_mem == NULL) {
1528                 return ldb_module_oom(io->ac->module);
1529         }
1530
1531         pgb->gpg_blob = data_blob_talloc(io->ac,
1532                                          (const uint8_t *)crypt_mem,
1533                                          crypt_length);
1534         gpgme_free(crypt_mem);
1535         crypt_mem = NULL;
1536         crypt_length = 0;
1537         if (pgb->gpg_blob.data == NULL) {
1538                 return ldb_module_oom(io->ac->module);
1539         }
1540
1541         return LDB_SUCCESS;
1542 #else /* ENABLE_GPGME */
1543         ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1544                       "You configured 'password hash gpg key ids', "
1545                       "but GPGME support is missing. (%s:%d)",
1546                       __FILE__, __LINE__);
1547         return LDB_ERR_UNWILLING_TO_PERFORM;
1548 #endif /* else ENABLE_GPGME */
1549 }
1550
1551 static int setup_supplemental_field(struct setup_password_fields_io *io)
1552 {
1553         struct ldb_context *ldb;
1554         struct supplementalCredentialsBlob scb;
1555         struct supplementalCredentialsBlob *old_scb = NULL;
1556         /* Packages + (Kerberos-Newer-Keys, Kerberos, WDigest, CLEARTEXT, SambaGPG) */
1557         uint32_t num_names = 0;
1558         const char *names[1+5];
1559         uint32_t num_packages = 0;
1560         struct supplementalCredentialsPackage packages[1+5];
1561         /* Packages */
1562         struct supplementalCredentialsPackage *pp = NULL;
1563         struct package_PackagesBlob pb;
1564         DATA_BLOB pb_blob;
1565         char *pb_hexstr;
1566         /* Primary:Kerberos-Newer-Keys */
1567         const char **nkn = NULL;
1568         struct supplementalCredentialsPackage *pkn = NULL;
1569         struct package_PrimaryKerberosBlob pknb;
1570         DATA_BLOB pknb_blob;
1571         char *pknb_hexstr;
1572         /* Primary:Kerberos */
1573         const char **nk = NULL;
1574         struct supplementalCredentialsPackage *pk = NULL;
1575         struct package_PrimaryKerberosBlob pkb;
1576         DATA_BLOB pkb_blob;
1577         char *pkb_hexstr;
1578         /* Primary:WDigest */
1579         const char **nd = NULL;
1580         struct supplementalCredentialsPackage *pd = NULL;
1581         struct package_PrimaryWDigestBlob pdb;
1582         DATA_BLOB pdb_blob;
1583         char *pdb_hexstr;
1584         /* Primary:CLEARTEXT */
1585         const char **nc = NULL;
1586         struct supplementalCredentialsPackage *pc = NULL;
1587         struct package_PrimaryCLEARTEXTBlob pcb;
1588         DATA_BLOB pcb_blob;
1589         char *pcb_hexstr;
1590         /* Primary:SambaGPG */
1591         const char **ng = NULL;
1592         struct supplementalCredentialsPackage *pg = NULL;
1593         struct package_PrimarySambaGPGBlob pgb;
1594         DATA_BLOB pgb_blob;
1595         char *pgb_hexstr;
1596         int ret;
1597         enum ndr_err_code ndr_err;
1598         uint8_t zero16[16];
1599         bool do_newer_keys = false;
1600         bool do_cleartext = false;
1601         bool do_samba_gpg = false;
1602
1603         ZERO_STRUCT(zero16);
1604         ZERO_STRUCT(names);
1605         ZERO_STRUCT(packages);
1606
1607         ldb = ldb_module_get_ctx(io->ac->module);
1608
1609         if (!io->n.cleartext_utf8) {
1610                 /* 
1611                  * when we don't have a cleartext password
1612                  * we can't setup a supplementalCredential value
1613                  */
1614                 return LDB_SUCCESS;
1615         }
1616
1617         /* if there's an old supplementaCredentials blob then use it */
1618         if (io->o.supplemental) {
1619                 if (io->o.scb.sub.signature == SUPPLEMENTAL_CREDENTIALS_SIGNATURE) {
1620                         old_scb = &io->o.scb;
1621                 } else {
1622                         ldb_debug(ldb, LDB_DEBUG_ERROR,
1623                                   "setup_supplemental_field: "
1624                                   "supplementalCredentialsBlob "
1625                                   "signature[0x%04X] expected[0x%04X]",
1626                                   io->o.scb.sub.signature,
1627                                   SUPPLEMENTAL_CREDENTIALS_SIGNATURE);
1628                 }
1629         }
1630         /* Per MS-SAMR 3.1.1.8.11.6 we create AES keys if our domain functionality level is 2008 or higher */
1631         do_newer_keys = (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2008);
1632
1633         if (io->ac->status->domain_data.store_cleartext &&
1634             (io->u.userAccountControl & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) {
1635                 do_cleartext = true;
1636         }
1637
1638         if (io->ac->gpg_key_ids != NULL) {
1639                 do_samba_gpg = true;
1640         }
1641
1642         /*
1643          * The ordering is this
1644          *
1645          * Primary:Kerberos-Newer-Keys (optional)
1646          * Primary:Kerberos
1647          * Primary:WDigest
1648          * Primary:CLEARTEXT (optional)
1649          * Primary:SambaGPG (optional)
1650          *
1651          * And the 'Packages' package is insert before the last
1652          * other package.
1653          *
1654          * Note: it's important that Primary:SambaGPG is added as
1655          * the last element. This is the indication that it matches
1656          * the current password. When a password change happens on
1657          * a Windows DC, it will keep the old Primary:SambaGPG value,
1658          * but as the first element.
1659          */
1660         if (do_newer_keys) {
1661                 /* Primary:Kerberos-Newer-Keys */
1662                 nkn = &names[num_names++];
1663                 pkn = &packages[num_packages++];
1664         }
1665
1666         /* Primary:Kerberos */
1667         nk = &names[num_names++];
1668         pk = &packages[num_packages++];
1669
1670         if (!do_cleartext && !do_samba_gpg) {
1671                 /* Packages */
1672                 pp = &packages[num_packages++];
1673         }
1674
1675         /* Primary:WDigest */
1676         nd = &names[num_names++];
1677         pd = &packages[num_packages++];
1678
1679         if (do_cleartext) {
1680                 if (!do_samba_gpg) {
1681                         /* Packages */
1682                         pp = &packages[num_packages++];
1683                 }
1684
1685                 /* Primary:CLEARTEXT */
1686                 nc = &names[num_names++];
1687                 pc = &packages[num_packages++];
1688         }
1689
1690         if (do_samba_gpg) {
1691                 /* Packages */
1692                 pp = &packages[num_packages++];
1693
1694                 /* Primary:SambaGPG */
1695                 ng = &names[num_names++];
1696                 pg = &packages[num_packages++];
1697         }
1698
1699         if (pkn) {
1700                 /*
1701                  * setup 'Primary:Kerberos-Newer-Keys' element
1702                  */
1703                 *nkn = "Kerberos-Newer-Keys";
1704
1705                 ret = setup_primary_kerberos_newer(io, old_scb, &pknb);
1706                 if (ret != LDB_SUCCESS) {
1707                         return ret;
1708                 }
1709
1710                 ndr_err = ndr_push_struct_blob(&pknb_blob, io->ac,
1711                                                &pknb,
1712                                                (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
1713                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1714                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1715                         ldb_asprintf_errstring(ldb,
1716                                                "setup_supplemental_field: "
1717                                                "failed to push package_PrimaryKerberosNeverBlob: %s",
1718                                                nt_errstr(status));
1719                         return LDB_ERR_OPERATIONS_ERROR;
1720                 }
1721                 pknb_hexstr = data_blob_hex_string_upper(io->ac, &pknb_blob);
1722                 if (!pknb_hexstr) {
1723                         return ldb_oom(ldb);
1724                 }
1725                 pkn->name       = "Primary:Kerberos-Newer-Keys";
1726                 pkn->reserved   = 1;
1727                 pkn->data       = pknb_hexstr;
1728         }
1729
1730         /*
1731          * setup 'Primary:Kerberos' element
1732          */
1733         *nk = "Kerberos";
1734
1735         ret = setup_primary_kerberos(io, old_scb, &pkb);
1736         if (ret != LDB_SUCCESS) {
1737                 return ret;
1738         }
1739
1740         ndr_err = ndr_push_struct_blob(&pkb_blob, io->ac, 
1741                                        &pkb,
1742                                        (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
1743         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1744                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1745                 ldb_asprintf_errstring(ldb,
1746                                        "setup_supplemental_field: "
1747                                        "failed to push package_PrimaryKerberosBlob: %s",
1748                                        nt_errstr(status));
1749                 return LDB_ERR_OPERATIONS_ERROR;
1750         }
1751         pkb_hexstr = data_blob_hex_string_upper(io->ac, &pkb_blob);
1752         if (!pkb_hexstr) {
1753                 return ldb_oom(ldb);
1754         }
1755         pk->name        = "Primary:Kerberos";
1756         pk->reserved    = 1;
1757         pk->data        = pkb_hexstr;
1758
1759         /*
1760          * setup 'Primary:WDigest' element
1761          */
1762         *nd = "WDigest";
1763
1764         ret = setup_primary_wdigest(io, old_scb, &pdb);
1765         if (ret != LDB_SUCCESS) {
1766                 return ret;
1767         }
1768
1769         ndr_err = ndr_push_struct_blob(&pdb_blob, io->ac, 
1770                                        &pdb,
1771                                        (ndr_push_flags_fn_t)ndr_push_package_PrimaryWDigestBlob);
1772         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1773                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1774                 ldb_asprintf_errstring(ldb,
1775                                        "setup_supplemental_field: "
1776                                        "failed to push package_PrimaryWDigestBlob: %s",
1777                                        nt_errstr(status));
1778                 return LDB_ERR_OPERATIONS_ERROR;
1779         }
1780         pdb_hexstr = data_blob_hex_string_upper(io->ac, &pdb_blob);
1781         if (!pdb_hexstr) {
1782                 return ldb_oom(ldb);
1783         }
1784         pd->name        = "Primary:WDigest";
1785         pd->reserved    = 1;
1786         pd->data        = pdb_hexstr;
1787
1788         /*
1789          * setup 'Primary:CLEARTEXT' element
1790          */
1791         if (pc) {
1792                 *nc             = "CLEARTEXT";
1793
1794                 pcb.cleartext   = *io->n.cleartext_utf16;
1795
1796                 ndr_err = ndr_push_struct_blob(&pcb_blob, io->ac, 
1797                                                &pcb,
1798                                                (ndr_push_flags_fn_t)ndr_push_package_PrimaryCLEARTEXTBlob);
1799                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1800                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1801                         ldb_asprintf_errstring(ldb,
1802                                                "setup_supplemental_field: "
1803                                                "failed to push package_PrimaryCLEARTEXTBlob: %s",
1804                                                nt_errstr(status));
1805                         return LDB_ERR_OPERATIONS_ERROR;
1806                 }
1807                 pcb_hexstr = data_blob_hex_string_upper(io->ac, &pcb_blob);
1808                 if (!pcb_hexstr) {
1809                         return ldb_oom(ldb);
1810                 }
1811                 pc->name        = "Primary:CLEARTEXT";
1812                 pc->reserved    = 1;
1813                 pc->data        = pcb_hexstr;
1814         }
1815
1816         /*
1817          * setup 'Primary:SambaGPG' element
1818          */
1819         if (pg) {
1820                 *ng             = "SambaGPG";
1821
1822                 ret = setup_primary_samba_gpg(io, &pgb);
1823                 if (ret != LDB_SUCCESS) {
1824                         return ret;
1825                 }
1826
1827                 ndr_err = ndr_push_struct_blob(&pgb_blob, io->ac, &pgb,
1828                         (ndr_push_flags_fn_t)ndr_push_package_PrimarySambaGPGBlob);
1829                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1830                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1831                         ldb_asprintf_errstring(ldb,
1832                                         "setup_supplemental_field: failed to "
1833                                         "push package_PrimarySambaGPGBlob: %s",
1834                                         nt_errstr(status));
1835                         return LDB_ERR_OPERATIONS_ERROR;
1836                 }
1837                 pgb_hexstr = data_blob_hex_string_upper(io->ac, &pgb_blob);
1838                 if (!pgb_hexstr) {
1839                         return ldb_oom(ldb);
1840                 }
1841                 pg->name        = "Primary:SambaGPG";
1842                 pg->reserved    = 1;
1843                 pg->data        = pgb_hexstr;
1844         }
1845
1846         /*
1847          * setup 'Packages' element
1848          */
1849         pb.names = names;
1850         ndr_err = ndr_push_struct_blob(&pb_blob, io->ac, 
1851                                        &pb,
1852                                        (ndr_push_flags_fn_t)ndr_push_package_PackagesBlob);
1853         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1854                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1855                 ldb_asprintf_errstring(ldb,
1856                                        "setup_supplemental_field: "
1857                                        "failed to push package_PackagesBlob: %s",
1858                                        nt_errstr(status));
1859                 return LDB_ERR_OPERATIONS_ERROR;
1860         }
1861         pb_hexstr = data_blob_hex_string_upper(io->ac, &pb_blob);
1862         if (!pb_hexstr) {
1863                 return ldb_oom(ldb);
1864         }
1865         pp->name        = "Packages";
1866         pp->reserved    = 2;
1867         pp->data        = pb_hexstr;
1868
1869         /*
1870          * setup 'supplementalCredentials' value
1871          */
1872         ZERO_STRUCT(scb);
1873         scb.sub.signature       = SUPPLEMENTAL_CREDENTIALS_SIGNATURE;
1874         scb.sub.num_packages    = num_packages;
1875         scb.sub.packages        = packages;
1876
1877         ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac, 
1878                                        &scb,
1879                                        (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
1880         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1881                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1882                 ldb_asprintf_errstring(ldb,
1883                                        "setup_supplemental_field: "
1884                                        "failed to push supplementalCredentialsBlob: %s",
1885                                        nt_errstr(status));
1886                 return LDB_ERR_OPERATIONS_ERROR;
1887         }
1888
1889         return LDB_SUCCESS;
1890 }
1891
1892 static int setup_last_set_field(struct setup_password_fields_io *io)
1893 {
1894         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1895         const struct ldb_message *msg = NULL;
1896         struct timeval tv = { .tv_sec = 0 };
1897         const struct ldb_val *old_val = NULL;
1898         const struct ldb_val *new_val = NULL;
1899         int ret;
1900
1901         switch (io->ac->req->operation) {
1902         case LDB_ADD:
1903                 msg = io->ac->req->op.add.message;
1904                 break;
1905         case LDB_MODIFY:
1906                 msg = io->ac->req->op.mod.message;
1907                 break;
1908         default:
1909                 return LDB_ERR_OPERATIONS_ERROR;
1910                 break;
1911         }
1912
1913         if (io->ac->pwd_last_set_bypass) {
1914                 struct ldb_message_element *el1 = NULL;
1915                 struct ldb_message_element *el2 = NULL;
1916
1917                 if (msg == NULL) {
1918                         return LDB_ERR_CONSTRAINT_VIOLATION;
1919                 }
1920
1921                 el1 = dsdb_get_single_valued_attr(msg, "pwdLastSet",
1922                                                   io->ac->req->operation);
1923                 if (el1 == NULL) {
1924                         return LDB_ERR_CONSTRAINT_VIOLATION;
1925                 }
1926                 el2 = ldb_msg_find_element(msg, "pwdLastSet");
1927                 if (el2 == NULL) {
1928                         return LDB_ERR_CONSTRAINT_VIOLATION;
1929                 }
1930                 if (el1 != el2) {
1931                         return LDB_ERR_CONSTRAINT_VIOLATION;
1932                 }
1933
1934                 io->g.last_set = samdb_result_nttime(msg, "pwdLastSet", 0);
1935                 return LDB_SUCCESS;
1936         }
1937
1938         ret = msg_find_old_and_new_pwd_val(msg, "pwdLastSet",
1939                                            io->ac->req->operation,
1940                                            &new_val, &old_val);
1941         if (ret != LDB_SUCCESS) {
1942                 return ret;
1943         }
1944
1945         if (old_val != NULL && new_val == NULL) {
1946                 ldb_set_errstring(ldb,
1947                                   "'pwdLastSet' deletion is not allowed!");
1948                 return LDB_ERR_UNWILLING_TO_PERFORM;
1949         }
1950
1951         io->g.last_set = UINT64_MAX;
1952         if (new_val != NULL) {
1953                 struct ldb_message *tmp_msg = NULL;
1954
1955                 tmp_msg = ldb_msg_new(io->ac);
1956                 if (tmp_msg == NULL) {
1957                         return ldb_module_oom(io->ac->module);
1958                 }
1959
1960                 if (old_val != NULL) {
1961                         NTTIME old_last_set = 0;
1962
1963                         ret = ldb_msg_add_value(tmp_msg, "oldval",
1964                                                 old_val, NULL);
1965                         if (ret != LDB_SUCCESS) {
1966                                 return ret;
1967                         }
1968
1969                         old_last_set = samdb_result_nttime(tmp_msg,
1970                                                            "oldval",
1971                                                            1);
1972                         if (io->u.pwdLastSet != old_last_set) {
1973                                 return dsdb_module_werror(io->ac->module,
1974                                         LDB_ERR_NO_SUCH_ATTRIBUTE,
1975                                         WERR_DS_CANT_REM_MISSING_ATT_VAL,
1976                                         "setup_last_set_field: old pwdLastSet "
1977                                         "value not found!");
1978                         }
1979                 }
1980
1981                 ret = ldb_msg_add_value(tmp_msg, "newval",
1982                                         new_val, NULL);
1983                 if (ret != LDB_SUCCESS) {
1984                         return ret;
1985                 }
1986
1987                 io->g.last_set = samdb_result_nttime(tmp_msg,
1988                                                      "newval",
1989                                                      1);
1990         } else if (ldb_msg_find_element(msg, "pwdLastSet")) {
1991                 ldb_set_errstring(ldb,
1992                                   "'pwdLastSet' deletion is not allowed!");
1993                 return LDB_ERR_UNWILLING_TO_PERFORM;
1994         } else if (io->ac->smartcard_reset) {
1995                 /*
1996                  * adding UF_SMARTCARD_REQUIRED doesn't update
1997                  * pwdLastSet implicitly.
1998                  */
1999                 io->ac->update_lastset = false;
2000         }
2001
2002         /* only 0 or -1 (0xFFFFFFFFFFFFFFFF) are allowed */
2003         switch (io->g.last_set) {
2004         case 0:
2005                 if (!io->ac->pwd_last_set_default) {
2006                         break;
2007                 }
2008                 if (!io->ac->update_password) {
2009                         break;
2010                 }
2011                 /* fall through */
2012         case UINT64_MAX:
2013                 if (!io->ac->update_password &&
2014                     io->u.pwdLastSet != 0 &&
2015                     io->u.pwdLastSet != UINT64_MAX)
2016                 {
2017                         /*
2018                          * Just setting pwdLastSet to -1, while not changing
2019                          * any password field has no effect if pwdLastSet
2020                          * is already non-zero.
2021                          */
2022                         io->ac->update_lastset = false;
2023                         break;
2024                 }
2025                 /* -1 means set it as now */
2026                 GetTimeOfDay(&tv);
2027                 io->g.last_set = timeval_to_nttime(&tv);
2028                 break;
2029         default:
2030                 return dsdb_module_werror(io->ac->module,
2031                                           LDB_ERR_OTHER,
2032                                           WERR_INVALID_PARAM,
2033                                           "setup_last_set_field: "
2034                                           "pwdLastSet must be 0 or -1 only!");
2035         }
2036
2037         if (io->ac->req->operation == LDB_ADD) {
2038                 /*
2039                  * We always need to store the value on add
2040                  * operations.
2041                  */
2042                 return LDB_SUCCESS;
2043         }
2044
2045         if (io->g.last_set == io->u.pwdLastSet) {
2046                 /*
2047                  * Just setting pwdLastSet to 0, is no-op if it's already 0.
2048                  */
2049                 io->ac->update_lastset = false;
2050         }
2051
2052         return LDB_SUCCESS;
2053 }
2054
2055 static int setup_given_passwords(struct setup_password_fields_io *io,
2056                                  struct setup_password_fields_given *g)
2057 {
2058         struct ldb_context *ldb;
2059         bool ok;
2060
2061         ldb = ldb_module_get_ctx(io->ac->module);
2062
2063         if (g->cleartext_utf8) {
2064                 struct ldb_val *cleartext_utf16_blob;
2065
2066                 cleartext_utf16_blob = talloc(io->ac, struct ldb_val);
2067                 if (!cleartext_utf16_blob) {
2068                         return ldb_oom(ldb);
2069                 }
2070                 if (!convert_string_talloc(io->ac,
2071                                            CH_UTF8, CH_UTF16,
2072                                            g->cleartext_utf8->data,
2073                                            g->cleartext_utf8->length,
2074                                            (void *)&cleartext_utf16_blob->data,
2075                                            &cleartext_utf16_blob->length)) {
2076                         if (g->cleartext_utf8->length != 0) {
2077                                 talloc_free(cleartext_utf16_blob);
2078                                 ldb_asprintf_errstring(ldb,
2079                                                        "setup_password_fields: "
2080                                                        "failed to generate UTF16 password from cleartext UTF8 one for user '%s'!",
2081                                                        io->u.sAMAccountName);
2082                                 return LDB_ERR_CONSTRAINT_VIOLATION;
2083                         } else {
2084                                 /* passwords with length "0" are valid! */
2085                                 cleartext_utf16_blob->data = NULL;
2086                                 cleartext_utf16_blob->length = 0;
2087                         }
2088                 }
2089                 g->cleartext_utf16 = cleartext_utf16_blob;
2090         } else if (g->cleartext_utf16) {
2091                 struct ldb_val *cleartext_utf8_blob;
2092
2093                 cleartext_utf8_blob = talloc(io->ac, struct ldb_val);
2094                 if (!cleartext_utf8_blob) {
2095                         return ldb_oom(ldb);
2096                 }
2097                 if (!convert_string_talloc(io->ac,
2098                                            CH_UTF16MUNGED, CH_UTF8,
2099                                            g->cleartext_utf16->data,
2100                                            g->cleartext_utf16->length,
2101                                            (void *)&cleartext_utf8_blob->data,
2102                                            &cleartext_utf8_blob->length)) {
2103                         if (g->cleartext_utf16->length != 0) {
2104                                 /* We must bail out here, the input wasn't even
2105                                  * a multiple of 2 bytes */
2106                                 talloc_free(cleartext_utf8_blob);
2107                                 ldb_asprintf_errstring(ldb,
2108                                                        "setup_password_fields: "
2109                                                        "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)!",
2110                                                        io->u.sAMAccountName);
2111                                 return LDB_ERR_CONSTRAINT_VIOLATION;
2112                         } else {
2113                                 /* passwords with length "0" are valid! */
2114                                 cleartext_utf8_blob->data = NULL;
2115                                 cleartext_utf8_blob->length = 0;
2116                         }
2117                 }
2118                 g->cleartext_utf8 = cleartext_utf8_blob;
2119         }
2120
2121         if (g->cleartext_utf16) {
2122                 struct samr_Password *nt_hash;
2123
2124                 nt_hash = talloc(io->ac, struct samr_Password);
2125                 if (!nt_hash) {
2126                         return ldb_oom(ldb);
2127                 }
2128                 g->nt_hash = nt_hash;
2129
2130                 /* compute the new nt hash */
2131                 mdfour(nt_hash->hash,
2132                        g->cleartext_utf16->data,
2133                        g->cleartext_utf16->length);
2134         }
2135
2136         if (g->cleartext_utf8) {
2137                 struct samr_Password *lm_hash;
2138
2139                 lm_hash = talloc(io->ac, struct samr_Password);
2140                 if (!lm_hash) {
2141                         return ldb_oom(ldb);
2142                 }
2143
2144                 /* compute the new lm hash */
2145                 ok = E_deshash((char *)g->cleartext_utf8->data, lm_hash->hash);
2146                 if (ok) {
2147                         g->lm_hash = lm_hash;
2148                 } else {
2149                         talloc_free(lm_hash);
2150                 }
2151         }
2152
2153         return LDB_SUCCESS;
2154 }
2155
2156 static int setup_password_fields(struct setup_password_fields_io *io)
2157 {
2158         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2159         struct loadparm_context *lp_ctx =
2160                 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2161                                          struct loadparm_context);
2162         int ret;
2163
2164         ret = setup_last_set_field(io);
2165         if (ret != LDB_SUCCESS) {
2166                 return ret;
2167         }
2168
2169         if (!io->ac->update_password) {
2170                 return LDB_SUCCESS;
2171         }
2172
2173         /* transform the old password (for password changes) */
2174         ret = setup_given_passwords(io, &io->og);
2175         if (ret != LDB_SUCCESS) {
2176                 return ret;
2177         }
2178
2179         /* transform the new password */
2180         ret = setup_given_passwords(io, &io->n);
2181         if (ret != LDB_SUCCESS) {
2182                 return ret;
2183         }
2184
2185         if (io->n.cleartext_utf8) {
2186                 ret = setup_kerberos_keys(io);
2187                 if (ret != LDB_SUCCESS) {
2188                         return ret;
2189                 }
2190         }
2191
2192         ret = setup_nt_fields(io);
2193         if (ret != LDB_SUCCESS) {
2194                 return ret;
2195         }
2196
2197         if (lpcfg_lanman_auth(lp_ctx)) {
2198                 ret = setup_lm_fields(io);
2199                 if (ret != LDB_SUCCESS) {
2200                         return ret;
2201                 }
2202         } else {
2203                 io->g.lm_hash = NULL;
2204                 io->g.lm_history_len = 0;
2205         }
2206
2207         ret = setup_supplemental_field(io);
2208         if (ret != LDB_SUCCESS) {
2209                 return ret;
2210         }
2211
2212         return LDB_SUCCESS;
2213 }
2214
2215 static int setup_smartcard_reset(struct setup_password_fields_io *io)
2216 {
2217         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2218         struct loadparm_context *lp_ctx = talloc_get_type(
2219                 ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
2220         struct supplementalCredentialsBlob scb = { .__ndr_size = 0 };
2221         enum ndr_err_code ndr_err;
2222
2223         if (!io->ac->smartcard_reset) {
2224                 return LDB_SUCCESS;
2225         }
2226
2227         io->g.nt_hash = talloc(io->ac, struct samr_Password);
2228         if (io->g.nt_hash == NULL) {
2229                 return ldb_module_oom(io->ac->module);
2230         }
2231         generate_secret_buffer(io->g.nt_hash->hash,
2232                                sizeof(io->g.nt_hash->hash));
2233         io->g.nt_history_len = 0;
2234
2235         if (lpcfg_lanman_auth(lp_ctx)) {
2236                 io->g.lm_hash = talloc(io->ac, struct samr_Password);
2237                 if (io->g.lm_hash == NULL) {
2238                         return ldb_module_oom(io->ac->module);
2239                 }
2240                 generate_secret_buffer(io->g.lm_hash->hash,
2241                                        sizeof(io->g.lm_hash->hash));
2242         } else {
2243                 io->g.lm_hash = NULL;
2244         }
2245         io->g.lm_history_len = 0;
2246
2247         /*
2248          * We take the "old" value and store it
2249          * with num_packages = 0.
2250          *
2251          * On "add" we have scb.sub.signature == 0, which
2252          * results in:
2253          *
2254          * [0000] 00 00 00 00 00 00 00 00   00 00 00 00 00
2255          *
2256          * On modify it's likely to be scb.sub.signature ==
2257          * SUPPLEMENTAL_CREDENTIALS_SIGNATURE (0x0050), which results in
2258          * something like:
2259          *
2260          * [0000] 00 00 00 00 62 00 00 00   00 00 00 00 20 00 20 00
2261          * [0010] 20 00 20 00 20 00 20 00   20 00 20 00 20 00 20 00
2262          * [0020] 20 00 20 00 20 00 20 00   20 00 20 00 20 00 20 00
2263          * [0030] 20 00 20 00 20 00 20 00   20 00 20 00 20 00 20 00
2264          * [0040] 20 00 20 00 20 00 20 00   20 00 20 00 20 00 20 00
2265          * [0050] 20 00 20 00 20 00 20 00   20 00 20 00 20 00 20 00
2266          * [0060] 20 00 20 00 20 00 20 00   20 00 20 00 50 00 00
2267          *
2268          * See https://bugzilla.samba.org/show_bug.cgi?id=11441
2269          * and ndr_{push,pull}_supplementalCredentialsSubBlob().
2270          */
2271         scb = io->o.scb;
2272         scb.sub.num_packages = 0;
2273
2274         /*
2275          * setup 'supplementalCredentials' value without packages
2276          */
2277         ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac,
2278                                        &scb,
2279                                        (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
2280         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2281                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2282                 ldb_asprintf_errstring(ldb,
2283                                        "setup_smartcard_reset: "
2284                                        "failed to push supplementalCredentialsBlob: %s",
2285                                        nt_errstr(status));
2286                 return LDB_ERR_OPERATIONS_ERROR;
2287         }
2288
2289         io->ac->update_password = true;
2290         return LDB_SUCCESS;
2291 }
2292
2293 static int make_error_and_update_badPwdCount(struct setup_password_fields_io *io)
2294 {
2295         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2296         struct ldb_message *mod_msg = NULL;
2297         NTSTATUS status;
2298         int ret;
2299
2300         status = dsdb_update_bad_pwd_count(io->ac, ldb,
2301                                            io->ac->search_res->message,
2302                                            io->ac->dom_res->message,
2303                                            &mod_msg);
2304         if (!NT_STATUS_IS_OK(status)) {
2305                 goto done;
2306         }
2307
2308         if (mod_msg == NULL) {
2309                 goto done;
2310         }
2311
2312         /*
2313          * OK, horrible semantics ahead.
2314          *
2315          * - We need to abort any existing transaction
2316          * - create a transaction arround the badPwdCount update
2317          * - re-open the transaction so the upper layer
2318          *   doesn't know what happened.
2319          *
2320          * This is needed because returning an error to the upper
2321          * layer will cancel the transaction and undo the badPwdCount
2322          * update.
2323          */
2324
2325         /*
2326          * Checking errors here is a bit pointless.
2327          * What can we do if we can't end the transaction?
2328          */
2329         ret = ldb_next_del_trans(io->ac->module);
2330         if (ret != LDB_SUCCESS) {
2331                 ldb_debug(ldb, LDB_DEBUG_FATAL,
2332                           "Failed to abort transaction prior to update of badPwdCount of %s: %s",
2333                           ldb_dn_get_linearized(io->ac->search_res->message->dn),
2334                           ldb_errstring(ldb));
2335                 /*
2336                  * just return the original error
2337                  */
2338                 goto done;
2339         }
2340
2341         /* Likewise, what should we do if we can't open a new transaction? */
2342         ret = ldb_next_start_trans(io->ac->module);
2343         if (ret != LDB_SUCCESS) {
2344                 ldb_debug(ldb, LDB_DEBUG_ERROR,
2345                           "Failed to open transaction to update badPwdCount of %s: %s",
2346                           ldb_dn_get_linearized(io->ac->search_res->message->dn),
2347                           ldb_errstring(ldb));
2348                 /*
2349                  * just return the original error
2350                  */
2351                 goto done;
2352         }
2353
2354         ret = dsdb_module_modify(io->ac->module, mod_msg,
2355                                  DSDB_FLAG_NEXT_MODULE,
2356                                  io->ac->req);
2357         if (ret != LDB_SUCCESS) {
2358                 ldb_debug(ldb, LDB_DEBUG_ERROR,
2359                           "Failed to update badPwdCount of %s: %s",
2360                           ldb_dn_get_linearized(io->ac->search_res->message->dn),
2361                           ldb_errstring(ldb));
2362                 /*
2363                  * We can only ignore this...
2364                  */
2365         }
2366
2367         ret = ldb_next_end_trans(io->ac->module);
2368         if (ret != LDB_SUCCESS) {
2369                 ldb_debug(ldb, LDB_DEBUG_ERROR,
2370                           "Failed to close transaction to update badPwdCount of %s: %s",
2371                           ldb_dn_get_linearized(io->ac->search_res->message->dn),
2372                           ldb_errstring(ldb));
2373                 /*
2374                  * We can only ignore this...
2375                  */
2376         }
2377
2378         ret = ldb_next_start_trans(io->ac->module);
2379         if (ret != LDB_SUCCESS) {
2380                 ldb_debug(ldb, LDB_DEBUG_ERROR,
2381                           "Failed to open transaction after update of badPwdCount of %s: %s",
2382                           ldb_dn_get_linearized(io->ac->search_res->message->dn),
2383                           ldb_errstring(ldb));
2384                 /*
2385                  * We can only ignore this...
2386                  */
2387         }
2388
2389 done:
2390         ret = LDB_ERR_CONSTRAINT_VIOLATION;
2391         ldb_asprintf_errstring(ldb,
2392                                "%08X: %s - check_password_restrictions: "
2393                                "The old password specified doesn't match!",
2394                                W_ERROR_V(WERR_INVALID_PASSWORD),
2395                                ldb_strerror(ret));
2396         return ret;
2397 }
2398
2399 static int check_password_restrictions(struct setup_password_fields_io *io)
2400 {
2401         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2402         int ret;
2403         struct loadparm_context *lp_ctx =
2404                 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2405                                          struct loadparm_context);
2406
2407         if (!io->ac->update_password) {
2408                 return LDB_SUCCESS;
2409         }
2410
2411         /* First check the old password is correct, for password changes */
2412         if (!io->ac->pwd_reset) {
2413                 bool nt_hash_checked = false;
2414
2415                 /* we need the old nt or lm hash given by the client */
2416                 if (!io->og.nt_hash && !io->og.lm_hash) {
2417                         ldb_asprintf_errstring(ldb,
2418                                 "check_password_restrictions: "
2419                                 "You need to provide the old password in order "
2420                                 "to change it!");
2421                         return LDB_ERR_UNWILLING_TO_PERFORM;
2422                 }
2423
2424                 /* The password modify through the NT hash is encouraged and
2425                    has no problems at all */
2426                 if (io->og.nt_hash) {
2427                         if (!io->o.nt_hash || memcmp(io->og.nt_hash->hash, io->o.nt_hash->hash, 16) != 0) {
2428                                 return make_error_and_update_badPwdCount(io);
2429                         }
2430
2431                         nt_hash_checked = true;
2432                 }
2433
2434                 /* But it is also possible to change a password by the LM hash
2435                  * alone for compatibility reasons. This check is optional if
2436                  * the NT hash was already checked - otherwise it's mandatory.
2437                  * (as the SAMR operations request it). */
2438                 if (io->og.lm_hash) {
2439                         if ((!io->o.lm_hash && !nt_hash_checked)
2440                             || (io->o.lm_hash && memcmp(io->og.lm_hash->hash, io->o.lm_hash->hash, 16) != 0)) {
2441                                 return make_error_and_update_badPwdCount(io);
2442                         }
2443                 }
2444         }
2445
2446         if (io->u.restrictions == 0) {
2447                 /* FIXME: Is this right? */
2448                 return LDB_SUCCESS;
2449         }
2450
2451         /* Password minimum age: yes, this is a minus. The ages are in negative 100nsec units! */
2452         if ((io->u.pwdLastSet - io->ac->status->domain_data.minPwdAge > io->g.last_set) &&
2453             !io->ac->pwd_reset)
2454         {
2455                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2456                 ldb_asprintf_errstring(ldb,
2457                         "%08X: %s - check_password_restrictions: "
2458                         "password is too young to change!",
2459                         W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2460                         ldb_strerror(ret));
2461                 return ret;
2462         }
2463
2464         /*
2465          * Fundamental password checks done by the call
2466          * "samdb_check_password".
2467          * It is also in use by "dcesrv_samr_ValidatePassword".
2468          */
2469         if (io->n.cleartext_utf8 != NULL) {
2470                 enum samr_ValidationStatus vstat;
2471                 vstat = samdb_check_password(io->ac, lp_ctx,
2472                                              io->n.cleartext_utf8,
2473                                              io->ac->status->domain_data.pwdProperties,
2474                                              io->ac->status->domain_data.minPwdLength);
2475                 switch (vstat) {
2476                 case SAMR_VALIDATION_STATUS_SUCCESS:
2477                                 /* perfect -> proceed! */
2478                         break;
2479
2480                 case SAMR_VALIDATION_STATUS_PWD_TOO_SHORT:
2481                         ret = LDB_ERR_CONSTRAINT_VIOLATION;
2482                         ldb_asprintf_errstring(ldb,
2483                                 "%08X: %s - check_password_restrictions: "
2484                                 "the password is too short. It should be equal or longer than %u characters!",
2485                                 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2486                                 ldb_strerror(ret),
2487                                 io->ac->status->domain_data.minPwdLength);
2488                         io->ac->status->reject_reason = SAM_PWD_CHANGE_PASSWORD_TOO_SHORT;
2489                         return ret;
2490
2491                 case SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH:
2492                         ret = LDB_ERR_CONSTRAINT_VIOLATION;
2493                         ldb_asprintf_errstring(ldb,
2494                                 "%08X: %s - check_password_restrictions: "
2495                                 "the password does not meet the complexity criteria!",
2496                                 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2497                                 ldb_strerror(ret));
2498                         io->ac->status->reject_reason = SAM_PWD_CHANGE_NOT_COMPLEX;
2499                         return ret;
2500
2501                 default:
2502                         ret = LDB_ERR_CONSTRAINT_VIOLATION;
2503                         ldb_asprintf_errstring(ldb,
2504                                 "%08X: %s - check_password_restrictions: "
2505                                 "the password doesn't fit due to a miscellaneous restriction!",
2506                                 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2507                                 ldb_strerror(ret));
2508                         return ret;
2509                 }
2510         }
2511
2512         if (io->ac->pwd_reset) {
2513                 return LDB_SUCCESS;
2514         }
2515
2516         if (io->n.nt_hash) {
2517                 uint32_t i;
2518
2519                 /* checks the NT hash password history */
2520                 for (i = 0; i < io->o.nt_history_len; i++) {
2521                         ret = memcmp(io->n.nt_hash, io->o.nt_history[i].hash, 16);
2522                         if (ret == 0) {
2523                                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2524                                 ldb_asprintf_errstring(ldb,
2525                                         "%08X: %s - check_password_restrictions: "
2526                                         "the password was already used (in history)!",
2527                                         W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2528                                         ldb_strerror(ret));
2529                                 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
2530                                 return ret;
2531                         }
2532                 }
2533         }
2534
2535         if (io->n.lm_hash) {
2536                 uint32_t i;
2537
2538                 /* checks the LM hash password history */
2539                 for (i = 0; i < io->o.lm_history_len; i++) {
2540                         ret = memcmp(io->n.lm_hash, io->o.lm_history[i].hash, 16);
2541                         if (ret == 0) {
2542                                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2543                                 ldb_asprintf_errstring(ldb,
2544                                         "%08X: %s - check_password_restrictions: "
2545                                         "the password was already used (in history)!",
2546                                         W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2547                                         ldb_strerror(ret));
2548                                 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
2549                                 return ret;
2550                         }
2551                 }
2552         }
2553
2554         /* are all password changes disallowed? */
2555         if (io->ac->status->domain_data.pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
2556                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2557                 ldb_asprintf_errstring(ldb,
2558                         "%08X: %s - check_password_restrictions: "
2559                         "password changes disabled!",
2560                         W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2561                         ldb_strerror(ret));
2562                 return ret;
2563         }
2564
2565         /* can this user change the password? */
2566         if (io->u.userAccountControl & UF_PASSWD_CANT_CHANGE) {
2567                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2568                 ldb_asprintf_errstring(ldb,
2569                         "%08X: %s - check_password_restrictions: "
2570                         "password can't be changed on this account!",
2571                         W_ERROR_V(WERR_PASSWORD_RESTRICTION),
2572                         ldb_strerror(ret));
2573                 return ret;
2574         }
2575
2576         return LDB_SUCCESS;
2577 }
2578
2579 static int update_final_msg(struct setup_password_fields_io *io)
2580 {
2581         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2582         int ret;
2583         int el_flags = 0;
2584         bool update_password = io->ac->update_password;
2585         bool update_scb = io->ac->update_password;
2586
2587         /*
2588          * If we add a user without initial password,
2589          * we need to add replication meta data for
2590          * following attributes:
2591          * - unicodePwd
2592          * - dBCSPwd
2593          * - ntPwdHistory
2594          * - lmPwdHistory
2595          *
2596          * If we add a user with initial password or a
2597          * password is changed of an existing user,
2598          * we need to replace the following attributes
2599          * with a forced meta data update, e.g. also
2600          * when updating an empty attribute with an empty value:
2601          * - unicodePwd
2602          * - dBCSPwd
2603          * - ntPwdHistory
2604          * - lmPwdHistory
2605          * - supplementalCredentials
2606          */
2607
2608         switch (io->ac->req->operation) {
2609         case LDB_ADD:
2610                 update_password = true;
2611                 el_flags |= DSDB_FLAG_INTERNAL_FORCE_META_DATA;
2612                 break;
2613         case LDB_MODIFY:
2614                 el_flags |= LDB_FLAG_MOD_REPLACE;
2615                 el_flags |= DSDB_FLAG_INTERNAL_FORCE_META_DATA;
2616                 break;
2617         default:
2618                 return ldb_module_operr(io->ac->module);
2619         }
2620
2621         if (update_password) {
2622                 ret = ldb_msg_add_empty(io->ac->update_msg,
2623                                         "unicodePwd",
2624                                         el_flags, NULL);
2625                 if (ret != LDB_SUCCESS) {
2626                         return ret;
2627                 }
2628                 ret = ldb_msg_add_empty(io->ac->update_msg,
2629                                         "dBCSPwd",
2630                                         el_flags, NULL);
2631                 if (ret != LDB_SUCCESS) {
2632                         return ret;
2633                 }
2634                 ret = ldb_msg_add_empty(io->ac->update_msg,
2635                                         "ntPwdHistory",
2636                                         el_flags, NULL);
2637                 if (ret != LDB_SUCCESS) {
2638                         return ret;
2639                 }
2640                 ret = ldb_msg_add_empty(io->ac->update_msg,
2641                                         "lmPwdHistory",
2642                                         el_flags, NULL);
2643                 if (ret != LDB_SUCCESS) {
2644                         return ret;
2645                 }
2646         }
2647         if (update_scb) {
2648                 ret = ldb_msg_add_empty(io->ac->update_msg,
2649                                         "supplementalCredentials",
2650                                         el_flags, NULL);
2651                 if (ret != LDB_SUCCESS) {
2652                         return ret;
2653                 }
2654         }
2655         if (io->ac->update_lastset) {
2656                 ret = ldb_msg_add_empty(io->ac->update_msg,
2657                                         "pwdLastSet",
2658                                         el_flags, NULL);
2659                 if (ret != LDB_SUCCESS) {
2660                         return ret;
2661                 }
2662         }
2663
2664         if (io->g.nt_hash != NULL) {
2665                 ret = samdb_msg_add_hash(ldb, io->ac,
2666                                          io->ac->update_msg,
2667                                          "unicodePwd",
2668                                          io->g.nt_hash);
2669                 if (ret != LDB_SUCCESS) {
2670                         return ret;
2671                 }
2672         }
2673         if (io->g.lm_hash != NULL) {
2674                 ret = samdb_msg_add_hash(ldb, io->ac,
2675                                          io->ac->update_msg,
2676                                          "dBCSPwd",
2677                                          io->g.lm_hash);
2678                 if (ret != LDB_SUCCESS) {
2679                         return ret;
2680                 }
2681         }
2682         if (io->g.nt_history_len > 0) {
2683                 ret = samdb_msg_add_hashes(ldb, io->ac,
2684                                            io->ac->update_msg,
2685                                            "ntPwdHistory",
2686                                            io->g.nt_history,
2687                                            io->g.nt_history_len);
2688                 if (ret != LDB_SUCCESS) {
2689                         return ret;
2690                 }
2691         }
2692         if (io->g.lm_history_len > 0) {
2693                 ret = samdb_msg_add_hashes(ldb, io->ac,
2694                                            io->ac->update_msg,
2695                                            "lmPwdHistory",
2696                                            io->g.lm_history,
2697                                            io->g.lm_history_len);
2698                 if (ret != LDB_SUCCESS) {
2699                         return ret;
2700                 }
2701         }
2702         if (io->g.supplemental.length > 0) {
2703                 ret = ldb_msg_add_value(io->ac->update_msg,
2704                                         "supplementalCredentials",
2705                                         &io->g.supplemental, NULL);
2706                 if (ret != LDB_SUCCESS) {
2707                         return ret;
2708                 }
2709         }
2710         if (io->ac->update_lastset) {
2711                 ret = samdb_msg_add_uint64(ldb, io->ac,
2712                                            io->ac->update_msg,
2713                                            "pwdLastSet",
2714                                            io->g.last_set);
2715                 if (ret != LDB_SUCCESS) {
2716                         return ret;
2717                 }
2718         }
2719
2720         return LDB_SUCCESS;
2721 }
2722
2723 /*
2724  * This is intended for use by the "password_hash" module since there
2725  * password changes can be specified through one message element with the
2726  * new password (to set) and another one with the old password (to unset).
2727  *
2728  * The first which sets a password (new value) can have flags
2729  * (LDB_FLAG_MOD_ADD, LDB_FLAG_MOD_REPLACE) but also none (on "add" operations
2730  * for entries). The latter (old value) has always specified
2731  * LDB_FLAG_MOD_DELETE.
2732  *
2733  * Returns LDB_ERR_CONSTRAINT_VIOLATION and LDB_ERR_UNWILLING_TO_PERFORM if
2734  * matching message elements are malformed in respect to the set/change rules.
2735  * Otherwise it returns LDB_SUCCESS.
2736  */
2737 static int msg_find_old_and_new_pwd_val(const struct ldb_message *msg,
2738                                         const char *name,
2739                                         enum ldb_request_type operation,
2740                                         const struct ldb_val **new_val,
2741                                         const struct ldb_val **old_val)
2742 {
2743         unsigned int i;
2744
2745         *new_val = NULL;
2746         *old_val = NULL;
2747
2748         if (msg == NULL) {
2749                 return LDB_SUCCESS;
2750         }
2751
2752         for (i = 0; i < msg->num_elements; i++) {
2753                 if (ldb_attr_cmp(msg->elements[i].name, name) != 0) {
2754                         continue;
2755                 }
2756
2757                 if ((operation == LDB_MODIFY) &&
2758                     (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_DELETE)) {
2759                         /* 0 values are allowed */
2760                         if (msg->elements[i].num_values == 1) {
2761                                 *old_val = &msg->elements[i].values[0];
2762                         } else if (msg->elements[i].num_values > 1) {
2763                                 return LDB_ERR_CONSTRAINT_VIOLATION;
2764                         }
2765                 } else if ((operation == LDB_MODIFY) &&
2766                            (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_REPLACE)) {
2767                         if (msg->elements[i].num_values > 0) {
2768                                 *new_val = &msg->elements[i].values[msg->elements[i].num_values - 1];
2769                         } else {
2770                                 return LDB_ERR_UNWILLING_TO_PERFORM;
2771                         }
2772                 } else {
2773                         /* Add operations and LDB_FLAG_MOD_ADD */
2774                         if (msg->elements[i].num_values > 0) {
2775                                 *new_val = &msg->elements[i].values[msg->elements[i].num_values - 1];
2776                         } else {
2777                                 return LDB_ERR_CONSTRAINT_VIOLATION;
2778                         }
2779                 }
2780         }
2781
2782         return LDB_SUCCESS;
2783 }
2784
2785 static int setup_io(struct ph_context *ac, 
2786                     const struct ldb_message *client_msg,
2787                     const struct ldb_message *existing_msg,
2788                     struct setup_password_fields_io *io) 
2789
2790         const struct ldb_val *quoted_utf16, *old_quoted_utf16, *lm_hash, *old_lm_hash;
2791         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2792         struct loadparm_context *lp_ctx = talloc_get_type(
2793                 ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
2794         int ret;
2795         const struct ldb_message *info_msg = NULL;
2796
2797         ZERO_STRUCTP(io);
2798
2799         /* Some operations below require kerberos contexts */
2800
2801         if (existing_msg != NULL) {
2802                 /*
2803                  * This is a modify operation
2804                  */
2805                 info_msg = existing_msg;
2806         } else {
2807                 /*
2808                  * This is an add operation
2809                  */
2810                 info_msg = client_msg;
2811         }
2812
2813         if (smb_krb5_init_context(ac,
2814                                   (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm"),
2815                                   &io->smb_krb5_context) != 0) {
2816                 return ldb_operr(ldb);
2817         }
2818
2819         io->ac                          = ac;
2820
2821         io->u.userAccountControl        = ldb_msg_find_attr_as_uint(info_msg,
2822                                                                     "userAccountControl", 0);
2823         if (info_msg == existing_msg) {
2824                 /*
2825                  * We only take pwdLastSet from the existing object
2826                  * otherwise we leave it as 0.
2827                  *
2828                  * If no attribute is available, e.g. on deleted objects
2829                  * we remember that as UINT64_MAX.
2830                  */
2831                 io->u.pwdLastSet = samdb_result_nttime(info_msg, "pwdLastSet",
2832                                                        UINT64_MAX);
2833         }
2834         io->u.sAMAccountName            = ldb_msg_find_attr_as_string(info_msg,
2835                                                                       "sAMAccountName", NULL);
2836         io->u.user_principal_name       = ldb_msg_find_attr_as_string(info_msg,
2837                                                                       "userPrincipalName", NULL);
2838         io->u.is_computer               = ldb_msg_check_string_attribute(info_msg, "objectClass", "computer");
2839
2840         if (io->u.sAMAccountName == NULL) {
2841                 ldb_asprintf_errstring(ldb,
2842                                        "setup_io: sAMAccountName attribute is missing on %s for attempted password set/change",
2843                                        ldb_dn_get_linearized(info_msg->dn));
2844
2845                 return LDB_ERR_CONSTRAINT_VIOLATION;
2846         }
2847
2848         if (io->u.userAccountControl & UF_INTERDOMAIN_TRUST_ACCOUNT) {
2849                 struct ldb_control *permit_trust = ldb_request_get_control(ac->req,
2850                                 DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
2851
2852                 if (permit_trust == NULL) {
2853                         ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2854                         ldb_asprintf_errstring(ldb,
2855                                 "%08X: %s - setup_io: changing the interdomain trust password "
2856                                 "on %s not allowed via LDAP. Use LSA or NETLOGON",
2857                                 W_ERROR_V(WERR_ACCESS_DENIED),
2858                                 ldb_strerror(ret),
2859                                 ldb_dn_get_linearized(info_msg->dn));
2860                         return ret;
2861                 }
2862         }
2863
2864         /* Only non-trust accounts have restrictions (possibly this test is the
2865          * wrong way around, but we like to be restrictive if possible */
2866         io->u.restrictions = !(io->u.userAccountControl
2867                 & (UF_INTERDOMAIN_TRUST_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT
2868                         | UF_SERVER_TRUST_ACCOUNT));
2869
2870         if (ac->userPassword) {
2871                 ret = msg_find_old_and_new_pwd_val(client_msg, "userPassword",
2872                                                    ac->req->operation,
2873                                                    &io->n.cleartext_utf8,
2874                                                    &io->og.cleartext_utf8);
2875                 if (ret != LDB_SUCCESS) {
2876                         ldb_asprintf_errstring(ldb,
2877                                 "setup_io: "
2878                                 "it's only allowed to set the old password once!");
2879                         return ret;
2880                 }
2881         }
2882
2883         if (io->n.cleartext_utf8 != NULL) {
2884                 struct ldb_val *cleartext_utf8_blob;
2885                 char *p;
2886
2887                 cleartext_utf8_blob = talloc(io->ac, struct ldb_val);
2888                 if (!cleartext_utf8_blob) {
2889                         return ldb_oom(ldb);
2890                 }
2891
2892                 *cleartext_utf8_blob = *io->n.cleartext_utf8;
2893
2894                 /* make sure we have a null terminated string */
2895                 p = talloc_strndup(cleartext_utf8_blob,
2896                                    (const char *)io->n.cleartext_utf8->data,
2897                                    io->n.cleartext_utf8->length);
2898                 if ((p == NULL) && (io->n.cleartext_utf8->length > 0)) {
2899                         return ldb_oom(ldb);
2900                 }
2901                 cleartext_utf8_blob->data = (uint8_t *)p;
2902
2903                 io->n.cleartext_utf8 = cleartext_utf8_blob;
2904         }
2905
2906         ret = msg_find_old_and_new_pwd_val(client_msg, "clearTextPassword",
2907                                            ac->req->operation,
2908                                            &io->n.cleartext_utf16,
2909                                            &io->og.cleartext_utf16);
2910         if (ret != LDB_SUCCESS) {
2911                 ldb_asprintf_errstring(ldb,
2912                         "setup_io: "
2913                         "it's only allowed to set the old password once!");
2914                 return ret;
2915         }
2916
2917         /* this rather strange looking piece of code is there to
2918            handle a ldap client setting a password remotely using the
2919            unicodePwd ldap field. The syntax is that the password is
2920            in UTF-16LE, with a " at either end. Unfortunately the
2921            unicodePwd field is also used to store the nt hashes
2922            internally in Samba, and is used in the nt hash format on
2923            the wire in DRS replication, so we have a single name for
2924            two distinct values. The code below leaves us with a small
2925            chance (less than 1 in 2^32) of a mixup, if someone manages
2926            to create a MD4 hash which starts and ends in 0x22 0x00, as
2927            that would then be treated as a UTF16 password rather than
2928            a nthash */
2929
2930         ret = msg_find_old_and_new_pwd_val(client_msg, "unicodePwd",
2931                                            ac->req->operation,
2932                                            &quoted_utf16,
2933                                            &old_quoted_utf16);
2934         if (ret != LDB_SUCCESS) {
2935                 ldb_asprintf_errstring(ldb,
2936                         "setup_io: "
2937                         "it's only allowed to set the old password once!");
2938                 return ret;
2939         }
2940
2941         /* Checks and converts the actual "unicodePwd" attribute */
2942         if (!ac->hash_values &&
2943             quoted_utf16 &&
2944             quoted_utf16->length >= 4 &&
2945             quoted_utf16->data[0] == '"' &&
2946             quoted_utf16->data[1] == 0 &&
2947             quoted_utf16->data[quoted_utf16->length-2] == '"' &&
2948             quoted_utf16->data[quoted_utf16->length-1] == 0) {
2949                 struct ldb_val *quoted_utf16_2;
2950
2951                 if (io->n.cleartext_utf16) {
2952                         /* refuse the change if someone wants to change with
2953                            with both UTF16 possibilities at the same time... */
2954                         ldb_asprintf_errstring(ldb,
2955                                 "setup_io: "
2956                                 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'clearTextPassword'");
2957                         return LDB_ERR_UNWILLING_TO_PERFORM;
2958                 }
2959
2960                 /*
2961                  * adapt the quoted UTF16 string to be a real
2962                  * cleartext one
2963                  */
2964                 quoted_utf16_2 = talloc(io->ac, struct ldb_val);
2965                 if (quoted_utf16_2 == NULL) {
2966                         return ldb_oom(ldb);
2967                 }
2968
2969                 quoted_utf16_2->data = quoted_utf16->data + 2;
2970                 quoted_utf16_2->length = quoted_utf16->length-4;
2971                 io->n.cleartext_utf16 = quoted_utf16_2;
2972                 io->n.nt_hash = NULL;
2973
2974         } else if (quoted_utf16) {
2975                 /* We have only the hash available -> so no plaintext here */
2976                 if (!ac->hash_values) {
2977                         /* refuse the change if someone wants to change
2978                            the hash without control specified... */
2979                         ldb_asprintf_errstring(ldb,
2980                                 "setup_io: "
2981                                 "it's not allowed to set the NT hash password directly'");
2982                         /* this looks odd but this is what Windows does:
2983                            returns "UNWILLING_TO_PERFORM" on wrong
2984                            password sets and "CONSTRAINT_VIOLATION" on
2985                            wrong password changes. */
2986                         if (old_quoted_utf16 == NULL) {
2987                                 return LDB_ERR_UNWILLING_TO_PERFORM;
2988                         }
2989
2990                         return LDB_ERR_CONSTRAINT_VIOLATION;
2991                 }
2992
2993                 io->n.nt_hash = talloc(io->ac, struct samr_Password);
2994                 memcpy(io->n.nt_hash->hash, quoted_utf16->data,
2995                        MIN(quoted_utf16->length, sizeof(io->n.nt_hash->hash)));
2996         }
2997
2998         /* Checks and converts the previous "unicodePwd" attribute */
2999         if (!ac->hash_values &&
3000             old_quoted_utf16 &&
3001             old_quoted_utf16->length >= 4 &&
3002             old_quoted_utf16->data[0] == '"' &&
3003             old_quoted_utf16->data[1] == 0 &&
3004             old_quoted_utf16->data[old_quoted_utf16->length-2] == '"' &&
3005             old_quoted_utf16->data[old_quoted_utf16->length-1] == 0) {
3006                 struct ldb_val *old_quoted_utf16_2;
3007
3008                 if (io->og.cleartext_utf16) {
3009                         /* refuse the change if someone wants to change with
3010                            both UTF16 possibilities at the same time... */
3011                         ldb_asprintf_errstring(ldb,
3012                                 "setup_io: "
3013                                 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'clearTextPassword'");
3014                         return LDB_ERR_UNWILLING_TO_PERFORM;
3015                 }
3016
3017                 /*
3018                  * adapt the quoted UTF16 string to be a real
3019                  * cleartext one
3020                  */
3021                 old_quoted_utf16_2 = talloc(io->ac, struct ldb_val);
3022                 if (old_quoted_utf16_2 == NULL) {
3023                         return ldb_oom(ldb);
3024                 }
3025
3026                 old_quoted_utf16_2->data = old_quoted_utf16->data + 2;
3027                 old_quoted_utf16_2->length = old_quoted_utf16->length-4;
3028
3029                 io->og.cleartext_utf16 = old_quoted_utf16_2;
3030                 io->og.nt_hash = NULL;
3031         } else if (old_quoted_utf16) {
3032                 /* We have only the hash available -> so no plaintext here */
3033                 if (!ac->hash_values) {
3034                         /* refuse the change if someone wants to change
3035                            the hash without control specified... */
3036                         ldb_asprintf_errstring(ldb,
3037                                 "setup_io: "
3038                                 "it's not allowed to set the NT hash password directly'");
3039                         return LDB_ERR_UNWILLING_TO_PERFORM;
3040                 }
3041
3042                 io->og.nt_hash = talloc(io->ac, struct samr_Password);
3043                 memcpy(io->og.nt_hash->hash, old_quoted_utf16->data,
3044                        MIN(old_quoted_utf16->length, sizeof(io->og.nt_hash->hash)));
3045         }
3046
3047         /* Handles the "dBCSPwd" attribute (LM hash) */
3048         io->n.lm_hash = NULL; io->og.lm_hash = NULL;
3049         ret = msg_find_old_and_new_pwd_val(client_msg, "dBCSPwd",
3050                                            ac->req->operation,
3051                                            &lm_hash, &old_lm_hash);
3052         if (ret != LDB_SUCCESS) {
3053                 ldb_asprintf_errstring(ldb,
3054                         "setup_io: "
3055                         "it's only allowed to set the old password once!");
3056                 return ret;
3057         }
3058
3059         if (((lm_hash != NULL) || (old_lm_hash != NULL)) && (!ac->hash_values)) {
3060                 /* refuse the change if someone wants to change the hash
3061                    without control specified... */
3062                 ldb_asprintf_errstring(ldb,
3063                         "setup_io: "
3064                         "it's not allowed to set the LM hash password directly'");
3065                 return LDB_ERR_UNWILLING_TO_PERFORM;
3066         }
3067
3068         if (lpcfg_lanman_auth(lp_ctx) && (lm_hash != NULL)) {
3069                 io->n.lm_hash = talloc(io->ac, struct samr_Password);
3070                 memcpy(io->n.lm_hash->hash, lm_hash->data, MIN(lm_hash->length,
3071                        sizeof(io->n.lm_hash->hash)));
3072         }
3073         if (lpcfg_lanman_auth(lp_ctx) && (old_lm_hash != NULL)) {
3074                 io->og.lm_hash = talloc(io->ac, struct samr_Password);
3075                 memcpy(io->og.lm_hash->hash, old_lm_hash->data, MIN(old_lm_hash->length,
3076                        sizeof(io->og.lm_hash->hash)));
3077         }
3078
3079         /*
3080          * Handles the password change control if it's specified. It has the
3081          * precedance and overrides already specified old password values of
3082          * change requests (but that shouldn't happen since the control is
3083          * fully internal and only used in conjunction with replace requests!).
3084          */
3085         if (ac->change != NULL) {
3086                 io->og.nt_hash = NULL;
3087                 if (ac->change->old_nt_pwd_hash != NULL) {
3088                         io->og.nt_hash = talloc_memdup(io->ac,
3089                                                        ac->change->old_nt_pwd_hash,
3090                                                        sizeof(struct samr_Password));
3091                 }
3092                 io->og.lm_hash = NULL;
3093                 if (lpcfg_lanman_auth(lp_ctx) && (ac->change->old_lm_pwd_hash != NULL)) {
3094                         io->og.lm_hash = talloc_memdup(io->ac,
3095                                                        ac->change->old_lm_pwd_hash,
3096                                                        sizeof(struct samr_Password));
3097                 }
3098         }
3099
3100         /* refuse the change if someone wants to change the clear-
3101            text and supply his own hashes at the same time... */
3102         if ((io->n.cleartext_utf8 || io->n.cleartext_utf16)
3103                         && (io->n.nt_hash || io->n.lm_hash)) {
3104                 ldb_asprintf_errstring(ldb,
3105                         "setup_io: "
3106                         "it's only allowed to set the password in form of cleartext attributes or as hashes");
3107                 return LDB_ERR_UNWILLING_TO_PERFORM;
3108         }
3109
3110         /* refuse the change if someone wants to change the password
3111            using both plaintext methods (UTF8 and UTF16) at the same time... */
3112         if (io->n.cleartext_utf8 && io->n.cleartext_utf16) {
3113                 ldb_asprintf_errstring(ldb,
3114                         "setup_io: "
3115                         "it's only allowed to set the cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
3116                 return LDB_ERR_UNWILLING_TO_PERFORM;
3117         }
3118
3119         /* refuse the change if someone tries to set/change the password by
3120          * the lanman hash alone and we've deactivated that mechanism. This
3121          * would end in an account without any password! */
3122         if (io->ac->update_password
3123             && (!io->n.cleartext_utf8) && (!io->n.cleartext_utf16)
3124             && (!io->n.nt_hash) && (!io->n.lm_hash)) {
3125                 ldb_asprintf_errstring(ldb,
3126                         "setup_io: "
3127                         "It's not possible to delete the password (changes using the LAN Manager hash alone could be deactivated)!");
3128                 /* on "userPassword" and "clearTextPassword" we've to return
3129                  * something different, since these are virtual attributes */
3130                 if ((ldb_msg_find_element(client_msg, "userPassword") != NULL) ||
3131                     (ldb_msg_find_element(client_msg, "clearTextPassword") != NULL)) {
3132                         return LDB_ERR_CONSTRAINT_VIOLATION;
3133                 }
3134                 return LDB_ERR_UNWILLING_TO_PERFORM;
3135         }
3136
3137         /* refuse the change if someone wants to compare against a plaintext
3138            or hash at the same time for a "password modify" operation... */
3139         if ((io->og.cleartext_utf8 || io->og.cleartext_utf16)
3140             && (io->og.nt_hash || io->og.lm_hash)) {
3141                 ldb_asprintf_errstring(ldb,
3142                         "setup_io: "
3143                         "it's only allowed to provide the old password in form of cleartext attributes or as hashes");
3144                 return LDB_ERR_UNWILLING_TO_PERFORM;
3145         }
3146
3147         /* refuse the change if someone wants to compare against both
3148          * plaintexts at the same time for a "password modify" operation... */
3149         if (io->og.cleartext_utf8 && io->og.cleartext_utf16) {
3150                 ldb_asprintf_errstring(ldb,
3151                         "setup_io: "
3152                         "it's only allowed to provide the old cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
3153                 return LDB_ERR_UNWILLING_TO_PERFORM;
3154         }
3155
3156         /* Decides if we have a password modify or password reset operation */
3157         if (ac->req->operation == LDB_ADD) {
3158                 /* On "add" we have only "password reset" */
3159                 ac->pwd_reset = true;
3160         } else if (ac->req->operation == LDB_MODIFY) {
3161                 if (io->og.cleartext_utf8 || io->og.cleartext_utf16
3162                     || io->og.nt_hash || io->og.lm_hash) {
3163                         /* If we have an old password specified then for sure it
3164                          * is a user "password change" */
3165                         ac->pwd_reset = false;
3166                 } else {
3167                         /* Otherwise we have also here a "password reset" */
3168                         ac->pwd_reset = true;
3169                 }
3170         } else {
3171                 /* this shouldn't happen */
3172                 return ldb_operr(ldb);
3173         }
3174
3175         if (existing_msg != NULL) {
3176                 NTSTATUS status;
3177
3178                 if (ac->pwd_reset) {
3179                         /* Get the old password from the database */
3180                         status = samdb_result_passwords_no_lockout(ac,
3181                                                                    lp_ctx,
3182                                                                    existing_msg,
3183                                                                    &io->o.lm_hash,
3184                                                                    &io->o.nt_hash);
3185                 } else {
3186                         /* Get the old password from the database */
3187                         status = samdb_result_passwords(ac,
3188                                                         lp_ctx,
3189                                                         existing_msg,
3190                                                         &io->o.lm_hash,
3191                                                         &io->o.nt_hash);
3192                 }
3193
3194                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
3195                         return dsdb_module_werror(ac->module,
3196                                                   LDB_ERR_CONSTRAINT_VIOLATION,
3197                                                   WERR_ACCOUNT_LOCKED_OUT,
3198                                                   "Password change not permitted,"
3199                                                   " account locked out!");
3200                 }
3201
3202                 if (!NT_STATUS_IS_OK(status)) {
3203                         /*
3204                          * This only happens if the database has gone weird,
3205                          * not if we are just missing the passwords
3206                          */
3207                         return ldb_operr(ldb);
3208                 }
3209
3210                 io->o.nt_history_len = samdb_result_hashes(ac, existing_msg,
3211                                                            "ntPwdHistory",
3212                                                            &io->o.nt_history);
3213                 io->o.lm_history_len = samdb_result_hashes(ac, existing_msg,
3214                                                            "lmPwdHistory",
3215                                                            &io->o.lm_history);
3216                 io->o.supplemental = ldb_msg_find_ldb_val(existing_msg,
3217                                                           "supplementalCredentials");
3218
3219                 if (io->o.supplemental != NULL) {
3220                         enum ndr_err_code ndr_err;
3221
3222                         ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac,
3223                                         &io->o.scb,
3224                                         (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
3225                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3226                                 status = ndr_map_error2ntstatus(ndr_err);
3227                                 ldb_asprintf_errstring(ldb,
3228                                                 "setup_io: failed to pull "
3229                                                 "old supplementalCredentialsBlob: %s",
3230                                                 nt_errstr(status));
3231                                 return LDB_ERR_OPERATIONS_ERROR;
3232                         }
3233                 }
3234         }
3235
3236         return LDB_SUCCESS;
3237 }
3238
3239 static struct ph_context *ph_init_context(struct ldb_module *module,
3240                                           struct ldb_request *req,
3241                                           bool userPassword,
3242                                           bool update_password)
3243 {
3244         struct ldb_context *ldb;
3245         struct ph_context *ac;
3246         struct loadparm_context *lp_ctx = NULL;
3247
3248         ldb = ldb_module_get_ctx(module);
3249
3250         ac = talloc_zero(req, struct ph_context);
3251         if (ac == NULL) {
3252                 ldb_set_errstring(ldb, "Out of Memory");
3253                 return NULL;
3254         }
3255
3256         ac->module = module;
3257         ac->req = req;
3258         ac->userPassword = userPassword;
3259         ac->update_password = update_password;
3260         ac->update_lastset = true;
3261
3262         lp_ctx = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"),
3263                                        struct loadparm_context);
3264         ac->gpg_key_ids = lpcfg_password_hash_gpg_key_ids(lp_ctx);
3265
3266         return ac;
3267 }
3268
3269 static void ph_apply_controls(struct ph_context *ac)
3270 {
3271         struct ldb_control *ctrl;
3272
3273         ac->change_status = false;
3274         ctrl = ldb_request_get_control(ac->req,
3275                                        DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID);
3276         if (ctrl != NULL) {
3277                 ac->change_status = true;
3278
3279                 /* Mark the "change status" control as uncritical (done) */
3280                 ctrl->critical = false;
3281         }
3282
3283         ac->hash_values = false;
3284         ctrl = ldb_request_get_control(ac->req,
3285                                        DSDB_CONTROL_PASSWORD_HASH_VALUES_OID);
3286         if (ctrl != NULL) {
3287                 ac->hash_values = true;
3288
3289                 /* Mark the "hash values" control as uncritical (done) */
3290                 ctrl->critical = false;
3291         }
3292
3293         ctrl = ldb_request_get_control(ac->req,
3294                                        DSDB_CONTROL_PASSWORD_CHANGE_OID);
3295         if (ctrl != NULL) {
3296                 ac->change = (struct dsdb_control_password_change *) ctrl->data;
3297
3298                 /* Mark the "change" control as uncritical (done) */
3299                 ctrl->critical = false;
3300         }
3301
3302         ac->pwd_last_set_bypass = false;
3303         ctrl = ldb_request_get_control(ac->req,
3304                                 DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID);
3305         if (ctrl != NULL) {
3306                 ac->pwd_last_set_bypass = true;
3307
3308                 /* Mark the "bypass pwdLastSet" control as uncritical (done) */
3309                 ctrl->critical = false;
3310         }
3311
3312         ac->pwd_last_set_default = false;
3313         ctrl = ldb_request_get_control(ac->req,
3314                                 DSDB_CONTROL_PASSWORD_DEFAULT_LAST_SET_OID);
3315         if (ctrl != NULL) {
3316                 ac->pwd_last_set_default = true;
3317
3318                 /* Mark the "bypass pwdLastSet" control as uncritical (done) */
3319                 ctrl->critical = false;
3320         }
3321
3322         ac->smartcard_reset = false;
3323         ctrl = ldb_request_get_control(ac->req,
3324                                 DSDB_CONTROL_PASSWORD_USER_ACCOUNT_CONTROL_OID);
3325         if (ctrl != NULL) {
3326                 struct dsdb_control_password_user_account_control *uac = NULL;
3327                 uint32_t added_flags = 0;
3328
3329                 uac = talloc_get_type_abort(ctrl->data,
3330                         struct dsdb_control_password_user_account_control);
3331
3332                 added_flags = uac->new_flags & ~uac->old_flags;
3333
3334                 if (added_flags & UF_SMARTCARD_REQUIRED) {
3335                         ac->smartcard_reset = true;
3336                 }
3337
3338                 /* Mark the "smartcard required" control as uncritical (done) */
3339                 ctrl->critical = false;
3340         }
3341 }
3342
3343 static int ph_op_callback(struct ldb_request *req, struct ldb_reply *ares)
3344 {
3345         struct ph_context *ac;
3346
3347         ac = talloc_get_type(req->context, struct ph_context);
3348
3349         if (!ares) {
3350                 return ldb_module_done(ac->req, NULL, NULL,
3351                                         LDB_ERR_OPERATIONS_ERROR);
3352         }
3353
3354         if (ares->type == LDB_REPLY_REFERRAL) {
3355                 return ldb_module_send_referral(ac->req, ares->referral);
3356         }
3357
3358         if ((ares->error != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
3359                 /* On success and trivial errors a status control is being
3360                  * added (used for example by the "samdb_set_password" call) */
3361                 ldb_reply_add_control(ares,
3362                                       DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
3363                                       false,
3364                                       ac->status);
3365         }
3366
3367         if (ares->error != LDB_SUCCESS) {
3368                 return ldb_module_done(ac->req, ares->controls,
3369                                         ares->response, ares->error);
3370         }
3371
3372         if (ares->type != LDB_REPLY_DONE) {
3373                 talloc_free(ares);
3374                 return ldb_module_done(ac->req, NULL, NULL,
3375                                         LDB_ERR_OPERATIONS_ERROR);
3376         }
3377
3378         return ldb_module_done(ac->req, ares->controls,
3379                                 ares->response, ares->error);
3380 }
3381
3382 static int password_hash_add_do_add(struct ph_context *ac);
3383 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares);
3384 static int password_hash_mod_search_self(struct ph_context *ac);
3385 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares);
3386 static int password_hash_mod_do_mod(struct ph_context *ac);
3387
3388 static int get_domain_data_callback(struct ldb_request *req,
3389                                     struct ldb_reply *ares)
3390 {
3391         struct ldb_context *ldb;
3392         struct ph_context *ac;
3393         struct loadparm_context *lp_ctx;
3394         int ret = LDB_SUCCESS;
3395
3396         ac = talloc_get_type(req->context, struct ph_context);
3397         ldb = ldb_module_get_ctx(ac->module);
3398
3399         if (!ares) {
3400                 ret = LDB_ERR_OPERATIONS_ERROR;
3401                 goto done;
3402         }
3403         if (ares->error != LDB_SUCCESS) {
3404                 return ldb_module_done(ac->req, ares->controls,
3405                                         ares->response, ares->error);
3406         }
3407
3408         switch (ares->type) {
3409         case LDB_REPLY_ENTRY:
3410                 if (ac->status != NULL) {
3411                         talloc_free(ares);
3412
3413                         ldb_set_errstring(ldb, "Too many results");
3414                         ret = LDB_ERR_OPERATIONS_ERROR;
3415                         goto done;
3416                 }
3417
3418                 /* Setup the "status" structure (used as control later) */
3419                 ac->status = talloc_zero(ac->req,
3420                                          struct dsdb_control_password_change_status);
3421                 if (ac->status == NULL) {
3422                         talloc_free(ares);
3423
3424                         ldb_oom(ldb);
3425                         ret = LDB_ERR_OPERATIONS_ERROR;
3426                         goto done;
3427                 }
3428
3429                 /* Setup the "domain data" structure */
3430                 ac->status->domain_data.pwdProperties =
3431                         ldb_msg_find_attr_as_uint(ares->message, "pwdProperties", -1);
3432                 ac->status->domain_data.pwdHistoryLength =
3433                         ldb_msg_find_attr_as_uint(ares->message, "pwdHistoryLength", -1);
3434                 ac->status->domain_data.maxPwdAge =
3435                         ldb_msg_find_attr_as_int64(ares->message, "maxPwdAge", -1);
3436                 ac->status->domain_data.minPwdAge =
3437                         ldb_msg_find_attr_as_int64(ares->message, "minPwdAge", -1);
3438                 ac->status->domain_data.minPwdLength =
3439                         ldb_msg_find_attr_as_uint(ares->message, "minPwdLength", -1);
3440                 ac->status->domain_data.store_cleartext =
3441                         ac->status->domain_data.pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT;
3442
3443                 /* For a domain DN, this puts things in dotted notation */
3444                 /* For builtin domains, this will give details for the host,
3445                  * but that doesn't really matter, as it's just used for salt
3446                  * and kerberos principals, which don't exist here */
3447
3448                 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
3449                                          struct loadparm_context);
3450
3451                 ac->status->domain_data.dns_domain = lpcfg_dnsdomain(lp_ctx);
3452                 ac->status->domain_data.realm = lpcfg_realm(lp_ctx);
3453                 ac->status->domain_data.netbios_domain = lpcfg_sam_name(lp_ctx);
3454
3455                 ac->status->reject_reason = SAM_PWD_CHANGE_NO_ERROR;
3456
3457                 if (ac->dom_res != NULL) {
3458                         talloc_free(ares);
3459
3460                         ldb_set_errstring(ldb, "Too many results");
3461                         ret = LDB_ERR_OPERATIONS_ERROR;
3462                         goto done;
3463                 }
3464
3465                 ac->dom_res = talloc_steal(ac, ares);
3466                 ret = LDB_SUCCESS;
3467                 break;
3468
3469         case LDB_REPLY_REFERRAL:
3470                 /* ignore */
3471                 talloc_free(ares);
3472                 ret = LDB_SUCCESS;
3473                 break;
3474
3475         case LDB_REPLY_DONE:
3476                 talloc_free(ares);
3477                 /* call the next step */
3478                 switch (ac->req->operation) {
3479                 case LDB_ADD:
3480                         ret = password_hash_add_do_add(ac);
3481                         break;
3482
3483                 case LDB_MODIFY:
3484                         ret = password_hash_mod_do_mod(ac);
3485                         break;
3486
3487                 default:
3488                         ret = LDB_ERR_OPERATIONS_ERROR;
3489                         break;
3490                 }
3491                 break;
3492         }
3493
3494 done:
3495         if (ret != LDB_SUCCESS) {
3496                 struct ldb_reply *new_ares;
3497
3498                 new_ares = talloc_zero(ac->req, struct ldb_reply);
3499                 if (new_ares == NULL) {
3500                         ldb_oom(ldb);
3501                         return ldb_module_done(ac->req, NULL, NULL,
3502                                                LDB_ERR_OPERATIONS_ERROR);
3503                 }
3504
3505                 new_ares->error = ret;
3506                 if ((ret != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
3507                         /* On success and trivial errors a status control is being
3508                          * added (used for example by the "samdb_set_password" call) */
3509                         ldb_reply_add_control(new_ares,
3510                                               DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
3511                                               false,
3512                                               ac->status);
3513                 }
3514
3515                 return ldb_module_done(ac->req, new_ares->controls,
3516                                        new_ares->response, new_ares->error);
3517         }
3518
3519         return LDB_SUCCESS;
3520 }
3521
3522 static int build_domain_data_request(struct ph_context *ac)
3523 {
3524         /* attrs[] is returned from this function in
3525            ac->dom_req->op.search.attrs, so it must be static, as
3526            otherwise the compiler can put it on the stack */
3527         struct ldb_context *ldb;
3528         static const char * const attrs[] = { "pwdProperties",
3529                                               "pwdHistoryLength",
3530                                               "maxPwdAge",
3531                                               "minPwdAge",
3532                                               "minPwdLength",
3533                                               "lockoutThreshold",
3534                                               "lockOutObservationWindow",
3535                                               NULL };
3536         int ret;
3537
3538         ldb = ldb_module_get_ctx(ac->module);
3539
3540         ret = ldb_build_search_req(&ac->dom_req, ldb, ac,
3541                                    ldb_get_default_basedn(ldb),
3542                                    LDB_SCOPE_BASE,
3543                                    NULL, attrs,
3544                                    NULL,
3545                                    ac, get_domain_data_callback,
3546                                    ac->req);
3547         LDB_REQ_SET_LOCATION(ac->dom_req);
3548         return ret;
3549 }
3550
3551 static int password_hash_needed(struct ldb_module *module,
3552                                 struct ldb_request *req,
3553                                 struct ph_context **_ac)
3554 {
3555         struct ldb_context *ldb = ldb_module_get_ctx(module);
3556         const char *operation = NULL;
3557         const struct ldb_message *msg = NULL;
3558         struct ph_context *ac = NULL;
3559         const char *passwordAttrs[] = {
3560                 "userPassword",
3561                 "clearTextPassword",
3562                 "unicodePwd",
3563                 "dBCSPwd",
3564                 NULL
3565         };
3566         const char **a = NULL;
3567         unsigned int attr_cnt = 0;
3568         struct ldb_control *bypass = NULL;
3569         struct ldb_control *uac_ctrl = NULL;
3570         bool userPassword = dsdb_user_password_support(module, req, req);
3571         bool update_password = false;
3572         bool processing_needed = false;
3573
3574         *_ac = NULL;
3575
3576         ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_needed\n");
3577
3578         switch (req->operation) {
3579         case LDB_ADD:
3580                 operation = "add";
3581                 msg = req->op.add.message;
3582                 break;
3583         case LDB_MODIFY:
3584                 operation = "modify";
3585                 msg = req->op.mod.message;
3586                 break;
3587         default:
3588                 return ldb_next_request(module, req);
3589         }
3590
3591         if (ldb_dn_is_special(msg->dn)) { /* do not manipulate our control entries */
3592                 return ldb_next_request(module, req);
3593         }
3594
3595         bypass = ldb_request_get_control(req,
3596                                          DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID);
3597         if (bypass != NULL) {
3598                 /* Mark the "bypass" control as uncritical (done) */
3599                 bypass->critical = false;
3600                 ldb_debug(ldb, LDB_DEBUG_TRACE,
3601                           "password_hash_needed(%s) (bypassing)\n",
3602                           operation);
3603                 return password_hash_bypass(module, req);
3604         }
3605
3606         /* nobody must touch password histories and 'supplementalCredentials' */
3607         if (ldb_msg_find_element(msg, "ntPwdHistory")) {
3608                 return LDB_ERR_UNWILLING_TO_PERFORM;
3609         }
3610         if (ldb_msg_find_element(msg, "lmPwdHistory")) {
3611                 return LDB_ERR_UNWILLING_TO_PERFORM;
3612         }
3613         if (ldb_msg_find_element(msg, "supplementalCredentials")) {
3614                 return LDB_ERR_UNWILLING_TO_PERFORM;
3615         }
3616
3617         /*
3618          * If no part of this touches the 'userPassword' OR 'clearTextPassword'
3619          * OR 'unicodePwd' OR 'dBCSPwd' we don't need to make any changes.
3620          * For password changes/set there should be a 'delete' or a 'modify'
3621          * on these attributes.
3622          */
3623         for (a = passwordAttrs; *a != NULL; a++) {
3624                 if ((!userPassword) && (ldb_attr_cmp(*a, "userPassword") == 0)) {
3625                         continue;
3626                 }
3627
3628                 if (ldb_msg_find_element(msg, *a) != NULL) {
3629                         /* MS-ADTS 3.1.1.3.1.5.2 */
3630                         if ((ldb_attr_cmp(*a, "userPassword") == 0) &&
3631                             (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003)) {
3632                                 return LDB_ERR_CONSTRAINT_VIOLATION;
3633                         }
3634
3635                         ++attr_cnt;
3636                 }
3637         }
3638
3639         if (attr_cnt > 0) {
3640                 update_password = true;
3641                 processing_needed = true;
3642         }
3643
3644         if (ldb_msg_find_element(msg, "pwdLastSet")) {
3645                 processing_needed = true;
3646         }
3647
3648         uac_ctrl = ldb_request_get_control(req,
3649                                 DSDB_CONTROL_PASSWORD_USER_ACCOUNT_CONTROL_OID);
3650         if (uac_ctrl != NULL) {
3651                 struct dsdb_control_password_user_account_control *uac = NULL;
3652                 uint32_t added_flags = 0;
3653
3654                 uac = talloc_get_type_abort(uac_ctrl->data,
3655                         struct dsdb_control_password_user_account_control);
3656
3657                 added_flags = uac->new_flags & ~uac->old_flags;
3658
3659                 if (added_flags & UF_SMARTCARD_REQUIRED) {
3660                         processing_needed = true;
3661                 }
3662         }
3663
3664         if (!processing_needed) {
3665                 return ldb_next_request(module, req);
3666         }
3667
3668         ac = ph_init_context(module, req, userPassword, update_password);
3669         if (!ac) {
3670                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
3671                 return ldb_operr(ldb);
3672         }
3673         ph_apply_controls(ac);
3674
3675         /*
3676          * Make a copy in order to apply our modifications
3677          * to the final update
3678          */
3679         ac->update_msg = ldb_msg_copy_shallow(ac, msg);
3680         if (ac->update_msg == NULL) {
3681                 return ldb_oom(ldb);
3682         }
3683
3684         /*
3685          * Remove all password related attributes.
3686          */
3687         if (ac->userPassword) {
3688                 ldb_msg_remove_attr(ac->update_msg, "userPassword");
3689         }
3690         ldb_msg_remove_attr(ac->update_msg, "clearTextPassword");
3691         ldb_msg_remove_attr(ac->update_msg, "unicodePwd");
3692         ldb_msg_remove_attr(ac->update_msg, "ntPwdHistory");
3693         ldb_msg_remove_attr(ac->update_msg, "dBCSPwd");
3694         ldb_msg_remove_attr(ac->update_msg, "lmPwdHistory");
3695         ldb_msg_remove_attr(ac->update_msg, "supplementalCredentials");
3696         ldb_msg_remove_attr(ac->update_msg, "pwdLastSet");
3697
3698         *_ac = ac;
3699         return LDB_SUCCESS;
3700 }
3701
3702 static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
3703 {
3704         struct ldb_context *ldb = ldb_module_get_ctx(module);
3705         struct ph_context *ac = NULL;
3706         int ret;
3707
3708         ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_add\n");
3709
3710         ret = password_hash_needed(module, req, &ac);
3711         if (ret != LDB_SUCCESS) {
3712                 return ret;
3713         }
3714         if (ac == NULL) {
3715                 return ret;
3716         }
3717
3718         /* Make sure we are performing the password set action on a (for us)
3719          * valid object. Those are instances of either "user" and/or
3720          * "inetOrgPerson". Otherwise continue with the submodules. */
3721         if ((!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "user"))
3722                 && (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "inetOrgPerson"))) {
3723
3724                 TALLOC_FREE(ac);
3725
3726                 if (ldb_msg_find_element(req->op.add.message, "clearTextPassword") != NULL) {
3727                         ldb_set_errstring(ldb,
3728                                           "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
3729                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
3730                 }
3731
3732                 return ldb_next_request(module, req);
3733         }
3734
3735         /* get user domain data */
3736         ret = build_domain_data_request(ac);
3737         if (ret != LDB_SUCCESS) {
3738                 return ret;
3739         }
3740
3741         return ldb_next_request(module, ac->dom_req);
3742 }
3743
3744 static int password_hash_add_do_add(struct ph_context *ac)
3745 {
3746         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3747         struct ldb_request *down_req;
3748         struct setup_password_fields_io io;
3749         int ret;
3750
3751         /* Prepare the internal data structure containing the passwords */
3752         ret = setup_io(ac, ac->req->op.add.message, NULL, &io);
3753         if (ret != LDB_SUCCESS) {
3754                 return ret;
3755         }
3756
3757         ret = setup_password_fields(&io);
3758         if (ret != LDB_SUCCESS) {
3759                 return ret;
3760         }
3761
3762         ret = check_password_restrictions(&io);
3763         if (ret != LDB_SUCCESS) {
3764                 return ret;
3765         }
3766
3767         ret = setup_smartcard_reset(&io);
3768         if (ret != LDB_SUCCESS) {
3769                 return ret;
3770         }
3771
3772         ret = update_final_msg(&io);
3773         if (ret != LDB_SUCCESS) {
3774                 return ret;
3775         }
3776
3777         ret = ldb_build_add_req(&down_req, ldb, ac,
3778                                 ac->update_msg,
3779                                 ac->req->controls,
3780                                 ac, ph_op_callback,
3781                                 ac->req);
3782         LDB_REQ_SET_LOCATION(down_req);
3783         if (ret != LDB_SUCCESS) {
3784                 return ret;
3785         }
3786
3787         return ldb_next_request(ac->module, down_req);
3788 }
3789
3790 static int password_hash_modify(struct ldb_module *module, struct ldb_request *req)
3791 {
3792         struct ldb_context *ldb = ldb_module_get_ctx(module);
3793         struct ph_context *ac = NULL;
3794         const char *passwordAttrs[] = { "userPassword", "clearTextPassword",
3795                 "unicodePwd", "dBCSPwd", NULL }, **l;
3796         unsigned int del_attr_cnt, add_attr_cnt, rep_attr_cnt;
3797         struct ldb_message_element *passwordAttr;
3798         struct ldb_message *msg;
3799         struct ldb_request *down_req;
3800         struct ldb_control *restore = NULL;
3801         int ret;
3802         unsigned int i = 0;
3803
3804         ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_modify\n");
3805
3806         ret = password_hash_needed(module, req, &ac);
3807         if (ret != LDB_SUCCESS) {
3808                 return ret;
3809         }
3810         if (ac == NULL) {
3811                 return ret;
3812         }
3813
3814         /* use a new message structure so that we can modify it */
3815         msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
3816         if (msg == NULL) {
3817                 return ldb_oom(ldb);
3818         }
3819
3820         /* - check for single-valued password attributes
3821          *   (if not return "CONSTRAINT_VIOLATION")
3822          * - check that for a password change operation one add and one delete
3823          *   operation exists
3824          *   (if not return "CONSTRAINT_VIOLATION" or "UNWILLING_TO_PERFORM")
3825          * - check that a password change and a password set operation cannot
3826          *   be mixed
3827          *   (if not return "UNWILLING_TO_PERFORM")
3828          * - remove all password attributes modifications from the first change
3829          *   operation (anything without the passwords) - we will make the real
3830          *   modification later */
3831         del_attr_cnt = 0;
3832         add_attr_cnt = 0;
3833         rep_attr_cnt = 0;
3834         for (l = passwordAttrs; *l != NULL; l++) {
3835                 if ((!ac->userPassword) &&
3836                     (ldb_attr_cmp(*l, "userPassword") == 0)) {
3837                         continue;
3838                 }
3839
3840                 while ((passwordAttr = ldb_msg_find_element(msg, *l)) != NULL) {
3841                         if (LDB_FLAG_MOD_TYPE(passwordAttr->flags) == LDB_FLAG_MOD_DELETE) {
3842                                 ++del_attr_cnt;
3843                         }
3844                         if (LDB_FLAG_MOD_TYPE(passwordAttr->flags) == LDB_FLAG_MOD_ADD) {
3845                                 ++add_attr_cnt;
3846                         }
3847                         if (LDB_FLAG_MOD_TYPE(passwordAttr->flags) == LDB_FLAG_MOD_REPLACE) {
3848                                 ++rep_attr_cnt;
3849                         }
3850                         if ((passwordAttr->num_values != 1) &&
3851                             (LDB_FLAG_MOD_TYPE(passwordAttr->flags) == LDB_FLAG_MOD_ADD)) {
3852                                 talloc_free(ac);
3853                                 ldb_asprintf_errstring(ldb,
3854                                                        "'%s' attribute must have exactly one value on add operations!",
3855                                                        *l);
3856                                 return LDB_ERR_CONSTRAINT_VIOLATION;
3857                         }
3858                         if ((passwordAttr->num_values > 1) &&
3859                             (LDB_FLAG_MOD_TYPE(passwordAttr->flags) == LDB_FLAG_MOD_DELETE)) {
3860                                 talloc_free(ac);
3861                                 ldb_asprintf_errstring(ldb,
3862                                                        "'%s' attribute must have zero or one value(s) on delete operations!",
3863                                                        *l);
3864                                 return LDB_ERR_CONSTRAINT_VIOLATION;
3865                         }
3866                         ldb_msg_remove_element(msg, passwordAttr);
3867                 }
3868         }
3869         if ((del_attr_cnt == 0) && (add_attr_cnt > 0)) {
3870                 talloc_free(ac);
3871                 ldb_set_errstring(ldb,
3872                                   "Only the add action for a password change specified!");
3873                 return LDB_ERR_UNWILLING_TO_PERFORM;
3874         }
3875         if ((del_attr_cnt > 1) || (add_attr_cnt > 1)) {
3876                 talloc_free(ac);
3877                 ldb_set_errstring(ldb,
3878                                   "Only one delete and one add action for a password change allowed!");
3879                 return LDB_ERR_UNWILLING_TO_PERFORM;
3880         }
3881         if ((rep_attr_cnt > 0) && ((del_attr_cnt > 0) || (add_attr_cnt > 0))) {
3882                 talloc_free(ac);
3883                 ldb_set_errstring(ldb,
3884                                   "Either a password change or a password set operation is allowed!");
3885                 return LDB_ERR_UNWILLING_TO_PERFORM;
3886         }
3887
3888         restore = ldb_request_get_control(req,
3889                                         DSDB_CONTROL_RESTORE_TOMBSTONE_OID);
3890         if (restore == NULL) {
3891                 /*
3892                  * A tomstone reanimation generates a double update
3893                  * of pwdLastSet.
3894                  *
3895                  * So we only remove it without the
3896                  * DSDB_CONTROL_RESTORE_TOMBSTONE_OID control.
3897                  */
3898                 ldb_msg_remove_attr(msg, "pwdLastSet");
3899         }
3900
3901
3902         /* if there was nothing else to be modified skip to next step */
3903         if (msg->num_elements == 0) {
3904                 return password_hash_mod_search_self(ac);
3905         }
3906
3907         /*
3908          * Now we apply all changes remaining in msg
3909          * and remove them from our final update_msg
3910          */
3911
3912         for (i = 0; i < msg->num_elements; i++) {
3913                 ldb_msg_remove_attr(ac->update_msg,
3914                                     msg->elements[i].name);
3915         }
3916
3917         ret = ldb_build_mod_req(&down_req, ldb, ac,
3918                                 msg,
3919                                 req->controls,
3920                                 ac, ph_modify_callback,
3921                                 req);
3922         LDB_REQ_SET_LOCATION(down_req);
3923         if (ret != LDB_SUCCESS) {
3924                 return ret;
3925         }
3926
3927         return ldb_next_request(module, down_req);
3928 }
3929
3930 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
3931 {
3932         struct ph_context *ac;
3933
3934         ac = talloc_get_type(req->context, struct ph_context);
3935
3936         if (!ares) {
3937                 return ldb_module_done(ac->req, NULL, NULL,
3938                                         LDB_ERR_OPERATIONS_ERROR);
3939         }
3940
3941         if (ares->type == LDB_REPLY_REFERRAL) {
3942                 return ldb_module_send_referral(ac->req, ares->referral);
3943         }
3944
3945         if (ares->error != LDB_SUCCESS) {
3946                 return ldb_module_done(ac->req, ares->controls,
3947                                         ares->response, ares->error);
3948         }
3949
3950         if (ares->type != LDB_REPLY_DONE) {
3951                 talloc_free(ares);
3952                 return ldb_module_done(ac->req, NULL, NULL,
3953                                         LDB_ERR_OPERATIONS_ERROR);
3954         }
3955
3956         talloc_free(ares);
3957
3958         return password_hash_mod_search_self(ac);
3959 }
3960
3961 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares)
3962 {
3963         struct ldb_context *ldb;
3964         struct ph_context *ac;
3965         int ret = LDB_SUCCESS;
3966
3967         ac = talloc_get_type(req->context, struct ph_context);
3968         ldb = ldb_module_get_ctx(ac->module);
3969
3970         if (!ares) {
3971                 ret = LDB_ERR_OPERATIONS_ERROR;
3972                 goto done;
3973         }
3974         if (ares->error != LDB_SUCCESS) {
3975                 return ldb_module_done(ac->req, ares->controls,
3976                                         ares->response, ares->error);
3977         }
3978
3979         /* we are interested only in the single reply (base search) */
3980         switch (ares->type) {
3981         case LDB_REPLY_ENTRY:
3982                 /* Make sure we are performing the password change action on a
3983                  * (for us) valid object. Those are instances of either "user"
3984                  * and/or "inetOrgPerson". Otherwise continue with the
3985                  * submodules. */
3986                 if ((!ldb_msg_check_string_attribute(ares->message, "objectClass", "user"))
3987                         && (!ldb_msg_check_string_attribute(ares->message, "objectClass", "inetOrgPerson"))) {
3988                         talloc_free(ares);
3989
3990                         if (ldb_msg_find_element(ac->req->op.mod.message, "clearTextPassword") != NULL) {
3991                                 ldb_set_errstring(ldb,
3992                                                   "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
3993                                 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
3994                                 goto done;
3995                         }
3996
3997                         ret = ldb_next_request(ac->module, ac->req);
3998                         goto done;
3999                 }
4000
4001                 if (ac->search_res != NULL) {
4002                         talloc_free(ares);
4003
4004                         ldb_set_errstring(ldb, "Too many results");
4005                         ret = LDB_ERR_OPERATIONS_ERROR;
4006                         goto done;
4007                 }
4008
4009                 ac->search_res = talloc_steal(ac, ares);
4010                 ret = LDB_SUCCESS;
4011                 break;
4012
4013         case LDB_REPLY_REFERRAL:
4014                 /* ignore anything else for now */
4015                 talloc_free(ares);
4016                 ret = LDB_SUCCESS;
4017                 break;
4018
4019         case LDB_REPLY_DONE:
4020                 talloc_free(ares);
4021
4022                 /* get user domain data */
4023                 ret = build_domain_data_request(ac);
4024                 if (ret != LDB_SUCCESS) {
4025                         return ldb_module_done(ac->req, NULL, NULL, ret);
4026                 }
4027
4028                 ret = ldb_next_request(ac->module, ac->dom_req);
4029                 break;
4030         }
4031
4032 done:
4033         if (ret != LDB_SUCCESS) {
4034                 return ldb_module_done(ac->req, NULL, NULL, ret);
4035         }
4036
4037         return LDB_SUCCESS;
4038 }
4039
4040 static int password_hash_mod_search_self(struct ph_context *ac)
4041 {
4042         struct ldb_context *ldb;
4043         static const char * const attrs[] = { "objectClass",
4044                                               "userAccountControl",
4045                                               "msDS-User-Account-Control-Computed",
4046                                               "pwdLastSet",
4047                                               "sAMAccountName",
4048                                               "objectSid",
4049                                               "userPrincipalName",
4050                                               "supplementalCredentials",
4051                                               "lmPwdHistory",
4052                                               "ntPwdHistory",
4053                                               "dBCSPwd",
4054                                               "unicodePwd",
4055                                               "badPasswordTime",
4056                                               "badPwdCount",
4057                                               "lockoutTime",
4058                                               NULL };
4059         struct ldb_request *search_req;
4060         int ret;
4061
4062         ldb = ldb_module_get_ctx(ac->module);
4063
4064         ret = ldb_build_search_req(&search_req, ldb, ac,
4065                                    ac->req->op.mod.message->dn,
4066                                    LDB_SCOPE_BASE,
4067                                    "(objectclass=*)",
4068                                    attrs,
4069                                    NULL,
4070                                    ac, ph_mod_search_callback,
4071                                    ac->req);
4072         LDB_REQ_SET_LOCATION(search_req);
4073         if (ret != LDB_SUCCESS) {
4074                 return ret;
4075         }
4076
4077         return ldb_next_request(ac->module, search_req);
4078 }
4079
4080 static int password_hash_mod_do_mod(struct ph_context *ac)
4081 {
4082         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
4083         struct ldb_request *mod_req;
4084         struct setup_password_fields_io io;
4085         int ret;
4086
4087         /* Prepare the internal data structure containing the passwords */
4088         ret = setup_io(ac, ac->req->op.mod.message,
4089                        ac->search_res->message, &io);
4090         if (ret != LDB_SUCCESS) {
4091                 return ret;
4092         }
4093
4094         ret = setup_password_fields(&io);
4095         if (ret != LDB_SUCCESS) {
4096                 return ret;
4097         }
4098
4099         ret = check_password_restrictions(&io);
4100         if (ret != LDB_SUCCESS) {
4101                 return ret;
4102         }
4103
4104         ret = setup_smartcard_reset(&io);
4105         if (ret != LDB_SUCCESS) {
4106                 return ret;
4107         }
4108
4109         ret = update_final_msg(&io);
4110         if (ret != LDB_SUCCESS) {
4111                 return ret;
4112         }
4113
4114         ret = ldb_build_mod_req(&mod_req, ldb, ac,
4115                                 ac->update_msg,
4116                                 ac->req->controls,
4117                                 ac, ph_op_callback,
4118                                 ac->req);
4119         LDB_REQ_SET_LOCATION(mod_req);
4120         if (ret != LDB_SUCCESS) {
4121                 return ret;
4122         }
4123
4124         return ldb_next_request(ac->module, mod_req);
4125 }
4126
4127 static const struct ldb_module_ops ldb_password_hash_module_ops = {
4128         .name          = "password_hash",
4129         .add           = password_hash_add,
4130         .modify        = password_hash_modify
4131 };
4132
4133 int ldb_password_hash_module_init(const char *version)
4134 {
4135 #ifdef ENABLE_GPGME
4136         const char *gversion = NULL;
4137 #endif /* ENABLE_GPGME */
4138
4139         LDB_MODULE_CHECK_VERSION(version);
4140
4141 #ifdef ENABLE_GPGME
4142         /*
4143          * Note: this sets a SIGPIPE handler
4144          * if none is active already. See:
4145          * https://www.gnupg.org/documentation/manuals/gpgme/Signal-Handling.html#Signal-Handling
4146          */
4147         gversion = gpgme_check_version(GPGME_VERSION);
4148         if (gversion == NULL) {
4149                 fprintf(stderr, "%s() in %s version[%s]: "
4150                         "gpgme_check_version(%s) not available, "
4151                         "gpgme_check_version(NULL) => '%s'\n",
4152                         __func__, __FILE__, version,
4153                         GPGME_VERSION, gpgme_check_version(NULL));
4154                 return LDB_ERR_UNAVAILABLE;
4155         }
4156 #endif /* ENABLE_GPGME */
4157
4158         return ldb_register_module(&ldb_password_hash_module_ops);
4159 }