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