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