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
27 #include "wine/debug.h"
28 #include "wine/heap.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(security
);
39 { L
"GA", GENERIC_ALL
},
40 { L
"GR", GENERIC_READ
},
41 { L
"GW", GENERIC_WRITE
},
42 { L
"GX", GENERIC_EXECUTE
},
44 { L
"RC", READ_CONTROL
},
47 { L
"WO", WRITE_OWNER
},
49 { L
"RP", ADS_RIGHT_DS_READ_PROP
},
50 { L
"WP", ADS_RIGHT_DS_WRITE_PROP
},
51 { L
"CC", ADS_RIGHT_DS_CREATE_CHILD
},
52 { L
"DC", ADS_RIGHT_DS_DELETE_CHILD
},
53 { L
"LC", ADS_RIGHT_ACTRL_DS_LIST
},
54 { L
"SW", ADS_RIGHT_DS_SELF
},
55 { L
"LO", ADS_RIGHT_DS_LIST_OBJECT
},
56 { L
"DT", ADS_RIGHT_DS_DELETE_TREE
},
57 { L
"CR", ADS_RIGHT_DS_CONTROL_ACCESS
},
59 { L
"FA", FILE_ALL_ACCESS
},
60 { L
"FR", FILE_GENERIC_READ
},
61 { L
"FW", FILE_GENERIC_WRITE
},
62 { L
"FX", FILE_GENERIC_EXECUTE
},
64 { L
"KA", KEY_ALL_ACCESS
},
67 { L
"KX", KEY_EXECUTE
},
69 { L
"NR", SYSTEM_MANDATORY_LABEL_NO_READ_UP
},
70 { L
"NW", SYSTEM_MANDATORY_LABEL_NO_WRITE_UP
},
71 { L
"NX", SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP
},
76 /* same fields as struct _SID */
78 BYTE SubAuthorityCount
;
79 SID_IDENTIFIER_AUTHORITY IdentifierAuthority
;
80 DWORD SubAuthority
[SID_MAX_SUB_AUTHORITIES
];
86 WELL_KNOWN_SID_TYPE Type
;
91 { {0,0}, WinNullSid
, { SID_REVISION
, 1, { SECURITY_NULL_SID_AUTHORITY
}, { SECURITY_NULL_RID
} } },
92 { {'W','D'}, WinWorldSid
, { SID_REVISION
, 1, { SECURITY_WORLD_SID_AUTHORITY
}, { SECURITY_WORLD_RID
} } },
93 { {0,0}, WinLocalSid
, { SID_REVISION
, 1, { SECURITY_LOCAL_SID_AUTHORITY
}, { SECURITY_LOCAL_RID
} } },
94 { {'C','O'}, WinCreatorOwnerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_RID
} } },
95 { {'C','G'}, WinCreatorGroupSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_GROUP_RID
} } },
96 { {'O','W'}, WinCreatorOwnerRightsSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_RIGHTS_RID
} } },
97 { {0,0}, WinCreatorOwnerServerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_SERVER_RID
} } },
98 { {0,0}, WinCreatorGroupServerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_GROUP_SERVER_RID
} } },
99 { {0,0}, WinNtAuthoritySid
, { SID_REVISION
, 0, { SECURITY_NT_AUTHORITY
}, { SECURITY_NULL_RID
} } },
100 { {0,0}, WinDialupSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_DIALUP_RID
} } },
101 { {'N','U'}, WinNetworkSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_NETWORK_RID
} } },
102 { {0,0}, WinBatchSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_BATCH_RID
} } },
103 { {'I','U'}, WinInteractiveSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_INTERACTIVE_RID
} } },
104 { {'S','U'}, WinServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_SERVICE_RID
} } },
105 { {'A','N'}, WinAnonymousSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_ANONYMOUS_LOGON_RID
} } },
106 { {0,0}, WinProxySid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_PROXY_RID
} } },
107 { {'E','D'}, WinEnterpriseControllersSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_ENTERPRISE_CONTROLLERS_RID
} } },
108 { {'P','S'}, WinSelfSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_PRINCIPAL_SELF_RID
} } },
109 { {'A','U'}, WinAuthenticatedUserSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_AUTHENTICATED_USER_RID
} } },
110 { {'R','C'}, WinRestrictedCodeSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_RESTRICTED_CODE_RID
} } },
111 { {0,0}, WinTerminalServerSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_TERMINAL_SERVER_RID
} } },
112 { {0,0}, WinRemoteLogonIdSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_REMOTE_LOGON_RID
} } },
113 { {0,0}, WinLogonIdsSid
, { SID_REVISION
, SECURITY_LOGON_IDS_RID_COUNT
, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOGON_IDS_RID
} } },
114 { {'S','Y'}, WinLocalSystemSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOCAL_SYSTEM_RID
} } },
115 { {'L','S'}, WinLocalServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOCAL_SERVICE_RID
} } },
116 { {'N','S'}, WinNetworkServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_NETWORK_SERVICE_RID
} } },
117 { {0,0}, WinBuiltinDomainSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
} } },
118 { {'B','A'}, WinBuiltinAdministratorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ADMINS
} } },
119 { {'B','U'}, WinBuiltinUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_USERS
} } },
120 { {'B','G'}, WinBuiltinGuestsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_GUESTS
} } },
121 { {'P','U'}, WinBuiltinPowerUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_POWER_USERS
} } },
122 { {'A','O'}, WinBuiltinAccountOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ACCOUNT_OPS
} } },
123 { {'S','O'}, WinBuiltinSystemOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_SYSTEM_OPS
} } },
124 { {'P','O'}, WinBuiltinPrintOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_PRINT_OPS
} } },
125 { {'B','O'}, WinBuiltinBackupOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_BACKUP_OPS
} } },
126 { {'R','E'}, WinBuiltinReplicatorSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_REPLICATOR
} } },
127 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS
} } },
128 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS
} } },
129 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS
} } },
130 { {0,0}, WinNTLMAuthenticationSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_PACKAGE_BASE_RID
, SECURITY_PACKAGE_NTLM_RID
} } },
131 { {0,0}, WinDigestAuthenticationSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_PACKAGE_BASE_RID
, SECURITY_PACKAGE_DIGEST_RID
} } },
132 { {0,0}, WinSChannelAuthenticationSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_PACKAGE_BASE_RID
, SECURITY_PACKAGE_SCHANNEL_RID
} } },
133 { {0,0}, WinThisOrganizationSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_THIS_ORGANIZATION_RID
} } },
134 { {0,0}, WinOtherOrganizationSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_OTHER_ORGANIZATION_RID
} } },
135 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS
} } },
136 { {0,0}, WinBuiltinPerfMonitoringUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_MONITORING_USERS
} } },
137 { {0,0}, WinBuiltinPerfLoggingUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_LOGGING_USERS
} } },
138 { {0,0}, WinBuiltinAuthorizationAccessSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS
} } },
139 { {0,0}, WinBuiltinTerminalServerLicenseServersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS
} } },
140 { {0,0}, WinBuiltinDCOMUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_DCOM_USERS
} } },
141 { {'L','W'}, WinLowLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_LOW_RID
} } },
142 { {'M','E'}, WinMediumLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_MEDIUM_RID
} } },
143 { {'H','I'}, WinHighLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_HIGH_RID
} } },
144 { {'S','I'}, WinSystemLabelSid
, { SID_REVISION
, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY
}, { SECURITY_MANDATORY_SYSTEM_RID
} } },
145 { {'A','C'}, WinBuiltinAnyPackageSid
, { SID_REVISION
, 2, { SECURITY_APP_PACKAGE_AUTHORITY
}, { SECURITY_APP_PACKAGE_BASE_RID
, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE
} } },
148 /* these SIDs must be constructed as relative to some domain - only the RID is well-known */
152 WELL_KNOWN_SID_TYPE type
;
157 { {'L','A'}, WinAccountAdministratorSid
, DOMAIN_USER_RID_ADMIN
},
158 { {'L','G'}, WinAccountGuestSid
, DOMAIN_USER_RID_GUEST
},
159 { {0,0}, WinAccountKrbtgtSid
, DOMAIN_USER_RID_KRBTGT
},
160 { {'D','A'}, WinAccountDomainAdminsSid
, DOMAIN_GROUP_RID_ADMINS
},
161 { {'D','U'}, WinAccountDomainUsersSid
, DOMAIN_GROUP_RID_USERS
},
162 { {'D','G'}, WinAccountDomainGuestsSid
, DOMAIN_GROUP_RID_GUESTS
},
163 { {'D','C'}, WinAccountComputersSid
, DOMAIN_GROUP_RID_COMPUTERS
},
164 { {'D','D'}, WinAccountControllersSid
, DOMAIN_GROUP_RID_CONTROLLERS
},
165 { {'C','A'}, WinAccountCertAdminsSid
, DOMAIN_GROUP_RID_CERT_ADMINS
},
166 { {'S','A'}, WinAccountSchemaAdminsSid
, DOMAIN_GROUP_RID_SCHEMA_ADMINS
},
167 { {'E','A'}, WinAccountEnterpriseAdminsSid
, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS
},
168 { {'P','A'}, WinAccountPolicyAdminsSid
, DOMAIN_GROUP_RID_POLICY_ADMINS
},
169 { {'R','S'}, WinAccountRasAndIasServersSid
, DOMAIN_ALIAS_RID_RAS_SERVERS
},
173 static void print_string(const WCHAR
*string
, int cch
, WCHAR
**pwptr
, ULONG
*plen
)
176 cch
= wcslen(string
);
183 memcpy(*pwptr
, string
, sizeof(WCHAR
)*cch
);
188 static BOOL
print_sid_numeric(PSID psid
, WCHAR
**pwptr
, ULONG
*plen
)
194 if( !IsValidSid( psid
) || pisid
->Revision
!= SDDL_REVISION
)
196 SetLastError(ERROR_INVALID_SID
);
200 if (pisid
->IdentifierAuthority
.Value
[0] ||
201 pisid
->IdentifierAuthority
.Value
[1])
203 FIXME("not matching MS' bugs\n");
204 SetLastError(ERROR_INVALID_SID
);
208 swprintf( buf
, ARRAY_SIZE(buf
), L
"S-%u-%d", pisid
->Revision
, MAKELONG(
209 MAKEWORD( pisid
->IdentifierAuthority
.Value
[5], pisid
->IdentifierAuthority
.Value
[4] ),
210 MAKEWORD( pisid
->IdentifierAuthority
.Value
[3], pisid
->IdentifierAuthority
.Value
[2] )
212 print_string(buf
, -1, pwptr
, plen
);
214 for( i
=0; i
<pisid
->SubAuthorityCount
; i
++ )
216 swprintf( buf
, ARRAY_SIZE(buf
), L
"-%u", pisid
->SubAuthority
[i
] );
217 print_string(buf
, -1, pwptr
, plen
);
222 /******************************************************************************
223 * ConvertSidToStringSidW (sechost.@)
225 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertSidToStringSidW( PSID sid
, WCHAR
**pstr
)
230 TRACE("%p %p\n", sid
, pstr
);
233 if (!print_sid_numeric( sid
, NULL
, &len
))
235 wstr
= wptr
= LocalAlloc( 0, (len
+ 1) * sizeof(WCHAR
) );
236 print_sid_numeric( sid
, &wptr
, NULL
);
243 static BOOL
print_sid(PSID psid
, WCHAR
**pwptr
, ULONG
*plen
)
246 for (i
= 0; i
< ARRAY_SIZE(well_known_sids
); i
++)
248 if (well_known_sids
[i
].str
[0] && EqualSid(psid
, (PSID
)&well_known_sids
[i
].sid
.Revision
))
250 print_string(well_known_sids
[i
].str
, 2, pwptr
, plen
);
255 return print_sid_numeric(psid
, pwptr
, plen
);
258 static void print_rights(DWORD mask
, WCHAR
**pwptr
, ULONG
*plen
)
260 static const WCHAR
*bit_names
[32] =
302 /* first check if the right have name */
303 for (i
= 0; i
< ARRAY_SIZE(ace_rights
); i
++)
305 if (mask
== ace_rights
[i
].value
)
307 print_string(ace_rights
[i
].str
, -1, pwptr
, plen
);
312 /* then check if it can be built from bit names */
313 for (i
= 0; i
< 32; i
++)
315 if ((mask
& (1 << i
)) && !bit_names
[i
])
317 /* can't be built from bit names */
318 swprintf(buf
, ARRAY_SIZE(buf
), L
"0x%x", mask
);
319 print_string(buf
, -1, pwptr
, plen
);
324 /* build from bit names */
325 for (i
= 0; i
< 32; i
++)
327 print_string(bit_names
[i
], -1, pwptr
, plen
);
330 static inline BOOL
is_object_ace(BYTE type
)
334 case ACCESS_ALLOWED_OBJECT_ACE_TYPE
:
335 case ACCESS_DENIED_OBJECT_ACE_TYPE
:
336 case ACCESS_AUDIT_OBJECT_ACE_TYPE
:
337 case ACCESS_ALARM_OBJECT_ACE_TYPE
:
338 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE
:
339 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE
:
340 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE
:
341 case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE
:
349 static BOOL
print_ace(void *pace
, WCHAR
**pwptr
, ULONG
*plen
)
351 ACCESS_ALLOWED_ACE
*piace
; /* all the supported ACEs have the same memory layout */
356 if (piace
->Header
.AceType
> ACCESS_MAX_MS_V5_ACE_TYPE
|| piace
->Header
.AceSize
< sizeof(ACCESS_ALLOWED_ACE
))
358 SetLastError(ERROR_INVALID_ACL
);
362 print_string(L
"(", -1, pwptr
, plen
);
363 switch (piace
->Header
.AceType
)
365 case ACCESS_ALLOWED_ACE_TYPE
:
366 print_string(L
"A", -1, pwptr
, plen
);
368 case ACCESS_DENIED_ACE_TYPE
:
369 print_string(L
"D", -1, pwptr
, plen
);
371 case SYSTEM_AUDIT_ACE_TYPE
:
372 print_string(L
"AU", -1, pwptr
, plen
);
374 case SYSTEM_ALARM_ACE_TYPE
:
375 print_string(L
"AL", -1, pwptr
, plen
);
378 print_string(L
";", -1, pwptr
, plen
);
380 if (piace
->Header
.AceFlags
& OBJECT_INHERIT_ACE
)
381 print_string(L
"OI", -1, pwptr
, plen
);
382 if (piace
->Header
.AceFlags
& CONTAINER_INHERIT_ACE
)
383 print_string(L
"CI", -1, pwptr
, plen
);
384 if (piace
->Header
.AceFlags
& NO_PROPAGATE_INHERIT_ACE
)
385 print_string(L
"NP", -1, pwptr
, plen
);
386 if (piace
->Header
.AceFlags
& INHERIT_ONLY_ACE
)
387 print_string(L
"IO", -1, pwptr
, plen
);
388 if (piace
->Header
.AceFlags
& INHERITED_ACE
)
389 print_string(L
"ID", -1, pwptr
, plen
);
390 if (piace
->Header
.AceFlags
& SUCCESSFUL_ACCESS_ACE_FLAG
)
391 print_string(L
"SA", -1, pwptr
, plen
);
392 if (piace
->Header
.AceFlags
& FAILED_ACCESS_ACE_FLAG
)
393 print_string(L
"FA", -1, pwptr
, plen
);
394 print_string(L
";", -1, pwptr
, plen
);
395 print_rights(piace
->Mask
, pwptr
, plen
);
396 print_string(L
";", -1, pwptr
, plen
);
397 sid_start
= &piace
->SidStart
;
398 if (is_object_ace(piace
->Header
.AceType
))
400 ACCESS_ALLOWED_OBJECT_ACE
*objace
= pace
;
402 sid_start
++; /* Flags */
403 if (objace
->Flags
& ACE_OBJECT_TYPE_PRESENT
)
404 sid_start
+= sizeof(GUID
) / sizeof(*sid_start
); /* ObjectType */
405 if (objace
->Flags
& ACE_INHERITED_OBJECT_TYPE_PRESENT
)
406 sid_start
+= sizeof(GUID
) / sizeof(*sid_start
); /* InheritedObjectType */
408 /* objects not supported */
409 print_string(L
";", -1, pwptr
, plen
);
410 /* objects not supported */
411 print_string(L
";", -1, pwptr
, plen
);
412 if (!print_sid(sid_start
, pwptr
, plen
))
414 print_string(L
")", -1, pwptr
, plen
);
418 static BOOL
print_acl(ACL
*pacl
, WCHAR
**pwptr
, ULONG
*plen
, SECURITY_DESCRIPTOR_CONTROL control
)
423 if (control
& SE_DACL_PROTECTED
)
424 print_string(L
"P", -1, pwptr
, plen
);
425 if (control
& SE_DACL_AUTO_INHERIT_REQ
)
426 print_string(L
"AR", -1, pwptr
, plen
);
427 if (control
& SE_DACL_AUTO_INHERITED
)
428 print_string(L
"AI", -1, pwptr
, plen
);
433 if (!IsValidAcl(pacl
))
436 count
= pacl
->AceCount
;
437 for (i
= 0; i
< count
; i
++)
440 if (!GetAce(pacl
, i
, &ace
))
442 if (!print_ace(ace
, pwptr
, plen
))
449 static BOOL
print_owner(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
454 if (!GetSecurityDescriptorOwner(sd
, &psid
, &defaulted
))
460 print_string(L
"O:", -1, pwptr
, plen
);
461 if (!print_sid(psid
, pwptr
, plen
))
466 static BOOL
print_group(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
471 if (!GetSecurityDescriptorGroup(sd
, &psid
, &defaulted
))
477 print_string(L
"G:", -1, pwptr
, plen
);
478 if (!print_sid(psid
, pwptr
, plen
))
483 static BOOL
print_dacl(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
485 SECURITY_DESCRIPTOR_CONTROL control
;
486 BOOL present
, defaulted
;
490 if (!GetSecurityDescriptorDacl(sd
, &present
, &pacl
, &defaulted
))
493 if (!GetSecurityDescriptorControl(sd
, &control
, &revision
))
499 print_string(L
"D:", -1, pwptr
, plen
);
500 if (!print_acl(pacl
, pwptr
, plen
, control
))
505 static BOOL
print_sacl(PSECURITY_DESCRIPTOR sd
, WCHAR
**pwptr
, ULONG
*plen
)
507 SECURITY_DESCRIPTOR_CONTROL control
;
508 BOOL present
, defaulted
;
512 if (!GetSecurityDescriptorSacl(sd
, &present
, &pacl
, &defaulted
))
515 if (!GetSecurityDescriptorControl(sd
, &control
, &revision
))
521 print_string(L
"S:", -1, pwptr
, plen
);
522 if (!print_acl(pacl
, pwptr
, plen
, control
))
527 /******************************************************************************
528 * ConvertSecurityDescriptorToStringSecurityDescriptorW (sechost.@)
530 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertSecurityDescriptorToStringSecurityDescriptorW( PSECURITY_DESCRIPTOR sd
,
531 DWORD revision
, SECURITY_INFORMATION flags
, WCHAR
**string
, ULONG
*ret_len
)
536 if (revision
!= SDDL_REVISION_1
)
538 ERR("Unhandled SDDL revision %d\n", revision
);
539 SetLastError( ERROR_UNKNOWN_REVISION
);
543 if ((flags
& OWNER_SECURITY_INFORMATION
) && !print_owner(sd
, NULL
, &len
))
545 if ((flags
& GROUP_SECURITY_INFORMATION
) && !print_group(sd
, NULL
, &len
))
547 if ((flags
& DACL_SECURITY_INFORMATION
) && !print_dacl(sd
, NULL
, &len
))
549 if ((flags
& SACL_SECURITY_INFORMATION
) && !print_sacl(sd
, NULL
, &len
))
552 wstr
= wptr
= LocalAlloc( 0, (len
+ 1) * sizeof(WCHAR
) );
553 if ((flags
& OWNER_SECURITY_INFORMATION
) && !print_owner(sd
, &wptr
, NULL
))
558 if ((flags
& GROUP_SECURITY_INFORMATION
) && !print_group(sd
, &wptr
, NULL
))
563 if ((flags
& DACL_SECURITY_INFORMATION
) && !print_dacl(sd
, &wptr
, NULL
))
568 if ((flags
& SACL_SECURITY_INFORMATION
) && !print_sacl(sd
, &wptr
, NULL
))
575 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr
), len
);
577 if (ret_len
) *ret_len
= wcslen(*string
) + 1;
581 static BOOL
get_computer_sid( PSID sid
)
583 static const struct /* same fields as struct SID */
586 BYTE SubAuthorityCount
;
587 SID_IDENTIFIER_AUTHORITY IdentifierAuthority
;
588 DWORD SubAuthority
[4];
590 { SID_REVISION
, 4, { SECURITY_NT_AUTHORITY
}, { SECURITY_NT_NON_UNIQUE
, 0, 0, 0 } };
592 memcpy( sid
, &computer_sid
, sizeof(computer_sid
) );
596 static DWORD
get_sid_size( const WCHAR
*string
)
598 if (string
[0] == 'S' && string
[1] == '-') /* S-R-I(-S)+ */
608 if (token_count
>= 3)
609 return GetSidLengthRequired( token_count
- 2 );
611 else /* String constant format - Only available in winxp and above */
615 for (i
= 0; i
< ARRAY_SIZE(well_known_sids
); i
++)
617 if (!wcsncmp( well_known_sids
[i
].str
, string
, 2 ))
618 return GetSidLengthRequired( well_known_sids
[i
].sid
.SubAuthorityCount
);
621 for (i
= 0; i
< ARRAY_SIZE(well_known_rids
); i
++)
623 if (!wcsncmp( well_known_rids
[i
].str
, string
, 2 ))
625 struct max_sid local
;
626 get_computer_sid(&local
);
627 return GetSidLengthRequired( *GetSidSubAuthorityCount(&local
) + 1 );
632 return GetSidLengthRequired( 0 );
635 static BOOL
parse_sid( const WCHAR
*string
, SID
*pisid
, DWORD
*size
)
637 while (*string
== ' ')
640 *size
= get_sid_size( string
);
641 if (!pisid
) /* Simply compute the size */
644 if (string
[0] == 'S' && string
[1] == '-') /* S-R-I-S-S */
646 DWORD i
= 0, identAuth
;
647 DWORD csubauth
= ((*size
- GetSidLengthRequired(0)) / sizeof(DWORD
));
649 string
+= 2; /* Advance to Revision */
650 pisid
->Revision
= wcstoul( string
, NULL
, 10 );
652 if (pisid
->Revision
!= SDDL_REVISION
)
654 TRACE("Revision %d is unknown\n", pisid
->Revision
);
655 SetLastError( ERROR_INVALID_SID
);
660 TRACE("SubAuthorityCount is 0\n");
661 SetLastError( ERROR_INVALID_SID
);
665 pisid
->SubAuthorityCount
= csubauth
;
667 /* Advance to identifier authority */
668 while (*string
&& *string
!= '-')
673 /* MS' implementation can't handle values greater than 2^32 - 1, so
674 * we don't either; assume most significant bytes are always 0
676 pisid
->IdentifierAuthority
.Value
[0] = 0;
677 pisid
->IdentifierAuthority
.Value
[1] = 0;
678 identAuth
= wcstoul( string
, NULL
, 10 );
679 pisid
->IdentifierAuthority
.Value
[5] = identAuth
& 0xff;
680 pisid
->IdentifierAuthority
.Value
[4] = (identAuth
& 0xff00) >> 8;
681 pisid
->IdentifierAuthority
.Value
[3] = (identAuth
& 0xff0000) >> 16;
682 pisid
->IdentifierAuthority
.Value
[2] = (identAuth
& 0xff000000) >> 24;
684 /* Advance to first sub authority */
685 while (*string
&& *string
!= '-')
692 pisid
->SubAuthority
[i
++] = wcstoul( string
, NULL
, 10 );
694 while (*string
&& *string
!= '-')
700 if (i
!= pisid
->SubAuthorityCount
)
702 SetLastError( ERROR_INVALID_SID
);
708 else /* String constant format - Only available in winxp and above */
711 pisid
->Revision
= SDDL_REVISION
;
713 for (i
= 0; i
< ARRAY_SIZE(well_known_sids
); i
++)
715 if (!wcsncmp(well_known_sids
[i
].str
, string
, 2))
718 pisid
->SubAuthorityCount
= well_known_sids
[i
].sid
.SubAuthorityCount
;
719 pisid
->IdentifierAuthority
= well_known_sids
[i
].sid
.IdentifierAuthority
;
720 for (j
= 0; j
< well_known_sids
[i
].sid
.SubAuthorityCount
; j
++)
721 pisid
->SubAuthority
[j
] = well_known_sids
[i
].sid
.SubAuthority
[j
];
726 for (i
= 0; i
< ARRAY_SIZE(well_known_rids
); i
++)
728 if (!wcsncmp(well_known_rids
[i
].str
, string
, 2))
730 get_computer_sid(pisid
);
731 pisid
->SubAuthority
[pisid
->SubAuthorityCount
] = well_known_rids
[i
].rid
;
732 pisid
->SubAuthorityCount
++;
737 FIXME("String constant not supported: %s\n", debugstr_wn(string
, 2));
738 SetLastError( ERROR_INVALID_SID
);
743 /******************************************************************************
744 * ConvertStringSidToSidW (sechost.@)
746 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertStringSidToSidW( const WCHAR
*string
, PSID
*sid
)
750 TRACE("%s, %p\n", debugstr_w(string
), sid
);
752 if (GetVersion() & 0x80000000)
754 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
760 SetLastError(ERROR_INVALID_PARAMETER
);
764 if (!parse_sid( string
, NULL
, &size
))
767 *sid
= LocalAlloc( 0, size
);
769 if (!parse_sid( string
, *sid
, &size
))
777 static DWORD
parse_acl_flags( const WCHAR
**string_ptr
)
780 const WCHAR
*string
= *string_ptr
;
782 while (*string
&& *string
!= '(')
786 flags
|= SE_DACL_PROTECTED
;
788 else if (*string
== 'A')
792 flags
|= SE_DACL_AUTO_INHERIT_REQ
;
793 else if (*string
== 'I')
794 flags
|= SE_DACL_AUTO_INHERITED
;
799 *string_ptr
= string
;
803 static BYTE
parse_ace_type( const WCHAR
**string_ptr
)
812 { L
"AL", SYSTEM_ALARM_ACE_TYPE
},
813 { L
"AU", SYSTEM_AUDIT_ACE_TYPE
},
814 { L
"A", ACCESS_ALLOWED_ACE_TYPE
},
815 { L
"D", ACCESS_DENIED_ACE_TYPE
},
816 { L
"ML", SYSTEM_MANDATORY_LABEL_ACE_TYPE
},
818 { ACCESS_ALLOWED_OBJECT_ACE_TYPE },
819 { ACCESS_DENIED_OBJECT_ACE_TYPE },
820 { SYSTEM_ALARM_OBJECT_ACE_TYPE },
821 { SYSTEM_AUDIT_OBJECT_ACE_TYPE },
825 const WCHAR
*string
= *string_ptr
;
828 while (*string
== ' ')
831 for (i
= 0; i
< ARRAY_SIZE(ace_types
); ++i
)
833 size_t len
= wcslen( ace_types
[i
].str
);
834 if (!wcsncmp( string
, ace_types
[i
].str
, len
))
836 *string_ptr
= string
+ len
;
837 return ace_types
[i
].value
;
843 static DWORD
parse_ace_flag( const WCHAR
*string
)
852 { L
"CI", CONTAINER_INHERIT_ACE
},
853 { L
"FA", FAILED_ACCESS_ACE_FLAG
},
854 { L
"ID", INHERITED_ACE
},
855 { L
"IO", INHERIT_ONLY_ACE
},
856 { L
"NP", NO_PROPAGATE_INHERIT_ACE
},
857 { L
"OI", OBJECT_INHERIT_ACE
},
858 { L
"SA", SUCCESSFUL_ACCESS_ACE_FLAG
},
863 for (i
= 0; i
< ARRAY_SIZE(ace_flags
); ++i
)
865 if (!wcsncmp( string
, ace_flags
[i
].str
, 2 ))
866 return ace_flags
[i
].value
;
871 static DWORD
parse_ace_right( const WCHAR
*string
)
875 for (i
= 0; i
< ARRAY_SIZE(ace_rights
); ++i
)
877 if (!wcsncmp( string
, ace_rights
[i
].str
, 2 ))
878 return ace_rights
[i
].value
;
883 static BYTE
parse_ace_flags( const WCHAR
**string_ptr
)
885 const WCHAR
*string
= *string_ptr
;
888 while (*string
== ' ')
891 while (*string
!= ';')
893 DWORD flag
= parse_ace_flag( string
);
899 *string_ptr
= string
;
903 static DWORD
parse_ace_rights( const WCHAR
**string_ptr
)
906 const WCHAR
*string
= *string_ptr
;
908 while (*string
== ' ')
911 if (string
[0] == '0' && string
[1] == 'x')
913 const WCHAR
*p
= string
;
915 while (*p
&& *p
!= ';')
918 if (p
- string
<= 10 /* 8 hex digits + "0x" */ )
920 rights
= wcstoul( string
, NULL
, 16 );
924 WARN("Invalid rights string format: %s\n", debugstr_wn(string
, p
- string
));
928 while (*string
!= ';')
930 DWORD right
= parse_ace_right( string
);
931 if (!right
) return 0;
937 *string_ptr
= string
;
941 static BOOL
parse_acl( const WCHAR
*string
, DWORD
*flags
, ACL
*acl
, DWORD
*ret_size
)
945 DWORD length
= sizeof(ACL
);
948 ACCESS_ALLOWED_ACE
*ace
= NULL
; /* pointer to current ACE */
950 TRACE("%s\n", debugstr_w(string
));
952 if (acl
) /* ace is only useful if we're setting values */
953 ace
= (ACCESS_ALLOWED_ACE
*)(acl
+ 1);
955 /* Parse ACL flags */
956 *flags
= parse_acl_flags( &string
);
959 while (*string
== '(')
964 val
= parse_ace_type( &string
);
966 ace
->Header
.AceType
= val
;
969 SetLastError( RPC_S_INVALID_STRING_UUID
);
974 /* Parse ACE flags */
975 val
= parse_ace_flags( &string
);
977 ace
->Header
.AceFlags
= val
;
982 /* Parse ACE rights */
983 val
= parse_ace_rights( &string
);
990 /* Parse ACE object guid */
991 while (*string
== ' ')
995 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1000 /* Parse ACE inherit object guid */
1001 while (*string
== ' ')
1005 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1010 /* Parse ACE account sid */
1011 if (parse_sid( string
, ace
? (SID
*)&ace
->SidStart
: NULL
, &sidlen
))
1013 while (*string
&& *string
!= ')')
1021 acesize
= sizeof(ACCESS_ALLOWED_ACE
) - sizeof(DWORD
) + sidlen
;
1025 ace
->Header
.AceSize
= acesize
;
1026 ace
= (ACCESS_ALLOWED_ACE
*)((BYTE
*)ace
+ acesize
);
1033 if (length
> 0xffff)
1035 ERR("ACL too large\n");
1041 acl
->AclRevision
= ACL_REVISION
;
1043 acl
->AclSize
= length
;
1044 acl
->AceCount
= acecount
;
1050 SetLastError( ERROR_INVALID_ACL
);
1051 WARN("Invalid ACE string format\n");
1055 static BOOL
parse_sd( const WCHAR
*string
, SECURITY_DESCRIPTOR_RELATIVE
*sd
, DWORD
*size
)
1060 const WCHAR
*lptoken
;
1064 *size
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
1066 tok
= heap_alloc( (wcslen(string
) + 1) * sizeof(WCHAR
) );
1069 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1074 next
= (BYTE
*)(sd
+ 1);
1076 while (*string
== ' ')
1083 /* Expect char identifier followed by ':' */
1087 SetLastError( ERROR_INVALID_PARAMETER
);
1094 while (*lptoken
&& *lptoken
!= ':')
1100 len
= lptoken
- string
;
1101 memcpy( tok
, string
, len
* sizeof(WCHAR
) );
1110 if (!parse_sid( tok
, (SID
*)next
, &bytes
))
1115 sd
->Owner
= next
- (BYTE
*)sd
;
1116 next
+= bytes
; /* Advance to next token */
1128 if (!parse_sid( tok
, (SID
*)next
, &bytes
))
1133 sd
->Group
= next
- (BYTE
*)sd
;
1134 next
+= bytes
; /* Advance to next token */
1147 if (!parse_acl( tok
, &flags
, (ACL
*)next
, &bytes
))
1152 sd
->Control
|= SE_DACL_PRESENT
| flags
;
1153 sd
->Dacl
= next
- (BYTE
*)sd
;
1154 next
+= bytes
; /* Advance to next token */
1167 if (!parse_acl( tok
, &flags
, (ACL
*)next
, &bytes
))
1172 sd
->Control
|= SE_SACL_PRESENT
| flags
;
1173 sd
->Sacl
= next
- (BYTE
*)sd
;
1174 next
+= bytes
; /* Advance to next token */
1183 FIXME("Unknown token\n");
1184 SetLastError( ERROR_INVALID_PARAMETER
);
1198 /******************************************************************************
1199 * ConvertStringSecurityDescriptorToSecurityDescriptorW (sechost.@)
1201 BOOL WINAPI DECLSPEC_HOTPATCH
ConvertStringSecurityDescriptorToSecurityDescriptorW(
1202 const WCHAR
*string
, DWORD revision
, PSECURITY_DESCRIPTOR
*sd
, ULONG
*ret_size
)
1205 SECURITY_DESCRIPTOR
*psd
;
1207 TRACE("%s, %u, %p, %p\n", debugstr_w(string
), revision
, sd
, ret_size
);
1209 if (GetVersion() & 0x80000000)
1211 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1216 SetLastError(ERROR_INVALID_PARAMETER
);
1219 if (revision
!= SID_REVISION
)
1221 SetLastError(ERROR_UNKNOWN_REVISION
);
1225 /* Compute security descriptor length */
1226 if (!parse_sd( string
, NULL
, &size
))
1229 psd
= *sd
= LocalAlloc( GMEM_ZEROINIT
, size
);
1232 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1236 psd
->Revision
= SID_REVISION
;
1237 psd
->Control
|= SE_SELF_RELATIVE
;
1239 if (!parse_sd( string
, (SECURITY_DESCRIPTOR_RELATIVE
*)psd
, &size
))
1245 if (ret_size
) *ret_size
= size
;