2 * COPYRIGHT: See COPYING in the top level directory
4 * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
6 * Copyright 2006 Hervé Poussineau
8 * PROJECT: ReactOS system libraries
9 * FILE: lib/advapi32/sec/sid.c
10 * PURPOSE: Security ID functions
15 #include <wine/debug.h>
16 #include <wine/unicode.h>
18 WINE_DEFAULT_DEBUG_CHANNEL(advapi
);
20 #define MAX_GUID_STRING_LEN 39
29 typedef struct _MAX_SID
31 /* same fields as struct _SID */
33 BYTE SubAuthorityCount
;
34 SID_IDENTIFIER_AUTHORITY IdentifierAuthority
;
35 DWORD SubAuthority
[SID_MAX_SUB_AUTHORITIES
];
38 typedef struct WELLKNOWNSID
41 WELL_KNOWN_SID_TYPE Type
;
45 static const WELLKNOWNSID WellKnownSids
[] =
47 { {0,0}, WinNullSid
, { SID_REVISION
, 1, { SECURITY_NULL_SID_AUTHORITY
}, { SECURITY_NULL_RID
} } },
48 { {'W','D'}, WinWorldSid
, { SID_REVISION
, 1, { SECURITY_WORLD_SID_AUTHORITY
}, { SECURITY_WORLD_RID
} } },
49 { {0,0}, WinLocalSid
, { SID_REVISION
, 1, { SECURITY_LOCAL_SID_AUTHORITY
}, { SECURITY_LOCAL_RID
} } },
50 { {'C','O'}, WinCreatorOwnerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_RID
} } },
51 { {'C','G'}, WinCreatorGroupSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_GROUP_RID
} } },
52 { {0,0}, WinCreatorOwnerServerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_SERVER_RID
} } },
53 { {0,0}, WinCreatorGroupServerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_GROUP_SERVER_RID
} } },
54 { {0,0}, WinNtAuthoritySid
, { SID_REVISION
, 0, { SECURITY_NT_AUTHORITY
}, { } } },
55 { {0,0}, WinDialupSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_DIALUP_RID
} } },
56 { {'N','U'}, WinNetworkSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_NETWORK_RID
} } },
57 { {0,0}, WinBatchSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_BATCH_RID
} } },
58 { {'I','U'}, WinInteractiveSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_INTERACTIVE_RID
} } },
59 { {'S','U'}, WinServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_SERVICE_RID
} } },
60 { {'A','N'}, WinAnonymousSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_ANONYMOUS_LOGON_RID
} } },
61 { {0,0}, WinProxySid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_PROXY_RID
} } },
62 { {'E','D'}, WinEnterpriseControllersSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_ENTERPRISE_CONTROLLERS_RID
} } },
63 { {'P','S'}, WinSelfSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_PRINCIPAL_SELF_RID
} } },
64 { {'A','U'}, WinAuthenticatedUserSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_AUTHENTICATED_USER_RID
} } },
65 { {'R','C'}, WinRestrictedCodeSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_RESTRICTED_CODE_RID
} } },
66 { {0,0}, WinTerminalServerSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_TERMINAL_SERVER_RID
} } },
67 { {0,0}, WinRemoteLogonIdSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_REMOTE_LOGON_RID
} } },
68 { {'S','Y'}, WinLocalSystemSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOCAL_SYSTEM_RID
} } },
69 { {'L','S'}, WinLocalServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOCAL_SERVICE_RID
} } },
70 { {'N','S'}, WinNetworkServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_NETWORK_SERVICE_RID
} } },
71 { {0,0}, WinBuiltinDomainSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
} } },
72 { {'B','A'}, WinBuiltinAdministratorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ADMINS
} } },
73 { {'B','U'}, WinBuiltinUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_USERS
} } },
74 { {'B','G'}, WinBuiltinGuestsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_GUESTS
} } },
75 { {'P','U'}, WinBuiltinPowerUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_POWER_USERS
} } },
76 { {'A','O'}, WinBuiltinAccountOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ACCOUNT_OPS
} } },
77 { {'S','O'}, WinBuiltinSystemOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_SYSTEM_OPS
} } },
78 { {'P','O'}, WinBuiltinPrintOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_PRINT_OPS
} } },
79 { {'B','O'}, WinBuiltinBackupOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_BACKUP_OPS
} } },
80 { {'R','E'}, WinBuiltinReplicatorSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_REPLICATOR
} } },
81 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS
} } },
82 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS
} } },
83 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS
} } },
86 static const SID sidWorld
= { SID_REVISION
, 1, { SECURITY_WORLD_SID_AUTHORITY
} , { SECURITY_WORLD_RID
} };
91 static const WCHAR SDDL_ACCESS_ALLOWED
[] = {'A',0};
92 static const WCHAR SDDL_ACCESS_DENIED
[] = {'D',0};
93 static const WCHAR SDDL_OBJECT_ACCESS_ALLOWED
[] = {'O','A',0};
94 static const WCHAR SDDL_OBJECT_ACCESS_DENIED
[] = {'O','D',0};
95 static const WCHAR SDDL_AUDIT
[] = {'A','U',0};
96 static const WCHAR SDDL_ALARM
[] = {'A','L',0};
97 static const WCHAR SDDL_OBJECT_AUDIT
[] = {'O','U',0};
98 static const WCHAR SDDL_OBJECT_ALARM
[] = {'O','L',0};
103 #define ADS_RIGHT_DS_CREATE_CHILD 0x0001
104 #define ADS_RIGHT_DS_DELETE_CHILD 0x0002
105 #define ADS_RIGHT_ACTRL_DS_LIST 0x0004
106 #define ADS_RIGHT_DS_SELF 0x0008
107 #define ADS_RIGHT_DS_READ_PROP 0x0010
108 #define ADS_RIGHT_DS_WRITE_PROP 0x0020
109 #define ADS_RIGHT_DS_DELETE_TREE 0x0040
110 #define ADS_RIGHT_DS_LIST_OBJECT 0x0080
111 #define ADS_RIGHT_DS_CONTROL_ACCESS 0x0100
116 static const WCHAR SDDL_CONTAINER_INHERIT
[] = {'C','I',0};
117 static const WCHAR SDDL_OBJECT_INHERIT
[] = {'O','I',0};
118 static const WCHAR SDDL_NO_PROPAGATE
[] = {'N','P',0};
119 static const WCHAR SDDL_INHERIT_ONLY
[] = {'I','O',0};
120 static const WCHAR SDDL_INHERITED
[] = {'I','D',0};
121 static const WCHAR SDDL_AUDIT_SUCCESS
[] = {'S','A',0};
122 static const WCHAR SDDL_AUDIT_FAILURE
[] = {'F','A',0};
124 static const char * debugstr_sid(PSID sid
)
127 SID
* psid
= (SID
*)sid
;
132 auth
= psid
->IdentifierAuthority
.Value
[5] +
133 (psid
->IdentifierAuthority
.Value
[4] << 8) +
134 (psid
->IdentifierAuthority
.Value
[3] << 16) +
135 (psid
->IdentifierAuthority
.Value
[2] << 24);
137 switch (psid
->SubAuthorityCount
) {
139 return wine_dbg_sprintf("S-%d-%d", psid
->Revision
, auth
);
141 return wine_dbg_sprintf("S-%d-%d-%lu", psid
->Revision
, auth
,
142 psid
->SubAuthority
[0]);
144 return wine_dbg_sprintf("S-%d-%d-%lu-%lu", psid
->Revision
, auth
,
145 psid
->SubAuthority
[0], psid
->SubAuthority
[1]);
147 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu", psid
->Revision
, auth
,
148 psid
->SubAuthority
[0], psid
->SubAuthority
[1], psid
->SubAuthority
[2]);
150 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu", psid
->Revision
, auth
,
151 psid
->SubAuthority
[0], psid
->SubAuthority
[1], psid
->SubAuthority
[2],
152 psid
->SubAuthority
[3]);
154 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu", psid
->Revision
, auth
,
155 psid
->SubAuthority
[0], psid
->SubAuthority
[1], psid
->SubAuthority
[2],
156 psid
->SubAuthority
[3], psid
->SubAuthority
[4]);
158 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu", psid
->Revision
, auth
,
159 psid
->SubAuthority
[3], psid
->SubAuthority
[1], psid
->SubAuthority
[2],
160 psid
->SubAuthority
[0], psid
->SubAuthority
[4], psid
->SubAuthority
[5]);
162 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid
->Revision
, auth
,
163 psid
->SubAuthority
[0], psid
->SubAuthority
[1], psid
->SubAuthority
[2],
164 psid
->SubAuthority
[3], psid
->SubAuthority
[4], psid
->SubAuthority
[5],
165 psid
->SubAuthority
[6]);
167 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid
->Revision
, auth
,
168 psid
->SubAuthority
[0], psid
->SubAuthority
[1], psid
->SubAuthority
[2],
169 psid
->SubAuthority
[3], psid
->SubAuthority
[4], psid
->SubAuthority
[5],
170 psid
->SubAuthority
[6], psid
->SubAuthority
[7]);
175 /* set last error code from NT status and get the proper boolean return value */
176 /* used for functions that are a simple wrapper around the corresponding ntdll API */
177 static __inline BOOL
set_ntstatus( NTSTATUS status
)
179 if (status
) SetLastError( RtlNtStatusToDosError( status
));
185 IN
const RECORD
* Table
,
187 OUT SIZE_T
* pKeyLength
,
190 const RECORD
* pRecord
= Table
;
191 while (pRecord
->key
!= NULL
)
193 if (wcsncmp(pRecord
->key
, Key
, wcslen(pRecord
->key
)) == 0)
195 *pKeyLength
= wcslen(pRecord
->key
);
196 *pItem
= pRecord
->value
;
201 SetLastError(ERROR_INVALID_PARAMETER
);
211 WCHAR str
[SDDL_ALIAS_SIZE
+ 1];
217 wcsncpy(str
, Buffer
, SDDL_ALIAS_SIZE
);
218 for (i
= SDDL_ALIAS_SIZE
; i
> 0; i
--)
220 str
[i
] = UNICODE_NULL
;
221 if (ConvertStringSidToSidW(str
, pSid
))
228 end
= wcschr(Buffer
, SDDL_ACE_ENDC
);
231 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
234 strSid
= (LPWSTR
)LocalAlloc(0, (end
- Buffer
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
237 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
240 wcsncpy(strSid
, Buffer
, end
- Buffer
+ 1);
241 strSid
[end
- Buffer
] = UNICODE_NULL
;
242 *pLength
= end
- Buffer
;
243 ret
= ConvertStringSidToSidW(strSid
, pSid
);
248 static const RECORD DaclFlagTable
[] =
250 { SDDL_PROTECTED
, SE_DACL_PROTECTED
},
251 { SDDL_AUTO_INHERIT_REQ
, SE_DACL_AUTO_INHERIT_REQ
},
252 { SDDL_AUTO_INHERITED
, SE_DACL_AUTO_INHERITED
},
256 static const RECORD SaclFlagTable
[] =
258 { SDDL_PROTECTED
, SE_SACL_PROTECTED
},
259 { SDDL_AUTO_INHERIT_REQ
, SE_SACL_AUTO_INHERIT_REQ
},
260 { SDDL_AUTO_INHERITED
, SE_SACL_AUTO_INHERITED
},
264 static const RECORD AceFlagTable
[] =
266 { SDDL_CONTAINER_INHERIT
, CONTAINER_INHERIT_ACE
},
267 { SDDL_OBJECT_INHERIT
, OBJECT_INHERIT_ACE
},
268 { SDDL_NO_PROPAGATE
, NO_PROPAGATE_INHERIT_ACE
},
269 { SDDL_INHERIT_ONLY
, INHERIT_ONLY_ACE
},
270 { SDDL_INHERITED
, INHERITED_ACE
},
271 { SDDL_AUDIT_SUCCESS
, SUCCESSFUL_ACCESS_ACE_FLAG
},
272 { SDDL_AUDIT_FAILURE
, FAILED_ACCESS_ACE_FLAG
},
279 IN
const RECORD
* FlagTable
,
284 LPCWSTR ptr
= Buffer
;
285 SIZE_T PartialLength
;
289 while (*ptr
!= LimitChar
)
291 if (!FindKeyInTable(FlagTable
, ptr
, &PartialLength
, &Flag
))
294 ptr
+= PartialLength
;
296 *pLength
= ptr
- Buffer
;
300 static const RECORD AccessMaskTable
[] =
302 { SDDL_GENERIC_ALL
, GENERIC_ALL
},
303 { SDDL_GENERIC_READ
, GENERIC_READ
},
304 { SDDL_GENERIC_WRITE
, GENERIC_WRITE
},
305 { SDDL_GENERIC_EXECUTE
, GENERIC_EXECUTE
},
306 { SDDL_READ_CONTROL
, READ_CONTROL
},
307 { SDDL_STANDARD_DELETE
, DELETE
},
308 { SDDL_WRITE_DAC
, WRITE_DAC
},
309 { SDDL_WRITE_OWNER
, WRITE_OWNER
},
310 { SDDL_READ_PROPERTY
, ADS_RIGHT_DS_READ_PROP
},
311 { SDDL_WRITE_PROPERTY
, ADS_RIGHT_DS_WRITE_PROP
},
312 { SDDL_CREATE_CHILD
, ADS_RIGHT_DS_CREATE_CHILD
},
313 { SDDL_DELETE_CHILD
, ADS_RIGHT_DS_DELETE_CHILD
},
314 { SDDL_LIST_CHILDREN
, ADS_RIGHT_ACTRL_DS_LIST
},
315 { SDDL_SELF_WRITE
, ADS_RIGHT_DS_SELF
},
316 { SDDL_LIST_OBJECT
, ADS_RIGHT_DS_LIST_OBJECT
},
317 { SDDL_DELETE_TREE
, ADS_RIGHT_DS_DELETE_TREE
},
318 { SDDL_CONTROL_ACCESS
, ADS_RIGHT_DS_CONTROL_ACCESS
},
319 { SDDL_FILE_ALL
, FILE_ALL_ACCESS
},
320 { SDDL_FILE_READ
, FILE_GENERIC_READ
},
321 { SDDL_FILE_WRITE
, FILE_GENERIC_WRITE
},
322 { SDDL_FILE_EXECUTE
, FILE_GENERIC_EXECUTE
},
323 { SDDL_KEY_ALL
, KEY_ALL_ACCESS
},
324 { SDDL_KEY_READ
, KEY_READ
},
325 { SDDL_KEY_WRITE
, KEY_WRITE
},
326 { SDDL_KEY_EXECUTE
, KEY_EXECUTE
},
331 ParseAccessMaskString(
333 OUT DWORD
* pAccessMask
,
336 /* FIXME: Allow hexadecimal string for access rights! */
338 return ParseFlagsString(Buffer
, AccessMaskTable
, SDDL_SEPERATORC
, pAccessMask
, pLength
);
345 OUT BOOL
* pIsGuidValid
,
348 WCHAR GuidStr
[MAX_GUID_STRING_LEN
+ 1];
351 end
= wcschr(Buffer
, SDDL_SEPERATORC
);
354 SetLastError(ERROR_INVALID_PARAMETER
);
358 *pLength
= end
- Buffer
;
359 *pIsGuidValid
= (end
!= Buffer
);
363 if (end
- Buffer
> MAX_GUID_STRING_LEN
- 1)
365 SetLastError(ERROR_INVALID_PARAMETER
);
368 GuidStr
[end
- Buffer
] = UNICODE_NULL
;
369 wcsncpy(GuidStr
, Buffer
, end
- Buffer
);
370 if (RPC_S_OK
!= UuidFromStringW((unsigned short*)&GuidStr
, pGuid
))
372 SetLastError(ERROR_INVALID_PARAMETER
);
378 static const RECORD AceTypeTable
[] =
380 { SDDL_OBJECT_ACCESS_ALLOWED
, ACCESS_ALLOWED_OBJECT_ACE_TYPE
},
381 { SDDL_OBJECT_ACCESS_DENIED
, ACCESS_DENIED_OBJECT_ACE_TYPE
},
382 { SDDL_AUDIT
, SYSTEM_AUDIT_ACE_TYPE
},
383 { SDDL_ALARM
, SYSTEM_ALARM_ACE_TYPE
},
384 { SDDL_OBJECT_AUDIT
, SYSTEM_AUDIT_OBJECT_ACE_TYPE
},
385 { SDDL_OBJECT_ALARM
, SYSTEM_ALARM_OBJECT_ACE_TYPE
},
386 { SDDL_ACCESS_ALLOWED
, ACCESS_ALLOWED_ACE_TYPE
},
387 { SDDL_ACCESS_DENIED
, ACCESS_DENIED_ACE_TYPE
},
397 LPCWSTR ptr
= Buffer
;
398 SIZE_T PartialLength
;
399 DWORD aceType
, aceFlags
, accessMask
;
400 GUID object
, inheritObject
;
401 BOOL objectValid
, inheritObjectValid
;
405 if (*ptr
!= SDDL_ACE_BEGINC
)
407 SetLastError(ERROR_INVALID_PARAMETER
);
410 ptr
++; /* Skip SDDL_ACE_BEGINC */
412 if (!FindKeyInTable(AceTypeTable
, ptr
, &PartialLength
, &aceType
))
414 ptr
+= PartialLength
;
416 if (*ptr
!= SDDL_SEPERATORC
)
418 SetLastError(ERROR_INVALID_PARAMETER
);
421 ptr
++; /* Skip SDDL_SEPERATORC */
423 if (!ParseFlagsString(ptr
, AceFlagTable
, SDDL_SEPERATORC
, &aceFlags
, &PartialLength
))
425 ptr
+= PartialLength
+ 1;
427 if (!ParseAccessMaskString(ptr
, &accessMask
, &PartialLength
))
429 ptr
+= PartialLength
+ 1;
431 if (!ParseGuidString(ptr
, &object
, &objectValid
, &PartialLength
))
433 ptr
+= PartialLength
+ 1;
435 if (!ParseGuidString(ptr
, &inheritObject
, &inheritObjectValid
, &PartialLength
))
437 ptr
+= PartialLength
+ 1;
439 if (!ParseSidString(ptr
, &sid
, &PartialLength
))
441 ptr
+= PartialLength
;
442 if (*ptr
!= SDDL_ACE_ENDC
)
444 SetLastError(ERROR_INVALID_PARAMETER
);
447 ptr
++; /* Skip SDDL_ACE_ENDC */
448 *pLength
= ptr
- Buffer
;
452 case ACCESS_ALLOWED_ACE_TYPE
:
453 ret
= AddAccessAllowedAceEx(
460 case ACCESS_ALLOWED_OBJECT_ACE_TYPE
:
461 ret
= AddAccessAllowedObjectAce(
466 objectValid
? &object
: NULL
,
467 inheritObjectValid
? &inheritObject
: NULL
,
470 case ACCESS_DENIED_ACE_TYPE
:
471 ret
= AddAccessDeniedAceEx(
478 case ACCESS_DENIED_OBJECT_ACE_TYPE
:
479 ret
= AddAccessDeniedObjectAce(
484 objectValid
? &object
: NULL
,
485 inheritObjectValid
? &inheritObject
: NULL
,
488 case SYSTEM_AUDIT_ACE_TYPE
:
489 ret
= AddAuditAccessAceEx(
498 case SYSTEM_AUDIT_OBJECT_ACE_TYPE
:
499 ret
= AddAuditAccessObjectAce(
504 objectValid
? &object
: NULL
,
505 inheritObjectValid
? &inheritObject
: NULL
,
510 case SYSTEM_ALARM_ACE_TYPE
:
511 case SYSTEM_ALARM_OBJECT_ACE_TYPE
:
514 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
522 /* Exported functions */
528 AllocateLocallyUniqueId(PLUID Luid
)
532 Status
= NtAllocateLocallyUniqueId (Luid
);
533 if (!NT_SUCCESS (Status
))
535 SetLastError (RtlNtStatusToDosError (Status
));
547 AllocateAndInitializeSid (PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority
,
548 BYTE nSubAuthorityCount
,
549 DWORD dwSubAuthority0
,
550 DWORD dwSubAuthority1
,
551 DWORD dwSubAuthority2
,
552 DWORD dwSubAuthority3
,
553 DWORD dwSubAuthority4
,
554 DWORD dwSubAuthority5
,
555 DWORD dwSubAuthority6
,
556 DWORD dwSubAuthority7
,
561 Status
= RtlAllocateAndInitializeSid (pIdentifierAuthority
,
572 if (!NT_SUCCESS (Status
))
574 SetLastError (RtlNtStatusToDosError (Status
));
586 CopySid (DWORD nDestinationSidLength
,
587 PSID pDestinationSid
,
592 Status
= RtlCopySid (nDestinationSidLength
,
595 if (!NT_SUCCESS (Status
))
597 SetLastError (RtlNtStatusToDosError (Status
));
603 /******************************************************************************
604 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
608 ConvertStringSecurityDescriptorToSecurityDescriptorW(
609 IN LPCWSTR StringSecurityDescriptor
,
610 IN DWORD StringSDRevision
,
611 OUT PSECURITY_DESCRIPTOR
* SecurityDescriptor
,
612 OUT PULONG SecurityDescriptorSize
)
614 PSECURITY_DESCRIPTOR sd
= NULL
;
617 if (!StringSecurityDescriptor
)
618 SetLastError(ERROR_INVALID_PARAMETER
);
619 else if (StringSDRevision
!= SDDL_REVISION_1
)
620 SetLastError(ERROR_INVALID_PARAMETER
);
623 LPCWSTR ptr
= StringSecurityDescriptor
;
624 DWORD numberOfAces
= 0;
625 DWORD relativeSdSize
;
627 PSECURITY_DESCRIPTOR relativeSd
= NULL
;
631 /* An easy way to know how much space we need for an ACL is to count
632 * the number of ACEs and say that we have 1 SID by ACE
634 ptr
= wcschr(StringSecurityDescriptor
, SDDL_ACE_BEGINC
);
638 ptr
= wcschr(ptr
+ 1, SDDL_ACE_BEGINC
);
640 MaxAclSize
= sizeof(ACL
) + numberOfAces
*
641 (sizeof(ACCESS_ALLOWED_OBJECT_ACE
) + SECURITY_MAX_SID_SIZE
);
643 sd
= (SECURITY_DESCRIPTOR
*)LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR
));
646 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
649 ret
= InitializeSecurityDescriptor(sd
, SECURITY_DESCRIPTOR_REVISION
);
653 /* Now, really parse the string */
654 ptr
= StringSecurityDescriptor
;
657 if (ptr
[1] != SDDL_DELIMINATORC
)
659 SetLastError(ERROR_INVALID_PARAMETER
);
672 ret
= ParseSidString(ptr
, &pSid
, &Length
);
676 ret
= SetSecurityDescriptorOwner(sd
, pSid
, FALSE
);
678 ret
= SetSecurityDescriptorGroup(sd
, pSid
, FALSE
);
692 BOOL isDacl
= (ptr
[-2] == 'D');
695 ret
= ParseFlagsString(ptr
, DaclFlagTable
, SDDL_ACE_BEGINC
, &aclFlags
, &Length
);
697 ret
= ParseFlagsString(ptr
, SaclFlagTable
, SDDL_ACE_BEGINC
, &aclFlags
, &Length
);
700 pAcl
= (PACL
)LocalAlloc(0, MaxAclSize
);
703 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
707 if (!InitializeAcl(pAcl
, (DWORD
)MaxAclSize
, ACL_REVISION_DS
))
714 ret
= SetSecurityDescriptorControl(
716 (SECURITY_DESCRIPTOR_CONTROL
)aclFlags
,
717 (SECURITY_DESCRIPTOR_CONTROL
)aclFlags
);
725 while (*ptr
== SDDL_ACE_BEGINC
)
727 ret
= ParseAceString(ptr
, pAcl
, &Length
);
736 ret
= SetSecurityDescriptorDacl(sd
, TRUE
, pAcl
, FALSE
);
738 ret
= SetSecurityDescriptorSacl(sd
, TRUE
, pAcl
, FALSE
);
748 SetLastError(ERROR_INVALID_PARAMETER
);
759 LocalFree(relativeSd
);
760 relativeSd
= LocalAlloc(0, relativeSdSize
);
763 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
766 ret
= MakeSelfRelativeSD(sd
, relativeSd
, &relativeSdSize
);
767 if (ret
|| GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
770 if (SecurityDescriptorSize
)
771 *SecurityDescriptorSize
= relativeSdSize
;
772 *SecurityDescriptor
= relativeSd
;
775 if (GetSecurityDescriptorOwner(sd
, &pSid
, &dummy
))
777 if (GetSecurityDescriptorGroup(sd
, &pSid
, &dummy
))
779 if (GetSecurityDescriptorDacl(sd
, &present
, &pAcl
, &dummy
) && present
)
781 if (GetSecurityDescriptorSacl(sd
, &present
, &pAcl
, &dummy
) && present
)
789 /* Winehq cvs 20050916 */
790 /******************************************************************************
791 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
794 BOOL WINAPI
ConvertStringSecurityDescriptorToSecurityDescriptorA(
795 LPCSTR StringSecurityDescriptor
,
796 DWORD StringSDRevision
,
797 PSECURITY_DESCRIPTOR
* SecurityDescriptor
,
798 PULONG SecurityDescriptorSize
)
802 LPWSTR StringSecurityDescriptorW
;
804 len
= MultiByteToWideChar(CP_ACP
, 0, StringSecurityDescriptor
, -1, NULL
, 0);
805 StringSecurityDescriptorW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
807 if (StringSecurityDescriptorW
)
809 MultiByteToWideChar(CP_ACP
, 0, StringSecurityDescriptor
, -1, StringSecurityDescriptorW
, len
);
811 ret
= ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW
,
812 StringSDRevision
, SecurityDescriptor
,
813 SecurityDescriptorSize
);
814 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW
);
824 EqualPrefixSid (PSID pSid1
,
827 return RtlEqualPrefixSid (pSid1
, pSid2
);
835 EqualSid (PSID pSid1
,
838 return RtlEqualSid (pSid1
, pSid2
);
846 * Docs says this function does NOT return a value
847 * even thou it's defined to return a PVOID...
852 return RtlFreeSid (pSid
);
860 GetLengthSid (PSID pSid
)
862 return (DWORD
)RtlLengthSid (pSid
);
869 PSID_IDENTIFIER_AUTHORITY STDCALL
870 GetSidIdentifierAuthority (PSID pSid
)
872 return RtlIdentifierAuthoritySid (pSid
);
880 GetSidLengthRequired (UCHAR nSubAuthorityCount
)
882 return (DWORD
)RtlLengthRequiredSid (nSubAuthorityCount
);
890 GetSidSubAuthority (PSID pSid
,
893 return (PDWORD
)RtlSubAuthoritySid (pSid
, nSubAuthority
);
901 GetSidSubAuthorityCount (PSID pSid
)
903 return RtlSubAuthorityCountSid (pSid
);
911 InitializeSid (PSID Sid
,
912 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority
,
913 BYTE nSubAuthorityCount
)
917 Status
= RtlInitializeSid (Sid
,
918 pIdentifierAuthority
,
920 if (!NT_SUCCESS (Status
))
922 SetLastError (RtlNtStatusToDosError (Status
));
934 IsValidSid (PSID pSid
)
936 return (BOOL
)RtlValidSid (pSid
);
943 ConvertSidToStringSidW(PSID Sid
, LPWSTR
*StringSid
)
946 UNICODE_STRING UnicodeString
;
947 WCHAR FixedBuffer
[64];
949 if (! RtlValidSid(Sid
))
951 SetLastError(ERROR_INVALID_SID
);
955 UnicodeString
.Length
= 0;
956 UnicodeString
.MaximumLength
= sizeof(FixedBuffer
);
957 UnicodeString
.Buffer
= FixedBuffer
;
958 Status
= RtlConvertSidToUnicodeString(&UnicodeString
, Sid
, FALSE
);
959 if (STATUS_BUFFER_TOO_SMALL
== Status
)
961 Status
= RtlConvertSidToUnicodeString(&UnicodeString
, Sid
, TRUE
);
963 if (! NT_SUCCESS(Status
))
965 SetLastError(RtlNtStatusToDosError(Status
));
969 *StringSid
= LocalAlloc(LMEM_FIXED
, UnicodeString
.Length
+ sizeof(WCHAR
));
970 if (NULL
== *StringSid
)
972 if (UnicodeString
.Buffer
!= FixedBuffer
)
974 RtlFreeUnicodeString(&UnicodeString
);
976 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
980 MoveMemory(*StringSid
, UnicodeString
.Buffer
, UnicodeString
.Length
);
981 ZeroMemory((PCHAR
) *StringSid
+ UnicodeString
.Length
, sizeof(WCHAR
));
982 if (UnicodeString
.Buffer
!= FixedBuffer
)
984 RtlFreeUnicodeString(&UnicodeString
);
995 ConvertSidToStringSidA(PSID Sid
, LPSTR
*StringSid
)
1000 if (! ConvertSidToStringSidW(Sid
, &StringSidW
))
1005 Len
= WideCharToMultiByte(CP_ACP
, 0, StringSidW
, -1, NULL
, 0, NULL
, NULL
);
1008 LocalFree(StringSidW
);
1009 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1012 *StringSid
= LocalAlloc(LMEM_FIXED
, Len
);
1013 if (NULL
== *StringSid
)
1015 LocalFree(StringSidW
);
1016 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1020 if (! WideCharToMultiByte(CP_ACP
, 0, StringSidW
, -1, *StringSid
, Len
, NULL
, NULL
))
1022 LocalFree(StringSid
);
1023 LocalFree(StringSidW
);
1027 LocalFree(StringSidW
);
1037 EqualDomainSid(IN PSID pSid1
,
1041 FIXME("%s() not implemented!\n", __FUNCTION__
);
1050 GetWindowsAccountDomainSid(IN PSID pSid
,
1051 OUT PSID ppDomainSid
,
1052 IN OUT DWORD
* cbSid
)
1054 FIXME("%s() not implemented!\n", __FUNCTION__
);
1063 CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType
,
1064 IN PSID DomainSid OPTIONAL
,
1066 IN OUT DWORD
* cbSid
)
1069 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType
, debugstr_sid(DomainSid
), pSid
, cbSid
);
1071 if (DomainSid
!= NULL
) {
1072 FIXME("Only local computer supported!\n");
1073 SetLastError(ERROR_INVALID_PARAMETER
); /* FIXME */
1077 if (cbSid
== NULL
|| pSid
== NULL
) {
1078 SetLastError(ERROR_INVALID_PARAMETER
);
1082 for (i
= 0; i
< sizeof(WellKnownSids
)/sizeof(WellKnownSids
[0]); i
++) {
1083 if (WellKnownSids
[i
].Type
== WellKnownSidType
) {
1084 DWORD length
= GetSidLengthRequired(WellKnownSids
[i
].Sid
.SubAuthorityCount
);
1086 if (*cbSid
< length
) {
1087 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1091 CopyMemory(pSid
, &WellKnownSids
[i
].Sid
.Revision
, length
);
1097 SetLastError(ERROR_INVALID_PARAMETER
);
1106 IsWellKnownSid(IN PSID pSid
,
1107 IN WELL_KNOWN_SID_TYPE WellKnownSidType
)
1110 TRACE("(%s, %d)\n", debugstr_sid(pSid
), WellKnownSidType
);
1112 for (i
= 0; i
< sizeof(WellKnownSids
)/sizeof(WellKnownSids
[0]); i
++)
1113 if (WellKnownSids
[i
].Type
== WellKnownSidType
)
1114 if (EqualSid(pSid
, (PSID
)&(WellKnownSids
[i
].Sid
.Revision
)))
1125 ConvertStringSidToSidA(
1126 IN LPCSTR StringSid
,
1129 BOOL bRetVal
= FALSE
;
1131 if (!StringSid
|| !sid
)
1132 SetLastError(ERROR_INVALID_PARAMETER
);
1135 UINT len
= MultiByteToWideChar(CP_ACP
, 0, StringSid
, -1, NULL
, 0);
1136 LPWSTR wStringSid
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1137 MultiByteToWideChar(CP_ACP
, 0, StringSid
, - 1, wStringSid
, len
);
1138 bRetVal
= ConvertStringSidToSidW(wStringSid
, sid
);
1139 HeapFree(GetProcessHeap(), 0, wStringSid
);
1144 /******************************************************************************
1145 * ComputeStringSidSize
1147 static DWORD
ComputeStringSidSize(LPCWSTR StringSid
)
1149 DWORD size
= sizeof(SID
);
1151 if (StringSid
[0] == 'S' && StringSid
[1] == '-') /* S-R-I-S-S */
1156 if (*StringSid
== '-')
1162 size
+= (ctok
- 3) * sizeof(DWORD
);
1164 else /* String constant format - Only available in winxp and above */
1168 for (i
= 0; i
< sizeof(WellKnownSids
)/sizeof(WellKnownSids
[0]); i
++)
1169 if (!strncmpW(WellKnownSids
[i
].wstr
, StringSid
, 2))
1170 size
+= (WellKnownSids
[i
].Sid
.SubAuthorityCount
- 1) * sizeof(DWORD
);
1176 static const RECORD SidTable
[] =
1178 { SDDL_ACCOUNT_OPERATORS
, WinBuiltinAccountOperatorsSid
},
1179 { SDDL_ALIAS_PREW2KCOMPACC
, WinBuiltinPreWindows2000CompatibleAccessSid
},
1180 { SDDL_ANONYMOUS
, WinAnonymousSid
},
1181 { SDDL_AUTHENTICATED_USERS
, WinAuthenticatedUserSid
},
1182 { SDDL_BUILTIN_ADMINISTRATORS
, WinBuiltinAdministratorsSid
},
1183 { SDDL_BUILTIN_GUESTS
, WinBuiltinGuestsSid
},
1184 { SDDL_BACKUP_OPERATORS
, WinBuiltinBackupOperatorsSid
},
1185 { SDDL_BUILTIN_USERS
, WinBuiltinUsersSid
},
1186 { SDDL_CERT_SERV_ADMINISTRATORS
, WinAccountCertAdminsSid
/* FIXME: DOMAIN_GROUP_RID_CERT_ADMINS */ },
1187 { SDDL_CREATOR_GROUP
, WinCreatorGroupSid
},
1188 { SDDL_CREATOR_OWNER
, WinCreatorOwnerSid
},
1189 { SDDL_DOMAIN_ADMINISTRATORS
, WinAccountDomainAdminsSid
/* FIXME: DOMAIN_GROUP_RID_ADMINS */ },
1190 { SDDL_DOMAIN_COMPUTERS
, WinAccountComputersSid
/* FIXME: DOMAIN_GROUP_RID_COMPUTERS */ },
1191 { SDDL_DOMAIN_DOMAIN_CONTROLLERS
, WinAccountControllersSid
/* FIXME: DOMAIN_GROUP_RID_CONTROLLERS */ },
1192 { SDDL_DOMAIN_GUESTS
, WinAccountDomainGuestsSid
/* FIXME: DOMAIN_GROUP_RID_GUESTS */ },
1193 { SDDL_DOMAIN_USERS
, WinAccountDomainUsersSid
/* FIXME: DOMAIN_GROUP_RID_USERS */ },
1194 { SDDL_ENTERPRISE_ADMINS
, WinAccountEnterpriseAdminsSid
/* FIXME: DOMAIN_GROUP_RID_ENTERPRISE_ADMINS */ },
1195 { SDDL_ENTERPRISE_DOMAIN_CONTROLLERS
, WinLogonIdsSid
/* FIXME: SECURITY_SERVER_LOGON_RID */ },
1196 { SDDL_EVERYONE
, WinWorldSid
},
1197 { SDDL_GROUP_POLICY_ADMINS
, WinAccountPolicyAdminsSid
/* FIXME: DOMAIN_GROUP_RID_POLICY_ADMINS */ },
1198 { SDDL_INTERACTIVE
, WinInteractiveSid
},
1199 { SDDL_LOCAL_ADMIN
, WinAccountAdministratorSid
/* FIXME: DOMAIN_USER_RID_ADMIN */ },
1200 { SDDL_LOCAL_GUEST
, WinAccountGuestSid
/* FIXME: DOMAIN_USER_RID_GUEST */ },
1201 { SDDL_LOCAL_SERVICE
, WinLocalServiceSid
},
1202 { SDDL_LOCAL_SYSTEM
, WinLocalSystemSid
},
1203 { SDDL_NETWORK
, WinNetworkSid
},
1204 { SDDL_NETWORK_CONFIGURATION_OPS
, WinBuiltinNetworkConfigurationOperatorsSid
},
1205 { SDDL_NETWORK_SERVICE
, WinNetworkServiceSid
},
1206 { SDDL_PRINTER_OPERATORS
, WinBuiltinPrintOperatorsSid
},
1207 { SDDL_PERSONAL_SELF
, WinSelfSid
},
1208 { SDDL_POWER_USERS
, WinBuiltinPowerUsersSid
},
1209 { SDDL_RAS_SERVERS
, WinAccountRasAndIasServersSid
/* FIXME: DOMAIN_ALIAS_RID_RAS_SERVERS */ },
1210 { SDDL_REMOTE_DESKTOP
, WinBuiltinRemoteDesktopUsersSid
},
1211 { SDDL_REPLICATOR
, WinBuiltinReplicatorSid
},
1212 { SDDL_RESTRICTED_CODE
, WinRestrictedCodeSid
},
1213 { SDDL_SCHEMA_ADMINISTRATORS
, WinAccountSchemaAdminsSid
/* FIXME: DOMAIN_GROUP_RID_SCHEMA_ADMINS */ },
1214 { SDDL_SERVER_OPERATORS
, WinBuiltinSystemOperatorsSid
},
1215 { SDDL_SERVICE
, WinServiceSid
},
1223 ConvertStringSidToSidW(
1224 IN LPCWSTR StringSid
,
1228 DWORD i
, cBytes
, identAuth
, csubauth
;
1232 TRACE("%s %p\n", StringSid
, sid
);
1236 SetLastError(ERROR_INVALID_SID
);
1239 for (i
= 0; i
< sizeof(SidTable
) / sizeof(SidTable
[0]) - 1; i
++)
1241 if (wcscmp(StringSid
, SidTable
[i
].key
) == 0)
1243 WELL_KNOWN_SID_TYPE knownSid
= (WELL_KNOWN_SID_TYPE
)SidTable
[i
].value
;
1244 size
= SECURITY_MAX_SID_SIZE
;
1245 *sid
= LocalAlloc(0, size
);
1248 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1251 ret
= CreateWellKnownSid(
1258 SetLastError(ERROR_INVALID_SID
);
1265 /* That's probably a string S-R-I-S-S... */
1266 if (StringSid
[0] != 'S' || StringSid
[1] != '-')
1268 SetLastError(ERROR_INVALID_SID
);
1272 cBytes
= ComputeStringSidSize(StringSid
);
1273 pisid
= (SID
*)LocalAlloc( 0, cBytes
);
1276 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1281 csubauth
= ((cBytes
- sizeof(SID
)) / sizeof(DWORD
)) + 1;
1283 StringSid
+= 2; /* Advance to Revision */
1284 pisid
->Revision
= atoiW(StringSid
);
1286 if (pisid
->Revision
!= SDDL_REVISION
)
1288 TRACE("Revision %d is unknown\n", pisid
->Revision
);
1289 goto lend
; /* ERROR_INVALID_SID */
1293 TRACE("SubAuthorityCount is 0\n");
1294 goto lend
; /* ERROR_INVALID_SID */
1297 pisid
->SubAuthorityCount
= csubauth
;
1299 /* Advance to identifier authority */
1300 while (*StringSid
&& *StringSid
!= '-')
1302 if (*StringSid
== '-')
1305 /* MS' implementation can't handle values greater than 2^32 - 1, so
1306 * we don't either; assume most significant bytes are always 0
1308 pisid
->IdentifierAuthority
.Value
[0] = 0;
1309 pisid
->IdentifierAuthority
.Value
[1] = 0;
1310 identAuth
= atoiW(StringSid
);
1311 pisid
->IdentifierAuthority
.Value
[5] = identAuth
& 0xff;
1312 pisid
->IdentifierAuthority
.Value
[4] = (identAuth
& 0xff00) >> 8;
1313 pisid
->IdentifierAuthority
.Value
[3] = (identAuth
& 0xff0000) >> 16;
1314 pisid
->IdentifierAuthority
.Value
[2] = (identAuth
& 0xff000000) >> 24;
1316 /* Advance to first sub authority */
1317 while (*StringSid
&& *StringSid
!= '-')
1319 if (*StringSid
== '-')
1324 while (*StringSid
&& *StringSid
!= '-')
1326 if (*StringSid
== '-')
1329 pisid
->SubAuthority
[i
++] = atoiW(StringSid
);
1332 if (i
!= pisid
->SubAuthorityCount
)
1333 goto lend
; /* ERROR_INVALID_SID */
1340 SetLastError(ERROR_INVALID_SID
);
1342 TRACE("returning %s\n", ret
? "TRUE" : "FALSE");