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
28 #include "wine/debug.h"
29 #include "wine/heap.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(security
);
40 { L
"GA", GENERIC_ALL
},
41 { L
"GR", GENERIC_READ
},
42 { L
"GW", GENERIC_WRITE
},
43 { L
"GX", GENERIC_EXECUTE
},
45 { L
"RC", READ_CONTROL
},
48 { L
"WO", WRITE_OWNER
},
50 { L
"RP", ADS_RIGHT_DS_READ_PROP
},
51 { L
"WP", ADS_RIGHT_DS_WRITE_PROP
},
52 { L
"CC", ADS_RIGHT_DS_CREATE_CHILD
},
53 { L
"DC", ADS_RIGHT_DS_DELETE_CHILD
},
54 { L
"LC", ADS_RIGHT_ACTRL_DS_LIST
},
55 { L
"SW", ADS_RIGHT_DS_SELF
},
56 { L
"LO", ADS_RIGHT_DS_LIST_OBJECT
},
57 { L
"DT", ADS_RIGHT_DS_DELETE_TREE
},
58 { L
"CR", ADS_RIGHT_DS_CONTROL_ACCESS
},
60 { L
"FA", FILE_ALL_ACCESS
},
61 { L
"FR", FILE_GENERIC_READ
},
62 { L
"FW", FILE_GENERIC_WRITE
},
63 { L
"FX", FILE_GENERIC_EXECUTE
},
65 { L
"KA", KEY_ALL_ACCESS
},
68 { L
"KX", KEY_EXECUTE
},
70 { L
"NR", SYSTEM_MANDATORY_LABEL_NO_READ_UP
},
71 { L
"NW", SYSTEM_MANDATORY_LABEL_NO_WRITE_UP
},
72 { L
"NX", SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP
},
77 /* same fields as struct _SID */
79 BYTE SubAuthorityCount
;
80 SID_IDENTIFIER_AUTHORITY IdentifierAuthority
;
81 DWORD SubAuthority
[SID_MAX_SUB_AUTHORITIES
];
87 WELL_KNOWN_SID_TYPE Type
;
92 { {0,0}, WinNullSid
, { SID_REVISION
, 1, { SECURITY_NULL_SID_AUTHORITY
}, { SECURITY_NULL_RID
} } },
93 { {'W','D'}, WinWorldSid
, { SID_REVISION
, 1, { SECURITY_WORLD_SID_AUTHORITY
}, { SECURITY_WORLD_RID
} } },
94 { {0,0}, WinLocalSid
, { SID_REVISION
, 1, { SECURITY_LOCAL_SID_AUTHORITY
}, { SECURITY_LOCAL_RID
} } },
95 { {'C','O'}, WinCreatorOwnerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_RID
} } },
96 { {'C','G'}, WinCreatorGroupSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_GROUP_RID
} } },
97 { {'O','W'}, WinCreatorOwnerRightsSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_RIGHTS_RID
} } },
98 { {0,0}, WinCreatorOwnerServerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_SERVER_RID
} } },
99 { {0,0}, WinCreatorGroupServerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_GROUP_SERVER_RID
} } },
100 { {0,0}, WinNtAuthoritySid
, { SID_REVISION
, 0, { SECURITY_NT_AUTHORITY
}, { SECURITY_NULL_RID
} } },
101 { {0,0}, WinDialupSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_DIALUP_RID
} } },
102 { {'N','U'}, WinNetworkSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_NETWORK_RID
} } },
103 { {0,0}, WinBatchSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_BATCH_RID
} } },
104 { {'I','U'}, WinInteractiveSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_INTERACTIVE_RID
} } },
105 { {'S','U'}, WinServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_SERVICE_RID
} } },
106 { {'A','N'}, WinAnonymousSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_ANONYMOUS_LOGON_RID
} } },
107 { {0,0}, WinProxySid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_PROXY_RID
} } },
108 { {'E','D'}, WinEnterpriseControllersSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_ENTERPRISE_CONTROLLERS_RID
} } },
109 { {'P','S'}, WinSelfSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_PRINCIPAL_SELF_RID
} } },
110 { {'A','U'}, WinAuthenticatedUserSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_AUTHENTICATED_USER_RID
} } },
111 { {'R','C'}, WinRestrictedCodeSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_RESTRICTED_CODE_RID
} } },
112 { {0,0}, WinTerminalServerSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_TERMINAL_SERVER_RID
} } },
113 { {0,0}, WinRemoteLogonIdSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_REMOTE_LOGON_RID
} } },
114 { {0,0}, WinLogonIdsSid
, { SID_REVISION
, SECURITY_LOGON_IDS_RID_COUNT
, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOGON_IDS_RID
} } },
115 { {'S','Y'}, WinLocalSystemSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOCAL_SYSTEM_RID
} } },
116 { {'L','S'}, WinLocalServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOCAL_SERVICE_RID
} } },
117 { {'N','S'}, WinNetworkServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_NETWORK_SERVICE_RID
} } },
118 { {0,0}, WinBuiltinDomainSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
} } },
119 { {'B','A'}, WinBuiltinAdministratorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ADMINS
} } },
120 { {'B','U'}, WinBuiltinUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_USERS
} } },
121 { {'B','G'}, WinBuiltinGuestsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_GUESTS
} } },
122 { {'P','U'}, WinBuiltinPowerUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_POWER_USERS
} } },
123 { {'A','O'}, WinBuiltinAccountOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ACCOUNT_OPS
} } },
124 { {'S','O'}, WinBuiltinSystemOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_SYSTEM_OPS
} } },
125 { {'P','O'}, WinBuiltinPrintOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_PRINT_OPS
} } },
126 { {'B','O'}, WinBuiltinBackupOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_BACKUP_OPS
} } },
127 { {'R','E'}, WinBuiltinReplicatorSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_REPLICATOR
} } },
128 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS
} } },
129 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS
} } },
130 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS
} } },
131 { {0,0}, WinNTLMAuthenticationSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_PACKAGE_BASE_RID
, SECURITY_PACKAGE_NTLM_RID
} } },
132 { {0,0}, WinDigestAuthenticationSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_PACKAGE_BASE_RID
, SECURITY_PACKAGE_DIGEST_RID
} } },
133 { {0,0}, WinSChannelAuthenticationSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_PACKAGE_BASE_RID
, SECURITY_PACKAGE_SCHANNEL_RID
} } },
134 { {0,0}, WinThisOrganizationSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_THIS_ORGANIZATION_RID
} } },
135 { {0,0}, WinOtherOrganizationSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_OTHER_ORGANIZATION_RID
} } },
136 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS
} } },
137 { {0,0}, WinBuiltinPerfMonitoringUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_MONITORING_USERS
} } },
138 { {0,0}, WinBuiltinPerfLoggingUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_LOGGING_USERS
} } },
139 { {0,0}, WinBuiltinAuthorizationAccessSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS
} } },
140 { {0,0}, WinBuiltinTerminalServerLicenseServersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS
} } },
141 { {0,0}, WinBuiltinDCOMUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_DCOM_USERS
} } },
142 { {'L','W'}, WinLowLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_LOW_RID
} } },
143 { {'M','E'}, WinMediumLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_MEDIUM_RID
} } },
144 { {'H','I'}, WinHighLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_HIGH_RID
} } },
145 { {'S','I'}, WinSystemLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_SYSTEM_RID
} } },
146 { {'A','C'}, WinBuiltinAnyPackageSid
, { SID_REVISION
, 2, { SECURITY_APP_PACKAGE_AUTHORITY
}, { SECURITY_APP_PACKAGE_BASE_RID
, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE
} } },
149 /* these SIDs must be constructed as relative to some domain - only the RID is well-known */
153 WELL_KNOWN_SID_TYPE type
;
158 { {'L','A'}, WinAccountAdministratorSid
, DOMAIN_USER_RID_ADMIN
},
159 { {'L','G'}, WinAccountGuestSid
, DOMAIN_USER_RID_GUEST
},
160 { {0,0}, WinAccountKrbtgtSid
, DOMAIN_USER_RID_KRBTGT
},
161 { {'D','A'}, WinAccountDomainAdminsSid
, DOMAIN_GROUP_RID_ADMINS
},
162 { {'D','U'}, WinAccountDomainUsersSid
, DOMAIN_GROUP_RID_USERS
},
163 { {'D','G'}, WinAccountDomainGuestsSid
, DOMAIN_GROUP_RID_GUESTS
},
164 { {'D','C'}, WinAccountComputersSid
, DOMAIN_GROUP_RID_COMPUTERS
},
165 { {'D','D'}, WinAccountControllersSid
, DOMAIN_GROUP_RID_CONTROLLERS
},
166 { {'C','A'}, WinAccountCertAdminsSid
, DOMAIN_GROUP_RID_CERT_ADMINS
},
167 { {'S','A'}, WinAccountSchemaAdminsSid
, DOMAIN_GROUP_RID_SCHEMA_ADMINS
},
168 { {'E','A'}, WinAccountEnterpriseAdminsSid
, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS
},
169 { {'P','A'}, WinAccountPolicyAdminsSid
, DOMAIN_GROUP_RID_POLICY_ADMINS
},
170 { {'R','S'}, WinAccountRasAndIasServersSid
, DOMAIN_ALIAS_RID_RAS_SERVERS
},
174 static void print_string(const WCHAR
*string
, int cch
, WCHAR
**pwptr
, ULONG
*plen
)
177 cch
= wcslen(string
);
184 memcpy(*pwptr
, string
, sizeof(WCHAR
)*cch
);
189 static BOOL
print_sid_numeric(PSID psid
, WCHAR
**pwptr
, ULONG
*plen
)
195 if( !IsValidSid( psid
) || pisid
->Revision
!= SDDL_REVISION
)
197 SetLastError(ERROR_INVALID_SID
);
201 if (pisid
->IdentifierAuthority
.Value
[0] ||
202 pisid
->IdentifierAuthority
.Value
[1])
204 FIXME("not matching MS' bugs\n");
205 SetLastError(ERROR_INVALID_SID
);
209 swprintf( buf
, ARRAY_SIZE(buf
), L
"S-%u-%d", pisid
->Revision
, MAKELONG(
210 MAKEWORD( pisid
->IdentifierAuthority
.Value
[5], pisid
->IdentifierAuthority
.Value
[4] ),
211 MAKEWORD( pisid
->IdentifierAuthority
.Value
[3], pisid
->IdentifierAuthority
.Value
[2] )
213 print_string(buf
, -1, pwptr
, plen
);
215 for( i
=0; i
<pisid
->SubAuthorityCount
; i
++ )
217 swprintf( buf
, ARRAY_SIZE(buf
), L
"-%u", pisid
->SubAuthority
[i
] );
218 print_string(buf
, -1, pwptr
, plen
);
223 /******************************************************************************
224 * ConvertSidToStringSidW (sechost.@)
226 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertSidToStringSidW( PSID sid
, WCHAR
**pstr
)
231 TRACE("%p %p\n", sid
, pstr
);
234 if (!print_sid_numeric( sid
, NULL
, &len
))
236 wstr
= wptr
= LocalAlloc( 0, (len
+ 1) * sizeof(WCHAR
) );
237 print_sid_numeric( sid
, &wptr
, NULL
);
244 static BOOL
print_sid(PSID psid
, WCHAR
**pwptr
, ULONG
*plen
)
247 for (i
= 0; i
< ARRAY_SIZE(well_known_sids
); i
++)
249 if (well_known_sids
[i
].str
[0] && EqualSid(psid
, (PSID
)&well_known_sids
[i
].sid
.Revision
))
251 print_string(well_known_sids
[i
].str
, 2, pwptr
, plen
);
256 return print_sid_numeric(psid
, pwptr
, plen
);
259 static void print_rights(DWORD mask
, WCHAR
**pwptr
, ULONG
*plen
)
261 static const WCHAR
*bit_names
[32] =
303 /* first check if the right have name */
304 for (i
= 0; i
< ARRAY_SIZE(ace_rights
); i
++)
306 if (mask
== ace_rights
[i
].value
)
308 print_string(ace_rights
[i
].str
, -1, pwptr
, plen
);
313 /* then check if it can be built from bit names */
314 for (i
= 0; i
< 32; i
++)
316 if ((mask
& (1 << i
)) && !bit_names
[i
])
318 /* can't be built from bit names */
319 swprintf(buf
, ARRAY_SIZE(buf
), L
"0x%x", mask
);
320 print_string(buf
, -1, pwptr
, plen
);
325 /* build from bit names */
326 for (i
= 0; i
< 32; i
++)
328 print_string(bit_names
[i
], -1, pwptr
, plen
);
331 static inline BOOL
is_object_ace(BYTE type
)
335 case ACCESS_ALLOWED_OBJECT_ACE_TYPE
:
336 case ACCESS_DENIED_OBJECT_ACE_TYPE
:
337 case ACCESS_AUDIT_OBJECT_ACE_TYPE
:
338 case ACCESS_ALARM_OBJECT_ACE_TYPE
:
339 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE
:
340 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE
:
341 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE
:
342 case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE
:
350 static BOOL
print_ace(void *pace
, WCHAR
**pwptr
, ULONG
*plen
)
352 ACCESS_ALLOWED_ACE
*piace
; /* all the supported ACEs have the same memory layout */
357 if (piace
->Header
.AceType
> ACCESS_MAX_MS_V5_ACE_TYPE
|| piace
->Header
.AceSize
< sizeof(ACCESS_ALLOWED_ACE
))
359 SetLastError(ERROR_INVALID_ACL
);
363 print_string(L
"(", -1, pwptr
, plen
);
364 switch (piace
->Header
.AceType
)
366 case ACCESS_ALLOWED_ACE_TYPE
:
367 print_string(L
"A", -1, pwptr
, plen
);
369 case ACCESS_DENIED_ACE_TYPE
:
370 print_string(L
"D", -1, pwptr
, plen
);
372 case SYSTEM_AUDIT_ACE_TYPE
:
373 print_string(L
"AU", -1, pwptr
, plen
);
375 case SYSTEM_ALARM_ACE_TYPE
:
376 print_string(L
"AL", -1, pwptr
, plen
);
379 print_string(L
";", -1, pwptr
, plen
);
381 if (piace
->Header
.AceFlags
& OBJECT_INHERIT_ACE
)
382 print_string(L
"OI", -1, pwptr
, plen
);
383 if (piace
->Header
.AceFlags
& CONTAINER_INHERIT_ACE
)
384 print_string(L
"CI", -1, pwptr
, plen
);
385 if (piace
->Header
.AceFlags
& NO_PROPAGATE_INHERIT_ACE
)
386 print_string(L
"NP", -1, pwptr
, plen
);
387 if (piace
->Header
.AceFlags
& INHERIT_ONLY_ACE
)
388 print_string(L
"IO", -1, pwptr
, plen
);
389 if (piace
->Header
.AceFlags
& INHERITED_ACE
)
390 print_string(L
"ID", -1, pwptr
, plen
);
391 if (piace
->Header
.AceFlags
& SUCCESSFUL_ACCESS_ACE_FLAG
)
392 print_string(L
"SA", -1, pwptr
, plen
);
393 if (piace
->Header
.AceFlags
& FAILED_ACCESS_ACE_FLAG
)
394 print_string(L
"FA", -1, pwptr
, plen
);
395 print_string(L
";", -1, pwptr
, plen
);
396 print_rights(piace
->Mask
, pwptr
, plen
);
397 print_string(L
";", -1, pwptr
, plen
);
398 sid_start
= &piace
->SidStart
;
399 if (is_object_ace(piace
->Header
.AceType
))
401 ACCESS_ALLOWED_OBJECT_ACE
*objace
= pace
;
403 sid_start
++; /* Flags */
404 if (objace
->Flags
& ACE_OBJECT_TYPE_PRESENT
)
405 sid_start
+= sizeof(GUID
) / sizeof(*sid_start
); /* ObjectType */
406 if (objace
->Flags
& ACE_INHERITED_OBJECT_TYPE_PRESENT
)
407 sid_start
+= sizeof(GUID
) / sizeof(*sid_start
); /* InheritedObjectType */
409 /* objects not supported */
410 print_string(L
";", -1, pwptr
, plen
);
411 /* objects not supported */
412 print_string(L
";", -1, pwptr
, plen
);
413 if (!print_sid(sid_start
, pwptr
, plen
))
415 print_string(L
")", -1, pwptr
, plen
);
419 static BOOL
print_acl(ACL
*pacl
, WCHAR
**pwptr
, ULONG
*plen
, SECURITY_DESCRIPTOR_CONTROL control
)
424 if (control
& SE_DACL_PROTECTED
)
425 print_string(L
"P", -1, pwptr
, plen
);
426 if (control
& SE_DACL_AUTO_INHERIT_REQ
)
427 print_string(L
"AR", -1, pwptr
, plen
);
428 if (control
& SE_DACL_AUTO_INHERITED
)
429 print_string(L
"AI", -1, pwptr
, plen
);
434 if (!IsValidAcl(pacl
))
437 count
= pacl
->AceCount
;
438 for (i
= 0; i
< count
; i
++)
441 if (!GetAce(pacl
, i
, &ace
))
443 if (!print_ace(ace
, pwptr
, plen
))
450 static BOOL
print_owner(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
455 if (!GetSecurityDescriptorOwner(sd
, &psid
, &defaulted
))
461 print_string(L
"O:", -1, pwptr
, plen
);
462 if (!print_sid(psid
, pwptr
, plen
))
467 static BOOL
print_group(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
472 if (!GetSecurityDescriptorGroup(sd
, &psid
, &defaulted
))
478 print_string(L
"G:", -1, pwptr
, plen
);
479 if (!print_sid(psid
, pwptr
, plen
))
484 static BOOL
print_dacl(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
486 SECURITY_DESCRIPTOR_CONTROL control
;
487 BOOL present
, defaulted
;
491 if (!GetSecurityDescriptorDacl(sd
, &present
, &pacl
, &defaulted
))
494 if (!GetSecurityDescriptorControl(sd
, &control
, &revision
))
500 print_string(L
"D:", -1, pwptr
, plen
);
501 if (!print_acl(pacl
, pwptr
, plen
, control
))
506 static BOOL
print_sacl(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
508 SECURITY_DESCRIPTOR_CONTROL control
;
509 BOOL present
, defaulted
;
513 if (!GetSecurityDescriptorSacl(sd
, &present
, &pacl
, &defaulted
))
516 if (!GetSecurityDescriptorControl(sd
, &control
, &revision
))
522 print_string(L
"S:", -1, pwptr
, plen
);
523 if (!print_acl(pacl
, pwptr
, plen
, control
))
528 /******************************************************************************
529 * ConvertSecurityDescriptorToStringSecurityDescriptorW (sechost.@)
531 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertSecurityDescriptorToStringSecurityDescriptorW( PSECURITY_DESCRIPTOR sd
,
532 DWORD revision
, SECURITY_INFORMATION flags
, WCHAR
**string
, ULONG
*ret_len
)
537 if (revision
!= SDDL_REVISION_1
)
539 ERR("Unhandled SDDL revision %ld\n", revision
);
540 SetLastError( ERROR_UNKNOWN_REVISION
);
544 if ((flags
& OWNER_SECURITY_INFORMATION
) && !print_owner(sd
, NULL
, &len
))
546 if ((flags
& GROUP_SECURITY_INFORMATION
) && !print_group(sd
, NULL
, &len
))
548 if ((flags
& DACL_SECURITY_INFORMATION
) && !print_dacl(sd
, NULL
, &len
))
550 if ((flags
& SACL_SECURITY_INFORMATION
) && !print_sacl(sd
, NULL
, &len
))
553 wstr
= wptr
= LocalAlloc( 0, (len
+ 1) * sizeof(WCHAR
) );
554 if ((flags
& OWNER_SECURITY_INFORMATION
) && !print_owner(sd
, &wptr
, NULL
))
559 if ((flags
& GROUP_SECURITY_INFORMATION
) && !print_group(sd
, &wptr
, NULL
))
564 if ((flags
& DACL_SECURITY_INFORMATION
) && !print_dacl(sd
, &wptr
, NULL
))
569 if ((flags
& SACL_SECURITY_INFORMATION
) && !print_sacl(sd
, &wptr
, NULL
))
576 TRACE("ret: %s, %ld\n", wine_dbgstr_w(wstr
), len
);
578 if (ret_len
) *ret_len
= wcslen(*string
) + 1;
582 static BOOL
get_computer_sid( PSID sid
)
584 static const struct /* same fields as struct SID */
587 BYTE SubAuthorityCount
;
588 SID_IDENTIFIER_AUTHORITY IdentifierAuthority
;
589 DWORD SubAuthority
[4];
591 { SID_REVISION
, 4, { SECURITY_NT_AUTHORITY
}, { SECURITY_NT_NON_UNIQUE
, 0, 0, 0 } };
593 memcpy( sid
, &computer_sid
, sizeof(computer_sid
) );
597 static BOOL
parse_token( const WCHAR
*string
, const WCHAR
**end
, DWORD
*result
)
599 if (string
[0] == '0' && (string
[1] == 'X' || string
[1] == 'x'))
602 *result
= wcstoul( string
+ 2, (WCHAR
**)&string
, 16 );
608 else if (iswdigit(string
[0]) || string
[0] == '-')
610 *result
= wcstoul( string
, (WCHAR
**)&string
, 10 );
622 static DWORD
get_sid_size( const WCHAR
*string
, const WCHAR
**end
)
624 if ((string
[0] == 'S' || string
[0] == 's') && string
[1] == '-') /* S-R-I(-S)+ */
631 while (parse_token( string
, &string
, &value
))
637 if (token_count
>= 3)
638 return GetSidLengthRequired( token_count
- 2 );
640 else /* String constant format - Only available in winxp and above */
647 for (i
= 0; i
< ARRAY_SIZE(well_known_sids
); i
++)
649 if (!wcsnicmp( well_known_sids
[i
].str
, string
, 2 ))
650 return GetSidLengthRequired( well_known_sids
[i
].sid
.SubAuthorityCount
);
653 for (i
= 0; i
< ARRAY_SIZE(well_known_rids
); i
++)
655 if (!wcsnicmp( well_known_rids
[i
].str
, string
, 2 ))
657 struct max_sid local
;
658 get_computer_sid(&local
);
659 return GetSidLengthRequired( *GetSidSubAuthorityCount(&local
) + 1 );
664 return GetSidLengthRequired( 0 );
667 static BOOL
parse_sid( const WCHAR
*string
, const WCHAR
**end
, SID
*pisid
, DWORD
*size
)
669 while (*string
== ' ')
672 *size
= get_sid_size( string
, end
);
673 if (!pisid
) /* Simply compute the size */
676 if ((string
[0] == 'S' || string
[0] == 's') && string
[1] == '-') /* S-R-I-S-S */
678 DWORD i
= 0, identAuth
;
679 DWORD csubauth
= ((*size
- GetSidLengthRequired(0)) / sizeof(DWORD
));
682 string
+= 2; /* Advance to Revision */
683 parse_token( string
, &string
, &token
);
684 pisid
->Revision
= token
;
686 if (pisid
->Revision
!= SDDL_REVISION
)
688 TRACE("Revision %d is unknown\n", pisid
->Revision
);
689 SetLastError( ERROR_INVALID_SID
);
694 TRACE("SubAuthorityCount is 0\n");
695 SetLastError( ERROR_INVALID_SID
);
699 pisid
->SubAuthorityCount
= csubauth
;
701 /* MS' implementation can't handle values greater than 2^32 - 1, so
702 * we don't either; assume most significant bytes are always 0
704 pisid
->IdentifierAuthority
.Value
[0] = 0;
705 pisid
->IdentifierAuthority
.Value
[1] = 0;
706 parse_token( string
, &string
, &identAuth
);
707 pisid
->IdentifierAuthority
.Value
[5] = identAuth
& 0xff;
708 pisid
->IdentifierAuthority
.Value
[4] = (identAuth
& 0xff00) >> 8;
709 pisid
->IdentifierAuthority
.Value
[3] = (identAuth
& 0xff0000) >> 16;
710 pisid
->IdentifierAuthority
.Value
[2] = (identAuth
& 0xff000000) >> 24;
712 while (parse_token( string
, &string
, &token
))
714 pisid
->SubAuthority
[i
++] = token
;
717 if (i
!= pisid
->SubAuthorityCount
)
719 SetLastError( ERROR_INVALID_SID
);
724 assert(*end
== string
);
728 else /* String constant format - Only available in winxp and above */
731 pisid
->Revision
= SDDL_REVISION
;
733 for (i
= 0; i
< ARRAY_SIZE(well_known_sids
); i
++)
735 if (!wcsnicmp(well_known_sids
[i
].str
, string
, 2))
738 pisid
->SubAuthorityCount
= well_known_sids
[i
].sid
.SubAuthorityCount
;
739 pisid
->IdentifierAuthority
= well_known_sids
[i
].sid
.IdentifierAuthority
;
740 for (j
= 0; j
< well_known_sids
[i
].sid
.SubAuthorityCount
; j
++)
741 pisid
->SubAuthority
[j
] = well_known_sids
[i
].sid
.SubAuthority
[j
];
746 for (i
= 0; i
< ARRAY_SIZE(well_known_rids
); i
++)
748 if (!wcsnicmp(well_known_rids
[i
].str
, string
, 2))
750 get_computer_sid(pisid
);
751 pisid
->SubAuthority
[pisid
->SubAuthorityCount
] = well_known_rids
[i
].rid
;
752 pisid
->SubAuthorityCount
++;
757 FIXME("String constant not supported: %s\n", debugstr_wn(string
, 2));
758 SetLastError( ERROR_INVALID_SID
);
763 /******************************************************************************
764 * ConvertStringSidToSidW (sechost.@)
766 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertStringSidToSidW( const WCHAR
*string
, PSID
*sid
)
769 const WCHAR
*string_end
;
771 TRACE("%s, %p\n", debugstr_w(string
), sid
);
773 if (GetVersion() & 0x80000000)
775 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
781 SetLastError(ERROR_INVALID_PARAMETER
);
785 if (!parse_sid( string
, &string_end
, NULL
, &size
))
790 SetLastError(ERROR_INVALID_SID
);
794 *sid
= LocalAlloc( 0, size
);
796 if (!parse_sid( string
, NULL
, *sid
, &size
))
804 static DWORD
parse_acl_flags( const WCHAR
**string_ptr
)
807 const WCHAR
*string
= *string_ptr
;
809 while (*string
&& *string
!= '(')
813 flags
|= SE_DACL_PROTECTED
;
815 else if (*string
== 'A')
819 flags
|= SE_DACL_AUTO_INHERIT_REQ
;
820 else if (*string
== 'I')
821 flags
|= SE_DACL_AUTO_INHERITED
;
826 *string_ptr
= string
;
830 static BYTE
parse_ace_type( const WCHAR
**string_ptr
)
839 { L
"AL", SYSTEM_ALARM_ACE_TYPE
},
840 { L
"AU", SYSTEM_AUDIT_ACE_TYPE
},
841 { L
"A", ACCESS_ALLOWED_ACE_TYPE
},
842 { L
"D", ACCESS_DENIED_ACE_TYPE
},
843 { L
"ML", SYSTEM_MANDATORY_LABEL_ACE_TYPE
},
845 { ACCESS_ALLOWED_OBJECT_ACE_TYPE },
846 { ACCESS_DENIED_OBJECT_ACE_TYPE },
847 { SYSTEM_ALARM_OBJECT_ACE_TYPE },
848 { SYSTEM_AUDIT_OBJECT_ACE_TYPE },
852 const WCHAR
*string
= *string_ptr
;
855 while (*string
== ' ')
858 for (i
= 0; i
< ARRAY_SIZE(ace_types
); ++i
)
860 size_t len
= wcslen( ace_types
[i
].str
);
861 if (!wcsncmp( string
, ace_types
[i
].str
, len
))
863 *string_ptr
= string
+ len
;
864 return ace_types
[i
].value
;
870 static DWORD
parse_ace_flag( const WCHAR
*string
)
879 { L
"CI", CONTAINER_INHERIT_ACE
},
880 { L
"FA", FAILED_ACCESS_ACE_FLAG
},
881 { L
"ID", INHERITED_ACE
},
882 { L
"IO", INHERIT_ONLY_ACE
},
883 { L
"NP", NO_PROPAGATE_INHERIT_ACE
},
884 { L
"OI", OBJECT_INHERIT_ACE
},
885 { L
"SA", SUCCESSFUL_ACCESS_ACE_FLAG
},
890 for (i
= 0; i
< ARRAY_SIZE(ace_flags
); ++i
)
892 if (!wcsncmp( string
, ace_flags
[i
].str
, 2 ))
893 return ace_flags
[i
].value
;
898 static DWORD
parse_ace_right( const WCHAR
**string_ptr
)
900 const WCHAR
*string
= *string_ptr
;
903 if (string
[0] == '0' && string
[1] == 'x')
904 return wcstoul( string
, (WCHAR
**)string_ptr
, 16 );
906 for (i
= 0; i
< ARRAY_SIZE(ace_rights
); ++i
)
908 if (!wcsncmp( string
, ace_rights
[i
].str
, 2 ))
911 return ace_rights
[i
].value
;
917 static BYTE
parse_ace_flags( const WCHAR
**string_ptr
)
919 const WCHAR
*string
= *string_ptr
;
922 while (*string
== ' ')
925 while (*string
!= ';')
927 DWORD flag
= parse_ace_flag( string
);
933 *string_ptr
= string
;
937 static DWORD
parse_ace_rights( const WCHAR
**string_ptr
)
940 const WCHAR
*string
= *string_ptr
;
942 while (*string
== ' ')
945 while (*string
!= ';')
947 DWORD right
= parse_ace_right( &string
);
948 if (!right
) return 0;
952 *string_ptr
= string
;
956 static BOOL
parse_acl( const WCHAR
*string
, DWORD
*flags
, ACL
*acl
, DWORD
*ret_size
)
960 DWORD length
= sizeof(ACL
);
963 ACCESS_ALLOWED_ACE
*ace
= NULL
; /* pointer to current ACE */
965 TRACE("%s\n", debugstr_w(string
));
967 if (acl
) /* ace is only useful if we're setting values */
968 ace
= (ACCESS_ALLOWED_ACE
*)(acl
+ 1);
970 /* Parse ACL flags */
971 *flags
= parse_acl_flags( &string
);
974 while (*string
== '(')
979 val
= parse_ace_type( &string
);
981 ace
->Header
.AceType
= val
;
984 SetLastError( RPC_S_INVALID_STRING_UUID
);
989 /* Parse ACE flags */
990 val
= parse_ace_flags( &string
);
992 ace
->Header
.AceFlags
= val
;
997 /* Parse ACE rights */
998 val
= parse_ace_rights( &string
);
1005 /* Parse ACE object guid */
1006 while (*string
== ' ')
1010 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1015 /* Parse ACE inherit object guid */
1016 while (*string
== ' ')
1020 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1025 /* Parse ACE account sid */
1026 if (!parse_sid( string
, &string
, ace
? (SID
*)&ace
->SidStart
: NULL
, &sidlen
))
1029 while (*string
== ' ')
1036 acesize
= sizeof(ACCESS_ALLOWED_ACE
) - sizeof(DWORD
) + sidlen
;
1040 ace
->Header
.AceSize
= acesize
;
1041 ace
= (ACCESS_ALLOWED_ACE
*)((BYTE
*)ace
+ acesize
);
1048 if (length
> 0xffff)
1050 ERR("ACL too large\n");
1056 acl
->AclRevision
= ACL_REVISION
;
1058 acl
->AclSize
= length
;
1059 acl
->AceCount
= acecount
;
1065 SetLastError( ERROR_INVALID_ACL
);
1066 WARN("Invalid ACE string format\n");
1070 static BOOL
parse_sd( const WCHAR
*string
, SECURITY_DESCRIPTOR_RELATIVE
*sd
, DWORD
*size
)
1075 const WCHAR
*lptoken
;
1079 *size
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
1081 tok
= heap_alloc( (wcslen(string
) + 1) * sizeof(WCHAR
) );
1084 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1089 next
= (BYTE
*)(sd
+ 1);
1091 while (*string
== ' ')
1098 /* Expect char identifier followed by ':' */
1102 SetLastError( ERROR_INVALID_PARAMETER
);
1109 while (*lptoken
&& *lptoken
!= ':')
1115 len
= lptoken
- string
;
1116 memcpy( tok
, string
, len
* sizeof(WCHAR
) );
1125 if (!parse_sid( tok
, NULL
, (SID
*)next
, &bytes
))
1130 sd
->Owner
= next
- (BYTE
*)sd
;
1131 next
+= bytes
; /* Advance to next token */
1143 if (!parse_sid( tok
, NULL
, (SID
*)next
, &bytes
))
1148 sd
->Group
= next
- (BYTE
*)sd
;
1149 next
+= bytes
; /* Advance to next token */
1162 if (!parse_acl( tok
, &flags
, (ACL
*)next
, &bytes
))
1167 sd
->Control
|= SE_DACL_PRESENT
| flags
;
1168 sd
->Dacl
= next
- (BYTE
*)sd
;
1169 next
+= bytes
; /* Advance to next token */
1182 if (!parse_acl( tok
, &flags
, (ACL
*)next
, &bytes
))
1187 sd
->Control
|= SE_SACL_PRESENT
| flags
;
1188 sd
->Sacl
= next
- (BYTE
*)sd
;
1189 next
+= bytes
; /* Advance to next token */
1198 FIXME("Unknown token\n");
1199 SetLastError( ERROR_INVALID_PARAMETER
);
1213 /******************************************************************************
1214 * ConvertStringSecurityDescriptorToSecurityDescriptorW (sechost.@)
1216 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertStringSecurityDescriptorToSecurityDescriptorW(
1217 const WCHAR
*string
, DWORD revision
, PSECURITY_DESCRIPTOR
*sd
, ULONG
*ret_size
)
1220 SECURITY_DESCRIPTOR
*psd
;
1222 TRACE("%s, %lu, %p, %p\n", debugstr_w(string
), revision
, sd
, ret_size
);
1224 if (GetVersion() & 0x80000000)
1226 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1231 SetLastError(ERROR_INVALID_PARAMETER
);
1234 if (revision
!= SID_REVISION
)
1236 SetLastError(ERROR_UNKNOWN_REVISION
);
1240 /* Compute security descriptor length */
1241 if (!parse_sd( string
, NULL
, &size
))
1244 psd
= *sd
= LocalAlloc( GMEM_ZEROINIT
, size
);
1247 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1251 psd
->Revision
= SID_REVISION
;
1252 psd
->Control
|= SE_SELF_RELATIVE
;
1254 if (!parse_sd( string
, (SECURITY_DESCRIPTOR_RELATIVE
*)psd
, &size
))
1260 if (ret_size
) *ret_size
= size
;