Log debug message when hires timestamps are available on the
[ira/wip.git] / source3 / smbd / service.c
1 /* 
2    Unix SMB/CIFS implementation.
3    service (connection) opening and closing
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 extern userdom_struct current_user_info;
24
25 static bool canonicalize_connect_path(connection_struct *conn)
26 {
27 #ifdef REALPATH_TAKES_NULL
28         bool ret;
29         char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,NULL);
30         if (!resolved_name) {
31                 return false;
32         }
33         ret = set_conn_connectpath(conn,resolved_name);
34         SAFE_FREE(resolved_name);
35         return ret;
36 #else
37         char resolved_name_buf[PATH_MAX+1];
38         char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,resolved_name_buf);
39         if (!resolved_name) {
40                 return false;
41         }
42         return set_conn_connectpath(conn,resolved_name);
43 #endif /* REALPATH_TAKES_NULL */
44 }
45
46 /****************************************************************************
47  Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
48  absolute path stating in / and not ending in /.
49  Observent people will notice a similarity between this and check_path_syntax :-).
50 ****************************************************************************/
51
52 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
53 {
54         char *destname;
55         char *d;
56         const char *s = connectpath;
57         bool start_of_name_component = true;
58
59         destname = SMB_STRDUP(connectpath);
60         if (!destname) {
61                 return false;
62         }
63         d = destname;
64
65         *d++ = '/'; /* Always start with root. */
66
67         while (*s) {
68                 if (*s == '/') {
69                         /* Eat multiple '/' */
70                         while (*s == '/') {
71                                 s++;
72                         }
73                         if ((d > destname + 1) && (*s != '\0')) {
74                                 *d++ = '/';
75                         }
76                         start_of_name_component = True;
77                         continue;
78                 }
79
80                 if (start_of_name_component) {
81                         if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
82                                 /* Uh oh - "/../" or "/..\0" ! */
83
84                                 /* Go past the ../ or .. */
85                                 if (s[2] == '/') {
86                                         s += 3;
87                                 } else {
88                                         s += 2; /* Go past the .. */
89                                 }
90
91                                 /* If  we just added a '/' - delete it */
92                                 if ((d > destname) && (*(d-1) == '/')) {
93                                         *(d-1) = '\0';
94                                         d--;
95                                 }
96
97                                 /* Are we at the start ? Can't go back further if so. */
98                                 if (d <= destname) {
99                                         *d++ = '/'; /* Can't delete root */
100                                         continue;
101                                 }
102                                 /* Go back one level... */
103                                 /* Decrement d first as d points to the *next* char to write into. */
104                                 for (d--; d > destname; d--) {
105                                         if (*d == '/') {
106                                                 break;
107                                         }
108                                 }
109                                 /* We're still at the start of a name component, just the previous one. */
110                                 continue;
111                         } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
112                                 /* Component of pathname can't be "." only - skip the '.' . */
113                                 if (s[1] == '/') {
114                                         s += 2;
115                                 } else {
116                                         s++;
117                                 }
118                                 continue;
119                         }
120                 }
121
122                 if (!(*s & 0x80)) {
123                         *d++ = *s++;
124                 } else {
125                         size_t siz;
126                         /* Get the size of the next MB character. */
127                         next_codepoint(s,&siz);
128                         switch(siz) {
129                                 case 5:
130                                         *d++ = *s++;
131                                         /*fall through*/
132                                 case 4:
133                                         *d++ = *s++;
134                                         /*fall through*/
135                                 case 3:
136                                         *d++ = *s++;
137                                         /*fall through*/
138                                 case 2:
139                                         *d++ = *s++;
140                                         /*fall through*/
141                                 case 1:
142                                         *d++ = *s++;
143                                         break;
144                                 default:
145                                         break;
146                         }
147                 }
148                 start_of_name_component = false;
149         }
150         *d = '\0';
151
152         /* And must not end in '/' */
153         if (d > destname + 1 && (*(d-1) == '/')) {
154                 *(d-1) = '\0';
155         }
156
157         DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
158                 lp_servicename(SNUM(conn)), destname ));
159
160         string_set(&conn->connectpath, destname);
161         SAFE_FREE(destname);
162         return true;
163 }
164
165 /****************************************************************************
166  Load parameters specific to a connection/service.
167 ****************************************************************************/
168
169 bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
170 {
171         int snum;
172
173         if (!conn)  {
174                 last_conn = NULL;
175                 return(False);
176         }
177
178         conn->lastused_count++;
179
180         snum = SNUM(conn);
181   
182         if (do_chdir &&
183             vfs_ChDir(conn,conn->connectpath) != 0 &&
184             vfs_ChDir(conn,conn->origpath) != 0) {
185                 DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
186                          conn->connectpath, strerror(errno)));
187                 return(False);
188         }
189
190         if ((conn == last_conn) && (last_flags == flags)) {
191                 return(True);
192         }
193
194         last_conn = conn;
195         last_flags = flags;
196         
197         /* Obey the client case sensitivity requests - only for clients that support it. */
198         switch (lp_casesensitive(snum)) {
199                 case Auto:
200                         {
201                                 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
202                                 enum remote_arch_types ra_type = get_remote_arch();
203                                 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
204                                         /* Client can't support per-packet case sensitive pathnames. */
205                                         conn->case_sensitive = False;
206                                 } else {
207                                         conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
208                                 }
209                         }
210                         break;
211                 case True:
212                         conn->case_sensitive = True;
213                         break;
214                 default:
215                         conn->case_sensitive = False;
216                         break;
217         }
218         return(True);
219 }
220
221 static int load_registry_service(const char *servicename)
222 {
223         if (!lp_registry_shares()) {
224                 return -1;
225         }
226
227         if ((servicename == NULL) || (*servicename == '\0')) {
228                 return -1;
229         }
230
231         if (strequal(servicename, GLOBAL_NAME)) {
232                 return -2;
233         }
234
235         if (!process_registry_service(servicename)) {
236                 return -1;
237         }
238
239         return lp_servicenumber(servicename);
240 }
241
242 void load_registry_shares(void)
243 {
244         DEBUG(8, ("load_registry_shares()\n"));
245         if (!lp_registry_shares()) {
246                 return;
247         }
248
249         process_registry_shares();
250
251         return;
252 }
253
254 /****************************************************************************
255  Add a home service. Returns the new service number or -1 if fail.
256 ****************************************************************************/
257
258 int add_home_service(const char *service, const char *username, const char *homedir)
259 {
260         int iHomeService;
261
262         if (!service || !homedir)
263                 return -1;
264
265         if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
266                 if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
267                         return -1;
268                 }
269         }
270
271         /*
272          * If this is a winbindd provided username, remove
273          * the domain component before adding the service.
274          * Log a warning if the "path=" parameter does not
275          * include any macros.
276          */
277
278         {
279                 const char *p = strchr(service,*lp_winbind_separator());
280
281                 /* We only want the 'user' part of the string */
282                 if (p) {
283                         service = p + 1;
284                 }
285         }
286
287         if (!lp_add_home(service, iHomeService, username, homedir)) {
288                 return -1;
289         }
290         
291         return lp_servicenumber(service);
292
293 }
294
295 /**
296  * Find a service entry.
297  *
298  * @param service is modified (to canonical form??)
299  **/
300
301 int find_service(fstring service)
302 {
303         int iService;
304         struct smbd_server_connection *sconn = smbd_server_conn;
305
306         all_string_sub(service,"\\","/",0);
307
308         iService = lp_servicenumber(service);
309
310         /* now handle the special case of a home directory */
311         if (iService < 0) {
312                 char *phome_dir = get_user_home_dir(talloc_tos(), service);
313
314                 if(!phome_dir) {
315                         /*
316                          * Try mapping the servicename, it may
317                          * be a Windows to unix mapped user name.
318                          */
319                         if(map_username(sconn, service))
320                                 phome_dir = get_user_home_dir(
321                                         talloc_tos(), service);
322                 }
323
324                 DEBUG(3,("checking for home directory %s gave %s\n",service,
325                         phome_dir?phome_dir:"(NULL)"));
326
327                 iService = add_home_service(service,service /* 'username' */, phome_dir);
328         }
329
330         /* If we still don't have a service, attempt to add it as a printer. */
331         if (iService < 0) {
332                 int iPrinterService;
333
334                 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
335                         iPrinterService = load_registry_service(PRINTERS_NAME);
336                 }
337                 if (iPrinterService) {
338                         DEBUG(3,("checking whether %s is a valid printer name...\n", service));
339                         if (pcap_printername_ok(service)) {
340                                 DEBUG(3,("%s is a valid printer name\n", service));
341                                 DEBUG(3,("adding %s as a printer service\n", service));
342                                 lp_add_printer(service, iPrinterService);
343                                 iService = lp_servicenumber(service);
344                                 if (iService < 0) {
345                                         DEBUG(0,("failed to add %s as a printer service!\n", service));
346                                 }
347                         } else {
348                                 DEBUG(3,("%s is not a valid printer name\n", service));
349                         }
350                 }
351         }
352
353         /* Check for default vfs service?  Unsure whether to implement this */
354         if (iService < 0) {
355         }
356
357         if (iService < 0) {
358                 iService = load_registry_service(service);
359         }
360
361         /* Is it a usershare service ? */
362         if (iService < 0 && *lp_usershare_path()) {
363                 /* Ensure the name is canonicalized. */
364                 strlower_m(service);
365                 iService = load_usershare_service(service);
366         }
367
368         /* just possibly it's a default service? */
369         if (iService < 0) {
370                 char *pdefservice = lp_defaultservice();
371                 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
372                         /*
373                          * We need to do a local copy here as lp_defaultservice() 
374                          * returns one of the rotating lp_string buffers that
375                          * could get overwritten by the recursive find_service() call
376                          * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
377                          */
378                         char *defservice = SMB_STRDUP(pdefservice);
379
380                         if (!defservice) {
381                                 goto fail;
382                         }
383
384                         /* Disallow anything except explicit share names. */
385                         if (strequal(defservice,HOMES_NAME) ||
386                                         strequal(defservice, PRINTERS_NAME) ||
387                                         strequal(defservice, "IPC$")) {
388                                 SAFE_FREE(defservice);
389                                 goto fail;
390                         }
391
392                         iService = find_service(defservice);
393                         if (iService >= 0) {
394                                 all_string_sub(service, "_","/",0);
395                                 iService = lp_add_service(service, iService);
396                         }
397                         SAFE_FREE(defservice);
398                 }
399         }
400
401         if (iService >= 0) {
402                 if (!VALID_SNUM(iService)) {
403                         DEBUG(0,("Invalid snum %d for %s\n",iService, service));
404                         iService = -1;
405                 }
406         }
407
408   fail:
409
410         if (iService < 0)
411                 DEBUG(3,("find_service() failed to find service %s\n", service));
412
413         return (iService);
414 }
415
416
417 /****************************************************************************
418  do some basic sainity checks on the share.  
419  This function modifies dev, ecode.
420 ****************************************************************************/
421
422 static NTSTATUS share_sanity_checks(int snum, fstring dev) 
423 {
424         
425         if (!lp_snum_ok(snum) || 
426             !check_access(smbd_server_fd(), 
427                           lp_hostsallow(snum), lp_hostsdeny(snum))) {    
428                 return NT_STATUS_ACCESS_DENIED;
429         }
430
431         if (dev[0] == '?' || !dev[0]) {
432                 if (lp_print_ok(snum)) {
433                         fstrcpy(dev,"LPT1:");
434                 } else if (strequal(lp_fstype(snum), "IPC")) {
435                         fstrcpy(dev, "IPC");
436                 } else {
437                         fstrcpy(dev,"A:");
438                 }
439         }
440
441         strupper_m(dev);
442
443         if (lp_print_ok(snum)) {
444                 if (!strequal(dev, "LPT1:")) {
445                         return NT_STATUS_BAD_DEVICE_TYPE;
446                 }
447         } else if (strequal(lp_fstype(snum), "IPC")) {
448                 if (!strequal(dev, "IPC")) {
449                         return NT_STATUS_BAD_DEVICE_TYPE;
450                 }
451         } else if (!strequal(dev, "A:")) {
452                 return NT_STATUS_BAD_DEVICE_TYPE;
453         }
454
455         /* Behave as a printer if we are supposed to */
456         if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
457                 fstrcpy(dev, "LPT1:");
458         }
459
460         return NT_STATUS_OK;
461 }
462
463 /*
464  * Go through lookup_name etc to find the force'd group.  
465  *
466  * Create a new token from src_token, replacing the primary group sid with the
467  * one found.
468  */
469
470 static NTSTATUS find_forced_group(bool force_user,
471                                   int snum, const char *username,
472                                   DOM_SID *pgroup_sid,
473                                   gid_t *pgid)
474 {
475         NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
476         TALLOC_CTX *frame = talloc_stackframe();
477         DOM_SID group_sid;
478         enum lsa_SidType type;
479         char *groupname;
480         bool user_must_be_member = False;
481         gid_t gid;
482
483         groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
484         if (groupname == NULL) {
485                 DEBUG(1, ("talloc_strdup failed\n"));
486                 result = NT_STATUS_NO_MEMORY;
487                 goto done;
488         }
489
490         if (groupname[0] == '+') {
491                 user_must_be_member = True;
492                 groupname += 1;
493         }
494
495         groupname = talloc_string_sub(talloc_tos(), groupname,
496                                       "%S", lp_servicename(snum));
497         if (groupname == NULL) {
498                 DEBUG(1, ("talloc_string_sub failed\n"));
499                 result = NT_STATUS_NO_MEMORY;
500                 goto done;
501         }
502
503         if (!lookup_name_smbconf(talloc_tos(), groupname,
504                          LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
505                          NULL, NULL, &group_sid, &type)) {
506                 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
507                            groupname));
508                 goto done;
509         }
510
511         if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
512             (type != SID_NAME_WKN_GRP)) {
513                 DEBUG(10, ("%s is a %s, not a group\n", groupname,
514                            sid_type_lookup(type)));
515                 goto done;
516         }
517
518         if (!sid_to_gid(&group_sid, &gid)) {
519                 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
520                            sid_string_dbg(&group_sid), groupname));
521                 goto done;
522         }
523
524         /*
525          * If the user has been forced and the forced group starts with a '+',
526          * then we only set the group to be the forced group if the forced
527          * user is a member of that group.  Otherwise, the meaning of the '+'
528          * would be ignored.
529          */
530
531         if (force_user && user_must_be_member) {
532                 if (user_in_group_sid(username, &group_sid)) {
533                         sid_copy(pgroup_sid, &group_sid);
534                         *pgid = gid;
535                         DEBUG(3,("Forced group %s for member %s\n",
536                                  groupname, username));
537                 } else {
538                         DEBUG(0,("find_forced_group: forced user %s is not a member "
539                                 "of forced group %s. Disallowing access.\n",
540                                 username, groupname ));
541                         result = NT_STATUS_MEMBER_NOT_IN_GROUP;
542                         goto done;
543                 }
544         } else {
545                 sid_copy(pgroup_sid, &group_sid);
546                 *pgid = gid;
547                 DEBUG(3,("Forced group %s\n", groupname));
548         }
549
550         result = NT_STATUS_OK;
551  done:
552         TALLOC_FREE(frame);
553         return result;
554 }
555
556 /****************************************************************************
557   Create an auth_serversupplied_info structure for a connection_struct
558 ****************************************************************************/
559
560 static NTSTATUS create_connection_server_info(struct smbd_server_connection *sconn,
561                                               TALLOC_CTX *mem_ctx, int snum,
562                                               struct auth_serversupplied_info *vuid_serverinfo,
563                                               DATA_BLOB password,
564                                               struct auth_serversupplied_info **presult)
565 {
566         if (lp_guest_only(snum)) {
567                 return make_server_info_guest(mem_ctx, presult);
568         }
569
570         if (vuid_serverinfo != NULL) {
571
572                 struct auth_serversupplied_info *result;
573
574                 /*
575                  * This is the normal security != share case where we have a
576                  * valid vuid from the session setup.                 */
577
578                 if (vuid_serverinfo->guest) {
579                         if (!lp_guest_ok(snum)) {
580                                 DEBUG(2, ("guest user (from session setup) "
581                                           "not permitted to access this share "
582                                           "(%s)\n", lp_servicename(snum)));
583                                 return NT_STATUS_ACCESS_DENIED;
584                         }
585                 } else {
586                         if (!user_ok_token(vuid_serverinfo->unix_name,
587                                            pdb_get_domain(vuid_serverinfo->sam_account),
588                                            vuid_serverinfo->ptok, snum)) {
589                                 DEBUG(2, ("user '%s' (from session setup) not "
590                                           "permitted to access this share "
591                                           "(%s)\n",
592                                           vuid_serverinfo->unix_name,
593                                           lp_servicename(snum)));
594                                 return NT_STATUS_ACCESS_DENIED;
595                         }
596                 }
597
598                 result = copy_serverinfo(mem_ctx, vuid_serverinfo);
599                 if (result == NULL) {
600                         return NT_STATUS_NO_MEMORY;
601                 }
602
603                 *presult = result;
604                 return NT_STATUS_OK;
605         }
606
607         if (lp_security() == SEC_SHARE) {
608
609                 fstring user;
610                 bool guest;
611
612                 /* add the sharename as a possible user name if we
613                    are in share mode security */
614
615                 add_session_user(sconn, lp_servicename(snum));
616
617                 /* shall we let them in? */
618
619                 if (!authorise_login(sconn, snum,user,password,&guest)) {
620                         DEBUG( 2, ( "Invalid username/password for [%s]\n",
621                                     lp_servicename(snum)) );
622                         return NT_STATUS_WRONG_PASSWORD;
623                 }
624
625                 return make_serverinfo_from_username(mem_ctx, user, guest,
626                                                      presult);
627         }
628
629         DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
630         return NT_STATUS_ACCESS_DENIED;
631 }
632
633
634 /****************************************************************************
635   Make a connection, given the snum to connect to, and the vuser of the
636   connecting user if appropriate.
637 ****************************************************************************/
638
639 connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
640                                         int snum, user_struct *vuser,
641                                         DATA_BLOB password,
642                                         const char *pdev,
643                                         NTSTATUS *pstatus)
644 {
645         connection_struct *conn;
646         struct smb_filename *smb_fname_cpath = NULL;
647         fstring dev;
648         int ret;
649         char addr[INET6_ADDRSTRLEN];
650         bool on_err_call_dis_hook = false;
651         NTSTATUS status;
652
653         fstrcpy(dev, pdev);
654
655         if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) {
656                 return NULL;
657         }       
658
659         conn = conn_new(sconn);
660         if (!conn) {
661                 DEBUG(0,("Couldn't find free connection.\n"));
662                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
663                 return NULL;
664         }
665
666         conn->params->service = snum;
667
668         status = create_connection_server_info(sconn,
669                 conn, snum, vuser ? vuser->server_info : NULL, password,
670                 &conn->server_info);
671
672         if (!NT_STATUS_IS_OK(status)) {
673                 DEBUG(1, ("create_connection_server_info failed: %s\n",
674                           nt_errstr(status)));
675                 *pstatus = status;
676                 conn_free(conn);
677                 return NULL;
678         }
679
680         if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
681                 conn->force_user = true;
682         }
683
684         add_session_user(sconn, conn->server_info->unix_name);
685
686         safe_strcpy(conn->client_address,
687                         client_addr(get_client_fd(),addr,sizeof(addr)), 
688                         sizeof(conn->client_address)-1);
689         conn->num_files_open = 0;
690         conn->lastused = conn->lastused_count = time(NULL);
691         conn->used = True;
692         conn->printer = (strncmp(dev,"LPT",3) == 0);
693         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
694                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
695
696         /* Case options for the share. */
697         if (lp_casesensitive(snum) == Auto) {
698                 /* We will be setting this per packet. Set to be case
699                  * insensitive for now. */
700                 conn->case_sensitive = False;
701         } else {
702                 conn->case_sensitive = (bool)lp_casesensitive(snum);
703         }
704
705         conn->case_preserve = lp_preservecase(snum);
706         conn->short_case_preserve = lp_shortpreservecase(snum);
707
708         conn->encrypt_level = lp_smb_encrypt(snum);
709
710         conn->veto_list = NULL;
711         conn->hide_list = NULL;
712         conn->veto_oplock_list = NULL;
713         conn->aio_write_behind_list = NULL;
714
715         conn->read_only = lp_readonly(SNUM(conn));
716         conn->admin_user = False;
717
718         if (*lp_force_user(snum)) {
719
720                 /*
721                  * Replace conn->server_info with a completely faked up one
722                  * from the username we are forced into :-)
723                  */
724
725                 char *fuser;
726                 struct auth_serversupplied_info *forced_serverinfo;
727
728                 fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
729                                           lp_servicename(snum));
730                 if (fuser == NULL) {
731                         conn_free(conn);
732                         *pstatus = NT_STATUS_NO_MEMORY;
733                         return NULL;
734                 }
735
736                 status = make_serverinfo_from_username(
737                         conn, fuser, conn->server_info->guest,
738                         &forced_serverinfo);
739                 if (!NT_STATUS_IS_OK(status)) {
740                         conn_free(conn);
741                         *pstatus = status;
742                         return NULL;
743                 }
744
745                 TALLOC_FREE(conn->server_info);
746                 conn->server_info = forced_serverinfo;
747
748                 conn->force_user = True;
749                 DEBUG(3,("Forced user %s\n", fuser));
750         }
751
752         /*
753          * If force group is true, then override
754          * any groupid stored for the connecting user.
755          */
756
757         if (*lp_force_group(snum)) {
758
759                 status = find_forced_group(
760                         conn->force_user, snum, conn->server_info->unix_name,
761                         &conn->server_info->ptok->user_sids[1],
762                         &conn->server_info->utok.gid);
763
764                 if (!NT_STATUS_IS_OK(status)) {
765                         conn_free(conn);
766                         *pstatus = status;
767                         return NULL;
768                 }
769
770                 /*
771                  * We need to cache this gid, to use within
772                  * change_to_user() separately from the conn->server_info
773                  * struct. We only use conn->server_info directly if
774                  * "force_user" was set.
775                  */
776                 conn->force_group_gid = conn->server_info->utok.gid;
777         }
778
779         conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
780
781         {
782                 char *s = talloc_sub_advanced(talloc_tos(),
783                                         lp_servicename(SNUM(conn)),
784                                         conn->server_info->unix_name,
785                                         conn->connectpath,
786                                         conn->server_info->utok.gid,
787                                         conn->server_info->sanitized_username,
788                                         pdb_get_domain(conn->server_info->sam_account),
789                                         lp_pathname(snum));
790                 if (!s) {
791                         conn_free(conn);
792                         *pstatus = NT_STATUS_NO_MEMORY;
793                         return NULL;
794                 }
795
796                 if (!set_conn_connectpath(conn,s)) {
797                         TALLOC_FREE(s);
798                         conn_free(conn);
799                         *pstatus = NT_STATUS_NO_MEMORY;
800                         return NULL;
801                 }
802                 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
803                          lp_servicename(snum)));
804                 TALLOC_FREE(s);
805         }
806
807         /*
808          * New code to check if there's a share security descripter
809          * added from NT server manager. This is done after the
810          * smb.conf checks are done as we need a uid and token. JRA.
811          *
812          */
813
814         {
815                 bool can_write = False;
816
817                 can_write = share_access_check(conn->server_info->ptok,
818                                                lp_servicename(snum),
819                                                FILE_WRITE_DATA);
820
821                 if (!can_write) {
822                         if (!share_access_check(conn->server_info->ptok,
823                                                 lp_servicename(snum),
824                                                 FILE_READ_DATA)) {
825                                 /* No access, read or write. */
826                                 DEBUG(0,("make_connection: connection to %s "
827                                          "denied due to security "
828                                          "descriptor.\n",
829                                           lp_servicename(snum)));
830                                 conn_free(conn);
831                                 *pstatus = NT_STATUS_ACCESS_DENIED;
832                                 return NULL;
833                         } else {
834                                 conn->read_only = True;
835                         }
836                 }
837         }
838         /* Initialise VFS function pointers */
839
840         if (!smbd_vfs_init(conn)) {
841                 DEBUG(0, ("vfs_init failed for service %s\n",
842                           lp_servicename(snum)));
843                 conn_free(conn);
844                 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
845                 return NULL;
846         }
847
848         /*
849          * If widelinks are disallowed we need to canonicalise the connect
850          * path here to ensure we don't have any symlinks in the
851          * connectpath. We will be checking all paths on this connection are
852          * below this directory. We must do this after the VFS init as we
853          * depend on the realpath() pointer in the vfs table. JRA.
854          */
855         if (!lp_widelinks(snum)) {
856                 if (!canonicalize_connect_path(conn)) {
857                         DEBUG(0, ("canonicalize_connect_path failed "
858                         "for service %s, path %s\n",
859                                 lp_servicename(snum),
860                                 conn->connectpath));
861                         conn_free(conn);
862                         *pstatus = NT_STATUS_BAD_NETWORK_NAME;
863                         return NULL;
864                 }
865         }
866
867         if ((!conn->printer) && (!conn->ipc)) {
868                 conn->notify_ctx = notify_init(conn, server_id_self(),
869                                                smbd_messaging_context(),
870                                                smbd_event_context(),
871                                                conn);
872         }
873
874 /* ROOT Activities: */  
875         /*
876          * Enforce the max connections parameter.
877          */
878
879         if ((lp_max_connections(snum) > 0)
880             && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
881                 lp_max_connections(snum))) {
882
883                 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
884                           lp_max_connections(snum), lp_servicename(snum)));
885                 conn_free(conn);
886                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
887                 return NULL;
888         }  
889
890         /*
891          * Get us an entry in the connections db
892          */
893         if (!claim_connection(conn, lp_servicename(snum), 0)) {
894                 DEBUG(1, ("Could not store connections entry\n"));
895                 conn_free(conn);
896                 *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
897                 return NULL;
898         }  
899
900         /* Preexecs are done here as they might make the dir we are to ChDir
901          * to below */
902         /* execute any "root preexec = " line */
903         if (*lp_rootpreexec(snum)) {
904                 char *cmd = talloc_sub_advanced(talloc_tos(),
905                                         lp_servicename(SNUM(conn)),
906                                         conn->server_info->unix_name,
907                                         conn->connectpath,
908                                         conn->server_info->utok.gid,
909                                         conn->server_info->sanitized_username,
910                                         pdb_get_domain(conn->server_info->sam_account),
911                                         lp_rootpreexec(snum));
912                 DEBUG(5,("cmd=%s\n",cmd));
913                 ret = smbrun(cmd,NULL);
914                 TALLOC_FREE(cmd);
915                 if (ret != 0 && lp_rootpreexec_close(snum)) {
916                         DEBUG(1,("root preexec gave %d - failing "
917                                  "connection\n", ret));
918                         yield_connection(conn, lp_servicename(snum));
919                         conn_free(conn);
920                         *pstatus = NT_STATUS_ACCESS_DENIED;
921                         return NULL;
922                 }
923         }
924
925 /* USER Activites: */
926         if (!change_to_user(conn, conn->vuid)) {
927                 /* No point continuing if they fail the basic checks */
928                 DEBUG(0,("Can't become connected user!\n"));
929                 yield_connection(conn, lp_servicename(snum));
930                 conn_free(conn);
931                 *pstatus = NT_STATUS_LOGON_FAILURE;
932                 return NULL;
933         }
934
935         /* Remember that a different vuid can connect later without these
936          * checks... */
937         
938         /* Preexecs are done here as they might make the dir we are to ChDir
939          * to below */
940
941         /* execute any "preexec = " line */
942         if (*lp_preexec(snum)) {
943                 char *cmd = talloc_sub_advanced(talloc_tos(),
944                                         lp_servicename(SNUM(conn)),
945                                         conn->server_info->unix_name,
946                                         conn->connectpath,
947                                         conn->server_info->utok.gid,
948                                         conn->server_info->sanitized_username,
949                                         pdb_get_domain(conn->server_info->sam_account),
950                                         lp_preexec(snum));
951                 ret = smbrun(cmd,NULL);
952                 TALLOC_FREE(cmd);
953                 if (ret != 0 && lp_preexec_close(snum)) {
954                         DEBUG(1,("preexec gave %d - failing connection\n",
955                                  ret));
956                         *pstatus = NT_STATUS_ACCESS_DENIED;
957                         goto err_root_exit;
958                 }
959         }
960
961 #ifdef WITH_FAKE_KASERVER
962         if (lp_afs_share(snum)) {
963                 afs_login(conn);
964         }
965 #endif
966         
967         /* Add veto/hide lists */
968         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
969                 set_namearray( &conn->veto_list, lp_veto_files(snum));
970                 set_namearray( &conn->hide_list, lp_hide_files(snum));
971                 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
972                 set_namearray( &conn->aio_write_behind_list,
973                                 lp_aio_write_behind(snum));
974         }
975         
976         /* Invoke VFS make connection hook - do this before the VFS_STAT call
977            to allow any filesystems needing user credentials to initialize
978            themselves. */
979
980         if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
981                             conn->server_info->unix_name) < 0) {
982                 DEBUG(0,("make_connection: VFS make connection failed!\n"));
983                 *pstatus = NT_STATUS_UNSUCCESSFUL;
984                 goto err_root_exit;
985         }
986
987         /* Any error exit after here needs to call the disconnect hook. */
988         on_err_call_dis_hook = true;
989
990         status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
991                                             NULL, NULL, &smb_fname_cpath);
992         if (!NT_STATUS_IS_OK(status)) {
993                 *pstatus = status;
994                 goto err_root_exit;
995         }
996
997         /* win2000 does not check the permissions on the directory
998            during the tree connect, instead relying on permission
999            check during individual operations. To match this behaviour
1000            I have disabled this chdir check (tridge) */
1001         /* the alternative is just to check the directory exists */
1002         if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
1003             !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1004                 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1005                         DEBUG(0,("'%s' is not a directory, when connecting to "
1006                                  "[%s]\n", conn->connectpath,
1007                                  lp_servicename(snum)));
1008                 } else {
1009                         DEBUG(0,("'%s' does not exist or permission denied "
1010                                  "when connecting to [%s] Error was %s\n",
1011                                  conn->connectpath, lp_servicename(snum),
1012                                  strerror(errno) ));
1013                 }
1014                 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1015                 goto err_root_exit;
1016         }
1017
1018         if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
1019                         smb_fname_cpath->st.st_ex_atime.tv_nsec ||
1020                         smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
1021                 /* If any of the normal UNIX directory timestamps
1022                  * have a non-zero tv_nsec component assume
1023                  * we can fully store hires timestamps. We need
1024                  * to make a runtime/share level distinction
1025                  * as on Linux ext3 doesn't have hires timestamps, but
1026                  * ext4 does, so a compile time test won't work. JRA.
1027                  */
1028                 DEBUG(10,("make_connection_snum: hires timestamps "
1029                         "available on share %s, directory %s\n",
1030                         lp_servicename(snum),
1031                         conn->connectpath ));
1032                 conn->hires_timestamps_avail = true;
1033         }
1034
1035         string_set(&conn->origpath,conn->connectpath);
1036
1037 #if SOFTLINK_OPTIMISATION
1038         /* resolve any soft links early if possible */
1039         if (vfs_ChDir(conn,conn->connectpath) == 0) {
1040                 TALLOC_CTX *ctx = talloc_tos();
1041                 char *s = vfs_GetWd(ctx,s);
1042                 if (!s) {
1043                         *status = map_nt_error_from_unix(errno);
1044                         goto err_root_exit;
1045                 }
1046                 if (!set_conn_connectpath(conn,s)) {
1047                         *status = NT_STATUS_NO_MEMORY;
1048                         goto err_root_exit;
1049                 }
1050                 vfs_ChDir(conn,conn->connectpath);
1051         }
1052 #endif
1053
1054         /* Figure out the characteristics of the underlying filesystem. This
1055          * assumes that all the filesystem mounted withing a share path have
1056          * the same characteristics, which is likely but not guaranteed.
1057          */
1058
1059         conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
1060
1061         /*
1062          * Print out the 'connected as' stuff here as we need
1063          * to know the effective uid and gid we will be using
1064          * (at least initially).
1065          */
1066
1067         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1068                 dbgtext( "%s (%s) ", get_remote_machine_name(),
1069                          conn->client_address );
1070                 dbgtext( "%s", srv_is_signing_active(smbd_server_conn) ? "signed " : "");
1071                 dbgtext( "connect to service %s ", lp_servicename(snum) );
1072                 dbgtext( "initially as user %s ",
1073                          conn->server_info->unix_name );
1074                 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1075                 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1076         }
1077
1078         /* we've finished with the user stuff - go back to root */
1079         change_to_root_user();
1080         return(conn);
1081
1082   err_root_exit:
1083         TALLOC_FREE(smb_fname_cpath);
1084         change_to_root_user();
1085         if (on_err_call_dis_hook) {
1086                 /* Call VFS disconnect hook */
1087                 SMB_VFS_DISCONNECT(conn);
1088         }
1089         yield_connection(conn, lp_servicename(snum));
1090         conn_free(conn);
1091         return NULL;
1092 }
1093
1094 /****************************************************************************
1095  Make a connection to a service.
1096  *
1097  * @param service 
1098 ****************************************************************************/
1099
1100 connection_struct *make_connection(struct smbd_server_connection *sconn,
1101                                    const char *service_in, DATA_BLOB password,
1102                                    const char *pdev, uint16 vuid,
1103                                    NTSTATUS *status)
1104 {
1105         uid_t euid;
1106         user_struct *vuser = NULL;
1107         fstring service;
1108         fstring dev;
1109         int snum = -1;
1110         char addr[INET6_ADDRSTRLEN];
1111
1112         fstrcpy(dev, pdev);
1113
1114         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1115          * root. */
1116         if (!non_root_mode() && (euid = geteuid()) != 0) {
1117                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1118                          "(%u)\n", (unsigned int)euid ));
1119                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1120         }
1121
1122         if (conn_num_open(sconn) > 2047) {
1123                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1124                 return NULL;
1125         }
1126
1127         if(lp_security() != SEC_SHARE) {
1128                 vuser = get_valid_user_struct(sconn, vuid);
1129                 if (!vuser) {
1130                         DEBUG(1,("make_connection: refusing to connect with "
1131                                  "no session setup\n"));
1132                         *status = NT_STATUS_ACCESS_DENIED;
1133                         return NULL;
1134                 }
1135         }
1136
1137         /* Logic to try and connect to the correct [homes] share, preferably
1138            without too many getpwnam() lookups.  This is particulary nasty for
1139            winbind usernames, where the share name isn't the same as unix
1140            username.
1141
1142            The snum of the homes share is stored on the vuser at session setup
1143            time.
1144         */
1145
1146         if (strequal(service_in,HOMES_NAME)) {
1147                 if(lp_security() != SEC_SHARE) {
1148                         DATA_BLOB no_pw = data_blob_null;
1149                         if (vuser->homes_snum == -1) {
1150                                 DEBUG(2, ("[homes] share not available for "
1151                                           "this user because it was not found "
1152                                           "or created at session setup "
1153                                           "time\n"));
1154                                 *status = NT_STATUS_BAD_NETWORK_NAME;
1155                                 return NULL;
1156                         }
1157                         DEBUG(5, ("making a connection to [homes] service "
1158                                   "created at session setup time\n"));
1159                         return make_connection_snum(sconn,
1160                                                     vuser->homes_snum,
1161                                                     vuser, no_pw, 
1162                                                     dev, status);
1163                 } else {
1164                         /* Security = share. Try with
1165                          * current_user_info.smb_name as the username.  */
1166                         if (*current_user_info.smb_name) {
1167                                 fstring unix_username;
1168                                 fstrcpy(unix_username,
1169                                         current_user_info.smb_name);
1170                                 map_username(sconn, unix_username);
1171                                 snum = find_service(unix_username);
1172                         } 
1173                         if (snum != -1) {
1174                                 DEBUG(5, ("making a connection to 'homes' "
1175                                           "service %s based on "
1176                                           "security=share\n", service_in));
1177                                 return make_connection_snum(sconn,
1178                                                             snum, NULL,
1179                                                             password,
1180                                                             dev, status);
1181                         }
1182                 }
1183         } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1184                    && strequal(service_in,
1185                                lp_servicename(vuser->homes_snum))) {
1186                 DATA_BLOB no_pw = data_blob_null;
1187                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1188                           "created at session setup time\n", service_in));
1189                 return make_connection_snum(sconn,
1190                                             vuser->homes_snum,
1191                                             vuser, no_pw, 
1192                                             dev, status);
1193         }
1194         
1195         fstrcpy(service, service_in);
1196
1197         strlower_m(service);
1198
1199         snum = find_service(service);
1200
1201         if (snum < 0) {
1202                 if (strequal(service,"IPC$") ||
1203                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1204                         DEBUG(3,("refusing IPC connection to %s\n", service));
1205                         *status = NT_STATUS_ACCESS_DENIED;
1206                         return NULL;
1207                 }
1208
1209                 DEBUG(0,("%s (%s) couldn't find service %s\n",
1210                         get_remote_machine_name(),
1211                         client_addr(get_client_fd(),addr,sizeof(addr)),
1212                         service));
1213                 *status = NT_STATUS_BAD_NETWORK_NAME;
1214                 return NULL;
1215         }
1216
1217         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1218         if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0'))  {
1219                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1220                           "(pointing to %s)\n", 
1221                         service, lp_msdfs_proxy(snum)));
1222                 *status = NT_STATUS_BAD_NETWORK_NAME;
1223                 return NULL;
1224         }
1225
1226         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1227
1228         return make_connection_snum(sconn, snum, vuser,
1229                                     password,
1230                                     dev, status);
1231 }
1232
1233 /****************************************************************************
1234  Close a cnum.
1235 ****************************************************************************/
1236
1237 void close_cnum(connection_struct *conn, uint16 vuid)
1238 {
1239         file_close_conn(conn);
1240
1241         if (!IS_IPC(conn)) {
1242                 dptr_closecnum(conn);
1243         }
1244
1245         change_to_root_user();
1246
1247         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1248                                  get_remote_machine_name(),
1249                                  conn->client_address,
1250                                  lp_servicename(SNUM(conn))));
1251
1252         /* Call VFS disconnect hook */    
1253         SMB_VFS_DISCONNECT(conn);
1254
1255         yield_connection(conn, lp_servicename(SNUM(conn)));
1256
1257         /* make sure we leave the directory available for unmount */
1258         vfs_ChDir(conn, "/");
1259
1260         /* execute any "postexec = " line */
1261         if (*lp_postexec(SNUM(conn)) && 
1262             change_to_user(conn, vuid))  {
1263                 char *cmd = talloc_sub_advanced(talloc_tos(),
1264                                         lp_servicename(SNUM(conn)),
1265                                         conn->server_info->unix_name,
1266                                         conn->connectpath,
1267                                         conn->server_info->utok.gid,
1268                                         conn->server_info->sanitized_username,
1269                                         pdb_get_domain(conn->server_info->sam_account),
1270                                         lp_postexec(SNUM(conn)));
1271                 smbrun(cmd,NULL);
1272                 TALLOC_FREE(cmd);
1273                 change_to_root_user();
1274         }
1275
1276         change_to_root_user();
1277         /* execute any "root postexec = " line */
1278         if (*lp_rootpostexec(SNUM(conn)))  {
1279                 char *cmd = talloc_sub_advanced(talloc_tos(),
1280                                         lp_servicename(SNUM(conn)),
1281                                         conn->server_info->unix_name,
1282                                         conn->connectpath,
1283                                         conn->server_info->utok.gid,
1284                                         conn->server_info->sanitized_username,
1285                                         pdb_get_domain(conn->server_info->sam_account),
1286                                         lp_rootpostexec(SNUM(conn)));
1287                 smbrun(cmd,NULL);
1288                 TALLOC_FREE(cmd);
1289         }
1290
1291         conn_free(conn);
1292 }