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