Annotation of embedaddon/ntp/lib/isc/win32/fsaccess.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
! 3: * Copyright (C) 2000-2002 Internet Software Consortium.
! 4: *
! 5: * Permission to use, copy, modify, and/or distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
! 10: * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
! 11: * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
! 12: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
! 13: * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
! 14: * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
! 15: * PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17:
! 18: /* $Id: fsaccess.c,v 1.15 2007/06/19 23:47:19 tbox Exp $ */
! 19:
! 20: /*
! 21: * Note that Win32 does not have the concept of files having access
! 22: * and ownership bits. The FAT File system only has a readonly flag
! 23: * for everyone and that's all. NTFS uses ACL's which is a totally
! 24: * different concept of controlling access.
! 25: *
! 26: * This code needs to be revisited to set up proper access control for
! 27: * NTFS file systems. Nothing can be done for FAT file systems.
! 28: */
! 29:
! 30: #include <config.h>
! 31:
! 32: #include <aclapi.h>
! 33:
! 34: #include <sys/types.h>
! 35: #include <sys/stat.h>
! 36: #include <io.h>
! 37: #include <errno.h>
! 38:
! 39: #include <isc/file.h>
! 40: #include <isc/stat.h>
! 41:
! 42: #include "errno2result.h"
! 43:
! 44: /*
! 45: * The OS-independent part of the API is in lib/isc.
! 46: */
! 47: #include "../fsaccess.c"
! 48:
! 49: /* Store the user account name locally */
! 50: static char username[255] = "\0";
! 51: static DWORD namelen = 0;
! 52:
! 53: /*
! 54: * In order to set or retrieve access information, we need to obtain
! 55: * the File System type. These could be UNC-type shares.
! 56: */
! 57:
! 58: BOOL
! 59: is_ntfs(const char * file) {
! 60:
! 61: char drive[255];
! 62: char FSType[20];
! 63: char tmpbuf[256];
! 64: char *machinename;
! 65: char *sharename;
! 66: char filename[1024];
! 67:
! 68: REQUIRE(filename != NULL);
! 69:
! 70: if (isc_file_absolutepath(file, filename,
! 71: sizeof(filename)) != ISC_R_SUCCESS) {
! 72: return (FALSE);
! 73: }
! 74:
! 75: /*
! 76: * Look for c:\path\... style, c:/path/... or \\computer\shar\path...
! 77: * the UNC style file specs
! 78: */
! 79: if (isalpha(filename[0]) && filename[1] == ':' &&
! 80: (filename[2] == '\\' || filename[2] == '/')) {
! 81: strncpy(drive, filename, 3);
! 82: drive[3] = '\0';
! 83: }
! 84:
! 85: else if ((filename[0] == '\\') && (filename[1] == '\\')) {
! 86: /* Find the machine and share name and rebuild the UNC */
! 87: strcpy(tmpbuf, filename);
! 88: machinename = strtok(tmpbuf, "\\");
! 89: sharename = strtok(NULL, "\\");
! 90: strcpy(drive, "\\\\");
! 91: strcat(drive, machinename);
! 92: strcat(drive, "\\");
! 93: strcat(drive, sharename);
! 94: strcat(drive, "\\");
! 95:
! 96: }
! 97: else /* Not determinable */
! 98: return (FALSE);
! 99:
! 100: GetVolumeInformation(drive, NULL, 0, NULL, 0, NULL, FSType,
! 101: sizeof(FSType));
! 102: if(strcmp(FSType,"NTFS") == 0)
! 103: return (TRUE);
! 104: else
! 105: return (FALSE);
! 106: }
! 107:
! 108: /*
! 109: * If it's not NTFS, we assume that it is FAT and proceed
! 110: * with almost nothing to do. Only the write flag can be set or
! 111: * cleared.
! 112: */
! 113: isc_result_t
! 114: FAT_fsaccess_set(const char *path, isc_fsaccess_t access) {
! 115: int mode;
! 116: isc_fsaccess_t bits;
! 117:
! 118: /*
! 119: * Done with checking bad bits. Set mode_t.
! 120: */
! 121: mode = 0;
! 122:
! 123: #define SET_AND_CLEAR1(modebit) \
! 124: if ((access & bits) != 0) { \
! 125: mode |= modebit; \
! 126: access &= ~bits; \
! 127: }
! 128: #define SET_AND_CLEAR(user, group, other) \
! 129: SET_AND_CLEAR1(user); \
! 130: bits <<= STEP; \
! 131: SET_AND_CLEAR1(group); \
! 132: bits <<= STEP; \
! 133: SET_AND_CLEAR1(other);
! 134:
! 135: bits = ISC_FSACCESS_READ | ISC_FSACCESS_LISTDIRECTORY;
! 136:
! 137: SET_AND_CLEAR(S_IRUSR, S_IRGRP, S_IROTH);
! 138:
! 139: bits = ISC_FSACCESS_WRITE |
! 140: ISC_FSACCESS_CREATECHILD |
! 141: ISC_FSACCESS_DELETECHILD;
! 142:
! 143: SET_AND_CLEAR(S_IWUSR, S_IWGRP, S_IWOTH);
! 144:
! 145: INSIST(access == 0);
! 146:
! 147: if (_chmod(path, mode) < 0)
! 148: return (isc__errno2result(errno));
! 149:
! 150: return (ISC_R_SUCCESS);
! 151: }
! 152:
! 153: isc_result_t
! 154: NTFS_Access_Control(const char *filename, const char *user, int access,
! 155: isc_boolean_t isdir) {
! 156: SECURITY_DESCRIPTOR sd;
! 157: BYTE aclBuffer[1024];
! 158: PACL pacl=(PACL)&aclBuffer;
! 159: BYTE sidBuffer[100];
! 160: PSID psid=(PSID) &sidBuffer;
! 161: DWORD sidBufferSize = sizeof(sidBuffer);
! 162: BYTE adminSidBuffer[100];
! 163: PSID padminsid=(PSID) &adminSidBuffer;
! 164: DWORD adminSidBufferSize = sizeof(adminSidBuffer);
! 165: BYTE otherSidBuffer[100];
! 166: PSID pothersid=(PSID) &otherSidBuffer;
! 167: DWORD otherSidBufferSize = sizeof(otherSidBuffer);
! 168: char domainBuffer[100];
! 169: DWORD domainBufferSize = sizeof(domainBuffer);
! 170: SID_NAME_USE snu;
! 171: int errval;
! 172: DWORD NTFSbits;
! 173: int caccess;
! 174:
! 175:
! 176: /* Initialize an ACL */
! 177: if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
! 178: return (ISC_R_NOPERM);
! 179: if (!InitializeAcl(pacl, sizeof(aclBuffer), ACL_REVISION))
! 180: return (ISC_R_NOPERM);
! 181: if (!LookupAccountName(0, user, psid, &sidBufferSize, domainBuffer,
! 182: &domainBufferSize, &snu))
! 183: return (ISC_R_NOPERM);
! 184: domainBufferSize = sizeof(domainBuffer);
! 185: if (!LookupAccountName(0, "Administrators", padminsid,
! 186: &adminSidBufferSize, domainBuffer, &domainBufferSize, &snu)) {
! 187: errval = GetLastError();
! 188: return (ISC_R_NOPERM);
! 189: }
! 190: domainBufferSize = sizeof(domainBuffer);
! 191: if (!LookupAccountName(0, "Everyone", pothersid,
! 192: &otherSidBufferSize, domainBuffer, &domainBufferSize, &snu)) {
! 193: errval = GetLastError();
! 194: return (ISC_R_NOPERM);
! 195: }
! 196:
! 197: caccess = access;
! 198: /* Owner check */
! 199:
! 200: NTFSbits = 0;
! 201: if (caccess & ISC_FSACCESS_READ)
! 202: NTFSbits |= FILE_GENERIC_READ;
! 203: if (caccess & ISC_FSACCESS_WRITE)
! 204: NTFSbits |= FILE_GENERIC_WRITE;
! 205: if (caccess & ISC_FSACCESS_EXECUTE)
! 206: NTFSbits |= FILE_GENERIC_EXECUTE;
! 207:
! 208: /* For directories check the directory-specific bits */
! 209: if (isdir == ISC_TRUE) {
! 210: if (caccess & ISC_FSACCESS_CREATECHILD)
! 211: NTFSbits |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE;
! 212: if (caccess & ISC_FSACCESS_DELETECHILD)
! 213: NTFSbits |= FILE_DELETE_CHILD;
! 214: if (caccess & ISC_FSACCESS_LISTDIRECTORY)
! 215: NTFSbits |= FILE_LIST_DIRECTORY;
! 216: if (caccess & ISC_FSACCESS_ACCESSCHILD)
! 217: NTFSbits |= FILE_TRAVERSE;
! 218: }
! 219:
! 220: if (NTFSbits == (FILE_GENERIC_READ | FILE_GENERIC_WRITE
! 221: | FILE_GENERIC_EXECUTE))
! 222: NTFSbits |= FILE_ALL_ACCESS;
! 223: /*
! 224: * Owner and Administrator also get STANDARD_RIGHTS_ALL
! 225: * to ensure that they have full control
! 226: */
! 227:
! 228: NTFSbits |= STANDARD_RIGHTS_ALL;
! 229:
! 230: /* Add the ACE to the ACL */
! 231: if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, psid))
! 232: return (ISC_R_NOPERM);
! 233: if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, padminsid))
! 234: return (ISC_R_NOPERM);
! 235:
! 236: /*
! 237: * Group is ignored since we can be in multiple groups or no group
! 238: * and its meaning is not clear on Win32
! 239: */
! 240:
! 241: caccess = caccess >> STEP;
! 242:
! 243: /*
! 244: * Other check. We translate this to be the same as Everyone
! 245: */
! 246:
! 247: caccess = caccess >> STEP;
! 248:
! 249: NTFSbits = 0;
! 250: if (caccess & ISC_FSACCESS_READ)
! 251: NTFSbits |= FILE_GENERIC_READ;
! 252: if (caccess & ISC_FSACCESS_WRITE)
! 253: NTFSbits |= FILE_GENERIC_WRITE;
! 254: if (caccess & ISC_FSACCESS_EXECUTE)
! 255: NTFSbits |= FILE_GENERIC_EXECUTE;
! 256:
! 257: /* For directories check the directory-specific bits */
! 258: if (isdir == TRUE) {
! 259: if (caccess & ISC_FSACCESS_CREATECHILD)
! 260: NTFSbits |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE;
! 261: if (caccess & ISC_FSACCESS_DELETECHILD)
! 262: NTFSbits |= FILE_DELETE_CHILD;
! 263: if (caccess & ISC_FSACCESS_LISTDIRECTORY)
! 264: NTFSbits |= FILE_LIST_DIRECTORY;
! 265: if (caccess & ISC_FSACCESS_ACCESSCHILD)
! 266: NTFSbits |= FILE_TRAVERSE;
! 267: }
! 268: /* Add the ACE to the ACL */
! 269: if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits,
! 270: pothersid))
! 271: return (ISC_R_NOPERM);
! 272:
! 273: if (!SetSecurityDescriptorDacl(&sd, TRUE, pacl, FALSE))
! 274: return (ISC_R_NOPERM);
! 275: if (!SetFileSecurity(filename, DACL_SECURITY_INFORMATION, &sd)) {
! 276: return (ISC_R_NOPERM);
! 277: }
! 278:
! 279: return(ISC_R_SUCCESS);
! 280: }
! 281:
! 282: isc_result_t
! 283: NTFS_fsaccess_set(const char *path, isc_fsaccess_t access,
! 284: isc_boolean_t isdir){
! 285:
! 286: /*
! 287: * For NTFS we first need to get the name of the account under
! 288: * which BIND is running
! 289: */
! 290: if (namelen <= 0) {
! 291: namelen = sizeof(username);
! 292: if (GetUserName(username, &namelen) == 0)
! 293: return (ISC_R_FAILURE);
! 294: }
! 295: return (NTFS_Access_Control(path, username, access, isdir));
! 296: }
! 297:
! 298: isc_result_t
! 299: isc_fsaccess_set(const char *path, isc_fsaccess_t access) {
! 300: struct stat statb;
! 301: isc_boolean_t is_dir = ISC_FALSE;
! 302: isc_result_t result;
! 303:
! 304: if (stat(path, &statb) != 0)
! 305: return (isc__errno2result(errno));
! 306:
! 307: if ((statb.st_mode & S_IFDIR) != 0)
! 308: is_dir = ISC_TRUE;
! 309: else if ((statb.st_mode & S_IFREG) == 0)
! 310: return (ISC_R_INVALIDFILE);
! 311:
! 312: result = check_bad_bits(access, is_dir);
! 313: if (result != ISC_R_SUCCESS)
! 314: return (result);
! 315:
! 316: /*
! 317: * Determine if this is a FAT or NTFS disk and
! 318: * call the appropriate function to set the permissions
! 319: */
! 320: if (is_ntfs(path))
! 321: return (NTFS_fsaccess_set(path, access, is_dir));
! 322: else
! 323: return (FAT_fsaccess_set(path, access));
! 324: }
! 325:
! 326: isc_result_t
! 327: isc_fsaccess_changeowner(const char *filename, const char *user) {
! 328: SECURITY_DESCRIPTOR psd;
! 329: BYTE sidBuffer[500];
! 330: BYTE groupBuffer[500];
! 331: PSID psid=(PSID) &sidBuffer;
! 332: DWORD sidBufferSize = sizeof(sidBuffer);
! 333: char domainBuffer[100];
! 334: DWORD domainBufferSize = sizeof(domainBuffer);
! 335: SID_NAME_USE snu;
! 336: PSID pSidGroup = (PSID) &groupBuffer;
! 337: DWORD groupBufferSize = sizeof(groupBuffer);
! 338:
! 339:
! 340: /*
! 341: * Determine if this is a FAT or NTFS disk and
! 342: * call the appropriate function to set the ownership
! 343: * FAT disks do not have ownership attributes so it's
! 344: * a noop.
! 345: */
! 346: if (is_ntfs(filename) == FALSE)
! 347: return (ISC_R_SUCCESS);
! 348:
! 349: if (!InitializeSecurityDescriptor(&psd, SECURITY_DESCRIPTOR_REVISION))
! 350: return (ISC_R_NOPERM);
! 351:
! 352: if (!LookupAccountName(0, user, psid, &sidBufferSize, domainBuffer,
! 353: &domainBufferSize, &snu))
! 354: return (ISC_R_NOPERM);
! 355:
! 356: /* Make sure administrators can get to it */
! 357: domainBufferSize = sizeof(domainBuffer);
! 358: if (!LookupAccountName(0, "Administrators", pSidGroup,
! 359: &groupBufferSize, domainBuffer, &domainBufferSize, &snu))
! 360: return (ISC_R_NOPERM);
! 361:
! 362: if (!SetSecurityDescriptorOwner(&psd, psid, FALSE))
! 363: return (ISC_R_NOPERM);
! 364:
! 365: if (!SetSecurityDescriptorGroup(&psd, pSidGroup, FALSE))
! 366: return (ISC_R_NOPERM);
! 367:
! 368: if (!SetFileSecurity(filename,
! 369: OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION,
! 370: &psd))
! 371: return (ISC_R_NOPERM);
! 372:
! 373: return (ISC_R_SUCCESS);
! 374: }
! 375:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>