2 * WoW64 security functions
4 * Copyright 2021 Alexandre Julliard
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
24 #define WIN32_NO_STATUS
29 #include "wow64_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wow
);
35 static TOKEN_GROUPS
*token_groups_32to64( const TOKEN_GROUPS32
*groups32
)
40 if (!groups32
) return NULL
;
41 groups
= Wow64AllocateTemp( offsetof( TOKEN_GROUPS
, Groups
[groups32
->GroupCount
] ));
42 groups
->GroupCount
= groups32
->GroupCount
;
43 for (i
= 0; i
< groups
->GroupCount
; i
++)
45 groups
->Groups
[i
].Sid
= ULongToPtr( groups32
->Groups
[i
].Sid
);
46 groups
->Groups
[i
].Attributes
= groups32
->Groups
[i
].Attributes
;
52 /**********************************************************************
55 NTSTATUS WINAPI
wow64_NtAccessCheck( UINT
*args
)
57 SECURITY_DESCRIPTOR
*sd32
= get_ptr( &args
);
58 HANDLE handle
= get_handle( &args
);
59 ACCESS_MASK access
= get_ulong( &args
);
60 GENERIC_MAPPING
*mapping
= get_ptr( &args
);
61 PRIVILEGE_SET
*privs
= get_ptr( &args
);
62 ULONG
*retlen
= get_ptr( &args
);
63 ACCESS_MASK
*access_granted
= get_ptr( &args
);
64 NTSTATUS
*access_status
= get_ptr( &args
);
66 SECURITY_DESCRIPTOR sd
;
68 return NtAccessCheck( secdesc_32to64( &sd
, sd32
), handle
, access
, mapping
,
69 privs
, retlen
, access_granted
, access_status
);
73 /**********************************************************************
74 * wow64_NtAccessCheckAndAuditAlarm
76 NTSTATUS WINAPI
wow64_NtAccessCheckAndAuditAlarm( UINT
*args
)
78 UNICODE_STRING32
*subsystem32
= get_ptr( &args
);
79 HANDLE handle
= get_handle( &args
);
80 UNICODE_STRING32
*typename32
= get_ptr( &args
);
81 UNICODE_STRING32
*objname32
= get_ptr( &args
);
82 SECURITY_DESCRIPTOR
*sd32
= get_ptr( &args
);
83 ACCESS_MASK access
= get_ulong( &args
);
84 GENERIC_MAPPING
*mapping
= get_ptr( &args
);
85 BOOLEAN creation
= get_ulong( &args
);
86 ACCESS_MASK
*access_granted
= get_ptr( &args
);
87 BOOLEAN
*access_status
= get_ptr( &args
);
88 BOOLEAN
*onclose
= get_ptr( &args
);
90 UNICODE_STRING subsystem
, typename
, objname
;
91 SECURITY_DESCRIPTOR sd
;
93 return NtAccessCheckAndAuditAlarm( unicode_str_32to64( &subsystem
, subsystem32
), handle
,
94 unicode_str_32to64( &typename
, typename32
),
95 unicode_str_32to64( &objname
, objname32
),
96 secdesc_32to64( &sd
, sd32
), access
, mapping
, creation
,
97 access_granted
, access_status
, onclose
);
101 /**********************************************************************
102 * wow64_NtAdjustGroupsToken
104 NTSTATUS WINAPI
wow64_NtAdjustGroupsToken( UINT
*args
)
106 HANDLE handle
= get_handle( &args
);
107 BOOLEAN reset
= get_ulong( &args
);
108 TOKEN_GROUPS32
*groups
= get_ptr( &args
);
109 ULONG len
= get_ulong( &args
);
110 TOKEN_GROUPS32
*prev
= get_ptr( &args
);
111 ULONG
*retlen
= get_ptr( &args
);
113 FIXME( "%p %d %p %lu %p %p\n", handle
, reset
, groups
, len
, prev
, retlen
);
114 return STATUS_NOT_IMPLEMENTED
;
118 /**********************************************************************
119 * wow64_NtAdjustPrivilegesToken
121 NTSTATUS WINAPI
wow64_NtAdjustPrivilegesToken( UINT
*args
)
123 HANDLE handle
= get_handle( &args
);
124 BOOLEAN disable
= get_ulong( &args
);
125 TOKEN_PRIVILEGES
*privs
= get_ptr( &args
);
126 ULONG len
= get_ulong( &args
);
127 TOKEN_PRIVILEGES
*prev
= get_ptr( &args
);
128 ULONG
*retlen
= get_ptr( &args
);
130 return NtAdjustPrivilegesToken( handle
, disable
, privs
, len
, prev
, retlen
);
134 /**********************************************************************
135 * wow64_NtCreateLowBoxToken
137 NTSTATUS WINAPI
wow64_NtCreateLowBoxToken( UINT
*args
)
139 ULONG
*handle_ptr
= get_ptr( &args
);
140 HANDLE token
= get_handle( &args
);
141 ACCESS_MASK access
= get_ulong( &args
);
142 OBJECT_ATTRIBUTES32
*attr32
= get_ptr( &args
);
143 SID
*sid
= get_ptr( &args
);
144 ULONG count
= get_ulong( &args
);
145 SID_AND_ATTRIBUTES32
*capabilities32
= get_ptr( &args
);
146 ULONG handle_count
= get_ulong( &args
);
147 ULONG
*handles32
= get_ptr( &args
);
149 FIXME( "%p %p %lx %p %p %lu %p %lu %p: stub\n",
150 handle_ptr
, token
, access
, attr32
, sid
, count
, capabilities32
, handle_count
, handles32
);
153 return STATUS_SUCCESS
;
157 /**********************************************************************
158 * wow64_NtDuplicateToken
160 NTSTATUS WINAPI
wow64_NtDuplicateToken( UINT
*args
)
162 HANDLE token
= get_handle( &args
);
163 ACCESS_MASK access
= get_ulong( &args
);
164 OBJECT_ATTRIBUTES32
*attr32
= get_ptr( &args
);
165 SECURITY_IMPERSONATION_LEVEL level
= get_ulong( &args
);
166 TOKEN_TYPE type
= get_ulong( &args
);
167 ULONG
*handle_ptr
= get_ptr( &args
);
169 struct object_attr64 attr
;
174 status
= NtDuplicateToken( token
, access
, objattr_32to64( &attr
, attr32
), level
, type
, &handle
);
175 put_handle( handle_ptr
, handle
);
180 /**********************************************************************
181 * wow64_NtFilterToken
183 NTSTATUS WINAPI
wow64_NtFilterToken( UINT
*args
)
185 HANDLE token
= get_handle( &args
);
186 ULONG flags
= get_ulong( &args
);
187 TOKEN_GROUPS32
*disable_sids32
= get_ptr( &args
);
188 TOKEN_PRIVILEGES
*privs
= get_ptr( &args
);
189 TOKEN_GROUPS32
*restrict_sids32
= get_ptr( &args
);
190 ULONG
*handle_ptr
= get_ptr( &args
);
196 status
= NtFilterToken( token
, flags
, token_groups_32to64( disable_sids32
), privs
,
197 token_groups_32to64( restrict_sids32
), &handle
);
198 put_handle( handle_ptr
, handle
);
203 /**********************************************************************
204 * wow64_NtImpersonateAnonymousToken
206 NTSTATUS WINAPI
wow64_NtImpersonateAnonymousToken( UINT
*args
)
208 HANDLE handle
= get_handle( &args
);
210 return NtImpersonateAnonymousToken( handle
);
214 /**********************************************************************
215 * wow64_NtOpenProcessToken
217 NTSTATUS WINAPI
wow64_NtOpenProcessToken( UINT
*args
)
219 HANDLE process
= get_handle( &args
);
220 ACCESS_MASK access
= get_ulong( &args
);
221 ULONG
*handle_ptr
= get_ptr( &args
);
227 status
= NtOpenProcessToken( process
, access
, &handle
);
228 put_handle( handle_ptr
, handle
);
233 /**********************************************************************
234 * wow64_NtOpenProcessTokenEx
236 NTSTATUS WINAPI
wow64_NtOpenProcessTokenEx( UINT
*args
)
238 HANDLE process
= get_handle( &args
);
239 ACCESS_MASK access
= get_ulong( &args
);
240 ULONG attributes
= get_ulong( &args
);
241 ULONG
*handle_ptr
= get_ptr( &args
);
247 status
= NtOpenProcessTokenEx( process
, access
, attributes
, &handle
);
248 put_handle( handle_ptr
, handle
);
253 /**********************************************************************
254 * wow64_NtOpenThreadToken
256 NTSTATUS WINAPI
wow64_NtOpenThreadToken( UINT
*args
)
258 HANDLE thread
= get_handle( &args
);
259 ACCESS_MASK access
= get_ulong( &args
);
260 BOOLEAN self
= get_ulong( &args
);
261 ULONG
*handle_ptr
= get_ptr( &args
);
267 status
= NtOpenThreadToken( thread
, access
, self
, &handle
);
268 put_handle( handle_ptr
, handle
);
273 /**********************************************************************
274 * wow64_NtOpenThreadTokenEx
276 NTSTATUS WINAPI
wow64_NtOpenThreadTokenEx( UINT
*args
)
278 HANDLE thread
= get_handle( &args
);
279 ACCESS_MASK access
= get_ulong( &args
);
280 BOOLEAN self
= get_ulong( &args
);
281 ULONG attributes
= get_ulong( &args
);
282 ULONG
*handle_ptr
= get_ptr( &args
);
288 status
= NtOpenThreadTokenEx( thread
, access
, self
, attributes
, &handle
);
289 put_handle( handle_ptr
, handle
);
294 /**********************************************************************
295 * wow64_NtPrivilegeCheck
297 NTSTATUS WINAPI
wow64_NtPrivilegeCheck( UINT
*args
)
299 HANDLE token
= get_handle( &args
);
300 PRIVILEGE_SET
*privs
= get_ptr( &args
);
301 BOOLEAN
*res
= get_ptr( &args
);
303 return NtPrivilegeCheck( token
, privs
, res
);
307 /**********************************************************************
308 * wow64_NtQueryInformationToken
310 NTSTATUS WINAPI
wow64_NtQueryInformationToken( UINT
*args
)
312 HANDLE handle
= get_handle( &args
);
313 TOKEN_INFORMATION_CLASS
class = get_ulong( &args
);
314 void *info
= get_ptr( &args
);
315 ULONG len
= get_ulong( &args
);
316 ULONG
*retlen
= get_ptr( &args
);
319 ULONG ret_size
, sid_len
;
323 case TokenPrivileges
: /* TOKEN_PRIVILEGES */
324 case TokenImpersonationLevel
: /* SECURITY_IMPERSONATION_LEVEL */
325 case TokenStatistics
: /* TOKEN_STATISTICS */
326 case TokenType
: /* TOKEN_TYPE */
327 case TokenElevationType
: /* TOKEN_ELEVATION_TYPE */
328 case TokenElevation
: /* TOKEN_ELEVATION */
329 case TokenSessionId
: /* ULONG */
330 case TokenVirtualizationEnabled
: /* ULONG */
331 case TokenIsAppContainer
: /* ULONG */
333 return NtQueryInformationToken( handle
, class, info
, len
, retlen
);
335 case TokenUser
: /* TOKEN_USER + SID */
336 case TokenIntegrityLevel
: /* TOKEN_MANDATORY_LABEL + SID */
338 ULONG_PTR buffer
[(sizeof(TOKEN_USER
) + SECURITY_MAX_SID_SIZE
) / sizeof(ULONG_PTR
)];
339 TOKEN_USER
*user
= (TOKEN_USER
*)buffer
;
340 TOKEN_USER32
*user32
= info
;
343 status
= NtQueryInformationToken( handle
, class, &buffer
, sizeof(buffer
), &ret_size
);
344 if (status
) return status
;
345 sid
= user
->User
.Sid
;
346 sid_len
= offsetof( SID
, SubAuthority
[sid
->SubAuthorityCount
] );
347 if (len
>= sizeof(*user32
) + sid_len
)
349 user32
->User
.Sid
= PtrToUlong( user32
+ 1 );
350 user32
->User
.Attributes
= user
->User
.Attributes
;
351 memcpy( user32
+ 1, sid
, sid_len
);
353 else status
= STATUS_BUFFER_TOO_SMALL
;
354 if (retlen
) *retlen
= sizeof(*user32
) + sid_len
;
358 case TokenOwner
: /* TOKEN_OWNER + SID */
359 case TokenPrimaryGroup
: /* TOKEN_PRIMARY_GROUP + SID */
360 case TokenAppContainerSid
: /* TOKEN_APPCONTAINER_INFORMATION + SID */
362 ULONG_PTR buffer
[(sizeof(TOKEN_OWNER
) + SECURITY_MAX_SID_SIZE
) / sizeof(ULONG_PTR
)];
363 TOKEN_OWNER
*owner
= (TOKEN_OWNER
*)buffer
;
364 TOKEN_OWNER32
*owner32
= info
;
367 status
= NtQueryInformationToken( handle
, class, &buffer
, sizeof(buffer
), &ret_size
);
368 if (status
) return status
;
370 sid_len
= offsetof( SID
, SubAuthority
[sid
->SubAuthorityCount
] );
371 if (len
>= sizeof(*owner32
) + sid_len
)
373 owner32
->Owner
= PtrToUlong( owner32
+ 1 );
374 memcpy( owner32
+ 1, sid
, sid_len
);
376 else status
= STATUS_BUFFER_TOO_SMALL
;
377 if (retlen
) *retlen
= sizeof(*owner32
) + sid_len
;
381 case TokenGroups
: /* TOKEN_GROUPS */
382 case TokenLogonSid
: /* TOKEN_GROUPS */
384 TOKEN_GROUPS32
*groups32
= info
;
385 TOKEN_GROUPS
*groups
;
386 ULONG i
, group_len
, group32_len
;
388 status
= NtQueryInformationToken( handle
, class, NULL
, 0, &ret_size
);
389 if (status
!= STATUS_BUFFER_TOO_SMALL
) return status
;
390 groups
= Wow64AllocateTemp( ret_size
);
391 status
= NtQueryInformationToken( handle
, class, groups
, ret_size
, &ret_size
);
392 if (status
) return status
;
393 group_len
= offsetof( TOKEN_GROUPS
, Groups
[groups
->GroupCount
] );
394 group32_len
= offsetof( TOKEN_GROUPS32
, Groups
[groups
->GroupCount
] );
395 sid_len
= ret_size
- group_len
;
396 ret_size
= group32_len
+ sid_len
;
399 SID
*sid
= (SID
*)((char *)groups
+ group_len
);
400 SID
*sid32
= (SID
*)((char *)groups32
+ group32_len
);
402 memcpy( sid32
, sid
, sid_len
);
403 groups32
->GroupCount
= groups
->GroupCount
;
404 for (i
= 0; i
< groups
->GroupCount
; i
++)
406 groups32
->Groups
[i
].Sid
= PtrToUlong(sid32
) + ((char *)groups
->Groups
[i
].Sid
- (char *)sid
);
407 groups32
->Groups
[i
].Attributes
= groups
->Groups
[i
].Attributes
;
410 else status
= STATUS_BUFFER_TOO_SMALL
;
411 if (retlen
) *retlen
= ret_size
;
415 case TokenDefaultDacl
: /* TOKEN_DEFAULT_DACL + ACL */
417 ULONG size
= len
+ sizeof(TOKEN_DEFAULT_DACL
) - sizeof(TOKEN_DEFAULT_DACL32
);
418 TOKEN_DEFAULT_DACL32
*dacl32
= info
;
419 TOKEN_DEFAULT_DACL
*dacl
= Wow64AllocateTemp( size
);
421 status
= NtQueryInformationToken( handle
, class, dacl
, size
, &ret_size
);
424 dacl32
->DefaultDacl
= dacl
->DefaultDacl
? PtrToUlong( dacl32
+ 1 ) : 0;
425 memcpy( dacl32
+ 1, dacl
->DefaultDacl
, ret_size
- sizeof(*dacl
) );
427 if (retlen
) *retlen
= ret_size
+ sizeof(*dacl32
) - sizeof(*dacl
);
431 case TokenLinkedToken
: /* TOKEN_LINKED_TOKEN */
433 TOKEN_LINKED_TOKEN link
;
435 status
= NtQueryInformationToken( handle
, class, &link
, sizeof(link
), &ret_size
);
436 if (!status
) *(ULONG
*)info
= HandleToLong( link
.LinkedToken
);
437 if (retlen
) *retlen
= sizeof(ULONG
);
442 FIXME( "unsupported class %u\n", class );
443 return STATUS_INVALID_INFO_CLASS
;
448 /**********************************************************************
449 * wow64_NtQuerySecurityObject
451 NTSTATUS WINAPI
wow64_NtQuerySecurityObject( UINT
*args
)
453 HANDLE handle
= get_handle( &args
);
454 SECURITY_INFORMATION info
= get_ulong( &args
);
455 SECURITY_DESCRIPTOR
*sd
= get_ptr( &args
);
456 ULONG len
= get_ulong( &args
);
457 ULONG
*retlen
= get_ptr( &args
);
459 /* returned descriptor is always SE_SELF_RELATIVE, no mapping needed */
460 return NtQuerySecurityObject( handle
, info
, sd
, len
, retlen
);
464 /**********************************************************************
465 * wow64_NtSetInformationToken
467 NTSTATUS WINAPI
wow64_NtSetInformationToken( UINT
*args
)
469 HANDLE handle
= get_handle( &args
);
470 TOKEN_INFORMATION_CLASS
class = get_ulong( &args
);
471 void *ptr
= get_ptr( &args
);
472 ULONG len
= get_ulong( &args
);
476 case TokenSessionId
: /* ULONG */
477 return NtSetInformationToken( handle
, class, ptr
, len
);
479 case TokenDefaultDacl
: /* TOKEN_DEFAULT_DACL */
480 if (len
>= sizeof(TOKEN_DEFAULT_DACL32
))
482 TOKEN_DEFAULT_DACL32
*dacl32
= ptr
;
483 TOKEN_DEFAULT_DACL dacl
= { ULongToPtr( dacl32
->DefaultDacl
) };
485 return NtSetInformationToken( handle
, class, &dacl
, sizeof(dacl
) );
487 else return STATUS_INFO_LENGTH_MISMATCH
;
490 FIXME( "unsupported class %u\n", class );
491 return STATUS_INVALID_INFO_CLASS
;
496 /**********************************************************************
497 * wow64_NtSetSecurityObject
499 NTSTATUS WINAPI
wow64_NtSetSecurityObject( UINT
*args
)
501 HANDLE handle
= get_handle( &args
);
502 SECURITY_INFORMATION info
= get_ulong( &args
);
503 SECURITY_DESCRIPTOR
*sd32
= get_ptr( &args
);
505 SECURITY_DESCRIPTOR sd
;
507 return NtSetSecurityObject( handle
, info
, secdesc_32to64( &sd
, sd32
));