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>