mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-01 02:46:32 +00:00
server: Clone file_get_sd() and file_set_fd() for directories.
This commit is contained in:
parent
d87af3dfb2
commit
6435a5ddab
2 changed files with 134 additions and 2 deletions
|
@ -777,6 +777,43 @@ static void test_FileSecurity(void)
|
|||
|
||||
HeapFree (GetProcessHeap (), 0, sd);
|
||||
|
||||
/* Repeat for the temporary directory ... */
|
||||
|
||||
/* Get size needed */
|
||||
retSize = 0;
|
||||
SetLastError (NO_ERROR);
|
||||
rc = pGetFileSecurityA (path, request, NULL, 0, &retSize);
|
||||
ok (!rc, "GetFileSecurityA "
|
||||
"was expected to fail for '%s'\n", path);
|
||||
ok (GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetFileSecurityA "
|
||||
"returned %d; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError());
|
||||
ok (retSize > sizeof (SECURITY_DESCRIPTOR), "GetFileSecurityA "
|
||||
"returned size %d; expected > %d\n", retSize, sizeof (SECURITY_DESCRIPTOR));
|
||||
|
||||
sdSize = retSize;
|
||||
sd = HeapAlloc (GetProcessHeap (), 0, sdSize);
|
||||
|
||||
/* Get security descriptor for real */
|
||||
retSize = 0;
|
||||
SetLastError (NO_ERROR);
|
||||
rc = pGetFileSecurityA (path, request, sd, sdSize, &retSize);
|
||||
ok (rc, "GetFileSecurityA "
|
||||
"was not expected to fail '%s'\n", path);
|
||||
ok (GetLastError () == NO_ERROR, "GetFileSecurityA "
|
||||
"returned %d; expected NO_ERROR\n", GetLastError ());
|
||||
ok (retSize == sdSize, "GetFileSecurityA "
|
||||
"returned size %d; expected %d\n", retSize, sdSize);
|
||||
|
||||
/* Use it to set security descriptor */
|
||||
SetLastError (NO_ERROR);
|
||||
rc = pSetFileSecurityA (path, request, sd);
|
||||
ok (rc, "SetFileSecurityA "
|
||||
"was not expected to fail '%s'\n", path);
|
||||
ok (GetLastError () == NO_ERROR, "SetFileSecurityA "
|
||||
"returned %d; expected NO_ERROR\n", GetLastError ());
|
||||
|
||||
HeapFree (GetProcessHeap (), 0, sd);
|
||||
|
||||
/* Remove temporary file and directory */
|
||||
DeleteFileA (file);
|
||||
RemoveDirectoryA (path);
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
#include "handle.h"
|
||||
#include "thread.h"
|
||||
#include "request.h"
|
||||
#include "process.h"
|
||||
#include "security.h"
|
||||
#include "winternl.h"
|
||||
|
||||
/* dnotify support */
|
||||
|
@ -146,6 +148,8 @@ struct dir
|
|||
{
|
||||
struct object obj; /* object header */
|
||||
struct fd *fd; /* file descriptor to the directory */
|
||||
mode_t mode; /* file stat.st_mode */
|
||||
uid_t uid; /* file stat.st_uid */
|
||||
struct list entry; /* entry in global change notifications list */
|
||||
unsigned int filter; /* notification filter */
|
||||
int notified; /* SIGIO counter */
|
||||
|
@ -157,6 +161,9 @@ struct dir
|
|||
};
|
||||
|
||||
static struct fd *dir_get_fd( struct object *obj );
|
||||
static struct security_descriptor *dir_get_sd( struct object *obj );
|
||||
static int dir_set_sd( struct object *obj, const struct security_descriptor *sd,
|
||||
unsigned int set_info );
|
||||
static void dir_dump( struct object *obj, int verbose );
|
||||
static void dir_destroy( struct object *obj );
|
||||
|
||||
|
@ -172,8 +179,8 @@ static const struct object_ops dir_ops =
|
|||
no_signal, /* signal */
|
||||
dir_get_fd, /* get_fd */
|
||||
default_fd_map_access, /* map_access */
|
||||
default_get_sd, /* get_sd */
|
||||
default_set_sd, /* set_sd */
|
||||
dir_get_sd, /* get_sd */
|
||||
dir_set_sd, /* set_sd */
|
||||
no_lookup_name, /* lookup_name */
|
||||
no_open_file, /* open_file */
|
||||
fd_close_handle, /* close_handle */
|
||||
|
@ -291,6 +298,94 @@ static struct fd *dir_get_fd( struct object *obj )
|
|||
return (struct fd *)grab_object( dir->fd );
|
||||
}
|
||||
|
||||
static int get_dir_unix_fd( struct dir *dir )
|
||||
{
|
||||
return get_unix_fd( dir->fd );
|
||||
}
|
||||
|
||||
static struct security_descriptor *dir_get_sd( struct object *obj )
|
||||
{
|
||||
struct dir *dir = (struct dir *)obj;
|
||||
int unix_fd;
|
||||
struct stat st;
|
||||
struct security_descriptor *sd;
|
||||
assert( obj->ops == &dir_ops );
|
||||
|
||||
unix_fd = get_dir_unix_fd( dir );
|
||||
|
||||
if (unix_fd == -1 || fstat( unix_fd, &st ) == -1)
|
||||
return obj->sd;
|
||||
|
||||
/* mode and uid the same? if so, no need to re-generate security descriptor */
|
||||
if (obj->sd &&
|
||||
(st.st_mode & (S_IRWXU|S_IRWXO)) == (dir->mode & (S_IRWXU|S_IRWXO)) &&
|
||||
(st.st_uid == dir->uid))
|
||||
return obj->sd;
|
||||
|
||||
sd = mode_to_sd( st.st_mode,
|
||||
security_unix_uid_to_sid( st.st_uid ),
|
||||
token_get_primary_group( current->process->token ));
|
||||
if (!sd) return obj->sd;
|
||||
|
||||
dir->mode = st.st_mode;
|
||||
dir->uid = st.st_uid;
|
||||
free( obj->sd );
|
||||
obj->sd = sd;
|
||||
return sd;
|
||||
}
|
||||
|
||||
static int dir_set_sd( struct object *obj, const struct security_descriptor *sd,
|
||||
unsigned int set_info )
|
||||
{
|
||||
struct dir *dir = (struct dir *)obj;
|
||||
const SID *owner;
|
||||
mode_t mode;
|
||||
int unix_fd;
|
||||
|
||||
assert( obj->ops == &dir_ops );
|
||||
|
||||
unix_fd = get_dir_unix_fd( dir );
|
||||
|
||||
if (unix_fd == -1) return 1;
|
||||
|
||||
if (set_info & OWNER_SECURITY_INFORMATION)
|
||||
{
|
||||
owner = sd_get_owner( sd );
|
||||
if (!owner)
|
||||
{
|
||||
set_error( STATUS_INVALID_SECURITY_DESCR );
|
||||
return 0;
|
||||
}
|
||||
if (!obj->sd || !security_equal_sid( owner, sd_get_owner( obj->sd ) ))
|
||||
{
|
||||
/* FIXME: get Unix uid and call fchown */
|
||||
}
|
||||
}
|
||||
else if (obj->sd)
|
||||
owner = sd_get_owner( obj->sd );
|
||||
else
|
||||
owner = token_get_user( current->process->token );
|
||||
|
||||
if (set_info & DACL_SECURITY_INFORMATION)
|
||||
{
|
||||
/* keep the bits that we don't map to access rights in the ACL */
|
||||
mode = dir->mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXG);
|
||||
mode |= sd_to_mode( sd, owner );
|
||||
|
||||
if (dir->mode != mode)
|
||||
{
|
||||
if (fchmod( unix_fd, mode ) == -1)
|
||||
{
|
||||
file_set_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
dir->mode = mode;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct change_record *get_first_change_record( struct dir *dir )
|
||||
{
|
||||
struct list *ptr = list_head( &dir->change_records );
|
||||
|
|
Loading…
Reference in a new issue