mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-27 09:06:51 -04:00
Added support for NTFS disks
This commit is contained in:
parent
2612cf1a5e
commit
5c4e92b973
1 changed files with 240 additions and 27 deletions
|
|
@ -15,7 +15,7 @@
|
|||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: fsaccess.c,v 1.9 2001/07/09 21:06:07 gson Exp $ */
|
||||
/* $Id: fsaccess.c,v 1.10 2001/11/13 05:07:57 mayer Exp $ */
|
||||
|
||||
/*
|
||||
* Note that Win32 does not have the concept of files having access
|
||||
|
|
@ -34,6 +34,7 @@
|
|||
#include <io.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <isc/file.h>
|
||||
#include <isc/stat.h>
|
||||
|
||||
#include "errno2result.h"
|
||||
|
|
@ -43,25 +44,74 @@
|
|||
*/
|
||||
#include "../fsaccess.c"
|
||||
|
||||
/* Store the user account name locally */
|
||||
static char username[255] = "\0";
|
||||
static DWORD namelen = 0;
|
||||
|
||||
/*
|
||||
* In order to set or retrieve access information, we need to obtain
|
||||
* the File System type. These could be UNC-type shares.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for c:\path\... style, c:/path/... or \\computer\shar\path...
|
||||
* the UNC style file specs
|
||||
*/
|
||||
if (isalpha(filename[0]) && filename[1] == ':' &&
|
||||
(filename[2] == '\\' || filename[2] == '/')) {
|
||||
strncpy(drive, filename, 3);
|
||||
drive[3] = '\0';
|
||||
}
|
||||
|
||||
else if ((filename[0] == '\\') && (filename[1] == '\\')) {
|
||||
/* Find the machine and share name and rebuild the UNC */
|
||||
strcpy(tmpbuf, filename);
|
||||
machinename = strtok(tmpbuf, "\\");
|
||||
sharename = strtok(NULL, "\\");
|
||||
strcpy(drive, "\\\\");
|
||||
strcat(drive, machinename);
|
||||
strcat(drive, "\\");
|
||||
strcat(drive, sharename);
|
||||
strcat(drive, "\\");
|
||||
|
||||
}
|
||||
else /* Not determinable */
|
||||
return (FALSE);
|
||||
|
||||
GetVolumeInformation(drive, NULL, 0, NULL, 0, NULL, FSType,
|
||||
sizeof(FSType));
|
||||
if(strcmp(FSType,"NTFS") == 0)
|
||||
return (TRUE);
|
||||
else
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's not NTFS, we assume that it is FAT and proceed
|
||||
* with almost nothing to do. Only the write flag can be set or
|
||||
* cleared.
|
||||
*/
|
||||
isc_result_t
|
||||
isc_fsaccess_set(const char *path, isc_fsaccess_t access) {
|
||||
struct stat statb;
|
||||
FAT_fsaccess_set(const char *path, isc_fsaccess_t access) {
|
||||
int mode;
|
||||
isc_boolean_t is_dir = ISC_FALSE;
|
||||
isc_fsaccess_t bits;
|
||||
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);
|
||||
|
||||
/*
|
||||
* Done with checking bad bits. Set mode_t.
|
||||
|
|
@ -90,16 +140,6 @@ isc_fsaccess_set(const char *path, isc_fsaccess_t access) {
|
|||
|
||||
SET_AND_CLEAR(S_IWUSR, S_IWGRP, S_IWOTH);
|
||||
|
||||
#ifdef notyet
|
||||
/*
|
||||
* WIN32 doesn't have the concept of execute bits. We leave this here
|
||||
* for when we review this module.
|
||||
*/
|
||||
bits = ISC_FSACCESS_EXECUTE |
|
||||
ISC_FSACCESS_ACCESSCHILD;
|
||||
|
||||
SET_AND_CLEAR(S_IXUSR, S_IXGRP, S_IXOTH);
|
||||
#endif
|
||||
INSIST(access == 0);
|
||||
|
||||
if (_chmod(path, mode) < 0)
|
||||
|
|
@ -107,3 +147,176 @@ isc_fsaccess_set(const char *path, isc_fsaccess_t access) {
|
|||
|
||||
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;
|
||||
|
||||
|
||||
/* Initialize an ACL */
|
||||
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;
|
||||
/* Owner check */
|
||||
|
||||
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;
|
||||
|
||||
/* For directories check the directory-specific bits */
|
||||
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;
|
||||
/*
|
||||
* Owner and Administrator also get STANDARD_RIGHTS_ALL
|
||||
* to ensure that they have full control
|
||||
*/
|
||||
|
||||
NTFSbits |= STANDARD_RIGHTS_ALL;
|
||||
|
||||
/* Add the ACE to the ACL */
|
||||
if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, psid))
|
||||
return (ISC_R_NOPERM);
|
||||
if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, padminsid))
|
||||
return (ISC_R_NOPERM);
|
||||
|
||||
/*
|
||||
* Group is ignored since we can be in multiple groups or no group
|
||||
* and its meaning is not clear on Win32
|
||||
*/
|
||||
|
||||
caccess = caccess >> STEP;
|
||||
|
||||
/*
|
||||
* Other check. We translate this to be the same as Everyone
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/* For directories check the directory-specific bits */
|
||||
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;
|
||||
}
|
||||
/* Add the ACE to the ACL */
|
||||
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){
|
||||
|
||||
/*
|
||||
* For NTFS we first need to get the name of the account under
|
||||
* which BIND is running
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* Determine if this is a FAT or NTFS disk and
|
||||
* call the appropriate function to set the permissions
|
||||
*/
|
||||
if (is_ntfs(path))
|
||||
return (NTFS_fsaccess_set(path, access, is_dir));
|
||||
else
|
||||
return (FAT_fsaccess_set(path, access));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue