ldb: mark the location of a lot more ldb requests
[samba.git] / source4 / dsdb / samdb / ldb_modules / password_hash.c
1 /* 
2    ldb database module
3
4    Copyright (C) Simo Sorce  2004-2008
5    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2006
6    Copyright (C) Andrew Tridgell 2004
7    Copyright (C) Stefan Metzmacher 2007-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         struct dsdb_control_password_change *change;
99
100         bool pwd_reset;
101
102         bool change_status;
103         bool hash_values;
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) {
1440                 bool nt_hash_checked = false;
1441
1442                 /* we need the old nt or lm hash given by the client */
1443                 if (!io->og.nt_hash && !io->og.lm_hash) {
1444                         ldb_asprintf_errstring(ldb,
1445                                 "check_password_restrictions: "
1446                                 "You need to provide the old password in order "
1447                                 "to change it!");
1448                         return LDB_ERR_UNWILLING_TO_PERFORM;
1449                 }
1450
1451                 /* The password modify through the NT hash is encouraged and
1452                    has no problems at all */
1453                 if (io->og.nt_hash) {
1454                         if (!io->o.nt_hash) {
1455                                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
1456                                 ldb_asprintf_errstring(ldb,
1457                                         "%08X: %s - check_password_restrictions: "
1458                                         "There's no old nt_hash, which is needed "
1459                                         "in order to change your password!",
1460                                         W_ERROR_V(WERR_INVALID_PASSWORD),
1461                                         ldb_strerror(ret));
1462                                 return ret;
1463                         }
1464
1465                         if (memcmp(io->og.nt_hash->hash, io->o.nt_hash->hash, 16) != 0) {
1466                                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
1467                                 ldb_asprintf_errstring(ldb,
1468                                         "%08X: %s - check_password_restrictions: "
1469                                         "The old password specified doesn't match!",
1470                                         W_ERROR_V(WERR_INVALID_PASSWORD),
1471                                         ldb_strerror(ret));
1472                                 return ret;
1473                         }
1474
1475                         nt_hash_checked = true;
1476                 }
1477
1478                 /* But it is also possible to change a password by the LM hash
1479                  * alone for compatibility reasons. This check is optional if
1480                  * the NT hash was already checked - otherwise it's mandatory.
1481                  * (as the SAMR operations request it). */
1482                 if (io->og.lm_hash) {
1483                         if (!io->o.lm_hash && !nt_hash_checked) {
1484                                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
1485                                 ldb_asprintf_errstring(ldb,
1486                                         "%08X: %s - check_password_restrictions: "
1487                                         "There's no old lm_hash, which is needed "
1488                                         "in order to change your password!",
1489                                         W_ERROR_V(WERR_INVALID_PASSWORD),
1490                                         ldb_strerror(ret));
1491                                 return ret;
1492                         }
1493
1494                         if (io->o.lm_hash &&
1495                             memcmp(io->og.lm_hash->hash, io->o.lm_hash->hash, 16) != 0) {
1496                                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
1497                                 ldb_asprintf_errstring(ldb,
1498                                         "%08X: %s - check_password_restrictions: "
1499                                         "The old password specified doesn't match!",
1500                                         W_ERROR_V(WERR_INVALID_PASSWORD),
1501                                         ldb_strerror(ret));
1502                                 return ret;
1503                         }
1504                 }
1505         }
1506
1507         if (io->u.restrictions == 0) {
1508                 /* FIXME: Is this right? */
1509                 return LDB_SUCCESS;
1510         }
1511
1512         /*
1513          * Fundamental password checks done by the call
1514          * "samdb_check_password".
1515          * It is also in use by "dcesrv_samr_ValidatePassword".
1516          */
1517         if (io->n.cleartext_utf8 != NULL) {
1518                 stat = samdb_check_password(io->n.cleartext_utf8,
1519                                             io->ac->status->domain_data.pwdProperties,
1520                                             io->ac->status->domain_data.minPwdLength);
1521                 switch (stat) {
1522                 case SAMR_VALIDATION_STATUS_SUCCESS:
1523                                 /* perfect -> proceed! */
1524                         break;
1525
1526                 case SAMR_VALIDATION_STATUS_PWD_TOO_SHORT:
1527                         ret = LDB_ERR_CONSTRAINT_VIOLATION;
1528                         ldb_asprintf_errstring(ldb,
1529                                 "%08X: %s - check_password_restrictions: "
1530                                 "the password is too short. It should be equal or longer than %u characters!",
1531                                 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
1532                                 ldb_strerror(ret),
1533                                 io->ac->status->domain_data.minPwdLength);
1534                         io->ac->status->reject_reason = SAM_PWD_CHANGE_PASSWORD_TOO_SHORT;
1535                         return ret;
1536
1537                 case SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH:
1538                         ret = LDB_ERR_CONSTRAINT_VIOLATION;
1539                         ldb_asprintf_errstring(ldb,
1540                                 "%08X: %s - check_password_restrictions: "
1541                                 "the password does not meet the complexity criterias!",
1542                                 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
1543                                 ldb_strerror(ret));
1544                         io->ac->status->reject_reason = SAM_PWD_CHANGE_NOT_COMPLEX;
1545                         return ret;
1546
1547                 default:
1548                         ret = LDB_ERR_CONSTRAINT_VIOLATION;
1549                         ldb_asprintf_errstring(ldb,
1550                                 "%08X: %s - check_password_restrictions: "
1551                                 "the password doesn't fit by a certain reason!",
1552                                 W_ERROR_V(WERR_PASSWORD_RESTRICTION),
1553                                 ldb_strerror(ret));
1554                         return ret;
1555                 }
1556         }
1557
1558         if (io->ac->pwd_reset) {
1559                 return LDB_SUCCESS;
1560         }
1561
1562         if (io->n.nt_hash) {
1563                 uint32_t i;
1564
1565                 /* checks the NT hash password history */
1566                 for (i = 0; i < io->o.nt_history_len; i++) {
1567                         ret = memcmp(io->n.nt_hash, io->o.nt_history[i].hash, 16);
1568                         if (ret == 0) {
1569                                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
1570                                 ldb_asprintf_errstring(ldb,
1571                                         "%08X: %s - check_password_restrictions: "
1572                                         "the password was already used (in history)!",
1573                                         W_ERROR_V(WERR_PASSWORD_RESTRICTION),
1574                                         ldb_strerror(ret));
1575                                 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
1576                                 return ret;
1577                         }
1578                 }
1579         }
1580
1581         if (io->n.lm_hash) {
1582                 uint32_t i;
1583
1584                 /* checks the LM hash password history */
1585                 for (i = 0; i < io->o.lm_history_len; i++) {
1586                         ret = memcmp(io->n.nt_hash, io->o.lm_history[i].hash, 16);
1587                         if (ret == 0) {
1588                                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
1589                                 ldb_asprintf_errstring(ldb,
1590                                         "%08X: %s - check_password_restrictions: "
1591                                         "the password was already used (in history)!",
1592                                         W_ERROR_V(WERR_PASSWORD_RESTRICTION),
1593                                         ldb_strerror(ret));
1594                                 io->ac->status->reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
1595                                 return ret;
1596                         }
1597                 }
1598         }
1599
1600         /* are all password changes disallowed? */
1601         if (io->ac->status->domain_data.pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
1602                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
1603                 ldb_asprintf_errstring(ldb,
1604                         "%08X: %s - check_password_restrictions: "
1605                         "password changes disabled!",
1606                         W_ERROR_V(WERR_PASSWORD_RESTRICTION),
1607                         ldb_strerror(ret));
1608                 return ret;
1609         }
1610
1611         /* can this user change the password? */
1612         if (io->u.userAccountControl & UF_PASSWD_CANT_CHANGE) {
1613                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
1614                 ldb_asprintf_errstring(ldb,
1615                         "%08X: %s - check_password_restrictions: "
1616                         "password can't be changed on this account!",
1617                         W_ERROR_V(WERR_PASSWORD_RESTRICTION),
1618                         ldb_strerror(ret));
1619                 return ret;
1620         }
1621
1622         /* Password minimum age: yes, this is a minus. The ages are in negative 100nsec units! */
1623         if (io->u.pwdLastSet - io->ac->status->domain_data.minPwdAge > io->g.last_set) {
1624                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
1625                 ldb_asprintf_errstring(ldb,
1626                         "%08X: %s - check_password_restrictions: "
1627                         "password is too young to change!",
1628                         W_ERROR_V(WERR_PASSWORD_RESTRICTION),
1629                         ldb_strerror(ret));
1630                 return ret;
1631         }
1632
1633         return LDB_SUCCESS;
1634 }
1635
1636 static int setup_io(struct ph_context *ac, 
1637                     const struct ldb_message *orig_msg,
1638                     const struct ldb_message *searched_msg, 
1639                     struct setup_password_fields_io *io) 
1640
1641         const struct ldb_val *quoted_utf16, *old_quoted_utf16, *lm_hash, *old_lm_hash;
1642         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1643         struct loadparm_context *lp_ctx =
1644                 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
1645                                          struct loadparm_context);
1646         int ret;
1647
1648         ZERO_STRUCTP(io);
1649
1650         /* Some operations below require kerberos contexts */
1651
1652         if (smb_krb5_init_context(ac,
1653                                   ldb_get_event_context(ldb),
1654                                   (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm"),
1655                                   &io->smb_krb5_context) != 0) {
1656                 return ldb_operr(ldb);
1657         }
1658
1659         io->ac                          = ac;
1660
1661         io->u.userAccountControl        = samdb_result_uint(searched_msg, "userAccountControl", 0);
1662         io->u.pwdLastSet                = samdb_result_nttime(searched_msg, "pwdLastSet", 0);
1663         io->u.sAMAccountName            = samdb_result_string(searched_msg, "sAMAccountName", NULL);
1664         io->u.user_principal_name       = samdb_result_string(searched_msg, "userPrincipalName", NULL);
1665         io->u.is_computer               = ldb_msg_check_string_attribute(searched_msg, "objectClass", "computer");
1666
1667         if (io->u.sAMAccountName == NULL) {
1668                 ldb_asprintf_errstring(ldb,
1669                                        "setup_io: sAMAccountName attribute is missing on %s for attempted password set/change",
1670                                        ldb_dn_get_linearized(searched_msg->dn));
1671
1672                 return LDB_ERR_CONSTRAINT_VIOLATION;
1673         }
1674
1675         /* Only non-trust accounts have restrictions (possibly this test is the
1676          * wrong way around, but we like to be restrictive if possible */
1677         io->u.restrictions = !(io->u.userAccountControl
1678                 & (UF_INTERDOMAIN_TRUST_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT
1679                         | UF_SERVER_TRUST_ACCOUNT));
1680
1681         if ((io->u.userAccountControl & UF_PASSWD_NOTREQD) != 0) {
1682                 /* see [MS-ADTS] 2.2.15 */
1683                 io->u.restrictions = 0;
1684         }
1685
1686         ret = samdb_msg_find_old_and_new_ldb_val(orig_msg, "userPassword",
1687                 &io->n.cleartext_utf8, &io->og.cleartext_utf8);
1688         if (ret != LDB_SUCCESS) {
1689                 ldb_asprintf_errstring(ldb,
1690                         "setup_io: "
1691                         "it's only allowed to set the old password once!");
1692                 return ret;
1693         }
1694
1695         ret = samdb_msg_find_old_and_new_ldb_val(orig_msg, "clearTextPassword",
1696                 &io->n.cleartext_utf16, &io->og.cleartext_utf16);
1697         if (ret != LDB_SUCCESS) {
1698                 ldb_asprintf_errstring(ldb,
1699                         "setup_io: "
1700                         "it's only allowed to set the old password once!");
1701                 return ret;
1702         }
1703
1704         /* this rather strange looking piece of code is there to
1705            handle a ldap client setting a password remotely using the
1706            unicodePwd ldap field. The syntax is that the password is
1707            in UTF-16LE, with a " at either end. Unfortunately the
1708            unicodePwd field is also used to store the nt hashes
1709            internally in Samba, and is used in the nt hash format on
1710            the wire in DRS replication, so we have a single name for
1711            two distinct values. The code below leaves us with a small
1712            chance (less than 1 in 2^32) of a mixup, if someone manages
1713            to create a MD4 hash which starts and ends in 0x22 0x00, as
1714            that would then be treated as a UTF16 password rather than
1715            a nthash */
1716
1717         ret = samdb_msg_find_old_and_new_ldb_val(orig_msg, "unicodePwd",
1718                 &quoted_utf16, &old_quoted_utf16);
1719         if (ret != LDB_SUCCESS) {
1720                 ldb_asprintf_errstring(ldb,
1721                         "setup_io: "
1722                         "it's only allowed to set the old password once!");
1723                 return ret;
1724         }
1725
1726         /* Checks and converts the actual "unicodePwd" attribute */
1727         if (quoted_utf16 &&
1728             quoted_utf16->length >= 4 &&
1729             quoted_utf16->data[0] == '"' &&
1730             quoted_utf16->data[1] == 0 &&
1731             quoted_utf16->data[quoted_utf16->length-2] == '"' &&
1732             quoted_utf16->data[quoted_utf16->length-1] == 0) {
1733                 struct ldb_val *quoted_utf16_2;
1734
1735                 if (io->n.cleartext_utf16) {
1736                         /* refuse the change if someone wants to change with
1737                            with both UTF16 possibilities at the same time... */
1738                         ldb_asprintf_errstring(ldb,
1739                                 "setup_io: "
1740                                 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'clearTextPassword'");
1741                         return LDB_ERR_UNWILLING_TO_PERFORM;
1742                 }
1743
1744                 /*
1745                  * adapt the quoted UTF16 string to be a real
1746                  * cleartext one
1747                  */
1748                 quoted_utf16_2 = talloc(io->ac, struct ldb_val);
1749                 if (quoted_utf16_2 == NULL) {
1750                         return ldb_oom(ldb);
1751                 }
1752
1753                 quoted_utf16_2->data = quoted_utf16->data + 2;
1754                 quoted_utf16_2->length = quoted_utf16->length-4;
1755                 io->n.cleartext_utf16 = quoted_utf16_2;
1756                 io->n.nt_hash = NULL;
1757
1758         } else if (quoted_utf16) {
1759                 /* We have only the hash available -> so no plaintext here */
1760                 if (!ac->hash_values) {
1761                         /* refuse the change if someone wants to change
1762                            the hash without control specified... */
1763                         ldb_asprintf_errstring(ldb,
1764                                 "setup_io: "
1765                                 "it's not allowed to set the NT hash password directly'");
1766                         /* this looks odd but this is what Windows does:
1767                            returns "UNWILLING_TO_PERFORM" on wrong
1768                            password sets and "CONSTRAINT_VIOLATION" on
1769                            wrong password changes. */
1770                         if (old_quoted_utf16 == NULL) {
1771                                 return LDB_ERR_UNWILLING_TO_PERFORM;
1772                         }
1773
1774                         return LDB_ERR_CONSTRAINT_VIOLATION;
1775                 }
1776
1777                 io->n.nt_hash = talloc(io->ac, struct samr_Password);
1778                 memcpy(io->n.nt_hash->hash, quoted_utf16->data,
1779                        MIN(quoted_utf16->length, sizeof(io->n.nt_hash->hash)));
1780         }
1781
1782         /* Checks and converts the previous "unicodePwd" attribute */
1783         if (old_quoted_utf16 &&
1784             old_quoted_utf16->length >= 4 &&
1785             old_quoted_utf16->data[0] == '"' &&
1786             old_quoted_utf16->data[1] == 0 &&
1787             old_quoted_utf16->data[old_quoted_utf16->length-2] == '"' &&
1788             old_quoted_utf16->data[old_quoted_utf16->length-1] == 0) {
1789                 struct ldb_val *old_quoted_utf16_2;
1790
1791                 if (io->og.cleartext_utf16) {
1792                         /* refuse the change if someone wants to change with
1793                            both UTF16 possibilities at the same time... */
1794                         ldb_asprintf_errstring(ldb,
1795                                 "setup_io: "
1796                                 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'clearTextPassword'");
1797                         return LDB_ERR_UNWILLING_TO_PERFORM;
1798                 }
1799
1800                 /*
1801                  * adapt the quoted UTF16 string to be a real
1802                  * cleartext one
1803                  */
1804                 old_quoted_utf16_2 = talloc(io->ac, struct ldb_val);
1805                 if (old_quoted_utf16_2 == NULL) {
1806                         return ldb_oom(ldb);
1807                 }
1808
1809                 old_quoted_utf16_2->data = old_quoted_utf16->data + 2;
1810                 old_quoted_utf16_2->length = old_quoted_utf16->length-4;
1811
1812                 io->og.cleartext_utf16 = old_quoted_utf16_2;
1813                 io->og.nt_hash = NULL;
1814         } else if (old_quoted_utf16) {
1815                 /* We have only the hash available -> so no plaintext here */
1816                 if (!ac->hash_values) {
1817                         /* refuse the change if someone wants to change
1818                            the hash without control specified... */
1819                         ldb_asprintf_errstring(ldb,
1820                                 "setup_io: "
1821                                 "it's not allowed to set the NT hash password directly'");
1822                         return LDB_ERR_UNWILLING_TO_PERFORM;
1823                 }
1824
1825                 io->og.nt_hash = talloc(io->ac, struct samr_Password);
1826                 memcpy(io->og.nt_hash->hash, old_quoted_utf16->data,
1827                        MIN(old_quoted_utf16->length, sizeof(io->og.nt_hash->hash)));
1828         }
1829
1830         /* Handles the "dBCSPwd" attribute (LM hash) */
1831         io->n.lm_hash = NULL; io->og.lm_hash = NULL;
1832         ret = samdb_msg_find_old_and_new_ldb_val(orig_msg, "dBCSPwd",
1833                 &lm_hash, &old_lm_hash);
1834         if (ret != LDB_SUCCESS) {
1835                 ldb_asprintf_errstring(ldb,
1836                         "setup_io: "
1837                         "it's only allowed to set the old password once!");
1838                 return ret;
1839         }
1840
1841         if (((lm_hash != NULL) || (old_lm_hash != NULL)) && (!ac->hash_values)) {
1842                 /* refuse the change if someone wants to change the hash
1843                    without control specified... */
1844                 ldb_asprintf_errstring(ldb,
1845                         "setup_io: "
1846                         "it's not allowed to set the LM hash password directly'");
1847                 return LDB_ERR_UNWILLING_TO_PERFORM;
1848         }
1849
1850         if (lpcfg_lanman_auth(lp_ctx) && (lm_hash != NULL)) {
1851                 io->n.lm_hash = talloc(io->ac, struct samr_Password);
1852                 memcpy(io->n.lm_hash->hash, lm_hash->data, MIN(lm_hash->length,
1853                        sizeof(io->n.lm_hash->hash)));
1854         }
1855         if (lpcfg_lanman_auth(lp_ctx) && (old_lm_hash != NULL)) {
1856                 io->og.lm_hash = talloc(io->ac, struct samr_Password);
1857                 memcpy(io->og.lm_hash->hash, old_lm_hash->data, MIN(old_lm_hash->length,
1858                        sizeof(io->og.lm_hash->hash)));
1859         }
1860
1861         /*
1862          * Handles the password change control if it's specified. It has the
1863          * precedance and overrides already specified old password values of
1864          * change requests (but that shouldn't happen since the control is
1865          * fully internal and only used in conjunction with replace requests!).
1866          */
1867         if (ac->change != NULL) {
1868                 io->og.nt_hash = NULL;
1869                 if (ac->change->old_nt_pwd_hash != NULL) {
1870                         io->og.nt_hash = talloc_memdup(io->ac,
1871                                                        ac->change->old_nt_pwd_hash,
1872                                                        sizeof(struct samr_Password));
1873                 }
1874                 io->og.lm_hash = NULL;
1875                 if (lpcfg_lanman_auth(lp_ctx) && (ac->change->old_lm_pwd_hash != NULL)) {
1876                         io->og.lm_hash = talloc_memdup(io->ac,
1877                                                        ac->change->old_lm_pwd_hash,
1878                                                        sizeof(struct samr_Password));
1879                 }
1880         }
1881
1882         /* refuse the change if someone wants to change the clear-
1883            text and supply his own hashes at the same time... */
1884         if ((io->n.cleartext_utf8 || io->n.cleartext_utf16)
1885                         && (io->n.nt_hash || io->n.lm_hash)) {
1886                 ldb_asprintf_errstring(ldb,
1887                         "setup_io: "
1888                         "it's only allowed to set the password in form of cleartext attributes or as hashes");
1889                 return LDB_ERR_UNWILLING_TO_PERFORM;
1890         }
1891
1892         /* refuse the change if someone wants to change the password
1893            using both plaintext methods (UTF8 and UTF16) at the same time... */
1894         if (io->n.cleartext_utf8 && io->n.cleartext_utf16) {
1895                 ldb_asprintf_errstring(ldb,
1896                         "setup_io: "
1897                         "it's only allowed to set the cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
1898                 return LDB_ERR_UNWILLING_TO_PERFORM;
1899         }
1900
1901         /* refuse the change if someone tries to set/change the password by
1902          * the lanman hash alone and we've deactivated that mechanism. This
1903          * would end in an account without any password! */
1904         if ((!io->n.cleartext_utf8) && (!io->n.cleartext_utf16)
1905             && (!io->n.nt_hash) && (!io->n.lm_hash)) {
1906                 ldb_asprintf_errstring(ldb,
1907                         "setup_io: "
1908                         "The password change/set operations performed using the LAN Manager hash alone are deactivated!");
1909                 return LDB_ERR_UNWILLING_TO_PERFORM;
1910         }
1911
1912         /* refuse the change if someone wants to compare against a plaintext
1913            or hash at the same time for a "password modify" operation... */
1914         if ((io->og.cleartext_utf8 || io->og.cleartext_utf16)
1915             && (io->og.nt_hash || io->og.lm_hash)) {
1916                 ldb_asprintf_errstring(ldb,
1917                         "setup_io: "
1918                         "it's only allowed to provide the old password in form of cleartext attributes or as hashes");
1919                 return LDB_ERR_UNWILLING_TO_PERFORM;
1920         }
1921
1922         /* refuse the change if someone wants to compare against both
1923          * plaintexts at the same time for a "password modify" operation... */
1924         if (io->og.cleartext_utf8 && io->og.cleartext_utf16) {
1925                 ldb_asprintf_errstring(ldb,
1926                         "setup_io: "
1927                         "it's only allowed to provide the old cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
1928                 return LDB_ERR_UNWILLING_TO_PERFORM;
1929         }
1930
1931         /* Decides if we have a password modify or password reset operation */
1932         if (ac->req->operation == LDB_ADD) {
1933                 /* On "add" we have only "password reset" */
1934                 ac->pwd_reset = true;
1935         } else if (ac->req->operation == LDB_MODIFY) {
1936                 if (io->og.cleartext_utf8 || io->og.cleartext_utf16
1937                     || io->og.nt_hash || io->og.lm_hash) {
1938                         /* If we have an old password specified then for sure it
1939                          * is a user "password change" */
1940                         ac->pwd_reset = false;
1941                 } else {
1942                         /* Otherwise we have also here a "password reset" */
1943                         ac->pwd_reset = true;
1944                 }
1945         } else {
1946                 /* this shouldn't happen */
1947                 return ldb_operr(ldb);
1948         }
1949
1950         return LDB_SUCCESS;
1951 }
1952
1953 static struct ph_context *ph_init_context(struct ldb_module *module,
1954                                           struct ldb_request *req)
1955 {
1956         struct ldb_context *ldb;
1957         struct ph_context *ac;
1958
1959         ldb = ldb_module_get_ctx(module);
1960
1961         ac = talloc_zero(req, struct ph_context);
1962         if (ac == NULL) {
1963                 ldb_set_errstring(ldb, "Out of Memory");
1964                 return NULL;
1965         }
1966
1967         ac->module = module;
1968         ac->req = req;
1969
1970         return ac;
1971 }
1972
1973 static void ph_apply_controls(struct ph_context *ac)
1974 {
1975         struct ldb_control *ctrl;
1976
1977         ac->change_status = false;
1978         ctrl = ldb_request_get_control(ac->req,
1979                                        DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID);
1980         if (ctrl != NULL) {
1981                 ac->change_status = true;
1982
1983                 /* Mark the "change status" control as uncritical (done) */
1984                 ctrl->critical = false;
1985         }
1986
1987         ac->hash_values = false;
1988         ctrl = ldb_request_get_control(ac->req,
1989                                        DSDB_CONTROL_PASSWORD_HASH_VALUES_OID);
1990         if (ctrl != NULL) {
1991                 ac->hash_values = true;
1992
1993                 /* Mark the "hash values" control as uncritical (done) */
1994                 ctrl->critical = false;
1995         }
1996
1997         ctrl = ldb_request_get_control(ac->req,
1998                                        DSDB_CONTROL_PASSWORD_CHANGE_OID);
1999         if (ctrl != NULL) {
2000                 ac->change = (struct dsdb_control_password_change *) ctrl->data;
2001
2002                 /* Mark the "change" control as uncritical (done) */
2003                 ctrl->critical = false;
2004         }
2005 }
2006
2007 static int ph_op_callback(struct ldb_request *req, struct ldb_reply *ares)
2008 {
2009         struct ph_context *ac;
2010
2011         ac = talloc_get_type(req->context, struct ph_context);
2012
2013         if (!ares) {
2014                 return ldb_module_done(ac->req, NULL, NULL,
2015                                         LDB_ERR_OPERATIONS_ERROR);
2016         }
2017
2018         if (ares->type == LDB_REPLY_REFERRAL) {
2019                 return ldb_module_send_referral(ac->req, ares->referral);
2020         }
2021
2022         if ((ares->error != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
2023                 /* On success and trivial errors a status control is being
2024                  * added (used for example by the "samdb_set_password" call) */
2025                 ldb_reply_add_control(ares,
2026                                       DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
2027                                       false,
2028                                       ac->status);
2029         }
2030
2031         if (ares->error != LDB_SUCCESS) {
2032                 return ldb_module_done(ac->req, ares->controls,
2033                                         ares->response, ares->error);
2034         }
2035
2036         if (ares->type != LDB_REPLY_DONE) {
2037                 talloc_free(ares);
2038                 return ldb_module_done(ac->req, NULL, NULL,
2039                                         LDB_ERR_OPERATIONS_ERROR);
2040         }
2041
2042         return ldb_module_done(ac->req, ares->controls,
2043                                 ares->response, ares->error);
2044 }
2045
2046 static int password_hash_add_do_add(struct ph_context *ac);
2047 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares);
2048 static int password_hash_mod_search_self(struct ph_context *ac);
2049 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares);
2050 static int password_hash_mod_do_mod(struct ph_context *ac);
2051
2052 static int get_domain_data_callback(struct ldb_request *req,
2053                                     struct ldb_reply *ares)
2054 {
2055         struct ldb_context *ldb;
2056         struct ph_context *ac;
2057         struct loadparm_context *lp_ctx;
2058         int ret;
2059
2060         ac = talloc_get_type(req->context, struct ph_context);
2061         ldb = ldb_module_get_ctx(ac->module);
2062
2063         if (!ares) {
2064                 ret = LDB_ERR_OPERATIONS_ERROR;
2065                 goto done;
2066         }
2067         if (ares->error != LDB_SUCCESS) {
2068                 return ldb_module_done(ac->req, ares->controls,
2069                                         ares->response, ares->error);
2070         }
2071
2072         switch (ares->type) {
2073         case LDB_REPLY_ENTRY:
2074                 if (ac->status != NULL) {
2075                         talloc_free(ares);
2076
2077                         ldb_set_errstring(ldb, "Too many results");
2078                         ret = LDB_ERR_OPERATIONS_ERROR;
2079                         goto done;
2080                 }
2081
2082                 /* Setup the "status" structure (used as control later) */
2083                 ac->status = talloc_zero(ac->req,
2084                                          struct dsdb_control_password_change_status);
2085                 if (ac->status == NULL) {
2086                         talloc_free(ares);
2087
2088                         ldb_oom(ldb);
2089                         ret = LDB_ERR_OPERATIONS_ERROR;
2090                         goto done;
2091                 }
2092
2093                 /* Setup the "domain data" structure */
2094                 ac->status->domain_data.pwdProperties = samdb_result_uint(ares->message, "pwdProperties", -1);
2095                 ac->status->domain_data.pwdHistoryLength = samdb_result_uint(ares->message, "pwdHistoryLength", -1);
2096                 ac->status->domain_data.maxPwdAge = samdb_result_int64(ares->message, "maxPwdAge", -1);
2097                 ac->status->domain_data.minPwdAge = samdb_result_int64(ares->message, "minPwdAge", -1);
2098                 ac->status->domain_data.minPwdLength = samdb_result_uint(ares->message, "minPwdLength", -1);
2099                 ac->status->domain_data.store_cleartext =
2100                         ac->status->domain_data.pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT;
2101
2102                 talloc_free(ares);
2103
2104                 /* For a domain DN, this puts things in dotted notation */
2105                 /* For builtin domains, this will give details for the host,
2106                  * but that doesn't really matter, as it's just used for salt
2107                  * and kerberos principals, which don't exist here */
2108
2109                 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2110                                          struct loadparm_context);
2111
2112                 ac->status->domain_data.dns_domain = lpcfg_dnsdomain(lp_ctx);
2113                 ac->status->domain_data.realm = lpcfg_realm(lp_ctx);
2114                 ac->status->domain_data.netbios_domain = lpcfg_sam_name(lp_ctx);
2115
2116                 ac->status->reject_reason = SAM_PWD_CHANGE_NO_ERROR;
2117
2118                 ret = LDB_SUCCESS;
2119                 break;
2120
2121         case LDB_REPLY_REFERRAL:
2122                 /* ignore */
2123                 talloc_free(ares);
2124                 ret = LDB_SUCCESS;
2125                 break;
2126
2127         case LDB_REPLY_DONE:
2128                 talloc_free(ares);
2129                 /* call the next step */
2130                 switch (ac->req->operation) {
2131                 case LDB_ADD:
2132                         ret = password_hash_add_do_add(ac);
2133                         break;
2134
2135                 case LDB_MODIFY:
2136                         ret = password_hash_mod_do_mod(ac);
2137                         break;
2138
2139                 default:
2140                         ret = LDB_ERR_OPERATIONS_ERROR;
2141                         break;
2142                 }
2143                 break;
2144         }
2145
2146 done:
2147         if (ret != LDB_SUCCESS) {
2148                 struct ldb_reply *new_ares;
2149
2150                 new_ares = talloc_zero(ac->req, struct ldb_reply);
2151                 if (new_ares == NULL) {
2152                         ldb_oom(ldb);
2153                         return ldb_module_done(ac->req, NULL, NULL,
2154                                                LDB_ERR_OPERATIONS_ERROR);
2155                 }
2156
2157                 new_ares->error = ret;
2158                 if ((ret != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
2159                         /* On success and trivial errors a status control is being
2160                          * added (used for example by the "samdb_set_password" call) */
2161                         ldb_reply_add_control(new_ares,
2162                                               DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
2163                                               false,
2164                                               ac->status);
2165                 }
2166
2167                 return ldb_module_done(ac->req, new_ares->controls,
2168                                        new_ares->response, new_ares->error);
2169         }
2170
2171         return LDB_SUCCESS;
2172 }
2173
2174 static int build_domain_data_request(struct ph_context *ac)
2175 {
2176         /* attrs[] is returned from this function in
2177            ac->dom_req->op.search.attrs, so it must be static, as
2178            otherwise the compiler can put it on the stack */
2179         struct ldb_context *ldb;
2180         static const char * const attrs[] = { "pwdProperties",
2181                                               "pwdHistoryLength",
2182                                               "maxPwdAge",
2183                                               "minPwdAge",
2184                                               "minPwdLength",
2185                                               NULL };
2186         int ret;
2187
2188         ldb = ldb_module_get_ctx(ac->module);
2189
2190         ret = ldb_build_search_req(&ac->dom_req, ldb, ac,
2191                                    ldb_get_default_basedn(ldb),
2192                                    LDB_SCOPE_BASE,
2193                                    NULL, attrs,
2194                                    NULL,
2195                                    ac, get_domain_data_callback,
2196                                    ac->req);
2197         LDB_REQ_SET_LOCATION(ac->dom_req);
2198         return ret;
2199 }
2200
2201 static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
2202 {
2203         struct ldb_context *ldb;
2204         struct ph_context *ac;
2205         struct ldb_message_element *userPasswordAttr, *clearTextPasswordAttr,
2206                 *ntAttr, *lmAttr;
2207         int ret;
2208         struct ldb_control *bypass = NULL;
2209
2210         ldb = ldb_module_get_ctx(module);
2211
2212         ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_add\n");
2213
2214         if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */
2215                 return ldb_next_request(module, req);
2216         }
2217
2218         /* If the caller is manipulating the local passwords directly, let them pass */
2219         if (ldb_dn_compare_base(ldb_dn_new(req, ldb, LOCAL_BASE),
2220                                 req->op.add.message->dn) == 0) {
2221                 return ldb_next_request(module, req);
2222         }
2223
2224         bypass = ldb_request_get_control(req,
2225                                          DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID);
2226         if (bypass != NULL) {
2227                 /* Mark the "bypass" control as uncritical (done) */
2228                 bypass->critical = false;
2229                 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_add (bypassing)\n");
2230                 return ldb_next_request(module, req);
2231         }
2232
2233         /* nobody must touch password histories and 'supplementalCredentials' */
2234         if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) {
2235                 return LDB_ERR_UNWILLING_TO_PERFORM;
2236         }
2237         if (ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) {
2238                 return LDB_ERR_UNWILLING_TO_PERFORM;
2239         }
2240         if (ldb_msg_find_element(req->op.add.message, "supplementalCredentials")) {
2241                 return LDB_ERR_UNWILLING_TO_PERFORM;
2242         }
2243
2244         /* If no part of this touches the 'userPassword' OR 'clearTextPassword'
2245          * OR 'unicodePwd' OR 'dBCSPwd' we don't need to make any changes. */
2246
2247         userPasswordAttr = ldb_msg_find_element(req->op.add.message, "userPassword");
2248         clearTextPasswordAttr = ldb_msg_find_element(req->op.add.message, "clearTextPassword");
2249         ntAttr = ldb_msg_find_element(req->op.add.message, "unicodePwd");
2250         lmAttr = ldb_msg_find_element(req->op.add.message, "dBCSPwd");
2251
2252         if ((!userPasswordAttr) && (!clearTextPasswordAttr) && (!ntAttr) && (!lmAttr)) {
2253                 return ldb_next_request(module, req);
2254         }
2255
2256         /* Make sure we are performing the password set action on a (for us)
2257          * valid object. Those are instances of either "user" and/or
2258          * "inetOrgPerson". Otherwise continue with the submodules. */
2259         if ((!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "user"))
2260                 && (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "inetOrgPerson"))) {
2261
2262                 if (ldb_msg_find_element(req->op.add.message, "clearTextPassword") != NULL) {
2263                         ldb_set_errstring(ldb,
2264                                           "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
2265                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
2266                 }
2267
2268                 return ldb_next_request(module, req);
2269         }
2270
2271         ac = ph_init_context(module, req);
2272         if (ac == NULL) {
2273                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
2274                 return ldb_operr(ldb);
2275         }
2276         ph_apply_controls(ac);
2277
2278         /* get user domain data */
2279         ret = build_domain_data_request(ac);
2280         if (ret != LDB_SUCCESS) {
2281                 return ret;
2282         }
2283
2284         return ldb_next_request(module, ac->dom_req);
2285 }
2286
2287 static int password_hash_add_do_add(struct ph_context *ac)
2288 {
2289         struct ldb_context *ldb;
2290         struct ldb_request *down_req;
2291         struct ldb_message *msg;
2292         struct setup_password_fields_io io;
2293         int ret;
2294
2295         /* Prepare the internal data structure containing the passwords */
2296         ret = setup_io(ac, ac->req->op.add.message, ac->req->op.add.message, &io);
2297         if (ret != LDB_SUCCESS) {
2298                 return ret;
2299         }
2300
2301         ldb = ldb_module_get_ctx(ac->module);
2302
2303         msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
2304         if (msg == NULL) {
2305                 return ldb_operr(ldb);
2306         }
2307
2308         /* remove attributes that we just read into 'io' */
2309         ldb_msg_remove_attr(msg, "userPassword");
2310         ldb_msg_remove_attr(msg, "clearTextPassword");
2311         ldb_msg_remove_attr(msg, "unicodePwd");
2312         ldb_msg_remove_attr(msg, "dBCSPwd");
2313         ldb_msg_remove_attr(msg, "pwdLastSet");
2314
2315         ret = setup_password_fields(&io);
2316         if (ret != LDB_SUCCESS) {
2317                 return ret;
2318         }
2319
2320         ret = check_password_restrictions(&io);
2321         if (ret != LDB_SUCCESS) {
2322                 return ret;
2323         }
2324
2325         if (io.g.nt_hash) {
2326                 ret = samdb_msg_add_hash(ldb, ac, msg,
2327                                          "unicodePwd", io.g.nt_hash);
2328                 if (ret != LDB_SUCCESS) {
2329                         return ret;
2330                 }
2331         }
2332         if (io.g.lm_hash) {
2333                 ret = samdb_msg_add_hash(ldb, ac, msg,
2334                                          "dBCSPwd", io.g.lm_hash);
2335                 if (ret != LDB_SUCCESS) {
2336                         return ret;
2337                 }
2338         }
2339         if (io.g.nt_history_len > 0) {
2340                 ret = samdb_msg_add_hashes(ldb, ac, msg,
2341                                            "ntPwdHistory",
2342                                            io.g.nt_history,
2343                                            io.g.nt_history_len);
2344                 if (ret != LDB_SUCCESS) {
2345                         return ret;
2346                 }
2347         }
2348         if (io.g.lm_history_len > 0) {
2349                 ret = samdb_msg_add_hashes(ldb, ac, msg,
2350                                            "lmPwdHistory",
2351                                            io.g.lm_history,
2352                                            io.g.lm_history_len);
2353                 if (ret != LDB_SUCCESS) {
2354                         return ret;
2355                 }
2356         }
2357         if (io.g.supplemental.length > 0) {
2358                 ret = ldb_msg_add_value(msg, "supplementalCredentials",
2359                                         &io.g.supplemental, NULL);
2360                 if (ret != LDB_SUCCESS) {
2361                         return ret;
2362                 }
2363         }
2364         ret = samdb_msg_add_uint64(ldb, ac, msg,
2365                                    "pwdLastSet",
2366                                    io.g.last_set);
2367         if (ret != LDB_SUCCESS) {
2368                 return ret;
2369         }
2370
2371         ret = ldb_build_add_req(&down_req, ldb, ac,
2372                                 msg,
2373                                 ac->req->controls,
2374                                 ac, ph_op_callback,
2375                                 ac->req);
2376         LDB_REQ_SET_LOCATION(down_req);
2377         if (ret != LDB_SUCCESS) {
2378                 return ret;
2379         }
2380
2381         return ldb_next_request(ac->module, down_req);
2382 }
2383
2384 static int password_hash_modify(struct ldb_module *module, struct ldb_request *req)
2385 {
2386         struct ldb_context *ldb;
2387         struct ph_context *ac;
2388         const char *passwordAttrs[] = { "userPassword", "clearTextPassword",
2389                 "unicodePwd", "dBCSPwd", NULL }, **l;
2390         unsigned int attr_cnt, del_attr_cnt, add_attr_cnt, rep_attr_cnt;
2391         struct ldb_message_element *passwordAttr;
2392         struct ldb_message *msg;
2393         struct ldb_request *down_req;
2394         int ret;
2395         struct ldb_control *bypass = NULL;
2396
2397         ldb = ldb_module_get_ctx(module);
2398
2399         ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_modify\n");
2400
2401         if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */
2402                 return ldb_next_request(module, req);
2403         }
2404         
2405         /* If the caller is manipulating the local passwords directly, let them pass */
2406         if (ldb_dn_compare_base(ldb_dn_new(req, ldb, LOCAL_BASE),
2407                                 req->op.mod.message->dn) == 0) {
2408                 return ldb_next_request(module, req);
2409         }
2410
2411         bypass = ldb_request_get_control(req,
2412                                          DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID);
2413         if (bypass != NULL) {
2414                 /* Mark the "bypass" control as uncritical (done) */
2415                 bypass->critical = false;
2416                 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_modify (bypassing)\n");
2417                 return ldb_next_request(module, req);
2418         }
2419
2420         /* nobody must touch password histories and 'supplementalCredentials' */
2421         if (ldb_msg_find_element(req->op.mod.message, "ntPwdHistory")) {
2422                 return LDB_ERR_UNWILLING_TO_PERFORM;
2423         }
2424         if (ldb_msg_find_element(req->op.mod.message, "lmPwdHistory")) {
2425                 return LDB_ERR_UNWILLING_TO_PERFORM;
2426         }
2427         if (ldb_msg_find_element(req->op.mod.message, "supplementalCredentials")) {
2428                 return LDB_ERR_UNWILLING_TO_PERFORM;
2429         }
2430
2431         /* If no part of this touches the 'userPassword' OR 'clearTextPassword'
2432          * OR 'unicodePwd' OR 'dBCSPwd' we don't need to make any changes.
2433          * For password changes/set there should be a 'delete' or a 'modify'
2434          * on these attributes. */
2435         attr_cnt = 0;
2436         for (l = passwordAttrs; *l != NULL; l++) {
2437                 if (ldb_msg_find_element(req->op.mod.message, *l) != NULL) {
2438                         ++attr_cnt;
2439                 }
2440         }
2441         if (attr_cnt == 0) {
2442                 return ldb_next_request(module, req);
2443         }
2444
2445         ac = ph_init_context(module, req);
2446         if (!ac) {
2447                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
2448                 return ldb_operr(ldb);
2449         }
2450         ph_apply_controls(ac);
2451
2452         /* use a new message structure so that we can modify it */
2453         msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
2454         if (msg == NULL) {
2455                 return ldb_oom(ldb);
2456         }
2457
2458         /* - check for single-valued password attributes
2459          *   (if not return "CONSTRAINT_VIOLATION")
2460          * - check that for a password change operation one add and one delete
2461          *   operation exists
2462          *   (if not return "CONSTRAINT_VIOLATION" or "UNWILLING_TO_PERFORM")
2463          * - check that a password change and a password set operation cannot
2464          *   be mixed
2465          *   (if not return "UNWILLING_TO_PERFORM")
2466          * - remove all password attributes modifications from the first change
2467          *   operation (anything without the passwords) - we will make the real
2468          *   modification later */
2469         del_attr_cnt = 0;
2470         add_attr_cnt = 0;
2471         rep_attr_cnt = 0;
2472         for (l = passwordAttrs; *l != NULL; l++) {
2473                 while ((passwordAttr = ldb_msg_find_element(msg, *l)) != NULL) {
2474                         if (LDB_FLAG_MOD_TYPE(passwordAttr->flags) == LDB_FLAG_MOD_DELETE) {
2475                                 ++del_attr_cnt;
2476                         }
2477                         if (LDB_FLAG_MOD_TYPE(passwordAttr->flags) == LDB_FLAG_MOD_ADD) {
2478                                 ++add_attr_cnt;
2479                         }
2480                         if (LDB_FLAG_MOD_TYPE(passwordAttr->flags) == LDB_FLAG_MOD_REPLACE) {
2481                                 ++rep_attr_cnt;
2482                         }
2483                         if ((passwordAttr->num_values != 1) &&
2484                             (LDB_FLAG_MOD_TYPE(passwordAttr->flags) == LDB_FLAG_MOD_ADD)) {
2485                                 talloc_free(ac);
2486                                 ldb_asprintf_errstring(ldb,
2487                                                        "'%s' attribute must have exactly one value on add operations!",
2488                                                        *l);
2489                                 return LDB_ERR_CONSTRAINT_VIOLATION;
2490                         }
2491                         if ((passwordAttr->num_values > 1) &&
2492                             (LDB_FLAG_MOD_TYPE(passwordAttr->flags) == LDB_FLAG_MOD_DELETE)) {
2493                                 talloc_free(ac);
2494                                 ldb_asprintf_errstring(ldb,
2495                                                        "'%s' attribute must have zero or one value(s) on delete operations!",
2496                                                        *l);
2497                                 return LDB_ERR_CONSTRAINT_VIOLATION;
2498                         }
2499                         ldb_msg_remove_element(msg, passwordAttr);
2500                 }
2501         }
2502         if ((del_attr_cnt > 0) && (add_attr_cnt == 0)) {
2503                 talloc_free(ac);
2504                 ldb_set_errstring(ldb,
2505                                   "Only the delete action for a password change specified!");
2506                 return LDB_ERR_CONSTRAINT_VIOLATION;
2507         }
2508         if ((del_attr_cnt == 0) && (add_attr_cnt > 0)) {
2509                 talloc_free(ac);
2510                 ldb_set_errstring(ldb,
2511                                   "Only the add action for a password change specified!");
2512                 return LDB_ERR_UNWILLING_TO_PERFORM;
2513         }
2514         if ((del_attr_cnt > 1) || (add_attr_cnt > 1)) {
2515                 talloc_free(ac);
2516                 ldb_set_errstring(ldb,
2517                                   "Only one delete and one add action for a password change allowed!");
2518                 return LDB_ERR_UNWILLING_TO_PERFORM;
2519         }
2520         if ((rep_attr_cnt > 0) && ((del_attr_cnt > 0) || (add_attr_cnt > 0))) {
2521                 talloc_free(ac);
2522                 ldb_set_errstring(ldb,
2523                                   "Either a password change or a password set operation is allowed!");
2524                 return LDB_ERR_UNWILLING_TO_PERFORM;
2525         }
2526
2527         /* if there was nothing else to be modified skip to next step */
2528         if (msg->num_elements == 0) {
2529                 return password_hash_mod_search_self(ac);
2530         }
2531
2532         ret = ldb_build_mod_req(&down_req, ldb, ac,
2533                                 msg,
2534                                 req->controls,
2535                                 ac, ph_modify_callback,
2536                                 req);
2537         LDB_REQ_SET_LOCATION(down_req);
2538         if (ret != LDB_SUCCESS) {
2539                 return ret;
2540         }
2541
2542         return ldb_next_request(module, down_req);
2543 }
2544
2545 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
2546 {
2547         struct ph_context *ac;
2548
2549         ac = talloc_get_type(req->context, struct ph_context);
2550
2551         if (!ares) {
2552                 return ldb_module_done(ac->req, NULL, NULL,
2553                                         LDB_ERR_OPERATIONS_ERROR);
2554         }
2555
2556         if (ares->type == LDB_REPLY_REFERRAL) {
2557                 return ldb_module_send_referral(ac->req, ares->referral);
2558         }
2559
2560         if (ares->error != LDB_SUCCESS) {
2561                 return ldb_module_done(ac->req, ares->controls,
2562                                         ares->response, ares->error);
2563         }
2564
2565         if (ares->type != LDB_REPLY_DONE) {
2566                 talloc_free(ares);
2567                 return ldb_module_done(ac->req, NULL, NULL,
2568                                         LDB_ERR_OPERATIONS_ERROR);
2569         }
2570
2571         talloc_free(ares);
2572
2573         return password_hash_mod_search_self(ac);
2574 }
2575
2576 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares)
2577 {
2578         struct ldb_context *ldb;
2579         struct ph_context *ac;
2580         int ret;
2581
2582         ac = talloc_get_type(req->context, struct ph_context);
2583         ldb = ldb_module_get_ctx(ac->module);
2584
2585         if (!ares) {
2586                 ret = LDB_ERR_OPERATIONS_ERROR;
2587                 goto done;
2588         }
2589         if (ares->error != LDB_SUCCESS) {
2590                 return ldb_module_done(ac->req, ares->controls,
2591                                         ares->response, ares->error);
2592         }
2593
2594         /* we are interested only in the single reply (base search) */
2595         switch (ares->type) {
2596         case LDB_REPLY_ENTRY:
2597                 /* Make sure we are performing the password change action on a
2598                  * (for us) valid object. Those are instances of either "user"
2599                  * and/or "inetOrgPerson". Otherwise continue with the
2600                  * submodules. */
2601                 if ((!ldb_msg_check_string_attribute(ares->message, "objectClass", "user"))
2602                         && (!ldb_msg_check_string_attribute(ares->message, "objectClass", "inetOrgPerson"))) {
2603                         talloc_free(ares);
2604
2605                         if (ldb_msg_find_element(ac->req->op.mod.message, "clearTextPassword") != NULL) {
2606                                 ldb_set_errstring(ldb,
2607                                                   "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
2608                                 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
2609                                 goto done;
2610                         }
2611
2612                         ret = ldb_next_request(ac->module, ac->req);
2613                         goto done;
2614                 }
2615
2616                 if (ac->search_res != NULL) {
2617                         talloc_free(ares);
2618
2619                         ldb_set_errstring(ldb, "Too many results");
2620                         ret = LDB_ERR_OPERATIONS_ERROR;
2621                         goto done;
2622                 }
2623
2624                 ac->search_res = talloc_steal(ac, ares);
2625                 ret = LDB_SUCCESS;
2626                 break;
2627
2628         case LDB_REPLY_REFERRAL:
2629                 /* ignore anything else for now */
2630                 talloc_free(ares);
2631                 ret = LDB_SUCCESS;
2632                 break;
2633
2634         case LDB_REPLY_DONE:
2635                 talloc_free(ares);
2636
2637                 /* get user domain data */
2638                 ret = build_domain_data_request(ac);
2639                 if (ret != LDB_SUCCESS) {
2640                         return ldb_module_done(ac->req, NULL, NULL, ret);
2641                 }
2642
2643                 ret = ldb_next_request(ac->module, ac->dom_req);
2644                 break;
2645         }
2646
2647 done:
2648         if (ret != LDB_SUCCESS) {
2649                 return ldb_module_done(ac->req, NULL, NULL, ret);
2650         }
2651
2652         return LDB_SUCCESS;
2653 }
2654
2655 static int password_hash_mod_search_self(struct ph_context *ac)
2656 {
2657         struct ldb_context *ldb;
2658         static const char * const attrs[] = { "objectClass",
2659                                               "userAccountControl",
2660                                               "pwdLastSet",
2661                                               "sAMAccountName",
2662                                               "objectSid",
2663                                               "userPrincipalName",
2664                                               "supplementalCredentials",
2665                                               "lmPwdHistory",
2666                                               "ntPwdHistory",
2667                                               "dBCSPwd",
2668                                               "unicodePwd",
2669                                               NULL };
2670         struct ldb_request *search_req;
2671         int ret;
2672
2673         ldb = ldb_module_get_ctx(ac->module);
2674
2675         ret = ldb_build_search_req(&search_req, ldb, ac,
2676                                    ac->req->op.mod.message->dn,
2677                                    LDB_SCOPE_BASE,
2678                                    "(objectclass=*)",
2679                                    attrs,
2680                                    NULL,
2681                                    ac, ph_mod_search_callback,
2682                                    ac->req);
2683         LDB_REQ_SET_LOCATION(search_req);
2684         if (ret != LDB_SUCCESS) {
2685                 return ret;
2686         }
2687
2688         return ldb_next_request(ac->module, search_req);
2689 }
2690
2691 static int password_hash_mod_do_mod(struct ph_context *ac)
2692 {
2693         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2694         struct loadparm_context *lp_ctx =
2695                                 talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2696                                                 struct loadparm_context);
2697         struct ldb_request *mod_req;
2698         struct ldb_message *msg;
2699         const struct ldb_message *orig_msg, *searched_msg;
2700         struct setup_password_fields_io io;
2701         int ret;
2702         NTSTATUS status;
2703
2704         /* use a new message structure so that we can modify it */
2705         msg = ldb_msg_new(ac);
2706         if (msg == NULL) {
2707                 return ldb_operr(ldb);
2708         }
2709
2710         /* modify dn */
2711         msg->dn = ac->req->op.mod.message->dn;
2712
2713         orig_msg = ac->req->op.mod.message;
2714         searched_msg = ac->search_res->message;
2715
2716         /* Prepare the internal data structure containing the passwords */
2717         ret = setup_io(ac, orig_msg, searched_msg, &io);
2718         if (ret != LDB_SUCCESS) {
2719                 return ret;
2720         }
2721         
2722         /* Get the old password from the database */
2723         status = samdb_result_passwords(io.ac,
2724                                         lp_ctx,
2725                                         discard_const_p(struct ldb_message, searched_msg),
2726                                         &io.o.lm_hash, &io.o.nt_hash);
2727         if (!NT_STATUS_IS_OK(status)) {
2728                 return ldb_operr(ldb);
2729         }
2730
2731         io.o.nt_history_len             = samdb_result_hashes(io.ac, searched_msg, "ntPwdHistory", &io.o.nt_history);
2732         io.o.lm_history_len             = samdb_result_hashes(io.ac, searched_msg, "lmPwdHistory", &io.o.lm_history);
2733         io.o.supplemental               = ldb_msg_find_ldb_val(searched_msg, "supplementalCredentials");
2734
2735         ret = setup_password_fields(&io);
2736         if (ret != LDB_SUCCESS) {
2737                 return ret;
2738         }
2739
2740         ret = check_password_restrictions(&io);
2741         if (ret != LDB_SUCCESS) {
2742                 return ret;
2743         }
2744
2745         /* make sure we replace all the old attributes */
2746         ret = ldb_msg_add_empty(msg, "unicodePwd", LDB_FLAG_MOD_REPLACE, NULL);
2747         ret = ldb_msg_add_empty(msg, "dBCSPwd", LDB_FLAG_MOD_REPLACE, NULL);
2748         ret = ldb_msg_add_empty(msg, "ntPwdHistory", LDB_FLAG_MOD_REPLACE, NULL);
2749         ret = ldb_msg_add_empty(msg, "lmPwdHistory", LDB_FLAG_MOD_REPLACE, NULL);
2750         ret = ldb_msg_add_empty(msg, "supplementalCredentials", LDB_FLAG_MOD_REPLACE, NULL);
2751         ret = ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE, NULL);
2752
2753         if (io.g.nt_hash) {
2754                 ret = samdb_msg_add_hash(ldb, ac, msg,
2755                                          "unicodePwd", io.g.nt_hash);
2756                 if (ret != LDB_SUCCESS) {
2757                         return ret;
2758                 }
2759         }
2760         if (io.g.lm_hash) {
2761                 ret = samdb_msg_add_hash(ldb, ac, msg,
2762                                          "dBCSPwd", io.g.lm_hash);
2763                 if (ret != LDB_SUCCESS) {
2764                         return ret;
2765                 }
2766         }
2767         if (io.g.nt_history_len > 0) {
2768                 ret = samdb_msg_add_hashes(ldb, ac, msg,
2769                                            "ntPwdHistory",
2770                                            io.g.nt_history,
2771                                            io.g.nt_history_len);
2772                 if (ret != LDB_SUCCESS) {
2773                         return ret;
2774                 }
2775         }
2776         if (io.g.lm_history_len > 0) {
2777                 ret = samdb_msg_add_hashes(ldb, ac, msg,
2778                                            "lmPwdHistory",
2779                                            io.g.lm_history,
2780                                            io.g.lm_history_len);
2781                 if (ret != LDB_SUCCESS) {
2782                         return ret;
2783                 }
2784         }
2785         if (io.g.supplemental.length > 0) {
2786                 ret = ldb_msg_add_value(msg, "supplementalCredentials",
2787                                         &io.g.supplemental, NULL);
2788                 if (ret != LDB_SUCCESS) {
2789                         return ret;
2790                 }
2791         }
2792         ret = samdb_msg_add_uint64(ldb, ac, msg,
2793                                    "pwdLastSet",
2794                                    io.g.last_set);
2795         if (ret != LDB_SUCCESS) {
2796                 return ret;
2797         }
2798
2799         ret = ldb_build_mod_req(&mod_req, ldb, ac,
2800                                 msg,
2801                                 ac->req->controls,
2802                                 ac, ph_op_callback,
2803                                 ac->req);
2804         LDB_REQ_SET_LOCATION(mod_req);
2805         if (ret != LDB_SUCCESS) {
2806                 return ret;
2807         }
2808
2809         return ldb_next_request(ac->module, mod_req);
2810 }
2811
2812 _PUBLIC_ const struct ldb_module_ops ldb_password_hash_module_ops = {
2813         .name          = "password_hash",
2814         .add           = password_hash_add,
2815         .modify        = password_hash_modify
2816 };