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