only add the service name and client machine name to list of users names
[tprouty/samba.git] / source / smbd / service.c
1 #define OLD_NTDOMAIN 1
2
3 /* 
4    Unix SMB/Netbios implementation.
5    Version 1.9.
6    service (connection) opening and closing
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 extern struct timeval smb_last_time;
29 extern int case_default;
30 extern BOOL case_preserve;
31 extern BOOL short_case_preserve;
32 extern BOOL case_mangle;
33 extern BOOL case_sensitive;
34 extern BOOL use_mangled_map;
35 extern fstring remote_machine;
36 extern userdom_struct current_user_info;
37 extern fstring remote_machine;
38
39
40 /****************************************************************************
41 load parameters specific to a connection/service
42 ****************************************************************************/
43 BOOL become_service(connection_struct *conn,BOOL do_chdir)
44 {
45         extern char magic_char;
46         static connection_struct *last_conn;
47         int snum;
48
49         if (!conn)  {
50                 last_conn = NULL;
51                 return(False);
52         }
53
54         conn->lastused = smb_last_time.tv_sec;
55
56         snum = SNUM(conn);
57   
58         if (do_chdir &&
59             vfs_ChDir(conn,conn->connectpath) != 0 &&
60             vfs_ChDir(conn,conn->origpath) != 0) {
61                 DEBUG(0,("chdir (%s) failed\n",
62                          conn->connectpath));
63                 return(False);
64         }
65
66         if (conn == last_conn)
67                 return(True);
68
69         last_conn = conn;
70
71         case_default = lp_defaultcase(snum);
72         case_preserve = lp_preservecase(snum);
73         short_case_preserve = lp_shortpreservecase(snum);
74         case_mangle = lp_casemangle(snum);
75         case_sensitive = lp_casesensitive(snum);
76         magic_char = lp_magicchar(snum);
77         use_mangled_map = (*lp_mangled_map(snum) ? True:False);
78         return(True);
79 }
80
81
82 /****************************************************************************
83   find a service entry. service is always in dos codepage
84 ****************************************************************************/
85 int find_service(char *service)
86 {
87    int iService;
88
89    all_string_sub(service,"\\","/",0);
90
91    iService = lp_servicenumber(service);
92
93    /* now handle the special case of a home directory */
94    if (iService < 0)
95    {
96       char *phome_dir = get_user_home_dir(service);
97
98       if(!phome_dir)
99       {
100         /*
101          * Try mapping the servicename, it may
102          * be a Windows to unix mapped user name.
103          */
104         if(map_username(service))
105           phome_dir = get_user_home_dir(service);
106       }
107
108       DEBUG(3,("checking for home directory %s gave %s\n",service,
109             phome_dir?phome_dir:"(NULL)"));
110
111       if (phome_dir)
112       {   
113         int iHomeService;
114         if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
115         {
116           /*
117            * If this is a winbindd provided username, remove
118            * the domain component before adding the service.
119            * Log a warning if the "path=" parameter does not
120            * include any macros.
121            */
122
123           fstring new_service;
124           char *usr_p = NULL;
125
126           fstrcpy(new_service, service);
127
128           if ((usr_p = strchr(service,*lp_winbind_separator())) != NULL)
129             fstrcpy(new_service, usr_p+1);
130
131           lp_add_home(new_service,iHomeService,phome_dir);
132           iService = lp_servicenumber(new_service);
133
134           if (usr_p && (strchr(lp_pathname(iService),'%') == NULL))
135               DEBUG(0,("find_service: Service %s added for user %s - contains non-local (Domain) user \
136 with non parameterised path (%s). This may be cause the wrong directory to be seen.\n",
137                  new_service, service, lp_pathname(iService) ));
138         }
139       }
140    }
141
142    /* If we still don't have a service, attempt to add it as a printer. */
143    if (iService < 0)
144    {
145       int iPrinterService;
146
147       if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
148       {
149          char *pszTemp;
150
151          DEBUG(3,("checking whether %s is a valid printer name...\n", service));
152          pszTemp = PRINTCAP;
153          if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
154          {
155             DEBUG(3,("%s is a valid printer name\n", service));
156             DEBUG(3,("adding %s as a printer service\n", service));
157             lp_add_printer(service,iPrinterService);
158             iService = lp_servicenumber(service);
159             if (iService < 0)
160                DEBUG(0,("failed to add %s as a printer service!\n", service));
161          }
162          else
163             DEBUG(3,("%s is not a valid printer name\n", service));
164       }
165    }
166
167    /* Check for default vfs service?  Unsure whether to implement this */
168    if (iService < 0)
169    {
170    }
171
172    /* just possibly it's a default service? */
173    if (iService < 0) 
174    {
175      char *pdefservice = lp_defaultservice();
176      if (pdefservice && *pdefservice && 
177          !strequal(pdefservice,service) &&
178          !strstr(service,".."))
179      {
180        /*
181         * We need to do a local copy here as lp_defaultservice() 
182         * returns one of the rotating lp_string buffers that
183         * could get overwritten by the recursive find_service() call
184         * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
185         */
186        pstring defservice;
187        pstrcpy(defservice, pdefservice);
188        iService = find_service(defservice);
189        if (iService >= 0)
190        {
191          all_string_sub(service,"_","/",0);
192          iService = lp_add_service(service,iService);
193        }
194      }
195    }
196
197    if (iService >= 0)
198      if (!VALID_SNUM(iService))
199      {
200        DEBUG(0,("Invalid snum %d for %s\n",iService,service));
201        iService = -1;
202      }
203
204    if (iService < 0)
205      DEBUG(3,("find_service() failed to find service %s\n", service));
206
207    return (iService);
208 }
209
210
211 /****************************************************************************
212   make a connection to a service
213 ****************************************************************************/
214 connection_struct *make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid, int *ecode)
215 {
216         int snum;
217         struct passwd *pass = NULL;
218         BOOL guest = False;
219         BOOL force = False;
220         connection_struct *conn;
221         int ret;
222
223         strlower(service);
224
225         snum = find_service(service);
226         if (snum < 0) {
227                 if (strequal(service,"IPC$")) {
228                         DEBUG(3,("refusing IPC connection\n"));
229                         *ecode = ERRnoipc;
230                         return NULL;
231                 }
232
233                 DEBUG(0,("%s (%s) couldn't find service %s\n",
234                          remote_machine, client_addr(), service));
235                 *ecode = ERRnosuchshare;
236                 return NULL;
237         }
238
239         if (strequal(service,HOMES_NAME)) {
240                 if (*user && Get_Pwnam(user,True)) {
241                         fstring dos_username;
242                         fstrcpy(dos_username, user);
243                         unix_to_dos(dos_username, True);
244                         return(make_connection(dos_username,user,password,
245                                                pwlen,dev,vuid,ecode));
246                 }
247
248                 if(lp_security() != SEC_SHARE) {
249                         if (validated_username(vuid)) {
250                                 fstring dos_username;
251                                 fstrcpy(user,validated_username(vuid));
252                                 fstrcpy(dos_username, user);
253                                 unix_to_dos(dos_username, True);
254                                 return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode));
255                         }
256                 } else {
257                         /* Security = share. Try with current_user_info.smb_name
258                          * as the username.  */
259                         if(*current_user_info.smb_name) {
260                                 fstring dos_username;
261                                 fstrcpy(user,current_user_info.smb_name);
262                                 fstrcpy(dos_username, user);
263                                 unix_to_dos(dos_username, True);
264                                 return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode));
265                         }
266                 }
267         }
268
269         if (!lp_snum_ok(snum) || 
270             !check_access(smbd_server_fd(), 
271                           lp_hostsallow(snum), lp_hostsdeny(snum))) {    
272                 *ecode = ERRaccess;
273                 return NULL;
274         }
275
276         /* you can only connect to the IPC$ service as an ipc device */
277         if (strequal(service,"IPC$"))
278                 pstrcpy(dev,"IPC");
279         
280         if (*dev == '?' || !*dev) {
281                 if (lp_print_ok(snum)) {
282                         pstrcpy(dev,"LPT1:");
283                 } else {
284                         pstrcpy(dev,"A:");
285                 }
286         }
287
288         /* if the request is as a printer and you can't print then refuse */
289         strupper(dev);
290         if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
291                 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
292                 *ecode = ERRinvdevice;
293                 return NULL;
294         }
295
296         /* Behave as a printer if we are supposed to */
297         if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
298                 pstrcpy(dev, "LPT1:");
299         }
300
301         /* lowercase the user name */
302         strlower(user);
303
304         /* add it as a possible user name if we 
305            are in share mode security */
306         if (lp_security() == SEC_SHARE) {
307                 add_session_user(service);
308         }
309
310         /* shall we let them in? */
311         if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) {
312                 DEBUG( 2, ( "Invalid username/password for %s [%s]\n", service, user ) );
313                 *ecode = ERRbadpw;
314                 return NULL;
315         }
316   
317         conn = conn_new();
318         if (!conn) {
319                 DEBUG(0,("Couldn't find free connection.\n"));
320                 *ecode = ERRnoresource;
321                 conn_free(conn);
322                 return NULL;
323         }
324
325         /* find out some info about the user */
326         pass = smb_getpwnam(user,True);
327
328         if (pass == NULL) {
329                 DEBUG(0,( "Couldn't find account %s\n",user));
330                 *ecode = ERRbaduid;
331                 conn_free(conn);
332                 return NULL;
333         }
334
335         conn->read_only = lp_readonly(snum);
336
337         {
338                 pstring list;
339                 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
340                 pstring_sub(list,"%S",service);
341
342                 if (user_in_list(user,list))
343                         conn->read_only = True;
344                 
345                 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
346                 pstring_sub(list,"%S",service);
347                 
348                 if (user_in_list(user,list))
349                         conn->read_only = False;    
350         }
351
352         /* admin user check */
353         
354         /* JRA - original code denied admin user if the share was
355            marked read_only. Changed as I don't think this is needed,
356            but old code left in case there is a problem here.
357         */
358         if (user_in_list(user,lp_admin_users(snum)) 
359 #if 0
360             && !conn->read_only
361 #endif
362             ) {
363                 conn->admin_user = True;
364                 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
365         } else {
366                 conn->admin_user = False;
367         }
368     
369         conn->force_user = force;
370         conn->vuid = vuid;
371         conn->uid = pass->pw_uid;
372         conn->gid = pass->pw_gid;
373         safe_strcpy(conn->client_address, client_addr(), sizeof(conn->client_address)-1);
374         conn->num_files_open = 0;
375         conn->lastused = time(NULL);
376         conn->service = snum;
377         conn->used = True;
378         conn->printer = (strncmp(dev,"LPT",3) == 0);
379         conn->ipc = (strncmp(dev,"IPC",3) == 0);
380         conn->dirptr = NULL;
381         conn->veto_list = NULL;
382         conn->hide_list = NULL;
383         conn->veto_oplock_list = NULL;
384         string_set(&conn->dirpath,"");
385         string_set(&conn->user,user);
386         conn->nt_user_token = NULL;
387         
388         /*
389          * If force user is true, then store the
390          * given userid and also the primary groupid
391          * of the user we're forcing.
392          */
393         
394         if (*lp_force_user(snum)) {
395                 struct passwd *pass2;
396                 pstring fuser;
397                 pstrcpy(fuser,lp_force_user(snum));
398
399                 /* Allow %S to be used by force user. */
400                 pstring_sub(fuser,"%S",service);
401
402                 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
403                 if (pass2) {
404                         conn->uid = pass2->pw_uid;
405                         conn->gid = pass2->pw_gid;
406                         string_set(&conn->user,fuser);
407                         fstrcpy(user,fuser);
408                         conn->force_user = True;
409                         DEBUG(3,("Forced user %s\n",fuser));      
410                 } else {
411                         DEBUG(1,("Couldn't find user %s\n",fuser));
412                 }
413         }
414
415         /* admin users always run as uid=0 */
416         if (conn->admin_user) {
417                 conn->uid = 0;
418         }
419
420 #ifdef HAVE_GETGRNAM 
421         /*
422          * If force group is true, then override
423          * any groupid stored for the connecting user.
424          */
425         
426         if (*lp_force_group(snum)) {
427                 gid_t gid;
428                 pstring gname;
429                 pstring tmp_gname;
430                 BOOL user_must_be_member = False;
431                 
432                 StrnCpy(tmp_gname,lp_force_group(snum),sizeof(pstring)-1);
433
434                 if (tmp_gname[0] == '+') {
435                         user_must_be_member = True;
436                         StrnCpy(gname,&tmp_gname[1],sizeof(pstring)-2);
437                 } else {
438                         StrnCpy(gname,tmp_gname,sizeof(pstring)-1);
439                 }
440                 /* default service may be a group name          */
441                 pstring_sub(gname,"%S",service);
442                 gid = nametogid(gname);
443                 
444                 if (gid != (gid_t)-1) {
445                         /*
446                          * If the user has been forced and the forced group starts
447                          * with a '+', then we only set the group to be the forced
448                          * group if the forced user is a member of that group.
449                          * Otherwise, the meaning of the '+' would be ignored.
450                          */
451                         if (conn->force_user && user_must_be_member) {
452                                 if (user_in_group_list( user, gname )) {
453                                                 conn->gid = gid;
454                                                 DEBUG(3,("Forced group %s for member %s\n",gname,user));
455                                 }
456                         } else {
457                                 conn->gid = gid;
458                                 DEBUG(3,("Forced group %s\n",gname));
459                         }
460                 } else {
461                         DEBUG(1,("Couldn't find group %s\n",gname));
462                 }
463         }
464 #endif /* HAVE_GETGRNAM */
465
466         {
467                 pstring s;
468                 pstrcpy(s,lp_pathname(snum));
469                 standard_sub_conn(conn,s);
470                 string_set(&conn->connectpath,s);
471                 DEBUG(3,("Connect path is %s\n",s));
472         }
473
474         /* groups stuff added by ih */
475         conn->ngroups = 0;
476         conn->groups = NULL;
477         
478         /* Find all the groups this uid is in and
479            store them. Used by become_user() */
480         initialise_groups(conn->user, conn->uid, conn->gid); 
481         get_current_groups(&conn->ngroups,&conn->groups);
482                 
483         /* check number of connections */
484         if (!claim_connection(conn,
485                               lp_servicename(SNUM(conn)),
486                               lp_max_connections(SNUM(conn)),
487                               False)) {
488                 DEBUG(1,("too many connections - rejected\n"));
489                 *ecode = ERRnoresource;
490                 conn_free(conn);
491                 return NULL;
492         }  
493                 
494         conn->nt_user_token = create_nt_token(conn->uid, conn->gid, 
495                                               conn->ngroups, conn->groups,
496                                               guest);
497
498         /* Initialise VFS function pointers */
499
500         if (*lp_vfsobj(SNUM(conn))) {
501
502 #ifdef HAVE_LIBDL
503
504             /* Loadable object file */
505
506             if (!vfs_init_custom(conn)) {
507                 DEBUG(0, ("vfs_init failed\n"));
508                     conn_free(conn);
509                         return NULL;
510             }
511 #else
512             DEBUG(0, ("No libdl present - cannot use VFS objects\n"));
513             conn_free(conn);
514             return NULL;
515 #endif
516
517         } else {
518
519             /* Normal share - initialise with disk access functions */
520
521             vfs_init_default(conn);
522         }
523
524         /* execute any "root preexec = " line */
525         if (*lp_rootpreexec(SNUM(conn))) {
526                 pstring cmd;
527                 pstrcpy(cmd,lp_rootpreexec(SNUM(conn)));
528                 standard_sub_conn(conn,cmd);
529                 DEBUG(5,("cmd=%s\n",cmd));
530                 ret = smbrun(cmd,NULL,False);
531                 if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) {
532                         DEBUG(1,("preexec gave %d - failing connection\n", ret));
533                         conn_free(conn);
534                         *ecode = ERRsrverror;
535                         return NULL;
536                 }
537         }
538         
539         if (!become_user(conn, conn->vuid)) {
540                 DEBUG(0,("Can't become connected user!\n"));
541                 yield_connection(conn,
542                                  lp_servicename(SNUM(conn)),
543                                  lp_max_connections(SNUM(conn)));
544                 conn_free(conn);
545                 *ecode = ERRbadpw;
546                 return NULL;
547         }
548         
549         if (vfs_ChDir(conn,conn->connectpath) != 0) {
550                 DEBUG(0,("Can't change directory to %s (%s)\n",
551                          conn->connectpath,strerror(errno)));
552                 unbecome_user();
553                 yield_connection(conn,
554                                  lp_servicename(SNUM(conn)),
555                                  lp_max_connections(SNUM(conn)));
556                 conn_free(conn);
557                 *ecode = ERRnosuchshare;
558                 return NULL;
559         }
560         
561         string_set(&conn->origpath,conn->connectpath);
562         
563 #if SOFTLINK_OPTIMISATION
564         /* resolve any soft links early */
565         {
566                 pstring s;
567                 pstrcpy(s,conn->connectpath);
568                 vfs_GetWd(conn,s);
569                 string_set(&conn->connectpath,s);
570                 vfs_ChDir(conn,conn->connectpath);
571         }
572 #endif
573         
574         add_session_user(user);
575                 
576         /* execute any "preexec = " line */
577         if (*lp_preexec(SNUM(conn))) {
578                 pstring cmd;
579                 pstrcpy(cmd,lp_preexec(SNUM(conn)));
580                 standard_sub_conn(conn,cmd);
581                 ret = smbrun(cmd,NULL,False);
582                 if (ret != 0 && lp_preexec_close(SNUM(conn))) {
583                         DEBUG(1,("preexec gave %d - failing connection\n", ret));
584                         conn_free(conn);
585                         *ecode = ERRsrverror;
586                         return NULL;
587                 }
588         }
589
590         /*
591          * Print out the 'connected as' stuff here as we need
592          * to know the effective uid and gid we will be using.
593          */
594
595         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
596                 dbgtext( "%s (%s) ", remote_machine, conn->client_address );
597                 dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) );
598                 dbgtext( "as user %s ", user );
599                 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
600                 dbgtext( "(pid %d)\n", (int)sys_getpid() );
601         }
602         
603         /* we've finished with the sensitive stuff */
604         unbecome_user();
605         
606         /* Add veto/hide lists */
607         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
608                 set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn)));
609                 set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn)));
610                 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn)));
611         }
612         
613         /* Invoke VFS make connection hook */
614
615         if (conn->vfs_ops.connect) {
616                 if (conn->vfs_ops.connect(conn, service, user) < 0)
617                         return NULL;
618         }
619             
620         return(conn);
621 }
622
623
624 /****************************************************************************
625 close a cnum
626 ****************************************************************************/
627 void close_cnum(connection_struct *conn, uint16 vuid)
628 {
629         DirCacheFlush(SNUM(conn));
630
631         unbecome_user();
632
633         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
634                                  remote_machine,conn->client_address,
635                                  lp_servicename(SNUM(conn))));
636
637         if (conn->vfs_ops.disconnect != NULL) {
638
639             /* Call VFS disconnect hook */
640             
641             conn->vfs_ops.disconnect(conn);
642             
643         }
644
645         yield_connection(conn,
646                          lp_servicename(SNUM(conn)),
647                          lp_max_connections(SNUM(conn)));
648
649         file_close_conn(conn);
650         dptr_closecnum(conn);
651
652         /* execute any "postexec = " line */
653         if (*lp_postexec(SNUM(conn)) && 
654             become_user(conn, vuid))  {
655                 pstring cmd;
656                 pstrcpy(cmd,lp_postexec(SNUM(conn)));
657                 standard_sub_conn(conn,cmd);
658                 smbrun(cmd,NULL,False);
659                 unbecome_user();
660         }
661
662         unbecome_user();
663         /* execute any "root postexec = " line */
664         if (*lp_rootpostexec(SNUM(conn)))  {
665                 pstring cmd;
666                 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
667                 standard_sub_conn(conn,cmd);
668                 smbrun(cmd,NULL,False);
669         }
670         conn_free(conn);
671 }
672
673 #undef OLD_NTDOMAIN