/** * Security descriptor / NT Token level access check function. */ bool can_access_file_acl(struct connection_struct *conn, const char * fname, uint32_t access_mask) { NTSTATUS status; uint32_t access_granted; struct security_descriptor *secdesc = NULL; if (conn->server_info->utok.uid == 0 || conn->admin_user) { /* I'm sorry sir, I didn't know you were root... */ return true; } status = SMB_VFS_GET_NT_ACL(conn, fname, (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION), &secdesc); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("Could not get acl: %s\n", nt_errstr(status))); return false; } status = se_access_check(secdesc, conn->server_info->ptok, access_mask, &access_granted); TALLOC_FREE(secdesc); return NT_STATUS_IS_OK(status); }
bool regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted, const struct nt_user_token *token ) { SEC_DESC *sec_desc; NTSTATUS status; WERROR err; /* use the default security check if the backend has not defined its * own */ if (key->ops && key->ops->reg_access_check) { return key->ops->reg_access_check(key->name, requested, granted, token); } err = regkey_get_secdesc(talloc_tos(), key, &sec_desc); if (!W_ERROR_IS_OK(err)) { return false; } se_map_generic( &requested, ®_generic_map ); status =se_access_check(sec_desc, token, requested, granted); TALLOC_FREE(sec_desc); if (!NT_STATUS_IS_OK(status)) { return false; } return NT_STATUS_IS_OK(status); }
BOOL share_access_check(const NT_USER_TOKEN *token, const char *sharename, uint32 desired_access) { uint32 granted; NTSTATUS status; TALLOC_CTX *mem_ctx = NULL; SEC_DESC *psd = NULL; size_t sd_size; BOOL ret = True; if (!(mem_ctx = talloc_init("share_access_check"))) { return False; } psd = get_share_security(mem_ctx, sharename, &sd_size); if (!psd) { TALLOC_FREE(mem_ctx); return True; } ret = se_access_check(psd, token, desired_access, &granted, &status); talloc_destroy(mem_ctx); return ret; }
bool share_access_check(const struct security_token *token, const char *sharename, uint32 desired_access, uint32_t *pgranted) { uint32 granted; NTSTATUS status; struct security_descriptor *psd = NULL; size_t sd_size; psd = get_share_security(talloc_tos(), sharename, &sd_size); if (!psd) { if (pgranted != NULL) { *pgranted = desired_access; } return false; } status = se_access_check(psd, token, desired_access, &granted); TALLOC_FREE(psd); if (pgranted != NULL) { *pgranted = granted; } return NT_STATUS_IS_OK(status); }
BOOL emptysd_check(struct passwd *pw, int ngroups, gid_t *groups) { uint32 acc_granted, status; BOOL result; /* For no DACL, access is allowed and the desired access mask is returned */ result = se_access_check(sd, pw->pw_uid, pw->pw_gid, ngroups, groups, SEC_RIGHTS_MAXIMUM_ALLOWED, &acc_granted, &status); if (!result || !(acc_granted == SEC_RIGHTS_MAXIMUM_ALLOWED)) { printf("FAIL: no dacl for %s (%d/%d)\n", pw->pw_name, pw->pw_uid, pw->pw_gid); failed = True; } result = se_access_check(sd, pw->pw_uid, pw->pw_gid, ngroups, groups, 0x1234, &acc_granted, &status); if (!result || !(acc_granted == 0x1234)) { printf("FAIL: no dacl2 for %s (%d/%d)\n", pw->pw_name, pw->pw_uid, pw->pw_gid); failed = True; } /* If desired access mask is empty then no access is allowed */ result = se_access_check(sd, pw->pw_uid, pw->pw_gid, ngroups, groups, 0, &acc_granted, &status); if (result) { printf("FAIL: zero desired access for %s (%d/%d)\n", pw->pw_name, pw->pw_uid, pw->pw_gid); failed = True; } return True; }
BOOL test_user(char *username, uint32 acc_desired, uint32 *acc_granted) { struct passwd *pw; uint32 status; if (!(pw = getpwnam(username))) { printf("FAIL: could not lookup user info for %s\n", username); exit(1); } return se_access_check(sd, pw->pw_uid, pw->pw_gid, 0, NULL, acc_desired, acc_granted, &status); }
static bool elog_check_access( EVENTLOG_INFO *info, NT_USER_TOKEN *token ) { char *tdbname = elog_tdbname(talloc_tos(), info->logname ); SEC_DESC *sec_desc; NTSTATUS status; if ( !tdbname ) return False; /* get the security descriptor for the file */ sec_desc = get_nt_acl_no_snum( info, tdbname ); TALLOC_FREE( tdbname ); if ( !sec_desc ) { DEBUG(5,("elog_check_access: Unable to get NT ACL for %s\n", tdbname)); return False; } /* root free pass */ if ( geteuid() == sec_initial_uid() ) { DEBUG(5,("elog_check_access: using root's token\n")); token = get_root_nt_token(); } /* run the check, try for the max allowed */ status = se_access_check( sec_desc, token, MAXIMUM_ALLOWED_ACCESS, &info->access_granted); if ( sec_desc ) TALLOC_FREE( sec_desc ); if (!NT_STATUS_IS_OK(status)) { DEBUG(8,("elog_check_access: se_access_check() return %s\n", nt_errstr(status))); return False; } /* we have to have READ permission for a successful open */ return ( info->access_granted & SA_RIGHT_FILE_READ_DATA ); }
bool regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted, const struct nt_user_token *token ) { SEC_DESC *sec_desc; NTSTATUS status; WERROR err; TALLOC_CTX *mem_ctx; /* use the default security check if the backend has not defined its * own */ if (key->ops && key->ops->reg_access_check) { return key->ops->reg_access_check(key->name, requested, granted, token); } /* * The secdesc routines can't yet cope with a NULL talloc ctx sanely. */ if (!(mem_ctx = talloc_init("regkey_access_check"))) { return false; } err = regkey_get_secdesc(mem_ctx, key, &sec_desc); if (!W_ERROR_IS_OK(err)) { TALLOC_FREE(mem_ctx); return false; } se_map_generic( &requested, ®_generic_map ); status =se_access_check(sec_desc, token, requested, granted); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(mem_ctx); return false; } TALLOC_FREE(mem_ctx); return NT_STATUS_IS_OK(status); }
bool share_access_check(const NT_USER_TOKEN *token, const char *sharename, uint32 desired_access) { uint32 granted; NTSTATUS status; SEC_DESC *psd = NULL; size_t sd_size; psd = get_share_security(talloc_tos(), sharename, &sd_size); if (!psd) { return True; } status = se_access_check(psd, token, desired_access, &granted); TALLOC_FREE(psd); return NT_STATUS_IS_OK(status); }
bool regkey_access_check(struct registry_key_handle *key, uint32 requested, uint32 *granted, const struct security_token *token ) { struct security_descriptor *sec_desc; NTSTATUS status; WERROR err; /* root free-pass, like we have on all other pipes like samr, lsa, etc. */ if (geteuid() == sec_initial_uid()) { *granted = REG_KEY_ALL; return true; } /* use the default security check if the backend has not defined its * own */ if (key->ops && key->ops->reg_access_check) { return key->ops->reg_access_check(key->name, requested, granted, token); } err = regkey_get_secdesc(talloc_tos(), key, &sec_desc); if (!W_ERROR_IS_OK(err)) { return false; } se_map_generic( &requested, ®_generic_map ); status =se_access_check(sec_desc, token, requested, granted); TALLOC_FREE(sec_desc); if (!NT_STATUS_IS_OK(status)) { return false; } return NT_STATUS_IS_OK(status); }
BOOL denysome_check(struct passwd *pw, int ngroups, gid_t *groups) { uint32 acc_granted, status; fstring name; BOOL result; int len1, len2; /* Check only user1 and user3 denied access */ result = se_access_check(sd, pw->pw_uid, pw->pw_gid, ngroups, groups, SEC_RIGHTS_MAXIMUM_ALLOWED, &acc_granted, &status); len1 = (int)strlen(pw->pw_name) - strlen("user1"); len2 = (int)strlen(pw->pw_name) - strlen("user3"); if ((strncmp("user1", &pw->pw_name[MAX(len1, 0)], strlen("user1")) == 0) || (strncmp("user3", &pw->pw_name[MAX(len2, 0)], strlen("user3")) == 0)) { if (result || acc_granted != 0) { printf("FAIL: access not denied for %s\n", pw->pw_name); } } else { if (!result || acc_granted != GENERIC_ALL_ACCESS) { printf("FAIL: access denied for %s\n", pw->pw_name); } } printf("result %s for user %s\n", result ? "allowed" : "denied", pw->pw_name); return True; }
/* The main entry point for access checking FOR THE FILE SERVER ONLY ! If returning ACCESS_DENIED this function returns the denied bits in the uint32_t pointed to by the access_granted pointer. */ NTSTATUS se_file_access_check(const struct security_descriptor *sd, const struct security_token *token, bool priv_open_requested, uint32_t access_desired, uint32_t *access_granted) { uint32_t bits_remaining; NTSTATUS status; if (!priv_open_requested) { /* Fall back to generic se_access_check(). */ return se_access_check(sd, token, access_desired, access_granted); } /* * We need to handle the maximum allowed flag * outside of se_access_check(), as we need to * add in the access allowed by the privileges * as well. */ if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) { uint32_t orig_access_desired = access_desired; access_desired |= access_check_max_allowed(sd, token); access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED; if (security_token_has_privilege(token, SEC_PRIV_BACKUP)) { access_desired |= SEC_RIGHTS_PRIV_BACKUP; } if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) { access_desired |= SEC_RIGHTS_PRIV_RESTORE; } DEBUG(10,("se_file_access_check: MAX desired = 0x%x " "mapped to 0x%x\n", orig_access_desired, access_desired)); } status = se_access_check(sd, token, access_desired, access_granted); if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { return status; } bits_remaining = *access_granted; /* Check if we should override with privileges. */ if ((bits_remaining & SEC_RIGHTS_PRIV_BACKUP) && security_token_has_privilege(token, SEC_PRIV_BACKUP)) { bits_remaining &= ~(SEC_RIGHTS_PRIV_BACKUP); } if ((bits_remaining & SEC_RIGHTS_PRIV_RESTORE) && security_token_has_privilege(token, SEC_PRIV_RESTORE)) { bits_remaining &= ~(SEC_RIGHTS_PRIV_RESTORE); } if (bits_remaining != 0) { *access_granted = bits_remaining; return NT_STATUS_ACCESS_DENIED; } return NT_STATUS_OK; }
NTSTATUS access_check_object( struct security_descriptor *psd, struct security_token *token, enum sec_privilege needed_priv_1, enum sec_privilege needed_priv_2, uint32 rights_mask, uint32 des_access, uint32 *acc_granted, const char *debug ) { NTSTATUS status = NT_STATUS_ACCESS_DENIED; uint32 saved_mask = 0; bool priv_granted = false; /* check privileges; certain SAM access bits should be overridden by privileges (mostly having to do with creating/modifying/deleting users and groups) */ if ((needed_priv_1 != SEC_PRIV_INVALID && security_token_has_privilege(token, needed_priv_1)) || (needed_priv_2 != SEC_PRIV_INVALID && security_token_has_privilege(token, needed_priv_2))) { priv_granted = true; saved_mask = (des_access & rights_mask); des_access &= ~saved_mask; DEBUG(4,("access_check_object: user rights access mask [0x%x]\n", rights_mask)); } /* check the security descriptor first */ status = se_access_check(psd, token, des_access, acc_granted); if (NT_STATUS_IS_OK(status)) { goto done; } /* give root a free pass */ if ( geteuid() == sec_initial_uid() ) { DEBUG(4,("%s: ACCESS should be DENIED (requested: %#010x)\n", debug, des_access)); DEBUGADD(4,("but overritten by euid == sec_initial_uid()\n")); priv_granted = true; *acc_granted = des_access; status = NT_STATUS_OK; goto done; } done: if (priv_granted) { /* add in any bits saved during the privilege check (only matters if status is ok) */ *acc_granted |= rights_mask; } DEBUG(4,("%s: access %s (requested: 0x%08x, granted: 0x%08x)\n", debug, NT_STATUS_IS_OK(status) ? "GRANTED" : "DENIED", des_access, *acc_granted)); return status; }
static bool elog_check_access( EVENTLOG_INFO *info, const struct security_token *token ) { char *tdbname = elog_tdbname(talloc_tos(), info->logname ); struct security_descriptor *sec_desc; struct security_ace *ace; NTSTATUS status; if ( !tdbname ) return False; /* get the security descriptor for the file */ sec_desc = get_nt_acl_no_snum( info, tdbname ); TALLOC_FREE( tdbname ); if ( !sec_desc ) { DEBUG(5,("elog_check_access: Unable to get NT ACL for %s\n", tdbname)); return False; } ace = talloc_zero(sec_desc, struct security_ace); if (ace == NULL) { TALLOC_FREE(sec_desc); return false; } ace->type = SEC_ACE_TYPE_ACCESS_ALLOWED; ace->flags = 0; ace->access_mask = REG_KEY_ALL; ace->trustee = global_sid_System; status = security_descriptor_dacl_add(sec_desc, ace); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(sec_desc); return false; } /* root free pass */ if ( geteuid() == sec_initial_uid() ) { DEBUG(5,("elog_check_access: running as root, using system token\n")); token = get_system_token(); } /* run the check, try for the max allowed */ status = se_access_check( sec_desc, token, MAXIMUM_ALLOWED_ACCESS, &info->access_granted); TALLOC_FREE(sec_desc); if (!NT_STATUS_IS_OK(status)) { DEBUG(8,("elog_check_access: se_access_check() return %s\n", nt_errstr(status))); return False; } /* we have to have READ permission for a successful open */ return ( info->access_granted & SEC_FILE_READ_DATA ); }
NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, uint32_t access_desired, struct lsa_policy_state **_state) { struct auth_session_info *session_info = dce_call->conn->auth_state.session_info; enum security_user_level security_level; struct lsa_policy_state *state; struct ldb_result *dom_res; const char *dom_attrs[] = { "objectSid", "objectGUID", "nTMixedDomain", "fSMORoleOwner", NULL }; char *p; int ret; state = talloc_zero(mem_ctx, struct lsa_policy_state); if (!state) { return NT_STATUS_NO_MEMORY; } /* make sure the sam database is accessible */ state->sam_ldb = samdb_connect(state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info, dce_call->conn->remote_address, 0); if (state->sam_ldb == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } /* and the privilege database */ state->pdb = privilege_connect(state, dce_call->conn->dce_ctx->lp_ctx); if (state->pdb == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } /* work out the domain_dn - useful for so many calls its worth fetching here */ state->domain_dn = ldb_get_default_basedn(state->sam_ldb); if (!state->domain_dn) { return NT_STATUS_NO_MEMORY; } /* work out the forest root_dn - useful for so many calls its worth fetching here */ state->forest_dn = ldb_get_root_basedn(state->sam_ldb); if (!state->forest_dn) { return NT_STATUS_NO_MEMORY; } ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res, state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL); if (ret != LDB_SUCCESS) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } if (dom_res->count != 1) { return NT_STATUS_NO_SUCH_DOMAIN; } state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid"); if (!state->domain_sid) { return NT_STATUS_NO_SUCH_DOMAIN; } state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0); talloc_free(dom_res); state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx); state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn); if (!state->domain_dns) { return NT_STATUS_NO_SUCH_DOMAIN; } p = strchr(state->domain_dns, '/'); if (p) { *p = '\0'; } state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn); if (!state->forest_dns) { return NT_STATUS_NO_SUCH_DOMAIN; } p = strchr(state->forest_dns, '/'); if (p) { *p = '\0'; } /* work out the builtin_dn - useful for so many calls its worth fetching here */ state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)"); if (!state->builtin_dn) { return NT_STATUS_NO_SUCH_DOMAIN; } /* work out the system_dn - useful for so many calls its worth fetching here */ state->system_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(&(objectClass=container)(cn=System))"); if (!state->system_dn) { return NT_STATUS_NO_SUCH_DOMAIN; } state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN); if (!state->builtin_sid) { return NT_STATUS_NO_SUCH_DOMAIN; } state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY); if (!state->nt_authority_sid) { return NT_STATUS_NO_SUCH_DOMAIN; } state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN); if (!state->creator_owner_domain_sid) { return NT_STATUS_NO_SUCH_DOMAIN; } state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN); if (!state->world_domain_sid) { return NT_STATUS_NO_SUCH_DOMAIN; } state->sd = sddl_decode(state, DCESRV_LSA_POLICY_SD_SDDL, state->domain_sid); if (state->sd == NULL) { return NT_STATUS_NO_MEMORY; } state->sd->dacl->revision = SECURITY_ACL_REVISION_NT4; se_map_generic(&access_desired, &dcesrv_lsa_policy_mapping); security_acl_map_generic(state->sd->dacl, &dcesrv_lsa_policy_mapping); security_level = security_session_user_level(session_info, NULL); if (security_level >= SECURITY_SYSTEM) { /* * The security descriptor doesn't allow system, * but we want to allow system via ncalrpc as root. */ state->access_mask = access_desired; if (state->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) { state->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED; state->access_mask |= LSA_POLICY_ALL_ACCESS; } } else { NTSTATUS status; status = se_access_check(state->sd, session_info->security_token, access_desired, &state->access_mask); if (!NT_STATUS_IS_OK(status)) { DEBUG(2,("%s: access desired[0x%08X] rejected[0x%08X] - %s\n", __func__, (unsigned)access_desired, (unsigned)state->access_mask, nt_errstr(status))); return status; } } DEBUG(10,("%s: access desired[0x%08X] granted[0x%08X] - success.\n", __func__, (unsigned)access_desired, (unsigned)state->access_mask)); *_state = state; return NT_STATUS_OK; }