Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adding new custom actions GetAccountSid and TranslateNameFormatted.

  • Loading branch information...
commit 586b718e9c6cc38c21937283230ff49808ede512 1 parent 0b6b8d7
jhite authored
View
2  doc/WhatsNew.html
@@ -29,6 +29,8 @@
<ul>
<li>Upgraded to Wix 3.5.</li>
<li>Added <code>Xml_DeleteNodes</code>.</li>
+ <li>Added User Privileges <code>GetAccountSid</code>.</li>
+ <li>Added User Privileges <code>TranslateNameFormatted</code>.</li>
</ul>
</li>
<li><strong>Bugs</strong>:
View
18 src/Common/Lsa/Sid.cpp
@@ -60,6 +60,24 @@ std::wstring Sid::ToString() const
return buffer;
}
+std::wstring Sid::ToHexString() const
+{
+ CHECK_BOOL(IsValid(), L"Invalid sid");
+
+ std::wstringstream ss(std::wstringstream::out);
+ ss << L"0x";
+ ss.flags (std::ios::right| std::ios::hex | std::ios::uppercase);
+ ss.fill('0');
+ std::vector<byte>::const_iterator it;
+ for (it = m_data.begin(); it != m_data.end(); it++)
+ {
+ ss.width(2);
+ ss << *it;
+ }
+
+ return ss.str();
+}
+
void Sid::Set(PSID psid, SID_NAME_USE use)
{
CHECK_BOOL(NULL != psid, L"Missing sid");
View
2  src/Common/Lsa/Sid.h
@@ -27,6 +27,8 @@ namespace AppSecInc
Sid& operator=(const std::wstring&);
//! return a string representation of a sid
std::wstring ToString() const;
+ //! return a hexidecimal string reperesntation of the sid.
+ std::wstring ToHexString() const;
//! return the length of the SID
DWORD GetLength() const;
//! return a PSID
View
30 src/Common/Lsa/SidUnitTests.cpp
@@ -43,4 +43,32 @@ void SidUnitTests::testSidToString()
CPPUNIT_ASSERT(::GetLengthSid(sid.GetPSID()) == sid.GetLength());
CPPUNIT_ASSERT(testdata[i] == sid.ToString());
}
-}
+}
+
+void SidUnitTests::testSidToHexString()
+{
+ struct TestData
+ {
+ LPCWSTR sid;
+ };
+
+ LPCWSTR testdata[] =
+ {
+ { L"S-1-5-32-545" }, // Users
+ { L"S-1-5-32-544" }, // Administrators
+ };
+
+ LPCWSTR testresults[] =
+ {
+ {L"0x01020000000000052000000021020000"}, //Users
+ {L"0x01020000000000052000000020020000"}, //Administrators
+ };
+
+ for (int i = 0; i < ARRAYSIZE(testdata); i++)
+ {
+ AppSecInc::LSA::Sid sid(testdata[i]);
+ std::wcout << std::endl << testdata[i] << L" => " << sid.GetLength() << " byte(s)";
+ CPPUNIT_ASSERT(::GetLengthSid(sid.GetPSID()) == sid.GetLength());
+ CPPUNIT_ASSERT(testresults[i] == sid.ToHexString());
+ }
+}
View
2  src/Common/Lsa/SidUnitTests.h
@@ -11,10 +11,12 @@ namespace AppSecInc
CPPUNIT_TEST_SUITE( SidUnitTests );
CPPUNIT_TEST( testSidConstructorsAndOperators );
CPPUNIT_TEST( testSidToString );
+ CPPUNIT_TEST( testSidToHexString );
CPPUNIT_TEST_SUITE_END();
public:
void testSidConstructorsAndOperators();
void testSidToString();
+ void testSidToHexString();
};
}
}
View
42 src/CustomActions/UserPrivileges/UserInfo.cpp
@@ -16,6 +16,12 @@ static const FlagMapEntry s_ExtendedNameFormats[] =
{ L"NameDnsDomain", NameDnsDomain }
};
+static const FlagMapEntry s_SidFormats[] =
+{
+ { L"SidString", 0},
+ { L"SidStringHex", 1}
+};
+
CA_API UINT __stdcall GetUserInfo(MSIHANDLE hInstall)
{
MSI_EXCEPTION_HANDLER_PROLOG;
@@ -47,3 +53,39 @@ CA_API UINT __stdcall GetUserNameFormatted(MSIHANDLE hInstall)
MSI_EXCEPTION_HANDLER_EPILOG;
return ERROR_SUCCESS;
}
+
+CA_API UINT __stdcall GetAccountSid(MSIHANDLE hInstall)
+{
+ MSI_EXCEPTION_HANDLER_PROLOG;
+ MsiInstall msiInstall(hInstall);
+ std::wstring accountName = msiInstall.GetProperty(L"ACCOUNT_NAME");
+ std::wstring sidFormat = msiInstall.GetProperty(L"ACCOUNT_SID_FORMAT");
+
+ AppSecInc::LSA::Account account;
+ account.LookupAccount(accountName);
+
+ if (sidFormat == L"SidStringHex")
+ {
+ msiInstall.SetProperty(L"ACCOUNT_SID",account.GetSid().ToHexString());
+ }
+ else
+ {
+ msiInstall.SetProperty(L"ACCOUNT_SID",account.GetSid().ToString());
+ }
+ MSI_EXCEPTION_HANDLER_EPILOG;
+ return ERROR_SUCCESS;
+}
+
+CA_API UINT __stdcall TranslateNameFormatted(MSIHANDLE hInstall)
+{
+ MSI_EXCEPTION_HANDLER_PROLOG;
+ MsiInstall msiInstall(hInstall);
+ std::wstring accountName = msiInstall.GetProperty(L"ACCOUNT_NAME");
+ EXTENDED_NAME_FORMAT accountNameFormat = (EXTENDED_NAME_FORMAT) GetPropertyValue(msiInstall, L"ACCOUNT_NAME_FORMAT", s_ExtendedNameFormats);
+
+ std::wstring translated = AppSecInc::LSA::Account::Translate(accountName, NameUnknown, accountNameFormat);
+
+ msiInstall.SetProperty(L"ACCOUNT_NAME", translated);
+ MSI_EXCEPTION_HANDLER_EPILOG;
+ return ERROR_SUCCESS;
+}
View
31 src/CustomActions/UserPrivileges/UserInfo.h
@@ -56,3 +56,34 @@ the DNS username instead of the SAM username, also call \ref GetUserNameFormatte
*/
CA_API UINT __stdcall GetUserNameFormatted(MSIHANDLE hInstall);
+
+/*!
+\brief Looks up the account and returns the SID.
+\param ACCOUNT_NAME Account name to look up. Can be in DNS, FQDN or UPN format
+\param ACCOUNT_SID_FORMAT format of the returned SID. This can be one of
+ \li \b SidString the string representation of the SID. This is the default value if ACCOUNT_SID_FORMAT is not specified.
+ \li \b SidStringHex the hexadecimal representation of the binary SID.
+\return ACCOUNT_SID Account SID in the specified format
+
+*/
+CA_API UINT __stdcall GetAccountSid(MSIHANDLE hInstall);
+
+/*!
+
+\brief Translate an account name to a specific format.
+
+\param ACCOUNT_NAME the account name to translate. This can be in any of the EXTENDED_NAME_FORMATs.
+\param ACCOUNT_NAME_FORMAT name format, one of EXTENDED_NAME_FORMAT, see http://msdn.microsoft.com/en-us/library/ms724268(VS.85).aspx
+ \li \b NameFullyQualifiedDN The fully-qualified distinguished name (for example, CN=Jeff Smith,OU=Users,DC=Engineering,DC=Microsoft,DC=Com).
+ \li \b NameSamCompatible A legacy account name (for example, Engineering\\JSmith). The domain-only version includes trailing backslashes (\\\\).
+ \li \b NameDisplay A "friendly" display name (for example, Jeff Smith). The display name is not necessarily the defining relative distinguished name (RDN).
+ \li \b NameUniqueId A GUID string that the IIDFromString function returns (for example, {4fa050f0-f561-11cf-bdd9-00aa003a77b6}).
+ \li \b NameCanonical The complete canonical name (for example, engineering.microsoft.com/software/someone). The domain-only version includes a trailing forward slash (/).
+ \li \b NameUserPrincipal The user principal name (for example, someone@example.com).
+ \li \b NameCanonicalEx The same as NameCanonical except that the rightmost forward slash (/) is replaced with a new line character (\n), even in a domain-only case (for example, engineering.microsoft.com/software\\nJSmith).
+ \li \b NameServicePrincipal The generalized service principal name (for example, www/www.microsoft.com@microsoft.com).
+ \li \b NameDnsDomain The DNS domain name followed by a backward-slash and the SAM username.
+\return ACCOUNT_NAME the account name translated to the specified format.
+
+*/
+CA_API UINT __stdcall TranslateNameFormatted(MSIHANDLE hInstall);
View
72 src/CustomActions/UserPrivileges/UserInfoUnitTests.cpp
@@ -62,11 +62,81 @@ void UserInfoUnitTests::Test_GetUserNameFormattedDomain()
}
}
+void UserInfoUnitTests::Test_GetAccountSid()
+{
+ AppSecInc::Msi::MsiShim hInstall;
+ MsiInstall msiInstall(hInstall);
+ msiInstall.SetProperty(L"ACCOUNT_NAME", L"BUILTIN\\Administrators");
+ msiInstall.SetProperty(L"ACCOUNT_SID_FORMAT", L"SidString");
+ CPPUNIT_ASSERT(ERROR_SUCCESS == hInstall.ExecuteCA(L"UserPrivileges.dll", L"GetAccountSid"));
+ std::wstring accountSid = msiInstall.GetProperty(L"ACCOUNT_SID");
+ CPPUNIT_ASSERT(accountSid.length() > 0);
+ CPPUNIT_ASSERT(accountSid == L"S-1-5-32-544");
+ std::wcout << std::endl << L"Account SID: " << accountSid;
+
+ msiInstall.SetProperty(L"ACCOUNT_SID_FORMAT", L"SidStringHex");
+ CPPUNIT_ASSERT(ERROR_SUCCESS == hInstall.ExecuteCA(L"UserPrivileges.dll", L"GetAccountSid"));
+ std::wstring accountSidHex = msiInstall.GetProperty(L"ACCOUNT_SID");
+ CPPUNIT_ASSERT(accountSidHex.length() > 0);
+ CPPUNIT_ASSERT(accountSidHex == L"0x01020000000000052000000020020000");
+ std::wcout << std::endl << L"Account SID (HEX): " << accountSidHex;
+}
+
+void UserInfoUnitTests::Test_GetAccountSid_DefaultParam()
+{
+ AppSecInc::Msi::MsiShim hInstall;
+ MsiInstall msiInstall(hInstall);
+ msiInstall.SetProperty(L"ACCOUNT_NAME", L"BUILTIN\\Administrators");
+ CPPUNIT_ASSERT(ERROR_SUCCESS == hInstall.ExecuteCA(L"UserPrivileges.dll", L"GetAccountSid"));
+ std::wstring accountSid = msiInstall.GetProperty(L"ACCOUNT_SID");
+ CPPUNIT_ASSERT(accountSid.length() > 0);
+ CPPUNIT_ASSERT(accountSid == L"S-1-5-32-544");
+ std::wcout << std::endl << L"Account SID: " << accountSid;
+}
+
+void UserInfoUnitTests::Test_TranslateNameFormatted()
+{
+ CPPUNIT_IGNORE(NetSetupDomainName != AppSecInc::Net::DirectoryServices::GetJoinStatus().join_status);
+
+ AppSecInc::Msi::MsiShim hInstall;
+ MsiInstall msiInstall(hInstall);
+
+ LPCWSTR usernameformats[] =
+ {
+ L"NameFullyQualifiedDN",
+ L"NameSamCompatible",
+ L"NameDisplay",
+ L"NameUniqueId",
+ L"NameCanonical",
+ L"NameUserPrincipal",
+ L"NameCanonicalEx"
+ // L"NameServicePrincipal", \todo fails with "No mapping between account names and security IDs was done." (?)
+ //L"NameDnsDomain" \todo fails with "Error translating from format 0 to 12, error fetching result size: The specified account does not exist."
+ };
+
+ msiInstall.SetProperty(L"USERNAME_FORMAT", L"NameSamCompatible");
+ CPPUNIT_ASSERT(ERROR_SUCCESS == hInstall.ExecuteCA(L"UserPrivileges.dll", L"GetUserNameFormatted"));
+ std::wstring username = msiInstall.GetProperty(L"USER_FQN");
+ CPPUNIT_ASSERT(username.length() > 0);
+
+ for (int i = 0; i < ARRAYSIZE(usernameformats); i++)
+ {
+ msiInstall.SetProperty(L"ACCOUNT_NAME", username);
+ msiInstall.SetProperty(L"ACCOUNT_NAME_FORMAT", usernameformats[i]);
+ CPPUNIT_ASSERT(ERROR_SUCCESS == hInstall.ExecuteCA(L"UserPrivileges.dll", L"TranslateNameFormatted"));
+ std::wstring userfqn = msiInstall.GetProperty(L"ACCOUNT_NAME");
+ CPPUNIT_ASSERT(userfqn.length() > 0);
+ std::wcout << std::endl << usernameformats[i] << L": " << userfqn;
+ }
+}
+
void UserInfoUnitTests::Test_EntryPoints()
{
HMODULE h = ::LoadLibrary(L"UserPrivileges.dll");
CPPUNIT_ASSERT_MESSAGE("Missing UserPrivileges.dll", h != NULL);
CPPUNIT_ASSERT(NULL != GetProcAddress(h, "GetUserInfo"));
CPPUNIT_ASSERT(NULL != GetProcAddress(h, "GetUserNameFormatted"));
+ CPPUNIT_ASSERT(NULL != GetProcAddress(h, "GetAccountSid"));
+ CPPUNIT_ASSERT(NULL != GetProcAddress(h, "TranslateNameFormatted"));
::FreeModule(h);
-}
+}
View
6 src/CustomActions/UserPrivileges/UserInfoUnitTests.h
@@ -13,12 +13,18 @@ namespace AppSecInc
CPPUNIT_TEST( Test_GetUserNameFormatted );
CPPUNIT_TEST( Test_GetUserNameFormattedDomain );
CPPUNIT_TEST( Test_EntryPoints );
+ CPPUNIT_TEST( Test_GetAccountSid );
+ CPPUNIT_TEST( Test_GetAccountSid_DefaultParam );
+ CPPUNIT_TEST( Test_TranslateNameFormatted );
CPPUNIT_TEST_SUITE_END();
public:
void Test_GetUserInfo();
void Test_EntryPoints();
void Test_GetUserNameFormatted();
void Test_GetUserNameFormattedDomain();
+ void Test_GetAccountSid();
+ void Test_GetAccountSid_DefaultParam();
+ void Test_TranslateNameFormatted();
};
}
}
View
2  src/CustomActions/UserPrivileges/UserPrivileges.def
@@ -8,7 +8,9 @@ EXPORTS
CheckPrivilege
CheckMembership
GetUserInfo
+ GetAccountSid
GetUserNameFormatted
+ TranslateNameFormatted
LocalUsers_Immediate
LocalGroups_Immediate
LocalGroupMembers_Immediate
Please sign in to comment.
Something went wrong with that request. Please try again.