* sec_helper.cc (cygpsid::get_id): Move Samba SID->uid/gid mapping
from get_sids_info here. (get_sids_info): Vice versa. * security.cc (convert_samba_sd): New static function to map a Samba security descriptor to a security descriptor with UNIX users and groups converted to Windows SIDs per RFC 2307 mapping. (check_file_access): Call convert_samba_sd on Samba security descriptors.
This commit is contained in:
		
							parent
							
								
									f024a32928
								
							
						
					
					
						commit
						c7b9a091a5
					
				|  | @ -1,3 +1,14 @@ | |||
| 2014-03-03  Corinna Vinschen  <corinna@vinschen.de> | ||||
| 
 | ||||
| 	* sec_helper.cc (cygpsid::get_id): Move Samba SID->uid/gid mapping | ||||
| 	from get_sids_info here. | ||||
| 	(get_sids_info): Vice versa. | ||||
| 	* security.cc (convert_samba_sd): New static function to map a Samba | ||||
| 	security descriptor to a security descriptor with UNIX users and groups | ||||
| 	converted to Windows SIDs per RFC 2307 mapping. | ||||
| 	(check_file_access): Call convert_samba_sd on Samba security | ||||
| 	descriptors. | ||||
| 
 | ||||
| 2014-02-28  Corinna Vinschen  <corinna@vinschen.de> | ||||
| 
 | ||||
| 	* uinfo.cc (pwdgrp::fetch_account_from_windows): Only fetch extended | ||||
|  |  | |||
|  | @ -103,9 +103,27 @@ cygpsid::get_id (BOOL search_grp, int *type, cyg_ldap *pldap) | |||
|       struct group *gr; | ||||
|       if (cygheap->user.groups.pgsid == psid) | ||||
| 	id = myself->gid; | ||||
|       else if (sid_id_auth (psid) == 22) | ||||
| 	{ | ||||
| 	  /* Samba UNIX group.  Try to map to Cygwin gid.  If there's no
 | ||||
| 	     mapping in the cache, try to fetch it from the configured | ||||
| 	     RFC 2307 domain (see last comment in cygheap_domain_info::init() | ||||
| 	     for more information) and add it to the mapping cache. */ | ||||
| 	  gid_t gid = sid_sub_auth_rid (psid); | ||||
| 	  gid_t map_gid = cygheap->ugid_cache.get_gid (gid); | ||||
| 	  if (map_gid == ILLEGAL_GID) | ||||
| 	    { | ||||
| 	      if (pldap->open (cygheap->dom.get_rfc2307_domain ())) | ||||
| 		map_gid = pldap->remap_gid (gid); | ||||
| 	      if (map_gid == ILLEGAL_GID)  | ||||
| 		map_gid = MAP_UNIX_TO_CYGWIN_ID (gid); | ||||
| 	      cygheap->ugid_cache.add_gid (gid, map_gid); | ||||
| 	    } | ||||
| 	  id = (uid_t) map_gid; | ||||
| 	} | ||||
|       else if ((gr = internal_getgrsid (*this, pldap))) | ||||
| 	id = gr->gr_gid; | ||||
|       if (id != ILLEGAL_UID) | ||||
|       if ((gid_t) id != ILLEGAL_GID) | ||||
| 	{ | ||||
| 	  if (type) | ||||
| 	    *type = GROUP; | ||||
|  | @ -117,6 +135,21 @@ cygpsid::get_id (BOOL search_grp, int *type, cyg_ldap *pldap) | |||
|       struct passwd *pw; | ||||
|       if (*this == cygheap->user.sid ()) | ||||
| 	id = myself->uid; | ||||
|       else if (sid_id_auth (psid) == 22) | ||||
| 	{ | ||||
| 	  /* Samba UNIX user.  See comment above. */ | ||||
| 	  uid_t uid = sid_sub_auth_rid (psid); | ||||
| 	  uid_t map_uid = cygheap->ugid_cache.get_uid (uid); | ||||
| 	  if (map_uid == ILLEGAL_UID) | ||||
| 	    { | ||||
| 	      if (pldap->open (cygheap->dom.get_rfc2307_domain ())) | ||||
| 		map_uid = pldap->remap_uid (uid); | ||||
| 	      if (map_uid == ILLEGAL_UID) | ||||
| 		map_uid = MAP_UNIX_TO_CYGWIN_ID (uid); | ||||
| 	      cygheap->ugid_cache.add_uid (uid, map_uid); | ||||
| 	    } | ||||
| 	  id = map_uid; | ||||
| 	} | ||||
|       else if ((pw = internal_getpwsid (*this, pldap))) | ||||
| 	id = pw->pw_uid; | ||||
|       if (id != ILLEGAL_UID && type) | ||||
|  | @ -295,44 +328,16 @@ cygsidlist::add (const PSID nsi, bool well_known) | |||
| bool | ||||
| get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gidret) | ||||
| { | ||||
|   struct passwd *pw; | ||||
|   struct group *gr = NULL; | ||||
|   BOOL ret = false; | ||||
|   PWCHAR domain; | ||||
|   cyg_ldap cldap; | ||||
| 
 | ||||
|   owner_sid.debug_print ("get_sids_info: owner SID ="); | ||||
|   group_sid.debug_print ("get_sids_info: group SID ="); | ||||
| 
 | ||||
|   if (group_sid == cygheap->user.groups.pgsid) | ||||
|     *gidret = myself->gid; | ||||
|   else if (sid_id_auth (group_sid) == 22) | ||||
|   *uidret = owner_sid.get_uid (&cldap); | ||||
|   *gidret = group_sid.get_gid (&cldap); | ||||
|   if (*uidret == myself->uid) | ||||
|     { | ||||
|       /* Samba UNIX group.  Try to map to Cygwin gid.  If there's no mapping in
 | ||||
| 	 the cache, try to fetch it from the configured RFC 2307 domain (see | ||||
| 	 last comment in cygheap_domain_info::init() for more information) and | ||||
| 	 add it to the mapping cache. */ | ||||
|       gid_t gid = sid_sub_auth_rid (group_sid); | ||||
|       gid_t map_gid = cygheap->ugid_cache.get_gid (gid); | ||||
|       if (map_gid == ILLEGAL_GID) | ||||
| 	{ | ||||
| 	  domain = cygheap->dom.get_rfc2307_domain (); | ||||
| 	  if (cldap.open (domain)) | ||||
| 	    map_gid = cldap.remap_gid (gid); | ||||
| 	  if (map_gid == ILLEGAL_GID) | ||||
| 	    map_gid = MAP_UNIX_TO_CYGWIN_ID (gid); | ||||
| 	  cygheap->ugid_cache.add_gid (gid, map_gid); | ||||
| 	} | ||||
|       *gidret = map_gid; | ||||
|     } | ||||
|   else if ((gr = internal_getgrsid (group_sid, &cldap))) | ||||
|     *gidret = gr->gr_gid; | ||||
|   else | ||||
|     *gidret = ILLEGAL_GID; | ||||
| 
 | ||||
|   if (owner_sid == cygheap->user.sid ()) | ||||
|     { | ||||
|       *uidret = myself->uid; | ||||
|       if (*gidret == myself->gid) | ||||
| 	ret = TRUE; | ||||
|       else | ||||
|  | @ -340,34 +345,6 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid | |||
| 			      ? cygheap->user.imp_token () : NULL, | ||||
| 			      group_sid, &ret); | ||||
|     } | ||||
|   else if (sid_id_auth (owner_sid) == 22) | ||||
|     { | ||||
|       /* Samba UNIX user.  See comment above. */ | ||||
|       uid_t uid = sid_sub_auth_rid (owner_sid); | ||||
|       uid_t map_uid = cygheap->ugid_cache.get_uid (uid); | ||||
|       if (map_uid == ILLEGAL_UID) | ||||
| 	{ | ||||
| 	  domain = cygheap->dom.get_rfc2307_domain (); | ||||
| 	  if (cldap.open (domain)) | ||||
| 	    map_uid = cldap.remap_uid (uid); | ||||
| 	  if (map_uid == ILLEGAL_UID) | ||||
| 	    map_uid = MAP_UNIX_TO_CYGWIN_ID (uid); | ||||
| 	  cygheap->ugid_cache.add_uid (uid, map_uid); | ||||
| 	} | ||||
|       *uidret = map_uid; | ||||
|     } | ||||
|   else if ((pw = internal_getpwsid (owner_sid, &cldap))) | ||||
|     { | ||||
|       *uidret = pw->pw_uid; | ||||
|       if (gr || (*gidret != ILLEGAL_GID | ||||
| 		 && (gr = internal_getgrgid (*gidret, &cldap)))) | ||||
| 	for (int idx = 0; gr->gr_mem[idx]; ++idx) | ||||
| 	  if ((ret = strcasematch (pw->pw_name, gr->gr_mem[idx]))) | ||||
| 	    break; | ||||
|     } | ||||
|   else | ||||
|     *uidret = ILLEGAL_UID; | ||||
| 
 | ||||
|   return (bool) ret; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1046,6 +1046,95 @@ check_access (security_descriptor &sd, GENERIC_MAPPING &mapping, | |||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| /* Samba override.  Check security descriptor for Samba UNIX user and group
 | ||||
|    accounts and check if we have an RFC 2307 mapping to a Windows account. | ||||
|    Create a new security descriptor with all of the UNIX acocunts with | ||||
|    valid mapping replaced with their WIndows counterpart. */ | ||||
| static void | ||||
| convert_samba_sd (security_descriptor &sd_ret) | ||||
| { | ||||
|   NTSTATUS status; | ||||
|   BOOLEAN dummy; | ||||
|   PSID sid; | ||||
|   cygsid owner; | ||||
|   cygsid group; | ||||
|   SECURITY_DESCRIPTOR sd; | ||||
|   cyg_ldap cldap; | ||||
|   tmp_pathbuf tp; | ||||
|   PACL acl, oacl; | ||||
|   size_t acl_len; | ||||
|   PACCESS_ALLOWED_ACE ace; | ||||
| 
 | ||||
|   if (!NT_SUCCESS (RtlGetOwnerSecurityDescriptor (sd_ret, &sid, &dummy))) | ||||
|     return; | ||||
|   owner = sid; | ||||
|   if (!NT_SUCCESS (RtlGetGroupSecurityDescriptor (sd_ret, &sid, &dummy))) | ||||
|     return; | ||||
|   group = sid; | ||||
| 
 | ||||
|   if (sid_id_auth (owner) == 22) | ||||
|     { | ||||
|       struct passwd *pwd; | ||||
|       uid_t uid = owner.get_uid (&cldap); | ||||
|       if (uid < UNIX_POSIX_OFFSET && (pwd = internal_getpwuid (uid))) | ||||
|       	owner.getfrompw (pwd); | ||||
|     } | ||||
|   if (sid_id_auth (group) == 22) | ||||
|     { | ||||
|       struct group *grp; | ||||
|       gid_t gid = group.get_gid (&cldap); | ||||
|       if (gid < UNIX_POSIX_OFFSET && (grp = internal_getgrgid (gid))) | ||||
|       	group.getfromgr (grp); | ||||
|     } | ||||
| 
 | ||||
|   if (!NT_SUCCESS (RtlGetDaclSecurityDescriptor (sd_ret, &dummy, | ||||
| 						 &oacl, &dummy))) | ||||
|     return; | ||||
|   acl = (PACL) tp.w_get (); | ||||
|   RtlCreateAcl (acl, ACL_MAXIMUM_SIZE, ACL_REVISION); | ||||
|   acl_len = sizeof (ACL); | ||||
| 
 | ||||
|   for (DWORD i = 0; i < oacl->AceCount; ++i) | ||||
|     if (NT_SUCCESS (RtlGetAce (oacl, i, (PVOID *) &ace))) | ||||
|       { | ||||
| 	cygsid ace_sid ((PSID) &ace->SidStart); | ||||
| 	if (sid_id_auth (ace_sid) == 22) | ||||
| 	  { | ||||
| 	    if (sid_sub_auth (ace_sid, 0) == 1) /* user */ | ||||
| 	      { | ||||
| 		struct passwd *pwd; | ||||
| 		uid_t uid = ace_sid.get_uid (&cldap); | ||||
| 		if (uid < UNIX_POSIX_OFFSET && (pwd = internal_getpwuid (uid))) | ||||
| 		  ace_sid.getfrompw (pwd); | ||||
| 	      } | ||||
| 	    else /* group */ | ||||
| 	      { | ||||
| 		struct group *grp; | ||||
| 		gid_t gid = ace_sid.get_gid (&cldap); | ||||
| 		if (gid < UNIX_POSIX_OFFSET && (grp = internal_getgrgid (gid))) | ||||
| 		  ace_sid.getfromgr (grp); | ||||
| 	      } | ||||
| 	    if (!add_access_allowed_ace (acl, i, ace->Mask, ace_sid, acl_len, | ||||
| 					 ace->Header.AceFlags)) | ||||
| 	      return; | ||||
| 	  } | ||||
|       } | ||||
|   acl->AclSize = acl_len; | ||||
| 
 | ||||
|   RtlCreateSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION); | ||||
|   RtlSetControlSecurityDescriptor (&sd, SE_DACL_PROTECTED, SE_DACL_PROTECTED); | ||||
|   RtlSetOwnerSecurityDescriptor (&sd, owner, FALSE); | ||||
|   RtlSetGroupSecurityDescriptor (&sd, group, FALSE); | ||||
| 
 | ||||
|   status = RtlSetDaclSecurityDescriptor (&sd, TRUE, acl, FALSE); | ||||
|   if (!NT_SUCCESS (status)) | ||||
|     return; | ||||
|   DWORD sd_size = 0; | ||||
|   status = RtlAbsoluteToSelfRelativeSD (&sd, sd_ret, &sd_size); | ||||
|   if (sd_size > 0 && sd_ret.malloc (sd_size)) | ||||
|     RtlAbsoluteToSelfRelativeSD (&sd, sd_ret, &sd_size); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| check_file_access (path_conv &pc, int flags, bool effective) | ||||
| { | ||||
|  | @ -1059,7 +1148,12 @@ check_file_access (path_conv &pc, int flags, bool effective) | |||
|   if (flags & X_OK) | ||||
|     desired |= FILE_EXECUTE; | ||||
|   if (!get_file_sd (pc.handle (), pc, sd, false)) | ||||
|     ret = check_access (sd, file_mapping, desired, flags, effective); | ||||
|     { | ||||
|       /* Tweak Samba security descriptor as necessary. */ | ||||
|       if (pc.fs_is_samba ()) | ||||
| 	convert_samba_sd (sd); | ||||
|       ret = check_access (sd, file_mapping, desired, flags, effective); | ||||
|     } | ||||
|   debug_printf ("flags %y, ret %d", flags, ret); | ||||
|   return ret; | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue