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