Changeset 745 for trunk/server/source4/rpc_server/drsuapi
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 7 edited
- 1 copied
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/drsuapi/addentry.c
r414 r745 23 23 #include "includes.h" 24 24 #include "rpc_server/dcerpc_server.h" 25 #include "rpc_server/common/common.h"26 25 #include "dsdb/samdb/samdb.h" 27 #include " lib/ldb/include/ldb_errors.h"26 #include "dsdb/common/util.h" 28 27 #include "param/param.h" 29 #include "lib rpc/gen_ndr/ndr_drsblobs.h"30 #include " auth/auth.h"28 #include "libcli/security/security.h" 29 #include "libcli/security/session.h" 31 30 #include "rpc_server/drsuapi/dcesrv_drsuapi.h" 32 #include "libcli/security/security.h"33 #include "librpc/gen_ndr/ndr_drsblobs.h"34 31 #include "librpc/gen_ndr/ndr_drsuapi.h" 35 36 32 37 33 /* … … 50 46 const char *dn_string = obj->object.identifier->dn; 51 47 struct ldb_dn *dn = ldb_dn_new(mem_ctx, b_state->sam_ctx, dn_string); 52 struct ldb_result *res ;48 struct ldb_result *res, *res2; 53 49 struct ldb_dn *ref_dn; 54 50 struct GUID ntds_guid; … … 57 53 const char *ntds_guid_str; 58 54 const char *dom_string; 55 const char *attrs2[] = { "dNSHostName", "cn", NULL }; 56 const char *dNSHostName, *cn; 59 57 60 58 DEBUG(6,(__location__ ": Adding SPNs for %s\n", … … 83 81 ntds_guid_str = GUID_string(res, &ntds_guid); 84 82 85 dom_string = lp_realm(dce_call->conn->dce_ctx->lp_ctx); 83 dom_string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx); 84 85 /* get the dNSHostName and cn */ 86 ret = ldb_search(b_state->sam_ctx, mem_ctx, &res2, 87 ref_dn, LDB_SCOPE_BASE, attrs2, NULL); 88 if (ret != LDB_SUCCESS) { 89 DEBUG(0,(__location__ ": Failed to find ref_dn '%s'\n", 90 ldb_dn_get_linearized(ref_dn))); 91 return WERR_DS_DRA_INTERNAL_ERROR; 92 } 93 94 dNSHostName = ldb_msg_find_attr_as_string(res2->msgs[0], "dNSHostName", NULL); 95 cn = ldb_msg_find_attr_as_string(res2->msgs[0], "cn", NULL); 86 96 87 97 /* … … 101 111 } 102 112 103 el->num_values = 2; 104 el->values = talloc_array(msg->elements, struct ldb_val, 2); 105 if (el->values == NULL) { 113 114 ldb_msg_add_steal_string(msg, "servicePrincipalName", 115 talloc_asprintf(el->values, 116 "E3514235-4B06-11D1-AB04-00C04FC2DCD2/%s/%s", 117 ntds_guid_str, dom_string)); 118 ldb_msg_add_steal_string(msg, "servicePrincipalName", 119 talloc_asprintf(el->values, "ldap/%s._msdcs.%s", 120 ntds_guid_str, dom_string)); 121 if (cn) { 122 ldb_msg_add_steal_string(msg, "servicePrincipalName", 123 talloc_asprintf(el->values, "ldap/%s", cn)); 124 } 125 if (dNSHostName) { 126 ldb_msg_add_steal_string(msg, "servicePrincipalName", 127 talloc_asprintf(el->values, "ldap/%s", dNSHostName)); 128 } 129 if (el->num_values < 2) { 106 130 return WERR_NOMEM; 107 131 } 108 /* the magic constant is the GUID of the DRSUAPI RPC 109 interface */ 110 el->values[0].data = (uint8_t *)talloc_asprintf(el->values, 111 "E3514235-4B06-11D1-AB04-00C04FC2DCD2/%s/%s", 112 ntds_guid_str, dom_string); 113 el->values[0].length = strlen((char *)el->values[0].data); 114 el->values[1].data = (uint8_t *)talloc_asprintf(el->values, "ldap/%s._msdcs.%s", 115 ntds_guid_str, dom_string); 116 el->values[1].length = strlen((char *)el->values[1].data); 117 118 ret = ldb_modify(b_state->sam_ctx, msg); 132 133 ret = dsdb_modify(b_state->sam_ctx, msg, DSDB_MODIFY_PERMISSIVE); 119 134 if (ret != LDB_SUCCESS) { 120 135 DEBUG(0,(__location__ ": Failed to add SPNs - %s\n", … … 152 167 ZERO_STRUCTP(r->out.ctr); 153 168 *r->out.level_out = 3; 154 r->out.ctr->ctr3. level= 1;155 r->out.ctr->ctr3.err or = talloc_zero(mem_ctx, union drsuapi_DsAddEntryError);169 r->out.ctr->ctr3.err_ver = 1; 170 r->out.ctr->ctr3.err_data = talloc_zero(mem_ctx, union drsuapi_DsAddEntry_ErrData); 156 171 157 172 DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); 158 173 b_state = h->data; 159 174 160 status = drs_security_level_check(dce_call, "DsAddEntry" );175 status = drs_security_level_check(dce_call, "DsAddEntry", SECURITY_DOMAIN_CONTROLLER, NULL); 161 176 if (!W_ERROR_IS_OK(status)) { 162 177 return status; … … 179 194 &ids); 180 195 if (!W_ERROR_IS_OK(status)) { 181 r->out.ctr->ctr3.err or->info1.status = status;196 r->out.ctr->ctr3.err_data->v1.status = status; 182 197 ldb_transaction_cancel(b_state->sam_ctx); 198 DEBUG(0,(__location__ ": DsAddEntry failed - %s\n", win_errstr(status))); 183 199 return status; 184 200 } … … 197 213 status = drsuapi_add_SPNs(b_state, dce_call, mem_ctx, first_object); 198 214 if (!W_ERROR_IS_OK(status)) { 199 r->out.ctr->ctr3.err or->info1.status = status;215 r->out.ctr->ctr3.err_data->v1.status = status; 200 216 ldb_transaction_cancel(b_state->sam_ctx); 217 DEBUG(0,(__location__ ": DsAddEntry add SPNs failed - %s\n", win_errstr(status))); 201 218 return status; 202 219 } … … 204 221 ret = ldb_transaction_commit(b_state->sam_ctx); 205 222 if (ret != LDB_SUCCESS) { 223 DEBUG(0,(__location__ ": DsAddEntry commit failed: %s\n", 224 ldb_errstring(b_state->sam_ctx))); 206 225 return WERR_DS_DRA_INTERNAL_ERROR; 207 226 } -
trunk/server/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
r414 r745 26 26 #include "rpc_server/common/common.h" 27 27 #include "dsdb/samdb/samdb.h" 28 #include "libcli/security/security.h" 29 #include "libcli/security/session.h" 28 30 #include "rpc_server/drsuapi/dcesrv_drsuapi.h" 29 #include "libcli/security/security.h" 31 #include "auth/auth.h" 32 #include "param/param.h" 33 #include "lib/messaging/irpc.h" 34 35 #define DRSUAPI_UNSUPPORTED(fname) do { \ 36 DEBUG(1,(__location__ ": Unsupported DRS call %s\n", #fname)); \ 37 if (DEBUGLVL(2)) NDR_PRINT_IN_DEBUG(fname, r); \ 38 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); \ 39 } while (0) 30 40 31 41 /* … … 48 58 uint32_t repl_epoch; 49 59 int ret; 60 struct auth_session_info *auth_info; 61 WERROR werr; 62 bool connected_as_system = false; 50 63 51 64 r->out.bind_info = NULL; … … 55 68 W_ERROR_HAVE_NO_MEMORY(b_state); 56 69 70 /* if this is a DC connecting, give them system level access */ 71 werr = drs_security_level_check(dce_call, NULL, SECURITY_DOMAIN_CONTROLLER, NULL); 72 if (W_ERROR_IS_OK(werr)) { 73 DEBUG(3,(__location__ ": doing DsBind with system_session\n")); 74 auth_info = system_session(dce_call->conn->dce_ctx->lp_ctx); 75 connected_as_system = true; 76 } else { 77 auth_info = dce_call->conn->auth_state.session_info; 78 } 79 57 80 /* 58 81 * connect to the samdb 59 82 */ 60 b_state->sam_ctx = samdb_connect(b_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info); 83 b_state->sam_ctx = samdb_connect(b_state, dce_call->event_ctx, 84 dce_call->conn->dce_ctx->lp_ctx, auth_info, 0); 61 85 if (!b_state->sam_ctx) { 62 86 return WERR_FOOBAR; 87 } 88 89 if (connected_as_system) { 90 b_state->sam_ctx_system = b_state->sam_ctx; 91 } else { 92 /* an RODC also needs system samdb access for secret 93 attribute replication */ 94 werr = drs_security_level_check(dce_call, NULL, SECURITY_RO_DOMAIN_CONTROLLER, 95 samdb_domain_sid(b_state->sam_ctx)); 96 if (W_ERROR_IS_OK(werr)) { 97 b_state->sam_ctx_system = samdb_connect(b_state, dce_call->event_ctx, 98 dce_call->conn->dce_ctx->lp_ctx, 99 system_session(dce_call->conn->dce_ctx->lp_ctx), 0); 100 if (!b_state->sam_ctx_system) { 101 return WERR_FOOBAR; 102 } 103 } 63 104 } 64 105 … … 95 136 return WERR_DS_DRA_INTERNAL_ERROR; 96 137 } 97 repl_epoch = samdb_result_uint(ntds_res->msgs[0], "ms-DS-ReplicationEpoch", 0); 138 repl_epoch = ldb_msg_find_attr_as_uint(ntds_res->msgs[0], 139 "ms-DS-ReplicationEpoch", 0); 98 140 99 141 /* … … 147 189 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE; 148 190 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2; 149 if (0 /*domain.behavior_version == 2*/) { 150 /* TODO: find out how this is really triggered! */ 151 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION; 152 } 191 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION; 153 192 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2; 154 193 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD; … … 160 199 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY; 161 200 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3; 162 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ 00100000;201 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V5; 163 202 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2; 164 203 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6; … … 173 212 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS; 174 213 #endif 214 b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10; 175 215 b_state->local_info28.site_guid = site_guid; 176 216 b_state->local_info28.pid = pid; … … 230 270 { 231 271 WERROR status; 232 233 status = drs_security_level_check(dce_call, "DsReplicaSync"); 272 uint32_t timeout; 273 274 status = drs_security_level_check(dce_call, "DsReplicaSync", SECURITY_DOMAIN_CONTROLLER, NULL); 234 275 if (!W_ERROR_IS_OK(status)) { 235 276 return status; 236 277 } 237 278 238 dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, r, NDR_DRSUAPI_DSREPLICASYNC, 279 if (r->in.level != 1) { 280 DEBUG(0,("DsReplicaSync called with unsupported level %d\n", r->in.level)); 281 return WERR_DS_DRA_INVALID_PARAMETER; 282 } 283 284 if (r->in.req->req1.options & DRSUAPI_DRS_ASYNC_OP) { 285 timeout = IRPC_CALL_TIMEOUT; 286 } else { 287 /* 288 * use Infinite time for timeout in case 289 * the caller made a sync call 290 */ 291 timeout = IRPC_CALL_TIMEOUT_INF; 292 } 293 294 dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, 295 r, NDR_DRSUAPI_DSREPLICASYNC, 239 296 &ndr_table_drsuapi, 240 "dreplsrv", "DsReplicaSync"); 297 "dreplsrv", "DsReplicaSync", 298 timeout); 241 299 242 300 return WERR_OK; … … 250 308 struct drsuapi_DsReplicaAdd *r) 251 309 { 252 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); 310 WERROR status; 311 312 status = drs_security_level_check(dce_call, "DsReplicaAdd", SECURITY_DOMAIN_CONTROLLER, NULL); 313 if (!W_ERROR_IS_OK(status)) { 314 return status; 315 } 316 317 dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, 318 r, NDR_DRSUAPI_DSREPLICAADD, 319 &ndr_table_drsuapi, 320 "dreplsrv", "DsReplicaAdd", 321 IRPC_CALL_TIMEOUT); 322 323 return WERR_OK; 253 324 } 254 325 … … 260 331 struct drsuapi_DsReplicaDel *r) 261 332 { 262 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); 333 WERROR status; 334 335 status = drs_security_level_check(dce_call, "DsReplicaDel", SECURITY_DOMAIN_CONTROLLER, NULL); 336 if (!W_ERROR_IS_OK(status)) { 337 return status; 338 } 339 340 dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, 341 r, NDR_DRSUAPI_DSREPLICADEL, 342 &ndr_table_drsuapi, 343 "dreplsrv", "DsReplicaDel", 344 IRPC_CALL_TIMEOUT); 345 346 return WERR_OK; 263 347 } 264 348 … … 270 354 struct drsuapi_DsReplicaMod *r) 271 355 { 272 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); 356 WERROR status; 357 358 status = drs_security_level_check(dce_call, "DsReplicaMod", SECURITY_DOMAIN_CONTROLLER, NULL); 359 if (!W_ERROR_IS_OK(status)) { 360 return status; 361 } 362 363 dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, 364 r, NDR_DRSUAPI_DSREPLICAMOD, 365 &ndr_table_drsuapi, 366 "dreplsrv", "DsReplicaMod", 367 IRPC_CALL_TIMEOUT); 368 369 return WERR_OK; 273 370 } 274 371 … … 280 377 struct DRSUAPI_VERIFY_NAMES *r) 281 378 { 282 D CESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);379 DRSUAPI_UNSUPPORTED(DRSUAPI_VERIFY_NAMES); 283 380 } 284 381 … … 290 387 struct drsuapi_DsGetMemberships *r) 291 388 { 292 D CESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);389 DRSUAPI_UNSUPPORTED(drsuapi_DsGetMemberships); 293 390 } 294 391 … … 300 397 struct DRSUAPI_INTER_DOMAIN_MOVE *r) 301 398 { 302 D CESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);399 DRSUAPI_UNSUPPORTED(DRSUAPI_INTER_DOMAIN_MOVE); 303 400 } 304 401 … … 310 407 struct drsuapi_DsGetNT4ChangeLog *r) 311 408 { 312 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); 313 } 314 409 DRSUAPI_UNSUPPORTED(drsuapi_DsGetNT4ChangeLog); 410 } 315 411 316 412 /* … … 320 416 struct drsuapi_DsCrackNames *r) 321 417 { 322 WERROR status;323 418 struct drsuapi_bind_state *b_state; 324 419 struct dcesrv_handle *h; … … 334 429 switch (r->in.level) { 335 430 case 1: { 336 struct drsuapi_DsNameCtr1 *ctr1; 337 struct drsuapi_DsNameInfo1 *names; 338 int count; 339 int i; 340 341 ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1); 342 W_ERROR_HAVE_NO_MEMORY(ctr1); 343 344 count = r->in.req->req1.count; 345 names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count); 346 W_ERROR_HAVE_NO_MEMORY(names); 347 348 for (i=0; i < count; i++) { 349 status = DsCrackNameOneName(b_state->sam_ctx, mem_ctx, 350 r->in.req->req1.format_flags, 351 r->in.req->req1.format_offered, 352 r->in.req->req1.format_desired, 353 r->in.req->req1.names[i].str, 354 &names[i]); 355 if (!W_ERROR_IS_OK(status)) { 356 return status; 357 } 358 } 359 360 ctr1->count = count; 361 ctr1->array = names; 362 r->out.ctr->ctr1 = ctr1; 363 364 return WERR_OK; 365 } 366 } 367 368 return WERR_UNKNOWN_LEVEL; 369 } 370 371 /* 372 drsuapi_DsWriteAccountSpn 373 */ 374 static WERROR dcesrv_drsuapi_DsWriteAccountSpn(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 375 struct drsuapi_DsWriteAccountSpn *r) 376 { 377 struct drsuapi_bind_state *b_state; 378 struct dcesrv_handle *h; 379 380 *r->out.level_out = r->in.level; 381 382 DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); 383 b_state = h->data; 384 385 r->out.res = talloc(mem_ctx, union drsuapi_DsWriteAccountSpnResult); 386 W_ERROR_HAVE_NO_MEMORY(r->out.res); 387 388 switch (r->in.level) { 389 case 1: { 390 struct drsuapi_DsWriteAccountSpnRequest1 *req; 391 struct ldb_message *msg; 392 int count, i, ret; 393 req = &r->in.req->req1; 394 count = req->count; 395 396 msg = ldb_msg_new(mem_ctx); 397 if (msg == NULL) { 398 return WERR_NOMEM; 399 } 400 401 msg->dn = ldb_dn_new(msg, b_state->sam_ctx, req->object_dn); 402 if ( ! ldb_dn_validate(msg->dn)) { 403 r->out.res->res1.status = WERR_OK; 431 switch(r->in.req->req1.format_offered){ 432 case DRSUAPI_DS_NAME_FORMAT_UPN_AND_ALTSECID: 433 case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN_EX: 434 case DRSUAPI_DS_NAME_FORMAT_LIST_GLOBAL_CATALOG_SERVERS: 435 case DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON: 436 case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_WITH_DCS_IN_SITE: 437 case DRSUAPI_DS_NAME_FORMAT_STRING_SID_NAME: 438 case DRSUAPI_DS_NAME_FORMAT_ALT_SECURITY_IDENTITIES_NAME: 439 case DRSUAPI_DS_NAME_FORMAT_LIST_NCS: 440 case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS: 441 case DRSUAPI_DS_NAME_FORMAT_MAP_SCHEMA_GUID: 442 case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN: 443 case DRSUAPI_DS_NAME_FORMAT_LIST_INFO_FOR_SERVER: 444 case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_FOR_DOMAIN_IN_SITE: 445 case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS_IN_SITE: 446 case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_IN_SITE: 447 case DRSUAPI_DS_NAME_FORMAT_LIST_SITES: 448 DEBUG(0, ("DsCrackNames: Unsupported operation requested: %X", 449 r->in.req->req1.format_offered)); 404 450 return WERR_OK; 405 } 406 407 /* construct mods */ 408 for (i = 0; i < count; i++) { 409 samdb_msg_add_string(b_state->sam_ctx, 410 msg, msg, "servicePrincipalName", 411 req->spn_names[i].str); 412 } 413 for (i=0;i<msg->num_elements;i++) { 414 switch (req->operation) { 415 case DRSUAPI_DS_SPN_OPERATION_ADD: 416 msg->elements[i].flags = LDB_FLAG_MOD_ADD; 417 break; 418 case DRSUAPI_DS_SPN_OPERATION_REPLACE: 419 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; 420 break; 421 case DRSUAPI_DS_SPN_OPERATION_DELETE: 422 msg->elements[i].flags = LDB_FLAG_MOD_DELETE; 423 break; 424 } 425 } 426 427 /* Apply to database */ 428 429 ret = ldb_modify(b_state->sam_ctx, msg); 430 if (ret != 0) { 431 DEBUG(0,("Failed to modify SPNs on %s: %s\n", 432 ldb_dn_get_linearized(msg->dn), 433 ldb_errstring(b_state->sam_ctx))); 434 r->out.res->res1.status = WERR_ACCESS_DENIED; 435 } else { 436 r->out.res->res1.status = WERR_OK; 437 } 438 439 return WERR_OK; 440 } 441 } 442 451 case DRSUAPI_DS_NAME_FORMAT_LIST_ROLES: 452 return dcesrv_drsuapi_ListRoles(b_state->sam_ctx, mem_ctx, 453 &r->in.req->req1, &r->out.ctr->ctr1); 454 default:/* format_offered is in the enum drsuapi_DsNameFormat*/ 455 return dcesrv_drsuapi_CrackNamesByNameFormat(b_state->sam_ctx, mem_ctx, 456 &r->in.req->req1, &r->out.ctr->ctr1); 457 } 458 } 459 } 443 460 return WERR_UNKNOWN_LEVEL; 444 461 } … … 458 475 WERROR status; 459 476 460 ZERO_STRUCT(r->out.res);461 477 *r->out.level_out = 1; 462 478 463 status = drs_security_level_check(dce_call, "DsRemoveDSServer" );479 status = drs_security_level_check(dce_call, "DsRemoveDSServer", SECURITY_DOMAIN_CONTROLLER, NULL); 464 480 if (!W_ERROR_IS_OK(status)) { 465 481 return status; … … 508 524 struct DRSUAPI_REMOVE_DS_DOMAIN *r) 509 525 { 510 D CESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);526 DRSUAPI_UNSUPPORTED(DRSUAPI_REMOVE_DS_DOMAIN); 511 527 } 512 528 513 529 /* Obtain the site name from a server DN */ 514 static const char *result_site_name(struct ldb_dn *s ite_dn)530 static const char *result_site_name(struct ldb_dn *server_dn) 515 531 { 516 532 /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */ 517 const struct ldb_val *val = ldb_dn_get_component_val(s ite_dn, 2);518 const char *name = ldb_dn_get_component_name(s ite_dn, 2);533 const struct ldb_val *val = ldb_dn_get_component_val(server_dn, 2); 534 const char *name = ldb_dn_get_component_name(server_dn, 2); 519 535 520 536 if (!name || (ldb_attr_cmp(name, "cn") != 0)) { … … 556 572 struct drsuapi_DsGetDCInfoCtr2 *ctr2; 557 573 558 int ret, i; 574 int ret; 575 unsigned int i; 559 576 560 577 *r->out.level_out = r->in.req->req1.level; … … 686 703 if (ret == LDB_SUCCESS && res_ntds->count == 1) { 687 704 ctr2->array[i].is_gc 688 = (ldb_msg_find_attr_as_ int(res_ntds->msgs[0], "options", 0) == 1);705 = (ldb_msg_find_attr_as_uint(res_ntds->msgs[0], "options", 0) & DS_NTDSDSA_OPT_IS_GC); 689 706 ctr2->array[i].ntds_guid 690 707 = samdb_result_guid(res_ntds->msgs[0], "objectGUID"); … … 784 801 struct drsuapi_DsExecuteKCC *r) 785 802 { 786 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); 803 WERROR status; 804 status = drs_security_level_check(dce_call, "DsExecuteKCC", SECURITY_DOMAIN_CONTROLLER, NULL); 805 806 if (!W_ERROR_IS_OK(status)) { 807 return status; 808 } 809 810 dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, r, NDR_DRSUAPI_DSEXECUTEKCC, 811 &ndr_table_drsuapi, "kccsrv", "DsExecuteKCC", 812 IRPC_CALL_TIMEOUT); 813 return WERR_OK; 787 814 } 788 815 … … 794 821 struct drsuapi_DsReplicaGetInfo *r) 795 822 { 796 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); 823 enum security_user_level level; 824 825 if (!lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL, 826 "drs", "disable_sec_check", false)) { 827 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL); 828 if (level < SECURITY_DOMAIN_CONTROLLER) { 829 DEBUG(1,(__location__ ": Administrator access required for DsReplicaGetInfo\n")); 830 security_token_debug(0, 2, dce_call->conn->auth_state.session_info->security_token); 831 return WERR_DS_DRA_ACCESS_DENIED; 832 } 833 } 834 835 dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, r, NDR_DRSUAPI_DSREPLICAGETINFO, 836 &ndr_table_drsuapi, "kccsrv", "DsReplicaGetInfo", 837 IRPC_CALL_TIMEOUT); 838 839 return WERR_OK; 797 840 } 798 841 … … 804 847 struct DRSUAPI_ADD_SID_HISTORY *r) 805 848 { 806 D CESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);849 DRSUAPI_UNSUPPORTED(DRSUAPI_ADD_SID_HISTORY); 807 850 } 808 851 … … 813 856 struct drsuapi_DsGetMemberships2 *r) 814 857 { 815 D CESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);858 DRSUAPI_UNSUPPORTED(drsuapi_DsGetMemberships2); 816 859 } 817 860 … … 822 865 struct DRSUAPI_REPLICA_VERIFY_OBJECTS *r) 823 866 { 824 D CESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);867 DRSUAPI_UNSUPPORTED(DRSUAPI_REPLICA_VERIFY_OBJECTS); 825 868 } 826 869 … … 832 875 struct DRSUAPI_GET_OBJECT_EXISTENCE *r) 833 876 { 834 D CESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);877 DRSUAPI_UNSUPPORTED(DRSUAPI_GET_OBJECT_EXISTENCE); 835 878 } 836 879 … … 842 885 struct drsuapi_QuerySitesByCost *r) 843 886 { 844 D CESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);887 DRSUAPI_UNSUPPORTED(drsuapi_QuerySitesByCost); 845 888 } 846 889 -
trunk/server/source4/rpc_server/drsuapi/dcesrv_drsuapi.h
r414 r745 32 32 struct drsuapi_bind_state { 33 33 struct ldb_context *sam_ctx; 34 struct ldb_context *sam_ctx_system; 34 35 struct GUID remote_bind_guid; 35 36 struct drsuapi_DsBindInfo28 remote_info28; … … 40 41 41 42 /* prototypes of internal functions */ 43 WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx, 44 struct drsuapi_DsReplicaUpdateRefsRequest1 *req); 42 45 WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 43 46 struct drsuapi_DsReplicaUpdateRefs *r); … … 46 49 WERROR dcesrv_drsuapi_DsAddEntry(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 47 50 struct drsuapi_DsAddEntry *r); 51 WERROR dcesrv_drsuapi_DsWriteAccountSpn(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 52 struct drsuapi_DsWriteAccountSpn *r); 48 53 49 54 char *drs_ObjectIdentifier_to_string(TALLOC_CTX *mem_ctx, … … 56 61 enum ldb_scope scope, 57 62 const char * const *attrs, 58 const char *sort_attrib,59 63 const char *filter); 60 64 61 65 WERROR drs_security_level_check(struct dcesrv_call_state *dce_call, 62 const char* call); 66 const char* call, enum security_user_level minimum_level, 67 const struct dom_sid *domain_sid); 63 68 64 69 void drsuapi_process_secret_attribute(struct drsuapi_DsReplicaAttribute *attr, 65 70 struct drsuapi_DsReplicaMetaData *meta_data); 71 72 WERROR drs_security_access_check(struct ldb_context *sam_ctx, 73 TALLOC_CTX *mem_ctx, 74 struct security_token *token, 75 struct drsuapi_DsReplicaObjectIdentifier *nc, 76 const char *ext_right); 77 78 WERROR drs_security_access_check_nc_root(struct ldb_context *sam_ctx, 79 TALLOC_CTX *mem_ctx, 80 struct security_token *token, 81 struct drsuapi_DsReplicaObjectIdentifier *nc, 82 const char *ext_right); -
trunk/server/source4/rpc_server/drsuapi/drsutil.c
r414 r745 23 23 #include "rpc_server/dcerpc_server.h" 24 24 #include "dsdb/samdb/samdb.h" 25 #include "libcli/security/dom_sid.h"26 #include "rpc_server/drsuapi/dcesrv_drsuapi.h"27 25 #include "libcli/security/security.h" 26 #include "libcli/security/session.h" 28 27 #include "param/param.h" 29 30 /* 31 format a drsuapi_DsReplicaObjectIdentifier naming context as a string 32 */ 33 char *drs_ObjectIdentifier_to_string(TALLOC_CTX *mem_ctx, 34 struct drsuapi_DsReplicaObjectIdentifier *nc) 35 { 36 char *guid, *sid, *ret; 37 guid = GUID_string(mem_ctx, &nc->guid); 38 sid = dom_sid_string(mem_ctx, &nc->sid); 39 ret = talloc_asprintf(mem_ctx, "<GUID=%s>;<SID=%s>;%s", 40 guid, sid, nc->dn); 41 talloc_free(guid); 42 talloc_free(sid); 43 return ret; 44 } 28 #include "auth/session.h" 45 29 46 30 int drsuapi_search_with_extended_dn(struct ldb_context *ldb, … … 50 34 enum ldb_scope scope, 51 35 const char * const *attrs, 52 const char *sort_attrib,53 36 const char *filter) 54 37 { … … 84 67 } 85 68 86 ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL); 87 if (ret != LDB_SUCCESS) { 88 return ret; 89 } 90 91 if (sort_attrib) { 92 struct ldb_server_sort_control **sort_control; 93 sort_control = talloc_array(req, struct ldb_server_sort_control *, 2); 94 if (sort_control == NULL) { 95 talloc_free(tmp_ctx); 96 return LDB_ERR_OPERATIONS_ERROR; 97 } 98 sort_control[0] = talloc(req, struct ldb_server_sort_control); 99 sort_control[0]->attributeName = sort_attrib; 100 sort_control[0]->orderingRule = NULL; 101 sort_control[0]->reverse = 1; 102 sort_control[1] = NULL; 103 104 ret = ldb_request_add_control(req, LDB_CONTROL_SERVER_SORT_OID, true, sort_control); 105 if (ret != LDB_SUCCESS) { 106 return ret; 107 } 108 } 109 69 ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_RECYCLED_OID, true, NULL); 70 if (ret != LDB_SUCCESS) { 71 return ret; 72 } 73 74 ret = ldb_request_add_control(req, LDB_CONTROL_REVEAL_INTERNALS, false, NULL); 75 if (ret != LDB_SUCCESS) { 76 return ret; 77 } 110 78 111 79 ret = ldb_request(ldb, req); … … 119 87 } 120 88 121 WERROR drs_security_level_check(struct dcesrv_call_state *dce_call, const char* call) 122 { 123 if (lp_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL, 89 WERROR drs_security_level_check(struct dcesrv_call_state *dce_call, 90 const char* call, 91 enum security_user_level minimum_level, 92 const struct dom_sid *domain_sid) 93 { 94 enum security_user_level level; 95 96 if (lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL, 124 97 "drs", "disable_sec_check", false)) { 125 98 return WERR_OK; 126 99 } 127 100 128 if (security_session_user_level(dce_call->conn->auth_state.session_info) < 129 SECURITY_DOMAIN_CONTROLLER) { 130 DEBUG(0,("DsReplicaGetInfo refused for security token\n")); 101 level = security_session_user_level(dce_call->conn->auth_state.session_info, domain_sid); 102 if (level < minimum_level) { 103 if (call) { 104 DEBUG(0,("%s refused for security token (level=%u)\n", 105 call, (unsigned)level)); 106 security_token_debug(0, 2, dce_call->conn->auth_state.session_info->security_token); 107 } 131 108 return WERR_DS_DRA_ACCESS_DENIED; 132 109 } … … 143 120 144 121 switch (attr->attid) { 145 case DRSUAPI_ATT RIBUTE_dBCSPwd:146 case DRSUAPI_ATT RIBUTE_unicodePwd:147 case DRSUAPI_ATT RIBUTE_ntPwdHistory:148 case DRSUAPI_ATT RIBUTE_lmPwdHistory:149 case DRSUAPI_ATT RIBUTE_supplementalCredentials:150 case DRSUAPI_ATT RIBUTE_priorValue:151 case DRSUAPI_ATT RIBUTE_currentValue:152 case DRSUAPI_ATT RIBUTE_trustAuthOutgoing:153 case DRSUAPI_ATT RIBUTE_trustAuthIncoming:154 case DRSUAPI_ATT RIBUTE_initialAuthOutgoing:155 case DRSUAPI_ATT RIBUTE_initialAuthIncoming:122 case DRSUAPI_ATTID_dBCSPwd: 123 case DRSUAPI_ATTID_unicodePwd: 124 case DRSUAPI_ATTID_ntPwdHistory: 125 case DRSUAPI_ATTID_lmPwdHistory: 126 case DRSUAPI_ATTID_supplementalCredentials: 127 case DRSUAPI_ATTID_priorValue: 128 case DRSUAPI_ATTID_currentValue: 129 case DRSUAPI_ATTID_trustAuthOutgoing: 130 case DRSUAPI_ATTID_trustAuthIncoming: 131 case DRSUAPI_ATTID_initialAuthOutgoing: 132 case DRSUAPI_ATTID_initialAuthIncoming: 156 133 /*set value to null*/ 157 134 attr->value_ctr.num_values = 0; … … 163 140 return; 164 141 } 165 return; 166 } 142 } 143 144 145 /* 146 check security on a DN, with logging of errors 147 */ 148 static WERROR drs_security_access_check_log(struct ldb_context *sam_ctx, 149 TALLOC_CTX *mem_ctx, 150 struct security_token *token, 151 struct ldb_dn *dn, 152 const char *ext_right) 153 { 154 int ret; 155 if (!dn) { 156 DEBUG(3,("drs_security_access_check: Null dn provided, access is denied for %s\n", 157 ext_right)); 158 return WERR_DS_DRA_ACCESS_DENIED; 159 } 160 ret = dsdb_check_access_on_dn(sam_ctx, 161 mem_ctx, 162 dn, 163 token, 164 SEC_ADS_CONTROL_ACCESS, 165 ext_right); 166 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { 167 DEBUG(3,("%s refused for security token on %s\n", 168 ext_right, ldb_dn_get_linearized(dn))); 169 security_token_debug(2, 0, token); 170 return WERR_DS_DRA_ACCESS_DENIED; 171 } else if (ret != LDB_SUCCESS) { 172 DEBUG(1,("Failed to perform access check on %s\n", ldb_dn_get_linearized(dn))); 173 return WERR_DS_DRA_INTERNAL_ERROR; 174 } 175 return WERR_OK; 176 } 177 178 179 /* 180 check security on a object identifier 181 */ 182 WERROR drs_security_access_check(struct ldb_context *sam_ctx, 183 TALLOC_CTX *mem_ctx, 184 struct security_token *token, 185 struct drsuapi_DsReplicaObjectIdentifier *nc, 186 const char *ext_right) 187 { 188 struct ldb_dn *dn = drs_ObjectIdentifier_to_dn(mem_ctx, sam_ctx, nc); 189 WERROR werr; 190 werr = drs_security_access_check_log(sam_ctx, mem_ctx, token, dn, ext_right); 191 talloc_free(dn); 192 return werr; 193 } 194 195 /* 196 check security on the NC root of a object identifier 197 */ 198 WERROR drs_security_access_check_nc_root(struct ldb_context *sam_ctx, 199 TALLOC_CTX *mem_ctx, 200 struct security_token *token, 201 struct drsuapi_DsReplicaObjectIdentifier *nc, 202 const char *ext_right) 203 { 204 struct ldb_dn *dn, *nc_root; 205 WERROR werr; 206 int ret; 207 208 dn = drs_ObjectIdentifier_to_dn(mem_ctx, sam_ctx, nc); 209 W_ERROR_HAVE_NO_MEMORY(dn); 210 ret = dsdb_find_nc_root(sam_ctx, dn, dn, &nc_root); 211 if (ret != LDB_SUCCESS) { 212 return WERR_DS_CANT_FIND_EXPECTED_NC; 213 } 214 werr = drs_security_access_check_log(sam_ctx, mem_ctx, token, nc_root, ext_right); 215 talloc_free(dn); 216 return werr; 217 } -
trunk/server/source4/rpc_server/drsuapi/getncchanges.c
r414 r745 2 2 Unix SMB/CIFS implementation. 3 3 4 implement the D RSUpdateRefs call4 implement the DSGetNCChanges call 5 5 6 6 Copyright (C) Anatoliy Atanasov 2009 … … 22 22 23 23 #include "includes.h" 24 #include "librpc/gen_ndr/ndr_drsuapi.h"25 24 #include "rpc_server/dcerpc_server.h" 26 25 #include "dsdb/samdb/samdb.h" 27 26 #include "param/param.h" 28 27 #include "librpc/gen_ndr/ndr_drsblobs.h" 29 #include "auth/auth.h" 28 #include "librpc/gen_ndr/ndr_drsuapi.h" 29 #include "librpc/gen_ndr/ndr_security.h" 30 #include "libcli/security/security.h" 31 #include "libcli/security/session.h" 30 32 #include "rpc_server/drsuapi/dcesrv_drsuapi.h" 31 33 #include "rpc_server/dcerpc_server_proto.h" 32 34 #include "../libcli/drsuapi/drsuapi.h" 33 #include "libcli/security/security.h" 35 #include "lib/util/binsearch.h" 36 #include "lib/util/tsort.h" 37 #include "auth/session.h" 38 #include "dsdb/common/util.h" 39 40 /* 41 build a DsReplicaObjectIdentifier from a ldb msg 42 */ 43 static struct drsuapi_DsReplicaObjectIdentifier *get_object_identifier(TALLOC_CTX *mem_ctx, 44 struct ldb_message *msg) 45 { 46 struct drsuapi_DsReplicaObjectIdentifier *identifier; 47 struct dom_sid *sid; 48 49 identifier = talloc(mem_ctx, struct drsuapi_DsReplicaObjectIdentifier); 50 if (identifier == NULL) { 51 return NULL; 52 } 53 54 identifier->dn = ldb_dn_alloc_linearized(identifier, msg->dn); 55 identifier->guid = samdb_result_guid(msg, "objectGUID"); 56 57 sid = samdb_result_dom_sid(identifier, msg, "objectSid"); 58 if (sid) { 59 identifier->sid = *sid; 60 } else { 61 ZERO_STRUCT(identifier->sid); 62 } 63 return identifier; 64 } 65 66 static int udv_compare(const struct GUID *guid1, struct GUID guid2) 67 { 68 return GUID_compare(guid1, &guid2); 69 } 70 71 /* 72 see if we can filter an attribute using the uptodateness_vector 73 */ 74 static bool udv_filter(const struct drsuapi_DsReplicaCursorCtrEx *udv, 75 const struct GUID *originating_invocation_id, 76 uint64_t originating_usn) 77 { 78 const struct drsuapi_DsReplicaCursor *c; 79 if (udv == NULL) return false; 80 BINARY_ARRAY_SEARCH(udv->cursors, udv->count, source_dsa_invocation_id, 81 originating_invocation_id, udv_compare, c); 82 if (c && originating_usn <= c->highest_usn) { 83 return true; 84 } 85 return false; 86 87 } 88 89 static int attid_cmp(enum drsuapi_DsAttributeId a1, enum drsuapi_DsAttributeId a2) 90 { 91 if (a1 == a2) return 0; 92 return ((uint32_t)a1) > ((uint32_t)a2) ? 1 : -1; 93 } 94 95 /* 96 check if an attribute is in a partial_attribute_set 97 */ 98 static bool check_partial_attribute_set(const struct dsdb_attribute *sa, 99 struct drsuapi_DsPartialAttributeSet *pas) 100 { 101 enum drsuapi_DsAttributeId *result; 102 BINARY_ARRAY_SEARCH_V(pas->attids, pas->num_attids, (enum drsuapi_DsAttributeId)sa->attributeID_id, 103 attid_cmp, result); 104 return result != NULL; 105 } 106 34 107 35 108 /* … … 40 113 struct ldb_context *sam_ctx, 41 114 struct ldb_dn *ncRoot_dn, 115 bool is_schema_nc, 42 116 struct dsdb_schema *schema, 43 117 DATA_BLOB *session_key, 44 118 uint64_t highest_usn, 45 uint32_t replica_flags) 119 uint32_t replica_flags, 120 struct drsuapi_DsPartialAttributeSet *partial_attribute_set, 121 struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector, 122 enum drsuapi_DsExtendedOperation extended_op) 46 123 { 47 124 const struct ldb_val *md_value; 48 int i, n; 49 struct ldb_dn *obj_dn; 125 uint32_t i, n; 50 126 struct replPropertyMetaDataBlob md; 51 struct dom_sid *sid;52 127 uint32_t rid = 0; 53 128 enum ndr_err_code ndr_err; … … 55 130 const char *rdn; 56 131 const struct dsdb_attribute *rdn_sa; 57 58 if (ldb_dn_compare(ncRoot_dn, msg->dn) == 0) { 132 unsigned int instanceType; 133 struct dsdb_syntax_ctx syntax_ctx; 134 135 /* make dsdb sytanx context for conversions */ 136 dsdb_syntax_ctx_init(&syntax_ctx, sam_ctx, schema); 137 syntax_ctx.is_schema_nc = is_schema_nc; 138 139 instanceType = ldb_msg_find_attr_as_uint(msg, "instanceType", 0); 140 if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) { 59 141 obj->is_nc_prefix = true; 60 142 obj->parent_object_guid = NULL; 61 143 } else { 62 struct ldb_dn *parent_dn;63 uint32_t instance_type;64 65 instance_type = ldb_msg_find_attr_as_uint(msg, "instanceType", 0);66 if (instance_type & INSTANCE_TYPE_IS_NC_HEAD) {67 struct ldb_result *res;68 int ret;69 char *dnstr = ldb_dn_get_linearized(msg->dn);70 msg->dn = ldb_dn_new(msg, sam_ctx, dnstr);71 /* we need to re-search the msg, to avoid the72 * broken dual message problems with our73 * partitions implementation */74 DEBUG(6,(__location__ ": Re-fetching subref %s\n",75 ldb_dn_get_linearized(msg->dn)));76 ret = drsuapi_search_with_extended_dn(sam_ctx, msg, &res,77 msg->dn, LDB_SCOPE_BASE, NULL,78 NULL, NULL);79 if (ret != LDB_SUCCESS || res->count < 1) {80 DEBUG(0,(__location__ ": Failed to reload subref head %s in %s\n",81 ldb_dn_get_linearized(msg->dn), ldb_dn_get_linearized(ncRoot_dn)));82 return WERR_DS_DRA_INTERNAL_ERROR;83 }84 msg = res->msgs[0];85 }86 87 parent_dn = ldb_dn_copy(msg, msg->dn);88 144 obj->is_nc_prefix = false; 89 145 obj->parent_object_guid = talloc(obj, struct GUID); 90 if ( parent_dn== NULL) {146 if (obj->parent_object_guid == NULL) { 91 147 return WERR_DS_DRA_INTERNAL_ERROR; 92 148 } 93 if (ldb_dn_remove_child_components(parent_dn, 1) != true) { 94 DEBUG(0,(__location__ ": Unable to remove DN component\n")); 149 *obj->parent_object_guid = samdb_result_guid(msg, "parentGUID"); 150 if (GUID_all_zero(obj->parent_object_guid)) { 151 DEBUG(0,(__location__ ": missing parentGUID for %s\n", 152 ldb_dn_get_linearized(msg->dn))); 95 153 return WERR_DS_DRA_INTERNAL_ERROR; 96 154 } 97 if (dsdb_find_guid_by_dn(sam_ctx, parent_dn, obj->parent_object_guid) != LDB_SUCCESS) {98 DEBUG(0,(__location__ ": Unable to find parent DN %s %s\n",99 ldb_dn_get_linearized(msg->dn), ldb_dn_get_linearized(parent_dn)));100 }101 talloc_free(parent_dn);102 155 } 103 156 obj->next_object = NULL; … … 109 162 } 110 163 111 ndr_err = ndr_pull_struct_blob(md_value, obj, 112 lp_iconv_convenience(ldb_get_opaque(sam_ctx, "loadparm")), &md, 164 if (instanceType & INSTANCE_TYPE_UNINSTANT) { 165 /* don't send uninstantiated objects */ 166 return WERR_OK; 167 } 168 169 ndr_err = ndr_pull_struct_blob(md_value, obj, &md, 113 170 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob); 114 171 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { … … 135 192 obj->meta_data_ctr = talloc(obj, struct drsuapi_DsReplicaMetaDataCtr); 136 193 attids = talloc_array(obj, uint32_t, md.ctr.ctr1.count); 194 195 obj->object.identifier = get_object_identifier(obj, msg); 196 if (obj->object.identifier == NULL) { 197 return WERR_NOMEM; 198 } 199 dom_sid_split_rid(NULL, &obj->object.identifier->sid, NULL, &rid); 137 200 138 201 obj->meta_data_ctr->meta_data = talloc_array(obj, struct drsuapi_DsReplicaMetaData, md.ctr.ctr1.count); 139 202 for (n=i=0; i<md.ctr.ctr1.count; i++) { 203 const struct dsdb_attribute *sa; 204 bool force_attribute = false; 205 140 206 /* if the attribute has not changed, and it is not the 141 207 instanceType then don't include it */ 142 208 if (md.ctr.ctr1.array[i].local_usn < highest_usn && 143 md.ctr.ctr1.array[i].attid != DRSUAPI_ATTRIBUTE_instanceType) continue; 209 extended_op != DRSUAPI_EXOP_REPL_SECRET && 210 md.ctr.ctr1.array[i].attid != DRSUAPI_ATTID_instanceType) continue; 211 144 212 /* don't include the rDN */ 145 213 if (md.ctr.ctr1.array[i].attid == rdn_sa->attributeID_id) continue; 214 215 sa = dsdb_attribute_by_attributeID_id(schema, md.ctr.ctr1.array[i].attid); 216 if (!sa) { 217 DEBUG(0,(__location__ ": Failed to find attribute in schema for attrid %u mentioned in replPropertyMetaData of %s\n", 218 (unsigned int)md.ctr.ctr1.array[i].attid, 219 ldb_dn_get_linearized(msg->dn))); 220 return WERR_DS_DRA_INTERNAL_ERROR; 221 } 222 223 if (sa->linkID) { 224 struct ldb_message_element *el; 225 el = ldb_msg_find_element(msg, sa->lDAPDisplayName); 226 if (el && el->num_values && dsdb_dn_is_upgraded_link_val(&el->values[0])) { 227 /* don't send upgraded links inline */ 228 continue; 229 } 230 } 231 232 if (extended_op == DRSUAPI_EXOP_REPL_SECRET && 233 !dsdb_attr_in_rodc_fas(sa)) { 234 force_attribute = true; 235 DEBUG(4,("Forcing attribute %s in %s\n", 236 sa->lDAPDisplayName, ldb_dn_get_linearized(msg->dn))); 237 } 238 239 /* filter by uptodateness_vector */ 240 if (md.ctr.ctr1.array[i].attid != DRSUAPI_ATTID_instanceType && 241 !force_attribute && 242 udv_filter(uptodateness_vector, 243 &md.ctr.ctr1.array[i].originating_invocation_id, 244 md.ctr.ctr1.array[i].originating_usn)) { 245 continue; 246 } 247 248 /* filter by partial_attribute_set */ 249 if (partial_attribute_set && !check_partial_attribute_set(sa, partial_attribute_set)) { 250 continue; 251 } 252 146 253 obj->meta_data_ctr->meta_data[n].originating_change_time = md.ctr.ctr1.array[i].originating_change_time; 147 254 obj->meta_data_ctr->meta_data[n].version = md.ctr.ctr1.array[i].version; … … 152 259 } 153 260 154 /* 155 note that if n==0 we still need to send the change, as it 156 could be a rename, which changes the uSNChanged, but not any 157 of the replicated attributes 158 */ 261 /* ignore it if its an empty change. Note that renames always 262 * change the 'name' attribute, so they won't be ignored by 263 * this */ 264 if (n == 0 || 265 (n == 1 && attids[0] == DRSUAPI_ATTID_instanceType)) { 266 talloc_free(obj->meta_data_ctr); 267 obj->meta_data_ctr = NULL; 268 return WERR_OK; 269 } 159 270 160 271 obj->meta_data_ctr->count = n; 161 162 obj->object.identifier = talloc(obj, struct drsuapi_DsReplicaObjectIdentifier);163 obj_dn = ldb_msg_find_attr_as_dn(sam_ctx, obj, msg, "distinguishedName");164 obj->object.identifier->dn = ldb_dn_get_linearized(obj_dn);165 obj->object.identifier->guid = samdb_result_guid(msg, "objectGUID");166 sid = samdb_result_dom_sid(obj, msg, "objectSid");167 if (sid) {168 dom_sid_split_rid(NULL, sid, NULL, &rid);169 obj->object.identifier->sid = *sid;170 } else {171 ZERO_STRUCT(obj->object.identifier->sid);172 }173 272 174 273 obj->object.flags = DRSUAPI_DS_REPLICA_OBJECT_FROM_MASTER; … … 194 293 el = ldb_msg_find_element(msg, sa->lDAPDisplayName); 195 294 if (el == NULL) { 196 DEBUG(0,("No element '%s' for attributeID %u in message\n", 295 /* this happens for attributes that have been removed */ 296 DEBUG(5,("No element '%s' for attributeID %u in message\n", 197 297 sa->lDAPDisplayName, attids[i])); 198 298 ZERO_STRUCT(obj->object.attribute_ctr.attributes[i]); 199 obj->object.attribute_ctr.attributes[i].attid = attids[i]; 299 obj->object.attribute_ctr.attributes[i].attid = 300 dsdb_attribute_get_attid(sa, syntax_ctx.is_schema_nc); 200 301 } else { 201 werr = dsdb_attribute_ldb_to_drsuapi(sam_ctx, schema, el, obj,202 302 werr = sa->syntax->ldb_to_drsuapi(&syntax_ctx, sa, el, obj, 303 &obj->object.attribute_ctr.attributes[i]); 203 304 if (!W_ERROR_IS_OK(werr)) { 204 305 DEBUG(0,("Unable to convert %s to DRS object - %s\n", … … 206 307 return werr; 207 308 } 208 /* if DRSUAPI_D S_REPLICA_NEIGHBOUR_SPECIAL_SECRET_PROCESSING is set309 /* if DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING is set 209 310 * check if attribute is secret and send a null value 210 * TODO: check if we can make this in the database layer211 311 */ 212 if ((replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_SPECIAL_SECRET_PROCESSING) 213 == DRSUAPI_DS_REPLICA_NEIGHBOUR_SPECIAL_SECRET_PROCESSING) { 312 if (replica_flags & DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) { 214 313 drsuapi_process_secret_attribute(&obj->object.attribute_ctr.attributes[i], 215 314 &obj->meta_data_ctr->meta_data[i]); … … 230 329 } 231 330 331 232 332 /* 233 load replUpToDateVector from a DN 333 add one linked attribute from an object to the list of linked 334 attributes in a getncchanges request 234 335 */ 235 static WERROR load_udv(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, 236 struct ldb_dn *dn, struct replUpToDateVectorBlob *ouv) 237 { 238 const char *attrs[] = { "replUpToDateVector", NULL }; 239 struct ldb_result *res = NULL; 336 static WERROR get_nc_changes_add_la(TALLOC_CTX *mem_ctx, 337 struct ldb_context *sam_ctx, 338 const struct dsdb_schema *schema, 339 const struct dsdb_attribute *sa, 340 struct ldb_message *msg, 341 struct dsdb_dn *dsdb_dn, 342 struct drsuapi_DsReplicaLinkedAttribute **la_list, 343 uint32_t *la_count) 344 { 345 struct drsuapi_DsReplicaLinkedAttribute *la; 346 bool active; 347 NTSTATUS status; 348 WERROR werr; 349 350 (*la_list) = talloc_realloc(mem_ctx, *la_list, struct drsuapi_DsReplicaLinkedAttribute, (*la_count)+1); 351 W_ERROR_HAVE_NO_MEMORY(*la_list); 352 353 la = &(*la_list)[*la_count]; 354 355 la->identifier = get_object_identifier(*la_list, msg); 356 W_ERROR_HAVE_NO_MEMORY(la->identifier); 357 358 active = (dsdb_dn_rmd_flags(dsdb_dn->dn) & DSDB_RMD_FLAG_DELETED) == 0; 359 360 la->attid = sa->attributeID_id; 361 la->flags = active?DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE:0; 362 363 status = dsdb_get_extended_dn_nttime(dsdb_dn->dn, &la->originating_add_time, "RMD_ADDTIME"); 364 if (!NT_STATUS_IS_OK(status)) { 365 return ntstatus_to_werror(status); 366 } 367 status = dsdb_get_extended_dn_uint32(dsdb_dn->dn, &la->meta_data.version, "RMD_VERSION"); 368 if (!NT_STATUS_IS_OK(status)) { 369 return ntstatus_to_werror(status); 370 } 371 status = dsdb_get_extended_dn_nttime(dsdb_dn->dn, &la->meta_data.originating_change_time, "RMD_CHANGETIME"); 372 if (!NT_STATUS_IS_OK(status)) { 373 return ntstatus_to_werror(status); 374 } 375 status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &la->meta_data.originating_invocation_id, "RMD_INVOCID"); 376 if (!NT_STATUS_IS_OK(status)) { 377 return ntstatus_to_werror(status); 378 } 379 status = dsdb_get_extended_dn_uint64(dsdb_dn->dn, &la->meta_data.originating_usn, "RMD_ORIGINATING_USN"); 380 if (!NT_STATUS_IS_OK(status)) { 381 return ntstatus_to_werror(status); 382 } 383 384 werr = dsdb_dn_la_to_blob(sam_ctx, sa, schema, *la_list, dsdb_dn, &la->value.blob); 385 W_ERROR_NOT_OK_RETURN(werr); 386 387 (*la_count)++; 388 return WERR_OK; 389 } 390 391 392 /* 393 add linked attributes from an object to the list of linked 394 attributes in a getncchanges request 395 */ 396 static WERROR get_nc_changes_add_links(struct ldb_context *sam_ctx, 397 TALLOC_CTX *mem_ctx, 398 struct ldb_dn *ncRoot_dn, 399 struct dsdb_schema *schema, 400 uint64_t highest_usn, 401 uint32_t replica_flags, 402 struct ldb_message *msg, 403 struct drsuapi_DsReplicaLinkedAttribute **la_list, 404 uint32_t *la_count, 405 struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector) 406 { 407 unsigned int i; 240 408 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 241 struct ldb_message_element *el; 242 enum ndr_err_code ndr_err; 243 244 ZERO_STRUCTP(ouv); 245 246 if (ldb_search(sam_ctx, tmp_ctx, &res, dn, LDB_SCOPE_BASE, attrs, NULL) != LDB_SUCCESS || 247 res->count < 1) { 248 DEBUG(0,("load_udv: failed to read partition object\n")); 249 talloc_free(tmp_ctx); 250 return WERR_DS_DRA_INTERNAL_ERROR; 251 } 252 253 el = ldb_msg_find_element(res->msgs[0], "replUpToDateVector"); 254 if (el == NULL || el->num_values < 1) { 255 talloc_free(tmp_ctx); 256 ouv->version = 2; 257 return WERR_OK; 258 } 259 260 ndr_err = ndr_pull_struct_blob(&el->values[0], 261 mem_ctx, lp_iconv_convenience(ldb_get_opaque(sam_ctx, "loadparm")), 262 ouv, 263 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob); 409 uint64_t uSNChanged = ldb_msg_find_attr_as_int(msg, "uSNChanged", -1); 410 411 for (i=0; i<msg->num_elements; i++) { 412 struct ldb_message_element *el = &msg->elements[i]; 413 const struct dsdb_attribute *sa; 414 unsigned int j; 415 416 sa = dsdb_attribute_by_lDAPDisplayName(schema, el->name); 417 418 if (!sa || sa->linkID == 0 || (sa->linkID & 1)) { 419 /* we only want forward links */ 420 continue; 421 } 422 423 if (el->num_values && !dsdb_dn_is_upgraded_link_val(&el->values[0])) { 424 /* its an old style link, it will have been 425 * sent in the main replication data */ 426 continue; 427 } 428 429 for (j=0; j<el->num_values; j++) { 430 struct dsdb_dn *dsdb_dn; 431 uint64_t local_usn; 432 NTSTATUS status; 433 WERROR werr; 434 435 dsdb_dn = dsdb_dn_parse(tmp_ctx, sam_ctx, &el->values[j], sa->syntax->ldap_oid); 436 if (dsdb_dn == NULL) { 437 DEBUG(1,(__location__ ": Failed to parse DN for %s in %s\n", 438 el->name, ldb_dn_get_linearized(msg->dn))); 439 talloc_free(tmp_ctx); 440 return WERR_DS_DRA_INTERNAL_ERROR; 441 } 442 443 status = dsdb_get_extended_dn_uint64(dsdb_dn->dn, &local_usn, "RMD_LOCAL_USN"); 444 if (!NT_STATUS_IS_OK(status)) { 445 /* this can happen for attributes 446 given to us with old style meta 447 data */ 448 continue; 449 } 450 451 if (local_usn > uSNChanged) { 452 DEBUG(1,(__location__ ": uSNChanged less than RMD_LOCAL_USN for %s on %s\n", 453 el->name, ldb_dn_get_linearized(msg->dn))); 454 talloc_free(tmp_ctx); 455 return WERR_DS_DRA_INTERNAL_ERROR; 456 } 457 458 if (local_usn < highest_usn) { 459 continue; 460 } 461 462 werr = get_nc_changes_add_la(mem_ctx, sam_ctx, schema, sa, msg, 463 dsdb_dn, la_list, la_count); 464 if (!W_ERROR_IS_OK(werr)) { 465 talloc_free(tmp_ctx); 466 return werr; 467 } 468 } 469 } 470 264 471 talloc_free(tmp_ctx); 265 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {266 DEBUG(0,(__location__ ": Failed to parse replUpToDateVector for %s\n",267 ldb_dn_get_linearized(dn)));268 return WERR_DS_DRA_INTERNAL_ERROR;269 }270 271 472 return WERR_OK; 272 273 473 } 274 474 … … 280 480 struct drsuapi_DsReplicaCursor2CtrEx *udv) 281 481 { 482 int ret; 483 484 udv->version = 2; 485 udv->reserved1 = 0; 486 udv->reserved2 = 0; 487 488 ret = dsdb_load_udv_v2(sam_ctx, ncRoot_dn, udv, &udv->cursors, &udv->count); 489 if (ret != LDB_SUCCESS) { 490 DEBUG(0,(__location__ ": Failed to load UDV for %s - %s\n", 491 ldb_dn_get_linearized(ncRoot_dn), ldb_errstring(sam_ctx))); 492 return WERR_DS_DRA_INTERNAL_ERROR; 493 } 494 495 return WERR_OK; 496 } 497 498 499 /* comparison function for linked attributes - see CompareLinks() in 500 * MS-DRSR section 4.1.10.5.17 */ 501 static int linked_attribute_compare(const struct drsuapi_DsReplicaLinkedAttribute *la1, 502 const struct drsuapi_DsReplicaLinkedAttribute *la2, 503 struct ldb_context *sam_ctx) 504 { 505 int c; 282 506 WERROR werr; 283 struct drsuapi_DsReplicaCursor2 *tmp_cursor; 284 uint64_t highest_commited_usn; 285 NTTIME now; 286 time_t t = time(NULL); 507 TALLOC_CTX *tmp_ctx; 508 const struct dsdb_schema *schema; 509 const struct dsdb_attribute *schema_attrib; 510 struct dsdb_dn *dn1, *dn2; 511 struct GUID guid1, guid2; 512 NTSTATUS status; 513 514 c = GUID_compare(&la1->identifier->guid, 515 &la2->identifier->guid); 516 if (c != 0) return c; 517 518 if (la1->attid != la2->attid) { 519 return la1->attid < la2->attid? -1:1; 520 } 521 522 if ((la1->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE) != 523 (la2->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE)) { 524 return (la1->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE)? 1:-1; 525 } 526 527 /* we need to get the target GUIDs to compare */ 528 tmp_ctx = talloc_new(sam_ctx); 529 530 schema = dsdb_get_schema(sam_ctx, tmp_ctx); 531 schema_attrib = dsdb_attribute_by_attributeID_id(schema, la1->attid); 532 533 werr = dsdb_dn_la_from_blob(sam_ctx, schema_attrib, schema, tmp_ctx, la1->value.blob, &dn1); 534 if (!W_ERROR_IS_OK(werr)) { 535 DEBUG(0,(__location__ ": Bad la1 blob in sort\n")); 536 talloc_free(tmp_ctx); 537 return 0; 538 } 539 540 werr = dsdb_dn_la_from_blob(sam_ctx, schema_attrib, schema, tmp_ctx, la2->value.blob, &dn2); 541 if (!W_ERROR_IS_OK(werr)) { 542 DEBUG(0,(__location__ ": Bad la2 blob in sort\n")); 543 talloc_free(tmp_ctx); 544 return 0; 545 } 546 547 status = dsdb_get_extended_dn_guid(dn1->dn, &guid1, "GUID"); 548 if (!NT_STATUS_IS_OK(status)) { 549 DEBUG(0,(__location__ ": Bad la1 guid in sort\n")); 550 talloc_free(tmp_ctx); 551 return 0; 552 } 553 status = dsdb_get_extended_dn_guid(dn2->dn, &guid2, "GUID"); 554 if (!NT_STATUS_IS_OK(status)) { 555 DEBUG(0,(__location__ ": Bad la2 guid in sort\n")); 556 talloc_free(tmp_ctx); 557 return 0; 558 } 559 560 talloc_free(tmp_ctx); 561 562 return GUID_compare(&guid1, &guid2); 563 } 564 565 566 /* 567 sort the objects we send by tree order 568 */ 569 static int site_res_cmp_parent_order(struct ldb_message **m1, struct ldb_message **m2) 570 { 571 return ldb_dn_compare((*m2)->dn, (*m1)->dn); 572 } 573 574 /* 575 sort the objects we send first by uSNChanged 576 */ 577 static int site_res_cmp_usn_order(struct ldb_message **m1, struct ldb_message **m2) 578 { 579 unsigned usnchanged1, usnchanged2; 580 unsigned cn1, cn2; 581 cn1 = ldb_dn_get_comp_num((*m1)->dn); 582 cn2 = ldb_dn_get_comp_num((*m2)->dn); 583 if (cn1 != cn2) { 584 return cn1 > cn2 ? 1 : -1; 585 } 586 usnchanged1 = ldb_msg_find_attr_as_uint(*m1, "uSNChanged", 0); 587 usnchanged2 = ldb_msg_find_attr_as_uint(*m2, "uSNChanged", 0); 588 if (usnchanged1 == usnchanged2) { 589 return 0; 590 } 591 return usnchanged1 > usnchanged2 ? 1 : -1; 592 } 593 594 595 /* 596 handle a DRSUAPI_EXOP_FSMO_RID_ALLOC call 597 */ 598 static WERROR getncchanges_rid_alloc(struct drsuapi_bind_state *b_state, 599 TALLOC_CTX *mem_ctx, 600 struct drsuapi_DsGetNCChangesRequest10 *req10, 601 struct drsuapi_DsGetNCChangesCtr6 *ctr6) 602 { 603 struct ldb_dn *rid_manager_dn, *fsmo_role_dn, *req_dn; 287 604 int ret; 288 struct replUpToDateVectorBlob ouv; 289 290 werr = load_udv(sam_ctx, udv, ncRoot_dn, &ouv); 605 struct ldb_context *ldb = b_state->sam_ctx; 606 struct ldb_result *ext_res; 607 struct ldb_dn *base_dn; 608 struct dsdb_fsmo_extended_op *exop; 609 610 /* 611 steps: 612 - verify that the DN being asked for is the RID Manager DN 613 - verify that we are the RID Manager 614 */ 615 616 /* work out who is the RID Manager */ 617 ret = samdb_rid_manager_dn(ldb, mem_ctx, &rid_manager_dn); 618 if (ret != LDB_SUCCESS) { 619 DEBUG(0, (__location__ ": Failed to find RID Manager object - %s\n", ldb_errstring(ldb))); 620 return WERR_DS_DRA_INTERNAL_ERROR; 621 } 622 623 req_dn = drs_ObjectIdentifier_to_dn(mem_ctx, ldb, req10->naming_context); 624 if (!ldb_dn_validate(req_dn) || 625 ldb_dn_compare(req_dn, rid_manager_dn) != 0) { 626 /* that isn't the RID Manager DN */ 627 DEBUG(0,(__location__ ": RID Alloc request for wrong DN %s\n", 628 drs_ObjectIdentifier_to_string(mem_ctx, req10->naming_context))); 629 ctr6->extended_ret = DRSUAPI_EXOP_ERR_MISMATCH; 630 return WERR_OK; 631 } 632 633 /* find the DN of the RID Manager */ 634 ret = samdb_reference_dn(ldb, mem_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn); 635 if (ret != LDB_SUCCESS) { 636 DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in RID Manager object - %s\n", 637 ldb_errstring(ldb))); 638 ctr6->extended_ret = DRSUAPI_EXOP_ERR_FSMO_NOT_OWNER; 639 return WERR_DS_DRA_INTERNAL_ERROR; 640 } 641 642 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) { 643 /* we're not the RID Manager - go away */ 644 DEBUG(0,(__location__ ": RID Alloc request when not RID Manager\n")); 645 ctr6->extended_ret = DRSUAPI_EXOP_ERR_FSMO_NOT_OWNER; 646 return WERR_OK; 647 } 648 649 exop = talloc(mem_ctx, struct dsdb_fsmo_extended_op); 650 W_ERROR_HAVE_NO_MEMORY(exop); 651 652 exop->fsmo_info = req10->fsmo_info; 653 exop->destination_dsa_guid = req10->destination_dsa_guid; 654 655 ret = ldb_transaction_start(ldb); 656 if (ret != LDB_SUCCESS) { 657 DEBUG(0,(__location__ ": Failed transaction start - %s\n", 658 ldb_errstring(ldb))); 659 return WERR_DS_DRA_INTERNAL_ERROR; 660 } 661 662 /* 663 * FIXME (kim): this is a temp hack to return just few object, 664 * but not the whole domain NC. 665 * We should remove this hack and implement a 'scope' 666 * building function to return just the set of object 667 * documented for DRSUAPI_EXOP_FSMO_RID_ALLOC extended_op 668 */ 669 ldb_sequence_number(ldb, LDB_SEQ_HIGHEST_SEQ, &req10->highwatermark.highest_usn); 670 671 ret = ldb_extended(ldb, DSDB_EXTENDED_ALLOCATE_RID_POOL, exop, &ext_res); 672 if (ret != LDB_SUCCESS) { 673 DEBUG(0,(__location__ ": Failed extended allocation RID pool operation - %s\n", 674 ldb_errstring(ldb))); 675 ldb_transaction_cancel(ldb); 676 return WERR_DS_DRA_INTERNAL_ERROR; 677 } 678 679 ret = ldb_transaction_commit(ldb); 680 if (ret != LDB_SUCCESS) { 681 DEBUG(0,(__location__ ": Failed transaction commit - %s\n", 682 ldb_errstring(ldb))); 683 return WERR_DS_DRA_INTERNAL_ERROR; 684 } 685 686 talloc_free(ext_res); 687 688 base_dn = ldb_get_default_basedn(ldb); 689 690 DEBUG(2,("Allocated RID pool for server %s\n", 691 GUID_string(mem_ctx, &req10->destination_dsa_guid))); 692 693 ctr6->extended_ret = DRSUAPI_EXOP_ERR_SUCCESS; 694 695 return WERR_OK; 696 } 697 698 /* 699 return an array of SIDs from a ldb_message given an attribute name 700 assumes the SIDs are in extended DN format 701 */ 702 static WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx, 703 struct ldb_message *msg, 704 TALLOC_CTX *mem_ctx, 705 const char *attr, 706 const struct dom_sid ***sids) 707 { 708 struct ldb_message_element *el; 709 unsigned int i; 710 711 el = ldb_msg_find_element(msg, attr); 712 if (!el) { 713 *sids = NULL; 714 return WERR_OK; 715 } 716 717 (*sids) = talloc_array(mem_ctx, const struct dom_sid *, el->num_values + 1); 718 W_ERROR_HAVE_NO_MEMORY(*sids); 719 720 for (i=0; i<el->num_values; i++) { 721 struct ldb_dn *dn = ldb_dn_from_ldb_val(mem_ctx, sam_ctx, &el->values[i]); 722 NTSTATUS status; 723 struct dom_sid *sid; 724 725 sid = talloc(*sids, struct dom_sid); 726 W_ERROR_HAVE_NO_MEMORY(sid); 727 status = dsdb_get_extended_dn_sid(dn, sid, "SID"); 728 if (!NT_STATUS_IS_OK(status)) { 729 return WERR_INTERNAL_DB_CORRUPTION; 730 } 731 (*sids)[i] = sid; 732 } 733 (*sids)[i] = NULL; 734 735 return WERR_OK; 736 } 737 738 739 /* 740 return an array of SIDs from a ldb_message given an attribute name 741 assumes the SIDs are in NDR form 742 */ 743 static WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx, 744 struct ldb_message *msg, 745 TALLOC_CTX *mem_ctx, 746 const char *attr, 747 const struct dom_sid ***sids) 748 { 749 struct ldb_message_element *el; 750 unsigned int i; 751 752 el = ldb_msg_find_element(msg, attr); 753 if (!el) { 754 *sids = NULL; 755 return WERR_OK; 756 } 757 758 (*sids) = talloc_array(mem_ctx, const struct dom_sid *, el->num_values + 1); 759 W_ERROR_HAVE_NO_MEMORY(*sids); 760 761 for (i=0; i<el->num_values; i++) { 762 enum ndr_err_code ndr_err; 763 struct dom_sid *sid; 764 765 sid = talloc(*sids, struct dom_sid); 766 W_ERROR_HAVE_NO_MEMORY(sid); 767 768 ndr_err = ndr_pull_struct_blob(&el->values[i], sid, sid, 769 (ndr_pull_flags_fn_t)ndr_pull_dom_sid); 770 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 771 return WERR_INTERNAL_DB_CORRUPTION; 772 } 773 (*sids)[i] = sid; 774 } 775 (*sids)[i] = NULL; 776 777 return WERR_OK; 778 } 779 780 /* 781 see if any SIDs in list1 are in list2 782 */ 783 static bool sid_list_match(const struct dom_sid **list1, const struct dom_sid **list2) 784 { 785 unsigned int i, j; 786 /* do we ever have enough SIDs here to worry about O(n^2) ? */ 787 for (i=0; list1[i]; i++) { 788 for (j=0; list2[j]; j++) { 789 if (dom_sid_equal(list1[i], list2[j])) { 790 return true; 791 } 792 } 793 } 794 return false; 795 } 796 797 /* 798 handle a DRSUAPI_EXOP_REPL_SECRET call 799 */ 800 static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, 801 TALLOC_CTX *mem_ctx, 802 struct drsuapi_DsGetNCChangesRequest10 *req10, 803 struct dom_sid *user_sid, 804 struct drsuapi_DsGetNCChangesCtr6 *ctr6) 805 { 806 struct drsuapi_DsReplicaObjectIdentifier *ncRoot = req10->naming_context; 807 struct ldb_dn *obj_dn, *rodc_dn, *krbtgt_link_dn; 808 int ret; 809 const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", NULL }; 810 const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL }; 811 struct ldb_result *rodc_res, *obj_res; 812 const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids; 813 WERROR werr; 814 815 DEBUG(3,(__location__ ": DRSUAPI_EXOP_REPL_SECRET extended op on %s\n", 816 drs_ObjectIdentifier_to_string(mem_ctx, ncRoot))); 817 818 /* 819 * we need to work out if we will allow this RODC to 820 * replicate the secrets for this object 821 * 822 * see 4.1.10.5.14 GetRevealSecretsPolicyForUser for details 823 * of this function 824 */ 825 826 if (b_state->sam_ctx_system == NULL) { 827 /* this operation needs system level access */ 828 ctr6->extended_ret = DRSUAPI_EXOP_ERR_ACCESS_DENIED; 829 return WERR_DS_DRA_SOURCE_DISABLED; 830 } 831 832 obj_dn = drs_ObjectIdentifier_to_dn(mem_ctx, b_state->sam_ctx_system, ncRoot); 833 if (!ldb_dn_validate(obj_dn)) goto failed; 834 835 rodc_dn = ldb_dn_new_fmt(mem_ctx, b_state->sam_ctx_system, "<SID=%s>", 836 dom_sid_string(mem_ctx, user_sid)); 837 if (!ldb_dn_validate(rodc_dn)) goto failed; 838 839 /* do the two searches we need */ 840 ret = dsdb_search_dn(b_state->sam_ctx_system, mem_ctx, &rodc_res, rodc_dn, rodc_attrs, 841 DSDB_SEARCH_SHOW_EXTENDED_DN); 842 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto failed; 843 844 ret = dsdb_search_dn(b_state->sam_ctx_system, mem_ctx, &obj_res, obj_dn, obj_attrs, 0); 845 if (ret != LDB_SUCCESS || obj_res->count != 1) goto failed; 846 847 /* if the object SID is equal to the user_sid, allow */ 848 if (dom_sid_equal(user_sid, 849 samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid"))) { 850 goto allowed; 851 } 852 853 /* an RODC is allowed to get its own krbtgt account secrets */ 854 krbtgt_link_dn = samdb_result_dn(b_state->sam_ctx_system, mem_ctx, 855 rodc_res->msgs[0], "msDS-KrbTgtLink", NULL); 856 if (krbtgt_link_dn != NULL && 857 ldb_dn_compare(obj_dn, krbtgt_link_dn) == 0) { 858 goto allowed; 859 } 860 861 /* but it isn't allowed to get anyone elses krbtgt secrets */ 862 if (samdb_result_dn(b_state->sam_ctx_system, mem_ctx, 863 obj_res->msgs[0], "msDS-KrbTgtLinkBL", NULL)) { 864 goto denied; 865 } 866 867 if (ldb_msg_find_attr_as_uint(obj_res->msgs[0], 868 "userAccountControl", 0) & 869 UF_INTERDOMAIN_TRUST_ACCOUNT) { 870 goto denied; 871 } 872 873 werr = samdb_result_sid_array_dn(b_state->sam_ctx_system, rodc_res->msgs[0], 874 mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids); 291 875 if (!W_ERROR_IS_OK(werr)) { 292 return werr; 293 } 294 295 ret = ldb_sequence_number(sam_ctx, LDB_SEQ_HIGHEST_SEQ, &highest_commited_usn); 876 goto denied; 877 } 878 879 werr = samdb_result_sid_array_dn(b_state->sam_ctx_system, rodc_res->msgs[0], 880 mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids); 881 if (!W_ERROR_IS_OK(werr)) { 882 goto denied; 883 } 884 885 werr = samdb_result_sid_array_ndr(b_state->sam_ctx_system, obj_res->msgs[0], 886 mem_ctx, "tokenGroups", &token_sids); 887 if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { 888 goto denied; 889 } 890 891 if (never_reveal_sids && 892 sid_list_match(token_sids, never_reveal_sids)) { 893 goto denied; 894 } 895 896 if (reveal_sids && 897 sid_list_match(token_sids, reveal_sids)) { 898 goto allowed; 899 } 900 901 /* default deny */ 902 denied: 903 DEBUG(2,(__location__ ": Denied RODC secret replication for %s by RODC %s\n", 904 ldb_dn_get_linearized(obj_dn), ldb_dn_get_linearized(rodc_res->msgs[0]->dn))); 905 ctr6->extended_ret = DRSUAPI_EXOP_ERR_NONE; 906 return WERR_DS_DRA_ACCESS_DENIED; 907 908 allowed: 909 DEBUG(2,(__location__ ": Allowed RODC secret replication for %s by RODC %s\n", 910 ldb_dn_get_linearized(obj_dn), ldb_dn_get_linearized(rodc_res->msgs[0]->dn))); 911 ctr6->extended_ret = DRSUAPI_EXOP_ERR_SUCCESS; 912 req10->highwatermark.highest_usn = 0; 913 return WERR_OK; 914 915 failed: 916 DEBUG(2,(__location__ ": Failed RODC secret replication for %s by RODC %s\n", 917 ldb_dn_get_linearized(obj_dn), dom_sid_string(mem_ctx, user_sid))); 918 ctr6->extended_ret = DRSUAPI_EXOP_ERR_NONE; 919 return WERR_DS_DRA_BAD_DN; 920 } 921 922 923 /* 924 handle a DRSUAPI_EXOP_REPL_OBJ call 925 */ 926 static WERROR getncchanges_repl_obj(struct drsuapi_bind_state *b_state, 927 TALLOC_CTX *mem_ctx, 928 struct drsuapi_DsGetNCChangesRequest10 *req10, 929 struct dom_sid *user_sid, 930 struct drsuapi_DsGetNCChangesCtr6 *ctr6) 931 { 932 struct drsuapi_DsReplicaObjectIdentifier *ncRoot = req10->naming_context; 933 934 DEBUG(3,(__location__ ": DRSUAPI_EXOP_REPL_OBJ extended op on %s\n", 935 drs_ObjectIdentifier_to_string(mem_ctx, ncRoot))); 936 937 ctr6->extended_ret = DRSUAPI_EXOP_ERR_SUCCESS; 938 req10->highwatermark.highest_usn = 0; 939 return WERR_OK; 940 } 941 942 943 /* 944 handle DRSUAPI_EXOP_FSMO_REQ_ROLE, 945 DRSUAPI_EXOP_FSMO_RID_REQ_ROLE, 946 and DRSUAPI_EXOP_FSMO_REQ_PDC calls 947 */ 948 static WERROR getncchanges_change_master(struct drsuapi_bind_state *b_state, 949 TALLOC_CTX *mem_ctx, 950 struct drsuapi_DsGetNCChangesRequest10 *req10, 951 struct drsuapi_DsGetNCChangesCtr6 *ctr6) 952 { 953 struct ldb_dn *fsmo_role_dn, *req_dn, *ntds_dn; 954 int ret; 955 unsigned int i; 956 struct ldb_context *ldb = b_state->sam_ctx; 957 struct ldb_message *msg; 958 959 /* 960 steps: 961 - verify that the client dn exists 962 - verify that we are the current master 963 */ 964 965 req_dn = drs_ObjectIdentifier_to_dn(mem_ctx, ldb, req10->naming_context); 966 if (!ldb_dn_validate(req_dn)) { 967 /* that is not a valid dn */ 968 DEBUG(0,(__location__ ": FSMO role transfer request for invalid DN %s\n", 969 drs_ObjectIdentifier_to_string(mem_ctx, req10->naming_context))); 970 ctr6->extended_ret = DRSUAPI_EXOP_ERR_MISMATCH; 971 return WERR_OK; 972 } 973 974 /* retrieve the current role owner */ 975 ret = samdb_reference_dn(ldb, mem_ctx, req_dn, "fSMORoleOwner", &fsmo_role_dn); 296 976 if (ret != LDB_SUCCESS) { 297 return WERR_DS_DRA_INTERNAL_ERROR; 298 } 299 300 tmp_cursor = talloc(udv, struct drsuapi_DsReplicaCursor2); 301 tmp_cursor->source_dsa_invocation_id = *(samdb_ntds_invocation_id(sam_ctx)); 302 tmp_cursor->highest_usn = highest_commited_usn; 303 unix_to_nt_time(&now, t); 304 tmp_cursor->last_sync_success = now; 305 306 udv->count = ouv.ctr.ctr2.count + 1; 307 udv->cursors = talloc_steal(udv, ouv.ctr.ctr2.cursors); 308 udv->cursors = talloc_realloc(udv, udv->cursors, struct drsuapi_DsReplicaCursor2, udv->count); 309 if (!udv->cursors) { 310 return WERR_DS_DRA_INTERNAL_ERROR; 311 } 312 udv->cursors[udv->count - 1] = *tmp_cursor; 313 314 qsort(udv->cursors, udv->count, 315 sizeof(struct drsuapi_DsReplicaCursor2), 316 (comparison_fn_t)drsuapi_DsReplicaCursor2_compare); 977 DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in context - %s\n", 978 ldb_errstring(ldb))); 979 ctr6->extended_ret = DRSUAPI_EXOP_ERR_FSMO_NOT_OWNER; 980 return WERR_DS_DRA_INTERNAL_ERROR; 981 } 982 983 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) { 984 /* we're not the current owner - go away */ 985 DEBUG(0,(__location__ ": FSMO transfer request when not owner\n")); 986 ctr6->extended_ret = DRSUAPI_EXOP_ERR_FSMO_NOT_OWNER; 987 return WERR_OK; 988 } 989 990 /* change the current master */ 991 msg = ldb_msg_new(ldb); 992 W_ERROR_HAVE_NO_MEMORY(msg); 993 msg->dn = drs_ObjectIdentifier_to_dn(msg, ldb, req10->naming_context); 994 W_ERROR_HAVE_NO_MEMORY(msg->dn); 995 996 ret = dsdb_find_dn_by_guid(ldb, msg, &req10->destination_dsa_guid, &ntds_dn); 997 if (ret != LDB_SUCCESS) { 998 DEBUG(0, (__location__ ": Unable to find NTDS object for guid %s - %s\n", 999 GUID_string(mem_ctx, &req10->destination_dsa_guid), ldb_errstring(ldb))); 1000 talloc_free(msg); 1001 return WERR_DS_DRA_INTERNAL_ERROR; 1002 } 1003 1004 ret = ldb_msg_add_string(msg, "fSMORoleOwner", ldb_dn_get_linearized(ntds_dn)); 1005 if (ret != 0) { 1006 talloc_free(msg); 1007 return WERR_DS_DRA_INTERNAL_ERROR; 1008 } 1009 1010 for (i=0;i<msg->num_elements;i++) { 1011 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; 1012 } 1013 1014 ret = ldb_transaction_start(ldb); 1015 if (ret != LDB_SUCCESS) { 1016 DEBUG(0,(__location__ ": Failed transaction start - %s\n", 1017 ldb_errstring(ldb))); 1018 return WERR_DS_DRA_INTERNAL_ERROR; 1019 } 1020 1021 ret = ldb_modify(ldb, msg); 1022 if (ret != LDB_SUCCESS) { 1023 DEBUG(0,(__location__ ": Failed to change current owner - %s\n", 1024 ldb_errstring(ldb))); 1025 ldb_transaction_cancel(ldb); 1026 return WERR_DS_DRA_INTERNAL_ERROR; 1027 } 1028 1029 ret = ldb_transaction_commit(ldb); 1030 if (ret != LDB_SUCCESS) { 1031 DEBUG(0,(__location__ ": Failed transaction commit - %s\n", 1032 ldb_errstring(ldb))); 1033 return WERR_DS_DRA_INTERNAL_ERROR; 1034 } 1035 1036 ctr6->extended_ret = DRSUAPI_EXOP_ERR_SUCCESS; 317 1037 318 1038 return WERR_OK; … … 321 1041 /* state of a partially completed getncchanges call */ 322 1042 struct drsuapi_getncchanges_state { 323 struct ldb_result *site_res;324 uint32_t num_ sent;325 struct ldb_context *sam_ctx;1043 struct GUID *guids; 1044 uint32_t num_records; 1045 uint32_t num_processed; 326 1046 struct ldb_dn *ncRoot_dn; 327 uint32_t min_usn; 1047 bool is_schema_nc; 1048 uint64_t min_usn; 1049 uint64_t highest_usn; 1050 struct ldb_dn *last_dn; 1051 struct drsuapi_DsReplicaLinkedAttribute *la_list; 1052 uint32_t la_count; 1053 bool la_sorted; 1054 uint32_t la_idx; 1055 struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector; 328 1056 }; 1057 1058 /* 1059 see if this getncchanges request includes a request to reveal secret information 1060 */ 1061 static WERROR dcesrv_drsuapi_is_reveal_secrets_request(struct drsuapi_bind_state *b_state, 1062 struct drsuapi_DsGetNCChangesRequest10 *req10, 1063 bool *is_secret_request) 1064 { 1065 enum drsuapi_DsExtendedOperation exop; 1066 uint32_t i; 1067 struct dsdb_schema *schema; 1068 1069 *is_secret_request = true; 1070 1071 exop = req10->extended_op; 1072 1073 switch (exop) { 1074 case DRSUAPI_EXOP_FSMO_REQ_ROLE: 1075 case DRSUAPI_EXOP_FSMO_RID_ALLOC: 1076 case DRSUAPI_EXOP_FSMO_RID_REQ_ROLE: 1077 case DRSUAPI_EXOP_FSMO_REQ_PDC: 1078 case DRSUAPI_EXOP_FSMO_ABANDON_ROLE: 1079 /* FSMO exops can reveal secrets */ 1080 *is_secret_request = true; 1081 return WERR_OK; 1082 case DRSUAPI_EXOP_REPL_SECRET: 1083 case DRSUAPI_EXOP_REPL_OBJ: 1084 case DRSUAPI_EXOP_NONE: 1085 break; 1086 } 1087 1088 if (req10->replica_flags & DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) { 1089 *is_secret_request = false; 1090 return WERR_OK; 1091 } 1092 1093 if (exop == DRSUAPI_EXOP_REPL_SECRET || 1094 req10->partial_attribute_set == NULL) { 1095 /* they want secrets */ 1096 *is_secret_request = true; 1097 return WERR_OK; 1098 } 1099 1100 schema = dsdb_get_schema(b_state->sam_ctx, NULL); 1101 1102 /* check the attributes they asked for */ 1103 for (i=0; i<req10->partial_attribute_set->num_attids; i++) { 1104 const struct dsdb_attribute *sa; 1105 sa = dsdb_attribute_by_attributeID_id(schema, req10->partial_attribute_set->attids[i]); 1106 if (sa == NULL) { 1107 return WERR_DS_DRA_SCHEMA_MISMATCH; 1108 } 1109 if (!dsdb_attr_in_rodc_fas(sa)) { 1110 *is_secret_request = true; 1111 return WERR_OK; 1112 } 1113 } 1114 1115 /* check the attributes they asked for */ 1116 for (i=0; i<req10->partial_attribute_set_ex->num_attids; i++) { 1117 const struct dsdb_attribute *sa; 1118 sa = dsdb_attribute_by_attributeID_id(schema, req10->partial_attribute_set_ex->attids[i]); 1119 if (sa == NULL) { 1120 return WERR_DS_DRA_SCHEMA_MISMATCH; 1121 } 1122 if (!dsdb_attr_in_rodc_fas(sa)) { 1123 *is_secret_request = true; 1124 return WERR_OK; 1125 } 1126 } 1127 1128 *is_secret_request = false; 1129 return WERR_OK; 1130 } 1131 1132 1133 /* 1134 map from req8 to req10 1135 */ 1136 static struct drsuapi_DsGetNCChangesRequest10 * 1137 getncchanges_map_req8(TALLOC_CTX *mem_ctx, 1138 struct drsuapi_DsGetNCChangesRequest8 *req8) 1139 { 1140 struct drsuapi_DsGetNCChangesRequest10 *req10 = talloc_zero(mem_ctx, 1141 struct drsuapi_DsGetNCChangesRequest10); 1142 if (req10 == NULL) { 1143 return NULL; 1144 } 1145 1146 req10->destination_dsa_guid = req8->destination_dsa_guid; 1147 req10->source_dsa_invocation_id = req8->source_dsa_invocation_id; 1148 req10->naming_context = req8->naming_context; 1149 req10->highwatermark = req8->highwatermark; 1150 req10->uptodateness_vector = req8->uptodateness_vector; 1151 req10->replica_flags = req8->replica_flags; 1152 req10->max_object_count = req8->max_object_count; 1153 req10->max_ndr_size = req8->max_ndr_size; 1154 req10->extended_op = req8->extended_op; 1155 req10->fsmo_info = req8->fsmo_info; 1156 req10->partial_attribute_set = req8->partial_attribute_set; 1157 req10->partial_attribute_set_ex = req8->partial_attribute_set_ex; 1158 req10->mapping_ctr = req8->mapping_ctr; 1159 1160 return req10; 1161 } 1162 329 1163 330 1164 /* 331 1165 drsuapi_DsGetNCChanges 1166 1167 see MS-DRSR 4.1.10.5.2 for basic logic of this function 332 1168 */ 333 1169 WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, … … 336 1172 struct drsuapi_DsReplicaObjectIdentifier *ncRoot; 337 1173 int ret; 338 int i;1174 uint32_t i; 339 1175 struct dsdb_schema *schema; 340 1176 struct drsuapi_DsReplicaOIDMapping_Ctr *ctr; … … 342 1178 NTSTATUS status; 343 1179 DATA_BLOB session_key; 344 const char *attrs[] = { "*", "distinguishedName", NULL }; 1180 const char *attrs[] = { "uSNChanged", 1181 "objectGUID" , 1182 NULL }; 345 1183 WERROR werr; 346 1184 struct dcesrv_handle *h; 347 1185 struct drsuapi_bind_state *b_state; 348 1186 struct drsuapi_getncchanges_state *getnc_state; 1187 struct drsuapi_DsGetNCChangesRequest10 *req10; 1188 uint32_t options; 1189 uint32_t max_objects; 1190 uint32_t max_links; 1191 uint32_t link_count = 0; 1192 uint32_t link_total = 0; 1193 uint32_t link_given = 0; 1194 struct ldb_dn *search_dn = NULL; 1195 bool am_rodc, null_scope=false; 1196 enum security_user_level security_level; 1197 struct ldb_context *sam_ctx; 1198 struct dom_sid *user_sid; 1199 bool is_secret_request; 349 1200 350 1201 DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); 351 1202 b_state = h->data; 1203 1204 sam_ctx = b_state->sam_ctx_system?b_state->sam_ctx_system:b_state->sam_ctx; 352 1205 353 1206 *r->out.level_out = 6; … … 361 1214 r->out.ctr->ctr6.uptodateness_vector = NULL; 362 1215 363 /* Check request revision. */ 364 if (r->in.level != 8) { 1216 /* a RODC doesn't allow for any replication */ 1217 ret = samdb_rodc(sam_ctx, &am_rodc); 1218 if (ret == LDB_SUCCESS && am_rodc) { 1219 DEBUG(0,(__location__ ": DsGetNCChanges attempt on RODC\n")); 1220 return WERR_DS_DRA_SOURCE_DISABLED; 1221 } 1222 1223 /* Check request revision. 1224 */ 1225 switch (r->in.level) { 1226 case 8: 1227 req10 = getncchanges_map_req8(mem_ctx, &r->in.req->req8); 1228 if (req10 == NULL) { 1229 return WERR_NOMEM; 1230 } 1231 break; 1232 case 10: 1233 req10 = &r->in.req->req10; 1234 break; 1235 default: 1236 DEBUG(0,(__location__ ": Request for DsGetNCChanges with unsupported level %u\n", 1237 r->in.level)); 365 1238 return WERR_REVISION_MISMATCH; 366 1239 } 367 1240 1241 368 1242 /* Perform access checks. */ 369 if (r->in.req->req8.naming_context == NULL) { 1243 /* TODO: we need to support a sync on a specific non-root 1244 * DN. We'll need to find the real partition root here */ 1245 ncRoot = req10->naming_context; 1246 if (ncRoot == NULL) { 1247 DEBUG(0,(__location__ ": Request for DsGetNCChanges with no NC\n")); 370 1248 return WERR_DS_DRA_INVALID_PARAMETER; 371 1249 } 372 1250 373 ncRoot = r->in.req->req8.naming_context; 374 if (ncRoot == NULL) { 375 return WERR_DS_DRA_BAD_NC; 376 } 377 378 if ((r->in.req->req8.replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_SYNC_PACKET) 379 == DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_SYNC_PACKET) { 380 /* Ignore the _in_ uptpdateness vector*/ 381 r->in.req->req8.uptodateness_vector = NULL; 382 } 383 384 werr = drs_security_level_check(dce_call, "DsGetNCChanges"); 1251 if (samdb_ntds_options(sam_ctx, &options) != LDB_SUCCESS) { 1252 return WERR_DS_DRA_INTERNAL_ERROR; 1253 } 1254 1255 if ((options & DS_NTDSDSA_OPT_DISABLE_OUTBOUND_REPL) && 1256 !(req10->replica_flags & DRSUAPI_DRS_SYNC_FORCED)) { 1257 return WERR_DS_DRA_SOURCE_DISABLED; 1258 } 1259 1260 user_sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX]; 1261 1262 werr = drs_security_access_check_nc_root(b_state->sam_ctx, 1263 mem_ctx, 1264 dce_call->conn->auth_state.session_info->security_token, 1265 req10->naming_context, 1266 GUID_DRS_GET_CHANGES); 385 1267 if (!W_ERROR_IS_OK(werr)) { 386 1268 return werr; 387 1269 } 388 1270 1271 werr = dcesrv_drsuapi_is_reveal_secrets_request(b_state, req10, &is_secret_request); 1272 if (!W_ERROR_IS_OK(werr)) { 1273 return werr; 1274 } 1275 if (is_secret_request && req10->extended_op != DRSUAPI_EXOP_REPL_SECRET) { 1276 werr = drs_security_access_check_nc_root(b_state->sam_ctx, 1277 mem_ctx, 1278 dce_call->conn->auth_state.session_info->security_token, 1279 req10->naming_context, 1280 GUID_DRS_GET_ALL_CHANGES); 1281 if (!W_ERROR_IS_OK(werr)) { 1282 return werr; 1283 } 1284 } 1285 1286 /* for non-administrator replications, check that they have 1287 given the correct source_dsa_invocation_id */ 1288 security_level = security_session_user_level(dce_call->conn->auth_state.session_info, 1289 samdb_domain_sid(sam_ctx)); 1290 if (security_level == SECURITY_RO_DOMAIN_CONTROLLER) { 1291 if (req10->replica_flags & DRSUAPI_DRS_WRIT_REP) { 1292 /* we rely on this flag being unset for RODC requests */ 1293 req10->replica_flags &= ~DRSUAPI_DRS_WRIT_REP; 1294 } 1295 } 1296 1297 if (req10->replica_flags & DRSUAPI_DRS_FULL_SYNC_PACKET) { 1298 /* Ignore the _in_ uptpdateness vector*/ 1299 req10->uptodateness_vector = NULL; 1300 } 1301 389 1302 getnc_state = b_state->getncchanges_state; 1303 1304 /* see if a previous replication has been abandoned */ 1305 if (getnc_state) { 1306 struct ldb_dn *new_dn = drs_ObjectIdentifier_to_dn(getnc_state, sam_ctx, ncRoot); 1307 if (ldb_dn_compare(new_dn, getnc_state->ncRoot_dn) != 0) { 1308 DEBUG(0,(__location__ ": DsGetNCChanges 2nd replication on different DN %s %s (last_dn %s)\n", 1309 ldb_dn_get_linearized(new_dn), 1310 ldb_dn_get_linearized(getnc_state->ncRoot_dn), 1311 ldb_dn_get_linearized(getnc_state->last_dn))); 1312 talloc_free(getnc_state); 1313 getnc_state = NULL; 1314 } 1315 } 1316 390 1317 if (getnc_state == NULL) { 391 1318 getnc_state = talloc_zero(b_state, struct drsuapi_getncchanges_state); … … 394 1321 } 395 1322 b_state->getncchanges_state = getnc_state; 396 1323 getnc_state->ncRoot_dn = drs_ObjectIdentifier_to_dn(getnc_state, sam_ctx, ncRoot); 1324 1325 /* find out if we are to replicate Schema NC */ 1326 ret = ldb_dn_compare(getnc_state->ncRoot_dn, 1327 ldb_get_schema_basedn(b_state->sam_ctx)); 1328 getnc_state->is_schema_nc = (0 == ret); 397 1329 398 1330 /* 399 * connect to the samdb. TODO: We need to check that the caller 400 * has the rights to do this. This exposes all attributes, 401 * including all passwords. 1331 * This is the first replication cycle and it is 1332 * a good place to handle extended operations 1333 * 1334 * FIXME: we don't fully support extended operations yet 402 1335 */ 403 getnc_state->sam_ctx = samdb_connect(getnc_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, 404 system_session(getnc_state, dce_call->conn->dce_ctx->lp_ctx)); 405 if (!getnc_state->sam_ctx) { 406 return WERR_FOOBAR; 407 } 1336 switch (req10->extended_op) { 1337 case DRSUAPI_EXOP_NONE: 1338 break; 1339 case DRSUAPI_EXOP_FSMO_RID_ALLOC: 1340 werr = getncchanges_rid_alloc(b_state, mem_ctx, req10, &r->out.ctr->ctr6); 1341 W_ERROR_NOT_OK_RETURN(werr); 1342 search_dn = ldb_get_default_basedn(sam_ctx); 1343 break; 1344 case DRSUAPI_EXOP_REPL_SECRET: 1345 werr = getncchanges_repl_secret(b_state, mem_ctx, req10, user_sid, &r->out.ctr->ctr6); 1346 r->out.result = werr; 1347 W_ERROR_NOT_OK_RETURN(werr); 1348 break; 1349 case DRSUAPI_EXOP_FSMO_REQ_ROLE: 1350 werr = getncchanges_change_master(b_state, mem_ctx, req10, &r->out.ctr->ctr6); 1351 W_ERROR_NOT_OK_RETURN(werr); 1352 break; 1353 case DRSUAPI_EXOP_FSMO_RID_REQ_ROLE: 1354 werr = getncchanges_change_master(b_state, mem_ctx, req10, &r->out.ctr->ctr6); 1355 W_ERROR_NOT_OK_RETURN(werr); 1356 break; 1357 case DRSUAPI_EXOP_FSMO_REQ_PDC: 1358 werr = getncchanges_change_master(b_state, mem_ctx, req10, &r->out.ctr->ctr6); 1359 W_ERROR_NOT_OK_RETURN(werr); 1360 break; 1361 case DRSUAPI_EXOP_REPL_OBJ: 1362 werr = getncchanges_repl_obj(b_state, mem_ctx, req10, user_sid, &r->out.ctr->ctr6); 1363 r->out.result = werr; 1364 W_ERROR_NOT_OK_RETURN(werr); 1365 break; 1366 1367 case DRSUAPI_EXOP_FSMO_ABANDON_ROLE: 1368 1369 DEBUG(0,(__location__ ": Request for DsGetNCChanges unsupported extended op 0x%x\n", 1370 (unsigned)req10->extended_op)); 1371 return WERR_DS_DRA_NOT_SUPPORTED; 1372 } 1373 } 1374 1375 if (!ldb_dn_validate(getnc_state->ncRoot_dn) || 1376 ldb_dn_is_null(getnc_state->ncRoot_dn)) { 1377 DEBUG(0,(__location__ ": Bad DN '%s'\n", 1378 drs_ObjectIdentifier_to_string(mem_ctx, ncRoot))); 1379 return WERR_DS_DRA_INVALID_PARAMETER; 408 1380 } 409 1381 … … 415 1387 } 416 1388 417 if (getnc_state->site_res == NULL) { 1389 /* 1390 TODO: MS-DRSR section 4.1.10.1.1 1391 Work out if this is the start of a new cycle */ 1392 1393 if (getnc_state->guids == NULL) { 418 1394 char* search_filter; 419 1395 enum ldb_scope scope = LDB_SCOPE_SUBTREE; 420 421 getnc_state->min_usn = r->in.req->req8.highwatermark.highest_usn; 1396 const char *extra_filter; 1397 struct ldb_result *search_res; 1398 1399 if (req10->extended_op == DRSUAPI_EXOP_REPL_OBJ || 1400 req10->extended_op == DRSUAPI_EXOP_REPL_SECRET) { 1401 scope = LDB_SCOPE_BASE; 1402 } 1403 1404 extra_filter = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "object filter"); 1405 1406 getnc_state->min_usn = req10->highwatermark.highest_usn; 422 1407 423 1408 /* Construct response. */ … … 425 1410 "(uSNChanged>=%llu)", 426 1411 (unsigned long long)(getnc_state->min_usn+1)); 427 428 if (r->in.req->req8.replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_CRITICAL_ONLY) { 1412 1413 if (extra_filter) { 1414 search_filter = talloc_asprintf(mem_ctx, "(&%s(%s))", search_filter, extra_filter); 1415 } 1416 1417 if (req10->replica_flags & DRSUAPI_DRS_CRITICAL_ONLY) { 429 1418 search_filter = talloc_asprintf(mem_ctx, 430 1419 "(&%s(isCriticalSystemObject=TRUE))", … … 432 1421 } 433 1422 434 getnc_state->ncRoot_dn = ldb_dn_new(getnc_state, getnc_state->sam_ctx, ncRoot->dn); 435 if (r->in.req->req8.replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_ASYNC_REP) { 1423 if (req10->replica_flags & DRSUAPI_DRS_ASYNC_REP) { 436 1424 scope = LDB_SCOPE_BASE; 437 1425 } 438 1426 439 DEBUG(6,(__location__ ": getncchanges on %s using filter %s\n", 1427 if (!search_dn) { 1428 search_dn = getnc_state->ncRoot_dn; 1429 } 1430 1431 DEBUG(2,(__location__ ": getncchanges on %s using filter %s\n", 440 1432 ldb_dn_get_linearized(getnc_state->ncRoot_dn), search_filter)); 441 ret = drsuapi_search_with_extended_dn(getnc_state->sam_ctx, getnc_state, &getnc_state->site_res, 442 getnc_state->ncRoot_dn, scope, attrs, 443 "distinguishedName", 1433 ret = drsuapi_search_with_extended_dn(sam_ctx, getnc_state, &search_res, 1434 search_dn, scope, attrs, 444 1435 search_filter); 445 1436 if (ret != LDB_SUCCESS) { 446 1437 return WERR_DS_DRA_INTERNAL_ERROR; 447 1438 } 1439 1440 if (req10->replica_flags & DRSUAPI_DRS_GET_ANC) { 1441 TYPESAFE_QSORT(search_res->msgs, 1442 search_res->count, 1443 site_res_cmp_parent_order); 1444 } else { 1445 TYPESAFE_QSORT(search_res->msgs, 1446 search_res->count, 1447 site_res_cmp_usn_order); 1448 } 1449 1450 /* extract out the GUIDs list */ 1451 getnc_state->num_records = search_res->count; 1452 getnc_state->guids = talloc_array(getnc_state, struct GUID, getnc_state->num_records); 1453 W_ERROR_HAVE_NO_MEMORY(getnc_state->guids); 1454 1455 for (i=0; i<getnc_state->num_records; i++) { 1456 getnc_state->guids[i] = samdb_result_guid(search_res->msgs[i], "objectGUID"); 1457 if (GUID_all_zero(&getnc_state->guids[i])) { 1458 DEBUG(2,("getncchanges: bad objectGUID from %s\n", ldb_dn_get_linearized(search_res->msgs[i]->dn))); 1459 return WERR_DS_DRA_INTERNAL_ERROR; 1460 } 1461 } 1462 1463 1464 talloc_free(search_res); 1465 1466 getnc_state->uptodateness_vector = talloc_steal(getnc_state, req10->uptodateness_vector); 1467 if (getnc_state->uptodateness_vector) { 1468 /* make sure its sorted */ 1469 TYPESAFE_QSORT(getnc_state->uptodateness_vector->cursors, 1470 getnc_state->uptodateness_vector->count, 1471 drsuapi_DsReplicaCursor_compare); 1472 } 448 1473 } 449 1474 450 1475 /* Prefix mapping */ 451 schema = dsdb_get_schema( getnc_state->sam_ctx);1476 schema = dsdb_get_schema(sam_ctx, mem_ctx); 452 1477 if (!schema) { 453 1478 DEBUG(0,("No schema in sam_ctx\n")); … … 458 1483 *r->out.ctr->ctr6.naming_context = *ncRoot; 459 1484 460 if (dsdb_find_guid_by_dn( getnc_state->sam_ctx, getnc_state->ncRoot_dn,1485 if (dsdb_find_guid_by_dn(sam_ctx, getnc_state->ncRoot_dn, 461 1486 &r->out.ctr->ctr6.naming_context->guid) != LDB_SUCCESS) { 462 1487 DEBUG(0,(__location__ ": Failed to find GUID of ncRoot_dn %s\n", … … 466 1491 467 1492 /* find the SID if there is one */ 468 dsdb_find_sid_by_dn( getnc_state->sam_ctx, getnc_state->ncRoot_dn, &r->out.ctr->ctr6.naming_context->sid);1493 dsdb_find_sid_by_dn(sam_ctx, getnc_state->ncRoot_dn, &r->out.ctr->ctr6.naming_context->sid); 469 1494 470 1495 dsdb_get_oid_mappings_drsuapi(schema, true, mem_ctx, &ctr); 471 1496 r->out.ctr->ctr6.mapping_ctr = *ctr; 472 1497 473 r->out.ctr->ctr6.source_dsa_guid = *(samdb_ntds_objectGUID( getnc_state->sam_ctx));474 r->out.ctr->ctr6.source_dsa_invocation_id = *(samdb_ntds_invocation_id( getnc_state->sam_ctx));475 476 r->out.ctr->ctr6.old_highwatermark = r ->in.req->req8.highwatermark;477 r->out.ctr->ctr6.new_highwatermark = r ->in.req->req8.highwatermark;1498 r->out.ctr->ctr6.source_dsa_guid = *(samdb_ntds_objectGUID(sam_ctx)); 1499 r->out.ctr->ctr6.source_dsa_invocation_id = *(samdb_ntds_invocation_id(sam_ctx)); 1500 1501 r->out.ctr->ctr6.old_highwatermark = req10->highwatermark; 1502 r->out.ctr->ctr6.new_highwatermark = req10->highwatermark; 478 1503 479 1504 r->out.ctr->ctr6.first_object = NULL; 480 1505 currentObject = &r->out.ctr->ctr6.first_object; 481 1506 482 for(i=getnc_state->num_sent; 483 i<getnc_state->site_res->count && 484 (r->out.ctr->ctr6.object_count < r->in.req->req8.max_object_count); 1507 /* use this to force single objects at a time, which is useful 1508 * for working out what object is giving problems 1509 */ 1510 max_objects = lpcfg_parm_int(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "max object sync", 1000); 1511 if (req10->max_object_count < max_objects) { 1512 max_objects = req10->max_object_count; 1513 } 1514 /* 1515 * TODO: work out how the maximum should be calculated 1516 */ 1517 max_links = lpcfg_parm_int(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "max link sync", 1500); 1518 1519 for (i=getnc_state->num_processed; 1520 i<getnc_state->num_records && 1521 !null_scope && 1522 (r->out.ctr->ctr6.object_count < max_objects); 485 1523 i++) { 486 1524 int uSN; 487 1525 struct drsuapi_DsReplicaObjectListItemEx *obj; 1526 struct ldb_message *msg; 1527 static const char * const msg_attrs[] = { 1528 "*", 1529 "nTSecurityDescriptor", 1530 "parentGUID", 1531 "replPropertyMetaData", 1532 DSDB_SECRET_ATTRIBUTES, 1533 NULL }; 1534 struct ldb_result *msg_res; 1535 struct ldb_dn *msg_dn; 1536 488 1537 obj = talloc_zero(mem_ctx, struct drsuapi_DsReplicaObjectListItemEx); 489 490 uSN = ldb_msg_find_attr_as_int(getnc_state->site_res->msgs[i], "uSNChanged", -1); 1538 W_ERROR_HAVE_NO_MEMORY(obj); 1539 1540 msg_dn = ldb_dn_new_fmt(obj, sam_ctx, "<GUID=%s>", GUID_string(obj, &getnc_state->guids[i])); 1541 W_ERROR_HAVE_NO_MEMORY(msg_dn); 1542 1543 1544 /* by re-searching here we avoid having a lot of full 1545 * records in memory between calls to getncchanges 1546 */ 1547 ret = drsuapi_search_with_extended_dn(sam_ctx, obj, &msg_res, 1548 msg_dn, 1549 LDB_SCOPE_BASE, msg_attrs, NULL); 1550 if (ret != LDB_SUCCESS) { 1551 if (ret != LDB_ERR_NO_SUCH_OBJECT) { 1552 DEBUG(1,("getncchanges: failed to fetch DN %s - %s\n", 1553 ldb_dn_get_extended_linearized(obj, msg_dn, 1), ldb_errstring(sam_ctx))); 1554 } 1555 talloc_free(obj); 1556 continue; 1557 } 1558 1559 msg = msg_res->msgs[0]; 1560 1561 werr = get_nc_changes_build_object(obj, msg, 1562 sam_ctx, getnc_state->ncRoot_dn, 1563 getnc_state->is_schema_nc, 1564 schema, &session_key, getnc_state->min_usn, 1565 req10->replica_flags, 1566 req10->partial_attribute_set, 1567 getnc_state->uptodateness_vector, 1568 req10->extended_op); 1569 if (!W_ERROR_IS_OK(werr)) { 1570 return werr; 1571 } 1572 1573 werr = get_nc_changes_add_links(sam_ctx, getnc_state, 1574 getnc_state->ncRoot_dn, 1575 schema, getnc_state->min_usn, 1576 req10->replica_flags, 1577 msg, 1578 &getnc_state->la_list, 1579 &getnc_state->la_count, 1580 getnc_state->uptodateness_vector); 1581 if (!W_ERROR_IS_OK(werr)) { 1582 return werr; 1583 } 1584 1585 uSN = ldb_msg_find_attr_as_int(msg, "uSNChanged", -1); 491 1586 if (uSN > r->out.ctr->ctr6.new_highwatermark.tmp_highest_usn) { 492 1587 r->out.ctr->ctr6.new_highwatermark.tmp_highest_usn = uSN; 493 1588 } 494 495 werr = get_nc_changes_build_object(obj, getnc_state->site_res->msgs[i], 496 getnc_state->sam_ctx, getnc_state->ncRoot_dn, 497 schema, &session_key, getnc_state->min_usn, 498 r->in.req->req8.replica_flags); 499 if (!W_ERROR_IS_OK(werr)) { 500 return werr; 1589 if (uSN > getnc_state->highest_usn) { 1590 getnc_state->highest_usn = uSN; 501 1591 } 502 1592 503 1593 if (obj->meta_data_ctr == NULL) { 504 DEBUG( 0,(__location__ ": getncchanges skipping send of object %s\n",505 ldb_dn_get_linearized( getnc_state->site_res->msgs[i]->dn)));1594 DEBUG(8,(__location__ ": getncchanges skipping send of object %s\n", 1595 ldb_dn_get_linearized(msg->dn))); 506 1596 /* no attributes to send */ 507 1597 talloc_free(obj); … … 513 1603 *currentObject = obj; 514 1604 currentObject = &obj->next_object; 515 } 516 517 getnc_state->num_sent += r->out.ctr->ctr6.object_count; 518 519 r->out.ctr->ctr6.nc_object_count = getnc_state->site_res->count; 520 521 if (i < getnc_state->site_res->count) { 1605 1606 talloc_free(getnc_state->last_dn); 1607 getnc_state->last_dn = ldb_dn_copy(getnc_state, msg->dn); 1608 1609 DEBUG(8,(__location__ ": replicating object %s\n", ldb_dn_get_linearized(msg->dn))); 1610 1611 talloc_free(msg_res); 1612 talloc_free(msg_dn); 1613 } 1614 1615 getnc_state->num_processed = i; 1616 1617 r->out.ctr->ctr6.nc_object_count = getnc_state->num_records; 1618 1619 /* the client can us to call UpdateRefs on its behalf to 1620 re-establish monitoring of the NC */ 1621 if ((req10->replica_flags & (DRSUAPI_DRS_ADD_REF | DRSUAPI_DRS_REF_GCSPN)) && 1622 !GUID_all_zero(&req10->destination_dsa_guid)) { 1623 struct drsuapi_DsReplicaUpdateRefsRequest1 ureq; 1624 DEBUG(3,("UpdateRefs on getncchanges for %s\n", 1625 GUID_string(mem_ctx, &req10->destination_dsa_guid))); 1626 ureq.naming_context = ncRoot; 1627 ureq.dest_dsa_dns_name = talloc_asprintf(mem_ctx, "%s._msdcs.%s", 1628 GUID_string(mem_ctx, &req10->destination_dsa_guid), 1629 lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx)); 1630 if (!ureq.dest_dsa_dns_name) { 1631 return WERR_NOMEM; 1632 } 1633 ureq.dest_dsa_guid = req10->destination_dsa_guid; 1634 ureq.options = DRSUAPI_DRS_ADD_REF | 1635 DRSUAPI_DRS_ASYNC_OP | 1636 DRSUAPI_DRS_GETCHG_CHECK; 1637 1638 /* we also need to pass through the 1639 DRSUAPI_DRS_REF_GCSPN bit so that repsTo gets flagged 1640 to send notifies using the GC SPN */ 1641 ureq.options |= (req10->replica_flags & DRSUAPI_DRS_REF_GCSPN); 1642 1643 werr = drsuapi_UpdateRefs(b_state, mem_ctx, &ureq); 1644 if (!W_ERROR_IS_OK(werr)) { 1645 DEBUG(0,(__location__ ": Failed UpdateRefs in DsGetNCChanges - %s\n", 1646 win_errstr(werr))); 1647 } 1648 } 1649 1650 /* 1651 * TODO: 1652 * This is just a guess, how to calculate the 1653 * number of linked attributes to send, we need to 1654 * find out how to do this right. 1655 */ 1656 if (r->out.ctr->ctr6.object_count >= max_links) { 1657 max_links = 0; 1658 } else { 1659 max_links -= r->out.ctr->ctr6.object_count; 1660 } 1661 1662 link_total = getnc_state->la_count; 1663 1664 if (i < getnc_state->num_records) { 522 1665 r->out.ctr->ctr6.more_data = true; 523 1666 } else { 1667 /* sort the whole array the first time */ 1668 if (!getnc_state->la_sorted) { 1669 LDB_TYPESAFE_QSORT(getnc_state->la_list, getnc_state->la_count, 1670 sam_ctx, linked_attribute_compare); 1671 getnc_state->la_sorted = true; 1672 } 1673 1674 link_count = getnc_state->la_count - getnc_state->la_idx; 1675 link_count = MIN(max_links, link_count); 1676 1677 r->out.ctr->ctr6.linked_attributes_count = link_count; 1678 r->out.ctr->ctr6.linked_attributes = getnc_state->la_list + getnc_state->la_idx; 1679 1680 getnc_state->la_idx += link_count; 1681 link_given = getnc_state->la_idx; 1682 1683 if (getnc_state->la_idx < getnc_state->la_count) { 1684 r->out.ctr->ctr6.more_data = true; 1685 } 1686 } 1687 1688 if (!r->out.ctr->ctr6.more_data) { 1689 talloc_steal(mem_ctx, getnc_state->la_list); 1690 524 1691 r->out.ctr->ctr6.uptodateness_vector = talloc(mem_ctx, struct drsuapi_DsReplicaCursor2CtrEx); 525 r->out.ctr->ctr6.uptodateness_vector->version = 2;526 r->out.ctr->ctr6.uptodateness_vector->reserved1 = 0;527 r->out.ctr->ctr6.uptodateness_vector->reserved2 = 0;528 529 1692 r->out.ctr->ctr6.new_highwatermark.highest_usn = r->out.ctr->ctr6.new_highwatermark.tmp_highest_usn; 530 1693 531 werr = get_nc_changes_udv( getnc_state->sam_ctx, getnc_state->ncRoot_dn,1694 werr = get_nc_changes_udv(sam_ctx, getnc_state->ncRoot_dn, 532 1695 r->out.ctr->ctr6.uptodateness_vector); 533 1696 if (!W_ERROR_IS_OK(werr)) { … … 539 1702 } 540 1703 541 DEBUG(3,("DsGetNCChanges with uSNChanged >= %llu on %s gave %u objects\n", 542 (unsigned long long)(r->in.req->req8.highwatermark.highest_usn+1), 543 ncRoot->dn, r->out.ctr->ctr6.object_count)); 1704 if (req10->extended_op != DRSUAPI_EXOP_NONE) { 1705 r->out.ctr->ctr6.uptodateness_vector = NULL; 1706 r->out.ctr->ctr6.nc_object_count = 0; 1707 ZERO_STRUCT(r->out.ctr->ctr6.new_highwatermark); 1708 r->out.ctr->ctr6.extended_ret = DRSUAPI_EXOP_ERR_SUCCESS; 1709 } 1710 1711 DEBUG(r->out.ctr->ctr6.more_data?4:2, 1712 ("DsGetNCChanges with uSNChanged >= %llu flags 0x%08x on %s gave %u objects (done %u/%u) %u links (done %u/%u (as %s))\n", 1713 (unsigned long long)(req10->highwatermark.highest_usn+1), 1714 req10->replica_flags, drs_ObjectIdentifier_to_string(mem_ctx, ncRoot), 1715 r->out.ctr->ctr6.object_count, 1716 i, r->out.ctr->ctr6.more_data?getnc_state->num_records:i, 1717 r->out.ctr->ctr6.linked_attributes_count, 1718 link_given, link_total, 1719 dom_sid_string(mem_ctx, user_sid))); 1720 1721 #if 0 1722 if (!r->out.ctr->ctr6.more_data && req10->extended_op != DRSUAPI_EXOP_NONE) { 1723 NDR_PRINT_FUNCTION_DEBUG(drsuapi_DsGetNCChanges, NDR_BOTH, r); 1724 } 1725 #endif 544 1726 545 1727 return WERR_OK; -
trunk/server/source4/rpc_server/drsuapi/updaterefs.c
r414 r745 23 23 #include "rpc_server/dcerpc_server.h" 24 24 #include "dsdb/samdb/samdb.h" 25 #include "auth/auth.h" 25 #include "libcli/security/security.h" 26 #include "libcli/security/session.h" 26 27 #include "rpc_server/drsuapi/dcesrv_drsuapi.h" 27 #include "libcli/security/security.h" 28 #include "auth/session.h" 29 #include "librpc/gen_ndr/ndr_drsuapi.h" 28 30 29 31 struct repsTo { … … 36 38 */ 37 39 static WERROR uref_add_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, 38 struct ldb_dn *dn, struct repsFromTo1 *dest) 40 struct ldb_dn *dn, struct repsFromTo1 *dest, 41 uint32_t options) 39 42 { 40 43 struct repsTo reps; 41 44 WERROR werr; 45 unsigned int i; 42 46 43 47 werr = dsdb_loadreps(sam_ctx, mem_ctx, dn, "repsTo", &reps.r, &reps.count); 44 48 if (!W_ERROR_IS_OK(werr)) { 45 49 return werr; 50 } 51 52 for (i=0; i<reps.count; i++) { 53 if (GUID_compare(&dest->source_dsa_obj_guid, 54 &reps.r[i].ctr.ctr1.source_dsa_obj_guid) == 0) { 55 if (options & DRSUAPI_DRS_GETCHG_CHECK) { 56 return WERR_OK; 57 } else { 58 return WERR_DS_DRA_REF_ALREADY_EXISTS; 59 } 60 } 46 61 } 47 62 … … 53 68 reps.r[reps.count].version = 1; 54 69 reps.r[reps.count].ctr.ctr1 = *dest; 70 /* add the GCSPN flag if the client asked for it */ 71 reps.r[reps.count].ctr.ctr1.replica_flags |= (options & DRSUAPI_DRS_REF_GCSPN); 55 72 reps.count++; 56 73 … … 67 84 */ 68 85 static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, 69 struct ldb_dn *dn, struct GUID *dest_guid) 86 struct ldb_dn *dn, struct GUID *dest_guid, 87 uint32_t options) 70 88 { 71 89 struct repsTo reps; 72 90 WERROR werr; 73 int i; 91 unsigned int i; 92 bool found = false; 74 93 75 94 werr = dsdb_loadreps(sam_ctx, mem_ctx, dn, "repsTo", &reps.r, &reps.count); … … 84 103 } 85 104 reps.count--; 105 found = true; 86 106 } 87 107 } … … 92 112 } 93 113 114 if (!found && 115 !(options & DRSUAPI_DRS_GETCHG_CHECK) && 116 !(options & DRSUAPI_DRS_ADD_REF)) { 117 return WERR_DS_DRA_REF_NOT_FOUND; 118 } 119 94 120 return WERR_OK; 121 } 122 123 /* 124 drsuapi_DsReplicaUpdateRefs - a non RPC version callable from getncchanges 125 */ 126 WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx, 127 struct drsuapi_DsReplicaUpdateRefsRequest1 *req) 128 { 129 WERROR werr; 130 struct ldb_dn *dn; 131 struct ldb_context *sam_ctx = b_state->sam_ctx_system?b_state->sam_ctx_system:b_state->sam_ctx; 132 133 DEBUG(4,("DsReplicaUpdateRefs for host '%s' with GUID %s options 0x%08x nc=%s\n", 134 req->dest_dsa_dns_name, GUID_string(mem_ctx, &req->dest_dsa_guid), 135 req->options, 136 drs_ObjectIdentifier_to_string(mem_ctx, req->naming_context))); 137 138 dn = ldb_dn_new(mem_ctx, sam_ctx, req->naming_context->dn); 139 if (dn == NULL) { 140 return WERR_DS_INVALID_DN_SYNTAX; 141 } 142 143 if (ldb_transaction_start(sam_ctx) != LDB_SUCCESS) { 144 DEBUG(0,(__location__ ": Failed to start transaction on samdb: %s\n", 145 ldb_errstring(sam_ctx))); 146 return WERR_DS_DRA_INTERNAL_ERROR; 147 } 148 149 if (req->options & DRSUAPI_DRS_DEL_REF) { 150 werr = uref_del_dest(sam_ctx, mem_ctx, dn, &req->dest_dsa_guid, req->options); 151 if (!W_ERROR_IS_OK(werr)) { 152 DEBUG(0,("Failed to delete repsTo for %s: %s\n", 153 GUID_string(mem_ctx, &req->dest_dsa_guid), 154 win_errstr(werr))); 155 goto failed; 156 } 157 } 158 159 if (req->options & DRSUAPI_DRS_ADD_REF) { 160 struct repsFromTo1 dest; 161 struct repsFromTo1OtherInfo oi; 162 163 ZERO_STRUCT(dest); 164 ZERO_STRUCT(oi); 165 166 oi.dns_name = req->dest_dsa_dns_name; 167 dest.other_info = &oi; 168 dest.source_dsa_obj_guid = req->dest_dsa_guid; 169 dest.replica_flags = req->options; 170 171 werr = uref_add_dest(sam_ctx, mem_ctx, dn, &dest, req->options); 172 if (!W_ERROR_IS_OK(werr)) { 173 DEBUG(0,("Failed to add repsTo for %s: %s\n", 174 GUID_string(mem_ctx, &dest.source_dsa_obj_guid), 175 win_errstr(werr))); 176 goto failed; 177 } 178 } 179 180 if (ldb_transaction_commit(sam_ctx) != LDB_SUCCESS) { 181 DEBUG(0,(__location__ ": Failed to commit transaction on samdb: %s\n", 182 ldb_errstring(sam_ctx))); 183 return WERR_DS_DRA_INTERNAL_ERROR; 184 } 185 186 return WERR_OK; 187 188 failed: 189 ldb_transaction_cancel(sam_ctx); 190 return werr; 95 191 } 96 192 … … 101 197 struct drsuapi_DsReplicaUpdateRefs *r) 102 198 { 199 struct dcesrv_handle *h; 200 struct drsuapi_bind_state *b_state; 103 201 struct drsuapi_DsReplicaUpdateRefsRequest1 *req; 104 struct ldb_context *sam_ctx; 105 WERROR werr; 106 struct ldb_dn *dn; 107 108 werr = drs_security_level_check(dce_call, "DsReplicaUpdateRefs"); 109 if (!W_ERROR_IS_OK(werr)) { 110 return werr; 111 } 202 WERROR werr; 203 int ret; 204 enum security_user_level security_level; 205 206 DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); 207 b_state = h->data; 112 208 113 209 if (r->in.level != 1) { … … 115 211 return WERR_DS_DRA_INVALID_PARAMETER; 116 212 } 117 118 213 req = &r->in.req.req1; 119 DEBUG(4,("DsReplicaUpdateRefs for host '%s' with GUID %s options 0x%08x nc=%s\n", 120 req->dest_dsa_dns_name, GUID_string(mem_ctx, &req->dest_dsa_guid), 121 req->options, 122 drs_ObjectIdentifier_to_string(mem_ctx, req->naming_context))); 123 124 /* TODO: We need to authenticate this operation pretty carefully */ 125 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, 126 system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx)); 127 if (!sam_ctx) { 128 return WERR_DS_DRA_INTERNAL_ERROR; 129 } 130 131 dn = ldb_dn_new(mem_ctx, sam_ctx, req->naming_context->dn); 132 if (dn == NULL) { 133 talloc_free(sam_ctx); 134 return WERR_DS_INVALID_DN_SYNTAX; 135 } 136 137 if (ldb_transaction_start(sam_ctx) != LDB_SUCCESS) { 138 DEBUG(0,(__location__ ": Failed to start transaction on samdb\n")); 139 talloc_free(sam_ctx); 140 return WERR_DS_DRA_INTERNAL_ERROR; 141 } 142 143 if (req->options & DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE) { 144 werr = uref_del_dest(sam_ctx, mem_ctx, dn, &req->dest_dsa_guid); 145 if (!W_ERROR_IS_OK(werr)) { 146 DEBUG(0,("Failed to delete repsTo for %s\n", 147 GUID_string(dce_call, &req->dest_dsa_guid))); 148 goto failed; 149 } 150 } 151 152 if (req->options & DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE) { 153 struct repsFromTo1 dest; 154 struct repsFromTo1OtherInfo oi; 155 156 ZERO_STRUCT(dest); 157 ZERO_STRUCT(oi); 158 159 oi.dns_name = req->dest_dsa_dns_name; 160 dest.other_info = &oi; 161 dest.source_dsa_obj_guid = req->dest_dsa_guid; 162 dest.replica_flags = req->options; 163 164 werr = uref_add_dest(sam_ctx, mem_ctx, dn, &dest); 165 if (!W_ERROR_IS_OK(werr)) { 166 DEBUG(0,("Failed to delete repsTo for %s\n", 167 GUID_string(dce_call, &dest.source_dsa_obj_guid))); 168 goto failed; 169 } 170 } 171 172 if (ldb_transaction_commit(sam_ctx) != LDB_SUCCESS) { 173 DEBUG(0,(__location__ ": Failed to commit transaction on samdb\n")); 174 return WERR_DS_DRA_INTERNAL_ERROR; 175 } 176 177 talloc_free(sam_ctx); 178 return WERR_OK; 179 180 failed: 181 ldb_transaction_cancel(sam_ctx); 182 talloc_free(sam_ctx); 214 werr = drs_security_access_check(b_state->sam_ctx, 215 mem_ctx, 216 dce_call->conn->auth_state.session_info->security_token, 217 req->naming_context, 218 GUID_DRS_MANAGE_TOPOLOGY); 219 220 if (!W_ERROR_IS_OK(werr)) { 221 return werr; 222 } 223 224 security_level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL); 225 if (security_level < SECURITY_ADMINISTRATOR) { 226 /* check that they are using an DSA objectGUID that they own */ 227 ret = dsdb_validate_dsa_guid(b_state->sam_ctx, 228 &req->dest_dsa_guid, 229 &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX]); 230 if (ret != LDB_SUCCESS) { 231 DEBUG(0,(__location__ ": Refusing DsReplicaUpdateRefs for sid %s with GUID %s\n", 232 dom_sid_string(mem_ctx, 233 &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX]), 234 GUID_string(mem_ctx, &req->dest_dsa_guid))); 235 return WERR_DS_DRA_ACCESS_DENIED; 236 } 237 } 238 239 werr = drsuapi_UpdateRefs(b_state, mem_ctx, req); 240 241 #if 0 242 NDR_PRINT_FUNCTION_DEBUG(drsuapi_DsReplicaUpdateRefs, NDR_BOTH, r); 243 #endif 244 183 245 return werr; 184 246 }
Note:
See TracChangeset
for help on using the changeset viewer.