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>