s3-uid: Use struct pipes_struct.
[samba.git] / source3 / smbd / uid.c
1 /* 
2    Unix SMB/CIFS implementation.
3    uid/user handling
4    Copyright (C) Andrew Tridgell 1992-1998
5
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 3 of the License, or
9    (at your option) any later version.
10
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.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "smbd/globals.h"
22
23 /* what user is current? */
24 extern struct current_user current_user;
25
26 /****************************************************************************
27  Become the guest user without changing the security context stack.
28 ****************************************************************************/
29
30 bool change_to_guest(void)
31 {
32         struct passwd *pass;
33
34         pass = getpwnam_alloc(talloc_autofree_context(), lp_guestaccount());
35         if (!pass) {
36                 return false;
37         }
38
39 #ifdef AIX
40         /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before 
41            setting IDs */
42         initgroups(pass->pw_name, pass->pw_gid);
43 #endif
44
45         set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
46
47         current_user.conn = NULL;
48         current_user.vuid = UID_FIELD_INVALID;
49
50         TALLOC_FREE(pass);
51
52         return true;
53 }
54
55 /****************************************************************************
56  talloc free the conn->server_info if not used in the vuid cache.
57 ****************************************************************************/
58
59 static void free_conn_server_info_if_unused(connection_struct *conn)
60 {
61         unsigned int i;
62
63         for (i = 0; i < VUID_CACHE_SIZE; i++) {
64                 struct vuid_cache_entry *ent;
65                 ent = &conn->vuid_cache.array[i];
66                 if (ent->vuid != UID_FIELD_INVALID &&
67                                 conn->server_info == ent->server_info) {
68                         return;
69                 }
70         }
71         /* Not used, safe to free. */
72         TALLOC_FREE(conn->server_info);
73 }
74
75 /*******************************************************************
76  Check if a username is OK.
77
78  This sets up conn->server_info with a copy related to this vuser that
79  later code can then mess with.
80 ********************************************************************/
81
82 static bool check_user_ok(connection_struct *conn,
83                         uint16_t vuid,
84                         const struct auth_serversupplied_info *server_info,
85                         int snum)
86 {
87         bool valid_vuid = (vuid != UID_FIELD_INVALID);
88         unsigned int i;
89         bool readonly_share;
90         bool admin_user;
91
92         if (valid_vuid) {
93                 struct vuid_cache_entry *ent;
94
95                 for (i=0; i<VUID_CACHE_SIZE; i++) {
96                         ent = &conn->vuid_cache.array[i];
97                         if (ent->vuid == vuid) {
98                                 free_conn_server_info_if_unused(conn);
99                                 conn->server_info = ent->server_info;
100                                 conn->read_only = ent->read_only;
101                                 return(True);
102                         }
103                 }
104         }
105
106         if (!user_ok_token(server_info->unix_name,
107                            server_info->info3->base.domain.string,
108                            server_info->ptok, snum))
109                 return(False);
110
111         readonly_share = is_share_read_only_for_token(
112                 server_info->unix_name,
113                 server_info->info3->base.domain.string,
114                 server_info->ptok,
115                 conn);
116
117         if (!readonly_share &&
118             !share_access_check(server_info->ptok, lp_servicename(snum),
119                                 FILE_WRITE_DATA)) {
120                 /* smb.conf allows r/w, but the security descriptor denies
121                  * write. Fall back to looking at readonly. */
122                 readonly_share = True;
123                 DEBUG(5,("falling back to read-only access-evaluation due to "
124                          "security descriptor\n"));
125         }
126
127         if (!share_access_check(server_info->ptok, lp_servicename(snum),
128                                 readonly_share ?
129                                 FILE_READ_DATA : FILE_WRITE_DATA)) {
130                 return False;
131         }
132
133         admin_user = token_contains_name_in_list(
134                 server_info->unix_name,
135                 server_info->info3->base.domain.string,
136                 NULL, server_info->ptok, lp_admin_users(snum));
137
138         if (valid_vuid) {
139                 struct vuid_cache_entry *ent =
140                         &conn->vuid_cache.array[conn->vuid_cache.next_entry];
141
142                 conn->vuid_cache.next_entry =
143                         (conn->vuid_cache.next_entry + 1) % VUID_CACHE_SIZE;
144
145                 TALLOC_FREE(ent->server_info);
146
147                 /*
148                  * If force_user was set, all server_info's are based on the same
149                  * username-based faked one.
150                  */
151
152                 ent->server_info = copy_serverinfo(
153                         conn, conn->force_user ? conn->server_info : server_info);
154
155                 if (ent->server_info == NULL) {
156                         ent->vuid = UID_FIELD_INVALID;
157                         return false;
158                 }
159
160                 ent->vuid = vuid;
161                 ent->read_only = readonly_share;
162                 free_conn_server_info_if_unused(conn);
163                 conn->server_info = ent->server_info;
164         }
165
166         conn->read_only = readonly_share;
167         if (admin_user) {
168                 DEBUG(2,("check_user_ok: user %s is an admin user. "
169                         "Setting uid as %d\n",
170                         conn->server_info->unix_name,
171                         sec_initial_uid() ));
172                 conn->server_info->utok.uid = sec_initial_uid();
173         }
174
175         return(True);
176 }
177
178 /****************************************************************************
179  Clear a vuid out of the connection's vuid cache
180  This is only called on SMBulogoff.
181 ****************************************************************************/
182
183 void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid)
184 {
185         int i;
186
187         for (i=0; i<VUID_CACHE_SIZE; i++) {
188                 struct vuid_cache_entry *ent;
189
190                 ent = &conn->vuid_cache.array[i];
191
192                 if (ent->vuid == vuid) {
193                         ent->vuid = UID_FIELD_INVALID;
194                         /*
195                          * We need to keep conn->server_info around
196                          * if it's equal to ent->server_info as a SMBulogoff
197                          * is often followed by a SMBtdis (with an invalid
198                          * vuid). The debug code (or regular code in
199                          * vfs_full_audit) wants to refer to the
200                          * conn->server_info pointer to print debug
201                          * statements. Theoretically this is a bug,
202                          * as once the vuid is gone the server_info
203                          * on the conn struct isn't valid any more,
204                          * but there's enough code that assumes
205                          * conn->server_info is never null that
206                          * it's easier to hold onto the old pointer
207                          * until we get a new sessionsetupX.
208                          * As everything is hung off the
209                          * conn pointer as a talloc context we're not
210                          * leaking memory here. See bug #6315. JRA.
211                          */
212                         if (conn->server_info == ent->server_info) {
213                                 ent->server_info = NULL;
214                         } else {
215                                 TALLOC_FREE(ent->server_info);
216                         }
217                         ent->read_only = False;
218                 }
219         }
220 }
221
222 /****************************************************************************
223  Become the user of a connection number without changing the security context
224  stack, but modify the current_user entries.
225 ****************************************************************************/
226
227 bool change_to_user(connection_struct *conn, uint16 vuid)
228 {
229         const struct auth_serversupplied_info *server_info = NULL;
230         user_struct *vuser = get_valid_user_struct(conn->sconn, vuid);
231         int snum;
232         gid_t gid;
233         uid_t uid;
234         char group_c;
235         int num_groups = 0;
236         gid_t *group_list = NULL;
237
238         if (!conn) {
239                 DEBUG(2,("change_to_user: Connection not open\n"));
240                 return(False);
241         }
242
243         /*
244          * We need a separate check in security=share mode due to vuid
245          * always being UID_FIELD_INVALID. If we don't do this then
246          * in share mode security we are *always* changing uid's between
247          * SMB's - this hurts performance - Badly.
248          */
249
250         if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
251            (current_user.ut.uid == conn->server_info->utok.uid)) {
252                 DEBUG(4,("change_to_user: Skipping user change - already "
253                          "user\n"));
254                 return(True);
255         } else if ((current_user.conn == conn) && 
256                    (vuser != NULL) && (current_user.vuid == vuid) &&
257                    (current_user.ut.uid == vuser->server_info->utok.uid)) {
258                 DEBUG(4,("change_to_user: Skipping user change - already "
259                          "user\n"));
260                 return(True);
261         }
262
263         snum = SNUM(conn);
264
265         server_info = vuser ? vuser->server_info : conn->server_info;
266
267         if (!server_info) {
268                 /* Invalid vuid sent - even with security = share. */
269                 DEBUG(2,("change_to_user: Invalid vuid %d used on "
270                          "share %s.\n",vuid, lp_servicename(snum) ));
271                 return false;
272         }
273
274         if (!check_user_ok(conn, vuid, server_info, snum)) {
275                 DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) "
276                          "not permitted access to share %s.\n",
277                          server_info->sanitized_username,
278                          server_info->unix_name, vuid,
279                          lp_servicename(snum)));
280                 return false;
281         }
282
283         /* security = share sets force_user. */
284         if (!conn->force_user && !vuser) {
285                 DEBUG(2,("change_to_user: Invalid vuid used %d in accessing "
286                         "share %s.\n",vuid, lp_servicename(snum) ));
287                 return False;
288         }
289
290         /*
291          * conn->server_info is now correctly set up with a copy we can mess
292          * with for force_group etc.
293          */
294
295         uid = conn->server_info->utok.uid;
296         gid = conn->server_info->utok.gid;
297         num_groups = conn->server_info->utok.ngroups;
298         group_list  = conn->server_info->utok.groups;
299
300         /*
301          * See if we should force group for this service.
302          * If so this overrides any group set in the force
303          * user code.
304          */
305
306         if((group_c = *lp_force_group(snum))) {
307
308                 SMB_ASSERT(conn->force_group_gid != (gid_t)-1);
309
310                 if(group_c == '+') {
311
312                         /*
313                          * Only force group if the user is a member of
314                          * the service group. Check the group memberships for
315                          * this user (we already have this) to
316                          * see if we should force the group.
317                          */
318
319                         int i;
320                         for (i = 0; i < num_groups; i++) {
321                                 if (group_list[i]
322                                     == conn->force_group_gid) {
323                                         conn->server_info->utok.gid =
324                                                 conn->force_group_gid;
325                                         gid = conn->force_group_gid;
326                                         gid_to_sid(&conn->server_info->ptok
327                                                    ->user_sids[1], gid);
328                                         break;
329                                 }
330                         }
331                 } else {
332                         conn->server_info->utok.gid = conn->force_group_gid;
333                         gid = conn->force_group_gid;
334                         gid_to_sid(&conn->server_info->ptok->user_sids[1],
335                                    gid);
336                 }
337         }
338
339         /* Now set current_user since we will immediately also call
340            set_sec_ctx() */
341
342         current_user.ut.ngroups = num_groups;
343         current_user.ut.groups  = group_list;
344
345         set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups,
346                     conn->server_info->ptok);
347
348         current_user.conn = conn;
349         current_user.vuid = vuid;
350
351         DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n",
352                  (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
353
354         return(True);
355 }
356
357 /****************************************************************************
358  Go back to being root without changing the security context stack,
359  but modify the current_user entries.
360 ****************************************************************************/
361
362 bool change_to_root_user(void)
363 {
364         set_root_sec_ctx();
365
366         DEBUG(5,("change_to_root_user: now uid=(%d,%d) gid=(%d,%d)\n",
367                 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
368
369         current_user.conn = NULL;
370         current_user.vuid = UID_FIELD_INVALID;
371
372         return(True);
373 }
374
375 /****************************************************************************
376  Become the user of an authenticated connected named pipe.
377  When this is called we are currently running as the connection
378  user. Doesn't modify current_user.
379 ****************************************************************************/
380
381 bool become_authenticated_pipe_user(struct pipes_struct *p)
382 {
383         if (!push_sec_ctx())
384                 return False;
385
386         set_sec_ctx(p->server_info->utok.uid, p->server_info->utok.gid,
387                     p->server_info->utok.ngroups, p->server_info->utok.groups,
388                     p->server_info->ptok);
389
390         return True;
391 }
392
393 /****************************************************************************
394  Unbecome the user of an authenticated connected named pipe.
395  When this is called we are running as the authenticated pipe
396  user and need to go back to being the connection user. Doesn't modify
397  current_user.
398 ****************************************************************************/
399
400 bool unbecome_authenticated_pipe_user(void)
401 {
402         return pop_sec_ctx();
403 }
404
405 /****************************************************************************
406  Utility functions used by become_xxx/unbecome_xxx.
407 ****************************************************************************/
408
409 static void push_conn_ctx(void)
410 {
411         struct conn_ctx *ctx_p;
412
413         /* Check we don't overflow our stack */
414
415         if (conn_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) {
416                 DEBUG(0, ("Connection context stack overflow!\n"));
417                 smb_panic("Connection context stack overflow!\n");
418         }
419
420         /* Store previous user context */
421         ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
422
423         ctx_p->conn = current_user.conn;
424         ctx_p->vuid = current_user.vuid;
425
426         DEBUG(3, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n",
427                 (unsigned int)ctx_p->vuid, conn_ctx_stack_ndx ));
428
429         conn_ctx_stack_ndx++;
430 }
431
432 static void pop_conn_ctx(void)
433 {
434         struct conn_ctx *ctx_p;
435
436         /* Check for stack underflow. */
437
438         if (conn_ctx_stack_ndx == 0) {
439                 DEBUG(0, ("Connection context stack underflow!\n"));
440                 smb_panic("Connection context stack underflow!\n");
441         }
442
443         conn_ctx_stack_ndx--;
444         ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
445
446         current_user.conn = ctx_p->conn;
447         current_user.vuid = ctx_p->vuid;
448
449         ctx_p->conn = NULL;
450         ctx_p->vuid = UID_FIELD_INVALID;
451 }
452
453 /****************************************************************************
454  Temporarily become a root user.  Must match with unbecome_root(). Saves and
455  restores the connection context.
456 ****************************************************************************/
457
458 void become_root(void)
459 {
460          /*
461           * no good way to handle push_sec_ctx() failing without changing
462           * the prototype of become_root()
463           */
464         if (!push_sec_ctx()) {
465                 smb_panic("become_root: push_sec_ctx failed");
466         }
467         push_conn_ctx();
468         set_root_sec_ctx();
469 }
470
471 /* Unbecome the root user */
472
473 void unbecome_root(void)
474 {
475         pop_sec_ctx();
476         pop_conn_ctx();
477 }
478
479 /****************************************************************************
480  Push the current security context then force a change via change_to_user().
481  Saves and restores the connection context.
482 ****************************************************************************/
483
484 bool become_user(connection_struct *conn, uint16 vuid)
485 {
486         if (!push_sec_ctx())
487                 return False;
488
489         push_conn_ctx();
490
491         if (!change_to_user(conn, vuid)) {
492                 pop_sec_ctx();
493                 pop_conn_ctx();
494                 return False;
495         }
496
497         return True;
498 }
499
500 bool unbecome_user(void)
501 {
502         pop_sec_ctx();
503         pop_conn_ctx();
504         return True;
505 }
506
507 /****************************************************************************
508  Return the current user we are running effectively as on this connection.
509  I'd like to make this return conn->server_info->utok.uid, but become_root()
510  doesn't alter this value.
511 ****************************************************************************/
512
513 uid_t get_current_uid(connection_struct *conn)
514 {
515         return current_user.ut.uid;
516 }
517
518 /****************************************************************************
519  Return the current group we are running effectively as on this connection.
520  I'd like to make this return conn->server_info->utok.gid, but become_root()
521  doesn't alter this value.
522 ****************************************************************************/
523
524 gid_t get_current_gid(connection_struct *conn)
525 {
526         return current_user.ut.gid;
527 }
528
529 /****************************************************************************
530  Return the UNIX token we are running effectively as on this connection.
531  I'd like to make this return &conn->server_info->utok, but become_root()
532  doesn't alter this value.
533 ****************************************************************************/
534
535 const UNIX_USER_TOKEN *get_current_utok(connection_struct *conn)
536 {
537         return &current_user.ut;
538 }
539
540 const NT_USER_TOKEN *get_current_nttok(connection_struct *conn)
541 {
542         return current_user.nt_user_token;
543 }
544
545 uint16_t get_current_vuid(connection_struct *conn)
546 {
547         return current_user.vuid;
548 }