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.
+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
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)
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)
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;
}
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:
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);}
/**********************************************************************/
/* 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,
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;
}
#include "winsup.h"
#include <errno.h>
+#include <ctype.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <iphlpapi.h>
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);
set_has_buggy_open (strcmp (fs.name, "SUNWNFS") == 0);
}
}
-#if 0
if (issocket ())
devn = FH_SOCKET;
-#endif
if (!(opt & PC_FULL))
{
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;
}
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;
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,
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;
+}
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);
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 ());
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 ());
return ret;
}
-extern int acl_access (const char *, int);
-
extern "C" int
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;