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_fsp->fsp_name is initialized.
76 * start as conn->connectpath.
78 TALLOC_FREE(conn->cwd_fsp->fsp_name);
79 conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn,
84 if (conn->cwd_fsp->fsp_name == 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 int saved_errno = errno;
157 if (saved_errno == EACCES) {
158 char *str = utok_string(
160 conn->session_info->unix_token);
161 DBG_WARNING("vfs_ChDir(%s) got "
162 "permission denied, current "
164 conn->connectpath, str);
167 DBG_ERR("vfs_ChDir(%s) failed: "
170 strerror(saved_errno));
175 ret = vfs_ChDir(conn, &origpath_fname);
177 int saved_errno = errno;
179 if (saved_errno == EACCES) {
180 char *str = utok_string(
182 conn->session_info->unix_token);
183 DBG_WARNING("vfs_ChDir(%s) got "
184 "permission denied, current "
186 conn->origpath, str);
189 DBG_ERR("vfs_ChDir(%s) failed: "
192 strerror(saved_errno));
200 /****************************************************************************
201 do some basic sainity checks on the share.
202 This function modifies dev, ecode.
203 ****************************************************************************/
205 static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
212 raddr = tsocket_address_inet_addr_string(remote_address,
215 return NT_STATUS_NO_MEMORY;
218 if (!lp_snum_ok(snum) ||
219 !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
221 return NT_STATUS_ACCESS_DENIED;
224 if (dev[0] == '?' || !dev[0]) {
225 if (lp_printable(snum)) {
226 fstrcpy(dev,"LPT1:");
227 } else if (strequal(lp_fstype(snum), "IPC")) {
234 if (!strupper_m(dev)) {
235 DEBUG(2,("strupper_m %s failed\n", dev));
236 return NT_STATUS_INVALID_PARAMETER;
239 if (lp_printable(snum)) {
240 if (!strequal(dev, "LPT1:")) {
241 return NT_STATUS_BAD_DEVICE_TYPE;
243 } else if (strequal(lp_fstype(snum), "IPC")) {
244 if (!strequal(dev, "IPC")) {
245 return NT_STATUS_BAD_DEVICE_TYPE;
247 } else if (!strequal(dev, "A:")) {
248 return NT_STATUS_BAD_DEVICE_TYPE;
251 /* Behave as a printer if we are supposed to */
252 if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) {
253 fstrcpy(dev, "LPT1:");
260 * Go through lookup_name etc to find the force'd group.
262 * Create a new token from src_token, replacing the primary group sid with the
266 static NTSTATUS find_forced_group(bool force_user,
267 int snum, const char *username,
268 struct dom_sid *pgroup_sid,
271 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
272 TALLOC_CTX *frame = talloc_stackframe();
273 const struct loadparm_substitution *lp_sub =
274 loadparm_s3_global_substitution();
275 struct dom_sid group_sid;
276 enum lsa_SidType type;
278 bool user_must_be_member = False;
281 groupname = lp_force_group(talloc_tos(), lp_sub, snum);
282 if (groupname == NULL) {
283 DEBUG(1, ("talloc_strdup failed\n"));
284 result = NT_STATUS_NO_MEMORY;
288 if (groupname[0] == '+') {
289 user_must_be_member = True;
293 groupname = talloc_string_sub(talloc_tos(), groupname,
294 "%S", lp_const_servicename(snum));
295 if (groupname == NULL) {
296 DEBUG(1, ("talloc_string_sub failed\n"));
297 result = NT_STATUS_NO_MEMORY;
301 if (!lookup_name_smbconf(talloc_tos(), groupname,
302 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
303 NULL, NULL, &group_sid, &type)) {
304 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
309 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
310 (type != SID_NAME_WKN_GRP)) {
311 DEBUG(10, ("%s is a %s, not a group\n", groupname,
312 sid_type_lookup(type)));
316 if (!sid_to_gid(&group_sid, &gid)) {
317 struct dom_sid_buf buf;
318 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
319 dom_sid_str_buf(&group_sid, &buf), groupname));
324 * If the user has been forced and the forced group starts with a '+',
325 * then we only set the group to be the forced group if the forced
326 * user is a member of that group. Otherwise, the meaning of the '+'
330 if (force_user && user_must_be_member) {
331 if (user_in_group_sid(username, &group_sid)) {
332 sid_copy(pgroup_sid, &group_sid);
334 DEBUG(3,("Forced group %s for member %s\n",
335 groupname, username));
337 DEBUG(0,("find_forced_group: forced user %s is not a member "
338 "of forced group %s. Disallowing access.\n",
339 username, groupname ));
340 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
344 sid_copy(pgroup_sid, &group_sid);
346 DEBUG(3,("Forced group %s\n", groupname));
349 result = NT_STATUS_OK;
355 /****************************************************************************
356 Create an auth_session_info structure for a connection_struct
357 ****************************************************************************/
359 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
360 TALLOC_CTX *mem_ctx, int snum,
361 struct auth_session_info *session_info,
362 struct auth_session_info **presult)
364 struct auth_session_info *result;
366 if (lp_guest_only(snum)) {
367 return make_session_info_guest(mem_ctx, presult);
371 * This is the normal security != share case where we have a
372 * valid vuid from the session setup. */
374 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
375 if (!lp_guest_ok(snum)) {
376 DBG_WARNING("guest user (from session setup) "
377 "not permitted to access this share "
378 "(%s)\n", lp_const_servicename(snum));
379 return NT_STATUS_ACCESS_DENIED;
382 if (!user_ok_token(session_info->unix_info->unix_name,
383 session_info->info->domain_name,
384 session_info->security_token, snum)) {
385 DBG_WARNING("user '%s' (from session setup) not "
386 "permitted to access this share "
388 session_info->unix_info->unix_name,
389 lp_const_servicename(snum));
390 return NT_STATUS_ACCESS_DENIED;
394 result = copy_session_info(mem_ctx, session_info);
395 if (result == NULL) {
396 return NT_STATUS_NO_MEMORY;
403 /****************************************************************************
404 Set relevant user and group settings corresponding to force user/group
405 configuration for the given snum.
406 ****************************************************************************/
408 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
410 const struct loadparm_substitution *lp_sub =
411 loadparm_s3_global_substitution();
414 if (*lp_force_user(talloc_tos(), lp_sub, snum)) {
417 * Replace conn->session_info with a completely faked up one
418 * from the username we are forced into :-)
422 char *sanitized_username;
423 struct auth_session_info *forced_serverinfo;
426 fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), lp_sub, snum), "%S",
427 lp_const_servicename(snum));
429 return NT_STATUS_NO_MEMORY;
432 guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;
434 status = make_session_info_from_username(
438 if (!NT_STATUS_IS_OK(status)) {
442 /* We don't want to replace the original sanitized_username
443 as it is the original user given in the connect attempt.
444 This is used in '%U' substitutions. */
445 sanitized_username = discard_const_p(char,
446 forced_serverinfo->unix_info->sanitized_username);
447 TALLOC_FREE(sanitized_username);
448 forced_serverinfo->unix_info->sanitized_username =
449 talloc_move(forced_serverinfo->unix_info,
450 &conn->session_info->unix_info->sanitized_username);
452 TALLOC_FREE(conn->session_info);
453 conn->session_info = forced_serverinfo;
455 conn->force_user = true;
456 DEBUG(3,("Forced user %s\n", fuser));
460 * If force group is true, then override
461 * any groupid stored for the connecting user.
464 if (*lp_force_group(talloc_tos(), lp_sub, snum)) {
466 status = find_forced_group(
467 conn->force_user, snum, conn->session_info->unix_info->unix_name,
468 &conn->session_info->security_token->sids[1],
469 &conn->session_info->unix_token->gid);
471 if (!NT_STATUS_IS_OK(status)) {
476 * We need to cache this gid, to use within
477 * change_to_user() separately from the conn->session_info
478 * struct. We only use conn->session_info directly if
479 * "force_user" was set.
481 conn->force_group_gid = conn->session_info->unix_token->gid;
487 static NTSTATUS notify_init_sconn(struct smbd_server_connection *sconn)
491 if (sconn->notify_ctx != NULL) {
495 sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx,
496 sconn, notify_callback);
497 if (sconn->notify_ctx == NULL) {
498 return NT_STATUS_NO_MEMORY;
501 status = messaging_register(sconn->msg_ctx, sconn,
502 MSG_SMB_NOTIFY_CANCEL_DELETED,
503 smbd_notify_cancel_deleted);
504 if (!NT_STATUS_IS_OK(status)) {
505 DBG_DEBUG("messaging_register failed: %s\n",
507 TALLOC_FREE(sconn->notify_ctx);
511 status = messaging_register(sconn->msg_ctx, sconn,
512 MSG_SMB_NOTIFY_STARTED,
513 smbd_notifyd_restarted);
514 if (!NT_STATUS_IS_OK(status)) {
515 DBG_DEBUG("messaging_register failed: %s\n",
517 messaging_deregister(sconn->msg_ctx,
518 MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
519 TALLOC_FREE(sconn->notify_ctx);
526 /****************************************************************************
527 Make a connection, given the snum to connect to, and the vuser of the
528 connecting user if appropriate.
529 ****************************************************************************/
531 static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
532 connection_struct *conn,
533 int snum, struct user_struct *vuser,
536 struct smbd_server_connection *sconn = xconn->client->sconn;
537 const struct loadparm_substitution *lp_sub =
538 loadparm_s3_global_substitution();
539 struct smb_filename *smb_fname_cpath = NULL;
542 bool on_err_call_dis_hook = false;
549 status = share_sanity_checks(sconn->remote_address,
550 sconn->remote_hostname,
553 if (NT_STATUS_IS_ERR(status)) {
557 conn->params->service = snum;
559 status = create_connection_session_info(sconn,
560 conn, snum, vuser->session_info,
561 &conn->session_info);
563 if (!NT_STATUS_IS_OK(status)) {
564 DEBUG(1, ("create_connection_session_info failed: %s\n",
569 if (lp_guest_only(snum)) {
570 conn->force_user = true;
573 conn->num_files_open = 0;
574 conn->lastused = conn->lastused_count = time(NULL);
575 conn->printer = (strncmp(dev,"LPT",3) == 0);
576 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
577 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
579 /* Case options for the share. */
580 if (lp_case_sensitive(snum) == Auto) {
581 /* We will be setting this per packet. Set to be case
582 * insensitive for now. */
583 conn->case_sensitive = False;
585 conn->case_sensitive = (bool)lp_case_sensitive(snum);
588 conn->case_preserve = lp_preserve_case(snum);
589 conn->short_case_preserve = lp_short_preserve_case(snum);
591 conn->encrypt_level = lp_smb_encrypt(snum);
592 if (conn->encrypt_level > SMB_SIGNING_OFF) {
593 if (lp_smb_encrypt(-1) == SMB_SIGNING_OFF) {
594 if (conn->encrypt_level == SMB_SIGNING_REQUIRED) {
595 DBG_ERR("Service [%s] requires encryption, but "
596 "it is disabled globally!\n",
597 lp_const_servicename(snum));
598 status = NT_STATUS_ACCESS_DENIED;
601 conn->encrypt_level = SMB_SIGNING_OFF;
605 conn->veto_list = NULL;
606 conn->hide_list = NULL;
607 conn->veto_oplock_list = NULL;
608 conn->aio_write_behind_list = NULL;
610 conn->read_only = lp_read_only(SNUM(conn));
612 status = set_conn_force_user_group(conn, snum);
613 if (!NT_STATUS_IS_OK(status)) {
617 conn->vuid = vuser->vuid;
620 char *s = talloc_sub_full(talloc_tos(),
621 lp_const_servicename(SNUM(conn)),
622 conn->session_info->unix_info->unix_name,
624 conn->session_info->unix_token->gid,
625 conn->session_info->unix_info->sanitized_username,
626 conn->session_info->info->domain_name,
627 lp_path(talloc_tos(), lp_sub, snum));
629 status = NT_STATUS_NO_MEMORY;
633 if (!set_conn_connectpath(conn,s)) {
635 status = NT_STATUS_NO_MEMORY;
638 DBG_NOTICE("Connect path is '%s' for service [%s]\n", s,
639 lp_const_servicename(snum));
644 * Set up the share security descriptor.
645 * NOTE - we use the *INCOMING USER* session_info
646 * here, as does (indirectly) change_to_user(),
647 * which can be called on any incoming packet.
648 * This way we set up the share access based
649 * on the authenticated user, not the forced
652 * https://bugzilla.samba.org/show_bug.cgi?id=9878
655 status = check_user_share_access(conn,
659 if (!NT_STATUS_IS_OK(status)) {
663 /* Initialise VFS function pointers */
665 if (!smbd_vfs_init(conn)) {
666 DBG_ERR("vfs_init failed for service %s\n",
667 lp_const_servicename(snum));
668 status = NT_STATUS_BAD_NETWORK_NAME;
672 /* ROOT Activities: */
673 /* explicitly check widelinks here so that we can correctly warn
675 widelinks_warning(snum);
678 * Enforce the max connections parameter.
681 if ((lp_max_connections(snum) > 0)
682 && (count_current_connections(lp_const_servicename(SNUM(conn)), true) >=
683 lp_max_connections(snum))) {
685 DBG_WARNING("Max connections (%d) exceeded for %s\n",
686 lp_max_connections(snum),
687 lp_const_servicename(snum));
688 status = NT_STATUS_INSUFFICIENT_RESOURCES;
692 /* Invoke VFS make connection hook - this must be the first
693 filesystem operation that we do. */
695 if (SMB_VFS_CONNECT(conn, lp_const_servicename(snum),
696 conn->session_info->unix_info->unix_name) < 0) {
697 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
698 lp_const_servicename(snum), conn->connectpath,
700 status = NT_STATUS_UNSUCCESSFUL;
704 /* Any error exit after here needs to call the disconnect hook. */
705 on_err_call_dis_hook = true;
707 if ((!conn->printer) && (!conn->ipc) &&
708 lp_change_notify()) {
710 status = notify_init_sconn(sconn);
711 if (!NT_STATUS_IS_OK(status)) {
716 if (lp_kernel_oplocks(snum)) {
717 init_kernel_oplocks(conn->sconn);
721 * Fix compatibility issue pointed out by Volker.
722 * We pass the conn->connectpath to the preexec
723 * scripts as a parameter, so attempt to canonicalize
724 * it here before calling the preexec scripts.
725 * We ignore errors here, as it is possible that
726 * the conn->connectpath doesn't exist yet and
727 * the preexec scripts will create them.
730 (void)canonicalize_connect_path(conn);
732 /* Preexecs are done here as they might make the dir we are to ChDir
734 /* execute any "root preexec = " line */
735 if (*lp_root_preexec(talloc_tos(), lp_sub, snum)) {
736 char *cmd = talloc_sub_full(talloc_tos(),
737 lp_const_servicename(SNUM(conn)),
738 conn->session_info->unix_info->unix_name,
740 conn->session_info->unix_token->gid,
741 conn->session_info->unix_info->sanitized_username,
742 conn->session_info->info->domain_name,
743 lp_root_preexec(talloc_tos(), lp_sub, snum));
744 DEBUG(5,("cmd=%s\n",cmd));
745 ret = smbrun(cmd, NULL, NULL);
747 if (ret != 0 && lp_root_preexec_close(snum)) {
748 DEBUG(1,("root preexec gave %d - failing "
749 "connection\n", ret));
750 status = NT_STATUS_ACCESS_DENIED;
755 /* USER Activites: */
756 if (!change_to_user_and_service(conn, conn->vuid)) {
757 /* No point continuing if they fail the basic checks */
758 DEBUG(0,("Can't become connected user!\n"));
759 status = NT_STATUS_LOGON_FAILURE;
766 /* Remember that a different vuid can connect later without these
769 /* Preexecs are done here as they might make the dir we are to ChDir
772 /* execute any "preexec = " line */
773 if (*lp_preexec(talloc_tos(), lp_sub, snum)) {
774 char *cmd = talloc_sub_full(talloc_tos(),
775 lp_const_servicename(SNUM(conn)),
776 conn->session_info->unix_info->unix_name,
778 conn->session_info->unix_token->gid,
779 conn->session_info->unix_info->sanitized_username,
780 conn->session_info->info->domain_name,
781 lp_preexec(talloc_tos(), lp_sub, snum));
782 ret = smbrun(cmd, NULL, NULL);
784 if (ret != 0 && lp_preexec_close(snum)) {
785 DEBUG(1,("preexec gave %d - failing connection\n",
787 status = NT_STATUS_ACCESS_DENIED;
792 #ifdef WITH_FAKE_KASERVER
793 if (lp_afs_share(snum)) {
799 * we've finished with the user stuff - go back to root
800 * so the SMB_VFS_STAT call will only fail on path errors,
801 * not permission problems.
803 change_to_root_user();
804 /* ROOT Activites: */
807 * If widelinks are disallowed we need to canonicalise the connect
808 * path here to ensure we don't have any symlinks in the
809 * connectpath. We will be checking all paths on this connection are
810 * below this directory. We must do this after the VFS init as we
811 * depend on the realpath() pointer in the vfs table. JRA.
813 if (!lp_widelinks(snum)) {
814 if (!canonicalize_connect_path(conn)) {
815 DBG_ERR("canonicalize_connect_path failed "
816 "for service %s, path %s\n",
817 lp_const_servicename(snum),
819 status = NT_STATUS_BAD_NETWORK_NAME;
824 /* Add veto/hide lists */
825 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
826 set_namearray( &conn->veto_list,
827 lp_veto_files(talloc_tos(), lp_sub, snum));
828 set_namearray( &conn->hide_list,
829 lp_hide_files(talloc_tos(), lp_sub, snum));
830 set_namearray( &conn->veto_oplock_list,
831 lp_veto_oplock_files(talloc_tos(), lp_sub, snum));
832 set_namearray( &conn->aio_write_behind_list,
833 lp_aio_write_behind(talloc_tos(), lp_sub, snum));
835 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
840 if (smb_fname_cpath == NULL) {
841 status = NT_STATUS_NO_MEMORY;
845 /* win2000 does not check the permissions on the directory
846 during the tree connect, instead relying on permission
847 check during individual operations. To match this behaviour
848 I have disabled this chdir check (tridge) */
849 /* the alternative is just to check the directory exists */
851 if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
852 !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
853 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
854 DBG_ERR("'%s' is not a directory, when connecting to "
855 "[%s]\n", conn->connectpath,
856 lp_const_servicename(snum));
858 DBG_ERR("'%s' does not exist or permission denied "
859 "when connecting to [%s] Error was %s\n",
861 lp_const_servicename(snum),
864 status = NT_STATUS_BAD_NETWORK_NAME;
867 conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
869 talloc_free(conn->origpath);
870 conn->origpath = talloc_strdup(conn, conn->connectpath);
872 /* Figure out the characteristics of the underlying filesystem. This
873 * assumes that all the filesystem mounted within a share path have
874 * the same characteristics, which is likely but not guaranteed.
877 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
880 * Print out the 'connected as' stuff here as we need
881 * to know the effective uid and gid we will be using
882 * (at least initially).
885 if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
886 dbgtext( "%s (%s) ", get_remote_machine_name(),
887 tsocket_address_string(conn->sconn->remote_address,
889 dbgtext( "%s", srv_is_signing_active(xconn) ? "signed " : "");
890 dbgtext( "connect to service %s ",
891 lp_const_servicename(snum) );
892 dbgtext( "initially as user %s ",
893 conn->session_info->unix_info->unix_name );
894 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
895 dbgtext( "(pid %d)\n", (int)getpid() );
898 conn->tcon_done = true;
903 TALLOC_FREE(smb_fname_cpath);
904 /* We must exit this function as root. */
905 if (geteuid() != 0) {
906 change_to_root_user();
908 if (on_err_call_dis_hook) {
909 /* Call VFS disconnect hook */
910 SMB_VFS_DISCONNECT(conn);
915 /****************************************************************************
916 Make a connection to a service from SMB1. Internal interface.
917 ****************************************************************************/
919 static connection_struct *make_connection_smb1(struct smb_request *req,
921 int snum, struct user_struct *vuser,
925 const struct loadparm_substitution *lp_sub =
926 loadparm_s3_global_substitution();
927 struct smbXsrv_tcon *tcon;
929 struct connection_struct *conn;
931 status = smb1srv_tcon_create(req->xconn, now, &tcon);
932 if (!NT_STATUS_IS_OK(status)) {
933 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
939 conn = conn_new(req->sconn);
943 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
944 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
948 conn->cnum = tcon->global->tcon_wire_id;
951 *pstatus = make_connection_snum(req->xconn,
956 if (!NT_STATUS_IS_OK(*pstatus)) {
962 tcon->global->share_name = lp_servicename(tcon->global, lp_sub, SNUM(conn));
963 if (tcon->global->share_name == NULL) {
966 *pstatus = NT_STATUS_NO_MEMORY;
969 tcon->global->session_global_id =
970 vuser->session->global->session_global_id;
972 tcon->compat = talloc_move(tcon, &conn);
973 tcon->status = NT_STATUS_OK;
975 *pstatus = smbXsrv_tcon_update(tcon);
976 if (!NT_STATUS_IS_OK(*pstatus)) {
984 /****************************************************************************
985 Make a connection to a service from SMB2. External SMB2 interface.
986 We must set cnum before claiming connection.
987 ****************************************************************************/
989 connection_struct *make_connection_smb2(struct smbd_smb2_request *req,
990 struct smbXsrv_tcon *tcon,
992 struct user_struct *vuser,
996 struct smbd_server_connection *sconn = req->sconn;
997 connection_struct *conn = conn_new(sconn);
999 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
1000 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
1004 conn->cnum = tcon->global->tcon_wire_id;
1007 *pstatus = make_connection_snum(req->xconn,
1012 if (!NT_STATUS_IS_OK(*pstatus)) {
1019 /****************************************************************************
1020 Make a connection to a service. External SMB1 interface.
1023 ****************************************************************************/
1025 connection_struct *make_connection(struct smb_request *req,
1027 const char *service_in,
1028 const char *pdev, uint64_t vuid,
1031 struct smbd_server_connection *sconn = req->sconn;
1032 const struct loadparm_substitution *lp_sub =
1033 loadparm_s3_global_substitution();
1035 struct user_struct *vuser = NULL;
1036 char *service = NULL;
1042 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1044 if (!non_root_mode() && (euid = geteuid()) != 0) {
1045 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1046 "(%u)\n", (unsigned int)euid ));
1047 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1050 if (conn_num_open(sconn) > 2047) {
1051 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1055 vuser = get_valid_user_struct(sconn, vuid);
1057 DEBUG(1,("make_connection: refusing to connect with "
1058 "no session setup\n"));
1059 *status = NT_STATUS_ACCESS_DENIED;
1063 /* Logic to try and connect to the correct [homes] share, preferably
1064 without too many getpwnam() lookups. This is particulary nasty for
1065 winbind usernames, where the share name isn't the same as unix
1068 The snum of the homes share is stored on the vuser at session setup
1072 if (strequal(service_in,HOMES_NAME)) {
1073 if (vuser->homes_snum == -1) {
1074 DEBUG(2, ("[homes] share not available for "
1075 "this user because it was not found "
1076 "or created at session setup "
1078 *status = NT_STATUS_BAD_NETWORK_NAME;
1081 DEBUG(5, ("making a connection to [homes] service "
1082 "created at session setup time\n"));
1083 return make_connection_smb1(req, now,
1087 } else if ((vuser->homes_snum != -1)
1088 && strequal(service_in,
1089 lp_const_servicename(vuser->homes_snum))) {
1090 DEBUG(5, ("making a connection to 'homes' service [%s] "
1091 "created at session setup time\n", service_in));
1092 return make_connection_smb1(req, now,
1098 service = talloc_strdup(talloc_tos(), service_in);
1100 *status = NT_STATUS_NO_MEMORY;
1104 if (!strlower_m(service)) {
1105 DEBUG(2, ("strlower_m %s failed\n", service));
1106 *status = NT_STATUS_INVALID_PARAMETER;
1110 snum = find_service(talloc_tos(), service, &service);
1112 *status = NT_STATUS_NO_MEMORY;
1117 if (strequal(service,"IPC$") ||
1118 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1119 DEBUG(3,("refusing IPC connection to %s\n", service));
1120 *status = NT_STATUS_ACCESS_DENIED;
1124 DEBUG(3,("%s (%s) couldn't find service %s\n",
1125 get_remote_machine_name(),
1126 tsocket_address_string(
1127 sconn->remote_address, talloc_tos()),
1129 *status = NT_STATUS_BAD_NETWORK_NAME;
1133 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1134 if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), lp_sub, snum) != '\0')) {
1135 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1136 "(pointing to %s)\n",
1137 service, lp_msdfs_proxy(talloc_tos(), lp_sub, snum)));
1138 *status = NT_STATUS_BAD_NETWORK_NAME;
1142 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1144 return make_connection_smb1(req, now, snum, vuser,
1148 /****************************************************************************
1150 ****************************************************************************/
1152 void close_cnum(connection_struct *conn, uint64_t vuid)
1154 char rootpath[2] = { '/', '\0'};
1155 struct smb_filename root_fname = { .base_name = rootpath };
1156 const struct loadparm_substitution *lp_sub =
1157 loadparm_s3_global_substitution();
1159 file_close_conn(conn);
1161 change_to_root_user();
1163 DEBUG(IS_IPC(conn)?3:2, ("%s (%s) closed connection to service %s\n",
1164 get_remote_machine_name(),
1165 tsocket_address_string(conn->sconn->remote_address,
1167 lp_const_servicename(SNUM(conn))));
1169 /* make sure we leave the directory available for unmount */
1170 vfs_ChDir(conn, &root_fname);
1172 /* Call VFS disconnect hook */
1173 SMB_VFS_DISCONNECT(conn);
1175 /* execute any "postexec = " line */
1176 if (*lp_postexec(talloc_tos(), lp_sub, SNUM(conn)) &&
1177 change_to_user_and_service(conn, vuid)) {
1178 char *cmd = talloc_sub_full(talloc_tos(),
1179 lp_const_servicename(SNUM(conn)),
1180 conn->session_info->unix_info->unix_name,
1182 conn->session_info->unix_token->gid,
1183 conn->session_info->unix_info->sanitized_username,
1184 conn->session_info->info->domain_name,
1185 lp_postexec(talloc_tos(), lp_sub, SNUM(conn)));
1186 smbrun(cmd, NULL, NULL);
1188 change_to_root_user();
1191 change_to_root_user();
1192 /* execute any "root postexec = " line */
1193 if (*lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn))) {
1194 char *cmd = talloc_sub_full(talloc_tos(),
1195 lp_const_servicename(SNUM(conn)),
1196 conn->session_info->unix_info->unix_name,
1198 conn->session_info->unix_token->gid,
1199 conn->session_info->unix_info->sanitized_username,
1200 conn->session_info->info->domain_name,
1201 lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn)));
1202 smbrun(cmd, NULL, NULL);