* sec_acl.cc (setacl): Fix bug which leads to ACE duplication in
case owner SID == group SID. (getacl): Reverse order of SID test against group or owner sid to prefer owner attributes over group attributes. Disable setting group permissions equivalent to owner permissions if owner == group. Add comment to explain why. Fix indentation. * security.cc (get_attribute_from_acl): Change type of local variables containing permission to mode_t. Apply deny mask to group if group SID == owner SID to avoid Everyone permissions to spill over into group permissions. Disable setting group permissions equivalent to owner permissions if owner == group. Add comment to explain why. * uinfo.cc (pwdgrp::fetch_account_from_windows): Allow user SID as group account if user is a "Microsoft Account". Explain why. Drop workaround enforcing primary group "Users" for "Microsoft Accounts".
This commit is contained in:
		| @@ -1,3 +1,20 @@ | |||||||
|  | 2015-02-27  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
|  | 	* sec_acl.cc (setacl): Fix bug which leads to ACE duplication in | ||||||
|  | 	case owner SID == group SID. | ||||||
|  | 	(getacl): Reverse order of SID test against group or owner sid to | ||||||
|  | 	prefer owner attributes over group attributes.  Disable setting group | ||||||
|  | 	permissions equivalent to owner permissions if owner == group.  Add | ||||||
|  | 	comment to explain why.  Fix indentation. | ||||||
|  | 	* security.cc (get_attribute_from_acl): Change type of local variables | ||||||
|  | 	containing permission to mode_t.  Apply deny mask to group if group SID | ||||||
|  | 	== owner SID to avoid Everyone permissions to spill over into group | ||||||
|  | 	permissions.  Disable setting group permissions equivalent to owner | ||||||
|  | 	permissions if owner == group.  Add comment to explain why. | ||||||
|  | 	* uinfo.cc (pwdgrp::fetch_account_from_windows): Allow user SID as | ||||||
|  | 	group account if user is a "Microsoft Account".  Explain why.  Drop | ||||||
|  | 	workaround enforcing primary group "Users" for "Microsoft Accounts". | ||||||
|  |  | ||||||
| 2015-02-26  Corinna Vinschen  <corinna@vinschen.de> | 2015-02-26  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
| 	* ldap.cc (cyg_ldap::wait): Call cygwait with cw_infinite timeout value | 	* ldap.cc (cyg_ldap::wait): Call cygwait with cw_infinite timeout value | ||||||
|   | |||||||
| @@ -169,7 +169,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp, | |||||||
| 	*allow |= FILE_DELETE_CHILD; | 	*allow |= FILE_DELETE_CHILD; | ||||||
|       invalid[i] = true; |       invalid[i] = true; | ||||||
|     } |     } | ||||||
|   bool isownergroup = (owner_sid == group_sid); |   bool isownergroup = (owner == group); | ||||||
|   DWORD owner_deny = ~owner_allow & (group_allow | other_allow); |   DWORD owner_deny = ~owner_allow & (group_allow | other_allow); | ||||||
|   owner_deny &= ~(STANDARD_RIGHTS_READ |   owner_deny &= ~(STANDARD_RIGHTS_READ | ||||||
| 		  | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES); | 		  | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES); | ||||||
| @@ -179,27 +179,27 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp, | |||||||
|   /* Set deny ACE for owner. */ |   /* Set deny ACE for owner. */ | ||||||
|   if (owner_deny |   if (owner_deny | ||||||
|       && !add_access_denied_ace (acl, ace_off++, owner_deny, |       && !add_access_denied_ace (acl, ace_off++, owner_deny, | ||||||
| 				 owner_sid, acl_len, NO_INHERITANCE)) | 				 owner, acl_len, NO_INHERITANCE)) | ||||||
|     return -1; |     return -1; | ||||||
|   /* Set deny ACE for group here to respect the canonical order, |   /* Set deny ACE for group here to respect the canonical order, | ||||||
|      if this does not impact owner */ |      if this does not impact owner */ | ||||||
|   if (group_deny && !(group_deny & owner_allow) && !isownergroup |   if (group_deny && !(group_deny & owner_allow) && !isownergroup | ||||||
|       && !add_access_denied_ace (acl, ace_off++, group_deny, |       && !add_access_denied_ace (acl, ace_off++, group_deny, | ||||||
| 				 group_sid, acl_len, NO_INHERITANCE)) | 				 group, acl_len, NO_INHERITANCE)) | ||||||
|     return -1; |     return -1; | ||||||
|   /* Set allow ACE for owner. */ |   /* Set allow ACE for owner. */ | ||||||
|   if (!add_access_allowed_ace (acl, ace_off++, owner_allow, |   if (!add_access_allowed_ace (acl, ace_off++, owner_allow, | ||||||
| 			       owner_sid, acl_len, NO_INHERITANCE)) | 			       owner, acl_len, NO_INHERITANCE)) | ||||||
|     return -1; |     return -1; | ||||||
|   /* Set deny ACE for group, if still needed. */ |   /* Set deny ACE for group, if still needed. */ | ||||||
|   if (group_deny & owner_allow && !isownergroup |   if (group_deny & owner_allow && !isownergroup | ||||||
|       && !add_access_denied_ace (acl, ace_off++, group_deny, |       && !add_access_denied_ace (acl, ace_off++, group_deny, | ||||||
| 				 group_sid, acl_len, NO_INHERITANCE)) | 				 group, acl_len, NO_INHERITANCE)) | ||||||
|     return -1; |     return -1; | ||||||
|   /* Set allow ACE for group. */ |   /* Set allow ACE for group. */ | ||||||
|   if (!isownergroup |   if (!isownergroup | ||||||
|       && !add_access_allowed_ace (acl, ace_off++, group_allow, |       && !add_access_allowed_ace (acl, ace_off++, group_allow, | ||||||
|                                   group_sid, acl_len, NO_INHERITANCE)) |                                   group, acl_len, NO_INHERITANCE)) | ||||||
|     return -1; |     return -1; | ||||||
|   /* Set allow ACE for everyone. */ |   /* Set allow ACE for everyone. */ | ||||||
|   if (!add_access_allowed_ace (acl, ace_off++, other_allow, |   if (!add_access_allowed_ace (acl, ace_off++, other_allow, | ||||||
| @@ -451,16 +451,16 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp) | |||||||
| 	      type = OTHER_OBJ; | 	      type = OTHER_OBJ; | ||||||
| 	      id = ILLEGAL_GID; | 	      id = ILLEGAL_GID; | ||||||
| 	    } | 	    } | ||||||
| 	  else if (ace_sid == group_sid) |  | ||||||
| 	    { |  | ||||||
| 	      type = GROUP_OBJ; |  | ||||||
| 	      id = gid; |  | ||||||
| 	    } |  | ||||||
| 	  else if (ace_sid == owner_sid) | 	  else if (ace_sid == owner_sid) | ||||||
| 	    { | 	    { | ||||||
| 	      type = USER_OBJ; | 	      type = USER_OBJ; | ||||||
| 	      id = uid; | 	      id = uid; | ||||||
| 	    } | 	    } | ||||||
|  | 	  else if (ace_sid == group_sid) | ||||||
|  | 	    { | ||||||
|  | 	      type = GROUP_OBJ; | ||||||
|  | 	      id = gid; | ||||||
|  | 	    } | ||||||
| 	  else if (ace_sid == well_known_creator_group_sid) | 	  else if (ace_sid == well_known_creator_group_sid) | ||||||
| 	    { | 	    { | ||||||
| 	      type = DEF_GROUP_OBJ; | 	      type = DEF_GROUP_OBJ; | ||||||
| @@ -563,9 +563,16 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp) | |||||||
|     } |     } | ||||||
|   if ((pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) < 0) |   if ((pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) < 0) | ||||||
|     pos = MAX_ACL_ENTRIES; |     pos = MAX_ACL_ENTRIES; | ||||||
|   if (aclbufp) { |   if (aclbufp) | ||||||
|  |     { | ||||||
|  | #if 0 | ||||||
|  |       /* Disable owner/group permissions equivalence if owner SID == group SID. | ||||||
|  | 	 It's technically not quite correct, but it helps in case a security | ||||||
|  | 	 conscious application checks if a file has too open permissions.  In | ||||||
|  | 	 fact, since owner == group, there's no security issue here. */ | ||||||
|       if (owner_sid == group_sid) |       if (owner_sid == group_sid) | ||||||
|       lacl[0].a_perm = lacl[1].a_perm; | 	lacl[1].a_perm = lacl[0].a_perm; | ||||||
|  | #endif | ||||||
|       if (pos > nentries) |       if (pos > nentries) | ||||||
| 	{ | 	{ | ||||||
| 	  set_errno (ENOSPC); | 	  set_errno (ENOSPC); | ||||||
|   | |||||||
| @@ -239,9 +239,9 @@ get_attribute_from_acl (mode_t *attribute, PACL acl, PSID owner_sid, | |||||||
| 			PSID group_sid, bool grp_member) | 			PSID group_sid, bool grp_member) | ||||||
| { | { | ||||||
|   ACCESS_ALLOWED_ACE *ace; |   ACCESS_ALLOWED_ACE *ace; | ||||||
|   int allow = 0; |   mode_t allow = 0; | ||||||
|   int deny = 0; |   mode_t deny = 0; | ||||||
|   int *flags, *anti; |   mode_t *flags, *anti; | ||||||
|  |  | ||||||
|   for (DWORD i = 0; i < acl->AceCount; ++i) |   for (DWORD i = 0; i < acl->AceCount; ++i) | ||||||
|     { |     { | ||||||
| @@ -301,6 +301,17 @@ get_attribute_from_acl (mode_t *attribute, PACL acl, PSID owner_sid, | |||||||
| 	    *flags |= ((!(*anti & S_IWUSR)) ? S_IWUSR : 0); | 	    *flags |= ((!(*anti & S_IWUSR)) ? S_IWUSR : 0); | ||||||
| 	  if (ace->Mask & FILE_EXEC_BITS) | 	  if (ace->Mask & FILE_EXEC_BITS) | ||||||
| 	    *flags |= ((!(*anti & S_IXUSR)) ? S_IXUSR : 0); | 	    *flags |= ((!(*anti & S_IXUSR)) ? S_IXUSR : 0); | ||||||
|  | 	  /* Apply deny mask to group if group SID == owner SID. */ | ||||||
|  | 	  if (group_sid && RtlEqualSid (owner_sid, group_sid) | ||||||
|  | 	      && ace->Header.AceType == ACCESS_DENIED_ACE_TYPE) | ||||||
|  | 	    { | ||||||
|  | 	      if (ace->Mask & FILE_READ_BITS) | ||||||
|  | 		*flags |= ((!(*anti & S_IRUSR)) ? S_IRGRP : 0); | ||||||
|  | 	      if (ace->Mask & FILE_WRITE_BITS) | ||||||
|  | 		*flags |= ((!(*anti & S_IWUSR)) ? S_IWGRP : 0); | ||||||
|  | 	      if (ace->Mask & FILE_EXEC_BITS) | ||||||
|  | 		*flags |= ((!(*anti & S_IXUSR)) ? S_IXGRP : 0); | ||||||
|  | 	    } | ||||||
| 	} | 	} | ||||||
|       else if (ace_sid == group_sid) |       else if (ace_sid == group_sid) | ||||||
| 	{ | 	{ | ||||||
| @@ -331,6 +342,11 @@ get_attribute_from_acl (mode_t *attribute, PACL acl, PSID owner_sid, | |||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|   *attribute &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX | S_ISGID | S_ISUID); |   *attribute &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX | S_ISGID | S_ISUID); | ||||||
|  | #if 0 | ||||||
|  |   /* Disable owner/group permissions equivalence if owner SID == group SID. | ||||||
|  |      It's technically not quite correct, but it helps in case a security | ||||||
|  |      conscious application checks if a file has too open permissions.  In | ||||||
|  |      fact, since owner == group, there's no security issue here. */ | ||||||
|   if (owner_sid && group_sid && RtlEqualSid (owner_sid, group_sid) |   if (owner_sid && group_sid && RtlEqualSid (owner_sid, group_sid) | ||||||
|       /* FIXME: temporary exception for /var/empty */ |       /* FIXME: temporary exception for /var/empty */ | ||||||
|       && well_known_system_sid != group_sid) |       && well_known_system_sid != group_sid) | ||||||
| @@ -340,6 +356,7 @@ get_attribute_from_acl (mode_t *attribute, PACL acl, PSID owner_sid, | |||||||
| 		| ((allow & S_IWUSR) ? S_IWGRP : 0) | 		| ((allow & S_IWUSR) ? S_IWGRP : 0) | ||||||
| 		| ((allow & S_IXUSR) ? S_IXGRP : 0)); | 		| ((allow & S_IXUSR) ? S_IXGRP : 0)); | ||||||
|     } |     } | ||||||
|  | #endif | ||||||
|   *attribute |= allow; |   *attribute |= allow; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2053,12 +2053,31 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) | |||||||
|       switch (acc_type) |       switch (acc_type) | ||||||
|       	{ |       	{ | ||||||
| 	case SidTypeUser: | 	case SidTypeUser: | ||||||
| 	  /* Don't allow users as group.  While this is technically possible, | 	  if (is_group () && acc_type == SidTypeUser) | ||||||
| 	     it doesn't make sense in a POSIX scenario.  It *is* used for | 	    { | ||||||
| 	     Microsoft Accounts, but those are converted to well-known groups | 	      /* Don't allow users as group.  While this is technically | ||||||
| 	     above. */ | 		 possible, it doesn't make sense in a POSIX scenario. | ||||||
| 	  if (is_group ()) | 	  | ||||||
|  | 		 And then there are the so-called Microsoft Accounts.  The | ||||||
|  | 		 special SID with security authority 11 is converted to a | ||||||
|  | 		 well known group above, but additionally, when logging in | ||||||
|  | 		 with such an account, the user's primary group SID is the | ||||||
|  | 		 user's SID.  Those we let pass, but no others. */ | ||||||
|  | 	      bool its_ok = false; | ||||||
|  | 	      if (wincap.has_microsoft_accounts ()) | ||||||
|  | 		{ | ||||||
|  | 		  struct cyg_USER_INFO_24 *ui24; | ||||||
|  | 		  if (NetUserGetInfo (NULL, name, 24, (PBYTE *) &ui24) | ||||||
|  | 		      == NERR_Success) | ||||||
|  | 		    { | ||||||
|  | 		      if (ui24->usri24_internet_identity) | ||||||
|  | 			its_ok = true; | ||||||
|  | 		      NetApiBufferFree (ui24); | ||||||
|  | 		    } | ||||||
|  | 		} | ||||||
|  | 	      if (!its_ok) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  | 	    } | ||||||
| 	  /*FALLTHRU*/ | 	  /*FALLTHRU*/ | ||||||
| 	case SidTypeGroup: | 	case SidTypeGroup: | ||||||
| 	case SidTypeAlias: | 	case SidTypeAlias: | ||||||
| @@ -2231,25 +2250,6 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) | |||||||
| 		      debug_printf ("NetUserGetInfo(%W) %u", name, nas); | 		      debug_printf ("NetUserGetInfo(%W) %u", name, nas); | ||||||
| 		      break; | 		      break; | ||||||
| 		    } | 		    } | ||||||
| 		  /* Logging in with a Microsoft Account, the user's primary |  | ||||||
| 		     group SID is the user's SID.  Security sensitive tools |  | ||||||
| 		     expecting tight file permissions choke on that.  We need |  | ||||||
| 		     an explicit primary group which is not identical to the |  | ||||||
| 		     user account.  Unfortunately, while the default primary |  | ||||||
| 		     group of the account in SAM is still "None", "None" is not |  | ||||||
| 		     in the user token group list.  So, what we do here is to |  | ||||||
| 		     use "Users" as a sane default primary group instead. */ |  | ||||||
| 		  if (wincap.has_microsoft_accounts ()) |  | ||||||
| 		    { |  | ||||||
| 		      struct cyg_USER_INFO_24 *ui24; |  | ||||||
| 		      nas = NetUserGetInfo (NULL, name, 24, (PBYTE *) &ui24); |  | ||||||
| 		      if (nas == NERR_Success) |  | ||||||
| 			{ |  | ||||||
| 			  if (ui24->usri24_internet_identity) |  | ||||||
| 			    gid = DOMAIN_ALIAS_RID_USERS; |  | ||||||
| 			  NetApiBufferFree (ui24); |  | ||||||
| 			} |  | ||||||
| 		    } |  | ||||||
| 		  /* Fetch user attributes. */ | 		  /* Fetch user attributes. */ | ||||||
| 		  home = cygheap->pg.get_home (ui, sid, dom, name, | 		  home = cygheap->pg.get_home (ui, sid, dom, name, | ||||||
| 					       fully_qualified_name); | 					       fully_qualified_name); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user