summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2010-04-22 16:48:01 +1000
committerAndrew Tridgell <tridge@samba.org>2010-04-22 19:36:16 +1000
commitbb1ba4ff76eb90d0d62dd3edbe288f45cf7a0a1e (patch)
tree8fd3704eb6819063b1916c78bb1893ba16c7fe72 /source4
parentec0bb2f46b855d44cccb71a5511c2acb7d8eae09 (diff)
downloadsamba-bb1ba4ff76eb90d0d62dd3edbe288f45cf7a0a1e.tar.gz
samba-bb1ba4ff76eb90d0d62dd3edbe288f45cf7a0a1e.tar.bz2
samba-bb1ba4ff76eb90d0d62dd3edbe288f45cf7a0a1e.zip
s4-drs: added new SECURITY_RO_DOMAIN_CONTROLLER level
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>
Diffstat (limited to 'source4')
-rw-r--r--source4/dsdb/samdb/ldb_modules/kludge_acl.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/repl_meta_data.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/rootdse.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/util.c2
-rw-r--r--source4/libcli/security/security.h11
-rw-r--r--source4/libcli/security/security_token.c13
-rw-r--r--source4/rpc_server/drsuapi/addentry.c4
-rw-r--r--source4/rpc_server/drsuapi/dcesrv_drsuapi.c10
-rw-r--r--source4/rpc_server/drsuapi/dcesrv_drsuapi.h3
-rw-r--r--source4/rpc_server/drsuapi/drsutil.c8
-rw-r--r--source4/rpc_server/drsuapi/updaterefs.c23
-rw-r--r--source4/rpc_server/lsa/dcesrv_lsa.c10
-rw-r--r--source4/rpc_server/winreg/rpc_winreg.c16
13 files changed, 69 insertions, 37 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/kludge_acl.c b/source4/dsdb/samdb/ldb_modules/kludge_acl.c
index 72863adebd..42f0a306f4 100644
--- a/source4/dsdb/samdb/ldb_modules/kludge_acl.c
+++ b/source4/dsdb/samdb/ldb_modules/kludge_acl.c
@@ -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)
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 75aed6ae7e..efb44bfd4c 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -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;
diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c
index f10a125eb6..5fffef7c86 100644
--- a/source4/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c
@@ -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;
}
diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c
index fe0ff7510b..7913ac8049 100644
--- a/source4/dsdb/samdb/ldb_modules/util.c
+++ b/source4/dsdb/samdb/ldb_modules/util.c
@@ -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;
}
/*
diff --git a/source4/libcli/security/security.h b/source4/libcli/security/security.h
index e3fdb0c794..585170ed61 100644
--- a/source4/libcli/security/security.h
+++ b/source4/libcli/security/security.h
@@ -23,11 +23,12 @@
#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;
diff --git a/source4/libcli/security/security_token.c b/source4/libcli/security/security_token.c
index d3eff93ddb..f105ed391f 100644
--- a/source4/libcli/security/security_token.c
+++ b/source4/libcli/security/security_token.c
@@ -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;
}
diff --git a/source4/rpc_server/drsuapi/addentry.c b/source4/rpc_server/drsuapi/addentry.c
index cfddd80fe4..e87c940597 100644
--- a/source4/rpc_server/drsuapi/addentry.c
+++ b/source4/rpc_server/drsuapi/addentry.c
@@ -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;
}
diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
index 270c716d46..5d3c513f3f 100644
--- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
+++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
@@ -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);
diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.h b/source4/rpc_server/drsuapi/dcesrv_drsuapi.h
index ba6bb21145..3b733deec1 100644
--- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.h
+++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.h
@@ -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);
diff --git a/source4/rpc_server/drsuapi/drsutil.c b/source4/rpc_server/drsuapi/drsutil.c
index 28ec7bb848..11eff25fab 100644
--- a/source4/rpc_server/drsuapi/drsutil.c
+++ b/source4/rpc_server/drsuapi/drsutil.c
@@ -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));
diff --git a/source4/rpc_server/drsuapi/updaterefs.c b/source4/rpc_server/drsuapi/updaterefs.c
index dd3a3342b5..0403db8f88 100644
--- a/source4/rpc_server/drsuapi/updaterefs.c
+++ b/source4/rpc_server/drsuapi/updaterefs.c
@@ -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);
}
-
-
diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c
index aaa0f7baa2..8ab3cbfe6b 100644
--- a/source4/rpc_server/lsa/dcesrv_lsa.c
+++ b/source4/rpc_server/lsa/dcesrv_lsa.c
@@ -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:
diff --git a/source4/rpc_server/winreg/rpc_winreg.c b/source4/rpc_server/winreg/rpc_winreg.c
index cfaee09113..c639c634d1 100644
--- a/source4/rpc_server/winreg/rpc_winreg.c
+++ b/source4/rpc_server/winreg/rpc_winreg.c
@@ -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: