38617b08c59996f9e0d1fc045206bd38f1f323df
[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 if (quoted_utf16) {
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                 io->n.nt_hash = talloc(io->ac, struct samr_Password);
1785                 memcpy(io->n.nt_hash->hash, quoted_utf16->data,
1786                        MIN(quoted_utf16->length, sizeof(io->n.nt_hash->hash)));
1787         }
1788
1789         /* Checks and converts the previous "unicodePwd" attribute */
1790         if (old_quoted_utf16 &&
1791             old_quoted_utf16->length >= 4 &&
1792             old_quoted_utf16->data[0] == '"' &&
1793             old_quoted_utf16->data[1] == 0 &&
1794             old_quoted_utf16->data[old_quoted_utf16->length-2] == '"' &&
1795             old_quoted_utf16->data[old_quoted_utf16->length-1] == 0) {
1796                 struct ldb_val *old_quoted_utf16_2;
1797
1798                 if (io->og.cleartext_utf16) {
1799                         /* refuse the change if someone wants to change with
1800                            both UTF16 possibilities at the same time... */
1801                         ldb_asprintf_errstring(ldb,
1802                                 "setup_io: "
1803                                 "it's only allowed to set the cleartext password as 'unicodePwd' or as 'clearTextPassword'");
1804                         return LDB_ERR_UNWILLING_TO_PERFORM;
1805                 }
1806
1807                 /*
1808                  * adapt the quoted UTF16 string to be a real
1809                  * cleartext one
1810                  */
1811                 old_quoted_utf16_2 = talloc(io->ac, struct ldb_val);
1812                 if (old_quoted_utf16_2 == NULL) {
1813                         ldb_oom(ldb);
1814                         return LDB_ERR_OPERATIONS_ERROR;
1815                 }
1816
1817                 old_quoted_utf16_2->data = old_quoted_utf16->data + 2;
1818                 old_quoted_utf16_2->length = old_quoted_utf16->length-4;
1819
1820                 io->og.cleartext_utf16 = old_quoted_utf16_2;
1821                 io->og.nt_hash = NULL;
1822         } else if (old_quoted_utf16) {
1823                 /* We have only the hash available -> so no plaintext here */
1824                 if (!ac->hash_values) {
1825                         /* refuse the change if someone wants to change
1826                            the hash without control specified... */
1827                         ldb_asprintf_errstring(ldb,
1828                                 "setup_io: "
1829                                 "it's not allowed to set the NT hash password directly'");
1830                         return LDB_ERR_UNWILLING_TO_PERFORM;
1831                 }
1832
1833                 io->og.nt_hash = talloc(io->ac, struct samr_Password);
1834                 memcpy(io->og.nt_hash->hash, old_quoted_utf16->data,
1835                        MIN(old_quoted_utf16->length, sizeof(io->og.nt_hash->hash)));
1836         }
1837
1838         /* Handles the "dBCSPwd" attribute (LM hash) */
1839         io->n.lm_hash = NULL; io->og.lm_hash = NULL;
1840         ret = samdb_msg_find_old_and_new_ldb_val(orig_msg, "dBCSPwd",
1841                 &lm_hash, &old_lm_hash);
1842         if (ret != LDB_SUCCESS) {
1843                 ldb_asprintf_errstring(ldb,
1844                         "setup_io: "
1845                         "it's only allowed to set the old password once!");
1846                 return ret;
1847         }
1848
1849         if (((lm_hash != NULL) || (old_lm_hash != NULL)) && (!ac->hash_values)) {
1850                 /* refuse the change if someone wants to change the hash
1851                    without control specified... */
1852                 ldb_asprintf_errstring(ldb,
1853                         "setup_io: "
1854                         "it's not allowed to set the LM hash password directly'");
1855                 return LDB_ERR_UNWILLING_TO_PERFORM;
1856         }
1857         if (lm_hash != NULL) {
1858                 io->n.lm_hash = talloc(io->ac, struct samr_Password);
1859                 memcpy(io->n.lm_hash->hash, lm_hash->data, MIN(lm_hash->length,
1860                        sizeof(io->n.lm_hash->hash)));
1861         }
1862
1863         if (old_lm_hash != NULL) {
1864                 io->og.lm_hash = talloc(io->ac, struct samr_Password);
1865                 memcpy(io->og.lm_hash->hash, old_lm_hash->data, MIN(old_lm_hash->length,
1866                        sizeof(io->og.lm_hash->hash)));
1867         }
1868
1869         /* refuse the change if someone wants to change the clear-
1870            text and supply his own hashes at the same time... */
1871         if ((io->n.cleartext_utf8 || io->n.cleartext_utf16)
1872                         && (io->n.nt_hash || io->n.lm_hash)) {
1873                 ldb_asprintf_errstring(ldb,
1874                         "setup_io: "
1875                         "it's only allowed to set the password in form of cleartext attributes or as hashes");
1876                 return LDB_ERR_UNWILLING_TO_PERFORM;
1877         }
1878
1879         /* refuse the change if someone wants to change the password
1880            using both plaintext methods (UTF8 and UTF16) at the same time... */
1881         if (io->n.cleartext_utf8 && io->n.cleartext_utf16) {
1882                 ldb_asprintf_errstring(ldb,
1883                         "setup_io: "
1884                         "it's only allowed to set the cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
1885                 return LDB_ERR_UNWILLING_TO_PERFORM;
1886         }
1887
1888         /* refuse the change if someone wants to compare against a plaintext
1889            or hash at the same time for a "password modify" operation... */
1890         if ((io->og.cleartext_utf8 || io->og.cleartext_utf16)
1891             && (io->og.nt_hash || io->og.lm_hash)) {
1892                 ldb_asprintf_errstring(ldb,
1893                         "setup_io: "
1894                         "it's only allowed to provide the old password in form of cleartext attributes or as hashes");
1895                 return LDB_ERR_UNWILLING_TO_PERFORM;
1896         }
1897
1898         /* refuse the change if someone wants to compare against both
1899          * plaintexts at the same time for a "password modify" operation... */
1900         if (io->og.cleartext_utf8 && io->og.cleartext_utf16) {
1901                 ldb_asprintf_errstring(ldb,
1902                         "setup_io: "
1903                         "it's only allowed to provide the old cleartext password as 'unicodePwd' or as 'userPassword' or as 'clearTextPassword'");
1904                 return LDB_ERR_UNWILLING_TO_PERFORM;
1905         }
1906
1907         /* refuse the change if someone wants to compare against both
1908          * hashes at the same time for a "password modify" operation... */
1909         if (io->og.nt_hash && io->og.lm_hash) {
1910                 ldb_asprintf_errstring(ldb,
1911                         "setup_io: "
1912                         "it's only allowed to provide the old password in hash format as 'unicodePwd' or as 'dBCSPwd'");
1913                 return LDB_ERR_UNWILLING_TO_PERFORM;
1914         }
1915
1916         /* Decides if we have a password modify or password reset operation */
1917         if (ac->req->operation == LDB_ADD) {
1918                 /* On "add" we have only "password reset" */
1919                 ac->pwd_reset = true;
1920         } else if (ac->req->operation == LDB_MODIFY) {
1921                 if (io->og.cleartext_utf8 || io->og.cleartext_utf16
1922                     || io->og.nt_hash || io->og.lm_hash
1923                     || ac->change_old_pw_checked) {
1924                         /* If we have an old password or the "change old
1925                          * password checked" control specified then for sure it
1926                          * is a user "password change" */
1927                         ac->pwd_reset = false;
1928                 } else {
1929                         /* Otherwise we have also here a "password reset" */
1930                         ac->pwd_reset = true;
1931                 }
1932         } else {
1933                 /* this shouldn't happen */
1934                 return LDB_ERR_OPERATIONS_ERROR;
1935         }
1936
1937         return LDB_SUCCESS;
1938 }
1939
1940 static struct ph_context *ph_init_context(struct ldb_module *module,
1941                                           struct ldb_request *req)
1942 {
1943         struct ldb_context *ldb;
1944         struct ph_context *ac;
1945
1946         ldb = ldb_module_get_ctx(module);
1947
1948         ac = talloc_zero(req, struct ph_context);
1949         if (ac == NULL) {
1950                 ldb_set_errstring(ldb, "Out of Memory");
1951                 return NULL;
1952         }
1953
1954         ac->module = module;
1955         ac->req = req;
1956
1957         return ac;
1958 }
1959
1960 static void ph_apply_controls(struct ph_context *ac)
1961 {
1962         struct ldb_control *ctrl;
1963
1964         ac->change_status = false;
1965         ctrl = ldb_request_get_control(ac->req,
1966                                        DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID);
1967         if (ctrl != NULL) {
1968                 ac->change_status = true;
1969
1970                 /* Mark the "change status" control as uncritical (done) */
1971                 ctrl->critical = false;
1972         }
1973
1974         ac->hash_values = false;
1975         ctrl = ldb_request_get_control(ac->req,
1976                                        DSDB_CONTROL_PASSWORD_HASH_VALUES_OID);
1977         if (ctrl != NULL) {
1978                 ac->hash_values = true;
1979
1980                 /* Mark the "hash values" control as uncritical (done) */
1981                 ctrl->critical = false;
1982         }
1983
1984         ac->change_old_pw_checked = false;
1985         ctrl = ldb_request_get_control(ac->req,
1986                                        DSDB_CONTROL_PASSWORD_CHANGE_OLD_PW_CHECKED_OID);
1987         if (ctrl != NULL) {
1988                 ac->change_old_pw_checked = true;
1989
1990                 /* Mark the "change old password checked" control as uncritical
1991                  * (done) */
1992                 ctrl->critical = false;
1993         }
1994 }
1995
1996 static int ph_op_callback(struct ldb_request *req, struct ldb_reply *ares)
1997 {
1998         struct ph_context *ac;
1999
2000         ac = talloc_get_type(req->context, struct ph_context);
2001
2002         if (!ares) {
2003                 return ldb_module_done(ac->req, NULL, NULL,
2004                                         LDB_ERR_OPERATIONS_ERROR);
2005         }
2006
2007         if (ares->type == LDB_REPLY_REFERRAL) {
2008                 return ldb_module_send_referral(ac->req, ares->referral);
2009         }
2010
2011         if ((ares->error != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
2012                 /* On success and trivial errors a status control is being
2013                  * added (used for example by the "samdb_set_password" call) */
2014                 ldb_reply_add_control(ares,
2015                                       DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
2016                                       false,
2017                                       ac->status);
2018         }
2019
2020         if (ares->error != LDB_SUCCESS) {
2021                 return ldb_module_done(ac->req, ares->controls,
2022                                         ares->response, ares->error);
2023         }
2024
2025         if (ares->type != LDB_REPLY_DONE) {
2026                 talloc_free(ares);
2027                 return ldb_module_done(ac->req, NULL, NULL,
2028                                         LDB_ERR_OPERATIONS_ERROR);
2029         }
2030
2031         return ldb_module_done(ac->req, ares->controls,
2032                                 ares->response, ares->error);
2033 }
2034
2035 static int password_hash_add_do_add(struct ph_context *ac);
2036 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares);
2037 static int password_hash_mod_search_self(struct ph_context *ac);
2038 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares);
2039 static int password_hash_mod_do_mod(struct ph_context *ac);
2040
2041 static int get_domain_data_callback(struct ldb_request *req,
2042                                     struct ldb_reply *ares)
2043 {
2044         struct ldb_context *ldb;
2045         struct ph_context *ac;
2046         struct loadparm_context *lp_ctx;
2047         int ret;
2048
2049         ac = talloc_get_type(req->context, struct ph_context);
2050         ldb = ldb_module_get_ctx(ac->module);
2051
2052         if (!ares) {
2053                 ret = LDB_ERR_OPERATIONS_ERROR;
2054                 goto done;
2055         }
2056         if (ares->error != LDB_SUCCESS) {
2057                 return ldb_module_done(ac->req, ares->controls,
2058                                         ares->response, ares->error);
2059         }
2060
2061         switch (ares->type) {
2062         case LDB_REPLY_ENTRY:
2063                 if (ac->status != NULL) {
2064                         talloc_free(ares);
2065
2066                         ldb_set_errstring(ldb, "Too many results");
2067                         ret = LDB_ERR_OPERATIONS_ERROR;
2068                         goto done;
2069                 }
2070
2071                 /* Setup the "status" structure (used as control later) */
2072                 ac->status = talloc_zero(ac->req,
2073                                          struct dsdb_control_password_change_status);
2074                 if (ac->status == NULL) {
2075                         talloc_free(ares);
2076
2077                         ldb_oom(ldb);
2078                         ret = LDB_ERR_OPERATIONS_ERROR;
2079                         goto done;
2080                 }
2081
2082                 /* Setup the "domain data" structure */
2083                 ac->status->domain_data.pwdProperties = samdb_result_uint(ares->message, "pwdProperties", -1);
2084                 ac->status->domain_data.pwdHistoryLength = samdb_result_uint(ares->message, "pwdHistoryLength", -1);
2085                 ac->status->domain_data.maxPwdAge = samdb_result_int64(ares->message, "maxPwdAge", -1);
2086                 ac->status->domain_data.minPwdAge = samdb_result_int64(ares->message, "minPwdAge", -1);
2087                 ac->status->domain_data.minPwdLength = samdb_result_uint(ares->message, "minPwdLength", -1);
2088                 ac->status->domain_data.store_cleartext =
2089                         ac->status->domain_data.pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT;
2090
2091                 talloc_free(ares);
2092
2093                 /* For a domain DN, this puts things in dotted notation */
2094                 /* For builtin domains, this will give details for the host,
2095                  * but that doesn't really matter, as it's just used for salt
2096                  * and kerberos principals, which don't exist here */
2097
2098                 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2099                                          struct loadparm_context);
2100
2101                 ac->status->domain_data.dns_domain = lp_dnsdomain(lp_ctx);
2102                 ac->status->domain_data.realm = lp_realm(lp_ctx);
2103                 ac->status->domain_data.netbios_domain = lp_sam_name(lp_ctx);
2104
2105                 ac->status->reject_reason = SAM_PWD_CHANGE_NO_ERROR;
2106
2107                 ret = LDB_SUCCESS;
2108                 break;
2109
2110         case LDB_REPLY_REFERRAL:
2111                 /* ignore */
2112                 talloc_free(ares);
2113                 ret = LDB_SUCCESS;
2114                 break;
2115
2116         case LDB_REPLY_DONE:
2117                 talloc_free(ares);
2118                 /* call the next step */
2119                 switch (ac->req->operation) {
2120                 case LDB_ADD:
2121                         ret = password_hash_add_do_add(ac);
2122                         break;
2123
2124                 case LDB_MODIFY:
2125                         ret = password_hash_mod_do_mod(ac);
2126                         break;
2127
2128                 default:
2129                         ret = LDB_ERR_OPERATIONS_ERROR;
2130                         break;
2131                 }
2132                 break;
2133         }
2134
2135 done:
2136         if (ret != LDB_SUCCESS) {
2137                 struct ldb_reply *new_ares;
2138
2139                 new_ares = talloc_zero(ac->req, struct ldb_reply);
2140                 if (new_ares == NULL) {
2141                         ldb_oom(ldb);
2142                         return ldb_module_done(ac->req, NULL, NULL,
2143                                                LDB_ERR_OPERATIONS_ERROR);
2144                 }
2145
2146                 new_ares->error = ret;
2147                 if ((ret != LDB_ERR_OPERATIONS_ERROR) && (ac->change_status)) {
2148                         /* On success and trivial errors a status control is being
2149                          * added (used for example by the "samdb_set_password" call) */
2150                         ldb_reply_add_control(new_ares,
2151                                               DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
2152                                               false,
2153                                               ac->status);
2154                 }
2155
2156                 return ldb_module_done(ac->req, new_ares->controls,
2157                                        new_ares->response, new_ares->error);
2158         }
2159
2160         return LDB_SUCCESS;
2161 }
2162
2163 static int build_domain_data_request(struct ph_context *ac)
2164 {
2165         /* attrs[] is returned from this function in
2166            ac->dom_req->op.search.attrs, so it must be static, as
2167            otherwise the compiler can put it on the stack */
2168         struct ldb_context *ldb;
2169         static const char * const attrs[] = { "pwdProperties",
2170                                               "pwdHistoryLength",
2171                                               "maxPwdAge",
2172                                               "minPwdAge",
2173                                               "minPwdLength",
2174                                               NULL };
2175
2176         ldb = ldb_module_get_ctx(ac->module);
2177
2178         return ldb_build_search_req(&ac->dom_req, ldb, ac,
2179                                     ldb_get_default_basedn(ldb),
2180                                     LDB_SCOPE_BASE,
2181                                     NULL, attrs,
2182                                     NULL,
2183                                     ac, get_domain_data_callback,
2184                                     ac->req);
2185 }
2186
2187 static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
2188 {
2189         struct ldb_context *ldb;
2190         struct ph_context *ac;
2191         struct ldb_message_element *userPasswordAttr, *clearTextPasswordAttr,
2192                 *ntAttr, *lmAttr;
2193         int ret;
2194
2195         ldb = ldb_module_get_ctx(module);
2196
2197         ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_add\n");
2198
2199         if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */
2200                 return ldb_next_request(module, req);
2201         }
2202
2203         /* If the caller is manipulating the local passwords directly, let them pass */
2204         if (ldb_dn_compare_base(ldb_dn_new(req, ldb, LOCAL_BASE),
2205                                 req->op.add.message->dn) == 0) {
2206                 return ldb_next_request(module, req);
2207         }
2208
2209         /* nobody must touch password histories and 'supplementalCredentials' */
2210         if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) {
2211                 return LDB_ERR_UNWILLING_TO_PERFORM;
2212         }
2213         if (ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) {
2214                 return LDB_ERR_UNWILLING_TO_PERFORM;
2215         }
2216         if (ldb_msg_find_element(req->op.add.message, "supplementalCredentials")) {
2217                 return LDB_ERR_UNWILLING_TO_PERFORM;
2218         }
2219
2220         /* If no part of this touches the 'userPassword' OR 'clearTextPassword'
2221          * OR 'unicodePwd' OR 'dBCSPwd' we don't need to make any changes. */
2222
2223         userPasswordAttr = ldb_msg_find_element(req->op.add.message, "userPassword");
2224         clearTextPasswordAttr = ldb_msg_find_element(req->op.add.message, "clearTextPassword");
2225         ntAttr = ldb_msg_find_element(req->op.add.message, "unicodePwd");
2226         lmAttr = ldb_msg_find_element(req->op.add.message, "dBCSPwd");
2227
2228         if ((!userPasswordAttr) && (!clearTextPasswordAttr) && (!ntAttr) && (!lmAttr)) {
2229                 return ldb_next_request(module, req);
2230         }
2231
2232         /* Make sure we are performing the password set action on a (for us)
2233          * valid object. Those are instances of either "user" and/or
2234          * "inetOrgPerson". Otherwise continue with the submodules. */
2235         if ((!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "user"))
2236                 && (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "inetOrgPerson"))) {
2237
2238                 if (ldb_msg_find_element(req->op.add.message, "clearTextPassword") != NULL) {
2239                         ldb_set_errstring(ldb,
2240                                           "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
2241                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
2242                 }
2243
2244                 return ldb_next_request(module, req);
2245         }
2246
2247         ac = ph_init_context(module, req);
2248         if (ac == NULL) {
2249                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
2250                 return LDB_ERR_OPERATIONS_ERROR;
2251         }
2252         ph_apply_controls(ac);
2253
2254         /* get user domain data */
2255         ret = build_domain_data_request(ac);
2256         if (ret != LDB_SUCCESS) {
2257                 return ret;
2258         }
2259
2260         return ldb_next_request(module, ac->dom_req);
2261 }
2262
2263 static int password_hash_add_do_add(struct ph_context *ac)
2264 {
2265         struct ldb_context *ldb;
2266         struct ldb_request *down_req;
2267         struct ldb_message *msg;
2268         struct setup_password_fields_io io;
2269         int ret;
2270
2271         /* Prepare the internal data structure containing the passwords */
2272         ret = setup_io(ac, ac->req->op.add.message, ac->req->op.add.message, &io);
2273         if (ret != LDB_SUCCESS) {
2274                 return ret;
2275         }
2276
2277         msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
2278         if (msg == NULL) {
2279                 return LDB_ERR_OPERATIONS_ERROR;
2280         }
2281
2282         /* remove attributes that we just read into 'io' (handle also superfluous
2283          * "password modify" trials - multiple attributes with the same name -
2284          * on add operations) */
2285         while (ldb_msg_find_element(msg, "userPassword") != NULL) {
2286                 ldb_msg_remove_attr(msg, "userPassword");
2287         }
2288         while (ldb_msg_find_element(msg, "clearTextPassword") != NULL) {
2289                 ldb_msg_remove_attr(msg, "clearTextPassword");
2290         }
2291         while (ldb_msg_find_element(msg, "unicodePwd") != NULL) {
2292                 ldb_msg_remove_attr(msg, "unicodePwd");
2293         }
2294         while (ldb_msg_find_element(msg, "dBCSPwd") != NULL) {
2295                 ldb_msg_remove_attr(msg, "dBCSPwd");
2296         }
2297
2298         ldb_msg_remove_attr(msg, "pwdLastSet");
2299
2300         ldb = ldb_module_get_ctx(ac->module);
2301
2302         ret = setup_password_fields(&io);
2303         if (ret != LDB_SUCCESS) {
2304                 return ret;
2305         }
2306
2307         ret = check_password_restrictions(&io);
2308         if (ret != LDB_SUCCESS) {
2309                 return ret;
2310         }
2311
2312         if (io.g.nt_hash) {
2313                 ret = samdb_msg_add_hash(ldb, ac, msg,
2314                                          "unicodePwd", io.g.nt_hash);
2315                 if (ret != LDB_SUCCESS) {
2316                         return ret;
2317                 }
2318         }
2319         if (io.g.lm_hash) {
2320                 ret = samdb_msg_add_hash(ldb, ac, msg,
2321                                          "dBCSPwd", io.g.lm_hash);
2322                 if (ret != LDB_SUCCESS) {
2323                         return ret;
2324                 }
2325         }
2326         if (io.g.nt_history_len > 0) {
2327                 ret = samdb_msg_add_hashes(ac, msg,
2328                                            "ntPwdHistory",
2329                                            io.g.nt_history,
2330                                            io.g.nt_history_len);
2331                 if (ret != LDB_SUCCESS) {
2332                         return ret;
2333                 }
2334         }
2335         if (io.g.lm_history_len > 0) {
2336                 ret = samdb_msg_add_hashes(ac, msg,
2337                                            "lmPwdHistory",
2338                                            io.g.lm_history,
2339                                            io.g.lm_history_len);
2340                 if (ret != LDB_SUCCESS) {
2341                         return ret;
2342                 }
2343         }
2344         if (io.g.supplemental.length > 0) {
2345                 ret = ldb_msg_add_value(msg, "supplementalCredentials",
2346                                         &io.g.supplemental, NULL);
2347                 if (ret != LDB_SUCCESS) {
2348                         return ret;
2349                 }
2350         }
2351         ret = samdb_msg_add_uint64(ldb, ac, msg,
2352                                    "pwdLastSet",
2353                                    io.g.last_set);
2354         if (ret != LDB_SUCCESS) {
2355                 return ret;
2356         }
2357
2358         ret = ldb_build_add_req(&down_req, ldb, ac,
2359                                 msg,
2360                                 ac->req->controls,
2361                                 ac, ph_op_callback,
2362                                 ac->req);
2363         if (ret != LDB_SUCCESS) {
2364                 return ret;
2365         }
2366
2367         return ldb_next_request(ac->module, down_req);
2368 }
2369
2370 static int password_hash_modify(struct ldb_module *module, struct ldb_request *req)
2371 {
2372         struct ldb_context *ldb;
2373         struct ph_context *ac;
2374         const char *passwordAttrs[] = { "userPassword", "clearTextPassword",
2375                 "unicodePwd", "dBCSPwd", NULL }, **l;
2376         unsigned int attr_cnt, del_attr_cnt, add_attr_cnt, rep_attr_cnt;
2377         struct ldb_message_element *passwordAttr;
2378         struct ldb_message *msg;
2379         struct ldb_request *down_req;
2380         int ret;
2381
2382         ldb = ldb_module_get_ctx(module);
2383
2384         ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_modify\n");
2385
2386         if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */
2387                 return ldb_next_request(module, req);
2388         }
2389         
2390         /* If the caller is manipulating the local passwords directly, let them pass */
2391         if (ldb_dn_compare_base(ldb_dn_new(req, ldb, LOCAL_BASE),
2392                                 req->op.mod.message->dn) == 0) {
2393                 return ldb_next_request(module, req);
2394         }
2395
2396         /* nobody must touch password histories and 'supplementalCredentials' */
2397         if (ldb_msg_find_element(req->op.mod.message, "ntPwdHistory")) {
2398                 return LDB_ERR_UNWILLING_TO_PERFORM;
2399         }
2400         if (ldb_msg_find_element(req->op.mod.message, "lmPwdHistory")) {
2401                 return LDB_ERR_UNWILLING_TO_PERFORM;
2402         }
2403         if (ldb_msg_find_element(req->op.mod.message, "supplementalCredentials")) {
2404                 return LDB_ERR_UNWILLING_TO_PERFORM;
2405         }
2406
2407         /* If no part of this touches the 'userPassword' OR 'clearTextPassword'
2408          * OR 'unicodePwd' OR 'dBCSPwd' we don't need to make any changes.
2409          * For password changes/set there should be a 'delete' or a 'modify'
2410          * on these attributes. */
2411         attr_cnt = 0;
2412         for (l = passwordAttrs; *l != NULL; l++) {
2413                 if (ldb_msg_find_element(req->op.mod.message, *l) != NULL) {
2414                         ++attr_cnt;
2415                 }
2416         }
2417         if (attr_cnt == 0) {
2418                 return ldb_next_request(module, req);
2419         }
2420
2421         ac = ph_init_context(module, req);
2422         if (!ac) {
2423                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
2424                 return LDB_ERR_OPERATIONS_ERROR;
2425         }
2426         ph_apply_controls(ac);
2427
2428         /* use a new message structure so that we can modify it */
2429         msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
2430         if (msg == NULL) {
2431                 ldb_oom(ldb);
2432                 return LDB_ERR_OPERATIONS_ERROR;
2433         }
2434
2435         /* - check for single-valued password attributes
2436          *   (if not return "CONSTRAINT_VIOLATION")
2437          * - check that for a password change operation one add and one delete
2438          *   operation exists
2439          *   (if not return "CONSTRAINT_VIOLATION" or "UNWILLING_TO_PERFORM")
2440          * - check that a password change and a password set operation cannot
2441          *   be mixed
2442          *   (if not return "UNWILLING_TO_PERFORM")
2443          * - remove all password attributes modifications from the first change
2444          *   operation (anything without the passwords) - we will make the real
2445          *   modification later */
2446         del_attr_cnt = 0;
2447         add_attr_cnt = 0;
2448         rep_attr_cnt = 0;
2449         for (l = passwordAttrs; *l != NULL; l++) {
2450                 while ((passwordAttr = ldb_msg_find_element(msg, *l)) != NULL) {
2451                         if (passwordAttr->flags == LDB_FLAG_MOD_DELETE) {
2452                                 ++del_attr_cnt;
2453                         }
2454                         if (passwordAttr->flags == LDB_FLAG_MOD_ADD) {
2455                                 ++add_attr_cnt;
2456                         }
2457                         if (passwordAttr->flags == LDB_FLAG_MOD_REPLACE) {
2458                                 ++rep_attr_cnt;
2459                         }
2460                         if ((passwordAttr->num_values != 1) &&
2461                             (passwordAttr->flags != LDB_FLAG_MOD_REPLACE)) {
2462                                 talloc_free(ac);
2463                                 ldb_asprintf_errstring(ldb,
2464                                                        "'%s' attributes must have exactly one value!",
2465                                                        *l);
2466                                 return LDB_ERR_CONSTRAINT_VIOLATION;
2467                         }
2468                         ldb_msg_remove_attr(msg, *l);
2469                 }
2470         }
2471         if ((del_attr_cnt > 0) && (add_attr_cnt == 0)) {
2472                 talloc_free(ac);
2473                 ldb_set_errstring(ldb,
2474                                   "Only the delete action for a password change specified!");
2475                 return LDB_ERR_CONSTRAINT_VIOLATION;
2476         }
2477         if ((del_attr_cnt == 0) && (add_attr_cnt > 0)) {
2478                 talloc_free(ac);
2479                 ldb_set_errstring(ldb,
2480                                   "Only the add action for a password change specified!");
2481                 return LDB_ERR_UNWILLING_TO_PERFORM;
2482         }
2483         if ((del_attr_cnt > 1) || (add_attr_cnt > 1)) {
2484                 talloc_free(ac);
2485                 ldb_set_errstring(ldb,
2486                                   "Only one delete and one add action for a password change allowed!");
2487                 return LDB_ERR_UNWILLING_TO_PERFORM;
2488         }
2489         if ((rep_attr_cnt > 0) && ((del_attr_cnt > 0) || (add_attr_cnt > 0))) {
2490                 talloc_free(ac);
2491                 ldb_set_errstring(ldb,
2492                                   "Either a password change or a password set operation is allowed!");
2493                 return LDB_ERR_UNWILLING_TO_PERFORM;
2494         }
2495
2496         /* if there was nothing else to be modified skip to next step */
2497         if (msg->num_elements == 0) {
2498                 return password_hash_mod_search_self(ac);
2499         }
2500
2501         ret = ldb_build_mod_req(&down_req, ldb, ac,
2502                                 msg,
2503                                 req->controls,
2504                                 ac, ph_modify_callback,
2505                                 req);
2506         if (ret != LDB_SUCCESS) {
2507                 return ret;
2508         }
2509
2510         return ldb_next_request(module, down_req);
2511 }
2512
2513 static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
2514 {
2515         struct ph_context *ac;
2516
2517         ac = talloc_get_type(req->context, struct ph_context);
2518
2519         if (!ares) {
2520                 return ldb_module_done(ac->req, NULL, NULL,
2521                                         LDB_ERR_OPERATIONS_ERROR);
2522         }
2523
2524         if (ares->type == LDB_REPLY_REFERRAL) {
2525                 return ldb_module_send_referral(ac->req, ares->referral);
2526         }
2527
2528         if (ares->error != LDB_SUCCESS) {
2529                 return ldb_module_done(ac->req, ares->controls,
2530                                         ares->response, ares->error);
2531         }
2532
2533         if (ares->type != LDB_REPLY_DONE) {
2534                 talloc_free(ares);
2535                 return ldb_module_done(ac->req, NULL, NULL,
2536                                         LDB_ERR_OPERATIONS_ERROR);
2537         }
2538
2539         talloc_free(ares);
2540
2541         return password_hash_mod_search_self(ac);
2542 }
2543
2544 static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares)
2545 {
2546         struct ldb_context *ldb;
2547         struct ph_context *ac;
2548         int ret;
2549
2550         ac = talloc_get_type(req->context, struct ph_context);
2551         ldb = ldb_module_get_ctx(ac->module);
2552
2553         if (!ares) {
2554                 ret = LDB_ERR_OPERATIONS_ERROR;
2555                 goto done;
2556         }
2557         if (ares->error != LDB_SUCCESS) {
2558                 return ldb_module_done(ac->req, ares->controls,
2559                                         ares->response, ares->error);
2560         }
2561
2562         /* we are interested only in the single reply (base search) */
2563         switch (ares->type) {
2564         case LDB_REPLY_ENTRY:
2565                 /* Make sure we are performing the password change action on a
2566                  * (for us) valid object. Those are instances of either "user"
2567                  * and/or "inetOrgPerson". Otherwise continue with the
2568                  * submodules. */
2569                 if ((!ldb_msg_check_string_attribute(ares->message, "objectClass", "user"))
2570                         && (!ldb_msg_check_string_attribute(ares->message, "objectClass", "inetOrgPerson"))) {
2571                         talloc_free(ares);
2572
2573                         if (ldb_msg_find_element(ac->req->op.mod.message, "clearTextPassword") != NULL) {
2574                                 ldb_set_errstring(ldb,
2575                                                   "'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
2576                                 ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
2577                                 goto done;
2578                         }
2579
2580                         ret = ldb_next_request(ac->module, ac->req);
2581                         goto done;
2582                 }
2583
2584                 if (ac->search_res != NULL) {
2585                         talloc_free(ares);
2586
2587                         ldb_set_errstring(ldb, "Too many results");
2588                         ret = LDB_ERR_OPERATIONS_ERROR;
2589                         goto done;
2590                 }
2591
2592                 ac->search_res = talloc_steal(ac, ares);
2593                 ret = LDB_SUCCESS;
2594                 break;
2595
2596         case LDB_REPLY_REFERRAL:
2597                 /* ignore anything else for now */
2598                 talloc_free(ares);
2599                 ret = LDB_SUCCESS;
2600                 break;
2601
2602         case LDB_REPLY_DONE:
2603                 talloc_free(ares);
2604
2605                 /* get user domain data */
2606                 ret = build_domain_data_request(ac);
2607                 if (ret != LDB_SUCCESS) {
2608                         return ldb_module_done(ac->req, NULL, NULL, ret);
2609                 }
2610
2611                 ret = ldb_next_request(ac->module, ac->dom_req);
2612                 break;
2613         }
2614
2615 done:
2616         if (ret != LDB_SUCCESS) {
2617                 return ldb_module_done(ac->req, NULL, NULL, ret);
2618         }
2619
2620         return LDB_SUCCESS;
2621 }
2622
2623 static int password_hash_mod_search_self(struct ph_context *ac)
2624 {
2625         struct ldb_context *ldb;
2626         static const char * const attrs[] = { "objectClass",
2627                                               "userAccountControl",
2628                                               "pwdLastSet",
2629                                               "sAMAccountName",
2630                                               "objectSid",
2631                                               "userPrincipalName",
2632                                               "supplementalCredentials",
2633                                               "lmPwdHistory",
2634                                               "ntPwdHistory",
2635                                               "dBCSPwd",
2636                                               "unicodePwd",
2637                                               NULL };
2638         struct ldb_request *search_req;
2639         int ret;
2640
2641         ldb = ldb_module_get_ctx(ac->module);
2642
2643         ret = ldb_build_search_req(&search_req, ldb, ac,
2644                                    ac->req->op.mod.message->dn,
2645                                    LDB_SCOPE_BASE,
2646                                    "(objectclass=*)",
2647                                    attrs,
2648                                    NULL,
2649                                    ac, ph_mod_search_callback,
2650                                    ac->req);
2651
2652         if (ret != LDB_SUCCESS) {
2653                 return ret;
2654         }
2655
2656         return ldb_next_request(ac->module, search_req);
2657 }
2658
2659 static int password_hash_mod_do_mod(struct ph_context *ac)
2660 {
2661         struct ldb_context *ldb;
2662         struct ldb_request *mod_req;
2663         struct ldb_message *msg;
2664         const struct ldb_message *orig_msg, *searched_msg;
2665         struct setup_password_fields_io io;
2666         int ret;
2667         NTSTATUS status;
2668
2669         ldb = ldb_module_get_ctx(ac->module);
2670
2671         /* use a new message structure so that we can modify it */
2672         msg = ldb_msg_new(ac);
2673         if (msg == NULL) {
2674                 return LDB_ERR_OPERATIONS_ERROR;
2675         }
2676
2677         /* modify dn */
2678         msg->dn = ac->req->op.mod.message->dn;
2679
2680         orig_msg = ac->req->op.mod.message;
2681         searched_msg = ac->search_res->message;
2682
2683         /* Prepare the internal data structure containing the passwords */
2684         ret = setup_io(ac, orig_msg, searched_msg, &io);
2685         if (ret != LDB_SUCCESS) {
2686                 return ret;
2687         }
2688         
2689         /* Get the old password from the database */
2690         status = samdb_result_passwords(io.ac,
2691                                         ldb_get_opaque(ldb, "loadparm"),
2692                                         discard_const_p(struct ldb_message, searched_msg),
2693                                         &io.o.lm_hash, &io.o.nt_hash);
2694         if (!NT_STATUS_IS_OK(status)) {
2695                 return LDB_ERR_OPERATIONS_ERROR;
2696         }
2697
2698         io.o.nt_history_len             = samdb_result_hashes(io.ac, searched_msg, "ntPwdHistory", &io.o.nt_history);
2699         io.o.lm_history_len             = samdb_result_hashes(io.ac, searched_msg, "lmPwdHistory", &io.o.lm_history);
2700         io.o.supplemental               = ldb_msg_find_ldb_val(searched_msg, "supplementalCredentials");
2701
2702         ret = setup_password_fields(&io);
2703         if (ret != LDB_SUCCESS) {
2704                 return ret;
2705         }
2706
2707         ret = check_password_restrictions(&io);
2708         if (ret != LDB_SUCCESS) {
2709                 return ret;
2710         }
2711
2712         /* make sure we replace all the old attributes */
2713         ret = ldb_msg_add_empty(msg, "unicodePwd", LDB_FLAG_MOD_REPLACE, NULL);
2714         ret = ldb_msg_add_empty(msg, "dBCSPwd", LDB_FLAG_MOD_REPLACE, NULL);
2715         ret = ldb_msg_add_empty(msg, "ntPwdHistory", LDB_FLAG_MOD_REPLACE, NULL);
2716         ret = ldb_msg_add_empty(msg, "lmPwdHistory", LDB_FLAG_MOD_REPLACE, NULL);
2717         ret = ldb_msg_add_empty(msg, "supplementalCredentials", LDB_FLAG_MOD_REPLACE, NULL);
2718         ret = ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE, NULL);
2719
2720         if (io.g.nt_hash) {
2721                 ret = samdb_msg_add_hash(ldb, ac, msg,
2722                                          "unicodePwd", io.g.nt_hash);
2723                 if (ret != LDB_SUCCESS) {
2724                         return ret;
2725                 }
2726         }
2727         if (io.g.lm_hash) {
2728                 ret = samdb_msg_add_hash(ldb, ac, msg,
2729                                          "dBCSPwd", io.g.lm_hash);
2730                 if (ret != LDB_SUCCESS) {
2731                         return ret;
2732                 }
2733         }
2734         if (io.g.nt_history_len > 0) {
2735                 ret = samdb_msg_add_hashes(ac, msg,
2736                                            "ntPwdHistory",
2737                                            io.g.nt_history,
2738                                            io.g.nt_history_len);
2739                 if (ret != LDB_SUCCESS) {
2740                         return ret;
2741                 }
2742         }
2743         if (io.g.lm_history_len > 0) {
2744                 ret = samdb_msg_add_hashes(ac, msg,
2745                                            "lmPwdHistory",
2746                                            io.g.lm_history,
2747                                            io.g.lm_history_len);
2748                 if (ret != LDB_SUCCESS) {
2749                         return ret;
2750                 }
2751         }
2752         if (io.g.supplemental.length > 0) {
2753                 ret = ldb_msg_add_value(msg, "supplementalCredentials",
2754                                         &io.g.supplemental, NULL);
2755                 if (ret != LDB_SUCCESS) {
2756                         return ret;
2757                 }
2758         }
2759         ret = samdb_msg_add_uint64(ldb, ac, msg,
2760                                    "pwdLastSet",
2761                                    io.g.last_set);
2762         if (ret != LDB_SUCCESS) {
2763                 return ret;
2764         }
2765
2766         ret = ldb_build_mod_req(&mod_req, ldb, ac,
2767                                 msg,
2768                                 ac->req->controls,
2769                                 ac, ph_op_callback,
2770                                 ac->req);
2771         if (ret != LDB_SUCCESS) {
2772                 return ret;
2773         }
2774
2775         return ldb_next_request(ac->module, mod_req);
2776 }
2777
2778 _PUBLIC_ const struct ldb_module_ops ldb_password_hash_module_ops = {
2779         .name          = "password_hash",
2780         .add           = password_hash_add,
2781         .modify        = password_hash_modify
2782 };