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