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