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