Moved some static functions to sec_ctx.c
[kai/samba.git] / source3 / smbd / uid.c
1 #define OLD_NTDOMAIN 1
2
3 /* 
4    Unix SMB/Netbios implementation.
5    Version 1.9.
6    uid/user handling
7    Copyright (C) Andrew Tridgell 1992-1998
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 extern int DEBUGLEVEL;
27
28 /* what user is current? */
29 extern struct current_user current_user;
30
31 /****************************************************************************
32  Become the guest user.
33 ****************************************************************************/
34
35 BOOL become_guest(void)
36 {
37         static struct passwd *pass=NULL;
38         
39         if (!pass)
40                 pass = Get_Pwnam(lp_guestaccount(-1),True);
41         if (!pass) return(False);
42         
43 #ifdef AIX
44         /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before 
45            setting IDs */
46         initgroups(pass->pw_name, (gid_t)pass->pw_gid);
47 #endif
48         
49         set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL);
50         
51         current_user.conn = NULL;
52         current_user.vuid = UID_FIELD_INVALID;
53         
54         return True;
55 }
56
57 /*******************************************************************
58  Check if a username is OK.
59 ********************************************************************/
60
61 static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
62 {
63   int i;
64   for (i=0;i<conn->uid_cache.entries;i++)
65     if (conn->uid_cache.list[i] == vuser->uid) return(True);
66
67   if (!user_ok(vuser->user.unix_name,snum)) return(False);
68
69   i = conn->uid_cache.entries % UID_CACHE_SIZE;
70   conn->uid_cache.list[i] = vuser->uid;
71
72   if (conn->uid_cache.entries < UID_CACHE_SIZE)
73     conn->uid_cache.entries++;
74
75   return(True);
76 }
77
78 /****************************************************************************
79  Become the user of a connection number.
80 ****************************************************************************/
81
82 BOOL become_user(connection_struct *conn, uint16 vuid)
83 {
84         user_struct *vuser = get_valid_user_struct(vuid);
85         int snum;
86         gid_t gid;
87         uid_t uid;
88         char group_c;
89
90         if (!conn) {
91                 DEBUG(2,("Connection not open\n"));
92                 return(False);
93         }
94
95         /*
96          * We need a separate check in security=share mode due to vuid
97          * always being UID_FIELD_INVALID. If we don't do this then
98          * in share mode security we are *always* changing uid's between
99          * SMB's - this hurts performance - Badly.
100          */
101
102         if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
103            (current_user.uid == conn->uid)) {
104                 DEBUG(4,("Skipping become_user - already user\n"));
105                 return(True);
106         } else if ((current_user.conn == conn) && 
107                    (vuser != 0) && (current_user.vuid == vuid) && 
108                    (current_user.uid == vuser->uid)) {
109                 DEBUG(4,("Skipping become_user - already user\n"));
110                 return(True);
111         }
112
113         snum = SNUM(conn);
114
115         if((vuser != NULL) && !check_user_ok(conn, vuser, snum))
116                 return False;
117
118         if (conn->force_user || 
119             lp_security() == SEC_SHARE ||
120             !(vuser) || (vuser->guest)) {
121                 uid = conn->uid;
122                 gid = conn->gid;
123                 current_user.groups = conn->groups;
124                 current_user.ngroups = conn->ngroups;
125         } else {
126                 if (!vuser) {
127                         DEBUG(2,("Invalid vuid used %d\n",vuid));
128                         return(False);
129                 }
130                 uid = vuser->uid;
131                 gid = vuser->gid;
132                 current_user.ngroups = vuser->n_groups;
133                 current_user.groups  = vuser->groups;
134         }
135
136         /*
137          * See if we should force group for this service.
138          * If so this overrides any group set in the force
139          * user code.
140          */
141
142         if((group_c = *lp_force_group(snum))) {
143                 if(group_c == '+') {
144
145                         /*
146                          * Only force group if the user is a member of
147                          * the service group. Check the group memberships for
148                          * this user (we already have this) to
149                          * see if we should force the group.
150                          */
151
152                         int i;
153                         for (i = 0; i < current_user.ngroups; i++) {
154                                 if (current_user.groups[i] == conn->gid) {
155                                         gid = conn->gid;
156                                         break;
157                                 }
158                         }
159                 } else {
160                         gid = conn->gid;
161                 }
162         }
163         
164         set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups);
165
166         current_user.conn = conn;
167         current_user.vuid = vuid;
168
169         DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n",
170                  (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
171   
172         return(True);
173 }
174
175 /****************************************************************************
176  Unbecome the user of a connection number.
177 ****************************************************************************/
178
179 BOOL unbecome_user(void )
180 {
181         set_root_sec_ctx();
182
183         DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n",
184                 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
185
186         current_user.conn = NULL;
187         current_user.vuid = UID_FIELD_INVALID;
188
189         return(True);
190 }
191
192 /****************************************************************************
193  Become the user of an authenticated connected named pipe.
194  When this is called we are currently running as the connection
195  user.
196 ****************************************************************************/
197
198 BOOL become_authenticated_pipe_user(pipes_struct *p)
199 {
200         BOOL res = push_sec_ctx();
201
202         if (!res) {
203                 return False;
204         }
205
206         set_sec_ctx(p->uid, p->gid, 0, NULL);  /* fix group stuff */
207 }
208
209 /****************************************************************************
210  Unbecome the user of an authenticated connected named pipe.
211  When this is called we are running as the authenticated pipe
212  user and need to go back to being the connection user.
213 ****************************************************************************/
214
215 BOOL unbecome_authenticated_pipe_user(pipes_struct *p)
216 {
217         return pop_sec_ctx();
218 }
219
220 /* Temporarily become a root user.  Must match with unbecome_root(). */
221
222 void become_root(void)
223 {
224         push_sec_ctx();
225         set_root_sec_ctx();
226 }
227
228 /* Unbecome the root user */
229
230 void unbecome_root(void)
231 {
232         pop_sec_ctx();
233 }
234
235 #undef OLD_NTDOMAIN