* autoload.cc (GetSecurityInfo): Define new autoload function.

(RegQueryInfoKeyA): Ditto.
* fhandler.h (fhandler_virtual::fill_filebuf): Change return type to bool.
(fhandler_proc::fill_filebuf): Ditto.
(fhandler_registry::fill_filebuf): Ditto.
(fhandler_process::fill_filebuf): Ditto.
(fhandler_registry::value_name): Add new member.
(fhandler_registry::close): Add new method.
(fhandler_process::p): Remove member.
* fhandler_proc.cc (fhandler_proc::open): Add set_nohandle after calling
superclass method.  Check return value of fill_filebuf.
(fhandler_proc::fill_filebuf): Change return type to bool.  Add return
statement.
* fhandler_process.cc (fhandler_process::open): Add set_nohandle after calling
superclass method.  Remove references to p.  Check return value of
fill_filebuf.
(fhandler_process::fill_filebuf): Change return type to bool.  Don't use
dereference operator on p.  Add return statement.
(fhandler_process::format_process_stat): Fix typo.
* fhandler_registry.cc: Add static open_key declaration.
(fhandler_registry::exists): Assume path is already normalised.  Try opening
the path as a key in its own right first, before reverting to enumerating
subkeys and values of the parent key.
(fhandler_registry::fstat): Add additional code to return more relevant
information about the registry key/value.
(fhandler_registry::readdir): Explicitly set desired access when opening
registry key.  Remove output of buf from debug_printf format string.
(fhandler_registry::open): Use set_io_handle to store registry key handle.  Set
value_name member.  Move code to read a value from the registry to
fill_filebuf.  Add call to fill_filebuf.
(fhandler_registry::close): New method.
(fhandler_registry::fill_filebuf): Change return type to bool.  Add code to
read a value from registry.
(fhandler_registry::open_key): Make function static.  Use KEY_READ as desired
access unless this is the last path component.  Check the return value of
RegOpenKeyEx for an error instead of hKey.
* fhandler_virtual.cc (fhandler_virtual::lseek): Check the return value of
fill_filebuf.
(fhandler_virtual::open): Remove call to set_nohandle.
(fhandler_virtual::fill_filebuf): Change return type to bool.  Add return
statement.
* security.cc (get_nt_object_attribute): New function.
(get_object_attribute): New function.
* security.h (get_object_attribute): New function declaration.
This commit is contained in:
Christopher Faylor 2002-07-02 01:36:15 +00:00
parent cc81f456ac
commit 74fcdaec20
9 changed files with 508 additions and 153 deletions

View File

@ -1,4 +1,53 @@
2002-07-01 Pierre Humblet <pierre.humblet@ieee.org>
2002-07-02 Christopher January <chris@atomice.net>
* autoload.cc (GetSecurityInfo): Define new autoload function.
(RegQueryInfoKeyA): Ditto.
* fhandler.h (fhandler_virtual::fill_filebuf): Change return type to
bool.
(fhandler_proc::fill_filebuf): Ditto.
(fhandler_registry::fill_filebuf): Ditto.
(fhandler_process::fill_filebuf): Ditto.
(fhandler_registry::value_name): Add new member.
(fhandler_registry::close): Add new method.
(fhandler_process::p): Remove member.
* fhandler_proc.cc (fhandler_proc::open): Add set_nohandle after
calling superclass method. Check return value of fill_filebuf.
(fhandler_proc::fill_filebuf): Change return type to bool. Add return
statement.
* fhandler_process.cc (fhandler_process::open): Add set_nohandle after
calling superclass method. Remove references to p. Check return value
of fill_filebuf.
(fhandler_process::fill_filebuf): Change return type to bool. Don't
use dereference operator on p. Add return statement.
(fhandler_process::format_process_stat): Fix typo.
* fhandler_registry.cc: Add static open_key declaration.
(fhandler_registry::exists): Assume path is already normalised. Try
opening the path as a key in its own right first, before reverting to
enumerating subkeys and values of the parent key.
(fhandler_registry::fstat): Add additional code to return more relevant
information about the registry key/value.
(fhandler_registry::readdir): Explicitly set desired access when
opening registry key. Remove output of buf from debug_printf format
string.
(fhandler_registry::open): Use set_io_handle to store registry key
handle. Set value_name member. Move code to read a value from the
registry to fill_filebuf. Add call to fill_filebuf.
(fhandler_registry::close): New method.
(fhandler_registry::fill_filebuf): Change return type to bool. Add
code to read a value from registry.
(fhandler_registry::open_key): Make function static. Use KEY_READ as
desired access unless this is the last path component. Check the
return value of RegOpenKeyEx for an error instead of hKey.
* fhandler_virtual.cc (fhandler_virtual::lseek): Check the return value
of fill_filebuf.
(fhandler_virtual::open): Remove call to set_nohandle.
(fhandler_virtual::fill_filebuf): Change return type to bool. Add
return statement.
* security.cc (get_nt_object_attribute): New function.
(get_object_attribute): New function.
* security.h (get_object_attribute): New function declaration.
2002-07-01 Pierre Humblet <pierre.humblet@ieee.org>
* syscalls.c (seteuid32): Do not return an error when the token cannot
be created only because of a problem with the gid.

View File

@ -326,6 +326,7 @@ LoadDLLfunc (GetLengthSid, 4, advapi32)
LoadDLLfunc (GetSecurityDescriptorDacl, 16, advapi32)
LoadDLLfunc (GetSecurityDescriptorGroup, 12, advapi32)
LoadDLLfunc (GetSecurityDescriptorOwner, 12, advapi32)
LoadDLLfunc (GetSecurityInfo, 32, advapi32)
LoadDLLfunc (GetSidIdentifierAuthority, 4, advapi32)
LoadDLLfunc (GetSidSubAuthority, 8, advapi32)
LoadDLLfunc (GetSidSubAuthorityCount, 4, advapi32)
@ -358,6 +359,7 @@ LoadDLLfunc (RegLoadKeyA, 12, advapi32)
LoadDLLfunc (RegEnumKeyExA, 32, advapi32)
LoadDLLfunc (RegEnumValueA, 32, advapi32)
LoadDLLfunc (RegOpenKeyExA, 20, advapi32)
LoadDLLfunc (RegQueryInfoKeyA, 48, advapi32)
LoadDLLfunc (RegQueryValueExA, 24, advapi32)
LoadDLLfunc (RegSetValueExA, 24, advapi32)
LoadDLLfunc (RegisterEventSourceA, 8, advapi32)

View File

@ -1090,7 +1090,7 @@ class fhandler_virtual : public fhandler_base
int open (path_conv *, int flags, mode_t mode = 0);
int close (void);
int __stdcall fstat (struct stat *buf, path_conv *pc) __attribute__ ((regparm (3)));
virtual void fill_filebuf ();
virtual bool fill_filebuf ();
};
class fhandler_proc: public fhandler_virtual
@ -1104,11 +1104,13 @@ class fhandler_proc: public fhandler_virtual
int open (path_conv *real_path, int flags, mode_t mode = 0);
int __stdcall fstat (struct __stat64 *buf, path_conv *) __attribute__ ((regparm (3)));
void fill_filebuf ();
bool fill_filebuf ();
};
class fhandler_registry: public fhandler_proc
{
private:
char *value_name;
public:
fhandler_registry ();
int exists();
@ -1120,22 +1122,21 @@ class fhandler_registry: public fhandler_proc
int open (path_conv *real_path, int flags, mode_t mode = 0);
int __stdcall fstat (struct __stat64 *buf, path_conv *) __attribute__ ((regparm (3)));
HKEY open_key(const char *name, REGSAM access = KEY_READ, bool isValue = false);
void fill_filebuf ();
bool fill_filebuf ();
int close (void);
};
class pinfo;
class fhandler_process: public fhandler_proc
{
pid_t pid;
pinfo *p;
public:
fhandler_process ();
int exists();
struct dirent *readdir (DIR *);
int open (path_conv *real_path, int flags, mode_t mode = 0);
int __stdcall fstat (struct __stat64 *buf, path_conv *) __attribute__ ((regparm (3)));
void fill_filebuf ();
bool fill_filebuf ();
};
typedef union

View File

@ -216,6 +216,8 @@ fhandler_proc::open (path_conv *pc, int flags, mode_t mode)
if (!res)
goto out;
set_nohandle (true);
const char *path;
path = get_name () + proc_len;
@ -291,7 +293,11 @@ fhandler_proc::open (path_conv *pc, int flags, mode_t mode)
}
fileid = proc_file_no;
fill_filebuf ();
if (!fill_filebuf ())
{
res = 0;
goto out;
}
if (flags & O_APPEND)
position = filesize;
@ -307,7 +313,7 @@ out:
return res;
}
void
bool
fhandler_proc::fill_filebuf ()
{
switch (fileid)
@ -361,6 +367,7 @@ fhandler_proc::fill_filebuf ()
break;
}
}
return true;
}
static

View File

@ -41,7 +41,8 @@ static const int PROCESS_CTTY = 11;
static const int PROCESS_STAT = 12;
static const int PROCESS_STATM = 13;
static const char *process_listing[] = {
static const char * const process_listing[] =
{
".",
"..",
"ppid",
@ -59,14 +60,17 @@ static const char *process_listing[] = {
NULL
};
static const int PROCESS_LINK_COUNT = (sizeof(process_listing) / sizeof(const char *)) - 1;
static const int PROCESS_LINK_COUNT =
(sizeof(process_listing) / sizeof(const char *)) - 1;
static off_t format_process_stat (_pinfo *p, char *destbuf, size_t maxsize);
static off_t format_process_status (_pinfo *p, char *destbuf, size_t maxsize);
static off_t format_process_statm (_pinfo *p, char *destbuf, size_t maxsize);
static int get_process_state (DWORD dwProcessId);
static bool get_mem_values(DWORD dwProcessId, unsigned long *vmsize, unsigned long *vmrss, unsigned long *vmtext,
unsigned long *vmdata, unsigned long *vmlib, unsigned long *vmshare);
static bool get_mem_values(DWORD dwProcessId, unsigned long *vmsize,
unsigned long *vmrss, unsigned long *vmtext,
unsigned long *vmdata, unsigned long *vmlib,
unsigned long *vmshare);
/* Returns 0 if path doesn't exist, >0 if path is a directory,
* <0 if path is a file.
@ -159,6 +163,8 @@ fhandler_process::open (path_conv *pc, int flags, mode_t mode)
if (!res)
goto out;
set_nohandle (true);
const char *path;
path = get_name () + proc_len + 1;
pid = atoi (path);
@ -215,25 +221,17 @@ fhandler_process::open (path_conv *pc, int flags, mode_t mode)
goto out;
}
{
pinfo p (pid);
if (!p)
{
set_errno (ENOENT);
res = 0;
goto out;
}
fileid = process_file_no;
this->p = &p;
fill_filebuf ();
if (!fill_filebuf ())
{
res = 0;
goto out;
}
if (flags & O_APPEND)
position = filesize;
else
position = 0;
this->p = NULL;
}
success:
res = 1;
@ -244,20 +242,17 @@ out:
return res;
}
void
bool
fhandler_process::fill_filebuf ()
{
pinfo pmaybe;
pinfo p (pid);
if (!p)
{
pmaybe.init (pid);
p = &pmaybe;
set_errno (ENOENT);
return false;
}
if (!p)
return;
switch (fileid)
{
case PROCESS_UID:
@ -268,27 +263,27 @@ fhandler_process::fill_filebuf ()
case PROCESS_PPID:
{
if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40);
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40);
int num;
switch (fileid)
{
case PROCESS_PPID:
num = (*p)->ppid;
num = p->ppid;
break;
case PROCESS_UID:
num = (*p)->uid;
num = p->uid;
break;
case PROCESS_PGID:
num = (*p)->pgid;
num = p->pgid;
break;
case PROCESS_SID:
num = (*p)->sid;
num = p->sid;
break;
case PROCESS_GID:
num = (*p)->gid;
num = p->gid;
break;
case PROCESS_CTTY:
num = (*p)->ctty;
num = p->ctty;
break;
default: // what's this here for?
num = 0;
@ -301,12 +296,12 @@ fhandler_process::fill_filebuf ()
case PROCESS_EXENAME:
{
if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = MAX_PATH);
if ((*p)->process_state & (PID_ZOMBIE | PID_EXITED))
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = MAX_PATH);
if (p->process_state & (PID_ZOMBIE | PID_EXITED))
strcpy (filebuf, "<defunct>");
else
{
mount_table->conv_to_posix_path ((*p)->progname, filebuf, 1);
mount_table->conv_to_posix_path (p->progname, filebuf, 1);
int len = strlen (filebuf);
if (len > 4)
{
@ -321,17 +316,17 @@ fhandler_process::fill_filebuf ()
case PROCESS_WINPID:
{
if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40);
__small_sprintf (filebuf, "%d\n", (*p)->dwProcessId);
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40);
__small_sprintf (filebuf, "%d\n", p->dwProcessId);
filesize = strlen (filebuf);
break;
}
case PROCESS_WINEXENAME:
{
int len = strlen ((*p)->progname);
int len = strlen (p->progname);
if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = (len + 2));
strcpy (filebuf, (*p)->progname);
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = (len + 2));
strcpy (filebuf, p->progname);
filebuf[len] = '\n';
filesize = len + 1;
break;
@ -340,27 +335,26 @@ fhandler_process::fill_filebuf ()
{
if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048);
filesize = format_process_status ((*p), filebuf, bufalloc);
filesize = format_process_status (*p, filebuf, bufalloc);
break;
}
case PROCESS_STAT:
{
if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048);
filesize = format_process_stat ((*p), filebuf, bufalloc);
filesize = format_process_stat (*p, filebuf, bufalloc);
break;
}
case PROCESS_STATM:
{
if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048);
filesize = format_process_statm ((*p), filebuf, bufalloc);
filesize = format_process_statm (*p, filebuf, bufalloc);
break;
}
}
if (p == &pmaybe)
p = NULL;
return true;
}
static
@ -375,7 +369,7 @@ format_process_stat (_pinfo *p, char *destbuf, size_t maxsize)
vmsize = 0UL, vmrss = 0UL, vmmaxrss = 0UL;
int priority = 0;
if (p->process_state & (PID_ZOMBIE | PID_EXITED))
strcpy (cmd, "<defunct");
strcpy (cmd, "<defunct>");
else
{
strcpy(cmd, p->progname);
@ -598,11 +592,12 @@ static
off_t
format_process_statm (_pinfo *p, char *destbuf, size_t maxsize)
{
unsigned long vmsize = 0UL, vmrss = 0UL, vmtext = 0UL, vmdata = 0UL, vmlib = 0UL,
vmshare = 0UL;
unsigned long vmsize = 0UL, vmrss = 0UL, vmtext = 0UL, vmdata = 0UL,
vmlib = 0UL, vmshare = 0UL;
if (wincap.is_winnt ())
{
if (!get_mem_values (p->dwProcessId, &vmsize, &vmrss, &vmtext, &vmdata, &vmlib, &vmshare))
if (!get_mem_values (p->dwProcessId, &vmsize, &vmrss, &vmtext, &vmdata,
&vmlib, &vmshare))
return 0;
}
return __small_sprintf (destbuf, "%ld %ld %ld %ld %ld %ld %ld",

View File

@ -33,7 +33,7 @@ static const int registry_len = sizeof ("registry") - 1;
* make up the value index if we are enuerating values.
*/
static const __off32_t REG_ENUM_VALUES_MASK = 0x8000000;
static const __off32_t REG_POSITION_MASK = 0xffff;
static const __off32_t REG_POSITION_MASK = 0xffff;
/* List of root keys in /proc/registry.
* Possibly we should filter out those not relevant to the flavour of Windows
@ -49,7 +49,7 @@ static const char *registry_listing[] =
"HKEY_LOCAL_MACHINE",
"HKEY_USERS",
"HKEY_DYN_DATA", // 95/98/Me
"HKEY_PERFOMANCE_DATA", // NT/2000/XP
"HKEY_PERFOMANCE_DATA", // NT/2000/XP
NULL
};
@ -66,7 +66,7 @@ static const HKEY registry_keys[] =
HKEY_PERFORMANCE_DATA
};
static const int ROOT_KEY_COUNT = sizeof(registry_keys) / sizeof(HKEY);
static const int ROOT_KEY_COUNT = sizeof (registry_keys) / sizeof (HKEY);
/* These get added to each subdirectory in /proc/registry.
* If we wanted to implement writing, we could maybe add a '.writable' entry or
@ -79,11 +79,14 @@ static const char *special_dot_files[] =
NULL
};
static const int SPECIAL_DOT_FILE_COUNT = (sizeof(special_dot_files) / sizeof(const char *)) - 1;
static const int SPECIAL_DOT_FILE_COUNT =
(sizeof (special_dot_files) / sizeof (const char *)) - 1;
/* Name given to default values */
static const char *DEFAULT_VALUE_NAME = "@";
static HKEY open_key (const char *name, REGSAM access, bool isValue);
/* Returns 0 if path doesn't exist, >0 if path is a directory,
* <0 if path is a file.
*
@ -103,10 +106,7 @@ fhandler_registry::exists ()
const char *path = get_name ();
debug_printf ("exists (%s)", path);
path += proc_len + 1 + registry_len;
while (SLASH_P (*path))
path++;
path += proc_len + registry_len + 2;
if (*path == 0)
{
file_type = 2;
@ -132,44 +132,52 @@ fhandler_registry::exists ()
goto out;
}
hKey = open_key (path, KEY_READ, true);
if (hKey == (HKEY) INVALID_HANDLE_VALUE)
return 0;
hKey = open_key (path, KEY_READ, false);
if (hKey != (HKEY) INVALID_HANDLE_VALUE)
file_type = 1;
else
{
hKey = open_key (path, KEY_READ, true);
if (hKey == (HKEY) INVALID_HANDLE_VALUE)
return 0;
while (ERROR_SUCCESS ==
(error = RegEnumKeyEx (hKey, index++, buf, &buf_size, NULL, NULL,
NULL, NULL)) || (error == ERROR_MORE_DATA))
{
if (pathmatch (buf, file))
while (ERROR_SUCCESS ==
(error = RegEnumKeyEx (hKey, index++, buf, &buf_size, NULL, NULL,
NULL, NULL))
|| (error == ERROR_MORE_DATA))
{
file_type = 1;
if (pathmatch (buf, file))
{
file_type = 1;
goto out;
}
buf_size = MAX_PATH;
}
if (error != ERROR_NO_MORE_ITEMS)
{
seterrno_from_win_error (__FILE__, __LINE__, error);
goto out;
}
index = 0;
buf_size = MAX_PATH;
}
if (error != ERROR_NO_MORE_ITEMS)
{
seterrno_from_win_error (__FILE__, __LINE__, error);
goto out;
}
index = 0;
buf_size = MAX_PATH;
while (ERROR_SUCCESS ==
(error = RegEnumValue (hKey, index++, buf, &buf_size, NULL, NULL,
NULL, NULL)) || (error == ERROR_MORE_DATA))
{
if (pathmatch (buf, file) || (buf[0] == '\0' &&
pathmatch (file, DEFAULT_VALUE_NAME)))
while (ERROR_SUCCESS ==
(error = RegEnumValue (hKey, index++, buf, &buf_size, NULL, NULL,
NULL, NULL))
|| (error == ERROR_MORE_DATA))
{
file_type = -1;
if (pathmatch (buf, file) || (buf[0] == '\0' &&
pathmatch (file, DEFAULT_VALUE_NAME)))
{
file_type = -1;
goto out;
}
buf_size = MAX_PATH;
}
if (error != ERROR_NO_MORE_ITEMS)
{
seterrno_from_win_error (__FILE__, __LINE__, error);
goto out;
}
buf_size = MAX_PATH;
}
if (error != ERROR_NO_MORE_ITEMS)
{
seterrno_from_win_error (__FILE__, __LINE__, error);
goto out;
}
out:
if (hKey != (HKEY) INVALID_HANDLE_VALUE)
@ -178,12 +186,12 @@ out:
}
fhandler_registry::fhandler_registry ():
fhandler_proc (FH_REGISTRY)
fhandler_proc (FH_REGISTRY)
{
}
int
fhandler_registry::fstat (struct __stat64 *buf, path_conv *pc)
fhandler_registry::fstat (struct __stat64 *buf, path_conv * pc)
{
this->fhandler_base::fstat (buf, pc);
buf->st_mode &= ~_IFMT & NO_W;
@ -206,6 +214,61 @@ fhandler_registry::fstat (struct __stat64 *buf, path_conv *pc)
buf->st_mode &= NO_X;
break;
}
if (file_type != 0 && file_type != 2)
{
HKEY hKey;
const char *path = get_name () + proc_len + registry_len + 2;
hKey =
open_key (path, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE,
(file_type < 0) ? true : false);
if (hKey != (HKEY) INVALID_HANDLE_VALUE)
{
FILETIME ftLastWriteTime;
DWORD subkey_count;
if (ERROR_SUCCESS ==
RegQueryInfoKey (hKey, NULL, NULL, NULL, &subkey_count, NULL,
NULL, NULL, NULL, NULL, NULL,
&ftLastWriteTime))
{
to_timestruc_t (&ftLastWriteTime, &buf->st_mtim);
buf->st_ctim = buf->st_mtim;
time_as_timestruc_t (&buf->st_atim);
if (file_type > 0)
buf->st_nlink = subkey_count;
else
{
int pathlen = strlen (path);
const char *value_name = path + pathlen - 1;
if (SLASH_P (*value_name) && pathlen > 1)
value_name--;
while (!SLASH_P (*value_name))
value_name--;
value_name++;
DWORD dwSize;
if (ERROR_SUCCESS ==
RegQueryValueEx (hKey, value_name, NULL, NULL, NULL,
&dwSize))
buf->st_size = dwSize;
}
__uid32_t uid;
__gid32_t gid;
if (get_object_attribute
((HANDLE) hKey, SE_REGISTRY_KEY, &buf->st_mode, &uid,
&gid) == 0)
{
buf->st_uid = uid;
buf->st_gid = gid;
buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
if (file_type > 0)
buf->st_mode |= S_IFDIR;
else
buf->st_mode &= NO_X;
}
}
RegCloseKey (hKey);
}
}
return 0;
}
@ -230,14 +293,15 @@ fhandler_registry::readdir (DIR * dir)
if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE
&& dir->__d_position == 0)
{
handle = open_key (path + 1);
dir->__d_u.__d_data.__handle = handle;;
handle = open_key (path + 1, KEY_READ, false);
dir->__d_u.__d_data.__handle = handle;
}
if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE)
goto out;
if (dir->__d_position < SPECIAL_DOT_FILE_COUNT)
{
strcpy (dir->__d_dirent->d_name, special_dot_files[dir->__d_position++]);
strcpy (dir->__d_dirent->d_name,
special_dot_files[dir->__d_position++]);
res = dir->__d_dirent;
goto out;
}
@ -252,7 +316,8 @@ retry:
else
error =
RegEnumKeyEx ((HKEY) dir->__d_u.__d_data.__handle, dir->__d_position -
SPECIAL_DOT_FILE_COUNT, buf, &buf_size, NULL, NULL, NULL, NULL);
SPECIAL_DOT_FILE_COUNT, buf, &buf_size, NULL, NULL, NULL,
NULL);
if (error == ERROR_NO_MORE_ITEMS
&& (dir->__d_position & REG_ENUM_VALUES_MASK) == 0)
{
@ -280,7 +345,7 @@ retry:
dir->__d_position += 0x10000;
res = dir->__d_dirent;
out:
syscall_printf ("%p = readdir (%p) (%s)", &dir->__d_dirent, dir, buf);
syscall_printf ("%p = readdir (%p)", &dir->__d_dirent, dir);
return res;
}
@ -329,13 +394,11 @@ fhandler_registry::closedir (DIR * dir)
}
int
fhandler_registry::open (path_conv *pc, int flags, mode_t mode)
fhandler_registry::open (path_conv * pc, int flags, mode_t mode)
{
DWORD type, size;
LONG error;
HKEY hKey = (HKEY) INVALID_HANDLE_VALUE;
int pathlen;
const char *file;
HKEY handle;
int res = fhandler_virtual::open (pc, flags, mode);
if (!res)
@ -418,33 +481,88 @@ fhandler_registry::open (path_conv *pc, int flags, mode_t mode)
goto out;
}
hKey = open_key (path, KEY_READ, true);
if (hKey == (HKEY) INVALID_HANDLE_VALUE)
handle = open_key (path, KEY_READ, true);
if (handle == (HKEY) INVALID_HANDLE_VALUE)
{
res = 0;
goto out;
}
if (pathmatch (file, DEFAULT_VALUE_NAME))
file = "";
if (hKey != HKEY_PERFORMANCE_DATA)
set_io_handle (handle);
if (pathmatch (file, DEFAULT_VALUE_NAME))
value_name = cstrdup ("");
else
value_name = cstrdup (file);
if (!fill_filebuf ())
{
error = RegQueryValueEx (hKey, file, NULL, &type, NULL, &size);
RegCloseKey (handle);
res = 0;
goto out;
}
if (flags & O_APPEND)
position = filesize;
else
position = 0;
success:
res = 1;
set_flags ((flags & ~O_TEXT) | O_BINARY);
set_open_status ();
out:
syscall_printf ("%d = fhandler_registry::open (%p, %d)", res, flags, mode);
return res;
}
int
fhandler_registry::close ()
{
int res = fhandler_virtual::close ();
if (res != 0)
return res;
HKEY handle = (HKEY) get_handle ();
if (handle != (HKEY) INVALID_HANDLE_VALUE)
{
if (RegCloseKey (handle) != ERROR_SUCCESS)
{
__seterrno ();
res = -1;
}
}
if (value_name)
cfree (value_name);
return 0;
}
bool
fhandler_registry::fill_filebuf ()
{
DWORD type, size;
LONG error;
HKEY handle = (HKEY) get_handle ();
if (handle != HKEY_PERFORMANCE_DATA)
{
error = RegQueryValueEx (handle, value_name, NULL, &type, NULL, &size);
if (error != ERROR_SUCCESS)
{
seterrno_from_win_error (__FILE__, __LINE__, error);
res = -1;
goto out;
if (error != ERROR_FILE_NOT_FOUND)
{
seterrno_from_win_error (__FILE__, __LINE__, error);
return false;
}
goto value_not_found;
}
bufalloc = size;
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc);
error =
RegQueryValueEx (hKey, file, NULL, NULL, (BYTE *) filebuf, &size);
RegQueryValueEx (handle, value_name, NULL, NULL, (BYTE *) filebuf,
&size);
if (error != ERROR_SUCCESS)
{
seterrno_from_win_error (__FILE__, __LINE__, error);
res = 0;
goto out;
return true;
}
filesize = size;
}
@ -460,43 +578,49 @@ fhandler_registry::open (path_conv *pc, int flags, mode_t mode)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc);
}
error =
RegQueryValueEx (hKey, file, NULL, &type, (BYTE *) filebuf,
&size);
if (error != ERROR_SUCCESS && res != ERROR_MORE_DATA)
RegQueryValueEx (handle, value_name, NULL, &type,
(BYTE *) filebuf, &size);
if (error != ERROR_SUCCESS && error != ERROR_MORE_DATA)
{
seterrno_from_win_error (__FILE__, __LINE__, error);
res = 0;
goto out;
if (error != ERROR_FILE_NOT_FOUND)
{
seterrno_from_win_error (__FILE__, __LINE__, error);
return true;
}
goto value_not_found;
}
}
while (error == ERROR_MORE_DATA);
filesize = size;
}
if (flags & O_APPEND)
position = filesize;
else
position = 0;
success:
res = 1;
set_flags ((flags & ~O_TEXT) | O_BINARY);
set_open_status ();
out:
if (hKey != (HKEY) INVALID_HANDLE_VALUE)
RegCloseKey (hKey);
syscall_printf ("%d = fhandler_registry::open (%p, %d)", res, flags, mode);
return res;
}
void
fhandler_registry::fill_filebuf ()
{
return true;
value_not_found:
DWORD buf_size = MAX_PATH;
char buf[buf_size];
int index = 0;
while (ERROR_SUCCESS ==
(error = RegEnumKeyEx (handle, index++, buf, &buf_size, NULL, NULL,
NULL, NULL)) || (error == ERROR_MORE_DATA))
{
if (pathmatch (buf, value_name))
{
set_errno (EISDIR);
return false;
}
buf_size = MAX_PATH;
}
if (error != ERROR_NO_MORE_ITEMS)
{
seterrno_from_win_error (__FILE__, __LINE__, error);
return false;
}
set_errno (ENOENT);
return false;
}
/* Auxillary member function to open registry keys. */
HKEY
fhandler_registry::open_key (const char *name, REGSAM access, bool isValue)
static HKEY
open_key (const char *name, REGSAM access, bool isValue)
{
HKEY hKey = (HKEY) INVALID_HANDLE_VALUE;
HKEY hParentKey = (HKEY) INVALID_HANDLE_VALUE;
@ -517,10 +641,15 @@ fhandler_registry::open_key (const char *name, REGSAM access, bool isValue)
if (hParentKey != (HKEY) INVALID_HANDLE_VALUE)
{
hKey = (HKEY) INVALID_HANDLE_VALUE;
LONG error = RegOpenKeyEx (hParentKey, component, 0, access, &hKey);
if (hKey == (HKEY) INVALID_HANDLE_VALUE)
REGSAM effective_access = KEY_READ;
if ((strchr (name, '/') == NULL && isValue == true) || *name == 0)
effective_access = access;
LONG
error =
RegOpenKeyEx (hParentKey, component, 0, effective_access, &hKey);
if (error != ERROR_SUCCESS)
{
hKey = (HKEY) INVALID_HANDLE_VALUE;
seterrno_from_win_error (__FILE__, __LINE__, error);
return hKey;
}

View File

@ -115,7 +115,8 @@ fhandler_virtual::lseek (__off64_t offset, int whence)
* On Linux, when you lseek within a /proc file,
* the contents of the file are updated.
*/
fill_filebuf ();
if (!fill_filebuf ())
return (__off64_t) -1;
switch (whence)
{
case SEEK_SET:
@ -209,8 +210,6 @@ fhandler_virtual::open (path_conv *, int flags, mode_t mode)
set_flags ((flags & ~O_TEXT) | O_BINARY);
set_nohandle (true);
return 1;
}
@ -220,7 +219,8 @@ fhandler_virtual::exists ()
return 0;
}
void
bool
fhandler_virtual::fill_filebuf ()
{
return true;
}

View File

@ -28,6 +28,7 @@ details. */
#include <wininet.h>
#include <ntsecapi.h>
#include <subauth.h>
#include <aclapi.h>
#include "cygerrno.h"
#include "security.h"
#include "fhandler.h"
@ -1301,6 +1302,174 @@ get_file_attribute (int use_ntsec, const char *file,
return res > 0 ? 0 : -1;
}
static int
get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribute,
__uid32_t *uidret, __gid32_t *gidret)
{
if (!wincap.has_security ())
return 0;
PSECURITY_DESCRIPTOR psd = NULL;
PSID owner_sid;
PSID group_sid;
PACL acl;
if (ERROR_SUCCESS != GetSecurityInfo (handle, object_type,
DACL_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
OWNER_SECURITY_INFORMATION,
&owner_sid,
&group_sid,
&acl,
NULL,
&psd))
{
__seterrno ();
debug_printf ("GetSecurityInfo %E");
return -1;
}
__uid32_t uid = cygsid (owner_sid).get_uid ();
__gid32_t gid = cygsid (group_sid).get_gid ();
if (uidret)
*uidret = uid;
if (gidret)
*gidret = gid;
if (!attribute)
{
syscall_printf ("uid %d, gid %d", uid, gid);
LocalFree (psd);
return 0;
}
BOOL grp_member = is_grp_member (uid, gid);
if (!acl)
{
*attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
syscall_printf ("No ACL = %x, uid %d, gid %d",
*attribute, uid, gid);
LocalFree (psd);
return 0;
}
ACCESS_ALLOWED_ACE *ace;
int allow = 0;
int deny = 0;
int *flags, *anti;
for (DWORD i = 0; i < acl->AceCount; ++i)
{
if (!GetAce (acl, i, (PVOID *) &ace))
continue;
if (ace->Header.AceFlags & INHERIT_ONLY_ACE)
continue;
switch (ace->Header.AceType)
{
case ACCESS_ALLOWED_ACE_TYPE:
flags = &allow;
anti = &deny;
break;
case ACCESS_DENIED_ACE_TYPE:
flags = &deny;
anti = &allow;
break;
default:
continue;
}
cygsid ace_sid ((PSID) &ace->SidStart);
if (owner_sid && ace_sid == owner_sid)
{
if (ace->Mask & FILE_READ_DATA)
*flags |= S_IRUSR;
if (ace->Mask & FILE_WRITE_DATA)
*flags |= S_IWUSR;
if (ace->Mask & FILE_EXECUTE)
*flags |= S_IXUSR;
}
else if (group_sid && ace_sid == group_sid)
{
if (ace->Mask & FILE_READ_DATA)
*flags |= S_IRGRP
| ((grp_member && !(*anti & S_IRUSR)) ? S_IRUSR : 0);
if (ace->Mask & FILE_WRITE_DATA)
*flags |= S_IWGRP
| ((grp_member && !(*anti & S_IWUSR)) ? S_IWUSR : 0);
if (ace->Mask & FILE_EXECUTE)
*flags |= S_IXGRP
| ((grp_member && !(*anti & S_IXUSR)) ? S_IXUSR : 0);
}
else if (ace_sid == well_known_world_sid)
{
if (ace->Mask & FILE_READ_DATA)
*flags |= S_IROTH
| ((!(*anti & S_IRGRP)) ? S_IRGRP : 0)
| ((!(*anti & S_IRUSR)) ? S_IRUSR : 0);
if (ace->Mask & FILE_WRITE_DATA)
*flags |= S_IWOTH
| ((!(*anti & S_IWGRP)) ? S_IWGRP : 0)
| ((!(*anti & S_IWUSR)) ? S_IWUSR : 0);
if (ace->Mask & FILE_EXECUTE)
{
*flags |= S_IXOTH
| ((!(*anti & S_IXGRP)) ? S_IXGRP : 0)
| ((!(*anti & S_IXUSR)) ? S_IXUSR : 0);
}
if ((*attribute & S_IFDIR) &&
(ace->Mask & (FILE_WRITE_DATA | FILE_EXECUTE | FILE_DELETE_CHILD))
== (FILE_WRITE_DATA | FILE_EXECUTE))
*flags |= S_ISVTX;
}
else if (ace_sid == well_known_null_sid)
{
/* Read SUID, SGID and VTX bits from NULL ACE. */
if (ace->Mask & FILE_READ_DATA)
*flags |= S_ISVTX;
if (ace->Mask & FILE_WRITE_DATA)
*flags |= S_ISGID;
if (ace->Mask & FILE_APPEND_DATA)
*flags |= S_ISUID;
}
}
*attribute &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX | S_ISGID | S_ISUID);
*attribute |= allow;
*attribute &= ~deny;
LocalFree (psd);
syscall_printf ("%x, uid %d, gid %d", *attribute, uid, gid);
return 0;
}
int
get_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type,
int *attribute, __uid32_t *uidret, __gid32_t *gidret)
{
if (allow_ntsec)
{
int res = get_nt_object_attribute (handle, object_type, attribute, uidret, gidret);
if (attribute && (*attribute & S_IFLNK) == S_IFLNK)
*attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
return res;
}
if (uidret)
*uidret = getuid32 ();
if (gidret)
*gidret = getgid32 ();
if (!attribute)
return 0;
/* symlinks are everything for everyone!*/
if ((*attribute & S_IFLNK) == S_IFLNK)
*attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
return 0;
}
BOOL
add_access_allowed_ace (PACL acl, int offset, DWORD attributes,
PSID sid, size_t &len_add, DWORD inherit)

View File

@ -8,6 +8,7 @@ This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include <accctrl.h>
#define DONT_INHERIT (0)
#define INHERIT_ALL (CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
#define INHERIT_ONLY (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
@ -169,6 +170,8 @@ int __stdcall get_file_attribute (int, const char *, int *,
__uid32_t * = NULL, __gid32_t * = NULL);
int __stdcall set_file_attribute (int, const char *, int);
int __stdcall set_file_attribute (int, const char *, __uid32_t, __gid32_t, int);
int __stdcall get_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *,
__uid32_t * = NULL, __gid32_t * = NULL);
LONG __stdcall read_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, LPDWORD sd_size);
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);