static uint32_t create_share_access_mask(int snum, bool readonly_share, const struct security_token *token) { uint32_t share_access = 0; share_access_check(token, lp_servicename(talloc_tos(), snum), MAXIMUM_ALLOWED_ACCESS, &share_access); if (readonly_share) { share_access &= ~(SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA | SEC_FILE_WRITE_EA | SEC_FILE_WRITE_ATTRIBUTE | SEC_DIR_DELETE_CHILD ); } if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) { share_access |= SEC_FLAG_SYSTEM_SECURITY; } if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) { share_access |= SEC_RIGHTS_PRIV_RESTORE; } if (security_token_has_privilege(token, SEC_PRIV_BACKUP)) { share_access |= SEC_RIGHTS_PRIV_BACKUP; } if (security_token_has_privilege(token, SEC_PRIV_TAKE_OWNERSHIP)) { share_access |= SEC_STD_WRITE_OWNER; } return share_access; }
/* * Determine whether to process an FSRVP operation from connected user @p. * Windows checks for Administrators or Backup Operators group membership. We * also allow for the SEC_PRIV_BACKUP privilege. */ static bool fss_permitted(struct pipes_struct *p) { if (p->session_info->unix_token->uid == sec_initial_uid()) { DEBUG(6, ("Granting FSRVP op, user started smbd\n")); return true; } if (nt_token_check_sid(&global_sid_Builtin_Administrators, p->session_info->security_token)) { DEBUG(6, ("Granting FSRVP op, administrators group member\n")); return true; } if (nt_token_check_sid(&global_sid_Builtin_Backup_Operators, p->session_info->security_token)) { DEBUG(6, ("Granting FSRVP op, backup operators group member\n")); return true; } if (security_token_has_privilege(p->session_info->security_token, SEC_PRIV_BACKUP)) { DEBUG(6, ("Granting FSRVP op, backup privilege present\n")); return true; } DEBUG(2, ("FSRVP operation blocked due to lack of backup privilege " "or Administrators/Backup Operators group membership\n")); return false; }
static bool smbconf_reg_access_check(const char *keyname, uint32_t requested, uint32_t *granted, const struct security_token *token) { if (!security_token_has_privilege(token, SEC_PRIV_DISK_OPERATOR)) { return False; } *granted = REG_KEY_ALL; return True; }
/* perform a SEC_FLAG_MAXIMUM_ALLOWED access check */ static uint32_t access_check_max_allowed(const struct security_descriptor *sd, const struct security_token *token) { uint32_t denied = 0, granted = 0; unsigned i; if (security_token_has_sid(token, sd->owner_sid)) { granted |= SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL | SEC_STD_DELETE; } else if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) { granted |= SEC_STD_DELETE; } if (sd->dacl == NULL) { return granted & ~denied; } for (i = 0;i<sd->dacl->num_aces; i++) { struct security_ace *ace = &sd->dacl->aces[i]; if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { continue; } if (!security_token_has_sid(token, &ace->trustee)) { continue; } switch (ace->type) { case SEC_ACE_TYPE_ACCESS_ALLOWED: granted |= ace->access_mask; break; case SEC_ACE_TYPE_ACCESS_DENIED: case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: denied |= ace->access_mask; break; default: /* Other ACE types not handled/supported */ break; } } return granted & ~denied; }
WERROR _wkssvc_NetrUnjoinDomain2(struct pipes_struct *p, struct wkssvc_NetrUnjoinDomain2 *r) { struct libnet_UnjoinCtx *u = NULL; char *cleartext_pwd = NULL; char *admin_domain = NULL; char *admin_account = NULL; WERROR werr; struct security_token *token = p->session_info->security_token; if (!r->in.account || !r->in.encrypted_password) { return WERR_INVALID_PARAM; } if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) && !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) && !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) { DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have " "sufficient privileges\n")); return WERR_ACCESS_DENIED; } werr = decode_wkssvc_join_password_buffer( p->mem_ctx, r->in.encrypted_password, &p->session_info->session_key, &cleartext_pwd); if (!W_ERROR_IS_OK(werr)) { return werr; } split_domain_user(p->mem_ctx, r->in.account, &admin_domain, &admin_account); werr = libnet_init_UnjoinCtx(p->mem_ctx, &u); if (!W_ERROR_IS_OK(werr)) { return werr; } u->in.domain_name = lp_realm(); u->in.unjoin_flags = r->in.unjoin_flags | WKSSVC_JOIN_FLAGS_JOIN_TYPE; u->in.admin_account = admin_account; u->in.admin_password = cleartext_pwd; u->in.debug = true; u->in.modify_config = lp_config_backend_is_registry(); u->in.msg_ctx = p->msg_ctx; become_root(); werr = libnet_Unjoin(p->mem_ctx, u); unbecome_root(); if (!W_ERROR_IS_OK(werr)) { DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n", u->out.error_string ? u->out.error_string : win_errstr(werr))); } TALLOC_FREE(u); return werr; }
NTSTATUS sec_access_check_ds(const struct security_descriptor *sd, const struct security_token *token, uint32_t access_desired, uint32_t *access_granted, struct object_tree *tree, struct dom_sid *replace_sid) { uint32_t i; uint32_t bits_remaining; struct object_tree *node; const struct GUID *type; struct dom_sid self_sid; dom_sid_parse(SID_NT_SELF, &self_sid); *access_granted = access_desired; bits_remaining = access_desired; /* handle the maximum allowed flag */ if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) { access_desired |= access_check_max_allowed(sd, token); access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED; *access_granted = access_desired; bits_remaining = access_desired; } if (access_desired & SEC_FLAG_SYSTEM_SECURITY) { if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) { bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY; } else { return NT_STATUS_PRIVILEGE_NOT_HELD; } } /* the owner always gets SEC_STD_WRITE_DAC and SEC_STD_READ_CONTROL */ if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL)) && security_token_has_sid(token, sd->owner_sid)) { bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL); } /* TODO: remove this, as it is file server specific */ if ((bits_remaining & SEC_RIGHTS_PRIV_RESTORE) && security_token_has_privilege(token, SEC_PRIV_RESTORE)) { bits_remaining &= ~(SEC_RIGHTS_PRIV_RESTORE); } if ((bits_remaining & SEC_RIGHTS_PRIV_BACKUP) && security_token_has_privilege(token, SEC_PRIV_BACKUP)) { bits_remaining &= ~(SEC_RIGHTS_PRIV_BACKUP); } /* a NULL dacl allows access */ if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) { *access_granted = access_desired; return NT_STATUS_OK; } if (sd->dacl == NULL) { goto done; } /* check each ace in turn. */ for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) { struct dom_sid *trustee; struct security_ace *ace = &sd->dacl->aces[i]; if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { continue; } if (dom_sid_equal(&ace->trustee, &self_sid) && replace_sid) { trustee = replace_sid; } else { trustee = &ace->trustee; } if (!security_token_has_sid(token, trustee)) { continue; } switch (ace->type) { case SEC_ACE_TYPE_ACCESS_ALLOWED: if (tree) { object_tree_modify_access(tree, ace->access_mask); } bits_remaining &= ~ace->access_mask; break; case SEC_ACE_TYPE_ACCESS_DENIED: if (bits_remaining & ace->access_mask) { return NT_STATUS_ACCESS_DENIED; } break; case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: /* * check only in case we have provided a tree, * the ACE has an object type and that type * is in the tree */ type = get_ace_object_type(ace); if (!tree) { continue; } if (!type) { node = tree; } else { if (!(node = get_object_tree_by_GUID(tree, type))) { continue; } } if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT) { object_tree_modify_access(node, ace->access_mask); if (node->remaining_access == 0) { return NT_STATUS_OK; } } else { if (node->remaining_access & ace->access_mask){ return NT_STATUS_ACCESS_DENIED; } } break; default: /* Other ACE types not handled/supported */ break; } } done: if (bits_remaining != 0) { return NT_STATUS_ACCESS_DENIED; } return NT_STATUS_OK; }
/* 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; }
/* The main entry point for access checking. If returning ACCESS_DENIED this function returns the denied bits in the uint32_t pointed to by the access_granted pointer. */ NTSTATUS se_access_check(const struct security_descriptor *sd, const struct security_token *token, uint32_t access_desired, uint32_t *access_granted) { uint32_t i; uint32_t bits_remaining; uint32_t explicitly_denied_bits = 0; /* * Up until Windows Server 2008, owner always had these rights. Now * we have to use Owner Rights perms if they are on the file. * * In addition we have to accumulate these bits and apply them * correctly. See bug #8795 */ uint32_t owner_rights_allowed = 0; uint32_t owner_rights_denied = 0; bool owner_rights_default = true; *access_granted = access_desired; bits_remaining = access_desired; /* handle the maximum allowed flag */ 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; *access_granted = access_desired; bits_remaining = access_desired; DEBUG(10,("se_access_check: MAX desired = 0x%x, granted = 0x%x, remaining = 0x%x\n", orig_access_desired, *access_granted, bits_remaining)); } /* a NULL dacl allows access */ if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) { *access_granted = access_desired; return NT_STATUS_OK; } if (sd->dacl == NULL) { goto done; } /* check each ace in turn. */ for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) { struct security_ace *ace = &sd->dacl->aces[i]; if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { continue; } /* * We need the Owner Rights permissions to ensure we * give or deny the correct permissions to the owner. Replace * owner_rights with the perms here if it is present. * * We don't care if we are not the owner because that is taken * care of below when we check if our token has the owner SID. * */ if (dom_sid_equal(&ace->trustee, &global_sid_Owner_Rights)) { if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) { owner_rights_allowed |= ace->access_mask; owner_rights_default = false; } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) { owner_rights_denied |= ace->access_mask; owner_rights_default = false; } continue; } if (!security_token_has_sid(token, &ace->trustee)) { continue; } switch (ace->type) { case SEC_ACE_TYPE_ACCESS_ALLOWED: bits_remaining &= ~ace->access_mask; break; case SEC_ACE_TYPE_ACCESS_DENIED: case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: explicitly_denied_bits |= (bits_remaining & ace->access_mask); break; default: /* Other ACE types not handled/supported */ break; } } /* Explicitly denied bits always override */ bits_remaining |= explicitly_denied_bits; /* The owner always gets owner rights as defined above. */ if (security_token_has_sid(token, sd->owner_sid)) { if (owner_rights_default) { /* * Just remove them, no need to check if they are * there. */ bits_remaining &= ~(SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL); } else { bits_remaining &= ~owner_rights_allowed; bits_remaining |= owner_rights_denied; } } /* * We check privileges here because they override even DENY entries. */ /* Does the user have the privilege to gain SEC_PRIV_SECURITY? */ if (bits_remaining & SEC_FLAG_SYSTEM_SECURITY) { if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) { bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY; } else { return NT_STATUS_PRIVILEGE_NOT_HELD; } } if ((bits_remaining & SEC_STD_WRITE_OWNER) && security_token_has_privilege(token, SEC_PRIV_TAKE_OWNERSHIP)) { bits_remaining &= ~(SEC_STD_WRITE_OWNER); } done: if (bits_remaining != 0) { *access_granted = bits_remaining; return NT_STATUS_ACCESS_DENIED; } return NT_STATUS_OK; }
/* the main entry point for access checking. */ NTSTATUS sec_access_check(const struct security_descriptor *sd, const struct security_token *token, uint32_t access_desired, uint32_t *access_granted) { int i; uint32_t bits_remaining; *access_granted = access_desired; bits_remaining = access_desired; /* handle the maximum allowed flag */ if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) { access_desired |= access_check_max_allowed(sd, token); access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED; *access_granted = access_desired; bits_remaining = access_desired & ~SEC_STD_DELETE; } if (access_desired & SEC_FLAG_SYSTEM_SECURITY) { if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) { bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY; } else { return NT_STATUS_PRIVILEGE_NOT_HELD; } } /* a NULL dacl allows access */ if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) { *access_granted = access_desired; return NT_STATUS_OK; } /* the owner always gets SEC_STD_WRITE_DAC, SEC_STD_READ_CONTROL and SEC_STD_DELETE */ if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE)) && security_token_has_sid(token, sd->owner_sid)) { bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE); } if ((bits_remaining & SEC_RIGHTS_PRIV_RESTORE) && security_token_has_privilege(token, SEC_PRIV_RESTORE)) { bits_remaining &= ~(SEC_RIGHTS_PRIV_RESTORE); } if ((bits_remaining & SEC_RIGHTS_PRIV_BACKUP) && security_token_has_privilege(token, SEC_PRIV_BACKUP)) { bits_remaining &= ~(SEC_RIGHTS_PRIV_BACKUP); } if (sd->dacl == NULL) { goto done; } /* check each ace in turn. */ for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) { struct security_ace *ace = &sd->dacl->aces[i]; if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { continue; } if (!security_token_has_sid(token, &ace->trustee)) { continue; } switch (ace->type) { case SEC_ACE_TYPE_ACCESS_ALLOWED: bits_remaining &= ~ace->access_mask; break; case SEC_ACE_TYPE_ACCESS_DENIED: case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: if (bits_remaining & ace->access_mask) { return NT_STATUS_ACCESS_DENIED; } break; default: /* Other ACE types not handled/supported */ break; } } done: if (bits_remaining != 0) { 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; }
/* The main entry point for access checking. If returning ACCESS_DENIED this function returns the denied bits in the uint32_t pointed to by the access_granted pointer. */ NTSTATUS se_access_check(const struct security_descriptor *sd, const struct security_token *token, uint32_t access_desired, uint32_t *access_granted) { uint32_t i; uint32_t bits_remaining; *access_granted = access_desired; bits_remaining = access_desired; /* handle the maximum allowed flag */ 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; *access_granted = access_desired; bits_remaining = access_desired; DEBUG(10,("se_access_check: MAX desired = 0x%x, granted = 0x%x, remaining = 0x%x\n", orig_access_desired, *access_granted, bits_remaining)); } /* s3 had this with #if 0 previously. To be sure the merge doesn't change any behaviour, we have the above #if check on _SAMBA_BUILD_. */ if (access_desired & SEC_FLAG_SYSTEM_SECURITY) { if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) { bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY; } else { return NT_STATUS_PRIVILEGE_NOT_HELD; } } /* the owner always gets SEC_STD_WRITE_DAC and SEC_STD_READ_CONTROL */ if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL)) && security_token_has_sid(token, sd->owner_sid)) { bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL); } /* TODO: remove this, as it is file server specific */ if ((bits_remaining & SEC_RIGHTS_PRIV_RESTORE) && security_token_has_privilege(token, SEC_PRIV_RESTORE)) { bits_remaining &= ~(SEC_RIGHTS_PRIV_RESTORE); } if ((bits_remaining & SEC_RIGHTS_PRIV_BACKUP) && security_token_has_privilege(token, SEC_PRIV_BACKUP)) { bits_remaining &= ~(SEC_RIGHTS_PRIV_BACKUP); } /* a NULL dacl allows access */ if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) { *access_granted = access_desired; return NT_STATUS_OK; } if (sd->dacl == NULL) { goto done; } /* check each ace in turn. */ for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) { struct security_ace *ace = &sd->dacl->aces[i]; if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { continue; } if (!security_token_has_sid(token, &ace->trustee)) { continue; } switch (ace->type) { case SEC_ACE_TYPE_ACCESS_ALLOWED: bits_remaining &= ~ace->access_mask; break; case SEC_ACE_TYPE_ACCESS_DENIED: case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: if (bits_remaining & ace->access_mask) { return NT_STATUS_ACCESS_DENIED; } break; default: /* Other ACE types not handled/supported */ break; } } done: if (bits_remaining != 0) { *access_granted = bits_remaining; return NT_STATUS_ACCESS_DENIED; } return NT_STATUS_OK; }