4 * Copyright (C) 1998 Alexandre Julliard
5 * Copyright (C) 2003 Mike McCormack
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 struct object obj
; /* object header */
38 struct list privileges
; /* privileges available to the token */
45 int enabled
: 1; /* is the privilege currently enabled? */
46 int def
: 1; /* is the privilege enabled by default? */
49 static void token_dump( struct object
*obj
, int verbose
);
50 static void token_destroy( struct object
*obj
);
52 static const struct object_ops token_ops
=
54 sizeof(struct token
), /* size */
55 token_dump
, /* dump */
56 no_add_queue
, /* add_queue */
57 NULL
, /* remove_queue */
60 no_get_fd
, /* get_fd */
61 token_destroy
/* destroy */
65 static void token_dump( struct object
*obj
, int verbose
)
67 fprintf( stderr
, "Security token\n" );
70 static inline int is_equal_luid( const LUID
*luid1
, const LUID
*luid2
)
72 return (luid1
->LowPart
== luid2
->LowPart
&& luid1
->HighPart
== luid2
->HighPart
);
75 static inline void luid_and_attr_from_privilege( LUID_AND_ATTRIBUTES
*out
, const struct privilege
*in
)
79 (in
->enabled
? SE_PRIVILEGE_ENABLED
: 0) |
80 (in
->def
? SE_PRIVILEGE_ENABLED_BY_DEFAULT
: 0);
83 static struct privilege
*privilege_add( struct token
*token
, const LUID
*luid
, int enabled
)
85 struct privilege
*privilege
= mem_alloc( sizeof(*privilege
) );
88 privilege
->luid
= *luid
;
89 privilege
->def
= privilege
->enabled
= (enabled
!= 0);
90 list_add_tail( &token
->privileges
, &privilege
->entry
);
95 static void privilege_remove( struct privilege
*privilege
)
97 list_remove( &privilege
->entry
);
101 static void token_destroy( struct object
*obj
)
104 struct list
*cursor
, *cursor_next
;
106 assert( obj
->ops
== &token_ops
);
107 token
= (struct token
*)obj
;
109 LIST_FOR_EACH_SAFE( cursor
, cursor_next
, &token
->privileges
)
111 struct privilege
*privilege
= LIST_ENTRY( cursor
, struct privilege
, entry
);
112 privilege_remove( privilege
);
116 static struct token
*create_token( const LUID_AND_ATTRIBUTES
*privs
, unsigned int priv_count
)
118 struct token
*token
= alloc_object( &token_ops
);
122 list_init( &token
->privileges
);
123 for (i
= 0; i
< priv_count
; i
++)
125 /* note: we don't check uniqueness: the caller must make sure
126 * privs doesn't contain any duplicate luids */
127 if (!privilege_add( token
, &privs
[i
].Luid
,
128 privs
[i
].Attributes
& SE_PRIVILEGE_ENABLED
))
130 release_object( token
);
138 struct token
*create_admin_token( void )
140 static const LUID_AND_ATTRIBUTES admin_privs
[] =
142 { { 23, 0 }, SE_PRIVILEGE_ENABLED
}, /* SeChangeNotifyPrivilege */
143 { { 8, 0 }, 0 }, /* SeSecurityPrivilege */
144 { { 17, 0 }, 0 }, /* SeBackupPrivilege */
145 { { 18, 0 }, 0 }, /* SeRestorePrivilege */
146 { { 12, 0 }, 0 }, /* SeSystemtimePrivilege */
147 { { 19, 0 }, 0 }, /* SeShutdownPrivilege */
148 { { 24, 0 }, 0 }, /* SeRemoteShutdownPrivilege */
149 { { 9, 0 }, 0 }, /* SeTakeOwnershipPrivilege */
150 { { 20, 0 }, 0 }, /* SeDebugPrivilege */
151 { { 22, 0 }, 0 }, /* SeSystemEnvironmentPrivilege */
152 { { 11, 0 }, 0 }, /* SeSystemProfilePrivilege */
153 { { 13, 0 }, 0 }, /* SeProfileSingleProcessPrivilege */
154 { { 14, 0 }, 0 }, /* SeIncreaseBasePriorityPrivilege */
155 { { 10, 0 }, 0 }, /* SeLoadDriverPrivilege */
156 { { 15, 0 }, 0 }, /* SeCreatePagefilePrivilege */
157 { { 5, 0 }, 0 }, /* SeIncreaseQuotaPrivilege */
158 { { 25, 0 }, 0 }, /* SeUndockPrivilege */
159 { { 28, 0 }, 0 }, /* SeManageVolumePrivilege */
160 { { 29, 0 }, SE_PRIVILEGE_ENABLED
}, /* SeImpersonatePrivilege */
161 { { 30, 0 }, SE_PRIVILEGE_ENABLED
}, /* SeCreateGlobalPrivilege */
163 return create_token( admin_privs
, sizeof(admin_privs
)/sizeof(admin_privs
[0]) );
166 static struct privilege
*token_find_privilege( struct token
*token
, const LUID
*luid
, int enabled_only
)
168 struct privilege
*privilege
;
169 LIST_FOR_EACH_ENTRY( privilege
, &token
->privileges
, struct privilege
, entry
)
171 if (is_equal_luid( luid
, &privilege
->luid
))
173 if (enabled_only
&& !privilege
->enabled
)
181 static unsigned int token_adjust_privileges( struct token
*token
, const LUID_AND_ATTRIBUTES
*privs
,
182 unsigned int count
, LUID_AND_ATTRIBUTES
*mod_privs
,
183 unsigned int mod_privs_count
)
186 unsigned int modified_count
= 0;
188 for (i
= 0; i
< count
; i
++)
190 struct privilege
*privilege
=
191 token_find_privilege( token
, &privs
[i
].Luid
, FALSE
);
194 set_error( STATUS_NOT_ALL_ASSIGNED
);
198 if (privs
[i
].Attributes
& SE_PRIVILEGE_REMOVE
)
199 privilege_remove( privilege
);
202 /* save previous state for caller */
205 luid_and_attr_from_privilege(mod_privs
, privilege
);
211 if (privs
[i
].Attributes
& SE_PRIVILEGE_ENABLED
)
212 privilege
->enabled
= TRUE
;
214 privilege
->enabled
= FALSE
;
217 return modified_count
;
220 static void token_disable_privileges( struct token
*token
)
222 struct privilege
*privilege
;
223 LIST_FOR_EACH_ENTRY( privilege
, &token
->privileges
, struct privilege
, entry
)
224 privilege
->enabled
= FALSE
;
227 /* open a security token */
228 DECL_HANDLER(open_token
)
230 if( req
->flags
& OPEN_TOKEN_THREAD
)
232 struct thread
*thread
= get_thread_from_handle( req
->handle
, 0 );
236 reply
->token
= alloc_handle( current
->process
, thread
->token
, TOKEN_ALL_ACCESS
, 0);
238 set_error(STATUS_NO_TOKEN
);
239 release_object( thread
);
244 struct process
*process
= get_process_from_handle( req
->handle
, 0 );
248 reply
->token
= alloc_handle( current
->process
, process
->token
, TOKEN_ALL_ACCESS
, 0);
250 set_error(STATUS_NO_TOKEN
);
251 release_object( process
);
256 /* adjust the privileges held by a token */
257 DECL_HANDLER(adjust_token_privileges
)
260 unsigned int access
= TOKEN_ADJUST_PRIVILEGES
;
262 if (req
->get_modified_state
) access
|= TOKEN_QUERY
;
264 if ((token
= (struct token
*)get_handle_obj( current
->process
, req
->handle
,
265 access
, &token_ops
)))
267 const LUID_AND_ATTRIBUTES
*privs
= get_req_data();
268 LUID_AND_ATTRIBUTES
*modified_privs
= NULL
;
269 unsigned int priv_count
= get_req_data_size() / sizeof(LUID_AND_ATTRIBUTES
);
270 unsigned int modified_priv_count
= 0;
272 if (req
->get_modified_state
&& !req
->disable_all
)
275 /* count modified privs */
276 for (i
= 0; i
< priv_count
; i
++)
278 struct privilege
*privilege
=
279 token_find_privilege( token
, &privs
[i
].Luid
, FALSE
);
280 if (privilege
&& req
->get_modified_state
)
281 modified_priv_count
++;
283 reply
->len
= modified_priv_count
;
284 modified_priv_count
= min( modified_priv_count
, get_reply_max_size() / sizeof(*modified_privs
) );
285 if (modified_priv_count
)
286 modified_privs
= set_reply_data_size( modified_priv_count
* sizeof(*modified_privs
) );
288 reply
->len
= modified_priv_count
* sizeof(*modified_privs
);
290 if (req
->disable_all
)
291 token_disable_privileges( token
);
293 modified_priv_count
= token_adjust_privileges( token
, privs
,
294 priv_count
, modified_privs
, modified_priv_count
);
296 release_object( token
);
300 /* retrieves the list of privileges that may be held be the token */
301 DECL_HANDLER(get_token_privileges
)
305 if ((token
= (struct token
*)get_handle_obj( current
->process
, req
->handle
,
310 LUID_AND_ATTRIBUTES
*privs
;
311 struct privilege
*privilege
;
313 LIST_FOR_EACH_ENTRY( privilege
, &token
->privileges
, struct privilege
, entry
)
316 reply
->len
= priv_count
* sizeof(*privs
);
317 if (reply
->len
<= get_reply_max_size())
319 privs
= set_reply_data_size( priv_count
* sizeof(*privs
) );
323 LIST_FOR_EACH_ENTRY( privilege
, &token
->privileges
, struct privilege
, entry
)
325 luid_and_attr_from_privilege( &privs
[i
], privilege
);
331 set_error(STATUS_BUFFER_TOO_SMALL
);
333 release_object( token
);
337 /* creates a duplicate of the token */
338 DECL_HANDLER(duplicate_token
)
340 struct token
*src_token
;
341 if ((src_token
= (struct token
*)get_handle_obj( current
->process
, req
->handle
,
345 /* FIXME: use req->primary and req->impersonation_level */
346 struct token
*token
= create_token( NULL
, 0 );
349 struct privilege
*privilege
;
352 LIST_FOR_EACH_ENTRY( privilege
, &src_token
->privileges
, struct privilege
, entry
)
353 privilege_add( token
, &privilege
->luid
, privilege
->enabled
);
355 access
= req
->access
;
356 if (access
& MAXIMUM_ALLOWED
) access
= TOKEN_ALL_ACCESS
; /* FIXME: needs general solution */
357 reply
->new_handle
= alloc_handle( current
->process
, token
, access
, req
->inherit
);
358 release_object( token
);
360 release_object( src_token
);