[USB]
[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 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
16
17 #define MAX_GUID_STRING_LEN 39
18
19 BOOL WINAPI
20 AddAuditAccessAceEx(PACL pAcl,
21 DWORD dwAceRevision,
22 DWORD AceFlags,
23 DWORD dwAccessMask,
24 PSID pSid,
25 BOOL bAuditSuccess,
26 BOOL bAuditFailure);
27
28 typedef struct RECORD
29 {
30 LPCWSTR key;
31 DWORD value;
32 } RECORD;
33
34
35 typedef struct _MAX_SID
36 {
37 /* same fields as struct _SID */
38 BYTE Revision;
39 BYTE SubAuthorityCount;
40 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
41 DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
42 } MAX_SID;
43
44 typedef struct WELLKNOWNSID
45 {
46 WCHAR wstr[2];
47 WELL_KNOWN_SID_TYPE Type;
48 MAX_SID Sid;
49 } WELLKNOWNSID;
50
51 typedef struct _ACEFLAG
52 {
53 LPCWSTR wstr;
54 DWORD value;
55 } ACEFLAG, *LPACEFLAG;
56
57 static const WELLKNOWNSID WellKnownSids[] =
58 {
59 { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
60 { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
61 { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
62 { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
63 { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
64 { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
65 { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
66 { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
67 { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
68 { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
69 { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
70 { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
71 { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
72 { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
73 { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
74 { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
75 { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
76 { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
77 { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
78 { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
79 { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
80 { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
81 { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
82 { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
83 { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
84 { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
85 { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
86 { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
87 { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
88 { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
89 { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
90 { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
91 { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
92 { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
93 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
94 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
95 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
96 { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } },
97 { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } },
98 { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } },
99 { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } },
100 { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } },
101 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS } } },
102 { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } },
103 { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } },
104 { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } },
105 { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } },
106 { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } },
107 { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } },
108 { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } },
109 { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } },
110 { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } },
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 /************************************************************
303 * ADVAPI_GetComputerSid
304 *
305 * Reads the computer SID from the registry.
306 */
307 BOOL ADVAPI_GetComputerSid(PSID sid)
308 {
309 HKEY key;
310 LONG ret;
311 BOOL retval = FALSE;
312 static const WCHAR Account[] = { 'S','E','C','U','R','I','T','Y','\\','S','A','M','\\','D','o','m','a','i','n','s','\\','A','c','c','o','u','n','t',0 };
313 static const WCHAR V[] = { 'V',0 };
314
315 if ((ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, Account, 0,
316 KEY_READ, &key)) == ERROR_SUCCESS)
317 {
318 DWORD size = 0;
319 ret = RegQueryValueExW(key, V, NULL, NULL, NULL, &size);
320 if (ret == ERROR_MORE_DATA || ret == ERROR_SUCCESS)
321 {
322 BYTE * data = HeapAlloc(GetProcessHeap(), 0, size);
323 if (data)
324 {
325 if ((ret = RegQueryValueExW(key, V, NULL, NULL,
326 data, &size)) == ERROR_SUCCESS)
327 {
328 /* the SID is in the last 24 bytes of the binary data */
329 CopyMemory(sid, &data[size-24], 24);
330 retval = TRUE;
331 }
332 HeapFree(GetProcessHeap(), 0, data);
333 }
334 }
335 RegCloseKey(key);
336 }
337
338 if(retval == TRUE) return retval;
339
340 /* create a new random SID */
341 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, Account,
342 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL) == ERROR_SUCCESS)
343 {
344 PSID new_sid;
345 SID_IDENTIFIER_AUTHORITY identifierAuthority = {SECURITY_NT_AUTHORITY};
346 DWORD id[3];
347
348 if (RtlGenRandom(id, sizeof(id)))
349 {
350 if (AllocateAndInitializeSid(&identifierAuthority, 4, SECURITY_NT_NON_UNIQUE, id[0], id[1], id[2], 0, 0, 0, 0, &new_sid))
351 {
352 if (RegSetValueExW(key, V, 0, REG_BINARY, new_sid, GetLengthSid(new_sid)) == ERROR_SUCCESS)
353 retval = CopySid(GetLengthSid(new_sid), sid, new_sid);
354
355 FreeSid(new_sid);
356 }
357 }
358 RegCloseKey(key);
359 }
360
361 return retval;
362 }
363
364 /* Exported functions */
365
366 /*
367 * @implemented
368 */
369 BOOL WINAPI
370 AllocateLocallyUniqueId(PLUID Luid)
371 {
372 NTSTATUS Status;
373
374 Status = NtAllocateLocallyUniqueId (Luid);
375 if (!NT_SUCCESS (Status))
376 {
377 SetLastError(RtlNtStatusToDosError(Status));
378 return FALSE;
379 }
380
381 return TRUE;
382 }
383
384
385 /*
386 * @implemented
387 */
388 BOOL WINAPI
389 AllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
390 BYTE nSubAuthorityCount,
391 DWORD dwSubAuthority0,
392 DWORD dwSubAuthority1,
393 DWORD dwSubAuthority2,
394 DWORD dwSubAuthority3,
395 DWORD dwSubAuthority4,
396 DWORD dwSubAuthority5,
397 DWORD dwSubAuthority6,
398 DWORD dwSubAuthority7,
399 PSID *pSid)
400 {
401 NTSTATUS Status;
402
403 Status = RtlAllocateAndInitializeSid(pIdentifierAuthority,
404 nSubAuthorityCount,
405 dwSubAuthority0,
406 dwSubAuthority1,
407 dwSubAuthority2,
408 dwSubAuthority3,
409 dwSubAuthority4,
410 dwSubAuthority5,
411 dwSubAuthority6,
412 dwSubAuthority7,
413 pSid);
414 if (!NT_SUCCESS(Status))
415 {
416 SetLastError(RtlNtStatusToDosError(Status));
417 return FALSE;
418 }
419
420 return TRUE;
421 }
422
423
424 /*
425 * @implemented
426 */
427 BOOL WINAPI
428 CopySid(DWORD nDestinationSidLength,
429 PSID pDestinationSid,
430 PSID pSourceSid)
431 {
432 NTSTATUS Status;
433
434 Status = RtlCopySid(nDestinationSidLength,
435 pDestinationSid,
436 pSourceSid);
437 if (!NT_SUCCESS (Status))
438 {
439 SetLastError(RtlNtStatusToDosError(Status));
440 return FALSE;
441 }
442
443 return TRUE;
444 }
445
446 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
447 {
448 if (cch == -1)
449 cch = strlenW(string);
450
451 if (plen)
452 *plen += cch;
453
454 if (pwptr)
455 {
456 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
457 *pwptr += cch;
458 }
459 }
460
461 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
462 {
463 DWORD i;
464 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
465 WCHAR subauthfmt[] = { '-','%','u',0 };
466 WCHAR buf[26];
467 SID *pisid = psid;
468
469 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
470 {
471 SetLastError(ERROR_INVALID_SID);
472 return FALSE;
473 }
474
475 if (pisid->IdentifierAuthority.Value[0] ||
476 pisid->IdentifierAuthority.Value[1])
477 {
478 FIXME("not matching MS' bugs\n");
479 SetLastError(ERROR_INVALID_SID);
480 return FALSE;
481 }
482
483 sprintfW( buf, fmt, pisid->Revision,
484 MAKELONG(
485 MAKEWORD( pisid->IdentifierAuthority.Value[5],
486 pisid->IdentifierAuthority.Value[4] ),
487 MAKEWORD( pisid->IdentifierAuthority.Value[3],
488 pisid->IdentifierAuthority.Value[2] )
489 ) );
490 DumpString(buf, -1, pwptr, plen);
491
492 for( i=0; i<pisid->SubAuthorityCount; i++ )
493 {
494 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
495 DumpString(buf, -1, pwptr, plen);
496 }
497 return TRUE;
498 }
499
500 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
501 {
502 size_t i;
503 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
504 {
505 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
506 {
507 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
508 return TRUE;
509 }
510 }
511
512 return DumpSidNumeric(psid, pwptr, plen);
513 }
514
515 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
516 {
517 static const WCHAR fmtW[] = {'0','x','%','x',0};
518 WCHAR buf[15];
519 size_t i;
520
521 if (mask == 0)
522 return;
523
524 /* first check if the right have name */
525 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
526 {
527 if (AceRights[i].wstr == NULL)
528 break;
529 if (mask == AceRights[i].value)
530 {
531 DumpString(AceRights[i].wstr, -1, pwptr, plen);
532 return;
533 }
534 }
535
536 /* then check if it can be built from bit names */
537 for (i = 0; i < 32; i++)
538 {
539 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
540 {
541 /* can't be built from bit names */
542 sprintfW(buf, fmtW, mask);
543 DumpString(buf, -1, pwptr, plen);
544 return;
545 }
546 }
547
548 /* build from bit names */
549 for (i = 0; i < 32; i++)
550 if (mask & (1 << i))
551 DumpString(AceRightBitNames[i], -1, pwptr, plen);
552 }
553
554 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
555 {
556 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
557 static const WCHAR openbr = '(';
558 static const WCHAR closebr = ')';
559 static const WCHAR semicolon = ';';
560
561 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
562 {
563 SetLastError(ERROR_INVALID_ACL);
564 return FALSE;
565 }
566
567 piace = pace;
568 DumpString(&openbr, 1, pwptr, plen);
569 switch (piace->Header.AceType)
570 {
571 case ACCESS_ALLOWED_ACE_TYPE:
572 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
573 break;
574 case ACCESS_DENIED_ACE_TYPE:
575 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
576 break;
577 case SYSTEM_AUDIT_ACE_TYPE:
578 DumpString(SDDL_AUDIT, -1, pwptr, plen);
579 break;
580 case SYSTEM_ALARM_ACE_TYPE:
581 DumpString(SDDL_ALARM, -1, pwptr, plen);
582 break;
583 }
584 DumpString(&semicolon, 1, pwptr, plen);
585
586 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
587 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
588 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
589 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
590 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
591 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
592 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
593 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
594 if (piace->Header.AceFlags & INHERITED_ACE)
595 DumpString(SDDL_INHERITED, -1, pwptr, plen);
596 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
597 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
598 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
599 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
600 DumpString(&semicolon, 1, pwptr, plen);
601 DumpRights(piace->Mask, pwptr, plen);
602 DumpString(&semicolon, 1, pwptr, plen);
603 /* objects not supported */
604 DumpString(&semicolon, 1, pwptr, plen);
605 /* objects not supported */
606 DumpString(&semicolon, 1, pwptr, plen);
607 if (!DumpSid((PSID)&piace->SidStart, pwptr, plen))
608 return FALSE;
609 DumpString(&closebr, 1, pwptr, plen);
610 return TRUE;
611 }
612
613 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
614 {
615 WORD count;
616 int i;
617
618 if (protected)
619 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
620 if (autoInheritReq)
621 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
622 if (autoInherited)
623 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
624
625 if (pacl == NULL)
626 return TRUE;
627
628 if (!IsValidAcl(pacl))
629 return FALSE;
630
631 count = pacl->AceCount;
632 for (i = 0; i < count; i++)
633 {
634 LPVOID ace;
635 if (!GetAce(pacl, i, &ace))
636 return FALSE;
637 if (!DumpAce(ace, pwptr, plen))
638 return FALSE;
639 }
640
641 return TRUE;
642 }
643
644 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
645 {
646 static const WCHAR prefix[] = {'O',':',0};
647 BOOL bDefaulted;
648 PSID psid;
649
650 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
651 return FALSE;
652
653 if (psid == NULL)
654 return TRUE;
655
656 DumpString(prefix, -1, pwptr, plen);
657 if (!DumpSid(psid, pwptr, plen))
658 return FALSE;
659 return TRUE;
660 }
661
662 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
663 {
664 static const WCHAR prefix[] = {'G',':',0};
665 BOOL bDefaulted;
666 PSID psid;
667
668 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
669 return FALSE;
670
671 if (psid == NULL)
672 return TRUE;
673
674 DumpString(prefix, -1, pwptr, plen);
675 if (!DumpSid(psid, pwptr, plen))
676 return FALSE;
677 return TRUE;
678 }
679
680 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
681 {
682 static const WCHAR dacl[] = {'D',':',0};
683 SECURITY_DESCRIPTOR_CONTROL control;
684 BOOL present, defaulted;
685 DWORD revision;
686 PACL pacl;
687
688 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
689 return FALSE;
690
691 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
692 return FALSE;
693
694 if (!present)
695 return TRUE;
696
697 DumpString(dacl, 2, pwptr, plen);
698 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
699 return FALSE;
700 return TRUE;
701 }
702
703 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
704 {
705 static const WCHAR sacl[] = {'S',':',0};
706 SECURITY_DESCRIPTOR_CONTROL control;
707 BOOL present, defaulted;
708 DWORD revision;
709 PACL pacl;
710
711 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
712 return FALSE;
713
714 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
715 return FALSE;
716
717 if (!present)
718 return TRUE;
719
720 DumpString(sacl, 2, pwptr, plen);
721 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
722 return FALSE;
723 return TRUE;
724 }
725
726 /******************************************************************************
727 * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
728 * @implemented
729 */
730 BOOL WINAPI
731 ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor,
732 DWORD SDRevision,
733 SECURITY_INFORMATION SecurityInformation,
734 LPWSTR *OutputString,
735 PULONG OutputLen)
736 {
737 ULONG len;
738 WCHAR *wptr, *wstr;
739
740 if (SDRevision != SDDL_REVISION_1)
741 {
742 ERR("Pogram requested unknown SDDL revision %d\n", SDRevision);
743 SetLastError(ERROR_UNKNOWN_REVISION);
744 return FALSE;
745 }
746
747 len = 0;
748 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
749 if (!DumpOwner(SecurityDescriptor, NULL, &len))
750 return FALSE;
751 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
752 if (!DumpGroup(SecurityDescriptor, NULL, &len))
753 return FALSE;
754 if (SecurityInformation & DACL_SECURITY_INFORMATION)
755 if (!DumpDacl(SecurityDescriptor, NULL, &len))
756 return FALSE;
757 if (SecurityInformation & SACL_SECURITY_INFORMATION)
758 if (!DumpSacl(SecurityDescriptor, NULL, &len))
759 return FALSE;
760
761 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
762 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
763 if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
764 return FALSE;
765 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
766 if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
767 return FALSE;
768 if (SecurityInformation & DACL_SECURITY_INFORMATION)
769 if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
770 return FALSE;
771 if (SecurityInformation & SACL_SECURITY_INFORMATION)
772 if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
773 return FALSE;
774 *wptr = 0;
775
776 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
777 *OutputString = wstr;
778 if (OutputLen)
779 *OutputLen = strlenW(*OutputString)+1;
780 return TRUE;
781 }
782
783
784 /******************************************************************************
785 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
786 * @implemented
787 */
788 BOOL WINAPI
789 ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor,
790 DWORD SDRevision,
791 SECURITY_INFORMATION Information,
792 LPSTR *OutputString,
793 PULONG OutputLen)
794 {
795 LPWSTR wstr;
796 ULONG len;
797 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
798 {
799 int lenA;
800
801 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
802 *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
803 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
804 LocalFree(wstr);
805
806 if (OutputLen != NULL)
807 *OutputLen = lenA;
808 return TRUE;
809 }
810 else
811 {
812 *OutputString = NULL;
813 if (OutputLen)
814 *OutputLen = 0;
815 return FALSE;
816 }
817 }
818
819
820 /******************************************************************************
821 * ComputeStringSidSize
822 */
823 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
824 {
825 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
826 {
827 int ctok = 0;
828 while (*StringSid)
829 {
830 if (*StringSid == '-')
831 ctok++;
832 StringSid++;
833 }
834
835 if (ctok >= 3)
836 return GetSidLengthRequired(ctok - 2);
837 }
838 else /* String constant format - Only available in winxp and above */
839 {
840 unsigned int i;
841
842 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
843 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
844 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
845 }
846
847 return GetSidLengthRequired(0);
848 }
849
850 /******************************************************************************
851 * ParseStringSidToSid
852 */
853 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
854 {
855 BOOL bret = FALSE;
856 SID* pisid=pSid;
857
858 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
859 if (!StringSid)
860 {
861 SetLastError(ERROR_INVALID_PARAMETER);
862 TRACE("StringSid is NULL, returning FALSE\n");
863 return FALSE;
864 }
865
866 while (*StringSid == ' ')
867 StringSid++;
868
869 *cBytes = ComputeStringSidSize(StringSid);
870 if (!pisid) /* Simply compute the size */
871 {
872 TRACE("only size requested, returning TRUE\n");
873 return TRUE;
874 }
875
876 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
877 {
878 DWORD i = 0, identAuth;
879 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
880
881 StringSid += 2; /* Advance to Revision */
882 pisid->Revision = atoiW(StringSid);
883
884 if (pisid->Revision != SDDL_REVISION)
885 {
886 TRACE("Revision %d is unknown\n", pisid->Revision);
887 goto lend; /* ERROR_INVALID_SID */
888 }
889 if (csubauth == 0)
890 {
891 TRACE("SubAuthorityCount is 0\n");
892 goto lend; /* ERROR_INVALID_SID */
893 }
894
895 pisid->SubAuthorityCount = csubauth;
896
897 /* Advance to identifier authority */
898 while (*StringSid && *StringSid != '-')
899 StringSid++;
900 if (*StringSid == '-')
901 StringSid++;
902
903 /* MS' implementation can't handle values greater than 2^32 - 1, so
904 * we don't either; assume most significant bytes are always 0
905 */
906 pisid->IdentifierAuthority.Value[0] = 0;
907 pisid->IdentifierAuthority.Value[1] = 0;
908 identAuth = atoiW(StringSid);
909 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
910 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
911 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
912 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
913
914 /* Advance to first sub authority */
915 while (*StringSid && *StringSid != '-')
916 StringSid++;
917 if (*StringSid == '-')
918 StringSid++;
919
920 while (*StringSid)
921 {
922 pisid->SubAuthority[i++] = atoiW(StringSid);
923
924 while (*StringSid && *StringSid != '-')
925 StringSid++;
926 if (*StringSid == '-')
927 StringSid++;
928 }
929
930 if (i != pisid->SubAuthorityCount)
931 goto lend; /* ERROR_INVALID_SID */
932
933 bret = TRUE;
934 }
935 else /* String constant format - Only available in winxp and above */
936 {
937 unsigned int i;
938 pisid->Revision = SDDL_REVISION;
939
940 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
941 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
942 {
943 DWORD j;
944 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
945 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
946 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
947 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
948 bret = TRUE;
949 }
950
951 if (!bret)
952 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
953 }
954
955 lend:
956 if (!bret)
957 SetLastError(ERROR_INVALID_SID);
958
959 TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
960 return bret;
961 }
962
963 /******************************************************************************
964 * ParseAclStringFlags
965 */
966 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
967 {
968 DWORD flags = 0;
969 LPCWSTR szAcl = *StringAcl;
970
971 while (*szAcl != '(')
972 {
973 if (*szAcl == 'P')
974 {
975 flags |= SE_DACL_PROTECTED;
976 }
977 else if (*szAcl == 'A')
978 {
979 szAcl++;
980 if (*szAcl == 'R')
981 flags |= SE_DACL_AUTO_INHERIT_REQ;
982 else if (*szAcl == 'I')
983 flags |= SE_DACL_AUTO_INHERITED;
984 }
985 szAcl++;
986 }
987
988 *StringAcl = szAcl;
989 return flags;
990 }
991
992 /******************************************************************************
993 * ParseAceStringType
994 */
995 static const ACEFLAG AceType[] =
996 {
997 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
998 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
999 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
1000 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
1001 /*
1002 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
1003 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
1004 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
1005 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
1006 */
1007 { NULL, 0 },
1008 };
1009
1010 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
1011 {
1012 UINT len = 0;
1013 LPCWSTR szAcl = *StringAcl;
1014 const ACEFLAG *lpaf = AceType;
1015
1016 while (lpaf->wstr &&
1017 (len = strlenW(lpaf->wstr)) &&
1018 strncmpW(lpaf->wstr, szAcl, len))
1019 lpaf++;
1020
1021 if (!lpaf->wstr)
1022 return 0;
1023
1024 *StringAcl += len;
1025 return lpaf->value;
1026 }
1027
1028
1029 /******************************************************************************
1030 * ParseAceStringFlags
1031 */
1032 static const ACEFLAG AceFlags[] =
1033 {
1034 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
1035 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
1036 { SDDL_INHERITED, INHERITED_ACE },
1037 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
1038 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
1039 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
1040 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
1041 { NULL, 0 },
1042 };
1043
1044 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
1045 {
1046 UINT len = 0;
1047 BYTE flags = 0;
1048 LPCWSTR szAcl = *StringAcl;
1049
1050 while (*szAcl != ';')
1051 {
1052 const ACEFLAG *lpaf = AceFlags;
1053
1054 while (lpaf->wstr &&
1055 (len = strlenW(lpaf->wstr)) &&
1056 strncmpW(lpaf->wstr, szAcl, len))
1057 lpaf++;
1058
1059 if (!lpaf->wstr)
1060 return 0;
1061
1062 flags |= lpaf->value;
1063 szAcl += len;
1064 }
1065
1066 *StringAcl = szAcl;
1067 return flags;
1068 }
1069
1070
1071 /******************************************************************************
1072 * ParseAceStringRights
1073 */
1074 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
1075 {
1076 UINT len = 0;
1077 DWORD rights = 0;
1078 LPCWSTR szAcl = *StringAcl;
1079
1080 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
1081 {
1082 LPCWSTR p = szAcl;
1083
1084 while (*p && *p != ';')
1085 p++;
1086
1087 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
1088 {
1089 rights = strtoulW(szAcl, NULL, 16);
1090 szAcl = p;
1091 }
1092 else
1093 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
1094 }
1095 else
1096 {
1097 while (*szAcl != ';')
1098 {
1099 const ACEFLAG *lpaf = AceRights;
1100
1101 while (lpaf->wstr &&
1102 (len = strlenW(lpaf->wstr)) &&
1103 strncmpW(lpaf->wstr, szAcl, len))
1104 {
1105 lpaf++;
1106 }
1107
1108 if (!lpaf->wstr)
1109 return 0;
1110
1111 rights |= lpaf->value;
1112 szAcl += len;
1113 }
1114 }
1115
1116 *StringAcl = szAcl;
1117 return rights;
1118 }
1119
1120
1121 /******************************************************************************
1122 * ParseStringAclToAcl
1123 *
1124 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
1125 */
1126 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
1127 PACL pAcl, LPDWORD cBytes)
1128 {
1129 DWORD val;
1130 DWORD sidlen;
1131 DWORD length = sizeof(ACL);
1132 DWORD acesize = 0;
1133 DWORD acecount = 0;
1134 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
1135
1136 TRACE("%s\n", debugstr_w(StringAcl));
1137
1138 if (!StringAcl)
1139 return FALSE;
1140
1141 if (pAcl) /* pAce is only useful if we're setting values */
1142 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
1143
1144 /* Parse ACL flags */
1145 *lpdwFlags = ParseAclStringFlags(&StringAcl);
1146
1147 /* Parse ACE */
1148 while (*StringAcl == '(')
1149 {
1150 StringAcl++;
1151
1152 /* Parse ACE type */
1153 val = ParseAceStringType(&StringAcl);
1154 if (pAce)
1155 pAce->Header.AceType = (BYTE) val;
1156 if (*StringAcl != ';')
1157 goto lerr;
1158 StringAcl++;
1159
1160 /* Parse ACE flags */
1161 val = ParseAceStringFlags(&StringAcl);
1162 if (pAce)
1163 pAce->Header.AceFlags = (BYTE) val;
1164 if (*StringAcl != ';')
1165 goto lerr;
1166 StringAcl++;
1167
1168 /* Parse ACE rights */
1169 val = ParseAceStringRights(&StringAcl);
1170 if (pAce)
1171 pAce->Mask = val;
1172 if (*StringAcl != ';')
1173 goto lerr;
1174 StringAcl++;
1175
1176 /* Parse ACE object guid */
1177 if (*StringAcl != ';')
1178 {
1179 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1180 goto lerr;
1181 }
1182 StringAcl++;
1183
1184 /* Parse ACE inherit object guid */
1185 if (*StringAcl != ';')
1186 {
1187 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1188 goto lerr;
1189 }
1190 StringAcl++;
1191
1192 /* Parse ACE account sid */
1193 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
1194 {
1195 while (*StringAcl && *StringAcl != ')')
1196 StringAcl++;
1197 }
1198
1199 if (*StringAcl != ')')
1200 goto lerr;
1201 StringAcl++;
1202
1203 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
1204 length += acesize;
1205 if (pAce)
1206 {
1207 pAce->Header.AceSize = acesize;
1208 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
1209 }
1210 acecount++;
1211 }
1212
1213 *cBytes = length;
1214
1215 if (length > 0xffff)
1216 {
1217 ERR("ACL too large\n");
1218 goto lerr;
1219 }
1220
1221 if (pAcl)
1222 {
1223 pAcl->AclRevision = ACL_REVISION;
1224 pAcl->Sbz1 = 0;
1225 pAcl->AclSize = length;
1226 pAcl->AceCount = acecount++;
1227 pAcl->Sbz2 = 0;
1228 }
1229 return TRUE;
1230
1231 lerr:
1232 SetLastError(ERROR_INVALID_ACL);
1233 WARN("Invalid ACE string format\n");
1234 return FALSE;
1235 }
1236
1237
1238 /******************************************************************************
1239 * ParseStringSecurityDescriptorToSecurityDescriptor
1240 */
1241 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
1242 LPCWSTR StringSecurityDescriptor,
1243 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
1244 LPDWORD cBytes)
1245 {
1246 BOOL bret = FALSE;
1247 WCHAR toktype;
1248 WCHAR tok[MAX_PATH];
1249 LPCWSTR lptoken;
1250 LPBYTE lpNext = NULL;
1251 DWORD len;
1252
1253 *cBytes = sizeof(SECURITY_DESCRIPTOR);
1254
1255 if (SecurityDescriptor)
1256 lpNext = (LPBYTE)(SecurityDescriptor + 1);
1257
1258 while (*StringSecurityDescriptor)
1259 {
1260 toktype = *StringSecurityDescriptor;
1261
1262 /* Expect char identifier followed by ':' */
1263 StringSecurityDescriptor++;
1264 if (*StringSecurityDescriptor != ':')
1265 {
1266 SetLastError(ERROR_INVALID_PARAMETER);
1267 goto lend;
1268 }
1269 StringSecurityDescriptor++;
1270
1271 /* Extract token */
1272 lptoken = StringSecurityDescriptor;
1273 while (*lptoken && *lptoken != ':')
1274 lptoken++;
1275
1276 if (*lptoken)
1277 lptoken--;
1278
1279 len = lptoken - StringSecurityDescriptor;
1280 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
1281 tok[len] = 0;
1282
1283 switch (toktype)
1284 {
1285 case 'O':
1286 {
1287 DWORD bytes;
1288
1289 if (!ParseStringSidToSid(tok, lpNext, &bytes))
1290 goto lend;
1291
1292 if (SecurityDescriptor)
1293 {
1294 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
1295 lpNext += bytes; /* Advance to next token */
1296 }
1297
1298 *cBytes += bytes;
1299
1300 break;
1301 }
1302
1303 case 'G':
1304 {
1305 DWORD bytes;
1306
1307 if (!ParseStringSidToSid(tok, lpNext, &bytes))
1308 goto lend;
1309
1310 if (SecurityDescriptor)
1311 {
1312 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
1313 lpNext += bytes; /* Advance to next token */
1314 }
1315
1316 *cBytes += bytes;
1317
1318 break;
1319 }
1320
1321 case 'D':
1322 {
1323 DWORD flags;
1324 DWORD bytes;
1325
1326 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
1327 goto lend;
1328
1329 if (SecurityDescriptor)
1330 {
1331 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
1332 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
1333 lpNext += bytes; /* Advance to next token */
1334 }
1335
1336 *cBytes += bytes;
1337
1338 break;
1339 }
1340
1341 case 'S':
1342 {
1343 DWORD flags;
1344 DWORD bytes;
1345
1346 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
1347 goto lend;
1348
1349 if (SecurityDescriptor)
1350 {
1351 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
1352 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
1353 lpNext += bytes; /* Advance to next token */
1354 }
1355
1356 *cBytes += bytes;
1357
1358 break;
1359 }
1360
1361 default:
1362 FIXME("Unknown token\n");
1363 SetLastError(ERROR_INVALID_PARAMETER);
1364 goto lend;
1365 }
1366
1367 StringSecurityDescriptor = lptoken;
1368 }
1369
1370 bret = TRUE;
1371
1372 lend:
1373 return bret;
1374 }
1375
1376
1377 /******************************************************************************
1378 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
1379 * @implemented
1380 */
1381 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
1382 LPCWSTR StringSecurityDescriptor,
1383 DWORD StringSDRevision,
1384 PSECURITY_DESCRIPTOR* SecurityDescriptor,
1385 PULONG SecurityDescriptorSize)
1386 {
1387 DWORD cBytes;
1388 SECURITY_DESCRIPTOR* psd;
1389 BOOL bret = FALSE;
1390
1391 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
1392
1393 if (GetVersion() & 0x80000000)
1394 {
1395 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1396 goto lend;
1397 }
1398 else if (!StringSecurityDescriptor || !SecurityDescriptor)
1399 {
1400 SetLastError(ERROR_INVALID_PARAMETER);
1401 goto lend;
1402 }
1403 else if (StringSDRevision != SID_REVISION)
1404 {
1405 SetLastError(ERROR_UNKNOWN_REVISION);
1406 goto lend;
1407 }
1408
1409 /* Compute security descriptor length */
1410 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
1411 NULL, &cBytes))
1412 goto lend;
1413
1414 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
1415 if (!psd) goto lend;
1416
1417 psd->Revision = SID_REVISION;
1418 psd->Control |= SE_SELF_RELATIVE;
1419
1420 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
1421 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
1422 {
1423 LocalFree(psd);
1424 goto lend;
1425 }
1426
1427 if (SecurityDescriptorSize)
1428 *SecurityDescriptorSize = cBytes;
1429
1430 bret = TRUE;
1431
1432 lend:
1433 TRACE(" ret=%d\n", bret);
1434 return bret;
1435 }
1436
1437
1438 /* Winehq cvs 20050916 */
1439 /******************************************************************************
1440 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
1441 * @implemented
1442 */
1443 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
1444 LPCSTR StringSecurityDescriptor,
1445 DWORD StringSDRevision,
1446 PSECURITY_DESCRIPTOR* SecurityDescriptor,
1447 PULONG SecurityDescriptorSize)
1448 {
1449 UINT len;
1450 BOOL ret = FALSE;
1451 LPWSTR StringSecurityDescriptorW;
1452
1453 len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
1454 StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1455
1456 if (StringSecurityDescriptorW)
1457 {
1458 MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
1459
1460 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
1461 StringSDRevision, SecurityDescriptor,
1462 SecurityDescriptorSize);
1463 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
1464 }
1465
1466 return ret;
1467 }
1468
1469 /*
1470 * @implemented
1471 */
1472 BOOL WINAPI
1473 EqualPrefixSid(PSID pSid1,
1474 PSID pSid2)
1475 {
1476 return RtlEqualPrefixSid (pSid1, pSid2);
1477 }
1478
1479
1480 /*
1481 * @implemented
1482 */
1483 BOOL WINAPI
1484 EqualSid(PSID pSid1,
1485 PSID pSid2)
1486 {
1487 return RtlEqualSid (pSid1, pSid2);
1488 }
1489
1490
1491 /*
1492 * @implemented
1493 *
1494 * RETURNS
1495 * Docs says this function does NOT return a value
1496 * even thou it's defined to return a PVOID...
1497 */
1498 PVOID WINAPI
1499 FreeSid(PSID pSid)
1500 {
1501 return RtlFreeSid(pSid);
1502 }
1503
1504
1505 /*
1506 * @implemented
1507 */
1508 DWORD WINAPI
1509 GetLengthSid(PSID pSid)
1510 {
1511 return (DWORD)RtlLengthSid(pSid);
1512 }
1513
1514
1515 /*
1516 * @implemented
1517 */
1518 PSID_IDENTIFIER_AUTHORITY WINAPI
1519 GetSidIdentifierAuthority(PSID pSid)
1520 {
1521 return RtlIdentifierAuthoritySid(pSid);
1522 }
1523
1524
1525 /*
1526 * @implemented
1527 */
1528 DWORD WINAPI
1529 GetSidLengthRequired(UCHAR nSubAuthorityCount)
1530 {
1531 return (DWORD)RtlLengthRequiredSid(nSubAuthorityCount);
1532 }
1533
1534
1535 /*
1536 * @implemented
1537 */
1538 PDWORD WINAPI
1539 GetSidSubAuthority(PSID pSid,
1540 DWORD nSubAuthority)
1541 {
1542 return (PDWORD)RtlSubAuthoritySid(pSid, nSubAuthority);
1543 }
1544
1545
1546 /*
1547 * @implemented
1548 */
1549 PUCHAR WINAPI
1550 GetSidSubAuthorityCount(PSID pSid)
1551 {
1552 return RtlSubAuthorityCountSid(pSid);
1553 }
1554
1555
1556 /*
1557 * @implemented
1558 */
1559 BOOL WINAPI
1560 InitializeSid(PSID Sid,
1561 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
1562 BYTE nSubAuthorityCount)
1563 {
1564 NTSTATUS Status;
1565
1566 Status = RtlInitializeSid(Sid,
1567 pIdentifierAuthority,
1568 nSubAuthorityCount);
1569 if (!NT_SUCCESS(Status))
1570 {
1571 SetLastError(RtlNtStatusToDosError(Status));
1572 return FALSE;
1573 }
1574
1575 return TRUE;
1576 }
1577
1578
1579 /*
1580 * @implemented
1581 */
1582 BOOL WINAPI
1583 IsValidSid(PSID pSid)
1584 {
1585 return (BOOL)RtlValidSid(pSid);
1586 }
1587
1588
1589 /*
1590 * @implemented
1591 */
1592 BOOL WINAPI
1593 ConvertSidToStringSidW(PSID Sid,
1594 LPWSTR *StringSid)
1595 {
1596 NTSTATUS Status;
1597 UNICODE_STRING UnicodeString;
1598 WCHAR FixedBuffer[64];
1599
1600 if (!RtlValidSid(Sid))
1601 {
1602 SetLastError(ERROR_INVALID_SID);
1603 return FALSE;
1604 }
1605
1606 UnicodeString.Length = 0;
1607 UnicodeString.MaximumLength = sizeof(FixedBuffer);
1608 UnicodeString.Buffer = FixedBuffer;
1609 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
1610 if (STATUS_BUFFER_TOO_SMALL == Status)
1611 {
1612 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
1613 }
1614
1615 if (!NT_SUCCESS(Status))
1616 {
1617 SetLastError(RtlNtStatusToDosError(Status));
1618 return FALSE;
1619 }
1620
1621 *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
1622 if (NULL == *StringSid)
1623 {
1624 if (UnicodeString.Buffer != FixedBuffer)
1625 {
1626 RtlFreeUnicodeString(&UnicodeString);
1627 }
1628 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1629 return FALSE;
1630 }
1631
1632 MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
1633 ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
1634 if (UnicodeString.Buffer != FixedBuffer)
1635 {
1636 RtlFreeUnicodeString(&UnicodeString);
1637 }
1638
1639 return TRUE;
1640 }
1641
1642
1643 /*
1644 * @implemented
1645 */
1646 BOOL WINAPI
1647 ConvertSidToStringSidA(PSID Sid,
1648 LPSTR *StringSid)
1649 {
1650 LPWSTR StringSidW;
1651 int Len;
1652
1653 if (!ConvertSidToStringSidW(Sid, &StringSidW))
1654 {
1655 return FALSE;
1656 }
1657
1658 Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
1659 if (Len <= 0)
1660 {
1661 LocalFree(StringSidW);
1662 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1663 return FALSE;
1664 }
1665
1666 *StringSid = LocalAlloc(LMEM_FIXED, Len);
1667 if (NULL == *StringSid)
1668 {
1669 LocalFree(StringSidW);
1670 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1671 return FALSE;
1672 }
1673
1674 if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
1675 {
1676 LocalFree(StringSid);
1677 LocalFree(StringSidW);
1678 return FALSE;
1679 }
1680
1681 LocalFree(StringSidW);
1682
1683 return TRUE;
1684 }
1685
1686
1687 /*
1688 * @unimplemented
1689 */
1690 BOOL WINAPI
1691 EqualDomainSid(IN PSID pSid1,
1692 IN PSID pSid2,
1693 OUT BOOL* pfEqual)
1694 {
1695 UNIMPLEMENTED;
1696 return FALSE;
1697 }
1698
1699
1700 /*
1701 * @unimplemented
1702 */
1703 BOOL WINAPI
1704 GetWindowsAccountDomainSid(IN PSID pSid,
1705 OUT PSID ppDomainSid,
1706 IN OUT DWORD* cbSid)
1707 {
1708 UNIMPLEMENTED;
1709 return FALSE;
1710 }
1711
1712
1713 /*
1714 * @unimplemented
1715 */
1716 BOOL WINAPI
1717 CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType,
1718 IN PSID DomainSid OPTIONAL,
1719 OUT PSID pSid,
1720 IN OUT DWORD* cbSid)
1721 {
1722 unsigned int i;
1723 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
1724
1725 if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
1726 {
1727 SetLastError(ERROR_INVALID_PARAMETER);
1728 return FALSE;
1729 }
1730
1731 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
1732 if (WellKnownSids[i].Type == WellKnownSidType) {
1733 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
1734
1735 if (*cbSid < length)
1736 {
1737 *cbSid = length;
1738 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1739 return FALSE;
1740 }
1741 if (!pSid)
1742 {
1743 SetLastError(ERROR_INVALID_PARAMETER);
1744 return FALSE;
1745 }
1746 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
1747 *cbSid = length;
1748 return TRUE;
1749 }
1750 }
1751
1752 if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
1753 {
1754 SetLastError(ERROR_INVALID_PARAMETER);
1755 return FALSE;
1756 }
1757
1758 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
1759 if (WellKnownRids[i].Type == WellKnownSidType) {
1760 UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
1761 DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
1762 DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
1763
1764 if (*cbSid < output_sid_length)
1765 {
1766 *cbSid = output_sid_length;
1767 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1768 return FALSE;
1769 }
1770 if (!pSid)
1771 {
1772 SetLastError(ERROR_INVALID_PARAMETER);
1773 return FALSE;
1774 }
1775 CopyMemory(pSid, DomainSid, domain_sid_length);
1776 (*GetSidSubAuthorityCount(pSid))++;
1777 (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
1778 *cbSid = output_sid_length;
1779 return TRUE;
1780 }
1781
1782 SetLastError(ERROR_INVALID_PARAMETER);
1783 return FALSE;
1784 }
1785
1786
1787 /*
1788 * @unimplemented
1789 */
1790 BOOL WINAPI
1791 IsWellKnownSid(IN PSID pSid,
1792 IN WELL_KNOWN_SID_TYPE WellKnownSidType)
1793 {
1794 unsigned int i;
1795 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
1796
1797 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
1798 {
1799 if (WellKnownSids[i].Type == WellKnownSidType)
1800 {
1801 if (EqualSid(pSid, (PSID)(&WellKnownSids[i].Sid.Revision)))
1802 return TRUE;
1803 }
1804 }
1805
1806 return FALSE;
1807 }
1808
1809
1810 /*
1811 * @implemented
1812 */
1813 BOOL WINAPI
1814 ConvertStringSidToSidA(IN LPCSTR StringSid,
1815 OUT PSID* sid)
1816 {
1817 BOOL bRetVal = FALSE;
1818
1819 TRACE("%s, %p\n", debugstr_a(StringSid), sid);
1820 if (GetVersion() & 0x80000000)
1821 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1822 else if (!StringSid || !sid)
1823 SetLastError(ERROR_INVALID_PARAMETER);
1824 else
1825 {
1826 UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
1827 LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1828 MultiByteToWideChar(CP_ACP, 0, StringSid, - 1, wStringSid, len);
1829 bRetVal = ConvertStringSidToSidW(wStringSid, sid);
1830 HeapFree(GetProcessHeap(), 0, wStringSid);
1831 }
1832 return bRetVal;
1833 }
1834
1835
1836 static const RECORD SidTable[] =
1837 {
1838 { SDDL_ACCOUNT_OPERATORS, WinBuiltinAccountOperatorsSid },
1839 { SDDL_ALIAS_PREW2KCOMPACC, WinBuiltinPreWindows2000CompatibleAccessSid },
1840 { SDDL_ANONYMOUS, WinAnonymousSid },
1841 { SDDL_AUTHENTICATED_USERS, WinAuthenticatedUserSid },
1842 { SDDL_BUILTIN_ADMINISTRATORS, WinBuiltinAdministratorsSid },
1843 { SDDL_BUILTIN_GUESTS, WinBuiltinGuestsSid },
1844 { SDDL_BACKUP_OPERATORS, WinBuiltinBackupOperatorsSid },
1845 { SDDL_BUILTIN_USERS, WinBuiltinUsersSid },
1846 { SDDL_CERT_SERV_ADMINISTRATORS, WinAccountCertAdminsSid /* FIXME: DOMAIN_GROUP_RID_CERT_ADMINS */ },
1847 { SDDL_CREATOR_GROUP, WinCreatorGroupSid },
1848 { SDDL_CREATOR_OWNER, WinCreatorOwnerSid },
1849 { SDDL_DOMAIN_ADMINISTRATORS, WinAccountDomainAdminsSid /* FIXME: DOMAIN_GROUP_RID_ADMINS */ },
1850 { SDDL_DOMAIN_COMPUTERS, WinAccountComputersSid /* FIXME: DOMAIN_GROUP_RID_COMPUTERS */ },
1851 { SDDL_DOMAIN_DOMAIN_CONTROLLERS, WinAccountControllersSid /* FIXME: DOMAIN_GROUP_RID_CONTROLLERS */ },
1852 { SDDL_DOMAIN_GUESTS, WinAccountDomainGuestsSid /* FIXME: DOMAIN_GROUP_RID_GUESTS */ },
1853 { SDDL_DOMAIN_USERS, WinAccountDomainUsersSid /* FIXME: DOMAIN_GROUP_RID_USERS */ },
1854 { SDDL_ENTERPRISE_ADMINS, WinAccountEnterpriseAdminsSid /* FIXME: DOMAIN_GROUP_RID_ENTERPRISE_ADMINS */ },
1855 { SDDL_ENTERPRISE_DOMAIN_CONTROLLERS, WinLogonIdsSid /* FIXME: SECURITY_SERVER_LOGON_RID */ },
1856 { SDDL_EVERYONE, WinWorldSid },
1857 { SDDL_GROUP_POLICY_ADMINS, WinAccountPolicyAdminsSid /* FIXME: DOMAIN_GROUP_RID_POLICY_ADMINS */ },
1858 { SDDL_INTERACTIVE, WinInteractiveSid },
1859 { SDDL_LOCAL_ADMIN, WinAccountAdministratorSid /* FIXME: DOMAIN_USER_RID_ADMIN */ },
1860 { SDDL_LOCAL_GUEST, WinAccountGuestSid /* FIXME: DOMAIN_USER_RID_GUEST */ },
1861 { SDDL_LOCAL_SERVICE, WinLocalServiceSid },
1862 { SDDL_LOCAL_SYSTEM, WinLocalSystemSid },
1863 { SDDL_NETWORK, WinNetworkSid },
1864 { SDDL_NETWORK_CONFIGURATION_OPS, WinBuiltinNetworkConfigurationOperatorsSid },
1865 { SDDL_NETWORK_SERVICE, WinNetworkServiceSid },
1866 { SDDL_PRINTER_OPERATORS, WinBuiltinPrintOperatorsSid },
1867 { SDDL_PERSONAL_SELF, WinSelfSid },
1868 { SDDL_POWER_USERS, WinBuiltinPowerUsersSid },
1869 { SDDL_RAS_SERVERS, WinAccountRasAndIasServersSid /* FIXME: DOMAIN_ALIAS_RID_RAS_SERVERS */ },
1870 { SDDL_REMOTE_DESKTOP, WinBuiltinRemoteDesktopUsersSid },
1871 { SDDL_REPLICATOR, WinBuiltinReplicatorSid },
1872 { SDDL_RESTRICTED_CODE, WinRestrictedCodeSid },
1873 { SDDL_SCHEMA_ADMINISTRATORS, WinAccountSchemaAdminsSid /* FIXME: DOMAIN_GROUP_RID_SCHEMA_ADMINS */ },
1874 { SDDL_SERVER_OPERATORS, WinBuiltinSystemOperatorsSid },
1875 { SDDL_SERVICE, WinServiceSid },
1876 { NULL, 0 },
1877 };
1878
1879 /*
1880 * @implemented
1881 */
1882 BOOL WINAPI
1883 ConvertStringSidToSidW(IN LPCWSTR StringSid,
1884 OUT PSID* sid)
1885 {
1886 DWORD size;
1887 DWORD i, cBytes, identAuth, csubauth;
1888 BOOL ret;
1889 SID* pisid;
1890
1891 TRACE("%s %p\n", debugstr_w(StringSid), sid);
1892
1893 if (!StringSid)
1894 {
1895 SetLastError(ERROR_INVALID_SID);
1896 return FALSE;
1897 }
1898 for (i = 0; i < sizeof(SidTable) / sizeof(SidTable[0]) - 1; i++)
1899 {
1900 if (wcscmp(StringSid, SidTable[i].key) == 0)
1901 {
1902 WELL_KNOWN_SID_TYPE knownSid = (WELL_KNOWN_SID_TYPE)SidTable[i].value;
1903 size = SECURITY_MAX_SID_SIZE;
1904 *sid = LocalAlloc(0, size);
1905 if (!*sid)
1906 {
1907 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1908 return FALSE;
1909 }
1910 ret = CreateWellKnownSid(
1911 knownSid,
1912 NULL,
1913 *sid,
1914 &size);
1915 if (!ret)
1916 {
1917 SetLastError(ERROR_INVALID_SID);
1918 LocalFree(*sid);
1919 }
1920 return ret;
1921 }
1922 }
1923
1924 /* That's probably a string S-R-I-S-S... */
1925 if (StringSid[0] != 'S' || StringSid[1] != '-')
1926 {
1927 SetLastError(ERROR_INVALID_SID);
1928 return FALSE;
1929 }
1930
1931 cBytes = ComputeStringSidSize(StringSid);
1932 pisid = (SID*)LocalAlloc( 0, cBytes );
1933 if (!pisid)
1934 {
1935 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1936 return FALSE;
1937 }
1938 i = 0;
1939 ret = FALSE;
1940 csubauth = ((cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
1941
1942 StringSid += 2; /* Advance to Revision */
1943 pisid->Revision = atoiW(StringSid);
1944
1945 if (pisid->Revision != SDDL_REVISION)
1946 {
1947 TRACE("Revision %d is unknown\n", pisid->Revision);
1948 goto lend; /* ERROR_INVALID_SID */
1949 }
1950 if (csubauth == 0)
1951 {
1952 TRACE("SubAuthorityCount is 0\n");
1953 goto lend; /* ERROR_INVALID_SID */
1954 }
1955
1956 pisid->SubAuthorityCount = csubauth;
1957
1958 /* Advance to identifier authority */
1959 while (*StringSid && *StringSid != '-')
1960 StringSid++;
1961 if (*StringSid == '-')
1962 StringSid++;
1963
1964 /* MS' implementation can't handle values greater than 2^32 - 1, so
1965 * we don't either; assume most significant bytes are always 0
1966 */
1967 pisid->IdentifierAuthority.Value[0] = 0;
1968 pisid->IdentifierAuthority.Value[1] = 0;
1969 identAuth = atoiW(StringSid);
1970 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
1971 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
1972 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
1973 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
1974
1975 /* Advance to first sub authority */
1976 while (*StringSid && *StringSid != '-')
1977 StringSid++;
1978 if (*StringSid == '-')
1979 StringSid++;
1980
1981 while (*StringSid)
1982 {
1983 pisid->SubAuthority[i++] = atoiW(StringSid);
1984
1985 while (*StringSid && *StringSid != '-')
1986 StringSid++;
1987 if (*StringSid == '-')
1988 StringSid++;
1989 }
1990
1991 if (i != pisid->SubAuthorityCount)
1992 goto lend; /* ERROR_INVALID_SID */
1993
1994 *sid = pisid;
1995 ret = TRUE;
1996
1997 lend:
1998 if (!ret)
1999 {
2000 LocalFree(pisid);
2001 SetLastError(ERROR_INVALID_SID);
2002 }
2003
2004 TRACE("returning %s\n", ret ? "TRUE" : "FALSE");
2005 return ret;
2006 }
2007
2008
2009 /* EOF */