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