Tcl Source Code

Check-in [63315eaf46]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:2974459,2879351,1951574,1852572,1661378,1613456 Revisions to the NativeAccess() routine that queries file permissions on Windows native filesystems. Meant to fix numerous bugs where [file writable|readable|executable] "lies" about what operations are possible, especially when the file resides on a Samba share. Patch cherrypicked off the fix-win-native-access branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | core-8-4-branch
Files: files | file ages | folders
SHA1: 63315eaf46dcbee6118c9b6a73ad1972ba01fb66
User & Date: dgp 2012-02-02 16:44:06
Context
2012-02-02
21:12
[Frq 3464401] Support Unicode 6.1 check-in: 756c93768d user: jan.nijtmans tags: core-8-4-branch
17:21
2974459,2879351,1951574,1852572,1661378,1613456 Revisions to the NativeAccess() routine that queries... check-in: 6203735037 user: dgp tags: core-8-5-branch
16:44
2974459,2879351,1951574,1852572,1661378,1613456 Revisions to the NativeAccess() routine that queries... check-in: 63315eaf46 user: dgp tags: core-8-4-branch
2012-02-01
15:46
merge to bugfix branch Closed-Leaf check-in: 0b276de667 user: dgp tags: fix-win-native-access
2012-01-23
17:43
Backport patch 2834a01435 to prevent test failures from timing matters. check-in: 4d9599f7e5 user: dgp tags: core-8-4-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ChangeLog.











1
2
3
4
5
6
7










2012-01-22  Jan Nijtmans  <[email protected]>

	* tools/uniClass.tcl:    [Frq 3473670]: Various Unicode-related 
	* tools/uniParse.tcl:    speedups/robustness. Enhanced tools to
	* generic/tclUniData.c:  be able to handle characters > 0xffff
	* generic/tclUtf.c:      Done in all branches in order to simplify
	* generic/regc_locale.c: merges for new Unicode versions (such as 6.1)
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2012-02-02  Don Porter  <[email protected]>

	* win/tclWinFile.c:	[Bugs 2974459,2879351,1951574,1852572,
	1661378,1613456]: Revisions to the NativeAccess() routine that
	queries file permissions on Windows native filesystems.  Meant to
	fix numerous bugs where [file writable|readable|executable] "lies"
	about what operations are possible, especially when the file resides
	on a Samba share.  Patch cherrypicked off the fix-win-native-access
	branch.

2012-01-22  Jan Nijtmans  <[email protected]>

	* tools/uniClass.tcl:    [Frq 3473670]: Various Unicode-related 
	* tools/uniParse.tcl:    speedups/robustness. Enhanced tools to
	* generic/tclUniData.c:  be able to handle characters > 0xffff
	* generic/tclUtf.c:      Done in all branches in order to simplify
	* generic/regc_locale.c: merges for new Unicode versions (such as 6.1)

Changes to win/tclWinFile.c.

1338
1339
1340
1341
1342
1343
1344








1345
1346
1347

1348
1349
1350




1351
1352
1353
1354
1355
1356
1357
1358
1359
	 * File doesn't exist.
	 */

	TclWinConvertError(GetLastError());
	return -1;
    }









    if ((mode & W_OK) 
      && (tclWinProcs->getFileSecurityProc == NULL)
      && (attr & FILE_ATTRIBUTE_READONLY)) {

	/*
	 * We don't have the advanced 'getFileSecurityProc', and
	 * our attributes say the file is not writable.  If we




	 * do have 'getFileSecurityProc', we'll do a more
	 * robust XP-related check below.
	 */

	Tcl_SetErrno(EACCES);
	return -1;
    }

    if (mode & X_OK) {







>
>
>
>
>
>
>
>
|
<
|
>

<
|
>
>
>
>
|
|







1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353

1354
1355
1356

1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
	 * File doesn't exist.
	 */

	TclWinConvertError(GetLastError());
	return -1;
    }

    if (mode == F_OK) {
	/*
	 * File exists, nothing else to check.
	 */

	return 0;
    }

    if ((mode & W_OK)

	&& (attr & FILE_ATTRIBUTE_READONLY)
	&& !(attr & FILE_ATTRIBUTE_DIRECTORY)) {
	/*

	 * The attributes say the file is not writable.	 If the file is a
	 * regular file (i.e., not a directory), then the file is not
	 * writable, full stop.	 For directories, the read-only bit is
	 * (mostly) ignored by Windows, so we can't ascertain anything about
	 * directory access from the attrib data.  However, if we have the
	 * advanced 'getFileSecurityProc', then more robust ACL checks
	 * will be done below.
	 */

	Tcl_SetErrno(EACCES);
	return -1;
    }

    if (mode & X_OK) {
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384



1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401

1402
1403
1404
1405
1406
1407
1408
    }

    /*
     * It looks as if the permissions are ok, but if we are on NT, 2000 or XP,
     * we have a more complex permissions structure so we try to check that.
     * The code below is remarkably complex for such a simple thing as finding
     * what permissions the OS has set for a file.
     *
     * If we are simply checking for file existence, then we don't need all
     * these complications (which are really quite slow: with this code 'file
     * readable' is 5-6 times slower than 'file exists').
     */

    if ((mode != F_OK) && (tclWinProcs->getFileSecurityProc != NULL)) {
	SECURITY_DESCRIPTOR *sdPtr = NULL;
	unsigned long size;



	GENERIC_MAPPING genMap;
	HANDLE hToken = NULL;
	DWORD desiredAccess = 0;
	DWORD grantedAccess = 0;
	BOOL accessYesNo = FALSE;
	PRIVILEGE_SET privSet;
	DWORD privSetSize = sizeof(PRIVILEGE_SET);
	int error;

	/*
	 * First find out how big the buffer needs to be
	 */

	size = 0;
	(*tclWinProcs->getFileSecurityProc)(nativePath,
		OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
		| DACL_SECURITY_INFORMATION, 0, 0, &size);


	/*
	 * Should have failed with ERROR_INSUFFICIENT_BUFFER
	 */

	error = GetLastError();
	if (error != ERROR_INSUFFICIENT_BUFFER) {







<
<
<
<


|


>
>
>
















|
>







1380
1381
1382
1383
1384
1385
1386




1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
    }

    /*
     * It looks as if the permissions are ok, but if we are on NT, 2000 or XP,
     * we have a more complex permissions structure so we try to check that.
     * The code below is remarkably complex for such a simple thing as finding
     * what permissions the OS has set for a file.




     */

    if (tclWinProcs->getFileSecurityProc != NULL) {
	SECURITY_DESCRIPTOR *sdPtr = NULL;
	unsigned long size;
	SID *pSid = 0;
	BOOL SidDefaulted;
	SID_IDENTIFIER_AUTHORITY samba_unmapped = { 0, 0, 0, 0, 0, 22 };
	GENERIC_MAPPING genMap;
	HANDLE hToken = NULL;
	DWORD desiredAccess = 0;
	DWORD grantedAccess = 0;
	BOOL accessYesNo = FALSE;
	PRIVILEGE_SET privSet;
	DWORD privSetSize = sizeof(PRIVILEGE_SET);
	int error;

	/*
	 * First find out how big the buffer needs to be
	 */

	size = 0;
	(*tclWinProcs->getFileSecurityProc)(nativePath,
		OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
		| DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION,
		0, 0, &size);

	/*
	 * Should have failed with ERROR_INSUFFICIENT_BUFFER
	 */

	error = GetLastError();
	if (error != ERROR_INSUFFICIENT_BUFFER) {
1427
1428
1429
1430
1431
1432
1433
1434

1435
1436
1437
1438
1439
1440




















1441
1442
1443
1444
1445
1446
1447

	/*
	 * Call GetFileSecurity() for real
	 */

	if (!(*tclWinProcs->getFileSecurityProc)(nativePath,
		OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
		| DACL_SECURITY_INFORMATION, sdPtr, size, &size)) {

	    /*
	     * Error getting owner SD
	     */

	    goto accessError;
	}





















	/*
	 * Perform security impersonation of the user and open the
	 * resulting thread token.
	 */

	if (!(*tclWinProcs->impersonateSelfProc)(SecurityImpersonation)) {







|
>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479

	/*
	 * Call GetFileSecurity() for real
	 */

	if (!(*tclWinProcs->getFileSecurityProc)(nativePath,
		OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
		| DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION,
		sdPtr, size, &size)) {
	    /*
	     * Error getting owner SD
	     */

	    goto accessError;
	}

	/*
	 * As of Samba 3.0.23 (10-Jul-2006), unmapped users and groups are
	 * assigned to SID domains S-1-22-1 and S-1-22-2, where "22" is the
	 * top-level authority.	 If the file owner and group is unmapped then
	 * the ACL access check below will only test against world access,
	 * which is likely to be more restrictive than the actual access
	 * restrictions.  Since the ACL tests are more likely wrong than
	 * right, skip them.  Moreover, the unix owner access permissions are
	 * usually mapped to the Windows attributes, so if the user is the
	 * file owner then the attrib checks above are correct (as far as they
	 * go).
	 */

	if(!GetSecurityDescriptorOwner(sdPtr,&pSid,&SidDefaulted) ||
	   memcmp(GetSidIdentifierAuthority(pSid),&samba_unmapped,
		  sizeof(SID_IDENTIFIER_AUTHORITY))==0) {
	    HeapFree(GetProcessHeap(), 0, sdPtr);
	    return 0; /* Attrib tests say access allowed. */
	}

	/*
	 * Perform security impersonation of the user and open the
	 * resulting thread token.
	 */

	if (!(*tclWinProcs->impersonateSelfProc)(SecurityImpersonation)) {
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534

	HeapFree(GetProcessHeap (), 0, sdPtr);
	CloseHandle(hToken);
	if (!accessYesNo) {
	    Tcl_SetErrno(EACCES);
	    return -1;
	}
	/*
	 * For directories the above checks are ok.  For files, though,
	 * we must still check the 'attr' value.
	 */
	if ((mode & W_OK)
	  && !(attr & FILE_ATTRIBUTE_DIRECTORY)
	  && (attr & FILE_ATTRIBUTE_READONLY)) {
	    Tcl_SetErrno(EACCES);
	    return -1;
	}
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *







<
<
<
<
<
<
<
<
<
<







1543
1544
1545
1546
1547
1548
1549










1550
1551
1552
1553
1554
1555
1556

	HeapFree(GetProcessHeap (), 0, sdPtr);
	CloseHandle(hToken);
	if (!accessYesNo) {
	    Tcl_SetErrno(EACCES);
	    return -1;
	}










    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *