2
Unix SMB/CIFS implementation.
4
Copyright (C) Andrew Tridgell 1992-1998
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
11
This program 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
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
/* what user is current? */
24
extern struct current_user current_user;
26
/****************************************************************************
27
Iterator functions for getting all gid's from current_user.
28
****************************************************************************/
30
gid_t get_current_user_gid_first(int *piterator)
33
return current_user.ut.gid;
36
gid_t get_current_user_gid_next(int *piterator)
40
if (!current_user.ut.groups || *piterator >= current_user.ut.ngroups) {
44
ret = current_user.ut.groups[*piterator];
49
/****************************************************************************
50
Become the guest user without changing the security context stack.
51
****************************************************************************/
53
BOOL change_to_guest(void)
55
static struct passwd *pass=NULL;
58
/* Don't need to free() this as its stored in a static */
59
pass = getpwnam_alloc(NULL, lp_guestaccount());
65
/* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before
67
initgroups(pass->pw_name, pass->pw_gid);
70
set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
72
current_user.conn = NULL;
73
current_user.vuid = UID_FIELD_INVALID;
81
/*******************************************************************
82
Check if a username is OK.
83
********************************************************************/
85
static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
88
struct vuid_cache_entry *ent = NULL;
91
for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++) {
92
if (conn->vuid_cache.array[i].vuid == vuser->vuid) {
93
ent = &conn->vuid_cache.array[i];
94
conn->read_only = ent->read_only;
95
conn->admin_user = ent->admin_user;
100
if (!user_ok_token(vuser->user.unix_name, vuser->nt_user_token, snum))
103
readonly_share = is_share_read_only_for_token(vuser->user.unix_name,
104
vuser->nt_user_token,
107
if (!readonly_share &&
108
!share_access_check(conn, snum, vuser, FILE_WRITE_DATA)) {
109
/* smb.conf allows r/w, but the security descriptor denies
110
* write. Fall back to looking at readonly. */
111
readonly_share = True;
112
DEBUG(5,("falling back to read-only access-evaluation due to "
113
"security descriptor\n"));
116
if (!share_access_check(conn, snum, vuser,
118
FILE_READ_DATA : FILE_WRITE_DATA)) {
122
i = conn->vuid_cache.entries % VUID_CACHE_SIZE;
123
if (conn->vuid_cache.entries < VUID_CACHE_SIZE)
124
conn->vuid_cache.entries++;
126
ent = &conn->vuid_cache.array[i];
127
ent->vuid = vuser->vuid;
128
ent->read_only = readonly_share;
130
ent->admin_user = token_contains_name_in_list(
131
vuser->user.unix_name, NULL, vuser->nt_user_token,
132
lp_admin_users(SNUM(conn)));
134
conn->read_only = ent->read_only;
135
conn->admin_user = ent->admin_user;
140
/****************************************************************************
141
Become the user of a connection number without changing the security context
142
stack, but modify the current_user entries.
143
****************************************************************************/
145
BOOL change_to_user(connection_struct *conn, uint16 vuid)
147
user_struct *vuser = get_valid_user_struct(vuid);
152
BOOL must_free_token = False;
153
NT_USER_TOKEN *token = NULL;
156
DEBUG(2,("change_to_user: Connection not open\n"));
161
* We need a separate check in security=share mode due to vuid
162
* always being UID_FIELD_INVALID. If we don't do this then
163
* in share mode security we are *always* changing uid's between
164
* SMB's - this hurts performance - Badly.
167
if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
168
(current_user.ut.uid == conn->uid)) {
169
DEBUG(4,("change_to_user: Skipping user change - already "
172
} else if ((current_user.conn == conn) &&
173
(vuser != 0) && (current_user.vuid == vuid) &&
174
(current_user.ut.uid == vuser->uid)) {
175
DEBUG(4,("change_to_user: Skipping user change - already "
182
if ((vuser) && !check_user_ok(conn, vuser, snum)) {
183
DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) "
184
"not permitted access to share %s.\n",
185
vuser->user.smb_name, vuser->user.unix_name, vuid,
186
lp_servicename(snum)));
190
if (conn->force_user) /* security = share sets this too */ {
193
current_user.ut.groups = conn->groups;
194
current_user.ut.ngroups = conn->ngroups;
195
token = conn->nt_user_token;
197
uid = conn->admin_user ? 0 : vuser->uid;
199
current_user.ut.ngroups = vuser->n_groups;
200
current_user.ut.groups = vuser->groups;
201
token = vuser->nt_user_token;
203
DEBUG(2,("change_to_user: Invalid vuid used %d in accessing "
204
"share %s.\n",vuid, lp_servicename(snum) ));
209
* See if we should force group for this service.
210
* If so this overrides any group set in the force
214
if((group_c = *lp_force_group(snum))) {
216
token = dup_nt_token(NULL, token);
218
DEBUG(0, ("dup_nt_token failed\n"));
221
must_free_token = True;
226
* Only force group if the user is a member of
227
* the service group. Check the group memberships for
228
* this user (we already have this) to
229
* see if we should force the group.
233
for (i = 0; i < current_user.ut.ngroups; i++) {
234
if (current_user.ut.groups[i] == conn->gid) {
236
gid_to_sid(&token->user_sids[1], gid);
242
gid_to_sid(&token->user_sids[1], gid);
246
set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups,
250
* Free the new token (as set_sec_ctx copies it).
256
current_user.conn = conn;
257
current_user.vuid = vuid;
259
DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n",
260
(int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
265
/****************************************************************************
266
Go back to being root without changing the security context stack,
267
but modify the current_user entries.
268
****************************************************************************/
270
BOOL change_to_root_user(void)
274
DEBUG(5,("change_to_root_user: now uid=(%d,%d) gid=(%d,%d)\n",
275
(int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
277
current_user.conn = NULL;
278
current_user.vuid = UID_FIELD_INVALID;
283
/****************************************************************************
284
Become the user of an authenticated connected named pipe.
285
When this is called we are currently running as the connection
286
user. Doesn't modify current_user.
287
****************************************************************************/
289
BOOL become_authenticated_pipe_user(pipes_struct *p)
294
set_sec_ctx(p->pipe_user.ut.uid, p->pipe_user.ut.gid,
295
p->pipe_user.ut.ngroups, p->pipe_user.ut.groups,
296
p->pipe_user.nt_user_token);
301
/****************************************************************************
302
Unbecome the user of an authenticated connected named pipe.
303
When this is called we are running as the authenticated pipe
304
user and need to go back to being the connection user. Doesn't modify
306
****************************************************************************/
308
BOOL unbecome_authenticated_pipe_user(void)
310
return pop_sec_ctx();
313
/****************************************************************************
314
Utility functions used by become_xxx/unbecome_xxx.
315
****************************************************************************/
318
connection_struct *conn;
322
/* A stack of current_user connection contexts. */
324
static struct conn_ctx conn_ctx_stack[MAX_SEC_CTX_DEPTH];
325
static int conn_ctx_stack_ndx;
327
static void push_conn_ctx(void)
329
struct conn_ctx *ctx_p;
331
/* Check we don't overflow our stack */
333
if (conn_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) {
334
DEBUG(0, ("Connection context stack overflow!\n"));
335
smb_panic("Connection context stack overflow!\n");
338
/* Store previous user context */
339
ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
341
ctx_p->conn = current_user.conn;
342
ctx_p->vuid = current_user.vuid;
344
DEBUG(3, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n",
345
(unsigned int)ctx_p->vuid, conn_ctx_stack_ndx ));
347
conn_ctx_stack_ndx++;
350
static void pop_conn_ctx(void)
352
struct conn_ctx *ctx_p;
354
/* Check for stack underflow. */
356
if (conn_ctx_stack_ndx == 0) {
357
DEBUG(0, ("Connection context stack underflow!\n"));
358
smb_panic("Connection context stack underflow!\n");
361
conn_ctx_stack_ndx--;
362
ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
364
current_user.conn = ctx_p->conn;
365
current_user.vuid = ctx_p->vuid;
368
ctx_p->vuid = UID_FIELD_INVALID;
371
/****************************************************************************
372
Temporarily become a root user. Must match with unbecome_root(). Saves and
373
restores the connection context.
374
****************************************************************************/
376
void become_root(void)
383
/* Unbecome the root user */
385
void unbecome_root(void)
391
/****************************************************************************
392
Push the current security context then force a change via change_to_user().
393
Saves and restores the connection context.
394
****************************************************************************/
396
BOOL become_user(connection_struct *conn, uint16 vuid)
403
if (!change_to_user(conn, vuid)) {
412
BOOL unbecome_user(void)