[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 #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 while (*StringSid == ' ')
809 StringSid++;
810
811 *cBytes = ComputeStringSidSize(StringSid);
812 if (!pisid) /* Simply compute the size */
813 {
814 TRACE("only size requested, returning TRUE\n");
815 return TRUE;
816 }
817
818 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
819 {
820 DWORD i = 0, identAuth;
821 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
822
823 StringSid += 2; /* Advance to Revision */
824 pisid->Revision = atoiW(StringSid);
825
826 if (pisid->Revision != SDDL_REVISION)
827 {
828 TRACE("Revision %d is unknown\n", pisid->Revision);
829 goto lend; /* ERROR_INVALID_SID */
830 }
831 if (csubauth == 0)
832 {
833 TRACE("SubAuthorityCount is 0\n");
834 goto lend; /* ERROR_INVALID_SID */
835 }
836
837 pisid->SubAuthorityCount = csubauth;
838
839 /* Advance to identifier authority */
840 while (*StringSid && *StringSid != '-')
841 StringSid++;
842 if (*StringSid == '-')
843 StringSid++;
844
845 /* MS' implementation can't handle values greater than 2^32 - 1, so
846 * we don't either; assume most significant bytes are always 0
847 */
848 pisid->IdentifierAuthority.Value[0] = 0;
849 pisid->IdentifierAuthority.Value[1] = 0;
850 identAuth = atoiW(StringSid);
851 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
852 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
853 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
854 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
855
856 /* Advance to first sub authority */
857 while (*StringSid && *StringSid != '-')
858 StringSid++;
859 if (*StringSid == '-')
860 StringSid++;
861
862 while (*StringSid)
863 {
864 pisid->SubAuthority[i++] = atoiW(StringSid);
865
866 while (*StringSid && *StringSid != '-')
867 StringSid++;
868 if (*StringSid == '-')
869 StringSid++;
870 }
871
872 if (i != pisid->SubAuthorityCount)
873 goto lend; /* ERROR_INVALID_SID */
874
875 bret = TRUE;
876 }
877 else /* String constant format - Only available in winxp and above */
878 {
879 unsigned int i;
880 pisid->Revision = SDDL_REVISION;
881
882 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
883 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
884 {
885 DWORD j;
886 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
887 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
888 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
889 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
890 bret = TRUE;
891 }
892
893 if (!bret)
894 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
895 }
896
897 lend:
898 if (!bret)
899 SetLastError(ERROR_INVALID_SID);
900
901 TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
902 return bret;
903 }
904
905 /******************************************************************************
906 * ParseAclStringFlags
907 */
908 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
909 {
910 DWORD flags = 0;
911 LPCWSTR szAcl = *StringAcl;
912
913 while (*szAcl != '(')
914 {
915 if (*szAcl == 'P')
916 {
917 flags |= SE_DACL_PROTECTED;
918 }
919 else if (*szAcl == 'A')
920 {
921 szAcl++;
922 if (*szAcl == 'R')
923 flags |= SE_DACL_AUTO_INHERIT_REQ;
924 else if (*szAcl == 'I')
925 flags |= SE_DACL_AUTO_INHERITED;
926 }
927 szAcl++;
928 }
929
930 *StringAcl = szAcl;
931 return flags;
932 }
933
934 /******************************************************************************
935 * ParseAceStringType
936 */
937 static const ACEFLAG AceType[] =
938 {
939 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
940 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
941 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
942 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
943 /*
944 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
945 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
946 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
947 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
948 */
949 { NULL, 0 },
950 };
951
952 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
953 {
954 UINT len = 0;
955 LPCWSTR szAcl = *StringAcl;
956 const ACEFLAG *lpaf = AceType;
957
958 while (lpaf->wstr &&
959 (len = strlenW(lpaf->wstr)) &&
960 strncmpW(lpaf->wstr, szAcl, len))
961 lpaf++;
962
963 if (!lpaf->wstr)
964 return 0;
965
966 *StringAcl += len;
967 return lpaf->value;
968 }
969
970
971 /******************************************************************************
972 * ParseAceStringFlags
973 */
974 static const ACEFLAG AceFlags[] =
975 {
976 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
977 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
978 { SDDL_INHERITED, INHERITED_ACE },
979 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
980 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
981 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
982 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
983 { NULL, 0 },
984 };
985
986 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
987 {
988 UINT len = 0;
989 BYTE flags = 0;
990 LPCWSTR szAcl = *StringAcl;
991
992 while (*szAcl != ';')
993 {
994 const ACEFLAG *lpaf = AceFlags;
995
996 while (lpaf->wstr &&
997 (len = strlenW(lpaf->wstr)) &&
998 strncmpW(lpaf->wstr, szAcl, len))
999 lpaf++;
1000
1001 if (!lpaf->wstr)
1002 return 0;
1003
1004 flags |= lpaf->value;
1005 szAcl += len;
1006 }
1007
1008 *StringAcl = szAcl;
1009 return flags;
1010 }
1011
1012
1013 /******************************************************************************
1014 * ParseAceStringRights
1015 */
1016 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
1017 {
1018 UINT len = 0;
1019 DWORD rights = 0;
1020 LPCWSTR szAcl = *StringAcl;
1021
1022 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
1023 {
1024 LPCWSTR p = szAcl;
1025
1026 while (*p && *p != ';')
1027 p++;
1028
1029 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
1030 {
1031 rights = strtoulW(szAcl, NULL, 16);
1032 szAcl = p;
1033 }
1034 else
1035 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
1036 }
1037 else
1038 {
1039 while (*szAcl != ';')
1040 {
1041 const ACEFLAG *lpaf = AceRights;
1042
1043 while (lpaf->wstr &&
1044 (len = strlenW(lpaf->wstr)) &&
1045 strncmpW(lpaf->wstr, szAcl, len))
1046 {
1047 lpaf++;
1048 }
1049
1050 if (!lpaf->wstr)
1051 return 0;
1052
1053 rights |= lpaf->value;
1054 szAcl += len;
1055 }
1056 }
1057
1058 *StringAcl = szAcl;
1059 return rights;
1060 }
1061
1062
1063 /******************************************************************************
1064 * ParseStringAclToAcl
1065 *
1066 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
1067 */
1068 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
1069 PACL pAcl, LPDWORD cBytes)
1070 {
1071 DWORD val;
1072 DWORD sidlen;
1073 DWORD length = sizeof(ACL);
1074 DWORD acesize = 0;
1075 DWORD acecount = 0;
1076 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
1077
1078 TRACE("%s\n", debugstr_w(StringAcl));
1079
1080 if (!StringAcl)
1081 return FALSE;
1082
1083 if (pAcl) /* pAce is only useful if we're setting values */
1084 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
1085
1086 /* Parse ACL flags */
1087 *lpdwFlags = ParseAclStringFlags(&StringAcl);
1088
1089 /* Parse ACE */
1090 while (*StringAcl == '(')
1091 {
1092 StringAcl++;
1093
1094 /* Parse ACE type */
1095 val = ParseAceStringType(&StringAcl);
1096 if (pAce)
1097 pAce->Header.AceType = (BYTE) val;
1098 if (*StringAcl != ';')
1099 goto lerr;
1100 StringAcl++;
1101
1102 /* Parse ACE flags */
1103 val = ParseAceStringFlags(&StringAcl);
1104 if (pAce)
1105 pAce->Header.AceFlags = (BYTE) val;
1106 if (*StringAcl != ';')
1107 goto lerr;
1108 StringAcl++;
1109
1110 /* Parse ACE rights */
1111 val = ParseAceStringRights(&StringAcl);
1112 if (pAce)
1113 pAce->Mask = val;
1114 if (*StringAcl != ';')
1115 goto lerr;
1116 StringAcl++;
1117
1118 /* Parse ACE object guid */
1119 if (*StringAcl != ';')
1120 {
1121 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1122 goto lerr;
1123 }
1124 StringAcl++;
1125
1126 /* Parse ACE inherit object guid */
1127 if (*StringAcl != ';')
1128 {
1129 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1130 goto lerr;
1131 }
1132 StringAcl++;
1133
1134 /* Parse ACE account sid */
1135 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
1136 {
1137 while (*StringAcl && *StringAcl != ')')
1138 StringAcl++;
1139 }
1140
1141 if (*StringAcl != ')')
1142 goto lerr;
1143 StringAcl++;
1144
1145 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
1146 length += acesize;
1147 if (pAce)
1148 {
1149 pAce->Header.AceSize = acesize;
1150 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
1151 }
1152 acecount++;
1153 }
1154
1155 *cBytes = length;
1156
1157 if (length > 0xffff)
1158 {
1159 ERR("ACL too large\n");
1160 goto lerr;
1161 }
1162
1163 if (pAcl)
1164 {
1165 pAcl->AclRevision = ACL_REVISION;
1166 pAcl->Sbz1 = 0;
1167 pAcl->AclSize = length;
1168 pAcl->AceCount = acecount++;
1169 pAcl->Sbz2 = 0;
1170 }
1171 return TRUE;
1172
1173 lerr:
1174 SetLastError(ERROR_INVALID_ACL);
1175 WARN("Invalid ACE string format\n");
1176 return FALSE;
1177 }
1178
1179
1180 /******************************************************************************
1181 * ParseStringSecurityDescriptorToSecurityDescriptor
1182 */
1183 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
1184 LPCWSTR StringSecurityDescriptor,
1185 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
1186 LPDWORD cBytes)
1187 {
1188 BOOL bret = FALSE;
1189 WCHAR toktype;
1190 WCHAR tok[MAX_PATH];
1191 LPCWSTR lptoken;
1192 LPBYTE lpNext = NULL;
1193 DWORD len;
1194
1195 *cBytes = sizeof(SECURITY_DESCRIPTOR);
1196
1197 if (SecurityDescriptor)
1198 lpNext = (LPBYTE)(SecurityDescriptor + 1);
1199
1200 while (*StringSecurityDescriptor)
1201 {
1202 toktype = *StringSecurityDescriptor;
1203
1204 /* Expect char identifier followed by ':' */
1205 StringSecurityDescriptor++;
1206 if (*StringSecurityDescriptor != ':')
1207 {
1208 SetLastError(ERROR_INVALID_PARAMETER);
1209 goto lend;
1210 }
1211 StringSecurityDescriptor++;
1212
1213 /* Extract token */
1214 lptoken = StringSecurityDescriptor;
1215 while (*lptoken && *lptoken != ':')
1216 lptoken++;
1217
1218 if (*lptoken)
1219 lptoken--;
1220
1221 len = lptoken - StringSecurityDescriptor;
1222 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
1223 tok[len] = 0;
1224
1225 switch (toktype)
1226 {
1227 case 'O':
1228 {
1229 DWORD bytes;
1230
1231 if (!ParseStringSidToSid(tok, lpNext, &bytes))
1232 goto lend;
1233
1234 if (SecurityDescriptor)
1235 {
1236 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
1237 lpNext += bytes; /* Advance to next token */
1238 }
1239
1240 *cBytes += bytes;
1241
1242 break;
1243 }
1244
1245 case 'G':
1246 {
1247 DWORD bytes;
1248
1249 if (!ParseStringSidToSid(tok, lpNext, &bytes))
1250 goto lend;
1251
1252 if (SecurityDescriptor)
1253 {
1254 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
1255 lpNext += bytes; /* Advance to next token */
1256 }
1257
1258 *cBytes += bytes;
1259
1260 break;
1261 }
1262
1263 case 'D':
1264 {
1265 DWORD flags;
1266 DWORD bytes;
1267
1268 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
1269 goto lend;
1270
1271 if (SecurityDescriptor)
1272 {
1273 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
1274 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
1275 lpNext += bytes; /* Advance to next token */
1276 }
1277
1278 *cBytes += bytes;
1279
1280 break;
1281 }
1282
1283 case 'S':
1284 {
1285 DWORD flags;
1286 DWORD bytes;
1287
1288 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
1289 goto lend;
1290
1291 if (SecurityDescriptor)
1292 {
1293 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
1294 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
1295 lpNext += bytes; /* Advance to next token */
1296 }
1297
1298 *cBytes += bytes;
1299
1300 break;
1301 }
1302
1303 default:
1304 FIXME("Unknown token\n");
1305 SetLastError(ERROR_INVALID_PARAMETER);
1306 goto lend;
1307 }
1308
1309 StringSecurityDescriptor = lptoken;
1310 }
1311
1312 bret = TRUE;
1313
1314 lend:
1315 return bret;
1316 }
1317
1318
1319 /******************************************************************************
1320 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
1321 * @implemented
1322 */
1323 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
1324 LPCWSTR StringSecurityDescriptor,
1325 DWORD StringSDRevision,
1326 PSECURITY_DESCRIPTOR* SecurityDescriptor,
1327 PULONG SecurityDescriptorSize)
1328 {
1329 DWORD cBytes;
1330 SECURITY_DESCRIPTOR* psd;
1331 BOOL bret = FALSE;
1332
1333 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
1334
1335 if (GetVersion() & 0x80000000)
1336 {
1337 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1338 goto lend;
1339 }
1340 else if (!StringSecurityDescriptor || !SecurityDescriptor)
1341 {
1342 SetLastError(ERROR_INVALID_PARAMETER);
1343 goto lend;
1344 }
1345 else if (StringSDRevision != SID_REVISION)
1346 {
1347 SetLastError(ERROR_UNKNOWN_REVISION);
1348 goto lend;
1349 }
1350
1351 /* Compute security descriptor length */
1352 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
1353 NULL, &cBytes))
1354 goto lend;
1355
1356 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
1357 if (!psd) goto lend;
1358
1359 psd->Revision = SID_REVISION;
1360 psd->Control |= SE_SELF_RELATIVE;
1361
1362 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
1363 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
1364 {
1365 LocalFree(psd);
1366 goto lend;
1367 }
1368
1369 if (SecurityDescriptorSize)
1370 *SecurityDescriptorSize = cBytes;
1371
1372 bret = TRUE;
1373
1374 lend:
1375 TRACE(" ret=%d\n", bret);
1376 return bret;
1377 }
1378
1379
1380 /* Winehq cvs 20050916 */
1381 /******************************************************************************
1382 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
1383 * @implemented
1384 */
1385 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
1386 LPCSTR StringSecurityDescriptor,
1387 DWORD StringSDRevision,
1388 PSECURITY_DESCRIPTOR* SecurityDescriptor,
1389 PULONG SecurityDescriptorSize)
1390 {
1391 UINT len;
1392 BOOL ret = FALSE;
1393 LPWSTR StringSecurityDescriptorW;
1394
1395 len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
1396 StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1397
1398 if (StringSecurityDescriptorW)
1399 {
1400 MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
1401
1402 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
1403 StringSDRevision, SecurityDescriptor,
1404 SecurityDescriptorSize);
1405 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
1406 }
1407
1408 return ret;
1409 }
1410
1411 /*
1412 * @implemented
1413 */
1414 BOOL WINAPI
1415 EqualPrefixSid(PSID pSid1,
1416 PSID pSid2)
1417 {
1418 return RtlEqualPrefixSid (pSid1, pSid2);
1419 }
1420
1421
1422 /*
1423 * @implemented
1424 */
1425 BOOL WINAPI
1426 EqualSid(PSID pSid1,
1427 PSID pSid2)
1428 {
1429 return RtlEqualSid (pSid1, pSid2);
1430 }
1431
1432
1433 /*
1434 * @implemented
1435 *
1436 * RETURNS
1437 * Docs says this function does NOT return a value
1438 * even thou it's defined to return a PVOID...
1439 */
1440 PVOID WINAPI
1441 FreeSid(PSID pSid)
1442 {
1443 return RtlFreeSid(pSid);
1444 }
1445
1446
1447 /*
1448 * @implemented
1449 */
1450 DWORD WINAPI
1451 GetLengthSid(PSID pSid)
1452 {
1453 return (DWORD)RtlLengthSid(pSid);
1454 }
1455
1456
1457 /*
1458 * @implemented
1459 */
1460 PSID_IDENTIFIER_AUTHORITY WINAPI
1461 GetSidIdentifierAuthority(PSID pSid)
1462 {
1463 return RtlIdentifierAuthoritySid(pSid);
1464 }
1465
1466
1467 /*
1468 * @implemented
1469 */
1470 DWORD WINAPI
1471 GetSidLengthRequired(UCHAR nSubAuthorityCount)
1472 {
1473 return (DWORD)RtlLengthRequiredSid(nSubAuthorityCount);
1474 }
1475
1476
1477 /*
1478 * @implemented
1479 */
1480 PDWORD WINAPI
1481 GetSidSubAuthority(PSID pSid,
1482 DWORD nSubAuthority)
1483 {
1484 return (PDWORD)RtlSubAuthoritySid(pSid, nSubAuthority);
1485 }
1486
1487
1488 /*
1489 * @implemented
1490 */
1491 PUCHAR WINAPI
1492 GetSidSubAuthorityCount(PSID pSid)
1493 {
1494 return RtlSubAuthorityCountSid(pSid);
1495 }
1496
1497
1498 /*
1499 * @implemented
1500 */
1501 BOOL WINAPI
1502 InitializeSid(PSID Sid,
1503 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
1504 BYTE nSubAuthorityCount)
1505 {
1506 NTSTATUS Status;
1507
1508 Status = RtlInitializeSid(Sid,
1509 pIdentifierAuthority,
1510 nSubAuthorityCount);
1511 if (!NT_SUCCESS(Status))
1512 {
1513 SetLastError(RtlNtStatusToDosError(Status));
1514 return FALSE;
1515 }
1516
1517 return TRUE;
1518 }
1519
1520
1521 /*
1522 * @implemented
1523 */
1524 BOOL WINAPI
1525 IsValidSid(PSID pSid)
1526 {
1527 return (BOOL)RtlValidSid(pSid);
1528 }
1529
1530
1531 /*
1532 * @implemented
1533 */
1534 BOOL WINAPI
1535 ConvertSidToStringSidW(PSID Sid,
1536 LPWSTR *StringSid)
1537 {
1538 NTSTATUS Status;
1539 UNICODE_STRING UnicodeString;
1540 WCHAR FixedBuffer[64];
1541
1542 if (!RtlValidSid(Sid))
1543 {
1544 SetLastError(ERROR_INVALID_SID);
1545 return FALSE;
1546 }
1547
1548 UnicodeString.Length = 0;
1549 UnicodeString.MaximumLength = sizeof(FixedBuffer);
1550 UnicodeString.Buffer = FixedBuffer;
1551 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
1552 if (STATUS_BUFFER_TOO_SMALL == Status)
1553 {
1554 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
1555 }
1556
1557 if (!NT_SUCCESS(Status))
1558 {
1559 SetLastError(RtlNtStatusToDosError(Status));
1560 return FALSE;
1561 }
1562
1563 *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
1564 if (NULL == *StringSid)
1565 {
1566 if (UnicodeString.Buffer != FixedBuffer)
1567 {
1568 RtlFreeUnicodeString(&UnicodeString);
1569 }
1570 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1571 return FALSE;
1572 }
1573
1574 MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
1575 ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
1576 if (UnicodeString.Buffer != FixedBuffer)
1577 {
1578 RtlFreeUnicodeString(&UnicodeString);
1579 }
1580
1581 return TRUE;
1582 }
1583
1584
1585 /*
1586 * @implemented
1587 */
1588 BOOL WINAPI
1589 ConvertSidToStringSidA(PSID Sid,
1590 LPSTR *StringSid)
1591 {
1592 LPWSTR StringSidW;
1593 int Len;
1594
1595 if (!ConvertSidToStringSidW(Sid, &StringSidW))
1596 {
1597 return FALSE;
1598 }
1599
1600 Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
1601 if (Len <= 0)
1602 {
1603 LocalFree(StringSidW);
1604 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1605 return FALSE;
1606 }
1607
1608 *StringSid = LocalAlloc(LMEM_FIXED, Len);
1609 if (NULL == *StringSid)
1610 {
1611 LocalFree(StringSidW);
1612 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1613 return FALSE;
1614 }
1615
1616 if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
1617 {
1618 LocalFree(StringSid);
1619 LocalFree(StringSidW);
1620 return FALSE;
1621 }
1622
1623 LocalFree(StringSidW);
1624
1625 return TRUE;
1626 }
1627
1628
1629 /*
1630 * @unimplemented
1631 */
1632 BOOL WINAPI
1633 EqualDomainSid(IN PSID pSid1,
1634 IN PSID pSid2,
1635 OUT BOOL* pfEqual)
1636 {
1637 UNIMPLEMENTED;
1638 return FALSE;
1639 }
1640
1641
1642 /*
1643 * @unimplemented
1644 */
1645 BOOL WINAPI
1646 GetWindowsAccountDomainSid(IN PSID pSid,
1647 OUT PSID ppDomainSid,
1648 IN OUT DWORD* cbSid)
1649 {
1650 UNIMPLEMENTED;
1651 return FALSE;
1652 }
1653
1654
1655 /*
1656 * @unimplemented
1657 */
1658 BOOL WINAPI
1659 CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType,
1660 IN PSID DomainSid OPTIONAL,
1661 OUT PSID pSid,
1662 IN OUT DWORD* cbSid)
1663 {
1664 unsigned int i;
1665 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
1666
1667 if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
1668 {
1669 SetLastError(ERROR_INVALID_PARAMETER);
1670 return FALSE;
1671 }
1672
1673 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
1674 if (WellKnownSids[i].Type == WellKnownSidType) {
1675 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
1676
1677 if (*cbSid < length)
1678 {
1679 *cbSid = length;
1680 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1681 return FALSE;
1682 }
1683 if (!pSid)
1684 {
1685 SetLastError(ERROR_INVALID_PARAMETER);
1686 return FALSE;
1687 }
1688 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
1689 *cbSid = length;
1690 return TRUE;
1691 }
1692 }
1693
1694 if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
1695 {
1696 SetLastError(ERROR_INVALID_PARAMETER);
1697 return FALSE;
1698 }
1699
1700 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
1701 if (WellKnownRids[i].Type == WellKnownSidType) {
1702 UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
1703 DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
1704 DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
1705
1706 if (*cbSid < output_sid_length)
1707 {
1708 *cbSid = output_sid_length;
1709 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1710 return FALSE;
1711 }
1712 if (!pSid)
1713 {
1714 SetLastError(ERROR_INVALID_PARAMETER);
1715 return FALSE;
1716 }
1717 CopyMemory(pSid, DomainSid, domain_sid_length);
1718 (*GetSidSubAuthorityCount(pSid))++;
1719 (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
1720 *cbSid = output_sid_length;
1721 return TRUE;
1722 }
1723
1724 SetLastError(ERROR_INVALID_PARAMETER);
1725 return FALSE;
1726 }
1727
1728
1729 /*
1730 * @unimplemented
1731 */
1732 BOOL WINAPI
1733 IsWellKnownSid(IN PSID pSid,
1734 IN WELL_KNOWN_SID_TYPE WellKnownSidType)
1735 {
1736 unsigned int i;
1737 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
1738
1739 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
1740 {
1741 if (WellKnownSids[i].Type == WellKnownSidType)
1742 {
1743 if (EqualSid(pSid, (PSID)((ULONG_PTR)&WellKnownSids[i].Sid.Revision)))
1744 return TRUE;
1745 }
1746 }
1747
1748 return FALSE;
1749 }
1750
1751
1752 /*
1753 * @implemented
1754 */
1755 BOOL WINAPI
1756 ConvertStringSidToSidA(IN LPCSTR StringSid,
1757 OUT PSID* sid)
1758 {
1759 BOOL bRetVal = FALSE;
1760
1761 if (!StringSid || !sid)
1762 SetLastError(ERROR_INVALID_PARAMETER);
1763 else
1764 {
1765 UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
1766 LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1767 MultiByteToWideChar(CP_ACP, 0, StringSid, - 1, wStringSid, len);
1768 bRetVal = ConvertStringSidToSidW(wStringSid, sid);
1769 HeapFree(GetProcessHeap(), 0, wStringSid);
1770 }
1771 return bRetVal;
1772 }
1773
1774
1775 static const RECORD SidTable[] =
1776 {
1777 { SDDL_ACCOUNT_OPERATORS, WinBuiltinAccountOperatorsSid },
1778 { SDDL_ALIAS_PREW2KCOMPACC, WinBuiltinPreWindows2000CompatibleAccessSid },
1779 { SDDL_ANONYMOUS, WinAnonymousSid },
1780 { SDDL_AUTHENTICATED_USERS, WinAuthenticatedUserSid },
1781 { SDDL_BUILTIN_ADMINISTRATORS, WinBuiltinAdministratorsSid },
1782 { SDDL_BUILTIN_GUESTS, WinBuiltinGuestsSid },
1783 { SDDL_BACKUP_OPERATORS, WinBuiltinBackupOperatorsSid },
1784 { SDDL_BUILTIN_USERS, WinBuiltinUsersSid },
1785 { SDDL_CERT_SERV_ADMINISTRATORS, WinAccountCertAdminsSid /* FIXME: DOMAIN_GROUP_RID_CERT_ADMINS */ },
1786 { SDDL_CREATOR_GROUP, WinCreatorGroupSid },
1787 { SDDL_CREATOR_OWNER, WinCreatorOwnerSid },
1788 { SDDL_DOMAIN_ADMINISTRATORS, WinAccountDomainAdminsSid /* FIXME: DOMAIN_GROUP_RID_ADMINS */ },
1789 { SDDL_DOMAIN_COMPUTERS, WinAccountComputersSid /* FIXME: DOMAIN_GROUP_RID_COMPUTERS */ },
1790 { SDDL_DOMAIN_DOMAIN_CONTROLLERS, WinAccountControllersSid /* FIXME: DOMAIN_GROUP_RID_CONTROLLERS */ },
1791 { SDDL_DOMAIN_GUESTS, WinAccountDomainGuestsSid /* FIXME: DOMAIN_GROUP_RID_GUESTS */ },
1792 { SDDL_DOMAIN_USERS, WinAccountDomainUsersSid /* FIXME: DOMAIN_GROUP_RID_USERS */ },
1793 { SDDL_ENTERPRISE_ADMINS, WinAccountEnterpriseAdminsSid /* FIXME: DOMAIN_GROUP_RID_ENTERPRISE_ADMINS */ },
1794 { SDDL_ENTERPRISE_DOMAIN_CONTROLLERS, WinLogonIdsSid /* FIXME: SECURITY_SERVER_LOGON_RID */ },
1795 { SDDL_EVERYONE, WinWorldSid },
1796 { SDDL_GROUP_POLICY_ADMINS, WinAccountPolicyAdminsSid /* FIXME: DOMAIN_GROUP_RID_POLICY_ADMINS */ },
1797 { SDDL_INTERACTIVE, WinInteractiveSid },
1798 { SDDL_LOCAL_ADMIN, WinAccountAdministratorSid /* FIXME: DOMAIN_USER_RID_ADMIN */ },
1799 { SDDL_LOCAL_GUEST, WinAccountGuestSid /* FIXME: DOMAIN_USER_RID_GUEST */ },
1800 { SDDL_LOCAL_SERVICE, WinLocalServiceSid },
1801 { SDDL_LOCAL_SYSTEM, WinLocalSystemSid },
1802 { SDDL_NETWORK, WinNetworkSid },
1803 { SDDL_NETWORK_CONFIGURATION_OPS, WinBuiltinNetworkConfigurationOperatorsSid },
1804 { SDDL_NETWORK_SERVICE, WinNetworkServiceSid },
1805 { SDDL_PRINTER_OPERATORS, WinBuiltinPrintOperatorsSid },
1806 { SDDL_PERSONAL_SELF, WinSelfSid },
1807 { SDDL_POWER_USERS, WinBuiltinPowerUsersSid },
1808 { SDDL_RAS_SERVERS, WinAccountRasAndIasServersSid /* FIXME: DOMAIN_ALIAS_RID_RAS_SERVERS */ },
1809 { SDDL_REMOTE_DESKTOP, WinBuiltinRemoteDesktopUsersSid },
1810 { SDDL_REPLICATOR, WinBuiltinReplicatorSid },
1811 { SDDL_RESTRICTED_CODE, WinRestrictedCodeSid },
1812 { SDDL_SCHEMA_ADMINISTRATORS, WinAccountSchemaAdminsSid /* FIXME: DOMAIN_GROUP_RID_SCHEMA_ADMINS */ },
1813 { SDDL_SERVER_OPERATORS, WinBuiltinSystemOperatorsSid },
1814 { SDDL_SERVICE, WinServiceSid },
1815 { NULL, 0 },
1816 };
1817
1818 /*
1819 * @implemented
1820 */
1821 BOOL WINAPI
1822 ConvertStringSidToSidW(IN LPCWSTR StringSid,
1823 OUT PSID* sid)
1824 {
1825 DWORD size;
1826 DWORD i, cBytes, identAuth, csubauth;
1827 BOOL ret;
1828 SID* pisid;
1829
1830 TRACE("%s %p\n", debugstr_w(StringSid), sid);
1831
1832 if (!StringSid)
1833 {
1834 SetLastError(ERROR_INVALID_SID);
1835 return FALSE;
1836 }
1837 for (i = 0; i < sizeof(SidTable) / sizeof(SidTable[0]) - 1; i++)
1838 {
1839 if (wcscmp(StringSid, SidTable[i].key) == 0)
1840 {
1841 WELL_KNOWN_SID_TYPE knownSid = (WELL_KNOWN_SID_TYPE)SidTable[i].value;
1842 size = SECURITY_MAX_SID_SIZE;
1843 *sid = LocalAlloc(0, size);
1844 if (!*sid)
1845 {
1846 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1847 return FALSE;
1848 }
1849 ret = CreateWellKnownSid(
1850 knownSid,
1851 NULL,
1852 *sid,
1853 &size);
1854 if (!ret)
1855 {
1856 SetLastError(ERROR_INVALID_SID);
1857 LocalFree(*sid);
1858 }
1859 return ret;
1860 }
1861 }
1862
1863 /* That's probably a string S-R-I-S-S... */
1864 if (StringSid[0] != 'S' || StringSid[1] != '-')
1865 {
1866 SetLastError(ERROR_INVALID_SID);
1867 return FALSE;
1868 }
1869
1870 cBytes = ComputeStringSidSize(StringSid);
1871 pisid = (SID*)LocalAlloc( 0, cBytes );
1872 if (!pisid)
1873 {
1874 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1875 return FALSE;
1876 }
1877 i = 0;
1878 ret = FALSE;
1879 csubauth = ((cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
1880
1881 StringSid += 2; /* Advance to Revision */
1882 pisid->Revision = atoiW(StringSid);
1883
1884 if (pisid->Revision != SDDL_REVISION)
1885 {
1886 TRACE("Revision %d is unknown\n", pisid->Revision);
1887 goto lend; /* ERROR_INVALID_SID */
1888 }
1889 if (csubauth == 0)
1890 {
1891 TRACE("SubAuthorityCount is 0\n");
1892 goto lend; /* ERROR_INVALID_SID */
1893 }
1894
1895 pisid->SubAuthorityCount = csubauth;
1896
1897 /* Advance to identifier authority */
1898 while (*StringSid && *StringSid != '-')
1899 StringSid++;
1900 if (*StringSid == '-')
1901 StringSid++;
1902
1903 /* MS' implementation can't handle values greater than 2^32 - 1, so
1904 * we don't either; assume most significant bytes are always 0
1905 */
1906 pisid->IdentifierAuthority.Value[0] = 0;
1907 pisid->IdentifierAuthority.Value[1] = 0;
1908 identAuth = atoiW(StringSid);
1909 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
1910 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
1911 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
1912 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
1913
1914 /* Advance to first sub authority */
1915 while (*StringSid && *StringSid != '-')
1916 StringSid++;
1917 if (*StringSid == '-')
1918 StringSid++;
1919
1920 pisid->SubAuthority[i] = atoiW(StringSid);
1921
1922 while (*StringSid)
1923 {
1924 while (*StringSid && *StringSid != '-')
1925 StringSid++;
1926 if (*StringSid == '-')
1927 StringSid++;
1928
1929 pisid->SubAuthority[++i] = atoiW(StringSid);
1930 }
1931
1932 if (i != pisid->SubAuthorityCount)
1933 goto lend; /* ERROR_INVALID_SID */
1934
1935 *sid = pisid;
1936 ret = TRUE;
1937
1938 lend:
1939 if (!ret)
1940 SetLastError(ERROR_INVALID_SID);
1941
1942 TRACE("returning %s\n", ret ? "TRUE" : "FALSE");
1943 return ret;
1944 }
1945
1946
1947 /* EOF */