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