Change uint_t to unsigned int in source4
[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         if (ares->error != LDB_SUCCESS) {
1531                 return ldb_module_done(ac->req, ares->controls,
1532                                         ares->response, ares->error);
1533         }
1534
1535         if (ares->type != LDB_REPLY_DONE) {
1536                 talloc_free(ares);
1537                 return ldb_module_done(ac->req, NULL, NULL,
1538                                         LDB_ERR_OPERATIONS_ERROR);
1539         }
1540
1541         return ldb_module_done(ac->req, ares->controls,
1542                                 ares->response, ares->error);
1543 }
1544
1545 static int password_hash_add_do_add(struct ph_context *ac);
1546 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares);
1547 static int password_hash_mod_search_self(struct ph_context *ac);
1548 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares);
1549 static int password_hash_mod_do_mod(struct ph_context *ac);
1550
1551 static int get_domain_data_callback(struct ldb_request *req,
1552                                     struct ldb_reply *ares)
1553 {
1554         struct ldb_context *ldb;
1555         struct domain_data *data;
1556         struct ph_context *ac;
1557         struct loadparm_context *lp_ctx;
1558         int ret;
1559
1560         ac = talloc_get_type(req->context, struct ph_context);
1561         ldb = ldb_module_get_ctx(ac->module);
1562
1563         if (!ares) {
1564                 return ldb_module_done(ac->req, NULL, NULL,
1565                                         LDB_ERR_OPERATIONS_ERROR);
1566         }
1567         if (ares->error != LDB_SUCCESS) {
1568                 return ldb_module_done(ac->req, ares->controls,
1569                                         ares->response, ares->error);
1570         }
1571
1572         switch (ares->type) {
1573         case LDB_REPLY_ENTRY:
1574                 if (ac->domain != NULL) {
1575                         ldb_set_errstring(ldb, "Too many results");
1576                         return ldb_module_done(ac->req, NULL, NULL,
1577                                                 LDB_ERR_OPERATIONS_ERROR);
1578                 }
1579
1580                 data = talloc_zero(ac, struct domain_data);
1581                 if (data == NULL) {
1582                         return ldb_module_done(ac->req, NULL, NULL,
1583                                                 LDB_ERR_OPERATIONS_ERROR);
1584                 }
1585
1586                 data->pwdProperties = samdb_result_uint(ares->message, "pwdProperties", 0);
1587                 data->store_cleartext = data->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT;
1588                 data->pwdHistoryLength = samdb_result_uint(ares->message, "pwdHistoryLength", 0);
1589
1590                 /* For a domain DN, this puts things in dotted notation */
1591                 /* For builtin domains, this will give details for the host,
1592                  * but that doesn't really matter, as it's just used for salt
1593                  * and kerberos principals, which don't exist here */
1594
1595                 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
1596                                          struct loadparm_context);
1597
1598                 data->dns_domain = lp_dnsdomain(lp_ctx);
1599                 data->realm = lp_realm(lp_ctx);
1600                 data->netbios_domain = lp_sam_name(lp_ctx);
1601
1602                 ac->domain = data;
1603                 break;
1604
1605         case LDB_REPLY_DONE:
1606
1607                 /* call the next step */
1608                 switch (ac->req->operation) {
1609                 case LDB_ADD:
1610                         ret = password_hash_add_do_add(ac);
1611                         break;
1612
1613                 case LDB_MODIFY:
1614                         ret = password_hash_mod_do_mod(ac);
1615                         break;
1616
1617                 default:
1618                         ret = LDB_ERR_OPERATIONS_ERROR;
1619                         break;
1620                 }
1621                 if (ret != LDB_SUCCESS) {
1622                         return ldb_module_done(ac->req, NULL, NULL, ret);
1623                 }
1624                 break;
1625
1626         case LDB_REPLY_REFERRAL:
1627                 /* ignore */
1628                 break;
1629         }
1630
1631         talloc_free(ares);
1632         return LDB_SUCCESS;
1633 }
1634
1635 static int build_domain_data_request(struct ph_context *ac)
1636 {
1637         /* attrs[] is returned from this function in
1638            ac->dom_req->op.search.attrs, so it must be static, as
1639            otherwise the compiler can put it on the stack */
1640         struct ldb_context *ldb;
1641         static const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", NULL };
1642
1643         ldb = ldb_module_get_ctx(ac->module);
1644
1645         return ldb_build_search_req(&ac->dom_req, ldb, ac,
1646                                     ldb_get_default_basedn(ldb),
1647                                     LDB_SCOPE_BASE,
1648                                     NULL, attrs,
1649                                     NULL,
1650                                     ac, get_domain_data_callback,
1651                                     ac->req);
1652 }
1653
1654 static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
1655 {
1656         struct ldb_context *ldb;
1657         struct ph_context *ac;
1658         struct ldb_message_element *sambaAttr;
1659         struct ldb_message_element *clearTextPasswordAttr;
1660         struct ldb_message_element *ntAttr;
1661         struct ldb_message_element *lmAttr;
1662         int ret;
1663
1664         ldb = ldb_module_get_ctx(module);
1665
1666         ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_add\n");
1667
1668         if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */
1669                 return ldb_next_request(module, req);
1670         }
1671
1672         /* If the caller is manipulating the local passwords directly, let them pass */
1673         if (ldb_dn_compare_base(ldb_dn_new(req, ldb, LOCAL_BASE),
1674                                 req->op.add.message->dn) == 0) {
1675                 return ldb_next_request(module, req);
1676         }
1677
1678         /* nobody must touch these fields */
1679         if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) {
1680                 return LDB_ERR_UNWILLING_TO_PERFORM;
1681         }
1682         if (ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) {
1683                 return LDB_ERR_UNWILLING_TO_PERFORM;
1684         }
1685         if (ldb_msg_find_element(req->op.add.message, "supplementalCredentials")) {
1686                 return LDB_ERR_UNWILLING_TO_PERFORM;
1687         }
1688
1689         /* If no part of this ADD touches the userPassword, or the NT
1690          * or LM hashes, then we don't need to make any changes.  */
1691
1692         sambaAttr = ldb_msg_find_element(req->op.mod.message, "userPassword");
1693         clearTextPasswordAttr = ldb_msg_find_element(req->op.mod.message, "clearTextPassword");
1694         ntAttr = ldb_msg_find_element(req->op.mod.message, "unicodePwd");
1695         lmAttr = ldb_msg_find_element(req->op.mod.message, "dBCSPwd");
1696
1697         if ((!sambaAttr) && (!clearTextPasswordAttr) && (!ntAttr) && (!lmAttr)) {
1698                 return ldb_next_request(module, req);
1699         }
1700
1701         /* if it is not an entry of type person its an error */
1702         /* TODO: remove this when userPassword will be in schema */
1703         if (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "person")) {
1704                 ldb_set_errstring(ldb, "Cannot set a password on entry that does not have objectClass 'person'");
1705                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1706         }
1707
1708         /* check userPassword is single valued here */
1709         /* TODO: remove this when userPassword will be single valued in schema */
1710         if (sambaAttr && sambaAttr->num_values > 1) {
1711                 ldb_set_errstring(ldb, "mupltiple values for userPassword not allowed!\n");
1712                 return LDB_ERR_CONSTRAINT_VIOLATION;
1713         }
1714         if (clearTextPasswordAttr && clearTextPasswordAttr->num_values > 1) {
1715                 ldb_set_errstring(ldb, "mupltiple values for clearTextPassword not allowed!\n");
1716                 return LDB_ERR_CONSTRAINT_VIOLATION;
1717         }
1718
1719         if (ntAttr && (ntAttr->num_values > 1)) {
1720                 ldb_set_errstring(ldb, "mupltiple values for unicodePwd not allowed!\n");
1721                 return LDB_ERR_CONSTRAINT_VIOLATION;
1722         }
1723         if (lmAttr && (lmAttr->num_values > 1)) {
1724                 ldb_set_errstring(ldb, "mupltiple values for dBCSPwd not allowed!\n");
1725                 return LDB_ERR_CONSTRAINT_VIOLATION;
1726         }
1727
1728         if (sambaAttr && sambaAttr->num_values == 0) {
1729                 ldb_set_errstring(ldb, "userPassword must have a value!\n");
1730                 return LDB_ERR_CONSTRAINT_VIOLATION;
1731         }
1732
1733         if (clearTextPasswordAttr && clearTextPasswordAttr->num_values == 0) {
1734                 ldb_set_errstring(ldb, "clearTextPassword must have a value!\n");
1735                 return LDB_ERR_CONSTRAINT_VIOLATION;
1736         }
1737
1738         if (ntAttr && (ntAttr->num_values == 0)) {
1739                 ldb_set_errstring(ldb, "unicodePwd must have a value!\n");
1740                 return LDB_ERR_CONSTRAINT_VIOLATION;
1741         }
1742         if (lmAttr && (lmAttr->num_values == 0)) {
1743                 ldb_set_errstring(ldb, "dBCSPwd must have a value!\n");
1744                 return LDB_ERR_CONSTRAINT_VIOLATION;
1745         }
1746
1747         ac = ph_init_context(module, req);
1748         if (ac == NULL) {
1749                 return LDB_ERR_OPERATIONS_ERROR;
1750         }
1751
1752         /* get user domain data */
1753         ret = build_domain_data_request(ac);
1754         if (ret != LDB_SUCCESS) {
1755                 return ret;
1756         }
1757
1758         return ldb_next_request(module, ac->dom_req);
1759 }
1760
1761 static int password_hash_add_do_add(struct ph_context *ac)
1762 {
1763         struct ldb_context *ldb;
1764         struct ldb_request *down_req;
1765         struct ldb_message *msg;
1766         struct setup_password_fields_io io;
1767         int ret;
1768
1769         /* Prepare the internal data structure containing the passwords */
1770         ret = setup_io(ac, ac->req->op.add.message, ac->req->op.add.message, &io);
1771         if (ret != LDB_SUCCESS) {
1772                 return ret;
1773         }
1774
1775         msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
1776         if (msg == NULL) {
1777                 return LDB_ERR_OPERATIONS_ERROR;
1778         }
1779
1780         /* remove attributes that we just read into 'io' */
1781         ldb_msg_remove_attr(msg, "userPassword");
1782         ldb_msg_remove_attr(msg, "clearTextPassword");
1783         ldb_msg_remove_attr(msg, "unicodePwd");
1784         ldb_msg_remove_attr(msg, "dBCSPwd");
1785         ldb_msg_remove_attr(msg, "pwdLastSet");
1786         io.o.kvno = samdb_result_uint(msg, "msDs-KeyVersionNumber", 1) - 1;
1787         ldb_msg_remove_attr(msg, "msDs-KeyVersionNumber");
1788
1789         ldb = ldb_module_get_ctx(ac->module);
1790
1791         ret = setup_password_fields(&io);
1792         if (ret != LDB_SUCCESS) {
1793                 return ret;
1794         }
1795
1796         if (io.g.nt_hash) {
1797                 ret = samdb_msg_add_hash(ldb, ac, msg,
1798                                          "unicodePwd", io.g.nt_hash);
1799                 if (ret != LDB_SUCCESS) {
1800                         return ret;
1801                 }
1802         }
1803         if (io.g.lm_hash) {
1804                 ret = samdb_msg_add_hash(ldb, ac, msg,
1805                                          "dBCSPwd", io.g.lm_hash);
1806                 if (ret != LDB_SUCCESS) {
1807                         return ret;
1808                 }
1809         }
1810         if (io.g.nt_history_len > 0) {
1811                 ret = samdb_msg_add_hashes(ac, msg,
1812                                            "ntPwdHistory",
1813                                            io.g.nt_history,
1814                                            io.g.nt_history_len);
1815                 if (ret != LDB_SUCCESS) {
1816                         return ret;
1817                 }
1818         }
1819         if (io.g.lm_history_len > 0) {
1820                 ret = samdb_msg_add_hashes(ac, msg,
1821                                            "lmPwdHistory",
1822                                            io.g.lm_history,
1823                                            io.g.lm_history_len);
1824                 if (ret != LDB_SUCCESS) {
1825                         return ret;
1826                 }
1827         }
1828         if (io.g.supplemental.length > 0) {
1829                 ret = ldb_msg_add_value(msg, "supplementalCredentials",
1830                                         &io.g.supplemental, NULL);
1831                 if (ret != LDB_SUCCESS) {
1832                         return ret;
1833                 }
1834         }
1835         ret = samdb_msg_add_uint64(ldb, ac, msg,
1836                                    "pwdLastSet",
1837                                    io.g.last_set);
1838         if (ret != LDB_SUCCESS) {
1839                 return ret;
1840         }
1841         ret = samdb_msg_add_uint(ldb, ac, msg,
1842                                  "msDs-KeyVersionNumber",
1843                                  io.g.kvno);
1844         if (ret != LDB_SUCCESS) {
1845                 return ret;
1846         }
1847
1848         ret = ldb_build_add_req(&down_req, ldb, ac,
1849                                 msg,
1850                                 ac->req->controls,
1851                                 ac, ph_op_callback,
1852                                 ac->req);
1853         if (ret != LDB_SUCCESS) {
1854                 return ret;
1855         }
1856
1857         return ldb_next_request(ac->module, down_req);
1858 }
1859
1860 static int password_hash_modify(struct ldb_module *module, struct ldb_request *req)
1861 {
1862         struct ldb_context *ldb;
1863         struct ph_context *ac;
1864         struct ldb_message_element *sambaAttr;
1865         struct ldb_message_element *clearTextAttr;
1866         struct ldb_message_element *ntAttr;
1867         struct ldb_message_element *lmAttr;
1868         struct ldb_message *msg;
1869         struct ldb_request *down_req;
1870         int ret;
1871
1872         ldb = ldb_module_get_ctx(module);
1873
1874         ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_modify\n");
1875
1876         if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */
1877                 return ldb_next_request(module, req);
1878         }
1879         
1880         /* If the caller is manipulating the local passwords directly, let them pass */
1881         if (ldb_dn_compare_base(ldb_dn_new(req, ldb, LOCAL_BASE),
1882                                 req->op.mod.message->dn) == 0) {
1883                 return ldb_next_request(module, req);
1884         }
1885
1886         /* nobody must touch password Histories */
1887         if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) {
1888                 return LDB_ERR_UNWILLING_TO_PERFORM;
1889         }
1890         if (ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) {
1891                 return LDB_ERR_UNWILLING_TO_PERFORM;
1892         }
1893         if (ldb_msg_find_element(req->op.add.message, "supplementalCredentials")) {
1894                 return LDB_ERR_UNWILLING_TO_PERFORM;
1895         }
1896
1897         sambaAttr = ldb_msg_find_element(req->op.mod.message, "userPassword");
1898         clearTextAttr = ldb_msg_find_element(req->op.mod.message, "clearTextPassword");
1899         ntAttr = ldb_msg_find_element(req->op.mod.message, "unicodePwd");
1900         lmAttr = ldb_msg_find_element(req->op.mod.message, "dBCSPwd");
1901
1902         /* If no part of this touches the userPassword OR
1903          * clearTextPassword OR unicodePwd and/or dBCSPwd, then we
1904          * don't need to make any changes.  For password changes/set
1905          * there should be a 'delete' or a 'modify' on this
1906          * attribute. */
1907         if ((!sambaAttr) && (!clearTextAttr) && (!ntAttr) && (!lmAttr)) {
1908                 return ldb_next_request(module, req);
1909         }
1910
1911         /* check passwords are single valued here */
1912         /* TODO: remove this when passwords will be single valued in schema */
1913         if (sambaAttr && (sambaAttr->num_values > 1)) {
1914                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1915                 return LDB_ERR_CONSTRAINT_VIOLATION;
1916         }
1917         if (clearTextAttr && (clearTextAttr->num_values > 1)) {
1918                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1919                 return LDB_ERR_CONSTRAINT_VIOLATION;
1920         }
1921         if (ntAttr && (ntAttr->num_values > 1)) {
1922                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1923                 return LDB_ERR_CONSTRAINT_VIOLATION;
1924         }
1925         if (lmAttr && (lmAttr->num_values > 1)) {
1926                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1927                 return LDB_ERR_CONSTRAINT_VIOLATION;
1928         }
1929
1930         ac = ph_init_context(module, req);
1931         if (!ac) {
1932                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1933                 return LDB_ERR_OPERATIONS_ERROR;
1934         }
1935
1936         /* use a new message structure so that we can modify it */
1937         msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
1938         if (msg == NULL) {
1939                 ldb_oom(ldb);
1940                 return LDB_ERR_OPERATIONS_ERROR;
1941         }
1942
1943         /* - remove any modification to the password from the first commit
1944          *   we will make the real modification later */
1945         if (sambaAttr) ldb_msg_remove_attr(msg, "userPassword");
1946         if (clearTextAttr) ldb_msg_remove_attr(msg, "clearTextPassword");
1947         if (ntAttr) ldb_msg_remove_attr(msg, "unicodePwd");
1948         if (lmAttr) ldb_msg_remove_attr(msg, "dBCSPwd");
1949
1950         /* if there was nothing else to be modified skip to next step */
1951         if (msg->num_elements == 0) {
1952                 return password_hash_mod_search_self(ac);
1953         }
1954
1955         ret = ldb_build_mod_req(&down_req, ldb, ac,
1956                                 msg,
1957                                 req->controls,
1958                                 ac, ph_modify_callback,
1959                                 req);
1960         if (ret != LDB_SUCCESS) {
1961                 return ret;
1962         }
1963
1964         return ldb_next_request(module, down_req);
1965 }
1966
1967 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
1968 {
1969         struct ph_context *ac;
1970         int ret;
1971
1972         ac = talloc_get_type(req->context, struct ph_context);
1973
1974         if (!ares) {
1975                 return ldb_module_done(ac->req, NULL, NULL,
1976                                         LDB_ERR_OPERATIONS_ERROR);
1977         }
1978         if (ares->error != LDB_SUCCESS) {
1979                 return ldb_module_done(ac->req, ares->controls,
1980                                         ares->response, ares->error);
1981         }
1982
1983         if (ares->type != LDB_REPLY_DONE) {
1984                 talloc_free(ares);
1985                 return ldb_module_done(ac->req, NULL, NULL,
1986                                         LDB_ERR_OPERATIONS_ERROR);
1987         }
1988
1989         ret = password_hash_mod_search_self(ac);
1990         if (ret != LDB_SUCCESS) {
1991                 return ldb_module_done(ac->req, NULL, NULL, ret);
1992         }
1993
1994         talloc_free(ares);
1995         return LDB_SUCCESS;
1996 }
1997
1998 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares)
1999 {
2000         struct ldb_context *ldb;
2001         struct ph_context *ac;
2002         int ret;
2003
2004         ac = talloc_get_type(req->context, struct ph_context);
2005         ldb = ldb_module_get_ctx(ac->module);
2006
2007         if (!ares) {
2008                 return ldb_module_done(ac->req, NULL, NULL,
2009                                         LDB_ERR_OPERATIONS_ERROR);
2010         }
2011         if (ares->error != LDB_SUCCESS) {
2012                 return ldb_module_done(ac->req, ares->controls,
2013                                         ares->response, ares->error);
2014         }
2015
2016         /* we are interested only in the single reply (base search) */
2017         switch (ares->type) {
2018         case LDB_REPLY_ENTRY:
2019
2020                 if (ac->search_res != NULL) {
2021                         ldb_set_errstring(ldb, "Too many results");
2022                         talloc_free(ares);
2023                         return ldb_module_done(ac->req, NULL, NULL,
2024                                                 LDB_ERR_OPERATIONS_ERROR);
2025                 }
2026
2027                 /* if it is not an entry of type person this is an error */
2028                 /* TODO: remove this when sambaPassword will be in schema */
2029                 if (!ldb_msg_check_string_attribute(ares->message, "objectClass", "person")) {
2030                         ldb_set_errstring(ldb, "Object class violation");
2031                         talloc_free(ares);
2032                         return ldb_module_done(ac->req, NULL, NULL,
2033                                         LDB_ERR_OBJECT_CLASS_VIOLATION);
2034                 }
2035
2036                 ac->search_res = talloc_steal(ac, ares);
2037                 return LDB_SUCCESS;
2038
2039         case LDB_REPLY_DONE:
2040
2041                 /* get user domain data */
2042                 ret = build_domain_data_request(ac);
2043                 if (ret != LDB_SUCCESS) {
2044                         return ldb_module_done(ac->req, NULL, NULL,ret);
2045                 }
2046
2047                 return ldb_next_request(ac->module, ac->dom_req);
2048
2049         case LDB_REPLY_REFERRAL:
2050                 /*ignore anything else for now */
2051                 break;
2052         }
2053
2054         talloc_free(ares);
2055         return LDB_SUCCESS;
2056 }
2057
2058 static int password_hash_mod_search_self(struct ph_context *ac)
2059 {
2060         struct ldb_context *ldb;
2061         static const char * const attrs[] = { "userAccountControl", "lmPwdHistory", 
2062                                               "ntPwdHistory", 
2063                                               "objectSid", "msDS-KeyVersionNumber", 
2064                                               "objectClass", "userPrincipalName",
2065                                               "sAMAccountName", 
2066                                               "dBCSPwd", "unicodePwd",
2067                                               "supplementalCredentials",
2068                                               NULL };
2069         struct ldb_request *search_req;
2070         int ret;
2071
2072         ldb = ldb_module_get_ctx(ac->module);
2073
2074         ret = ldb_build_search_req(&search_req, ldb, ac,
2075                                    ac->req->op.mod.message->dn,
2076                                    LDB_SCOPE_BASE,
2077                                    "(objectclass=*)",
2078                                    attrs,
2079                                    NULL,
2080                                    ac, ph_mod_search_callback,
2081                                    ac->req);
2082
2083         if (ret != LDB_SUCCESS) {
2084                 return ret;
2085         }
2086
2087         return ldb_next_request(ac->module, search_req);
2088 }
2089
2090 static int password_hash_mod_do_mod(struct ph_context *ac)
2091 {
2092         struct ldb_context *ldb;
2093         struct ldb_request *mod_req;
2094         struct ldb_message *msg;
2095         const struct ldb_message *searched_msg;
2096         struct setup_password_fields_io io;
2097         int ret;
2098
2099         ldb = ldb_module_get_ctx(ac->module);
2100
2101         /* use a new message structure so that we can modify it */
2102         msg = ldb_msg_new(ac);
2103         if (msg == NULL) {
2104                 return LDB_ERR_OPERATIONS_ERROR;
2105         }
2106
2107         /* modify dn */
2108         msg->dn = ac->req->op.mod.message->dn;
2109
2110         /* Prepare the internal data structure containing the passwords */
2111         ret = setup_io(ac, 
2112                        ac->req->op.mod.message, 
2113                        ac->search_res->message, 
2114                        &io);
2115         if (ret != LDB_SUCCESS) {
2116                 return ret;
2117         }
2118         
2119         searched_msg = ac->search_res->message;
2120
2121         /* Fill in some final details (only relevent once the password has been set) */
2122         io.o.kvno                       = samdb_result_uint(searched_msg, "msDs-KeyVersionNumber", 0);
2123         io.o.nt_history_len             = samdb_result_hashes(io.ac, searched_msg, "ntPwdHistory", &io.o.nt_history);
2124         io.o.lm_history_len             = samdb_result_hashes(io.ac, searched_msg, "lmPwdHistory", &io.o.lm_history);
2125         io.o.supplemental               = ldb_msg_find_ldb_val(searched_msg, "supplementalCredentials");
2126
2127         ret = setup_password_fields(&io);
2128         if (ret != LDB_SUCCESS) {
2129                 return ret;
2130         }
2131
2132         /* make sure we replace all the old attributes */
2133         ret = ldb_msg_add_empty(msg, "unicodePwd", LDB_FLAG_MOD_REPLACE, NULL);
2134         ret = ldb_msg_add_empty(msg, "dBCSPwd", LDB_FLAG_MOD_REPLACE, NULL);
2135         ret = ldb_msg_add_empty(msg, "ntPwdHistory", LDB_FLAG_MOD_REPLACE, NULL);
2136         ret = ldb_msg_add_empty(msg, "lmPwdHistory", LDB_FLAG_MOD_REPLACE, NULL);
2137         ret = ldb_msg_add_empty(msg, "supplementalCredentials", LDB_FLAG_MOD_REPLACE, NULL);
2138         ret = ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE, NULL);
2139         ret = ldb_msg_add_empty(msg, "msDs-KeyVersionNumber", LDB_FLAG_MOD_REPLACE, NULL);
2140
2141         if (io.g.nt_hash) {
2142                 ret = samdb_msg_add_hash(ldb, ac, msg,
2143                                          "unicodePwd", io.g.nt_hash);
2144                 if (ret != LDB_SUCCESS) {
2145                         return ret;
2146                 }
2147         }
2148         if (io.g.lm_hash) {
2149                 ret = samdb_msg_add_hash(ldb, ac, msg,
2150                                          "dBCSPwd", io.g.lm_hash);
2151                 if (ret != LDB_SUCCESS) {
2152                         return ret;
2153                 }
2154         }
2155         if (io.g.nt_history_len > 0) {
2156                 ret = samdb_msg_add_hashes(ac, msg,
2157                                            "ntPwdHistory",
2158                                            io.g.nt_history,
2159                                            io.g.nt_history_len);
2160                 if (ret != LDB_SUCCESS) {
2161                         return ret;
2162                 }
2163         }
2164         if (io.g.lm_history_len > 0) {
2165                 ret = samdb_msg_add_hashes(ac, msg,
2166                                            "lmPwdHistory",
2167                                            io.g.lm_history,
2168                                            io.g.lm_history_len);
2169                 if (ret != LDB_SUCCESS) {
2170                         return ret;
2171                 }
2172         }
2173         if (io.g.supplemental.length > 0) {
2174                 ret = ldb_msg_add_value(msg, "supplementalCredentials",
2175                                         &io.g.supplemental, NULL);
2176                 if (ret != LDB_SUCCESS) {
2177                         return ret;
2178                 }
2179         }
2180         ret = samdb_msg_add_uint64(ldb, ac, msg,
2181                                    "pwdLastSet",
2182                                    io.g.last_set);
2183         if (ret != LDB_SUCCESS) {
2184                 return ret;
2185         }
2186         ret = samdb_msg_add_uint(ldb, ac, msg,
2187                                  "msDs-KeyVersionNumber",
2188                                  io.g.kvno);
2189         if (ret != LDB_SUCCESS) {
2190                 return ret;
2191         }
2192
2193         ret = ldb_build_mod_req(&mod_req, ldb, ac,
2194                                 msg,
2195                                 ac->req->controls,
2196                                 ac, ph_op_callback,
2197                                 ac->req);
2198         if (ret != LDB_SUCCESS) {
2199                 return ret;
2200         }
2201
2202         return ldb_next_request(ac->module, mod_req);
2203 }
2204
2205 _PUBLIC_ const struct ldb_module_ops ldb_password_hash_module_ops = {
2206         .name          = "password_hash",
2207         .add           = password_hash_add,
2208         .modify        = password_hash_modify,
2209 };