Changeset 745 for trunk/server/source4/rpc_server/samr
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source4/rpc_server/samr/dcesrv_samr.c
r414 r745 1 /* 1 /* 2 2 Unix SMB/CIFS implementation. 3 3 … … 8 8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 9 9 Copyright (C) Matthias Dieter Wallnöfer 2009 10 10 11 11 This program is free software; you can redistribute it and/or modify 12 12 it under the terms of the GNU General Public License as published by 13 13 the Free Software Foundation; either version 3 of the License, or 14 14 (at your option) any later version. 15 15 16 16 This program is distributed in the hope that it will be useful, 17 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 19 GNU General Public License for more details. 20 20 21 21 You should have received a copy of the GNU General Public License 22 22 along with this program. If not, see <http://www.gnu.org/licenses/>. … … 29 29 #include "rpc_server/samr/dcesrv_samr.h" 30 30 #include "system/time.h" 31 #include "lib/ldb/include/ldb.h"32 #include "lib/ldb/include/ldb_errors.h"31 #include <ldb.h> 32 #include <ldb_errors.h> 33 33 #include "../libds/common/flags.h" 34 34 #include "dsdb/samdb/samdb.h" 35 #include "dsdb/common/util.h" 35 36 #include "libcli/ldap/ldap_ndr.h" 36 37 #include "libcli/security/security.h" … … 38 39 #include "../lib/util/util_ldb.h" 39 40 #include "param/param.h" 41 #include "lib/util/tsort.h" 42 #include "libds/common/flag_mapping.h" 40 43 41 44 /* these query macros make samr_Query[User|Group|Alias]Info a bit easier to read */ 42 45 43 46 #define QUERY_STRING(msg, field, attr) \ 44 info->field.string = samdb_result_string(msg, attr, "");47 info->field.string = ldb_msg_find_attr_as_string(msg, attr, ""); 45 48 #define QUERY_UINT(msg, field, attr) \ 46 info->field = samdb_result_uint(msg, attr, 0);49 info->field = ldb_msg_find_attr_as_uint(msg, attr, 0); 47 50 #define QUERY_RID(msg, field, attr) \ 48 51 info->field = samdb_result_rid_from_sid(mem_ctx, msg, attr, 0); 49 52 #define QUERY_UINT64(msg, field, attr) \ 50 info->field = samdb_result_uint64(msg, attr, 0);53 info->field = ldb_msg_find_attr_as_uint64(msg, attr, 0); 51 54 #define QUERY_APASSC(msg, field, attr) \ 52 55 info->field = samdb_result_allow_password_change(sam_ctx, mem_ctx, \ … … 69 72 if (r->in.info->field.string == NULL) return NT_STATUS_INVALID_PARAMETER; \ 70 73 if (r->in.info->field.string[0] == '\0') { \ 71 if (ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, NULL) ) { \74 if (ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, NULL) != LDB_SUCCESS) { \ 72 75 return NT_STATUS_NO_MEMORY; \ 73 76 } \ 74 77 } \ 75 if (ldb_msg_add_string(msg, attr, r->in.info->field.string) != 0) { \78 if (ldb_msg_add_string(msg, attr, r->in.info->field.string) != LDB_SUCCESS) { \ 76 79 return NT_STATUS_NO_MEMORY; \ 77 80 } \ … … 82 85 #define SET_UINT(msg, field, attr) do { \ 83 86 struct ldb_message_element *set_el; \ 84 if (samdb_msg_add_uint(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \87 if (samdb_msg_add_uint(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != LDB_SUCCESS) { \ 85 88 return NT_STATUS_NO_MEMORY; \ 86 89 } \ 87 90 set_el = ldb_msg_find_element(msg, attr); \ 88 91 set_el->flags = LDB_FLAG_MOD_REPLACE; \ 89 } while (0) 90 92 } while (0) 93 91 94 #define SET_INT64(msg, field, attr) do { \ 92 95 struct ldb_message_element *set_el; \ 93 if (samdb_msg_add_int64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \96 if (samdb_msg_add_int64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != LDB_SUCCESS) { \ 94 97 return NT_STATUS_NO_MEMORY; \ 95 98 } \ 96 99 set_el = ldb_msg_find_element(msg, attr); \ 97 100 set_el->flags = LDB_FLAG_MOD_REPLACE; \ 98 } while (0) 99 101 } while (0) 102 100 103 #define SET_UINT64(msg, field, attr) do { \ 101 104 struct ldb_message_element *set_el; \ 102 if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \105 if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != LDB_SUCCESS) { \ 103 106 return NT_STATUS_NO_MEMORY; \ 104 107 } \ 105 108 set_el = ldb_msg_find_element(msg, attr); \ 106 109 set_el->flags = LDB_FLAG_MOD_REPLACE; \ 107 } while (0) 110 } while (0) 108 111 109 112 #define CHECK_FOR_MULTIPLES(value, flag, poss_flags) \ … … 113 116 } \ 114 117 } while (0) \ 115 116 /* Set account flags, discarding flags that cannot be set with SAMR */ 118 119 /* Set account flags, discarding flags that cannot be set with SAMR */ 117 120 #define SET_AFLAGS(msg, field, attr) do { \ 118 121 struct ldb_message_element *set_el; \ … … 129 132 set_el = ldb_msg_find_element(msg, attr); \ 130 133 set_el->flags = LDB_FLAG_MOD_REPLACE; \ 131 } while (0) 132 134 } while (0) 135 133 136 #define SET_LHOURS(msg, field, attr) do { \ 134 137 struct ldb_message_element *set_el; \ 135 if (samdb_msg_add_logon_hours(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \138 if (samdb_msg_add_logon_hours(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != LDB_SUCCESS) { \ 136 139 return NT_STATUS_NO_MEMORY; \ 137 140 } \ … … 143 146 struct ldb_message_element *set_el; \ 144 147 if (r->in.info->field.length != 0) { \ 145 if (samdb_msg_add_parameters(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \148 if (samdb_msg_add_parameters(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != LDB_SUCCESS) { \ 146 149 return NT_STATUS_NO_MEMORY; \ 147 150 } \ … … 153 156 154 157 155 /* 156 samr_Connect 158 /* 159 samr_Connect 157 160 158 161 create a connection to the SAM database … … 166 169 ZERO_STRUCTP(r->out.connect_handle); 167 170 168 c_state = talloc( dce_call->conn, struct samr_connect_state);171 c_state = talloc(mem_ctx, struct samr_connect_state); 169 172 if (!c_state) { 170 173 return NT_STATUS_NO_MEMORY; … … 172 175 173 176 /* make sure the sam database is accessible */ 174 c_state->sam_ctx = samdb_connect(c_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info );177 c_state->sam_ctx = samdb_connect(c_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info, 0); 175 178 if (c_state->sam_ctx == NULL) { 176 179 talloc_free(c_state); … … 194 197 195 198 196 /* 197 samr_Close 199 /* 200 samr_Close 198 201 */ 199 202 static NTSTATUS dcesrv_samr_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 214 217 215 218 216 /* 217 samr_SetSecurity 219 /* 220 samr_SetSecurity 218 221 */ 219 222 static NTSTATUS dcesrv_samr_SetSecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 224 227 225 228 226 /* 227 samr_QuerySecurity 229 /* 230 samr_QuerySecurity 228 231 */ 229 232 static NTSTATUS dcesrv_samr_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 250 253 251 254 252 /* 253 samr_Shutdown 255 /* 256 samr_Shutdown 254 257 255 258 we refuse this operation completely. If a admin wants to shutdown samr … … 263 266 264 267 265 /* 266 samr_LookupDomain 268 /* 269 samr_LookupDomain 267 270 268 271 this maps from a domain name to a SID … … 292 295 mem_ctx, NULL, &dom_msgs, dom_attrs, 293 296 "(objectClass=builtinDomain)"); 294 } else if (strcasecmp_m(r->in.domain_name->string, lp _sam_name(dce_call->conn->dce_ctx->lp_ctx)) == 0) {297 } else if (strcasecmp_m(r->in.domain_name->string, lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx)) == 0) { 295 298 ret = gendb_search_dn(c_state->sam_ctx, 296 mem_ctx, ldb_get_default_basedn(c_state->sam_ctx), 299 mem_ctx, ldb_get_default_basedn(c_state->sam_ctx), 297 300 &dom_msgs, dom_attrs); 298 301 } else { … … 302 305 return NT_STATUS_NO_SUCH_DOMAIN; 303 306 } 304 307 305 308 sid = samdb_result_dom_sid(mem_ctx, dom_msgs[0], 306 309 "objectSid"); 307 310 308 311 if (sid == NULL) { 309 312 return NT_STATUS_NO_SUCH_DOMAIN; … … 316 319 317 320 318 /* 319 samr_EnumDomains 321 /* 322 samr_EnumDomains 320 323 321 324 list the domains in the SAM … … 327 330 struct dcesrv_handle *h; 328 331 struct samr_SamArray *array; 329 int i, start_i;332 uint32_t i, start_i; 330 333 331 334 *r->out.resume_handle = 0; … … 350 353 return NT_STATUS_NO_MEMORY; 351 354 } 352 355 353 356 array->count = 0; 354 357 array->entries = NULL; … … 362 365 array->entries[i].idx = start_i + i; 363 366 if (i == 0) { 364 array->entries[i].name.string = lp _sam_name(dce_call->conn->dce_ctx->lp_ctx);367 array->entries[i].name.string = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx); 365 368 } else { 366 369 array->entries[i].name.string = "BUILTIN"; … … 376 379 377 380 378 /* 379 samr_OpenDomain 381 /* 382 samr_OpenDomain 380 383 */ 381 384 static NTSTATUS dcesrv_samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 399 402 } 400 403 401 d_state = talloc( c_state, struct samr_domain_state);404 d_state = talloc(mem_ctx, struct samr_domain_state); 402 405 if (!d_state) { 403 406 return NT_STATUS_NO_MEMORY; … … 411 414 } else { 412 415 d_state->builtin = false; 413 d_state->domain_name = lp _sam_name(dce_call->conn->dce_ctx->lp_ctx);416 d_state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx); 414 417 } 415 418 416 419 ret = gendb_search(c_state->sam_ctx, 417 420 mem_ctx, ldb_get_default_basedn(c_state->sam_ctx), &dom_msgs, dom_attrs, 418 "(objectSid=%s)", 421 "(objectSid=%s)", 419 422 ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid)); 420 423 421 424 if (ret == 0) { 422 425 talloc_free(d_state); … … 432 435 433 436 d_state->domain_dn = talloc_steal(d_state, dom_msgs[0]->dn); 434 d_state->role = lp _server_role(dce_call->conn->dce_ctx->lp_ctx);437 d_state->role = lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx); 435 438 d_state->connect_state = talloc_reference(d_state, c_state); 436 439 d_state->sam_ctx = c_state->sam_ctx; … … 444 447 return NT_STATUS_NO_MEMORY; 445 448 } 446 449 447 450 h_domain->data = talloc_steal(h_domain, d_state); 448 451 … … 456 459 */ 457 460 static NTSTATUS dcesrv_samr_info_DomInfo1(struct samr_domain_state *state, 458 459 460 461 TALLOC_CTX *mem_ctx, 462 struct ldb_message **dom_msgs, 463 struct samr_DomInfo1 *info) 461 464 { 462 465 info->min_password_length = 463 samdb_result_uint(dom_msgs[0], "minPwdLength", 0);466 ldb_msg_find_attr_as_uint(dom_msgs[0], "minPwdLength", 0); 464 467 info->password_history_length = 465 samdb_result_uint(dom_msgs[0], "pwdHistoryLength", 0);466 info->password_properties = 467 samdb_result_uint(dom_msgs[0], "pwdProperties", 0);468 info->max_password_age = 469 samdb_result_int64(dom_msgs[0], "maxPwdAge", 0);470 info->min_password_age = 471 samdb_result_int64(dom_msgs[0], "minPwdAge", 0);468 ldb_msg_find_attr_as_uint(dom_msgs[0], "pwdHistoryLength", 0); 469 info->password_properties = 470 ldb_msg_find_attr_as_uint(dom_msgs[0], "pwdProperties", 0); 471 info->max_password_age = 472 ldb_msg_find_attr_as_int64(dom_msgs[0], "maxPwdAge", 0); 473 info->min_password_age = 474 ldb_msg_find_attr_as_int64(dom_msgs[0], "minPwdAge", 0); 472 475 473 476 return NT_STATUS_OK; … … 477 480 return DomInfo2 478 481 */ 479 static NTSTATUS dcesrv_samr_info_DomGeneralInformation(struct samr_domain_state *state, 482 static NTSTATUS dcesrv_samr_info_DomGeneralInformation(struct samr_domain_state *state, 480 483 TALLOC_CTX *mem_ctx, 481 484 struct ldb_message **dom_msgs, 482 485 struct samr_DomGeneralInformation *info) 483 486 { 484 /* This pulls the NetBIOS name from the 485 cn=NTDS Settings,cn=<NETBIOS name of PDC>,.... 486 string */ 487 info->primary.string = samdb_result_fsmo_name(state->sam_ctx, mem_ctx, dom_msgs[0], "fSMORoleOwner"); 488 489 if (!info->primary.string) { 490 info->primary.string = lp_netbios_name(state->lp_ctx); 491 } 492 493 info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff", 487 /* MS-SAMR 2.2.4.1 - ReplicaSourceNodeName: "domainReplica" attribute */ 488 info->primary.string = ldb_msg_find_attr_as_string(dom_msgs[0], 489 "domainReplica", 490 ""); 491 492 info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff", 494 493 0x8000000000000000LL); 495 494 496 info->oem_information.string = samdb_result_string(dom_msgs[0], "oEMInformation", NULL); 495 info->oem_information.string = ldb_msg_find_attr_as_string(dom_msgs[0], 496 "oEMInformation", 497 ""); 497 498 info->domain_name.string = state->domain_name; 498 499 499 info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", 500 info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", 500 501 0); 501 502 switch (state->role) { 502 503 case ROLE_DOMAIN_CONTROLLER: 503 /* This pulls the NetBIOS name from the 504 /* This pulls the NetBIOS name from the 504 505 cn=NTDS Settings,cn=<NETBIOS name of PDC>,.... 505 506 string */ … … 518 519 } 519 520 520 /* No users in BUILTIN, and the LOCAL group types are only in builtin, and the global group type is never in BUILTIN */521 info->num_users = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn,521 info->num_users = samdb_search_count(state->sam_ctx, mem_ctx, 522 state->domain_dn, 522 523 "(objectClass=user)"); 523 info->num_groups = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn, 524 "(&(objectClass=group)(sAMAccountType=%u))", 525 ATYPE_GLOBAL_GROUP); 526 info->num_aliases = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn, 527 "(&(objectClass=group)(sAMAccountType=%u))", 528 ATYPE_LOCAL_GROUP); 524 info->num_groups = samdb_search_count(state->sam_ctx, mem_ctx, 525 state->domain_dn, 526 "(&(objectClass=group)(|(groupType=%d)(groupType=%d)))", 527 GTYPE_SECURITY_UNIVERSAL_GROUP, 528 GTYPE_SECURITY_GLOBAL_GROUP); 529 info->num_aliases = samdb_search_count(state->sam_ctx, mem_ctx, 530 state->domain_dn, 531 "(&(objectClass=group)(|(groupType=%d)(groupType=%d)))", 532 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, 533 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP); 529 534 530 535 return NT_STATUS_OK; … … 535 540 */ 536 541 static NTSTATUS dcesrv_samr_info_DomInfo3(struct samr_domain_state *state, 537 538 539 540 { 541 info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff", 542 TALLOC_CTX *mem_ctx, 543 struct ldb_message **dom_msgs, 544 struct samr_DomInfo3 *info) 545 { 546 info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff", 542 547 0x8000000000000000LL); 543 548 … … 553 558 struct samr_DomOEMInformation *info) 554 559 { 555 info->oem_information.string = samdb_result_string(dom_msgs[0], "oEMInformation", NULL); 560 info->oem_information.string = ldb_msg_find_attr_as_string(dom_msgs[0], 561 "oEMInformation", 562 ""); 556 563 557 564 return NT_STATUS_OK; … … 562 569 */ 563 570 static NTSTATUS dcesrv_samr_info_DomInfo5(struct samr_domain_state *state, 564 565 566 571 TALLOC_CTX *mem_ctx, 572 struct ldb_message **dom_msgs, 573 struct samr_DomInfo5 *info) 567 574 { 568 575 info->domain_name.string = state->domain_name; … … 575 582 */ 576 583 static NTSTATUS dcesrv_samr_info_DomInfo6(struct samr_domain_state *state, 577 TALLOC_CTX *mem_ctx, 578 struct ldb_message **dom_msgs, 579 struct samr_DomInfo6 *info) 580 { 581 /* This pulls the NetBIOS name from the 582 cn=NTDS Settings,cn=<NETBIOS name of PDC>,.... 583 string */ 584 info->primary.string = samdb_result_fsmo_name(state->sam_ctx, mem_ctx, 585 dom_msgs[0], "fSMORoleOwner"); 586 587 if (!info->primary.string) { 588 info->primary.string = lp_netbios_name(state->lp_ctx); 589 } 584 TALLOC_CTX *mem_ctx, 585 struct ldb_message **dom_msgs, 586 struct samr_DomInfo6 *info) 587 { 588 /* MS-SAMR 2.2.4.1 - ReplicaSourceNodeName: "domainReplica" attribute */ 589 info->primary.string = ldb_msg_find_attr_as_string(dom_msgs[0], 590 "domainReplica", 591 ""); 590 592 591 593 return NT_STATUS_OK; … … 596 598 */ 597 599 static NTSTATUS dcesrv_samr_info_DomInfo7(struct samr_domain_state *state, 598 599 600 600 TALLOC_CTX *mem_ctx, 601 struct ldb_message **dom_msgs, 602 struct samr_DomInfo7 *info) 601 603 { 602 604 603 605 switch (state->role) { 604 606 case ROLE_DOMAIN_CONTROLLER: 605 /* This pulls the NetBIOS name from the 607 /* This pulls the NetBIOS name from the 606 608 cn=NTDS Settings,cn=<NETBIOS name of PDC>,.... 607 609 string */ … … 627 629 */ 628 630 static NTSTATUS dcesrv_samr_info_DomInfo8(struct samr_domain_state *state, 629 630 631 632 { 633 info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", 631 TALLOC_CTX *mem_ctx, 632 struct ldb_message **dom_msgs, 633 struct samr_DomInfo8 *info) 634 { 635 info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", 634 636 time(NULL)); 635 637 … … 644 646 */ 645 647 static NTSTATUS dcesrv_samr_info_DomInfo9(struct samr_domain_state *state, 646 647 648 648 TALLOC_CTX *mem_ctx, 649 struct ldb_message **dom_msgs, 650 struct samr_DomInfo9 *info) 649 651 { 650 652 info->domain_server_state = DOMAIN_SERVER_ENABLED; … … 657 659 */ 658 660 static NTSTATUS dcesrv_samr_info_DomGeneralInformation2(struct samr_domain_state *state, 659 660 661 661 TALLOC_CTX *mem_ctx, 662 struct ldb_message **dom_msgs, 663 struct samr_DomGeneralInformation2 *info) 662 664 { 663 665 NTSTATUS status; … … 666 668 return status; 667 669 } 668 669 info->lockout_duration = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutDuration", 670 671 info->lockout_duration = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutDuration", 670 672 -18000000000LL); 671 673 info->lockout_window = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockOutObservationWindow", … … 680 682 */ 681 683 static NTSTATUS dcesrv_samr_info_DomInfo12(struct samr_domain_state *state, 682 TALLOC_CTX *mem_ctx,683 684 struct samr_DomInfo12 *info)685 { 686 info->lockout_duration = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutDuration", 684 TALLOC_CTX *mem_ctx, 685 struct ldb_message **dom_msgs, 686 struct samr_DomInfo12 *info) 687 { 688 info->lockout_duration = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutDuration", 687 689 -18000000000LL); 688 690 info->lockout_window = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockOutObservationWindow", … … 697 699 */ 698 700 static NTSTATUS dcesrv_samr_info_DomInfo13(struct samr_domain_state *state, 699 700 701 702 { 703 info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", 701 TALLOC_CTX *mem_ctx, 702 struct ldb_message **dom_msgs, 703 struct samr_DomInfo13 *info) 704 { 705 info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", 704 706 time(NULL)); 705 707 … … 712 714 } 713 715 714 /* 715 samr_QueryDomainInfo 716 */ 717 static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 718 struct samr_QueryDomainInfo *r) 716 /* 717 samr_QueryDomainInfo 718 */ 719 static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, 720 TALLOC_CTX *mem_ctx, 721 struct samr_QueryDomainInfo *r) 719 722 { 720 723 struct dcesrv_handle *h; … … 724 727 struct ldb_message **dom_msgs; 725 728 const char * const *attrs = NULL; 726 729 727 730 *r->out.info = NULL; 728 731 … … 731 734 d_state = h->data; 732 735 733 info = talloc(mem_ctx, union samr_DomainInfo);734 if (!info) {735 return NT_STATUS_NO_MEMORY;736 }737 738 736 switch (r->in.level) { 739 case 1: 737 case 1: 740 738 { 741 739 static const char * const attrs2[] = { "minPwdLength", … … 751 749 { 752 750 static const char * const attrs2[] = {"forceLogoff", 753 "oEMInformation", 754 "modifiedCount", 755 " fSMORoleOwner",751 "oEMInformation", 752 "modifiedCount", 753 "domainReplica", 756 754 NULL}; 757 755 attrs = attrs2; … … 760 758 case 3: 761 759 { 762 static const char * const attrs2[] = {"forceLogoff", 760 static const char * const attrs2[] = {"forceLogoff", 763 761 NULL}; 764 762 attrs = attrs2; … … 767 765 case 4: 768 766 { 769 static const char * const attrs2[] = {"oEMInformation", 767 static const char * const attrs2[] = {"oEMInformation", 770 768 NULL}; 771 769 attrs = attrs2; … … 779 777 case 6: 780 778 { 781 static const char * const attrs2[] = { "fSMORoleOwner",782 NULL};779 static const char * const attrs2[] = { "domainReplica", 780 NULL }; 783 781 attrs = attrs2; 784 782 break; … … 791 789 case 8: 792 790 { 793 static const char * const attrs2[] = { "modifiedCount", 794 "creationTime", 791 static const char * const attrs2[] = { "modifiedCount", 792 "creationTime", 795 793 NULL }; 796 794 attrs = attrs2; … … 798 796 } 799 797 case 9: 798 { 800 799 attrs = NULL; 801 break; 800 break; 801 } 802 802 case 11: 803 803 { 804 804 static const char * const attrs2[] = { "oEMInformation", 805 805 "forceLogoff", 806 "modifiedCount", 807 "lockoutDuration", 808 "lockOutObservationWindow", 809 "lockoutThreshold", 806 "modifiedCount", 807 "lockoutDuration", 808 "lockOutObservationWindow", 809 "lockoutThreshold", 810 810 NULL}; 811 811 attrs = attrs2; … … 814 814 case 12: 815 815 { 816 static const char * const attrs2[] = { "lockoutDuration", 817 "lockOutObservationWindow", 818 "lockoutThreshold", 816 static const char * const attrs2[] = { "lockoutDuration", 817 "lockOutObservationWindow", 818 "lockoutThreshold", 819 819 NULL}; 820 820 attrs = attrs2; … … 823 823 case 13: 824 824 { 825 static const char * const attrs2[] = { "modifiedCount", 826 "creationTime", 825 static const char * const attrs2[] = { "modifiedCount", 826 "creationTime", 827 827 NULL }; 828 828 attrs = attrs2; 829 829 break; 830 } 831 default: 832 { 833 return NT_STATUS_INVALID_INFO_CLASS; 830 834 } 831 835 } … … 836 840 ret = gendb_search_dn(d_state->sam_ctx, mem_ctx, 837 841 d_state->domain_dn, &dom_msgs, attrs); 842 if (ret == 0) { 843 return NT_STATUS_NO_SUCH_DOMAIN; 844 } 838 845 if (ret != 1) { 839 846 return NT_STATUS_INTERNAL_DB_CORRUPTION; … … 841 848 } 842 849 850 /* allocate the info structure */ 851 info = talloc_zero(mem_ctx, union samr_DomainInfo); 852 if (info == NULL) { 853 return NT_STATUS_NO_MEMORY; 854 } 855 843 856 *r->out.info = info; 844 845 ZERO_STRUCTP(info);846 857 847 858 switch (r->in.level) { 848 859 case 1: 849 return dcesrv_samr_info_DomInfo1(d_state, mem_ctx, dom_msgs, 860 return dcesrv_samr_info_DomInfo1(d_state, mem_ctx, dom_msgs, 850 861 &info->info1); 851 862 case 2: 852 return dcesrv_samr_info_DomGeneralInformation(d_state, mem_ctx, dom_msgs, 863 return dcesrv_samr_info_DomGeneralInformation(d_state, mem_ctx, dom_msgs, 853 864 &info->general); 854 865 case 3: 855 return dcesrv_samr_info_DomInfo3(d_state, mem_ctx, dom_msgs, 866 return dcesrv_samr_info_DomInfo3(d_state, mem_ctx, dom_msgs, 856 867 &info->info3); 857 868 case 4: 858 return dcesrv_samr_info_DomOEMInformation(d_state, mem_ctx, dom_msgs, 869 return dcesrv_samr_info_DomOEMInformation(d_state, mem_ctx, dom_msgs, 859 870 &info->oem); 860 871 case 5: 861 return dcesrv_samr_info_DomInfo5(d_state, mem_ctx, dom_msgs, 872 return dcesrv_samr_info_DomInfo5(d_state, mem_ctx, dom_msgs, 862 873 &info->info5); 863 874 case 6: 864 return dcesrv_samr_info_DomInfo6(d_state, mem_ctx, dom_msgs, 875 return dcesrv_samr_info_DomInfo6(d_state, mem_ctx, dom_msgs, 865 876 &info->info6); 866 877 case 7: 867 return dcesrv_samr_info_DomInfo7(d_state, mem_ctx, dom_msgs, 878 return dcesrv_samr_info_DomInfo7(d_state, mem_ctx, dom_msgs, 868 879 &info->info7); 869 880 case 8: 870 return dcesrv_samr_info_DomInfo8(d_state, mem_ctx, dom_msgs, 881 return dcesrv_samr_info_DomInfo8(d_state, mem_ctx, dom_msgs, 871 882 &info->info8); 872 883 case 9: 873 return dcesrv_samr_info_DomInfo9(d_state, mem_ctx, dom_msgs, 884 return dcesrv_samr_info_DomInfo9(d_state, mem_ctx, dom_msgs, 874 885 &info->info9); 875 886 case 11: 876 return dcesrv_samr_info_DomGeneralInformation2(d_state, mem_ctx, dom_msgs, 887 return dcesrv_samr_info_DomGeneralInformation2(d_state, mem_ctx, dom_msgs, 877 888 &info->general2); 878 889 case 12: 879 return dcesrv_samr_info_DomInfo12(d_state, mem_ctx, dom_msgs, 890 return dcesrv_samr_info_DomInfo12(d_state, mem_ctx, dom_msgs, 880 891 &info->info12); 881 892 case 13: 882 return dcesrv_samr_info_DomInfo13(d_state, mem_ctx, dom_msgs, 893 return dcesrv_samr_info_DomInfo13(d_state, mem_ctx, dom_msgs, 883 894 &info->info13); 884 }885 886 return NT_STATUS_INVALID_INFO_CLASS;887 } 888 889 890 /* 891 samr_SetDomainInfo 895 default: 896 return NT_STATUS_INVALID_INFO_CLASS; 897 } 898 } 899 900 901 /* 902 samr_SetDomainInfo 892 903 */ 893 904 static NTSTATUS dcesrv_samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 937 948 938 949 case 12: 939 950 /* 951 * It is not possible to set lockout_duration < lockout_window. 952 * (The test is the other way around since the negative numbers 953 * are stored...) 954 * 955 * TODO: 956 * This check should be moved to the backend, i.e. to some 957 * ldb module under dsdb/samdb/ldb_modules/ . 958 * 959 * This constraint is documented here for the samr rpc service: 960 * MS-SAMR 3.1.1.6 Attribute Constraints for Originating Updates 961 * http://msdn.microsoft.com/en-us/library/cc245667%28PROT.10%29.aspx 962 * 963 * And here for the ldap backend: 964 * MS-ADTS 3.1.1.5.3.2 Constraints 965 * http://msdn.microsoft.com/en-us/library/cc223462(PROT.10).aspx 966 */ 967 if (r->in.info->info12.lockout_duration > 968 r->in.info->info12.lockout_window) 969 { 970 return NT_STATUS_INVALID_PARAMETER; 971 } 940 972 SET_INT64 (msg, info12.lockout_duration, "lockoutDuration"); 941 973 SET_INT64 (msg, info12.lockout_window, "lockOutObservationWindow"); … … 950 982 /* modify the samdb record */ 951 983 ret = ldb_modify(sam_ctx, msg); 952 if (ret != 0) {984 if (ret != LDB_SUCCESS) { 953 985 DEBUG(1,("Failed to modify record %s: %s\n", 954 986 ldb_dn_get_linearized(d_state->domain_dn), … … 962 994 } 963 995 964 /* 965 samr_CreateDomainGroup 996 /* 997 samr_CreateDomainGroup 966 998 */ 967 999 static NTSTATUS dcesrv_samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 968 1000 struct samr_CreateDomainGroup *r) 969 1001 { 1002 NTSTATUS status; 970 1003 struct samr_domain_state *d_state; 971 1004 struct samr_account_state *a_state; 972 1005 struct dcesrv_handle *h; 973 const char *name;974 struct ldb_message *msg;975 struct dom_sid *sid;976 1006 const char *groupname; 1007 struct dom_sid *group_sid; 1008 struct ldb_dn *group_dn; 977 1009 struct dcesrv_handle *g_handle; 978 int ret;979 1010 980 1011 ZERO_STRUCTP(r->out.group_handle); … … 996 1027 } 997 1028 998 /* check if the group already exists */ 999 name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL, 1000 "sAMAccountName", 1001 "(&(sAMAccountName=%s)(objectclass=group))", 1002 ldb_binary_encode_string(mem_ctx, groupname)); 1003 if (name != NULL) { 1004 return NT_STATUS_GROUP_EXISTS; 1005 } 1006 1007 msg = ldb_msg_new(mem_ctx); 1008 if (msg == NULL) { 1009 return NT_STATUS_NO_MEMORY; 1010 } 1011 1012 /* add core elements to the ldb_message for the user */ 1013 msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn); 1014 ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", groupname); 1015 if (!msg->dn) { 1016 return NT_STATUS_NO_MEMORY; 1017 } 1018 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", groupname); 1019 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "group"); 1020 1021 /* create the group */ 1022 ret = ldb_add(d_state->sam_ctx, msg); 1023 switch (ret) { 1024 case LDB_SUCCESS: 1025 break; 1026 case LDB_ERR_ENTRY_ALREADY_EXISTS: 1027 DEBUG(0,("Failed to create group record %s: %s\n", 1028 ldb_dn_get_linearized(msg->dn), 1029 ldb_errstring(d_state->sam_ctx))); 1030 return NT_STATUS_GROUP_EXISTS; 1031 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: 1032 DEBUG(0,("Failed to create group record %s: %s\n", 1033 ldb_dn_get_linearized(msg->dn), 1034 ldb_errstring(d_state->sam_ctx))); 1035 return NT_STATUS_ACCESS_DENIED; 1036 default: 1037 DEBUG(0,("Failed to create group record %s: %s\n", 1038 ldb_dn_get_linearized(msg->dn), 1039 ldb_errstring(d_state->sam_ctx))); 1040 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1041 } 1042 1043 a_state = talloc(d_state, struct samr_account_state); 1029 status = dsdb_add_domain_group(d_state->sam_ctx, mem_ctx, groupname, &group_sid, &group_dn); 1030 if (!NT_STATUS_IS_OK(status)) { 1031 return status; 1032 } 1033 1034 a_state = talloc(mem_ctx, struct samr_account_state); 1044 1035 if (!a_state) { 1045 1036 return NT_STATUS_NO_MEMORY; … … 1048 1039 a_state->access_mask = r->in.access_mask; 1049 1040 a_state->domain_state = talloc_reference(a_state, d_state); 1050 a_state->account_dn = talloc_steal(a_state, msg->dn); 1051 1052 /* retrieve the sid for the group just created */ 1053 sid = samdb_search_dom_sid(d_state->sam_ctx, a_state, 1054 msg->dn, "objectSid", NULL); 1055 if (sid == NULL) { 1056 return NT_STATUS_UNSUCCESSFUL; 1057 } 1058 1059 a_state->account_name = talloc_strdup(a_state, groupname); 1060 if (!a_state->account_name) { 1061 return NT_STATUS_NO_MEMORY; 1062 } 1041 a_state->account_dn = talloc_steal(a_state, group_dn); 1042 1043 a_state->account_name = talloc_steal(a_state, groupname); 1063 1044 1064 1045 /* create the policy handle */ … … 1071 1052 1072 1053 *r->out.group_handle = g_handle->wire_handle; 1073 *r->out.rid = sid->sub_auths[sid->num_auths-1];1054 *r->out.rid = group_sid->sub_auths[group_sid->num_auths-1]; 1074 1055 1075 1056 return NT_STATUS_OK; … … 1085 1066 } 1086 1067 1087 /* 1088 samr_EnumDomainGroups 1068 /* 1069 samr_EnumDomainGroups 1089 1070 */ 1090 1071 static NTSTATUS dcesrv_samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 1094 1075 struct samr_domain_state *d_state; 1095 1076 struct ldb_message **res; 1096 int ldb_cnt, count, i, first; 1077 int i, ldb_cnt; 1078 uint32_t first, count; 1097 1079 struct samr_SamEntry *entries; 1098 const char * const attrs[ 3] = { "objectSid", "sAMAccountName", NULL };1080 const char * const attrs[] = { "objectSid", "sAMAccountName", NULL }; 1099 1081 struct samr_SamArray *sam; 1100 1082 … … 1112 1094 d_state->domain_dn, &res, attrs, 1113 1095 d_state->domain_sid, 1114 "(&(grouptype=%d)(objectclass=group))", 1096 "(&(|(groupType=%d)(groupType=%d))(objectClass=group))", 1097 GTYPE_SECURITY_UNIVERSAL_GROUP, 1115 1098 GTYPE_SECURITY_GLOBAL_GROUP); 1116 if (ldb_cnt == -1) {1099 if (ldb_cnt < 0) { 1117 1100 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1118 1101 } … … 1131 1114 group_sid = samdb_result_dom_sid(mem_ctx, res[i], 1132 1115 "objectSid"); 1133 if (group_sid == NULL) 1134 continue; 1116 if (group_sid == NULL) { 1117 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1118 } 1135 1119 1136 1120 entries[count].idx = 1137 1121 group_sid->sub_auths[group_sid->num_auths-1]; 1138 1122 entries[count].name.string = 1139 samdb_result_string(res[i], "sAMAccountName", "");1123 ldb_msg_find_attr_as_string(res[i], "sAMAccountName", ""); 1140 1124 count += 1; 1141 1125 } 1142 1126 1143 1127 /* sort the results by rid */ 1144 qsort(entries, count, sizeof(struct samr_SamEntry), 1145 (comparison_fn_t)compare_SamEntry); 1128 TYPESAFE_QSORT(entries, count, compare_SamEntry); 1146 1129 1147 1130 /* find the first entry to return */ … … 1150 1133 first++) ; 1151 1134 1152 /* return the rest, limit by max_size. Note that we 1135 /* return the rest, limit by max_size. Note that we 1153 1136 use the w2k3 element size value of 54 */ 1154 1137 *r->out.num_entries = count - first; … … 1166 1149 *r->out.sam = sam; 1167 1150 1151 if (first == count) { 1152 return NT_STATUS_OK; 1153 } 1154 1168 1155 if (*r->out.num_entries < count - first) { 1169 1156 *r->out.resume_handle = entries[first+*r->out.num_entries-1].idx; … … 1175 1162 1176 1163 1177 /* 1178 samr_CreateUser2 1164 /* 1165 samr_CreateUser2 1179 1166 1180 1167 This call uses transactions to ensure we don't get a new conflicting … … 1185 1172 struct samr_CreateUser2 *r) 1186 1173 { 1174 NTSTATUS status; 1187 1175 struct samr_domain_state *d_state; 1188 1176 struct samr_account_state *a_state; 1189 1177 struct dcesrv_handle *h; 1190 const char *name; 1191 struct ldb_message *msg; 1178 struct ldb_dn *dn; 1192 1179 struct dom_sid *sid; 1180 struct dcesrv_handle *u_handle; 1193 1181 const char *account_name; 1194 struct dcesrv_handle *u_handle;1195 int ret;1196 const char *container, *obj_class=NULL;1197 char *cn_name;1198 int cn_name_len;1199 1200 const char *attrs[] = {1201 "objectSid",1202 "userAccountControl",1203 NULL1204 };1205 1206 uint32_t user_account_control;1207 1208 struct ldb_message **msgs;1209 1182 1210 1183 ZERO_STRUCTP(r->out.user_handle); … … 1229 1202 } 1230 1203 1231 /* 1232 * Start a transaction, so we can query and do a subsequent atomic 1233 * modify 1234 */ 1235 1236 ret = ldb_transaction_start(d_state->sam_ctx); 1237 if (ret != 0) { 1238 DEBUG(0,("Failed to start a transaction for user creation: %s\n", 1239 ldb_errstring(d_state->sam_ctx))); 1240 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1241 } 1242 1243 /* check if the user already exists */ 1244 name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL, 1245 "sAMAccountName", 1246 "(&(sAMAccountName=%s)(objectclass=user))", 1247 ldb_binary_encode_string(mem_ctx, account_name)); 1248 if (name != NULL) { 1249 ldb_transaction_cancel(d_state->sam_ctx); 1250 return NT_STATUS_USER_EXISTS; 1251 } 1252 1253 msg = ldb_msg_new(mem_ctx); 1254 if (msg == NULL) { 1255 ldb_transaction_cancel(d_state->sam_ctx); 1256 return NT_STATUS_NO_MEMORY; 1257 } 1258 1259 cn_name = talloc_strdup(mem_ctx, account_name); 1260 if (!cn_name) { 1261 ldb_transaction_cancel(d_state->sam_ctx); 1262 return NT_STATUS_NO_MEMORY; 1263 } 1264 1265 cn_name_len = strlen(cn_name); 1266 1267 /* This must be one of these values *only* */ 1268 if (r->in.acct_flags == ACB_NORMAL) { 1269 container = "CN=Users"; 1270 obj_class = "user"; 1271 1272 } else if (r->in.acct_flags == ACB_WSTRUST) { 1273 if (cn_name[cn_name_len - 1] != '$') { 1274 ldb_transaction_cancel(d_state->sam_ctx); 1275 return NT_STATUS_FOOBAR; 1276 } 1277 cn_name[cn_name_len - 1] = '\0'; 1278 container = "CN=Computers"; 1279 obj_class = "computer"; 1280 samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, 1281 "primaryGroupID", DOMAIN_RID_DOMAIN_MEMBERS); 1282 1283 } else if (r->in.acct_flags == ACB_SVRTRUST) { 1284 if (cn_name[cn_name_len - 1] != '$') { 1285 ldb_transaction_cancel(d_state->sam_ctx); 1286 return NT_STATUS_FOOBAR; 1287 } 1288 cn_name[cn_name_len - 1] = '\0'; 1289 container = "OU=Domain Controllers"; 1290 obj_class = "computer"; 1291 samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, 1292 "primaryGroupID", DOMAIN_RID_DCS); 1293 } else { 1294 ldb_transaction_cancel(d_state->sam_ctx); 1295 return NT_STATUS_INVALID_PARAMETER; 1296 } 1297 1298 /* add core elements to the ldb_message for the user */ 1299 msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn); 1300 if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s,%s", cn_name, container)) { 1301 ldb_transaction_cancel(d_state->sam_ctx); 1302 return NT_STATUS_FOOBAR; 1303 } 1304 1305 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", 1306 account_name); 1307 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", 1308 obj_class); 1309 1310 /* create the user */ 1311 ret = ldb_add(d_state->sam_ctx, msg); 1312 switch (ret) { 1313 case LDB_SUCCESS: 1314 break; 1315 case LDB_ERR_ENTRY_ALREADY_EXISTS: 1316 ldb_transaction_cancel(d_state->sam_ctx); 1317 DEBUG(0,("Failed to create user record %s: %s\n", 1318 ldb_dn_get_linearized(msg->dn), 1319 ldb_errstring(d_state->sam_ctx))); 1320 return NT_STATUS_USER_EXISTS; 1321 case LDB_ERR_UNWILLING_TO_PERFORM: 1322 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: 1323 ldb_transaction_cancel(d_state->sam_ctx); 1324 DEBUG(0,("Failed to create user record %s: %s\n", 1325 ldb_dn_get_linearized(msg->dn), 1326 ldb_errstring(d_state->sam_ctx))); 1327 return NT_STATUS_ACCESS_DENIED; 1328 default: 1329 ldb_transaction_cancel(d_state->sam_ctx); 1330 DEBUG(0,("Failed to create user record %s: %s\n", 1331 ldb_dn_get_linearized(msg->dn), 1332 ldb_errstring(d_state->sam_ctx))); 1333 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1334 } 1335 1336 a_state = talloc(d_state, struct samr_account_state); 1204 status = dsdb_add_user(d_state->sam_ctx, mem_ctx, account_name, r->in.acct_flags, &sid, &dn); 1205 if (!NT_STATUS_IS_OK(status)) { 1206 return status; 1207 } 1208 a_state = talloc(mem_ctx, struct samr_account_state); 1337 1209 if (!a_state) { 1338 1210 ldb_transaction_cancel(d_state->sam_ctx); … … 1342 1214 a_state->access_mask = r->in.access_mask; 1343 1215 a_state->domain_state = talloc_reference(a_state, d_state); 1344 a_state->account_dn = talloc_steal(a_state, msg->dn); 1345 1346 /* retrieve the sid and account control bits for the user just created */ 1347 ret = gendb_search_dn(d_state->sam_ctx, a_state, 1348 msg->dn, &msgs, attrs); 1349 1350 if (ret != 1) { 1351 ldb_transaction_cancel(d_state->sam_ctx); 1352 DEBUG(0,("Apparently we failed to create an account record, as %s now doesn't exist\n", 1353 ldb_dn_get_linearized(msg->dn))); 1354 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1355 } 1356 sid = samdb_result_dom_sid(mem_ctx, msgs[0], "objectSid"); 1357 if (sid == NULL) { 1358 ldb_transaction_cancel(d_state->sam_ctx); 1359 DEBUG(0,("Apparently we failed to get the objectSid of the just created account record %s\n", 1360 ldb_dn_get_linearized(msg->dn))); 1361 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1362 } 1363 1364 /* Change the account control to be the correct account type. 1365 * The default is for a workstation account */ 1366 user_account_control = samdb_result_uint(msgs[0], "userAccountControl", 0); 1367 user_account_control = (user_account_control & 1368 ~(UF_NORMAL_ACCOUNT | 1369 UF_INTERDOMAIN_TRUST_ACCOUNT | 1370 UF_WORKSTATION_TRUST_ACCOUNT | 1371 UF_SERVER_TRUST_ACCOUNT)); 1372 user_account_control |= ds_acb2uf(r->in.acct_flags); 1373 1374 talloc_free(msg); 1375 msg = ldb_msg_new(mem_ctx); 1376 if (msg == NULL) { 1377 ldb_transaction_cancel(d_state->sam_ctx); 1378 return NT_STATUS_NO_MEMORY; 1379 } 1380 1381 msg->dn = ldb_dn_copy(msg, a_state->account_dn); 1382 1383 if (samdb_msg_add_uint(a_state->sam_ctx, mem_ctx, msg, 1384 "userAccountControl", 1385 user_account_control) != 0) { 1386 ldb_transaction_cancel(d_state->sam_ctx); 1387 return NT_STATUS_NO_MEMORY; 1388 } 1389 1390 /* modify the samdb record */ 1391 ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg); 1392 if (ret != 0) { 1393 DEBUG(0,("Failed to modify account record %s to set userAccountControl: %s\n", 1394 ldb_dn_get_linearized(msg->dn), 1395 ldb_errstring(d_state->sam_ctx))); 1396 ldb_transaction_cancel(d_state->sam_ctx); 1397 1398 /* we really need samdb.c to return NTSTATUS */ 1399 return NT_STATUS_UNSUCCESSFUL; 1400 } 1401 1402 ret = ldb_transaction_commit(d_state->sam_ctx); 1403 if (ret != 0) { 1404 DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n", 1405 ldb_dn_get_linearized(msg->dn), 1406 ldb_errstring(d_state->sam_ctx))); 1407 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1408 } 1216 a_state->account_dn = talloc_steal(a_state, dn); 1409 1217 1410 1218 a_state->account_name = talloc_steal(a_state, account_name); … … 1430 1238 1431 1239 1432 /* 1433 samr_CreateUser 1240 /* 1241 samr_CreateUser 1434 1242 */ 1435 1243 static NTSTATUS dcesrv_samr_CreateUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 1452 1260 } 1453 1261 1454 /* 1455 samr_EnumDomainUsers 1262 /* 1263 samr_EnumDomainUsers 1456 1264 */ 1457 1265 static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 1460 1268 struct dcesrv_handle *h; 1461 1269 struct samr_domain_state *d_state; 1462 struct ldb_result *res; 1463 int ret, num_filtered_entries, i, first; 1270 struct ldb_message **res; 1271 int i, ldb_cnt; 1272 uint32_t first, count; 1464 1273 struct samr_SamEntry *entries; 1465 1274 const char * const attrs[] = { "objectSid", "sAMAccountName", … … 1474 1283 1475 1284 d_state = h->data; 1476 1477 /* don't have to worry about users in the builtin domain, as there are none */ 1478 ret = ldb_search(d_state->sam_ctx, mem_ctx, &res, d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=user"); 1479 1480 if (ret != LDB_SUCCESS) { 1481 DEBUG(3, ("Failed to search for Domain Users in %s: %s\n", 1482 ldb_dn_get_linearized(d_state->domain_dn), ldb_errstring(d_state->sam_ctx))); 1285 1286 /* search for all domain users in this domain. This could possibly be 1287 cached and resumed on resume_key */ 1288 ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx, 1289 d_state->domain_dn, 1290 &res, attrs, 1291 d_state->domain_sid, 1292 "(objectClass=user)"); 1293 if (ldb_cnt < 0) { 1483 1294 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1484 1295 } 1485 1296 1486 1297 /* convert to SamEntry format */ 1487 entries = talloc_array(mem_ctx, struct samr_SamEntry, res->count);1298 entries = talloc_array(mem_ctx, struct samr_SamEntry, ldb_cnt); 1488 1299 if (!entries) { 1489 1300 return NT_STATUS_NO_MEMORY; 1490 1301 } 1491 num_filtered_entries = 0; 1492 for (i=0;i<res->count;i++) { 1302 1303 count = 0; 1304 1305 for (i=0;i<ldb_cnt;i++) { 1493 1306 /* Check if a mask has been requested */ 1494 1307 if (r->in.acct_flags 1495 && ((samdb_result_acct_flags(d_state->sam_ctx, mem_ctx, res->msgs[i],1496 d_state->domain_dn) & r->in.acct_flags) == 0)) {1308 && ((samdb_result_acct_flags(d_state->sam_ctx, mem_ctx, 1309 res[i], d_state->domain_dn) & r->in.acct_flags) == 0)) { 1497 1310 continue; 1498 1311 } 1499 entries[num_filtered_entries].idx = samdb_result_rid_from_sid(mem_ctx, res->msgs[i], "objectSid", 0); 1500 entries[num_filtered_entries].name.string = samdb_result_string(res->msgs[i], "sAMAccountName", ""); 1501 num_filtered_entries++; 1312 entries[count].idx = samdb_result_rid_from_sid(mem_ctx, res[i], 1313 "objectSid", 0); 1314 entries[count].name.string = ldb_msg_find_attr_as_string(res[i], 1315 "sAMAccountName", ""); 1316 count += 1; 1502 1317 } 1503 1318 1504 1319 /* sort the results by rid */ 1505 qsort(entries, num_filtered_entries, sizeof(struct samr_SamEntry), 1506 (comparison_fn_t)compare_SamEntry); 1320 TYPESAFE_QSORT(entries, count, compare_SamEntry); 1507 1321 1508 1322 /* find the first entry to return */ 1509 1323 for (first=0; 1510 first< num_filtered_entries&& entries[first].idx <= *r->in.resume_handle;1324 first<count && entries[first].idx <= *r->in.resume_handle; 1511 1325 first++) ; 1512 1326 1513 /* return the rest, limit by max_size. Note that we 1327 /* return the rest, limit by max_size. Note that we 1514 1328 use the w2k3 element size value of 54 */ 1515 *r->out.num_entries = num_filtered_entries- first;1329 *r->out.num_entries = count - first; 1516 1330 *r->out.num_entries = MIN(*r->out.num_entries, 1517 1331 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER)); … … 1527 1341 *r->out.sam = sam; 1528 1342 1529 if (first == num_filtered_entries) {1343 if (first == count) { 1530 1344 return NT_STATUS_OK; 1531 1345 } 1532 1346 1533 if (*r->out.num_entries < num_filtered_entries- first) {1347 if (*r->out.num_entries < count - first) { 1534 1348 *r->out.resume_handle = entries[first+*r->out.num_entries-1].idx; 1535 1349 return STATUS_MORE_ENTRIES; … … 1540 1354 1541 1355 1542 /* 1543 samr_CreateDomAlias 1356 /* 1357 samr_CreateDomAlias 1544 1358 */ 1545 1359 static NTSTATUS dcesrv_samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 1549 1363 struct samr_account_state *a_state; 1550 1364 struct dcesrv_handle *h; 1551 const char *alias_name, *name; 1552 struct ldb_message *msg; 1365 const char *alias_name; 1553 1366 struct dom_sid *sid; 1554 1367 struct dcesrv_handle *a_handle; 1555 int ret; 1368 struct ldb_dn *dn; 1369 NTSTATUS status; 1556 1370 1557 1371 ZERO_STRUCTP(r->out.alias_handle); … … 1573 1387 } 1574 1388 1575 /* Check if alias already exists */ 1576 name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL, 1577 "sAMAccountName", 1578 "(sAMAccountName=%s)(objectclass=group))", 1579 ldb_binary_encode_string(mem_ctx, alias_name)); 1580 1581 if (name != NULL) { 1582 return NT_STATUS_ALIAS_EXISTS; 1583 } 1584 1585 msg = ldb_msg_new(mem_ctx); 1586 if (msg == NULL) { 1587 return NT_STATUS_NO_MEMORY; 1588 } 1589 1590 /* add core elements to the ldb_message for the alias */ 1591 msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn); 1592 ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", alias_name); 1593 if (!msg->dn) { 1594 return NT_STATUS_NO_MEMORY; 1595 } 1596 1597 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", alias_name); 1598 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "group"); 1599 samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "groupType", GTYPE_SECURITY_DOMAIN_LOCAL_GROUP); 1600 1601 /* create the alias */ 1602 ret = ldb_add(d_state->sam_ctx, msg); 1603 switch (ret) { 1604 case LDB_SUCCESS: 1605 break; 1606 case LDB_ERR_ENTRY_ALREADY_EXISTS: 1607 return NT_STATUS_ALIAS_EXISTS; 1608 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: 1609 return NT_STATUS_ACCESS_DENIED; 1610 default: 1611 DEBUG(0,("Failed to create alias record %s: %s\n", 1612 ldb_dn_get_linearized(msg->dn), 1613 ldb_errstring(d_state->sam_ctx))); 1614 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1615 } 1616 1617 a_state = talloc(d_state, struct samr_account_state); 1389 status = dsdb_add_domain_alias(d_state->sam_ctx, mem_ctx, alias_name, &sid, &dn); 1390 if (!NT_STATUS_IS_OK(status)) { 1391 return status; 1392 } 1393 1394 a_state = talloc(mem_ctx, struct samr_account_state); 1618 1395 if (!a_state) { 1619 1396 return NT_STATUS_NO_MEMORY; … … 1623 1400 a_state->access_mask = r->in.access_mask; 1624 1401 a_state->domain_state = talloc_reference(a_state, d_state); 1625 a_state->account_dn = talloc_steal(a_state, msg->dn); 1626 1627 /* retrieve the sid for the alias just created */ 1628 sid = samdb_search_dom_sid(d_state->sam_ctx, a_state, 1629 msg->dn, "objectSid", NULL); 1630 1631 a_state->account_name = talloc_strdup(a_state, alias_name); 1632 if (!a_state->account_name) { 1633 return NT_STATUS_NO_MEMORY; 1634 } 1402 a_state->account_dn = talloc_steal(a_state, dn); 1403 1404 a_state->account_name = talloc_steal(a_state, alias_name); 1635 1405 1636 1406 /* create the policy handle */ … … 1649 1419 1650 1420 1651 /* 1652 samr_EnumDomainAliases 1421 /* 1422 samr_EnumDomainAliases 1653 1423 */ 1654 1424 static NTSTATUS dcesrv_samr_EnumDomainAliases(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 1658 1428 struct samr_domain_state *d_state; 1659 1429 struct ldb_message **res; 1660 int ldb_cnt, count, i, first; 1430 int i, ldb_cnt; 1431 uint32_t first, count; 1661 1432 struct samr_SamEntry *entries; 1662 const char * const attrs[ 3] = { "objectSid", "sAMAccountName", NULL };1433 const char * const attrs[] = { "objectSid", "sAMAccountName", NULL }; 1663 1434 struct samr_SamArray *sam; 1664 1435 … … 1671 1442 d_state = h->data; 1672 1443 1673 /* search for all domain groups in this domain. This could possibly be1444 /* search for all domain aliases in this domain. This could possibly be 1674 1445 cached and resumed based on resume_key */ 1675 ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx, 1676 d_state->domain_dn, 1677 &res, attrs, 1446 ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx, NULL, 1447 &res, attrs, 1678 1448 d_state->domain_sid, 1679 1449 "(&(|(grouptype=%d)(grouptype=%d)))" … … 1681 1451 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, 1682 1452 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP); 1683 if (ldb_cnt == -1) {1453 if (ldb_cnt < 0) { 1684 1454 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1685 }1686 if (ldb_cnt == 0) {1687 return NT_STATUS_OK;1688 1455 } 1689 1456 … … 1702 1469 "objectSid"); 1703 1470 1704 if (alias_sid == NULL) 1705 continue; 1471 if (alias_sid == NULL) { 1472 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1473 } 1706 1474 1707 1475 entries[count].idx = 1708 1476 alias_sid->sub_auths[alias_sid->num_auths-1]; 1709 1477 entries[count].name.string = 1710 samdb_result_string(res[i], "sAMAccountName", "");1478 ldb_msg_find_attr_as_string(res[i], "sAMAccountName", ""); 1711 1479 count += 1; 1712 1480 } 1713 1481 1714 1482 /* sort the results by rid */ 1715 qsort(entries, count, sizeof(struct samr_SamEntry), 1716 (comparison_fn_t)compare_SamEntry); 1483 TYPESAFE_QSORT(entries, count, compare_SamEntry); 1717 1484 1718 1485 /* find the first entry to return */ … … 1721 1488 first++) ; 1722 1489 1490 /* return the rest, limit by max_size. Note that we 1491 use the w2k3 element size value of 54 */ 1492 *r->out.num_entries = count - first; 1493 *r->out.num_entries = MIN(*r->out.num_entries, 1494 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER)); 1495 1496 sam = talloc(mem_ctx, struct samr_SamArray); 1497 if (!sam) { 1498 return NT_STATUS_NO_MEMORY; 1499 } 1500 1501 sam->entries = entries+first; 1502 sam->count = *r->out.num_entries; 1503 1504 *r->out.sam = sam; 1505 1723 1506 if (first == count) { 1724 1507 return NT_STATUS_OK; 1725 1508 } 1726 1727 *r->out.num_entries = count - first;1728 *r->out.num_entries = MIN(*r->out.num_entries, 1000);1729 1730 sam = talloc(mem_ctx, struct samr_SamArray);1731 if (!sam) {1732 return NT_STATUS_NO_MEMORY;1733 }1734 1735 sam->entries = entries+first;1736 sam->count = *r->out.num_entries;1737 1738 *r->out.sam = sam;1739 1509 1740 1510 if (*r->out.num_entries < count - first) { … … 1748 1518 1749 1519 1750 /* 1751 samr_GetAliasMembership 1520 /* 1521 samr_GetAliasMembership 1752 1522 */ 1753 1523 static NTSTATUS dcesrv_samr_GetAliasMembership(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 1756 1526 struct dcesrv_handle *h; 1757 1527 struct samr_domain_state *d_state; 1528 const char *filter; 1529 const char * const attrs[] = { "objectSid", NULL }; 1758 1530 struct ldb_message **res; 1759 int i, count = 0; 1531 uint32_t i; 1532 int count = 0; 1760 1533 1761 1534 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN); … … 1763 1536 d_state = h->data; 1764 1537 1765 if (r->in.sids->num_sids > 0) { 1766 const char *filter; 1767 const char * const attrs[2] = { "objectSid", NULL }; 1768 1769 filter = talloc_asprintf(mem_ctx, 1770 "(&(|(grouptype=%d)(grouptype=%d))" 1771 "(objectclass=group)(|", 1772 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, 1773 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP); 1774 if (filter == NULL) 1538 filter = talloc_asprintf(mem_ctx, 1539 "(&(|(grouptype=%d)(grouptype=%d))" 1540 "(objectclass=group)(|", 1541 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, 1542 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP); 1543 if (filter == NULL) { 1544 return NT_STATUS_NO_MEMORY; 1545 } 1546 1547 for (i=0; i<r->in.sids->num_sids; i++) { 1548 const char *memberdn; 1549 1550 memberdn = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL, 1551 "distinguishedName", 1552 "(objectSid=%s)", 1553 ldap_encode_ndr_dom_sid(mem_ctx, 1554 r->in.sids->sids[i].sid)); 1555 if (memberdn == NULL) { 1556 continue; 1557 } 1558 1559 filter = talloc_asprintf(mem_ctx, "%s(member=%s)", filter, 1560 memberdn); 1561 if (filter == NULL) { 1775 1562 return NT_STATUS_NO_MEMORY; 1776 1777 for (i=0; i<r->in.sids->num_sids; i++) {1778 const char *memberdn;1779 1780 memberdn =1781 samdb_search_string(d_state->sam_ctx,1782 mem_ctx, NULL,1783 "distinguishedName",1784 "(objectSid=%s)",1785 ldap_encode_ndr_dom_sid(mem_ctx,1786 r->in.sids->sids[i].sid));1787 1788 if (memberdn == NULL)1789 continue;1790 1791 filter = talloc_asprintf(mem_ctx, "%s(member=%s)",1792 filter, memberdn);1793 if (filter == NULL)1794 return NT_STATUS_NO_MEMORY;1795 1563 } 1796 1797 count = samdb_search_domain(d_state->sam_ctx, mem_ctx, 1798 d_state->domain_dn, &res, attrs, 1799 d_state->domain_sid, "%s))", filter); 1800 if (count < 0) 1564 } 1565 1566 /* Find out if we had at least one valid member SID passed - otherwise 1567 * just skip the search. */ 1568 if (strstr(filter, "member") != NULL) { 1569 count = samdb_search_domain(d_state->sam_ctx, mem_ctx, NULL, 1570 &res, attrs, d_state->domain_sid, 1571 "%s))", filter); 1572 if (count < 0) { 1801 1573 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1574 } 1802 1575 } 1803 1576 … … 1811 1584 1812 1585 alias_sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid"); 1813 1814 1586 if (alias_sid == NULL) { 1815 DEBUG(0, ("Could not find objectSid\n")); 1816 continue; 1587 return NT_STATUS_INTERNAL_DB_CORRUPTION; 1817 1588 } 1818 1589 … … 1826 1597 1827 1598 1828 /* 1829 samr_LookupNames 1599 /* 1600 samr_LookupNames 1830 1601 */ 1831 1602 static NTSTATUS dcesrv_samr_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 1834 1605 struct dcesrv_handle *h; 1835 1606 struct samr_domain_state *d_state; 1836 int i, num_mapped;1607 uint32_t i, num_mapped; 1837 1608 NTSTATUS status = NT_STATUS_OK; 1838 1609 const char * const attrs[] = { "sAMAccountType", "objectSid", NULL }; … … 1868 1639 r->out.types->ids[i] = SID_NAME_UNKNOWN; 1869 1640 1870 count = gendb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs, 1871 "sAMAccountName=%s", 1641 count = gendb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs, 1642 "sAMAccountName=%s", 1872 1643 ldb_binary_encode_string(mem_ctx, r->in.names[i].string)); 1873 1644 if (count != 1) { … … 1881 1652 continue; 1882 1653 } 1883 1884 atype = samdb_result_uint(res[0], "sAMAccountType", 0);1654 1655 atype = ldb_msg_find_attr_as_uint(res[0], "sAMAccountType", 0); 1885 1656 if (atype == 0) { 1886 1657 status = STATUS_SOME_UNMAPPED; … … 1889 1660 1890 1661 rtype = ds_atype_map(atype); 1891 1662 1892 1663 if (rtype == SID_NAME_UNKNOWN) { 1893 1664 status = STATUS_SOME_UNMAPPED; … … 1899 1670 num_mapped++; 1900 1671 } 1901 1672 1902 1673 if (num_mapped == 0) { 1903 1674 return NT_STATUS_NONE_MAPPED; … … 1907 1678 1908 1679 1909 /* 1910 samr_LookupRids 1680 /* 1681 samr_LookupRids 1911 1682 */ 1912 1683 static NTSTATUS dcesrv_samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 1913 1684 struct samr_LookupRids *r) 1914 1685 { 1686 NTSTATUS status; 1915 1687 struct dcesrv_handle *h; 1916 1688 struct samr_domain_state *d_state; 1917 int i, total; 1918 NTSTATUS status = NT_STATUS_OK; 1919 struct lsa_String *names; 1920 uint32_t *ids; 1689 const char **names; 1690 struct lsa_String *lsa_names; 1691 enum lsa_SidType *ids; 1921 1692 1922 1693 ZERO_STRUCTP(r->out.names); … … 1930 1701 return NT_STATUS_OK; 1931 1702 1932 names = talloc_array(mem_ctx, struct lsa_String, r->in.num_rids); 1933 ids = talloc_array(mem_ctx, uint32_t, r->in.num_rids); 1934 1935 if ((names == NULL) || (ids == NULL)) 1936 return NT_STATUS_NO_MEMORY; 1937 1938 total = 0; 1939 1940 for (i=0; i<r->in.num_rids; i++) { 1941 struct ldb_message **res; 1942 int count; 1943 const char * const attrs[] = { "sAMAccountType", 1944 "sAMAccountName", NULL }; 1945 uint32_t atype; 1946 struct dom_sid *sid; 1947 1948 ids[i] = SID_NAME_UNKNOWN; 1949 1950 sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, 1951 r->in.rids[i]); 1952 if (sid == NULL) { 1953 names[i].string = NULL; 1954 status = STATUS_SOME_UNMAPPED; 1955 continue; 1703 lsa_names = talloc_zero_array(mem_ctx, struct lsa_String, r->in.num_rids); 1704 names = talloc_zero_array(mem_ctx, const char *, r->in.num_rids); 1705 ids = talloc_zero_array(mem_ctx, enum lsa_SidType, r->in.num_rids); 1706 1707 if ((lsa_names == NULL) || (names == NULL) || (ids == NULL)) 1708 return NT_STATUS_NO_MEMORY; 1709 1710 r->out.names->names = lsa_names; 1711 r->out.names->count = r->in.num_rids; 1712 1713 r->out.types->ids = (uint32_t *) ids; 1714 r->out.types->count = r->in.num_rids; 1715 1716 status = dsdb_lookup_rids(d_state->sam_ctx, mem_ctx, d_state->domain_sid, 1717 r->in.num_rids, r->in.rids, names, ids); 1718 if (NT_STATUS_IS_OK(status) || NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED) || NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) { 1719 uint32_t i; 1720 for (i = 0; i < r->in.num_rids; i++) { 1721 lsa_names[i].string = names[i]; 1956 1722 } 1957 1958 count = gendb_search(d_state->sam_ctx, mem_ctx, 1959 d_state->domain_dn, &res, attrs, 1960 "(objectSid=%s)", 1961 ldap_encode_ndr_dom_sid(mem_ctx, sid)); 1962 if (count != 1) { 1963 names[i].string = NULL; 1964 status = STATUS_SOME_UNMAPPED; 1965 continue; 1966 } 1967 1968 names[i].string = samdb_result_string(res[0], "sAMAccountName", 1969 NULL); 1970 1971 atype = samdb_result_uint(res[0], "sAMAccountType", 0); 1972 if (atype == 0) { 1973 status = STATUS_SOME_UNMAPPED; 1974 continue; 1975 } 1976 1977 ids[i] = ds_atype_map(atype); 1978 1979 if (ids[i] == SID_NAME_UNKNOWN) { 1980 status = STATUS_SOME_UNMAPPED; 1981 continue; 1982 } 1983 } 1984 1985 r->out.names->names = names; 1986 r->out.names->count = r->in.num_rids; 1987 1988 r->out.types->ids = ids; 1989 r->out.types->count = r->in.num_rids; 1990 1723 } 1991 1724 return status; 1992 1725 } 1993 1726 1994 1727 1995 /* 1996 samr_OpenGroup 1728 /* 1729 samr_OpenGroup 1997 1730 */ 1998 1731 static NTSTATUS dcesrv_samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2024 1757 ret = gendb_search(d_state->sam_ctx, 2025 1758 mem_ctx, d_state->domain_dn, &msgs, attrs, 2026 "(&(objectSid=%s)(object class=group)"2027 "( grouptype=%d))",1759 "(&(objectSid=%s)(objectClass=group)" 1760 "(|(groupType=%d)(groupType=%d)))", 2028 1761 ldap_encode_ndr_dom_sid(mem_ctx, sid), 1762 GTYPE_SECURITY_UNIVERSAL_GROUP, 2029 1763 GTYPE_SECURITY_GLOBAL_GROUP); 2030 1764 if (ret == 0) { … … 2032 1766 } 2033 1767 if (ret != 1) { 2034 DEBUG(0,("Found %d records matching sid %s\n", 1768 DEBUG(0,("Found %d records matching sid %s\n", 2035 1769 ret, dom_sid_string(mem_ctx, sid))); 2036 1770 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2037 1771 } 2038 1772 2039 groupname = samdb_result_string(msgs[0], "sAMAccountName", NULL);1773 groupname = ldb_msg_find_attr_as_string(msgs[0], "sAMAccountName", NULL); 2040 1774 if (groupname == NULL) { 2041 DEBUG(0,("sAMAccountName field missing for sid %s\n", 1775 DEBUG(0,("sAMAccountName field missing for sid %s\n", 2042 1776 dom_sid_string(mem_ctx, sid))); 2043 1777 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2044 1778 } 2045 1779 2046 a_state = talloc( d_state, struct samr_account_state);1780 a_state = talloc(mem_ctx, struct samr_account_state); 2047 1781 if (!a_state) { 2048 1782 return NT_STATUS_NO_MEMORY; … … 2071 1805 } 2072 1806 2073 /* 2074 samr_QueryGroupInfo 1807 /* 1808 samr_QueryGroupInfo 2075 1809 */ 2076 1810 static NTSTATUS dcesrv_samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2079 1813 struct dcesrv_handle *h; 2080 1814 struct samr_account_state *a_state; 2081 struct ldb_message *msg; 2082 struct ldb_result *res; 1815 struct ldb_message *msg, **res; 2083 1816 const char * const attrs[4] = { "sAMAccountName", "description", 2084 1817 "numMembers", NULL }; … … 2091 1824 2092 1825 a_state = h->data; 2093 2094 ret = ldb_search(a_state->sam_ctx, mem_ctx, &res, a_state->account_dn,2095 LDB_SCOPE_SUBTREE, attrs, "objectClass=*");2096 2097 if (ret == LDB_ERR_NO_SUCH_OBJECT) {1826 1827 /* pull all the group attributes */ 1828 ret = gendb_search_dn(a_state->sam_ctx, mem_ctx, 1829 a_state->account_dn, &res, attrs); 1830 if (ret == 0) { 2098 1831 return NT_STATUS_NO_SUCH_GROUP; 2099 } else if (ret != LDB_SUCCESS) {2100 DEBUG(2, ("Error reading group info: %s\n", ldb_errstring(a_state->sam_ctx)));1832 } 1833 if (ret != 1) { 2101 1834 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2102 1835 } 2103 2104 if (res->count != 1) { 2105 DEBUG(2, ("Error finding group info, got %d entries\n", res->count)); 2106 2107 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2108 } 2109 msg = res->msgs[0]; 1836 msg = res[0]; 2110 1837 2111 1838 /* allocate the info structure */ … … 2149 1876 2150 1877 2151 /* 2152 samr_SetGroupInfo 1878 /* 1879 samr_SetGroupInfo 2153 1880 */ 2154 1881 static NTSTATUS dcesrv_samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2169 1896 if (msg == NULL) { 2170 1897 return NT_STATUS_NO_MEMORY; 2171 } 1898 } 2172 1899 2173 1900 msg->dn = ldb_dn_copy(mem_ctx, g_state->account_dn); … … 2194 1921 /* modify the samdb record */ 2195 1922 ret = ldb_modify(g_state->sam_ctx, msg); 2196 if (ret != 0) {1923 if (ret != LDB_SUCCESS) { 2197 1924 /* we really need samdb.c to return NTSTATUS */ 2198 1925 return NT_STATUS_UNSUCCESSFUL; … … 2203 1930 2204 1931 2205 /* 2206 samr_AddGroupMember 1932 /* 1933 samr_AddGroupMember 2207 1934 */ 2208 1935 static NTSTATUS dcesrv_samr_AddGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2225 1952 2226 1953 membersid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid); 2227 if (membersid == NULL) 2228 return NT_STATUS_NO_MEMORY; 2229 2230 /* In native mode, AD can also nest domain groups. Not sure yet 2231 * whether this is also available via RPC.*/1954 if (membersid == NULL) { 1955 return NT_STATUS_NO_MEMORY; 1956 } 1957 1958 /* according to MS-SAMR 3.1.5.8.2 all type of accounts are accepted */ 2232 1959 ret = ldb_search(d_state->sam_ctx, mem_ctx, &res, 2233 2234 "(&(objectSid=%s)(objectclass=user))",2235 2236 2237 if (ret != 0) {1960 d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs, 1961 "(objectSid=%s)", 1962 ldap_encode_ndr_dom_sid(mem_ctx, membersid)); 1963 1964 if (ret != LDB_SUCCESS) { 2238 1965 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2239 1966 } … … 2242 1969 return NT_STATUS_NO_SUCH_USER; 2243 1970 } 2244 1971 2245 1972 if (res->count > 1) { 2246 1973 return NT_STATUS_INTERNAL_DB_CORRUPTION; … … 2259 1986 mod->dn = talloc_reference(mem_ctx, a_state->account_dn); 2260 1987 2261 if (samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member", 2262 memberdn) != 0) 1988 ret = samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member", 1989 memberdn); 1990 if (ret != LDB_SUCCESS) { 2263 1991 return NT_STATUS_UNSUCCESSFUL; 1992 } 2264 1993 2265 1994 ret = ldb_modify(a_state->sam_ctx, mod); … … 2267 1996 case LDB_SUCCESS: 2268 1997 return NT_STATUS_OK; 2269 case LDB_ERR_ ATTRIBUTE_OR_VALUE_EXISTS:1998 case LDB_ERR_ENTRY_ALREADY_EXISTS: 2270 1999 return NT_STATUS_MEMBER_IN_GROUP; 2271 2000 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: … … 2274 2003 return NT_STATUS_UNSUCCESSFUL; 2275 2004 } 2276 2277 } 2278 2279 2280 /* 2281 samr_DeleteDomainGroup 2005 } 2006 2007 2008 /* 2009 samr_DeleteDomainGroup 2282 2010 */ 2283 2011 static NTSTATUS dcesrv_samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2295 2023 2296 2024 ret = ldb_delete(a_state->sam_ctx, a_state->account_dn); 2297 if (ret != 0) {2025 if (ret != LDB_SUCCESS) { 2298 2026 return NT_STATUS_UNSUCCESSFUL; 2299 2027 } 2300 2028 2029 talloc_free(h); 2301 2030 ZERO_STRUCTP(r->out.group_handle); 2302 2031 … … 2305 2034 2306 2035 2307 /* 2308 samr_DeleteGroupMember 2036 /* 2037 samr_DeleteGroupMember 2309 2038 */ 2310 2039 static NTSTATUS dcesrv_samr_DeleteGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2327 2056 2328 2057 membersid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid); 2329 if (membersid == NULL) 2330 return NT_STATUS_NO_MEMORY; 2331 2332 /* In native mode, AD can also nest domain groups. Not sure yet 2333 * whether this is also available via RPC.*/2058 if (membersid == NULL) { 2059 return NT_STATUS_NO_MEMORY; 2060 } 2061 2062 /* according to MS-SAMR 3.1.5.8.2 all type of accounts are accepted */ 2334 2063 ret = ldb_search(d_state->sam_ctx, mem_ctx, &res, 2335 2336 "(&(objectSid=%s)(objectclass=user))",2337 2338 2339 if (ret != 0) {2064 d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs, 2065 "(objectSid=%s)", 2066 ldap_encode_ndr_dom_sid(mem_ctx, membersid)); 2067 2068 if (ret != LDB_SUCCESS) { 2340 2069 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2341 2070 } … … 2344 2073 return NT_STATUS_NO_SUCH_USER; 2345 2074 } 2346 2075 2347 2076 if (res->count > 1) { 2348 2077 return NT_STATUS_INTERNAL_DB_CORRUPTION; … … 2361 2090 mod->dn = talloc_reference(mem_ctx, a_state->account_dn); 2362 2091 2363 if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member", 2364 memberdn) != 0) { 2092 ret = samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member", 2093 memberdn); 2094 if (ret != LDB_SUCCESS) { 2365 2095 return NT_STATUS_NO_MEMORY; 2366 2096 } … … 2370 2100 case LDB_SUCCESS: 2371 2101 return NT_STATUS_OK; 2372 case LDB_ERR_ NO_SUCH_ATTRIBUTE:2102 case LDB_ERR_UNWILLING_TO_PERFORM: 2373 2103 return NT_STATUS_MEMBER_NOT_IN_GROUP; 2374 2104 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: … … 2380 2110 2381 2111 2382 /* 2383 samr_QueryGroupMember 2112 /* 2113 samr_QueryGroupMember 2384 2114 */ 2385 2115 static NTSTATUS dcesrv_samr_QueryGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2388 2118 struct dcesrv_handle *h; 2389 2119 struct samr_account_state *a_state; 2390 struct ldb_message **res;2391 struct ldb_message_element *el;2392 struct samr_RidTypeArray *array;2393 const char * const attrs[2] = { "member", NULL };2394 int ret;2120 struct samr_domain_state *d_state; 2121 struct samr_RidAttrArray *array; 2122 unsigned int i, num_members; 2123 struct dom_sid *members; 2124 NTSTATUS status; 2395 2125 2396 2126 DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP); 2397 2127 2398 2128 a_state = h->data; 2399 2400 /* pull the member attribute */ 2401 ret = gendb_search_dn(a_state->sam_ctx, mem_ctx, 2402 a_state->account_dn, &res, attrs); 2403 2404 if (ret != 1) { 2405 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2406 } 2407 2408 array = talloc(mem_ctx, struct samr_RidTypeArray); 2409 2410 if (array == NULL) 2411 return NT_STATUS_NO_MEMORY; 2412 2413 ZERO_STRUCTP(array); 2414 2415 el = ldb_msg_find_element(res[0], "member"); 2416 2417 if (el != NULL) { 2418 int i; 2419 2420 array->count = el->num_values; 2421 2422 array->rids = talloc_array(mem_ctx, uint32_t, 2423 el->num_values); 2424 if (array->rids == NULL) 2425 return NT_STATUS_NO_MEMORY; 2426 2427 array->types = talloc_array(mem_ctx, uint32_t, 2428 el->num_values); 2429 if (array->types == NULL) 2430 return NT_STATUS_NO_MEMORY; 2431 2432 for (i=0; i<el->num_values; i++) { 2433 struct ldb_message **res2; 2434 const char * const attrs2[2] = { "objectSid", NULL }; 2435 ret = gendb_search_dn(a_state->sam_ctx, mem_ctx, 2436 ldb_dn_from_ldb_val(mem_ctx, a_state->sam_ctx, &el->values[i]), 2437 &res2, attrs2); 2438 if (ret != 1) 2439 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2440 2441 array->rids[i] = 2442 samdb_result_rid_from_sid(mem_ctx, res2[0], 2443 "objectSid", 0); 2444 2445 if (array->rids[i] == 0) 2446 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2447 2448 array->types[i] = 7; /* RID type of some kind, not sure what the value means. */ 2129 d_state = a_state->domain_state; 2130 2131 status = dsdb_enum_group_mem(d_state->sam_ctx, mem_ctx, 2132 a_state->account_dn, &members, 2133 &num_members); 2134 if (!NT_STATUS_IS_OK(status)) { 2135 return status; 2136 } 2137 2138 array = talloc_zero(mem_ctx, struct samr_RidAttrArray); 2139 if (array == NULL) { 2140 return NT_STATUS_NO_MEMORY; 2141 } 2142 2143 if (num_members == 0) { 2144 *r->out.rids = array; 2145 2146 return NT_STATUS_OK; 2147 } 2148 2149 array->rids = talloc_array(array, uint32_t, num_members); 2150 if (array->rids == NULL) { 2151 return NT_STATUS_NO_MEMORY; 2152 } 2153 2154 array->attributes = talloc_array(array, uint32_t, num_members); 2155 if (array->attributes == NULL) { 2156 return NT_STATUS_NO_MEMORY; 2157 } 2158 2159 array->count = 0; 2160 for (i=0; i<num_members; i++) { 2161 if (!dom_sid_in_domain(d_state->domain_sid, &members[i])) { 2162 continue; 2449 2163 } 2164 2165 status = dom_sid_split_rid(NULL, &members[i], NULL, 2166 &array->rids[array->count]); 2167 if (!NT_STATUS_IS_OK(status)) { 2168 return status; 2169 } 2170 2171 array->attributes[array->count] = SE_GROUP_MANDATORY | 2172 SE_GROUP_ENABLED_BY_DEFAULT | 2173 SE_GROUP_ENABLED; 2174 array->count++; 2450 2175 } 2451 2176 … … 2456 2181 2457 2182 2458 /* 2459 samr_SetMemberAttributesOfGroup 2183 /* 2184 samr_SetMemberAttributesOfGroup 2460 2185 */ 2461 2186 static NTSTATUS dcesrv_samr_SetMemberAttributesOfGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2466 2191 2467 2192 2468 /* 2469 samr_OpenAlias 2193 /* 2194 samr_OpenAlias 2470 2195 */ 2471 2196 static NTSTATUS dcesrv_samr_OpenAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2494 2219 2495 2220 /* search for the group record */ 2496 ret = gendb_search(d_state->sam_ctx, 2497 mem_ctx, d_state->domain_dn, &msgs, attrs, 2221 ret = gendb_search(d_state->sam_ctx, mem_ctx, NULL, &msgs, attrs, 2498 2222 "(&(objectSid=%s)(objectclass=group)" 2499 2223 "(|(grouptype=%d)(grouptype=%d)))", … … 2505 2229 } 2506 2230 if (ret != 1) { 2507 DEBUG(0,("Found %d records matching sid %s\n", 2231 DEBUG(0,("Found %d records matching sid %s\n", 2508 2232 ret, dom_sid_string(mem_ctx, sid))); 2509 2233 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2510 2234 } 2511 2235 2512 alias_name = samdb_result_string(msgs[0], "sAMAccountName", NULL);2236 alias_name = ldb_msg_find_attr_as_string(msgs[0], "sAMAccountName", NULL); 2513 2237 if (alias_name == NULL) { 2514 DEBUG(0,("sAMAccountName field missing for sid %s\n", 2238 DEBUG(0,("sAMAccountName field missing for sid %s\n", 2515 2239 dom_sid_string(mem_ctx, sid))); 2516 2240 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2517 2241 } 2518 2242 2519 a_state = talloc( d_state, struct samr_account_state);2243 a_state = talloc(mem_ctx, struct samr_account_state); 2520 2244 if (!a_state) { 2521 2245 return NT_STATUS_NO_MEMORY; … … 2545 2269 2546 2270 2547 /* 2548 samr_QueryAliasInfo 2271 /* 2272 samr_QueryAliasInfo 2549 2273 */ 2550 2274 static NTSTATUS dcesrv_samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2567 2291 /* pull all the alias attributes */ 2568 2292 ret = gendb_search_dn(a_state->sam_ctx, mem_ctx, 2569 a_state->account_dn ,&res, attrs); 2293 a_state->account_dn, &res, attrs); 2294 if (ret == 0) { 2295 return NT_STATUS_NO_SUCH_ALIAS; 2296 } 2570 2297 if (ret != 1) { 2571 2298 return NT_STATUS_INTERNAL_DB_CORRUPTION; … … 2602 2329 2603 2330 2604 /* 2605 samr_SetAliasInfo 2331 /* 2332 samr_SetAliasInfo 2606 2333 */ 2607 2334 static NTSTATUS dcesrv_samr_SetAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2644 2371 /* modify the samdb record */ 2645 2372 ret = ldb_modify(a_state->sam_ctx, msg); 2646 if (ret != 0) {2373 if (ret != LDB_SUCCESS) { 2647 2374 /* we really need samdb.c to return NTSTATUS */ 2648 2375 return NT_STATUS_UNSUCCESSFUL; … … 2653 2380 2654 2381 2655 /* 2656 samr_DeleteDomAlias 2382 /* 2383 samr_DeleteDomAlias 2657 2384 */ 2658 2385 static NTSTATUS dcesrv_samr_DeleteDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2670 2397 2671 2398 ret = ldb_delete(a_state->sam_ctx, a_state->account_dn); 2672 if (ret != 0) {2399 if (ret != LDB_SUCCESS) { 2673 2400 return NT_STATUS_UNSUCCESSFUL; 2674 2401 } 2675 2402 2403 talloc_free(h); 2676 2404 ZERO_STRUCTP(r->out.alias_handle); 2677 2405 … … 2680 2408 2681 2409 2682 /* 2683 samr_AddAliasMember 2410 /* 2411 samr_AddAliasMember 2684 2412 */ 2685 2413 static NTSTATUS dcesrv_samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2702 2430 2703 2431 ret = gendb_search(d_state->sam_ctx, mem_ctx, NULL, 2704 &msgs, attrs, "(objectsid=%s)", 2432 &msgs, attrs, "(objectsid=%s)", 2705 2433 ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid)); 2706 2434 2707 2435 if (ret == 1) { 2708 2436 memberdn = msgs[0]->dn; 2709 } else if (ret > 1) {2710 DEBUG(0,("Found %d records matching sid %s\n",2711 ret, dom_sid_string(mem_ctx, r->in.sid)));2712 return NT_STATUS_INTERNAL_DB_CORRUPTION;2713 2437 } else if (ret == 0) { 2714 2438 status = samdb_create_foreign_security_principal( … … 2718 2442 } 2719 2443 } else { 2720 DEBUG(0, ("samdb_search returned %d: %s\n", ret, ldb_errstring(d_state->sam_ctx))); 2444 DEBUG(0,("Found %d records matching sid %s\n", 2445 ret, dom_sid_string(mem_ctx, r->in.sid))); 2446 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2721 2447 } 2722 2448 … … 2733 2459 mod->dn = talloc_reference(mem_ctx, a_state->account_dn); 2734 2460 2735 if (samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member", 2736 ldb_dn_alloc_linearized(mem_ctx, memberdn)) != 0) 2461 ret = samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member", 2462 ldb_dn_alloc_linearized(mem_ctx, memberdn)); 2463 if (ret != LDB_SUCCESS) { 2737 2464 return NT_STATUS_UNSUCCESSFUL; 2738 2739 if (ldb_modify(a_state->sam_ctx, mod) != 0) 2465 } 2466 2467 ret = ldb_modify(a_state->sam_ctx, mod); 2468 switch (ret) { 2469 case LDB_SUCCESS: 2470 return NT_STATUS_OK; 2471 case LDB_ERR_ENTRY_ALREADY_EXISTS: 2472 return NT_STATUS_MEMBER_IN_GROUP; 2473 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: 2474 return NT_STATUS_ACCESS_DENIED; 2475 default: 2740 2476 return NT_STATUS_UNSUCCESSFUL; 2741 2742 return NT_STATUS_OK; 2743 } 2744 2745 2746 /* 2747 samr_DeleteAliasMember 2477 } 2478 } 2479 2480 2481 /* 2482 samr_DeleteAliasMember 2748 2483 */ 2749 2484 static NTSTATUS dcesrv_samr_DeleteAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2755 2490 struct ldb_message *mod; 2756 2491 const char *memberdn; 2492 int ret; 2757 2493 2758 2494 DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS); … … 2762 2498 2763 2499 memberdn = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL, 2764 "distinguishedName", "(objectSid=%s)", 2500 "distinguishedName", "(objectSid=%s)", 2765 2501 ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid)); 2766 2767 if (memberdn == NULL) 2502 if (memberdn == NULL) { 2768 2503 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 2504 } 2769 2505 2770 2506 mod = ldb_msg_new(mem_ctx); … … 2775 2511 mod->dn = talloc_reference(mem_ctx, a_state->account_dn); 2776 2512 2777 if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member", 2778 memberdn) != 0) 2513 ret = samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member", 2514 memberdn); 2515 if (ret != LDB_SUCCESS) { 2779 2516 return NT_STATUS_UNSUCCESSFUL; 2780 2781 if (ldb_modify(a_state->sam_ctx, mod) != 0) 2517 } 2518 2519 ret = ldb_modify(a_state->sam_ctx, mod); 2520 switch (ret) { 2521 case LDB_SUCCESS: 2522 return NT_STATUS_OK; 2523 case LDB_ERR_UNWILLING_TO_PERFORM: 2524 return NT_STATUS_MEMBER_NOT_IN_GROUP; 2525 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: 2526 return NT_STATUS_ACCESS_DENIED; 2527 default: 2782 2528 return NT_STATUS_UNSUCCESSFUL; 2783 2784 return NT_STATUS_OK; 2785 } 2786 2787 2788 /* 2789 samr_GetMembersInAlias 2529 } 2530 } 2531 2532 2533 /* 2534 samr_GetMembersInAlias 2790 2535 */ 2791 2536 static NTSTATUS dcesrv_samr_GetMembersInAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2795 2540 struct samr_account_state *a_state; 2796 2541 struct samr_domain_state *d_state; 2797 struct ldb_message **msgs; 2798 struct lsa_SidPtr *sids; 2799 struct ldb_message_element *el; 2800 const char * const attrs[2] = { "member", NULL}; 2801 int ret; 2542 struct lsa_SidPtr *array; 2543 unsigned int i, num_members; 2544 struct dom_sid *members; 2545 NTSTATUS status; 2802 2546 2803 2547 DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS); … … 2806 2550 d_state = a_state->domain_state; 2807 2551 2808 ret = gendb_search_dn(d_state->sam_ctx, mem_ctx, 2809 a_state->account_dn, &msgs, attrs); 2810 2811 if (ret == -1) { 2812 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2813 } else if (ret == 0) { 2814 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 2815 } else if (ret != 1) { 2816 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2817 } 2818 2819 r->out.sids->num_sids = 0; 2820 r->out.sids->sids = NULL; 2821 2822 el = ldb_msg_find_element(msgs[0], "member"); 2823 2824 if (el != NULL) { 2825 int i; 2826 2827 sids = talloc_array(mem_ctx, struct lsa_SidPtr, 2828 el->num_values); 2829 2830 if (sids == NULL) 2831 return NT_STATUS_NO_MEMORY; 2832 2833 for (i=0; i<el->num_values; i++) { 2834 struct ldb_message **msgs2; 2835 const char * const attrs2[2] = { "objectSid", NULL }; 2836 ret = gendb_search_dn(a_state->sam_ctx, mem_ctx, 2837 ldb_dn_from_ldb_val(mem_ctx, a_state->sam_ctx, &el->values[i]), 2838 &msgs2, attrs2); 2839 if (ret != 1) 2840 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2841 2842 sids[i].sid = samdb_result_dom_sid(mem_ctx, msgs2[0], 2843 "objectSid"); 2844 2845 if (sids[i].sid == NULL) 2846 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2847 } 2848 r->out.sids->num_sids = el->num_values; 2849 r->out.sids->sids = sids; 2850 } 2851 2852 return NT_STATUS_OK; 2853 } 2854 2855 /* 2856 samr_OpenUser 2552 status = dsdb_enum_group_mem(d_state->sam_ctx, mem_ctx, 2553 a_state->account_dn, &members, 2554 &num_members); 2555 if (!NT_STATUS_IS_OK(status)) { 2556 return status; 2557 } 2558 2559 if (num_members == 0) { 2560 r->out.sids->sids = NULL; 2561 2562 return NT_STATUS_OK; 2563 } 2564 2565 array = talloc_array(mem_ctx, struct lsa_SidPtr, num_members); 2566 if (array == NULL) { 2567 return NT_STATUS_NO_MEMORY; 2568 } 2569 2570 for (i=0; i<num_members; i++) { 2571 array[i].sid = &members[i]; 2572 } 2573 2574 r->out.sids->num_sids = num_members; 2575 r->out.sids->sids = array; 2576 2577 return NT_STATUS_OK; 2578 } 2579 2580 /* 2581 samr_OpenUser 2857 2582 */ 2858 2583 static NTSTATUS dcesrv_samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2884 2609 ret = gendb_search(d_state->sam_ctx, 2885 2610 mem_ctx, d_state->domain_dn, &msgs, attrs, 2886 "(&(objectSid=%s)(objectclass=user))", 2611 "(&(objectSid=%s)(objectclass=user))", 2887 2612 ldap_encode_ndr_dom_sid(mem_ctx, sid)); 2888 2613 if (ret == 0) { … … 2890 2615 } 2891 2616 if (ret != 1) { 2892 DEBUG(0,("Found %d records matching sid %s\n", ret, 2617 DEBUG(0,("Found %d records matching sid %s\n", ret, 2893 2618 dom_sid_string(mem_ctx, sid))); 2894 2619 return NT_STATUS_INTERNAL_DB_CORRUPTION; 2895 2620 } 2896 2621 2897 account_name = samdb_result_string(msgs[0], "sAMAccountName", NULL);2622 account_name = ldb_msg_find_attr_as_string(msgs[0], "sAMAccountName", NULL); 2898 2623 if (account_name == NULL) { 2899 DEBUG(0,("sAMAccountName field missing for sid %s\n", 2624 DEBUG(0,("sAMAccountName field missing for sid %s\n", 2900 2625 dom_sid_string(mem_ctx, sid))); 2901 2626 return NT_STATUS_INTERNAL_DB_CORRUPTION; … … 2931 2656 2932 2657 2933 /* 2934 samr_DeleteUser 2658 /* 2659 samr_DeleteUser 2935 2660 */ 2936 2661 static NTSTATUS dcesrv_samr_DeleteUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 2948 2673 2949 2674 ret = ldb_delete(a_state->sam_ctx, a_state->account_dn); 2950 if (ret != 0) {2951 DEBUG(1, ("Failed to delete user: %s: %s\n", 2952 ldb_dn_get_linearized(a_state->account_dn), 2675 if (ret != LDB_SUCCESS) { 2676 DEBUG(1, ("Failed to delete user: %s: %s\n", 2677 ldb_dn_get_linearized(a_state->account_dn), 2953 2678 ldb_errstring(a_state->sam_ctx))); 2954 2679 return NT_STATUS_UNSUCCESSFUL; 2955 2680 } 2956 2681 2682 talloc_free(h); 2957 2683 ZERO_STRUCTP(r->out.user_handle); 2958 2684 … … 2961 2687 2962 2688 2963 /* 2964 samr_QueryUserInfo 2689 /* 2690 samr_QueryUserInfo 2965 2691 */ 2966 2692 static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 3036 2762 case 5: 3037 2763 { 3038 static const char * const attrs2[] = {"sAMAccountName", 2764 static const char * const attrs2[] = {"sAMAccountName", 3039 2765 "displayName", 3040 2766 "objectSid", … … 3042 2768 "homeDirectory", 3043 2769 "homeDrive", 3044 "scriptPath", 2770 "scriptPath", 3045 2771 "profilePath", 3046 2772 "description", … … 3137 2863 attrs = attrs2; 3138 2864 break; 2865 } 2866 case 18: 2867 { 2868 return NT_STATUS_NOT_SUPPORTED; 3139 2869 } 3140 2870 case 20: … … 3173 2903 break; 3174 2904 } 2905 case 23: 2906 case 24: 2907 case 25: 2908 case 26: 2909 { 2910 return NT_STATUS_NOT_SUPPORTED; 2911 } 2912 default: 2913 { 2914 return NT_STATUS_INVALID_INFO_CLASS; 2915 } 3175 2916 } 3176 2917 3177 2918 /* pull all the user attributes */ 3178 2919 ret = gendb_search_dn(a_state->sam_ctx, mem_ctx, 3179 a_state->account_dn ,&res, attrs); 2920 a_state->account_dn, &res, attrs); 2921 if (ret == 0) { 2922 return NT_STATUS_NO_SUCH_USER; 2923 } 3180 2924 if (ret != 1) { 3181 2925 return NT_STATUS_INTERNAL_DB_CORRUPTION; … … 3321 3065 QUERY_UINT (msg, info21.primary_gid, "primaryGroupID"); 3322 3066 QUERY_AFLAGS(msg, info21.acct_flags, "userAccountControl"); 3323 info->info21.fields_present = 0x0 0FFFFFF;3067 info->info21.fields_present = 0x08FFFFFF; 3324 3068 QUERY_LHOURS(msg, info21.logon_hours, "logonHours"); 3325 3069 QUERY_UINT (msg, info21.bad_password_count, "badPwdCount"); 3326 3070 QUERY_UINT (msg, info21.logon_count, "logonCount"); 3071 if ((info->info21.acct_flags & ACB_PW_EXPIRED) != 0) { 3072 info->info21.password_expired = PASS_MUST_CHANGE_AT_NEXT_LOGON; 3073 } else { 3074 info->info21.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON; 3075 } 3327 3076 QUERY_UINT (msg, info21.country_code, "countryCode"); 3328 3077 QUERY_UINT (msg, info21.code_page, "codePage"); 3329 3078 break; 3330 3079 3331 3080 3332 3081 default: … … 3341 3090 3342 3091 3343 /* 3344 samr_SetUserInfo 3092 /* 3093 samr_SetUserInfo 3345 3094 */ 3346 3095 static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 3426 3175 break; 3427 3176 3177 case 18: 3178 status = samr_set_password_buffers(dce_call, 3179 a_state->sam_ctx, 3180 a_state->account_dn, 3181 a_state->domain_state->domain_dn, 3182 mem_ctx, 3183 r->in.info->info18.lm_pwd_active ? r->in.info->info18.lm_pwd.hash : NULL, 3184 r->in.info->info18.nt_pwd_active ? r->in.info->info18.nt_pwd.hash : NULL); 3185 if (!NT_STATUS_IS_OK(status)) { 3186 return status; 3187 } 3188 3189 if (r->in.info->info18.password_expired > 0) { 3190 struct ldb_message_element *set_el; 3191 if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, "pwdLastSet", 0) != LDB_SUCCESS) { 3192 return NT_STATUS_NO_MEMORY; 3193 } 3194 set_el = ldb_msg_find_element(msg, "pwdLastSet"); 3195 set_el->flags = LDB_FLAG_MOD_REPLACE; 3196 } 3197 break; 3198 3428 3199 case 20: 3429 3200 SET_PARAMETERS(msg, info20.parameters, "userParameters"); … … 3431 3202 3432 3203 case 21: 3204 if (r->in.info->info21.fields_present == 0) 3205 return NT_STATUS_INVALID_PARAMETER; 3206 3433 3207 #define IFSET(bit) if (bit & r->in.info->info21.fields_present) 3208 IFSET(SAMR_FIELD_LAST_LOGON) 3209 SET_UINT64(msg, info21.last_logon, "lastLogon"); 3210 IFSET(SAMR_FIELD_LAST_LOGOFF) 3211 SET_UINT64(msg, info21.last_logoff, "lastLogoff"); 3434 3212 IFSET(SAMR_FIELD_ACCT_EXPIRY) 3435 3213 SET_UINT64(msg, info21.acct_expiry, "accountExpires"); 3436 IFSET(SAMR_FIELD_ACCOUNT_NAME) 3214 IFSET(SAMR_FIELD_ACCOUNT_NAME) 3437 3215 SET_STRING(msg, info21.account_name, "samAccountName"); 3438 IFSET(SAMR_FIELD_FULL_NAME) 3216 IFSET(SAMR_FIELD_FULL_NAME) 3439 3217 SET_STRING(msg, info21.full_name, "displayName"); 3440 3218 IFSET(SAMR_FIELD_HOME_DIRECTORY) … … 3452 3230 IFSET(SAMR_FIELD_COMMENT) 3453 3231 SET_STRING(msg, info21.comment, "comment"); 3454 IFSET(SAMR_FIELD_PARAMETERS) 3232 IFSET(SAMR_FIELD_PARAMETERS) 3455 3233 SET_PARAMETERS(msg, info21.parameters, "userParameters"); 3456 3234 IFSET(SAMR_FIELD_PRIMARY_GID) … … 3460 3238 IFSET(SAMR_FIELD_LOGON_HOURS) 3461 3239 SET_LHOURS(msg, info21.logon_hours, "logonHours"); 3240 IFSET(SAMR_FIELD_BAD_PWD_COUNT) 3241 SET_UINT (msg, info21.bad_password_count, "badPwdCount"); 3242 IFSET(SAMR_FIELD_NUM_LOGONS) 3243 SET_UINT (msg, info21.logon_count, "logonCount"); 3462 3244 IFSET(SAMR_FIELD_COUNTRY_CODE) 3463 3245 SET_UINT (msg, info21.country_code, "countryCode"); 3464 3246 IFSET(SAMR_FIELD_CODE_PAGE) 3465 3247 SET_UINT (msg, info21.code_page, "codePage"); 3248 3249 /* password change fields */ 3250 IFSET(SAMR_FIELD_LAST_PWD_CHANGE) 3251 return NT_STATUS_ACCESS_DENIED; 3252 3253 IFSET((SAMR_FIELD_LM_PASSWORD_PRESENT 3254 | SAMR_FIELD_NT_PASSWORD_PRESENT)) { 3255 uint8_t *lm_pwd_hash = NULL, *nt_pwd_hash = NULL; 3256 3257 if (r->in.info->info21.lm_password_set) { 3258 if ((r->in.info->info21.lm_owf_password.length != 16) 3259 || (r->in.info->info21.lm_owf_password.size != 16)) { 3260 return NT_STATUS_INVALID_PARAMETER; 3261 } 3262 3263 lm_pwd_hash = (uint8_t *) r->in.info->info21.lm_owf_password.array; 3264 } 3265 if (r->in.info->info21.nt_password_set) { 3266 if ((r->in.info->info21.nt_owf_password.length != 16) 3267 || (r->in.info->info21.nt_owf_password.size != 16)) { 3268 return NT_STATUS_INVALID_PARAMETER; 3269 } 3270 3271 nt_pwd_hash = (uint8_t *) r->in.info->info21.nt_owf_password.array; 3272 } 3273 status = samr_set_password_buffers(dce_call, 3274 a_state->sam_ctx, 3275 a_state->account_dn, 3276 a_state->domain_state->domain_dn, 3277 mem_ctx, 3278 lm_pwd_hash, 3279 nt_pwd_hash); 3280 if (!NT_STATUS_IS_OK(status)) { 3281 return status; 3282 } 3283 } 3284 3285 3286 IFSET(SAMR_FIELD_EXPIRED_FLAG) { 3287 NTTIME t = 0; 3288 struct ldb_message_element *set_el; 3289 if (r->in.info->info21.password_expired 3290 == PASS_DONT_CHANGE_AT_NEXT_LOGON) { 3291 unix_to_nt_time(&t, time(NULL)); 3292 } 3293 if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, 3294 "pwdLastSet", t) != LDB_SUCCESS) { 3295 return NT_STATUS_NO_MEMORY; 3296 } 3297 set_el = ldb_msg_find_element(msg, "pwdLastSet"); 3298 set_el->flags = LDB_FLAG_MOD_REPLACE; 3299 } 3466 3300 #undef IFSET 3467 3301 break; 3468 3302 3469 3303 case 23: 3304 if (r->in.info->info23.info.fields_present == 0) 3305 return NT_STATUS_INVALID_PARAMETER; 3306 3470 3307 #define IFSET(bit) if (bit & r->in.info->info23.info.fields_present) 3308 IFSET(SAMR_FIELD_LAST_LOGON) 3309 SET_UINT64(msg, info23.info.last_logon, "lastLogon"); 3310 IFSET(SAMR_FIELD_LAST_LOGOFF) 3311 SET_UINT64(msg, info23.info.last_logoff, "lastLogoff"); 3471 3312 IFSET(SAMR_FIELD_ACCT_EXPIRY) 3472 3313 SET_UINT64(msg, info23.info.acct_expiry, "accountExpires"); 3473 IFSET(SAMR_FIELD_ACCOUNT_NAME) 3314 IFSET(SAMR_FIELD_ACCOUNT_NAME) 3474 3315 SET_STRING(msg, info23.info.account_name, "samAccountName"); 3475 3316 IFSET(SAMR_FIELD_FULL_NAME) … … 3497 3338 IFSET(SAMR_FIELD_LOGON_HOURS) 3498 3339 SET_LHOURS(msg, info23.info.logon_hours, "logonHours"); 3340 IFSET(SAMR_FIELD_BAD_PWD_COUNT) 3341 SET_UINT (msg, info23.info.bad_password_count, "badPwdCount"); 3342 IFSET(SAMR_FIELD_NUM_LOGONS) 3343 SET_UINT (msg, info23.info.logon_count, "logonCount"); 3344 3499 3345 IFSET(SAMR_FIELD_COUNTRY_CODE) 3500 3346 SET_UINT (msg, info23.info.country_code, "countryCode"); 3501 3347 IFSET(SAMR_FIELD_CODE_PAGE) 3502 3348 SET_UINT (msg, info23.info.code_page, "codePage"); 3349 3350 /* password change fields */ 3351 IFSET(SAMR_FIELD_LAST_PWD_CHANGE) 3352 return NT_STATUS_ACCESS_DENIED; 3503 3353 3504 3354 IFSET(SAMR_FIELD_NT_PASSWORD_PRESENT) { … … 3507 3357 a_state->account_dn, 3508 3358 a_state->domain_state->domain_dn, 3509 mem_ctx, msg,3359 mem_ctx, 3510 3360 &r->in.info->info23.password); 3511 3361 } else IFSET(SAMR_FIELD_LM_PASSWORD_PRESENT) { … … 3514 3364 a_state->account_dn, 3515 3365 a_state->domain_state->domain_dn, 3516 mem_ctx, msg,3366 mem_ctx, 3517 3367 &r->in.info->info23.password); 3368 } 3369 if (!NT_STATUS_IS_OK(status)) { 3370 return status; 3371 } 3372 3373 IFSET(SAMR_FIELD_EXPIRED_FLAG) { 3374 NTTIME t = 0; 3375 struct ldb_message_element *set_el; 3376 if (r->in.info->info23.info.password_expired 3377 == PASS_DONT_CHANGE_AT_NEXT_LOGON) { 3378 unix_to_nt_time(&t, time(NULL)); 3379 } 3380 if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, 3381 "pwdLastSet", t) != LDB_SUCCESS) { 3382 return NT_STATUS_NO_MEMORY; 3383 } 3384 set_el = ldb_msg_find_element(msg, "pwdLastSet"); 3385 set_el->flags = LDB_FLAG_MOD_REPLACE; 3518 3386 } 3519 3387 #undef IFSET … … 3526 3394 a_state->account_dn, 3527 3395 a_state->domain_state->domain_dn, 3528 mem_ctx, msg,3396 mem_ctx, 3529 3397 &r->in.info->info24.password); 3398 if (!NT_STATUS_IS_OK(status)) { 3399 return status; 3400 } 3401 3402 if (r->in.info->info24.password_expired > 0) { 3403 struct ldb_message_element *set_el; 3404 if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, "pwdLastSet", 0) != LDB_SUCCESS) { 3405 return NT_STATUS_NO_MEMORY; 3406 } 3407 set_el = ldb_msg_find_element(msg, "pwdLastSet"); 3408 set_el->flags = LDB_FLAG_MOD_REPLACE; 3409 } 3530 3410 break; 3531 3411 3532 3412 case 25: 3413 if (r->in.info->info25.info.fields_present == 0) 3414 return NT_STATUS_INVALID_PARAMETER; 3415 3533 3416 #define IFSET(bit) if (bit & r->in.info->info25.info.fields_present) 3417 IFSET(SAMR_FIELD_LAST_LOGON) 3418 SET_UINT64(msg, info25.info.last_logon, "lastLogon"); 3419 IFSET(SAMR_FIELD_LAST_LOGOFF) 3420 SET_UINT64(msg, info25.info.last_logoff, "lastLogoff"); 3534 3421 IFSET(SAMR_FIELD_ACCT_EXPIRY) 3535 3422 SET_UINT64(msg, info25.info.acct_expiry, "accountExpires"); 3536 IFSET(SAMR_FIELD_ACCOUNT_NAME) 3423 IFSET(SAMR_FIELD_ACCOUNT_NAME) 3537 3424 SET_STRING(msg, info25.info.account_name, "samAccountName"); 3538 3425 IFSET(SAMR_FIELD_FULL_NAME) … … 3560 3447 IFSET(SAMR_FIELD_LOGON_HOURS) 3561 3448 SET_LHOURS(msg, info25.info.logon_hours, "logonHours"); 3449 IFSET(SAMR_FIELD_BAD_PWD_COUNT) 3450 SET_UINT (msg, info25.info.bad_password_count, "badPwdCount"); 3451 IFSET(SAMR_FIELD_NUM_LOGONS) 3452 SET_UINT (msg, info25.info.logon_count, "logonCount"); 3562 3453 IFSET(SAMR_FIELD_COUNTRY_CODE) 3563 3454 SET_UINT (msg, info25.info.country_code, "countryCode"); 3564 3455 IFSET(SAMR_FIELD_CODE_PAGE) 3565 3456 SET_UINT (msg, info25.info.code_page, "codePage"); 3457 3458 /* password change fields */ 3459 IFSET(SAMR_FIELD_LAST_PWD_CHANGE) 3460 return NT_STATUS_ACCESS_DENIED; 3566 3461 3567 3462 IFSET(SAMR_FIELD_NT_PASSWORD_PRESENT) { … … 3570 3465 a_state->account_dn, 3571 3466 a_state->domain_state->domain_dn, 3572 mem_ctx, msg,3467 mem_ctx, 3573 3468 &r->in.info->info25.password); 3574 3469 } else IFSET(SAMR_FIELD_LM_PASSWORD_PRESENT) { … … 3577 3472 a_state->account_dn, 3578 3473 a_state->domain_state->domain_dn, 3579 mem_ctx, msg,3474 mem_ctx, 3580 3475 &r->in.info->info25.password); 3476 } 3477 if (!NT_STATUS_IS_OK(status)) { 3478 return status; 3479 } 3480 3481 IFSET(SAMR_FIELD_EXPIRED_FLAG) { 3482 NTTIME t = 0; 3483 struct ldb_message_element *set_el; 3484 if (r->in.info->info25.info.password_expired 3485 == PASS_DONT_CHANGE_AT_NEXT_LOGON) { 3486 unix_to_nt_time(&t, time(NULL)); 3487 } 3488 if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, 3489 "pwdLastSet", t) != LDB_SUCCESS) { 3490 return NT_STATUS_NO_MEMORY; 3491 } 3492 set_el = ldb_msg_find_element(msg, "pwdLastSet"); 3493 set_el->flags = LDB_FLAG_MOD_REPLACE; 3581 3494 } 3582 3495 #undef IFSET … … 3589 3502 a_state->account_dn, 3590 3503 a_state->domain_state->domain_dn, 3591 mem_ctx, msg,3504 mem_ctx, 3592 3505 &r->in.info->info26.password); 3593 break; 3594 3506 if (!NT_STATUS_IS_OK(status)) { 3507 return status; 3508 } 3509 3510 if (r->in.info->info26.password_expired > 0) { 3511 struct ldb_message_element *set_el; 3512 if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, "pwdLastSet", 0) != LDB_SUCCESS) { 3513 return NT_STATUS_NO_MEMORY; 3514 } 3515 set_el = ldb_msg_find_element(msg, "pwdLastSet"); 3516 set_el->flags = LDB_FLAG_MOD_REPLACE; 3517 } 3518 break; 3595 3519 3596 3520 default: … … 3604 3528 3605 3529 /* modify the samdb record */ 3606 ret = ldb_modify(a_state->sam_ctx, msg); 3607 if (ret != 0) { 3608 DEBUG(1,("Failed to modify record %s: %s\n", 3609 ldb_dn_get_linearized(a_state->account_dn), 3610 ldb_errstring(a_state->sam_ctx))); 3611 3612 /* we really need samdb.c to return NTSTATUS */ 3613 return NT_STATUS_UNSUCCESSFUL; 3614 } 3615 3616 return NT_STATUS_OK; 3617 } 3618 3619 3620 /* 3621 samr_GetGroupsForUser 3530 if (msg->num_elements > 0) { 3531 ret = ldb_modify(a_state->sam_ctx, msg); 3532 if (ret != LDB_SUCCESS) { 3533 DEBUG(1,("Failed to modify record %s: %s\n", 3534 ldb_dn_get_linearized(a_state->account_dn), 3535 ldb_errstring(a_state->sam_ctx))); 3536 3537 /* we really need samdb.c to return NTSTATUS */ 3538 return NT_STATUS_UNSUCCESSFUL; 3539 } 3540 } 3541 3542 return NT_STATUS_OK; 3543 } 3544 3545 3546 /* 3547 samr_GetGroupsForUser 3622 3548 */ 3623 3549 static NTSTATUS dcesrv_samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 3640 3566 d_state->domain_dn, &res, 3641 3567 attrs, d_state->domain_sid, 3642 "(&(member=%s)( grouptype=%d)(objectclass=group))",3568 "(&(member=%s)(|(grouptype=%d)(grouptype=%d))(objectclass=group))", 3643 3569 ldb_dn_get_linearized(a_state->account_dn), 3570 GTYPE_SECURITY_UNIVERSAL_GROUP, 3644 3571 GTYPE_SECURITY_GLOBAL_GROUP); 3645 3572 if (count < 0) … … 3672 3599 group_sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid"); 3673 3600 if (group_sid == NULL) { 3674 DEBUG(0, ("Couldn't find objectSid attrib\n")); 3675 continue; 3601 return NT_STATUS_INTERNAL_DB_CORRUPTION; 3676 3602 } 3677 3603 … … 3689 3615 3690 3616 3691 /* 3692 samr_QueryDisplayInfo 3617 /* 3618 samr_QueryDisplayInfo 3693 3619 */ 3694 3620 static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 3697 3623 struct dcesrv_handle *h; 3698 3624 struct samr_domain_state *d_state; 3699 struct ldb_message **res; 3700 int ldb_cnt, count, i; 3625 struct ldb_result *res; 3626 unsigned int i; 3627 uint32_t count; 3701 3628 const char * const attrs[] = { "objectSid", "sAMAccountName", 3702 3629 "displayName", "description", "userAccountControl", … … 3707 3634 struct samr_DispEntryGeneral *entriesGeneral = NULL; 3708 3635 const char *filter; 3636 int ret; 3709 3637 3710 3638 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN); … … 3716 3644 case 4: 3717 3645 filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)" 3718 "(sAMAccountType=% u))",3646 "(sAMAccountType=%d))", 3719 3647 ATYPE_NORMAL_ACCOUNT); 3720 3648 break; 3721 3649 case 2: 3722 3650 filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)" 3723 "(sAMAccountType=% u))",3651 "(sAMAccountType=%d))", 3724 3652 ATYPE_WORKSTATION_TRUST); 3725 3653 break; 3726 3654 case 3: 3727 3655 case 5: 3728 filter = talloc_asprintf(mem_ctx, "(&(grouptype=%d)" 3729 "(objectclass=group))", 3656 filter = talloc_asprintf(mem_ctx, 3657 "(&(|(groupType=%d)(groupType=%d))" 3658 "(objectClass=group))", 3659 GTYPE_SECURITY_UNIVERSAL_GROUP, 3730 3660 GTYPE_SECURITY_GLOBAL_GROUP); 3731 3661 break; … … 3734 3664 } 3735 3665 3736 /* search for all requested objects in this domain. This could3666 /* search for all requested objects in all domains. This could 3737 3667 possibly be cached and resumed based on resume_key */ 3738 ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx, 3739 d_state->domain_dn, &res, attrs, 3740 d_state->domain_sid, "%s", filter); 3741 if (ldb_cnt == -1) { 3668 ret = dsdb_search(d_state->sam_ctx, mem_ctx, &res, NULL, 3669 LDB_SCOPE_SUBTREE, attrs, 0, "%s", filter); 3670 if (ret != LDB_SUCCESS) { 3742 3671 return NT_STATUS_INTERNAL_DB_CORRUPTION; 3743 3672 } 3744 if ( ldb_cnt == 0 || r->in.max_entries == 0) {3673 if ((res->count == 0) || (r->in.max_entries == 0)) { 3745 3674 return NT_STATUS_OK; 3746 3675 } … … 3749 3678 case 1: 3750 3679 entriesGeneral = talloc_array(mem_ctx, 3751 struct samr_DispEntryGeneral,3752 ldb_cnt);3680 struct samr_DispEntryGeneral, 3681 res->count); 3753 3682 break; 3754 3683 case 2: 3755 3684 entriesFull = talloc_array(mem_ctx, 3756 3757 ldb_cnt);3685 struct samr_DispEntryFull, 3686 res->count); 3758 3687 break; 3759 3688 case 3: 3760 3689 entriesFullGroup = talloc_array(mem_ctx, 3761 3762 ldb_cnt);3690 struct samr_DispEntryFullGroup, 3691 res->count); 3763 3692 break; 3764 3693 case 4: 3765 3694 case 5: 3766 3695 entriesAscii = talloc_array(mem_ctx, 3767 3768 ldb_cnt);3696 struct samr_DispEntryAscii, 3697 res->count); 3769 3698 break; 3770 3699 } … … 3776 3705 count = 0; 3777 3706 3778 for (i =0; i<ldb_cnt; i++) {3707 for (i = 0; i < res->count; i++) { 3779 3708 struct dom_sid *objectsid; 3780 3709 3781 objectsid = samdb_result_dom_sid(mem_ctx, res [i],3710 objectsid = samdb_result_dom_sid(mem_ctx, res->msgs[i], 3782 3711 "objectSid"); 3783 3712 if (objectsid == NULL) … … 3787 3716 case 1: 3788 3717 entriesGeneral[count].idx = count + 1; 3789 entriesGeneral[count].rid = 3718 entriesGeneral[count].rid = 3790 3719 objectsid->sub_auths[objectsid->num_auths-1]; 3791 3720 entriesGeneral[count].acct_flags = 3792 samdb_result_acct_flags(d_state->sam_ctx, mem_ctx, 3793 res[i], 3721 samdb_result_acct_flags(d_state->sam_ctx, 3722 mem_ctx, 3723 res->msgs[i], 3794 3724 d_state->domain_dn); 3795 3725 entriesGeneral[count].account_name.string = 3796 samdb_result_string(res[i],3797 "sAMAccountName", "");3726 ldb_msg_find_attr_as_string(res->msgs[i], 3727 "sAMAccountName", ""); 3798 3728 entriesGeneral[count].full_name.string = 3799 samdb_result_string(res[i], "displayName", ""); 3729 ldb_msg_find_attr_as_string(res->msgs[i], 3730 "displayName", ""); 3800 3731 entriesGeneral[count].description.string = 3801 samdb_result_string(res[i], "description", ""); 3732 ldb_msg_find_attr_as_string(res->msgs[i], 3733 "description", ""); 3802 3734 break; 3803 3735 case 2: … … 3808 3740 /* No idea why we need to or in ACB_NORMAL here, but this is what Win2k3 seems to do... */ 3809 3741 entriesFull[count].acct_flags = 3810 samdb_result_acct_flags(d_state->sam_ctx, mem_ctx, 3811 res[i], 3742 samdb_result_acct_flags(d_state->sam_ctx, 3743 mem_ctx, 3744 res->msgs[i], 3812 3745 d_state->domain_dn) | ACB_NORMAL; 3813 3746 entriesFull[count].account_name.string = 3814 samdb_result_string(res[i], "sAMAccountName",3815 3747 ldb_msg_find_attr_as_string(res->msgs[i], 3748 "sAMAccountName", ""); 3816 3749 entriesFull[count].description.string = 3817 samdb_result_string(res[i], "description", ""); 3750 ldb_msg_find_attr_as_string(res->msgs[i], 3751 "description", ""); 3818 3752 break; 3819 3753 case 3: … … 3825 3759 = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; 3826 3760 entriesFullGroup[count].account_name.string = 3827 samdb_result_string(res[i], "sAMAccountName",3828 3761 ldb_msg_find_attr_as_string(res->msgs[i], 3762 "sAMAccountName", ""); 3829 3763 entriesFullGroup[count].description.string = 3830 samdb_result_string(res[i], "description", ""); 3764 ldb_msg_find_attr_as_string(res->msgs[i], 3765 "description", ""); 3831 3766 break; 3832 3767 case 4: … … 3834 3769 entriesAscii[count].idx = count + 1; 3835 3770 entriesAscii[count].account_name.string = 3836 samdb_result_string(res[i], "sAMAccountName",3837 3771 ldb_msg_find_attr_as_string(res->msgs[i], 3772 "sAMAccountName", ""); 3838 3773 break; 3839 3774 } … … 3905 3840 3906 3841 3907 /* 3908 samr_GetDisplayEnumerationIndex 3842 /* 3843 samr_GetDisplayEnumerationIndex 3909 3844 */ 3910 3845 static NTSTATUS dcesrv_samr_GetDisplayEnumerationIndex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 3915 3850 3916 3851 3917 /* 3918 samr_TestPrivateFunctionsDomain 3852 /* 3853 samr_TestPrivateFunctionsDomain 3919 3854 */ 3920 3855 static NTSTATUS dcesrv_samr_TestPrivateFunctionsDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 3925 3860 3926 3861 3927 /* 3928 samr_TestPrivateFunctionsUser 3862 /* 3863 samr_TestPrivateFunctionsUser 3929 3864 */ 3930 3865 static NTSTATUS dcesrv_samr_TestPrivateFunctionsUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 3935 3870 3936 3871 3937 /* 3938 samr_GetUserPwInfo 3872 /* 3873 samr_GetUserPwInfo 3939 3874 */ 3940 3875 static NTSTATUS dcesrv_samr_GetUserPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 3960 3895 3961 3896 3962 /* 3963 samr_RemoveMemberFromForeignDomain 3964 */ 3965 static NTSTATUS dcesrv_samr_RemoveMemberFromForeignDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 3966 struct samr_RemoveMemberFromForeignDomain *r) 3897 /* 3898 samr_RemoveMemberFromForeignDomain 3899 */ 3900 static NTSTATUS dcesrv_samr_RemoveMemberFromForeignDomain(struct dcesrv_call_state *dce_call, 3901 TALLOC_CTX *mem_ctx, 3902 struct samr_RemoveMemberFromForeignDomain *r) 3967 3903 { 3968 3904 struct dcesrv_handle *h; … … 3970 3906 const char *memberdn; 3971 3907 struct ldb_message **res; 3972 const char * const attrs[3] = { "distinguishedName", "objectSid",NULL };3908 const char *no_attrs[] = { NULL }; 3973 3909 int i, count; 3974 3910 … … 3978 3914 3979 3915 memberdn = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL, 3980 "distinguishedName", "(objectSid=%s)", 3916 "distinguishedName", "(objectSid=%s)", 3981 3917 ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid)); 3982 3918 /* Nothing to do */ … … 3985 3921 } 3986 3922 3987 /* TODO: Does this call only remove alias members, or does it do this3988 * for domain groups as well? */3989 3990 3923 count = samdb_search_domain(d_state->sam_ctx, mem_ctx, 3991 d_state->domain_dn, &res, attrs,3924 d_state->domain_dn, &res, no_attrs, 3992 3925 d_state->domain_sid, 3993 3926 "(&(member=%s)(objectClass=group)" … … 4008 3941 } 4009 3942 4010 mod->dn = samdb_result_dn(d_state->sam_ctx, mod, res[i], "distinguishedName", NULL); 4011 if (mod->dn == NULL) { 4012 talloc_free(mod); 4013 continue; 4014 } 3943 mod->dn = res[i]->dn; 4015 3944 4016 3945 if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, 4017 "member", memberdn) != 0)3946 "member", memberdn) != LDB_SUCCESS) 4018 3947 return NT_STATUS_NO_MEMORY; 4019 3948 4020 if (ldb_modify(d_state->sam_ctx, mod) != 0)3949 if (ldb_modify(d_state->sam_ctx, mod) != LDB_SUCCESS) 4021 3950 return NT_STATUS_UNSUCCESSFUL; 4022 3951 … … 4028 3957 4029 3958 4030 /* 4031 samr_QueryDomainInfo2 3959 /* 3960 samr_QueryDomainInfo2 4032 3961 4033 3962 just an alias for samr_QueryDomainInfo … … 4045 3974 4046 3975 status = dcesrv_samr_QueryDomainInfo(dce_call, mem_ctx, &r1); 4047 3976 4048 3977 return status; 4049 3978 } 4050 3979 4051 3980 4052 /* 4053 samr_QueryUserInfo2 3981 /* 3982 samr_QueryUserInfo2 4054 3983 4055 3984 just an alias for samr_QueryUserInfo … … 4064 3993 r1.in.level = r->in.level; 4065 3994 r1.out.info = r->out.info; 4066 3995 4067 3996 status = dcesrv_samr_QueryUserInfo(dce_call, mem_ctx, &r1); 4068 3997 … … 4071 4000 4072 4001 4073 /* 4074 samr_QueryDisplayInfo2 4002 /* 4003 samr_QueryDisplayInfo2 4075 4004 */ 4076 4005 static NTSTATUS dcesrv_samr_QueryDisplayInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 4095 4024 4096 4025 4097 /* 4098 samr_GetDisplayEnumerationIndex2 4026 /* 4027 samr_GetDisplayEnumerationIndex2 4099 4028 */ 4100 4029 static NTSTATUS dcesrv_samr_GetDisplayEnumerationIndex2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 4105 4034 4106 4035 4107 /* 4108 samr_QueryDisplayInfo3 4036 /* 4037 samr_QueryDisplayInfo3 4109 4038 */ 4110 4039 static NTSTATUS dcesrv_samr_QueryDisplayInfo3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 4129 4058 4130 4059 4131 /* 4132 samr_AddMultipleMembersToAlias 4060 /* 4061 samr_AddMultipleMembersToAlias 4133 4062 */ 4134 4063 static NTSTATUS dcesrv_samr_AddMultipleMembersToAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 4139 4068 4140 4069 4141 /* 4142 samr_RemoveMultipleMembersFromAlias 4070 /* 4071 samr_RemoveMultipleMembersFromAlias 4143 4072 */ 4144 4073 static NTSTATUS dcesrv_samr_RemoveMultipleMembersFromAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 4149 4078 4150 4079 4151 /* 4152 samr_GetDomPwInfo 4080 /* 4081 samr_GetDomPwInfo 4153 4082 4154 4083 this fetches the default password properties for a domain 4155 4084 4156 note that w2k3 completely ignores the domain name in this call, and 4085 note that w2k3 completely ignores the domain name in this call, and 4157 4086 always returns the information for the servers primary domain 4158 4087 */ … … 4167 4096 ZERO_STRUCTP(r->out.info); 4168 4097 4169 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info); 4098 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, 4099 dce_call->conn->dce_ctx->lp_ctx, 4100 dce_call->conn->auth_state.session_info, 0); 4170 4101 if (sam_ctx == NULL) { 4171 4102 return NT_STATUS_INVALID_SYSTEM_SERVICE; … … 4173 4104 4174 4105 /* The domain name in this call is ignored */ 4175 ret = gendb_search_dn(sam_ctx, 4106 ret = gendb_search_dn(sam_ctx, 4176 4107 mem_ctx, NULL, &msgs, attrs); 4177 4108 if (ret <= 0) { 4109 talloc_free(sam_ctx); 4110 4178 4111 return NT_STATUS_NO_SUCH_DOMAIN; 4179 4112 } 4180 4113 if (ret > 1) { 4181 4114 talloc_free(msgs); 4115 talloc_free(sam_ctx); 4116 4182 4117 return NT_STATUS_INTERNAL_DB_CORRUPTION; 4183 4118 } 4184 4119 4185 r->out.info->min_password_length = samdb_result_uint(msgs[0],4120 r->out.info->min_password_length = ldb_msg_find_attr_as_uint(msgs[0], 4186 4121 "minPwdLength", 0); 4187 r->out.info->password_properties = samdb_result_uint(msgs[0],4122 r->out.info->password_properties = ldb_msg_find_attr_as_uint(msgs[0], 4188 4123 "pwdProperties", 1); 4189 4124 4190 4125 talloc_free(msgs); 4191 4192 talloc_free(sam_ctx); 4193 return NT_STATUS_OK; 4194 } 4195 4196 4197 /* 4198 samr_Connect2 4126 talloc_unlink(mem_ctx, sam_ctx); 4127 4128 return NT_STATUS_OK; 4129 } 4130 4131 4132 /* 4133 samr_Connect2 4199 4134 */ 4200 4135 static NTSTATUS dcesrv_samr_Connect2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 4211 4146 4212 4147 4213 /* 4214 samr_SetUserInfo2 4148 /* 4149 samr_SetUserInfo2 4215 4150 4216 4151 just an alias for samr_SetUserInfo … … 4229 4164 4230 4165 4231 /* 4232 samr_SetBootKeyInformation 4166 /* 4167 samr_SetBootKeyInformation 4233 4168 */ 4234 4169 static NTSTATUS dcesrv_samr_SetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 4239 4174 4240 4175 4241 /* 4242 samr_GetBootKeyInformation 4176 /* 4177 samr_GetBootKeyInformation 4243 4178 */ 4244 4179 static NTSTATUS dcesrv_samr_GetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 4245 4180 struct samr_GetBootKeyInformation *r) 4246 4181 { 4247 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); 4248 } 4249 4250 4251 /* 4252 samr_Connect3 4182 /* Windows Server 2008 returns this */ 4183 return NT_STATUS_NOT_SUPPORTED; 4184 } 4185 4186 4187 /* 4188 samr_Connect3 4253 4189 */ 4254 4190 static NTSTATUS dcesrv_samr_Connect3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 4265 4201 4266 4202 4267 /* 4268 samr_Connect4 4203 /* 4204 samr_Connect4 4269 4205 */ 4270 4206 static NTSTATUS dcesrv_samr_Connect4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 4281 4217 4282 4218 4283 /* 4284 samr_Connect5 4219 /* 4220 samr_Connect5 4285 4221 */ 4286 4222 static NTSTATUS dcesrv_samr_Connect5(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 4304 4240 4305 4241 4306 /* 4307 samr_RidToSid 4242 /* 4243 samr_RidToSid 4308 4244 */ 4309 4245 static NTSTATUS dcesrv_samr_RidToSid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 4327 4263 4328 4264 4329 /* 4330 samr_SetDsrmPassword 4265 /* 4266 samr_SetDsrmPassword 4331 4267 */ 4332 4268 static NTSTATUS dcesrv_samr_SetDsrmPassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 4337 4273 4338 4274 4339 /* 4340 samr_ValidatePassword 4341 */ 4342 static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 4343 struct samr_ValidatePassword *r) 4344 { 4345 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); 4275 /* 4276 samr_ValidatePassword 4277 4278 For now the call checks the password complexity (if active) and the minimum 4279 password length on level 2 and 3. Level 1 is ignored for now. 4280 */ 4281 static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call, 4282 TALLOC_CTX *mem_ctx, 4283 struct samr_ValidatePassword *r) 4284 { 4285 struct samr_GetDomPwInfo r2; 4286 struct samr_PwInfo pwInfo; 4287 DATA_BLOB password; 4288 enum samr_ValidationStatus res; 4289 NTSTATUS status; 4290 4291 (*r->out.rep) = talloc_zero(mem_ctx, union samr_ValidatePasswordRep); 4292 4293 r2.in.domain_name = NULL; 4294 r2.out.info = &pwInfo; 4295 status = dcesrv_samr_GetDomPwInfo(dce_call, mem_ctx, &r2); 4296 if (!NT_STATUS_IS_OK(status)) { 4297 return status; 4298 } 4299 4300 switch (r->in.level) { 4301 case NetValidateAuthentication: 4302 /* we don't support this yet */ 4303 return NT_STATUS_NOT_SUPPORTED; 4304 break; 4305 case NetValidatePasswordChange: 4306 password = data_blob_const(r->in.req->req2.password.string, 4307 r->in.req->req2.password.length); 4308 res = samdb_check_password(&password, 4309 pwInfo.password_properties, 4310 pwInfo.min_password_length); 4311 (*r->out.rep)->ctr2.status = res; 4312 break; 4313 case NetValidatePasswordReset: 4314 password = data_blob_const(r->in.req->req3.password.string, 4315 r->in.req->req3.password.length); 4316 res = samdb_check_password(&password, 4317 pwInfo.password_properties, 4318 pwInfo.min_password_length); 4319 (*r->out.rep)->ctr3.status = res; 4320 break; 4321 default: 4322 return NT_STATUS_INVALID_INFO_CLASS; 4323 break; 4324 } 4325 4326 return NT_STATUS_OK; 4346 4327 } 4347 4328 -
trunk/server/source4/rpc_server/samr/dcesrv_samr.h
r414 r745 1 /* 1 /* 2 2 Unix SMB/CIFS implementation. 3 3 … … 5 5 6 6 Copyright (C) Andrew Tridgell 2004 7 7 8 8 This program is free software; you can redistribute it and/or modify 9 9 it under the terms of the GNU General Public License as published by 10 10 the Free Software Foundation; either version 3 of the License, or 11 11 (at your option) any later version. 12 12 13 13 This program is distributed in the hope that it will be useful, 14 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 16 GNU General Public License for more details. 17 17 18 18 You should have received a copy of the GNU General Public License 19 19 along with this program. If not, see <http://www.gnu.org/licenses/>. -
trunk/server/source4/rpc_server/samr/samr_password.c
r414 r745 1 /* 1 /* 2 2 Unix SMB/CIFS implementation. 3 3 … … 6 6 Copyright (C) Andrew Tridgell 2004 7 7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 8 8 9 9 This program is free software; you can redistribute it and/or modify 10 10 it under the terms of the GNU General Public License as published by 11 11 the Free Software Foundation; either version 3 of the License, or 12 12 (at your option) any later version. 13 13 14 14 This program is distributed in the hope that it will be useful, 15 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 17 GNU General Public License for more details. 18 18 19 19 You should have received a copy of the GNU General Public License 20 20 along with this program. If not, see <http://www.gnu.org/licenses/>. … … 31 31 #include "../lib/util/util_ldb.h" 32 32 33 /* 34 samr_ChangePasswordUser 35 */ 36 NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, 33 /* 34 samr_ChangePasswordUser 35 */ 36 NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, 37 37 TALLOC_CTX *mem_ctx, 38 38 struct samr_ChangePasswordUser *r) … … 41 41 struct samr_account_state *a_state; 42 42 struct ldb_context *sam_ctx; 43 struct ldb_message **res , *msg;43 struct ldb_message **res; 44 44 int ret; 45 45 struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash; … … 61 61 } 62 62 63 /* To change a password we need to open as system */ 64 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx)); 63 /* Connect to a SAMDB with system privileges for fetching the old pw 64 * hashes. */ 65 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, 66 dce_call->conn->dce_ctx->lp_ctx, 67 system_session(dce_call->conn->dce_ctx->lp_ctx), 0); 65 68 if (sam_ctx == NULL) { 66 69 return NT_STATUS_INVALID_SYSTEM_SERVICE; 67 }68 69 ret = ldb_transaction_start(sam_ctx);70 if (ret) {71 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));72 return NT_STATUS_TRANSACTION_ABORTED;73 70 } 74 71 … … 77 74 a_state->account_dn, &res, attrs); 78 75 if (ret != 1) { 79 ldb_transaction_cancel(sam_ctx); 80 return NT_STATUS_WRONG_PASSWORD; 81 } 82 msg = res[0]; 83 84 status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, 85 msg, &lm_pwd, &nt_pwd); 76 return NT_STATUS_WRONG_PASSWORD; 77 } 78 79 status = samdb_result_passwords(mem_ctx, 80 dce_call->conn->dce_ctx->lp_ctx, 81 res[0], &lm_pwd, &nt_pwd); 86 82 if (!NT_STATUS_IS_OK(status) || !nt_pwd) { 87 ldb_transaction_cancel(sam_ctx);88 83 return NT_STATUS_WRONG_PASSWORD; 89 84 } … … 94 89 D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash); 95 90 if (memcmp(checkHash.hash, lm_pwd, 16) != 0) { 96 ldb_transaction_cancel(sam_ctx);97 91 return NT_STATUS_WRONG_PASSWORD; 98 92 } … … 103 97 D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash); 104 98 if (memcmp(checkHash.hash, nt_pwd, 16) != 0) { 105 ldb_transaction_cancel(sam_ctx); 106 return NT_STATUS_WRONG_PASSWORD; 107 } 108 99 return NT_STATUS_WRONG_PASSWORD; 100 } 101 109 102 /* The NT Cross is not required by Win2k3 R2, but if present 110 103 check the nt cross hash */ … … 112 105 D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash); 113 106 if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) { 114 ldb_transaction_cancel(sam_ctx);115 107 return NT_STATUS_WRONG_PASSWORD; 116 108 } … … 122 114 D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash); 123 115 if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) { 124 ldb_transaction_cancel(sam_ctx);125 116 return NT_STATUS_WRONG_PASSWORD; 126 117 } 127 118 } 128 119 129 msg = ldb_msg_new(mem_ctx); 130 if (msg == NULL) { 131 ldb_transaction_cancel(sam_ctx); 132 return NT_STATUS_NO_MEMORY; 133 } 134 135 msg->dn = ldb_dn_copy(msg, a_state->account_dn); 136 if (!msg->dn) { 137 ldb_transaction_cancel(sam_ctx); 138 return NT_STATUS_NO_MEMORY; 139 } 140 141 /* setup password modify mods on the user DN specified. This may fail 142 * due to password policies. */ 120 /* Start a SAM with user privileges for the password change */ 121 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, 122 dce_call->conn->dce_ctx->lp_ctx, 123 dce_call->conn->auth_state.session_info, 0); 124 if (sam_ctx == NULL) { 125 return NT_STATUS_INVALID_SYSTEM_SERVICE; 126 } 127 128 /* Start transaction */ 129 ret = ldb_transaction_start(sam_ctx); 130 if (ret != LDB_SUCCESS) { 131 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx))); 132 return NT_STATUS_TRANSACTION_ABORTED; 133 } 134 135 /* Performs the password modification. We pass the old hashes read out 136 * from the database since they were already checked against the user- 137 * provided ones. */ 143 138 status = samdb_set_password(sam_ctx, mem_ctx, 144 a_state->account_dn, a_state->domain_state->domain_dn, 145 msg, NULL, &new_lmPwdHash, &new_ntPwdHash, 146 true, /* this is a user password change */ 139 a_state->account_dn, 140 a_state->domain_state->domain_dn, 141 NULL, &new_lmPwdHash, &new_ntPwdHash, 142 lm_pwd, nt_pwd, /* this is a user password change */ 147 143 NULL, 148 144 NULL); … … 152 148 } 153 149 154 /* The above call only setup the modifications, this actually155 * makes the write to the database. */156 ret = samdb_replace(sam_ctx, mem_ctx, msg);157 if (ret != 0) {158 DEBUG(2,("Failed to modify record to change password on %s: %s\n",159 ldb_dn_get_linearized(a_state->account_dn),160 ldb_errstring(sam_ctx)));161 ldb_transaction_cancel(sam_ctx);162 return NT_STATUS_INTERNAL_DB_CORRUPTION;163 }164 165 150 /* And this confirms it in a transaction commit */ 166 151 ret = ldb_transaction_commit(sam_ctx); 167 if (ret != 0) {152 if (ret != LDB_SUCCESS) { 168 153 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n", 169 154 ldb_dn_get_linearized(a_state->account_dn), … … 175 160 } 176 161 177 /* 178 samr_OemChangePasswordUser2 179 */ 180 NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 181 struct samr_OemChangePasswordUser2 *r) 162 /* 163 samr_OemChangePasswordUser2 164 */ 165 NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, 166 TALLOC_CTX *mem_ctx, 167 struct samr_OemChangePasswordUser2 *r) 182 168 { 183 169 NTSTATUS status; … … 188 174 struct ldb_dn *user_dn; 189 175 int ret; 190 struct ldb_message **res , *mod;176 struct ldb_message **res; 191 177 const char * const attrs[] = { "objectSid", "dBCSPwd", NULL }; 192 178 struct samr_Password *lm_pwd; … … 205 191 206 192 /* this call can only work with lanman auth */ 207 if (!lp_lanman_auth(dce_call->conn->dce_ctx->lp_ctx)) { 208 return NT_STATUS_NOT_SUPPORTED; 209 } 210 211 /* To change a password we need to open as system */ 212 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx)); 193 if (!lpcfg_lanman_auth(dce_call->conn->dce_ctx->lp_ctx)) { 194 return NT_STATUS_WRONG_PASSWORD; 195 } 196 197 /* Connect to a SAMDB with system privileges for fetching the old pw 198 * hashes. */ 199 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, 200 dce_call->conn->dce_ctx->lp_ctx, 201 system_session(dce_call->conn->dce_ctx->lp_ctx), 0); 213 202 if (sam_ctx == NULL) { 214 203 return NT_STATUS_INVALID_SYSTEM_SERVICE; 215 }216 217 ret = ldb_transaction_start(sam_ctx);218 if (ret) {219 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));220 return NT_STATUS_TRANSACTION_ABORTED;221 204 } 222 205 … … 224 207 user SID). We also need the current lm password hash in 225 208 order to decrypt the incoming password */ 226 ret = gendb_search(sam_ctx, 209 ret = gendb_search(sam_ctx, 227 210 mem_ctx, NULL, &res, attrs, 228 211 "(&(sAMAccountName=%s)(objectclass=user))", 229 212 r->in.account->string); 230 213 if (ret != 1) { 231 ldb_transaction_cancel(sam_ctx);232 214 /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */ 233 215 return NT_STATUS_WRONG_PASSWORD; … … 239 221 res[0], &lm_pwd, NULL); 240 222 if (!NT_STATUS_IS_OK(status) || !lm_pwd) { 241 ldb_transaction_cancel(sam_ctx);242 223 return NT_STATUS_WRONG_PASSWORD; 243 224 } 244 225 245 226 /* decrypt the password we have been given */ 246 lm_pwd_blob = data_blob(lm_pwd->hash, sizeof(lm_pwd->hash)); 227 lm_pwd_blob = data_blob(lm_pwd->hash, sizeof(lm_pwd->hash)); 247 228 arcfour_crypt_blob(pwbuf->data, 516, &lm_pwd_blob); 248 229 data_blob_free(&lm_pwd_blob); 249 230 250 231 if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) { 251 ldb_transaction_cancel(sam_ctx);252 232 DEBUG(3,("samr: failed to decode password buffer\n")); 253 233 return NT_STATUS_WRONG_PASSWORD; 254 234 } 255 256 if (!convert_string_talloc_convenience(mem_ctx, lp _iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),257 CH_DOS, CH_UNIX, 258 (const char *)new_password.data, 235 236 if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx), 237 CH_DOS, CH_UNIX, 238 (const char *)new_password.data, 259 239 new_password.length, 260 240 (void **)&new_pass, NULL, false)) { 261 241 DEBUG(3,("samr: failed to convert incoming password buffer to unix charset\n")); 262 ldb_transaction_cancel(sam_ctx); 263 return NT_STATUS_WRONG_PASSWORD; 264 } 265 266 if (!convert_string_talloc_convenience(mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx), 267 CH_DOS, CH_UTF16, 268 (const char *)new_password.data, 242 return NT_STATUS_WRONG_PASSWORD; 243 } 244 245 if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx), 246 CH_DOS, CH_UTF16, 247 (const char *)new_password.data, 269 248 new_password.length, 270 249 (void **)&new_unicode_password.data, &unicode_pw_len, false)) { 271 250 DEBUG(3,("samr: failed to convert incoming password buffer to UTF16 charset\n")); 272 ldb_transaction_cancel(sam_ctx);273 251 return NT_STATUS_WRONG_PASSWORD; 274 252 } … … 278 256 E_old_pw_hash(new_lm_hash, lm_pwd->hash, lm_verifier.hash); 279 257 if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) { 280 ldb_transaction_cancel(sam_ctx); 281 return NT_STATUS_WRONG_PASSWORD; 282 } 283 284 mod = ldb_msg_new(mem_ctx); 285 if (mod == NULL) { 286 ldb_transaction_cancel(sam_ctx); 287 return NT_STATUS_NO_MEMORY; 288 } 289 290 mod->dn = ldb_dn_copy(mod, user_dn); 291 if (!mod->dn) { 292 ldb_transaction_cancel(sam_ctx); 293 return NT_STATUS_NO_MEMORY; 294 } 295 296 /* set the password on the user DN specified. This may fail 297 * due to password policies */ 258 return NT_STATUS_WRONG_PASSWORD; 259 } 260 261 /* Connect to a SAMDB with user privileges for the password change */ 262 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, 263 dce_call->conn->dce_ctx->lp_ctx, 264 dce_call->conn->auth_state.session_info, 0); 265 if (sam_ctx == NULL) { 266 return NT_STATUS_INVALID_SYSTEM_SERVICE; 267 } 268 269 /* Start transaction */ 270 ret = ldb_transaction_start(sam_ctx); 271 if (ret != LDB_SUCCESS) { 272 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx))); 273 return NT_STATUS_TRANSACTION_ABORTED; 274 } 275 276 /* Performs the password modification. We pass the old hashes read out 277 * from the database since they were already checked against the user- 278 * provided ones. */ 298 279 status = samdb_set_password(sam_ctx, mem_ctx, 299 user_dn, NULL, 300 mod, &new_unicode_password,280 user_dn, NULL, 281 &new_unicode_password, 301 282 NULL, NULL, 302 true, /* this is a user password change */303 NULL, 283 lm_pwd, NULL, /* this is a user password change */ 284 NULL, 304 285 NULL); 305 286 if (!NT_STATUS_IS_OK(status)) { … … 308 289 } 309 290 310 /* The above call only setup the modifications, this actually311 * makes the write to the database. */312 ret = samdb_replace(sam_ctx, mem_ctx, mod);313 if (ret != 0) {314 DEBUG(2,("Failed to modify record to change password on %s: %s\n",315 ldb_dn_get_linearized(user_dn),316 ldb_errstring(sam_ctx)));317 ldb_transaction_cancel(sam_ctx);318 return NT_STATUS_INTERNAL_DB_CORRUPTION;319 }320 321 291 /* And this confirms it in a transaction commit */ 322 292 ret = ldb_transaction_commit(sam_ctx); 323 if (ret != 0) {293 if (ret != LDB_SUCCESS) { 324 294 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n", 325 295 ldb_dn_get_linearized(user_dn), … … 332 302 333 303 334 /* 335 samr_ChangePasswordUser3 336 */ 337 NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, 338 339 340 { 304 /* 305 samr_ChangePasswordUser3 306 */ 307 NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, 308 TALLOC_CTX *mem_ctx, 309 struct samr_ChangePasswordUser3 *r) 310 { 341 311 NTSTATUS status; 342 312 DATA_BLOB new_password; … … 344 314 struct ldb_dn *user_dn; 345 315 int ret; 346 struct ldb_message **res , *mod;316 struct ldb_message **res; 347 317 const char * const attrs[] = { "unicodePwd", "dBCSPwd", NULL }; 348 318 struct samr_Password *nt_pwd, *lm_pwd; 349 319 DATA_BLOB nt_pwd_blob; 350 320 struct samr_DomInfo1 *dominfo = NULL; 351 struct samr_ChangeReject*reject = NULL;352 enum sam r_RejectReason reason = SAMR_REJECT_OTHER;321 struct userPwdChangeFailureInformation *reject = NULL; 322 enum samPwdChangeReason reason = SAM_PWD_CHANGE_NO_ERROR; 353 323 uint8_t new_nt_hash[16], new_lm_hash[16]; 354 324 struct samr_Password nt_verifier, lm_verifier; … … 362 332 } 363 333 364 /* To change a password we need to open as system */ 365 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx)); 334 /* Connect to a SAMDB with system privileges for fetching the old pw 335 * hashes. */ 336 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, 337 dce_call->conn->dce_ctx->lp_ctx, 338 system_session(dce_call->conn->dce_ctx->lp_ctx), 0); 366 339 if (sam_ctx == NULL) { 367 340 return NT_STATUS_INVALID_SYSTEM_SERVICE; 368 }369 370 ret = ldb_transaction_start(sam_ctx);371 if (ret) {372 talloc_free(sam_ctx);373 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));374 return NT_STATUS_TRANSACTION_ABORTED;375 341 } 376 342 … … 378 344 user SID). We also need the current lm and nt password hashes 379 345 in order to decrypt the incoming passwords */ 380 ret = gendb_search(sam_ctx, 346 ret = gendb_search(sam_ctx, 381 347 mem_ctx, NULL, &res, attrs, 382 348 "(&(sAMAccountName=%s)(objectclass=user))", … … 390 356 user_dn = res[0]->dn; 391 357 392 status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, 358 status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, 393 359 res[0], &lm_pwd, &nt_pwd); 394 360 if (!NT_STATUS_IS_OK(status) ) { … … 407 373 408 374 if (!extract_pw_from_buffer(mem_ctx, r->in.nt_password->data, &new_password)) { 409 ldb_transaction_cancel(sam_ctx);410 375 DEBUG(3,("samr: failed to decode password buffer\n")); 411 return NT_STATUS_WRONG_PASSWORD; 412 } 413 376 status = NT_STATUS_WRONG_PASSWORD; 377 goto failed; 378 } 379 414 380 if (r->in.nt_verifier == NULL) { 415 381 status = NT_STATUS_WRONG_PASSWORD; … … 431 397 if (lm_pwd && r->in.lm_verifier != NULL) { 432 398 char *new_pass; 433 if (!convert_string_talloc_convenience(mem_ctx, lp _iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),434 CH_UTF16, CH_UNIX, 435 (const char *)new_password.data, 399 if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx), 400 CH_UTF16, CH_UNIX, 401 (const char *)new_password.data, 436 402 new_password.length, 437 403 (void **)&new_pass, NULL, false)) { … … 445 411 } 446 412 447 mod = ldb_msg_new(mem_ctx); 448 if (mod == NULL) { 449 status = NT_STATUS_NO_MEMORY; 450 goto failed; 451 } 452 453 mod->dn = ldb_dn_copy(mod, user_dn); 454 if (!mod->dn) { 455 status = NT_STATUS_NO_MEMORY; 456 goto failed; 457 } 458 459 /* set the password on the user DN specified. This may fail 460 * due to password policies */ 413 /* Connect to a SAMDB with user privileges for the password change */ 414 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, 415 dce_call->conn->dce_ctx->lp_ctx, 416 dce_call->conn->auth_state.session_info, 0); 417 if (sam_ctx == NULL) { 418 return NT_STATUS_INVALID_SYSTEM_SERVICE; 419 } 420 421 ret = ldb_transaction_start(sam_ctx); 422 if (ret != LDB_SUCCESS) { 423 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx))); 424 return NT_STATUS_TRANSACTION_ABORTED; 425 } 426 427 /* Performs the password modification. We pass the old hashes read out 428 * from the database since they were already checked against the user- 429 * provided ones. */ 461 430 status = samdb_set_password(sam_ctx, mem_ctx, 462 user_dn, NULL, 463 mod, &new_password,431 user_dn, NULL, 432 &new_password, 464 433 NULL, NULL, 465 true, /* this is a user password change */466 &reason, 434 lm_pwd, nt_pwd, /* this is a user password change */ 435 &reason, 467 436 &dominfo); 437 468 438 if (!NT_STATUS_IS_OK(status)) { 469 goto failed; 470 } 471 472 /* The above call only setup the modifications, this actually 473 * makes the write to the database. */ 474 ret = samdb_replace(sam_ctx, mem_ctx, mod); 475 if (ret != 0) { 476 DEBUG(2,("samdb_replace failed to change password for %s: %s\n", 477 ldb_dn_get_linearized(user_dn), 478 ldb_errstring(sam_ctx))); 479 status = NT_STATUS_UNSUCCESSFUL; 439 ldb_transaction_cancel(sam_ctx); 480 440 goto failed; 481 441 } … … 483 443 /* And this confirms it in a transaction commit */ 484 444 ret = ldb_transaction_commit(sam_ctx); 485 if (ret != 0) {445 if (ret != LDB_SUCCESS) { 486 446 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n", 487 447 ldb_dn_get_linearized(user_dn), … … 494 454 495 455 failed: 496 ldb_transaction_cancel(sam_ctx); 497 talloc_free(sam_ctx); 498 499 reject = talloc(mem_ctx, struct samr_ChangeReject); 456 reject = talloc_zero(mem_ctx, struct userPwdChangeFailureInformation); 457 if (reject != NULL) { 458 reject->extendedFailureReason = reason; 459 460 *r->out.reject = reject; 461 } 462 500 463 *r->out.dominfo = dominfo; 501 *r->out.reject = reject;502 503 if (reject == NULL) {504 return status;505 }506 ZERO_STRUCTP(reject);507 508 reject->reason = reason;509 464 510 465 return status; … … 512 467 513 468 514 /* 515 samr_ChangePasswordUser2 469 /* 470 samr_ChangePasswordUser2 516 471 517 472 easy - just a subset of samr_ChangePasswordUser3 518 473 */ 519 NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 520 struct samr_ChangePasswordUser2 *r) 474 NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call, 475 TALLOC_CTX *mem_ctx, 476 struct samr_ChangePasswordUser2 *r) 521 477 { 522 478 struct samr_ChangePasswordUser3 r2; 523 479 struct samr_DomInfo1 *dominfo = NULL; 524 struct samr_ChangeReject*reject = NULL;480 struct userPwdChangeFailureInformation *reject = NULL; 525 481 526 482 r2.in.server = r->in.server; … … 541 497 /* 542 498 set password via a samr_CryptPassword buffer 543 this will in the 'msg' with modify operations that will update the user544 password when applied545 499 */ 546 500 NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call, 547 void*sam_ctx,501 struct ldb_context *sam_ctx, 548 502 struct ldb_dn *account_dn, struct ldb_dn *domain_dn, 549 503 TALLOC_CTX *mem_ctx, 550 struct ldb_message *msg,551 504 struct samr_CryptPassword *pwbuf) 552 505 { … … 566 519 return NT_STATUS_WRONG_PASSWORD; 567 520 } 568 521 569 522 /* set the password - samdb needs to know both the domain and user DNs, 570 523 so the domain password policy can be used */ 571 524 return samdb_set_password(sam_ctx, mem_ctx, 572 account_dn, domain_dn, 573 msg, &new_password,525 account_dn, domain_dn, 526 &new_password, 574 527 NULL, NULL, 575 false, /* This is a password set, not change */528 NULL, NULL, /* This is a password set, not change */ 576 529 NULL, NULL); 577 530 } … … 580 533 /* 581 534 set password via a samr_CryptPasswordEx buffer 582 this will in the 'msg' with modify operations that will update the user583 password when applied584 535 */ 585 536 NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call, 586 537 struct ldb_context *sam_ctx, 587 struct ldb_dn *account_dn, struct ldb_dn *domain_dn, 538 struct ldb_dn *account_dn, 539 struct ldb_dn *domain_dn, 588 540 TALLOC_CTX *mem_ctx, 589 struct ldb_message *msg,590 541 struct samr_CryptPasswordEx *pwbuf) 591 542 { … … 610 561 MD5Update(&ctx, session_key.data, session_key.length); 611 562 MD5Final(co_session_key.data, &ctx); 612 563 613 564 arcfour_crypt_blob(pwbuf->data, 516, &co_session_key); 614 565 … … 617 568 return NT_STATUS_WRONG_PASSWORD; 618 569 } 619 570 620 571 /* set the password - samdb needs to know both the domain and user DNs, 621 572 so the domain password policy can be used */ 622 573 return samdb_set_password(sam_ctx, mem_ctx, 623 account_dn, domain_dn, 624 msg, &new_password,574 account_dn, domain_dn, 575 &new_password, 625 576 NULL, NULL, 626 false, /* This is a password set, not change */577 NULL, NULL, /* This is a password set, not change */ 627 578 NULL, NULL); 628 579 } 629 580 630 581 /* 582 set password via encrypted NT and LM hash buffers 583 */ 584 NTSTATUS samr_set_password_buffers(struct dcesrv_call_state *dce_call, 585 struct ldb_context *sam_ctx, 586 struct ldb_dn *account_dn, 587 struct ldb_dn *domain_dn, 588 TALLOC_CTX *mem_ctx, 589 const uint8_t *lm_pwd_hash, 590 const uint8_t *nt_pwd_hash) 591 { 592 struct samr_Password *d_lm_pwd_hash = NULL, *d_nt_pwd_hash = NULL; 593 DATA_BLOB session_key = data_blob(NULL, 0); 594 DATA_BLOB in, out; 595 NTSTATUS nt_status = NT_STATUS_OK; 596 597 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key); 598 if (!NT_STATUS_IS_OK(nt_status)) { 599 return nt_status; 600 } 601 602 if (lm_pwd_hash != NULL) { 603 in = data_blob_const(lm_pwd_hash, 16); 604 out = data_blob_talloc_zero(mem_ctx, 16); 605 606 sess_crypt_blob(&out, &in, &session_key, false); 607 608 d_lm_pwd_hash = (struct samr_Password *) out.data; 609 } 610 if (nt_pwd_hash != NULL) { 611 in = data_blob_const(nt_pwd_hash, 16); 612 out = data_blob_talloc_zero(mem_ctx, 16); 613 614 sess_crypt_blob(&out, &in, &session_key, false); 615 616 d_nt_pwd_hash = (struct samr_Password *) out.data; 617 } 618 619 if ((d_lm_pwd_hash != NULL) || (d_nt_pwd_hash != NULL)) { 620 nt_status = samdb_set_password(sam_ctx, mem_ctx, account_dn, 621 domain_dn, NULL, 622 d_lm_pwd_hash, d_nt_pwd_hash, 623 NULL, NULL, /* this is a password set */ 624 NULL, NULL); 625 } 626 627 return nt_status; 628 }
Note:
See TracChangeset
for help on using the changeset viewer.