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