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