You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by su...@apache.org on 2012/11/09 18:49:21 UTC
svn commit: r1407560 - in /hadoop/common/branches/branch-1-win: ./
src/test/org/apache/hadoop/util/ src/winutils/ src/winutils/include/
Author: suresh
Date: Fri Nov 9 17:49:20 2012
New Revision: 1407560
URL: http://svn.apache.org/viewvc?rev=1407560&view=rev
Log:
HADOOP-9006. Winutils should keep Administrators privileges intact. Contributed by Chuan Liu.
Modified:
hadoop/common/branches/branch-1-win/CHANGES.branch-1-win.txt
hadoop/common/branches/branch-1-win/src/test/org/apache/hadoop/util/TestWinUtils.java
hadoop/common/branches/branch-1-win/src/winutils/chmod.c
hadoop/common/branches/branch-1-win/src/winutils/chown.c
hadoop/common/branches/branch-1-win/src/winutils/include/winutils.h
hadoop/common/branches/branch-1-win/src/winutils/libwinutils.c
hadoop/common/branches/branch-1-win/src/winutils/ls.c
hadoop/common/branches/branch-1-win/src/winutils/main.c
hadoop/common/branches/branch-1-win/src/winutils/symlink.c
Modified: hadoop/common/branches/branch-1-win/CHANGES.branch-1-win.txt
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-1-win/CHANGES.branch-1-win.txt?rev=1407560&r1=1407559&r2=1407560&view=diff
==============================================================================
--- hadoop/common/branches/branch-1-win/CHANGES.branch-1-win.txt (original)
+++ hadoop/common/branches/branch-1-win/CHANGES.branch-1-win.txt Fri Nov 9 17:49:20 2012
@@ -208,3 +208,6 @@ Branch-hadoop-1-win - unreleased
HADOOP-9007. TestJobStatusPersistency.testJobStoreDisablingWithInvalidPath
failure. (Chuan Liu via suresh)
+
+ HADOOP-9006. Winutils should keep Administrators privileges intact.
+ (Chuan Liu via suresh)
Modified: hadoop/common/branches/branch-1-win/src/test/org/apache/hadoop/util/TestWinUtils.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-1-win/src/test/org/apache/hadoop/util/TestWinUtils.java?rev=1407560&r1=1407559&r2=1407560&view=diff
==============================================================================
--- hadoop/common/branches/branch-1-win/src/test/org/apache/hadoop/util/TestWinUtils.java (original)
+++ hadoop/common/branches/branch-1-win/src/test/org/apache/hadoop/util/TestWinUtils.java Fri Nov 9 17:49:20 2012
@@ -168,6 +168,27 @@ public class TestWinUtils {
assertFalse(a.exists());
}
+ private void testNewFileChmodInternal(String expectedPerm) throws IOException {
+ // Create a new directory
+ File dir = new File(TEST_DIR, "dir1");
+
+ assertTrue(dir.mkdir());
+
+ // Set permission use chmod
+ chmod("755", dir);
+
+ // Create a child file in the directory
+ File child = new File(dir, "file1");
+ assertTrue(child.createNewFile());
+
+ // Verify the child file has correct permissions
+ assertPermissions(child, expectedPerm);
+
+ child.delete();
+ dir.delete();
+ assertFalse(dir.exists());
+ }
+
private void testChmodInternalR(String mode, String expectedPerm,
String expectedPermx) throws IOException {
// Setup test folder hierarchy
@@ -281,6 +302,9 @@ public class TestWinUtils {
testChmodInternalR("u-x,g+rw", "rw-rw----", "rw-rw----");
testChmodInternalR("u-x,g+rwx-x,o=u", "rw-rw-rw-", "rw-rw-rw-");
testChmodInternalR("a+rX", "rw-r--r--", "rwxr-xr-x");
+
+ // Test a new file created in a chmod'ed directory has expected permission
+ testNewFileChmodInternal("-rwx------");
}
private void chown(String userGroup, File file) throws IOException {
Modified: hadoop/common/branches/branch-1-win/src/winutils/chmod.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-1-win/src/winutils/chmod.c?rev=1407560&r1=1407559&r2=1407560&view=diff
==============================================================================
--- hadoop/common/branches/branch-1-win/src/winutils/chmod.c (original)
+++ hadoop/common/branches/branch-1-win/src/winutils/chmod.c Fri Nov 9 17:49:20 2012
@@ -263,6 +263,7 @@ static BOOL ChangeFileModeRecursively(__
do
{
LPWSTR filename = NULL;
+ LPWSTR longFilename = NULL;
size_t filenameSize = 0;
if (wcscmp(ffd.cFileName, L".") == 0 ||
@@ -285,13 +286,25 @@ static BOOL ChangeFileModeRecursively(__
goto ChangeFileModeRecursivelyEnd;
}
- if(!ChangeFileModeRecursively(filename, mode, actions))
+ // The child fileanme is not prepended with long path prefix.
+ // Convert the filename to long path format.
+ //
+ dwRtnCode = ConvertToLongPath(filename, &longFilename);
+ LocalFree(filename);
+ if (dwRtnCode != ERROR_SUCCESS)
{
- LocalFree(filename);
+ ReportErrorCode(L"ConvertToLongPath", dwRtnCode);
+ LocalFree(longFilename);
goto ChangeFileModeRecursivelyEnd;
}
- LocalFree(filename);
+ if(!ChangeFileModeRecursively(longFilename, mode, actions))
+ {
+ LocalFree(longFilename);
+ goto ChangeFileModeRecursivelyEnd;
+ }
+
+ LocalFree(longFilename);
} while (FindNextFileW(hFind, &ffd));
@@ -877,4 +890,4 @@ Change the mode of the FILE to MODE.\n\
\n\
Each MODE is of the form '[ugoa]*([-+=]([rwxX]*|[ugo]))+'.\n",
program, program);
-}
\ No newline at end of file
+}
Modified: hadoop/common/branches/branch-1-win/src/winutils/chown.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-1-win/src/winutils/chown.c?rev=1407560&r1=1407559&r2=1407560&view=diff
==============================================================================
--- hadoop/common/branches/branch-1-win/src/winutils/chown.c (original)
+++ hadoop/common/branches/branch-1-win/src/winutils/chown.c Fri Nov 9 17:49:20 2012
@@ -18,266 +18,92 @@
#include "winutils.h"
//----------------------------------------------------------------------------
-// Function: GetNewAclSize
+// Function: ChangeFileOwnerBySid
//
// Description:
-// Compute the extra size of the new ACL if we replace the old owner Sid with
-// the new owner Sid.
+// Change a file or directory ownership by giving new owner and group SIDs
//
// Returns:
-// The extra size needed for the new ACL compared with the ACL passed in. If
-// the value is negative, it means the size of the new ACL could be reduced.
+// ERROR_SUCCESS: on success
+// Error code: otherwise
//
// Notes:
+// This function is long path safe, i.e. the path will be converted to long
+// path format if not already converted. So the caller does not need to do
+// the converstion before calling the method.
//
-static BOOL GetNewAclSizeDelta(__in PACL pDACL,
- __in PSID pOldOwnerSid, __in PSID pNewOwnerSid, __out PLONG pDelta)
+static DWORD ChangeFileOwnerBySid(__in LPCWSTR path,
+ __in_opt PSID pNewOwnerSid, __in_opt PSID pNewGroupSid)
{
- PVOID pAce = NULL;
- DWORD i;
- PSID aceSid = NULL;
- ACE_HEADER *aceHeader = NULL;
- PACCESS_ALLOWED_ACE accessAllowedAce = NULL;
- PACCESS_DENIED_ACE accessDenieddAce = NULL;
-
- assert(pDACL != NULL && pNewOwnerSid != NULL &&
- pOldOwnerSid != NULL && pDelta != NULL);
-
- *pDelta = 0;
- for (i = 0; i < pDACL->AceCount; i++)
- {
- if (!GetAce(pDACL, i, &pAce))
- {
- ReportErrorCode(L"GetAce", GetLastError());
- return FALSE;
- }
-
- aceHeader = (ACE_HEADER *) pAce;
- if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
- {
- accessAllowedAce = (PACCESS_ALLOWED_ACE) pAce;
- aceSid = (PSID) &accessAllowedAce->SidStart;
- }
- else if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
- {
- accessDenieddAce = (PACCESS_DENIED_ACE) pAce;
- aceSid = (PSID) &accessDenieddAce->SidStart;
- }
- else
- {
- continue;
- }
-
- if (EqualSid(pOldOwnerSid, aceSid))
- {
- *pDelta += GetLengthSid(pNewOwnerSid) - GetLengthSid(pOldOwnerSid);
- }
- }
-
- return TRUE;
-}
-
-//----------------------------------------------------------------------------
-// Function: AddNewAce
-//
-// Description:
-// Add an Ace of new owner to the new ACL
-//
-// Returns:
-// TRUE: on success
-//
-// Notes:
-// The Ace type should be either ACCESS_ALLOWED_ACE or ACCESS_DENIED_ACE
-//
-static BOOL AddNewAce(PACL pNewDACL, PVOID pOldAce,
- PSID pOwnerSid, PSID pUserSid)
-{
- PVOID pNewAce = NULL;
- DWORD newAceSize = 0;
-
- assert(pNewDACL != NULL && pOldAce != NULL &&
- pOwnerSid != NULL && pUserSid != NULL);
- assert(((PACE_HEADER)pOldAce)->AceType == ACCESS_ALLOWED_ACE_TYPE ||
- ((PACE_HEADER)pOldAce)->AceType == ACCESS_DENIED_ACE_TYPE);
+ LPWSTR longPathName = NULL;
+ INT oldMode = 0;
- newAceSize = ((PACE_HEADER)pOldAce)->AceSize +
- GetLengthSid(pUserSid) - GetLengthSid(pOwnerSid);
- pNewAce = LocalAlloc(LPTR, newAceSize);
- if (pNewAce == NULL)
- {
- ReportErrorCode(L"LocalAlloc", GetLastError());
- return FALSE;
- }
+ SECURITY_INFORMATION securityInformation = 0;
- ((PACE_HEADER)pNewAce)->AceType = ((PACE_HEADER) pOldAce)->AceType;
- ((PACE_HEADER)pNewAce)->AceFlags = ((PACE_HEADER) pOldAce)->AceFlags;
- ((PACE_HEADER)pNewAce)->AceSize = (WORD) newAceSize;
+ DWORD dwRtnCode = ERROR_SUCCESS;
- if (((PACE_HEADER)pOldAce)->AceType == ACCESS_ALLOWED_ACE_TYPE)
- {
- ((PACCESS_ALLOWED_ACE)pNewAce)->Mask = ((PACCESS_ALLOWED_ACE)pOldAce)->Mask;
- if (!CopySid(GetLengthSid(pUserSid),
- &((PACCESS_ALLOWED_ACE) pNewAce)->SidStart, pUserSid))
- {
- ReportErrorCode(L"CopySid", GetLastError());
- LocalFree(pNewAce);
- return FALSE;
- }
- }
- else
- {
- ((PACCESS_DENIED_ACE)pNewAce)->Mask = ((PACCESS_DENIED_ACE)pOldAce)->Mask;
- if (!CopySid(GetLengthSid(pUserSid),
- &((PACCESS_DENIED_ACE) pNewAce)->SidStart, pUserSid))
- {
- ReportErrorCode(L"CopySid", GetLastError());
- LocalFree(pNewAce);
- return FALSE;
- }
- }
-
- if (!AddAce(pNewDACL, ACL_REVISION, MAXDWORD,
- pNewAce, ((PACE_HEADER)pNewAce)->AceSize))
+ // Convert the path the the long path
+ //
+ dwRtnCode = ConvertToLongPath(path, &longPathName);
+ if (dwRtnCode != ERROR_SUCCESS)
{
- ReportErrorCode(L"AddAce", GetLastError());
- LocalFree(pNewAce);
- return FALSE;
+ goto ChangeFileOwnerByNameEnd;
}
- LocalFree(pNewAce);
- return TRUE;
-}
-
-//----------------------------------------------------------------------------
-// Function: CreateDaclForNewOwner
-//
-// Description:
-// Create a new DACL for the new owner
-//
-// Returns:
-// TRUE: on success
-//
-// Notes:
-// Caller needs to destroy the memory of the new DACL by calling LocalFree()
-//
-static BOOL CreateDaclForNewOwner(
- __in PACL pDACL,
- __in_opt PSID pOldOwnerSid,
- __in_opt PSID pNewOwnerSid,
- __in_opt PSID pOldGroupSid,
- __in_opt PSID pNewGroupSid,
- __out PACL *ppNewDACL)
-{
- PSID aceSid = NULL;
- PACE_HEADER aceHeader = NULL;
- PACCESS_ALLOWED_ACE accessAllowedAce = NULL;
- PACCESS_DENIED_ACE accessDenieddAce = NULL;
- PVOID pAce = NULL;
- ACL_SIZE_INFORMATION aclSizeInfo;
- LONG delta = 0;
- DWORD dwNewAclSize = 0;
- DWORD dwRtnCode = 0;
- DWORD i;
-
- assert(pDACL != NULL && ppNewDACL != NULL);
- assert(pOldOwnerSid != NULL && pOldGroupSid != NULL);
- assert(pNewOwnerSid != NULL || pNewGroupSid != NULL);
-
- if (!GetAclInformation(pDACL, (LPVOID)&aclSizeInfo,
- sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
+ // Get a pointer to the existing owner information and DACL
+ //
+ dwRtnCode = FindFileOwnerAndPermission(longPathName, NULL, NULL, &oldMode);
+ if (dwRtnCode != ERROR_SUCCESS)
{
- ReportErrorCode(L"GetAclInformation", GetLastError());
- return FALSE;
+ goto ChangeFileOwnerByNameEnd;
}
- dwNewAclSize = aclSizeInfo.AclBytesInUse + aclSizeInfo.AclBytesFree;
-
- delta = 0;
- if (pNewOwnerSid != NULL &&
- !GetNewAclSizeDelta(pDACL, pOldOwnerSid, pNewOwnerSid, &delta))
+ // We need SeTakeOwnershipPrivilege to set the owner if the caller does not
+ // have WRITE_OWNER access to the object; we need SeRestorePrivilege if the
+ // SID is not contained in the caller's token, and have the SE_GROUP_OWNER
+ // permission enabled.
+ //
+ if (!EnablePrivilege(L"SeTakeOwnershipPrivilege"))
{
- return FALSE;
+ fwprintf(stdout, L"INFO: The user does not have SeTakeOwnershipPrivilege.\n");
}
- dwNewAclSize += delta;
-
- delta = 0;
- if (pNewGroupSid != NULL &&
- !GetNewAclSizeDelta(pDACL, pOldGroupSid, pNewGroupSid, &delta))
+ if (!EnablePrivilege(L"SeRestorePrivilege"))
{
- return FALSE;
+ fwprintf(stdout, L"INFO: The user does not have SeRestorePrivilege.\n");
}
- dwNewAclSize += delta;
- *ppNewDACL = (PACL)LocalAlloc(LPTR, dwNewAclSize);
- if (*ppNewDACL == NULL)
- {
- ReportErrorCode(L"LocalAlloc", GetLastError());
- return FALSE;
- }
+ assert(pNewOwnerSid != NULL || pNewGroupSid != NULL);
- if (!InitializeAcl(*ppNewDACL, dwNewAclSize, ACL_REVISION))
+ // Set the owners of the file.
+ //
+ if (pNewOwnerSid != NULL) securityInformation |= OWNER_SECURITY_INFORMATION;
+ if (pNewGroupSid != NULL) securityInformation |= GROUP_SECURITY_INFORMATION;
+ dwRtnCode = SetNamedSecurityInfoW(
+ longPathName,
+ SE_FILE_OBJECT,
+ securityInformation,
+ pNewOwnerSid,
+ pNewGroupSid,
+ NULL,
+ NULL);
+ if (dwRtnCode != ERROR_SUCCESS)
{
- ReportErrorCode(L"InitializeAcl", GetLastError());
- return FALSE;
+ goto ChangeFileOwnerByNameEnd;
}
- // Go through the DACL to change permissions
+ // Set the permission on the file for the new owner.
//
- for (i = 0; i < pDACL->AceCount; i++)
+ dwRtnCode = ChangeFileModeByMask(longPathName, oldMode);
+ if (dwRtnCode != ERROR_SUCCESS)
{
- if (!GetAce(pDACL, i, &pAce))
- {
- ReportErrorCode(L"GetAce", GetLastError());
- return FALSE;
- }
-
- aceHeader = (PACE_HEADER) pAce;
- aceSid = NULL;
- if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
- {
- accessAllowedAce = (PACCESS_ALLOWED_ACE) pAce;
- aceSid = (PSID) &accessAllowedAce->SidStart;
- }
- else if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
- {
- accessDenieddAce = (PACCESS_DENIED_ACE) pAce;
- aceSid = (PSID) &accessDenieddAce->SidStart;
- }
-
- if (aceSid != NULL)
- {
- if (pNewOwnerSid != NULL && EqualSid(pOldOwnerSid, aceSid))
- {
- if (!AddNewAce(*ppNewDACL, pAce, pOldOwnerSid, pNewOwnerSid))
- return FALSE;
- else
- continue;
- }
- else if (pNewGroupSid != NULL && EqualSid(pOldGroupSid, aceSid))
- {
- if (!AddNewAce(*ppNewDACL, pAce, pOldGroupSid, pNewGroupSid))
- return FALSE;
- else
- continue;
- }
- }
-
- // At this point, either:
- // 1. The Ace is not of type ACCESS_ALLOWED_ACE or ACCESS_DENIED_ACE;
- // 2. The Ace does not belong to the owner
- // For both cases, we just add the oringal Ace to the new ACL.
- //
- if (!AddAce(*ppNewDACL, ACL_REVISION, MAXDWORD, pAce, aceHeader->AceSize))
- {
- ReportErrorCode(L"AddAce", dwRtnCode);
- return FALSE;
- }
+ goto ChangeFileOwnerByNameEnd;
}
- return TRUE;
+ChangeFileOwnerByNameEnd:
+ LocalFree(longPathName);
+ return dwRtnCode;
}
-
//----------------------------------------------------------------------------
// Function: Chown
//
@@ -293,7 +119,6 @@ static BOOL CreateDaclForNewOwner(
int Chown(int argc, wchar_t *argv[])
{
LPWSTR pathName = NULL;
- LPWSTR longPathName = NULL;
LPWSTR ownerInfo = NULL;
@@ -308,16 +133,6 @@ int Chown(int argc, wchar_t *argv[])
PSID pNewOwnerSid = NULL;
PSID pNewGroupSid = NULL;
- PACL pDACL = NULL;
- PACL pNewDACL = NULL;
-
- PSID pOldOwnerSid = NULL;
- PSID pOldGroupSid = NULL;
-
- PSECURITY_DESCRIPTOR pSD = NULL;
-
- SECURITY_INFORMATION securityInformation;
-
DWORD dwRtnCode = 0;
int ret = EXIT_FAILURE;
@@ -423,61 +238,10 @@ int Chown(int argc, wchar_t *argv[])
goto ChownEnd;
}
- // Convert the path the the long path
- //
- dwRtnCode = ConvertToLongPath(pathName, &longPathName);
- if (dwRtnCode != ERROR_SUCCESS)
- {
- ReportErrorCode(L"ConvertToLongPath", dwRtnCode);
- goto ChownEnd;
- }
-
- // Get a pointer to the existing owner information and DACL
- //
- dwRtnCode = GetNamedSecurityInfoW(
- longPathName,
- SE_FILE_OBJECT,
- OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
- DACL_SECURITY_INFORMATION,
- &pOldOwnerSid,
- &pOldGroupSid,
- &pDACL,
- NULL,
- &pSD);
- if (dwRtnCode != ERROR_SUCCESS)
- {
- ReportErrorCode(L"GetNamedSecurityInfo", dwRtnCode);
- goto ChownEnd;
- }
-
- // Create the new DACL
- //
- if (!CreateDaclForNewOwner(pDACL,
- pOldOwnerSid, pNewOwnerSid,
- pOldGroupSid, pNewGroupSid,
- &pNewDACL))
- {
- goto ChownEnd;
- }
-
- // Set the owner and DACLs in the object's security descriptor. Use
- // PROTECTED_DACL_SECURITY_INFORMATION flag to remove permission inheritance
- //
- securityInformation =
- DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION;
- if (pNewOwnerSid != NULL) securityInformation |= OWNER_SECURITY_INFORMATION;
- if (pNewGroupSid != NULL) securityInformation |= GROUP_SECURITY_INFORMATION;
- dwRtnCode = SetNamedSecurityInfoW(
- longPathName,
- SE_FILE_OBJECT,
- securityInformation,
- pNewOwnerSid,
- pNewGroupSid,
- pNewDACL,
- NULL);
+ dwRtnCode = ChangeFileOwnerBySid(pathName, pNewOwnerSid, pNewGroupSid);
if (dwRtnCode != ERROR_SUCCESS)
{
- ReportErrorCode(L"SetNamedSecurityInfo", dwRtnCode);
+ ReportErrorCode(L"ChangeFileOwnerBySid", dwRtnCode);
goto ChownEnd;
}
@@ -488,9 +252,6 @@ ChownEnd:
LocalFree(groupName);
LocalFree(pNewOwnerSid);
LocalFree(pNewGroupSid);
- LocalFree(pNewDACL);
- LocalFree(pSD);
- LocalFree(longPathName);
return ret;
}
Modified: hadoop/common/branches/branch-1-win/src/winutils/include/winutils.h
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-1-win/src/winutils/include/winutils.h?rev=1407560&r1=1407559&r2=1407560&view=diff
==============================================================================
--- hadoop/common/branches/branch-1-win/src/winutils/include/winutils.h (original)
+++ hadoop/common/branches/branch-1-win/src/winutils/include/winutils.h Fri Nov 9 17:49:20 2012
@@ -137,4 +137,6 @@ DWORD JunctionPointCheck(__in LPCWSTR pa
DWORD ChangeFileModeByMask(__in LPCWSTR path, INT mode);
DWORD GetLocalGroupsForUser(__in LPCWSTR user,
- __out LPLOCALGROUP_USERS_INFO_0 *groups, __out LPDWORD entries);
\ No newline at end of file
+ __out LPLOCALGROUP_USERS_INFO_0 *groups, __out LPDWORD entries);
+
+BOOL EnablePrivilege(__in LPCWSTR privilegeName);
\ No newline at end of file
Modified: hadoop/common/branches/branch-1-win/src/winutils/libwinutils.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-1-win/src/winutils/libwinutils.c?rev=1407560&r1=1407559&r2=1407560&view=diff
==============================================================================
--- hadoop/common/branches/branch-1-win/src/winutils/libwinutils.c (original)
+++ hadoop/common/branches/branch-1-win/src/winutils/libwinutils.c Fri Nov 9 17:49:20 2012
@@ -144,8 +144,8 @@ static BOOL IsLongWindowsPath(__in PCWST
static BOOL IsPrefixedAlready(__in PCWSTR path)
{
static const PCWSTR LongPathPrefix = L"\\\\?\\";
- int Prefixlen = (int)wcslen(LongPathPrefix);
- int i = 0;
+ size_t Prefixlen = wcslen(LongPathPrefix);
+ size_t i = 0;
if (path == NULL || wcslen(path) < Prefixlen)
{
@@ -481,7 +481,7 @@ DWORD GetSidFromAcctNameW(LPCWSTR acctNa
// Compute the 3 bit Unix mask for the owner, group, or, others
//
// Returns:
-// The 3 bit Unix mask in USHORT
+// The 3 bit Unix mask in INT
//
// Notes:
//
@@ -616,8 +616,11 @@ GetEffectiveRightsForSidEnd:
// Error code otherwise
//
// Notes:
-// Caller needs to destroy the memeory of owner and group names by calling
-// LocalFree() function.
+// - Caller needs to destroy the memeory of owner and group names by calling
+// LocalFree() function.
+//
+// - If the user or group name does not exist, the user or group SID will be
+// returned as the name.
//
DWORD FindFileOwnerAndPermission(
__in LPCWSTR pathName,
@@ -833,7 +836,17 @@ static void GetWindowsAccessMask(INT uni
// Error code: otherwise
//
// Notes:
-// none
+// - Administrators and SYSTEM are always given full permission to the file,
+// unless Administrators or SYSTEM itself is the file owner and the user
+// explictly set the permission to something else. For example, file 'foo'
+// belongs to Administrators, 'chmod 000' on the file will not directly
+// assign Administrators full permission on the file.
+// - Only full permission for Administrators and SYSTEM are inheritable.
+// - CREATOR OWNER is always given full permission and the permission is
+// inheritable, more specifically OBJECT_INHERIT_ACE, CONTAINER_INHERIT_ACE
+// flags are set. The reason is to give the creator of child file full
+// permission, i.e., the child file will have permission mode 700 for
+// a user other than Administrator or SYSTEM.
//
static DWORD GetWindowsDACLs(__in INT unixMask,
__in PSID pOwnerSid, __in PSID pGroupSid, __out PACL *ppNewDACL)
@@ -845,12 +858,22 @@ static DWORD GetWindowsDACLs(__in INT un
DWORD winOtherAccessAllowMask;
PSID pEveryoneSid = NULL;
+ DWORD cbEveryoneSidSize = SECURITY_MAX_SID_SIZE;
+
+ PSID pSystemSid = NULL;
+ DWORD cbSystemSidSize = SECURITY_MAX_SID_SIZE;
+ BOOL bAddSystemAcls = FALSE;
+
+ PSID pAdministratorsSid = NULL;
+ DWORD cbAdministratorsSidSize = SECURITY_MAX_SID_SIZE;
+ BOOL bAddAdministratorsAcls = FALSE;
+
+ PSID pCreatorOwnerSid = NULL;
+ DWORD cbCreatorOwnerSidSize = SECURITY_MAX_SID_SIZE;
PACL pNewDACL = NULL;
DWORD dwNewAclSize = 0;
- SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
-
DWORD ret = ERROR_SUCCESS;
GetWindowsAccessMask(unixMask,
@@ -860,12 +883,63 @@ static DWORD GetWindowsDACLs(__in INT un
// Create a well-known SID for the Everyone group
//
- if(!AllocateAndInitializeSid(&SIDAuthWorld, 1,
- SECURITY_WORLD_RID,
- 0, 0, 0, 0, 0, 0, 0,
- &pEveryoneSid))
+ if ((pEveryoneSid = LocalAlloc(LPTR, cbEveryoneSidSize)) == NULL)
{
- return GetLastError();
+ ret = GetLastError();
+ goto GetWindowsDACLsEnd;
+ }
+ if (!CreateWellKnownSid(WinWorldSid, NULL, pEveryoneSid, &cbEveryoneSidSize))
+ {
+ ret = GetLastError();
+ goto GetWindowsDACLsEnd;
+ }
+
+ // Create a well-known SID for the Administrators group
+ //
+ if ((pAdministratorsSid = LocalAlloc(LPTR, cbAdministratorsSidSize)) == NULL)
+ {
+ ret = GetLastError();
+ goto GetWindowsDACLsEnd;
+ }
+ if (!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL,
+ pAdministratorsSid, &cbAdministratorsSidSize))
+ {
+ ret = GetLastError();
+ goto GetWindowsDACLsEnd;
+ }
+ if (!EqualSid(pAdministratorsSid, pOwnerSid)
+ && !EqualSid(pAdministratorsSid, pGroupSid))
+ bAddAdministratorsAcls = TRUE;
+
+ // Create a well-known SID for the SYSTEM
+ //
+ if ((pSystemSid = LocalAlloc(LPTR, cbSystemSidSize)) == NULL)
+ {
+ ret = GetLastError();
+ goto GetWindowsDACLsEnd;
+ }
+ if (!CreateWellKnownSid(WinLocalSystemSid, NULL,
+ pSystemSid, &cbSystemSidSize))
+ {
+ ret = GetLastError();
+ goto GetWindowsDACLsEnd;
+ }
+ if (!EqualSid(pSystemSid, pOwnerSid)
+ && !EqualSid(pSystemSid, pGroupSid))
+ bAddSystemAcls = TRUE;
+
+ // Create a well-known SID for the Creator Owner
+ //
+ if ((pCreatorOwnerSid = LocalAlloc(LPTR, cbCreatorOwnerSidSize)) == NULL)
+ {
+ ret = GetLastError();
+ goto GetWindowsDACLsEnd;
+ }
+ if (!CreateWellKnownSid(WinCreatorOwnerSid, NULL,
+ pCreatorOwnerSid, &cbCreatorOwnerSidSize))
+ {
+ ret = GetLastError();
+ goto GetWindowsDACLsEnd;
}
// Create the new DACL
@@ -883,6 +957,22 @@ static DWORD GetWindowsDACLs(__in INT un
GetLengthSid(pGroupSid) - sizeof(DWORD);
dwNewAclSize += sizeof(ACCESS_ALLOWED_ACE) +
GetLengthSid(pEveryoneSid) - sizeof(DWORD);
+
+ if (bAddSystemAcls)
+ {
+ dwNewAclSize += sizeof(ACCESS_ALLOWED_ACE) +
+ cbSystemSidSize - sizeof(DWORD);
+ }
+
+ if (bAddAdministratorsAcls)
+ {
+ dwNewAclSize += sizeof(ACCESS_ALLOWED_ACE) +
+ cbAdministratorsSidSize - sizeof(DWORD);
+ }
+
+ dwNewAclSize += sizeof(ACCESS_ALLOWED_ACE) +
+ cbCreatorOwnerSidSize - sizeof(DWORD);
+
pNewDACL = (PACL)LocalAlloc(LPTR, dwNewAclSize);
if (pNewDACL == NULL)
{
@@ -895,33 +985,64 @@ static DWORD GetWindowsDACLs(__in INT un
goto GetWindowsDACLsEnd;
}
+ if (!AddAccessAllowedAceEx(pNewDACL, ACL_REVISION,
+ CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
+ GENERIC_ALL, pCreatorOwnerSid))
+ {
+ ret = GetLastError();
+ goto GetWindowsDACLsEnd;
+ }
+
+ if (bAddSystemAcls &&
+ !AddAccessAllowedAceEx(pNewDACL, ACL_REVISION,
+ CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
+ GENERIC_ALL, pSystemSid))
+ {
+ ret = GetLastError();
+ goto GetWindowsDACLsEnd;
+ }
+
+ if (bAddAdministratorsAcls &&
+ !AddAccessAllowedAceEx(pNewDACL, ACL_REVISION,
+ CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
+ GENERIC_ALL, pAdministratorsSid))
+ {
+ ret = GetLastError();
+ goto GetWindowsDACLsEnd;
+ }
+
if (winUserAccessDenyMask &&
- !AddAccessDeniedAce(pNewDACL, ACL_REVISION,
+ !AddAccessDeniedAceEx(pNewDACL, ACL_REVISION,
+ NO_PROPAGATE_INHERIT_ACE,
winUserAccessDenyMask, pOwnerSid))
{
ret = GetLastError();
goto GetWindowsDACLsEnd;
}
- if (!AddAccessAllowedAce(pNewDACL, ACL_REVISION,
+ if (!AddAccessAllowedAceEx(pNewDACL, ACL_REVISION,
+ NO_PROPAGATE_INHERIT_ACE,
winUserAccessAllowMask, pOwnerSid))
{
ret = GetLastError();
goto GetWindowsDACLsEnd;
}
if (winGroupAccessDenyMask &&
- !AddAccessDeniedAce(pNewDACL, ACL_REVISION,
+ !AddAccessDeniedAceEx(pNewDACL, ACL_REVISION,
+ NO_PROPAGATE_INHERIT_ACE,
winGroupAccessDenyMask, pGroupSid))
{
ret = GetLastError();
goto GetWindowsDACLsEnd;
}
- if (!AddAccessAllowedAce(pNewDACL, ACL_REVISION,
+ if (!AddAccessAllowedAceEx(pNewDACL, ACL_REVISION,
+ NO_PROPAGATE_INHERIT_ACE,
winGroupAccessAllowMask, pGroupSid))
{
ret = GetLastError();
goto GetWindowsDACLsEnd;
}
- if (!AddAccessAllowedAce(pNewDACL, ACL_REVISION,
+ if (!AddAccessAllowedAceEx(pNewDACL, ACL_REVISION,
+ NO_PROPAGATE_INHERIT_ACE,
winOtherAccessAllowMask, pEveryoneSid))
{
ret = GetLastError();
@@ -931,7 +1052,10 @@ static DWORD GetWindowsDACLs(__in INT un
*ppNewDACL = pNewDACL;
GetWindowsDACLsEnd:
- if (pEveryoneSid) FreeSid(pEveryoneSid);
+ LocalFree(pEveryoneSid);
+ LocalFree(pAdministratorsSid);
+ LocalFree(pSystemSid);
+ LocalFree(pCreatorOwnerSid);
if (ret != ERROR_SUCCESS) LocalFree(pNewDACL);
return ret;
@@ -955,7 +1079,6 @@ GetWindowsDACLsEnd:
DWORD ChangeFileModeByMask(__in LPCWSTR path, INT mode)
{
LPWSTR longPathName = NULL;
- PACL pOldDACL = NULL;
PACL pNewDACL = NULL;
PSID pOwnerSid = NULL;
PSID pGroupSid = NULL;
@@ -987,11 +1110,10 @@ DWORD ChangeFileModeByMask(__in LPCWSTR
dwRtnCode = GetNamedSecurityInfoW(
longPathName,
SE_FILE_OBJECT,
- OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
- DACL_SECURITY_INFORMATION,
+ OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION,
&pOwnerSid,
&pGroupSid,
- &pOldDACL,
+ NULL,
NULL,
&pSD);
if (ERROR_SUCCESS != dwRtnCode)
@@ -1224,12 +1346,15 @@ GetAccntNameFromSidEnd:
// Other error code on failure
//
// Notes:
-// - Because NetUserGetLocalGroups() only accepts full user name, we wil try
-// to find full user name given the user input if NetUserGetLocalGroups()
-// fails on first time with error code NERR_UserNotFound. It is not always
-// to find full user name given only user name. For example, a computer named
-// 'win1' joint domain 'redmond' can have both 'win1\alex' and
-// 'redmond\alex'. Given only alex, we cannot tell which one is correct.
+// - NetUserGetLocalGroups() function only accepts full user name in the format
+// [domain name]\[username]. The user input to this function can be only the
+// username. In this case, NetUserGetLocalGroups() will fail on the first try,
+// and we will try to find full user name using LookupAccountNameW() method,
+// and call NetUserGetLocalGroups() function again with full user name.
+// However, it is not always possible to find full user name given only user
+// name. For example, a computer named 'win1' joined domain 'redmond' can have
+// two different users, 'win1\alex' and 'redmond\alex'. Given only 'alex', we
+// cannot tell which one is correct.
//
// - Caller needs to destroy the memory of groups by using the
// NetApiBufferFree() function
@@ -1310,6 +1435,51 @@ GetLocalGroupsForUserEnd:
}
//----------------------------------------------------------------------------
+// Function: EnablePrivilege
+//
+// Description:
+// Check if the process has the given privilege. If yes, enable the privilege
+// to the process's access token.
+//
+// Returns:
+// TRUE: on success
+//
+// Notes:
+//
+BOOL EnablePrivilege(__in LPCWSTR privilegeName)
+{
+ HANDLE hToken = INVALID_HANDLE_VALUE;
+ TOKEN_PRIVILEGES tp = { 0 };
+ DWORD dwErrCode = ERROR_SUCCESS;
+
+ if (!OpenProcessToken(GetCurrentProcess(),
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+ {
+ ReportErrorCode(L"OpenProcessToken", GetLastError());
+ return FALSE;
+ }
+
+ tp.PrivilegeCount = 1;
+ if (!LookupPrivilegeValueW(NULL,
+ privilegeName, &(tp.Privileges[0].Luid)))
+ {
+ ReportErrorCode(L"LookupPrivilegeValue", GetLastError());
+ CloseHandle(hToken);
+ return FALSE;
+ }
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ // As stated on MSDN, we need to use GetLastError() to check if
+ // AdjustTokenPrivileges() adjusted all of the specified privileges.
+ //
+ AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
+ dwErrCode = GetLastError();
+ CloseHandle(hToken);
+
+ return dwErrCode == ERROR_SUCCESS;
+}
+
+//----------------------------------------------------------------------------
// Function: ReportErrorCode
//
// Description:
Modified: hadoop/common/branches/branch-1-win/src/winutils/ls.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-1-win/src/winutils/ls.c?rev=1407560&r1=1407559&r2=1407560&view=diff
==============================================================================
--- hadoop/common/branches/branch-1-win/src/winutils/ls.c (original)
+++ hadoop/common/branches/branch-1-win/src/winutils/ls.c Fri Nov 9 17:49:20 2012
@@ -287,7 +287,7 @@ int Ls(int argc, wchar_t *argv[])
goto LsEnd;
}
- dwErrorCode = SymbolicLinkCheck(pathName, &isSymlink);
+ dwErrorCode = SymbolicLinkCheck(longPathName, &isSymlink);
if (dwErrorCode != ERROR_SUCCESS)
{
ReportErrorCode(L"IsSymbolicLink", dwErrorCode);
Modified: hadoop/common/branches/branch-1-win/src/winutils/main.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-1-win/src/winutils/main.c?rev=1407560&r1=1407559&r2=1407560&view=diff
==============================================================================
--- hadoop/common/branches/branch-1-win/src/winutils/main.c (original)
+++ hadoop/common/branches/branch-1-win/src/winutils/main.c Fri Nov 9 17:49:20 2012
@@ -110,10 +110,9 @@ The available commands and their usages
fwprintf(stdout, L"%-15s%s\n\n", L"systeminfo", L"System information.");
SystemInfoUsage();
+ fwprintf(stdout, L"\n\n");
fwprintf(stdout, L"%-15s%s\n\n", L"task", L"Task operations.");
TaskUsage();
fwprintf(stdout, L"\n\n");
-
- fwprintf(stdout, L"\n\n");
}
Modified: hadoop/common/branches/branch-1-win/src/winutils/symlink.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-1-win/src/winutils/symlink.c?rev=1407560&r1=1407559&r2=1407560&view=diff
==============================================================================
--- hadoop/common/branches/branch-1-win/src/winutils/symlink.c (original)
+++ hadoop/common/branches/branch-1-win/src/winutils/symlink.c Fri Nov 9 17:49:20 2012
@@ -18,51 +18,6 @@
#include "winutils.h"
//----------------------------------------------------------------------------
-// Function: EnablePrivilege
-//
-// Description:
-// Check if the process has the given privilege. If yes, enable the privilege
-// to the process's access token.
-//
-// Returns:
-// TRUE: on success
-//
-// Notes:
-//
-static BOOL EnablePrivilege(__in LPCWSTR privilegeName)
-{
- HANDLE hToken;
- TOKEN_PRIVILEGES tp;
- DWORD dwErrCode;
-
- if (!OpenProcessToken(GetCurrentProcess(),
- TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
- {
- ReportErrorCode(L"OpenProcessToken", GetLastError());
- return FALSE;
- }
-
- tp.PrivilegeCount = 1;
- if (!LookupPrivilegeValueW(NULL,
- privilegeName, &(tp.Privileges[0].Luid)))
- {
- ReportErrorCode(L"LookupPrivilegeValue", GetLastError());
- CloseHandle(hToken);
- return FALSE;
- }
- tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-
- // As stated on MSDN, we need to use GetLastError() to check if
- // AdjustTokenPrivileges() adjusted all of the specified privileges.
- //
- AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
- dwErrCode = GetLastError();
- CloseHandle(hToken);
-
- return dwErrCode == ERROR_SUCCESS;
-}
-
-//----------------------------------------------------------------------------
// Function: Symlink
//
// Description: