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"
32 WINE_DEFAULT_DEBUG_CHANNEL(security
);
41 { L
"GA", GENERIC_ALL
},
42 { L
"GR", GENERIC_READ
},
43 { L
"GW", GENERIC_WRITE
},
44 { L
"GX", GENERIC_EXECUTE
},
46 { L
"RC", READ_CONTROL
},
49 { L
"WO", WRITE_OWNER
},
51 { L
"RP", ADS_RIGHT_DS_READ_PROP
},
52 { L
"WP", ADS_RIGHT_DS_WRITE_PROP
},
53 { L
"CC", ADS_RIGHT_DS_CREATE_CHILD
},
54 { L
"DC", ADS_RIGHT_DS_DELETE_CHILD
},
55 { L
"LC", ADS_RIGHT_ACTRL_DS_LIST
},
56 { L
"SW", ADS_RIGHT_DS_SELF
},
57 { L
"LO", ADS_RIGHT_DS_LIST_OBJECT
},
58 { L
"DT", ADS_RIGHT_DS_DELETE_TREE
},
59 { L
"CR", ADS_RIGHT_DS_CONTROL_ACCESS
},
61 { L
"FA", FILE_ALL_ACCESS
},
62 { L
"FR", FILE_GENERIC_READ
},
63 { L
"FW", FILE_GENERIC_WRITE
},
64 { L
"FX", FILE_GENERIC_EXECUTE
},
66 { L
"KA", KEY_ALL_ACCESS
},
69 { L
"KX", KEY_EXECUTE
},
71 { L
"NR", SYSTEM_MANDATORY_LABEL_NO_READ_UP
},
72 { L
"NW", SYSTEM_MANDATORY_LABEL_NO_WRITE_UP
},
73 { L
"NX", SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP
},
78 /* same fields as struct _SID */
80 BYTE SubAuthorityCount
;
81 SID_IDENTIFIER_AUTHORITY IdentifierAuthority
;
82 DWORD SubAuthority
[SID_MAX_SUB_AUTHORITIES
];
88 WELL_KNOWN_SID_TYPE Type
;
93 { {0,0}, WinNullSid
, { SID_REVISION
, 1, { SECURITY_NULL_SID_AUTHORITY
}, { SECURITY_NULL_RID
} } },
94 { {'W','D'}, WinWorldSid
, { SID_REVISION
, 1, { SECURITY_WORLD_SID_AUTHORITY
}, { SECURITY_WORLD_RID
} } },
95 { {0,0}, WinLocalSid
, { SID_REVISION
, 1, { SECURITY_LOCAL_SID_AUTHORITY
}, { SECURITY_LOCAL_RID
} } },
96 { {'C','O'}, WinCreatorOwnerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_RID
} } },
97 { {'C','G'}, WinCreatorGroupSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_GROUP_RID
} } },
98 { {'O','W'}, WinCreatorOwnerRightsSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_RIGHTS_RID
} } },
99 { {0,0}, WinCreatorOwnerServerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_SERVER_RID
} } },
100 { {0,0}, WinCreatorGroupServerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_GROUP_SERVER_RID
} } },
101 { {0,0}, WinNtAuthoritySid
, { SID_REVISION
, 0, { SECURITY_NT_AUTHORITY
}, { SECURITY_NULL_RID
} } },
102 { {0,0}, WinDialupSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_DIALUP_RID
} } },
103 { {'N','U'}, WinNetworkSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_NETWORK_RID
} } },
104 { {0,0}, WinBatchSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_BATCH_RID
} } },
105 { {'I','U'}, WinInteractiveSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_INTERACTIVE_RID
} } },
106 { {'S','U'}, WinServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_SERVICE_RID
} } },
107 { {'A','N'}, WinAnonymousSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_ANONYMOUS_LOGON_RID
} } },
108 { {0,0}, WinProxySid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_PROXY_RID
} } },
109 { {'E','D'}, WinEnterpriseControllersSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_ENTERPRISE_CONTROLLERS_RID
} } },
110 { {'P','S'}, WinSelfSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_PRINCIPAL_SELF_RID
} } },
111 { {'A','U'}, WinAuthenticatedUserSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_AUTHENTICATED_USER_RID
} } },
112 { {'R','C'}, WinRestrictedCodeSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_RESTRICTED_CODE_RID
} } },
113 { {0,0}, WinTerminalServerSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_TERMINAL_SERVER_RID
} } },
114 { {0,0}, WinRemoteLogonIdSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_REMOTE_LOGON_RID
} } },
115 { {0,0}, WinLogonIdsSid
, { SID_REVISION
, SECURITY_LOGON_IDS_RID_COUNT
, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOGON_IDS_RID
} } },
116 { {'S','Y'}, WinLocalSystemSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOCAL_SYSTEM_RID
} } },
117 { {'L','S'}, WinLocalServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOCAL_SERVICE_RID
} } },
118 { {'N','S'}, WinNetworkServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_NETWORK_SERVICE_RID
} } },
119 { {0,0}, WinBuiltinDomainSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
} } },
120 { {'B','A'}, WinBuiltinAdministratorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ADMINS
} } },
121 { {'B','U'}, WinBuiltinUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_USERS
} } },
122 { {'B','G'}, WinBuiltinGuestsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_GUESTS
} } },
123 { {'P','U'}, WinBuiltinPowerUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_POWER_USERS
} } },
124 { {'A','O'}, WinBuiltinAccountOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ACCOUNT_OPS
} } },
125 { {'S','O'}, WinBuiltinSystemOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_SYSTEM_OPS
} } },
126 { {'P','O'}, WinBuiltinPrintOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_PRINT_OPS
} } },
127 { {'B','O'}, WinBuiltinBackupOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_BACKUP_OPS
} } },
128 { {'R','E'}, WinBuiltinReplicatorSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_REPLICATOR
} } },
129 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS
} } },
130 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS
} } },
131 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS
} } },
132 { {0,0}, WinNTLMAuthenticationSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_PACKAGE_BASE_RID
, SECURITY_PACKAGE_NTLM_RID
} } },
133 { {0,0}, WinDigestAuthenticationSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_PACKAGE_BASE_RID
, SECURITY_PACKAGE_DIGEST_RID
} } },
134 { {0,0}, WinSChannelAuthenticationSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_PACKAGE_BASE_RID
, SECURITY_PACKAGE_SCHANNEL_RID
} } },
135 { {0,0}, WinThisOrganizationSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_THIS_ORGANIZATION_RID
} } },
136 { {0,0}, WinOtherOrganizationSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_OTHER_ORGANIZATION_RID
} } },
137 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS
} } },
138 { {0,0}, WinBuiltinPerfMonitoringUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_MONITORING_USERS
} } },
139 { {0,0}, WinBuiltinPerfLoggingUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_LOGGING_USERS
} } },
140 { {0,0}, WinBuiltinAuthorizationAccessSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS
} } },
141 { {0,0}, WinBuiltinTerminalServerLicenseServersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS
} } },
142 { {0,0}, WinBuiltinDCOMUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_DCOM_USERS
} } },
143 { {'L','W'}, WinLowLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_LOW_RID
} } },
144 { {'M','E'}, WinMediumLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_MEDIUM_RID
} } },
145 { {'H','I'}, WinHighLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_HIGH_RID
} } },
146 { {'S','I'}, WinSystemLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_SYSTEM_RID
} } },
147 { {'A','C'}, WinBuiltinAnyPackageSid
, { SID_REVISION
, 2, { SECURITY_APP_PACKAGE_AUTHORITY
}, { SECURITY_APP_PACKAGE_BASE_RID
, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE
} } },
150 /* these SIDs must be constructed as relative to some domain - only the RID is well-known */
154 WELL_KNOWN_SID_TYPE type
;
159 { {'L','A'}, WinAccountAdministratorSid
, DOMAIN_USER_RID_ADMIN
},
160 { {'L','G'}, WinAccountGuestSid
, DOMAIN_USER_RID_GUEST
},
161 { {0,0}, WinAccountKrbtgtSid
, DOMAIN_USER_RID_KRBTGT
},
162 { {'D','A'}, WinAccountDomainAdminsSid
, DOMAIN_GROUP_RID_ADMINS
},
163 { {'D','U'}, WinAccountDomainUsersSid
, DOMAIN_GROUP_RID_USERS
},
164 { {'D','G'}, WinAccountDomainGuestsSid
, DOMAIN_GROUP_RID_GUESTS
},
165 { {'D','C'}, WinAccountComputersSid
, DOMAIN_GROUP_RID_COMPUTERS
},
166 { {'D','D'}, WinAccountControllersSid
, DOMAIN_GROUP_RID_CONTROLLERS
},
167 { {'C','A'}, WinAccountCertAdminsSid
, DOMAIN_GROUP_RID_CERT_ADMINS
},
168 { {'S','A'}, WinAccountSchemaAdminsSid
, DOMAIN_GROUP_RID_SCHEMA_ADMINS
},
169 { {'E','A'}, WinAccountEnterpriseAdminsSid
, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS
},
170 { {'P','A'}, WinAccountPolicyAdminsSid
, DOMAIN_GROUP_RID_POLICY_ADMINS
},
171 { {'R','S'}, WinAccountRasAndIasServersSid
, DOMAIN_ALIAS_RID_RAS_SERVERS
},
175 static void print_string(const WCHAR
*string
, int cch
, WCHAR
**pwptr
, ULONG
*plen
)
178 cch
= wcslen(string
);
185 memcpy(*pwptr
, string
, sizeof(WCHAR
)*cch
);
190 static BOOL
print_sid_numeric(PSID psid
, WCHAR
**pwptr
, ULONG
*plen
)
196 if( !IsValidSid( psid
) || pisid
->Revision
!= SDDL_REVISION
)
198 SetLastError(ERROR_INVALID_SID
);
202 if (pisid
->IdentifierAuthority
.Value
[0] ||
203 pisid
->IdentifierAuthority
.Value
[1])
205 FIXME("not matching MS' bugs\n");
206 SetLastError(ERROR_INVALID_SID
);
210 swprintf( buf
, ARRAY_SIZE(buf
), L
"S-%u-%d", pisid
->Revision
, MAKELONG(
211 MAKEWORD( pisid
->IdentifierAuthority
.Value
[5], pisid
->IdentifierAuthority
.Value
[4] ),
212 MAKEWORD( pisid
->IdentifierAuthority
.Value
[3], pisid
->IdentifierAuthority
.Value
[2] )
214 print_string(buf
, -1, pwptr
, plen
);
216 for( i
=0; i
<pisid
->SubAuthorityCount
; i
++ )
218 swprintf( buf
, ARRAY_SIZE(buf
), L
"-%u", pisid
->SubAuthority
[i
] );
219 print_string(buf
, -1, pwptr
, plen
);
224 /******************************************************************************
225 * ConvertSidToStringSidW (sechost.@)
227 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertSidToStringSidW( PSID sid
, WCHAR
**pstr
)
232 TRACE("%p %p\n", sid
, pstr
);
235 if (!print_sid_numeric( sid
, NULL
, &len
))
237 wstr
= wptr
= LocalAlloc( 0, (len
+ 1) * sizeof(WCHAR
) );
238 print_sid_numeric( sid
, &wptr
, NULL
);
245 static BOOL
print_sid(PSID psid
, WCHAR
**pwptr
, ULONG
*plen
)
248 for (i
= 0; i
< ARRAY_SIZE(well_known_sids
); i
++)
250 if (well_known_sids
[i
].str
[0] && EqualSid(psid
, (PSID
)&well_known_sids
[i
].sid
.Revision
))
252 print_string(well_known_sids
[i
].str
, 2, pwptr
, plen
);
257 return print_sid_numeric(psid
, pwptr
, plen
);
260 static void print_rights(DWORD mask
, WCHAR
**pwptr
, ULONG
*plen
)
262 static const WCHAR
*bit_names
[32] =
304 /* first check if the right have name */
305 for (i
= 0; i
< ARRAY_SIZE(ace_rights
); i
++)
307 if (mask
== ace_rights
[i
].value
)
309 print_string(ace_rights
[i
].str
, -1, pwptr
, plen
);
314 /* then check if it can be built from bit names */
315 for (i
= 0; i
< 32; i
++)
317 if ((mask
& (1 << i
)) && !bit_names
[i
])
319 /* can't be built from bit names */
320 swprintf(buf
, ARRAY_SIZE(buf
), L
"0x%x", mask
);
321 print_string(buf
, -1, pwptr
, plen
);
326 /* build from bit names */
327 for (i
= 0; i
< 32; i
++)
329 print_string(bit_names
[i
], -1, pwptr
, plen
);
332 static inline BOOL
is_object_ace(BYTE type
)
336 case ACCESS_ALLOWED_OBJECT_ACE_TYPE
:
337 case ACCESS_DENIED_OBJECT_ACE_TYPE
:
338 case ACCESS_AUDIT_OBJECT_ACE_TYPE
:
339 case ACCESS_ALARM_OBJECT_ACE_TYPE
:
340 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE
:
341 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE
:
342 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE
:
343 case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE
:
351 static BOOL
print_ace(void *pace
, WCHAR
**pwptr
, ULONG
*plen
)
353 ACCESS_ALLOWED_ACE
*piace
; /* all the supported ACEs have the same memory layout */
358 if (piace
->Header
.AceType
> ACCESS_MAX_MS_V5_ACE_TYPE
|| piace
->Header
.AceSize
< sizeof(ACCESS_ALLOWED_ACE
))
360 SetLastError(ERROR_INVALID_ACL
);
364 print_string(L
"(", -1, pwptr
, plen
);
365 switch (piace
->Header
.AceType
)
367 case ACCESS_ALLOWED_ACE_TYPE
:
368 print_string(L
"A", -1, pwptr
, plen
);
370 case ACCESS_DENIED_ACE_TYPE
:
371 print_string(L
"D", -1, pwptr
, plen
);
373 case SYSTEM_AUDIT_ACE_TYPE
:
374 print_string(L
"AU", -1, pwptr
, plen
);
376 case SYSTEM_ALARM_ACE_TYPE
:
377 print_string(L
"AL", -1, pwptr
, plen
);
380 print_string(L
";", -1, pwptr
, plen
);
382 if (piace
->Header
.AceFlags
& OBJECT_INHERIT_ACE
)
383 print_string(L
"OI", -1, pwptr
, plen
);
384 if (piace
->Header
.AceFlags
& CONTAINER_INHERIT_ACE
)
385 print_string(L
"CI", -1, pwptr
, plen
);
386 if (piace
->Header
.AceFlags
& NO_PROPAGATE_INHERIT_ACE
)
387 print_string(L
"NP", -1, pwptr
, plen
);
388 if (piace
->Header
.AceFlags
& INHERIT_ONLY_ACE
)
389 print_string(L
"IO", -1, pwptr
, plen
);
390 if (piace
->Header
.AceFlags
& INHERITED_ACE
)
391 print_string(L
"ID", -1, pwptr
, plen
);
392 if (piace
->Header
.AceFlags
& SUCCESSFUL_ACCESS_ACE_FLAG
)
393 print_string(L
"SA", -1, pwptr
, plen
);
394 if (piace
->Header
.AceFlags
& FAILED_ACCESS_ACE_FLAG
)
395 print_string(L
"FA", -1, pwptr
, plen
);
396 print_string(L
";", -1, pwptr
, plen
);
397 print_rights(piace
->Mask
, pwptr
, plen
);
398 print_string(L
";", -1, pwptr
, plen
);
399 sid_start
= &piace
->SidStart
;
400 if (is_object_ace(piace
->Header
.AceType
))
402 ACCESS_ALLOWED_OBJECT_ACE
*objace
= pace
;
404 sid_start
++; /* Flags */
405 if (objace
->Flags
& ACE_OBJECT_TYPE_PRESENT
)
406 sid_start
+= sizeof(GUID
) / sizeof(*sid_start
); /* ObjectType */
407 if (objace
->Flags
& ACE_INHERITED_OBJECT_TYPE_PRESENT
)
408 sid_start
+= sizeof(GUID
) / sizeof(*sid_start
); /* InheritedObjectType */
410 /* objects not supported */
411 print_string(L
";", -1, pwptr
, plen
);
412 /* objects not supported */
413 print_string(L
";", -1, pwptr
, plen
);
414 if (!print_sid(sid_start
, pwptr
, plen
))
416 print_string(L
")", -1, pwptr
, plen
);
420 static BOOL
print_acl(ACL
*pacl
, WCHAR
**pwptr
, ULONG
*plen
, SECURITY_DESCRIPTOR_CONTROL control
)
425 if (control
& SE_DACL_PROTECTED
)
426 print_string(L
"P", -1, pwptr
, plen
);
427 if (control
& SE_DACL_AUTO_INHERIT_REQ
)
428 print_string(L
"AR", -1, pwptr
, plen
);
429 if (control
& SE_DACL_AUTO_INHERITED
)
430 print_string(L
"AI", -1, pwptr
, plen
);
435 if (!IsValidAcl(pacl
))
438 count
= pacl
->AceCount
;
439 for (i
= 0; i
< count
; i
++)
442 if (!GetAce(pacl
, i
, &ace
))
444 if (!print_ace(ace
, pwptr
, plen
))
451 static BOOL
print_owner(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
456 if (!GetSecurityDescriptorOwner(sd
, &psid
, &defaulted
))
462 print_string(L
"O:", -1, pwptr
, plen
);
463 if (!print_sid(psid
, pwptr
, plen
))
468 static BOOL
print_group(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
473 if (!GetSecurityDescriptorGroup(sd
, &psid
, &defaulted
))
479 print_string(L
"G:", -1, pwptr
, plen
);
480 if (!print_sid(psid
, pwptr
, plen
))
485 static BOOL
print_dacl(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
487 SECURITY_DESCRIPTOR_CONTROL control
;
488 BOOL present
, defaulted
;
492 if (!GetSecurityDescriptorDacl(sd
, &present
, &pacl
, &defaulted
))
495 if (!GetSecurityDescriptorControl(sd
, &control
, &revision
))
501 print_string(L
"D:", -1, pwptr
, plen
);
502 if (!print_acl(pacl
, pwptr
, plen
, control
))
507 static BOOL
print_sacl(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
509 SECURITY_DESCRIPTOR_CONTROL control
;
510 BOOL present
, defaulted
;
514 if (!GetSecurityDescriptorSacl(sd
, &present
, &pacl
, &defaulted
))
517 if (!GetSecurityDescriptorControl(sd
, &control
, &revision
))
523 print_string(L
"S:", -1, pwptr
, plen
);
524 if (!print_acl(pacl
, pwptr
, plen
, control
))
529 /******************************************************************************
530 * ConvertSecurityDescriptorToStringSecurityDescriptorW (sechost.@)
532 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertSecurityDescriptorToStringSecurityDescriptorW( PSECURITY_DESCRIPTOR sd
,
533 DWORD revision
, SECURITY_INFORMATION flags
, WCHAR
**string
, ULONG
*ret_len
)
538 if (revision
!= SDDL_REVISION_1
)
540 ERR("Unhandled SDDL revision %ld\n", revision
);
541 SetLastError( ERROR_UNKNOWN_REVISION
);
545 if ((flags
& OWNER_SECURITY_INFORMATION
) && !print_owner(sd
, NULL
, &len
))
547 if ((flags
& GROUP_SECURITY_INFORMATION
) && !print_group(sd
, NULL
, &len
))
549 if ((flags
& DACL_SECURITY_INFORMATION
) && !print_dacl(sd
, NULL
, &len
))
551 if ((flags
& SACL_SECURITY_INFORMATION
) && !print_sacl(sd
, NULL
, &len
))
554 wstr
= wptr
= LocalAlloc( 0, (len
+ 1) * sizeof(WCHAR
) );
555 if ((flags
& OWNER_SECURITY_INFORMATION
) && !print_owner(sd
, &wptr
, NULL
))
560 if ((flags
& GROUP_SECURITY_INFORMATION
) && !print_group(sd
, &wptr
, NULL
))
565 if ((flags
& DACL_SECURITY_INFORMATION
) && !print_dacl(sd
, &wptr
, NULL
))
570 if ((flags
& SACL_SECURITY_INFORMATION
) && !print_sacl(sd
, &wptr
, NULL
))
577 TRACE("ret: %s, %ld\n", wine_dbgstr_w(wstr
), len
);
579 if (ret_len
) *ret_len
= wcslen(*string
) + 1;
583 static BOOL
get_computer_sid( PSID sid
)
585 static const struct /* same fields as struct SID */
588 BYTE SubAuthorityCount
;
589 SID_IDENTIFIER_AUTHORITY IdentifierAuthority
;
590 DWORD SubAuthority
[4];
592 { SID_REVISION
, 4, { SECURITY_NT_AUTHORITY
}, { SECURITY_NT_NON_UNIQUE
, 0, 0, 0 } };
594 memcpy( sid
, &computer_sid
, sizeof(computer_sid
) );
598 static BOOL
parse_token( const WCHAR
*string
, const WCHAR
**end
, DWORD
*result
)
600 if (string
[0] == '0' && (string
[1] == 'X' || string
[1] == 'x'))
603 *result
= wcstoul( string
+ 2, (WCHAR
**)&string
, 16 );
609 else if (iswdigit(string
[0]) || string
[0] == '-')
611 *result
= wcstoul( string
, (WCHAR
**)&string
, 10 );
623 static DWORD
get_sid_size( const WCHAR
*string
, const WCHAR
**end
)
625 if ((string
[0] == 'S' || string
[0] == 's') && string
[1] == '-') /* S-R-I(-S)+ */
632 while (parse_token( string
, &string
, &value
))
638 if (token_count
>= 3)
639 return GetSidLengthRequired( token_count
- 2 );
641 else /* String constant format - Only available in winxp and above */
648 for (i
= 0; i
< ARRAY_SIZE(well_known_sids
); i
++)
650 if (!wcsnicmp( well_known_sids
[i
].str
, string
, 2 ))
651 return GetSidLengthRequired( well_known_sids
[i
].sid
.SubAuthorityCount
);
654 for (i
= 0; i
< ARRAY_SIZE(well_known_rids
); i
++)
656 if (!wcsnicmp( well_known_rids
[i
].str
, string
, 2 ))
658 struct max_sid local
;
659 get_computer_sid(&local
);
660 return GetSidLengthRequired( *GetSidSubAuthorityCount(&local
) + 1 );
665 return GetSidLengthRequired( 0 );
668 static BOOL
parse_sid( const WCHAR
*string
, const WCHAR
**end
, SID
*pisid
, DWORD
*size
)
670 while (*string
== ' ')
673 *size
= get_sid_size( string
, end
);
674 if (!pisid
) /* Simply compute the size */
677 if ((string
[0] == 'S' || string
[0] == 's') && string
[1] == '-') /* S-R-I-S-S */
679 DWORD i
= 0, identAuth
;
680 DWORD csubauth
= ((*size
- GetSidLengthRequired(0)) / sizeof(DWORD
));
683 string
+= 2; /* Advance to Revision */
684 parse_token( string
, &string
, &token
);
685 pisid
->Revision
= token
;
687 if (pisid
->Revision
!= SDDL_REVISION
)
689 TRACE("Revision %d is unknown\n", pisid
->Revision
);
690 SetLastError( ERROR_INVALID_SID
);
695 TRACE("SubAuthorityCount is 0\n");
696 SetLastError( ERROR_INVALID_SID
);
700 pisid
->SubAuthorityCount
= csubauth
;
702 /* MS' implementation can't handle values greater than 2^32 - 1, so
703 * we don't either; assume most significant bytes are always 0
705 pisid
->IdentifierAuthority
.Value
[0] = 0;
706 pisid
->IdentifierAuthority
.Value
[1] = 0;
707 parse_token( string
, &string
, &identAuth
);
708 pisid
->IdentifierAuthority
.Value
[5] = identAuth
& 0xff;
709 pisid
->IdentifierAuthority
.Value
[4] = (identAuth
& 0xff00) >> 8;
710 pisid
->IdentifierAuthority
.Value
[3] = (identAuth
& 0xff0000) >> 16;
711 pisid
->IdentifierAuthority
.Value
[2] = (identAuth
& 0xff000000) >> 24;
713 while (parse_token( string
, &string
, &token
))
715 pisid
->SubAuthority
[i
++] = token
;
718 if (i
!= pisid
->SubAuthorityCount
)
720 SetLastError( ERROR_INVALID_SID
);
725 assert(*end
== string
);
729 else /* String constant format - Only available in winxp and above */
732 pisid
->Revision
= SDDL_REVISION
;
734 for (i
= 0; i
< ARRAY_SIZE(well_known_sids
); i
++)
736 if (!wcsnicmp(well_known_sids
[i
].str
, string
, 2))
739 pisid
->SubAuthorityCount
= well_known_sids
[i
].sid
.SubAuthorityCount
;
740 pisid
->IdentifierAuthority
= well_known_sids
[i
].sid
.IdentifierAuthority
;
741 for (j
= 0; j
< well_known_sids
[i
].sid
.SubAuthorityCount
; j
++)
742 pisid
->SubAuthority
[j
] = well_known_sids
[i
].sid
.SubAuthority
[j
];
747 for (i
= 0; i
< ARRAY_SIZE(well_known_rids
); i
++)
749 if (!wcsnicmp(well_known_rids
[i
].str
, string
, 2))
751 get_computer_sid(pisid
);
752 pisid
->SubAuthority
[pisid
->SubAuthorityCount
] = well_known_rids
[i
].rid
;
753 pisid
->SubAuthorityCount
++;
758 FIXME("String constant not supported: %s\n", debugstr_wn(string
, 2));
759 SetLastError( ERROR_INVALID_SID
);
764 /******************************************************************************
765 * ConvertStringSidToSidW (sechost.@)
767 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertStringSidToSidW( const WCHAR
*string
, PSID
*sid
)
770 const WCHAR
*string_end
;
772 TRACE("%s, %p\n", debugstr_w(string
), sid
);
774 if (GetVersion() & 0x80000000)
776 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
782 SetLastError(ERROR_INVALID_PARAMETER
);
786 if (!parse_sid( string
, &string_end
, NULL
, &size
))
791 SetLastError(ERROR_INVALID_SID
);
795 *sid
= LocalAlloc( 0, size
);
797 if (!parse_sid( string
, NULL
, *sid
, &size
))
805 static DWORD
parse_acl_flags( const WCHAR
**string_ptr
)
808 const WCHAR
*string
= *string_ptr
;
810 while (*string
&& *string
!= '(')
814 flags
|= SE_DACL_PROTECTED
;
816 else if (*string
== 'A')
820 flags
|= SE_DACL_AUTO_INHERIT_REQ
;
821 else if (*string
== 'I')
822 flags
|= SE_DACL_AUTO_INHERITED
;
827 *string_ptr
= string
;
831 static BYTE
parse_ace_type( const WCHAR
**string_ptr
)
840 { L
"AL", SYSTEM_ALARM_ACE_TYPE
},
841 { L
"AU", SYSTEM_AUDIT_ACE_TYPE
},
842 { L
"A", ACCESS_ALLOWED_ACE_TYPE
},
843 { L
"D", ACCESS_DENIED_ACE_TYPE
},
844 { L
"ML", SYSTEM_MANDATORY_LABEL_ACE_TYPE
},
846 { ACCESS_ALLOWED_OBJECT_ACE_TYPE },
847 { ACCESS_DENIED_OBJECT_ACE_TYPE },
848 { SYSTEM_ALARM_OBJECT_ACE_TYPE },
849 { SYSTEM_AUDIT_OBJECT_ACE_TYPE },
853 const WCHAR
*string
= *string_ptr
;
856 while (*string
== ' ')
859 for (i
= 0; i
< ARRAY_SIZE(ace_types
); ++i
)
861 size_t len
= wcslen( ace_types
[i
].str
);
862 if (!wcsncmp( string
, ace_types
[i
].str
, len
))
864 *string_ptr
= string
+ len
;
865 return ace_types
[i
].value
;
871 static DWORD
parse_ace_flag( const WCHAR
*string
)
880 { L
"CI", CONTAINER_INHERIT_ACE
},
881 { L
"FA", FAILED_ACCESS_ACE_FLAG
},
882 { L
"ID", INHERITED_ACE
},
883 { L
"IO", INHERIT_ONLY_ACE
},
884 { L
"NP", NO_PROPAGATE_INHERIT_ACE
},
885 { L
"OI", OBJECT_INHERIT_ACE
},
886 { L
"SA", SUCCESSFUL_ACCESS_ACE_FLAG
},
891 for (i
= 0; i
< ARRAY_SIZE(ace_flags
); ++i
)
893 if (!wcsncmp( string
, ace_flags
[i
].str
, 2 ))
894 return ace_flags
[i
].value
;
899 static DWORD
parse_ace_right( const WCHAR
**string_ptr
)
901 const WCHAR
*string
= *string_ptr
;
904 if (iswdigit( string
[0] ))
905 return wcstoul( string
, (WCHAR
**)string_ptr
, 0 );
907 for (i
= 0; i
< ARRAY_SIZE(ace_rights
); ++i
)
909 if (!wcsncmp( string
, ace_rights
[i
].str
, 2 ))
912 return ace_rights
[i
].value
;
918 static BYTE
parse_ace_flags( const WCHAR
**string_ptr
)
920 const WCHAR
*string
= *string_ptr
;
923 while (*string
== ' ')
926 while (*string
!= ';')
928 DWORD flag
= parse_ace_flag( string
);
934 *string_ptr
= string
;
938 static DWORD
parse_ace_rights( const WCHAR
**string_ptr
)
941 const WCHAR
*string
= *string_ptr
;
943 while (*string
== ' ')
946 while (*string
!= ';')
948 DWORD right
= parse_ace_right( &string
);
949 if (!right
) return 0;
953 *string_ptr
= string
;
957 static BOOL
parse_acl( const WCHAR
*string
, DWORD
*flags
, ACL
*acl
, DWORD
*ret_size
)
961 DWORD length
= sizeof(ACL
);
964 ACCESS_ALLOWED_ACE
*ace
= NULL
; /* pointer to current ACE */
966 TRACE("%s\n", debugstr_w(string
));
968 if (acl
) /* ace is only useful if we're setting values */
969 ace
= (ACCESS_ALLOWED_ACE
*)(acl
+ 1);
971 /* Parse ACL flags */
972 *flags
= parse_acl_flags( &string
);
975 while (*string
== '(')
980 val
= parse_ace_type( &string
);
982 ace
->Header
.AceType
= val
;
985 SetLastError( RPC_S_INVALID_STRING_UUID
);
990 /* Parse ACE flags */
991 val
= parse_ace_flags( &string
);
993 ace
->Header
.AceFlags
= val
;
998 /* Parse ACE rights */
999 val
= parse_ace_rights( &string
);
1006 /* Parse ACE object guid */
1007 while (*string
== ' ')
1011 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1016 /* Parse ACE inherit object guid */
1017 while (*string
== ' ')
1021 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1026 /* Parse ACE account sid */
1027 if (!parse_sid( string
, &string
, ace
? (SID
*)&ace
->SidStart
: NULL
, &sidlen
))
1030 while (*string
== ' ')
1037 acesize
= sizeof(ACCESS_ALLOWED_ACE
) - sizeof(DWORD
) + sidlen
;
1041 ace
->Header
.AceSize
= acesize
;
1042 ace
= (ACCESS_ALLOWED_ACE
*)((BYTE
*)ace
+ acesize
);
1049 if (length
> 0xffff)
1051 ERR("ACL too large\n");
1057 acl
->AclRevision
= ACL_REVISION
;
1059 acl
->AclSize
= length
;
1060 acl
->AceCount
= acecount
;
1066 SetLastError( ERROR_INVALID_ACL
);
1067 WARN("Invalid ACE string format\n");
1071 static BOOL
parse_sd( const WCHAR
*string
, SECURITY_DESCRIPTOR_RELATIVE
*sd
, DWORD
*size
)
1076 const WCHAR
*lptoken
;
1080 *size
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
1082 tok
= malloc( (wcslen(string
) + 1) * sizeof(WCHAR
) );
1085 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1090 next
= (BYTE
*)(sd
+ 1);
1092 while (*string
== ' ')
1099 /* Expect char identifier followed by ':' */
1103 SetLastError( ERROR_INVALID_PARAMETER
);
1110 while (*lptoken
&& *lptoken
!= ':')
1116 len
= lptoken
- string
;
1117 memcpy( tok
, string
, len
* sizeof(WCHAR
) );
1126 if (!parse_sid( tok
, NULL
, (SID
*)next
, &bytes
))
1131 sd
->Owner
= next
- (BYTE
*)sd
;
1132 next
+= bytes
; /* Advance to next token */
1144 if (!parse_sid( tok
, NULL
, (SID
*)next
, &bytes
))
1149 sd
->Group
= next
- (BYTE
*)sd
;
1150 next
+= bytes
; /* Advance to next token */
1163 if (!parse_acl( tok
, &flags
, (ACL
*)next
, &bytes
))
1168 sd
->Control
|= SE_DACL_PRESENT
| flags
;
1169 sd
->Dacl
= next
- (BYTE
*)sd
;
1170 next
+= bytes
; /* Advance to next token */
1183 if (!parse_acl( tok
, &flags
, (ACL
*)next
, &bytes
))
1188 sd
->Control
|= SE_SACL_PRESENT
| flags
;
1189 sd
->Sacl
= next
- (BYTE
*)sd
;
1190 next
+= bytes
; /* Advance to next token */
1199 FIXME("Unknown token\n");
1200 SetLastError( ERROR_INVALID_PARAMETER
);
1214 /******************************************************************************
1215 * ConvertStringSecurityDescriptorToSecurityDescriptorW (sechost.@)
1217 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertStringSecurityDescriptorToSecurityDescriptorW(
1218 const WCHAR
*string
, DWORD revision
, PSECURITY_DESCRIPTOR
*sd
, ULONG
*ret_size
)
1221 SECURITY_DESCRIPTOR
*psd
;
1223 TRACE("%s, %lu, %p, %p\n", debugstr_w(string
), revision
, sd
, ret_size
);
1225 if (GetVersion() & 0x80000000)
1227 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1232 SetLastError(ERROR_INVALID_PARAMETER
);
1235 if (revision
!= SID_REVISION
)
1237 SetLastError(ERROR_UNKNOWN_REVISION
);
1241 /* Compute security descriptor length */
1242 if (!parse_sd( string
, NULL
, &size
))
1245 psd
= *sd
= LocalAlloc( GMEM_ZEROINIT
, size
);
1248 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1252 psd
->Revision
= SID_REVISION
;
1253 psd
->Control
|= SE_SELF_RELATIVE
;
1255 if (!parse_sd( string
, (SECURITY_DESCRIPTOR_RELATIVE
*)psd
, &size
))
1261 if (ret_size
) *ret_size
= size
;