* 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))
|
||||
{
|
||||
/* 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