* autoload.cc (NtCreateFile): Add.

* dir.cc (mkdir): Change set_file_attribute call to indicate that
	NT security isn't used.
	* fhandler.cc (fhandler_base::open_9x): New method, created from
	fhandler_base::open.
	(fhandler_base::open): Rearrange to use NtCreateFile instead of
	CreateFile.
	* fhandler.h (enum query_state): Redefine query_null_access to
	query_stat_control.  query_null_access isn't allowed in NtCreateFile.
	(fhandler_base::open_9x): Declare.
	* fhandler_disk_file.cc (fhandler_base::fstat_fs): Use
	query_stat_control first, query_read_control if that fails.
	(fhandler_disk_file::fchmod): Call enable_restore_privilege before
	trying to open for query_write_control.  Don't fall back to
	opening for query_read_control.
	(fhandler_disk_file::fchown): Ditto.
	(fhandler_disk_file::facl):  Only request restore privilege and query
	access necessary for given cmd.
	* fhandler_raw.cc (fhandler_dev_raw::open): Call fhandler_base::open
	instead of opening device here.
	* ntdll.h (NtCreateFile): Declare.
	* path.cc (symlink_worker): Change set_file_attribute call to indicate
	that NT security isn't used.
	* sec_acl.cc (getacl): Fix bracketing.
	* sec_helper.cc (enable_restore_privilege): New function.
	* security.cc (str2buf2uni_cat): New function.
	(write_sd): Don't request restore permission here.
	* security.h (set_process_privileges): Drop stale declaration.
	(str2buf2uni): Declare.
	(str2buf2uni_cat): Declare.
	(enable_restore_privilege): Declare.
	* syscalls.cc (fchown32): Return immediate success on 9x.
This commit is contained in:
Corinna Vinschen 2004-04-16 21:22:13 +00:00
parent e2c248c18b
commit e859706578
14 changed files with 293 additions and 144 deletions

View File

@ -1,3 +1,38 @@
2004-04-16 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc (NtCreateFile): Add.
* dir.cc (mkdir): Change set_file_attribute call to indicate that
NT security isn't used.
* fhandler.cc (fhandler_base::open_9x): New method, created from
fhandler_base::open.
(fhandler_base::open): Rearrange to use NtCreateFile instead of
CreateFile.
* fhandler.h (enum query_state): Redefine query_null_access to
query_stat_control. query_null_access isn't allowed in NtCreateFile.
(fhandler_base::open_9x): Declare.
* fhandler_disk_file.cc (fhandler_base::fstat_fs): Use
query_stat_control first, query_read_control if that fails.
(fhandler_disk_file::fchmod): Call enable_restore_privilege before
trying to open for query_write_control. Don't fall back to
opening for query_read_control.
(fhandler_disk_file::fchown): Ditto.
(fhandler_disk_file::facl): Only request restore privilege and query
access necessary for given cmd.
* fhandler_raw.cc (fhandler_dev_raw::open): Call fhandler_base::open
instead of opening device here.
* ntdll.h (NtCreateFile): Declare.
* path.cc (symlink_worker): Change set_file_attribute call to indicate
that NT security isn't used.
* sec_acl.cc (getacl): Fix bracketing.
* sec_helper.cc (enable_restore_privilege): New function.
* security.cc (str2buf2uni_cat): New function.
(write_sd): Don't request restore permission here.
* security.h (set_process_privileges): Drop stale declaration.
(str2buf2uni): Declare.
(str2buf2uni_cat): Declare.
(enable_restore_privilege): Declare.
* syscalls.cc (fchown32): Return immediate success on 9x.
2004-04-15 Christopher Faylor <cgf@alum.bu.edu> 2004-04-15 Christopher Faylor <cgf@alum.bu.edu>
* autoload.cc (dll_chain1): Rename to dll_chain. Remove old dll_chain * autoload.cc (dll_chain1): Rename to dll_chain. Remove old dll_chain

View File

@ -375,6 +375,7 @@ LoadDLLfunc (NetUserGetGroups, 28, netapi32)
LoadDLLfunc (NetUserGetInfo, 16, netapi32) LoadDLLfunc (NetUserGetInfo, 16, netapi32)
LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32) LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32)
LoadDLLfuncEx (NtCreateFile, 44, ntdll, 1)
LoadDLLfuncEx (NtCreateToken, 52, ntdll, 1) LoadDLLfuncEx (NtCreateToken, 52, ntdll, 1)
LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1) LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1)
LoadDLLfuncEx (NtOpenFile, 24, ntdll, 1) LoadDLLfuncEx (NtOpenFile, 24, ntdll, 1)

View File

@ -284,7 +284,7 @@ mkdir (const char *dir, mode_t mode)
if (CreateDirectoryA (real_dir.get_win32 (), &sa)) if (CreateDirectoryA (real_dir.get_win32 (), &sa))
{ {
if (!allow_ntsec && allow_ntea) if (!allow_ntsec && allow_ntea)
set_file_attribute (real_dir.has_acls (), NULL, real_dir.get_win32 (), set_file_attribute (false, NULL, real_dir.get_win32 (),
S_IFDIR | ((mode & 07777) & ~cygheap->umask)); S_IFDIR | ((mode & 07777) & ~cygheap->umask));
#ifdef HIDDEN_DOT_FILES #ifdef HIDDEN_DOT_FILES
char *c = strrchr (real_dir.get_win32 (), '\\'); char *c = strrchr (real_dir.get_win32 (), '\\');

View File

@ -28,6 +28,8 @@ details. */
#include <assert.h> #include <assert.h>
#include <limits.h> #include <limits.h>
#include <winioctl.h> #include <winioctl.h>
#include <ntdef.h>
#include "ntdll.h"
static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */
@ -425,7 +427,7 @@ done:
/* Open system call handler function. */ /* Open system call handler function. */
int int
fhandler_base::open (int flags, mode_t mode) fhandler_base::open_9x (int flags, mode_t mode)
{ {
int res = 0; int res = 0;
HANDLE x; HANDLE x;
@ -435,7 +437,7 @@ fhandler_base::open (int flags, mode_t mode)
SECURITY_ATTRIBUTES sa = sec_none; SECURITY_ATTRIBUTES sa = sec_none;
security_descriptor sd; security_descriptor sd;
syscall_printf ("(%s, %p) query_open %d", get_win32_name (), flags, query_open ()); syscall_printf ("(%s, %p)", get_win32_name (), flags);
if (get_win32_name () == NULL) if (get_win32_name () == NULL)
{ {
@ -443,34 +445,12 @@ fhandler_base::open (int flags, mode_t mode)
goto done; goto done;
} }
switch (query_open ()) if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
{ access = GENERIC_READ;
case query_null_access: else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
access = 0; access = GENERIC_WRITE;
break; else
case query_read_control: access = GENERIC_READ | GENERIC_WRITE;
access = READ_CONTROL;
break;
case query_write_control:
access = READ_CONTROL | WRITE_OWNER | WRITE_DAC;
break;
default:
if (get_major () == DEV_TAPE_MAJOR)
access = GENERIC_READ | GENERIC_WRITE;
else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
access = GENERIC_READ;
else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
access = GENERIC_WRITE;
else
access = GENERIC_READ | GENERIC_WRITE;
break;
}
/* Allow reliable lseek on disk devices. */
if (get_major () == DEV_FLOPPY_MAJOR)
access |= GENERIC_READ;
/* FIXME: O_EXCL handling? */
if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY)) if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY))
{ {
@ -508,16 +488,6 @@ fhandler_base::open (int flags, mode_t mode)
} }
#endif #endif
/* CreateFile() with dwDesiredAccess == 0 when called on remote
share returns some handle, even if file doesn't exist. This code
works around this bug. */
if (query_open () && isremote () &&
creation_distribution == OPEN_EXISTING && !pc.exists ())
{
set_errno (ENOENT);
goto done;
}
/* If mode has no write bits set, we set the R/O attribute. */ /* If mode has no write bits set, we set the R/O attribute. */
if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH))) if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
file_attributes |= FILE_ATTRIBUTE_READONLY; file_attributes |= FILE_ATTRIBUTE_READONLY;
@ -564,6 +534,162 @@ done:
return res; return res;
} }
/* Open system call handler function. */
int
fhandler_base::open (int flags, mode_t mode)
{
if (!wincap.is_winnt ())
return fhandler_base::open_9x (flags, mode);
int res = 0;
HANDLE x;
ULONG file_attributes = 0;
ULONG shared = wincap.shared ();
ULONG create_disposition;
ULONG create_options;
SECURITY_ATTRIBUTES sa = sec_none;
security_descriptor sd;
UNICODE_STRING upath;
WCHAR wpath[CYG_MAX_PATH + 10];
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
NTSTATUS status;
syscall_printf ("(%s, %p)", get_win32_name (), flags);
if (get_win32_name () == NULL)
{
set_errno (ENOENT);
goto done;
}
if (get_win32_name ()[0] == '\\')
{
if (get_win32_name ()[1] == '\\')
{
str2buf2uni (upath, wpath, "\\??\\UNC");
str2buf2uni_cat (upath, get_win32_name () + 1);
}
else
str2buf2uni (upath, wpath, get_win32_name ());
}
else
{
str2buf2uni (upath, wpath, "\\??\\");
str2buf2uni_cat (upath, get_win32_name ());
}
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
sa.lpSecurityDescriptor, NULL);
switch (query_open ())
{
case query_read_control:
access = READ_CONTROL;
create_options = FILE_OPEN_FOR_BACKUP_INTENT;
break;
case query_stat_control:
access = READ_CONTROL | FILE_READ_ATTRIBUTES;
create_options = FILE_OPEN_FOR_BACKUP_INTENT;
break;
case query_write_control:
access = READ_CONTROL | WRITE_OWNER | WRITE_DAC;
create_options = FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY;
break;
default:
create_options = 0;
if (get_major () == DEV_TAPE_MAJOR && (flags & O_TEXT))
{
/* O_TEXT is used to indicate write-through on tape devices */
create_options |= FILE_WRITE_THROUGH;
flags &= ~O_TEXT;
}
if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
access = GENERIC_READ;
else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
access = GENERIC_WRITE;
else
access = GENERIC_READ | GENERIC_WRITE;
/* Allow reliable lseek on disk devices. */
if (get_major () == DEV_FLOPPY_MAJOR)
access |= GENERIC_READ;
else if (get_major () != DEV_SERIAL_MAJOR)
{
create_options |= FILE_SYNCHRONOUS_IO_NONALERT;
access |= SYNCHRONIZE;
}
break;
}
if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY))
{
if (flags & O_CREAT)
create_disposition = FILE_SUPERSEDE;
else
create_disposition = FILE_OVERWRITE;
}
else if (flags & O_CREAT)
create_disposition = FILE_OPEN_IF;
else
create_disposition = FILE_OPEN;
if ((flags & O_EXCL) && (flags & O_CREAT))
create_disposition = FILE_CREATE;
if (flags & O_APPEND)
append_mode (true);
if (flags & O_CREAT && get_device () == FH_FS)
{
file_attributes = FILE_ATTRIBUTE_NORMAL;
/* If mode has no write bits set, we set the R/O attribute. */
if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
file_attributes |= FILE_ATTRIBUTE_READONLY;
#ifdef HIDDEN_DOT_FILES
char *c = strrchr (get_win32_name (), '\\');
if ((c && c[1] == '.') || *get_win32_name () == '.')
file_attributes |= FILE_ATTRIBUTE_HIDDEN;
#endif
/* If the file should actually be created and ntsec is on,
set files attributes. */
if (allow_ntsec && has_acls ())
{
set_security_attribute (mode, &sa, sd);
attr.SecurityDescriptor = sa.lpSecurityDescriptor;
}
}
status = NtCreateFile (&x, access, &attr, &io, NULL, file_attributes, shared,
create_disposition, create_options, NULL, 0);
if (!NT_SUCCESS (status))
{
if (!wincap.can_open_directories () && pc.isdir ())
{
if (flags & (O_CREAT | O_EXCL) == (O_CREAT | O_EXCL))
set_errno (EEXIST);
else if (flags & (O_WRONLY | O_RDWR))
set_errno (EISDIR);
else
nohandle (true);
}
__seterrno_from_win_error (RtlNtStatusToDosError (status));
if (!nohandle ())
goto done;
}
syscall_printf ("%x = NtCreateFile "
"(%p, %x, %s, io, NULL, %x, %x, %x, %x, NULL, 0)",
status, x, access, get_win32_name (), file_attributes, shared,
create_disposition, create_options);
set_io_handle (x);
set_flags (flags, pc.binmode ());
res = 1;
set_open_status ();
done:
syscall_printf ("%d = fhandler_base::open (%s, %p)", res, get_win32_name (),
flags);
return res;
}
/* states: /* states:
open buffer in binary mode? Just do the read. open buffer in binary mode? Just do the read.

View File

@ -63,8 +63,8 @@ enum bg_check_types
enum query_state { enum query_state {
no_query = 0, no_query = 0,
query_null_access = 1, query_read_control = 1,
query_read_control = 2, query_stat_control = 2,
query_write_control = 3 query_write_control = 3
}; };
@ -226,6 +226,7 @@ class fhandler_base
void fork_fixup (HANDLE parent, HANDLE &h, const char *name); void fork_fixup (HANDLE parent, HANDLE &h, const char *name);
virtual bool need_fixup_before () const {return false;} virtual bool need_fixup_before () const {return false;}
int open_9x (int flags, mode_t mode = 0);
virtual int open (int flags, mode_t mode = 0); virtual int open (int flags, mode_t mode = 0);
int open_fs (int flags, mode_t mode = 0); int open_fs (int flags, mode_t mode = 0);
virtual int close (); virtual int close ();

View File

@ -174,16 +174,16 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
then just do a "query open" as it is apparently much faster. */ then just do a "query open" as it is apparently much faster. */
if (pc.exec_state () != dont_know_if_executable) if (pc.exec_state () != dont_know_if_executable)
{ {
query_open (query_read_control);
if (pc.fs_is_fat () && !strpbrk (get_win32_name (), "?*|<>")) if (pc.fs_is_fat () && !strpbrk (get_win32_name (), "?*|<>"))
return fstat_by_name (buf); return fstat_by_name (buf);
query_open (query_stat_control);
} }
if (!(oret = open_fs (open_flags, 0)) && get_errno () == EACCES) if (!(oret = open_fs (open_flags, 0)) && get_errno () == EACCES)
{ {
/* If we couldn't open the file, try a query open with no permissions. /* If we couldn't open the file, try a query open with no permissions.
This allows us to determine *some* things about the file, at least. */ This allows us to determine *some* things about the file, at least. */
pc.set_exec (0); pc.set_exec (0);
query_open (query_null_access); query_open (query_read_control);
oret = open_fs (open_flags, 0); oret = open_fs (open_flags, 0);
} }
@ -378,15 +378,15 @@ fhandler_disk_file::fchmod (mode_t mode)
if (pc.is_fs_special ()) if (pc.is_fs_special ())
return chmod_device (pc, mode); return chmod_device (pc, mode);
if (!get_io_handle ()) if (wincap.has_security ())
{ {
query_open (query_write_control); enable_restore_privilege ();
if (!(oret = open_fs (O_BINARY, 0))) if (!get_io_handle ())
{ {
query_open (query_read_control); query_open (query_write_control);
if (!(oret = open_fs (O_BINARY, 0))) if (!(oret = open_fs (O_BINARY, 0)))
return -1; return -1;
} }
} }
if (!allow_ntsec && allow_ntea) /* Not necessary when manipulating SD. */ if (!allow_ntsec && allow_ntea) /* Not necessary when manipulating SD. */
@ -423,15 +423,13 @@ int __stdcall
fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid) fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid)
{ {
int oret = 0; int oret = 0;
enable_restore_privilege ();
if (!get_io_handle ()) if (!get_io_handle ())
{ {
query_open (query_write_control); query_open (query_write_control);
if (!(oret = open_fs (O_BINARY, 0))) if (!(oret = open_fs (O_BINARY, 0)))
{ return -1;
query_open (query_read_control);
if (!(oret = open_fs (O_BINARY, 0)))
return -1;
}
} }
mode_t attrib = 0; mode_t attrib = 0;
@ -460,17 +458,6 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp)
int res = -1; int res = -1;
int oret = 0; int oret = 0;
if (!get_io_handle ())
{
query_open (query_write_control);
if (!(oret = open_fs (O_BINARY, 0)))
{
query_open (query_read_control);
if (!(oret = open_fs (O_BINARY, 0)))
return -1;
}
}
if (!pc.has_acls () || !allow_ntsec) if (!pc.has_acls () || !allow_ntsec)
{ {
switch (cmd) switch (cmd)
@ -485,30 +472,50 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp)
set_errno(EFAULT); set_errno(EFAULT);
else if (nentries < MIN_ACL_ENTRIES) else if (nentries < MIN_ACL_ENTRIES)
set_errno (ENOSPC); set_errno (ENOSPC);
else if (!fstat_by_handle (&st)) else
{ {
aclbufp[0].a_type = USER_OBJ; if (!get_io_handle ())
aclbufp[0].a_id = st.st_uid; {
aclbufp[0].a_perm = (st.st_mode & S_IRWXU) >> 6; query_open (query_read_control);
aclbufp[1].a_type = GROUP_OBJ; if (!(oret = open_fs (O_BINARY, 0)))
aclbufp[1].a_id = st.st_gid; return -1;
aclbufp[1].a_perm = (st.st_mode & S_IRWXG) >> 3; }
aclbufp[2].a_type = OTHER_OBJ; if (!fstat_by_handle (&st))
aclbufp[2].a_id = ILLEGAL_GID; {
aclbufp[2].a_perm = st.st_mode & S_IRWXO; aclbufp[0].a_type = USER_OBJ;
aclbufp[3].a_type = CLASS_OBJ; aclbufp[0].a_id = st.st_uid;
aclbufp[3].a_id = ILLEGAL_GID; aclbufp[0].a_perm = (st.st_mode & S_IRWXU) >> 6;
aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO; aclbufp[1].a_type = GROUP_OBJ;
res = MIN_ACL_ENTRIES; aclbufp[1].a_id = st.st_gid;
aclbufp[1].a_perm = (st.st_mode & S_IRWXG) >> 3;
aclbufp[2].a_type = OTHER_OBJ;
aclbufp[2].a_id = ILLEGAL_GID;
aclbufp[2].a_perm = st.st_mode & S_IRWXO;
aclbufp[3].a_type = CLASS_OBJ;
aclbufp[3].a_id = ILLEGAL_GID;
aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO;
res = MIN_ACL_ENTRIES;
}
} }
break; break;
case GETACLCNT: case GETACLCNT:
res = MIN_ACL_ENTRIES; res = MIN_ACL_ENTRIES;
break; break;
default:
set_errno (EINVAL);
break;
} }
} }
else else
{ {
if (cmd == SETACL)
enable_restore_privilege ();
if (!get_io_handle ())
{
query_open (cmd == SETACL ? query_write_control : query_read_control);
if (!(oret = open_fs (O_BINARY, 0)))
return -1;
}
switch (cmd) switch (cmd)
{ {
case SETACL: case SETACL:

View File

@ -144,41 +144,16 @@ fhandler_dev_raw::open (int flags, mode_t)
flags &= ~(O_CREAT | O_TRUNC); flags &= ~(O_CREAT | O_TRUNC);
flags |= O_BINARY; flags |= O_BINARY;
DWORD access = GENERIC_READ | SYNCHRONIZE;
if (get_major () == DEV_TAPE_MAJOR if (get_major () == DEV_TAPE_MAJOR
|| (flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY || (flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY
|| (flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDWR) || (flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDWR)
access |= GENERIC_WRITE; flags = ((flags & ~(O_WRONLY | O_RDWR)) | O_RDWR);
extern void str2buf2uni (UNICODE_STRING &, WCHAR *, const char *); int res = fhandler_base::open (flags, 0);
UNICODE_STRING dev; if (res && devbufsiz > 1L)
WCHAR devname[CYG_MAX_PATH + 1];
str2buf2uni (dev, devname, get_win32_name ());
OBJECT_ATTRIBUTES attr;
ULONG options = FILE_SYNCHRONOUS_IO_NONALERT;
/* The O_TEXT flag is used to indicate write-through on tape devices */
if (get_major () == DEV_TAPE_MAJOR && (flags & O_TEXT))
options |= FILE_WRITE_THROUGH;
flags &= ~O_TEXT;
InitializeObjectAttributes (&attr, &dev, OBJ_CASE_INSENSITIVE, NULL, NULL);
HANDLE h;
IO_STATUS_BLOCK io;
NTSTATUS status = NtOpenFile (&h, access, &attr, &io, 0 /* excl. access */,
options);
if (!NT_SUCCESS (status))
{
__seterrno_from_win_error (RtlNtStatusToDosError (status));
return 0;
}
set_io_handle (h);
set_flags ((flags & ~O_TEXT) | O_BINARY);
if (devbufsiz > 1L)
devbuf = new char [devbufsiz]; devbuf = new char [devbufsiz];
return 1; return res;
} }
int int

View File

@ -389,6 +389,9 @@ typedef struct _OBJECT_NAME_INFORMATION
standard Win32 header. */ standard Win32 header. */
extern "C" extern "C"
{ {
NTSTATUS NTAPI NtCreateFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG,
ULONG, ULONG, PVOID, ULONG);
NTSTATUS NTAPI NtCreateToken (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, NTSTATUS NTAPI NtCreateToken (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
TOKEN_TYPE, PLUID, PLARGE_INTEGER, PTOKEN_USER, TOKEN_TYPE, PLUID, PLARGE_INTEGER, PTOKEN_USER,
PTOKEN_GROUPS, PTOKEN_PRIVILEGES, PTOKEN_OWNER, PTOKEN_GROUPS, PTOKEN_PRIVILEGES, PTOKEN_OWNER,

View File

@ -2648,8 +2648,7 @@ symlink_worker (const char *topath, const char *frompath, bool use_winsym,
{ {
CloseHandle (h); CloseHandle (h);
if (!allow_ntsec && allow_ntea) if (!allow_ntsec && allow_ntea)
set_file_attribute (win32_path.has_acls (), NULL, set_file_attribute (false, NULL, win32_path.get_win32 (),
win32_path.get_win32 (),
S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO); S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
DWORD attr = use_winsym ? FILE_ATTRIBUTE_READONLY DWORD attr = use_winsym ? FILE_ATTRIBUTE_READONLY

View File

@ -261,7 +261,7 @@ getacl (HANDLE handle, const char *file, DWORD attr, int nentries,
{ {
security_descriptor sd; security_descriptor sd;
if (!handle || get_nt_object_security (handle, SE_FILE_OBJECT, sd) if ((!handle || get_nt_object_security (handle, SE_FILE_OBJECT, sd))
&& read_sd (file, sd) <= 0) && read_sd (file, sd) <= 0)
{ {
debug_printf ("read_sd %E"); debug_printf ("read_sd %E");

View File

@ -375,6 +375,20 @@ out:
return ret; return ret;
} }
/* Helper function to set the SE_RESTORE_NAME privilege once. */
void
enable_restore_privilege ()
{
static int NO_COPY saved_res;
bool issetuid = cygheap->user.issetuid ();
if (!saved_res || issetuid)
{
int res = 2 + set_process_privilege (SE_RESTORE_NAME, true, issetuid);
if (!issetuid)
saved_res = res;
}
}
/* /*
* Function to return a common SECURITY_DESCRIPTOR * that * Function to return a common SECURITY_DESCRIPTOR * that
* allows all access. * allows all access.

View File

@ -165,6 +165,16 @@ str2buf2uni (UNICODE_STRING &tgt, WCHAR *buf, const char *srcstr)
sys_mbstowcs (buf, srcstr, tgt.MaximumLength); sys_mbstowcs (buf, srcstr, tgt.MaximumLength);
} }
void
str2buf2uni_cat (UNICODE_STRING &tgt, const char *srcstr)
{
DWORD len = strlen (srcstr) * sizeof (WCHAR);
sys_mbstowcs (tgt.Buffer + tgt.Length / sizeof (WCHAR), srcstr,
len + tgt.MaximumLength);
tgt.Length += len;
tgt.MaximumLength += len;
}
#if 0 /* unused */ #if 0 /* unused */
static void static void
lsa2wchar (WCHAR *tgt, LSA_UNICODE_STRING &src, int size) lsa2wchar (WCHAR *tgt, LSA_UNICODE_STRING &src, int size)
@ -1119,38 +1129,9 @@ read_sd (const char *file, security_descriptor &sd)
LONG LONG
write_sd (HANDLE fh, const char *file, security_descriptor &sd) write_sd (HANDLE fh, const char *file, security_descriptor &sd)
{ {
/* Try turning privilege on, may not have WRITE_OWNER or WRITE_DAC access.
Must have privilege to set different owner, else BackupWrite misbehaves */
static int NO_COPY saved_res; /* 0: never, 1: failed, 2 & 3: OK */
int res;
if (!saved_res || cygheap->user.issetuid ())
{
res = 2 + set_process_privilege (SE_RESTORE_NAME, true,
cygheap->user.issetuid ());
if (!cygheap->user.issetuid ())
saved_res = res;
}
else
res = saved_res;
if (res == 1)
{
BOOL dummy;
cygpsid owner;
if (!GetSecurityDescriptorOwner (sd, (PSID *) &owner, &dummy))
{
__seterrno ();
return -1;
}
if (owner != cygheap->user.sid ())
{
set_errno (EPERM);
return -1;
}
}
NTSTATUS ret = STATUS_SUCCESS; NTSTATUS ret = STATUS_SUCCESS;
int retry = 0; int retry = 0;
res = -1; int res = -1;
for (; retry < 2; ++retry) for (; retry < 2; ++retry)
{ {
if (retry && (fh = CreateFile (file, WRITE_OWNER | WRITE_DAC, if (retry && (fh = CreateFile (file, WRITE_OWNER | WRITE_DAC,

View File

@ -248,7 +248,6 @@ extern bool allow_ntsec;
extern bool allow_smbntsec; extern bool allow_smbntsec;
/* File manipulation */ /* File manipulation */
int __stdcall set_process_privileges ();
int __stdcall get_file_attribute (int, HANDLE, const char *, mode_t *, int __stdcall get_file_attribute (int, HANDLE, const char *, mode_t *,
__uid32_t * = NULL, __gid32_t * = NULL); __uid32_t * = NULL, __gid32_t * = NULL);
int __stdcall set_file_attribute (bool, HANDLE, const char *, int); int __stdcall set_file_attribute (bool, HANDLE, const char *, int);
@ -275,6 +274,10 @@ extern "C" int acl32 (const char *, int, int, __acl32 *);
int getacl (HANDLE, const char *, DWORD, int, __acl32 *); int getacl (HANDLE, const char *, DWORD, int, __acl32 *);
int setacl (HANDLE, const char *, int, __acl32 *); int setacl (HANDLE, const char *, int, __acl32 *);
struct _UNICODE_STRING;
void __stdcall str2buf2uni (_UNICODE_STRING &, WCHAR *, const char *) __attribute__ ((regparm (3)));
void __stdcall str2buf2uni_cat (_UNICODE_STRING &, const char *) __attribute__ ((regparm (2)));
/* Try a subauthentication. */ /* Try a subauthentication. */
HANDLE subauth (struct passwd *pw); HANDLE subauth (struct passwd *pw);
/* Try creating a token directly. */ /* Try creating a token directly. */
@ -289,6 +292,7 @@ bool get_logon_server (const char * domain, char * server, WCHAR *wserver = NULL
/* sec_helper.cc: Security helper functions. */ /* sec_helper.cc: Security helper functions. */
int set_process_privilege (const char *privilege, bool enable = true, bool use_thread = false); int set_process_privilege (const char *privilege, bool enable = true, bool use_thread = false);
void enable_restore_privilege (void);
/* shared.cc: */ /* shared.cc: */
/* Retrieve a security descriptor that allows all access */ /* Retrieve a security descriptor that allows all access */

View File

@ -872,6 +872,9 @@ lchown (const char * name, __uid16_t uid, __gid16_t gid)
extern "C" int extern "C" int
fchown32 (int fd, __uid32_t uid, __gid32_t gid) fchown32 (int fd, __uid32_t uid, __gid32_t gid)
{ {
if (!wincap.has_security ()) // real chown only works on NT
return 0; // return zero (and do nothing) under Windows 9x
cygheap_fdget cfd (fd); cygheap_fdget cfd (fd);
if (cfd < 0) if (cfd < 0)
{ {