Excise snprintf -> slprintf.
[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)
42                 return(False);
43         
44 #ifdef AIX
45         /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before 
46            setting IDs */
47         initgroups(pass->pw_name, (gid_t)pass->pw_gid);
48 #endif
49         
50         set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
51         
52         current_user.conn = NULL;
53         current_user.vuid = UID_FIELD_INVALID;
54         
55         return True;
56 }
57
58 /*******************************************************************
59  Check if a username is OK.
60 ********************************************************************/
61
62 static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
63 {
64         int i;
65         for (i=0;i<conn->uid_cache.entries;i++)
66                 if (conn->uid_cache.list[i] == vuser->uid)
67                         return(True);
68
69         if (!user_ok(vuser->user.unix_name,snum))
70                 return(False);
71
72         i = conn->uid_cache.entries % UID_CACHE_SIZE;
73         conn->uid_cache.list[i] = vuser->uid;
74
75         if (conn->uid_cache.entries < UID_CACHE_SIZE)
76                 conn->uid_cache.entries++;
77
78         return(True);
79 }
80
81 /****************************************************************************
82  Become the user of a connection number.
83 ****************************************************************************/
84
85 BOOL become_user(connection_struct *conn, uint16 vuid)
86 {
87         user_struct *vuser = get_valid_user_struct(vuid);
88         int snum;
89         gid_t gid;
90         uid_t uid;
91         char group_c;
92         BOOL must_free_token = False;
93         NT_USER_TOKEN *token = NULL;
94
95         if (!conn) {
96                 DEBUG(2,("Connection not open\n"));
97                 return(False);
98         }
99
100         /*
101          * We need a separate check in security=share mode due to vuid
102          * always being UID_FIELD_INVALID. If we don't do this then
103          * in share mode security we are *always* changing uid's between
104          * SMB's - this hurts performance - Badly.
105          */
106
107         if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
108            (current_user.uid == conn->uid)) {
109                 DEBUG(4,("Skipping become_user - already user\n"));
110                 return(True);
111         } else if ((current_user.conn == conn) && 
112                    (vuser != 0) && (current_user.vuid == vuid) && 
113                    (current_user.uid == vuser->uid)) {
114                 DEBUG(4,("Skipping become_user - already user\n"));
115                 return(True);
116         }
117
118         snum = SNUM(conn);
119
120         if((vuser != NULL) && !check_user_ok(conn, vuser, snum))
121                 return False;
122
123         if (conn->force_user || 
124                 conn->admin_user ||
125             lp_security() == SEC_SHARE ||
126             !(vuser) || (vuser->guest)) {
127                 uid = conn->uid;
128                 gid = conn->gid;
129                 current_user.groups = conn->groups;
130                 current_user.ngroups = conn->ngroups;
131                 token = conn->nt_user_token;
132         } else {
133                 if (!vuser) {
134                         DEBUG(2,("Invalid vuid used %d\n",vuid));
135                         return(False);
136                 }
137                 uid = vuser->uid;
138                 gid = vuser->gid;
139                 current_user.ngroups = vuser->n_groups;
140                 current_user.groups  = vuser->groups;
141                 token = vuser->nt_user_token;
142         }
143
144         /*
145          * See if we should force group for this service.
146          * If so this overrides any group set in the force
147          * user code.
148          */
149
150         if((group_c = *lp_force_group(snum))) {
151                 BOOL is_guest = False;
152
153                 if(group_c == '+') {
154
155                         /*
156                          * Only force group if the user is a member of
157                          * the service group. Check the group memberships for
158                          * this user (we already have this) to
159                          * see if we should force the group.
160                          */
161
162                         int i;
163                         for (i = 0; i < current_user.ngroups; i++) {
164                                 if (current_user.groups[i] == conn->gid) {
165                                         gid = conn->gid;
166                                         break;
167                                 }
168                         }
169                 } else {
170                         gid = conn->gid;
171                 }
172
173                 /*
174                  * We've changed the group list in the token - we must
175                  * re-create it.
176                  */
177
178                 if (vuser && vuser->guest)
179                         is_guest = True;
180
181                 token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups, is_guest);
182                 must_free_token = True;
183         }
184         
185         set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups, token);
186
187         /*
188          * Free the new token (as set_sec_ctx copies it).
189          */
190
191         if (must_free_token)
192                 delete_nt_token(&token);
193
194         current_user.conn = conn;
195         current_user.vuid = vuid;
196
197         DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n",
198                  (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
199   
200         return(True);
201 }
202
203 /****************************************************************************
204  Unbecome the user of a connection number.
205 ****************************************************************************/
206
207 BOOL unbecome_user(void )
208 {
209         set_root_sec_ctx();
210
211         DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n",
212                 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
213
214         current_user.conn = NULL;
215         current_user.vuid = UID_FIELD_INVALID;
216
217         return(True);
218 }
219
220 /****************************************************************************
221  Become the user of an authenticated connected named pipe.
222  When this is called we are currently running as the connection
223  user.
224 ****************************************************************************/
225
226 BOOL become_authenticated_pipe_user(pipes_struct *p)
227 {
228         BOOL res = push_sec_ctx();
229
230         if (!res) {
231                 return False;
232         }
233
234         set_sec_ctx(p->pipe_user.uid, p->pipe_user.gid, 
235                     p->pipe_user.ngroups, p->pipe_user.groups, p->pipe_user.nt_user_token);
236
237         return True;
238 }
239
240 /****************************************************************************
241  Unbecome the user of an authenticated connected named pipe.
242  When this is called we are running as the authenticated pipe
243  user and need to go back to being the connection user.
244 ****************************************************************************/
245
246 BOOL unbecome_authenticated_pipe_user(pipes_struct *p)
247 {
248         return pop_sec_ctx();
249 }
250
251 /* Temporarily become a root user.  Must match with unbecome_root(). */
252
253 void become_root(void)
254 {
255         push_sec_ctx();
256         set_root_sec_ctx();
257 }
258
259 /* Unbecome the root user */
260
261 void unbecome_root(void)
262 {
263         pop_sec_ctx();
264 }
265
266 /*****************************************************************
267  *THE CANONICAL* convert name to SID function.
268  Tries winbind first - then uses local lookup.
269 *****************************************************************/  
270
271 BOOL lookup_name(char *name, DOM_SID *psid, enum SID_NAME_USE *name_type)
272 {
273         extern pstring global_myname;
274         extern fstring global_myworkgroup;
275         fstring sid;
276         char *sep = lp_winbind_separator();
277
278         if (!winbind_lookup_name(name, psid, name_type)) {
279                 BOOL ret;
280
281                 DEBUG(10, ("lookup_name: winbind lookup for %s failed - trying local\n", name));
282
283                 /* If we are looking up a domain user, make sure it is
284                    for the local machine only */
285
286                 if (strchr(name, sep[0]) || strchr(name, '\\')) {
287                         fstring domain, username;
288
289                         split_domain_name(name, domain, username);
290
291                         switch (lp_server_role()) {
292                                 case ROLE_DOMAIN_PDC:
293                                 case ROLE_DOMAIN_BDC:
294                                         if (strequal(domain, global_myworkgroup))
295                                                 fstrcpy(domain, global_myname);
296                                         /* No break is deliberate here. JRA. */
297                                 default:
298                                         if (strcasecmp(global_myname, domain) != 0) {
299                                                 DEBUG(5, ("domain %s is not local\n", domain));
300                                                 return False;
301                                         }
302                         }
303
304                         ret = local_lookup_name(domain, username, psid, 
305                                                 name_type);
306                 } else {
307
308                         ret = local_lookup_name(global_myname, name, psid, 
309                                                 name_type);
310                 }
311
312                 if (ret) {
313                         DEBUG(10,
314                               ("lookup_name: (local) %s -> SID %s (type %u)\n",
315                                name, sid_to_string(sid,psid),
316                                (unsigned int)*name_type ));
317                 } else {
318                         DEBUG(10,("lookup name: (local) %s failed.\n", name));
319                 }
320
321                 return ret;
322         }
323
324                 DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n",
325                           name, sid_to_string(sid, psid), 
326                           (unsigned int)*name_type));
327         return True;
328 }
329
330 /*****************************************************************
331  *THE CANONICAL* convert SID to name function.
332  Tries winbind first - then uses local lookup.
333 *****************************************************************/  
334
335 BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type)
336 {
337         if (!name_type)
338                 return False;
339
340         /* Check if this is our own sid.  This should perhaps be done by
341            winbind?  For the moment handle it here. */
342
343         if (sid->num_auths == 5) {
344                 DOM_SID tmp_sid;
345                 uint32 rid;
346
347                 sid_copy(&tmp_sid, sid);
348                 sid_split_rid(&tmp_sid, &rid);
349
350                 if (sid_equal(&global_sam_sid, &tmp_sid)) {
351
352                         return map_domain_sid_to_name(&tmp_sid, dom_name) &&
353                                 local_lookup_rid(rid, name, name_type);
354                 }
355         }
356
357         if (!winbind_lookup_sid(sid, dom_name, name, name_type)) {
358                 fstring sid_str;
359                 DOM_SID tmp_sid;
360                 uint32 rid;
361
362                 DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) ));
363
364                 sid_copy(&tmp_sid, sid);
365                 sid_split_rid(&tmp_sid, &rid);
366                 return map_domain_sid_to_name(&tmp_sid, dom_name) &&
367                                 lookup_known_rid(&tmp_sid, rid, name, name_type);
368         }
369         return True;
370 }
371
372 /*****************************************************************
373  *THE CANONICAL* convert uid_t to SID function.
374  Tries winbind first - then uses local lookup.
375  Returns SID pointer.
376 *****************************************************************/  
377
378 DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid)
379 {
380         fstring sid;
381
382         if (!winbind_uid_to_sid(psid, uid)) {
383                 DEBUG(10,("uid_to_sid: winbind lookup for uid %u failed - trying local.\n", (unsigned int)uid ));
384
385                 return local_uid_to_sid(psid, uid);
386         }
387
388         DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
389                 (unsigned int)uid, sid_to_string(sid, psid) ));
390
391         return psid;
392 }
393
394 /*****************************************************************
395  *THE CANONICAL* convert gid_t to SID function.
396  Tries winbind first - then uses local lookup.
397  Returns SID pointer.
398 *****************************************************************/  
399
400 DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid)
401 {
402         fstring sid;
403
404         if (!winbind_gid_to_sid(psid, gid)) {
405                 DEBUG(10,("gid_to_sid: winbind lookup for gid %u failed - trying local.\n", (unsigned int)gid ));
406
407                 return local_gid_to_sid(psid, gid);
408         }
409
410         DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
411                 (unsigned int)gid, sid_to_string(sid,psid) ));
412
413         return psid;
414 }
415
416 /*****************************************************************
417  *THE CANONICAL* convert SID to uid function.
418  Tries winbind first - then uses local lookup.
419  Returns True if this name is a user sid and the conversion
420  was done correctly, False if not.
421 *****************************************************************/  
422
423 BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype)
424 {
425         fstring dom_name, name, sid_str;
426         enum SID_NAME_USE name_type;
427
428         *sidtype = SID_NAME_UNKNOWN;
429
430         /*
431          * First we must look up the name and decide if this is a user sid.
432          */
433
434         if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) {
435                 DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n",
436                                 sid_to_string(sid_str, psid) ));
437
438                 return local_sid_to_uid(puid, psid, sidtype);
439         }
440
441         /*
442          * Ensure this is a user sid.
443          */
444
445         if (name_type != SID_NAME_USER) {
446                 DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a uid (%u)\n",
447                                 (unsigned int)name_type ));
448                 return False;
449         }
450
451         *sidtype = SID_NAME_USER;
452
453         /*
454          * Get the uid for this SID.
455          */
456
457         if (!winbind_sid_to_uid(puid, psid)) {
458                 DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed.\n",
459                                 sid_to_string(sid_str, psid) ));
460                 return False;
461         }
462
463         DEBUG(10,("sid_to_uid: winbindd %s -> %u\n",
464                 sid_to_string(sid_str, psid),
465                 (unsigned int)*puid ));
466
467         return True;
468 }
469
470 /*****************************************************************
471  *THE CANONICAL* convert SID to gid function.
472  Tries winbind first - then uses local lookup.
473  Returns True if this name is a user sid and the conversion
474  was done correctly, False if not.
475 *****************************************************************/  
476
477 BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype)
478 {
479         fstring dom_name, name, sid_str;
480         enum SID_NAME_USE name_type;
481
482         *sidtype = SID_NAME_UNKNOWN;
483
484         /*
485          * First we must look up the name and decide if this is a group sid.
486          */
487
488         if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) {
489                 DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n",
490                                 sid_to_string(sid_str, psid) ));
491
492                 return local_sid_to_gid(pgid, psid, sidtype);
493         }
494
495         /*
496          * Ensure this is a group sid.
497          */
498
499         if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) {
500                 DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n",
501                                 (unsigned int)name_type ));
502
503                 return local_sid_to_gid(pgid, psid, sidtype);
504         }
505
506         *sidtype = name_type;
507
508         /*
509          * Get the gid for this SID.
510          */
511
512         if (!winbind_sid_to_gid(pgid, psid)) {
513                 DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed.\n",
514                                 sid_to_string(sid_str, psid) ));
515                 return False;
516         }
517
518         DEBUG(10,("gid_to_uid: winbindd %s -> %u\n",
519                 sid_to_string(sid_str, psid),
520                 (unsigned int)*pgid ));
521
522         return True;
523 }
524
525 #undef OLD_NTDOMAIN