#include <config.h>
#include <aclapi.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#include <errno.h>
#include <isc/file.h>
#include <isc/stat.h>
#include "errno2result.h"
#include "../fsaccess.c"
static char username[255] = "\0";
static DWORD namelen = 0;
BOOL
is_ntfs(const char * file) {
char drive[255];
char FSType[20];
char tmpbuf[256];
char *machinename;
char *sharename;
char filename[1024];
REQUIRE(filename != NULL);
if (isc_file_absolutepath(file, filename,
sizeof(filename)) != ISC_R_SUCCESS) {
return (FALSE);
}
if (isalpha(filename[0]) && filename[1] == ':' &&
(filename[2] == '\\' || filename[2] == '/')) {
strncpy(drive, filename, 3);
drive[3] = '\0';
}
else if ((filename[0] == '\\') && (filename[1] == '\\')) {
strcpy(tmpbuf, filename);
machinename = strtok(tmpbuf, "\\");
sharename = strtok(NULL, "\\");
strcpy(drive, "\\\\");
strcat(drive, machinename);
strcat(drive, "\\");
strcat(drive, sharename);
strcat(drive, "\\");
}
else
return (FALSE);
GetVolumeInformation(drive, NULL, 0, NULL, 0, NULL, FSType,
sizeof(FSType));
if(strcmp(FSType,"NTFS") == 0)
return (TRUE);
else
return (FALSE);
}
isc_result_t
FAT_fsaccess_set(const char *path, isc_fsaccess_t access) {
int mode;
isc_fsaccess_t bits;
mode = 0;
#define SET_AND_CLEAR1(modebit) \
if ((access & bits) != 0) { \
mode |= modebit; \
access &= ~bits; \
}
#define SET_AND_CLEAR(user, group, other) \
SET_AND_CLEAR1(user); \
bits <<= STEP; \
SET_AND_CLEAR1(group); \
bits <<= STEP; \
SET_AND_CLEAR1(other);
bits = ISC_FSACCESS_READ | ISC_FSACCESS_LISTDIRECTORY;
SET_AND_CLEAR(S_IRUSR, S_IRGRP, S_IROTH);
bits = ISC_FSACCESS_WRITE |
ISC_FSACCESS_CREATECHILD |
ISC_FSACCESS_DELETECHILD;
SET_AND_CLEAR(S_IWUSR, S_IWGRP, S_IWOTH);
INSIST(access == 0);
if (_chmod(path, mode) < 0)
return (isc__errno2result(errno));
return (ISC_R_SUCCESS);
}
isc_result_t
NTFS_Access_Control(const char *filename, const char *user, int access,
isc_boolean_t isdir) {
SECURITY_DESCRIPTOR sd;
BYTE aclBuffer[1024];
PACL pacl=(PACL)&aclBuffer;
BYTE sidBuffer[100];
PSID psid=(PSID) &sidBuffer;
DWORD sidBufferSize = sizeof(sidBuffer);
BYTE adminSidBuffer[100];
PSID padminsid=(PSID) &adminSidBuffer;
DWORD adminSidBufferSize = sizeof(adminSidBuffer);
BYTE otherSidBuffer[100];
PSID pothersid=(PSID) &otherSidBuffer;
DWORD otherSidBufferSize = sizeof(otherSidBuffer);
char domainBuffer[100];
DWORD domainBufferSize = sizeof(domainBuffer);
SID_NAME_USE snu;
int errval;
DWORD NTFSbits;
int caccess;
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
return (ISC_R_NOPERM);
if (!InitializeAcl(pacl, sizeof(aclBuffer), ACL_REVISION))
return (ISC_R_NOPERM);
if (!LookupAccountName(0, user, psid, &sidBufferSize, domainBuffer,
&domainBufferSize, &snu))
return (ISC_R_NOPERM);
domainBufferSize = sizeof(domainBuffer);
if (!LookupAccountName(0, "Administrators", padminsid,
&adminSidBufferSize, domainBuffer, &domainBufferSize, &snu)) {
errval = GetLastError();
return (ISC_R_NOPERM);
}
domainBufferSize = sizeof(domainBuffer);
if (!LookupAccountName(0, "Everyone", pothersid,
&otherSidBufferSize, domainBuffer, &domainBufferSize, &snu)) {
errval = GetLastError();
return (ISC_R_NOPERM);
}
caccess = access;
NTFSbits = 0;
if (caccess & ISC_FSACCESS_READ)
NTFSbits |= FILE_GENERIC_READ;
if (caccess & ISC_FSACCESS_WRITE)
NTFSbits |= FILE_GENERIC_WRITE;
if (caccess & ISC_FSACCESS_EXECUTE)
NTFSbits |= FILE_GENERIC_EXECUTE;
if (isdir == ISC_TRUE) {
if (caccess & ISC_FSACCESS_CREATECHILD)
NTFSbits |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE;
if (caccess & ISC_FSACCESS_DELETECHILD)
NTFSbits |= FILE_DELETE_CHILD;
if (caccess & ISC_FSACCESS_LISTDIRECTORY)
NTFSbits |= FILE_LIST_DIRECTORY;
if (caccess & ISC_FSACCESS_ACCESSCHILD)
NTFSbits |= FILE_TRAVERSE;
}
if (NTFSbits == (FILE_GENERIC_READ | FILE_GENERIC_WRITE
| FILE_GENERIC_EXECUTE))
NTFSbits |= FILE_ALL_ACCESS;
NTFSbits |= STANDARD_RIGHTS_ALL;
if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, psid))
return (ISC_R_NOPERM);
if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, padminsid))
return (ISC_R_NOPERM);
caccess = caccess >> STEP;
caccess = caccess >> STEP;
NTFSbits = 0;
if (caccess & ISC_FSACCESS_READ)
NTFSbits |= FILE_GENERIC_READ;
if (caccess & ISC_FSACCESS_WRITE)
NTFSbits |= FILE_GENERIC_WRITE;
if (caccess & ISC_FSACCESS_EXECUTE)
NTFSbits |= FILE_GENERIC_EXECUTE;
if (isdir == TRUE) {
if (caccess & ISC_FSACCESS_CREATECHILD)
NTFSbits |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE;
if (caccess & ISC_FSACCESS_DELETECHILD)
NTFSbits |= FILE_DELETE_CHILD;
if (caccess & ISC_FSACCESS_LISTDIRECTORY)
NTFSbits |= FILE_LIST_DIRECTORY;
if (caccess & ISC_FSACCESS_ACCESSCHILD)
NTFSbits |= FILE_TRAVERSE;
}
if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits,
pothersid))
return (ISC_R_NOPERM);
if (!SetSecurityDescriptorDacl(&sd, TRUE, pacl, FALSE))
return (ISC_R_NOPERM);
if (!SetFileSecurity(filename, DACL_SECURITY_INFORMATION, &sd)) {
return (ISC_R_NOPERM);
}
return(ISC_R_SUCCESS);
}
isc_result_t
NTFS_fsaccess_set(const char *path, isc_fsaccess_t access,
isc_boolean_t isdir){
if (namelen <= 0) {
namelen = sizeof(username);
if (GetUserName(username, &namelen) == 0)
return (ISC_R_FAILURE);
}
return (NTFS_Access_Control(path, username, access, isdir));
}
isc_result_t
isc_fsaccess_set(const char *path, isc_fsaccess_t access) {
struct stat statb;
isc_boolean_t is_dir = ISC_FALSE;
isc_result_t result;
if (stat(path, &statb) != 0)
return (isc__errno2result(errno));
if ((statb.st_mode & S_IFDIR) != 0)
is_dir = ISC_TRUE;
else if ((statb.st_mode & S_IFREG) == 0)
return (ISC_R_INVALIDFILE);
result = check_bad_bits(access, is_dir);
if (result != ISC_R_SUCCESS)
return (result);
if (is_ntfs(path))
return (NTFS_fsaccess_set(path, access, is_dir));
else
return (FAT_fsaccess_set(path, access));
}
isc_result_t
isc_fsaccess_changeowner(const char *filename, const char *user) {
SECURITY_DESCRIPTOR psd;
BYTE sidBuffer[500];
BYTE groupBuffer[500];
PSID psid=(PSID) &sidBuffer;
DWORD sidBufferSize = sizeof(sidBuffer);
char domainBuffer[100];
DWORD domainBufferSize = sizeof(domainBuffer);
SID_NAME_USE snu;
PSID pSidGroup = (PSID) &groupBuffer;
DWORD groupBufferSize = sizeof(groupBuffer);
if (is_ntfs(filename) == FALSE)
return (ISC_R_SUCCESS);
if (!InitializeSecurityDescriptor(&psd, SECURITY_DESCRIPTOR_REVISION))
return (ISC_R_NOPERM);
if (!LookupAccountName(0, user, psid, &sidBufferSize, domainBuffer,
&domainBufferSize, &snu))
return (ISC_R_NOPERM);
domainBufferSize = sizeof(domainBuffer);
if (!LookupAccountName(0, "Administrators", pSidGroup,
&groupBufferSize, domainBuffer, &domainBufferSize, &snu))
return (ISC_R_NOPERM);
if (!SetSecurityDescriptorOwner(&psd, psid, FALSE))
return (ISC_R_NOPERM);
if (!SetSecurityDescriptorGroup(&psd, pSidGroup, FALSE))
return (ISC_R_NOPERM);
if (!SetFileSecurity(filename,
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION,
&psd))
return (ISC_R_NOPERM);
return (ISC_R_SUCCESS);
}