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