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