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