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