Correct a problem with parse_data if binary data was not in full bytes.
[wine.git] / server / token.c
blob1b94ec46a07d70c6b150efdb8a13364bf112b940
1 /*
2 * Tokens
4 * Copyright (C) 1998 Alexandre Julliard
5 * Copyright (C) 2003 Mike McCormack
6 * Copyright (C) 2005 Robert Shearman
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "config.h"
25 #include <assert.h>
26 #include <stdio.h>
27 #include <stdlib.h>
29 #include "windef.h"
31 #include "handle.h"
32 #include "thread.h"
33 #include "process.h"
34 #include "request.h"
35 #include "security.h"
37 #define MAX_SUBAUTH_COUNT 1
39 const LUID SeIncreaseQuotaPrivilege = { 5, 0 };
40 const LUID SeSecurityPrivilege = { 8, 0 };
41 const LUID SeTakeOwnershipPrivilege = { 9, 0 };
42 const LUID SeLoadDriverPrivilege = { 10, 0 };
43 const LUID SeSystemProfilePrivilege = { 11, 0 };
44 const LUID SeSystemtimePrivilege = { 12, 0 };
45 const LUID SeProfileSingleProcessPrivilege = { 13, 0 };
46 const LUID SeIncreaseBasePriorityPrivilege = { 14, 0 };
47 const LUID SeCreatePagefilePrivilege = { 15, 0 };
48 const LUID SeBackupPrivilege = { 17, 0 };
49 const LUID SeRestorePrivilege = { 18, 0 };
50 const LUID SeShutdownPrivilege = { 19, 0 };
51 const LUID SeDebugPrivilege = { 20, 0 };
52 const LUID SeSystemEnvironmentPrivilege = { 22, 0 };
53 const LUID SeChangeNotifyPrivilege = { 23, 0 };
54 const LUID SeRemoteShutdownPrivilege = { 24, 0 };
55 const LUID SeUndockPrivilege = { 25, 0 };
56 const LUID SeManageVolumePrivilege = { 28, 0 };
57 const LUID SeImpersonatePrivilege = { 29, 0 };
58 const LUID SeCreateGlobalPrivilege = { 30, 0 };
60 struct token
62 struct object obj; /* object header */
63 struct list privileges; /* privileges available to the token */
64 SID *user; /* SID of user this token represents */
67 struct privilege
69 struct list entry;
70 LUID luid;
71 unsigned enabled : 1; /* is the privilege currently enabled? */
72 unsigned def : 1; /* is the privilege enabled by default? */
75 static void token_dump( struct object *obj, int verbose );
76 static void token_destroy( struct object *obj );
78 static const struct object_ops token_ops =
80 sizeof(struct token), /* size */
81 token_dump, /* dump */
82 no_add_queue, /* add_queue */
83 NULL, /* remove_queue */
84 NULL, /* signaled */
85 NULL, /* satisfied */
86 no_signal, /* signal */
87 no_get_fd, /* get_fd */
88 token_destroy /* destroy */
92 static void token_dump( struct object *obj, int verbose )
94 fprintf( stderr, "Security token\n" );
97 static SID *security_sid_alloc( const SID_IDENTIFIER_AUTHORITY *idauthority, int subauthcount, const unsigned int subauth[] )
99 int i;
100 SID *sid = mem_alloc( FIELD_OFFSET(SID, SubAuthority[subauthcount]) );
101 if (!sid) return NULL;
102 sid->Revision = MAX_ACL_REVISION;
103 sid->SubAuthorityCount = subauthcount;
104 sid->IdentifierAuthority = *idauthority;
105 for (i = 0; i < subauthcount; i++)
106 sid->SubAuthority[i] = subauth[i];
107 return sid;
110 static inline int security_equal_sid( const SID *sid1, const SID *sid2 )
112 return ((sid1->SubAuthorityCount == sid2->SubAuthorityCount) &&
113 !memcmp( sid1, sid2, FIELD_OFFSET(SID, SubAuthority[sid1->SubAuthorityCount]) ));
116 static inline int is_equal_luid( const LUID *luid1, const LUID *luid2 )
118 return (luid1->LowPart == luid2->LowPart && luid1->HighPart == luid2->HighPart);
121 static inline void luid_and_attr_from_privilege( LUID_AND_ATTRIBUTES *out, const struct privilege *in)
123 out->Luid = in->luid;
124 out->Attributes =
125 (in->enabled ? SE_PRIVILEGE_ENABLED : 0) |
126 (in->def ? SE_PRIVILEGE_ENABLED_BY_DEFAULT : 0);
129 static struct privilege *privilege_add( struct token *token, const LUID *luid, int enabled )
131 struct privilege *privilege = mem_alloc( sizeof(*privilege) );
132 if (privilege)
134 privilege->luid = *luid;
135 privilege->def = privilege->enabled = (enabled != 0);
136 list_add_tail( &token->privileges, &privilege->entry );
138 return privilege;
141 static inline void privilege_remove( struct privilege *privilege )
143 list_remove( &privilege->entry );
144 free( privilege );
147 static void token_destroy( struct object *obj )
149 struct token* token;
150 struct list *cursor, *cursor_next;
152 assert( obj->ops == &token_ops );
153 token = (struct token *)obj;
155 free( token->user );
157 LIST_FOR_EACH_SAFE( cursor, cursor_next, &token->privileges )
159 struct privilege *privilege = LIST_ENTRY( cursor, struct privilege, entry );
160 privilege_remove( privilege );
164 static struct token *create_token( const SID *user, const LUID_AND_ATTRIBUTES *privs, unsigned int priv_count )
166 struct token *token = alloc_object( &token_ops );
167 if (token)
169 int i;
170 list_init( &token->privileges );
171 /* copy user */
172 token->user = memdup( user, FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) );
173 if (!token->user)
175 release_object( token );
176 return NULL;
178 /* copy privileges */
179 for (i = 0; i < priv_count; i++)
181 /* note: we don't check uniqueness: the caller must make sure
182 * privs doesn't contain any duplicate luids */
183 if (!privilege_add( token, &privs[i].Luid,
184 privs[i].Attributes & SE_PRIVILEGE_ENABLED ))
186 release_object( token );
187 return NULL;
191 return token;
194 struct sid_data
196 SID_IDENTIFIER_AUTHORITY idauth;
197 int count;
198 unsigned int subauth[MAX_SUBAUTH_COUNT];
201 struct token *token_create_admin( void )
203 struct token *token;
204 const LUID_AND_ATTRIBUTES admin_privs[] =
206 { SeChangeNotifyPrivilege , SE_PRIVILEGE_ENABLED },
207 { SeSecurityPrivilege , 0 },
208 { SeBackupPrivilege , 0 },
209 { SeRestorePrivilege , 0 },
210 { SeSystemtimePrivilege , 0 },
211 { SeShutdownPrivilege , 0 },
212 { SeRemoteShutdownPrivilege , 0 },
213 { SeTakeOwnershipPrivilege , 0 },
214 { SeDebugPrivilege , 0 },
215 { SeSystemEnvironmentPrivilege , 0 },
216 { SeSystemProfilePrivilege , 0 },
217 { SeProfileSingleProcessPrivilege, 0 },
218 { SeIncreaseBasePriorityPrivilege, 0 },
219 { SeLoadDriverPrivilege , 0 },
220 { SeCreatePagefilePrivilege , 0 },
221 { SeIncreaseQuotaPrivilege , 0 },
222 { SeUndockPrivilege , 0 },
223 { SeManageVolumePrivilege , 0 },
224 { SeImpersonatePrivilege , SE_PRIVILEGE_ENABLED },
225 { SeCreateGlobalPrivilege , SE_PRIVILEGE_ENABLED },
227 static const struct sid_data well_known_sid_data[] =
229 { { SECURITY_NT_AUTHORITY }, 1, { SECURITY_LOCAL_SYSTEM_RID } }, /* LOCAL_SYSTEM */
231 SID *local_system_sid = security_sid_alloc(
232 &well_known_sid_data[0].idauth,
233 well_known_sid_data[0].count,
234 well_known_sid_data[0].subauth );
235 if (!local_system_sid) return NULL;
236 token = create_token( local_system_sid, admin_privs, sizeof(admin_privs)/sizeof(admin_privs[0]) );
237 free( local_system_sid );
238 return token;
241 static struct privilege *token_find_privilege( struct token *token, const LUID *luid, int enabled_only)
243 struct privilege *privilege;
244 LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
246 if (is_equal_luid( luid, &privilege->luid ))
248 if (enabled_only && !privilege->enabled)
249 return NULL;
250 return privilege;
253 return NULL;
256 static unsigned int token_adjust_privileges( struct token *token, const LUID_AND_ATTRIBUTES *privs,
257 unsigned int count, LUID_AND_ATTRIBUTES *mod_privs,
258 unsigned int mod_privs_count)
260 int i;
261 unsigned int modified_count = 0;
263 for (i = 0; i < count; i++)
265 struct privilege *privilege =
266 token_find_privilege( token, &privs[i].Luid, FALSE );
267 if (!privilege)
269 set_error( STATUS_NOT_ALL_ASSIGNED );
270 continue;
273 if (privs[i].Attributes & SE_PRIVILEGE_REMOVE)
274 privilege_remove( privilege );
275 else
277 /* save previous state for caller */
278 if (mod_privs_count)
280 luid_and_attr_from_privilege(mod_privs, privilege);
281 mod_privs++;
282 mod_privs_count--;
283 modified_count++;
286 if (privs[i].Attributes & SE_PRIVILEGE_ENABLED)
287 privilege->enabled = TRUE;
288 else
289 privilege->enabled = FALSE;
292 return modified_count;
295 static void token_disable_privileges( struct token *token )
297 struct privilege *privilege;
298 LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
299 privilege->enabled = FALSE;
302 int token_check_privileges( struct token *token, int all_required,
303 const LUID_AND_ATTRIBUTES *reqprivs,
304 unsigned int count, LUID_AND_ATTRIBUTES *usedprivs)
306 int i;
307 unsigned int enabled_count = 0;
309 for (i = 0; i < count; i++)
311 struct privilege *privilege =
312 token_find_privilege( token, &reqprivs[i].Luid, TRUE );
314 if (usedprivs)
315 usedprivs[i] = reqprivs[i];
317 if (privilege && privilege->enabled)
319 enabled_count++;
320 if (usedprivs)
321 usedprivs[i].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
325 if (all_required)
326 return (enabled_count == count);
327 else
328 return (enabled_count > 0);
331 /* open a security token */
332 DECL_HANDLER(open_token)
334 if( req->flags & OPEN_TOKEN_THREAD )
336 struct thread *thread = get_thread_from_handle( req->handle, 0 );
337 if (thread)
339 if (thread->token)
340 reply->token = alloc_handle( current->process, thread->token, TOKEN_ALL_ACCESS, 0);
341 else
342 set_error(STATUS_NO_TOKEN);
343 release_object( thread );
346 else
348 struct process *process = get_process_from_handle( req->handle, 0 );
349 if (process)
351 if (process->token)
352 reply->token = alloc_handle( current->process, process->token, TOKEN_ALL_ACCESS, 0);
353 else
354 set_error(STATUS_NO_TOKEN);
355 release_object( process );
360 /* adjust the privileges held by a token */
361 DECL_HANDLER(adjust_token_privileges)
363 struct token *token;
364 unsigned int access = TOKEN_ADJUST_PRIVILEGES;
366 if (req->get_modified_state) access |= TOKEN_QUERY;
368 if ((token = (struct token *)get_handle_obj( current->process, req->handle,
369 access, &token_ops )))
371 const LUID_AND_ATTRIBUTES *privs = get_req_data();
372 LUID_AND_ATTRIBUTES *modified_privs = NULL;
373 unsigned int priv_count = get_req_data_size() / sizeof(LUID_AND_ATTRIBUTES);
374 unsigned int modified_priv_count = 0;
376 if (req->get_modified_state && !req->disable_all)
378 int i;
379 /* count modified privs */
380 for (i = 0; i < priv_count; i++)
382 struct privilege *privilege =
383 token_find_privilege( token, &privs[i].Luid, FALSE );
384 if (privilege && req->get_modified_state)
385 modified_priv_count++;
387 reply->len = modified_priv_count;
388 modified_priv_count = min( modified_priv_count, get_reply_max_size() / sizeof(*modified_privs) );
389 if (modified_priv_count)
390 modified_privs = set_reply_data_size( modified_priv_count * sizeof(*modified_privs) );
392 reply->len = modified_priv_count * sizeof(*modified_privs);
394 if (req->disable_all)
395 token_disable_privileges( token );
396 else
397 modified_priv_count = token_adjust_privileges( token, privs,
398 priv_count, modified_privs, modified_priv_count );
400 release_object( token );
404 /* retrieves the list of privileges that may be held be the token */
405 DECL_HANDLER(get_token_privileges)
407 struct token *token;
409 if ((token = (struct token *)get_handle_obj( current->process, req->handle,
410 TOKEN_QUERY,
411 &token_ops )))
413 int priv_count = 0;
414 LUID_AND_ATTRIBUTES *privs;
415 struct privilege *privilege;
417 LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
418 priv_count++;
420 reply->len = priv_count * sizeof(*privs);
421 if (reply->len <= get_reply_max_size())
423 privs = set_reply_data_size( priv_count * sizeof(*privs) );
424 if (privs)
426 int i = 0;
427 LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
429 luid_and_attr_from_privilege( &privs[i], privilege );
430 i++;
434 else
435 set_error(STATUS_BUFFER_TOO_SMALL);
437 release_object( token );
441 /* creates a duplicate of the token */
442 DECL_HANDLER(duplicate_token)
444 struct token *src_token;
445 if ((src_token = (struct token *)get_handle_obj( current->process, req->handle,
446 TOKEN_DUPLICATE,
447 &token_ops )))
449 /* FIXME: use req->primary and req->impersonation_level */
450 struct token *token = create_token( src_token->user, NULL, 0 );
451 if (token)
453 struct privilege *privilege;
454 unsigned int access;
456 LIST_FOR_EACH_ENTRY( privilege, &src_token->privileges, struct privilege, entry )
457 privilege_add( token, &privilege->luid, privilege->enabled );
459 access = req->access;
460 if (access & MAXIMUM_ALLOWED) access = TOKEN_ALL_ACCESS; /* FIXME: needs general solution */
461 reply->new_handle = alloc_handle( current->process, token, access, req->inherit);
462 release_object( token );
464 release_object( src_token );
468 /* checks the specified privileges are held by the token */
469 DECL_HANDLER(check_token_privileges)
471 struct token *token;
473 if ((token = (struct token *)get_handle_obj( current->process, req->handle,
474 TOKEN_QUERY,
475 &token_ops )))
477 unsigned int count = get_req_data_size() / sizeof(LUID_AND_ATTRIBUTES);
478 if (get_reply_max_size() >= count * sizeof(LUID_AND_ATTRIBUTES))
480 LUID_AND_ATTRIBUTES *usedprivs = set_reply_data_size( count * sizeof(*usedprivs) );
481 reply->has_privileges = token_check_privileges( token, req->all_required, get_req_data(), count, usedprivs );
483 else
484 set_error( STATUS_BUFFER_OVERFLOW );
485 release_object( token );