~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/dsdb/samdb/ldb_modules/password_hash.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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