uiautomationcore/tests: Add tests for cached value helper functions in the COM API.
[wine.git] / dlls / wow64 / security.c
blob26d413baa130e57d74851d8d9914d64940824b4d
1 /*
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
21 #include <stdarg.h>
23 #include "ntstatus.h"
24 #define WIN32_NO_STATUS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winnt.h"
28 #include "winternl.h"
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 )
37 TOKEN_GROUPS *groups;
38 ULONG i;
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;
48 return groups;
52 /**********************************************************************
53 * wow64_NtAccessCheck
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 );
152 *handle_ptr = 0;
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;
177 TOKEN_USER user;
178 TOKEN_OWNER owner;
179 TOKEN_PRIMARY_GROUP group;
180 TOKEN_DEFAULT_DACL dacl;
181 HANDLE handle = 0;
182 NTSTATUS status;
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 );
189 return status;
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;
206 HANDLE handle = 0;
207 NTSTATUS status;
209 *handle_ptr = 0;
210 status = NtDuplicateToken( token, access, objattr_32to64( &attr, attr32 ), effective_only, type, &handle );
211 put_handle( handle_ptr, handle );
212 return status;
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 );
228 HANDLE handle = 0;
229 NTSTATUS status;
231 *handle_ptr = 0;
232 status = NtFilterToken( token, flags, token_groups_32to64( disable_sids32 ), privs,
233 token_groups_32to64( restrict_sids32 ), &handle );
234 put_handle( handle_ptr, handle );
235 return status;
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 );
259 HANDLE handle = 0;
260 NTSTATUS status;
262 *handle_ptr = 0;
263 status = NtOpenProcessToken( process, access, &handle );
264 put_handle( handle_ptr, handle );
265 return status;
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 );
279 HANDLE handle = 0;
280 NTSTATUS status;
282 *handle_ptr = 0;
283 status = NtOpenProcessTokenEx( process, access, attributes, &handle );
284 put_handle( handle_ptr, handle );
285 return status;
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 );
299 HANDLE handle = 0;
300 NTSTATUS status;
302 *handle_ptr = 0;
303 status = NtOpenThreadToken( thread, access, self, &handle );
304 put_handle( handle_ptr, handle );
305 return status;
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 );
320 HANDLE handle = 0;
321 NTSTATUS status;
323 *handle_ptr = 0;
324 status = NtOpenThreadTokenEx( thread, access, self, attributes, &handle );
325 put_handle( handle_ptr, handle );
326 return status;
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 );
354 NTSTATUS status;
355 ULONG ret_size, sid_len;
357 switch (class)
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 */
368 /* nothing to map */
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;
377 SID *sid;
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;
391 return status;
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;
401 SID *sid;
403 status = NtQueryInformationToken( handle, class, &buffer, sizeof(buffer), &ret_size );
404 if (status) return status;
405 sid = owner->Owner;
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;
414 return status;
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;
433 if (len >= ret_size)
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;
448 return status;
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 );
458 if (!status)
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);
464 return status;
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);
474 return status;
477 default:
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 );
510 switch (class)
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;
525 default:
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 ));