More kludge ACLs!
authorAndrew Bartlett <abartlet@samba.org>
Thu, 20 Mar 2008 01:12:10 +0000 (12:12 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 20 Mar 2008 01:12:10 +0000 (12:12 +1100)
Rather than killing off the nasty 'kludge ACLs' stuff, this patch
extends it, to ensure that LSA secrets and the registry are also
protected.

Andrew Bartlett
(This used to be commit 2f2b110fb870132099bad1d4c16ed8962affb3ce)

source4/dsdb/samdb/ldb_modules/kludge_acl.c
source4/libcli/security/security.h
source4/libcli/security/security_token.c
source4/rpc_server/lsa/dcesrv_lsa.c
source4/rpc_server/winreg/rpc_winreg.c

index e3e1f7ac88b6e49e102698646983826a5560fe90..e418031271cf845ccb5fd295be493ec01407878c 100644 (file)
  *
  */
 
-enum user_is {
-       ANONYMOUS,
-       USER,
-       ADMINISTRATOR,
-       SYSTEM
-};
-
 struct kludge_private_data {
        const char **password_attrs;
 };
 
-static enum user_is what_is_user(struct ldb_module *module) 
+static enum security_user_level what_is_user(struct ldb_module *module) 
 {
        struct auth_session_info *session_info
                = (struct auth_session_info *)ldb_get_opaque(module->ldb, "sessionInfo");
-       if (!session_info) {
-               return ANONYMOUS;
-       }
-       
-       if (security_token_is_system(session_info->security_token)) {
-               return SYSTEM;
-       }
-
-       if (security_token_is_anonymous(session_info->security_token)) {
-               return ANONYMOUS;
-       }
-
-       if (security_token_has_builtin_administrators(session_info->security_token)) {
-               return ADMINISTRATOR;
-       }
-
-       if (security_token_has_nt_authenticated_users(session_info->security_token)) {
-               return USER;
-       }
-
-       return ANONYMOUS;
+       return security_session_user_level(session_info);
 }
 
 static const char *user_name(TALLOC_CTX *mem_ctx, struct ldb_module *module) 
@@ -104,7 +77,7 @@ struct kludge_acl_context {
        void *up_context;
        int (*up_callback)(struct ldb_context *, void *, struct ldb_reply *);
 
-       enum user_is user_type;
+       enum security_user_level user_type;
        bool allowedAttributes;
        bool allowedAttributesEffective;
        bool allowedChildClasses;
@@ -272,8 +245,8 @@ static int kludge_acl_callback(struct ldb_context *ldb, void *context, struct ld
        if (data && data->password_attrs) /* if we are not initialized just get through */
        {
                switch (ac->user_type) {
-               case SYSTEM:
-               case ADMINISTRATOR:
+               case SECURITY_SYSTEM:
+               case SECURITY_ADMINISTRATOR:
                        if (ac->allowedAttributesEffective) {
                                ret = kludge_acl_allowedAttributes(ldb, ares->message, "allowedAttributesEffective");
                                if (ret != LDB_SUCCESS) {
@@ -359,7 +332,7 @@ static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req)
           so we don't allow a search for 'sambaPassword=penguin',
           just as we would not allow that attribute to be returned */
        switch (ac->user_type) {
-       case SYSTEM:
+       case SECURITY_SYSTEM:
                break;
        default:
                /* remove password attributes */
@@ -391,10 +364,10 @@ static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req)
 /* ANY change type */
 static int kludge_acl_change(struct ldb_module *module, struct ldb_request *req)
 {
-       enum user_is user_type = what_is_user(module);
+       enum security_user_level user_type = what_is_user(module);
        switch (user_type) {
-       case SYSTEM:
-       case ADMINISTRATOR:
+       case SECURITY_SYSTEM:
+       case SECURITY_ADMINISTRATOR:
                return ldb_next_request(module, req);
        default:
                ldb_asprintf_errstring(module->ldb,
index d9485c825fe0de573f3fafb5f729648c0f9902f6..c7f2a093113acfb09e12fef1ea564cf4176dcd03 100644 (file)
 */
 
 #include "librpc/gen_ndr/security.h"
+
+enum security_user_level {
+       SECURITY_ANONYMOUS,
+       SECURITY_USER,
+       SECURITY_ADMINISTRATOR,
+       SECURITY_SYSTEM
+};
+
 #include "libcli/security/proto.h"
index e126340c4659f15d1cdb8defe5a20d3b01dc2b31..0680c542588b637e0026722fd0a256c1b7672334 100644 (file)
@@ -23,6 +23,7 @@
 #include "includes.h"
 #include "dsdb/samdb/samdb.h"
 #include "libcli/security/security.h"
+#include "auth/session.h"
 
 /*
   return a blank security token
@@ -141,3 +142,29 @@ bool security_token_has_nt_authenticated_users(const struct security_token *toke
 {
        return security_token_has_sid_string(token, SID_NT_AUTHENTICATED_USERS);
 }
+
+enum security_user_level security_session_user_level(struct auth_session_info *session_info) 
+{
+       if (!session_info) {
+               return SECURITY_ANONYMOUS;
+       }
+       
+       if (security_token_is_system(session_info->security_token)) {
+               return SECURITY_SYSTEM;
+       }
+
+       if (security_token_is_anonymous(session_info->security_token)) {
+               return SECURITY_ANONYMOUS;
+       }
+
+       if (security_token_has_builtin_administrators(session_info->security_token)) {
+               return SECURITY_ADMINISTRATOR;
+       }
+
+       if (security_token_has_nt_authenticated_users(session_info->security_token)) {
+               return SECURITY_USER;
+       }
+
+       return SECURITY_ANONYMOUS;
+}
+
index 4d381ea978c1077bbd87e35e2eee9cc6fe05c244..429c413b980421bee1dfd7c03c796db69c4300bb 100644 (file)
@@ -99,8 +99,21 @@ static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX
        int ret;
 
        DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
+
        if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
                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))
+               {
+               case SECURITY_SYSTEM:
+               case SECURITY_ADMINISTRATOR:
+                       break;
+               default:
+                       /* Users and annonymous are not allowed delete things */
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+
                ret = ldb_delete(secret_state->sam_ldb, 
                                 secret_state->secret_dn);
                talloc_free(h);
@@ -446,6 +459,8 @@ static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TAL
 
 /* 
   lsa_CreateAccount 
+
+  This call does not seem to have any long-term effects, hence no database operations
 */
 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                  struct lsa_CreateAccount *r)
@@ -1673,6 +1688,16 @@ 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))
+       {
+       case SECURITY_SYSTEM:
+       case SECURITY_ADMINISTRATOR:
+               break;
+       default:
+               /* Users and annonymous are not allowed create secrets */
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        policy_state = policy_handle->data;
 
        if (!r->in.name.string) {
@@ -1819,6 +1844,16 @@ 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))
+       {
+       case SECURITY_SYSTEM:
+       case SECURITY_ADMINISTRATOR:
+               break;
+       default:
+               /* Users and annonymous are not allowed to access secrets */
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        secret_state = talloc(mem_ctx, struct lsa_secret_state);
        if (!secret_state) {
                return NT_STATUS_NO_MEMORY;
@@ -1850,10 +1885,10 @@ static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC
                }
        
        } else {
+               secret_state->global = false;
                secret_state->sam_ldb = talloc_reference(secret_state, 
                                 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
 
-               secret_state->global = false;
                name = r->in.name.string;
                if (strlen(name) < 1) {
                        return NT_STATUS_INVALID_PARAMETER;
@@ -2085,6 +2120,17 @@ 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))
+       {
+       case SECURITY_SYSTEM:
+       case SECURITY_ADMINISTRATOR:
+               break;
+       default:
+               /* Users and annonymous are not allowed to read secrets */
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        secret_state = h->data;
 
        /* pull all the user attributes */
index 681e3b918f870afc11f38ce47c81539fbd3ee8c0..9993dc14c116630c4fb38faf3de3131cce7f0b09 100644 (file)
@@ -26,6 +26,7 @@
 #include "rpc_server/common/common.h"
 #include "librpc/gen_ndr/ndr_security.h"
 #include "param/param.h"
+#include "libcli/security/security.h"
 
 enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY };
 
@@ -120,32 +121,39 @@ static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call,
 
        newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
 
-       /* the security descriptor is optional */
-       if (r->in.secdesc != NULL) {
-               DATA_BLOB sdblob;
-               enum ndr_err_code ndr_err;
-               sdblob.data = r->in.secdesc->sd.data;
-               sdblob.length = r->in.secdesc->sd.len;
-               if (sdblob.data == NULL) {
-                       return WERR_INVALID_PARAM;
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       {
+       case SECURITY_SYSTEM:
+       case SECURITY_ADMINISTRATOR:
+               /* the security descriptor is optional */
+               if (r->in.secdesc != NULL) {
+                       DATA_BLOB sdblob;
+                       enum ndr_err_code ndr_err;
+                       sdblob.data = r->in.secdesc->sd.data;
+                       sdblob.length = r->in.secdesc->sd.len;
+                       if (sdblob.data == NULL) {
+                               return WERR_INVALID_PARAM;
+                       }
+                       ndr_err = ndr_pull_struct_blob_all(&sdblob, mem_ctx, NULL, &sd,
+                                                          (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+                       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                               return WERR_INVALID_PARAM;
+                       }
                }
-               ndr_err = ndr_pull_struct_blob_all(&sdblob, mem_ctx, NULL, &sd,
-                                                  (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
-               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-                       return WERR_INVALID_PARAM;
+               
+               error = reg_key_add_name(newh, (struct registry_key *)h->data,
+                                        r->in.name.name, NULL, r->in.secdesc?&sd:NULL,
+                                        (struct registry_key **)&newh->data);
+               if (W_ERROR_IS_OK(error)) {
+                       r->out.new_handle = &newh->wire_handle;
+               } else {
+                       talloc_free(newh);
                }
+               
+               return error;
+       default:
+               return WERR_ACCESS_DENIED;
        }
-
-       error = reg_key_add_name(newh, (struct registry_key *)h->data,
-                                r->in.name.name, NULL, r->in.secdesc?&sd:NULL,
-                                (struct registry_key **)&newh->data);
-       if (W_ERROR_IS_OK(error)) {
-               r->out.new_handle = &newh->wire_handle;
-       } else {
-               talloc_free(newh);
-       }
-
-       return error;
 }
 
 
@@ -160,7 +168,14 @@ static WERROR dcesrv_winreg_DeleteKey(struct dcesrv_call_state *dce_call,
 
        DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
 
-       return reg_key_del((struct registry_key *)h->data, r->in.key.name);
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       {
+       case SECURITY_SYSTEM:
+       case SECURITY_ADMINISTRATOR:
+               return reg_key_del((struct registry_key *)h->data, r->in.key.name);
+       default:
+               return WERR_ACCESS_DENIED;
+       }
 }
 
 
@@ -176,9 +191,16 @@ static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call,
 
        DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
 
-       key = h->data;
-
-       return reg_del_value(key, r->in.value.name);
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       {
+       case SECURITY_SYSTEM:
+       case SECURITY_ADMINISTRATOR:
+               key = h->data;
+               
+               return reg_del_value(key, r->in.value.name);
+       default:
+               return WERR_ACCESS_DENIED;
+       }
 }
 
 
@@ -289,7 +311,14 @@ static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call,
 
        DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
 
-       return reg_key_flush(h->data);
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       {
+       case SECURITY_SYSTEM:
+       case SECURITY_ADMINISTRATOR:
+               return reg_key_flush(h->data);
+       default:
+               return WERR_ACCESS_DENIED;
+       }
 }
 
 
@@ -342,23 +371,31 @@ static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call,
 
        DCESRV_PULL_HANDLE_FAULT(h, r->in.parent_handle, HTYPE_REGKEY);
 
-       if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) {
-               newh = talloc_reference(dce_call->context, h);
-               result = WERR_OK;
-       } else {
-               newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
-               result = reg_open_key(newh, (struct registry_key *)h->data,
-                                     r->in.keyname.name,
-                                     (struct registry_key **)&newh->data);
-       }
-
-       if (W_ERROR_IS_OK(result)) {
-               r->out.handle = &newh->wire_handle;
-       } else {
-               talloc_free(newh);
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       {
+       case SECURITY_SYSTEM:
+       case SECURITY_ADMINISTRATOR:
+       case SECURITY_USER:
+               if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) {
+                       newh = talloc_reference(dce_call->context, h);
+                       result = WERR_OK;
+               } else {
+                       newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
+                       result = reg_open_key(newh, (struct registry_key *)h->data,
+                                             r->in.keyname.name,
+                                             (struct registry_key **)&newh->data);
+               }
+               
+               if (W_ERROR_IS_OK(result)) {
+                       r->out.handle = &newh->wire_handle;
+               } else {
+                       talloc_free(newh);
+               }
+               return result;
+       default:
+               return WERR_ACCESS_DENIED;
        }
 
-       return result;
 }
 
 
@@ -376,17 +413,25 @@ static WERROR dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state *dce_call,
 
        DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
 
-       k = h->data;
-
-       ret = reg_key_get_info(mem_ctx, k, &classname, r->out.num_subkeys,
-                              r->out.num_values, r->out.last_changed_time,
-                              r->out.max_subkeylen, r->out.max_valnamelen, 
-                              r->out.max_valbufsize);
-
-       if (r->out.classname != NULL)
-               r->out.classname->name = classname;
-
-       return ret;
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       {
+       case SECURITY_SYSTEM:
+       case SECURITY_ADMINISTRATOR:
+       case SECURITY_USER:
+               k = h->data;
+               
+               ret = reg_key_get_info(mem_ctx, k, &classname, r->out.num_subkeys,
+                                      r->out.num_values, r->out.last_changed_time,
+                                      r->out.max_subkeylen, r->out.max_valnamelen, 
+                                      r->out.max_valbufsize);
+               
+               if (r->out.classname != NULL)
+                       r->out.classname->name = classname;
+               
+               return ret;
+       default:
+               return WERR_ACCESS_DENIED;
+       }
 }
 
 
@@ -405,35 +450,43 @@ static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call,
 
        DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
 
-       key = h->data;
-
-       result = reg_key_get_value_by_name(mem_ctx, key, r->in.value_name.name,
-                                          &value_type, &value_data);
-
-       if (!W_ERROR_IS_OK(result)) {
-               return result;
-       }
-
-       /* Just asking for the size of the buffer */
-       r->out.type = talloc(mem_ctx, uint32_t);
-       if (!r->out.type) {
-               return WERR_NOMEM;
-       }
-       *r->out.type = value_type;
-       r->out.length = talloc(mem_ctx, uint32_t);
-       if (!r->out.length) {
-               return WERR_NOMEM;
-       }
-       *r->out.length = value_data.length;
-       if (r->in.data == NULL) {
-               r->out.size = talloc(mem_ctx, uint32_t);
-               *r->out.size = value_data.length;
-       } else {
-               r->out.size = r->in.size;
-               r->out.data = value_data.data;
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       {
+       case SECURITY_SYSTEM:
+       case SECURITY_ADMINISTRATOR:
+       case SECURITY_USER:
+               key = h->data;
+               
+               result = reg_key_get_value_by_name(mem_ctx, key, r->in.value_name.name,
+                                                  &value_type, &value_data);
+               
+               if (!W_ERROR_IS_OK(result)) {
+                       return result;
+               }
+               
+               /* Just asking for the size of the buffer */
+               r->out.type = talloc(mem_ctx, uint32_t);
+               if (!r->out.type) {
+                       return WERR_NOMEM;
+               }
+               *r->out.type = value_type;
+               r->out.length = talloc(mem_ctx, uint32_t);
+               if (!r->out.length) {
+                       return WERR_NOMEM;
+               }
+               *r->out.length = value_data.length;
+               if (r->in.data == NULL) {
+                       r->out.size = talloc(mem_ctx, uint32_t);
+                       *r->out.size = value_data.length;
+               } else {
+                       r->out.size = r->in.size;
+                       r->out.data = value_data.data;
+               }
+               
+               return WERR_OK;
+       default:
+               return WERR_ACCESS_DENIED;
        }
-
-       return WERR_OK;
 }
 
 
@@ -497,11 +550,17 @@ static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call,
 
        key = h->data;
 
-       data.data = r->in.data;
-       data.length = r->in.size;
-       result = reg_val_set(key, r->in.name.name, r->in.type, data);
-
-       return result;
+       switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+       {
+       case SECURITY_SYSTEM:
+       case SECURITY_ADMINISTRATOR:
+               data.data = r->in.data;
+               data.length = r->in.size;
+               result = reg_val_set(key, r->in.name.name, r->in.type, data);
+               return result;
+       default:
+               return WERR_ACCESS_DENIED;
+       }
 }