* 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:
Corinna Vinschen 2003-02-21 14:29:18 +00:00
parent d05ef21d4f
commit cf762b08cf
11 changed files with 180 additions and 85 deletions

View File

@ -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

View File

@ -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)

View File

@ -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:

View File

@ -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);}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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;
}

View File

@ -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);

View File

@ -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;