aboutsummaryrefslogtreecommitdiff
path: root/src/dutil/acl2util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dutil/acl2util.cpp')
-rw-r--r--src/dutil/acl2util.cpp121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/dutil/acl2util.cpp b/src/dutil/acl2util.cpp
new file mode 100644
index 00000000..2261abe3
--- /dev/null
+++ b/src/dutil/acl2util.cpp
@@ -0,0 +1,121 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4
5/********************************************************************
6AclCalculateServiceSidString - gets the SID string for the given service name
7
8NOTE: psczSid should be freed with StrFree()
9********************************************************************/
10extern "C" HRESULT DAPI AclCalculateServiceSidString(
11 __in LPCWSTR wzServiceName,
12 __in int cchServiceName,
13 __deref_out_z LPWSTR* psczSid
14 )
15{
16 // TODO: use undocumented RtlCreateServiceSid function?
17 // http://blogs.technet.com/b/voy/archive/2007/03/22/per-service-sid.aspx
18 // Assume little endian.
19 HRESULT hr = S_OK;
20 LPWSTR sczUpperServiceName = NULL;
21 DWORD cbHash = SHA1_HASH_LEN;
22 BYTE* pbHash = NULL;
23
24 Assert(psczSid);
25
26 if (0 == cchServiceName)
27 {
28 hr = ::StringCchLengthW(wzServiceName, INT_MAX, reinterpret_cast<size_t*>(&cchServiceName));
29 ExitOnFailure(hr, "Failed to get the length of the service name.");
30 }
31
32 hr = StrAllocStringToUpperInvariant(&sczUpperServiceName, wzServiceName, cchServiceName);
33 ExitOnFailure(hr, "Failed to upper case the service name.");
34
35 pbHash = reinterpret_cast<BYTE*>(MemAlloc(cbHash, TRUE));
36 ExitOnNull(pbHash, hr, E_OUTOFMEMORY, "Failed to allocate hash byte array.");
37
38 hr = CrypHashBuffer(reinterpret_cast<BYTE*>(sczUpperServiceName), cchServiceName * 2, PROV_RSA_FULL, CALG_SHA1, pbHash, cbHash);
39 ExitOnNull(pbHash, hr, E_OUTOFMEMORY, "Failed to hash the service name.");
40
41 hr = StrAllocFormatted(psczSid, L"S-1-5-80-%u-%u-%u-%u-%u",
42 MAKEDWORD(MAKEWORD(pbHash[0], pbHash[1]), MAKEWORD(pbHash[2], pbHash[3])),
43 MAKEDWORD(MAKEWORD(pbHash[4], pbHash[5]), MAKEWORD(pbHash[6], pbHash[7])),
44 MAKEDWORD(MAKEWORD(pbHash[8], pbHash[9]), MAKEWORD(pbHash[10], pbHash[11])),
45 MAKEDWORD(MAKEWORD(pbHash[12], pbHash[13]), MAKEWORD(pbHash[14], pbHash[15])),
46 MAKEDWORD(MAKEWORD(pbHash[16], pbHash[17]), MAKEWORD(pbHash[18], pbHash[19])));
47
48LExit:
49 ReleaseMem(pbHash);
50 ReleaseStr(sczUpperServiceName);
51
52 return hr;
53}
54
55
56/********************************************************************
57AclGetAccountSidStringEx - gets a string version of the account's SID
58 calculates a service's SID if lookup fails
59
60NOTE: psczSid should be freed with StrFree()
61********************************************************************/
62extern "C" HRESULT DAPI AclGetAccountSidStringEx(
63 __in_z LPCWSTR wzSystem,
64 __in_z LPCWSTR wzAccount,
65 __deref_out_z LPWSTR* psczSid
66 )
67{
68 HRESULT hr = S_OK;
69 int cchAccount = 0;
70 PSID psid = NULL;
71 LPWSTR pwz = NULL;
72 LPWSTR sczSid = NULL;
73
74 Assert(psczSid);
75
76 hr = AclGetAccountSid(wzSystem, wzAccount, &psid);
77 if (SUCCEEDED(hr))
78 {
79 Assert(::IsValidSid(psid));
80
81 if (!::ConvertSidToStringSidW(psid, &pwz))
82 {
83 ExitWithLastError(hr, "Failed to convert SID to string for Account: %ls", wzAccount);
84 }
85
86 hr = StrAllocString(psczSid, pwz, 0);
87 }
88 else
89 {
90 if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr)
91 {
92 HRESULT hrLength = ::StringCchLengthW(wzAccount, INT_MAX, reinterpret_cast<size_t*>(&cchAccount));
93 ExitOnFailure(hrLength, "Failed to get the length of the account name.");
94
95 if (11 < cchAccount && CSTR_EQUAL == CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, L"NT SERVICE\\", 11, wzAccount, 11))
96 {
97 // If the service is not installed then LookupAccountName doesn't resolve the SID, but we can calculate it.
98 LPCWSTR wzServiceName = &wzAccount[11];
99 hr = AclCalculateServiceSidString(wzServiceName, cchAccount - 11, &sczSid);
100 ExitOnFailure(hr, "Failed to calculate the service SID for %ls", wzServiceName);
101
102 *psczSid = sczSid;
103 sczSid = NULL;
104 }
105 }
106 ExitOnFailure(hr, "Failed to get SID for account: %ls", wzAccount);
107 }
108
109LExit:
110 ReleaseStr(sczSid);
111 if (pwz)
112 {
113 ::LocalFree(pwz);
114 }
115 if (psid)
116 {
117 AclFreeSid(psid);
118 }
119
120 return hr;
121}