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