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_NtCreateToken
160 NTSTATUS WINAPI
wow64_NtCreateToken( UINT
*args
)
162 ULONG
*handle_ptr
= get_ptr( &args
);
163 ACCESS_MASK access
= get_ulong( &args
);
164 OBJECT_ATTRIBUTES32
*attr32
= get_ptr( &args
);
165 TOKEN_TYPE type
= get_ulong( &args
);
166 LUID
*luid
= get_ptr( &args
);
167 LARGE_INTEGER
*expire
= get_ptr( &args
);
168 TOKEN_USER32
*user32
= get_ptr( &args
);
169 TOKEN_GROUPS32
*groups32
= get_ptr( &args
);
170 TOKEN_PRIVILEGES
*privs
= get_ptr( &args
);
171 TOKEN_OWNER32
*owner32
= get_ptr( &args
);
172 TOKEN_PRIMARY_GROUP32
*group32
= get_ptr( &args
);
173 TOKEN_DEFAULT_DACL32
*dacl32
= get_ptr( &args
);
174 TOKEN_SOURCE
*source
= get_ptr( &args
);
176 struct object_attr64 attr
;
179 TOKEN_PRIMARY_GROUP group
;
180 TOKEN_DEFAULT_DACL dacl
;
184 status
= NtCreateToken( &handle
, access
, objattr_32to64( &attr
, attr32
), type
, luid
, expire
,
185 token_user_32to64( &user
, user32
), token_groups_32to64( groups32
), privs
,
186 token_owner_32to64( &owner
, owner32
), token_primary_group_32to64( &group
, group32
),
187 token_default_dacl_32to64( &dacl
, dacl32
), source
);
188 put_handle( handle_ptr
, handle
);
193 /**********************************************************************
194 * wow64_NtDuplicateToken
196 NTSTATUS WINAPI
wow64_NtDuplicateToken( UINT
*args
)
198 HANDLE token
= get_handle( &args
);
199 ACCESS_MASK access
= get_ulong( &args
);
200 OBJECT_ATTRIBUTES32
*attr32
= get_ptr( &args
);
201 BOOLEAN effective_only
= get_ulong( &args
);
202 TOKEN_TYPE type
= get_ulong( &args
);
203 ULONG
*handle_ptr
= get_ptr( &args
);
205 struct object_attr64 attr
;
210 status
= NtDuplicateToken( token
, access
, objattr_32to64( &attr
, attr32
), effective_only
, type
, &handle
);
211 put_handle( handle_ptr
, handle
);
216 /**********************************************************************
217 * wow64_NtFilterToken
219 NTSTATUS WINAPI
wow64_NtFilterToken( UINT
*args
)
221 HANDLE token
= get_handle( &args
);
222 ULONG flags
= get_ulong( &args
);
223 TOKEN_GROUPS32
*disable_sids32
= get_ptr( &args
);
224 TOKEN_PRIVILEGES
*privs
= get_ptr( &args
);
225 TOKEN_GROUPS32
*restrict_sids32
= get_ptr( &args
);
226 ULONG
*handle_ptr
= get_ptr( &args
);
232 status
= NtFilterToken( token
, flags
, token_groups_32to64( disable_sids32
), privs
,
233 token_groups_32to64( restrict_sids32
), &handle
);
234 put_handle( handle_ptr
, handle
);
239 /**********************************************************************
240 * wow64_NtImpersonateAnonymousToken
242 NTSTATUS WINAPI
wow64_NtImpersonateAnonymousToken( UINT
*args
)
244 HANDLE handle
= get_handle( &args
);
246 return NtImpersonateAnonymousToken( handle
);
250 /**********************************************************************
251 * wow64_NtOpenProcessToken
253 NTSTATUS WINAPI
wow64_NtOpenProcessToken( UINT
*args
)
255 HANDLE process
= get_handle( &args
);
256 ACCESS_MASK access
= get_ulong( &args
);
257 ULONG
*handle_ptr
= get_ptr( &args
);
263 status
= NtOpenProcessToken( process
, access
, &handle
);
264 put_handle( handle_ptr
, handle
);
269 /**********************************************************************
270 * wow64_NtOpenProcessTokenEx
272 NTSTATUS WINAPI
wow64_NtOpenProcessTokenEx( UINT
*args
)
274 HANDLE process
= get_handle( &args
);
275 ACCESS_MASK access
= get_ulong( &args
);
276 ULONG attributes
= get_ulong( &args
);
277 ULONG
*handle_ptr
= get_ptr( &args
);
283 status
= NtOpenProcessTokenEx( process
, access
, attributes
, &handle
);
284 put_handle( handle_ptr
, handle
);
289 /**********************************************************************
290 * wow64_NtOpenThreadToken
292 NTSTATUS WINAPI
wow64_NtOpenThreadToken( UINT
*args
)
294 HANDLE thread
= get_handle( &args
);
295 ACCESS_MASK access
= get_ulong( &args
);
296 BOOLEAN self
= get_ulong( &args
);
297 ULONG
*handle_ptr
= get_ptr( &args
);
303 status
= NtOpenThreadToken( thread
, access
, self
, &handle
);
304 put_handle( handle_ptr
, handle
);
309 /**********************************************************************
310 * wow64_NtOpenThreadTokenEx
312 NTSTATUS WINAPI
wow64_NtOpenThreadTokenEx( UINT
*args
)
314 HANDLE thread
= get_handle( &args
);
315 ACCESS_MASK access
= get_ulong( &args
);
316 BOOLEAN self
= get_ulong( &args
);
317 ULONG attributes
= get_ulong( &args
);
318 ULONG
*handle_ptr
= get_ptr( &args
);
324 status
= NtOpenThreadTokenEx( thread
, access
, self
, attributes
, &handle
);
325 put_handle( handle_ptr
, handle
);
330 /**********************************************************************
331 * wow64_NtPrivilegeCheck
333 NTSTATUS WINAPI
wow64_NtPrivilegeCheck( UINT
*args
)
335 HANDLE token
= get_handle( &args
);
336 PRIVILEGE_SET
*privs
= get_ptr( &args
);
337 BOOLEAN
*res
= get_ptr( &args
);
339 return NtPrivilegeCheck( token
, privs
, res
);
343 /**********************************************************************
344 * wow64_NtQueryInformationToken
346 NTSTATUS WINAPI
wow64_NtQueryInformationToken( UINT
*args
)
348 HANDLE handle
= get_handle( &args
);
349 TOKEN_INFORMATION_CLASS
class = get_ulong( &args
);
350 void *info
= get_ptr( &args
);
351 ULONG len
= get_ulong( &args
);
352 ULONG
*retlen
= get_ptr( &args
);
355 ULONG ret_size
, sid_len
;
359 case TokenPrivileges
: /* TOKEN_PRIVILEGES */
360 case TokenImpersonationLevel
: /* SECURITY_IMPERSONATION_LEVEL */
361 case TokenStatistics
: /* TOKEN_STATISTICS */
362 case TokenType
: /* TOKEN_TYPE */
363 case TokenElevationType
: /* TOKEN_ELEVATION_TYPE */
364 case TokenElevation
: /* TOKEN_ELEVATION */
365 case TokenSessionId
: /* ULONG */
366 case TokenVirtualizationEnabled
: /* ULONG */
367 case TokenIsAppContainer
: /* ULONG */
369 return NtQueryInformationToken( handle
, class, info
, len
, retlen
);
371 case TokenUser
: /* TOKEN_USER + SID */
372 case TokenIntegrityLevel
: /* TOKEN_MANDATORY_LABEL + SID */
374 ULONG_PTR buffer
[(sizeof(TOKEN_USER
) + SECURITY_MAX_SID_SIZE
) / sizeof(ULONG_PTR
)];
375 TOKEN_USER
*user
= (TOKEN_USER
*)buffer
;
376 TOKEN_USER32
*user32
= info
;
379 status
= NtQueryInformationToken( handle
, class, &buffer
, sizeof(buffer
), &ret_size
);
380 if (status
) return status
;
381 sid
= user
->User
.Sid
;
382 sid_len
= offsetof( SID
, SubAuthority
[sid
->SubAuthorityCount
] );
383 if (len
>= sizeof(*user32
) + sid_len
)
385 user32
->User
.Sid
= PtrToUlong( user32
+ 1 );
386 user32
->User
.Attributes
= user
->User
.Attributes
;
387 memcpy( user32
+ 1, sid
, sid_len
);
389 else status
= STATUS_BUFFER_TOO_SMALL
;
390 if (retlen
) *retlen
= sizeof(*user32
) + sid_len
;
394 case TokenOwner
: /* TOKEN_OWNER + SID */
395 case TokenPrimaryGroup
: /* TOKEN_PRIMARY_GROUP + SID */
396 case TokenAppContainerSid
: /* TOKEN_APPCONTAINER_INFORMATION + SID */
398 ULONG_PTR buffer
[(sizeof(TOKEN_OWNER
) + SECURITY_MAX_SID_SIZE
) / sizeof(ULONG_PTR
)];
399 TOKEN_OWNER
*owner
= (TOKEN_OWNER
*)buffer
;
400 TOKEN_OWNER32
*owner32
= info
;
403 status
= NtQueryInformationToken( handle
, class, &buffer
, sizeof(buffer
), &ret_size
);
404 if (status
) return status
;
406 sid_len
= offsetof( SID
, SubAuthority
[sid
->SubAuthorityCount
] );
407 if (len
>= sizeof(*owner32
) + sid_len
)
409 owner32
->Owner
= PtrToUlong( owner32
+ 1 );
410 memcpy( owner32
+ 1, sid
, sid_len
);
412 else status
= STATUS_BUFFER_TOO_SMALL
;
413 if (retlen
) *retlen
= sizeof(*owner32
) + sid_len
;
417 case TokenGroups
: /* TOKEN_GROUPS */
418 case TokenLogonSid
: /* TOKEN_GROUPS */
420 TOKEN_GROUPS32
*groups32
= info
;
421 TOKEN_GROUPS
*groups
;
422 ULONG i
, group_len
, group32_len
;
424 status
= NtQueryInformationToken( handle
, class, NULL
, 0, &ret_size
);
425 if (status
!= STATUS_BUFFER_TOO_SMALL
) return status
;
426 groups
= Wow64AllocateTemp( ret_size
);
427 status
= NtQueryInformationToken( handle
, class, groups
, ret_size
, &ret_size
);
428 if (status
) return status
;
429 group_len
= offsetof( TOKEN_GROUPS
, Groups
[groups
->GroupCount
] );
430 group32_len
= offsetof( TOKEN_GROUPS32
, Groups
[groups
->GroupCount
] );
431 sid_len
= ret_size
- group_len
;
432 ret_size
= group32_len
+ sid_len
;
435 SID
*sid
= (SID
*)((char *)groups
+ group_len
);
436 SID
*sid32
= (SID
*)((char *)groups32
+ group32_len
);
438 memcpy( sid32
, sid
, sid_len
);
439 groups32
->GroupCount
= groups
->GroupCount
;
440 for (i
= 0; i
< groups
->GroupCount
; i
++)
442 groups32
->Groups
[i
].Sid
= PtrToUlong(sid32
) + ((char *)groups
->Groups
[i
].Sid
- (char *)sid
);
443 groups32
->Groups
[i
].Attributes
= groups
->Groups
[i
].Attributes
;
446 else status
= STATUS_BUFFER_TOO_SMALL
;
447 if (retlen
) *retlen
= ret_size
;
451 case TokenDefaultDacl
: /* TOKEN_DEFAULT_DACL + ACL */
453 ULONG size
= len
+ sizeof(TOKEN_DEFAULT_DACL
) - sizeof(TOKEN_DEFAULT_DACL32
);
454 TOKEN_DEFAULT_DACL32
*dacl32
= info
;
455 TOKEN_DEFAULT_DACL
*dacl
= Wow64AllocateTemp( size
);
457 status
= NtQueryInformationToken( handle
, class, dacl
, size
, &ret_size
);
460 dacl32
->DefaultDacl
= dacl
->DefaultDacl
? PtrToUlong( dacl32
+ 1 ) : 0;
461 memcpy( dacl32
+ 1, dacl
->DefaultDacl
, ret_size
- sizeof(*dacl
) );
463 if (retlen
) *retlen
= ret_size
+ sizeof(*dacl32
) - sizeof(*dacl
);
467 case TokenLinkedToken
: /* TOKEN_LINKED_TOKEN */
469 TOKEN_LINKED_TOKEN link
;
471 status
= NtQueryInformationToken( handle
, class, &link
, sizeof(link
), &ret_size
);
472 if (!status
) *(ULONG
*)info
= HandleToLong( link
.LinkedToken
);
473 if (retlen
) *retlen
= sizeof(ULONG
);
478 FIXME( "unsupported class %u\n", class );
479 return STATUS_INVALID_INFO_CLASS
;
484 /**********************************************************************
485 * wow64_NtQuerySecurityObject
487 NTSTATUS WINAPI
wow64_NtQuerySecurityObject( UINT
*args
)
489 HANDLE handle
= get_handle( &args
);
490 SECURITY_INFORMATION info
= get_ulong( &args
);
491 SECURITY_DESCRIPTOR
*sd
= get_ptr( &args
);
492 ULONG len
= get_ulong( &args
);
493 ULONG
*retlen
= get_ptr( &args
);
495 /* returned descriptor is always SE_SELF_RELATIVE, no mapping needed */
496 return NtQuerySecurityObject( handle
, info
, sd
, len
, retlen
);
500 /**********************************************************************
501 * wow64_NtSetInformationToken
503 NTSTATUS WINAPI
wow64_NtSetInformationToken( UINT
*args
)
505 HANDLE handle
= get_handle( &args
);
506 TOKEN_INFORMATION_CLASS
class = get_ulong( &args
);
507 void *ptr
= get_ptr( &args
);
508 ULONG len
= get_ulong( &args
);
512 case TokenSessionId
: /* ULONG */
513 return NtSetInformationToken( handle
, class, ptr
, len
);
515 case TokenDefaultDacl
: /* TOKEN_DEFAULT_DACL */
516 if (len
>= sizeof(TOKEN_DEFAULT_DACL32
))
518 TOKEN_DEFAULT_DACL32
*dacl32
= ptr
;
519 TOKEN_DEFAULT_DACL dacl
= { ULongToPtr( dacl32
->DefaultDacl
) };
521 return NtSetInformationToken( handle
, class, &dacl
, sizeof(dacl
) );
523 else return STATUS_INFO_LENGTH_MISMATCH
;
526 FIXME( "unsupported class %u\n", class );
527 return STATUS_NOT_IMPLEMENTED
;
532 /**********************************************************************
533 * wow64_NtSetSecurityObject
535 NTSTATUS WINAPI
wow64_NtSetSecurityObject( UINT
*args
)
537 HANDLE handle
= get_handle( &args
);
538 SECURITY_INFORMATION info
= get_ulong( &args
);
539 SECURITY_DESCRIPTOR
*sd32
= get_ptr( &args
);
541 SECURITY_DESCRIPTOR sd
;
543 return NtSetSecurityObject( handle
, info
, secdesc_32to64( &sd
, sd32
));