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