Merging r37048, r37051, r37052, r37055 from the-real-msvc branch
[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 Hervé Poussineau
7 *
8 * PROJECT: ReactOS system libraries
9 * FILE: lib/advapi32/sec/sid.c
10 * PURPOSE: Security ID functions
11 */
12
13 #include <advapi32.h>
14 #include <sddl.h>
15 #include <wine/debug.h>
16 #include <wine/unicode.h>
17
18 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
19
20 #define MAX_GUID_STRING_LEN 39
21
22 BOOL STDCALL
23 AddAuditAccessAceEx(PACL pAcl,
24 DWORD dwAceRevision,
25 DWORD AceFlags,
26 DWORD dwAccessMask,
27 PSID pSid,
28 BOOL bAuditSuccess,
29 BOOL bAuditFailure);
30
31 typedef struct RECORD
32 {
33 LPCWSTR key;
34 DWORD value;
35 } RECORD;
36
37
38 typedef struct _MAX_SID
39 {
40 /* same fields as struct _SID */
41 BYTE Revision;
42 BYTE SubAuthorityCount;
43 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
44 DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
45 } MAX_SID;
46
47 typedef struct WELLKNOWNSID
48 {
49 WCHAR wstr[2];
50 WELL_KNOWN_SID_TYPE Type;
51 MAX_SID Sid;
52 } WELLKNOWNSID;
53
54 static const WELLKNOWNSID WellKnownSids[] =
55 {
56 { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
57 { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
58 { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
59 { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
60 { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
61 { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
62 { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
63 { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
64 { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
65 { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
66 { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
67 { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
68 { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
69 { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
70 { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
71 { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
72 { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
73 { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
74 { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
75 { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
76 { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
77 { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
78 { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
79 { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
80 { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
81 { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
82 { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
83 { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
84 { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
85 { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
86 { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
87 { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
88 { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
89 { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
90 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
91 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
92 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
93 };
94
95 static const SID sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
96
97 /*
98 * ACE types
99 */
100 static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0};
101 static const WCHAR SDDL_ACCESS_DENIED[] = {'D',0};
102 static const WCHAR SDDL_OBJECT_ACCESS_ALLOWED[] = {'O','A',0};
103 static const WCHAR SDDL_OBJECT_ACCESS_DENIED[] = {'O','D',0};
104 static const WCHAR SDDL_AUDIT[] = {'A','U',0};
105 static const WCHAR SDDL_ALARM[] = {'A','L',0};
106 static const WCHAR SDDL_OBJECT_AUDIT[] = {'O','U',0};
107 static const WCHAR SDDL_OBJECT_ALARM[] = {'O','L',0};
108
109 /*
110 * SDDL ADS Rights
111 */
112 #define ADS_RIGHT_DS_CREATE_CHILD 0x0001
113 #define ADS_RIGHT_DS_DELETE_CHILD 0x0002
114 #define ADS_RIGHT_ACTRL_DS_LIST 0x0004
115 #define ADS_RIGHT_DS_SELF 0x0008
116 #define ADS_RIGHT_DS_READ_PROP 0x0010
117 #define ADS_RIGHT_DS_WRITE_PROP 0x0020
118 #define ADS_RIGHT_DS_DELETE_TREE 0x0040
119 #define ADS_RIGHT_DS_LIST_OBJECT 0x0080
120 #define ADS_RIGHT_DS_CONTROL_ACCESS 0x0100
121
122 /*
123 * ACE flags
124 */
125 static const WCHAR SDDL_CONTAINER_INHERIT[] = {'C','I',0};
126 static const WCHAR SDDL_OBJECT_INHERIT[] = {'O','I',0};
127 static const WCHAR SDDL_NO_PROPAGATE[] = {'N','P',0};
128 static const WCHAR SDDL_INHERIT_ONLY[] = {'I','O',0};
129 static const WCHAR SDDL_INHERITED[] = {'I','D',0};
130 static const WCHAR SDDL_AUDIT_SUCCESS[] = {'S','A',0};
131 static const WCHAR SDDL_AUDIT_FAILURE[] = {'F','A',0};
132
133 static const char * debugstr_sid(PSID sid)
134 {
135 int auth = 0;
136 SID * psid = (SID *)sid;
137
138 if (psid == NULL)
139 return "(null)";
140
141 auth = psid->IdentifierAuthority.Value[5] +
142 (psid->IdentifierAuthority.Value[4] << 8) +
143 (psid->IdentifierAuthority.Value[3] << 16) +
144 (psid->IdentifierAuthority.Value[2] << 24);
145
146 switch (psid->SubAuthorityCount) {
147 case 0:
148 return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
149 case 1:
150 return wine_dbg_sprintf("S-%d-%d-%lu", psid->Revision, auth,
151 psid->SubAuthority[0]);
152 case 2:
153 return wine_dbg_sprintf("S-%d-%d-%lu-%lu", psid->Revision, auth,
154 psid->SubAuthority[0], psid->SubAuthority[1]);
155 case 3:
156 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu", psid->Revision, auth,
157 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
158 case 4:
159 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu", psid->Revision, auth,
160 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
161 psid->SubAuthority[3]);
162 case 5:
163 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
164 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
165 psid->SubAuthority[3], psid->SubAuthority[4]);
166 case 6:
167 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
168 psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
169 psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
170 case 7:
171 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
172 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
173 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
174 psid->SubAuthority[6]);
175 case 8:
176 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
177 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
178 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
179 psid->SubAuthority[6], psid->SubAuthority[7]);
180 }
181 return "(too-big)";
182 }
183
184 /* set last error code from NT status and get the proper boolean return value */
185 /* used for functions that are a simple wrapper around the corresponding ntdll API */
186 static __inline BOOL set_ntstatus( NTSTATUS status )
187 {
188 if (status) SetLastError( RtlNtStatusToDosError( status ));
189 return !status;
190 }
191
192 static BOOL
193 FindKeyInTable(
194 IN const RECORD* Table,
195 IN LPCWSTR Key,
196 OUT SIZE_T* pKeyLength,
197 OUT DWORD* pItem)
198 {
199 const RECORD* pRecord = Table;
200 while (pRecord->key != NULL)
201 {
202 if (wcsncmp(pRecord->key, Key, wcslen(pRecord->key)) == 0)
203 {
204 *pKeyLength = wcslen(pRecord->key);
205 *pItem = pRecord->value;
206 return TRUE;
207 }
208 pRecord++;
209 }
210 SetLastError(ERROR_INVALID_PARAMETER);
211 return FALSE;
212 }
213
214 static BOOL
215 ParseSidString(
216 IN LPCWSTR Buffer,
217 OUT PSID* pSid,
218 OUT SIZE_T* pLength)
219 {
220 WCHAR str[SDDL_ALIAS_SIZE + 1];
221 LPWSTR strSid;
222 LPCWSTR end;
223 BOOL ret;
224 DWORD i;
225
226 wcsncpy(str, Buffer, SDDL_ALIAS_SIZE);
227 for (i = SDDL_ALIAS_SIZE; i > 0; i--)
228 {
229 str[i] = UNICODE_NULL;
230 if (ConvertStringSidToSidW(str, pSid))
231 {
232 *pLength = i;
233 return TRUE;
234 }
235 }
236
237 end = wcschr(Buffer, SDDL_ACE_ENDC);
238 if (!end)
239 {
240 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
241 return FALSE;
242 }
243 strSid = (LPWSTR)LocalAlloc(0, (end - Buffer) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
244 if (!strSid)
245 {
246 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
247 return FALSE;
248 }
249 wcsncpy(strSid, Buffer, end - Buffer + 1);
250 strSid[end - Buffer] = UNICODE_NULL;
251 *pLength = end - Buffer;
252 ret = ConvertStringSidToSidW(strSid, pSid);
253 LocalFree(strSid);
254 return ret;
255 }
256
257 static const RECORD DaclFlagTable[] =
258 {
259 { SDDL_PROTECTED, SE_DACL_PROTECTED },
260 { SDDL_AUTO_INHERIT_REQ, SE_DACL_AUTO_INHERIT_REQ },
261 { SDDL_AUTO_INHERITED, SE_DACL_AUTO_INHERITED },
262 { NULL, 0 },
263 };
264
265 static const RECORD SaclFlagTable[] =
266 {
267 { SDDL_PROTECTED, SE_SACL_PROTECTED },
268 { SDDL_AUTO_INHERIT_REQ, SE_SACL_AUTO_INHERIT_REQ },
269 { SDDL_AUTO_INHERITED, SE_SACL_AUTO_INHERITED },
270 { NULL, 0 },
271 };
272
273 static const RECORD AceFlagTable[] =
274 {
275 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
276 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
277 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
278 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
279 { SDDL_INHERITED, INHERITED_ACE },
280 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
281 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
282 { NULL, 0 },
283 };
284
285 static BOOL
286 ParseFlagsString(
287 IN LPCWSTR Buffer,
288 IN const RECORD* FlagTable,
289 IN WCHAR LimitChar,
290 OUT DWORD* pFlags,
291 OUT SIZE_T* pLength)
292 {
293 LPCWSTR ptr = Buffer;
294 SIZE_T PartialLength;
295 DWORD Flag;
296
297 *pFlags = 0;
298 while (*ptr != LimitChar)
299 {
300 if (!FindKeyInTable(FlagTable, ptr, &PartialLength, &Flag))
301 return FALSE;
302 *pFlags |= Flag;
303 ptr += PartialLength;
304 }
305 *pLength = ptr - Buffer;
306 return TRUE;
307 }
308
309 static const RECORD AccessMaskTable[] =
310 {
311 { SDDL_GENERIC_ALL, GENERIC_ALL },
312 { SDDL_GENERIC_READ, GENERIC_READ },
313 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
314 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
315 { SDDL_READ_CONTROL, READ_CONTROL },
316 { SDDL_STANDARD_DELETE, DELETE },
317 { SDDL_WRITE_DAC, WRITE_DAC },
318 { SDDL_WRITE_OWNER, WRITE_OWNER },
319 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP },
320 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP },
321 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD },
322 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD },
323 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST },
324 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF },
325 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT },
326 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE },
327 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS },
328 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
329 { SDDL_FILE_READ, FILE_GENERIC_READ },
330 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
331 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
332 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
333 { SDDL_KEY_READ, KEY_READ },
334 { SDDL_KEY_WRITE, KEY_WRITE },
335 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
336 { NULL, 0 },
337 };
338
339 static BOOL
340 ParseAccessMaskString(
341 IN LPCWSTR Buffer,
342 OUT DWORD* pAccessMask,
343 OUT SIZE_T* pLength)
344 {
345 /* FIXME: Allow hexadecimal string for access rights! */
346
347 return ParseFlagsString(Buffer, AccessMaskTable, SDDL_SEPERATORC, pAccessMask, pLength);
348 }
349
350 static BOOL
351 ParseGuidString(
352 IN LPCWSTR Buffer,
353 OUT GUID* pGuid,
354 OUT BOOL* pIsGuidValid,
355 OUT SIZE_T* pLength)
356 {
357 WCHAR GuidStr[MAX_GUID_STRING_LEN + 1];
358 LPCWSTR end;
359
360 end = wcschr(Buffer, SDDL_SEPERATORC);
361 if (!end)
362 {
363 SetLastError(ERROR_INVALID_PARAMETER);
364 return FALSE;
365 }
366
367 *pLength = end - Buffer;
368 *pIsGuidValid = (end != Buffer);
369 if (!*pIsGuidValid)
370 return TRUE;
371
372 if (end - Buffer > MAX_GUID_STRING_LEN - 1)
373 {
374 SetLastError(ERROR_INVALID_PARAMETER);
375 return FALSE;
376 }
377 GuidStr[end - Buffer] = UNICODE_NULL;
378 wcsncpy(GuidStr, Buffer, end - Buffer);
379 if (RPC_S_OK != UuidFromStringW((unsigned short*)&GuidStr, pGuid))
380 {
381 SetLastError(ERROR_INVALID_PARAMETER);
382 return FALSE;
383 }
384 return TRUE;
385 }
386
387 static const RECORD AceTypeTable[] =
388 {
389 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
390 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
391 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
392 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
393 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
394 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
395 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
396 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
397 { NULL, 0 },
398 };
399
400 static BOOL
401 ParseAceString(
402 IN LPCWSTR Buffer,
403 IN PACL pAcl,
404 OUT SIZE_T* pLength)
405 {
406 LPCWSTR ptr = Buffer;
407 SIZE_T PartialLength;
408 DWORD aceType, aceFlags, accessMask;
409 GUID object, inheritObject;
410 BOOL objectValid, inheritObjectValid;
411 PSID sid = NULL;
412 BOOL ret;
413
414 if (*ptr != SDDL_ACE_BEGINC)
415 {
416 SetLastError(ERROR_INVALID_PARAMETER);
417 return FALSE;
418 }
419 ptr++; /* Skip SDDL_ACE_BEGINC */
420
421 if (!FindKeyInTable(AceTypeTable, ptr, &PartialLength, &aceType))
422 return FALSE;
423 ptr += PartialLength;
424
425 if (*ptr != SDDL_SEPERATORC)
426 {
427 SetLastError(ERROR_INVALID_PARAMETER);
428 return FALSE;
429 }
430 ptr++; /* Skip SDDL_SEPERATORC */
431
432 if (!ParseFlagsString(ptr, AceFlagTable, SDDL_SEPERATORC, &aceFlags, &PartialLength))
433 return FALSE;
434 ptr += PartialLength + 1;
435
436 if (!ParseAccessMaskString(ptr, &accessMask, &PartialLength))
437 return FALSE;
438 ptr += PartialLength + 1;
439
440 if (!ParseGuidString(ptr, &object, &objectValid, &PartialLength))
441 return FALSE;
442 ptr += PartialLength + 1;
443
444 if (!ParseGuidString(ptr, &inheritObject, &inheritObjectValid, &PartialLength))
445 return FALSE;
446 ptr += PartialLength + 1;
447
448 if (!ParseSidString(ptr, &sid, &PartialLength))
449 return FALSE;
450 ptr += PartialLength;
451 if (*ptr != SDDL_ACE_ENDC)
452 {
453 SetLastError(ERROR_INVALID_PARAMETER);
454 return FALSE;
455 }
456 ptr++; /* Skip SDDL_ACE_ENDC */
457 *pLength = ptr - Buffer;
458
459 switch (aceType)
460 {
461 case ACCESS_ALLOWED_ACE_TYPE:
462 ret = AddAccessAllowedAceEx(
463 pAcl,
464 ACL_REVISION_DS,
465 aceFlags,
466 accessMask,
467 sid);
468 break;
469 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
470 ret = AddAccessAllowedObjectAce(
471 pAcl,
472 ACL_REVISION_DS,
473 aceFlags,
474 accessMask,
475 objectValid ? &object : NULL,
476 inheritObjectValid ? &inheritObject : NULL,
477 sid);
478 break;
479 case ACCESS_DENIED_ACE_TYPE:
480 ret = AddAccessDeniedAceEx(
481 pAcl,
482 ACL_REVISION_DS,
483 aceFlags,
484 accessMask,
485 sid);
486 break;
487 case ACCESS_DENIED_OBJECT_ACE_TYPE:
488 ret = AddAccessDeniedObjectAce(
489 pAcl,
490 ACL_REVISION_DS,
491 aceFlags,
492 accessMask,
493 objectValid ? &object : NULL,
494 inheritObjectValid ? &inheritObject : NULL,
495 sid);
496 break;
497 case SYSTEM_AUDIT_ACE_TYPE:
498 ret = AddAuditAccessAceEx(
499 pAcl,
500 ACL_REVISION_DS,
501 aceFlags,
502 accessMask,
503 sid,
504 FALSE,
505 FALSE);
506 break;
507 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
508 ret = AddAuditAccessObjectAce(
509 pAcl,
510 ACL_REVISION_DS,
511 aceFlags,
512 accessMask,
513 objectValid ? &object : NULL,
514 inheritObjectValid ? &inheritObject : NULL,
515 sid,
516 FALSE,
517 FALSE);
518 break;
519 case SYSTEM_ALARM_ACE_TYPE:
520 case SYSTEM_ALARM_OBJECT_ACE_TYPE:
521 default:
522 {
523 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
524 ret = FALSE;
525 }
526 }
527 LocalFree(sid);
528 return ret;
529 }
530
531 /* Exported functions */
532
533 /*
534 * @implemented
535 */
536 BOOL STDCALL
537 AllocateLocallyUniqueId(PLUID Luid)
538 {
539 NTSTATUS Status;
540
541 Status = NtAllocateLocallyUniqueId (Luid);
542 if (!NT_SUCCESS (Status))
543 {
544 SetLastError(RtlNtStatusToDosError(Status));
545 return FALSE;
546 }
547
548 return TRUE;
549 }
550
551
552 /*
553 * @implemented
554 */
555 BOOL STDCALL
556 AllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
557 BYTE nSubAuthorityCount,
558 DWORD dwSubAuthority0,
559 DWORD dwSubAuthority1,
560 DWORD dwSubAuthority2,
561 DWORD dwSubAuthority3,
562 DWORD dwSubAuthority4,
563 DWORD dwSubAuthority5,
564 DWORD dwSubAuthority6,
565 DWORD dwSubAuthority7,
566 PSID *pSid)
567 {
568 NTSTATUS Status;
569
570 Status = RtlAllocateAndInitializeSid(pIdentifierAuthority,
571 nSubAuthorityCount,
572 dwSubAuthority0,
573 dwSubAuthority1,
574 dwSubAuthority2,
575 dwSubAuthority3,
576 dwSubAuthority4,
577 dwSubAuthority5,
578 dwSubAuthority6,
579 dwSubAuthority7,
580 pSid);
581 if (!NT_SUCCESS(Status))
582 {
583 SetLastError(RtlNtStatusToDosError(Status));
584 return FALSE;
585 }
586
587 return TRUE;
588 }
589
590
591 /*
592 * @implemented
593 */
594 BOOL STDCALL
595 CopySid(DWORD nDestinationSidLength,
596 PSID pDestinationSid,
597 PSID pSourceSid)
598 {
599 NTSTATUS Status;
600
601 Status = RtlCopySid(nDestinationSidLength,
602 pDestinationSid,
603 pSourceSid);
604 if (!NT_SUCCESS (Status))
605 {
606 SetLastError(RtlNtStatusToDosError(Status));
607 return FALSE;
608 }
609
610 return TRUE;
611 }
612
613
614 /******************************************************************************
615 * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
616 * @unimplemented
617 */
618 BOOL WINAPI
619 ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor,
620 DWORD SDRevision,
621 SECURITY_INFORMATION SecurityInformation,
622 LPWSTR *OutputString,
623 PULONG OutputLen)
624 {
625 if (SDRevision != SDDL_REVISION_1)
626 {
627 ERR("Pogram requested unknown SDDL revision %d\n", SDRevision);
628 SetLastError(ERROR_UNKNOWN_REVISION);
629 return FALSE;
630 }
631
632 FIXME("%s() not implemented!\n", __FUNCTION__);
633 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
634 return FALSE;
635 }
636
637
638 /******************************************************************************
639 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
640 * @implemented
641 */
642 BOOL WINAPI
643 ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor,
644 DWORD SDRevision,
645 SECURITY_INFORMATION Information,
646 LPSTR *OutputString,
647 PULONG OutputLen)
648 {
649 LPWSTR wstr;
650 ULONG len;
651 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
652 {
653 int lenA;
654
655 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
656 *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
657 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
658 LocalFree(wstr);
659
660 if (OutputLen != NULL)
661 *OutputLen = lenA;
662 return TRUE;
663 }
664 else
665 {
666 *OutputString = NULL;
667 if (OutputLen)
668 *OutputLen = 0;
669 return FALSE;
670 }
671 }
672
673 /******************************************************************************
674 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
675 * @implemented
676 */
677 BOOL WINAPI
678 ConvertStringSecurityDescriptorToSecurityDescriptorW(
679 IN LPCWSTR StringSecurityDescriptor,
680 IN DWORD StringSDRevision,
681 OUT PSECURITY_DESCRIPTOR* SecurityDescriptor,
682 OUT PULONG SecurityDescriptorSize)
683 {
684 PSECURITY_DESCRIPTOR sd = NULL;
685 BOOL ret = FALSE;
686
687 if (!StringSecurityDescriptor)
688 SetLastError(ERROR_INVALID_PARAMETER);
689 else if (StringSDRevision != SDDL_REVISION_1)
690 SetLastError(ERROR_INVALID_PARAMETER);
691 else
692 {
693 LPCWSTR ptr = StringSecurityDescriptor;
694 DWORD numberOfAces = 0;
695 DWORD relativeSdSize;
696 SIZE_T MaxAclSize;
697 PSECURITY_DESCRIPTOR relativeSd = NULL;
698 PSID pSid;
699 PACL pAcl;
700 BOOL present, dummy;
701 /* An easy way to know how much space we need for an ACL is to count
702 * the number of ACEs and say that we have 1 SID by ACE
703 */
704 ptr = wcschr(StringSecurityDescriptor, SDDL_ACE_BEGINC);
705 while (ptr != NULL)
706 {
707 numberOfAces++;
708 ptr = wcschr(ptr + 1, SDDL_ACE_BEGINC);
709 }
710 MaxAclSize = sizeof(ACL) + numberOfAces *
711 (sizeof(ACCESS_ALLOWED_OBJECT_ACE) + SECURITY_MAX_SID_SIZE);
712
713 sd = (SECURITY_DESCRIPTOR*)LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR));
714 if (!sd)
715 {
716 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
717 return FALSE;
718 }
719 ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
720 if (!ret)
721 goto cleanup;
722
723 /* Now, really parse the string */
724 ptr = StringSecurityDescriptor;
725 while (*ptr)
726 {
727 if (ptr[1] != SDDL_DELIMINATORC)
728 {
729 SetLastError(ERROR_INVALID_PARAMETER);
730 ret = FALSE;
731 goto cleanup;
732 }
733 ptr += 2;
734 switch (ptr[-2])
735 {
736 case 'O':
737 case 'G':
738 {
739 PSID pSid;
740 SIZE_T Length;
741
742 ret = ParseSidString(ptr, &pSid, &Length);
743 if (!ret)
744 goto cleanup;
745 if (ptr[-2] == 'O')
746 ret = SetSecurityDescriptorOwner(sd, pSid, FALSE);
747 else
748 ret = SetSecurityDescriptorGroup(sd, pSid, FALSE);
749 if (!ret)
750 {
751 LocalFree(pSid);
752 goto cleanup;
753 }
754 ptr += Length;
755 break;
756 }
757 case 'D':
758 case 'S':
759 {
760 DWORD aclFlags;
761 SIZE_T Length;
762 BOOL isDacl = (ptr[-2] == 'D');
763
764 if (isDacl)
765 ret = ParseFlagsString(ptr, DaclFlagTable, SDDL_ACE_BEGINC, &aclFlags, &Length);
766 else
767 ret = ParseFlagsString(ptr, SaclFlagTable, SDDL_ACE_BEGINC, &aclFlags, &Length);
768 if (!ret)
769 goto cleanup;
770 pAcl = (PACL)LocalAlloc(0, MaxAclSize);
771 if (!pAcl)
772 {
773 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
774 ret = FALSE;
775 goto cleanup;
776 }
777 if (!InitializeAcl(pAcl, (DWORD)MaxAclSize, ACL_REVISION_DS))
778 {
779 LocalFree(pAcl);
780 goto cleanup;
781 }
782 if (aclFlags != 0)
783 {
784 ret = SetSecurityDescriptorControl(
785 sd,
786 (SECURITY_DESCRIPTOR_CONTROL)aclFlags,
787 (SECURITY_DESCRIPTOR_CONTROL)aclFlags);
788 if (!ret)
789 {
790 LocalFree(pAcl);
791 goto cleanup;
792 }
793 }
794 ptr += Length;
795 while (*ptr == SDDL_ACE_BEGINC)
796 {
797 ret = ParseAceString(ptr, pAcl, &Length);
798 if (!ret)
799 {
800 LocalFree(pAcl);
801 goto cleanup;
802 }
803 ptr += Length;
804 }
805 if (isDacl)
806 ret = SetSecurityDescriptorDacl(sd, TRUE, pAcl, FALSE);
807 else
808 ret = SetSecurityDescriptorSacl(sd, TRUE, pAcl, FALSE);
809 if (!ret)
810 {
811 LocalFree(pAcl);
812 goto cleanup;
813 }
814 break;
815 }
816 default:
817 {
818 SetLastError(ERROR_INVALID_PARAMETER);
819 ret = FALSE;
820 goto cleanup;
821 }
822 }
823 }
824
825 relativeSdSize = 0;
826 while (TRUE)
827 {
828 if (relativeSd)
829 LocalFree(relativeSd);
830 relativeSd = LocalAlloc(0, relativeSdSize);
831 if (!relativeSd)
832 {
833 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
834 goto cleanup;
835 }
836 ret = MakeSelfRelativeSD(sd, relativeSd, &relativeSdSize);
837 if (ret || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
838 break;
839 }
840 if (SecurityDescriptorSize)
841 *SecurityDescriptorSize = relativeSdSize;
842 *SecurityDescriptor = relativeSd;
843
844 cleanup:
845 if (GetSecurityDescriptorOwner(sd, &pSid, &dummy))
846 LocalFree(pSid);
847 if (GetSecurityDescriptorGroup(sd, &pSid, &dummy))
848 LocalFree(pSid);
849 if (GetSecurityDescriptorDacl(sd, &present, &pAcl, &dummy) && present)
850 LocalFree(pAcl);
851 if (GetSecurityDescriptorSacl(sd, &present, &pAcl, &dummy) && present)
852 LocalFree(pAcl);
853 LocalFree(sd);
854 return ret;
855 }
856 return FALSE;
857 }
858
859 /* Winehq cvs 20050916 */
860 /******************************************************************************
861 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
862 * @implemented
863 */
864 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
865 LPCSTR StringSecurityDescriptor,
866 DWORD StringSDRevision,
867 PSECURITY_DESCRIPTOR* SecurityDescriptor,
868 PULONG SecurityDescriptorSize)
869 {
870 UINT len;
871 BOOL ret = FALSE;
872 LPWSTR StringSecurityDescriptorW;
873
874 len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
875 StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
876
877 if (StringSecurityDescriptorW)
878 {
879 MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
880
881 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
882 StringSDRevision, SecurityDescriptor,
883 SecurityDescriptorSize);
884 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
885 }
886
887 return ret;
888 }
889
890 /*
891 * @implemented
892 */
893 BOOL STDCALL
894 EqualPrefixSid(PSID pSid1,
895 PSID pSid2)
896 {
897 return RtlEqualPrefixSid (pSid1, pSid2);
898 }
899
900
901 /*
902 * @implemented
903 */
904 BOOL STDCALL
905 EqualSid(PSID pSid1,
906 PSID pSid2)
907 {
908 return RtlEqualSid (pSid1, pSid2);
909 }
910
911
912 /*
913 * @implemented
914 *
915 * RETURNS
916 * Docs says this function does NOT return a value
917 * even thou it's defined to return a PVOID...
918 */
919 PVOID STDCALL
920 FreeSid(PSID pSid)
921 {
922 return RtlFreeSid(pSid);
923 }
924
925
926 /*
927 * @implemented
928 */
929 DWORD STDCALL
930 GetLengthSid(PSID pSid)
931 {
932 return (DWORD)RtlLengthSid(pSid);
933 }
934
935
936 /*
937 * @implemented
938 */
939 PSID_IDENTIFIER_AUTHORITY STDCALL
940 GetSidIdentifierAuthority(PSID pSid)
941 {
942 return RtlIdentifierAuthoritySid(pSid);
943 }
944
945
946 /*
947 * @implemented
948 */
949 DWORD STDCALL
950 GetSidLengthRequired(UCHAR nSubAuthorityCount)
951 {
952 return (DWORD)RtlLengthRequiredSid(nSubAuthorityCount);
953 }
954
955
956 /*
957 * @implemented
958 */
959 PDWORD STDCALL
960 GetSidSubAuthority(PSID pSid,
961 DWORD nSubAuthority)
962 {
963 return (PDWORD)RtlSubAuthoritySid(pSid, nSubAuthority);
964 }
965
966
967 /*
968 * @implemented
969 */
970 PUCHAR STDCALL
971 GetSidSubAuthorityCount(PSID pSid)
972 {
973 return RtlSubAuthorityCountSid(pSid);
974 }
975
976
977 /*
978 * @implemented
979 */
980 BOOL STDCALL
981 InitializeSid(PSID Sid,
982 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
983 BYTE nSubAuthorityCount)
984 {
985 NTSTATUS Status;
986
987 Status = RtlInitializeSid(Sid,
988 pIdentifierAuthority,
989 nSubAuthorityCount);
990 if (!NT_SUCCESS(Status))
991 {
992 SetLastError(RtlNtStatusToDosError(Status));
993 return FALSE;
994 }
995
996 return TRUE;
997 }
998
999
1000 /*
1001 * @implemented
1002 */
1003 BOOL STDCALL
1004 IsValidSid(PSID pSid)
1005 {
1006 return (BOOL)RtlValidSid(pSid);
1007 }
1008
1009
1010 /*
1011 * @implemented
1012 */
1013 BOOL STDCALL
1014 ConvertSidToStringSidW(PSID Sid,
1015 LPWSTR *StringSid)
1016 {
1017 NTSTATUS Status;
1018 UNICODE_STRING UnicodeString;
1019 WCHAR FixedBuffer[64];
1020
1021 if (!RtlValidSid(Sid))
1022 {
1023 SetLastError(ERROR_INVALID_SID);
1024 return FALSE;
1025 }
1026
1027 UnicodeString.Length = 0;
1028 UnicodeString.MaximumLength = sizeof(FixedBuffer);
1029 UnicodeString.Buffer = FixedBuffer;
1030 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
1031 if (STATUS_BUFFER_TOO_SMALL == Status)
1032 {
1033 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
1034 }
1035
1036 if (!NT_SUCCESS(Status))
1037 {
1038 SetLastError(RtlNtStatusToDosError(Status));
1039 return FALSE;
1040 }
1041
1042 *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
1043 if (NULL == *StringSid)
1044 {
1045 if (UnicodeString.Buffer != FixedBuffer)
1046 {
1047 RtlFreeUnicodeString(&UnicodeString);
1048 }
1049 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1050 return FALSE;
1051 }
1052
1053 MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
1054 ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
1055 if (UnicodeString.Buffer != FixedBuffer)
1056 {
1057 RtlFreeUnicodeString(&UnicodeString);
1058 }
1059
1060 return TRUE;
1061 }
1062
1063
1064 /*
1065 * @implemented
1066 */
1067 BOOL STDCALL
1068 ConvertSidToStringSidA(PSID Sid,
1069 LPSTR *StringSid)
1070 {
1071 LPWSTR StringSidW;
1072 int Len;
1073
1074 if (!ConvertSidToStringSidW(Sid, &StringSidW))
1075 {
1076 return FALSE;
1077 }
1078
1079 Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
1080 if (Len <= 0)
1081 {
1082 LocalFree(StringSidW);
1083 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1084 return FALSE;
1085 }
1086
1087 *StringSid = LocalAlloc(LMEM_FIXED, Len);
1088 if (NULL == *StringSid)
1089 {
1090 LocalFree(StringSidW);
1091 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1092 return FALSE;
1093 }
1094
1095 if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
1096 {
1097 LocalFree(StringSid);
1098 LocalFree(StringSidW);
1099 return FALSE;
1100 }
1101
1102 LocalFree(StringSidW);
1103
1104 return TRUE;
1105 }
1106
1107
1108 /*
1109 * @unimplemented
1110 */
1111 BOOL STDCALL
1112 EqualDomainSid(IN PSID pSid1,
1113 IN PSID pSid2,
1114 OUT BOOL* pfEqual)
1115 {
1116 UNIMPLEMENTED;
1117 return FALSE;
1118 }
1119
1120
1121 /*
1122 * @unimplemented
1123 */
1124 BOOL STDCALL
1125 GetWindowsAccountDomainSid(IN PSID pSid,
1126 OUT PSID ppDomainSid,
1127 IN OUT DWORD* cbSid)
1128 {
1129 UNIMPLEMENTED;
1130 return FALSE;
1131 }
1132
1133
1134 /*
1135 * @unimplemented
1136 */
1137 BOOL STDCALL
1138 CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType,
1139 IN PSID DomainSid OPTIONAL,
1140 OUT PSID pSid,
1141 IN OUT DWORD* cbSid)
1142 {
1143 int i;
1144 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
1145
1146 if (DomainSid != NULL)
1147 {
1148 FIXME("Only local computer supported!\n");
1149 SetLastError(ERROR_INVALID_PARAMETER); /* FIXME */
1150 return FALSE;
1151 }
1152
1153 if (cbSid == NULL || pSid == NULL)
1154 {
1155 SetLastError(ERROR_INVALID_PARAMETER);
1156 return FALSE;
1157 }
1158
1159 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
1160 {
1161 if (WellKnownSids[i].Type == WellKnownSidType)
1162 {
1163 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
1164
1165 if (*cbSid < length)
1166 {
1167 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1168 return FALSE;
1169 }
1170
1171 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
1172 *cbSid = length;
1173 return TRUE;
1174 }
1175 }
1176
1177 SetLastError(ERROR_INVALID_PARAMETER);
1178 return FALSE;
1179 }
1180
1181
1182 /*
1183 * @unimplemented
1184 */
1185 BOOL STDCALL
1186 IsWellKnownSid(IN PSID pSid,
1187 IN WELL_KNOWN_SID_TYPE WellKnownSidType)
1188 {
1189 int i;
1190 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
1191
1192 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
1193 {
1194 if (WellKnownSids[i].Type == WellKnownSidType)
1195 {
1196 if (EqualSid(pSid, (PSID)((ULONG_PTR)&WellKnownSids[i].Sid.Revision)))
1197 return TRUE;
1198 }
1199 }
1200
1201 return FALSE;
1202 }
1203
1204
1205 /*
1206 * @implemented
1207 */
1208 BOOL STDCALL
1209 ConvertStringSidToSidA(IN LPCSTR StringSid,
1210 OUT PSID* sid)
1211 {
1212 BOOL bRetVal = FALSE;
1213
1214 if (!StringSid || !sid)
1215 SetLastError(ERROR_INVALID_PARAMETER);
1216 else
1217 {
1218 UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
1219 LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1220 MultiByteToWideChar(CP_ACP, 0, StringSid, - 1, wStringSid, len);
1221 bRetVal = ConvertStringSidToSidW(wStringSid, sid);
1222 HeapFree(GetProcessHeap(), 0, wStringSid);
1223 }
1224 return bRetVal;
1225 }
1226
1227
1228 /******************************************************************************
1229 * ComputeStringSidSize
1230 */
1231 static DWORD
1232 ComputeStringSidSize(LPCWSTR StringSid)
1233 {
1234 DWORD size = sizeof(SID);
1235
1236 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
1237 {
1238 int ctok = 0;
1239 while (*StringSid)
1240 {
1241 if (*StringSid == '-')
1242 ctok++;
1243 StringSid++;
1244 }
1245
1246 if (ctok > 3)
1247 size += (ctok - 3) * sizeof(DWORD);
1248 }
1249 else /* String constant format - Only available in winxp and above */
1250 {
1251 int i;
1252
1253 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
1254 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
1255 size += (WellKnownSids[i].Sid.SubAuthorityCount - 1) * sizeof(DWORD);
1256 }
1257
1258 return size;
1259 }
1260
1261 static const RECORD SidTable[] =
1262 {
1263 { SDDL_ACCOUNT_OPERATORS, WinBuiltinAccountOperatorsSid },
1264 { SDDL_ALIAS_PREW2KCOMPACC, WinBuiltinPreWindows2000CompatibleAccessSid },
1265 { SDDL_ANONYMOUS, WinAnonymousSid },
1266 { SDDL_AUTHENTICATED_USERS, WinAuthenticatedUserSid },
1267 { SDDL_BUILTIN_ADMINISTRATORS, WinBuiltinAdministratorsSid },
1268 { SDDL_BUILTIN_GUESTS, WinBuiltinGuestsSid },
1269 { SDDL_BACKUP_OPERATORS, WinBuiltinBackupOperatorsSid },
1270 { SDDL_BUILTIN_USERS, WinBuiltinUsersSid },
1271 { SDDL_CERT_SERV_ADMINISTRATORS, WinAccountCertAdminsSid /* FIXME: DOMAIN_GROUP_RID_CERT_ADMINS */ },
1272 { SDDL_CREATOR_GROUP, WinCreatorGroupSid },
1273 { SDDL_CREATOR_OWNER, WinCreatorOwnerSid },
1274 { SDDL_DOMAIN_ADMINISTRATORS, WinAccountDomainAdminsSid /* FIXME: DOMAIN_GROUP_RID_ADMINS */ },
1275 { SDDL_DOMAIN_COMPUTERS, WinAccountComputersSid /* FIXME: DOMAIN_GROUP_RID_COMPUTERS */ },
1276 { SDDL_DOMAIN_DOMAIN_CONTROLLERS, WinAccountControllersSid /* FIXME: DOMAIN_GROUP_RID_CONTROLLERS */ },
1277 { SDDL_DOMAIN_GUESTS, WinAccountDomainGuestsSid /* FIXME: DOMAIN_GROUP_RID_GUESTS */ },
1278 { SDDL_DOMAIN_USERS, WinAccountDomainUsersSid /* FIXME: DOMAIN_GROUP_RID_USERS */ },
1279 { SDDL_ENTERPRISE_ADMINS, WinAccountEnterpriseAdminsSid /* FIXME: DOMAIN_GROUP_RID_ENTERPRISE_ADMINS */ },
1280 { SDDL_ENTERPRISE_DOMAIN_CONTROLLERS, WinLogonIdsSid /* FIXME: SECURITY_SERVER_LOGON_RID */ },
1281 { SDDL_EVERYONE, WinWorldSid },
1282 { SDDL_GROUP_POLICY_ADMINS, WinAccountPolicyAdminsSid /* FIXME: DOMAIN_GROUP_RID_POLICY_ADMINS */ },
1283 { SDDL_INTERACTIVE, WinInteractiveSid },
1284 { SDDL_LOCAL_ADMIN, WinAccountAdministratorSid /* FIXME: DOMAIN_USER_RID_ADMIN */ },
1285 { SDDL_LOCAL_GUEST, WinAccountGuestSid /* FIXME: DOMAIN_USER_RID_GUEST */ },
1286 { SDDL_LOCAL_SERVICE, WinLocalServiceSid },
1287 { SDDL_LOCAL_SYSTEM, WinLocalSystemSid },
1288 { SDDL_NETWORK, WinNetworkSid },
1289 { SDDL_NETWORK_CONFIGURATION_OPS, WinBuiltinNetworkConfigurationOperatorsSid },
1290 { SDDL_NETWORK_SERVICE, WinNetworkServiceSid },
1291 { SDDL_PRINTER_OPERATORS, WinBuiltinPrintOperatorsSid },
1292 { SDDL_PERSONAL_SELF, WinSelfSid },
1293 { SDDL_POWER_USERS, WinBuiltinPowerUsersSid },
1294 { SDDL_RAS_SERVERS, WinAccountRasAndIasServersSid /* FIXME: DOMAIN_ALIAS_RID_RAS_SERVERS */ },
1295 { SDDL_REMOTE_DESKTOP, WinBuiltinRemoteDesktopUsersSid },
1296 { SDDL_REPLICATOR, WinBuiltinReplicatorSid },
1297 { SDDL_RESTRICTED_CODE, WinRestrictedCodeSid },
1298 { SDDL_SCHEMA_ADMINISTRATORS, WinAccountSchemaAdminsSid /* FIXME: DOMAIN_GROUP_RID_SCHEMA_ADMINS */ },
1299 { SDDL_SERVER_OPERATORS, WinBuiltinSystemOperatorsSid },
1300 { SDDL_SERVICE, WinServiceSid },
1301 { NULL, 0 },
1302 };
1303
1304 /*
1305 * @implemented
1306 */
1307 BOOL WINAPI
1308 ConvertStringSidToSidW(IN LPCWSTR StringSid,
1309 OUT PSID* sid)
1310 {
1311 DWORD size;
1312 DWORD i, cBytes, identAuth, csubauth;
1313 BOOL ret;
1314 SID* pisid;
1315
1316 TRACE("%s %p\n", debugstr_w(StringSid), sid);
1317
1318 if (!StringSid)
1319 {
1320 SetLastError(ERROR_INVALID_SID);
1321 return FALSE;
1322 }
1323 for (i = 0; i < sizeof(SidTable) / sizeof(SidTable[0]) - 1; i++)
1324 {
1325 if (wcscmp(StringSid, SidTable[i].key) == 0)
1326 {
1327 WELL_KNOWN_SID_TYPE knownSid = (WELL_KNOWN_SID_TYPE)SidTable[i].value;
1328 size = SECURITY_MAX_SID_SIZE;
1329 *sid = LocalAlloc(0, size);
1330 if (!*sid)
1331 {
1332 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1333 return FALSE;
1334 }
1335 ret = CreateWellKnownSid(
1336 knownSid,
1337 NULL,
1338 *sid,
1339 &size);
1340 if (!ret)
1341 {
1342 SetLastError(ERROR_INVALID_SID);
1343 LocalFree(*sid);
1344 }
1345 return ret;
1346 }
1347 }
1348
1349 /* That's probably a string S-R-I-S-S... */
1350 if (StringSid[0] != 'S' || StringSid[1] != '-')
1351 {
1352 SetLastError(ERROR_INVALID_SID);
1353 return FALSE;
1354 }
1355
1356 cBytes = ComputeStringSidSize(StringSid);
1357 pisid = (SID*)LocalAlloc( 0, cBytes );
1358 if (!pisid)
1359 {
1360 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1361 return FALSE;
1362 }
1363 i = 0;
1364 ret = FALSE;
1365 csubauth = ((cBytes - sizeof(SID)) / sizeof(DWORD)) + 1;
1366
1367 StringSid += 2; /* Advance to Revision */
1368 pisid->Revision = atoiW(StringSid);
1369
1370 if (pisid->Revision != SDDL_REVISION)
1371 {
1372 TRACE("Revision %d is unknown\n", pisid->Revision);
1373 goto lend; /* ERROR_INVALID_SID */
1374 }
1375 if (csubauth == 0)
1376 {
1377 TRACE("SubAuthorityCount is 0\n");
1378 goto lend; /* ERROR_INVALID_SID */
1379 }
1380
1381 pisid->SubAuthorityCount = csubauth;
1382
1383 /* Advance to identifier authority */
1384 while (*StringSid && *StringSid != '-')
1385 StringSid++;
1386 if (*StringSid == '-')
1387 StringSid++;
1388
1389 /* MS' implementation can't handle values greater than 2^32 - 1, so
1390 * we don't either; assume most significant bytes are always 0
1391 */
1392 pisid->IdentifierAuthority.Value[0] = 0;
1393 pisid->IdentifierAuthority.Value[1] = 0;
1394 identAuth = atoiW(StringSid);
1395 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
1396 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
1397 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
1398 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
1399
1400 /* Advance to first sub authority */
1401 while (*StringSid && *StringSid != '-')
1402 StringSid++;
1403 if (*StringSid == '-')
1404 StringSid++;
1405
1406 while (*StringSid)
1407 {
1408 while (*StringSid && *StringSid != '-')
1409 StringSid++;
1410 if (*StringSid == '-')
1411 StringSid++;
1412
1413 pisid->SubAuthority[i++] = atoiW(StringSid);
1414 }
1415
1416 if (i != pisid->SubAuthorityCount)
1417 goto lend; /* ERROR_INVALID_SID */
1418
1419 *sid = pisid;
1420 ret = TRUE;
1421
1422 lend:
1423 if (!ret)
1424 SetLastError(ERROR_INVALID_SID);
1425
1426 TRACE("returning %s\n", ret ? "TRUE" : "FALSE");
1427 return ret;
1428 }
1429
1430
1431 /* EOF */