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 "../libds/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 72struct 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 86struct 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 95struct 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 150static 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 192static 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 227static 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 = strlower_talloc(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 432static 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 534static 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 654static 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 984static 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 int *domainFunctionality; 1030 1031 ZERO_STRUCT(zero16); 1032 ZERO_STRUCT(names); 1033 1034 ldb = ldb_module_get_ctx(io->ac->module); 1035 1036 if (!io->n.cleartext_utf8) { 1037 /* 1038 * when we don't have a cleartext password 1039 * we can't setup a supplementalCredential value 1040 */ 1041 return LDB_SUCCESS; 1042 } 1043 1044 /* if there's an old supplementaCredentials blob then parse it */ 1045 if (io->o.supplemental) { 1046 ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac, 1047 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 1048 &_old_scb, 1049 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob); 1050 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1051 NTSTATUS status = ndr_map_error2ntstatus(ndr_err); 1052 ldb_asprintf_errstring(ldb, 1053 "setup_supplemental_field: " 1054 "failed to pull old supplementalCredentialsBlob: %s", 1055 nt_errstr(status)); 1056 return LDB_ERR_OPERATIONS_ERROR; 1057 } 1058 1059 if (_old_scb.sub.signature == SUPPLEMENTAL_CREDENTIALS_SIGNATURE) { 1060 old_scb = &_old_scb; 1061 } else { 1062 ldb_debug(ldb, LDB_DEBUG_ERROR, 1063 "setup_supplemental_field: " 1064 "supplementalCredentialsBlob signature[0x%04X] expected[0x%04X]", 1065 _old_scb.sub.signature, SUPPLEMENTAL_CREDENTIALS_SIGNATURE); 1066 } 1067 } 1068 /* Per MS-SAMR 3.1.1.8.11.6 we create AES keys if our domain functionality level is 2008 or higher */ 1069 domainFunctionality = talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), int); 1070 1071 do_newer_keys = *domainFunctionality && 1072 (*domainFunctionality >= DS_DOMAIN_FUNCTION_2008); 1073 1074 if (io->domain->store_cleartext && 1075 (io->u.user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { 1076 do_cleartext = true; 1077 } 1078 1079 /* 1080 * The ordering is this 1081 * 1082 * Primary:Kerberos-Newer-Keys (optional) 1083 * Primary:Kerberos 1084 * Primary:WDigest 1085 * Primary:CLEARTEXT (optional) 1086 * 1087 * And the 'Packages' package is insert before the last 1088 * other package. 1089 */ 1090 if (do_newer_keys) { 1091 /* Primary:Kerberos-Newer-Keys */ 1092 nkn = &names[num_names++]; 1093 pkn = &packages[num_packages++]; 1094 } 1095 1096 /* Primary:Kerberos */ 1097 nk = &names[num_names++]; 1098 pk = &packages[num_packages++]; 1099 1100 if (!do_cleartext) { 1101 /* Packages */ 1102 pp = &packages[num_packages++]; 1103 } 1104 1105 /* Primary:WDigest */ 1106 nd = &names[num_names++]; 1107 pd = &packages[num_packages++]; 1108 1109 if (do_cleartext) { 1110 /* Packages */ 1111 pp = &packages[num_packages++]; 1112 1113 /* Primary:CLEARTEXT */ 1114 nc = &names[num_names++]; 1115 pc = &packages[num_packages++]; 1116 } 1117 1118 if (pkn) { 1119 /* 1120 * setup 'Primary:Kerberos-Newer-Keys' element 1121 */ 1122 *nkn = "Kerberos-Newer-Keys"; 1123 1124 ret = setup_primary_kerberos_newer(io, old_scb, &pknb); 1125 if (ret != LDB_SUCCESS) { 1126 return ret; 1127 } 1128 1129 ndr_err = ndr_push_struct_blob(&pknb_blob, io->ac, 1130 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 1131 &pknb, 1132 (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob); 1133 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1134 NTSTATUS status = ndr_map_error2ntstatus(ndr_err); 1135 ldb_asprintf_errstring(ldb, 1136 "setup_supplemental_field: " 1137 "failed to push package_PrimaryKerberosNeverBlob: %s", 1138 nt_errstr(status)); 1139 return LDB_ERR_OPERATIONS_ERROR; 1140 } 1141 pknb_hexstr = data_blob_hex_string(io->ac, &pknb_blob); 1142 if (!pknb_hexstr) { 1143 ldb_oom(ldb); 1144 return LDB_ERR_OPERATIONS_ERROR; 1145 } 1146 pkn->name = "Primary:Kerberos-Newer-Keys"; 1147 pkn->reserved = 1; 1148 pkn->data = pknb_hexstr; 1149 } 1150 1151 /* 1152 * setup 'Primary:Kerberos' element 1153 */ 1154 *nk = "Kerberos"; 1155 1156 ret = setup_primary_kerberos(io, old_scb, &pkb); 1157 if (ret != LDB_SUCCESS) { 1158 return ret; 1159 } 1160 1161 ndr_err = ndr_push_struct_blob(&pkb_blob, io->ac, 1162 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 1163 &pkb, 1164 (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob); 1165 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1166 NTSTATUS status = ndr_map_error2ntstatus(ndr_err); 1167 ldb_asprintf_errstring(ldb, 1168 "setup_supplemental_field: " 1169 "failed to push package_PrimaryKerberosBlob: %s", 1170 nt_errstr(status)); 1171 return LDB_ERR_OPERATIONS_ERROR; 1172 } 1173 pkb_hexstr = data_blob_hex_string(io->ac, &pkb_blob); 1174 if (!pkb_hexstr) { 1175 ldb_oom(ldb); 1176 return LDB_ERR_OPERATIONS_ERROR; 1177 } 1178 pk->name = "Primary:Kerberos"; 1179 pk->reserved = 1; 1180 pk->data = pkb_hexstr; 1181 1182 /* 1183 * setup 'Primary:WDigest' element 1184 */ 1185 *nd = "WDigest"; 1186 1187 ret = setup_primary_wdigest(io, old_scb, &pdb); 1188 if (ret != LDB_SUCCESS) { 1189 return ret; 1190 } 1191 1192 ndr_err = ndr_push_struct_blob(&pdb_blob, io->ac, 1193 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 1194 &pdb, 1195 (ndr_push_flags_fn_t)ndr_push_package_PrimaryWDigestBlob); 1196 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1197 NTSTATUS status = ndr_map_error2ntstatus(ndr_err); 1198 ldb_asprintf_errstring(ldb, 1199 "setup_supplemental_field: " 1200 "failed to push package_PrimaryWDigestBlob: %s", 1201 nt_errstr(status)); 1202 return LDB_ERR_OPERATIONS_ERROR; 1203 } 1204 pdb_hexstr = data_blob_hex_string(io->ac, &pdb_blob); 1205 if (!pdb_hexstr) { 1206 ldb_oom(ldb); 1207 return LDB_ERR_OPERATIONS_ERROR; 1208 } 1209 pd->name = "Primary:WDigest"; 1210 pd->reserved = 1; 1211 pd->data = pdb_hexstr; 1212 1213 /* 1214 * setup 'Primary:CLEARTEXT' element 1215 */ 1216 if (pc) { 1217 *nc = "CLEARTEXT"; 1218 1219 pcb.cleartext = *io->n.cleartext_utf16; 1220 1221 ndr_err = ndr_push_struct_blob(&pcb_blob, io->ac, 1222 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 1223 &pcb, 1224 (ndr_push_flags_fn_t)ndr_push_package_PrimaryCLEARTEXTBlob); 1225 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1226 NTSTATUS status = ndr_map_error2ntstatus(ndr_err); 1227 ldb_asprintf_errstring(ldb, 1228 "setup_supplemental_field: " 1229 "failed to push package_PrimaryCLEARTEXTBlob: %s", 1230 nt_errstr(status)); 1231 return LDB_ERR_OPERATIONS_ERROR; 1232 } 1233 pcb_hexstr = data_blob_hex_string(io->ac, &pcb_blob); 1234 if (!pcb_hexstr) { 1235 ldb_oom(ldb); 1236 return LDB_ERR_OPERATIONS_ERROR; 1237 } 1238 pc->name = "Primary:CLEARTEXT"; 1239 pc->reserved = 1; 1240 pc->data = pcb_hexstr; 1241 } 1242 1243 /* 1244 * setup 'Packages' element 1245 */ 1246 pb.names = names; 1247 ndr_err = ndr_push_struct_blob(&pb_blob, io->ac, 1248 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 1249 &pb, 1250 (ndr_push_flags_fn_t)ndr_push_package_PackagesBlob); 1251 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1252 NTSTATUS status = ndr_map_error2ntstatus(ndr_err); 1253 ldb_asprintf_errstring(ldb, 1254 "setup_supplemental_field: " 1255 "failed to push package_PackagesBlob: %s", 1256 nt_errstr(status)); 1257 return LDB_ERR_OPERATIONS_ERROR; 1258 } 1259 pb_hexstr = data_blob_hex_string(io->ac, &pb_blob); 1260 if (!pb_hexstr) { 1261 ldb_oom(ldb); 1262 return LDB_ERR_OPERATIONS_ERROR; 1263 } 1264 pp->name = "Packages"; 1265 pp->reserved = 2; 1266 pp->data = pb_hexstr; 1267 1268 /* 1269 * setup 'supplementalCredentials' value 1270 */ 1271 ZERO_STRUCT(scb); 1272 scb.sub.num_packages = num_packages; 1273 scb.sub.packages = packages; 1274 1275 ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac, 1276 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 1277 &scb, 1278 (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob); 1279 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1280 NTSTATUS status = ndr_map_error2ntstatus(ndr_err); 1281 ldb_asprintf_errstring(ldb, 1282 "setup_supplemental_field: " 1283 "failed to push supplementalCredentialsBlob: %s", 1284 nt_errstr(status)); 1285 return LDB_ERR_OPERATIONS_ERROR; 1286 } 1287 1288 return LDB_SUCCESS; 1289} 1290 1291static int setup_last_set_field(struct setup_password_fields_io *io) 1292{ 1293 /* set it as now */ 1294 unix_to_nt_time(&io->g.last_set, time(NULL)); 1295 1296 return LDB_SUCCESS; 1297} 1298 1299static int setup_kvno_field(struct setup_password_fields_io *io) 1300{ 1301 /* increment by one */ 1302 io->g.kvno = io->o.kvno + 1; 1303 1304 return LDB_SUCCESS; 1305} 1306 1307static int setup_password_fields(struct setup_password_fields_io *io) 1308{ 1309 struct ldb_context *ldb; 1310 bool ok; 1311 int ret; 1312 size_t converted_pw_len; 1313 1314 ldb = ldb_module_get_ctx(io->ac->module); 1315 1316 /* 1317 * refuse the change if someone want to change the cleartext 1318 * and supply his own hashes at the same time... 1319 */ 1320 if ((io->n.cleartext_utf8 || io->n.cleartext_utf16) && (io->n.nt_hash || io->n.lm_hash)) { 1321 ldb_asprintf_errstring(ldb, 1322 "setup_password_fields: " 1323 "it's only allowed to set the cleartext password or the password hashes"); 1324 return LDB_ERR_UNWILLING_TO_PERFORM; 1325 } 1326 1327 if (io->n.cleartext_utf8 && io->n.cleartext_utf16) { 1328 ldb_asprintf_errstring(ldb, 1329 "setup_password_fields: " 1330 "it's only allowed to set the cleartext password as userPassword or clearTextPasssword, not both at once"); 1331 return LDB_ERR_UNWILLING_TO_PERFORM; 1332 } 1333 1334 if (io->n.cleartext_utf8) { 1335 char **cleartext_utf16_str; 1336 struct ldb_val *cleartext_utf16_blob; 1337 io->n.cleartext_utf16 = cleartext_utf16_blob = talloc(io->ac, struct ldb_val); 1338 if (!io->n.cleartext_utf16) { 1339 ldb_oom(ldb); 1340 return LDB_ERR_OPERATIONS_ERROR; 1341 } 1342 if (!convert_string_talloc_convenience(io->ac, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 1343 CH_UTF8, CH_UTF16, io->n.cleartext_utf8->data, io->n.cleartext_utf8->length, 1344 (void **)&cleartext_utf16_str, &converted_pw_len, false)) { 1345 ldb_asprintf_errstring(ldb, 1346 "setup_password_fields: " 1347 "failed to generate UTF16 password from cleartext UTF8 password"); 1348 return LDB_ERR_OPERATIONS_ERROR; 1349 } 1350 *cleartext_utf16_blob = data_blob_const(cleartext_utf16_str, converted_pw_len); 1351 } else if (io->n.cleartext_utf16) { 1352 char *cleartext_utf8_str; 1353 struct ldb_val *cleartext_utf8_blob; 1354 io->n.cleartext_utf8 = cleartext_utf8_blob = talloc(io->ac, struct ldb_val); 1355 if (!io->n.cleartext_utf8) { 1356 ldb_oom(ldb); 1357 return LDB_ERR_OPERATIONS_ERROR; 1358 } 1359 if (!convert_string_talloc_convenience(io->ac, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 1360 CH_UTF16MUNGED, CH_UTF8, io->n.cleartext_utf16->data, io->n.cleartext_utf16->length, 1361 (void **)&cleartext_utf8_str, &converted_pw_len, false)) { 1362 /* We can't bail out entirely, as these unconvertable passwords are frustratingly valid */ 1363 io->n.cleartext_utf8 = NULL; 1364 talloc_free(cleartext_utf8_blob); 1365 } 1366 *cleartext_utf8_blob = data_blob_const(cleartext_utf8_str, converted_pw_len); 1367 } 1368 if (io->n.cleartext_utf16) { 1369 struct samr_Password *nt_hash; 1370 nt_hash = talloc(io->ac, struct samr_Password); 1371 if (!nt_hash) { 1372 ldb_oom(ldb); 1373 return LDB_ERR_OPERATIONS_ERROR; 1374 } 1375 io->n.nt_hash = nt_hash; 1376 1377 /* compute the new nt hash */ 1378 mdfour(nt_hash->hash, io->n.cleartext_utf16->data, io->n.cleartext_utf16->length); 1379 } 1380 1381 if (io->n.cleartext_utf8) { 1382 struct samr_Password *lm_hash; 1383 char *cleartext_unix; 1384 if (lp_lanman_auth(ldb_get_opaque(ldb, "loadparm")) && 1385 convert_string_talloc_convenience(io->ac, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 1386 CH_UTF8, CH_UNIX, io->n.cleartext_utf8->data, io->n.cleartext_utf8->length, 1387 (void **)&cleartext_unix, &converted_pw_len, false)) { 1388 lm_hash = talloc(io->ac, struct samr_Password); 1389 if (!lm_hash) { 1390 ldb_oom(ldb); 1391 return LDB_ERR_OPERATIONS_ERROR; 1392 } 1393 1394 /* compute the new lm hash. */ 1395 ok = E_deshash((char *)cleartext_unix, lm_hash->hash); 1396 if (ok) { 1397 io->n.lm_hash = lm_hash; 1398 } else { 1399 talloc_free(lm_hash->hash); 1400 } 1401 } 1402 1403 ret = setup_kerberos_keys(io); 1404 if (ret != LDB_SUCCESS) { 1405 return ret; 1406 } 1407 } 1408 1409 ret = setup_nt_fields(io); 1410 if (ret != LDB_SUCCESS) { 1411 return ret; 1412 } 1413 1414 ret = setup_lm_fields(io); 1415 if (ret != LDB_SUCCESS) { 1416 return ret; 1417 } 1418 1419 ret = setup_supplemental_field(io); 1420 if (ret != LDB_SUCCESS) { 1421 return ret; 1422 } 1423 1424 ret = setup_last_set_field(io); 1425 if (ret != LDB_SUCCESS) { 1426 return ret; 1427 } 1428 1429 ret = setup_kvno_field(io); 1430 if (ret != LDB_SUCCESS) { 1431 return ret; 1432 } 1433 1434 return LDB_SUCCESS; 1435} 1436 1437static int setup_io(struct ph_context *ac, 1438 const struct ldb_message *new_msg, 1439 const struct ldb_message *searched_msg, 1440 struct setup_password_fields_io *io) 1441{ 1442 const struct ldb_val *quoted_utf16; 1443 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 1444 1445 ZERO_STRUCTP(io); 1446 1447 /* Some operations below require kerberos contexts */ 1448 if (smb_krb5_init_context(ac, 1449 ldb_get_event_context(ldb), 1450 (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm"), 1451 &io->smb_krb5_context) != 0) { 1452 return LDB_ERR_OPERATIONS_ERROR; 1453 } 1454 1455 io->ac = ac; 1456 io->domain = ac->domain; 1457 1458 io->u.user_account_control = samdb_result_uint(searched_msg, "userAccountControl", 0); 1459 io->u.sAMAccountName = samdb_result_string(searched_msg, "samAccountName", NULL); 1460 io->u.user_principal_name = samdb_result_string(searched_msg, "userPrincipalName", NULL); 1461 io->u.is_computer = ldb_msg_check_string_attribute(searched_msg, "objectClass", "computer"); 1462 1463 io->n.cleartext_utf8 = ldb_msg_find_ldb_val(new_msg, "userPassword"); 1464 io->n.cleartext_utf16 = ldb_msg_find_ldb_val(new_msg, "clearTextPassword"); 1465 1466 /* this rather strange looking piece of code is there to 1467 handle a ldap client setting a password remotely using the 1468 unicodePwd ldap field. The syntax is that the password is 1469 in UTF-16LE, with a " at either end. Unfortunately the 1470 unicodePwd field is also used to store the nt hashes 1471 internally in Samba, and is used in the nt hash format on 1472 the wire in DRS replication, so we have a single name for 1473 two distinct values. The code below leaves us with a small 1474 chance (less than 1 in 2^32) of a mixup, if someone manages 1475 to create a MD4 hash which starts and ends in 0x22 0x00, as 1476 that would then be treated as a UTF16 password rather than 1477 a nthash */ 1478 quoted_utf16 = ldb_msg_find_ldb_val(new_msg, "unicodePwd"); 1479 if (quoted_utf16 && 1480 quoted_utf16->length >= 4 && 1481 quoted_utf16->data[0] == '"' && 1482 quoted_utf16->data[1] == 0 && 1483 quoted_utf16->data[quoted_utf16->length-2] == '"' && 1484 quoted_utf16->data[quoted_utf16->length-1] == 0) { 1485 io->n.quoted_utf16.data = talloc_memdup(io->ac, quoted_utf16->data+2, quoted_utf16->length-4); 1486 io->n.quoted_utf16.length = quoted_utf16->length-4; 1487 io->n.cleartext_utf16 = &io->n.quoted_utf16; 1488 io->n.nt_hash = NULL; 1489 } else { 1490 io->n.nt_hash = samdb_result_hash(io->ac, new_msg, "unicodePwd"); 1491 } 1492 1493 io->n.lm_hash = samdb_result_hash(io->ac, new_msg, "dBCSPwd"); 1494 1495 return LDB_SUCCESS; 1496} 1497 1498static struct ph_context *ph_init_context(struct ldb_module *module, 1499 struct ldb_request *req) 1500{ 1501 struct ldb_context *ldb; 1502 struct ph_context *ac; 1503 1504 ldb = ldb_module_get_ctx(module); 1505 1506 ac = talloc_zero(req, struct ph_context); 1507 if (ac == NULL) { 1508 ldb_set_errstring(ldb, "Out of Memory"); 1509 return NULL; 1510 } 1511 1512 ac->module = module; 1513 ac->req = req; 1514 1515 return ac; 1516} 1517 1518static int ph_op_callback(struct ldb_request *req, struct ldb_reply *ares) 1519{ 1520 struct ph_context *ac; 1521 1522 ac = talloc_get_type(req->context, struct ph_context); 1523 1524 if (!ares) { 1525 return ldb_module_done(ac->req, NULL, NULL, 1526 LDB_ERR_OPERATIONS_ERROR); 1527 } 1528 if (ares->error != LDB_SUCCESS) { 1529 return ldb_module_done(ac->req, ares->controls, 1530 ares->response, ares->error); 1531 } 1532 1533 if (ares->type != LDB_REPLY_DONE) { 1534 talloc_free(ares); 1535 return ldb_module_done(ac->req, NULL, NULL, 1536 LDB_ERR_OPERATIONS_ERROR); 1537 } 1538 1539 return ldb_module_done(ac->req, ares->controls, 1540 ares->response, ares->error); 1541} 1542 1543static int password_hash_add_do_add(struct ph_context *ac); 1544static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares); 1545static int password_hash_mod_search_self(struct ph_context *ac); 1546static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares); 1547static int password_hash_mod_do_mod(struct ph_context *ac); 1548 1549static int get_domain_data_callback(struct ldb_request *req, 1550 struct ldb_reply *ares) 1551{ 1552 struct ldb_context *ldb; 1553 struct domain_data *data; 1554 struct ph_context *ac; 1555 int ret; 1556 char *tmp; 1557 char *p; 1558 1559 ac = talloc_get_type(req->context, struct ph_context); 1560 ldb = ldb_module_get_ctx(ac->module); 1561 1562 if (!ares) { 1563 return ldb_module_done(ac->req, NULL, NULL, 1564 LDB_ERR_OPERATIONS_ERROR); 1565 } 1566 if (ares->error != LDB_SUCCESS) { 1567 return ldb_module_done(ac->req, ares->controls, 1568 ares->response, ares->error); 1569 } 1570 1571 switch (ares->type) { 1572 case LDB_REPLY_ENTRY: 1573 if (ac->domain != NULL) { 1574 ldb_set_errstring(ldb, "Too many results"); 1575 return ldb_module_done(ac->req, NULL, NULL, 1576 LDB_ERR_OPERATIONS_ERROR); 1577 } 1578 1579 data = talloc_zero(ac, struct domain_data); 1580 if (data == NULL) { 1581 return ldb_module_done(ac->req, NULL, NULL, 1582 LDB_ERR_OPERATIONS_ERROR); 1583 } 1584 1585 data->pwdProperties = samdb_result_uint(ares->message, "pwdProperties", 0); 1586 data->store_cleartext = data->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT; 1587 data->pwdHistoryLength = samdb_result_uint(ares->message, "pwdHistoryLength", 0); 1588 1589 /* For a domain DN, this puts things in dotted notation */ 1590 /* For builtin domains, this will give details for the host, 1591 * but that doesn't really matter, as it's just used for salt 1592 * and kerberos principals, which don't exist here */ 1593 1594 tmp = ldb_dn_canonical_string(data, ares->message->dn); 1595 if (!tmp) { 1596 return ldb_module_done(ac->req, NULL, NULL, 1597 LDB_ERR_OPERATIONS_ERROR); 1598 } 1599 1600 /* But it puts a trailing (or just before 'builtin') / on things, so kill that */ 1601 p = strchr(tmp, '/'); 1602 if (p) { 1603 p[0] = '\0'; 1604 } 1605 1606 data->dns_domain = strlower_talloc(data, tmp); 1607 if (data->dns_domain == NULL) { 1608 ldb_oom(ldb); 1609 return ldb_module_done(ac->req, NULL, NULL, 1610 LDB_ERR_OPERATIONS_ERROR); 1611 } 1612 data->realm = strupper_talloc(data, tmp); 1613 if (data->realm == NULL) { 1614 ldb_oom(ldb); 1615 return ldb_module_done(ac->req, NULL, NULL, 1616 LDB_ERR_OPERATIONS_ERROR); 1617 } 1618 /* FIXME: NetbIOS name is *always* the first domain component ?? -SSS */ 1619 p = strchr(tmp, '.'); 1620 if (p) { 1621 p[0] = '\0'; 1622 } 1623 data->netbios_domain = strupper_talloc(data, tmp); 1624 if (data->netbios_domain == NULL) { 1625 ldb_oom(ldb); 1626 return ldb_module_done(ac->req, NULL, NULL, 1627 LDB_ERR_OPERATIONS_ERROR); 1628 } 1629 1630 talloc_free(tmp); 1631 ac->domain = data; 1632 break; 1633 1634 case LDB_REPLY_DONE: 1635 1636 /* call the next step */ 1637 switch (ac->req->operation) { 1638 case LDB_ADD: 1639 ret = password_hash_add_do_add(ac); 1640 break; 1641 1642 case LDB_MODIFY: 1643 ret = password_hash_mod_do_mod(ac); 1644 break; 1645 1646 default: 1647 ret = LDB_ERR_OPERATIONS_ERROR; 1648 break; 1649 } 1650 if (ret != LDB_SUCCESS) { 1651 return ldb_module_done(ac->req, NULL, NULL, ret); 1652 } 1653 break; 1654 1655 case LDB_REPLY_REFERRAL: 1656 /* ignore */ 1657 break; 1658 } 1659 1660 talloc_free(ares); 1661 return LDB_SUCCESS; 1662} 1663 1664static int build_domain_data_request(struct ph_context *ac) 1665{ 1666 /* attrs[] is returned from this function in 1667 ac->dom_req->op.search.attrs, so it must be static, as 1668 otherwise the compiler can put it on the stack */ 1669 struct ldb_context *ldb; 1670 static const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", NULL }; 1671 char *filter; 1672 1673 ldb = ldb_module_get_ctx(ac->module); 1674 1675 filter = talloc_asprintf(ac, 1676 "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))", 1677 ldap_encode_ndr_dom_sid(ac, ac->domain_sid)); 1678 if (filter == NULL) { 1679 ldb_oom(ldb); 1680 return LDB_ERR_OPERATIONS_ERROR; 1681 } 1682 1683 return ldb_build_search_req(&ac->dom_req, ldb, ac, 1684 ldb_get_default_basedn(ldb), 1685 LDB_SCOPE_SUBTREE, 1686 filter, attrs, 1687 NULL, 1688 ac, get_domain_data_callback, 1689 ac->req); 1690} 1691 1692static int password_hash_add(struct ldb_module *module, struct ldb_request *req) 1693{ 1694 struct ldb_context *ldb; 1695 struct ph_context *ac; 1696 struct ldb_message_element *sambaAttr; 1697 struct ldb_message_element *clearTextPasswordAttr; 1698 struct ldb_message_element *ntAttr; 1699 struct ldb_message_element *lmAttr; 1700 int ret; 1701 1702 ldb = ldb_module_get_ctx(module); 1703 1704 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_add\n"); 1705 1706 if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */ 1707 return ldb_next_request(module, req); 1708 } 1709 1710 /* If the caller is manipulating the local passwords directly, let them pass */ 1711 if (ldb_dn_compare_base(ldb_dn_new(req, ldb, LOCAL_BASE), 1712 req->op.add.message->dn) == 0) { 1713 return ldb_next_request(module, req); 1714 } 1715 1716 /* nobody must touch these fields */ 1717 if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) { 1718 return LDB_ERR_UNWILLING_TO_PERFORM; 1719 } 1720 if (ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) { 1721 return LDB_ERR_UNWILLING_TO_PERFORM; 1722 } 1723 if (ldb_msg_find_element(req->op.add.message, "supplementalCredentials")) { 1724 return LDB_ERR_UNWILLING_TO_PERFORM; 1725 } 1726 1727 /* If no part of this ADD touches the userPassword, or the NT 1728 * or LM hashes, then we don't need to make any changes. */ 1729 1730 sambaAttr = ldb_msg_find_element(req->op.mod.message, "userPassword"); 1731 clearTextPasswordAttr = ldb_msg_find_element(req->op.mod.message, "clearTextPassword"); 1732 ntAttr = ldb_msg_find_element(req->op.mod.message, "unicodePwd"); 1733 lmAttr = ldb_msg_find_element(req->op.mod.message, "dBCSPwd"); 1734 1735 if ((!sambaAttr) && (!clearTextPasswordAttr) && (!ntAttr) && (!lmAttr)) { 1736 return ldb_next_request(module, req); 1737 } 1738 1739 /* if it is not an entry of type person its an error */ 1740 /* TODO: remove this when userPassword will be in schema */ 1741 if (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "person")) { 1742 ldb_set_errstring(ldb, "Cannot set a password on entry that does not have objectClass 'person'"); 1743 return LDB_ERR_OBJECT_CLASS_VIOLATION; 1744 } 1745 1746 /* check userPassword is single valued here */ 1747 /* TODO: remove this when userPassword will be single valued in schema */ 1748 if (sambaAttr && sambaAttr->num_values > 1) { 1749 ldb_set_errstring(ldb, "mupltiple values for userPassword not allowed!\n"); 1750 return LDB_ERR_CONSTRAINT_VIOLATION; 1751 } 1752 if (clearTextPasswordAttr && clearTextPasswordAttr->num_values > 1) { 1753 ldb_set_errstring(ldb, "mupltiple values for clearTextPassword not allowed!\n"); 1754 return LDB_ERR_CONSTRAINT_VIOLATION; 1755 } 1756 1757 if (ntAttr && (ntAttr->num_values > 1)) { 1758 ldb_set_errstring(ldb, "mupltiple values for unicodePwd not allowed!\n"); 1759 return LDB_ERR_CONSTRAINT_VIOLATION; 1760 } 1761 if (lmAttr && (lmAttr->num_values > 1)) { 1762 ldb_set_errstring(ldb, "mupltiple values for dBCSPwd not allowed!\n"); 1763 return LDB_ERR_CONSTRAINT_VIOLATION; 1764 } 1765 1766 if (sambaAttr && sambaAttr->num_values == 0) { 1767 ldb_set_errstring(ldb, "userPassword must have a value!\n"); 1768 return LDB_ERR_CONSTRAINT_VIOLATION; 1769 } 1770 1771 if (clearTextPasswordAttr && clearTextPasswordAttr->num_values == 0) { 1772 ldb_set_errstring(ldb, "clearTextPassword must have a value!\n"); 1773 return LDB_ERR_CONSTRAINT_VIOLATION; 1774 } 1775 1776 if (ntAttr && (ntAttr->num_values == 0)) { 1777 ldb_set_errstring(ldb, "unicodePwd must have a value!\n"); 1778 return LDB_ERR_CONSTRAINT_VIOLATION; 1779 } 1780 if (lmAttr && (lmAttr->num_values == 0)) { 1781 ldb_set_errstring(ldb, "dBCSPwd must have a value!\n"); 1782 return LDB_ERR_CONSTRAINT_VIOLATION; 1783 } 1784 1785 ac = ph_init_context(module, req); 1786 if (ac == NULL) { 1787 return LDB_ERR_OPERATIONS_ERROR; 1788 } 1789 1790 /* get user domain data */ 1791 ac->domain_sid = samdb_result_sid_prefix(ac, req->op.add.message, "objectSid"); 1792 if (ac->domain_sid == NULL) { 1793 ldb_debug(ldb, LDB_DEBUG_ERROR, 1794 "can't handle entry with missing objectSid!\n"); 1795 return LDB_ERR_OPERATIONS_ERROR; 1796 } 1797 1798 ret = build_domain_data_request(ac); 1799 if (ret != LDB_SUCCESS) { 1800 return ret; 1801 } 1802 1803 return ldb_next_request(module, ac->dom_req); 1804} 1805 1806static int password_hash_add_do_add(struct ph_context *ac) 1807{ 1808 struct ldb_context *ldb; 1809 struct ldb_request *down_req; 1810 struct ldb_message *msg; 1811 struct setup_password_fields_io io; 1812 int ret; 1813 1814 /* Prepare the internal data structure containing the passwords */ 1815 ret = setup_io(ac, ac->req->op.add.message, ac->req->op.add.message, &io); 1816 if (ret != LDB_SUCCESS) { 1817 return ret; 1818 } 1819 1820 msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message); 1821 if (msg == NULL) { 1822 return LDB_ERR_OPERATIONS_ERROR; 1823 } 1824 1825 /* remove attributes that we just read into 'io' */ 1826 ldb_msg_remove_attr(msg, "userPassword"); 1827 ldb_msg_remove_attr(msg, "clearTextPassword"); 1828 ldb_msg_remove_attr(msg, "unicodePwd"); 1829 ldb_msg_remove_attr(msg, "dBCSPwd"); 1830 ldb_msg_remove_attr(msg, "pwdLastSet"); 1831 io.o.kvno = samdb_result_uint(msg, "msDs-KeyVersionNumber", 1) - 1; 1832 ldb_msg_remove_attr(msg, "msDs-KeyVersionNumber"); 1833 1834 ldb = ldb_module_get_ctx(ac->module); 1835 1836 ret = setup_password_fields(&io); 1837 if (ret != LDB_SUCCESS) { 1838 return ret; 1839 } 1840 1841 if (io.g.nt_hash) { 1842 ret = samdb_msg_add_hash(ldb, ac, msg, 1843 "unicodePwd", io.g.nt_hash); 1844 if (ret != LDB_SUCCESS) { 1845 return ret; 1846 } 1847 } 1848 if (io.g.lm_hash) { 1849 ret = samdb_msg_add_hash(ldb, ac, msg, 1850 "dBCSPwd", io.g.lm_hash); 1851 if (ret != LDB_SUCCESS) { 1852 return ret; 1853 } 1854 } 1855 if (io.g.nt_history_len > 0) { 1856 ret = samdb_msg_add_hashes(ac, msg, 1857 "ntPwdHistory", 1858 io.g.nt_history, 1859 io.g.nt_history_len); 1860 if (ret != LDB_SUCCESS) { 1861 return ret; 1862 } 1863 } 1864 if (io.g.lm_history_len > 0) { 1865 ret = samdb_msg_add_hashes(ac, msg, 1866 "lmPwdHistory", 1867 io.g.lm_history, 1868 io.g.lm_history_len); 1869 if (ret != LDB_SUCCESS) { 1870 return ret; 1871 } 1872 } 1873 if (io.g.supplemental.length > 0) { 1874 ret = ldb_msg_add_value(msg, "supplementalCredentials", 1875 &io.g.supplemental, NULL); 1876 if (ret != LDB_SUCCESS) { 1877 return ret; 1878 } 1879 } 1880 ret = samdb_msg_add_uint64(ldb, ac, msg, 1881 "pwdLastSet", 1882 io.g.last_set); 1883 if (ret != LDB_SUCCESS) { 1884 return ret; 1885 } 1886 ret = samdb_msg_add_uint(ldb, ac, msg, 1887 "msDs-KeyVersionNumber", 1888 io.g.kvno); 1889 if (ret != LDB_SUCCESS) { 1890 return ret; 1891 } 1892 1893 ret = ldb_build_add_req(&down_req, ldb, ac, 1894 msg, 1895 ac->req->controls, 1896 ac, ph_op_callback, 1897 ac->req); 1898 if (ret != LDB_SUCCESS) { 1899 return ret; 1900 } 1901 1902 return ldb_next_request(ac->module, down_req); 1903} 1904 1905static int password_hash_modify(struct ldb_module *module, struct ldb_request *req) 1906{ 1907 struct ldb_context *ldb; 1908 struct ph_context *ac; 1909 struct ldb_message_element *sambaAttr; 1910 struct ldb_message_element *clearTextAttr; 1911 struct ldb_message_element *ntAttr; 1912 struct ldb_message_element *lmAttr; 1913 struct ldb_message *msg; 1914 struct ldb_request *down_req; 1915 int ret; 1916 1917 ldb = ldb_module_get_ctx(module); 1918 1919 ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_modify\n"); 1920 1921 if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */ 1922 return ldb_next_request(module, req); 1923 } 1924 1925 /* If the caller is manipulating the local passwords directly, let them pass */ 1926 if (ldb_dn_compare_base(ldb_dn_new(req, ldb, LOCAL_BASE), 1927 req->op.mod.message->dn) == 0) { 1928 return ldb_next_request(module, req); 1929 } 1930 1931 /* nobody must touch password Histories */ 1932 if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) { 1933 return LDB_ERR_UNWILLING_TO_PERFORM; 1934 } 1935 if (ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) { 1936 return LDB_ERR_UNWILLING_TO_PERFORM; 1937 } 1938 if (ldb_msg_find_element(req->op.add.message, "supplementalCredentials")) { 1939 return LDB_ERR_UNWILLING_TO_PERFORM; 1940 } 1941 1942 sambaAttr = ldb_msg_find_element(req->op.mod.message, "userPassword"); 1943 clearTextAttr = ldb_msg_find_element(req->op.mod.message, "clearTextPassword"); 1944 ntAttr = ldb_msg_find_element(req->op.mod.message, "unicodePwd"); 1945 lmAttr = ldb_msg_find_element(req->op.mod.message, "dBCSPwd"); 1946 1947 /* If no part of this touches the userPassword OR 1948 * clearTextPassword OR unicodePwd and/or dBCSPwd, then we 1949 * don't need to make any changes. For password changes/set 1950 * there should be a 'delete' or a 'modify' on this 1951 * attribute. */ 1952 if ((!sambaAttr) && (!clearTextAttr) && (!ntAttr) && (!lmAttr)) { 1953 return ldb_next_request(module, req); 1954 } 1955 1956 /* check passwords are single valued here */ 1957 /* TODO: remove this when passwords will be single valued in schema */ 1958 if (sambaAttr && (sambaAttr->num_values > 1)) { 1959 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb))); 1960 return LDB_ERR_CONSTRAINT_VIOLATION; 1961 } 1962 if (clearTextAttr && (clearTextAttr->num_values > 1)) { 1963 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb))); 1964 return LDB_ERR_CONSTRAINT_VIOLATION; 1965 } 1966 if (ntAttr && (ntAttr->num_values > 1)) { 1967 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb))); 1968 return LDB_ERR_CONSTRAINT_VIOLATION; 1969 } 1970 if (lmAttr && (lmAttr->num_values > 1)) { 1971 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb))); 1972 return LDB_ERR_CONSTRAINT_VIOLATION; 1973 } 1974 1975 ac = ph_init_context(module, req); 1976 if (!ac) { 1977 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb))); 1978 return LDB_ERR_OPERATIONS_ERROR; 1979 } 1980 1981 /* use a new message structure so that we can modify it */ 1982 msg = ldb_msg_copy_shallow(ac, req->op.mod.message); 1983 if (msg == NULL) { 1984 ldb_oom(ldb); 1985 return LDB_ERR_OPERATIONS_ERROR; 1986 } 1987 1988 /* - remove any modification to the password from the first commit 1989 * we will make the real modification later */ 1990 if (sambaAttr) ldb_msg_remove_attr(msg, "userPassword"); 1991 if (clearTextAttr) ldb_msg_remove_attr(msg, "clearTextPassword"); 1992 if (ntAttr) ldb_msg_remove_attr(msg, "unicodePwd"); 1993 if (lmAttr) ldb_msg_remove_attr(msg, "dBCSPwd"); 1994 1995 /* if there was nothing else to be modified skip to next step */ 1996 if (msg->num_elements == 0) { 1997 return password_hash_mod_search_self(ac); 1998 } 1999 2000 ret = ldb_build_mod_req(&down_req, ldb, ac, 2001 msg, 2002 req->controls, 2003 ac, ph_modify_callback, 2004 req); 2005 if (ret != LDB_SUCCESS) { 2006 return ret; 2007 } 2008 2009 return ldb_next_request(module, down_req); 2010} 2011 2012static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares) 2013{ 2014 struct ph_context *ac; 2015 int ret; 2016 2017 ac = talloc_get_type(req->context, struct ph_context); 2018 2019 if (!ares) { 2020 return ldb_module_done(ac->req, NULL, NULL, 2021 LDB_ERR_OPERATIONS_ERROR); 2022 } 2023 if (ares->error != LDB_SUCCESS) { 2024 return ldb_module_done(ac->req, ares->controls, 2025 ares->response, ares->error); 2026 } 2027 2028 if (ares->type != LDB_REPLY_DONE) { 2029 talloc_free(ares); 2030 return ldb_module_done(ac->req, NULL, NULL, 2031 LDB_ERR_OPERATIONS_ERROR); 2032 } 2033 2034 ret = password_hash_mod_search_self(ac); 2035 if (ret != LDB_SUCCESS) { 2036 return ldb_module_done(ac->req, NULL, NULL, ret); 2037 } 2038 2039 talloc_free(ares); 2040 return LDB_SUCCESS; 2041} 2042 2043static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares) 2044{ 2045 struct ldb_context *ldb; 2046 struct ph_context *ac; 2047 int ret; 2048 2049 ac = talloc_get_type(req->context, struct ph_context); 2050 ldb = ldb_module_get_ctx(ac->module); 2051 2052 if (!ares) { 2053 return ldb_module_done(ac->req, NULL, NULL, 2054 LDB_ERR_OPERATIONS_ERROR); 2055 } 2056 if (ares->error != LDB_SUCCESS) { 2057 return ldb_module_done(ac->req, ares->controls, 2058 ares->response, ares->error); 2059 } 2060 2061 /* we are interested only in the single reply (base search) */ 2062 switch (ares->type) { 2063 case LDB_REPLY_ENTRY: 2064 2065 if (ac->search_res != NULL) { 2066 ldb_set_errstring(ldb, "Too many results"); 2067 talloc_free(ares); 2068 return ldb_module_done(ac->req, NULL, NULL, 2069 LDB_ERR_OPERATIONS_ERROR); 2070 } 2071 2072 /* if it is not an entry of type person this is an error */ 2073 /* TODO: remove this when sambaPassword will be in schema */ 2074 if (!ldb_msg_check_string_attribute(ares->message, "objectClass", "person")) { 2075 ldb_set_errstring(ldb, "Object class violation"); 2076 talloc_free(ares); 2077 return ldb_module_done(ac->req, NULL, NULL, 2078 LDB_ERR_OBJECT_CLASS_VIOLATION); 2079 } 2080 2081 ac->search_res = talloc_steal(ac, ares); 2082 return LDB_SUCCESS; 2083 2084 case LDB_REPLY_DONE: 2085 2086 /* get object domain sid */ 2087 ac->domain_sid = samdb_result_sid_prefix(ac, 2088 ac->search_res->message, 2089 "objectSid"); 2090 if (ac->domain_sid == NULL) { 2091 ldb_debug(ldb, LDB_DEBUG_ERROR, 2092 "can't handle entry without objectSid!\n"); 2093 return ldb_module_done(ac->req, NULL, NULL, 2094 LDB_ERR_OPERATIONS_ERROR); 2095 } 2096 2097 /* get user domain data */ 2098 ret = build_domain_data_request(ac); 2099 if (ret != LDB_SUCCESS) { 2100 return ldb_module_done(ac->req, NULL, NULL,ret); 2101 } 2102 2103 return ldb_next_request(ac->module, ac->dom_req); 2104 2105 case LDB_REPLY_REFERRAL: 2106 /*ignore anything else for now */ 2107 break; 2108 } 2109 2110 talloc_free(ares); 2111 return LDB_SUCCESS; 2112} 2113 2114static int password_hash_mod_search_self(struct ph_context *ac) 2115{ 2116 struct ldb_context *ldb; 2117 static const char * const attrs[] = { "userAccountControl", "lmPwdHistory", 2118 "ntPwdHistory", 2119 "objectSid", "msDS-KeyVersionNumber", 2120 "objectClass", "userPrincipalName", 2121 "sAMAccountName", 2122 "dBCSPwd", "unicodePwd", 2123 "supplementalCredentials", 2124 NULL }; 2125 struct ldb_request *search_req; 2126 int ret; 2127 2128 ldb = ldb_module_get_ctx(ac->module); 2129 2130 ret = ldb_build_search_req(&search_req, ldb, ac, 2131 ac->req->op.mod.message->dn, 2132 LDB_SCOPE_BASE, 2133 "(objectclass=*)", 2134 attrs, 2135 NULL, 2136 ac, ph_mod_search_callback, 2137 ac->req); 2138 2139 if (ret != LDB_SUCCESS) { 2140 return ret; 2141 } 2142 2143 return ldb_next_request(ac->module, search_req); 2144} 2145 2146static int password_hash_mod_do_mod(struct ph_context *ac) 2147{ 2148 struct ldb_context *ldb; 2149 struct ldb_request *mod_req; 2150 struct ldb_message *msg; 2151 const struct ldb_message *searched_msg; 2152 struct setup_password_fields_io io; 2153 int ret; 2154 2155 ldb = ldb_module_get_ctx(ac->module); 2156 2157 /* use a new message structure so that we can modify it */ 2158 msg = ldb_msg_new(ac); 2159 if (msg == NULL) { 2160 return LDB_ERR_OPERATIONS_ERROR; 2161 } 2162 2163 /* modify dn */ 2164 msg->dn = ac->req->op.mod.message->dn; 2165 2166 /* Prepare the internal data structure containing the passwords */ 2167 ret = setup_io(ac, 2168 ac->req->op.mod.message, 2169 ac->search_res->message, 2170 &io); 2171 if (ret != LDB_SUCCESS) { 2172 return ret; 2173 } 2174 2175 searched_msg = ac->search_res->message; 2176 2177 /* Fill in some final details (only relevent once the password has been set) */ 2178 io.o.kvno = samdb_result_uint(searched_msg, "msDs-KeyVersionNumber", 0); 2179 io.o.nt_history_len = samdb_result_hashes(io.ac, searched_msg, "ntPwdHistory", &io.o.nt_history); 2180 io.o.lm_history_len = samdb_result_hashes(io.ac, searched_msg, "lmPwdHistory", &io.o.lm_history); 2181 io.o.supplemental = ldb_msg_find_ldb_val(searched_msg, "supplementalCredentials"); 2182 2183 ret = setup_password_fields(&io); 2184 if (ret != LDB_SUCCESS) { 2185 return ret; 2186 } 2187 2188 /* make sure we replace all the old attributes */ 2189 ret = ldb_msg_add_empty(msg, "unicodePwd", LDB_FLAG_MOD_REPLACE, NULL); 2190 ret = ldb_msg_add_empty(msg, "dBCSPwd", LDB_FLAG_MOD_REPLACE, NULL); 2191 ret = ldb_msg_add_empty(msg, "ntPwdHistory", LDB_FLAG_MOD_REPLACE, NULL); 2192 ret = ldb_msg_add_empty(msg, "lmPwdHistory", LDB_FLAG_MOD_REPLACE, NULL); 2193 ret = ldb_msg_add_empty(msg, "supplementalCredentials", LDB_FLAG_MOD_REPLACE, NULL); 2194 ret = ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE, NULL); 2195 ret = ldb_msg_add_empty(msg, "msDs-KeyVersionNumber", LDB_FLAG_MOD_REPLACE, NULL); 2196 2197 if (io.g.nt_hash) { 2198 ret = samdb_msg_add_hash(ldb, ac, msg, 2199 "unicodePwd", io.g.nt_hash); 2200 if (ret != LDB_SUCCESS) { 2201 return ret; 2202 } 2203 } 2204 if (io.g.lm_hash) { 2205 ret = samdb_msg_add_hash(ldb, ac, msg, 2206 "dBCSPwd", io.g.lm_hash); 2207 if (ret != LDB_SUCCESS) { 2208 return ret; 2209 } 2210 } 2211 if (io.g.nt_history_len > 0) { 2212 ret = samdb_msg_add_hashes(ac, msg, 2213 "ntPwdHistory", 2214 io.g.nt_history, 2215 io.g.nt_history_len); 2216 if (ret != LDB_SUCCESS) { 2217 return ret; 2218 } 2219 } 2220 if (io.g.lm_history_len > 0) { 2221 ret = samdb_msg_add_hashes(ac, msg, 2222 "lmPwdHistory", 2223 io.g.lm_history, 2224 io.g.lm_history_len); 2225 if (ret != LDB_SUCCESS) { 2226 return ret; 2227 } 2228 } 2229 if (io.g.supplemental.length > 0) { 2230 ret = ldb_msg_add_value(msg, "supplementalCredentials", 2231 &io.g.supplemental, NULL); 2232 if (ret != LDB_SUCCESS) { 2233 return ret; 2234 } 2235 } 2236 ret = samdb_msg_add_uint64(ldb, ac, msg, 2237 "pwdLastSet", 2238 io.g.last_set); 2239 if (ret != LDB_SUCCESS) { 2240 return ret; 2241 } 2242 ret = samdb_msg_add_uint(ldb, ac, msg, 2243 "msDs-KeyVersionNumber", 2244 io.g.kvno); 2245 if (ret != LDB_SUCCESS) { 2246 return ret; 2247 } 2248 2249 ret = ldb_build_mod_req(&mod_req, ldb, ac, 2250 msg, 2251 ac->req->controls, 2252 ac, ph_op_callback, 2253 ac->req); 2254 if (ret != LDB_SUCCESS) { 2255 return ret; 2256 } 2257 2258 return ldb_next_request(ac->module, mod_req); 2259} 2260 2261_PUBLIC_ const struct ldb_module_ops ldb_password_hash_module_ops = { 2262 .name = "password_hash", 2263 .add = password_hash_add, 2264 .modify = password_hash_modify, 2265}; 2266