- Remove traces
[reactos.git] / reactos / dll / win32 / advapi32 / sec / sid.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * WINE COPYRIGHT:
4 * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
6 * Copyright 2006 Robert Reif
7 * Copyright 2006 Hervé Poussineau
8 *
9 * PROJECT: ReactOS system libraries
10 * FILE: dll/win32/advapi32/sec/sid.c
11 * PURPOSE: Security ID functions
12 */
13
14 #include <advapi32.h>
15 #include <sddl.h>
16 #include <wine/debug.h>
17 #include <wine/unicode.h>
18
19 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
20
21 #define MAX_GUID_STRING_LEN 39
22
23 BOOL WINAPI
24 AddAuditAccessAceEx(PACL pAcl,
25 DWORD dwAceRevision,
26 DWORD AceFlags,
27 DWORD dwAccessMask,
28 PSID pSid,
29 BOOL bAuditSuccess,
30 BOOL bAuditFailure);
31
32 typedef struct RECORD
33 {
34 LPCWSTR key;
35 DWORD value;
36 } RECORD;
37
38
39 typedef struct _MAX_SID
40 {
41 /* same fields as struct _SID */
42 BYTE Revision;
43 BYTE SubAuthorityCount;
44 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
45 DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
46 } MAX_SID;
47
48 typedef struct WELLKNOWNSID
49 {
50 WCHAR wstr[2];
51 WELL_KNOWN_SID_TYPE Type;
52 MAX_SID Sid;
53 } WELLKNOWNSID;
54
55 typedef struct _ACEFLAG
56 {
57 LPCWSTR wstr;
58 DWORD value;
59 } ACEFLAG, *LPACEFLAG;
60
61 static const WELLKNOWNSID WellKnownSids[] =
62 {
63 { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
64 { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
65 { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
66 { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
67 { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
68 { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
69 { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
70 { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
71 { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
72 { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
73 { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
74 { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
75 { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
76 { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
77 { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
78 { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
79 { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
80 { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
81 { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
82 { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
83 { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
84 { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
85 { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
86 { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
87 { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
88 { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
89 { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
90 { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
91 { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
92 { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
93 { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
94 { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
95 { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
96 { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
97 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
98 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
99 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
100 { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } },
101 { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } },
102 { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } },
103 { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } },
104 { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } },
105 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS } } },
106 { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } },
107 { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } },
108 { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } },
109 { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } },
110 { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } },
111 };
112
113 typedef struct WELLKNOWNRID
114 {
115 WELL_KNOWN_SID_TYPE Type;
116 DWORD Rid;
117 } WELLKNOWNRID;
118
119 static const WELLKNOWNRID WellKnownRids[] = {
120 { WinAccountAdministratorSid, DOMAIN_USER_RID_ADMIN },
121 { WinAccountGuestSid, DOMAIN_USER_RID_GUEST },
122 { WinAccountKrbtgtSid, DOMAIN_USER_RID_KRBTGT },
123 { WinAccountDomainAdminsSid, DOMAIN_GROUP_RID_ADMINS },
124 { WinAccountDomainUsersSid, DOMAIN_GROUP_RID_USERS },
125 { WinAccountDomainGuestsSid, DOMAIN_GROUP_RID_GUESTS },
126 { WinAccountComputersSid, DOMAIN_GROUP_RID_COMPUTERS },
127 { WinAccountControllersSid, DOMAIN_GROUP_RID_CONTROLLERS },
128 { WinAccountCertAdminsSid, DOMAIN_GROUP_RID_CERT_ADMINS },
129 { WinAccountSchemaAdminsSid, DOMAIN_GROUP_RID_SCHEMA_ADMINS },
130 { WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
131 { WinAccountPolicyAdminsSid, DOMAIN_GROUP_RID_POLICY_ADMINS },
132 { WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
133 };
134
135 static const SID sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
136
137 /*
138 * ACE types
139 */
140 static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0};
141 static const WCHAR SDDL_ACCESS_DENIED[] = {'D',0};
142 static const WCHAR SDDL_OBJECT_ACCESS_ALLOWED[] = {'O','A',0};
143 static const WCHAR SDDL_OBJECT_ACCESS_DENIED[] = {'O','D',0};
144 static const WCHAR SDDL_AUDIT[] = {'A','U',0};
145 static const WCHAR SDDL_ALARM[] = {'A','L',0};
146 static const WCHAR SDDL_OBJECT_AUDIT[] = {'O','U',0};
147 static const WCHAR SDDL_OBJECT_ALARM[] = {'O','L',0};
148
149 /*
150 * SDDL ADS Rights
151 */
152 #define ADS_RIGHT_DS_CREATE_CHILD 0x0001
153 #define ADS_RIGHT_DS_DELETE_CHILD 0x0002
154 #define ADS_RIGHT_ACTRL_DS_LIST 0x0004
155 #define ADS_RIGHT_DS_SELF 0x0008
156 #define ADS_RIGHT_DS_READ_PROP 0x0010
157 #define ADS_RIGHT_DS_WRITE_PROP 0x0020
158 #define ADS_RIGHT_DS_DELETE_TREE 0x0040
159 #define ADS_RIGHT_DS_LIST_OBJECT 0x0080
160 #define ADS_RIGHT_DS_CONTROL_ACCESS 0x0100
161
162 /*
163 * ACE flags
164 */
165 static const WCHAR SDDL_CONTAINER_INHERIT[] = {'C','I',0};
166 static const WCHAR SDDL_OBJECT_INHERIT[] = {'O','I',0};
167 static const WCHAR SDDL_NO_PROPAGATE[] = {'N','P',0};
168 static const WCHAR SDDL_INHERIT_ONLY[] = {'I','O',0};
169 static const WCHAR SDDL_INHERITED[] = {'I','D',0};
170 static const WCHAR SDDL_AUDIT_SUCCESS[] = {'S','A',0};
171 static const WCHAR SDDL_AUDIT_FAILURE[] = {'F','A',0};
172
173 static const char * debugstr_sid(PSID sid)
174 {
175 int auth = 0;
176 SID * psid = (SID *)sid;
177
178 if (psid == NULL)
179 return "(null)";
180
181 auth = psid->IdentifierAuthority.Value[5] +
182 (psid->IdentifierAuthority.Value[4] << 8) +
183 (psid->IdentifierAuthority.Value[3] << 16) +
184 (psid->IdentifierAuthority.Value[2] << 24);
185
186 switch (psid->SubAuthorityCount) {
187 case 0:
188 return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
189 case 1:
190 return wine_dbg_sprintf("S-%d-%d-%lu", psid->Revision, auth,
191 psid->SubAuthority[0]);
192 case 2:
193 return wine_dbg_sprintf("S-%d-%d-%lu-%lu", psid->Revision, auth,
194 psid->SubAuthority[0], psid->SubAuthority[1]);
195 case 3:
196 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu", psid->Revision, auth,
197 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
198 case 4:
199 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu", psid->Revision, auth,
200 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
201 psid->SubAuthority[3]);
202 case 5:
203 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
204 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
205 psid->SubAuthority[3], psid->SubAuthority[4]);
206 case 6:
207 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
208 psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
209 psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
210 case 7:
211 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
212 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
213 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
214 psid->SubAuthority[6]);
215 case 8:
216 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
217 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
218 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
219 psid->SubAuthority[6], psid->SubAuthority[7]);
220 }
221 return "(too-big)";
222 }
223
224 static const ACEFLAG AceRights[] =
225 {
226 { SDDL_GENERIC_ALL, GENERIC_ALL },
227 { SDDL_GENERIC_READ, GENERIC_READ },
228 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
229 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
230
231 { SDDL_READ_CONTROL, READ_CONTROL },
232 { SDDL_STANDARD_DELETE, DELETE },
233 { SDDL_WRITE_DAC, WRITE_DAC },
234 { SDDL_WRITE_OWNER, WRITE_OWNER },
235
236 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP},
237 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP},
238 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD},
239 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD},
240 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST},
241 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF},
242 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT},
243 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE},
244 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS},
245
246 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
247 { SDDL_FILE_READ, FILE_GENERIC_READ },
248 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
249 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
250
251 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
252 { SDDL_KEY_READ, KEY_READ },
253 { SDDL_KEY_WRITE, KEY_WRITE },
254 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
255 { NULL, 0 },
256 };
257
258 static const LPCWSTR AceRightBitNames[32] = {
259 SDDL_CREATE_CHILD, /* 0 */
260 SDDL_DELETE_CHILD,
261 SDDL_LIST_CHILDREN,
262 SDDL_SELF_WRITE,
263 SDDL_READ_PROPERTY, /* 4 */
264 SDDL_WRITE_PROPERTY,
265 SDDL_DELETE_TREE,
266 SDDL_LIST_OBJECT,
267 SDDL_CONTROL_ACCESS, /* 8 */
268 NULL,
269 NULL,
270 NULL,
271 NULL, /* 12 */
272 NULL,
273 NULL,
274 NULL,
275 SDDL_STANDARD_DELETE, /* 16 */
276 SDDL_READ_CONTROL,
277 SDDL_WRITE_DAC,
278 SDDL_WRITE_OWNER,
279 NULL, /* 20 */
280 NULL,
281 NULL,
282 NULL,
283 NULL, /* 24 */
284 NULL,
285 NULL,
286 NULL,
287 SDDL_GENERIC_ALL, /* 28 */
288 SDDL_GENERIC_EXECUTE,
289 SDDL_GENERIC_WRITE,
290 SDDL_GENERIC_READ
291 };
292
293
294 /* set last error code from NT status and get the proper boolean return value */
295 /* used for functions that are a simple wrapper around the corresponding ntdll API */
296 static __inline BOOL set_ntstatus( NTSTATUS status )
297 {
298 if (status) SetLastError( RtlNtStatusToDosError( status ));
299 return !status;
300 }
301
302 static BOOL
303 FindKeyInTable(
304 IN const RECORD* Table,
305 IN LPCWSTR Key,
306 OUT SIZE_T* pKeyLength,
307 OUT DWORD* pItem)
308 {
309 const RECORD* pRecord = Table;
310 while (pRecord->key != NULL)
311 {
312 if (wcsncmp(pRecord->key, Key, wcslen(pRecord->key)) == 0)
313 {
314 *pKeyLength = wcslen(pRecord->key);
315 *pItem = pRecord->value;
316 return TRUE;
317 }
318 pRecord++;
319 }
320 SetLastError(ERROR_INVALID_PARAMETER);
321 return FALSE;
322 }
323
324 static BOOL
325 ParseSidString(
326 IN LPCWSTR Buffer,
327 OUT PSID* pSid,
328 OUT SIZE_T* pLength)
329 {
330 WCHAR str[SDDL_ALIAS_SIZE + 1];
331 LPWSTR strSid;
332 LPCWSTR end;
333 BOOL ret;
334 DWORD i;
335
336 wcsncpy(str, Buffer, SDDL_ALIAS_SIZE);
337 for (i = SDDL_ALIAS_SIZE; i > 0; i--)
338 {
339 str[i] = UNICODE_NULL;
340 if (ConvertStringSidToSidW(str, pSid))
341 {
342 *pLength = i;
343 return TRUE;
344 }
345 }
346
347 end = wcschr(Buffer, SDDL_ACE_ENDC);
348 if (!end)
349 {
350 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
351 return FALSE;
352 }
353 strSid = (LPWSTR)LocalAlloc(0, (end - Buffer) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
354 if (!strSid)
355 {
356 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
357 return FALSE;
358 }
359 wcsncpy(strSid, Buffer, end - Buffer + 1);
360 strSid[end - Buffer] = UNICODE_NULL;
361 *pLength = end - Buffer;
362 ret = ConvertStringSidToSidW(strSid, pSid);
363 LocalFree(strSid);
364 return ret;
365 }
366
367 static const RECORD DaclFlagTable[] =
368 {
369 { SDDL_PROTECTED, SE_DACL_PROTECTED },
370 { SDDL_AUTO_INHERIT_REQ, SE_DACL_AUTO_INHERIT_REQ },
371 { SDDL_AUTO_INHERITED, SE_DACL_AUTO_INHERITED },
372 { NULL, 0 },
373 };
374
375 static const RECORD SaclFlagTable[] =
376 {
377 { SDDL_PROTECTED, SE_SACL_PROTECTED },
378 { SDDL_AUTO_INHERIT_REQ, SE_SACL_AUTO_INHERIT_REQ },
379 { SDDL_AUTO_INHERITED, SE_SACL_AUTO_INHERITED },
380 { NULL, 0 },
381 };
382
383 static const RECORD AceFlagTable[] =
384 {
385 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
386 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
387 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
388 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
389 { SDDL_INHERITED, INHERITED_ACE },
390 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
391 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
392 { NULL, 0 },
393 };
394
395 static BOOL
396 ParseFlagsString(
397 IN LPCWSTR Buffer,
398 IN const RECORD* FlagTable,
399 IN WCHAR LimitChar,
400 OUT DWORD* pFlags,
401 OUT SIZE_T* pLength)
402 {
403 LPCWSTR ptr = Buffer;
404 SIZE_T PartialLength;
405 DWORD Flag;
406
407 *pFlags = 0;
408 while (*ptr != LimitChar)
409 {
410 if (!FindKeyInTable(FlagTable, ptr, &PartialLength, &Flag))
411 return FALSE;
412 *pFlags |= Flag;
413 ptr += PartialLength;
414 }
415 *pLength = ptr - Buffer;
416 return TRUE;
417 }
418
419 static const RECORD AccessMaskTable[] =
420 {
421 { SDDL_GENERIC_ALL, GENERIC_ALL },
422 { SDDL_GENERIC_READ, GENERIC_READ },
423 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
424 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
425 { SDDL_READ_CONTROL, READ_CONTROL },
426 { SDDL_STANDARD_DELETE, DELETE },
427 { SDDL_WRITE_DAC, WRITE_DAC },
428 { SDDL_WRITE_OWNER, WRITE_OWNER },
429 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP },
430 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP },
431 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD },
432 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD },
433 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST },
434 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF },
435 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT },
436 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE },
437 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS },
438 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
439 { SDDL_FILE_READ, FILE_GENERIC_READ },
440 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
441 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
442 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
443 { SDDL_KEY_READ, KEY_READ },
444 { SDDL_KEY_WRITE, KEY_WRITE },
445 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
446 { NULL, 0 },
447 };
448
449 static BOOL
450 ParseAccessMaskString(
451 IN LPCWSTR Buffer,
452 OUT DWORD* pAccessMask,
453 OUT SIZE_T* pLength)
454 {
455 LPCWSTR szAcl = Buffer;
456 BOOL RetVal = FALSE;
457 LPCWSTR ptr;
458
459 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
460 {
461 LPCWSTR p = szAcl;
462
463 while (*p && *p != ';')
464 p++;
465
466 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
467 {
468 *pAccessMask = strtoulW(szAcl, NULL, 16);
469 ptr = wcschr(Buffer, SDDL_SEPERATORC);
470 if (ptr)
471 {
472 *pLength = ptr - Buffer;
473 RetVal = TRUE;
474 }
475 }
476 }
477 else
478 {
479 RetVal = ParseFlagsString(Buffer, AccessMaskTable, SDDL_SEPERATORC, pAccessMask, pLength);
480 }
481
482 return RetVal;
483 }
484
485 static BOOL
486 ParseGuidString(
487 IN LPCWSTR Buffer,
488 OUT GUID* pGuid,
489 OUT BOOL* pIsGuidValid,
490 OUT SIZE_T* pLength)
491 {
492 WCHAR GuidStr[MAX_GUID_STRING_LEN + 1];
493 LPCWSTR end;
494
495 end = wcschr(Buffer, SDDL_SEPERATORC);
496 if (!end)
497 {
498 SetLastError(ERROR_INVALID_PARAMETER);
499 return FALSE;
500 }
501
502 *pLength = end - Buffer;
503 *pIsGuidValid = (end != Buffer);
504 if (!*pIsGuidValid)
505 return TRUE;
506
507 if (end - Buffer > MAX_GUID_STRING_LEN - 1)
508 {
509 SetLastError(ERROR_INVALID_PARAMETER);
510 return FALSE;
511 }
512 GuidStr[end - Buffer] = UNICODE_NULL;
513 wcsncpy(GuidStr, Buffer, end - Buffer);
514 if (RPC_S_OK != UuidFromStringW((unsigned short*)&GuidStr, pGuid))
515 {
516 SetLastError(ERROR_INVALID_PARAMETER);
517 return FALSE;
518 }
519 return TRUE;
520 }
521
522 static const RECORD AceTypeTable[] =
523 {
524 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
525 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
526 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
527 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
528 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
529 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
530 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
531 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
532 { NULL, 0 },
533 };
534
535 static BOOL
536 ParseAceString(
537 IN LPCWSTR Buffer,
538 IN PACL pAcl,
539 OUT SIZE_T* pLength)
540 {
541 LPCWSTR ptr = Buffer;
542 SIZE_T PartialLength;
543 DWORD aceType, aceFlags, accessMask;
544 GUID object, inheritObject;
545 BOOL objectValid, inheritObjectValid;
546 PSID sid = NULL;
547 BOOL ret;
548
549 if (*ptr != SDDL_ACE_BEGINC)
550 {
551 SetLastError(ERROR_INVALID_PARAMETER);
552 return FALSE;
553 }
554 ptr++; /* Skip SDDL_ACE_BEGINC */
555
556 if (!FindKeyInTable(AceTypeTable, ptr, &PartialLength, &aceType))
557 return FALSE;
558 ptr += PartialLength;
559
560 if (*ptr != SDDL_SEPERATORC)
561 {
562 SetLastError(ERROR_INVALID_PARAMETER);
563 return FALSE;
564 }
565 ptr++; /* Skip SDDL_SEPERATORC */
566
567 if (!ParseFlagsString(ptr, AceFlagTable, SDDL_SEPERATORC, &aceFlags, &PartialLength))
568 return FALSE;
569 ptr += PartialLength + 1;
570
571 if (!ParseAccessMaskString(ptr, &accessMask, &PartialLength))
572 return FALSE;
573 ptr += PartialLength + 1;
574
575 if (!ParseGuidString(ptr, &object, &objectValid, &PartialLength))
576 return FALSE;
577 ptr += PartialLength + 1;
578
579 if (!ParseGuidString(ptr, &inheritObject, &inheritObjectValid, &PartialLength))
580 return FALSE;
581 ptr += PartialLength + 1;
582
583 if (!ParseSidString(ptr, &sid, &PartialLength))
584 return FALSE;
585 ptr += PartialLength;
586 if (*ptr != SDDL_ACE_ENDC)
587 {
588 SetLastError(ERROR_INVALID_PARAMETER);
589 return FALSE;
590 }
591 ptr++; /* Skip SDDL_ACE_ENDC */
592 *pLength = ptr - Buffer;
593
594 switch (aceType)
595 {
596 case ACCESS_ALLOWED_ACE_TYPE:
597 ret = AddAccessAllowedAceEx(
598 pAcl,
599 ACL_REVISION_DS,
600 aceFlags,
601 accessMask,
602 sid);
603 break;
604 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
605 ret = AddAccessAllowedObjectAce(
606 pAcl,
607 ACL_REVISION_DS,
608 aceFlags,
609 accessMask,
610 objectValid ? &object : NULL,
611 inheritObjectValid ? &inheritObject : NULL,
612 sid);
613 break;
614 case ACCESS_DENIED_ACE_TYPE:
615 ret = AddAccessDeniedAceEx(
616 pAcl,
617 ACL_REVISION_DS,
618 aceFlags,
619 accessMask,
620 sid);
621 break;
622 case ACCESS_DENIED_OBJECT_ACE_TYPE:
623 ret = AddAccessDeniedObjectAce(
624 pAcl,
625 ACL_REVISION_DS,
626 aceFlags,
627 accessMask,
628 objectValid ? &object : NULL,
629 inheritObjectValid ? &inheritObject : NULL,
630 sid);
631 break;
632 case SYSTEM_AUDIT_ACE_TYPE:
633 ret = AddAuditAccessAceEx(
634 pAcl,
635 ACL_REVISION_DS,
636 aceFlags,
637 accessMask,
638 sid,
639 FALSE,
640 FALSE);
641 break;
642 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
643 ret = AddAuditAccessObjectAce(
644 pAcl,
645 ACL_REVISION_DS,
646 aceFlags,
647 accessMask,
648 objectValid ? &object : NULL,
649 inheritObjectValid ? &inheritObject : NULL,
650 sid,
651 FALSE,
652 FALSE);
653 break;
654 case SYSTEM_ALARM_ACE_TYPE:
655 case SYSTEM_ALARM_OBJECT_ACE_TYPE:
656 default:
657 {
658 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
659 ret = FALSE;
660 }
661 }
662 LocalFree(sid);
663 return ret;
664 }
665
666 /* Exported functions */
667
668 /*
669 * @implemented
670 */
671 BOOL WINAPI
672 AllocateLocallyUniqueId(PLUID Luid)
673 {
674 NTSTATUS Status;
675
676 Status = NtAllocateLocallyUniqueId (Luid);
677 if (!NT_SUCCESS (Status))
678 {
679 SetLastError(RtlNtStatusToDosError(Status));
680 return FALSE;
681 }
682
683 return TRUE;
684 }
685
686
687 /*
688 * @implemented
689 */
690 BOOL WINAPI
691 AllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
692 BYTE nSubAuthorityCount,
693 DWORD dwSubAuthority0,
694 DWORD dwSubAuthority1,
695 DWORD dwSubAuthority2,
696 DWORD dwSubAuthority3,
697 DWORD dwSubAuthority4,
698 DWORD dwSubAuthority5,
699 DWORD dwSubAuthority6,
700 DWORD dwSubAuthority7,
701 PSID *pSid)
702 {
703 NTSTATUS Status;
704
705 Status = RtlAllocateAndInitializeSid(pIdentifierAuthority,
706 nSubAuthorityCount,
707 dwSubAuthority0,
708 dwSubAuthority1,
709 dwSubAuthority2,
710 dwSubAuthority3,
711 dwSubAuthority4,
712 dwSubAuthority5,
713 dwSubAuthority6,
714 dwSubAuthority7,
715 pSid);
716 if (!NT_SUCCESS(Status))
717 {
718 SetLastError(RtlNtStatusToDosError(Status));
719 return FALSE;
720 }
721
722 return TRUE;
723 }
724
725
726 /*
727 * @implemented
728 */
729 BOOL WINAPI
730 CopySid(DWORD nDestinationSidLength,
731 PSID pDestinationSid,
732 PSID pSourceSid)
733 {
734 NTSTATUS Status;
735
736 Status = RtlCopySid(nDestinationSidLength,
737 pDestinationSid,
738 pSourceSid);
739 if (!NT_SUCCESS (Status))
740 {
741 SetLastError(RtlNtStatusToDosError(Status));
742 return FALSE;
743 }
744
745 return TRUE;
746 }
747
748 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
749 {
750 if (cch == -1)
751 cch = strlenW(string);
752
753 if (plen)
754 *plen += cch;
755
756 if (pwptr)
757 {
758 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
759 *pwptr += cch;
760 }
761 }
762
763 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
764 {
765 DWORD i;
766 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
767 WCHAR subauthfmt[] = { '-','%','u',0 };
768 WCHAR buf[26];
769 SID *pisid = psid;
770
771 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
772 {
773 SetLastError(ERROR_INVALID_SID);
774 return FALSE;
775 }
776
777 if (pisid->IdentifierAuthority.Value[0] ||
778 pisid->IdentifierAuthority.Value[1])
779 {
780 FIXME("not matching MS' bugs\n");
781 SetLastError(ERROR_INVALID_SID);
782 return FALSE;
783 }
784
785 sprintfW( buf, fmt, pisid->Revision,
786 MAKELONG(
787 MAKEWORD( pisid->IdentifierAuthority.Value[5],
788 pisid->IdentifierAuthority.Value[4] ),
789 MAKEWORD( pisid->IdentifierAuthority.Value[3],
790 pisid->IdentifierAuthority.Value[2] )
791 ) );
792 DumpString(buf, -1, pwptr, plen);
793
794 for( i=0; i<pisid->SubAuthorityCount; i++ )
795 {
796 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
797 DumpString(buf, -1, pwptr, plen);
798 }
799 return TRUE;
800 }
801
802 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
803 {
804 size_t i;
805 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
806 {
807 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
808 {
809 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
810 return TRUE;
811 }
812 }
813
814 return DumpSidNumeric(psid, pwptr, plen);
815 }
816
817 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
818 {
819 static const WCHAR fmtW[] = {'0','x','%','x',0};
820 WCHAR buf[15];
821 size_t i;
822
823 if (mask == 0)
824 return;
825
826 /* first check if the right have name */
827 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
828 {
829 if (AceRights[i].wstr == NULL)
830 break;
831 if (mask == AceRights[i].value)
832 {
833 DumpString(AceRights[i].wstr, -1, pwptr, plen);
834 return;
835 }
836 }
837
838 /* then check if it can be built from bit names */
839 for (i = 0; i < 32; i++)
840 {
841 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
842 {
843 /* can't be built from bit names */
844 sprintfW(buf, fmtW, mask);
845 DumpString(buf, -1, pwptr, plen);
846 return;
847 }
848 }
849
850 /* build from bit names */
851 for (i = 0; i < 32; i++)
852 if (mask & (1 << i))
853 DumpString(AceRightBitNames[i], -1, pwptr, plen);
854 }
855
856 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
857 {
858 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
859 static const WCHAR openbr = '(';
860 static const WCHAR closebr = ')';
861 static const WCHAR semicolon = ';';
862
863 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
864 {
865 SetLastError(ERROR_INVALID_ACL);
866 return FALSE;
867 }
868
869 piace = (ACCESS_ALLOWED_ACE *)pace;
870 DumpString(&openbr, 1, pwptr, plen);
871 switch (piace->Header.AceType)
872 {
873 case ACCESS_ALLOWED_ACE_TYPE:
874 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
875 break;
876 case ACCESS_DENIED_ACE_TYPE:
877 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
878 break;
879 case SYSTEM_AUDIT_ACE_TYPE:
880 DumpString(SDDL_AUDIT, -1, pwptr, plen);
881 break;
882 case SYSTEM_ALARM_ACE_TYPE:
883 DumpString(SDDL_ALARM, -1, pwptr, plen);
884 break;
885 }
886 DumpString(&semicolon, 1, pwptr, plen);
887
888 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
889 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
890 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
891 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
892 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
893 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
894 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
895 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
896 if (piace->Header.AceFlags & INHERITED_ACE)
897 DumpString(SDDL_INHERITED, -1, pwptr, plen);
898 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
899 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
900 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
901 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
902 DumpString(&semicolon, 1, pwptr, plen);
903 DumpRights(piace->Mask, pwptr, plen);
904 DumpString(&semicolon, 1, pwptr, plen);
905 /* objects not supported */
906 DumpString(&semicolon, 1, pwptr, plen);
907 /* objects not supported */
908 DumpString(&semicolon, 1, pwptr, plen);
909 if (!DumpSid((PSID)&piace->SidStart, pwptr, plen))
910 return FALSE;
911 DumpString(&closebr, 1, pwptr, plen);
912 return TRUE;
913 }
914
915 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
916 {
917 WORD count;
918 int i;
919
920 if (protected)
921 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
922 if (autoInheritReq)
923 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
924 if (autoInherited)
925 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
926
927 if (pacl == NULL)
928 return TRUE;
929
930 if (!IsValidAcl(pacl))
931 return FALSE;
932
933 count = pacl->AceCount;
934 for (i = 0; i < count; i++)
935 {
936 LPVOID ace;
937 if (!GetAce(pacl, i, &ace))
938 return FALSE;
939 if (!DumpAce(ace, pwptr, plen))
940 return FALSE;
941 }
942
943 return TRUE;
944 }
945
946 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
947 {
948 static const WCHAR prefix[] = {'O',':',0};
949 BOOL bDefaulted;
950 PSID psid;
951
952 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
953 return FALSE;
954
955 if (psid == NULL)
956 return TRUE;
957
958 DumpString(prefix, -1, pwptr, plen);
959 if (!DumpSid(psid, pwptr, plen))
960 return FALSE;
961 return TRUE;
962 }
963
964 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
965 {
966 static const WCHAR prefix[] = {'G',':',0};
967 BOOL bDefaulted;
968 PSID psid;
969
970 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
971 return FALSE;
972
973 if (psid == NULL)
974 return TRUE;
975
976 DumpString(prefix, -1, pwptr, plen);
977 if (!DumpSid(psid, pwptr, plen))
978 return FALSE;
979 return TRUE;
980 }
981
982 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
983 {
984 static const WCHAR dacl[] = {'D',':',0};
985 SECURITY_DESCRIPTOR_CONTROL control;
986 BOOL present, defaulted;
987 DWORD revision;
988 PACL pacl;
989
990 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
991 return FALSE;
992
993 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
994 return FALSE;
995
996 if (!present)
997 return TRUE;
998
999 DumpString(dacl, 2, pwptr, plen);
1000 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
1001 return FALSE;
1002 return TRUE;
1003 }
1004
1005 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
1006 {
1007 static const WCHAR sacl[] = {'S',':',0};
1008 SECURITY_DESCRIPTOR_CONTROL control;
1009 BOOL present, defaulted;
1010 DWORD revision;
1011 PACL pacl;
1012
1013 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
1014 return FALSE;
1015
1016 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
1017 return FALSE;
1018
1019 if (!present)
1020 return TRUE;
1021
1022 DumpString(sacl, 2, pwptr, plen);
1023 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
1024 return FALSE;
1025 return TRUE;
1026 }
1027
1028 /******************************************************************************
1029 * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
1030 * @implemented
1031 */
1032 BOOL WINAPI
1033 ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor,
1034 DWORD SDRevision,
1035 SECURITY_INFORMATION SecurityInformation,
1036 LPWSTR *OutputString,
1037 PULONG OutputLen)
1038 {
1039 ULONG len;
1040 WCHAR *wptr, *wstr;
1041
1042 if (SDRevision != SDDL_REVISION_1)
1043 {
1044 ERR("Pogram requested unknown SDDL revision %d\n", SDRevision);
1045 SetLastError(ERROR_UNKNOWN_REVISION);
1046 return FALSE;
1047 }
1048
1049 len = 0;
1050 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1051 if (!DumpOwner(SecurityDescriptor, NULL, &len))
1052 return FALSE;
1053 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1054 if (!DumpGroup(SecurityDescriptor, NULL, &len))
1055 return FALSE;
1056 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1057 if (!DumpDacl(SecurityDescriptor, NULL, &len))
1058 return FALSE;
1059 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1060 if (!DumpSacl(SecurityDescriptor, NULL, &len))
1061 return FALSE;
1062
1063 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
1064 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1065 if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
1066 return FALSE;
1067 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1068 if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
1069 return FALSE;
1070 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1071 if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
1072 return FALSE;
1073 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1074 if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
1075 return FALSE;
1076 *wptr = 0;
1077
1078 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
1079 *OutputString = wstr;
1080 if (OutputLen)
1081 *OutputLen = strlenW(*OutputString)+1;
1082 return TRUE;
1083 }
1084
1085
1086 /******************************************************************************
1087 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
1088 * @implemented
1089 */
1090 BOOL WINAPI
1091 ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor,
1092 DWORD SDRevision,
1093 SECURITY_INFORMATION Information,
1094 LPSTR *OutputString,
1095 PULONG OutputLen)
1096 {
1097 LPWSTR wstr;
1098 ULONG len;
1099 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
1100 {
1101 int lenA;
1102
1103 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
1104 *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
1105 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
1106 LocalFree(wstr);
1107
1108 if (OutputLen != NULL)
1109 *OutputLen = lenA;
1110 return TRUE;
1111 }
1112 else
1113 {
1114 *OutputString = NULL;
1115 if (OutputLen)
1116 *OutputLen = 0;
1117 return FALSE;
1118 }
1119 }
1120
1121 /******************************************************************************
1122 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
1123 * @implemented
1124 */
1125 BOOL WINAPI
1126 ConvertStringSecurityDescriptorToSecurityDescriptorW(
1127 IN LPCWSTR StringSecurityDescriptor,
1128 IN DWORD StringSDRevision,
1129 OUT PSECURITY_DESCRIPTOR* SecurityDescriptor,
1130 OUT PULONG SecurityDescriptorSize)
1131 {
1132 PSECURITY_DESCRIPTOR sd = NULL;
1133 BOOL ret = FALSE;
1134
1135 if (!StringSecurityDescriptor)
1136 SetLastError(ERROR_INVALID_PARAMETER);
1137 else if (StringSDRevision != SDDL_REVISION_1)
1138 SetLastError(ERROR_INVALID_PARAMETER);
1139 else
1140 {
1141 LPCWSTR ptr = StringSecurityDescriptor;
1142 DWORD numberOfAces = 0;
1143 DWORD relativeSdSize;
1144 SIZE_T MaxAclSize;
1145 PSECURITY_DESCRIPTOR relativeSd = NULL;
1146 PSID pSid;
1147 PACL pAcl;
1148 BOOL present, dummy;
1149 /* An easy way to know how much space we need for an ACL is to count
1150 * the number of ACEs and say that we have 1 SID by ACE
1151 */
1152 ptr = wcschr(StringSecurityDescriptor, SDDL_ACE_BEGINC);
1153 while (ptr != NULL)
1154 {
1155 numberOfAces++;
1156 ptr = wcschr(ptr + 1, SDDL_ACE_BEGINC);
1157 }
1158 MaxAclSize = sizeof(ACL) + numberOfAces *
1159 (sizeof(ACCESS_ALLOWED_OBJECT_ACE) + SECURITY_MAX_SID_SIZE);
1160
1161 sd = (SECURITY_DESCRIPTOR*)LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR));
1162 if (!sd)
1163 {
1164 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1165 return FALSE;
1166 }
1167 ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
1168 if (!ret)
1169 goto cleanup;
1170
1171 /* Now, really parse the string */
1172 ptr = StringSecurityDescriptor;
1173 while (*ptr)
1174 {
1175 if (ptr[1] != SDDL_DELIMINATORC)
1176 {
1177 SetLastError(ERROR_INVALID_PARAMETER);
1178 ret = FALSE;
1179 goto cleanup;
1180 }
1181 ptr += 2;
1182 switch (ptr[-2])
1183 {
1184 case 'O':
1185 case 'G':
1186 {
1187 PSID pSid;
1188 SIZE_T Length;
1189
1190 ret = ParseSidString(ptr, &pSid, &Length);
1191 if (!ret)
1192 goto cleanup;
1193 if (ptr[-2] == 'O')
1194 ret = SetSecurityDescriptorOwner(sd, pSid, FALSE);
1195 else
1196 ret = SetSecurityDescriptorGroup(sd, pSid, FALSE);
1197 if (!ret)
1198 {
1199 LocalFree(pSid);
1200 goto cleanup;
1201 }
1202 ptr += Length;
1203 break;
1204 }
1205 case 'D':
1206 case 'S':
1207 {
1208 DWORD aclFlags;
1209 SIZE_T Length;
1210 BOOL isDacl = (ptr[-2] == 'D');
1211
1212 if (isDacl)
1213 ret = ParseFlagsString(ptr, DaclFlagTable, SDDL_ACE_BEGINC, &aclFlags, &Length);
1214 else
1215 ret = ParseFlagsString(ptr, SaclFlagTable, SDDL_ACE_BEGINC, &aclFlags, &Length);
1216 if (!ret)
1217 goto cleanup;
1218 pAcl = (PACL)LocalAlloc(0, MaxAclSize);
1219 if (!pAcl)
1220 {
1221 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1222 ret = FALSE;
1223 goto cleanup;
1224 }
1225 if (!InitializeAcl(pAcl, (DWORD)MaxAclSize, ACL_REVISION_DS))
1226 {
1227 LocalFree(pAcl);
1228 goto cleanup;
1229 }
1230 if (aclFlags != 0)
1231 {
1232 ret = SetSecurityDescriptorControl(
1233 sd,
1234 (SECURITY_DESCRIPTOR_CONTROL)aclFlags,
1235 (SECURITY_DESCRIPTOR_CONTROL)aclFlags);
1236 if (!ret)
1237 {
1238 LocalFree(pAcl);
1239 goto cleanup;
1240 }
1241 }
1242 ptr += Length;
1243 while (*ptr == SDDL_ACE_BEGINC)
1244 {
1245 ret = ParseAceString(ptr, pAcl, &Length);
1246 if (!ret)
1247 {
1248 LocalFree(pAcl);
1249 goto cleanup;
1250 }
1251 ptr += Length;
1252 }
1253 if (isDacl)
1254 ret = SetSecurityDescriptorDacl(sd, TRUE, pAcl, FALSE);
1255 else
1256 ret = SetSecurityDescriptorSacl(sd, TRUE, pAcl, FALSE);
1257 if (!ret)
1258 {
1259 LocalFree(pAcl);
1260 goto cleanup;
1261 }
1262 break;
1263 }
1264 default:
1265 {
1266 SetLastError(ERROR_INVALID_PARAMETER);
1267 ret = FALSE;
1268 goto cleanup;
1269 }
1270 }
1271 }
1272
1273 relativeSdSize = 0;
1274 while (TRUE)
1275 {
1276 if (relativeSd)
1277 LocalFree(relativeSd);
1278 relativeSd = LocalAlloc(0, relativeSdSize);
1279 if (!relativeSd)
1280 {
1281 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1282 goto cleanup;
1283 }
1284 ret = MakeSelfRelativeSD(sd, relativeSd, &relativeSdSize);
1285 if (ret || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1286 break;
1287 }
1288 if (SecurityDescriptorSize)
1289 *SecurityDescriptorSize = relativeSdSize;
1290 *SecurityDescriptor = relativeSd;
1291
1292 cleanup:
1293 if (GetSecurityDescriptorOwner(sd, &pSid, &dummy))
1294 LocalFree(pSid);
1295 if (GetSecurityDescriptorGroup(sd, &pSid, &dummy))
1296 LocalFree(pSid);
1297 if (GetSecurityDescriptorDacl(sd, &present, &pAcl, &dummy) && present)
1298 LocalFree(pAcl);
1299 if (GetSecurityDescriptorSacl(sd, &present, &pAcl, &dummy) && present)
1300 LocalFree(pAcl);
1301 LocalFree(sd);
1302 return ret;
1303 }
1304 return FALSE;
1305 }
1306
1307 /* Winehq cvs 20050916 */
1308 /******************************************************************************
1309 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
1310 * @implemented
1311 */
1312 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
1313 LPCSTR StringSecurityDescriptor,
1314 DWORD StringSDRevision,
1315 PSECURITY_DESCRIPTOR* SecurityDescriptor,
1316 PULONG SecurityDescriptorSize)
1317 {
1318 UINT len;
1319 BOOL ret = FALSE;
1320 LPWSTR StringSecurityDescriptorW;
1321
1322 len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
1323 StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1324
1325 if (StringSecurityDescriptorW)
1326 {
1327 MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
1328
1329 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
1330 StringSDRevision, SecurityDescriptor,
1331 SecurityDescriptorSize);
1332 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
1333 }
1334
1335 return ret;
1336 }
1337
1338 /*
1339 * @implemented
1340 */
1341 BOOL WINAPI
1342 EqualPrefixSid(PSID pSid1,
1343 PSID pSid2)
1344 {
1345 return RtlEqualPrefixSid (pSid1, pSid2);
1346 }
1347
1348
1349 /*
1350 * @implemented
1351 */
1352 BOOL WINAPI
1353 EqualSid(PSID pSid1,
1354 PSID pSid2)
1355 {
1356 return RtlEqualSid (pSid1, pSid2);
1357 }
1358
1359
1360 /*
1361 * @implemented
1362 *
1363 * RETURNS
1364 * Docs says this function does NOT return a value
1365 * even thou it's defined to return a PVOID...
1366 */
1367 PVOID WINAPI
1368 FreeSid(PSID pSid)
1369 {
1370 return RtlFreeSid(pSid);
1371 }
1372
1373
1374 /*
1375 * @implemented
1376 */
1377 DWORD WINAPI
1378 GetLengthSid(PSID pSid)
1379 {
1380 return (DWORD)RtlLengthSid(pSid);
1381 }
1382
1383
1384 /*
1385 * @implemented
1386 */
1387 PSID_IDENTIFIER_AUTHORITY WINAPI
1388 GetSidIdentifierAuthority(PSID pSid)
1389 {
1390 return RtlIdentifierAuthoritySid(pSid);
1391 }
1392
1393
1394 /*
1395 * @implemented
1396 */
1397 DWORD WINAPI
1398 GetSidLengthRequired(UCHAR nSubAuthorityCount)
1399 {
1400 return (DWORD)RtlLengthRequiredSid(nSubAuthorityCount);
1401 }
1402
1403
1404 /*
1405 * @implemented
1406 */
1407 PDWORD WINAPI
1408 GetSidSubAuthority(PSID pSid,
1409 DWORD nSubAuthority)
1410 {
1411 return (PDWORD)RtlSubAuthoritySid(pSid, nSubAuthority);
1412 }
1413
1414
1415 /*
1416 * @implemented
1417 */
1418 PUCHAR WINAPI
1419 GetSidSubAuthorityCount(PSID pSid)
1420 {
1421 return RtlSubAuthorityCountSid(pSid);
1422 }
1423
1424
1425 /*
1426 * @implemented
1427 */
1428 BOOL WINAPI
1429 InitializeSid(PSID Sid,
1430 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
1431 BYTE nSubAuthorityCount)
1432 {
1433 NTSTATUS Status;
1434
1435 Status = RtlInitializeSid(Sid,
1436 pIdentifierAuthority,
1437 nSubAuthorityCount);
1438 if (!NT_SUCCESS(Status))
1439 {
1440 SetLastError(RtlNtStatusToDosError(Status));
1441 return FALSE;
1442 }
1443
1444 return TRUE;
1445 }
1446
1447
1448 /*
1449 * @implemented
1450 */
1451 BOOL WINAPI
1452 IsValidSid(PSID pSid)
1453 {
1454 return (BOOL)RtlValidSid(pSid);
1455 }
1456
1457
1458 /*
1459 * @implemented
1460 */
1461 BOOL WINAPI
1462 ConvertSidToStringSidW(PSID Sid,
1463 LPWSTR *StringSid)
1464 {
1465 NTSTATUS Status;
1466 UNICODE_STRING UnicodeString;
1467 WCHAR FixedBuffer[64];
1468
1469 if (!RtlValidSid(Sid))
1470 {
1471 SetLastError(ERROR_INVALID_SID);
1472 return FALSE;
1473 }
1474
1475 UnicodeString.Length = 0;
1476 UnicodeString.MaximumLength = sizeof(FixedBuffer);
1477 UnicodeString.Buffer = FixedBuffer;
1478 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
1479 if (STATUS_BUFFER_TOO_SMALL == Status)
1480 {
1481 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
1482 }
1483
1484 if (!NT_SUCCESS(Status))
1485 {
1486 SetLastError(RtlNtStatusToDosError(Status));
1487 return FALSE;
1488 }
1489
1490 *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
1491 if (NULL == *StringSid)
1492 {
1493 if (UnicodeString.Buffer != FixedBuffer)
1494 {
1495 RtlFreeUnicodeString(&UnicodeString);
1496 }
1497 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1498 return FALSE;
1499 }
1500
1501 MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
1502 ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
1503 if (UnicodeString.Buffer != FixedBuffer)
1504 {
1505 RtlFreeUnicodeString(&UnicodeString);
1506 }
1507
1508 return TRUE;
1509 }
1510
1511
1512 /*
1513 * @implemented
1514 */
1515 BOOL WINAPI
1516 ConvertSidToStringSidA(PSID Sid,
1517 LPSTR *StringSid)
1518 {
1519 LPWSTR StringSidW;
1520 int Len;
1521
1522 if (!ConvertSidToStringSidW(Sid, &StringSidW))
1523 {
1524 return FALSE;
1525 }
1526
1527 Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
1528 if (Len <= 0)
1529 {
1530 LocalFree(StringSidW);
1531 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1532 return FALSE;
1533 }
1534
1535 *StringSid = LocalAlloc(LMEM_FIXED, Len);
1536 if (NULL == *StringSid)
1537 {
1538 LocalFree(StringSidW);
1539 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1540 return FALSE;
1541 }
1542
1543 if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
1544 {
1545 LocalFree(StringSid);
1546 LocalFree(StringSidW);
1547 return FALSE;
1548 }
1549
1550 LocalFree(StringSidW);
1551
1552 return TRUE;
1553 }
1554
1555
1556 /*
1557 * @unimplemented
1558 */
1559 BOOL WINAPI
1560 EqualDomainSid(IN PSID pSid1,
1561 IN PSID pSid2,
1562 OUT BOOL* pfEqual)
1563 {
1564 UNIMPLEMENTED;
1565 return FALSE;
1566 }
1567
1568
1569 /*
1570 * @unimplemented
1571 */
1572 BOOL WINAPI
1573 GetWindowsAccountDomainSid(IN PSID pSid,
1574 OUT PSID ppDomainSid,
1575 IN OUT DWORD* cbSid)
1576 {
1577 UNIMPLEMENTED;
1578 return FALSE;
1579 }
1580
1581
1582 /*
1583 * @unimplemented
1584 */
1585 BOOL WINAPI
1586 CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType,
1587 IN PSID DomainSid OPTIONAL,
1588 OUT PSID pSid,
1589 IN OUT DWORD* cbSid)
1590 {
1591 unsigned int i;
1592 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
1593
1594 if (cbSid == NULL || pSid == NULL || (DomainSid && !IsValidSid(DomainSid))) {
1595 SetLastError(ERROR_INVALID_PARAMETER);
1596 return FALSE;
1597 }
1598
1599 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
1600 if (WellKnownSids[i].Type == WellKnownSidType) {
1601 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
1602
1603 if (*cbSid < length) {
1604 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1605 return FALSE;
1606 }
1607
1608 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
1609 *cbSid = length;
1610 return TRUE;
1611 }
1612 }
1613
1614 if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
1615 {
1616 SetLastError(ERROR_INVALID_PARAMETER);
1617 return FALSE;
1618 }
1619
1620 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
1621 if (WellKnownRids[i].Type == WellKnownSidType) {
1622 UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
1623 DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
1624 DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
1625
1626 if (*cbSid < output_sid_length) {
1627 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1628 return FALSE;
1629 }
1630
1631 CopyMemory(pSid, DomainSid, domain_sid_length);
1632 (*GetSidSubAuthorityCount(pSid))++;
1633 (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
1634 *cbSid = output_sid_length;
1635 return TRUE;
1636 }
1637
1638 SetLastError(ERROR_INVALID_PARAMETER);
1639 return FALSE;
1640 }
1641
1642
1643 /*
1644 * @unimplemented
1645 */
1646 BOOL WINAPI
1647 IsWellKnownSid(IN PSID pSid,
1648 IN WELL_KNOWN_SID_TYPE WellKnownSidType)
1649 {
1650 unsigned int i;
1651 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
1652
1653 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
1654 {
1655 if (WellKnownSids[i].Type == WellKnownSidType)
1656 {
1657 if (EqualSid(pSid, (PSID)((ULONG_PTR)&WellKnownSids[i].Sid.Revision)))
1658 return TRUE;
1659 }
1660 }
1661
1662 return FALSE;
1663 }
1664
1665
1666 /*
1667 * @implemented
1668 */
1669 BOOL WINAPI
1670 ConvertStringSidToSidA(IN LPCSTR StringSid,
1671 OUT PSID* sid)
1672 {
1673 BOOL bRetVal = FALSE;
1674
1675 if (!StringSid || !sid)
1676 SetLastError(ERROR_INVALID_PARAMETER);
1677 else
1678 {
1679 UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
1680 LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1681 MultiByteToWideChar(CP_ACP, 0, StringSid, - 1, wStringSid, len);
1682 bRetVal = ConvertStringSidToSidW(wStringSid, sid);
1683 HeapFree(GetProcessHeap(), 0, wStringSid);
1684 }
1685 return bRetVal;
1686 }
1687
1688
1689 /******************************************************************************
1690 * ComputeStringSidSize
1691 */
1692 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
1693 {
1694 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
1695 {
1696 int ctok = 0;
1697 while (*StringSid)
1698 {
1699 if (*StringSid == '-')
1700 ctok++;
1701 StringSid++;
1702 }
1703
1704 if (ctok >= 3)
1705 return GetSidLengthRequired(ctok - 2);
1706 }
1707 else /* String constant format - Only available in winxp and above */
1708 {
1709 unsigned int i;
1710
1711 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
1712 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
1713 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
1714 }
1715
1716 return GetSidLengthRequired(0);
1717 }
1718
1719 static const RECORD SidTable[] =
1720 {
1721 { SDDL_ACCOUNT_OPERATORS, WinBuiltinAccountOperatorsSid },
1722 { SDDL_ALIAS_PREW2KCOMPACC, WinBuiltinPreWindows2000CompatibleAccessSid },
1723 { SDDL_ANONYMOUS, WinAnonymousSid },
1724 { SDDL_AUTHENTICATED_USERS, WinAuthenticatedUserSid },
1725 { SDDL_BUILTIN_ADMINISTRATORS, WinBuiltinAdministratorsSid },
1726 { SDDL_BUILTIN_GUESTS, WinBuiltinGuestsSid },
1727 { SDDL_BACKUP_OPERATORS, WinBuiltinBackupOperatorsSid },
1728 { SDDL_BUILTIN_USERS, WinBuiltinUsersSid },
1729 { SDDL_CERT_SERV_ADMINISTRATORS, WinAccountCertAdminsSid /* FIXME: DOMAIN_GROUP_RID_CERT_ADMINS */ },
1730 { SDDL_CREATOR_GROUP, WinCreatorGroupSid },
1731 { SDDL_CREATOR_OWNER, WinCreatorOwnerSid },
1732 { SDDL_DOMAIN_ADMINISTRATORS, WinAccountDomainAdminsSid /* FIXME: DOMAIN_GROUP_RID_ADMINS */ },
1733 { SDDL_DOMAIN_COMPUTERS, WinAccountComputersSid /* FIXME: DOMAIN_GROUP_RID_COMPUTERS */ },
1734 { SDDL_DOMAIN_DOMAIN_CONTROLLERS, WinAccountControllersSid /* FIXME: DOMAIN_GROUP_RID_CONTROLLERS */ },
1735 { SDDL_DOMAIN_GUESTS, WinAccountDomainGuestsSid /* FIXME: DOMAIN_GROUP_RID_GUESTS */ },
1736 { SDDL_DOMAIN_USERS, WinAccountDomainUsersSid /* FIXME: DOMAIN_GROUP_RID_USERS */ },
1737 { SDDL_ENTERPRISE_ADMINS, WinAccountEnterpriseAdminsSid /* FIXME: DOMAIN_GROUP_RID_ENTERPRISE_ADMINS */ },
1738 { SDDL_ENTERPRISE_DOMAIN_CONTROLLERS, WinLogonIdsSid /* FIXME: SECURITY_SERVER_LOGON_RID */ },
1739 { SDDL_EVERYONE, WinWorldSid },
1740 { SDDL_GROUP_POLICY_ADMINS, WinAccountPolicyAdminsSid /* FIXME: DOMAIN_GROUP_RID_POLICY_ADMINS */ },
1741 { SDDL_INTERACTIVE, WinInteractiveSid },
1742 { SDDL_LOCAL_ADMIN, WinAccountAdministratorSid /* FIXME: DOMAIN_USER_RID_ADMIN */ },
1743 { SDDL_LOCAL_GUEST, WinAccountGuestSid /* FIXME: DOMAIN_USER_RID_GUEST */ },
1744 { SDDL_LOCAL_SERVICE, WinLocalServiceSid },
1745 { SDDL_LOCAL_SYSTEM, WinLocalSystemSid },
1746 { SDDL_NETWORK, WinNetworkSid },
1747 { SDDL_NETWORK_CONFIGURATION_OPS, WinBuiltinNetworkConfigurationOperatorsSid },
1748 { SDDL_NETWORK_SERVICE, WinNetworkServiceSid },
1749 { SDDL_PRINTER_OPERATORS, WinBuiltinPrintOperatorsSid },
1750 { SDDL_PERSONAL_SELF, WinSelfSid },
1751 { SDDL_POWER_USERS, WinBuiltinPowerUsersSid },
1752 { SDDL_RAS_SERVERS, WinAccountRasAndIasServersSid /* FIXME: DOMAIN_ALIAS_RID_RAS_SERVERS */ },
1753 { SDDL_REMOTE_DESKTOP, WinBuiltinRemoteDesktopUsersSid },
1754 { SDDL_REPLICATOR, WinBuiltinReplicatorSid },
1755 { SDDL_RESTRICTED_CODE, WinRestrictedCodeSid },
1756 { SDDL_SCHEMA_ADMINISTRATORS, WinAccountSchemaAdminsSid /* FIXME: DOMAIN_GROUP_RID_SCHEMA_ADMINS */ },
1757 { SDDL_SERVER_OPERATORS, WinBuiltinSystemOperatorsSid },
1758 { SDDL_SERVICE, WinServiceSid },
1759 { NULL, 0 },
1760 };
1761
1762 /*
1763 * @implemented
1764 */
1765 BOOL WINAPI
1766 ConvertStringSidToSidW(IN LPCWSTR StringSid,
1767 OUT PSID* sid)
1768 {
1769 DWORD size;
1770 DWORD i, cBytes, identAuth, csubauth;
1771 BOOL ret;
1772 SID* pisid;
1773
1774 TRACE("%s %p\n", debugstr_w(StringSid), sid);
1775
1776 if (!StringSid)
1777 {
1778 SetLastError(ERROR_INVALID_SID);
1779 return FALSE;
1780 }
1781 for (i = 0; i < sizeof(SidTable) / sizeof(SidTable[0]) - 1; i++)
1782 {
1783 if (wcscmp(StringSid, SidTable[i].key) == 0)
1784 {
1785 WELL_KNOWN_SID_TYPE knownSid = (WELL_KNOWN_SID_TYPE)SidTable[i].value;
1786 size = SECURITY_MAX_SID_SIZE;
1787 *sid = LocalAlloc(0, size);
1788 if (!*sid)
1789 {
1790 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1791 return FALSE;
1792 }
1793 ret = CreateWellKnownSid(
1794 knownSid,
1795 NULL,
1796 *sid,
1797 &size);
1798 if (!ret)
1799 {
1800 SetLastError(ERROR_INVALID_SID);
1801 LocalFree(*sid);
1802 }
1803 return ret;
1804 }
1805 }
1806
1807 /* That's probably a string S-R-I-S-S... */
1808 if (StringSid[0] != 'S' || StringSid[1] != '-')
1809 {
1810 SetLastError(ERROR_INVALID_SID);
1811 return FALSE;
1812 }
1813
1814 cBytes = ComputeStringSidSize(StringSid);
1815 pisid = (SID*)LocalAlloc( 0, cBytes );
1816 if (!pisid)
1817 {
1818 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1819 return FALSE;
1820 }
1821 i = 0;
1822 ret = FALSE;
1823 csubauth = ((cBytes - sizeof(SID)) / sizeof(DWORD)) + 1;
1824
1825 StringSid += 2; /* Advance to Revision */
1826 pisid->Revision = atoiW(StringSid);
1827
1828 if (pisid->Revision != SDDL_REVISION)
1829 {
1830 TRACE("Revision %d is unknown\n", pisid->Revision);
1831 goto lend; /* ERROR_INVALID_SID */
1832 }
1833 if (csubauth == 0)
1834 {
1835 TRACE("SubAuthorityCount is 0\n");
1836 goto lend; /* ERROR_INVALID_SID */
1837 }
1838
1839 pisid->SubAuthorityCount = csubauth;
1840
1841 /* Advance to identifier authority */
1842 while (*StringSid && *StringSid != '-')
1843 StringSid++;
1844 if (*StringSid == '-')
1845 StringSid++;
1846
1847 /* MS' implementation can't handle values greater than 2^32 - 1, so
1848 * we don't either; assume most significant bytes are always 0
1849 */
1850 pisid->IdentifierAuthority.Value[0] = 0;
1851 pisid->IdentifierAuthority.Value[1] = 0;
1852 identAuth = atoiW(StringSid);
1853 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
1854 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
1855 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
1856 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
1857
1858 /* Advance to first sub authority */
1859 while (*StringSid && *StringSid != '-')
1860 StringSid++;
1861 if (*StringSid == '-')
1862 StringSid++;
1863
1864 pisid->SubAuthority[i] = atoiW(StringSid);
1865
1866 while (*StringSid)
1867 {
1868 while (*StringSid && *StringSid != '-')
1869 StringSid++;
1870 if (*StringSid == '-')
1871 StringSid++;
1872
1873 pisid->SubAuthority[++i] = atoiW(StringSid);
1874 }
1875
1876 if (i != pisid->SubAuthorityCount)
1877 goto lend; /* ERROR_INVALID_SID */
1878
1879 *sid = pisid;
1880 ret = TRUE;
1881
1882 lend:
1883 if (!ret)
1884 SetLastError(ERROR_INVALID_SID);
1885
1886 TRACE("returning %s\n", ret ? "TRUE" : "FALSE");
1887 return ret;
1888 }
1889
1890
1891 /* EOF */