2 Unix SMB/CIFS implementation.
3 service (connection) opening and closing
4 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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/>.
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"
31 #include "../auth/auth_util.h"
32 #include "lib/param/loadparm.h"
34 #include "lib/afs/afs_funcs.h"
35 #include "lib/util_path.h"
37 static bool canonicalize_connect_path(connection_struct *conn)
40 struct smb_filename con_fname = { .base_name = conn->connectpath };
41 struct smb_filename *resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(),
43 if (resolved_fname == NULL) {
46 ret = set_conn_connectpath(conn,resolved_fname->base_name);
47 TALLOC_FREE(resolved_fname);
51 /****************************************************************************
52 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
53 absolute path stating in / and not ending in /.
54 ****************************************************************************/
56 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
60 if (connectpath == NULL || connectpath[0] == '\0') {
64 destname = canonicalize_absolute_path(conn, connectpath);
65 if (destname == NULL) {
69 DBG_DEBUG("service %s, connectpath = %s\n",
70 lp_const_servicename(SNUM(conn)), destname);
72 talloc_free(conn->connectpath);
73 conn->connectpath = destname;
75 * Ensure conn->cwd_fname is initialized.
76 * start as conn->connectpath.
78 TALLOC_FREE(conn->cwd_fname);
79 conn->cwd_fname = synthetic_smb_fname(conn,
84 if (conn->cwd_fname == NULL) {
90 /****************************************************************************
91 Load parameters specific to a connection/service.
92 ****************************************************************************/
94 void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
97 enum remote_arch_types ra_type;
99 SMB_ASSERT(conn != NULL);
103 if ((conn == last_conn) && (last_flags == flags)) {
111 * Obey the client case sensitivity requests - only for clients that
113 switch (lp_case_sensitive(snum)) {
116 * We need this uglyness due to DOS/Win9x clients that lie
117 * about case insensitivity. */
118 ra_type = get_remote_arch();
119 if (conn->sconn->using_smb2) {
120 conn->case_sensitive = false;
121 } else if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
123 * Client can't support per-packet case sensitive
125 conn->case_sensitive = false;
127 conn->case_sensitive =
128 !(flags & FLAG_CASELESS_PATHNAMES);
132 conn->case_sensitive = true;
135 conn->case_sensitive = false;
141 bool chdir_current_service(connection_struct *conn)
143 const struct smb_filename connectpath_fname = {
144 .base_name = conn->connectpath,
146 const struct smb_filename origpath_fname = {
147 .base_name = conn->origpath,
151 conn->lastused_count++;
153 ret = vfs_ChDir(conn, &connectpath_fname);
155 DEBUG(((errno!=EACCES)?0:3),
156 ("chdir (%s) failed, reason: %s\n",
157 conn->connectpath, strerror(errno)));
161 ret = vfs_ChDir(conn, &origpath_fname);
163 DEBUG(((errno!=EACCES)?0:3),
164 ("chdir (%s) failed, reason: %s\n",
165 conn->origpath, strerror(errno)));
172 /****************************************************************************
173 do some basic sainity checks on the share.
174 This function modifies dev, ecode.
175 ****************************************************************************/
177 static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
184 raddr = tsocket_address_inet_addr_string(remote_address,
187 return NT_STATUS_NO_MEMORY;
190 if (!lp_snum_ok(snum) ||
191 !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
193 return NT_STATUS_ACCESS_DENIED;
196 if (dev[0] == '?' || !dev[0]) {
197 if (lp_printable(snum)) {
198 fstrcpy(dev,"LPT1:");
199 } else if (strequal(lp_fstype(snum), "IPC")) {
206 if (!strupper_m(dev)) {
207 DEBUG(2,("strupper_m %s failed\n", dev));
208 return NT_STATUS_INVALID_PARAMETER;
211 if (lp_printable(snum)) {
212 if (!strequal(dev, "LPT1:")) {
213 return NT_STATUS_BAD_DEVICE_TYPE;
215 } else if (strequal(lp_fstype(snum), "IPC")) {
216 if (!strequal(dev, "IPC")) {
217 return NT_STATUS_BAD_DEVICE_TYPE;
219 } else if (!strequal(dev, "A:")) {
220 return NT_STATUS_BAD_DEVICE_TYPE;
223 /* Behave as a printer if we are supposed to */
224 if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) {
225 fstrcpy(dev, "LPT1:");
232 * Go through lookup_name etc to find the force'd group.
234 * Create a new token from src_token, replacing the primary group sid with the
238 static NTSTATUS find_forced_group(bool force_user,
239 int snum, const char *username,
240 struct dom_sid *pgroup_sid,
243 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
244 TALLOC_CTX *frame = talloc_stackframe();
245 struct dom_sid group_sid;
246 enum lsa_SidType type;
248 bool user_must_be_member = False;
251 groupname = lp_force_group(talloc_tos(), snum);
252 if (groupname == NULL) {
253 DEBUG(1, ("talloc_strdup failed\n"));
254 result = NT_STATUS_NO_MEMORY;
258 if (groupname[0] == '+') {
259 user_must_be_member = True;
263 groupname = talloc_string_sub(talloc_tos(), groupname,
264 "%S", lp_const_servicename(snum));
265 if (groupname == NULL) {
266 DEBUG(1, ("talloc_string_sub failed\n"));
267 result = NT_STATUS_NO_MEMORY;
271 if (!lookup_name_smbconf(talloc_tos(), groupname,
272 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
273 NULL, NULL, &group_sid, &type)) {
274 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
279 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
280 (type != SID_NAME_WKN_GRP)) {
281 DEBUG(10, ("%s is a %s, not a group\n", groupname,
282 sid_type_lookup(type)));
286 if (!sid_to_gid(&group_sid, &gid)) {
287 struct dom_sid_buf buf;
288 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
289 dom_sid_str_buf(&group_sid, &buf), groupname));
294 * If the user has been forced and the forced group starts with a '+',
295 * then we only set the group to be the forced group if the forced
296 * user is a member of that group. Otherwise, the meaning of the '+'
300 if (force_user && user_must_be_member) {
301 if (user_in_group_sid(username, &group_sid)) {
302 sid_copy(pgroup_sid, &group_sid);
304 DEBUG(3,("Forced group %s for member %s\n",
305 groupname, username));
307 DEBUG(0,("find_forced_group: forced user %s is not a member "
308 "of forced group %s. Disallowing access.\n",
309 username, groupname ));
310 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
314 sid_copy(pgroup_sid, &group_sid);
316 DEBUG(3,("Forced group %s\n", groupname));
319 result = NT_STATUS_OK;
325 /****************************************************************************
326 Create an auth_session_info structure for a connection_struct
327 ****************************************************************************/
329 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
330 TALLOC_CTX *mem_ctx, int snum,
331 struct auth_session_info *session_info,
332 struct auth_session_info **presult)
334 struct auth_session_info *result;
336 if (lp_guest_only(snum)) {
337 return make_session_info_guest(mem_ctx, presult);
341 * This is the normal security != share case where we have a
342 * valid vuid from the session setup. */
344 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
345 if (!lp_guest_ok(snum)) {
346 DBG_WARNING("guest user (from session setup) "
347 "not permitted to access this share "
348 "(%s)\n", lp_const_servicename(snum));
349 return NT_STATUS_ACCESS_DENIED;
352 if (!user_ok_token(session_info->unix_info->unix_name,
353 session_info->info->domain_name,
354 session_info->security_token, snum)) {
355 DBG_WARNING("user '%s' (from session setup) not "
356 "permitted to access this share "
358 session_info->unix_info->unix_name,
359 lp_const_servicename(snum));
360 return NT_STATUS_ACCESS_DENIED;
364 result = copy_session_info(mem_ctx, session_info);
365 if (result == NULL) {
366 return NT_STATUS_NO_MEMORY;
373 /****************************************************************************
374 Set relevant user and group settings corresponding to force user/group
375 configuration for the given snum.
376 ****************************************************************************/
378 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
382 if (*lp_force_user(talloc_tos(), snum)) {
385 * Replace conn->session_info with a completely faked up one
386 * from the username we are forced into :-)
390 char *sanitized_username;
391 struct auth_session_info *forced_serverinfo;
394 fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), snum), "%S",
395 lp_const_servicename(snum));
397 return NT_STATUS_NO_MEMORY;
400 guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;
402 status = make_session_info_from_username(
406 if (!NT_STATUS_IS_OK(status)) {
410 /* We don't want to replace the original sanitized_username
411 as it is the original user given in the connect attempt.
412 This is used in '%U' substitutions. */
413 sanitized_username = discard_const_p(char,
414 forced_serverinfo->unix_info->sanitized_username);
415 TALLOC_FREE(sanitized_username);
416 forced_serverinfo->unix_info->sanitized_username =
417 talloc_move(forced_serverinfo->unix_info,
418 &conn->session_info->unix_info->sanitized_username);
420 TALLOC_FREE(conn->session_info);
421 conn->session_info = forced_serverinfo;
423 conn->force_user = true;
424 DEBUG(3,("Forced user %s\n", fuser));
428 * If force group is true, then override
429 * any groupid stored for the connecting user.
432 if (*lp_force_group(talloc_tos(), snum)) {
434 status = find_forced_group(
435 conn->force_user, snum, conn->session_info->unix_info->unix_name,
436 &conn->session_info->security_token->sids[1],
437 &conn->session_info->unix_token->gid);
439 if (!NT_STATUS_IS_OK(status)) {
444 * We need to cache this gid, to use within
445 * change_to_user() separately from the conn->session_info
446 * struct. We only use conn->session_info directly if
447 * "force_user" was set.
449 conn->force_group_gid = conn->session_info->unix_token->gid;
455 static NTSTATUS notify_init_sconn(struct smbd_server_connection *sconn)
459 if (sconn->notify_ctx != NULL) {
463 sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx,
464 sconn, notify_callback);
465 if (sconn->notify_ctx == NULL) {
466 return NT_STATUS_NO_MEMORY;
469 status = messaging_register(sconn->msg_ctx, sconn,
470 MSG_SMB_NOTIFY_CANCEL_DELETED,
471 smbd_notify_cancel_deleted);
472 if (!NT_STATUS_IS_OK(status)) {
473 DBG_DEBUG("messaging_register failed: %s\n",
475 TALLOC_FREE(sconn->notify_ctx);
479 status = messaging_register(sconn->msg_ctx, sconn,
480 MSG_SMB_NOTIFY_STARTED,
481 smbd_notifyd_restarted);
482 if (!NT_STATUS_IS_OK(status)) {
483 DBG_DEBUG("messaging_register failed: %s\n",
485 messaging_deregister(sconn->msg_ctx,
486 MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
487 TALLOC_FREE(sconn->notify_ctx);
494 /****************************************************************************
495 Make a connection, given the snum to connect to, and the vuser of the
496 connecting user if appropriate.
497 ****************************************************************************/
499 static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
500 connection_struct *conn,
501 int snum, struct user_struct *vuser,
504 struct smbd_server_connection *sconn = xconn->client->sconn;
505 struct smb_filename *smb_fname_cpath = NULL;
508 bool on_err_call_dis_hook = false;
515 status = share_sanity_checks(sconn->remote_address,
516 sconn->remote_hostname,
519 if (NT_STATUS_IS_ERR(status)) {
523 conn->params->service = snum;
525 status = create_connection_session_info(sconn,
526 conn, snum, vuser->session_info,
527 &conn->session_info);
529 if (!NT_STATUS_IS_OK(status)) {
530 DEBUG(1, ("create_connection_session_info failed: %s\n",
535 if (lp_guest_only(snum)) {
536 conn->force_user = true;
539 conn->num_files_open = 0;
540 conn->lastused = conn->lastused_count = time(NULL);
541 conn->printer = (strncmp(dev,"LPT",3) == 0);
542 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
543 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
545 /* Case options for the share. */
546 if (lp_case_sensitive(snum) == Auto) {
547 /* We will be setting this per packet. Set to be case
548 * insensitive for now. */
549 conn->case_sensitive = False;
551 conn->case_sensitive = (bool)lp_case_sensitive(snum);
554 conn->case_preserve = lp_preserve_case(snum);
555 conn->short_case_preserve = lp_short_preserve_case(snum);
557 conn->encrypt_level = lp_smb_encrypt(snum);
558 if (conn->encrypt_level > SMB_SIGNING_OFF) {
559 if (lp_smb_encrypt(-1) == SMB_SIGNING_OFF) {
560 if (conn->encrypt_level == SMB_SIGNING_REQUIRED) {
561 DBG_ERR("Service [%s] requires encryption, but "
562 "it is disabled globally!\n",
563 lp_const_servicename(snum));
564 status = NT_STATUS_ACCESS_DENIED;
567 conn->encrypt_level = SMB_SIGNING_OFF;
571 conn->veto_list = NULL;
572 conn->hide_list = NULL;
573 conn->veto_oplock_list = NULL;
574 conn->aio_write_behind_list = NULL;
576 conn->read_only = lp_read_only(SNUM(conn));
578 status = set_conn_force_user_group(conn, snum);
579 if (!NT_STATUS_IS_OK(status)) {
583 conn->vuid = vuser->vuid;
586 char *s = talloc_sub_advanced(talloc_tos(),
587 lp_const_servicename(SNUM(conn)),
588 conn->session_info->unix_info->unix_name,
590 conn->session_info->unix_token->gid,
591 conn->session_info->unix_info->sanitized_username,
592 conn->session_info->info->domain_name,
593 lp_path(talloc_tos(), snum));
595 status = NT_STATUS_NO_MEMORY;
599 if (!set_conn_connectpath(conn,s)) {
601 status = NT_STATUS_NO_MEMORY;
604 DBG_NOTICE("Connect path is '%s' for service [%s]\n", s,
605 lp_const_servicename(snum));
610 * Set up the share security descriptor.
611 * NOTE - we use the *INCOMING USER* session_info
612 * here, as does (indirectly) change_to_user(),
613 * which can be called on any incoming packet.
614 * This way we set up the share access based
615 * on the authenticated user, not the forced
618 * https://bugzilla.samba.org/show_bug.cgi?id=9878
621 status = check_user_share_access(conn,
625 if (!NT_STATUS_IS_OK(status)) {
629 /* Initialise VFS function pointers */
631 if (!smbd_vfs_init(conn)) {
632 DBG_ERR("vfs_init failed for service %s\n",
633 lp_const_servicename(snum));
634 status = NT_STATUS_BAD_NETWORK_NAME;
638 /* ROOT Activities: */
639 /* explicitly check widelinks here so that we can correctly warn
641 widelinks_warning(snum);
644 * Enforce the max connections parameter.
647 if ((lp_max_connections(snum) > 0)
648 && (count_current_connections(lp_const_servicename(SNUM(conn)), true) >=
649 lp_max_connections(snum))) {
651 DBG_WARNING("Max connections (%d) exceeded for %s\n",
652 lp_max_connections(snum),
653 lp_const_servicename(snum));
654 status = NT_STATUS_INSUFFICIENT_RESOURCES;
658 /* Invoke VFS make connection hook - this must be the first
659 filesystem operation that we do. */
661 if (SMB_VFS_CONNECT(conn, lp_const_servicename(snum),
662 conn->session_info->unix_info->unix_name) < 0) {
663 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
664 lp_const_servicename(snum), conn->connectpath,
666 status = NT_STATUS_UNSUCCESSFUL;
670 /* Any error exit after here needs to call the disconnect hook. */
671 on_err_call_dis_hook = true;
673 if ((!conn->printer) && (!conn->ipc) &&
674 lp_change_notify()) {
676 status = notify_init_sconn(sconn);
677 if (!NT_STATUS_IS_OK(status)) {
682 if (lp_kernel_oplocks(snum)) {
683 init_kernel_oplocks(conn->sconn);
687 * Fix compatibility issue pointed out by Volker.
688 * We pass the conn->connectpath to the preexec
689 * scripts as a parameter, so attempt to canonicalize
690 * it here before calling the preexec scripts.
691 * We ignore errors here, as it is possible that
692 * the conn->connectpath doesn't exist yet and
693 * the preexec scripts will create them.
696 (void)canonicalize_connect_path(conn);
698 /* Preexecs are done here as they might make the dir we are to ChDir
700 /* execute any "root preexec = " line */
701 if (*lp_root_preexec(talloc_tos(), snum)) {
702 char *cmd = talloc_sub_advanced(talloc_tos(),
703 lp_const_servicename(SNUM(conn)),
704 conn->session_info->unix_info->unix_name,
706 conn->session_info->unix_token->gid,
707 conn->session_info->unix_info->sanitized_username,
708 conn->session_info->info->domain_name,
709 lp_root_preexec(talloc_tos(), snum));
710 DEBUG(5,("cmd=%s\n",cmd));
711 ret = smbrun(cmd, NULL, NULL);
713 if (ret != 0 && lp_root_preexec_close(snum)) {
714 DEBUG(1,("root preexec gave %d - failing "
715 "connection\n", ret));
716 status = NT_STATUS_ACCESS_DENIED;
721 /* USER Activites: */
722 if (!change_to_user(conn, conn->vuid)) {
723 /* No point continuing if they fail the basic checks */
724 DEBUG(0,("Can't become connected user!\n"));
725 status = NT_STATUS_LOGON_FAILURE;
732 /* Remember that a different vuid can connect later without these
735 /* Preexecs are done here as they might make the dir we are to ChDir
738 /* execute any "preexec = " line */
739 if (*lp_preexec(talloc_tos(), snum)) {
740 char *cmd = talloc_sub_advanced(talloc_tos(),
741 lp_const_servicename(SNUM(conn)),
742 conn->session_info->unix_info->unix_name,
744 conn->session_info->unix_token->gid,
745 conn->session_info->unix_info->sanitized_username,
746 conn->session_info->info->domain_name,
747 lp_preexec(talloc_tos(), snum));
748 ret = smbrun(cmd, NULL, NULL);
750 if (ret != 0 && lp_preexec_close(snum)) {
751 DEBUG(1,("preexec gave %d - failing connection\n",
753 status = NT_STATUS_ACCESS_DENIED;
758 #ifdef WITH_FAKE_KASERVER
759 if (lp_afs_share(snum)) {
765 * we've finished with the user stuff - go back to root
766 * so the SMB_VFS_STAT call will only fail on path errors,
767 * not permission problems.
769 change_to_root_user();
770 /* ROOT Activites: */
773 * If widelinks are disallowed we need to canonicalise the connect
774 * path here to ensure we don't have any symlinks in the
775 * connectpath. We will be checking all paths on this connection are
776 * below this directory. We must do this after the VFS init as we
777 * depend on the realpath() pointer in the vfs table. JRA.
779 if (!lp_widelinks(snum)) {
780 if (!canonicalize_connect_path(conn)) {
781 DBG_ERR("canonicalize_connect_path failed "
782 "for service %s, path %s\n",
783 lp_const_servicename(snum),
785 status = NT_STATUS_BAD_NETWORK_NAME;
790 /* Add veto/hide lists */
791 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
792 set_namearray( &conn->veto_list,
793 lp_veto_files(talloc_tos(), snum));
794 set_namearray( &conn->hide_list,
795 lp_hide_files(talloc_tos(), snum));
796 set_namearray( &conn->veto_oplock_list,
797 lp_veto_oplock_files(talloc_tos(), snum));
798 set_namearray( &conn->aio_write_behind_list,
799 lp_aio_write_behind(talloc_tos(), snum));
801 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
806 if (smb_fname_cpath == NULL) {
807 status = NT_STATUS_NO_MEMORY;
811 /* win2000 does not check the permissions on the directory
812 during the tree connect, instead relying on permission
813 check during individual operations. To match this behaviour
814 I have disabled this chdir check (tridge) */
815 /* the alternative is just to check the directory exists */
817 if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
818 !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
819 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
820 DBG_ERR("'%s' is not a directory, when connecting to "
821 "[%s]\n", conn->connectpath,
822 lp_const_servicename(snum));
824 DBG_ERR("'%s' does not exist or permission denied "
825 "when connecting to [%s] Error was %s\n",
827 lp_const_servicename(snum),
830 status = NT_STATUS_BAD_NETWORK_NAME;
833 conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
835 talloc_free(conn->origpath);
836 conn->origpath = talloc_strdup(conn, conn->connectpath);
838 /* Figure out the characteristics of the underlying filesystem. This
839 * assumes that all the filesystem mounted withing a share path have
840 * the same characteristics, which is likely but not guaranteed.
843 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
846 * Print out the 'connected as' stuff here as we need
847 * to know the effective uid and gid we will be using
848 * (at least initially).
851 if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
852 dbgtext( "%s (%s) ", get_remote_machine_name(),
853 tsocket_address_string(conn->sconn->remote_address,
855 dbgtext( "%s", srv_is_signing_active(xconn) ? "signed " : "");
856 dbgtext( "connect to service %s ",
857 lp_const_servicename(snum) );
858 dbgtext( "initially as user %s ",
859 conn->session_info->unix_info->unix_name );
860 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
861 dbgtext( "(pid %d)\n", (int)getpid() );
864 conn->tcon_done = true;
869 TALLOC_FREE(smb_fname_cpath);
870 /* We must exit this function as root. */
871 if (geteuid() != 0) {
872 change_to_root_user();
874 if (on_err_call_dis_hook) {
875 /* Call VFS disconnect hook */
876 SMB_VFS_DISCONNECT(conn);
881 /****************************************************************************
882 Make a connection to a service from SMB1. Internal interface.
883 ****************************************************************************/
885 static connection_struct *make_connection_smb1(struct smb_request *req,
887 int snum, struct user_struct *vuser,
891 struct smbXsrv_tcon *tcon;
893 struct connection_struct *conn;
895 status = smb1srv_tcon_create(req->xconn, now, &tcon);
896 if (!NT_STATUS_IS_OK(status)) {
897 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
903 conn = conn_new(req->sconn);
907 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
908 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
912 conn->cnum = tcon->global->tcon_wire_id;
915 *pstatus = make_connection_snum(req->xconn,
920 if (!NT_STATUS_IS_OK(*pstatus)) {
926 tcon->global->share_name = lp_servicename(tcon->global, SNUM(conn));
927 if (tcon->global->share_name == NULL) {
930 *pstatus = NT_STATUS_NO_MEMORY;
933 tcon->global->session_global_id =
934 vuser->session->global->session_global_id;
936 tcon->compat = talloc_move(tcon, &conn);
937 tcon->status = NT_STATUS_OK;
939 *pstatus = smbXsrv_tcon_update(tcon);
940 if (!NT_STATUS_IS_OK(*pstatus)) {
948 /****************************************************************************
949 Make a connection to a service from SMB2. External SMB2 interface.
950 We must set cnum before claiming connection.
951 ****************************************************************************/
953 connection_struct *make_connection_smb2(struct smbd_smb2_request *req,
954 struct smbXsrv_tcon *tcon,
956 struct user_struct *vuser,
960 struct smbd_server_connection *sconn = req->sconn;
961 connection_struct *conn = conn_new(sconn);
963 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
964 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
968 conn->cnum = tcon->global->tcon_wire_id;
971 *pstatus = make_connection_snum(req->xconn,
976 if (!NT_STATUS_IS_OK(*pstatus)) {
983 /****************************************************************************
984 Make a connection to a service. External SMB1 interface.
987 ****************************************************************************/
989 connection_struct *make_connection(struct smb_request *req,
991 const char *service_in,
992 const char *pdev, uint64_t vuid,
995 struct smbd_server_connection *sconn = req->sconn;
997 struct user_struct *vuser = NULL;
998 char *service = NULL;
1004 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1006 if (!non_root_mode() && (euid = geteuid()) != 0) {
1007 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1008 "(%u)\n", (unsigned int)euid ));
1009 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1012 if (conn_num_open(sconn) > 2047) {
1013 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1017 vuser = get_valid_user_struct(sconn, vuid);
1019 DEBUG(1,("make_connection: refusing to connect with "
1020 "no session setup\n"));
1021 *status = NT_STATUS_ACCESS_DENIED;
1025 /* Logic to try and connect to the correct [homes] share, preferably
1026 without too many getpwnam() lookups. This is particulary nasty for
1027 winbind usernames, where the share name isn't the same as unix
1030 The snum of the homes share is stored on the vuser at session setup
1034 if (strequal(service_in,HOMES_NAME)) {
1035 if (vuser->homes_snum == -1) {
1036 DEBUG(2, ("[homes] share not available for "
1037 "this user because it was not found "
1038 "or created at session setup "
1040 *status = NT_STATUS_BAD_NETWORK_NAME;
1043 DEBUG(5, ("making a connection to [homes] service "
1044 "created at session setup time\n"));
1045 return make_connection_smb1(req, now,
1049 } else if ((vuser->homes_snum != -1)
1050 && strequal(service_in,
1051 lp_const_servicename(vuser->homes_snum))) {
1052 DEBUG(5, ("making a connection to 'homes' service [%s] "
1053 "created at session setup time\n", service_in));
1054 return make_connection_smb1(req, now,
1060 service = talloc_strdup(talloc_tos(), service_in);
1062 *status = NT_STATUS_NO_MEMORY;
1066 if (!strlower_m(service)) {
1067 DEBUG(2, ("strlower_m %s failed\n", service));
1068 *status = NT_STATUS_INVALID_PARAMETER;
1072 snum = find_service(talloc_tos(), service, &service);
1074 *status = NT_STATUS_NO_MEMORY;
1079 if (strequal(service,"IPC$") ||
1080 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1081 DEBUG(3,("refusing IPC connection to %s\n", service));
1082 *status = NT_STATUS_ACCESS_DENIED;
1086 DEBUG(3,("%s (%s) couldn't find service %s\n",
1087 get_remote_machine_name(),
1088 tsocket_address_string(
1089 sconn->remote_address, talloc_tos()),
1091 *status = NT_STATUS_BAD_NETWORK_NAME;
1095 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1096 if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), snum) != '\0')) {
1097 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1098 "(pointing to %s)\n",
1099 service, lp_msdfs_proxy(talloc_tos(), snum)));
1100 *status = NT_STATUS_BAD_NETWORK_NAME;
1104 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1106 return make_connection_smb1(req, now, snum, vuser,
1110 /****************************************************************************
1112 ****************************************************************************/
1114 void close_cnum(connection_struct *conn, uint64_t vuid)
1116 char rootpath[2] = { '/', '\0'};
1117 struct smb_filename root_fname = { .base_name = rootpath };
1119 file_close_conn(conn);
1121 if (!IS_IPC(conn)) {
1122 dptr_closecnum(conn);
1125 change_to_root_user();
1127 DEBUG(IS_IPC(conn)?3:2, ("%s (%s) closed connection to service %s\n",
1128 get_remote_machine_name(),
1129 tsocket_address_string(conn->sconn->remote_address,
1131 lp_const_servicename(SNUM(conn))));
1133 /* make sure we leave the directory available for unmount */
1134 vfs_ChDir(conn, &root_fname);
1136 /* Call VFS disconnect hook */
1137 SMB_VFS_DISCONNECT(conn);
1139 /* execute any "postexec = " line */
1140 if (*lp_postexec(talloc_tos(), SNUM(conn)) &&
1141 change_to_user(conn, vuid)) {
1142 char *cmd = talloc_sub_advanced(talloc_tos(),
1143 lp_const_servicename(SNUM(conn)),
1144 conn->session_info->unix_info->unix_name,
1146 conn->session_info->unix_token->gid,
1147 conn->session_info->unix_info->sanitized_username,
1148 conn->session_info->info->domain_name,
1149 lp_postexec(talloc_tos(), SNUM(conn)));
1150 smbrun(cmd, NULL, NULL);
1152 change_to_root_user();
1155 change_to_root_user();
1156 /* execute any "root postexec = " line */
1157 if (*lp_root_postexec(talloc_tos(), SNUM(conn))) {
1158 char *cmd = talloc_sub_advanced(talloc_tos(),
1159 lp_const_servicename(SNUM(conn)),
1160 conn->session_info->unix_info->unix_name,
1162 conn->session_info->unix_token->gid,
1163 conn->session_info->unix_info->sanitized_username,
1164 conn->session_info->info->domain_name,
1165 lp_root_postexec(talloc_tos(), SNUM(conn)));
1166 smbrun(cmd, NULL, NULL);