diff options
Diffstat (limited to 'source4/rpc_server')
-rw-r--r-- | source4/rpc_server/drsuapi/getncchanges.c | 100 |
1 files changed, 95 insertions, 5 deletions
diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index ca24b3deec..61a6002af8 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -1162,20 +1162,90 @@ static WERROR dcesrv_drsuapi_is_reveal_secrets_request(struct drsuapi_bind_state } } + if (req10->partial_attribute_set_ex) { + /* check the extended attributes they asked for */ + for (i=0; i<req10->partial_attribute_set_ex->num_attids; i++) { + const struct dsdb_attribute *sa; + sa = dsdb_attribute_by_attributeID_id(schema, req10->partial_attribute_set_ex->attids[i]); + if (sa == NULL) { + return WERR_DS_DRA_SCHEMA_MISMATCH; + } + if (!dsdb_attr_in_rodc_fas(sa)) { + *is_secret_request = true; + return WERR_OK; + } + } + } + + *is_secret_request = false; + return WERR_OK; +} + +/* + see if this getncchanges request is only for attributes in the GC + partial attribute set + */ +static WERROR dcesrv_drsuapi_is_gc_pas_request(struct drsuapi_bind_state *b_state, + struct drsuapi_DsGetNCChangesRequest10 *req10, + bool *is_gc_pas_request) +{ + enum drsuapi_DsExtendedOperation exop; + uint32_t i; + struct dsdb_schema *schema; + + exop = req10->extended_op; + + switch (exop) { + case DRSUAPI_EXOP_FSMO_REQ_ROLE: + case DRSUAPI_EXOP_FSMO_RID_ALLOC: + case DRSUAPI_EXOP_FSMO_RID_REQ_ROLE: + case DRSUAPI_EXOP_FSMO_REQ_PDC: + case DRSUAPI_EXOP_FSMO_ABANDON_ROLE: + case DRSUAPI_EXOP_REPL_SECRET: + *is_gc_pas_request = false; + return WERR_OK; + case DRSUAPI_EXOP_REPL_OBJ: + case DRSUAPI_EXOP_NONE: + break; + } + + if (req10->partial_attribute_set == NULL) { + /* they want it all */ + *is_gc_pas_request = false; + return WERR_OK; + } + + schema = dsdb_get_schema(b_state->sam_ctx, NULL); + /* check the attributes they asked for */ - for (i=0; i<req10->partial_attribute_set_ex->num_attids; i++) { + for (i=0; i<req10->partial_attribute_set->num_attids; i++) { const struct dsdb_attribute *sa; - sa = dsdb_attribute_by_attributeID_id(schema, req10->partial_attribute_set_ex->attids[i]); + sa = dsdb_attribute_by_attributeID_id(schema, req10->partial_attribute_set->attids[i]); if (sa == NULL) { return WERR_DS_DRA_SCHEMA_MISMATCH; } - if (!dsdb_attr_in_rodc_fas(sa)) { - *is_secret_request = true; + if (!sa->isMemberOfPartialAttributeSet) { + *is_gc_pas_request = false; return WERR_OK; } } - *is_secret_request = false; + if (req10->partial_attribute_set_ex) { + /* check the extended attributes they asked for */ + for (i=0; i<req10->partial_attribute_set_ex->num_attids; i++) { + const struct dsdb_attribute *sa; + sa = dsdb_attribute_by_attributeID_id(schema, req10->partial_attribute_set_ex->attids[i]); + if (sa == NULL) { + return WERR_DS_DRA_SCHEMA_MISMATCH; + } + if (!sa->isMemberOfPartialAttributeSet) { + *is_gc_pas_request = false; + return WERR_OK; + } + } + } + + *is_gc_pas_request = true; return WERR_OK; } @@ -1329,6 +1399,7 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ struct ldb_context *sam_ctx; struct dom_sid *user_sid; bool is_secret_request; + bool is_gc_pas_request; DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); b_state = h->data; @@ -1391,6 +1462,7 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ user_sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX]; + /* all clients must have GUID_DRS_GET_CHANGES */ werr = drs_security_access_check_nc_root(b_state->sam_ctx, mem_ctx, dce_call->conn->auth_state.session_info->security_token, @@ -1400,6 +1472,23 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ return werr; } + /* allowed if the GC PAS and client has + GUID_DRS_GET_FILTERED_ATTRIBUTES */ + werr = dcesrv_drsuapi_is_gc_pas_request(b_state, req10, &is_gc_pas_request); + if (!W_ERROR_IS_OK(werr)) { + return werr; + } + if (is_gc_pas_request) { + werr = drs_security_access_check_nc_root(b_state->sam_ctx, + mem_ctx, + dce_call->conn->auth_state.session_info->security_token, + req10->naming_context, + GUID_DRS_GET_FILTERED_ATTRIBUTES); + if (W_ERROR_IS_OK(werr)) { + goto allowed; + } + } + werr = dcesrv_drsuapi_is_reveal_secrets_request(b_state, req10, &is_secret_request); if (!W_ERROR_IS_OK(werr)) { return werr; @@ -1415,6 +1504,7 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ } } +allowed: /* for non-administrator replications, check that they have given the correct source_dsa_invocation_id */ security_level = security_session_user_level(dce_call->conn->auth_state.session_info, |