krb5-samba: interdomain trust uses different salt principal
[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_krbtgt;
134                 uint32_t restrictions;
135                 struct dom_sid *account_sid;
136         } u;
137
138         /* new credentials and old given credentials */
139         struct setup_password_fields_given {
140                 const struct ldb_val *cleartext_utf8;
141                 const struct ldb_val *cleartext_utf16;
142                 struct samr_Password *nt_hash;
143                 struct samr_Password *lm_hash;
144         } n, og;
145
146         /* old credentials */
147         struct {
148                 struct samr_Password *nt_hash;
149                 struct samr_Password *lm_hash;
150                 uint32_t nt_history_len;
151                 struct samr_Password *nt_history;
152                 uint32_t lm_history_len;
153                 struct samr_Password *lm_history;
154                 const struct ldb_val *supplemental;
155                 struct supplementalCredentialsBlob scb;
156         } o;
157
158         /* generated credentials */
159         struct {
160                 struct samr_Password *nt_hash;
161                 struct samr_Password *lm_hash;
162                 uint32_t nt_history_len;
163                 struct samr_Password *nt_history;
164                 uint32_t lm_history_len;
165                 struct samr_Password *lm_history;
166                 const char *salt;
167                 DATA_BLOB aes_256;
168                 DATA_BLOB aes_128;
169                 DATA_BLOB des_md5;
170                 DATA_BLOB des_crc;
171                 struct ldb_val supplemental;
172                 NTTIME last_set;
173         } g;
174 };
175
176 static int msg_find_old_and_new_pwd_val(const struct ldb_message *msg,
177                                         const char *name,
178                                         enum ldb_request_type operation,
179                                         const struct ldb_val **new_val,
180                                         const struct ldb_val **old_val);
181
182 static int password_hash_bypass(struct ldb_module *module, struct ldb_request *request)
183 {
184         struct ldb_context *ldb = ldb_module_get_ctx(module);
185         const struct ldb_message *msg;
186         struct ldb_message_element *nte;
187         struct ldb_message_element *lme;
188         struct ldb_message_element *nthe;
189         struct ldb_message_element *lmhe;
190         struct ldb_message_element *sce;
191
192         switch (request->operation) {
193         case LDB_ADD:
194                 msg = request->op.add.message;
195                 break;
196         case LDB_MODIFY:
197                 msg = request->op.mod.message;
198                 break;
199         default:
200                 return ldb_next_request(module, request);
201         }
202
203         /* nobody must touch password histories and 'supplementalCredentials' */
204         nte = dsdb_get_single_valued_attr(msg, "unicodePwd",
205                                           request->operation);
206         lme = dsdb_get_single_valued_attr(msg, "dBCSPwd",
207                                           request->operation);
208         nthe = dsdb_get_single_valued_attr(msg, "ntPwdHistory",
209                                            request->operation);
210         lmhe = dsdb_get_single_valued_attr(msg, "lmPwdHistory",
211                                            request->operation);
212         sce = dsdb_get_single_valued_attr(msg, "supplementalCredentials",
213                                           request->operation);
214
215 #define CHECK_HASH_ELEMENT(e, min, max) do {\
216         if (e && e->num_values) { \
217                 unsigned int _count; \
218                 if (e->num_values != 1) { \
219                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
220                                          "num_values != 1"); \
221                 } \
222                 if ((e->values[0].length % 16) != 0) { \
223                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
224                                          "length % 16 != 0"); \
225                 } \
226                 _count = e->values[0].length / 16; \
227                 if (_count < min) { \
228                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
229                                          "count < min"); \
230                 } \
231                 if (_count > max) { \
232                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, \
233                                          "count > max"); \
234                 } \
235         } \
236 } while (0)
237
238         CHECK_HASH_ELEMENT(nte, 1, 1);
239         CHECK_HASH_ELEMENT(lme, 1, 1);
240         CHECK_HASH_ELEMENT(nthe, 1, INT32_MAX);
241         CHECK_HASH_ELEMENT(lmhe, 1, INT32_MAX);
242
243         if (sce && sce->num_values) {
244                 enum ndr_err_code ndr_err;
245                 struct supplementalCredentialsBlob *scb;
246                 struct supplementalCredentialsPackage *scpp = NULL;
247                 struct supplementalCredentialsPackage *scpk = NULL;
248                 struct supplementalCredentialsPackage *scpkn = NULL;
249                 struct supplementalCredentialsPackage *scpct = NULL;
250                 DATA_BLOB scpbp = data_blob_null;
251                 DATA_BLOB scpbk = data_blob_null;
252                 DATA_BLOB scpbkn = data_blob_null;
253                 DATA_BLOB scpbct = data_blob_null;
254                 DATA_BLOB blob;
255                 uint32_t i;
256
257                 if (sce->num_values != 1) {
258                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
259                                          "num_values != 1");
260                 }
261
262                 scb = talloc_zero(request, struct supplementalCredentialsBlob);
263                 if (!scb) {
264                         return ldb_module_oom(module);
265                 }
266
267                 ndr_err = ndr_pull_struct_blob_all(&sce->values[0], scb, scb,
268                                 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
269                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
270                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
271                                          "ndr_pull_struct_blob_all");
272                 }
273
274                 if (scb->sub.num_packages < 2) {
275                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
276                                          "num_packages < 2");
277                 }
278
279                 for (i=0; i < scb->sub.num_packages; i++) {
280                         DATA_BLOB subblob;
281
282                         subblob = strhex_to_data_blob(scb, scb->sub.packages[i].data);
283                         if (subblob.data == NULL) {
284                                 return ldb_module_oom(module);
285                         }
286
287                         if (strcmp(scb->sub.packages[i].name, "Packages") == 0) {
288                                 if (scpp) {
289                                         return ldb_error(ldb,
290                                                          LDB_ERR_CONSTRAINT_VIOLATION,
291                                                          "Packages twice");
292                                 }
293                                 scpp = &scb->sub.packages[i];
294                                 scpbp = subblob;
295                                 continue;
296                         }
297                         if (strcmp(scb->sub.packages[i].name, "Primary:Kerberos") == 0) {
298                                 if (scpk) {
299                                         return ldb_error(ldb,
300                                                          LDB_ERR_CONSTRAINT_VIOLATION,
301                                                          "Primary:Kerberos twice");
302                                 }
303                                 scpk = &scb->sub.packages[i];
304                                 scpbk = subblob;
305                                 continue;
306                         }
307                         if (strcmp(scb->sub.packages[i].name, "Primary:Kerberos-Newer-Keys") == 0) {
308                                 if (scpkn) {
309                                         return ldb_error(ldb,
310                                                          LDB_ERR_CONSTRAINT_VIOLATION,
311                                                          "Primary:Kerberos-Newer-Keys twice");
312                                 }
313                                 scpkn = &scb->sub.packages[i];
314                                 scpbkn = subblob;
315                                 continue;
316                         }
317                         if (strcmp(scb->sub.packages[i].name, "Primary:CLEARTEXT") == 0) {
318                                 if (scpct) {
319                                         return ldb_error(ldb,
320                                                          LDB_ERR_CONSTRAINT_VIOLATION,
321                                                          "Primary:CLEARTEXT twice");
322                                 }
323                                 scpct = &scb->sub.packages[i];
324                                 scpbct = subblob;
325                                 continue;
326                         }
327
328                         data_blob_free(&subblob);
329                 }
330
331                 if (scpp == NULL) {
332                         return ldb_error(ldb,
333                                          LDB_ERR_CONSTRAINT_VIOLATION,
334                                          "Primary:Packages missing");
335                 }
336
337                 if (scpk == NULL) {
338                         /*
339                          * If Primary:Kerberos is missing w2k8r2 reboots
340                          * when a password is changed.
341                          */
342                         return ldb_error(ldb,
343                                          LDB_ERR_CONSTRAINT_VIOLATION,
344                                          "Primary:Kerberos missing");
345                 }
346
347                 if (scpp) {
348                         struct package_PackagesBlob *p;
349                         uint32_t n;
350
351                         p = talloc_zero(scb, struct package_PackagesBlob);
352                         if (p == NULL) {
353                                 return ldb_module_oom(module);
354                         }
355
356                         ndr_err = ndr_pull_struct_blob(&scpbp, p, p,
357                                         (ndr_pull_flags_fn_t)ndr_pull_package_PackagesBlob);
358                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
359                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
360                                                  "ndr_pull_struct_blob Packages");
361                         }
362
363                         if (p->names == NULL) {
364                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
365                                                  "Packages names == NULL");
366                         }
367
368                         for (n = 0; p->names[n]; n++) {
369                                 /* noop */
370                         }
371
372                         if (scb->sub.num_packages != (n + 1)) {
373                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
374                                                  "Packages num_packages != num_names + 1");
375                         }
376
377                         talloc_free(p);
378                 }
379
380                 if (scpk) {
381                         struct package_PrimaryKerberosBlob *k;
382
383                         k = talloc_zero(scb, struct package_PrimaryKerberosBlob);
384                         if (k == NULL) {
385                                 return ldb_module_oom(module);
386                         }
387
388                         ndr_err = ndr_pull_struct_blob(&scpbk, k, k,
389                                         (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
390                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
391                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
392                                                  "ndr_pull_struct_blob PrimaryKerberos");
393                         }
394
395                         if (k->version != 3) {
396                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
397                                                  "PrimaryKerberos version != 3");
398                         }
399
400                         if (k->ctr.ctr3.salt.string == NULL) {
401                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
402                                                  "PrimaryKerberos salt == NULL");
403                         }
404
405                         if (strlen(k->ctr.ctr3.salt.string) == 0) {
406                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
407                                                  "PrimaryKerberos strlen(salt) == 0");
408                         }
409
410                         if (k->ctr.ctr3.num_keys != 2) {
411                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
412                                                  "PrimaryKerberos num_keys != 2");
413                         }
414
415                         if (k->ctr.ctr3.num_old_keys > k->ctr.ctr3.num_keys) {
416                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
417                                                  "PrimaryKerberos num_old_keys > num_keys");
418                         }
419
420                         if (k->ctr.ctr3.keys[0].keytype != ENCTYPE_DES_CBC_MD5) {
421                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
422                                                  "PrimaryKerberos key[0] != DES_CBC_MD5");
423                         }
424                         if (k->ctr.ctr3.keys[1].keytype != ENCTYPE_DES_CBC_CRC) {
425                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
426                                                  "PrimaryKerberos key[1] != DES_CBC_CRC");
427                         }
428
429                         if (k->ctr.ctr3.keys[0].value_len != 8) {
430                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
431                                                  "PrimaryKerberos key[0] value_len != 8");
432                         }
433                         if (k->ctr.ctr3.keys[1].value_len != 8) {
434                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
435                                                  "PrimaryKerberos key[1] value_len != 8");
436                         }
437
438                         for (i = 0; i < k->ctr.ctr3.num_old_keys; i++) {
439                                 if (k->ctr.ctr3.old_keys[i].keytype ==
440                                     k->ctr.ctr3.keys[i].keytype &&
441                                     k->ctr.ctr3.old_keys[i].value_len ==
442                                     k->ctr.ctr3.keys[i].value_len) {
443                                         continue;
444                                 }
445
446                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
447                                                  "PrimaryKerberos old_keys type/value_len doesn't match");
448                         }
449
450                         talloc_free(k);
451                 }
452
453                 if (scpkn) {
454                         struct package_PrimaryKerberosBlob *k;
455
456                         k = talloc_zero(scb, struct package_PrimaryKerberosBlob);
457                         if (k == NULL) {
458                                 return ldb_module_oom(module);
459                         }
460
461                         ndr_err = ndr_pull_struct_blob(&scpbkn, k, k,
462                                         (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
463                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
464                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
465                                                  "ndr_pull_struct_blob PrimaryKerberosNeverKeys");
466                         }
467
468                         if (k->version != 4) {
469                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
470                                                  "KerberosNerverKeys version != 4");
471                         }
472
473                         if (k->ctr.ctr4.salt.string == NULL) {
474                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
475                                                  "KerberosNewerKeys salt == NULL");
476                         }
477
478                         if (strlen(k->ctr.ctr4.salt.string) == 0) {
479                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
480                                                  "KerberosNewerKeys strlen(salt) == 0");
481                         }
482
483                         if (k->ctr.ctr4.num_keys != 4) {
484                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
485                                                  "KerberosNewerKeys num_keys != 2");
486                         }
487
488                         if (k->ctr.ctr4.num_old_keys > k->ctr.ctr4.num_keys) {
489                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
490                                                  "KerberosNewerKeys num_old_keys > num_keys");
491                         }
492
493                         if (k->ctr.ctr4.num_older_keys > k->ctr.ctr4.num_old_keys) {
494                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
495                                                  "KerberosNewerKeys num_older_keys > num_old_keys");
496                         }
497
498                         if (k->ctr.ctr4.keys[0].keytype != ENCTYPE_AES256_CTS_HMAC_SHA1_96) {
499                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
500                                                  "KerberosNewerKeys key[0] != AES256");
501                         }
502                         if (k->ctr.ctr4.keys[1].keytype != ENCTYPE_AES128_CTS_HMAC_SHA1_96) {
503                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
504                                                  "KerberosNewerKeys key[1] != AES128");
505                         }
506                         if (k->ctr.ctr4.keys[2].keytype != ENCTYPE_DES_CBC_MD5) {
507                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
508                                                  "KerberosNewerKeys key[2] != DES_CBC_MD5");
509                         }
510                         if (k->ctr.ctr4.keys[3].keytype != ENCTYPE_DES_CBC_CRC) {
511                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
512                                                  "KerberosNewerKeys key[3] != DES_CBC_CRC");
513                         }
514
515                         if (k->ctr.ctr4.keys[0].value_len != 32) {
516                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
517                                                  "KerberosNewerKeys key[0] value_len != 32");
518                         }
519                         if (k->ctr.ctr4.keys[1].value_len != 16) {
520                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
521                                                  "KerberosNewerKeys key[1] value_len != 16");
522                         }
523                         if (k->ctr.ctr4.keys[2].value_len != 8) {
524                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
525                                                  "KerberosNewerKeys key[2] value_len != 8");
526                         }
527                         if (k->ctr.ctr4.keys[3].value_len != 8) {
528                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
529                                                  "KerberosNewerKeys key[3] value_len != 8");
530                         }
531
532                         /*
533                          * TODO:
534                          * Maybe we can check old and older keys here.
535                          * But we need to do some tests, if the old keys
536                          * can be taken from the PrimaryKerberos blob
537                          * (with only des keys), when the domain was upgraded
538                          * from w2k3 to w2k8.
539                          */
540
541                         talloc_free(k);
542                 }
543
544                 if (scpct) {
545                         struct package_PrimaryCLEARTEXTBlob *ct;
546
547                         ct = talloc_zero(scb, struct package_PrimaryCLEARTEXTBlob);
548                         if (ct == NULL) {
549                                 return ldb_module_oom(module);
550                         }
551
552                         ndr_err = ndr_pull_struct_blob(&scpbct, ct, ct,
553                                         (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryCLEARTEXTBlob);
554                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
555                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
556                                                  "ndr_pull_struct_blob PrimaryCLEARTEXT");
557                         }
558
559                         if ((ct->cleartext.length % 2) != 0) {
560                                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
561                                                  "PrimaryCLEARTEXT length % 2 != 0");
562                         }
563
564                         talloc_free(ct);
565                 }
566
567                 ndr_err = ndr_push_struct_blob(&blob, scb, scb,
568                                 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
569                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
570                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
571                                          "ndr_pull_struct_blob_all");
572                 }
573
574                 if (sce->values[0].length != blob.length) {
575                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
576                                          "supplementalCredentialsBlob length differ");
577                 }
578
579                 if (memcmp(sce->values[0].data, blob.data, blob.length) != 0) {
580                         return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION,
581                                          "supplementalCredentialsBlob memcmp differ");
582                 }
583
584                 talloc_free(scb);
585         }
586
587         ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_bypass - validated\n");
588         return ldb_next_request(module, request);
589 }
590
591 /* Get the NT hash, and fill it in as an entry in the password history, 
592    and specify it into io->g.nt_hash */
593
594 static int setup_nt_fields(struct setup_password_fields_io *io)
595 {
596         struct ldb_context *ldb;
597         uint32_t i;
598
599         io->g.nt_hash = io->n.nt_hash;
600         ldb = ldb_module_get_ctx(io->ac->module);
601
602         if (io->ac->status->domain_data.pwdHistoryLength == 0) {
603                 return LDB_SUCCESS;
604         }
605
606         /* We might not have an old NT password */
607         io->g.nt_history = talloc_array(io->ac,
608                                         struct samr_Password,
609                                         io->ac->status->domain_data.pwdHistoryLength);
610         if (!io->g.nt_history) {
611                 return ldb_oom(ldb);
612         }
613
614         for (i = 0; i < MIN(io->ac->status->domain_data.pwdHistoryLength-1,
615                             io->o.nt_history_len); i++) {
616                 io->g.nt_history[i+1] = io->o.nt_history[i];
617         }
618         io->g.nt_history_len = i + 1;
619
620         if (io->g.nt_hash) {
621                 io->g.nt_history[0] = *io->g.nt_hash;
622         } else {
623                 /* 
624                  * TODO: is this correct?
625                  * the simular behavior is correct for the lm history case
626                  */
627                 E_md4hash("", io->g.nt_history[0].hash);
628         }
629
630         return LDB_SUCCESS;
631 }
632
633 /* Get the LANMAN hash, and fill it in as an entry in the password history, 
634    and specify it into io->g.lm_hash */
635
636 static int setup_lm_fields(struct setup_password_fields_io *io)
637 {
638         struct ldb_context *ldb;
639         uint32_t i;
640
641         io->g.lm_hash = io->n.lm_hash;
642         ldb = ldb_module_get_ctx(io->ac->module);
643
644         if (io->ac->status->domain_data.pwdHistoryLength == 0) {
645                 return LDB_SUCCESS;
646         }
647
648         /* We might not have an old LM password */
649         io->g.lm_history = talloc_array(io->ac,
650                                         struct samr_Password,
651                                         io->ac->status->domain_data.pwdHistoryLength);
652         if (!io->g.lm_history) {
653                 return ldb_oom(ldb);
654         }
655
656         for (i = 0; i < MIN(io->ac->status->domain_data.pwdHistoryLength-1,
657                             io->o.lm_history_len); i++) {
658                 io->g.lm_history[i+1] = io->o.lm_history[i];
659         }
660         io->g.lm_history_len = i + 1;
661
662         if (io->g.lm_hash) {
663                 io->g.lm_history[0] = *io->g.lm_hash;
664         } else {
665                 E_deshash("", io->g.lm_history[0].hash);
666         }
667
668         return LDB_SUCCESS;
669 }
670
671 static int setup_kerberos_keys(struct setup_password_fields_io *io)
672 {
673         struct ldb_context *ldb;
674         krb5_error_code krb5_ret;
675         char *salt_principal = NULL;
676         char *salt_data = NULL;
677         krb5_data salt;
678         krb5_keyblock key;
679         krb5_data cleartext_data;
680         uint32_t uac_flags = 0;
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         uac_flags = io->u.userAccountControl & UF_ACCOUNT_TYPE_MASK;
687         krb5_ret = smb_krb5_salt_principal(io->ac->status->domain_data.realm,
688                                            io->u.sAMAccountName,
689                                            io->u.user_principal_name,
690                                            uac_flags,
691                                            io->ac,
692                                            &salt_principal);
693         if (krb5_ret) {
694                 ldb_asprintf_errstring(ldb,
695                                        "setup_kerberos_keys: "
696                                        "generation of a salting principal failed: %s",
697                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
698                                                                   krb5_ret, io->ac));
699                 return LDB_ERR_OPERATIONS_ERROR;
700         }
701
702         /*
703          * create salt from salt_principal
704          */
705         krb5_ret = smb_krb5_salt_principal2data(io->smb_krb5_context->krb5_context,
706                                                 salt_principal, io->ac, &salt_data);
707         if (krb5_ret) {
708                 ldb_asprintf_errstring(ldb,
709                                        "setup_kerberos_keys: "
710                                        "generation of krb5_salt failed: %s",
711                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
712                                                                   krb5_ret, io->ac));
713                 return LDB_ERR_OPERATIONS_ERROR;
714         }
715         io->g.salt = salt_data;
716
717         /* now use the talloced copy of the salt */
718         salt.data       = discard_const(io->g.salt);
719         salt.length     = strlen(io->g.salt);
720
721         /*
722          * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of
723          * the salt and the cleartext password
724          */
725         krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
726                                                    NULL,
727                                                    &salt,
728                                                    &cleartext_data,
729                                                    ENCTYPE_AES256_CTS_HMAC_SHA1_96,
730                                                    &key);
731         if (krb5_ret) {
732                 ldb_asprintf_errstring(ldb,
733                                        "setup_kerberos_keys: "
734                                        "generation of a aes256-cts-hmac-sha1-96 key failed: %s",
735                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
736                                                                   krb5_ret, io->ac));
737                 return LDB_ERR_OPERATIONS_ERROR;
738         }
739         io->g.aes_256 = data_blob_talloc(io->ac,
740                                          KRB5_KEY_DATA(&key),
741                                          KRB5_KEY_LENGTH(&key));
742         krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
743         if (!io->g.aes_256.data) {
744                 return ldb_oom(ldb);
745         }
746
747         /*
748          * create ENCTYPE_AES128_CTS_HMAC_SHA1_96 key out of
749          * the salt and the cleartext password
750          */
751         krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
752                                                    NULL,
753                                                    &salt,
754                                                    &cleartext_data,
755                                                    ENCTYPE_AES128_CTS_HMAC_SHA1_96,
756                                                    &key);
757         if (krb5_ret) {
758                 ldb_asprintf_errstring(ldb,
759                                        "setup_kerberos_keys: "
760                                        "generation of a aes128-cts-hmac-sha1-96 key failed: %s",
761                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
762                                                                   krb5_ret, io->ac));
763                 return LDB_ERR_OPERATIONS_ERROR;
764         }
765         io->g.aes_128 = data_blob_talloc(io->ac,
766                                          KRB5_KEY_DATA(&key),
767                                          KRB5_KEY_LENGTH(&key));
768         krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
769         if (!io->g.aes_128.data) {
770                 return ldb_oom(ldb);
771         }
772
773         /*
774          * create ENCTYPE_DES_CBC_MD5 key out of
775          * the salt and the cleartext password
776          */
777         krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
778                                                    NULL,
779                                                    &salt,
780                                                    &cleartext_data,
781                                                    ENCTYPE_DES_CBC_MD5,
782                                                    &key);
783         if (krb5_ret) {
784                 ldb_asprintf_errstring(ldb,
785                                        "setup_kerberos_keys: "
786                                        "generation of a des-cbc-md5 key failed: %s",
787                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
788                                                                   krb5_ret, io->ac));
789                 return LDB_ERR_OPERATIONS_ERROR;
790         }
791         io->g.des_md5 = data_blob_talloc(io->ac,
792                                          KRB5_KEY_DATA(&key),
793                                          KRB5_KEY_LENGTH(&key));
794         krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
795         if (!io->g.des_md5.data) {
796                 return ldb_oom(ldb);
797         }
798
799         /*
800          * create ENCTYPE_DES_CBC_CRC key out of
801          * the salt and the cleartext password
802          */
803         krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context,
804                                                    NULL,
805                                                    &salt,
806                                                    &cleartext_data,
807                                                    ENCTYPE_DES_CBC_CRC,
808                                                    &key);
809         if (krb5_ret) {
810                 ldb_asprintf_errstring(ldb,
811                                        "setup_kerberos_keys: "
812                                        "generation of a des-cbc-crc key failed: %s",
813                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context,
814                                                                   krb5_ret, io->ac));
815                 return LDB_ERR_OPERATIONS_ERROR;
816         }
817         io->g.des_crc = data_blob_talloc(io->ac,
818                                          KRB5_KEY_DATA(&key),
819                                          KRB5_KEY_LENGTH(&key));
820         krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
821         if (!io->g.des_crc.data) {
822                 return ldb_oom(ldb);
823         }
824
825         return LDB_SUCCESS;
826 }
827
828 static int setup_primary_kerberos(struct setup_password_fields_io *io,
829                                   const struct supplementalCredentialsBlob *old_scb,
830                                   struct package_PrimaryKerberosBlob *pkb)
831 {
832         struct ldb_context *ldb;
833         struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3;
834         struct supplementalCredentialsPackage *old_scp = NULL;
835         struct package_PrimaryKerberosBlob _old_pkb;
836         struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL;
837         uint32_t i;
838         enum ndr_err_code ndr_err;
839
840         ldb = ldb_module_get_ctx(io->ac->module);
841
842         /*
843          * prepare generation of keys
844          *
845          * ENCTYPE_DES_CBC_MD5
846          * ENCTYPE_DES_CBC_CRC
847          */
848         pkb->version            = 3;
849         pkb3->salt.string       = io->g.salt;
850         pkb3->num_keys          = 2;
851         pkb3->keys              = talloc_array(io->ac,
852                                                struct package_PrimaryKerberosKey3,
853                                                pkb3->num_keys);
854         if (!pkb3->keys) {
855                 return ldb_oom(ldb);
856         }
857
858         pkb3->keys[0].keytype   = ENCTYPE_DES_CBC_MD5;
859         pkb3->keys[0].value     = &io->g.des_md5;
860         pkb3->keys[1].keytype   = ENCTYPE_DES_CBC_CRC;
861         pkb3->keys[1].value     = &io->g.des_crc;
862
863         /* initialize the old keys to zero */
864         pkb3->num_old_keys      = 0;
865         pkb3->old_keys          = NULL;
866
867         /* if there're no old keys, then we're done */
868         if (!old_scb) {
869                 return LDB_SUCCESS;
870         }
871
872         for (i=0; i < old_scb->sub.num_packages; i++) {
873                 if (strcmp("Primary:Kerberos", old_scb->sub.packages[i].name) != 0) {
874                         continue;
875                 }
876
877                 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
878                         continue;
879                 }
880
881                 old_scp = &old_scb->sub.packages[i];
882                 break;
883         }
884         /* Primary:Kerberos element of supplementalCredentials */
885         if (old_scp) {
886                 DATA_BLOB blob;
887
888                 blob = strhex_to_data_blob(io->ac, old_scp->data);
889                 if (!blob.data) {
890                         return ldb_oom(ldb);
891                 }
892
893                 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
894                 ndr_err = ndr_pull_struct_blob(&blob, io->ac, &_old_pkb,
895                                                (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
896                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
897                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
898                         ldb_asprintf_errstring(ldb,
899                                                "setup_primary_kerberos: "
900                                                "failed to pull old package_PrimaryKerberosBlob: %s",
901                                                nt_errstr(status));
902                         return LDB_ERR_OPERATIONS_ERROR;
903                 }
904
905                 if (_old_pkb.version != 3) {
906                         ldb_asprintf_errstring(ldb,
907                                                "setup_primary_kerberos: "
908                                                "package_PrimaryKerberosBlob version[%u] expected[3]",
909                                                _old_pkb.version);
910                         return LDB_ERR_OPERATIONS_ERROR;
911                 }
912
913                 old_pkb3 = &_old_pkb.ctr.ctr3;
914         }
915
916         /* if we didn't found the old keys we're done */
917         if (!old_pkb3) {
918                 return LDB_SUCCESS;
919         }
920
921         /* fill in the old keys */
922         pkb3->num_old_keys      = old_pkb3->num_keys;
923         pkb3->old_keys          = old_pkb3->keys;
924
925         return LDB_SUCCESS;
926 }
927
928 static int setup_primary_kerberos_newer(struct setup_password_fields_io *io,
929                                         const struct supplementalCredentialsBlob *old_scb,
930                                         struct package_PrimaryKerberosBlob *pkb)
931 {
932         struct ldb_context *ldb;
933         struct package_PrimaryKerberosCtr4 *pkb4 = &pkb->ctr.ctr4;
934         struct supplementalCredentialsPackage *old_scp = NULL;
935         struct package_PrimaryKerberosBlob _old_pkb;
936         struct package_PrimaryKerberosCtr4 *old_pkb4 = NULL;
937         uint32_t i;
938         enum ndr_err_code ndr_err;
939
940         ldb = ldb_module_get_ctx(io->ac->module);
941
942         /*
943          * prepare generation of keys
944          *
945          * ENCTYPE_AES256_CTS_HMAC_SHA1_96
946          * ENCTYPE_AES128_CTS_HMAC_SHA1_96
947          * ENCTYPE_DES_CBC_MD5
948          * ENCTYPE_DES_CBC_CRC
949          */
950         pkb->version                    = 4;
951         pkb4->salt.string               = io->g.salt;
952         pkb4->default_iteration_count   = 4096;
953         pkb4->num_keys                  = 4;
954
955         pkb4->keys = talloc_array(io->ac,
956                                   struct package_PrimaryKerberosKey4,
957                                   pkb4->num_keys);
958         if (!pkb4->keys) {
959                 return ldb_oom(ldb);
960         }
961
962         pkb4->keys[0].iteration_count   = 4096;
963         pkb4->keys[0].keytype           = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
964         pkb4->keys[0].value             = &io->g.aes_256;
965         pkb4->keys[1].iteration_count   = 4096;
966         pkb4->keys[1].keytype           = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
967         pkb4->keys[1].value             = &io->g.aes_128;
968         pkb4->keys[2].iteration_count   = 4096;
969         pkb4->keys[2].keytype           = ENCTYPE_DES_CBC_MD5;
970         pkb4->keys[2].value             = &io->g.des_md5;
971         pkb4->keys[3].iteration_count   = 4096;
972         pkb4->keys[3].keytype           = ENCTYPE_DES_CBC_CRC;
973         pkb4->keys[3].value             = &io->g.des_crc;
974
975         /* initialize the old keys to zero */
976         pkb4->num_old_keys      = 0;
977         pkb4->old_keys          = NULL;
978         pkb4->num_older_keys    = 0;
979         pkb4->older_keys        = NULL;
980
981         /* if there're no old keys, then we're done */
982         if (!old_scb) {
983                 return LDB_SUCCESS;
984         }
985
986         for (i=0; i < old_scb->sub.num_packages; i++) {
987                 if (strcmp("Primary:Kerberos-Newer-Keys", old_scb->sub.packages[i].name) != 0) {
988                         continue;
989                 }
990
991                 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
992                         continue;
993                 }
994
995                 old_scp = &old_scb->sub.packages[i];
996                 break;
997         }
998         /* Primary:Kerberos-Newer-Keys element of supplementalCredentials */
999         if (old_scp) {
1000                 DATA_BLOB blob;
1001
1002                 blob = strhex_to_data_blob(io->ac, old_scp->data);
1003                 if (!blob.data) {
1004                         return ldb_oom(ldb);
1005                 }
1006
1007                 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
1008                 ndr_err = ndr_pull_struct_blob(&blob, io->ac,
1009                                                &_old_pkb,
1010                                                (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
1011                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1012                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1013                         ldb_asprintf_errstring(ldb,
1014                                                "setup_primary_kerberos_newer: "
1015                                                "failed to pull old package_PrimaryKerberosBlob: %s",
1016                                                nt_errstr(status));
1017                         return LDB_ERR_OPERATIONS_ERROR;
1018                 }
1019
1020                 if (_old_pkb.version != 4) {
1021                         ldb_asprintf_errstring(ldb,
1022                                                "setup_primary_kerberos_newer: "
1023                                                "package_PrimaryKerberosBlob version[%u] expected[4]",
1024                                                _old_pkb.version);
1025                         return LDB_ERR_OPERATIONS_ERROR;
1026                 }
1027
1028                 old_pkb4 = &_old_pkb.ctr.ctr4;
1029         }
1030
1031         /* if we didn't found the old keys we're done */
1032         if (!old_pkb4) {
1033                 return LDB_SUCCESS;
1034         }
1035
1036         /* fill in the old keys */
1037         pkb4->num_old_keys      = old_pkb4->num_keys;
1038         pkb4->old_keys          = old_pkb4->keys;
1039         pkb4->num_older_keys    = old_pkb4->num_old_keys;
1040         pkb4->older_keys        = old_pkb4->old_keys;
1041
1042         return LDB_SUCCESS;
1043 }
1044
1045 static int setup_primary_wdigest(struct setup_password_fields_io *io,
1046                                  const struct supplementalCredentialsBlob *old_scb,
1047                                  struct package_PrimaryWDigestBlob *pdb)
1048 {
1049         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1050         DATA_BLOB sAMAccountName;
1051         DATA_BLOB sAMAccountName_l;
1052         DATA_BLOB sAMAccountName_u;
1053         const char *user_principal_name = io->u.user_principal_name;
1054         DATA_BLOB userPrincipalName;
1055         DATA_BLOB userPrincipalName_l;
1056         DATA_BLOB userPrincipalName_u;
1057         DATA_BLOB netbios_domain;
1058         DATA_BLOB netbios_domain_l;
1059         DATA_BLOB netbios_domain_u;
1060         DATA_BLOB dns_domain;
1061         DATA_BLOB dns_domain_l;
1062         DATA_BLOB dns_domain_u;
1063         DATA_BLOB digest;
1064         DATA_BLOB delim;
1065         DATA_BLOB backslash;
1066         uint8_t i;
1067         struct {
1068                 DATA_BLOB *user;
1069                 DATA_BLOB *realm;
1070                 DATA_BLOB *nt4dom;
1071         } wdigest[] = {
1072         /*
1073          * See 3.1.1.8.11.3.1 WDIGEST_CREDENTIALS Construction
1074          *     https://msdn.microsoft.com/en-us/library/cc245680.aspx
1075          * for what precalculated hashes are supposed to be stored...
1076          *
1077          * I can't reproduce all values which should contain "Digest" as realm,
1078          * am I doing something wrong or is w2k3 just broken...?
1079          *
1080          * W2K3 fills in following for a user:
1081          *
1082          * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1083          * sAMAccountName: NewUser2Sam
1084          * userPrincipalName: NewUser2Princ@sub1.w2k3.vmnet1.vm.base
1085          *
1086          * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1087          * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1088          * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1089          * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1090          * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1091          * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1092          * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1093          * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1094          * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1095          * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1096          * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1097          * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1098          * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1099          * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1100          * 221c55284451ae9b3aacaa2a3c86f10f => NewUser2Princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1101          * 74e1be668853d4324d38c07e2acfb8ea => (w2k3 has a bug here!) newuser2princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1102          * e1e244ab7f098e3ae1761be7f9229bbb => NEWUSER2PRINC@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1103          * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1104          * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1105          * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1106          * 31dc704d3640335b2123d4ee28aa1f11 => ??? changes with NewUser2Sam => NewUser1Sam
1107          * 36349f5cecd07320fb3bb0e119230c43 => ??? changes with NewUser2Sam => NewUser1Sam
1108          * 12adf019d037fb535c01fd0608e78d9d => ??? changes with NewUser2Sam => NewUser1Sam
1109          * 6feecf8e724906f3ee1105819c5105a1 => ??? changes with NewUser2Princ => NewUser1Princ
1110          * 6c6911f3de6333422640221b9c51ff1f => ??? changes with NewUser2Princ => NewUser1Princ
1111          * 4b279877e742895f9348ac67a8de2f69 => ??? changes with NewUser2Princ => NewUser1Princ
1112          * db0c6bff069513e3ebb9870d29b57490 => ??? changes with NewUser2Sam => NewUser1Sam
1113          * 45072621e56b1c113a4e04a8ff68cd0e => ??? changes with NewUser2Sam => NewUser1Sam
1114          * 11d1220abc44a9c10cf91ef4a9c1de02 => ??? changes with NewUser2Sam => NewUser1Sam
1115          *
1116          * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
1117          * sAMAccountName: NewUser2Sam
1118          *
1119          * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1120          * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
1121          * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
1122          * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
1123          * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
1124          * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
1125          * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
1126          * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1127          * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1128          * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1129          * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1130          * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1131          * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
1132          * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
1133          * 8a140d30b6f0a5912735dc1e3bc993b4 => NewUser2Sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1134          * 86d95b2faae6cae4ec261e7fbaccf093 => (here w2k3 is correct) newuser2sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
1135          * dfeff1493110220efcdfc6362e5f5450 => NEWUSER2SAM@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
1136          * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
1137          * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
1138          * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
1139          * 31dc704d3640335b2123d4ee28aa1f11 => ???M1   changes with NewUser2Sam => NewUser1Sam
1140          * 36349f5cecd07320fb3bb0e119230c43 => ???M1.L changes with newuser2sam => newuser1sam
1141          * 12adf019d037fb535c01fd0608e78d9d => ???M1.U changes with NEWUSER2SAM => NEWUSER1SAM
1142          * 569b4533f2d9e580211dd040e5e360a8 => ???M2   changes with NewUser2Princ => NewUser1Princ
1143          * 52528bddf310a587c5d7e6a9ae2cbb20 => ???M2.L changes with newuser2princ => newuser1princ
1144          * 4f629a4f0361289ca4255ab0f658fcd5 => ???M3 changes with NewUser2Princ => NewUser1Princ (doesn't depend on case of userPrincipal )
1145          * db0c6bff069513e3ebb9870d29b57490 => ???M4 changes with NewUser2Sam => NewUser1Sam
1146          * 45072621e56b1c113a4e04a8ff68cd0e => ???M5 changes with NewUser2Sam => NewUser1Sam (doesn't depend on case of sAMAccountName)
1147          * 11d1220abc44a9c10cf91ef4a9c1de02 => ???M4.U changes with NEWUSER2SAM => NEWUSER1SAM
1148          */
1149
1150         /*
1151          * sAMAccountName, netbios_domain
1152          */
1153                 {
1154                 .user   = &sAMAccountName,
1155                 .realm  = &netbios_domain,
1156                 },
1157                 {
1158                 .user   = &sAMAccountName_l,
1159                 .realm  = &netbios_domain_l,
1160                 },
1161                 {
1162                 .user   = &sAMAccountName_u,
1163                 .realm  = &netbios_domain_u,
1164                 },
1165                 {
1166                 .user   = &sAMAccountName,
1167                 .realm  = &netbios_domain_u,
1168                 },
1169                 {
1170                 .user   = &sAMAccountName,
1171                 .realm  = &netbios_domain_l,
1172                 },
1173                 {
1174                 .user   = &sAMAccountName_u,
1175                 .realm  = &netbios_domain_l,
1176                 },
1177                 {
1178                 .user   = &sAMAccountName_l,
1179                 .realm  = &netbios_domain_u,
1180                 },
1181         /*
1182          * sAMAccountName, dns_domain
1183          *
1184          * TODO:
1185          * Windows preserves the case of the DNS domain,
1186          * Samba lower cases the domain at provision time
1187          * This means that for mixed case Domains, the WDigest08 hash
1188          * calculated by Samba differs from that calculated by Windows.
1189          * Until we get a real world use case this will remain a known
1190          * bug, as changing the case could have unforeseen impacts.
1191          *
1192          */
1193                 {
1194                 .user   = &sAMAccountName,
1195                 .realm  = &dns_domain,
1196                 },
1197                 {
1198                 .user   = &sAMAccountName_l,
1199                 .realm  = &dns_domain_l,
1200                 },
1201                 {
1202                 .user   = &sAMAccountName_u,
1203                 .realm  = &dns_domain_u,
1204                 },
1205                 {
1206                 .user   = &sAMAccountName,
1207                 .realm  = &dns_domain_u,
1208                 },
1209                 {
1210                 .user   = &sAMAccountName,
1211                 .realm  = &dns_domain_l,
1212                 },
1213                 {
1214                 .user   = &sAMAccountName_u,
1215                 .realm  = &dns_domain_l,
1216                 },
1217                 {
1218                 .user   = &sAMAccountName_l,
1219                 .realm  = &dns_domain_u,
1220                 },
1221         /* 
1222          * userPrincipalName, no realm
1223          */
1224                 {
1225                 .user   = &userPrincipalName,
1226                 },
1227                 {
1228                 /* 
1229                  * NOTE: w2k3 messes this up, if the user has a real userPrincipalName,
1230                  *       the fallback to the sAMAccountName based userPrincipalName is correct
1231                  */
1232                 .user   = &userPrincipalName_l,
1233                 },
1234                 {
1235                 .user   = &userPrincipalName_u,
1236                 },
1237         /* 
1238          * nt4dom\sAMAccountName, no realm
1239          */
1240                 {
1241                 .user   = &sAMAccountName,
1242                 .nt4dom = &netbios_domain
1243                 },
1244                 {
1245                 .user   = &sAMAccountName_l,
1246                 .nt4dom = &netbios_domain_l
1247                 },
1248                 {
1249                 .user   = &sAMAccountName_u,
1250                 .nt4dom = &netbios_domain_u
1251                 },
1252
1253         /*
1254          * the following ones are guessed depending on the technet2 article
1255          * but not reproducable on a w2k3 server
1256          */
1257         /* sAMAccountName with "Digest" realm */
1258                 {
1259                 .user   = &sAMAccountName,
1260                 .realm  = &digest
1261                 },
1262                 {
1263                 .user   = &sAMAccountName_l,
1264                 .realm  = &digest
1265                 },
1266                 {
1267                 .user   = &sAMAccountName_u,
1268                 .realm  = &digest
1269                 },
1270         /* userPrincipalName with "Digest" realm */
1271                 {
1272                 .user   = &userPrincipalName,
1273                 .realm  = &digest
1274                 },
1275                 {
1276                 .user   = &userPrincipalName_l,
1277                 .realm  = &digest
1278                 },
1279                 {
1280                 .user   = &userPrincipalName_u,
1281                 .realm  = &digest
1282                 },
1283         /* nt4dom\\sAMAccountName with "Digest" realm */
1284                 {
1285                 .user   = &sAMAccountName,
1286                 .nt4dom = &netbios_domain,
1287                 .realm  = &digest
1288                 },
1289                 {
1290                 .user   = &sAMAccountName_l,
1291                 .nt4dom = &netbios_domain_l,
1292                 .realm  = &digest
1293                 },
1294                 {
1295                 .user   = &sAMAccountName_u,
1296                 .nt4dom = &netbios_domain_u,
1297                 .realm  = &digest
1298                 },
1299         };
1300
1301         /* prepare DATA_BLOB's used in the combinations array */
1302         sAMAccountName          = data_blob_string_const(io->u.sAMAccountName);
1303         sAMAccountName_l        = data_blob_string_const(strlower_talloc(io->ac, io->u.sAMAccountName));
1304         if (!sAMAccountName_l.data) {
1305                 return ldb_oom(ldb);
1306         }
1307         sAMAccountName_u        = data_blob_string_const(strupper_talloc(io->ac, io->u.sAMAccountName));
1308         if (!sAMAccountName_u.data) {
1309                 return ldb_oom(ldb);
1310         }
1311
1312         /* if the user doesn't have a userPrincipalName, create one (with lower case realm) */
1313         if (!user_principal_name) {
1314                 user_principal_name = talloc_asprintf(io->ac, "%s@%s",
1315                                                       io->u.sAMAccountName,
1316                                                       io->ac->status->domain_data.dns_domain);
1317                 if (!user_principal_name) {
1318                         return ldb_oom(ldb);
1319                 }       
1320         }
1321         userPrincipalName       = data_blob_string_const(user_principal_name);
1322         userPrincipalName_l     = data_blob_string_const(strlower_talloc(io->ac, user_principal_name));
1323         if (!userPrincipalName_l.data) {
1324                 return ldb_oom(ldb);
1325         }
1326         userPrincipalName_u     = data_blob_string_const(strupper_talloc(io->ac, user_principal_name));
1327         if (!userPrincipalName_u.data) {
1328                 return ldb_oom(ldb);
1329         }
1330
1331         netbios_domain          = data_blob_string_const(io->ac->status->domain_data.netbios_domain);
1332         netbios_domain_l        = data_blob_string_const(strlower_talloc(io->ac,
1333                                                                          io->ac->status->domain_data.netbios_domain));
1334         if (!netbios_domain_l.data) {
1335                 return ldb_oom(ldb);
1336         }
1337         netbios_domain_u        = data_blob_string_const(strupper_talloc(io->ac,
1338                                                                          io->ac->status->domain_data.netbios_domain));
1339         if (!netbios_domain_u.data) {
1340                 return ldb_oom(ldb);
1341         }
1342
1343         dns_domain              = data_blob_string_const(io->ac->status->domain_data.dns_domain);
1344         dns_domain_l            = data_blob_string_const(io->ac->status->domain_data.dns_domain);
1345         dns_domain_u            = data_blob_string_const(io->ac->status->domain_data.realm);
1346
1347         digest                  = data_blob_string_const("Digest");
1348
1349         delim                   = data_blob_string_const(":");
1350         backslash               = data_blob_string_const("\\");
1351
1352         pdb->num_hashes = ARRAY_SIZE(wdigest);
1353         pdb->hashes     = talloc_array(io->ac, struct package_PrimaryWDigestHash,
1354                                        pdb->num_hashes);
1355         if (!pdb->hashes) {
1356                 return ldb_oom(ldb);
1357         }
1358
1359         for (i=0; i < ARRAY_SIZE(wdigest); i++) {
1360                 MD5_CTX md5;
1361                 MD5Init(&md5);
1362                 if (wdigest[i].nt4dom) {
1363                         MD5Update(&md5, wdigest[i].nt4dom->data, wdigest[i].nt4dom->length);
1364                         MD5Update(&md5, backslash.data, backslash.length);
1365                 }
1366                 MD5Update(&md5, wdigest[i].user->data, wdigest[i].user->length);
1367                 MD5Update(&md5, delim.data, delim.length);
1368                 if (wdigest[i].realm) {
1369                         MD5Update(&md5, wdigest[i].realm->data, wdigest[i].realm->length);
1370                 }
1371                 MD5Update(&md5, delim.data, delim.length);
1372                 MD5Update(&md5, io->n.cleartext_utf8->data, io->n.cleartext_utf8->length);
1373                 MD5Final(pdb->hashes[i].hash, &md5);
1374         }
1375
1376         return LDB_SUCCESS;
1377 }
1378
1379 #define SHA_SALT_PERMITTED_CHARS "abcdefghijklmnopqrstuvwxyz" \
1380                                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
1381                                  "0123456789./"
1382 #define SHA_SALT_SIZE 16
1383 #define SHA_256_SCHEME "CryptSHA256"
1384 #define SHA_512_SCHEME "CryptSHA512"
1385 #define CRYPT "{CRYPT}"
1386 #define SHA_ID_LEN 3
1387 #define SHA_256_ALGORITHM_ID 5
1388 #define SHA_512_ALGORITHM_ID 6
1389 #define ROUNDS_PARAMETER "rounds="
1390
1391 /*
1392  * Extract the crypt (3) algorithm number and number of hash rounds from the
1393  * supplied scheme string
1394  */
1395 static bool parse_scheme(const char *scheme, int *algorithm, int *rounds) {
1396
1397         const char *rp = NULL; /* Pointer to the 'rounds=' option */
1398         char digits[21];       /* digits extracted from the rounds option */
1399         int i = 0;             /* loop index variable */
1400
1401         if (strncasecmp(SHA_256_SCHEME, scheme, strlen(SHA_256_SCHEME)) == 0) {
1402                 *algorithm = SHA_256_ALGORITHM_ID;
1403         } else if (strncasecmp(SHA_512_SCHEME, scheme, strlen(SHA_256_SCHEME))
1404                    == 0) {
1405                 *algorithm = SHA_512_ALGORITHM_ID;
1406         } else {
1407                 return false;
1408         }
1409
1410         rp = strcasestr(scheme, ROUNDS_PARAMETER);
1411         if (rp == NULL) {
1412                 /* No options specified, use crypt default number of rounds */
1413                 *rounds = 0;
1414                 return true;
1415         }
1416         rp += strlen(ROUNDS_PARAMETER);
1417         for (i = 0; isdigit(rp[i]) && i < (sizeof(digits) - 1); i++) {
1418                 digits[i] = rp[i];
1419         }
1420         digits[i] = '\0';
1421         *rounds = atoi(digits);
1422         return true;
1423 }
1424
1425 /*
1426  * Calculate the password hash specified by scheme, and return it in
1427  * hash_value
1428  */
1429 static int setup_primary_userPassword_hash(
1430         TALLOC_CTX *ctx,
1431         struct setup_password_fields_io *io,
1432         const char* scheme,
1433         struct package_PrimaryUserPasswordValue *hash_value)
1434 {
1435         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1436         const char *salt = NULL;        /* Randomly generated salt */
1437         const char *cmd = NULL;         /* command passed to crypt */
1438         const char *hash = NULL;        /* password hash generated by crypt */
1439         int algorithm = 0;              /* crypt hash algorithm number */
1440         int rounds = 0;                 /* The number of hash rounds */
1441         DATA_BLOB *hash_blob = NULL;
1442         TALLOC_CTX *frame = talloc_stackframe();
1443 #ifdef HAVE_CRYPT_R
1444         struct crypt_data crypt_data;   /* working storage used by crypt */
1445 #endif
1446
1447         /* Genrate a random password salt */
1448         salt = generate_random_str_list(frame,
1449                                         SHA_SALT_SIZE,
1450                                         SHA_SALT_PERMITTED_CHARS);
1451         if (salt == NULL) {
1452                 TALLOC_FREE(frame);
1453                 return ldb_oom(ldb);
1454         }
1455
1456         /* determine the hashing algoritm and number of rounds*/
1457         if (!parse_scheme(scheme, &algorithm, &rounds)) {
1458                 ldb_asprintf_errstring(
1459                         ldb,
1460                         "setup_primary_userPassword: Invalid scheme of [%s] "
1461                         "specified for 'password hash userPassword schemes' in "
1462                         "samba.conf",
1463                         scheme);
1464                 TALLOC_FREE(frame);
1465                 return LDB_ERR_OPERATIONS_ERROR;
1466         }
1467         hash_value->scheme = talloc_strdup(ctx, CRYPT);
1468         hash_value->scheme_len = strlen(CRYPT) + 1;
1469
1470         /* generate the id/salt parameter used by crypt */
1471         if (rounds) {
1472                 cmd = talloc_asprintf(frame,
1473                                       "$%d$rounds=%d$%s",
1474                                       algorithm,
1475                                       rounds,
1476                                       salt);
1477         } else {
1478                 cmd = talloc_asprintf(frame, "$%d$%s", algorithm, salt);
1479         }
1480
1481         /*
1482          * Relies on the assertion that cleartext_utf8->data is a zero
1483          * terminated UTF-8 string
1484          */
1485 #ifdef HAVE_CRYPT_R
1486         hash = crypt_r((char *)io->n.cleartext_utf8->data, cmd, &crypt_data);
1487 #else
1488         /*
1489          * No crypt_r falling back to crypt, which is NOT thread safe
1490          * Thread safety MT-Unsafe race:crypt
1491          */
1492         hash = crypt((char *)io->n.cleartext_utf8->data, cmd);
1493 #endif
1494         if (hash == NULL) {
1495                 char buf[1024];
1496                 int err = strerror_r(errno, buf, sizeof(buf));
1497                 if (err != 0) {
1498                         strlcpy(buf, "Unknown error", sizeof(buf)-1);
1499                 }
1500                 ldb_asprintf_errstring(
1501                         ldb,
1502                         "setup_primary_userPassword: generation of a %s "
1503                         "password hash failed: (%s)",
1504                         scheme,
1505                         buf);
1506                 TALLOC_FREE(frame);
1507                 return LDB_ERR_OPERATIONS_ERROR;
1508         }
1509
1510         hash_blob = talloc_zero(ctx, DATA_BLOB);
1511
1512         if (hash_blob == NULL) {
1513                 TALLOC_FREE(frame);
1514                 return ldb_oom(ldb);
1515         }
1516
1517         *hash_blob =  data_blob_talloc(hash_blob,
1518                                        (const uint8_t *)hash,
1519                                        strlen(hash));
1520         if (hash_blob->data == NULL) {
1521                 TALLOC_FREE(frame);
1522                 return ldb_oom(ldb);
1523         }
1524         hash_value->value = hash_blob;
1525         TALLOC_FREE(frame);
1526         return LDB_SUCCESS;
1527 }
1528
1529 /*
1530  * Calculate the desired extra password hashes
1531  */
1532 static int setup_primary_userPassword(
1533         struct setup_password_fields_io *io,
1534         const struct supplementalCredentialsBlob *old_scb,
1535         struct package_PrimaryUserPasswordBlob *p_userPassword_b)
1536 {
1537         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1538         TALLOC_CTX *frame = talloc_stackframe();
1539         int i;
1540         int ret;
1541
1542         /*
1543          * Save the current nt_hash, use this to determine if the password
1544          * has been changed by windows. Which will invalidate the userPassword
1545          * hash. Note once NTLM-Strong-NOWTF becomes available it should be
1546          * used in preference to the NT password hash
1547          */
1548         if (io->g.nt_hash == NULL) {
1549                 ldb_asprintf_errstring(ldb,
1550                         "No NT Hash, unable to calculate userPassword hashes");
1551                         return LDB_ERR_UNWILLING_TO_PERFORM;
1552         }
1553         p_userPassword_b->current_nt_hash = *io->g.nt_hash;
1554
1555         /*
1556          * Determine the number of hashes
1557          * Note: that currently there is no limit on the number of hashes
1558          *       no checking is done on the number of schemes specified
1559          *       or for uniqueness.
1560          */
1561         p_userPassword_b->num_hashes = 0;
1562         for (i = 0; io->ac->userPassword_schemes[i]; i++) {
1563                 p_userPassword_b->num_hashes++;
1564         }
1565
1566         p_userPassword_b->hashes
1567                 = talloc_array(io->ac,
1568                                struct package_PrimaryUserPasswordValue,
1569                                p_userPassword_b->num_hashes);
1570         if (p_userPassword_b->hashes == NULL) {
1571                 TALLOC_FREE(frame);
1572                 return ldb_oom(ldb);
1573         }
1574
1575         for (i = 0; io->ac->userPassword_schemes[i]; i++) {
1576                 ret = setup_primary_userPassword_hash(
1577                         p_userPassword_b->hashes,
1578                         io,
1579                         io->ac->userPassword_schemes[i],
1580                         &p_userPassword_b->hashes[i]);
1581                 if (ret != LDB_SUCCESS) {
1582                         TALLOC_FREE(frame);
1583                         return ret;
1584                 }
1585         }
1586         return LDB_SUCCESS;
1587 }
1588
1589
1590 static int setup_primary_samba_gpg(struct setup_password_fields_io *io,
1591                                    struct package_PrimarySambaGPGBlob *pgb)
1592 {
1593         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
1594 #ifdef ENABLE_GPGME
1595         gpgme_error_t gret;
1596         gpgme_ctx_t ctx = NULL;
1597         size_t num_keys = str_list_length(io->ac->gpg_key_ids);
1598         gpgme_key_t keys[num_keys+1];
1599         size_t ki = 0;
1600         size_t kr = 0;
1601         gpgme_data_t plain_data = NULL;
1602         gpgme_data_t crypt_data = NULL;
1603         size_t crypt_length = 0;
1604         char *crypt_mem = NULL;
1605
1606         gret = gpgme_new(&ctx);
1607         if (gret != GPG_ERR_NO_ERROR) {
1608                 ldb_debug(ldb, LDB_DEBUG_ERROR,
1609                           "%s:%s: gret[%u] %s\n",
1610                           __location__, __func__,
1611                           gret, gpgme_strerror(gret));
1612                 return ldb_module_operr(io->ac->module);
1613         }
1614
1615         gpgme_set_armor(ctx, 1);
1616
1617         gret = gpgme_data_new_from_mem(&plain_data,
1618                                        (const char *)io->n.cleartext_utf16->data,
1619                                        io->n.cleartext_utf16->length,
1620                                        0 /* no copy */);
1621         if (gret != GPG_ERR_NO_ERROR) {
1622                 ldb_debug(ldb, LDB_DEBUG_ERROR,
1623                           "%s:%s: gret[%u] %s\n",
1624                           __location__, __func__,
1625                           gret, gpgme_strerror(gret));
1626                 gpgme_release(ctx);
1627                 return ldb_module_operr(io->ac->module);
1628         }
1629         gret = gpgme_data_new(&crypt_data);
1630         if (gret != GPG_ERR_NO_ERROR) {
1631                 ldb_debug(ldb, LDB_DEBUG_ERROR,
1632                           "%s:%s: gret[%u] %s\n",
1633                           __location__, __func__,
1634                           gret, gpgme_strerror(gret));
1635                 gpgme_data_release(plain_data);
1636                 gpgme_release(ctx);
1637                 return ldb_module_operr(io->ac->module);
1638         }
1639
1640         for (ki = 0; ki < num_keys; ki++) {
1641                 const char *key_id = io->ac->gpg_key_ids[ki];
1642                 size_t len = strlen(key_id);
1643
1644                 keys[ki] = NULL;
1645
1646                 if (len < 16) {
1647                         ldb_debug(ldb, LDB_DEBUG_FATAL,
1648                                   "%s:%s: ki[%zu] key_id[%s] strlen < 16, "
1649                                   "please specify at least the 64bit key id\n",
1650                                   __location__, __func__,
1651                                   ki, key_id);
1652                         for (kr = 0; keys[kr] != NULL; kr++) {
1653                                 gpgme_key_release(keys[kr]);
1654                         }
1655                         gpgme_data_release(crypt_data);
1656                         gpgme_data_release(plain_data);
1657                         gpgme_release(ctx);
1658                         return ldb_module_operr(io->ac->module);
1659                 }
1660
1661                 gret = gpgme_get_key(ctx, key_id, &keys[ki], 0 /* public key */);
1662                 if (gret != GPG_ERR_NO_ERROR) {
1663                         keys[ki] = NULL;
1664                         if (gpg_err_source(gret) == GPG_ERR_SOURCE_GPGME
1665                             && gpg_err_code(gret) == GPG_ERR_EOF) {
1666                                 ldb_debug(ldb, LDB_DEBUG_ERROR,
1667                                           "Invalid "
1668                                           "'password hash gpg key ids': "
1669                                           "Public Key ID [%s] "
1670                                           "not found in keyring\n",
1671                                           key_id);
1672
1673                         } else {
1674                                 ldb_debug(ldb, LDB_DEBUG_ERROR,
1675                                           "%s:%s: ki[%zu] key_id[%s] "
1676                                           "gret[%u] %s\n",
1677                                           __location__, __func__,
1678                                           ki, key_id,
1679                                           gret, gpgme_strerror(gret));
1680                         }
1681                         for (kr = 0; keys[kr] != NULL; kr++) {
1682                                 gpgme_key_release(keys[kr]);
1683                         }
1684                         gpgme_data_release(crypt_data);
1685                         gpgme_data_release(plain_data);
1686                         gpgme_release(ctx);
1687                         return ldb_module_operr(io->ac->module);
1688                 }
1689         }
1690         keys[ki] = NULL;
1691
1692         gret = gpgme_op_encrypt(ctx, keys,
1693                                 GPGME_ENCRYPT_ALWAYS_TRUST,
1694                                 plain_data, crypt_data);
1695         gpgme_data_release(plain_data);
1696         plain_data = NULL;
1697         for (kr = 0; keys[kr] != NULL; kr++) {
1698                 gpgme_key_release(keys[kr]);
1699                 keys[kr] = NULL;
1700         }
1701         gpgme_release(ctx);
1702         ctx = NULL;
1703         if (gret != GPG_ERR_NO_ERROR) {
1704                 ldb_debug(ldb, LDB_DEBUG_ERROR,
1705                           "%s:%s: gret[%u] %s\n",
1706                           __location__, __func__,
1707                           gret, gpgme_strerror(gret));
1708                 gpgme_data_release(crypt_data);
1709                 return ldb_module_operr(io->ac->module);
1710         }
1711
1712         crypt_mem = gpgme_data_release_and_get_mem(crypt_data, &crypt_length);
1713         crypt_data = NULL;
1714         if (crypt_mem == NULL) {
1715                 return ldb_module_oom(io->ac->module);
1716         }
1717
1718         pgb->gpg_blob = data_blob_talloc(io->ac,
1719                                          (const uint8_t *)crypt_mem,
1720                                          crypt_length);
1721         gpgme_free(crypt_mem);
1722         crypt_mem = NULL;
1723         crypt_length = 0;
1724         if (pgb->gpg_blob.data == NULL) {
1725                 return ldb_module_oom(io->ac->module);
1726         }
1727
1728         return LDB_SUCCESS;
1729 #else /* ENABLE_GPGME */
1730         ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1731                       "You configured 'password hash gpg key ids', "
1732                       "but GPGME support is missing. (%s:%d)",
1733                       __FILE__, __LINE__);
1734         return LDB_ERR_UNWILLING_TO_PERFORM;
1735 #endif /* else ENABLE_GPGME */
1736 }
1737
1738 #define NUM_PACKAGES 6
1739 static int setup_supplemental_field(struct setup_password_fields_io *io)
1740 {
1741         struct ldb_context *ldb;
1742         struct supplementalCredentialsBlob scb;
1743         struct supplementalCredentialsBlob *old_scb = NULL;
1744         /*
1745          * Packages +
1746          * ( Kerberos-Newer-Keys, Kerberos,
1747          *   WDigest, CLEARTEXT, userPassword, SambaGPG)
1748          */
1749         uint32_t num_names = 0;
1750         const char *names[1+NUM_PACKAGES];
1751         uint32_t num_packages = 0;
1752         struct supplementalCredentialsPackage packages[1+NUM_PACKAGES];
1753         struct supplementalCredentialsPackage *pp = packages;
1754         int ret;
1755         enum ndr_err_code ndr_err;
1756         bool do_newer_keys = false;
1757         bool do_cleartext = false;
1758         bool do_samba_gpg = false;
1759
1760         ZERO_STRUCT(names);
1761         ZERO_STRUCT(packages);
1762
1763         ldb = ldb_module_get_ctx(io->ac->module);
1764
1765         if (!io->n.cleartext_utf8) {
1766                 /*
1767                  * when we don't have a cleartext password
1768                  * we can't setup a supplementalCredential value
1769                  */
1770                 return LDB_SUCCESS;
1771         }
1772
1773         /* if there's an old supplementaCredentials blob then use it */
1774         if (io->o.supplemental) {
1775                 if (io->o.scb.sub.signature == SUPPLEMENTAL_CREDENTIALS_SIGNATURE) {
1776                         old_scb = &io->o.scb;
1777                 } else {
1778                         ldb_debug(ldb, LDB_DEBUG_ERROR,
1779                                   "setup_supplemental_field: "
1780                                   "supplementalCredentialsBlob "
1781                                   "signature[0x%04X] expected[0x%04X]",
1782                                   io->o.scb.sub.signature,
1783                                   SUPPLEMENTAL_CREDENTIALS_SIGNATURE);
1784                 }
1785         }
1786         /* Per MS-SAMR 3.1.1.8.11.6 we create AES keys if our domain functionality level is 2008 or higher */
1787
1788
1789
1790         /*
1791          * The ordering is this
1792          *
1793          * Primary:Kerberos-Newer-Keys (optional)
1794          * Primary:Kerberos
1795          * Primary:WDigest
1796          * Primary:CLEARTEXT (optional)
1797          * Primary:userPassword
1798          * Primary:SambaGPG (optional)
1799          *
1800          * And the 'Packages' package is insert before the last
1801          * other package.
1802          *
1803          * Note: it's important that Primary:SambaGPG is added as
1804          * the last element. This is the indication that it matches
1805          * the current password. When a password change happens on
1806          * a Windows DC, it will keep the old Primary:SambaGPG value,
1807          * but as the first element.
1808          */
1809         do_newer_keys = (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2008);
1810         if (do_newer_keys) {
1811                 struct package_PrimaryKerberosBlob pknb;
1812                 DATA_BLOB pknb_blob;
1813                 char *pknb_hexstr;
1814                 /*
1815                  * setup 'Primary:Kerberos-Newer-Keys' element
1816                  */
1817                 names[num_names++] = "Kerberos-Newer-Keys";
1818
1819                 ret = setup_primary_kerberos_newer(io, old_scb, &pknb);
1820                 if (ret != LDB_SUCCESS) {
1821                         return ret;
1822                 }
1823
1824                 ndr_err = ndr_push_struct_blob(
1825                         &pknb_blob, io->ac,
1826                         &pknb,
1827                         (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
1828                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1829                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1830                         ldb_asprintf_errstring(
1831                                 ldb,
1832                                 "setup_supplemental_field: "
1833                                 "failed to push "
1834                                 "package_PrimaryKerberosNeverBlob: %s",
1835                                 nt_errstr(status));
1836                         return LDB_ERR_OPERATIONS_ERROR;
1837                 }
1838                 pknb_hexstr = data_blob_hex_string_upper(io->ac, &pknb_blob);
1839                 if (!pknb_hexstr) {
1840                         return ldb_oom(ldb);
1841                 }
1842                 pp->name        = "Primary:Kerberos-Newer-Keys";
1843                 pp->reserved    = 1;
1844                 pp->data        = pknb_hexstr;
1845                 pp++;
1846                 num_packages++;
1847         }
1848
1849         {
1850                 /*
1851                  * setup 'Primary:Kerberos' element
1852                  */
1853                 /* Primary:Kerberos */
1854                 struct package_PrimaryKerberosBlob pkb;
1855                 DATA_BLOB pkb_blob;
1856                 char *pkb_hexstr;
1857
1858                 names[num_names++] = "Kerberos";
1859
1860                 ret = setup_primary_kerberos(io, old_scb, &pkb);
1861                 if (ret != LDB_SUCCESS) {
1862                         return ret;
1863                 }
1864
1865                 ndr_err = ndr_push_struct_blob(
1866                         &pkb_blob, io->ac,
1867                         &pkb,
1868                         (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
1869                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1870                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1871                         ldb_asprintf_errstring(
1872                                 ldb,
1873                                 "setup_supplemental_field: "
1874                                 "failed to push package_PrimaryKerberosBlob: %s",
1875                                 nt_errstr(status));
1876                         return LDB_ERR_OPERATIONS_ERROR;
1877                 }
1878                 pkb_hexstr = data_blob_hex_string_upper(io->ac, &pkb_blob);
1879                 if (!pkb_hexstr) {
1880                         return ldb_oom(ldb);
1881                 }
1882                 pp->name        = "Primary:Kerberos";
1883                 pp->reserved    = 1;
1884                 pp->data        = pkb_hexstr;
1885                 pp++;
1886                 num_packages++;
1887         }
1888
1889         {
1890                 /*
1891                  * setup 'Primary:WDigest' element
1892                  */
1893                 struct package_PrimaryWDigestBlob pdb;
1894                 DATA_BLOB pdb_blob;
1895                 char *pdb_hexstr;
1896
1897                 names[num_names++] = "WDigest";
1898
1899                 ret = setup_primary_wdigest(io, old_scb, &pdb);
1900                 if (ret != LDB_SUCCESS) {
1901                         return ret;
1902                 }
1903
1904                 ndr_err = ndr_push_struct_blob(
1905                         &pdb_blob, io->ac,
1906                         &pdb,
1907                         (ndr_push_flags_fn_t)ndr_push_package_PrimaryWDigestBlob);
1908                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1909                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1910                         ldb_asprintf_errstring(
1911                                 ldb,
1912                                 "setup_supplemental_field: "
1913                                 "failed to push package_PrimaryWDigestBlob: %s",
1914                                 nt_errstr(status));
1915                         return LDB_ERR_OPERATIONS_ERROR;
1916                 }
1917                 pdb_hexstr = data_blob_hex_string_upper(io->ac, &pdb_blob);
1918                 if (!pdb_hexstr) {
1919                         return ldb_oom(ldb);
1920                 }
1921                 pp->name        = "Primary:WDigest";
1922                 pp->reserved    = 1;
1923                 pp->data        = pdb_hexstr;
1924                 pp++;
1925                 num_packages++;
1926         }
1927
1928         /*
1929          * setup 'Primary:CLEARTEXT' element
1930          */
1931         if (io->ac->status->domain_data.store_cleartext &&
1932             (io->u.userAccountControl & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) {
1933                 do_cleartext = true;
1934         }
1935         if (do_cleartext) {
1936                 struct package_PrimaryCLEARTEXTBlob pcb;
1937                 DATA_BLOB pcb_blob;
1938                 char *pcb_hexstr;
1939
1940                 names[num_names++] = "CLEARTEXT";
1941
1942                 pcb.cleartext   = *io->n.cleartext_utf16;
1943
1944                 ndr_err = ndr_push_struct_blob(
1945                         &pcb_blob, io->ac,
1946                         &pcb,
1947                         (ndr_push_flags_fn_t)ndr_push_package_PrimaryCLEARTEXTBlob);
1948                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1949                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1950                         ldb_asprintf_errstring(
1951                                 ldb,
1952                                 "setup_supplemental_field: "
1953                                 "failed to push package_PrimaryCLEARTEXTBlob: %s",
1954                                 nt_errstr(status));
1955                         return LDB_ERR_OPERATIONS_ERROR;
1956                 }
1957                 pcb_hexstr = data_blob_hex_string_upper(io->ac, &pcb_blob);
1958                 if (!pcb_hexstr) {
1959                         return ldb_oom(ldb);
1960                 }
1961                 pp->name        = "Primary:CLEARTEXT";
1962                 pp->reserved    = 1;
1963                 pp->data        = pcb_hexstr;
1964                 pp++;
1965                 num_packages++;
1966         }
1967
1968         if (io->ac->userPassword_schemes) {
1969                 /*
1970                  * setup 'Primary:userPassword' element
1971                  */
1972                 struct package_PrimaryUserPasswordBlob
1973                         p_userPassword_b;
1974                 DATA_BLOB p_userPassword_b_blob;
1975                 char *p_userPassword_b_hexstr;
1976
1977                 names[num_names++] = "userPassword";
1978
1979                 ret = setup_primary_userPassword(io,
1980                                                  old_scb,
1981                                                  &p_userPassword_b);
1982                 if (ret != LDB_SUCCESS) {
1983                         return ret;
1984                 }
1985
1986                 ndr_err = ndr_push_struct_blob(
1987                         &p_userPassword_b_blob,
1988                         io->ac,
1989                         &p_userPassword_b,
1990                         (ndr_push_flags_fn_t)
1991                         ndr_push_package_PrimaryUserPasswordBlob);
1992                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1993                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1994                         ldb_asprintf_errstring(
1995                                 ldb,
1996                                 "setup_supplemental_field: failed to push "
1997                                 "package_PrimaryUserPasswordBlob: %s",
1998                                 nt_errstr(status));
1999                         return LDB_ERR_OPERATIONS_ERROR;
2000                 }
2001                 p_userPassword_b_hexstr
2002                         = data_blob_hex_string_upper(
2003                                 io->ac,
2004                                 &p_userPassword_b_blob);
2005                 if (!p_userPassword_b_hexstr) {
2006                         return ldb_oom(ldb);
2007                 }
2008                 pp->name     = "Primary:userPassword";
2009                 pp->reserved = 1;
2010                 pp->data     = p_userPassword_b_hexstr;
2011                 pp++;
2012                 num_packages++;
2013         }
2014
2015         /*
2016          * setup 'Primary:SambaGPG' element
2017          */
2018         if (io->ac->gpg_key_ids != NULL) {
2019                 do_samba_gpg = true;
2020         }
2021         if (do_samba_gpg) {
2022                 struct package_PrimarySambaGPGBlob pgb;
2023                 DATA_BLOB pgb_blob;
2024                 char *pgb_hexstr;
2025
2026                 names[num_names++] = "SambaGPG";
2027
2028                 ret = setup_primary_samba_gpg(io, &pgb);
2029                 if (ret != LDB_SUCCESS) {
2030                         return ret;
2031                 }
2032
2033                 ndr_err = ndr_push_struct_blob(&pgb_blob, io->ac, &pgb,
2034                         (ndr_push_flags_fn_t)ndr_push_package_PrimarySambaGPGBlob);
2035                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2036                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2037                         ldb_asprintf_errstring(ldb,
2038                                         "setup_supplemental_field: failed to "
2039                                         "push package_PrimarySambaGPGBlob: %s",
2040                                         nt_errstr(status));
2041                         return LDB_ERR_OPERATIONS_ERROR;
2042                 }
2043                 pgb_hexstr = data_blob_hex_string_upper(io->ac, &pgb_blob);
2044                 if (!pgb_hexstr) {
2045                         return ldb_oom(ldb);
2046                 }
2047                 pp->name        = "Primary:SambaGPG";
2048                 pp->reserved    = 1;
2049                 pp->data        = pgb_hexstr;
2050                 pp++;
2051                 num_packages++;
2052         }
2053
2054         /*
2055          * setup 'Packages' element
2056          */
2057         {
2058                 struct package_PackagesBlob pb;
2059                 DATA_BLOB pb_blob;
2060                 char *pb_hexstr;
2061
2062                 pb.names = names;
2063                 ndr_err = ndr_push_struct_blob(
2064                         &pb_blob, io->ac,
2065                         &pb,
2066                         (ndr_push_flags_fn_t)ndr_push_package_PackagesBlob);
2067                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2068                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2069                         ldb_asprintf_errstring(
2070                                 ldb,
2071                                 "setup_supplemental_field: "
2072                                 "failed to push package_PackagesBlob: %s",
2073                                 nt_errstr(status));
2074                         return LDB_ERR_OPERATIONS_ERROR;
2075                 }
2076                 pb_hexstr = data_blob_hex_string_upper(io->ac, &pb_blob);
2077                 if (!pb_hexstr) {
2078                         return ldb_oom(ldb);
2079                 }
2080                 pp->name        = "Packages";
2081                 pp->reserved    = 2;
2082                 pp->data        = pb_hexstr;
2083                 num_packages++;
2084                 /*
2085                  * We don't increment pp so it's pointing to the last package
2086                  */
2087         }
2088
2089         /*
2090          * setup 'supplementalCredentials' value
2091          */
2092         {
2093                 /*
2094                  * The 'Packages' element needs to be the second last element
2095                  * in supplementalCredentials
2096                  */
2097                 struct supplementalCredentialsPackage temp;
2098                 struct supplementalCredentialsPackage *prev;
2099
2100                 prev = pp-1;
2101                 temp = *prev;
2102                 *prev = *pp;
2103                 *pp = temp;
2104
2105                 ZERO_STRUCT(scb);
2106                 scb.sub.signature       = SUPPLEMENTAL_CREDENTIALS_SIGNATURE;
2107                 scb.sub.num_packages    = num_packages;
2108                 scb.sub.packages        = packages;
2109
2110                 ndr_err = ndr_push_struct_blob(
2111                         &io->g.supplemental, io->ac,
2112                         &scb,
2113                         (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
2114                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2115                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2116                         ldb_asprintf_errstring(
2117                                 ldb,
2118                                 "setup_supplemental_field: "
2119                                 "failed to push supplementalCredentialsBlob: %s",
2120                                 nt_errstr(status));
2121                         return LDB_ERR_OPERATIONS_ERROR;
2122                 }
2123         }
2124
2125         return LDB_SUCCESS;
2126 }
2127
2128 static int setup_last_set_field(struct setup_password_fields_io *io)
2129 {
2130         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2131         const struct ldb_message *msg = NULL;
2132         struct timeval tv = { .tv_sec = 0 };
2133         const struct ldb_val *old_val = NULL;
2134         const struct ldb_val *new_val = NULL;
2135         int ret;
2136
2137         switch (io->ac->req->operation) {
2138         case LDB_ADD:
2139                 msg = io->ac->req->op.add.message;
2140                 break;
2141         case LDB_MODIFY:
2142                 msg = io->ac->req->op.mod.message;
2143                 break;
2144         default:
2145                 return LDB_ERR_OPERATIONS_ERROR;
2146                 break;
2147         }
2148
2149         if (io->ac->pwd_last_set_bypass) {
2150                 struct ldb_message_element *el1 = NULL;
2151                 struct ldb_message_element *el2 = NULL;
2152
2153                 if (msg == NULL) {
2154                         return LDB_ERR_CONSTRAINT_VIOLATION;
2155                 }
2156
2157                 el1 = dsdb_get_single_valued_attr(msg, "pwdLastSet",
2158                                                   io->ac->req->operation);
2159                 if (el1 == NULL) {
2160                         return LDB_ERR_CONSTRAINT_VIOLATION;
2161                 }
2162                 el2 = ldb_msg_find_element(msg, "pwdLastSet");
2163                 if (el2 == NULL) {
2164                         return LDB_ERR_CONSTRAINT_VIOLATION;
2165                 }
2166                 if (el1 != el2) {
2167                         return LDB_ERR_CONSTRAINT_VIOLATION;
2168                 }
2169
2170                 io->g.last_set = samdb_result_nttime(msg, "pwdLastSet", 0);
2171                 return LDB_SUCCESS;
2172         }
2173
2174         ret = msg_find_old_and_new_pwd_val(msg, "pwdLastSet",
2175                                            io->ac->req->operation,
2176                                            &new_val, &old_val);
2177         if (ret != LDB_SUCCESS) {
2178                 return ret;
2179         }
2180
2181         if (old_val != NULL && new_val == NULL) {
2182                 ldb_set_errstring(ldb,
2183                                   "'pwdLastSet' deletion is not allowed!");
2184                 return LDB_ERR_UNWILLING_TO_PERFORM;
2185         }
2186
2187         io->g.last_set = UINT64_MAX;
2188         if (new_val != NULL) {
2189                 struct ldb_message *tmp_msg = NULL;
2190
2191                 tmp_msg = ldb_msg_new(io->ac);
2192                 if (tmp_msg == NULL) {
2193                         return ldb_module_oom(io->ac->module);
2194                 }
2195
2196                 if (old_val != NULL) {
2197                         NTTIME old_last_set = 0;
2198
2199                         ret = ldb_msg_add_value(tmp_msg, "oldval",
2200                                                 old_val, NULL);
2201                         if (ret != LDB_SUCCESS) {
2202                                 return ret;
2203                         }
2204
2205                         old_last_set = samdb_result_nttime(tmp_msg,
2206                                                            "oldval",
2207                                                            1);
2208                         if (io->u.pwdLastSet != old_last_set) {
2209                                 return dsdb_module_werror(io->ac->module,
2210                                         LDB_ERR_NO_SUCH_ATTRIBUTE,
2211                                         WERR_DS_CANT_REM_MISSING_ATT_VAL,
2212                                         "setup_last_set_field: old pwdLastSet "
2213                                         "value not found!");
2214                         }
2215                 }
2216
2217                 ret = ldb_msg_add_value(tmp_msg, "newval",
2218                                         new_val, NULL);
2219                 if (ret != LDB_SUCCESS) {
2220                         return ret;
2221                 }
2222
2223                 io->g.last_set = samdb_result_nttime(tmp_msg,
2224                                                      "newval",
2225                                                      1);
2226         } else if (ldb_msg_find_element(msg, "pwdLastSet")) {
2227                 ldb_set_errstring(ldb,
2228                                   "'pwdLastSet' deletion is not allowed!");
2229                 return LDB_ERR_UNWILLING_TO_PERFORM;
2230         } else if (io->ac->smartcard_reset) {
2231                 /*
2232                  * adding UF_SMARTCARD_REQUIRED doesn't update
2233                  * pwdLastSet implicitly.
2234                  */
2235                 io->ac->update_lastset = false;
2236         }
2237
2238         /* only 0 or -1 (0xFFFFFFFFFFFFFFFF) are allowed */
2239         switch (io->g.last_set) {
2240         case 0:
2241                 if (!io->ac->pwd_last_set_default) {
2242                         break;
2243                 }
2244                 if (!io->ac->update_password) {
2245                         break;
2246                 }
2247                 FALL_THROUGH;
2248         case UINT64_MAX:
2249                 if (!io->ac->update_password &&
2250                     io->u.pwdLastSet != 0 &&
2251                     io->u.pwdLastSet != UINT64_MAX)
2252                 {
2253                         /*
2254                          * Just setting pwdLastSet to -1, while not changing
2255                          * any password field has no effect if pwdLastSet
2256                          * is already non-zero.
2257                          */
2258                         io->ac->update_lastset = false;
2259                         break;
2260                 }
2261                 /* -1 means set it as now */
2262                 GetTimeOfDay(&tv);
2263                 io->g.last_set = timeval_to_nttime(&tv);
2264                 break;
2265         default:
2266                 return dsdb_module_werror(io->ac->module,
2267                                           LDB_ERR_OTHER,
2268                                           WERR_INVALID_PARAMETER,
2269                                           "setup_last_set_field: "
2270                                           "pwdLastSet must be 0 or -1 only!");
2271         }
2272
2273         if (io->ac->req->operation == LDB_ADD) {
2274                 /*
2275                  * We always need to store the value on add
2276                  * operations.
2277                  */
2278                 return LDB_SUCCESS;
2279         }
2280
2281         if (io->g.last_set == io->u.pwdLastSet) {
2282                 /*
2283                  * Just setting pwdLastSet to 0, is no-op if it's already 0.
2284                  */
2285                 io->ac->update_lastset = false;
2286         }
2287
2288         return LDB_SUCCESS;
2289 }
2290
2291 static int setup_given_passwords(struct setup_password_fields_io *io,
2292                                  struct setup_password_fields_given *g)
2293 {
2294         struct ldb_context *ldb;
2295         bool ok;
2296
2297         ldb = ldb_module_get_ctx(io->ac->module);
2298
2299         if (g->cleartext_utf8) {
2300                 struct ldb_val *cleartext_utf16_blob;
2301
2302                 cleartext_utf16_blob = talloc(io->ac, struct ldb_val);
2303                 if (!cleartext_utf16_blob) {
2304                         return ldb_oom(ldb);
2305                 }
2306                 if (!convert_string_talloc(io->ac,
2307                                            CH_UTF8, CH_UTF16,
2308                                            g->cleartext_utf8->data,
2309                                            g->cleartext_utf8->length,
2310                                            (void *)&cleartext_utf16_blob->data,
2311                                            &cleartext_utf16_blob->length)) {
2312                         if (g->cleartext_utf8->length != 0) {
2313                                 talloc_free(cleartext_utf16_blob);
2314                                 ldb_asprintf_errstring(ldb,
2315                                                        "setup_password_fields: "
2316                                                        "failed to generate UTF16 password from cleartext UTF8 one for user '%s'!",
2317                                                        io->u.sAMAccountName);
2318                                 return LDB_ERR_CONSTRAINT_VIOLATION;
2319                         } else {
2320                                 /* passwords with length "0" are valid! */
2321                                 cleartext_utf16_blob->data = NULL;
2322                                 cleartext_utf16_blob->length = 0;
2323                         }
2324                 }
2325                 g->cleartext_utf16 = cleartext_utf16_blob;
2326         } else if (g->cleartext_utf16) {
2327                 struct ldb_val *cleartext_utf8_blob;
2328
2329                 cleartext_utf8_blob = talloc(io->ac, struct ldb_val);
2330                 if (!cleartext_utf8_blob) {
2331                         return ldb_oom(ldb);
2332                 }
2333                 if (!convert_string_talloc(io->ac,
2334                                            CH_UTF16MUNGED, CH_UTF8,
2335                                            g->cleartext_utf16->data,
2336                                            g->cleartext_utf16->length,
2337                                            (void *)&cleartext_utf8_blob->data,
2338                                            &cleartext_utf8_blob->length)) {
2339                         if (g->cleartext_utf16->length != 0) {
2340                                 /* We must bail out here, the input wasn't even
2341                                  * a multiple of 2 bytes */
2342                                 talloc_free(cleartext_utf8_blob);
2343                                 ldb_asprintf_errstring(ldb,
2344                                                        "setup_password_fields: "
2345                                                        "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)!",
2346                                                        io->u.sAMAccountName);
2347                                 return LDB_ERR_CONSTRAINT_VIOLATION;
2348                         } else {
2349                                 /* passwords with length "0" are valid! */
2350                                 cleartext_utf8_blob->data = NULL;
2351                                 cleartext_utf8_blob->length = 0;
2352                         }
2353                 }
2354                 g->cleartext_utf8 = cleartext_utf8_blob;
2355         }
2356
2357         if (g->cleartext_utf16) {
2358                 struct samr_Password *nt_hash;
2359
2360                 nt_hash = talloc(io->ac, struct samr_Password);
2361                 if (!nt_hash) {
2362                         return ldb_oom(ldb);
2363                 }
2364                 g->nt_hash = nt_hash;
2365
2366                 /* compute the new nt hash */
2367                 mdfour(nt_hash->hash,
2368                        g->cleartext_utf16->data,
2369                        g->cleartext_utf16->length);
2370         }
2371
2372         if (g->cleartext_utf8) {
2373                 struct samr_Password *lm_hash;
2374
2375                 lm_hash = talloc(io->ac, struct samr_Password);
2376                 if (!lm_hash) {
2377                         return ldb_oom(ldb);
2378                 }
2379
2380                 /* compute the new lm hash */
2381                 ok = E_deshash((char *)g->cleartext_utf8->data, lm_hash->hash);
2382                 if (ok) {
2383                         g->lm_hash = lm_hash;
2384                 } else {
2385                         talloc_free(lm_hash);
2386                 }
2387         }
2388
2389         return LDB_SUCCESS;
2390 }
2391
2392 static int setup_password_fields(struct setup_password_fields_io *io)
2393 {
2394         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2395         struct loadparm_context *lp_ctx =
2396                 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2397                                          struct loadparm_context);
2398         int ret;
2399
2400         ret = setup_last_set_field(io);
2401         if (ret != LDB_SUCCESS) {
2402                 return ret;
2403         }
2404
2405         if (!io->ac->update_password) {
2406                 return LDB_SUCCESS;
2407         }
2408
2409         /* transform the old password (for password changes) */
2410         ret = setup_given_passwords(io, &io->og);
2411         if (ret != LDB_SUCCESS) {
2412                 return ret;
2413         }
2414
2415         /* transform the new password */
2416         ret = setup_given_passwords(io, &io->n);
2417         if (ret != LDB_SUCCESS) {
2418                 return ret;
2419         }
2420
2421         if (io->n.cleartext_utf8) {
2422                 ret = setup_kerberos_keys(io);
2423                 if (ret != LDB_SUCCESS) {
2424                         return ret;
2425                 }
2426         }
2427
2428         ret = setup_nt_fields(io);
2429         if (ret != LDB_SUCCESS) {
2430                 return ret;
2431         }
2432
2433         if (lpcfg_lanman_auth(lp_ctx)) {
2434                 ret = setup_lm_fields(io);
2435                 if (ret != LDB_SUCCESS) {
2436                         return ret;
2437                 }
2438         } else {
2439                 io->g.lm_hash = NULL;
2440                 io->g.lm_history_len = 0;
2441         }
2442
2443         ret = setup_supplemental_field(io);
2444         if (ret != LDB_SUCCESS) {
2445                 return ret;
2446         }
2447
2448         return LDB_SUCCESS;
2449 }
2450
2451 static int setup_smartcard_reset(struct setup_password_fields_io *io)
2452 {
2453         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2454         struct loadparm_context *lp_ctx = talloc_get_type(
2455                 ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
2456         struct supplementalCredentialsBlob scb = { .__ndr_size = 0 };
2457         enum ndr_err_code ndr_err;
2458
2459         if (!io->ac->smartcard_reset) {
2460                 return LDB_SUCCESS;
2461         }
2462
2463         io->g.nt_hash = talloc(io->ac, struct samr_Password);
2464         if (io->g.nt_hash == NULL) {
2465                 return ldb_module_oom(io->ac->module);
2466         }
2467         generate_secret_buffer(io->g.nt_hash->hash,
2468                                sizeof(io->g.nt_hash->hash));
2469         io->g.nt_history_len = 0;
2470
2471         if (lpcfg_lanman_auth(lp_ctx)) {
2472                 io->g.lm_hash = talloc(io->ac, struct samr_Password);
2473                 if (io->g.lm_hash == NULL) {
2474                         return ldb_module_oom(io->ac->module);
2475                 }
2476                 generate_secret_buffer(io->g.lm_hash->hash,
2477                                        sizeof(io->g.lm_hash->hash));
2478         } else {
2479                 io->g.lm_hash = NULL;
2480         }
2481         io->g.lm_history_len = 0;
2482
2483         /*
2484          * We take the "old" value and store it
2485          * with num_packages = 0.
2486          *
2487          * On "add" we have scb.sub.signature == 0, which
2488          * results in:
2489          *
2490          * [0000] 00 00 00 00 00 00 00 00   00 00 00 00 00
2491          *
2492          * On modify it's likely to be scb.sub.signature ==
2493          * SUPPLEMENTAL_CREDENTIALS_SIGNATURE (0x0050), which results in
2494          * something like:
2495          *
2496          * [0000] 00 00 00 00 62 00 00 00   00 00 00 00 20 00 20 00
2497          * [0010] 20 00 20 00 20 00 20 00   20 00 20 00 20 00 20 00
2498          * [0020] 20 00 20 00 20 00 20 00   20 00 20 00 20 00 20 00
2499          * [0030] 20 00 20 00 20 00 20 00   20 00 20 00 20 00 20 00
2500          * [0040] 20 00 20 00 20 00 20 00   20 00 20 00 20 00 20 00
2501          * [0050] 20 00 20 00 20 00 20 00   20 00 20 00 20 00 20 00
2502          * [0060] 20 00 20 00 20 00 20 00   20 00 20 00 50 00 00
2503          *
2504          * See https://bugzilla.samba.org/show_bug.cgi?id=11441
2505          * and ndr_{push,pull}_supplementalCredentialsSubBlob().
2506          */
2507         scb = io->o.scb;
2508         scb.sub.num_packages = 0;
2509
2510         /*
2511          * setup 'supplementalCredentials' value without packages
2512          */
2513         ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac,
2514                                        &scb,
2515                                        (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
2516         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2517                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2518                 ldb_asprintf_errstring(ldb,
2519                                        "setup_smartcard_reset: "
2520                                        "failed to push supplementalCredentialsBlob: %s",
2521                                        nt_errstr(status));
2522                 return LDB_ERR_OPERATIONS_ERROR;
2523         }
2524
2525         io->ac->update_password = true;
2526         return LDB_SUCCESS;
2527 }
2528
2529 static int make_error_and_update_badPwdCount(struct setup_password_fields_io *io, WERROR *werror)
2530 {
2531         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2532         struct ldb_message *mod_msg = NULL;
2533         struct ldb_message *pso_msg = NULL;
2534         NTSTATUS status;
2535         int ret;
2536
2537         /* PSO search result is optional (NULL if no PSO applies) */
2538         if (io->ac->pso_res != NULL) {
2539                 pso_msg = io->ac->pso_res->message;
2540         }
2541
2542         status = dsdb_update_bad_pwd_count(io->ac, ldb,
2543                                            io->ac->search_res->message,
2544                                            io->ac->dom_res->message,
2545                                            pso_msg,
2546                                            &mod_msg);
2547         if (!NT_STATUS_IS_OK(status)) {
2548                 goto done;
2549         }
2550
2551         if (mod_msg == NULL) {
2552                 goto done;
2553         }
2554
2555         /*
2556          * OK, horrible semantics ahead.
2557          *
2558          * - We need to abort any existing transaction
2559          * - create a transaction arround the badPwdCount update
2560          * - re-open the transaction so the upper layer
2561          *   doesn't know what happened.
2562          *
2563          * This is needed because returning an error to the upper
2564          * layer will cancel the transaction and undo the badPwdCount
2565          * update.
2566          */
2567
2568         /*
2569          * Checking errors here is a bit pointless.
2570          * What can we do if we can't end the transaction?
2571          */
2572         ret = ldb_next_del_trans(io->ac->module);
2573         if (ret != LDB_SUCCESS) {
2574                 ldb_debug(ldb, LDB_DEBUG_FATAL,
2575                           "Failed to abort transaction prior to update of badPwdCount of %s: %s",
2576                           ldb_dn_get_linearized(io->ac->search_res->message->dn),
2577                           ldb_errstring(ldb));
2578                 /*
2579                  * just return the original error
2580                  */
2581                 goto done;
2582         }
2583
2584         /* Likewise, what should we do if we can't open a new transaction? */
2585         ret = ldb_next_start_trans(io->ac->module);
2586         if (ret != LDB_SUCCESS) {
2587                 ldb_debug(ldb, LDB_DEBUG_ERROR,
2588                           "Failed to open transaction to update badPwdCount of %s: %s",
2589                           ldb_dn_get_linearized(io->ac->search_res->message->dn),
2590                           ldb_errstring(ldb));
2591                 /*
2592                  * just return the original error
2593                  */
2594                 goto done;
2595         }
2596
2597         ret = dsdb_module_modify(io->ac->module, mod_msg,
2598                                  DSDB_FLAG_NEXT_MODULE,
2599                                  io->ac->req);
2600         if (ret != LDB_SUCCESS) {
2601                 ldb_debug(ldb, LDB_DEBUG_ERROR,
2602                           "Failed to update badPwdCount of %s: %s",
2603                           ldb_dn_get_linearized(io->ac->search_res->message->dn),
2604                           ldb_errstring(ldb));
2605                 /*
2606                  * We can only ignore this...
2607                  */
2608         }
2609
2610         ret = ldb_next_end_trans(io->ac->module);
2611         if (ret != LDB_SUCCESS) {
2612                 ldb_debug(ldb, LDB_DEBUG_ERROR,
2613                           "Failed to close transaction to update badPwdCount of %s: %s",
2614                           ldb_dn_get_linearized(io->ac->search_res->message->dn),
2615                           ldb_errstring(ldb));
2616                 /*
2617                  * We can only ignore this...
2618                  */
2619         }
2620
2621         ret = ldb_next_start_trans(io->ac->module);
2622         if (ret != LDB_SUCCESS) {
2623                 ldb_debug(ldb, LDB_DEBUG_ERROR,
2624                           "Failed to open transaction after update of badPwdCount of %s: %s",
2625                           ldb_dn_get_linearized(io->ac->search_res->message->dn),
2626                           ldb_errstring(ldb));
2627                 /*
2628                  * We can only ignore this...
2629                  */
2630         }
2631
2632 done:
2633         ret = LDB_ERR_CONSTRAINT_VIOLATION;
2634         *werror = WERR_INVALID_PASSWORD;
2635         ldb_asprintf_errstring(ldb,
2636                                "%08X: %s - check_password_restrictions: "
2637                                "The old password specified doesn't match!",
2638                                W_ERROR_V(*werror),
2639                                ldb_strerror(ret));
2640         return ret;
2641 }
2642
2643 static int check_password_restrictions(struct setup_password_fields_io *io, WERROR *werror)
2644 {
2645         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2646         int ret;
2647         struct loadparm_context *lp_ctx =
2648                 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2649                                          struct loadparm_context);
2650
2651         *werror = WERR_INVALID_PARAMETER;
2652
2653         if (!io->ac->update_password) {
2654                 return LDB_SUCCESS;
2655         }
2656
2657         /* First check the old password is correct, for password changes */
2658         if (!io->ac->pwd_reset) {
2659                 bool nt_hash_checked = false;
2660
2661                 /* we need the old nt or lm hash given by the client */
2662                 if (!io->og.nt_hash && !io->og.lm_hash) {
2663                         ldb_asprintf_errstring(ldb,
2664                                 "check_password_restrictions: "
2665                                 "You need to provide the old password in order "
2666                                 "to change it!");
2667                         return LDB_ERR_UNWILLING_TO_PERFORM;
2668                 }
2669
2670                 /* The password modify through the NT hash is encouraged and
2671                    has no problems at all */
2672                 if (io->og.nt_hash) {
2673                         if (!io->o.nt_hash || memcmp(io->og.nt_hash->hash, io->o.nt_hash->hash, 16) != 0) {
2674                                 return make_error_and_update_badPwdCount(io, werror);
2675                         }
2676
2677                         nt_hash_checked = true;
2678                 }
2679
2680                 /* But it is also possible to change a password by the LM hash
2681                  * alone for compatibility reasons. This check is optional if
2682                  * the NT hash was already checked - otherwise it's mandatory.
2683                  * (as the SAMR operations request it). */
2684                 if (io->og.lm_hash) {
2685                         if ((!io->o.lm_hash && !nt_hash_checked)
2686                             || (io->o.lm_hash && memcmp(io->og.lm_hash->hash, io->o.lm_hash->hash, 16) != 0)) {
2687                                 return make_error_and_update_badPwdCount(io, werror);
2688                         }
2689                 }
2690         }
2691
2692         if (io->u.restrictions == 0) {
2693                 /* FIXME: Is this right? */
2694                 return LDB_SUCCESS;
2695         }
2696
2697         /* Password minimum age: yes, this is a minus. The ages are in negative 100nsec units! */
2698         if ((io->u.pwdLastSet - io->ac->status->domain_data.minPwdAge > io->g.last_set) &&
2699             !io->ac->pwd_reset)
2700         {
2701                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2702                 *werror = WERR_PASSWORD_RESTRICTION;
2703                 ldb_asprintf_errstring(ldb,
2704                         "%08X: %s - check_password_restrictions: "
2705                         "password is too young to change!",
2706                         W_ERROR_V(*werror),
2707                         ldb_strerror(ret));
2708                 return ret;
2709         }
2710
2711         /*
2712          * Fundamental password checks done by the call
2713          * "samdb_check_password".
2714          * It is also in use by "dcesrv_samr_ValidatePassword".
2715          */
2716         if (io->n.cleartext_utf8 != NULL) {
2717                 enum samr_ValidationStatus vstat;
2718                 vstat = samdb_check_password(io->ac, lp_ctx,
2719                                              io->n.cleartext_utf8,
2720                                              io->ac->status->domain_data.pwdProperties,
2721                                              io->ac->status->domain_data.minPwdLength);
2722                 switch (vstat) {
2723                 case SAMR_VALIDATION_STATUS_SUCCESS:
2724                                 /* perfect -> proceed! */
2725                         break;
2726
2727                 case SAMR_VALIDATION_STATUS_PWD_TOO_SHORT:
2728                         ret = LDB_ERR_CONSTRAINT_VIOLATION;
2729                         *werror = WERR_PASSWORD_RESTRICTION;
2730                         ldb_asprintf_errstring(ldb,
2731                                 "%08X: %s - check_password_restrictions: "
2732                                 "the password is too short. It should be equal or longer than %u characters!",
2733                                 W_ERROR_V(*werror),
2734                                 ldb_strerror(ret),
2735                                 io->ac->status->domain_data.minPwdLength);
2736                         io->ac->status->reject_reason = SAM_PWD_CHANGE_PASSWORD_TOO_SHORT;
2737                         return ret;
2738
2739                 case SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH:
2740                         ret = LDB_ERR_CONSTRAINT_VIOLATION;
2741                         *werror = WERR_PASSWORD_RESTRICTION;
2742                         ldb_asprintf_errstring(ldb,
2743                                 "%08X: %s - check_password_restrictions: "
2744                                 "the password does not meet the complexity criteria!",
2745                                 W_ERROR_V(*werror),
2746                                 ldb_strerror(ret));
2747                         io->ac->status->reject_reason = SAM_PWD_CHANGE_NOT_COMPLEX;
2748                         return ret;
2749
2750                 default:
2751                         ret = LDB_ERR_CONSTRAINT_VIOLATION;
2752                         *werror = WERR_PASSWORD_RESTRICTION;
2753                         ldb_asprintf_errstring(ldb,
2754                                 "%08X: %s - check_password_restrictions: "
2755                                 "the password doesn't fit due to a miscellaneous restriction!",
2756                                 W_ERROR_V(*werror),
2757                                 ldb_strerror(ret));
2758                         return ret;
2759                 }
2760         }
2761
2762         if (io->ac->pwd_reset) {
2763                 *werror = WERR_OK;
2764                 return LDB_SUCCESS;
2765         }
2766
2767         if (io->n.nt_hash) {
2768                 uint32_t i;
2769
2770                 /* checks the NT hash password history */
2771                 for (i = 0; i < io->o.nt_history_len; i++) {
2772                         ret = memcmp(io->n.nt_hash, io->o.nt_history[i].hash, 16);
2773                         if (ret == 0) {
2774                                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2775                                 *werror = WERR_PASSWORD_RESTRICTION;
2776                                 ldb_asprintf_errstring(ldb,
2777                                         "%08X: %s - check_password_restrictions: "
2778                                         "the password was already used (in history)!",
2779                                         W_ERROR_V(*werror),
2780                                         ldb_strerror(ret));
2781                                 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
2782                                 return ret;
2783                         }
2784                 }
2785         }
2786
2787         if (io->n.lm_hash) {
2788                 uint32_t i;
2789
2790                 /* checks the LM hash password history */
2791                 for (i = 0; i < io->o.lm_history_len; i++) {
2792                         ret = memcmp(io->n.lm_hash, io->o.lm_history[i].hash, 16);
2793                         if (ret == 0) {
2794                                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2795                                 *werror = WERR_PASSWORD_RESTRICTION;
2796                                 ldb_asprintf_errstring(ldb,
2797                                         "%08X: %s - check_password_restrictions: "
2798                                         "the password was already used (in history)!",
2799                                         W_ERROR_V(*werror),
2800                                         ldb_strerror(ret));
2801                                 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
2802                                 return ret;
2803                         }
2804                 }
2805         }
2806
2807         /* are all password changes disallowed? */
2808         if (io->ac->status->domain_data.pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
2809                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2810                 *werror = WERR_PASSWORD_RESTRICTION;
2811                 ldb_asprintf_errstring(ldb,
2812                         "%08X: %s - check_password_restrictions: "
2813                         "password changes disabled!",
2814                         W_ERROR_V(*werror),
2815                         ldb_strerror(ret));
2816                 return ret;
2817         }
2818
2819         /* can this user change the password? */
2820         if (io->u.userAccountControl & UF_PASSWD_CANT_CHANGE) {
2821                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
2822                 *werror = WERR_PASSWORD_RESTRICTION;
2823                 ldb_asprintf_errstring(ldb,
2824                         "%08X: %s - check_password_restrictions: "
2825                         "password can't be changed on this account!",
2826                         W_ERROR_V(*werror),
2827                         ldb_strerror(ret));
2828                 return ret;
2829         }
2830
2831         return LDB_SUCCESS;
2832 }
2833
2834 static int check_password_restrictions_and_log(struct setup_password_fields_io *io)
2835 {
2836         WERROR werror;
2837         int ret = check_password_restrictions(io, &werror);
2838         struct ph_context *ac = io->ac;
2839         /*
2840          * Password resets are not authentication events, and if the
2841          * upper layer checked the password and supplied the hash
2842          * values as proof, then this is also not an authentication
2843          * even at this layer (already logged).  This is to log LDAP
2844          * password changes.
2845          */
2846
2847         /* Do not record a failure in the auth log below in the success case */
2848         if (ret == LDB_SUCCESS) {
2849                 werror = WERR_OK;
2850         }
2851
2852         if (ac->pwd_reset == false && ac->change == NULL) {
2853                 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2854                 struct imessaging_context *msg_ctx;
2855                 struct loadparm_context *lp_ctx
2856                         = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"),
2857                                                 struct loadparm_context);
2858                 NTSTATUS status = werror_to_ntstatus(werror);
2859                 const char *domain_name = lpcfg_sam_name(lp_ctx);
2860                 void *opaque_remote_address = NULL;
2861                 /*
2862                  * Forcing this via the NTLM auth structure is not ideal, but
2863                  * it is the most practical option right now, and ensures the
2864                  * logs are consistent, even if some elements are always NULL.
2865                  */
2866                 struct auth_usersupplied_info ui = {
2867                         .mapped_state = true,
2868                         .was_mapped = true,
2869                         .client = {
2870                                 .account_name = io->u.sAMAccountName,
2871                                 .domain_name = domain_name,
2872                         },
2873                         .mapped = {
2874                                 .account_name = io->u.sAMAccountName,
2875                                 .domain_name = domain_name,
2876                         },
2877                         .service_description = "LDAP Password Change",
2878                         .auth_description = "LDAP Modify",
2879                         .password_type = "plaintext"
2880                 };
2881
2882                 opaque_remote_address = ldb_get_opaque(ldb,
2883                                                        "remoteAddress");
2884                 if (opaque_remote_address == NULL) {
2885                         ldb_asprintf_errstring(ldb,
2886                                                "Failed to obtain remote address for "
2887                                                "the LDAP client while changing the "
2888                                                "password");
2889                         return LDB_ERR_OPERATIONS_ERROR;
2890                 }
2891                 ui.remote_host = talloc_get_type(opaque_remote_address,
2892                                                  struct tsocket_address);
2893
2894                 msg_ctx = imessaging_client_init(ac, lp_ctx,
2895                                                  ldb_get_event_context(ldb));
2896                 if (!msg_ctx) {
2897                         ldb_asprintf_errstring(ldb,
2898                                                "Failed to generate client messaging context in %s",
2899                                                lpcfg_imessaging_path(ac, lp_ctx));
2900                         return LDB_ERR_OPERATIONS_ERROR;
2901                 }
2902                 log_authentication_event(msg_ctx,
2903                                          lp_ctx,
2904                                          NULL,
2905                                          &ui,
2906                                          status,
2907                                          domain_name,
2908                                          io->u.sAMAccountName,
2909                                          NULL,
2910                                          io->u.account_sid);
2911
2912         }
2913         return ret;
2914 }
2915
2916 static int update_final_msg(struct setup_password_fields_io *io)
2917 {
2918         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
2919         int ret;
2920         int el_flags = 0;
2921         bool update_password = io->ac->update_password;
2922         bool update_scb = io->ac->update_password;
2923
2924         /*
2925          * If we add a user without initial password,
2926          * we need to add replication meta data for
2927          * following attributes:
2928          * - unicodePwd
2929          * - dBCSPwd
2930          * - ntPwdHistory
2931          * - lmPwdHistory
2932          *
2933          * If we add a user with initial password or a
2934          * password is changed of an existing user,
2935          * we need to replace the following attributes
2936          * with a forced meta data update, e.g. also
2937          * when updating an empty attribute with an empty value:
2938          * - unicodePwd
2939          * - dBCSPwd
2940          * - ntPwdHistory
2941          * - lmPwdHistory
2942          * - supplementalCredentials
2943          */
2944
2945         switch (io->ac->req->operation) {
2946         case LDB_ADD:
2947                 update_password = true;
2948                 el_flags |= DSDB_FLAG_INTERNAL_FORCE_META_DATA;
2949                 break;
2950         case LDB_MODIFY:
2951                 el_flags |= LDB_FLAG_MOD_REPLACE;
2952                 el_flags |= DSDB_FLAG_INTERNAL_FORCE_META_DATA;
2953                 break;
2954         default:
2955                 return ldb_module_operr(io->ac->module);
2956         }
2957
2958         if (update_password) {
2959                 ret = ldb_msg_add_empty(io->ac->update_msg,
2960                                         "unicodePwd",
2961                                         el_flags, NULL);
2962                 if (ret != LDB_SUCCESS) {
2963                         return ret;
2964                 }
2965                 ret = ldb_msg_add_empty(io->ac->update_msg,
2966                                         "dBCSPwd",
2967                                         el_flags, NULL);
2968                 if (ret != LDB_SUCCESS) {
2969                         return ret;
2970                 }
2971                 ret = ldb_msg_add_empty(io->ac->update_msg,
2972                                         "ntPwdHistory",
2973                                         el_flags, NULL);
2974                 if (ret != LDB_SUCCESS) {
2975                         return ret;
2976                 }
2977                 ret = ldb_msg_add_empty(io->ac->update_msg,
2978                                         "lmPwdHistory",
2979                                         el_flags, NULL);
2980                 if (ret != LDB_SUCCESS) {
2981                         return ret;
2982                 }
2983         }
2984         if (update_scb) {
2985                 ret = ldb_msg_add_empty(io->ac->update_msg,
2986                                         "supplementalCredentials",
2987                                         el_flags, NULL);
2988                 if (ret != LDB_SUCCESS) {
2989                         return ret;
2990                 }
2991         }
2992         if (io->ac->update_lastset) {
2993                 ret = ldb_msg_add_empty(io->ac->update_msg,
2994                                         "pwdLastSet",
2995                                         el_flags, NULL);
2996                 if (ret != LDB_SUCCESS) {
2997                         return ret;
2998                 }
2999         }
3000
3001         if (io->g.nt_hash != NULL) {
3002                 ret = samdb_msg_add_hash(ldb, io->ac,
3003                                          io->ac->update_msg,
3004                                          "unicodePwd",
3005                                          io->g.nt_hash);
3006                 if (ret != LDB_SUCCESS) {
3007                         return ret;
3008                 }
3009         }
3010         if (io->g.lm_hash != NULL) {
3011                 ret = samdb_msg_add_hash(ldb, io->ac,
3012                                          io->ac->update_msg,
3013                                          "dBCSPwd",
3014                                          io->g.lm_hash);
3015                 if (ret != LDB_SUCCESS) {
3016                         return ret;
3017                 }
3018         }
3019         if (io->g.nt_history_len > 0) {
3020                 ret = samdb_msg_add_hashes(ldb, io->ac,
3021                                            io->ac->update_msg,
3022                                            "ntPwdHistory",
3023                                            io->g.nt_history,
3024                                            io->g.nt_history_len);
3025                 if (ret != LDB_SUCCESS) {
3026                         return ret;
3027                 }
3028         }
3029         if (io->g.lm_history_len > 0) {
3030                 ret = samdb_msg_add_hashes(ldb, io->ac,
3031                                            io->ac->update_msg,
3032                                            "lmPwdHistory",
3033                                            io->g.lm_history,
3034                                            io->g.lm_history_len);
3035                 if (ret != LDB_SUCCESS) {
3036                         return ret;
3037                 }
3038         }
3039         if (io->g.supplemental.length > 0) {
3040                 ret = ldb_msg_add_value(io->ac->update_msg,
3041                                         "supplementalCredentials",
3042                                         &io->g.supplemental, NULL);
3043                 if (ret != LDB_SUCCESS) {
3044                         return ret;
3045                 }
3046         }
3047         if (io->ac->update_lastset) {
3048                 ret = samdb_msg_add_uint64(ldb, io->ac,
3049                                            io->ac->update_msg,
3050                                            "pwdLastSet",
3051                                            io->g.last_set);
3052                 if (ret != LDB_SUCCESS) {
3053                         return ret;
3054                 }
3055         }
3056
3057         return LDB_SUCCESS;
3058 }
3059
3060 /*
3061  * This is intended for use by the "password_hash" module since there
3062  * password changes can be specified through one message element with the
3063  * new password (to set) and another one with the old password (to unset).
3064  *
3065  * The first which sets a password (new value) can have flags
3066  * (LDB_FLAG_MOD_ADD, LDB_FLAG_MOD_REPLACE) but also none (on "add" operations
3067  * for entries). The latter (old value) has always specified
3068  * LDB_FLAG_MOD_DELETE.
3069  *
3070  * Returns LDB_ERR_CONSTRAINT_VIOLATION and LDB_ERR_UNWILLING_TO_PERFORM if
3071  * matching message elements are malformed in respect to the set/change rules.
3072  * Otherwise it returns LDB_SUCCESS.
3073  */
3074 static int msg_find_old_and_new_pwd_val(const struct ldb_message *msg,
3075                                         const char *name,
3076                                         enum ldb_request_type operation,
3077                                         const struct ldb_val **new_val,
3078                                         const struct ldb_val **old_val)
3079 {
3080         unsigned int i;
3081
3082         *new_val = NULL;
3083         *old_val = NULL;
3084
3085         if (msg == NULL) {
3086                 return LDB_SUCCESS;
3087         }
3088
3089         for (i = 0; i < msg->num_elements; i++) {
3090                 if (ldb_attr_cmp(msg->elements[i].name, name) != 0) {
3091                         continue;
3092                 }
3093
3094                 if ((operation == LDB_MODIFY) &&
3095                     (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_DELETE)) {
3096                         /* 0 values are allowed */
3097                         if (msg->elements[i].num_values == 1) {
3098                                 *old_val = &msg->elements[i].values[0];
3099                         } else if (msg->elements[i].num_values > 1) {
3100                                 return LDB_ERR_CONSTRAINT_VIOLATION;
3101                         }
3102                 } else if ((operation == LDB_MODIFY) &&
3103                            (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_REPLACE)) {
3104                         if (msg->elements[i].num_values > 0) {
3105                                 *new_val = &msg->elements[i].values[msg->elements[i].num_values - 1];
3106                         } else {
3107                                 return LDB_ERR_UNWILLING_TO_PERFORM;
3108                         }
3109                 } else {
3110                         /* Add operations and LDB_FLAG_MOD_ADD */
3111                         if (msg->elements[i].num_values > 0) {
3112                                 *new_val = &msg->elements[i].values[msg->elements[i].num_values - 1];
3113                         } else {
3114                                 return LDB_ERR_CONSTRAINT_VIOLATION;
3115                         }
3116                 }
3117         }
3118
3119         return LDB_SUCCESS;
3120 }
3121
3122 static int setup_io(struct ph_context *ac, 
3123                     const struct ldb_message *client_msg,
3124                     const struct ldb_message *existing_msg,
3125                     struct setup_password_fields_io *io) 
3126
3127         const struct ldb_val *quoted_utf16, *old_quoted_utf16, *lm_hash, *old_lm_hash;
3128         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3129         struct loadparm_context *lp_ctx = talloc_get_type(
3130                 ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
3131         int ret;
3132         const struct ldb_message *info_msg = NULL;
3133         struct dom_sid *account_sid = NULL;
3134         int rodc_krbtgt = 0;
3135
3136         ZERO_STRUCTP(io);
3137
3138         /* Some operations below require kerberos contexts */
3139
3140         if (existing_msg != NULL) {
3141                 /*
3142                  * This is a modify operation
3143                  */
3144                 info_msg = existing_msg;
3145         } else {
3146                 /*
3147                  * This is an add operation
3148                  */
3149                 info_msg = client_msg;
3150         }
3151
3152         ret = smb_krb5_init_context(ac,
3153                                   (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm"),
3154                                   &io->smb_krb5_context);
3155
3156         if (ret != 0) {
3157                 /*
3158                  * In the special case of mit krb5.conf vs heimdal, the includedir
3159                  * statement causes ret == 22 (KRB5_CONFIG_BADFORMAT) to be returned.
3160                  * We look for this case so that we can give a more instructional
3161                  * message to the administrator.
3162                  */
3163                 if (ret == KRB5_CONFIG_BADFORMAT || ret == EINVAL) {
3164                         ldb_asprintf_errstring(ldb, "Failed to setup krb5_context: %s - "
3165                                 "This could be due to an invalid krb5 configuration. "
3166                                 "Please check your system's krb5 configuration is correct.",
3167                                 error_message(ret));
3168                 } else {
3169                         ldb_asprintf_errstring(ldb, "Failed to setup krb5_context: %s",
3170                                 error_message(ret));
3171                 }
3172                 return LDB_ERR_OPERATIONS_ERROR;
3173         }
3174
3175         io->ac                          = ac;
3176
3177         io->u.userAccountControl        = ldb_msg_find_attr_as_uint(info_msg,
3178                                                                     "userAccountControl", 0);
3179         if (info_msg == existing_msg) {
3180                 /*
3181                  * We only take pwdLastSet from the existing object
3182                  * otherwise we leave it as 0.
3183                  *
3184                  * If no attribute is available, e.g. on deleted objects
3185                  * we remember that as UINT64_MAX.
3186                  */
3187                 io->u.pwdLastSet = samdb_result_nttime(info_msg, "pwdLastSet",
3188                                                        UINT64_MAX);
3189         }
3190         io->u.sAMAccountName            = ldb_msg_find_attr_as_string(info_msg,
3191                                                                       "sAMAccountName", NULL);
3192         io->u.user_principal_name       = ldb_msg_find_attr_as_string(info_msg,
3193                                                                       "userPrincipalName", NULL);
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 }