* dtable.cc (dtable::build_fhandler_from_name): Set some fhandler
data on sockets to evaluate AF_LOCAL sockets correctly. (dtable::build_fhandler): Set unit number on sockets. * fhandler.h (fhandler_socket): Add unit number. (fhandler_socket::get_unit): New method. * fhandler_socket.cc (fhandler_socket::fhandler_socket): Set unit number. (fhandler_socket::fstat): Reorganize to return more Linux-like values. * net.cc: include ctype.h. (fdsock): Set unit number when building fhandler. * path.cc (path_conv::check): Set device type to FH_SOCKET if file is a AF_UNIX socket. (get_devn): Evaluate unit for virtual socket devices. (win32_device_name): Set windows path for sockets to unix_path with just backslashes to keep the different names. * syscalls.cc (fstat64): Don't override st_ino, st_dev and st_rdev for sockets. (stat_worker): Ditto. From Pierre Humblet: * autoload.cc (AccessCheck): Add. (DuplicateToken): Add. * security.h (check_file_access): Declare. * syscalls.cc (access): Convert path to Windows, check existence and readonly attribute. Call check_file_access instead of acl_access. * security.cc (check_file_access): Create. * sec_acl (acl_access): Delete.
This commit is contained in:
parent
d05ef21d4f
commit
cf762b08cf
|
@ -1,3 +1,35 @@
|
|||
2003-02-21 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* dtable.cc (dtable::build_fhandler_from_name): Set some fhandler
|
||||
data on sockets to evaluate AF_LOCAL sockets correctly.
|
||||
(dtable::build_fhandler): Set unit number on sockets.
|
||||
* fhandler.h (fhandler_socket): Add unit number.
|
||||
(fhandler_socket::get_unit): New method.
|
||||
* fhandler_socket.cc (fhandler_socket::fhandler_socket): Set unit
|
||||
number.
|
||||
(fhandler_socket::fstat): Reorganize to return more Linux-like
|
||||
values.
|
||||
* net.cc: include ctype.h.
|
||||
(fdsock): Set unit number when building fhandler.
|
||||
* path.cc (path_conv::check): Set device type to FH_SOCKET if file
|
||||
is a AF_UNIX socket.
|
||||
(get_devn): Evaluate unit for virtual socket devices.
|
||||
(win32_device_name): Set windows path for sockets to unix_path with
|
||||
just backslashes to keep the different names.
|
||||
* syscalls.cc (fstat64): Don't override st_ino, st_dev and st_rdev
|
||||
for sockets.
|
||||
(stat_worker): Ditto.
|
||||
|
||||
2003-02-21 Pierre Humblet <pierre.humblet@ieee.org>
|
||||
|
||||
* autoload.cc (AccessCheck): Add.
|
||||
(DuplicateToken): Add.
|
||||
* security.h (check_file_access): Declare.
|
||||
* syscalls.cc (access): Convert path to Windows, check existence
|
||||
and readonly attribute. Call check_file_access instead of acl_access.
|
||||
* security.cc (check_file_access): Create.
|
||||
* sec_acl (acl_access): Delete.
|
||||
|
||||
2003-02-19 Christopher Faylor <cgf@redhat.com>
|
||||
|
||||
* fhandler.cc (fhandler_base::open): Move some filesystem specific
|
||||
|
|
|
@ -307,6 +307,7 @@ wsock_init ()
|
|||
LoadDLLprime (wsock32, wsock_init)
|
||||
LoadDLLprime (ws2_32, wsock_init)
|
||||
|
||||
LoadDLLfunc (AccessCheck, 32, advapi32)
|
||||
LoadDLLfunc (AddAccessAllowedAce, 16, advapi32)
|
||||
LoadDLLfunc (AddAccessDeniedAce, 16, advapi32)
|
||||
LoadDLLfunc (AddAce, 20, advapi32)
|
||||
|
@ -318,6 +319,7 @@ LoadDLLfuncEx (CryptAcquireContextA, 20, advapi32, 1)
|
|||
LoadDLLfuncEx (CryptGenRandom, 12, advapi32, 1)
|
||||
LoadDLLfuncEx (CryptReleaseContext, 8, advapi32, 1)
|
||||
LoadDLLfunc (DeregisterEventSource, 4, advapi32)
|
||||
LoadDLLfunc (DuplicateToken, 12, advapi32)
|
||||
LoadDLLfuncEx (DuplicateTokenEx, 24, advapi32, 1)
|
||||
LoadDLLfunc (EqualSid, 8, advapi32)
|
||||
LoadDLLfunc (GetAce, 12, advapi32)
|
||||
|
|
|
@ -299,9 +299,15 @@ dtable::build_fhandler_from_name (int fd, const char *name, HANDLE handle,
|
|||
if (!pc.exists () && handle)
|
||||
pc.fillin (handle);
|
||||
|
||||
fhandler_base *fh = build_fhandler (fd, pc.get_devn (),
|
||||
pc.return_and_clear_normalized_path (),
|
||||
char *posix_path = pc.return_and_clear_normalized_path ();
|
||||
fhandler_base *fh = build_fhandler (fd, pc.get_devn (), posix_path,
|
||||
pc, pc.get_unitn ());
|
||||
if (pc.issocket ()) /* Only true for files pretending an AF_LOCAL socket. */
|
||||
{
|
||||
fhandler_socket * fhs = (fhandler_socket *) fh;
|
||||
fhs->set_addr_family (AF_LOCAL);
|
||||
fhs->set_sun_path (posix_path);
|
||||
}
|
||||
return fh;
|
||||
}
|
||||
|
||||
|
@ -352,7 +358,7 @@ dtable::build_fhandler (int fd, DWORD dev, char *unix_name,
|
|||
fh = cnew (fhandler_pipe) (dev);
|
||||
break;
|
||||
case FH_SOCKET:
|
||||
if ((fh = cnew (fhandler_socket) ()))
|
||||
if ((fh = cnew (fhandler_socket) (unit)))
|
||||
inc_need_fixup_before ();
|
||||
break;
|
||||
case FH_DISK:
|
||||
|
|
|
@ -385,12 +385,14 @@ class fhandler_socket: public fhandler_base
|
|||
struct _WSAPROTOCOL_INFOA *prot_info_ptr;
|
||||
char *sun_path;
|
||||
int had_connect_or_listen;
|
||||
int unit;
|
||||
|
||||
public:
|
||||
fhandler_socket ();
|
||||
fhandler_socket (int unit);
|
||||
~fhandler_socket ();
|
||||
int get_socket () { return (int) get_handle(); }
|
||||
fhandler_socket * is_socket () { return this; }
|
||||
int get_unit () { return unit; }
|
||||
|
||||
bool saw_shutdown_read () const {return FHISSETF (SHUTRD);}
|
||||
bool saw_shutdown_write () const {return FHISSETF (SHUTWR);}
|
||||
|
|
|
@ -94,8 +94,8 @@ get_inet_addr (const struct sockaddr *in, int inlen,
|
|||
/**********************************************************************/
|
||||
/* fhandler_socket */
|
||||
|
||||
fhandler_socket::fhandler_socket ()
|
||||
: fhandler_base (FH_SOCKET), sun_path (NULL)
|
||||
fhandler_socket::fhandler_socket (int nunit)
|
||||
: fhandler_base (FH_SOCKET), unit (nunit), sun_path (NULL)
|
||||
{
|
||||
set_need_fork_fixup ();
|
||||
prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF,
|
||||
|
@ -309,12 +309,47 @@ fhandler_socket::dup (fhandler_base *child)
|
|||
int __stdcall
|
||||
fhandler_socket::fstat (struct __stat64 *buf, path_conv *pc)
|
||||
{
|
||||
int res = fhandler_base::fstat (buf, pc);
|
||||
int res;
|
||||
if (get_addr_family () == AF_LOCAL && get_sun_path ())
|
||||
{
|
||||
path_conv spc (get_sun_path (),
|
||||
PC_SYM_NOFOLLOW | PC_NULLEMPTY | PC_FULL | PC_POSIX,
|
||||
NULL);
|
||||
fhandler_base *fh = cygheap->fdtab.build_fhandler (-1, FH_DISK,
|
||||
get_sun_path (),
|
||||
spc, 0);
|
||||
if (fh)
|
||||
{
|
||||
res = fh->fstat (buf, &spc);
|
||||
/* Faking Linux like values on top of the file specific values. */
|
||||
if (get_socket_type ()) /* fstat() */
|
||||
{
|
||||
buf->st_dev = 0;
|
||||
buf->st_mode |= S_IRWXU | S_IRWXG | S_IRWXO;
|
||||
buf->st_ino = (ino_t) get_handle ();
|
||||
}
|
||||
buf->st_rdev = buf->st_size = buf->st_blocks = 0;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
res = fhandler_base::fstat (buf, pc);
|
||||
if (!res)
|
||||
{
|
||||
buf->st_mode &= ~_IFMT;
|
||||
buf->st_mode |= _IFSOCK;
|
||||
buf->st_ino = (ino_t) get_handle ();
|
||||
if (get_socket_type ()) /* fstat */
|
||||
{
|
||||
buf->st_ino = (ino_t) get_handle ();
|
||||
buf->st_mode &= ~S_IFMT;
|
||||
buf->st_mode |= S_IFSOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
path_conv spc ("/dev", PC_SYM_NOFOLLOW | PC_NULLEMPTY, NULL);
|
||||
buf->st_dev = spc.volser ();
|
||||
buf->st_ino = (ino_t) get_namehash ();
|
||||
buf->st_mode &= ~S_IRWXO;
|
||||
buf->st_rdev = (get_device () << 16) | get_unit ();
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ details. */
|
|||
|
||||
#include "winsup.h"
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <iphlpapi.h>
|
||||
|
@ -521,8 +522,9 @@ fdsock (int &fd, const char *name, SOCKET soc)
|
|||
else
|
||||
debug_printf ("not setting socket inheritance since winsock2_active %d",
|
||||
winsock2_active);
|
||||
fhandler_socket *fh =
|
||||
(fhandler_socket *) cygheap->fdtab.build_fhandler (fd, FH_SOCKET, name);
|
||||
fhandler_socket *fh = (fhandler_socket *)
|
||||
cygheap->fdtab.build_fhandler (fd, FH_SOCKET, name, NULL,
|
||||
tolower (name[5]) - 'a');
|
||||
if (!fh)
|
||||
return NULL;
|
||||
fh->set_io_handle ((HANDLE) soc);
|
||||
|
|
|
@ -799,10 +799,8 @@ out:
|
|||
set_has_buggy_open (strcmp (fs.name, "SUNWNFS") == 0);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
if (issocket ())
|
||||
devn = FH_SOCKET;
|
||||
#endif
|
||||
|
||||
if (!(opt & PC_FULL))
|
||||
{
|
||||
|
@ -954,7 +952,10 @@ get_devn (const char *name, int &unit)
|
|||
devn = FH_PIPEW;
|
||||
else if (deveq ("tcp") || deveq ("udp") || deveq ("streamsocket")
|
||||
|| deveq ("dgsocket"))
|
||||
devn = FH_SOCKET;
|
||||
{
|
||||
devn = FH_SOCKET;
|
||||
unit = tolower (*name) - 'a';
|
||||
}
|
||||
|
||||
return devn;
|
||||
}
|
||||
|
@ -1118,6 +1119,12 @@ win32_device_name (const char *src_path, char *win32_path,
|
|||
return false;
|
||||
switch (devn)
|
||||
{
|
||||
case FH_SOCKET:
|
||||
char *c;
|
||||
strcpy (win32_path, src_path);
|
||||
while (c = strchr (win32_path, '/'))
|
||||
*c = '\\';
|
||||
break;
|
||||
case FH_RANDOM:
|
||||
__small_sprintf (win32_path, devfmt, unit == 8 ? "" : "u");
|
||||
break;
|
||||
|
|
|
@ -413,69 +413,6 @@ getacl (const char *file, DWORD attr, int nentries, __aclent32_t *aclbufp)
|
|||
return pos;
|
||||
}
|
||||
|
||||
int
|
||||
acl_access (const char *path, int flags)
|
||||
{
|
||||
__aclent32_t acls[MAX_ACL_ENTRIES];
|
||||
int cnt;
|
||||
|
||||
if ((cnt = acl32 (path, GETACL, MAX_ACL_ENTRIES, acls)) < 1)
|
||||
return -1;
|
||||
|
||||
/* Only check existence. */
|
||||
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 token groups
|
||||
*/
|
||||
cygsid owner;
|
||||
struct passwd *pw;
|
||||
|
||||
if ((pw = internal_getpwuid (acls[i].a_id)) != NULL
|
||||
&& owner.getfrompw (pw)
|
||||
&& internal_getgroups (0, NULL, &owner) > 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case GROUP_OBJ:
|
||||
case GROUP:
|
||||
if (acls[i].a_id != myself->gid)
|
||||
{
|
||||
cygsid group;
|
||||
struct __group32 *gr = NULL;
|
||||
|
||||
if ((gr = internal_getgrgid (acls[i].a_id)) != NULL
|
||||
&& group.getfromgr (gr)
|
||||
&& internal_getgroups (0, NULL, &group) > 0)
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
acl_worker (const char *path, int cmd, int nentries, __aclent32_t *aclbufp,
|
||||
|
|
|
@ -1918,3 +1918,54 @@ set_file_attribute (int use_ntsec, const char *file, int attribute)
|
|||
return set_file_attribute (use_ntsec, file,
|
||||
myself->uid, myself->gid, attribute);
|
||||
}
|
||||
|
||||
int
|
||||
check_file_access (const char *fn, int flags)
|
||||
{
|
||||
int ret = -1;
|
||||
char sd_buf[4096];
|
||||
DWORD sd_size = sizeof sd_buf;
|
||||
PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;
|
||||
HANDLE hToken, hIToken;
|
||||
BOOL status;
|
||||
char pbuf[sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES)];
|
||||
DWORD desired = 0, granted, plength = sizeof pbuf;
|
||||
static GENERIC_MAPPING NO_COPY mapping = { FILE_GENERIC_READ,
|
||||
FILE_GENERIC_WRITE,
|
||||
FILE_GENERIC_EXECUTE,
|
||||
FILE_ALL_ACCESS };
|
||||
if (read_sd (fn, psd, &sd_size) <= 0)
|
||||
goto done;
|
||||
|
||||
if (cygheap->user.issetuid ())
|
||||
hToken = cygheap->user.token;
|
||||
else if (!OpenProcessToken (hMainProc, TOKEN_DUPLICATE, &hToken))
|
||||
{
|
||||
__seterrno ();
|
||||
goto done;
|
||||
}
|
||||
if (!(status = DuplicateToken (hToken, SecurityIdentification, &hIToken)))
|
||||
__seterrno ();
|
||||
if (hToken != cygheap->user.token)
|
||||
CloseHandle (hToken);
|
||||
if (!status)
|
||||
goto done;
|
||||
|
||||
if (flags & R_OK)
|
||||
desired |= FILE_READ_DATA;
|
||||
if (flags & W_OK)
|
||||
desired |= FILE_WRITE_DATA;
|
||||
if (flags & X_OK)
|
||||
desired |= FILE_EXECUTE;
|
||||
if (!AccessCheck (psd, hIToken, desired, &mapping,
|
||||
(PPRIVILEGE_SET) pbuf, &plength, &granted, &status))
|
||||
__seterrno ();
|
||||
else if (!status)
|
||||
set_errno (EACCES);
|
||||
else
|
||||
ret = 0;
|
||||
CloseHandle (hIToken);
|
||||
done:
|
||||
debug_printf ("flags %x, ret %d", flags, ret);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -225,6 +225,7 @@ LONG __stdcall read_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, LPDWORD sd
|
|||
LONG __stdcall write_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_size);
|
||||
BOOL __stdcall add_access_allowed_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
|
||||
BOOL __stdcall add_access_denied_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
|
||||
int __stdcall check_file_access (const char *, int);
|
||||
|
||||
void set_security_attribute (int attribute, PSECURITY_ATTRIBUTES psa,
|
||||
void *sd_buf, DWORD sd_buf_size);
|
||||
|
|
|
@ -1016,7 +1016,7 @@ fstat64 (int fd, struct __stat64 *buf)
|
|||
path_conv pc (cfd->get_win32_name (), PC_SYM_NOFOLLOW);
|
||||
memset (buf, 0, sizeof (struct __stat64));
|
||||
res = cfd->fstat (buf, &pc);
|
||||
if (!res)
|
||||
if (!res && cfd->get_device () != FH_SOCKET)
|
||||
{
|
||||
if (!buf->st_ino)
|
||||
buf->st_ino = hash_path_name (0, cfd->get_win32_name ());
|
||||
|
@ -1106,7 +1106,7 @@ stat_worker (const char *name, struct __stat64 *buf, int nofollow,
|
|||
pc, (DWORD) real_path);
|
||||
memset (buf, 0, sizeof (*buf));
|
||||
res = fh->fstat (buf, pc);
|
||||
if (!res)
|
||||
if (!res && fh->get_device () != FH_SOCKET)
|
||||
{
|
||||
if (!buf->st_ino)
|
||||
buf->st_ino = hash_path_name (0, fh->get_win32_name ());
|
||||
|
@ -1163,8 +1163,6 @@ cygwin_lstat (const char *name, struct __stat32 *buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
extern int acl_access (const char *, int);
|
||||
|
||||
extern "C" int
|
||||
access (const char *fn, int flags)
|
||||
{
|
||||
|
@ -1176,11 +1174,33 @@ access (const char *fn, int flags)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (allow_ntsec)
|
||||
return acl_access (fn, flags);
|
||||
path_conv real_path (fn, PC_SYM_FOLLOW | PC_FULL, stat_suffixes);
|
||||
if (real_path.error)
|
||||
{
|
||||
set_errno (real_path.error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!real_path.exists ())
|
||||
{
|
||||
set_errno (ENOENT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(flags & (R_OK | W_OK | X_OK)))
|
||||
return 0;
|
||||
|
||||
if (real_path.has_attribute (FILE_ATTRIBUTE_READONLY) && (flags & W_OK))
|
||||
{
|
||||
set_errno (EACCES);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (real_path.has_acls () && allow_ntsec)
|
||||
return check_file_access (real_path, flags);
|
||||
|
||||
struct __stat64 st;
|
||||
int r = stat_worker (fn, &st, 0);
|
||||
int r = stat_worker (real_path, &st, 0);
|
||||
if (r)
|
||||
return -1;
|
||||
r = -1;
|
||||
|
|
Loading…
Reference in New Issue