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