mirror of
https://github.com/haiwen/seafile.git
synced 2025-01-07 03:17:13 +08:00
cb877e00d9
* portable visual studio 2019 * Need alignment and fix compile warning * Define related headers in common.h * del reference config.h * Add files generated by vala * Def reference config.h for windows * Support vs build Co-authored-by: sun <1184550842@qq.com>
334 lines
8.9 KiB
C
334 lines
8.9 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
#include "common.h"
|
|
|
|
#include "utils.h"
|
|
#define DEBUG_FLAG SEAFILE_DEBUG_SYNC
|
|
#include "log.h"
|
|
|
|
#include "set-perm.h"
|
|
|
|
#ifdef WIN32
|
|
|
|
#ifndef _WIN32_WINNT
|
|
#define _WIN32_WINNT 0x501
|
|
#endif
|
|
|
|
#include <windows.h>
|
|
#include <AccCtrl.h>
|
|
#include <AclApi.h>
|
|
|
|
#define WIN32_WRITE_ACCESS_MASK (FILE_WRITE_DATA | FILE_APPEND_DATA | \
|
|
FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES | DELETE)
|
|
|
|
// Remove explicit ACEs set by us.
|
|
static int
|
|
unset_permissions (PACL dacl)
|
|
{
|
|
ACL_SIZE_INFORMATION size_info;
|
|
|
|
if (!dacl)
|
|
return 0;
|
|
|
|
if (!GetAclInformation (dacl, &size_info,
|
|
sizeof(size_info), AclSizeInformation)) {
|
|
seaf_warning ("GetAclInformation Error: %lu\n", GetLastError());
|
|
return -1;
|
|
}
|
|
|
|
DWORD i;
|
|
ACE_HEADER *ace;
|
|
ACCESS_DENIED_ACE *deny_ace;
|
|
ACCESS_ALLOWED_ACE *allowed_ace;
|
|
for (i = 0; i < size_info.AceCount; ++i) {
|
|
if (!GetAce(dacl, i, (void**)&ace)) {
|
|
seaf_warning ("GetAce Error: %lu\n", GetLastError());
|
|
return -1;
|
|
}
|
|
|
|
// Skip inherited ACEs.
|
|
if (ace->AceFlags & INHERITED_ACE)
|
|
continue;
|
|
|
|
if (ace->AceType == ACCESS_DENIED_ACE_TYPE) {
|
|
deny_ace = (ACCESS_DENIED_ACE *)ace;
|
|
if (deny_ace->Mask == WIN32_WRITE_ACCESS_MASK) {
|
|
DeleteAce(dacl, i);
|
|
break;
|
|
}
|
|
} else if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE) {
|
|
allowed_ace = (ACCESS_ALLOWED_ACE *)ace;
|
|
if (allowed_ace->Mask == WIN32_WRITE_ACCESS_MASK) {
|
|
DeleteAce(dacl, i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
seaf_set_path_permission (const char *path, SeafPathPerm perm, gboolean recursive)
|
|
{
|
|
wchar_t *wpath = NULL;
|
|
int ret = 0;
|
|
DWORD res = 0;
|
|
PACL old_dacl = NULL, new_dacl = NULL;
|
|
PSECURITY_DESCRIPTOR sd = NULL;
|
|
EXPLICIT_ACCESS ea;
|
|
|
|
g_return_val_if_fail (perm == SEAF_PATH_PERM_RO || perm == SEAF_PATH_PERM_RW, -1);
|
|
|
|
seaf_debug ("set permission for %s, perm: %d, recursive: %d\n",
|
|
path, perm, recursive);
|
|
|
|
wpath = win32_long_path (path);
|
|
if (!wpath)
|
|
return -1;
|
|
|
|
res = GetNamedSecurityInfoW(wpath, SE_FILE_OBJECT,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL, NULL, &old_dacl, NULL, &sd);
|
|
if (ERROR_SUCCESS != res) {
|
|
seaf_warning( "GetNamedSecurityInfo Error for path %s: %lu\n", path, res );
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
|
|
unset_permissions (old_dacl);
|
|
|
|
// Initialize an EXPLICIT_ACCESS structure for the new ACE.
|
|
|
|
memset (&ea, 0, sizeof(EXPLICIT_ACCESS));
|
|
ea.grfAccessPermissions = WIN32_WRITE_ACCESS_MASK;
|
|
ea.grfAccessMode = ((perm == SEAF_PATH_PERM_RO)?DENY_ACCESS:GRANT_ACCESS);
|
|
ea.grfInheritance = (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE);
|
|
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
|
|
ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
|
|
ea.Trustee.ptstrName = L"CURRENT_USER";
|
|
|
|
// Create a new ACL that merges the new ACE
|
|
// into the existing DACL.
|
|
|
|
res = SetEntriesInAcl(1, &ea, old_dacl, &new_dacl);
|
|
if (ERROR_SUCCESS != res) {
|
|
seaf_warning( "SetEntriesInAcl Error %lu\n", res );
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
|
|
// Attach the new ACL as the object's DACL.
|
|
|
|
if (recursive) {
|
|
res = SetNamedSecurityInfoW(wpath, SE_FILE_OBJECT,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL, NULL, new_dacl, NULL);
|
|
if (ERROR_SUCCESS != res) {
|
|
seaf_warning( "SetNamedSecurityInfo Error %lu\n", res );
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
} else {
|
|
SECURITY_DESCRIPTOR new_sd;
|
|
|
|
InitializeSecurityDescriptor (&new_sd, SECURITY_DESCRIPTOR_REVISION);
|
|
SetSecurityDescriptorDacl (&new_sd, TRUE, new_dacl, FALSE);
|
|
|
|
if (!SetFileSecurityW (wpath, DACL_SECURITY_INFORMATION, &new_sd)) {
|
|
seaf_warning ("SetFileSecurity Error %lu\n", GetLastError());
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
g_free (wpath);
|
|
if(sd != NULL)
|
|
LocalFree((HLOCAL) sd);
|
|
if(new_dacl != NULL)
|
|
LocalFree((HLOCAL) new_dacl);
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
seaf_unset_path_permission (const char *path, gboolean recursive)
|
|
{
|
|
wchar_t *wpath = NULL;
|
|
int ret = 0;
|
|
DWORD res = 0;
|
|
PACL old_dacl = NULL, new_dacl = NULL;
|
|
PSECURITY_DESCRIPTOR sd = NULL;
|
|
|
|
seaf_debug ("unset permission for %s, recursive: %d\n",
|
|
path, recursive);
|
|
|
|
wpath = win32_long_path (path);
|
|
if (!wpath)
|
|
return -1;
|
|
|
|
res = GetNamedSecurityInfoW(wpath, SE_FILE_OBJECT,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL, NULL, &old_dacl, NULL, &sd);
|
|
if (ERROR_SUCCESS != res) {
|
|
seaf_warning( "GetNamedSecurityInfo Error %lu\n", res );
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
|
|
// Create a new copy of the old ACL
|
|
|
|
res = SetEntriesInAcl(0, NULL, old_dacl, &new_dacl);
|
|
if (ERROR_SUCCESS != res) {
|
|
seaf_warning( "SetEntriesInAcl Error %lu\n", res );
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!new_dacl) {
|
|
goto cleanup;
|
|
}
|
|
|
|
unset_permissions (new_dacl);
|
|
|
|
// Update path's ACL
|
|
|
|
if (recursive) {
|
|
res = SetNamedSecurityInfoW(wpath, SE_FILE_OBJECT,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL, NULL, new_dacl, NULL);
|
|
if (ERROR_SUCCESS != res) {
|
|
seaf_warning( "SetNamedSecurityInfo Error %lu\n", res );
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
} else {
|
|
SECURITY_DESCRIPTOR new_sd;
|
|
|
|
InitializeSecurityDescriptor (&new_sd, SECURITY_DESCRIPTOR_REVISION);
|
|
SetSecurityDescriptorDacl (&new_sd, TRUE, new_dacl, FALSE);
|
|
|
|
if (!SetFileSecurityW (wpath, DACL_SECURITY_INFORMATION, &new_sd)) {
|
|
seaf_warning ("SetFileSecurity Error %lu\n", GetLastError());
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
g_free (wpath);
|
|
if(sd != NULL)
|
|
LocalFree((HLOCAL) sd);
|
|
if(new_dacl != NULL)
|
|
LocalFree((HLOCAL) new_dacl);
|
|
return ret;
|
|
}
|
|
|
|
SeafPathPerm
|
|
seaf_get_path_permission (const char *path)
|
|
{
|
|
wchar_t *wpath = NULL;
|
|
SeafPathPerm ret = SEAF_PATH_PERM_UNKNOWN;
|
|
DWORD res = 0;
|
|
PACL dacl = NULL;
|
|
PSECURITY_DESCRIPTOR sd = NULL;
|
|
|
|
wpath = win32_long_path (path);
|
|
if (!wpath)
|
|
return ret;
|
|
|
|
res = GetNamedSecurityInfoW(wpath, SE_FILE_OBJECT,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL, NULL, &dacl, NULL, &sd);
|
|
if (ERROR_SUCCESS != res) {
|
|
seaf_warning( "GetNamedSecurityInfo Error %lu\n", res );
|
|
goto cleanup;
|
|
}
|
|
|
|
ACL_SIZE_INFORMATION size_info;
|
|
|
|
if (!GetAclInformation (dacl, &size_info,
|
|
sizeof(size_info), AclSizeInformation)) {
|
|
seaf_warning ("GetAclInformation Error: %lu\n", GetLastError());
|
|
goto cleanup;
|
|
}
|
|
|
|
DWORD i;
|
|
ACE_HEADER *ace;
|
|
ACCESS_DENIED_ACE *deny_ace;
|
|
ACCESS_ALLOWED_ACE *allowed_ace;
|
|
for (i = 0; i < size_info.AceCount; ++i) {
|
|
if (!GetAce(dacl, i, (void**)&ace)) {
|
|
seaf_warning ("GetAce Error: %lu\n", GetLastError());
|
|
goto cleanup;
|
|
}
|
|
|
|
// Skip inherited ACEs.
|
|
if (ace->AceFlags & INHERITED_ACE)
|
|
continue;
|
|
|
|
if (ace->AceType == ACCESS_DENIED_ACE_TYPE) {
|
|
deny_ace = (ACCESS_DENIED_ACE *)ace;
|
|
if (deny_ace->Mask == WIN32_WRITE_ACCESS_MASK) {
|
|
ret = SEAF_PATH_PERM_RO;
|
|
break;
|
|
}
|
|
} else if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE) {
|
|
allowed_ace = (ACCESS_ALLOWED_ACE *)ace;
|
|
if (allowed_ace->Mask == WIN32_WRITE_ACCESS_MASK) {
|
|
ret = SEAF_PATH_PERM_RW;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
g_free (wpath);
|
|
if(sd != NULL)
|
|
LocalFree((HLOCAL) sd);
|
|
return ret;
|
|
}
|
|
|
|
#else
|
|
|
|
#include <sys/stat.h>
|
|
|
|
int
|
|
seaf_set_path_permission (const char *path, SeafPathPerm perm, gboolean recursive)
|
|
{
|
|
struct stat st;
|
|
mode_t new_mode;
|
|
|
|
if (stat (path, &st) < 0) {
|
|
seaf_warning ("Failed to stat %s: %s\n", path, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
new_mode = st.st_mode;
|
|
if (perm == SEAF_PATH_PERM_RO)
|
|
new_mode &= ~(S_IWUSR);
|
|
else if (perm == SEAF_PATH_PERM_RW)
|
|
new_mode |= S_IWUSR;
|
|
|
|
if (chmod (path, new_mode) < 0) {
|
|
seaf_warning ("Failed to chmod %s to %d: %s\n", path, new_mode, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
seaf_unset_path_permission (const char *path, gboolean recursive)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
SeafPathPerm
|
|
seaf_get_path_permission (const char *path)
|
|
{
|
|
return SEAF_PATH_PERM_UNKNOWN;
|
|
}
|
|
|
|
#endif /* WIN32 */
|