s4-drs: added new SECURITY_RO_DOMAIN_CONTROLLER level
authorAndrew Tridgell <tridge@samba.org>
Thu, 22 Apr 2010 06:48:01 +0000 (16:48 +1000)
committerAndrew Tridgell <tridge@samba.org>
Thu, 22 Apr 2010 09:36:16 +0000 (19:36 +1000)
This is used for allowing operations by RODCs, and denying them
operations that should only be allowed for a full DC

This required a new domain_sid argument to
security_session_user_level()

Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
Pair-Programmed-With: Rusty Russell <rusty@samba.org>

13 files changed:
source4/dsdb/samdb/ldb_modules/kludge_acl.c
source4/dsdb/samdb/ldb_modules/repl_meta_data.c
source4/dsdb/samdb/ldb_modules/rootdse.c
source4/dsdb/samdb/ldb_modules/util.c
source4/libcli/security/security.h
source4/libcli/security/security_token.c
source4/rpc_server/drsuapi/addentry.c
source4/rpc_server/drsuapi/dcesrv_drsuapi.c
source4/rpc_server/drsuapi/dcesrv_drsuapi.h
source4/rpc_server/drsuapi/drsutil.c
source4/rpc_server/drsuapi/updaterefs.c
source4/rpc_server/lsa/dcesrv_lsa.c
source4/rpc_server/winreg/rpc_winreg.c

index 72863adebdba28211460126c827c52c826151cb0..42f0a306f43e34f731f0bc84072d5f7b3ea5f28d 100644 (file)
@@ -56,7 +56,7 @@ static enum security_user_level what_is_user(struct ldb_module *module)
        struct ldb_context *ldb = ldb_module_get_ctx(module);
        struct auth_session_info *session_info
                = (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
-       return security_session_user_level(session_info);
+       return security_session_user_level(session_info, NULL);
 }
 
 static const char *user_name(TALLOC_CTX *mem_ctx, struct ldb_module *module) 
index 75aed6ae7e41e4aba9f3101b69644e1700bfd341..efb44bfd4c0ca9f488018983677ac29dfe5233f7 100644 (file)
@@ -2402,7 +2402,7 @@ static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
        if (next_deletion_state == OBJECT_REMOVED) {
                struct auth_session_info *session_info =
                                (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
-               if (security_session_user_level(session_info) != SECURITY_SYSTEM) {
+               if (security_session_user_level(session_info, NULL) != SECURITY_SYSTEM) {
                        ldb_asprintf_errstring(ldb, "Refusing to delete deleted object %s",
                                        ldb_dn_get_linearized(old_msg->dn));
                        return LDB_ERR_UNWILLING_TO_PERFORM;
index f10a125eb618f3424c3be4566f803d6fed308995..5fffef7c864372a5f5c04b252905c3b3020b12d2 100644 (file)
@@ -884,7 +884,7 @@ static int rootdse_enableoptionalfeature(struct ldb_module *module, struct ldb_r
        int ret;
        const char *guid_string;
 
-       if (security_session_user_level(session_info) != SECURITY_SYSTEM) {
+       if (security_session_user_level(session_info, NULL) != SECURITY_SYSTEM) {
                ldb_asprintf_errstring(ldb, "rootdse: Insufficient rights for enableoptionalfeature");
                return LDB_ERR_UNWILLING_TO_PERFORM;
        }
index fe0ff7510ba88535b923726957a3e76b5442f02f..7913ac8049b8a5fb0f4afabfada15be7f95ff197 100644 (file)
@@ -799,7 +799,7 @@ bool dsdb_module_am_system(struct ldb_module *module)
        struct ldb_context *ldb = ldb_module_get_ctx(module);
        struct auth_session_info *session_info
                = (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
-       return security_session_user_level(session_info) == SECURITY_SYSTEM;
+       return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
 }
 
 /*
index e3fdb0c794882759838968d2e824c1599e238ff6..585170ed61c5f017d23e3cbf2a16c9d53e2e74fe 100644 (file)
 #include "librpc/gen_ndr/security.h"
 
 enum security_user_level {
-       SECURITY_ANONYMOUS,
-       SECURITY_USER,
-       SECURITY_DOMAIN_CONTROLLER,
-       SECURITY_ADMINISTRATOR,
-       SECURITY_SYSTEM
+       SECURITY_ANONYMOUS            = 0,
+       SECURITY_USER                 = 10,
+       SECURITY_RO_DOMAIN_CONTROLLER = 20,
+       SECURITY_DOMAIN_CONTROLLER    = 30,
+       SECURITY_ADMINISTRATOR        = 40,
+       SECURITY_SYSTEM               = 50
 };
 
 struct auth_session_info;
index d3eff93ddb78610321e15d6a610c546f8c6363ee..f105ed391f9df144ac7e0ef969c188a2a88499bf 100644 (file)
@@ -147,7 +147,8 @@ bool security_token_has_enterprise_dcs(const struct security_token *token)
        return security_token_has_sid_string(token, SID_NT_ENTERPRISE_DCS);
 }
 
-enum security_user_level security_session_user_level(struct auth_session_info *session_info) 
+enum security_user_level security_session_user_level(struct auth_session_info *session_info,
+                                                    const struct dom_sid *domain_sid)
 {
        if (!session_info) {
                return SECURITY_ANONYMOUS;
@@ -165,6 +166,16 @@ enum security_user_level security_session_user_level(struct auth_session_info *s
                return SECURITY_ADMINISTRATOR;
        }
 
+       if (domain_sid &&
+           dom_sid_in_domain(domain_sid, session_info->security_token->user_sid)) {
+               uint32_t rid;
+               NTSTATUS status = dom_sid_split_rid(NULL, session_info->security_token->user_sid,
+                                                   NULL, &rid);
+               if (NT_STATUS_IS_OK(status) && rid == DOMAIN_RID_ENTERPRISE_READONLY_DCS) {
+                       return SECURITY_RO_DOMAIN_CONTROLLER;
+               }
+       }
+
        if (security_token_has_enterprise_dcs(session_info->security_token)) {
                return SECURITY_DOMAIN_CONTROLLER;
        }
index cfddd80fe4b3615d8f745334c9f362416afa76ce..e87c9405971edb1bb702bdb572f96c7fb2c1cca8 100644 (file)
@@ -27,7 +27,7 @@
 #include "param/param.h"
 #include "rpc_server/drsuapi/dcesrv_drsuapi.h"
 #include "librpc/gen_ndr/ndr_drsuapi.h"
-
+#include "libcli/security/security.h"
 
 /*
   add special SPNs needed for DRS replication to machine accounts when
@@ -171,7 +171,7 @@ WERROR dcesrv_drsuapi_DsAddEntry(struct dcesrv_call_state *dce_call, TALLOC_CTX
        DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
        b_state = h->data;
 
-       status = drs_security_level_check(dce_call, "DsAddEntry");
+       status = drs_security_level_check(dce_call, "DsAddEntry", SECURITY_DOMAIN_CONTROLLER);
        if (!W_ERROR_IS_OK(status)) {
                return status;
        }
index 270c716d468c0b8f5a324c3953be7858286d8d65..5d3c513f3f30ab32eae9386b23f108172baca685 100644 (file)
@@ -65,7 +65,7 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C
        W_ERROR_HAVE_NO_MEMORY(b_state);
 
        /* if this is a DC connecting, give them system level access */
-       werr = drs_security_level_check(dce_call, NULL);
+       werr = drs_security_level_check(dce_call, NULL, SECURITY_DOMAIN_CONTROLLER);
        if (W_ERROR_IS_OK(werr)) {
                DEBUG(3,(__location__ ": doing DsBind with system_session\n"));
                auth_info = system_session(dce_call->conn->dce_ctx->lp_ctx);
@@ -247,7 +247,7 @@ static WERROR dcesrv_drsuapi_DsReplicaSync(struct dcesrv_call_state *dce_call, T
 {
        WERROR status;
 
-       status = drs_security_level_check(dce_call, "DsReplicaSync");
+       status = drs_security_level_check(dce_call, "DsReplicaSync", SECURITY_DOMAIN_CONTROLLER);
        if (!W_ERROR_IS_OK(status)) {
                return status;
        }
@@ -401,7 +401,7 @@ static WERROR dcesrv_drsuapi_DsRemoveDSServer(struct dcesrv_call_state *dce_call
 
        *r->out.level_out = 1;
 
-       status = drs_security_level_check(dce_call, "DsRemoveDSServer");
+       status = drs_security_level_check(dce_call, "DsRemoveDSServer", SECURITY_DOMAIN_CONTROLLER);
        if (!W_ERROR_IS_OK(status)) {
                return status;
        }
@@ -726,7 +726,7 @@ static WERROR dcesrv_drsuapi_DsExecuteKCC(struct dcesrv_call_state *dce_call, TA
                                  struct drsuapi_DsExecuteKCC *r)
 {
        WERROR status;
-       status = drs_security_level_check(dce_call, "DsExecuteKCC");
+       status = drs_security_level_check(dce_call, "DsExecuteKCC", SECURITY_DOMAIN_CONTROLLER);
 
        if (!W_ERROR_IS_OK(status)) {
                return status;
@@ -748,7 +748,7 @@ static WERROR dcesrv_drsuapi_DsReplicaGetInfo(struct dcesrv_call_state *dce_call
 
        if (!lp_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL,
                         "drs", "disable_sec_check", false)) {
-               level = security_session_user_level(dce_call->conn->auth_state.session_info);
+               level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
                if (level < SECURITY_ADMINISTRATOR) {
                        DEBUG(1,(__location__ ": Administrator access required for DsReplicaGetInfo\n"));
                        security_token_debug(2, dce_call->conn->auth_state.session_info->security_token);
index ba6bb21145c5e41e0c226a6e50942af37d0d3913..3b733deec1b89de939fe9e57ddbe475bd83e5e40 100644 (file)
@@ -61,8 +61,9 @@ int drsuapi_search_with_extended_dn(struct ldb_context *ldb,
                                    const char * const *attrs,
                                    const char *filter);
 
+enum security_user_level;
 WERROR drs_security_level_check(struct dcesrv_call_state *dce_call,
-                               const char* call);
+                               const char* call, enum security_user_level minimum_level);
 
 void drsuapi_process_secret_attribute(struct drsuapi_DsReplicaAttribute *attr,
                                      struct drsuapi_DsReplicaMetaData *meta_data);
index 28ec7bb84889b62bd16dd427e550b3e4e090fe59..11eff25fabe0a836a3ce2daeb6deb98e083e2ef4 100644 (file)
@@ -101,7 +101,9 @@ int drsuapi_search_with_extended_dn(struct ldb_context *ldb,
        return ret;
 }
 
-WERROR drs_security_level_check(struct dcesrv_call_state *dce_call, const char* call)
+WERROR drs_security_level_check(struct dcesrv_call_state *dce_call,
+                               const char* call,
+                               enum security_user_level minimum_level)
 {
        enum security_user_level level;
 
@@ -110,8 +112,8 @@ WERROR drs_security_level_check(struct dcesrv_call_state *dce_call, const char*
                return WERR_OK;
        }
 
-       level = security_session_user_level(dce_call->conn->auth_state.session_info);
-       if (level < SECURITY_DOMAIN_CONTROLLER) {
+       level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
+       if (level < minimum_level) {
                if (call) {
                        DEBUG(0,("%s refused for security token (level=%u)\n",
                                 call, (unsigned)level));
index dd3a3342b59919b941ffbe1c30418f61b561f582..0403db8f88c936373a8358af24f0e39e496e5477 100644 (file)
@@ -23,6 +23,8 @@
 #include "rpc_server/dcerpc_server.h"
 #include "dsdb/samdb/samdb.h"
 #include "rpc_server/drsuapi/dcesrv_drsuapi.h"
+#include "libcli/security/security.h"
+#include "auth/session.h"
 
 struct repsTo {
        uint32_t count;
@@ -189,11 +191,13 @@ WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TA
        struct drsuapi_bind_state *b_state;
        struct drsuapi_DsReplicaUpdateRefsRequest1 *req;
        WERROR werr;
+       int ret;
+       enum security_user_level security_level;
 
        DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
        b_state = h->data;
 
-       werr = drs_security_level_check(dce_call, "DsReplicaUpdateRefs");
+       werr = drs_security_level_check(dce_call, "DsReplicaUpdateRefs", SECURITY_RO_DOMAIN_CONTROLLER);
        if (!W_ERROR_IS_OK(werr)) {
                return werr;
        }
@@ -205,7 +209,20 @@ WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TA
 
        req = &r->in.req.req1;
 
+       security_level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
+       if (security_level < SECURITY_ADMINISTRATOR) {
+               /* check that they are using an invocationId that they own */
+               ret = dsdb_validate_invocation_id(b_state->sam_ctx,
+                                                 &req->dest_dsa_guid,
+                                                 dce_call->conn->auth_state.session_info->security_token->user_sid);
+               if (ret != LDB_SUCCESS) {
+                       DEBUG(0,(__location__ ": Refusing DsReplicaUpdateRefs for sid %s with GUID %s\n",
+                                dom_sid_string(mem_ctx,
+                                               dce_call->conn->auth_state.session_info->security_token->user_sid),
+                                GUID_string(mem_ctx, &req->dest_dsa_guid)));
+                       return WERR_DS_DRA_ACCESS_DENIED;
+               }
+       }
+
        return drsuapi_UpdateRefs(b_state, mem_ctx, req);
 }
-
-
index aaa0f7baa2eb204d40ae95d6a8655502b4e4c137..8ab3cbfe6bd00e27a93bcf38903f129db5f5e166 100644 (file)
@@ -180,7 +180,7 @@ static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALL
                struct lsa_secret_state *secret_state = h->data;
 
                /* Ensure user is permitted to delete this... */
-               switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+               switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
                {
                case SECURITY_SYSTEM:
                case SECURITY_ADMINISTRATOR:
@@ -2577,7 +2577,7 @@ static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_
        struct lsa_EnumAccountRights r2;
        char *dnstr;
 
-       if (security_session_user_level(dce_call->conn->auth_state.session_info) < 
+       if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
            SECURITY_ADMINISTRATOR) {
                DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
                return NT_STATUS_ACCESS_DENIED;
@@ -2870,7 +2870,7 @@ static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALL
        DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
        ZERO_STRUCTP(r->out.sec_handle);
        
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
@@ -3019,7 +3019,7 @@ static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC
                return NT_STATUS_INVALID_PARAMETER;
        }
        
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
@@ -3299,7 +3299,7 @@ static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLO
        DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
 
        /* Ensure user is permitted to read this... */
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
index cfaee091133158d46129d0056160cef8e4e459af..c639c634d19e1fe17af43d7fff0b6b3fda809f85 100644 (file)
@@ -123,7 +123,7 @@ static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call,
 
        newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
 
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
@@ -186,7 +186,7 @@ static WERROR dcesrv_winreg_DeleteKey(struct dcesrv_call_state *dce_call,
        DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
        key = h->data;
 
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
@@ -213,7 +213,7 @@ static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call,
        DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
        key = h->data;
 
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
@@ -351,7 +351,7 @@ static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call,
        DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
        key = h->data;
 
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
@@ -413,7 +413,7 @@ static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call,
        DCESRV_PULL_HANDLE_FAULT(h, r->in.parent_handle, HTYPE_REGKEY);
        key = h->data;
 
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
@@ -454,7 +454,7 @@ static WERROR dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state *dce_call,
        DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
        key = h->data;
 
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
@@ -505,7 +505,7 @@ static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call,
        DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
        key = h->data;
 
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
@@ -613,7 +613,7 @@ static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call,
        DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
        key = h->data;
 
-       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
        {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR: