SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, size_t *psize, uint32 def_access) { uint32_t sa; SEC_ACE ace; SEC_ACL *psa = NULL; SEC_DESC *psd = NULL; uint32 spec_access = def_access; se_map_generic(&spec_access, &file_generic_mapping); sa = (def_access | spec_access ); init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0); if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 1, &ace)) != NULL) { psd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, psize); } if (!psd) { DEBUG(0,("get_share_security: Failed to make SEC_DESC.\n")); return NULL; } return psd; }
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); }
void security_acl_map_generic(struct security_acl *sa, const struct generic_mapping *mapping) { unsigned int i; if (!sa) { return; } for (i = 0; i < sa->num_aces; i++) { se_map_generic(&sa->aces[i].access_mask, mapping); } }
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 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 parse_usershare_acl(TALLOC_CTX *ctx, const char *acl_str, SEC_DESC **ppsd) { size_t s_size = 0; const char *pacl = acl_str; int num_aces = 0; SEC_ACE *ace_list = NULL; SEC_ACL *psa = NULL; SEC_DESC *psd = NULL; size_t sd_size = 0; int i; *ppsd = NULL; /* If the acl string is blank return "Everyone:R" */ if (!*acl_str) { SEC_DESC *default_psd = get_share_security_default(ctx, &s_size, GENERIC_READ_ACCESS); if (!default_psd) { return False; } *ppsd = default_psd; return True; } num_aces = 1; /* Add the number of ',' characters to get the number of aces. */ num_aces += count_chars(pacl,','); ace_list = TALLOC_ARRAY(ctx, SEC_ACE, num_aces); if (!ace_list) { return False; } for (i = 0; i < num_aces; i++) { SEC_ACCESS sa; uint32 g_access; uint32 s_access; DOM_SID sid; fstring sidstr; uint8 type = SEC_ACE_TYPE_ACCESS_ALLOWED; if (!next_token(&pacl, sidstr, ":", sizeof(sidstr))) { DEBUG(0,("parse_usershare_acl: malformed usershare acl looking " "for ':' in string '%s'\n", pacl)); return False; } if (!string_to_sid(&sid, sidstr)) { DEBUG(0,("parse_usershare_acl: failed to convert %s to sid.\n", sidstr )); return False; } switch (*pacl) { case 'F': /* Full Control, ie. R+W */ case 'f': /* Full Control, ie. R+W */ s_access = g_access = GENERIC_ALL_ACCESS; break; case 'R': /* Read only. */ case 'r': /* Read only. */ s_access = g_access = GENERIC_READ_ACCESS; break; case 'D': /* Deny all to this SID. */ case 'd': /* Deny all to this SID. */ type = SEC_ACE_TYPE_ACCESS_DENIED; s_access = g_access = GENERIC_ALL_ACCESS; break; default: DEBUG(0,("parse_usershare_acl: unknown acl type at %s.\n", pacl )); return False; } pacl++; if (*pacl && *pacl != ',') { DEBUG(0,("parse_usershare_acl: bad acl string at %s.\n", pacl )); return False; } pacl++; /* Go past any ',' */ se_map_generic(&s_access, &file_generic_mapping); init_sec_access(&sa, g_access | s_access ); init_sec_ace(&ace_list[i], &sid, type, sa, 0); } if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, num_aces, ace_list)) != NULL) { psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, &sd_size); } if (!psd) { DEBUG(0,("parse_usershare_acl: Failed to make SEC_DESC.\n")); return False; } *ppsd = psd; return True; }
static bool smbacl4_fill_ace4( const struct smb_filename *filename, smbacl4_vfs_params *params, uid_t ownerUID, gid_t ownerGID, const struct security_ace *ace_nt, /* input */ SMB_ACE4PROP_T *ace_v4 /* output */ ) { DEBUG(10, ("got ace for %s\n", sid_string_dbg(&ace_nt->trustee))); memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T)); /* only ACCESS|DENY supported right now */ ace_v4->aceType = ace_nt->type; ace_v4->aceFlags = map_windows_ace_flags_to_nfs4_ace_flags( ace_nt->flags); /* remove inheritance flags on files */ if (VALID_STAT(filename->st) && !S_ISDIR(filename->st.st_ex_mode)) { DEBUG(10, ("Removing inheritance flags from a file\n")); ace_v4->aceFlags &= ~(SMB_ACE4_FILE_INHERIT_ACE| SMB_ACE4_DIRECTORY_INHERIT_ACE| SMB_ACE4_NO_PROPAGATE_INHERIT_ACE| SMB_ACE4_INHERIT_ONLY_ACE); } ace_v4->aceMask = ace_nt->access_mask & (SEC_STD_ALL | SEC_FILE_ALL); se_map_generic(&ace_v4->aceMask, &file_generic_mapping); if (ace_v4->aceFlags!=ace_nt->flags) DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n", ace_v4->aceFlags, ace_nt->flags)); if (ace_v4->aceMask!=ace_nt->access_mask) DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->access_mask(0x%x)\n", ace_v4->aceMask, ace_nt->access_mask)); if (dom_sid_equal(&ace_nt->trustee, &global_sid_World)) { ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE; ace_v4->flags |= SMB_ACE4_ID_SPECIAL; } else if (params->mode!=e_special && dom_sid_equal(&ace_nt->trustee, &global_sid_Creator_Owner)) { DEBUG(10, ("Map creator owner\n")); ace_v4->who.special_id = SMB_ACE4_WHO_OWNER; ace_v4->flags |= SMB_ACE4_ID_SPECIAL; /* A non inheriting creator owner entry has no effect. */ ace_v4->aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE; if (!(ace_v4->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE) && !(ace_v4->aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) { return false; } } else if (params->mode!=e_special && dom_sid_equal(&ace_nt->trustee, &global_sid_Creator_Group)) { DEBUG(10, ("Map creator owner group\n")); ace_v4->who.special_id = SMB_ACE4_WHO_GROUP; ace_v4->flags |= SMB_ACE4_ID_SPECIAL; /* A non inheriting creator group entry has no effect. */ ace_v4->aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE; if (!(ace_v4->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE) && !(ace_v4->aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) { return false; } } else { uid_t uid; gid_t gid; if (sid_to_gid(&ace_nt->trustee, &gid)) { ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; ace_v4->who.gid = gid; } else if (sid_to_uid(&ace_nt->trustee, &uid)) { ace_v4->who.uid = uid; } else { DEBUG(1, ("nfs4_acls.c: file [%s]: could not " "convert %s to uid or gid\n", filename->base_name, sid_string_dbg(&ace_nt->trustee))); return false; } } return true; /* OK */ }
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; }