s4:provision Remove all references to samba4LocalDomain
[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
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /*
24  *  Name: ldb
25  *
26  *  Component: ldb password_hash module
27  *
28  *  Description: correctly update hash values based on changes to userPassword and friends
29  *
30  *  Author: Andrew Bartlett
31  *  Author: Stefan Metzmacher
32  */
33
34 #include "includes.h"
35 #include "libcli/ldap/ldap_ndr.h"
36 #include "ldb_module.h"
37 #include "librpc/gen_ndr/misc.h"
38 #include "librpc/gen_ndr/samr.h"
39 #include "libcli/auth/libcli_auth.h"
40 #include "libcli/security/security.h"
41 #include "system/kerberos.h"
42 #include "auth/kerberos/kerberos.h"
43 #include "system/time.h"
44 #include "dsdb/samdb/samdb.h"
45 #include "../libds/common/flags.h"
46 #include "dsdb/samdb/ldb_modules/password_modules.h"
47 #include "librpc/ndr/libndr.h"
48 #include "librpc/gen_ndr/ndr_drsblobs.h"
49 #include "../lib/crypto/crypto.h"
50 #include "param/param.h"
51
52 /* If we have decided there is reason to work on this request, then
53  * setup all the password hash types correctly.
54  *
55  * If the administrator doesn't want the userPassword stored (set in the
56  * domain and per-account policies) then we must strip that out before
57  * we do the first operation.
58  *
59  * Once this is done (which could update anything at all), we
60  * calculate the password hashes.
61  *
62  * This function must not only update the unicodePwd, dBCSPwd and
63  * supplementalCredentials fields, it must also atomicly increment the
64  * msDS-KeyVersionNumber.  We should be in a transaction, so all this
65  * should be quite safe...
66  *
67  * Finally, if the administrator has requested that a password history
68  * be maintained, then this should also be written out.
69  *
70  */
71
72 struct ph_context {
73
74         struct ldb_module *module;
75         struct ldb_request *req;
76
77         struct ldb_request *dom_req;
78         struct ldb_reply *dom_res;
79
80         struct ldb_reply *search_res;
81
82         struct dom_sid *domain_sid;
83         struct domain_data *domain;
84 };
85
86 struct domain_data {
87         bool store_cleartext;
88         uint_t pwdProperties;
89         uint_t pwdHistoryLength;
90         char *netbios_domain;
91         char *dns_domain;
92         char *realm;
93 };
94
95 struct setup_password_fields_io {
96         struct ph_context *ac;
97         struct domain_data *domain;
98         struct smb_krb5_context *smb_krb5_context;
99
100         /* infos about the user account */
101         struct {
102                 uint32_t user_account_control;
103                 const char *sAMAccountName;
104                 const char *user_principal_name;
105                 bool is_computer;
106         } u;
107
108         /* new credentials */
109         struct {
110                 const struct ldb_val *cleartext_utf8;
111                 const struct ldb_val *cleartext_utf16;
112                 struct ldb_val quoted_utf16;
113                 struct samr_Password *nt_hash;
114                 struct samr_Password *lm_hash;
115         } n;
116
117         /* old credentials */
118         struct {
119                 uint32_t nt_history_len;
120                 struct samr_Password *nt_history;
121                 uint32_t lm_history_len;
122                 struct samr_Password *lm_history;
123                 const struct ldb_val *supplemental;
124                 struct supplementalCredentialsBlob scb;
125                 uint32_t kvno;
126         } o;
127
128         /* generated credentials */
129         struct {
130                 struct samr_Password *nt_hash;
131                 struct samr_Password *lm_hash;
132                 uint32_t nt_history_len;
133                 struct samr_Password *nt_history;
134                 uint32_t lm_history_len;
135                 struct samr_Password *lm_history;
136                 const char *salt;
137                 DATA_BLOB aes_256;
138                 DATA_BLOB aes_128;
139                 DATA_BLOB des_md5;
140                 DATA_BLOB des_crc;
141                 struct ldb_val supplemental;
142                 NTTIME last_set;
143                 uint32_t kvno;
144         } g;
145 };
146
147 /* Get the NT hash, and fill it in as an entry in the password history, 
148    and specify it into io->g.nt_hash */
149
150 static int setup_nt_fields(struct setup_password_fields_io *io)
151 {
152         struct ldb_context *ldb;
153         uint32_t i;
154
155         io->g.nt_hash = io->n.nt_hash;
156         ldb = ldb_module_get_ctx(io->ac->module);
157
158         if (io->domain->pwdHistoryLength == 0) {
159                 return LDB_SUCCESS;
160         }
161
162         /* We might not have an old NT password */
163         io->g.nt_history = talloc_array(io->ac,
164                                         struct samr_Password,
165                                         io->domain->pwdHistoryLength);
166         if (!io->g.nt_history) {
167                 ldb_oom(ldb);
168                 return LDB_ERR_OPERATIONS_ERROR;
169         }
170
171         for (i = 0; i < MIN(io->domain->pwdHistoryLength-1, io->o.nt_history_len); i++) {
172                 io->g.nt_history[i+1] = io->o.nt_history[i];
173         }
174         io->g.nt_history_len = i + 1;
175
176         if (io->g.nt_hash) {
177                 io->g.nt_history[0] = *io->g.nt_hash;
178         } else {
179                 /* 
180                  * TODO: is this correct?
181                  * the simular behavior is correct for the lm history case
182                  */
183                 E_md4hash("", io->g.nt_history[0].hash);
184         }
185
186         return LDB_SUCCESS;
187 }
188
189 /* Get the LANMAN hash, and fill it in as an entry in the password history, 
190    and specify it into io->g.lm_hash */
191
192 static int setup_lm_fields(struct setup_password_fields_io *io)
193 {
194         struct ldb_context *ldb;
195         uint32_t i;
196
197         io->g.lm_hash = io->n.lm_hash;
198         ldb = ldb_module_get_ctx(io->ac->module);
199
200         if (io->domain->pwdHistoryLength == 0) {
201                 return LDB_SUCCESS;
202         }
203
204         /* We might not have an old NT password */
205         io->g.lm_history = talloc_array(io->ac,
206                                         struct samr_Password,
207                                         io->domain->pwdHistoryLength);
208         if (!io->g.lm_history) {
209                 ldb_oom(ldb);
210                 return LDB_ERR_OPERATIONS_ERROR;
211         }
212
213         for (i = 0; i < MIN(io->domain->pwdHistoryLength-1, io->o.lm_history_len); i++) {
214                 io->g.lm_history[i+1] = io->o.lm_history[i];
215         }
216         io->g.lm_history_len = i + 1;
217
218         if (io->g.lm_hash) {
219                 io->g.lm_history[0] = *io->g.lm_hash;
220         } else {
221                 E_deshash("", io->g.lm_history[0].hash);
222         }
223
224         return LDB_SUCCESS;
225 }
226
227 static int setup_kerberos_keys(struct setup_password_fields_io *io)
228 {
229         struct ldb_context *ldb;
230         krb5_error_code krb5_ret;
231         Principal *salt_principal;
232         krb5_salt salt;
233         krb5_keyblock key;
234         krb5_data cleartext_data;
235
236         ldb = ldb_module_get_ctx(io->ac->module);
237         cleartext_data.data = io->n.cleartext_utf8->data;
238         cleartext_data.length = io->n.cleartext_utf8->length;
239
240         /* Many, many thanks to lukeh@padl.com for this
241          * algorithm, described in his Nov 10 2004 mail to
242          * samba-technical@samba.org */
243
244         /*
245          * Determine a salting principal
246          */
247         if (io->u.is_computer) {
248                 char *name;
249                 char *saltbody;
250
251                 name = strlower_talloc(io->ac, io->u.sAMAccountName);
252                 if (!name) {
253                         ldb_oom(ldb);
254                         return LDB_ERR_OPERATIONS_ERROR;
255                 }
256
257                 if (name[strlen(name)-1] == '$') {
258                         name[strlen(name)-1] = '\0';
259                 }
260
261                 saltbody = talloc_asprintf(io->ac, "%s.%s", name, io->domain->dns_domain);
262                 if (!saltbody) {
263                         ldb_oom(ldb);
264                         return LDB_ERR_OPERATIONS_ERROR;
265                 }
266                 
267                 krb5_ret = krb5_make_principal(io->smb_krb5_context->krb5_context,
268                                                &salt_principal,
269                                                io->domain->realm, "host",
270                                                saltbody, NULL);
271         } else if (io->u.user_principal_name) {
272                 char *user_principal_name;
273                 char *p;
274
275                 user_principal_name = talloc_strdup(io->ac, io->u.user_principal_name);
276                 if (!user_principal_name) {
277                         ldb_oom(ldb);
278                         return LDB_ERR_OPERATIONS_ERROR;
279                 }
280
281                 p = strchr(user_principal_name, '@');
282                 if (p) {
283                         p[0] = '\0';
284                 }
285
286                 krb5_ret = krb5_make_principal(io->smb_krb5_context->krb5_context,
287                                                &salt_principal,
288                                                io->domain->realm, user_principal_name,
289                                                NULL);
290         } else {
291                 krb5_ret = krb5_make_principal(io->smb_krb5_context->krb5_context,
292                                                &salt_principal,
293                                                io->domain->realm, io->u.sAMAccountName,
294                                                NULL);
295         }
296         if (krb5_ret) {
297                 ldb_asprintf_errstring(ldb,
298                                        "setup_kerberos_keys: "
299                                        "generation of a salting principal failed: %s",
300                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac));
301                 return LDB_ERR_OPERATIONS_ERROR;
302         }
303
304         /*
305          * create salt from salt_principal
306          */
307         krb5_ret = krb5_get_pw_salt(io->smb_krb5_context->krb5_context,
308                                     salt_principal, &salt);
309         krb5_free_principal(io->smb_krb5_context->krb5_context, salt_principal);
310         if (krb5_ret) {
311                 ldb_asprintf_errstring(ldb,
312                                        "setup_kerberos_keys: "
313                                        "generation of krb5_salt failed: %s",
314                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac));
315                 return LDB_ERR_OPERATIONS_ERROR;
316         }
317         /* create a talloc copy */
318         io->g.salt = talloc_strndup(io->ac,
319                                     salt.saltvalue.data,
320                                     salt.saltvalue.length);
321         krb5_free_salt(io->smb_krb5_context->krb5_context, salt);
322         if (!io->g.salt) {
323                 ldb_oom(ldb);
324                 return LDB_ERR_OPERATIONS_ERROR;
325         }
326         salt.saltvalue.data     = discard_const(io->g.salt);
327         salt.saltvalue.length   = strlen(io->g.salt);
328
329         /*
330          * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of
331          * the salt and the cleartext password
332          */
333         krb5_ret = krb5_string_to_key_data_salt(io->smb_krb5_context->krb5_context,
334                                                 ENCTYPE_AES256_CTS_HMAC_SHA1_96,
335                                                 cleartext_data,
336                                                 salt,
337                                                 &key);
338         if (krb5_ret) {
339                 ldb_asprintf_errstring(ldb,
340                                        "setup_kerberos_keys: "
341                                        "generation of a aes256-cts-hmac-sha1-96 key failed: %s",
342                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac));
343                 return LDB_ERR_OPERATIONS_ERROR;
344         }
345         io->g.aes_256 = data_blob_talloc(io->ac,
346                                          key.keyvalue.data,
347                                          key.keyvalue.length);
348         krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
349         if (!io->g.aes_256.data) {
350                 ldb_oom(ldb);
351                 return LDB_ERR_OPERATIONS_ERROR;
352         }
353
354         /*
355          * create ENCTYPE_AES128_CTS_HMAC_SHA1_96 key out of
356          * the salt and the cleartext password
357          */
358         krb5_ret = krb5_string_to_key_data_salt(io->smb_krb5_context->krb5_context,
359                                                 ENCTYPE_AES128_CTS_HMAC_SHA1_96,
360                                                 cleartext_data,
361                                                 salt,
362                                                 &key);
363         if (krb5_ret) {
364                 ldb_asprintf_errstring(ldb,
365                                        "setup_kerberos_keys: "
366                                        "generation of a aes128-cts-hmac-sha1-96 key failed: %s",
367                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac));
368                 return LDB_ERR_OPERATIONS_ERROR;
369         }
370         io->g.aes_128 = data_blob_talloc(io->ac,
371                                          key.keyvalue.data,
372                                          key.keyvalue.length);
373         krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
374         if (!io->g.aes_128.data) {
375                 ldb_oom(ldb);
376                 return LDB_ERR_OPERATIONS_ERROR;
377         }
378
379         /*
380          * create ENCTYPE_DES_CBC_MD5 key out of
381          * the salt and the cleartext password
382          */
383         krb5_ret = krb5_string_to_key_data_salt(io->smb_krb5_context->krb5_context,
384                                                 ENCTYPE_DES_CBC_MD5,
385                                                 cleartext_data,
386                                                 salt,
387                                                 &key);
388         if (krb5_ret) {
389                 ldb_asprintf_errstring(ldb,
390                                        "setup_kerberos_keys: "
391                                        "generation of a des-cbc-md5 key failed: %s",
392                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac));
393                 return LDB_ERR_OPERATIONS_ERROR;
394         }
395         io->g.des_md5 = data_blob_talloc(io->ac,
396                                          key.keyvalue.data,
397                                          key.keyvalue.length);
398         krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
399         if (!io->g.des_md5.data) {
400                 ldb_oom(ldb);
401                 return LDB_ERR_OPERATIONS_ERROR;
402         }
403
404         /*
405          * create ENCTYPE_DES_CBC_CRC key out of
406          * the salt and the cleartext password
407          */
408         krb5_ret = krb5_string_to_key_data_salt(io->smb_krb5_context->krb5_context,
409                                                 ENCTYPE_DES_CBC_CRC,
410                                                 cleartext_data,
411                                                 salt,
412                                                 &key);
413         if (krb5_ret) {
414                 ldb_asprintf_errstring(ldb,
415                                        "setup_kerberos_keys: "
416                                        "generation of a des-cbc-crc key failed: %s",
417                                        smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac));
418                 return LDB_ERR_OPERATIONS_ERROR;
419         }
420         io->g.des_crc = data_blob_talloc(io->ac,
421                                          key.keyvalue.data,
422                                          key.keyvalue.length);
423         krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
424         if (!io->g.des_crc.data) {
425                 ldb_oom(ldb);
426                 return LDB_ERR_OPERATIONS_ERROR;
427         }
428
429         return LDB_SUCCESS;
430 }
431
432 static int setup_primary_kerberos(struct setup_password_fields_io *io,
433                                   const struct supplementalCredentialsBlob *old_scb,
434                                   struct package_PrimaryKerberosBlob *pkb)
435 {
436         struct ldb_context *ldb;
437         struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3;
438         struct supplementalCredentialsPackage *old_scp = NULL;
439         struct package_PrimaryKerberosBlob _old_pkb;
440         struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL;
441         uint32_t i;
442         enum ndr_err_code ndr_err;
443
444         ldb = ldb_module_get_ctx(io->ac->module);
445
446         /*
447          * prepare generation of keys
448          *
449          * ENCTYPE_DES_CBC_MD5
450          * ENCTYPE_DES_CBC_CRC
451          */
452         pkb->version            = 3;
453         pkb3->salt.string       = io->g.salt;
454         pkb3->num_keys          = 2;
455         pkb3->keys              = talloc_array(io->ac,
456                                                struct package_PrimaryKerberosKey3,
457                                                pkb3->num_keys);
458         if (!pkb3->keys) {
459                 ldb_oom(ldb);
460                 return LDB_ERR_OPERATIONS_ERROR;
461         }
462
463         pkb3->keys[0].keytype   = ENCTYPE_DES_CBC_MD5;
464         pkb3->keys[0].value     = &io->g.des_md5;
465         pkb3->keys[1].keytype   = ENCTYPE_DES_CBC_CRC;
466         pkb3->keys[1].value     = &io->g.des_crc;
467
468         /* initialize the old keys to zero */
469         pkb3->num_old_keys      = 0;
470         pkb3->old_keys          = NULL;
471
472         /* if there're no old keys, then we're done */
473         if (!old_scb) {
474                 return LDB_SUCCESS;
475         }
476
477         for (i=0; i < old_scb->sub.num_packages; i++) {
478                 if (strcmp("Primary:Kerberos", old_scb->sub.packages[i].name) != 0) {
479                         continue;
480                 }
481
482                 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
483                         continue;
484                 }
485
486                 old_scp = &old_scb->sub.packages[i];
487                 break;
488         }
489         /* Primary:Kerberos element of supplementalCredentials */
490         if (old_scp) {
491                 DATA_BLOB blob;
492
493                 blob = strhex_to_data_blob(io->ac, old_scp->data);
494                 if (!blob.data) {
495                         ldb_oom(ldb);
496                         return LDB_ERR_OPERATIONS_ERROR;
497                 }
498
499                 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
500                 ndr_err = ndr_pull_struct_blob(&blob, io->ac, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), &_old_pkb,
501                                                (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
502                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
503                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
504                         ldb_asprintf_errstring(ldb,
505                                                "setup_primary_kerberos: "
506                                                "failed to pull old package_PrimaryKerberosBlob: %s",
507                                                nt_errstr(status));
508                         return LDB_ERR_OPERATIONS_ERROR;
509                 }
510
511                 if (_old_pkb.version != 3) {
512                         ldb_asprintf_errstring(ldb,
513                                                "setup_primary_kerberos: "
514                                                "package_PrimaryKerberosBlob version[%u] expected[3]",
515                                                _old_pkb.version);
516                         return LDB_ERR_OPERATIONS_ERROR;
517                 }
518
519                 old_pkb3 = &_old_pkb.ctr.ctr3;
520         }
521
522         /* if we didn't found the old keys we're done */
523         if (!old_pkb3) {
524                 return LDB_SUCCESS;
525         }
526
527         /* fill in the old keys */
528         pkb3->num_old_keys      = old_pkb3->num_keys;
529         pkb3->old_keys          = old_pkb3->keys;
530
531         return LDB_SUCCESS;
532 }
533
534 static int setup_primary_kerberos_newer(struct setup_password_fields_io *io,
535                                         const struct supplementalCredentialsBlob *old_scb,
536                                         struct package_PrimaryKerberosBlob *pkb)
537 {
538         struct ldb_context *ldb;
539         struct package_PrimaryKerberosCtr4 *pkb4 = &pkb->ctr.ctr4;
540         struct supplementalCredentialsPackage *old_scp = NULL;
541         struct package_PrimaryKerberosBlob _old_pkb;
542         struct package_PrimaryKerberosCtr4 *old_pkb4 = NULL;
543         uint32_t i;
544         enum ndr_err_code ndr_err;
545
546         ldb = ldb_module_get_ctx(io->ac->module);
547
548         /*
549          * prepare generation of keys
550          *
551          * ENCTYPE_AES256_CTS_HMAC_SHA1_96
552          * ENCTYPE_AES128_CTS_HMAC_SHA1_96
553          * ENCTYPE_DES_CBC_MD5
554          * ENCTYPE_DES_CBC_CRC
555          */
556         pkb->version                    = 4;
557         pkb4->salt.string               = io->g.salt;
558         pkb4->default_iteration_count   = 4096;
559         pkb4->num_keys                  = 4;
560
561         pkb4->keys = talloc_array(io->ac,
562                                   struct package_PrimaryKerberosKey4,
563                                   pkb4->num_keys);
564         if (!pkb4->keys) {
565                 ldb_oom(ldb);
566                 return LDB_ERR_OPERATIONS_ERROR;
567         }
568
569         pkb4->keys[0].iteration_count   = 4096;
570         pkb4->keys[0].keytype           = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
571         pkb4->keys[0].value             = &io->g.aes_256;
572         pkb4->keys[1].iteration_count   = 4096;
573         pkb4->keys[1].keytype           = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
574         pkb4->keys[1].value             = &io->g.aes_128;
575         pkb4->keys[2].iteration_count   = 4096;
576         pkb4->keys[2].keytype           = ENCTYPE_DES_CBC_MD5;
577         pkb4->keys[2].value             = &io->g.des_md5;
578         pkb4->keys[3].iteration_count   = 4096;
579         pkb4->keys[3].keytype           = ENCTYPE_DES_CBC_CRC;
580         pkb4->keys[3].value             = &io->g.des_crc;
581
582         /* initialize the old keys to zero */
583         pkb4->num_old_keys      = 0;
584         pkb4->old_keys          = NULL;
585         pkb4->num_older_keys    = 0;
586         pkb4->older_keys        = NULL;
587
588         /* if there're no old keys, then we're done */
589         if (!old_scb) {
590                 return LDB_SUCCESS;
591         }
592
593         for (i=0; i < old_scb->sub.num_packages; i++) {
594                 if (strcmp("Primary:Kerberos-Newer-Keys", old_scb->sub.packages[i].name) != 0) {
595                         continue;
596                 }
597
598                 if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
599                         continue;
600                 }
601
602                 old_scp = &old_scb->sub.packages[i];
603                 break;
604         }
605         /* Primary:Kerberos-Newer-Keys element of supplementalCredentials */
606         if (old_scp) {
607                 DATA_BLOB blob;
608
609                 blob = strhex_to_data_blob(io->ac, old_scp->data);
610                 if (!blob.data) {
611                         ldb_oom(ldb);
612                         return LDB_ERR_OPERATIONS_ERROR;
613                 }
614
615                 /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
616                 ndr_err = ndr_pull_struct_blob(&blob, io->ac,
617                                                lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
618                                                &_old_pkb,
619                                                (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
620                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
621                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
622                         ldb_asprintf_errstring(ldb,
623                                                "setup_primary_kerberos_newer: "
624                                                "failed to pull old package_PrimaryKerberosBlob: %s",
625                                                nt_errstr(status));
626                         return LDB_ERR_OPERATIONS_ERROR;
627                 }
628
629                 if (_old_pkb.version != 4) {
630                         ldb_asprintf_errstring(ldb,
631                                                "setup_primary_kerberos_newer: "
632                                                "package_PrimaryKerberosBlob version[%u] expected[4]",
633                                                _old_pkb.version);
634                         return LDB_ERR_OPERATIONS_ERROR;
635                 }
636
637                 old_pkb4 = &_old_pkb.ctr.ctr4;
638         }
639
640         /* if we didn't found the old keys we're done */
641         if (!old_pkb4) {
642                 return LDB_SUCCESS;
643         }
644
645         /* fill in the old keys */
646         pkb4->num_old_keys      = old_pkb4->num_keys;
647         pkb4->old_keys          = old_pkb4->keys;
648         pkb4->num_older_keys    = old_pkb4->num_old_keys;
649         pkb4->older_keys        = old_pkb4->old_keys;
650
651         return LDB_SUCCESS;
652 }
653
654 static int setup_primary_wdigest(struct setup_password_fields_io *io,
655                                  const struct supplementalCredentialsBlob *old_scb,
656                                  struct package_PrimaryWDigestBlob *pdb)
657 {
658         struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
659         DATA_BLOB sAMAccountName;
660         DATA_BLOB sAMAccountName_l;
661         DATA_BLOB sAMAccountName_u;
662         const char *user_principal_name = io->u.user_principal_name;
663         DATA_BLOB userPrincipalName;
664         DATA_BLOB userPrincipalName_l;
665         DATA_BLOB userPrincipalName_u;
666         DATA_BLOB netbios_domain;
667         DATA_BLOB netbios_domain_l;
668         DATA_BLOB netbios_domain_u;
669         DATA_BLOB dns_domain;
670         DATA_BLOB dns_domain_l;
671         DATA_BLOB dns_domain_u;
672         DATA_BLOB digest;
673         DATA_BLOB delim;
674         DATA_BLOB backslash;
675         uint8_t i;
676         struct {
677                 DATA_BLOB *user;
678                 DATA_BLOB *realm;
679                 DATA_BLOB *nt4dom;
680         } wdigest[] = {
681         /*
682          * See
683          * http://technet2.microsoft.com/WindowsServer/en/library/717b450c-f4a0-4cc9-86f4-cc0633aae5f91033.mspx?mfr=true
684          * for what precalculated hashes are supposed to be stored...
685          *
686          * I can't reproduce all values which should contain "Digest" as realm,
687          * am I doing something wrong or is w2k3 just broken...?
688          *
689          * W2K3 fills in following for a user:
690          *
691          * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
692          * sAMAccountName: NewUser2Sam
693          * userPrincipalName: NewUser2Princ@sub1.w2k3.vmnet1.vm.base
694          *
695          * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
696          * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
697          * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
698          * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
699          * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
700          * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
701          * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
702          * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
703          * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
704          * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
705          * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
706          * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
707          * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
708          * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
709          * 221c55284451ae9b3aacaa2a3c86f10f => NewUser2Princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
710          * 74e1be668853d4324d38c07e2acfb8ea => (w2k3 has a bug here!) newuser2princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007
711          * e1e244ab7f098e3ae1761be7f9229bbb => NEWUSER2PRINC@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
712          * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
713          * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
714          * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
715          * 31dc704d3640335b2123d4ee28aa1f11 => ??? changes with NewUser2Sam => NewUser1Sam
716          * 36349f5cecd07320fb3bb0e119230c43 => ??? changes with NewUser2Sam => NewUser1Sam
717          * 12adf019d037fb535c01fd0608e78d9d => ??? changes with NewUser2Sam => NewUser1Sam
718          * 6feecf8e724906f3ee1105819c5105a1 => ??? changes with NewUser2Princ => NewUser1Princ
719          * 6c6911f3de6333422640221b9c51ff1f => ??? changes with NewUser2Princ => NewUser1Princ
720          * 4b279877e742895f9348ac67a8de2f69 => ??? changes with NewUser2Princ => NewUser1Princ
721          * db0c6bff069513e3ebb9870d29b57490 => ??? changes with NewUser2Sam => NewUser1Sam
722          * 45072621e56b1c113a4e04a8ff68cd0e => ??? changes with NewUser2Sam => NewUser1Sam
723          * 11d1220abc44a9c10cf91ef4a9c1de02 => ??? changes with NewUser2Sam => NewUser1Sam
724          *
725          * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base
726          * sAMAccountName: NewUser2Sam
727          *
728          * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
729          * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007
730          * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007
731          * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007
732          * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007
733          * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007
734          * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007
735          * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
736          * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
737          * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
738          * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
739          * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007
740          * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007
741          * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007
742          * 8a140d30b6f0a5912735dc1e3bc993b4 => NewUser2Sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
743          * 86d95b2faae6cae4ec261e7fbaccf093 => (here w2k3 is correct) newuser2sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007
744          * dfeff1493110220efcdfc6362e5f5450 => NEWUSER2SAM@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007
745          * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007
746          * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007
747          * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007
748          * 31dc704d3640335b2123d4ee28aa1f11 => ???M1   changes with NewUser2Sam => NewUser1Sam
749          * 36349f5cecd07320fb3bb0e119230c43 => ???M1.L changes with newuser2sam => newuser1sam
750          * 12adf019d037fb535c01fd0608e78d9d => ???M1.U changes with NEWUSER2SAM => NEWUSER1SAM
751          * 569b4533f2d9e580211dd040e5e360a8 => ???M2   changes with NewUser2Princ => NewUser1Princ
752          * 52528bddf310a587c5d7e6a9ae2cbb20 => ???M2.L changes with newuser2princ => newuser1princ
753          * 4f629a4f0361289ca4255ab0f658fcd5 => ???M3 changes with NewUser2Princ => NewUser1Princ (doesn't depend on case of userPrincipal )
754          * db0c6bff069513e3ebb9870d29b57490 => ???M4 changes with NewUser2Sam => NewUser1Sam
755          * 45072621e56b1c113a4e04a8ff68cd0e => ???M5 changes with NewUser2Sam => NewUser1Sam (doesn't depend on case of sAMAccountName)
756          * 11d1220abc44a9c10cf91ef4a9c1de02 => ???M4.U changes with NEWUSER2SAM => NEWUSER1SAM
757          */
758
759         /*
760          * sAMAccountName, netbios_domain
761          */
762                 {
763                 .user   = &sAMAccountName,
764                 .realm  = &netbios_domain,
765                 },
766                 {
767                 .user   = &sAMAccountName_l,
768                 .realm  = &netbios_domain_l,
769                 },
770                 {
771                 .user   = &sAMAccountName_u,
772                 .realm  = &netbios_domain_u,
773                 },
774                 {
775                 .user   = &sAMAccountName,
776                 .realm  = &netbios_domain_u,
777                 },
778                 {
779                 .user   = &sAMAccountName,
780                 .realm  = &netbios_domain_l,
781                 },
782                 {
783                 .user   = &sAMAccountName_u,
784                 .realm  = &netbios_domain_l,
785                 },
786                 {
787                 .user   = &sAMAccountName_l,
788                 .realm  = &netbios_domain_u,
789                 },
790         /* 
791          * sAMAccountName, dns_domain
792          */
793                 {
794                 .user   = &sAMAccountName,
795                 .realm  = &dns_domain,
796                 },
797                 {
798                 .user   = &sAMAccountName_l,
799                 .realm  = &dns_domain_l,
800                 },
801                 {
802                 .user   = &sAMAccountName_u,
803                 .realm  = &dns_domain_u,
804                 },
805                 {
806                 .user   = &sAMAccountName,
807                 .realm  = &dns_domain_u,
808                 },
809                 {
810                 .user   = &sAMAccountName,
811                 .realm  = &dns_domain_l,
812                 },
813                 {
814                 .user   = &sAMAccountName_u,
815                 .realm  = &dns_domain_l,
816                 },
817                 {
818                 .user   = &sAMAccountName_l,
819                 .realm  = &dns_domain_u,
820                 },
821         /* 
822          * userPrincipalName, no realm
823          */
824                 {
825                 .user   = &userPrincipalName,
826                 },
827                 {
828                 /* 
829                  * NOTE: w2k3 messes this up, if the user has a real userPrincipalName,
830                  *       the fallback to the sAMAccountName based userPrincipalName is correct
831                  */
832                 .user   = &userPrincipalName_l,
833                 },
834                 {
835                 .user   = &userPrincipalName_u,
836                 },
837         /* 
838          * nt4dom\sAMAccountName, no realm
839          */
840                 {
841                 .user   = &sAMAccountName,
842                 .nt4dom = &netbios_domain
843                 },
844                 {
845                 .user   = &sAMAccountName_l,
846                 .nt4dom = &netbios_domain_l
847                 },
848                 {
849                 .user   = &sAMAccountName_u,
850                 .nt4dom = &netbios_domain_u
851                 },
852
853         /*
854          * the following ones are guessed depending on the technet2 article
855          * but not reproducable on a w2k3 server
856          */
857         /* sAMAccountName with "Digest" realm */
858                 {
859                 .user   = &sAMAccountName,
860                 .realm  = &digest
861                 },
862                 {
863                 .user   = &sAMAccountName_l,
864                 .realm  = &digest
865                 },
866                 {
867                 .user   = &sAMAccountName_u,
868                 .realm  = &digest
869                 },
870         /* userPrincipalName with "Digest" realm */
871                 {
872                 .user   = &userPrincipalName,
873                 .realm  = &digest
874                 },
875                 {
876                 .user   = &userPrincipalName_l,
877                 .realm  = &digest
878                 },
879                 {
880                 .user   = &userPrincipalName_u,
881                 .realm  = &digest
882                 },
883         /* nt4dom\\sAMAccountName with "Digest" realm */
884                 {
885                 .user   = &sAMAccountName,
886                 .nt4dom = &netbios_domain,
887                 .realm  = &digest
888                 },
889                 {
890                 .user   = &sAMAccountName_l,
891                 .nt4dom = &netbios_domain_l,
892                 .realm  = &digest
893                 },
894                 {
895                 .user   = &sAMAccountName_u,
896                 .nt4dom = &netbios_domain_u,
897                 .realm  = &digest
898                 },
899         };
900
901         /* prepare DATA_BLOB's used in the combinations array */
902         sAMAccountName          = data_blob_string_const(io->u.sAMAccountName);
903         sAMAccountName_l        = data_blob_string_const(strlower_talloc(io->ac, io->u.sAMAccountName));
904         if (!sAMAccountName_l.data) {
905                 ldb_oom(ldb);
906                 return LDB_ERR_OPERATIONS_ERROR;
907         }
908         sAMAccountName_u        = data_blob_string_const(strupper_talloc(io->ac, io->u.sAMAccountName));
909         if (!sAMAccountName_u.data) {
910                 ldb_oom(ldb);
911                 return LDB_ERR_OPERATIONS_ERROR;
912         }
913
914         /* if the user doesn't have a userPrincipalName, create one (with lower case realm) */
915         if (!user_principal_name) {
916                 user_principal_name = talloc_asprintf(io->ac, "%s@%s",
917                                                       io->u.sAMAccountName,
918                                                       io->domain->dns_domain);
919                 if (!user_principal_name) {
920                         ldb_oom(ldb);
921                         return LDB_ERR_OPERATIONS_ERROR;
922                 }       
923         }
924         userPrincipalName       = data_blob_string_const(user_principal_name);
925         userPrincipalName_l     = data_blob_string_const(strlower_talloc(io->ac, user_principal_name));
926         if (!userPrincipalName_l.data) {
927                 ldb_oom(ldb);
928                 return LDB_ERR_OPERATIONS_ERROR;
929         }
930         userPrincipalName_u     = data_blob_string_const(strupper_talloc(io->ac, user_principal_name));
931         if (!userPrincipalName_u.data) {
932                 ldb_oom(ldb);
933                 return LDB_ERR_OPERATIONS_ERROR;
934         }
935
936         netbios_domain          = data_blob_string_const(io->domain->netbios_domain);
937         netbios_domain_l        = data_blob_string_const(strlower_talloc(io->ac, io->domain->netbios_domain));
938         if (!netbios_domain_l.data) {
939                 ldb_oom(ldb);
940                 return LDB_ERR_OPERATIONS_ERROR;
941         }
942         netbios_domain_u        = data_blob_string_const(strupper_talloc(io->ac, io->domain->netbios_domain));
943         if (!netbios_domain_u.data) {
944                 ldb_oom(ldb);
945                 return LDB_ERR_OPERATIONS_ERROR;
946         }
947
948         dns_domain              = data_blob_string_const(io->domain->dns_domain);
949         dns_domain_l            = data_blob_string_const(io->domain->dns_domain);
950         dns_domain_u            = data_blob_string_const(io->domain->realm);
951
952         digest                  = data_blob_string_const("Digest");
953
954         delim                   = data_blob_string_const(":");
955         backslash               = data_blob_string_const("\\");
956
957         pdb->num_hashes = ARRAY_SIZE(wdigest);
958         pdb->hashes     = talloc_array(io->ac, struct package_PrimaryWDigestHash, pdb->num_hashes);
959         if (!pdb->hashes) {
960                 ldb_oom(ldb);
961                 return LDB_ERR_OPERATIONS_ERROR;
962         }
963
964         for (i=0; i < ARRAY_SIZE(wdigest); i++) {
965                 struct MD5Context md5;
966                 MD5Init(&md5);
967                 if (wdigest[i].nt4dom) {
968                         MD5Update(&md5, wdigest[i].nt4dom->data, wdigest[i].nt4dom->length);
969                         MD5Update(&md5, backslash.data, backslash.length);
970                 }
971                 MD5Update(&md5, wdigest[i].user->data, wdigest[i].user->length);
972                 MD5Update(&md5, delim.data, delim.length);
973                 if (wdigest[i].realm) {
974                         MD5Update(&md5, wdigest[i].realm->data, wdigest[i].realm->length);
975                 }
976                 MD5Update(&md5, delim.data, delim.length);
977                 MD5Update(&md5, io->n.cleartext_utf8->data, io->n.cleartext_utf8->length);
978                 MD5Final(pdb->hashes[i].hash, &md5);
979         }
980
981         return LDB_SUCCESS;
982 }
983
984 static int setup_supplemental_field(struct setup_password_fields_io *io)
985 {
986         struct ldb_context *ldb;
987         struct supplementalCredentialsBlob scb;
988         struct supplementalCredentialsBlob _old_scb;
989         struct supplementalCredentialsBlob *old_scb = NULL;
990         /* Packages + (Kerberos-Newer-Keys, Kerberos, WDigest and CLEARTEXT) */
991         uint32_t num_names = 0;
992         const char *names[1+4];
993         uint32_t num_packages = 0;
994         struct supplementalCredentialsPackage packages[1+4];
995         /* Packages */
996         struct supplementalCredentialsPackage *pp = NULL;
997         struct package_PackagesBlob pb;
998         DATA_BLOB pb_blob;
999         char *pb_hexstr;
1000         /* Primary:Kerberos-Newer-Keys */
1001         const char **nkn = NULL;
1002         struct supplementalCredentialsPackage *pkn = NULL;
1003         struct package_PrimaryKerberosBlob pknb;
1004         DATA_BLOB pknb_blob;
1005         char *pknb_hexstr;
1006         /* Primary:Kerberos */
1007         const char **nk = NULL;
1008         struct supplementalCredentialsPackage *pk = NULL;
1009         struct package_PrimaryKerberosBlob pkb;
1010         DATA_BLOB pkb_blob;
1011         char *pkb_hexstr;
1012         /* Primary:WDigest */
1013         const char **nd = NULL;
1014         struct supplementalCredentialsPackage *pd = NULL;
1015         struct package_PrimaryWDigestBlob pdb;
1016         DATA_BLOB pdb_blob;
1017         char *pdb_hexstr;
1018         /* Primary:CLEARTEXT */
1019         const char **nc = NULL;
1020         struct supplementalCredentialsPackage *pc = NULL;
1021         struct package_PrimaryCLEARTEXTBlob pcb;
1022         DATA_BLOB pcb_blob;
1023         char *pcb_hexstr;
1024         int ret;
1025         enum ndr_err_code ndr_err;
1026         uint8_t zero16[16];
1027         bool do_newer_keys = false;
1028         bool do_cleartext = false;
1029         int *domainFunctionality;
1030
1031         ZERO_STRUCT(zero16);
1032         ZERO_STRUCT(names);
1033
1034         ldb = ldb_module_get_ctx(io->ac->module);
1035
1036         if (!io->n.cleartext_utf8) {
1037                 /* 
1038                  * when we don't have a cleartext password
1039                  * we can't setup a supplementalCredential value
1040                  */
1041                 return LDB_SUCCESS;
1042         }
1043
1044         /* if there's an old supplementaCredentials blob then parse it */
1045         if (io->o.supplemental) {
1046                 ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac,
1047                                                    lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
1048                                                    &_old_scb,
1049                                                    (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
1050                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1051                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1052                         ldb_asprintf_errstring(ldb,
1053                                                "setup_supplemental_field: "
1054                                                "failed to pull old supplementalCredentialsBlob: %s",
1055                                                nt_errstr(status));
1056                         return LDB_ERR_OPERATIONS_ERROR;
1057                 }
1058
1059                 if (_old_scb.sub.signature == SUPPLEMENTAL_CREDENTIALS_SIGNATURE) {
1060                         old_scb = &_old_scb;
1061                 } else {
1062                         ldb_debug(ldb, LDB_DEBUG_ERROR,
1063                                                "setup_supplemental_field: "
1064                                                "supplementalCredentialsBlob signature[0x%04X] expected[0x%04X]",
1065                                                _old_scb.sub.signature, SUPPLEMENTAL_CREDENTIALS_SIGNATURE);
1066                 }
1067         }
1068         /* Per MS-SAMR 3.1.1.8.11.6 we create AES keys if our domain functionality level is 2008 or higher */
1069         domainFunctionality = talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), int);
1070
1071         do_newer_keys = *domainFunctionality &&
1072                 (*domainFunctionality >= DS_DOMAIN_FUNCTION_2008);
1073
1074         if (io->domain->store_cleartext &&
1075             (io->u.user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) {
1076                 do_cleartext = true;
1077         }
1078
1079         /*
1080          * The ordering is this
1081          *
1082          * Primary:Kerberos-Newer-Keys (optional)
1083          * Primary:Kerberos
1084          * Primary:WDigest
1085          * Primary:CLEARTEXT (optional)
1086          *
1087          * And the 'Packages' package is insert before the last
1088          * other package.
1089          */
1090         if (do_newer_keys) {
1091                 /* Primary:Kerberos-Newer-Keys */
1092                 nkn = &names[num_names++];
1093                 pkn = &packages[num_packages++];
1094         }
1095
1096         /* Primary:Kerberos */
1097         nk = &names[num_names++];
1098         pk = &packages[num_packages++];
1099
1100         if (!do_cleartext) {
1101                 /* Packages */
1102                 pp = &packages[num_packages++];
1103         }
1104
1105         /* Primary:WDigest */
1106         nd = &names[num_names++];
1107         pd = &packages[num_packages++];
1108
1109         if (do_cleartext) {
1110                 /* Packages */
1111                 pp = &packages[num_packages++];
1112
1113                 /* Primary:CLEARTEXT */
1114                 nc = &names[num_names++];
1115                 pc = &packages[num_packages++];
1116         }
1117
1118         if (pkn) {
1119                 /*
1120                  * setup 'Primary:Kerberos-Newer-Keys' element
1121                  */
1122                 *nkn = "Kerberos-Newer-Keys";
1123
1124                 ret = setup_primary_kerberos_newer(io, old_scb, &pknb);
1125                 if (ret != LDB_SUCCESS) {
1126                         return ret;
1127                 }
1128
1129                 ndr_err = ndr_push_struct_blob(&pknb_blob, io->ac,
1130                                                lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
1131                                                &pknb,
1132                                                (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
1133                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1134                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1135                         ldb_asprintf_errstring(ldb,
1136                                                "setup_supplemental_field: "
1137                                                "failed to push package_PrimaryKerberosNeverBlob: %s",
1138                                                nt_errstr(status));
1139                         return LDB_ERR_OPERATIONS_ERROR;
1140                 }
1141                 pknb_hexstr = data_blob_hex_string(io->ac, &pknb_blob);
1142                 if (!pknb_hexstr) {
1143                         ldb_oom(ldb);
1144                         return LDB_ERR_OPERATIONS_ERROR;
1145                 }
1146                 pkn->name       = "Primary:Kerberos-Newer-Keys";
1147                 pkn->reserved   = 1;
1148                 pkn->data       = pknb_hexstr;
1149         }
1150
1151         /*
1152          * setup 'Primary:Kerberos' element
1153          */
1154         *nk = "Kerberos";
1155
1156         ret = setup_primary_kerberos(io, old_scb, &pkb);
1157         if (ret != LDB_SUCCESS) {
1158                 return ret;
1159         }
1160
1161         ndr_err = ndr_push_struct_blob(&pkb_blob, io->ac, 
1162                                        lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
1163                                        &pkb,
1164                                        (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
1165         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1166                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1167                 ldb_asprintf_errstring(ldb,
1168                                        "setup_supplemental_field: "
1169                                        "failed to push package_PrimaryKerberosBlob: %s",
1170                                        nt_errstr(status));
1171                 return LDB_ERR_OPERATIONS_ERROR;
1172         }
1173         pkb_hexstr = data_blob_hex_string(io->ac, &pkb_blob);
1174         if (!pkb_hexstr) {
1175                 ldb_oom(ldb);
1176                 return LDB_ERR_OPERATIONS_ERROR;
1177         }
1178         pk->name        = "Primary:Kerberos";
1179         pk->reserved    = 1;
1180         pk->data        = pkb_hexstr;
1181
1182         /*
1183          * setup 'Primary:WDigest' element
1184          */
1185         *nd = "WDigest";
1186
1187         ret = setup_primary_wdigest(io, old_scb, &pdb);
1188         if (ret != LDB_SUCCESS) {
1189                 return ret;
1190         }
1191
1192         ndr_err = ndr_push_struct_blob(&pdb_blob, io->ac, 
1193                                        lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
1194                                        &pdb,
1195                                        (ndr_push_flags_fn_t)ndr_push_package_PrimaryWDigestBlob);
1196         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1197                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1198                 ldb_asprintf_errstring(ldb,
1199                                        "setup_supplemental_field: "
1200                                        "failed to push package_PrimaryWDigestBlob: %s",
1201                                        nt_errstr(status));
1202                 return LDB_ERR_OPERATIONS_ERROR;
1203         }
1204         pdb_hexstr = data_blob_hex_string(io->ac, &pdb_blob);
1205         if (!pdb_hexstr) {
1206                 ldb_oom(ldb);
1207                 return LDB_ERR_OPERATIONS_ERROR;
1208         }
1209         pd->name        = "Primary:WDigest";
1210         pd->reserved    = 1;
1211         pd->data        = pdb_hexstr;
1212
1213         /*
1214          * setup 'Primary:CLEARTEXT' element
1215          */
1216         if (pc) {
1217                 *nc             = "CLEARTEXT";
1218
1219                 pcb.cleartext   = *io->n.cleartext_utf16;
1220
1221                 ndr_err = ndr_push_struct_blob(&pcb_blob, io->ac, 
1222                                                lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
1223                                                &pcb,
1224                                                (ndr_push_flags_fn_t)ndr_push_package_PrimaryCLEARTEXTBlob);
1225                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1226                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1227                         ldb_asprintf_errstring(ldb,
1228                                                "setup_supplemental_field: "
1229                                                "failed to push package_PrimaryCLEARTEXTBlob: %s",
1230                                                nt_errstr(status));
1231                         return LDB_ERR_OPERATIONS_ERROR;
1232                 }
1233                 pcb_hexstr = data_blob_hex_string(io->ac, &pcb_blob);
1234                 if (!pcb_hexstr) {
1235                         ldb_oom(ldb);
1236                         return LDB_ERR_OPERATIONS_ERROR;
1237                 }
1238                 pc->name        = "Primary:CLEARTEXT";
1239                 pc->reserved    = 1;
1240                 pc->data        = pcb_hexstr;
1241         }
1242
1243         /*
1244          * setup 'Packages' element
1245          */
1246         pb.names = names;
1247         ndr_err = ndr_push_struct_blob(&pb_blob, io->ac, 
1248                                        lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 
1249                                        &pb,
1250                                        (ndr_push_flags_fn_t)ndr_push_package_PackagesBlob);
1251         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1252                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1253                 ldb_asprintf_errstring(ldb,
1254                                        "setup_supplemental_field: "
1255                                        "failed to push package_PackagesBlob: %s",
1256                                        nt_errstr(status));
1257                 return LDB_ERR_OPERATIONS_ERROR;
1258         }
1259         pb_hexstr = data_blob_hex_string(io->ac, &pb_blob);
1260         if (!pb_hexstr) {
1261                 ldb_oom(ldb);
1262                 return LDB_ERR_OPERATIONS_ERROR;
1263         }
1264         pp->name        = "Packages";
1265         pp->reserved    = 2;
1266         pp->data        = pb_hexstr;
1267
1268         /*
1269          * setup 'supplementalCredentials' value
1270          */
1271         ZERO_STRUCT(scb);
1272         scb.sub.num_packages    = num_packages;
1273         scb.sub.packages        = packages;
1274
1275         ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac, 
1276                                        lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
1277                                        &scb,
1278                                        (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
1279         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1280                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1281                 ldb_asprintf_errstring(ldb,
1282                                        "setup_supplemental_field: "
1283                                        "failed to push supplementalCredentialsBlob: %s",
1284                                        nt_errstr(status));
1285                 return LDB_ERR_OPERATIONS_ERROR;
1286         }
1287
1288         return LDB_SUCCESS;
1289 }
1290
1291 static int setup_last_set_field(struct setup_password_fields_io *io)
1292 {
1293         /* set it as now */
1294         unix_to_nt_time(&io->g.last_set, time(NULL));
1295
1296         return LDB_SUCCESS;
1297 }
1298
1299 static int setup_kvno_field(struct setup_password_fields_io *io)
1300 {
1301         /* increment by one */
1302         io->g.kvno = io->o.kvno + 1;
1303
1304         return LDB_SUCCESS;
1305 }
1306
1307 static int setup_password_fields(struct setup_password_fields_io *io)
1308 {
1309         struct ldb_context *ldb;
1310         bool ok;
1311         int ret;
1312         size_t converted_pw_len;
1313
1314         ldb = ldb_module_get_ctx(io->ac->module);
1315
1316         /*
1317          * refuse the change if someone want to change the cleartext
1318          * and supply his own hashes at the same time...
1319          */
1320         if ((io->n.cleartext_utf8 || io->n.cleartext_utf16) && (io->n.nt_hash || io->n.lm_hash)) {
1321                 ldb_asprintf_errstring(ldb,
1322                                        "setup_password_fields: "
1323                                        "it's only allowed to set the cleartext password or the password hashes");
1324                 return LDB_ERR_UNWILLING_TO_PERFORM;
1325         }
1326         
1327         if (io->n.cleartext_utf8 && io->n.cleartext_utf16) {
1328                 ldb_asprintf_errstring(ldb,
1329                                        "setup_password_fields: "
1330                                        "it's only allowed to set the cleartext password as userPassword or clearTextPasssword, not both at once");
1331                 return LDB_ERR_UNWILLING_TO_PERFORM;
1332         }
1333         
1334         if (io->n.cleartext_utf8) {
1335                 char **cleartext_utf16_str;
1336                 struct ldb_val *cleartext_utf16_blob;
1337                 io->n.cleartext_utf16 = cleartext_utf16_blob = talloc(io->ac, struct ldb_val);
1338                 if (!io->n.cleartext_utf16) {
1339                         ldb_oom(ldb);
1340                         return LDB_ERR_OPERATIONS_ERROR;
1341                 }
1342                 if (!convert_string_talloc_convenience(io->ac, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 
1343                                                          CH_UTF8, CH_UTF16, io->n.cleartext_utf8->data, io->n.cleartext_utf8->length, 
1344                                                          (void **)&cleartext_utf16_str, &converted_pw_len, false)) {
1345                         ldb_asprintf_errstring(ldb,
1346                                                "setup_password_fields: "
1347                                                "failed to generate UTF16 password from cleartext UTF8 password");
1348                         return LDB_ERR_OPERATIONS_ERROR;
1349                 }
1350                 *cleartext_utf16_blob = data_blob_const(cleartext_utf16_str, converted_pw_len);
1351         } else if (io->n.cleartext_utf16) {
1352                 char *cleartext_utf8_str;
1353                 struct ldb_val *cleartext_utf8_blob;
1354                 io->n.cleartext_utf8 = cleartext_utf8_blob = talloc(io->ac, struct ldb_val);
1355                 if (!io->n.cleartext_utf8) {
1356                         ldb_oom(ldb);
1357                         return LDB_ERR_OPERATIONS_ERROR;
1358                 }
1359                 if (!convert_string_talloc_convenience(io->ac, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 
1360                                                          CH_UTF16MUNGED, CH_UTF8, io->n.cleartext_utf16->data, io->n.cleartext_utf16->length, 
1361                                                          (void **)&cleartext_utf8_str, &converted_pw_len, false)) {
1362                         /* We can't bail out entirely, as these unconvertable passwords are frustratingly valid */
1363                         io->n.cleartext_utf8 = NULL;    
1364                         talloc_free(cleartext_utf8_blob);
1365                 }
1366                 *cleartext_utf8_blob = data_blob_const(cleartext_utf8_str, converted_pw_len);
1367         }
1368         if (io->n.cleartext_utf16) {
1369                 struct samr_Password *nt_hash;
1370                 nt_hash = talloc(io->ac, struct samr_Password);
1371                 if (!nt_hash) {
1372                         ldb_oom(ldb);
1373                         return LDB_ERR_OPERATIONS_ERROR;
1374                 }
1375                 io->n.nt_hash = nt_hash;
1376
1377                 /* compute the new nt hash */
1378                 mdfour(nt_hash->hash, io->n.cleartext_utf16->data, io->n.cleartext_utf16->length);
1379         }
1380
1381         if (io->n.cleartext_utf8) {
1382                 struct samr_Password *lm_hash;
1383                 char *cleartext_unix;
1384                 if (lp_lanman_auth(ldb_get_opaque(ldb, "loadparm")) &&
1385                     convert_string_talloc_convenience(io->ac, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 
1386                                                          CH_UTF8, CH_UNIX, io->n.cleartext_utf8->data, io->n.cleartext_utf8->length, 
1387                                                          (void **)&cleartext_unix, &converted_pw_len, false)) {
1388                         lm_hash = talloc(io->ac, struct samr_Password);
1389                         if (!lm_hash) {
1390                                 ldb_oom(ldb);
1391                                 return LDB_ERR_OPERATIONS_ERROR;
1392                         }
1393                         
1394                         /* compute the new lm hash.   */
1395                         ok = E_deshash((char *)cleartext_unix, lm_hash->hash);
1396                         if (ok) {
1397                                 io->n.lm_hash = lm_hash;
1398                         } else {
1399                                 talloc_free(lm_hash->hash);
1400                         }
1401                 }
1402
1403                 ret = setup_kerberos_keys(io);
1404                 if (ret != LDB_SUCCESS) {
1405                         return ret;
1406                 }
1407         }
1408
1409         ret = setup_nt_fields(io);
1410         if (ret != LDB_SUCCESS) {
1411                 return ret;
1412         }
1413
1414         ret = setup_lm_fields(io);
1415         if (ret != LDB_SUCCESS) {
1416                 return ret;
1417         }
1418
1419         ret = setup_supplemental_field(io);
1420         if (ret != LDB_SUCCESS) {
1421                 return ret;
1422         }
1423
1424         ret = setup_last_set_field(io);
1425         if (ret != LDB_SUCCESS) {
1426                 return ret;
1427         }
1428
1429         ret = setup_kvno_field(io);
1430         if (ret != LDB_SUCCESS) {
1431                 return ret;
1432         }
1433
1434         return LDB_SUCCESS;
1435 }
1436
1437 static int setup_io(struct ph_context *ac, 
1438                     const struct ldb_message *new_msg, 
1439                     const struct ldb_message *searched_msg, 
1440                     struct setup_password_fields_io *io) 
1441
1442         const struct ldb_val *quoted_utf16;
1443         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1444
1445         ZERO_STRUCTP(io);
1446
1447         /* Some operations below require kerberos contexts */
1448         if (smb_krb5_init_context(ac,
1449                                   ldb_get_event_context(ldb),
1450                                   (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm"),
1451                                   &io->smb_krb5_context) != 0) {
1452                 return LDB_ERR_OPERATIONS_ERROR;
1453         }
1454
1455         io->ac                          = ac;
1456         io->domain                      = ac->domain;
1457
1458         io->u.user_account_control      = samdb_result_uint(searched_msg, "userAccountControl", 0);
1459         io->u.sAMAccountName            = samdb_result_string(searched_msg, "samAccountName", NULL);
1460         io->u.user_principal_name       = samdb_result_string(searched_msg, "userPrincipalName", NULL);
1461         io->u.is_computer               = ldb_msg_check_string_attribute(searched_msg, "objectClass", "computer");
1462
1463         io->n.cleartext_utf8            = ldb_msg_find_ldb_val(new_msg, "userPassword");
1464         io->n.cleartext_utf16           = ldb_msg_find_ldb_val(new_msg, "clearTextPassword");
1465
1466         /* this rather strange looking piece of code is there to
1467            handle a ldap client setting a password remotely using the
1468            unicodePwd ldap field. The syntax is that the password is
1469            in UTF-16LE, with a " at either end. Unfortunately the
1470            unicodePwd field is also used to store the nt hashes
1471            internally in Samba, and is used in the nt hash format on
1472            the wire in DRS replication, so we have a single name for
1473            two distinct values. The code below leaves us with a small
1474            chance (less than 1 in 2^32) of a mixup, if someone manages
1475            to create a MD4 hash which starts and ends in 0x22 0x00, as
1476            that would then be treated as a UTF16 password rather than
1477            a nthash */
1478         quoted_utf16                    = ldb_msg_find_ldb_val(new_msg, "unicodePwd");
1479         if (quoted_utf16 && 
1480             quoted_utf16->length >= 4 &&
1481             quoted_utf16->data[0] == '"' && 
1482             quoted_utf16->data[1] == 0 && 
1483             quoted_utf16->data[quoted_utf16->length-2] == '"' && 
1484             quoted_utf16->data[quoted_utf16->length-1] == 0) {
1485                 io->n.quoted_utf16.data = talloc_memdup(io->ac, quoted_utf16->data+2, quoted_utf16->length-4);
1486                 io->n.quoted_utf16.length = quoted_utf16->length-4;
1487                 io->n.cleartext_utf16 = &io->n.quoted_utf16;
1488                 io->n.nt_hash = NULL;
1489         } else {
1490                 io->n.nt_hash           = samdb_result_hash(io->ac, new_msg, "unicodePwd");
1491         }
1492
1493         io->n.lm_hash                   = samdb_result_hash(io->ac, new_msg, "dBCSPwd");
1494
1495         return LDB_SUCCESS;
1496 }
1497
1498 static struct ph_context *ph_init_context(struct ldb_module *module,
1499                                           struct ldb_request *req)
1500 {
1501         struct ldb_context *ldb;
1502         struct ph_context *ac;
1503
1504         ldb = ldb_module_get_ctx(module);
1505
1506         ac = talloc_zero(req, struct ph_context);
1507         if (ac == NULL) {
1508                 ldb_set_errstring(ldb, "Out of Memory");
1509                 return NULL;
1510         }
1511
1512         ac->module = module;
1513         ac->req = req;
1514
1515         return ac;
1516 }
1517
1518 static int ph_op_callback(struct ldb_request *req, struct ldb_reply *ares)
1519 {
1520         struct ph_context *ac;
1521
1522         ac = talloc_get_type(req->context, struct ph_context);
1523
1524         if (!ares) {
1525                 return ldb_module_done(ac->req, NULL, NULL,
1526                                         LDB_ERR_OPERATIONS_ERROR);
1527         }
1528         if (ares->error != LDB_SUCCESS) {
1529                 return ldb_module_done(ac->req, ares->controls,
1530                                         ares->response, ares->error);
1531         }
1532
1533         if (ares->type != LDB_REPLY_DONE) {
1534                 talloc_free(ares);
1535                 return ldb_module_done(ac->req, NULL, NULL,
1536                                         LDB_ERR_OPERATIONS_ERROR);
1537         }
1538
1539         return ldb_module_done(ac->req, ares->controls,
1540                                 ares->response, ares->error);
1541 }
1542
1543 static int password_hash_add_do_add(struct ph_context *ac);
1544 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares);
1545 static int password_hash_mod_search_self(struct ph_context *ac);
1546 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares);
1547 static int password_hash_mod_do_mod(struct ph_context *ac);
1548
1549 static int get_domain_data_callback(struct ldb_request *req,
1550                                     struct ldb_reply *ares)
1551 {
1552         struct ldb_context *ldb;
1553         struct domain_data *data;
1554         struct ph_context *ac;
1555         int ret;
1556         char *tmp;
1557         char *p;
1558
1559         ac = talloc_get_type(req->context, struct ph_context);
1560         ldb = ldb_module_get_ctx(ac->module);
1561
1562         if (!ares) {
1563                 return ldb_module_done(ac->req, NULL, NULL,
1564                                         LDB_ERR_OPERATIONS_ERROR);
1565         }
1566         if (ares->error != LDB_SUCCESS) {
1567                 return ldb_module_done(ac->req, ares->controls,
1568                                         ares->response, ares->error);
1569         }
1570
1571         switch (ares->type) {
1572         case LDB_REPLY_ENTRY:
1573                 if (ac->domain != NULL) {
1574                         ldb_set_errstring(ldb, "Too many results");
1575                         return ldb_module_done(ac->req, NULL, NULL,
1576                                                 LDB_ERR_OPERATIONS_ERROR);
1577                 }
1578
1579                 data = talloc_zero(ac, struct domain_data);
1580                 if (data == NULL) {
1581                         return ldb_module_done(ac->req, NULL, NULL,
1582                                                 LDB_ERR_OPERATIONS_ERROR);
1583                 }
1584
1585                 data->pwdProperties = samdb_result_uint(ares->message, "pwdProperties", 0);
1586                 data->store_cleartext = data->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT;
1587                 data->pwdHistoryLength = samdb_result_uint(ares->message, "pwdHistoryLength", 0);
1588
1589                 /* For a domain DN, this puts things in dotted notation */
1590                 /* For builtin domains, this will give details for the host,
1591                  * but that doesn't really matter, as it's just used for salt
1592                  * and kerberos principals, which don't exist here */
1593
1594                 tmp = ldb_dn_canonical_string(data, ares->message->dn);
1595                 if (!tmp) {
1596                         return ldb_module_done(ac->req, NULL, NULL,
1597                                                 LDB_ERR_OPERATIONS_ERROR);
1598                 }
1599
1600                 /* But it puts a trailing (or just before 'builtin') / on things, so kill that */
1601                 p = strchr(tmp, '/');
1602                 if (p) {
1603                         p[0] = '\0';
1604                 }
1605
1606                 data->dns_domain = strlower_talloc(data, tmp);
1607                 if (data->dns_domain == NULL) {
1608                         ldb_oom(ldb);
1609                         return ldb_module_done(ac->req, NULL, NULL,
1610                                                 LDB_ERR_OPERATIONS_ERROR);
1611                 }
1612                 data->realm = strupper_talloc(data, tmp);
1613                 if (data->realm == NULL) {
1614                         ldb_oom(ldb);
1615                         return ldb_module_done(ac->req, NULL, NULL,
1616                                                 LDB_ERR_OPERATIONS_ERROR);
1617                 }
1618                 /* FIXME: NetbIOS name is *always* the first domain component ?? -SSS */
1619                 p = strchr(tmp, '.');
1620                 if (p) {
1621                         p[0] = '\0';
1622                 }
1623                 data->netbios_domain = strupper_talloc(data, tmp);
1624                 if (data->netbios_domain == NULL) {
1625                         ldb_oom(ldb);
1626                         return ldb_module_done(ac->req, NULL, NULL,
1627                                                 LDB_ERR_OPERATIONS_ERROR);
1628                 }
1629
1630                 talloc_free(tmp);
1631                 ac->domain = data;
1632                 break;
1633
1634         case LDB_REPLY_DONE:
1635
1636                 /* call the next step */
1637                 switch (ac->req->operation) {
1638                 case LDB_ADD:
1639                         ret = password_hash_add_do_add(ac);
1640                         break;
1641
1642                 case LDB_MODIFY:
1643                         ret = password_hash_mod_do_mod(ac);
1644                         break;
1645
1646                 default:
1647                         ret = LDB_ERR_OPERATIONS_ERROR;
1648                         break;
1649                 }
1650                 if (ret != LDB_SUCCESS) {
1651                         return ldb_module_done(ac->req, NULL, NULL, ret);
1652                 }
1653                 break;
1654
1655         case LDB_REPLY_REFERRAL:
1656                 /* ignore */
1657                 break;
1658         }
1659
1660         talloc_free(ares);
1661         return LDB_SUCCESS;
1662 }
1663
1664 static int build_domain_data_request(struct ph_context *ac)
1665 {
1666         /* attrs[] is returned from this function in
1667            ac->dom_req->op.search.attrs, so it must be static, as
1668            otherwise the compiler can put it on the stack */
1669         struct ldb_context *ldb;
1670         static const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", NULL };
1671         char *filter;
1672
1673         ldb = ldb_module_get_ctx(ac->module);
1674
1675         filter = talloc_asprintf(ac,
1676                                 "(&(objectSid=%s)(|(objectClass=domain)(objectClass=builtinDomain)))",
1677                                  ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
1678         if (filter == NULL) {
1679                 ldb_oom(ldb);
1680                 return LDB_ERR_OPERATIONS_ERROR;
1681         }
1682
1683         return ldb_build_search_req(&ac->dom_req, ldb, ac,
1684                                     ldb_get_default_basedn(ldb),
1685                                     LDB_SCOPE_SUBTREE,
1686                                     filter, attrs,
1687                                     NULL,
1688                                     ac, get_domain_data_callback,
1689                                     ac->req);
1690 }
1691
1692 static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
1693 {
1694         struct ldb_context *ldb;
1695         struct ph_context *ac;
1696         struct ldb_message_element *sambaAttr;
1697         struct ldb_message_element *clearTextPasswordAttr;
1698         struct ldb_message_element *ntAttr;
1699         struct ldb_message_element *lmAttr;
1700         int ret;
1701
1702         ldb = ldb_module_get_ctx(module);
1703
1704         ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_add\n");
1705
1706         if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */
1707                 return ldb_next_request(module, req);
1708         }
1709
1710         /* If the caller is manipulating the local passwords directly, let them pass */
1711         if (ldb_dn_compare_base(ldb_dn_new(req, ldb, LOCAL_BASE),
1712                                 req->op.add.message->dn) == 0) {
1713                 return ldb_next_request(module, req);
1714         }
1715
1716         /* nobody must touch these fields */
1717         if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) {
1718                 return LDB_ERR_UNWILLING_TO_PERFORM;
1719         }
1720         if (ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) {
1721                 return LDB_ERR_UNWILLING_TO_PERFORM;
1722         }
1723         if (ldb_msg_find_element(req->op.add.message, "supplementalCredentials")) {
1724                 return LDB_ERR_UNWILLING_TO_PERFORM;
1725         }
1726
1727         /* If no part of this ADD touches the userPassword, or the NT
1728          * or LM hashes, then we don't need to make any changes.  */
1729
1730         sambaAttr = ldb_msg_find_element(req->op.mod.message, "userPassword");
1731         clearTextPasswordAttr = ldb_msg_find_element(req->op.mod.message, "clearTextPassword");
1732         ntAttr = ldb_msg_find_element(req->op.mod.message, "unicodePwd");
1733         lmAttr = ldb_msg_find_element(req->op.mod.message, "dBCSPwd");
1734
1735         if ((!sambaAttr) && (!clearTextPasswordAttr) && (!ntAttr) && (!lmAttr)) {
1736                 return ldb_next_request(module, req);
1737         }
1738
1739         /* if it is not an entry of type person its an error */
1740         /* TODO: remove this when userPassword will be in schema */
1741         if (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "person")) {
1742                 ldb_set_errstring(ldb, "Cannot set a password on entry that does not have objectClass 'person'");
1743                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1744         }
1745
1746         /* check userPassword is single valued here */
1747         /* TODO: remove this when userPassword will be single valued in schema */
1748         if (sambaAttr && sambaAttr->num_values > 1) {
1749                 ldb_set_errstring(ldb, "mupltiple values for userPassword not allowed!\n");
1750                 return LDB_ERR_CONSTRAINT_VIOLATION;
1751         }
1752         if (clearTextPasswordAttr && clearTextPasswordAttr->num_values > 1) {
1753                 ldb_set_errstring(ldb, "mupltiple values for clearTextPassword not allowed!\n");
1754                 return LDB_ERR_CONSTRAINT_VIOLATION;
1755         }
1756
1757         if (ntAttr && (ntAttr->num_values > 1)) {
1758                 ldb_set_errstring(ldb, "mupltiple values for unicodePwd not allowed!\n");
1759                 return LDB_ERR_CONSTRAINT_VIOLATION;
1760         }
1761         if (lmAttr && (lmAttr->num_values > 1)) {
1762                 ldb_set_errstring(ldb, "mupltiple values for dBCSPwd not allowed!\n");
1763                 return LDB_ERR_CONSTRAINT_VIOLATION;
1764         }
1765
1766         if (sambaAttr && sambaAttr->num_values == 0) {
1767                 ldb_set_errstring(ldb, "userPassword must have a value!\n");
1768                 return LDB_ERR_CONSTRAINT_VIOLATION;
1769         }
1770
1771         if (clearTextPasswordAttr && clearTextPasswordAttr->num_values == 0) {
1772                 ldb_set_errstring(ldb, "clearTextPassword must have a value!\n");
1773                 return LDB_ERR_CONSTRAINT_VIOLATION;
1774         }
1775
1776         if (ntAttr && (ntAttr->num_values == 0)) {
1777                 ldb_set_errstring(ldb, "unicodePwd must have a value!\n");
1778                 return LDB_ERR_CONSTRAINT_VIOLATION;
1779         }
1780         if (lmAttr && (lmAttr->num_values == 0)) {
1781                 ldb_set_errstring(ldb, "dBCSPwd must have a value!\n");
1782                 return LDB_ERR_CONSTRAINT_VIOLATION;
1783         }
1784
1785         ac = ph_init_context(module, req);
1786         if (ac == NULL) {
1787                 return LDB_ERR_OPERATIONS_ERROR;
1788         }
1789
1790         /* get user domain data */
1791         ac->domain_sid = samdb_result_sid_prefix(ac, req->op.add.message, "objectSid");
1792         if (ac->domain_sid == NULL) {
1793                 ldb_debug(ldb, LDB_DEBUG_ERROR,
1794                           "can't handle entry with missing objectSid!\n");
1795                 return LDB_ERR_OPERATIONS_ERROR;
1796         }
1797
1798         ret = build_domain_data_request(ac);
1799         if (ret != LDB_SUCCESS) {
1800                 return ret;
1801         }
1802
1803         return ldb_next_request(module, ac->dom_req);
1804 }
1805
1806 static int password_hash_add_do_add(struct ph_context *ac)
1807 {
1808         struct ldb_context *ldb;
1809         struct ldb_request *down_req;
1810         struct ldb_message *msg;
1811         struct setup_password_fields_io io;
1812         int ret;
1813
1814         /* Prepare the internal data structure containing the passwords */
1815         ret = setup_io(ac, ac->req->op.add.message, ac->req->op.add.message, &io);
1816         if (ret != LDB_SUCCESS) {
1817                 return ret;
1818         }
1819
1820         msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
1821         if (msg == NULL) {
1822                 return LDB_ERR_OPERATIONS_ERROR;
1823         }
1824
1825         /* remove attributes that we just read into 'io' */
1826         ldb_msg_remove_attr(msg, "userPassword");
1827         ldb_msg_remove_attr(msg, "clearTextPassword");
1828         ldb_msg_remove_attr(msg, "unicodePwd");
1829         ldb_msg_remove_attr(msg, "dBCSPwd");
1830         ldb_msg_remove_attr(msg, "pwdLastSet");
1831         io.o.kvno = samdb_result_uint(msg, "msDs-KeyVersionNumber", 1) - 1;
1832         ldb_msg_remove_attr(msg, "msDs-KeyVersionNumber");
1833
1834         ldb = ldb_module_get_ctx(ac->module);
1835
1836         ret = setup_password_fields(&io);
1837         if (ret != LDB_SUCCESS) {
1838                 return ret;
1839         }
1840
1841         if (io.g.nt_hash) {
1842                 ret = samdb_msg_add_hash(ldb, ac, msg,
1843                                          "unicodePwd", io.g.nt_hash);
1844                 if (ret != LDB_SUCCESS) {
1845                         return ret;
1846                 }
1847         }
1848         if (io.g.lm_hash) {
1849                 ret = samdb_msg_add_hash(ldb, ac, msg,
1850                                          "dBCSPwd", io.g.lm_hash);
1851                 if (ret != LDB_SUCCESS) {
1852                         return ret;
1853                 }
1854         }
1855         if (io.g.nt_history_len > 0) {
1856                 ret = samdb_msg_add_hashes(ac, msg,
1857                                            "ntPwdHistory",
1858                                            io.g.nt_history,
1859                                            io.g.nt_history_len);
1860                 if (ret != LDB_SUCCESS) {
1861                         return ret;
1862                 }
1863         }
1864         if (io.g.lm_history_len > 0) {
1865                 ret = samdb_msg_add_hashes(ac, msg,
1866                                            "lmPwdHistory",
1867                                            io.g.lm_history,
1868                                            io.g.lm_history_len);
1869                 if (ret != LDB_SUCCESS) {
1870                         return ret;
1871                 }
1872         }
1873         if (io.g.supplemental.length > 0) {
1874                 ret = ldb_msg_add_value(msg, "supplementalCredentials",
1875                                         &io.g.supplemental, NULL);
1876                 if (ret != LDB_SUCCESS) {
1877                         return ret;
1878                 }
1879         }
1880         ret = samdb_msg_add_uint64(ldb, ac, msg,
1881                                    "pwdLastSet",
1882                                    io.g.last_set);
1883         if (ret != LDB_SUCCESS) {
1884                 return ret;
1885         }
1886         ret = samdb_msg_add_uint(ldb, ac, msg,
1887                                  "msDs-KeyVersionNumber",
1888                                  io.g.kvno);
1889         if (ret != LDB_SUCCESS) {
1890                 return ret;
1891         }
1892
1893         ret = ldb_build_add_req(&down_req, ldb, ac,
1894                                 msg,
1895                                 ac->req->controls,
1896                                 ac, ph_op_callback,
1897                                 ac->req);
1898         if (ret != LDB_SUCCESS) {
1899                 return ret;
1900         }
1901
1902         return ldb_next_request(ac->module, down_req);
1903 }
1904
1905 static int password_hash_modify(struct ldb_module *module, struct ldb_request *req)
1906 {
1907         struct ldb_context *ldb;
1908         struct ph_context *ac;
1909         struct ldb_message_element *sambaAttr;
1910         struct ldb_message_element *clearTextAttr;
1911         struct ldb_message_element *ntAttr;
1912         struct ldb_message_element *lmAttr;
1913         struct ldb_message *msg;
1914         struct ldb_request *down_req;
1915         int ret;
1916
1917         ldb = ldb_module_get_ctx(module);
1918
1919         ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_modify\n");
1920
1921         if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */
1922                 return ldb_next_request(module, req);
1923         }
1924         
1925         /* If the caller is manipulating the local passwords directly, let them pass */
1926         if (ldb_dn_compare_base(ldb_dn_new(req, ldb, LOCAL_BASE),
1927                                 req->op.mod.message->dn) == 0) {
1928                 return ldb_next_request(module, req);
1929         }
1930
1931         /* nobody must touch password Histories */
1932         if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) {
1933                 return LDB_ERR_UNWILLING_TO_PERFORM;
1934         }
1935         if (ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) {
1936                 return LDB_ERR_UNWILLING_TO_PERFORM;
1937         }
1938         if (ldb_msg_find_element(req->op.add.message, "supplementalCredentials")) {
1939                 return LDB_ERR_UNWILLING_TO_PERFORM;
1940         }
1941
1942         sambaAttr = ldb_msg_find_element(req->op.mod.message, "userPassword");
1943         clearTextAttr = ldb_msg_find_element(req->op.mod.message, "clearTextPassword");
1944         ntAttr = ldb_msg_find_element(req->op.mod.message, "unicodePwd");
1945         lmAttr = ldb_msg_find_element(req->op.mod.message, "dBCSPwd");
1946
1947         /* If no part of this touches the userPassword OR
1948          * clearTextPassword OR unicodePwd and/or dBCSPwd, then we
1949          * don't need to make any changes.  For password changes/set
1950          * there should be a 'delete' or a 'modify' on this
1951          * attribute. */
1952         if ((!sambaAttr) && (!clearTextAttr) && (!ntAttr) && (!lmAttr)) {
1953                 return ldb_next_request(module, req);
1954         }
1955
1956         /* check passwords are single valued here */
1957         /* TODO: remove this when passwords will be single valued in schema */
1958         if (sambaAttr && (sambaAttr->num_values > 1)) {
1959                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1960                 return LDB_ERR_CONSTRAINT_VIOLATION;
1961         }
1962         if (clearTextAttr && (clearTextAttr->num_values > 1)) {
1963                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1964                 return LDB_ERR_CONSTRAINT_VIOLATION;
1965         }
1966         if (ntAttr && (ntAttr->num_values > 1)) {
1967                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1968                 return LDB_ERR_CONSTRAINT_VIOLATION;
1969         }
1970         if (lmAttr && (lmAttr->num_values > 1)) {
1971                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1972                 return LDB_ERR_CONSTRAINT_VIOLATION;
1973         }
1974
1975         ac = ph_init_context(module, req);
1976         if (!ac) {
1977                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1978                 return LDB_ERR_OPERATIONS_ERROR;
1979         }
1980
1981         /* use a new message structure so that we can modify it */
1982         msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
1983         if (msg == NULL) {
1984                 ldb_oom(ldb);
1985                 return LDB_ERR_OPERATIONS_ERROR;
1986         }
1987
1988         /* - remove any modification to the password from the first commit
1989          *   we will make the real modification later */
1990         if (sambaAttr) ldb_msg_remove_attr(msg, "userPassword");
1991         if (clearTextAttr) ldb_msg_remove_attr(msg, "clearTextPassword");
1992         if (ntAttr) ldb_msg_remove_attr(msg, "unicodePwd");
1993         if (lmAttr) ldb_msg_remove_attr(msg, "dBCSPwd");
1994
1995         /* if there was nothing else to be modified skip to next step */
1996         if (msg->num_elements == 0) {
1997                 return password_hash_mod_search_self(ac);
1998         }
1999
2000         ret = ldb_build_mod_req(&down_req, ldb, ac,
2001                                 msg,
2002                                 req->controls,
2003                                 ac, ph_modify_callback,
2004                                 req);
2005         if (ret != LDB_SUCCESS) {
2006                 return ret;
2007         }
2008
2009         return ldb_next_request(module, down_req);
2010 }
2011
2012 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
2013 {
2014         struct ph_context *ac;
2015         int ret;
2016
2017         ac = talloc_get_type(req->context, struct ph_context);
2018
2019         if (!ares) {
2020                 return ldb_module_done(ac->req, NULL, NULL,
2021                                         LDB_ERR_OPERATIONS_ERROR);
2022         }
2023         if (ares->error != LDB_SUCCESS) {
2024                 return ldb_module_done(ac->req, ares->controls,
2025                                         ares->response, ares->error);
2026         }
2027
2028         if (ares->type != LDB_REPLY_DONE) {
2029                 talloc_free(ares);
2030                 return ldb_module_done(ac->req, NULL, NULL,
2031                                         LDB_ERR_OPERATIONS_ERROR);
2032         }
2033
2034         ret = password_hash_mod_search_self(ac);
2035         if (ret != LDB_SUCCESS) {
2036                 return ldb_module_done(ac->req, NULL, NULL, ret);
2037         }
2038
2039         talloc_free(ares);
2040         return LDB_SUCCESS;
2041 }
2042
2043 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares)
2044 {
2045         struct ldb_context *ldb;
2046         struct ph_context *ac;
2047         int ret;
2048
2049         ac = talloc_get_type(req->context, struct ph_context);
2050         ldb = ldb_module_get_ctx(ac->module);
2051
2052         if (!ares) {
2053                 return ldb_module_done(ac->req, NULL, NULL,
2054                                         LDB_ERR_OPERATIONS_ERROR);
2055         }
2056         if (ares->error != LDB_SUCCESS) {
2057                 return ldb_module_done(ac->req, ares->controls,
2058                                         ares->response, ares->error);
2059         }
2060
2061         /* we are interested only in the single reply (base search) */
2062         switch (ares->type) {
2063         case LDB_REPLY_ENTRY:
2064
2065                 if (ac->search_res != NULL) {
2066                         ldb_set_errstring(ldb, "Too many results");
2067                         talloc_free(ares);
2068                         return ldb_module_done(ac->req, NULL, NULL,
2069                                                 LDB_ERR_OPERATIONS_ERROR);
2070                 }
2071
2072                 /* if it is not an entry of type person this is an error */
2073                 /* TODO: remove this when sambaPassword will be in schema */
2074                 if (!ldb_msg_check_string_attribute(ares->message, "objectClass", "person")) {
2075                         ldb_set_errstring(ldb, "Object class violation");
2076                         talloc_free(ares);
2077                         return ldb_module_done(ac->req, NULL, NULL,
2078                                         LDB_ERR_OBJECT_CLASS_VIOLATION);
2079                 }
2080
2081                 ac->search_res = talloc_steal(ac, ares);
2082                 return LDB_SUCCESS;
2083
2084         case LDB_REPLY_DONE:
2085
2086                 /* get object domain sid */
2087                 ac->domain_sid = samdb_result_sid_prefix(ac,
2088                                                         ac->search_res->message,
2089                                                         "objectSid");
2090                 if (ac->domain_sid == NULL) {
2091                         ldb_debug(ldb, LDB_DEBUG_ERROR,
2092                                   "can't handle entry without objectSid!\n");
2093                         return ldb_module_done(ac->req, NULL, NULL,
2094                                                 LDB_ERR_OPERATIONS_ERROR);
2095                 }
2096
2097                 /* get user domain data */
2098                 ret = build_domain_data_request(ac);
2099                 if (ret != LDB_SUCCESS) {
2100                         return ldb_module_done(ac->req, NULL, NULL,ret);
2101                 }
2102
2103                 return ldb_next_request(ac->module, ac->dom_req);
2104
2105         case LDB_REPLY_REFERRAL:
2106                 /*ignore anything else for now */
2107                 break;
2108         }
2109
2110         talloc_free(ares);
2111         return LDB_SUCCESS;
2112 }
2113
2114 static int password_hash_mod_search_self(struct ph_context *ac)
2115 {
2116         struct ldb_context *ldb;
2117         static const char * const attrs[] = { "userAccountControl", "lmPwdHistory", 
2118                                               "ntPwdHistory", 
2119                                               "objectSid", "msDS-KeyVersionNumber", 
2120                                               "objectClass", "userPrincipalName",
2121                                               "sAMAccountName", 
2122                                               "dBCSPwd", "unicodePwd",
2123                                               "supplementalCredentials",
2124                                               NULL };
2125         struct ldb_request *search_req;
2126         int ret;
2127
2128         ldb = ldb_module_get_ctx(ac->module);
2129
2130         ret = ldb_build_search_req(&search_req, ldb, ac,
2131                                    ac->req->op.mod.message->dn,
2132                                    LDB_SCOPE_BASE,
2133                                    "(objectclass=*)",
2134                                    attrs,
2135                                    NULL,
2136                                    ac, ph_mod_search_callback,
2137                                    ac->req);
2138
2139         if (ret != LDB_SUCCESS) {
2140                 return ret;
2141         }
2142
2143         return ldb_next_request(ac->module, search_req);
2144 }
2145
2146 static int password_hash_mod_do_mod(struct ph_context *ac)
2147 {
2148         struct ldb_context *ldb;
2149         struct ldb_request *mod_req;
2150         struct ldb_message *msg;
2151         const struct ldb_message *searched_msg;
2152         struct setup_password_fields_io io;
2153         int ret;
2154
2155         ldb = ldb_module_get_ctx(ac->module);
2156
2157         /* use a new message structure so that we can modify it */
2158         msg = ldb_msg_new(ac);
2159         if (msg == NULL) {
2160                 return LDB_ERR_OPERATIONS_ERROR;
2161         }
2162
2163         /* modify dn */
2164         msg->dn = ac->req->op.mod.message->dn;
2165
2166         /* Prepare the internal data structure containing the passwords */
2167         ret = setup_io(ac, 
2168                        ac->req->op.mod.message, 
2169                        ac->search_res->message, 
2170                        &io);
2171         if (ret != LDB_SUCCESS) {
2172                 return ret;
2173         }
2174         
2175         searched_msg = ac->search_res->message;
2176
2177         /* Fill in some final details (only relevent once the password has been set) */
2178         io.o.kvno                       = samdb_result_uint(searched_msg, "msDs-KeyVersionNumber", 0);
2179         io.o.nt_history_len             = samdb_result_hashes(io.ac, searched_msg, "ntPwdHistory", &io.o.nt_history);
2180         io.o.lm_history_len             = samdb_result_hashes(io.ac, searched_msg, "lmPwdHistory", &io.o.lm_history);
2181         io.o.supplemental               = ldb_msg_find_ldb_val(searched_msg, "supplementalCredentials");
2182
2183         ret = setup_password_fields(&io);
2184         if (ret != LDB_SUCCESS) {
2185                 return ret;
2186         }
2187
2188         /* make sure we replace all the old attributes */
2189         ret = ldb_msg_add_empty(msg, "unicodePwd", LDB_FLAG_MOD_REPLACE, NULL);
2190         ret = ldb_msg_add_empty(msg, "dBCSPwd", LDB_FLAG_MOD_REPLACE, NULL);
2191         ret = ldb_msg_add_empty(msg, "ntPwdHistory", LDB_FLAG_MOD_REPLACE, NULL);
2192         ret = ldb_msg_add_empty(msg, "lmPwdHistory", LDB_FLAG_MOD_REPLACE, NULL);
2193         ret = ldb_msg_add_empty(msg, "supplementalCredentials", LDB_FLAG_MOD_REPLACE, NULL);
2194         ret = ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE, NULL);
2195         ret = ldb_msg_add_empty(msg, "msDs-KeyVersionNumber", LDB_FLAG_MOD_REPLACE, NULL);
2196
2197         if (io.g.nt_hash) {
2198                 ret = samdb_msg_add_hash(ldb, ac, msg,
2199                                          "unicodePwd", io.g.nt_hash);
2200                 if (ret != LDB_SUCCESS) {
2201                         return ret;
2202                 }
2203         }
2204         if (io.g.lm_hash) {
2205                 ret = samdb_msg_add_hash(ldb, ac, msg,
2206                                          "dBCSPwd", io.g.lm_hash);
2207                 if (ret != LDB_SUCCESS) {
2208                         return ret;
2209                 }
2210         }
2211         if (io.g.nt_history_len > 0) {
2212                 ret = samdb_msg_add_hashes(ac, msg,
2213                                            "ntPwdHistory",
2214                                            io.g.nt_history,
2215                                            io.g.nt_history_len);
2216                 if (ret != LDB_SUCCESS) {
2217                         return ret;
2218                 }
2219         }
2220         if (io.g.lm_history_len > 0) {
2221                 ret = samdb_msg_add_hashes(ac, msg,
2222                                            "lmPwdHistory",
2223                                            io.g.lm_history,
2224                                            io.g.lm_history_len);
2225                 if (ret != LDB_SUCCESS) {
2226                         return ret;
2227                 }
2228         }
2229         if (io.g.supplemental.length > 0) {
2230                 ret = ldb_msg_add_value(msg, "supplementalCredentials",
2231                                         &io.g.supplemental, NULL);
2232                 if (ret != LDB_SUCCESS) {
2233                         return ret;
2234                 }
2235         }
2236         ret = samdb_msg_add_uint64(ldb, ac, msg,
2237                                    "pwdLastSet",
2238                                    io.g.last_set);
2239         if (ret != LDB_SUCCESS) {
2240                 return ret;
2241         }
2242         ret = samdb_msg_add_uint(ldb, ac, msg,
2243                                  "msDs-KeyVersionNumber",
2244                                  io.g.kvno);
2245         if (ret != LDB_SUCCESS) {
2246                 return ret;
2247         }
2248
2249         ret = ldb_build_mod_req(&mod_req, ldb, ac,
2250                                 msg,
2251                                 ac->req->controls,
2252                                 ac, ph_op_callback,
2253                                 ac->req);
2254         if (ret != LDB_SUCCESS) {
2255                 return ret;
2256         }
2257
2258         return ldb_next_request(ac->module, mod_req);
2259 }
2260
2261 _PUBLIC_ const struct ldb_module_ops ldb_password_hash_module_ops = {
2262         .name          = "password_hash",
2263         .add           = password_hash_add,
2264         .modify        = password_hash_modify,
2265 };