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_NtCompareTokens
242 NTSTATUS WINAPI
wow64_NtCompareTokens( UINT
*args
)
244 HANDLE first
= get_handle( &args
);
245 HANDLE second
= get_handle( &args
);
246 BOOLEAN
*equal
= get_ptr( &args
);
248 return NtCompareTokens( first
, second
, equal
);
251 /**********************************************************************
252 * wow64_NtImpersonateAnonymousToken
254 NTSTATUS WINAPI
wow64_NtImpersonateAnonymousToken( UINT
*args
)
256 HANDLE handle
= get_handle( &args
);
258 return NtImpersonateAnonymousToken( handle
);
262 /**********************************************************************
263 * wow64_NtOpenProcessToken
265 NTSTATUS WINAPI
wow64_NtOpenProcessToken( UINT
*args
)
267 HANDLE process
= get_handle( &args
);
268 ACCESS_MASK access
= get_ulong( &args
);
269 ULONG
*handle_ptr
= get_ptr( &args
);
275 status
= NtOpenProcessToken( process
, access
, &handle
);
276 put_handle( handle_ptr
, handle
);
281 /**********************************************************************
282 * wow64_NtOpenProcessTokenEx
284 NTSTATUS WINAPI
wow64_NtOpenProcessTokenEx( UINT
*args
)
286 HANDLE process
= get_handle( &args
);
287 ACCESS_MASK access
= get_ulong( &args
);
288 ULONG attributes
= get_ulong( &args
);
289 ULONG
*handle_ptr
= get_ptr( &args
);
295 status
= NtOpenProcessTokenEx( process
, access
, attributes
, &handle
);
296 put_handle( handle_ptr
, handle
);
301 /**********************************************************************
302 * wow64_NtOpenThreadToken
304 NTSTATUS WINAPI
wow64_NtOpenThreadToken( UINT
*args
)
306 HANDLE thread
= get_handle( &args
);
307 ACCESS_MASK access
= get_ulong( &args
);
308 BOOLEAN self
= get_ulong( &args
);
309 ULONG
*handle_ptr
= get_ptr( &args
);
315 status
= NtOpenThreadToken( thread
, access
, self
, &handle
);
316 put_handle( handle_ptr
, handle
);
321 /**********************************************************************
322 * wow64_NtOpenThreadTokenEx
324 NTSTATUS WINAPI
wow64_NtOpenThreadTokenEx( UINT
*args
)
326 HANDLE thread
= get_handle( &args
);
327 ACCESS_MASK access
= get_ulong( &args
);
328 BOOLEAN self
= get_ulong( &args
);
329 ULONG attributes
= get_ulong( &args
);
330 ULONG
*handle_ptr
= get_ptr( &args
);
336 status
= NtOpenThreadTokenEx( thread
, access
, self
, attributes
, &handle
);
337 put_handle( handle_ptr
, handle
);
342 /**********************************************************************
343 * wow64_NtPrivilegeCheck
345 NTSTATUS WINAPI
wow64_NtPrivilegeCheck( UINT
*args
)
347 HANDLE token
= get_handle( &args
);
348 PRIVILEGE_SET
*privs
= get_ptr( &args
);
349 BOOLEAN
*res
= get_ptr( &args
);
351 return NtPrivilegeCheck( token
, privs
, res
);
355 /**********************************************************************
356 * wow64_NtQueryInformationToken
358 NTSTATUS WINAPI
wow64_NtQueryInformationToken( UINT
*args
)
360 HANDLE handle
= get_handle( &args
);
361 TOKEN_INFORMATION_CLASS
class = get_ulong( &args
);
362 void *info
= get_ptr( &args
);
363 ULONG len
= get_ulong( &args
);
364 ULONG
*retlen
= get_ptr( &args
);
367 ULONG ret_size
, sid_len
;
371 case TokenPrivileges
: /* TOKEN_PRIVILEGES */
372 case TokenImpersonationLevel
: /* SECURITY_IMPERSONATION_LEVEL */
373 case TokenStatistics
: /* TOKEN_STATISTICS */
374 case TokenType
: /* TOKEN_TYPE */
375 case TokenElevationType
: /* TOKEN_ELEVATION_TYPE */
376 case TokenElevation
: /* TOKEN_ELEVATION */
377 case TokenSessionId
: /* ULONG */
378 case TokenVirtualizationEnabled
: /* ULONG */
379 case TokenIsAppContainer
: /* ULONG */
381 return NtQueryInformationToken( handle
, class, info
, len
, retlen
);
383 case TokenUser
: /* TOKEN_USER + SID */
384 case TokenIntegrityLevel
: /* TOKEN_MANDATORY_LABEL + SID */
386 ULONG_PTR buffer
[(sizeof(TOKEN_USER
) + SECURITY_MAX_SID_SIZE
) / sizeof(ULONG_PTR
)];
387 TOKEN_USER
*user
= (TOKEN_USER
*)buffer
;
388 TOKEN_USER32
*user32
= info
;
391 status
= NtQueryInformationToken( handle
, class, &buffer
, sizeof(buffer
), &ret_size
);
392 if (status
) return status
;
393 sid
= user
->User
.Sid
;
394 sid_len
= offsetof( SID
, SubAuthority
[sid
->SubAuthorityCount
] );
395 if (len
>= sizeof(*user32
) + sid_len
)
397 user32
->User
.Sid
= PtrToUlong( user32
+ 1 );
398 user32
->User
.Attributes
= user
->User
.Attributes
;
399 memcpy( user32
+ 1, sid
, sid_len
);
401 else status
= STATUS_BUFFER_TOO_SMALL
;
402 if (retlen
) *retlen
= sizeof(*user32
) + sid_len
;
406 case TokenOwner
: /* TOKEN_OWNER + SID */
407 case TokenPrimaryGroup
: /* TOKEN_PRIMARY_GROUP + SID */
408 case TokenAppContainerSid
: /* TOKEN_APPCONTAINER_INFORMATION + SID */
410 ULONG_PTR buffer
[(sizeof(TOKEN_OWNER
) + SECURITY_MAX_SID_SIZE
) / sizeof(ULONG_PTR
)];
411 TOKEN_OWNER
*owner
= (TOKEN_OWNER
*)buffer
;
412 TOKEN_OWNER32
*owner32
= info
;
415 status
= NtQueryInformationToken( handle
, class, &buffer
, sizeof(buffer
), &ret_size
);
416 if (status
) return status
;
418 sid_len
= offsetof( SID
, SubAuthority
[sid
->SubAuthorityCount
] );
419 if (len
>= sizeof(*owner32
) + sid_len
)
421 owner32
->Owner
= PtrToUlong( owner32
+ 1 );
422 memcpy( owner32
+ 1, sid
, sid_len
);
424 else status
= STATUS_BUFFER_TOO_SMALL
;
425 if (retlen
) *retlen
= sizeof(*owner32
) + sid_len
;
429 case TokenGroups
: /* TOKEN_GROUPS */
430 case TokenLogonSid
: /* TOKEN_GROUPS */
432 TOKEN_GROUPS32
*groups32
= info
;
433 TOKEN_GROUPS
*groups
;
434 ULONG i
, group_len
, group32_len
;
436 status
= NtQueryInformationToken( handle
, class, NULL
, 0, &ret_size
);
437 if (status
!= STATUS_BUFFER_TOO_SMALL
) return status
;
438 groups
= Wow64AllocateTemp( ret_size
);
439 status
= NtQueryInformationToken( handle
, class, groups
, ret_size
, &ret_size
);
440 if (status
) return status
;
441 group_len
= offsetof( TOKEN_GROUPS
, Groups
[groups
->GroupCount
] );
442 group32_len
= offsetof( TOKEN_GROUPS32
, Groups
[groups
->GroupCount
] );
443 sid_len
= ret_size
- group_len
;
444 ret_size
= group32_len
+ sid_len
;
447 SID
*sid
= (SID
*)((char *)groups
+ group_len
);
448 SID
*sid32
= (SID
*)((char *)groups32
+ group32_len
);
450 memcpy( sid32
, sid
, sid_len
);
451 groups32
->GroupCount
= groups
->GroupCount
;
452 for (i
= 0; i
< groups
->GroupCount
; i
++)
454 groups32
->Groups
[i
].Sid
= PtrToUlong(sid32
) + ((char *)groups
->Groups
[i
].Sid
- (char *)sid
);
455 groups32
->Groups
[i
].Attributes
= groups
->Groups
[i
].Attributes
;
458 else status
= STATUS_BUFFER_TOO_SMALL
;
459 if (retlen
) *retlen
= ret_size
;
463 case TokenDefaultDacl
: /* TOKEN_DEFAULT_DACL + ACL */
465 ULONG size
= len
+ sizeof(TOKEN_DEFAULT_DACL
) - sizeof(TOKEN_DEFAULT_DACL32
);
466 TOKEN_DEFAULT_DACL32
*dacl32
= info
;
467 TOKEN_DEFAULT_DACL
*dacl
= Wow64AllocateTemp( size
);
469 status
= NtQueryInformationToken( handle
, class, dacl
, size
, &ret_size
);
472 dacl32
->DefaultDacl
= dacl
->DefaultDacl
? PtrToUlong( dacl32
+ 1 ) : 0;
473 memcpy( dacl32
+ 1, dacl
->DefaultDacl
, ret_size
- sizeof(*dacl
) );
475 if (retlen
) *retlen
= ret_size
+ sizeof(*dacl32
) - sizeof(*dacl
);
479 case TokenLinkedToken
: /* TOKEN_LINKED_TOKEN */
481 TOKEN_LINKED_TOKEN link
;
483 status
= NtQueryInformationToken( handle
, class, &link
, sizeof(link
), &ret_size
);
484 if (!status
) *(ULONG
*)info
= HandleToLong( link
.LinkedToken
);
485 if (retlen
) *retlen
= sizeof(ULONG
);
490 FIXME( "unsupported class %u\n", class );
491 return STATUS_INVALID_INFO_CLASS
;
496 /**********************************************************************
497 * wow64_NtQuerySecurityObject
499 NTSTATUS WINAPI
wow64_NtQuerySecurityObject( UINT
*args
)
501 HANDLE handle
= get_handle( &args
);
502 SECURITY_INFORMATION info
= get_ulong( &args
);
503 SECURITY_DESCRIPTOR
*sd
= get_ptr( &args
);
504 ULONG len
= get_ulong( &args
);
505 ULONG
*retlen
= get_ptr( &args
);
507 /* returned descriptor is always SE_SELF_RELATIVE, no mapping needed */
508 return NtQuerySecurityObject( handle
, info
, sd
, len
, retlen
);
512 /**********************************************************************
513 * wow64_NtSetInformationToken
515 NTSTATUS WINAPI
wow64_NtSetInformationToken( UINT
*args
)
517 HANDLE handle
= get_handle( &args
);
518 TOKEN_INFORMATION_CLASS
class = get_ulong( &args
);
519 void *ptr
= get_ptr( &args
);
520 ULONG len
= get_ulong( &args
);
524 case TokenIntegrityLevel
: /* TOKEN_MANDATORY_LABEL */
525 if (len
>= sizeof(TOKEN_MANDATORY_LABEL32
))
527 TOKEN_MANDATORY_LABEL32
*label32
= ptr
;
528 TOKEN_MANDATORY_LABEL label
;
530 label
.Label
.Sid
= ULongToPtr( label32
->Label
.Sid
);
531 label
.Label
.Attributes
= label32
->Label
.Attributes
;
532 return NtSetInformationToken( handle
, class, &label
, sizeof(label
) );
534 else return STATUS_INFO_LENGTH_MISMATCH
;
536 case TokenSessionId
: /* ULONG */
537 return NtSetInformationToken( handle
, class, ptr
, len
);
539 case TokenDefaultDacl
: /* TOKEN_DEFAULT_DACL */
540 if (len
>= sizeof(TOKEN_DEFAULT_DACL32
))
542 TOKEN_DEFAULT_DACL32
*dacl32
= ptr
;
543 TOKEN_DEFAULT_DACL dacl
= { ULongToPtr( dacl32
->DefaultDacl
) };
545 return NtSetInformationToken( handle
, class, &dacl
, sizeof(dacl
) );
547 else return STATUS_INFO_LENGTH_MISMATCH
;
550 FIXME( "unsupported class %u\n", class );
551 return STATUS_NOT_IMPLEMENTED
;
556 /**********************************************************************
557 * wow64_NtSetSecurityObject
559 NTSTATUS WINAPI
wow64_NtSetSecurityObject( UINT
*args
)
561 HANDLE handle
= get_handle( &args
);
562 SECURITY_INFORMATION info
= get_ulong( &args
);
563 SECURITY_DESCRIPTOR
*sd32
= get_ptr( &args
);
565 SECURITY_DESCRIPTOR sd
;
567 return NtSetSecurityObject( handle
, info
, secdesc_32to64( &sd
, sd32
));