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