Annotation of embedaddon/ntp/lib/isc/win32/fsaccess.c, revision 1.1.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>