4 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wine/debug.h"
31 #include "wine/heap.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(security
);
42 { L
"GA", GENERIC_ALL
},
43 { L
"GR", GENERIC_READ
},
44 { L
"GW", GENERIC_WRITE
},
45 { L
"GX", GENERIC_EXECUTE
},
47 { L
"RC", READ_CONTROL
},
50 { L
"WO", WRITE_OWNER
},
52 { L
"RP", ADS_RIGHT_DS_READ_PROP
},
53 { L
"WP", ADS_RIGHT_DS_WRITE_PROP
},
54 { L
"CC", ADS_RIGHT_DS_CREATE_CHILD
},
55 { L
"DC", ADS_RIGHT_DS_DELETE_CHILD
},
56 { L
"LC", ADS_RIGHT_ACTRL_DS_LIST
},
57 { L
"SW", ADS_RIGHT_DS_SELF
},
58 { L
"LO", ADS_RIGHT_DS_LIST_OBJECT
},
59 { L
"DT", ADS_RIGHT_DS_DELETE_TREE
},
60 { L
"CR", ADS_RIGHT_DS_CONTROL_ACCESS
},
62 { L
"FA", FILE_ALL_ACCESS
},
63 { L
"FR", FILE_GENERIC_READ
},
64 { L
"FW", FILE_GENERIC_WRITE
},
65 { L
"FX", FILE_GENERIC_EXECUTE
},
67 { L
"KA", KEY_ALL_ACCESS
},
70 { L
"KX", KEY_EXECUTE
},
72 { L
"NR", SYSTEM_MANDATORY_LABEL_NO_READ_UP
},
73 { L
"NW", SYSTEM_MANDATORY_LABEL_NO_WRITE_UP
},
74 { L
"NX", SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP
},
79 /* same fields as struct _SID */
81 BYTE SubAuthorityCount
;
82 SID_IDENTIFIER_AUTHORITY IdentifierAuthority
;
83 DWORD SubAuthority
[SID_MAX_SUB_AUTHORITIES
];
89 WELL_KNOWN_SID_TYPE Type
;
94 { {0,0}, WinNullSid
, { SID_REVISION
, 1, { SECURITY_NULL_SID_AUTHORITY
}, { SECURITY_NULL_RID
} } },
95 { {'W','D'}, WinWorldSid
, { SID_REVISION
, 1, { SECURITY_WORLD_SID_AUTHORITY
}, { SECURITY_WORLD_RID
} } },
96 { {0,0}, WinLocalSid
, { SID_REVISION
, 1, { SECURITY_LOCAL_SID_AUTHORITY
}, { SECURITY_LOCAL_RID
} } },
97 { {'C','O'}, WinCreatorOwnerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_RID
} } },
98 { {'C','G'}, WinCreatorGroupSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_GROUP_RID
} } },
99 { {'O','W'}, WinCreatorOwnerRightsSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_RIGHTS_RID
} } },
100 { {0,0}, WinCreatorOwnerServerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_SERVER_RID
} } },
101 { {0,0}, WinCreatorGroupServerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_GROUP_SERVER_RID
} } },
102 { {0,0}, WinNtAuthoritySid
, { SID_REVISION
, 0, { SECURITY_NT_AUTHORITY
}, { SECURITY_NULL_RID
} } },
103 { {0,0}, WinDialupSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_DIALUP_RID
} } },
104 { {'N','U'}, WinNetworkSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_NETWORK_RID
} } },
105 { {0,0}, WinBatchSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_BATCH_RID
} } },
106 { {'I','U'}, WinInteractiveSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_INTERACTIVE_RID
} } },
107 { {'S','U'}, WinServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_SERVICE_RID
} } },
108 { {'A','N'}, WinAnonymousSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_ANONYMOUS_LOGON_RID
} } },
109 { {0,0}, WinProxySid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_PROXY_RID
} } },
110 { {'E','D'}, WinEnterpriseControllersSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_ENTERPRISE_CONTROLLERS_RID
} } },
111 { {'P','S'}, WinSelfSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_PRINCIPAL_SELF_RID
} } },
112 { {'A','U'}, WinAuthenticatedUserSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_AUTHENTICATED_USER_RID
} } },
113 { {'R','C'}, WinRestrictedCodeSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_RESTRICTED_CODE_RID
} } },
114 { {0,0}, WinTerminalServerSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_TERMINAL_SERVER_RID
} } },
115 { {0,0}, WinRemoteLogonIdSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_REMOTE_LOGON_RID
} } },
116 { {0,0}, WinLogonIdsSid
, { SID_REVISION
, SECURITY_LOGON_IDS_RID_COUNT
, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOGON_IDS_RID
} } },
117 { {'S','Y'}, WinLocalSystemSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOCAL_SYSTEM_RID
} } },
118 { {'L','S'}, WinLocalServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOCAL_SERVICE_RID
} } },
119 { {'N','S'}, WinNetworkServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_NETWORK_SERVICE_RID
} } },
120 { {0,0}, WinBuiltinDomainSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
} } },
121 { {'B','A'}, WinBuiltinAdministratorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ADMINS
} } },
122 { {'B','U'}, WinBuiltinUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_USERS
} } },
123 { {'B','G'}, WinBuiltinGuestsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_GUESTS
} } },
124 { {'P','U'}, WinBuiltinPowerUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_POWER_USERS
} } },
125 { {'A','O'}, WinBuiltinAccountOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ACCOUNT_OPS
} } },
126 { {'S','O'}, WinBuiltinSystemOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_SYSTEM_OPS
} } },
127 { {'P','O'}, WinBuiltinPrintOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_PRINT_OPS
} } },
128 { {'B','O'}, WinBuiltinBackupOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_BACKUP_OPS
} } },
129 { {'R','E'}, WinBuiltinReplicatorSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_REPLICATOR
} } },
130 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS
} } },
131 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS
} } },
132 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS
} } },
133 { {0,0}, WinNTLMAuthenticationSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_PACKAGE_BASE_RID
, SECURITY_PACKAGE_NTLM_RID
} } },
134 { {0,0}, WinDigestAuthenticationSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_PACKAGE_BASE_RID
, SECURITY_PACKAGE_DIGEST_RID
} } },
135 { {0,0}, WinSChannelAuthenticationSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_PACKAGE_BASE_RID
, SECURITY_PACKAGE_SCHANNEL_RID
} } },
136 { {0,0}, WinThisOrganizationSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_THIS_ORGANIZATION_RID
} } },
137 { {0,0}, WinOtherOrganizationSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_OTHER_ORGANIZATION_RID
} } },
138 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS
} } },
139 { {0,0}, WinBuiltinPerfMonitoringUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_MONITORING_USERS
} } },
140 { {0,0}, WinBuiltinPerfLoggingUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_LOGGING_USERS
} } },
141 { {0,0}, WinBuiltinAuthorizationAccessSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS
} } },
142 { {0,0}, WinBuiltinTerminalServerLicenseServersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS
} } },
143 { {0,0}, WinBuiltinDCOMUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_DCOM_USERS
} } },
144 { {'L','W'}, WinLowLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_LOW_RID
} } },
145 { {'M','E'}, WinMediumLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_MEDIUM_RID
} } },
146 { {'H','I'}, WinHighLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_HIGH_RID
} } },
147 { {'S','I'}, WinSystemLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_SYSTEM_RID
} } },
148 { {'A','C'}, WinBuiltinAnyPackageSid
, { SID_REVISION
, 2, { SECURITY_APP_PACKAGE_AUTHORITY
}, { SECURITY_APP_PACKAGE_BASE_RID
, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE
} } },
151 /* these SIDs must be constructed as relative to some domain - only the RID is well-known */
155 WELL_KNOWN_SID_TYPE type
;
160 { {'L','A'}, WinAccountAdministratorSid
, DOMAIN_USER_RID_ADMIN
},
161 { {'L','G'}, WinAccountGuestSid
, DOMAIN_USER_RID_GUEST
},
162 { {0,0}, WinAccountKrbtgtSid
, DOMAIN_USER_RID_KRBTGT
},
163 { {'D','A'}, WinAccountDomainAdminsSid
, DOMAIN_GROUP_RID_ADMINS
},
164 { {'D','U'}, WinAccountDomainUsersSid
, DOMAIN_GROUP_RID_USERS
},
165 { {'D','G'}, WinAccountDomainGuestsSid
, DOMAIN_GROUP_RID_GUESTS
},
166 { {'D','C'}, WinAccountComputersSid
, DOMAIN_GROUP_RID_COMPUTERS
},
167 { {'D','D'}, WinAccountControllersSid
, DOMAIN_GROUP_RID_CONTROLLERS
},
168 { {'C','A'}, WinAccountCertAdminsSid
, DOMAIN_GROUP_RID_CERT_ADMINS
},
169 { {'S','A'}, WinAccountSchemaAdminsSid
, DOMAIN_GROUP_RID_SCHEMA_ADMINS
},
170 { {'E','A'}, WinAccountEnterpriseAdminsSid
, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS
},
171 { {'P','A'}, WinAccountPolicyAdminsSid
, DOMAIN_GROUP_RID_POLICY_ADMINS
},
172 { {'R','S'}, WinAccountRasAndIasServersSid
, DOMAIN_ALIAS_RID_RAS_SERVERS
},
176 static void print_string(const WCHAR
*string
, int cch
, WCHAR
**pwptr
, ULONG
*plen
)
179 cch
= wcslen(string
);
186 memcpy(*pwptr
, string
, sizeof(WCHAR
)*cch
);
191 static BOOL
print_sid_numeric(PSID psid
, WCHAR
**pwptr
, ULONG
*plen
)
197 if( !IsValidSid( psid
) || pisid
->Revision
!= SDDL_REVISION
)
199 SetLastError(ERROR_INVALID_SID
);
203 if (pisid
->IdentifierAuthority
.Value
[0] ||
204 pisid
->IdentifierAuthority
.Value
[1])
206 FIXME("not matching MS' bugs\n");
207 SetLastError(ERROR_INVALID_SID
);
211 swprintf( buf
, ARRAY_SIZE(buf
), L
"S-%u-%d", pisid
->Revision
, MAKELONG(
212 MAKEWORD( pisid
->IdentifierAuthority
.Value
[5], pisid
->IdentifierAuthority
.Value
[4] ),
213 MAKEWORD( pisid
->IdentifierAuthority
.Value
[3], pisid
->IdentifierAuthority
.Value
[2] )
215 print_string(buf
, -1, pwptr
, plen
);
217 for( i
=0; i
<pisid
->SubAuthorityCount
; i
++ )
219 swprintf( buf
, ARRAY_SIZE(buf
), L
"-%u", pisid
->SubAuthority
[i
] );
220 print_string(buf
, -1, pwptr
, plen
);
225 /******************************************************************************
226 * ConvertSidToStringSidW (sechost.@)
228 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertSidToStringSidW( PSID sid
, WCHAR
**pstr
)
233 TRACE("%p %p\n", sid
, pstr
);
236 if (!print_sid_numeric( sid
, NULL
, &len
))
238 wstr
= wptr
= LocalAlloc( 0, (len
+ 1) * sizeof(WCHAR
) );
239 print_sid_numeric( sid
, &wptr
, NULL
);
246 static BOOL
print_sid(PSID psid
, WCHAR
**pwptr
, ULONG
*plen
)
249 for (i
= 0; i
< ARRAY_SIZE(well_known_sids
); i
++)
251 if (well_known_sids
[i
].str
[0] && EqualSid(psid
, (PSID
)&well_known_sids
[i
].sid
.Revision
))
253 print_string(well_known_sids
[i
].str
, 2, pwptr
, plen
);
258 return print_sid_numeric(psid
, pwptr
, plen
);
261 static void print_rights(DWORD mask
, WCHAR
**pwptr
, ULONG
*plen
)
263 static const WCHAR
*bit_names
[32] =
305 /* first check if the right have name */
306 for (i
= 0; i
< ARRAY_SIZE(ace_rights
); i
++)
308 if (mask
== ace_rights
[i
].value
)
310 print_string(ace_rights
[i
].str
, -1, pwptr
, plen
);
315 /* then check if it can be built from bit names */
316 for (i
= 0; i
< 32; i
++)
318 if ((mask
& (1 << i
)) && !bit_names
[i
])
320 /* can't be built from bit names */
321 swprintf(buf
, ARRAY_SIZE(buf
), L
"0x%x", mask
);
322 print_string(buf
, -1, pwptr
, plen
);
327 /* build from bit names */
328 for (i
= 0; i
< 32; i
++)
330 print_string(bit_names
[i
], -1, pwptr
, plen
);
333 static inline BOOL
is_object_ace(BYTE type
)
337 case ACCESS_ALLOWED_OBJECT_ACE_TYPE
:
338 case ACCESS_DENIED_OBJECT_ACE_TYPE
:
339 case ACCESS_AUDIT_OBJECT_ACE_TYPE
:
340 case ACCESS_ALARM_OBJECT_ACE_TYPE
:
341 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE
:
342 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE
:
343 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE
:
344 case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE
:
352 static BOOL
print_ace(void *pace
, WCHAR
**pwptr
, ULONG
*plen
)
354 ACCESS_ALLOWED_ACE
*piace
; /* all the supported ACEs have the same memory layout */
359 if (piace
->Header
.AceType
> ACCESS_MAX_MS_V5_ACE_TYPE
|| piace
->Header
.AceSize
< sizeof(ACCESS_ALLOWED_ACE
))
361 SetLastError(ERROR_INVALID_ACL
);
365 print_string(L
"(", -1, pwptr
, plen
);
366 switch (piace
->Header
.AceType
)
368 case ACCESS_ALLOWED_ACE_TYPE
:
369 print_string(L
"A", -1, pwptr
, plen
);
371 case ACCESS_DENIED_ACE_TYPE
:
372 print_string(L
"D", -1, pwptr
, plen
);
374 case SYSTEM_AUDIT_ACE_TYPE
:
375 print_string(L
"AU", -1, pwptr
, plen
);
377 case SYSTEM_ALARM_ACE_TYPE
:
378 print_string(L
"AL", -1, pwptr
, plen
);
381 print_string(L
";", -1, pwptr
, plen
);
383 if (piace
->Header
.AceFlags
& OBJECT_INHERIT_ACE
)
384 print_string(L
"OI", -1, pwptr
, plen
);
385 if (piace
->Header
.AceFlags
& CONTAINER_INHERIT_ACE
)
386 print_string(L
"CI", -1, pwptr
, plen
);
387 if (piace
->Header
.AceFlags
& NO_PROPAGATE_INHERIT_ACE
)
388 print_string(L
"NP", -1, pwptr
, plen
);
389 if (piace
->Header
.AceFlags
& INHERIT_ONLY_ACE
)
390 print_string(L
"IO", -1, pwptr
, plen
);
391 if (piace
->Header
.AceFlags
& INHERITED_ACE
)
392 print_string(L
"ID", -1, pwptr
, plen
);
393 if (piace
->Header
.AceFlags
& SUCCESSFUL_ACCESS_ACE_FLAG
)
394 print_string(L
"SA", -1, pwptr
, plen
);
395 if (piace
->Header
.AceFlags
& FAILED_ACCESS_ACE_FLAG
)
396 print_string(L
"FA", -1, pwptr
, plen
);
397 print_string(L
";", -1, pwptr
, plen
);
398 print_rights(piace
->Mask
, pwptr
, plen
);
399 print_string(L
";", -1, pwptr
, plen
);
400 sid_start
= &piace
->SidStart
;
401 if (is_object_ace(piace
->Header
.AceType
))
403 ACCESS_ALLOWED_OBJECT_ACE
*objace
= pace
;
405 sid_start
++; /* Flags */
406 if (objace
->Flags
& ACE_OBJECT_TYPE_PRESENT
)
407 sid_start
+= sizeof(GUID
) / sizeof(*sid_start
); /* ObjectType */
408 if (objace
->Flags
& ACE_INHERITED_OBJECT_TYPE_PRESENT
)
409 sid_start
+= sizeof(GUID
) / sizeof(*sid_start
); /* InheritedObjectType */
411 /* objects not supported */
412 print_string(L
";", -1, pwptr
, plen
);
413 /* objects not supported */
414 print_string(L
";", -1, pwptr
, plen
);
415 if (!print_sid(sid_start
, pwptr
, plen
))
417 print_string(L
")", -1, pwptr
, plen
);
421 static BOOL
print_acl(ACL
*pacl
, WCHAR
**pwptr
, ULONG
*plen
, SECURITY_DESCRIPTOR_CONTROL control
)
426 if (control
& SE_DACL_PROTECTED
)
427 print_string(L
"P", -1, pwptr
, plen
);
428 if (control
& SE_DACL_AUTO_INHERIT_REQ
)
429 print_string(L
"AR", -1, pwptr
, plen
);
430 if (control
& SE_DACL_AUTO_INHERITED
)
431 print_string(L
"AI", -1, pwptr
, plen
);
436 if (!IsValidAcl(pacl
))
439 count
= pacl
->AceCount
;
440 for (i
= 0; i
< count
; i
++)
443 if (!GetAce(pacl
, i
, &ace
))
445 if (!print_ace(ace
, pwptr
, plen
))
452 static BOOL
print_owner(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
457 if (!GetSecurityDescriptorOwner(sd
, &psid
, &defaulted
))
463 print_string(L
"O:", -1, pwptr
, plen
);
464 if (!print_sid(psid
, pwptr
, plen
))
469 static BOOL
print_group(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
474 if (!GetSecurityDescriptorGroup(sd
, &psid
, &defaulted
))
480 print_string(L
"G:", -1, pwptr
, plen
);
481 if (!print_sid(psid
, pwptr
, plen
))
486 static BOOL
print_dacl(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
488 SECURITY_DESCRIPTOR_CONTROL control
;
489 BOOL present
, defaulted
;
493 if (!GetSecurityDescriptorDacl(sd
, &present
, &pacl
, &defaulted
))
496 if (!GetSecurityDescriptorControl(sd
, &control
, &revision
))
502 print_string(L
"D:", -1, pwptr
, plen
);
503 if (!print_acl(pacl
, pwptr
, plen
, control
))
508 static BOOL
print_sacl(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
510 SECURITY_DESCRIPTOR_CONTROL control
;
511 BOOL present
, defaulted
;
515 if (!GetSecurityDescriptorSacl(sd
, &present
, &pacl
, &defaulted
))
518 if (!GetSecurityDescriptorControl(sd
, &control
, &revision
))
524 print_string(L
"S:", -1, pwptr
, plen
);
525 if (!print_acl(pacl
, pwptr
, plen
, control
))
530 /******************************************************************************
531 * ConvertSecurityDescriptorToStringSecurityDescriptorW (sechost.@)
533 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertSecurityDescriptorToStringSecurityDescriptorW( PSECURITY_DESCRIPTOR sd
,
534 DWORD revision
, SECURITY_INFORMATION flags
, WCHAR
**string
, ULONG
*ret_len
)
539 if (revision
!= SDDL_REVISION_1
)
541 ERR("Unhandled SDDL revision %ld\n", revision
);
542 SetLastError( ERROR_UNKNOWN_REVISION
);
546 if ((flags
& OWNER_SECURITY_INFORMATION
) && !print_owner(sd
, NULL
, &len
))
548 if ((flags
& GROUP_SECURITY_INFORMATION
) && !print_group(sd
, NULL
, &len
))
550 if ((flags
& DACL_SECURITY_INFORMATION
) && !print_dacl(sd
, NULL
, &len
))
552 if ((flags
& SACL_SECURITY_INFORMATION
) && !print_sacl(sd
, NULL
, &len
))
555 wstr
= wptr
= LocalAlloc( 0, (len
+ 1) * sizeof(WCHAR
) );
556 if ((flags
& OWNER_SECURITY_INFORMATION
) && !print_owner(sd
, &wptr
, NULL
))
561 if ((flags
& GROUP_SECURITY_INFORMATION
) && !print_group(sd
, &wptr
, NULL
))
566 if ((flags
& DACL_SECURITY_INFORMATION
) && !print_dacl(sd
, &wptr
, NULL
))
571 if ((flags
& SACL_SECURITY_INFORMATION
) && !print_sacl(sd
, &wptr
, NULL
))
578 TRACE("ret: %s, %ld\n", wine_dbgstr_w(wstr
), len
);
580 if (ret_len
) *ret_len
= wcslen(*string
) + 1;
584 static BOOL
get_computer_sid( PSID sid
)
586 static const struct /* same fields as struct SID */
589 BYTE SubAuthorityCount
;
590 SID_IDENTIFIER_AUTHORITY IdentifierAuthority
;
591 DWORD SubAuthority
[4];
593 { SID_REVISION
, 4, { SECURITY_NT_AUTHORITY
}, { SECURITY_NT_NON_UNIQUE
, 0, 0, 0 } };
595 memcpy( sid
, &computer_sid
, sizeof(computer_sid
) );
599 static BOOL
parse_token( const WCHAR
*string
, const WCHAR
**end
, DWORD
*result
)
601 if (string
[0] == '0' && (string
[1] == 'X' || string
[1] == 'x'))
604 *result
= wcstoul( string
+ 2, (WCHAR
**)&string
, 16 );
610 else if (iswdigit(string
[0]) || string
[0] == '-')
612 *result
= wcstoul( string
, (WCHAR
**)&string
, 10 );
624 static DWORD
get_sid_size( const WCHAR
*string
, const WCHAR
**end
)
626 if ((string
[0] == 'S' || string
[0] == 's') && string
[1] == '-') /* S-R-I(-S)+ */
633 while (parse_token( string
, &string
, &value
))
639 if (token_count
>= 3)
640 return GetSidLengthRequired( token_count
- 2 );
642 else /* String constant format - Only available in winxp and above */
649 for (i
= 0; i
< ARRAY_SIZE(well_known_sids
); i
++)
651 if (!wcsnicmp( well_known_sids
[i
].str
, string
, 2 ))
652 return GetSidLengthRequired( well_known_sids
[i
].sid
.SubAuthorityCount
);
655 for (i
= 0; i
< ARRAY_SIZE(well_known_rids
); i
++)
657 if (!wcsnicmp( well_known_rids
[i
].str
, string
, 2 ))
659 struct max_sid local
;
660 get_computer_sid(&local
);
661 return GetSidLengthRequired( *GetSidSubAuthorityCount(&local
) + 1 );
666 return GetSidLengthRequired( 0 );
669 static BOOL
parse_sid( const WCHAR
*string
, const WCHAR
**end
, SID
*pisid
, DWORD
*size
)
671 while (*string
== ' ')
674 *size
= get_sid_size( string
, end
);
675 if (!pisid
) /* Simply compute the size */
678 if ((string
[0] == 'S' || string
[0] == 's') && string
[1] == '-') /* S-R-I-S-S */
680 DWORD i
= 0, identAuth
;
681 DWORD csubauth
= ((*size
- GetSidLengthRequired(0)) / sizeof(DWORD
));
684 string
+= 2; /* Advance to Revision */
685 parse_token( string
, &string
, &token
);
686 pisid
->Revision
= token
;
688 if (pisid
->Revision
!= SDDL_REVISION
)
690 TRACE("Revision %d is unknown\n", pisid
->Revision
);
691 SetLastError( ERROR_INVALID_SID
);
696 TRACE("SubAuthorityCount is 0\n");
697 SetLastError( ERROR_INVALID_SID
);
701 pisid
->SubAuthorityCount
= csubauth
;
703 /* MS' implementation can't handle values greater than 2^32 - 1, so
704 * we don't either; assume most significant bytes are always 0
706 pisid
->IdentifierAuthority
.Value
[0] = 0;
707 pisid
->IdentifierAuthority
.Value
[1] = 0;
708 parse_token( string
, &string
, &identAuth
);
709 pisid
->IdentifierAuthority
.Value
[5] = identAuth
& 0xff;
710 pisid
->IdentifierAuthority
.Value
[4] = (identAuth
& 0xff00) >> 8;
711 pisid
->IdentifierAuthority
.Value
[3] = (identAuth
& 0xff0000) >> 16;
712 pisid
->IdentifierAuthority
.Value
[2] = (identAuth
& 0xff000000) >> 24;
714 while (parse_token( string
, &string
, &token
))
716 pisid
->SubAuthority
[i
++] = token
;
719 if (i
!= pisid
->SubAuthorityCount
)
721 SetLastError( ERROR_INVALID_SID
);
726 assert(*end
== string
);
730 else /* String constant format - Only available in winxp and above */
733 pisid
->Revision
= SDDL_REVISION
;
735 for (i
= 0; i
< ARRAY_SIZE(well_known_sids
); i
++)
737 if (!wcsnicmp(well_known_sids
[i
].str
, string
, 2))
740 pisid
->SubAuthorityCount
= well_known_sids
[i
].sid
.SubAuthorityCount
;
741 pisid
->IdentifierAuthority
= well_known_sids
[i
].sid
.IdentifierAuthority
;
742 for (j
= 0; j
< well_known_sids
[i
].sid
.SubAuthorityCount
; j
++)
743 pisid
->SubAuthority
[j
] = well_known_sids
[i
].sid
.SubAuthority
[j
];
748 for (i
= 0; i
< ARRAY_SIZE(well_known_rids
); i
++)
750 if (!wcsnicmp(well_known_rids
[i
].str
, string
, 2))
752 get_computer_sid(pisid
);
753 pisid
->SubAuthority
[pisid
->SubAuthorityCount
] = well_known_rids
[i
].rid
;
754 pisid
->SubAuthorityCount
++;
759 FIXME("String constant not supported: %s\n", debugstr_wn(string
, 2));
760 SetLastError( ERROR_INVALID_SID
);
765 /******************************************************************************
766 * ConvertStringSidToSidW (sechost.@)
768 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertStringSidToSidW( const WCHAR
*string
, PSID
*sid
)
771 const WCHAR
*string_end
;
773 TRACE("%s, %p\n", debugstr_w(string
), sid
);
775 if (GetVersion() & 0x80000000)
777 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
783 SetLastError(ERROR_INVALID_PARAMETER
);
787 if (!parse_sid( string
, &string_end
, NULL
, &size
))
792 SetLastError(ERROR_INVALID_SID
);
796 *sid
= LocalAlloc( 0, size
);
798 if (!parse_sid( string
, NULL
, *sid
, &size
))
806 static DWORD
parse_acl_flags( const WCHAR
**string_ptr
)
809 const WCHAR
*string
= *string_ptr
;
811 while (*string
&& *string
!= '(')
815 flags
|= SE_DACL_PROTECTED
;
817 else if (*string
== 'A')
821 flags
|= SE_DACL_AUTO_INHERIT_REQ
;
822 else if (*string
== 'I')
823 flags
|= SE_DACL_AUTO_INHERITED
;
828 *string_ptr
= string
;
832 static BYTE
parse_ace_type( const WCHAR
**string_ptr
)
841 { L
"AL", SYSTEM_ALARM_ACE_TYPE
},
842 { L
"AU", SYSTEM_AUDIT_ACE_TYPE
},
843 { L
"A", ACCESS_ALLOWED_ACE_TYPE
},
844 { L
"D", ACCESS_DENIED_ACE_TYPE
},
845 { L
"ML", SYSTEM_MANDATORY_LABEL_ACE_TYPE
},
847 { ACCESS_ALLOWED_OBJECT_ACE_TYPE },
848 { ACCESS_DENIED_OBJECT_ACE_TYPE },
849 { SYSTEM_ALARM_OBJECT_ACE_TYPE },
850 { SYSTEM_AUDIT_OBJECT_ACE_TYPE },
854 const WCHAR
*string
= *string_ptr
;
857 while (*string
== ' ')
860 for (i
= 0; i
< ARRAY_SIZE(ace_types
); ++i
)
862 size_t len
= wcslen( ace_types
[i
].str
);
863 if (!wcsncmp( string
, ace_types
[i
].str
, len
))
865 *string_ptr
= string
+ len
;
866 return ace_types
[i
].value
;
872 static DWORD
parse_ace_flag( const WCHAR
*string
)
881 { L
"CI", CONTAINER_INHERIT_ACE
},
882 { L
"FA", FAILED_ACCESS_ACE_FLAG
},
883 { L
"ID", INHERITED_ACE
},
884 { L
"IO", INHERIT_ONLY_ACE
},
885 { L
"NP", NO_PROPAGATE_INHERIT_ACE
},
886 { L
"OI", OBJECT_INHERIT_ACE
},
887 { L
"SA", SUCCESSFUL_ACCESS_ACE_FLAG
},
892 for (i
= 0; i
< ARRAY_SIZE(ace_flags
); ++i
)
894 if (!wcsncmp( string
, ace_flags
[i
].str
, 2 ))
895 return ace_flags
[i
].value
;
900 static DWORD
parse_ace_right( const WCHAR
**string_ptr
)
902 const WCHAR
*string
= *string_ptr
;
905 if (iswdigit( string
[0] ))
906 return wcstoul( string
, (WCHAR
**)string_ptr
, 0 );
908 for (i
= 0; i
< ARRAY_SIZE(ace_rights
); ++i
)
910 if (!wcsncmp( string
, ace_rights
[i
].str
, 2 ))
913 return ace_rights
[i
].value
;
919 static BYTE
parse_ace_flags( const WCHAR
**string_ptr
)
921 const WCHAR
*string
= *string_ptr
;
924 while (*string
== ' ')
927 while (*string
!= ';')
929 DWORD flag
= parse_ace_flag( string
);
935 *string_ptr
= string
;
939 static DWORD
parse_ace_rights( const WCHAR
**string_ptr
)
942 const WCHAR
*string
= *string_ptr
;
944 while (*string
== ' ')
947 while (*string
!= ';')
949 DWORD right
= parse_ace_right( &string
);
950 if (!right
) return 0;
954 *string_ptr
= string
;
958 static BOOL
parse_acl( const WCHAR
*string
, DWORD
*flags
, ACL
*acl
, DWORD
*ret_size
)
962 DWORD length
= sizeof(ACL
);
965 ACCESS_ALLOWED_ACE
*ace
= NULL
; /* pointer to current ACE */
967 TRACE("%s\n", debugstr_w(string
));
969 if (acl
) /* ace is only useful if we're setting values */
970 ace
= (ACCESS_ALLOWED_ACE
*)(acl
+ 1);
972 /* Parse ACL flags */
973 *flags
= parse_acl_flags( &string
);
976 while (*string
== '(')
981 val
= parse_ace_type( &string
);
983 ace
->Header
.AceType
= val
;
986 SetLastError( RPC_S_INVALID_STRING_UUID
);
991 /* Parse ACE flags */
992 val
= parse_ace_flags( &string
);
994 ace
->Header
.AceFlags
= val
;
999 /* Parse ACE rights */
1000 val
= parse_ace_rights( &string
);
1007 /* Parse ACE object guid */
1008 while (*string
== ' ')
1012 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1017 /* Parse ACE inherit object guid */
1018 while (*string
== ' ')
1022 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1027 /* Parse ACE account sid */
1028 if (!parse_sid( string
, &string
, ace
? (SID
*)&ace
->SidStart
: NULL
, &sidlen
))
1031 while (*string
== ' ')
1038 acesize
= sizeof(ACCESS_ALLOWED_ACE
) - sizeof(DWORD
) + sidlen
;
1042 ace
->Header
.AceSize
= acesize
;
1043 ace
= (ACCESS_ALLOWED_ACE
*)((BYTE
*)ace
+ acesize
);
1050 if (length
> 0xffff)
1052 ERR("ACL too large\n");
1058 acl
->AclRevision
= ACL_REVISION
;
1060 acl
->AclSize
= length
;
1061 acl
->AceCount
= acecount
;
1067 SetLastError( ERROR_INVALID_ACL
);
1068 WARN("Invalid ACE string format\n");
1072 static BOOL
parse_sd( const WCHAR
*string
, SECURITY_DESCRIPTOR_RELATIVE
*sd
, DWORD
*size
)
1077 const WCHAR
*lptoken
;
1081 *size
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
1083 tok
= heap_alloc( (wcslen(string
) + 1) * sizeof(WCHAR
) );
1086 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1091 next
= (BYTE
*)(sd
+ 1);
1093 while (*string
== ' ')
1100 /* Expect char identifier followed by ':' */
1104 SetLastError( ERROR_INVALID_PARAMETER
);
1111 while (*lptoken
&& *lptoken
!= ':')
1117 len
= lptoken
- string
;
1118 memcpy( tok
, string
, len
* sizeof(WCHAR
) );
1127 if (!parse_sid( tok
, NULL
, (SID
*)next
, &bytes
))
1132 sd
->Owner
= next
- (BYTE
*)sd
;
1133 next
+= bytes
; /* Advance to next token */
1145 if (!parse_sid( tok
, NULL
, (SID
*)next
, &bytes
))
1150 sd
->Group
= next
- (BYTE
*)sd
;
1151 next
+= bytes
; /* Advance to next token */
1164 if (!parse_acl( tok
, &flags
, (ACL
*)next
, &bytes
))
1169 sd
->Control
|= SE_DACL_PRESENT
| flags
;
1170 sd
->Dacl
= next
- (BYTE
*)sd
;
1171 next
+= bytes
; /* Advance to next token */
1184 if (!parse_acl( tok
, &flags
, (ACL
*)next
, &bytes
))
1189 sd
->Control
|= SE_SACL_PRESENT
| flags
;
1190 sd
->Sacl
= next
- (BYTE
*)sd
;
1191 next
+= bytes
; /* Advance to next token */
1200 FIXME("Unknown token\n");
1201 SetLastError( ERROR_INVALID_PARAMETER
);
1215 /******************************************************************************
1216 * ConvertStringSecurityDescriptorToSecurityDescriptorW (sechost.@)
1218 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertStringSecurityDescriptorToSecurityDescriptorW(
1219 const WCHAR
*string
, DWORD revision
, PSECURITY_DESCRIPTOR
*sd
, ULONG
*ret_size
)
1222 SECURITY_DESCRIPTOR
*psd
;
1224 TRACE("%s, %lu, %p, %p\n", debugstr_w(string
), revision
, sd
, ret_size
);
1226 if (GetVersion() & 0x80000000)
1228 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1233 SetLastError(ERROR_INVALID_PARAMETER
);
1236 if (revision
!= SID_REVISION
)
1238 SetLastError(ERROR_UNKNOWN_REVISION
);
1242 /* Compute security descriptor length */
1243 if (!parse_sd( string
, NULL
, &size
))
1246 psd
= *sd
= LocalAlloc( GMEM_ZEROINIT
, size
);
1249 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1253 psd
->Revision
= SID_REVISION
;
1254 psd
->Control
|= SE_SELF_RELATIVE
;
1256 if (!parse_sd( string
, (SECURITY_DESCRIPTOR_RELATIVE
*)psd
, &size
))
1262 if (ret_size
) *ret_size
= size
;