⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sec_acl.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* secacl.cc: Sun compatible ACL functions.   Copyright 2000, 2001, 2002 Red Hat, Inc.   Written by Corinna Vinschen <corinna@vinschen.de>This file is part of Cygwin.This software is a copyrighted work licensed under the terms of theCygwin license.  Please consult the file "CYGWIN_LICENSE" fordetails. */#include "winsup.h"#include <grp.h>#include <pwd.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <limits.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/acl.h>#include <ctype.h>#include <wingdi.h>#include <winuser.h>#include "cygerrno.h"#include "security.h"#include "fhandler.h"#include "path.h"#include "dtable.h"#include "pinfo.h"#include "cygheap.h"extern "C" int aclsort (int nentries, int, __aclent16_t *aclbufp);extern "C" int acl (const char *path, int cmd, int nentries, __aclent16_t *aclbufp);static intsearchace (__aclent16_t *aclp, int nentries, int type, int id = -1){  int i;  for (i = 0; i < nentries; ++i)    if ((aclp[i].a_type == type && (id < 0 || aclp[i].a_id == id))	|| !aclp[i].a_type)      return i;  return -1;}static intsetacl (const char *file, int nentries, __aclent16_t *aclbufp){  DWORD sd_size = 4096;  char sd_buf[4096];  PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;  if (read_sd (file, psd, &sd_size) <= 0)    {      debug_printf ("read_sd %E");      return -1;    }  BOOL dummy;  /* Get owner SID. */  PSID owner_sid = NULL;  if (!GetSecurityDescriptorOwner (psd, &owner_sid, &dummy))    {      __seterrno ();      return -1;    }  cygsid owner (owner_sid);  /* Get group SID. */  PSID group_sid = NULL;  if (!GetSecurityDescriptorGroup (psd, &group_sid, &dummy))    {      __seterrno ();      return -1;    }  cygsid group (group_sid);  /* Initialize local security descriptor. */  SECURITY_DESCRIPTOR sd;  if (!InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION))    {      __seterrno ();      return -1;    }  if (!SetSecurityDescriptorOwner (&sd, owner, FALSE))    {      __seterrno ();      return -1;    }  if (group      && !SetSecurityDescriptorGroup (&sd, group, FALSE))    {      __seterrno ();      return -1;    }  /* Fill access control list. */  char acl_buf[3072];  PACL acl = (PACL) acl_buf;  size_t acl_len = sizeof (ACL);  int ace_off = 0;  cygsid sid;  struct passwd *pw;  struct __group32 *gr;  int pos;  if (!InitializeAcl (acl, 3072, ACL_REVISION))    {      __seterrno ();      return -1;    }  for (int i = 0; i < nentries; ++i)    {      DWORD allow = STANDARD_RIGHTS_READ		    | FILE_READ_ATTRIBUTES | FILE_READ_EA;      if (aclbufp[i].a_perm & S_IROTH)	allow |= FILE_GENERIC_READ;      if (aclbufp[i].a_perm & S_IWOTH)	allow |= STANDARD_RIGHTS_ALL | FILE_GENERIC_WRITE;      if (aclbufp[i].a_perm & S_IXOTH)	allow |= FILE_GENERIC_EXECUTE;      if ((aclbufp[i].a_perm & (S_IWOTH | S_IXOTH)) == (S_IWOTH | S_IXOTH))	allow |= FILE_DELETE_CHILD;      /* Set inherit property. */      DWORD inheritance = (aclbufp[i].a_type & ACL_DEFAULT)			  ? (SUB_CONTAINERS_AND_OBJECTS_INHERIT | INHERIT_ONLY)			  : NO_INHERITANCE;      /*       * If a specific acl contains a corresponding default entry with       * identical permissions, only one Windows ACE with proper       * inheritance bits is created.       */      if (!(aclbufp[i].a_type & ACL_DEFAULT)	  && (pos = searchace (aclbufp, nentries,			       aclbufp[i].a_type | ACL_DEFAULT,			       (aclbufp[i].a_type & (USER|GROUP))			       ? aclbufp[i].a_id : -1)) >= 0	  && aclbufp[pos].a_type	  && aclbufp[i].a_perm == aclbufp[pos].a_perm)	{	  inheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;	  /* This eliminates the corresponding default entry. */	  aclbufp[pos].a_type = 0;	}      switch (aclbufp[i].a_type)	{	case USER_OBJ:	case DEF_USER_OBJ:	  allow |= STANDARD_RIGHTS_ALL & ~DELETE;	  if (!add_access_allowed_ace (acl, ace_off++, allow,					owner, acl_len, inheritance))	    return -1;	  break;	case USER:	case DEF_USER:	  if (!(pw = getpwuid32 (aclbufp[i].a_id))	      || !sid.getfrompw (pw)	      || !add_access_allowed_ace (acl, ace_off++, allow,					   sid, acl_len, inheritance))	    return -1;	  break;	case GROUP_OBJ:	case DEF_GROUP_OBJ:	  if (!add_access_allowed_ace (acl, ace_off++, allow,					group, acl_len, inheritance))	    return -1;	  break;	case GROUP:	case DEF_GROUP:	  if (!(gr = getgrgid32 (aclbufp[i].a_id))	      || !sid.getfromgr (gr)	      || !add_access_allowed_ace (acl, ace_off++, allow,					   sid, acl_len, inheritance))	    return -1;	  break;	case OTHER_OBJ:	case DEF_OTHER_OBJ:	  if (!add_access_allowed_ace (acl, ace_off++, allow,				       well_known_world_sid,				       acl_len, inheritance))	    return -1;	  break;	}    }  /* Set AclSize to computed value. */  acl->AclSize = acl_len;  debug_printf ("ACL-Size: %d", acl_len);  /* Create DACL for local security descriptor. */  if (!SetSecurityDescriptorDacl (&sd, TRUE, acl, FALSE))    {      __seterrno ();      return -1;    }  /* Make self relative security descriptor in psd. */  sd_size = 0;  MakeSelfRelativeSD (&sd, psd, &sd_size);  if (sd_size <= 0)    {      __seterrno ();      return -1;    }  if (!MakeSelfRelativeSD (&sd, psd, &sd_size))    {      __seterrno ();      return -1;    }  debug_printf ("Created SD-Size: %d", sd_size);  return write_sd (file, psd, sd_size);}/* Temporary access denied bits */#define DENY_R 040000#define DENY_W 020000#define DENY_X 010000static voidgetace (__aclent16_t &acl, int type, int id, DWORD win_ace_mask,        DWORD win_ace_type){  acl.a_type = type;  acl.a_id = id;  if ((win_ace_mask & FILE_READ_DATA) && !(acl.a_perm & (S_IROTH | DENY_R)))    if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)      acl.a_perm |= S_IROTH;    else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)      acl.a_perm |= DENY_R;  if ((win_ace_mask & FILE_WRITE_DATA) && !(acl.a_perm & (S_IWOTH | DENY_W)))    if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)      acl.a_perm |= S_IWOTH;    else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)      acl.a_perm |= DENY_W;  if ((win_ace_mask & FILE_EXECUTE) && !(acl.a_perm & (S_IXOTH | DENY_X)))    if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)      acl.a_perm |= S_IXOTH;    else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)      acl.a_perm |= DENY_X;}static intgetacl (const char *file, DWORD attr, int nentries, __aclent16_t *aclbufp){  DWORD sd_size = 4096;  char sd_buf[4096];  PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;  int ret;  if ((ret = read_sd (file, psd, &sd_size)) <= 0)    {      debug_printf ("read_sd %E");      return ret;    }  PSID owner_sid;  PSID group_sid;  BOOL dummy;  __uid32_t uid;  __gid32_t gid;  if (!GetSecurityDescriptorOwner (psd, &owner_sid, &dummy))    {      debug_printf ("GetSecurityDescriptorOwner %E");      __seterrno ();      return -1;    }  uid = cygsid (owner_sid).get_uid ();  if (!GetSecurityDescriptorGroup (psd, &group_sid, &dummy))    {      debug_printf ("GetSecurityDescriptorGroup %E");      __seterrno ();      return -1;    }  gid = cygsid (group_sid).get_gid ();  __aclent16_t lacl[MAX_ACL_ENTRIES];  memset (&lacl, 0, MAX_ACL_ENTRIES * sizeof (__aclent16_t));  lacl[0].a_type = USER_OBJ;  lacl[0].a_id = uid;  lacl[1].a_type = GROUP_OBJ;  lacl[1].a_id = gid;  lacl[2].a_type = OTHER_OBJ;  lacl[2].a_id = ILLEGAL_GID;  lacl[3].a_type = CLASS_OBJ;  lacl[3].a_id = ILLEGAL_GID;  lacl[3].a_perm = S_IROTH | S_IWOTH | S_IXOTH;  PACL acl;  BOOL acl_exists;  if (!GetSecurityDescriptorDacl (psd, &acl_exists, &acl, &dummy))    {      __seterrno ();      debug_printf ("GetSecurityDescriptorDacl %E");      return -1;    }  int pos, i, types_def = 0;  if (!acl_exists || !acl)    for (pos = 0; pos < 3; ++pos) /* Don't change CLASS_OBJ entry */      lacl[pos].a_perm = S_IROTH | S_IWOTH | S_IXOTH;  else    {      for (i = 0; i < acl->AceCount; ++i)	{	  ACCESS_ALLOWED_ACE *ace;	  	  if (!GetAce (acl, i, (PVOID *) &ace))	    continue;	  cygsid ace_sid ((PSID) &ace->SidStart);	  int id;	  int type = 0;	  if (ace_sid == well_known_world_sid)	    {	      type = OTHER_OBJ;	      id = ILLEGAL_GID;	    }	  else if (ace_sid == group_sid)	    {	      type = GROUP_OBJ;	      id = gid;	    }	  else if (ace_sid == owner_sid)	    {	      type = USER_OBJ;	      id = uid;	    }	  else	    {	      id = ace_sid.get_id (FALSE, &type);	      if (type != GROUP)		{		  int type2 = 0;		  int id2 = ace_sid.get_id (TRUE, &type2);		  if (type2 == GROUP)		    {		      id = id2;		      type = GROUP;		    }		}	    }	  if (!type)	    continue;	  if (!(ace->Header.AceFlags & INHERIT_ONLY))	    {	      if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)		getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);	    }	  if ((ace->Header.AceFlags & SUB_CONTAINERS_AND_OBJECTS_INHERIT)	      && (attr & FILE_ATTRIBUTE_DIRECTORY))	    {	      type |= ACL_DEFAULT;	      types_def |= type;	      if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)		getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);	    }	}      /* Include DEF_CLASS_OBJ if any default ace exists */      if ((types_def & (USER|GROUP)) 	  && ((pos = searchace (lacl, MAX_ACL_ENTRIES, DEF_CLASS_OBJ)) >= 0))	{	  lacl[pos].a_type = DEF_CLASS_OBJ;	  lacl[pos].a_id = ILLEGAL_GID;	  lacl[pos].a_perm = S_IRWXU | S_IRWXG | S_IRWXO;	}    }  if ((pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) < 0)    pos = MAX_ACL_ENTRIES;  if (aclbufp) {    if (EqualSid (owner_sid, group_sid))       lacl[0].a_perm = lacl[1].a_perm;    if (pos > nentries)      {        set_errno (ENOSPC);	return -1;      }    memcpy (aclbufp, lacl, pos * sizeof (__aclent16_t));    for (i = 0; i < pos; ++i)      aclbufp[i].a_perm &= ~(DENY_R | DENY_W | DENY_X);    aclsort (pos, 0, aclbufp);  }  syscall_printf ("%d = getacl (%s)", pos, file);  return pos;}intacl_access (const char *path, int flags){  __aclent16_t acls[MAX_ACL_ENTRIES];  int cnt;  if ((cnt = acl (path, GETACL, MAX_ACL_ENTRIES, acls)) < 1)    return -1;  /* Only check existance. */  if (!(flags & (R_OK | W_OK | X_OK)))    return 0;  for (int i = 0; i < cnt; ++i)    {      switch (acls[i].a_type)	{	case USER_OBJ:	case USER:	  if (acls[i].a_id != myself->uid)	    {	      /*	       * Check if user is a NT group:	       * Take SID from passwd, search SID in group, check is_grp_member.	       */	      cygsid owner;	      cygsid group;	      struct passwd *pw;	      struct __group32 *gr = NULL;	      if ((pw = getpwuid32 (acls[i].a_id)) != NULL		  && owner.getfrompw (pw))		{		  for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)		    if (group.getfromgr (gr)			&& owner == group			&& is_grp_member (myself->uid, gr->gr_gid))		      break;		}	      if (!gr)		continue;	    }	  break;	case GROUP_OBJ:	case GROUP:	  if (acls[i].a_id != myself->gid &&	      !is_grp_member (myself->uid, acls[i].a_id))	    continue;	  break;	case OTHER_OBJ:	  break;	default:	  continue;	}      if ((!(flags & R_OK) || (acls[i].a_perm & S_IROTH))	  && (!(flags & W_OK) || (acls[i].a_perm & S_IWOTH))	  && (!(flags & X_OK) || (acls[i].a_perm & S_IXOTH)))	return 0;    }  set_errno (EACCES);  return -1;}staticintacl_worker (const char *path, int cmd, int nentries, __aclent16_t *aclbufp,	    int nofollow){  extern suffix_info stat_suffixes[];  path_conv real_path (path, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) | PC_FULL, stat_suffixes);  if (real_path.error)    {      set_errno (real_path.error);      syscall_printf ("-1 = acl (%s)", path);      return -1;    }  if (!real_path.has_acls () || !allow_ntsec)    {      struct __stat64 st;      int ret = -1;      switch (cmd)	{	case SETACL:	  set_errno (ENOSYS);	  break;	case GETACL:	  if (nentries < 1)	    set_errno (EINVAL);	  else if ((nofollow && !lstat64 (path, &st))		   || (!nofollow && !stat64 (path, &st)))	    {	      __aclent16_t lacl[4];	      if (nentries > 0)		{		  lacl[0].a_type = USER_OBJ;		  lacl[0].a_id = st.st_uid;		  lacl[0].a_perm = (st.st_mode & S_IRWXU) >> 6;		}	      if (nentries > 1)		{		  lacl[1].a_type = GROUP_OBJ;		  lacl[1].a_id = st.st_gid;		  lacl[1].a_perm = (st.st_mode & S_IRWXG) >> 3;		}	      if (nentries > 2)		{		  lacl[2].a_type = OTHER_OBJ;		  lacl[2].a_id = ILLEGAL_GID;		  lacl[2].a_perm = st.st_mode & S_IRWXO;		}	      if (nentries > 3)		{		  lacl[3].a_type = CLASS_OBJ;		  lacl[3].a_id = ILLEGAL_GID;		  lacl[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO;		}	      if (nentries > 4)		nentries = 4;	      if (aclbufp)		memcpy (aclbufp, lacl, nentries * sizeof (__aclent16_t));	      ret = nentries;	    }	  break;	case GETACLCNT:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -