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