* 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:
parent
e2c248c18b
commit
e859706578
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 (), '\\');
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue