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 "lib/param/loadparm.h"
33 #include "lib/afs/afs_funcs.h"
34 #include "lib/util_path.h"
36 static bool canonicalize_connect_path(connection_struct *conn)
39 struct smb_filename con_fname = { .base_name = conn->connectpath };
40 struct smb_filename *resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(),
42 if (resolved_fname == NULL) {
45 ret = set_conn_connectpath(conn,resolved_fname->base_name);
46 TALLOC_FREE(resolved_fname);
50 /****************************************************************************
51 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
52 absolute path stating in / and not ending in /.
53 ****************************************************************************/
55 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
59 if (connectpath == NULL || connectpath[0] == '\0') {
63 destname = canonicalize_absolute_path(conn, connectpath);
64 if (destname == NULL) {
68 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
69 lp_servicename(talloc_tos(), SNUM(conn)), destname ));
71 talloc_free(conn->connectpath);
72 conn->connectpath = destname;
74 * Ensure conn->cwd_fname is initialized.
75 * start as conn->connectpath.
77 TALLOC_FREE(conn->cwd_fname);
78 conn->cwd_fname = synthetic_smb_fname(conn,
83 if (conn->cwd_fname == NULL) {
89 /****************************************************************************
90 Load parameters specific to a connection/service.
91 ****************************************************************************/
93 void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
96 enum remote_arch_types ra_type;
98 SMB_ASSERT(conn != NULL);
102 if ((conn == last_conn) && (last_flags == flags)) {
110 * Obey the client case sensitivity requests - only for clients that
112 switch (lp_case_sensitive(snum)) {
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)) {
122 * Client can't support per-packet case sensitive
124 conn->case_sensitive = false;
126 conn->case_sensitive =
127 !(flags & FLAG_CASELESS_PATHNAMES);
131 conn->case_sensitive = true;
134 conn->case_sensitive = false;
140 bool chdir_current_service(connection_struct *conn)
142 const struct smb_filename connectpath_fname = {
143 .base_name = conn->connectpath,
145 const struct smb_filename origpath_fname = {
146 .base_name = conn->origpath,
150 conn->lastused_count++;
152 ret = vfs_ChDir(conn, &connectpath_fname);
154 DEBUG(((errno!=EACCES)?0:3),
155 ("chdir (%s) failed, reason: %s\n",
156 conn->connectpath, strerror(errno)));
160 ret = vfs_ChDir(conn, &origpath_fname);
162 DEBUG(((errno!=EACCES)?0:3),
163 ("chdir (%s) failed, reason: %s\n",
164 conn->origpath, strerror(errno)));
171 bool set_current_service(connection_struct *conn, uint16_t flags, bool do_chdir)
179 set_current_case_sensitive(conn, flags);
182 ok = chdir_current_service(conn);
191 /****************************************************************************
192 do some basic sainity checks on the share.
193 This function modifies dev, ecode.
194 ****************************************************************************/
196 static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
203 raddr = tsocket_address_inet_addr_string(remote_address,
206 return NT_STATUS_NO_MEMORY;
209 if (!lp_snum_ok(snum) ||
210 !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
212 return NT_STATUS_ACCESS_DENIED;
215 if (dev[0] == '?' || !dev[0]) {
216 if (lp_printable(snum)) {
217 fstrcpy(dev,"LPT1:");
218 } else if (strequal(lp_fstype(snum), "IPC")) {
225 if (!strupper_m(dev)) {
226 DEBUG(2,("strupper_m %s failed\n", dev));
227 return NT_STATUS_INVALID_PARAMETER;
230 if (lp_printable(snum)) {
231 if (!strequal(dev, "LPT1:")) {
232 return NT_STATUS_BAD_DEVICE_TYPE;
234 } else if (strequal(lp_fstype(snum), "IPC")) {
235 if (!strequal(dev, "IPC")) {
236 return NT_STATUS_BAD_DEVICE_TYPE;
238 } else if (!strequal(dev, "A:")) {
239 return NT_STATUS_BAD_DEVICE_TYPE;
242 /* Behave as a printer if we are supposed to */
243 if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) {
244 fstrcpy(dev, "LPT1:");
251 * Go through lookup_name etc to find the force'd group.
253 * Create a new token from src_token, replacing the primary group sid with the
257 static NTSTATUS find_forced_group(bool force_user,
258 int snum, const char *username,
259 struct dom_sid *pgroup_sid,
262 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
263 TALLOC_CTX *frame = talloc_stackframe();
264 struct dom_sid group_sid;
265 enum lsa_SidType type;
267 bool user_must_be_member = False;
270 groupname = lp_force_group(talloc_tos(), snum);
271 if (groupname == NULL) {
272 DEBUG(1, ("talloc_strdup failed\n"));
273 result = NT_STATUS_NO_MEMORY;
277 if (groupname[0] == '+') {
278 user_must_be_member = True;
282 groupname = talloc_string_sub(talloc_tos(), groupname,
283 "%S", lp_servicename(talloc_tos(), snum));
284 if (groupname == NULL) {
285 DEBUG(1, ("talloc_string_sub failed\n"));
286 result = NT_STATUS_NO_MEMORY;
290 if (!lookup_name_smbconf(talloc_tos(), groupname,
291 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
292 NULL, NULL, &group_sid, &type)) {
293 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
298 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
299 (type != SID_NAME_WKN_GRP)) {
300 DEBUG(10, ("%s is a %s, not a group\n", groupname,
301 sid_type_lookup(type)));
305 if (!sid_to_gid(&group_sid, &gid)) {
306 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
307 sid_string_dbg(&group_sid), groupname));
312 * If the user has been forced and the forced group starts with a '+',
313 * then we only set the group to be the forced group if the forced
314 * user is a member of that group. Otherwise, the meaning of the '+'
318 if (force_user && user_must_be_member) {
319 if (user_in_group_sid(username, &group_sid)) {
320 sid_copy(pgroup_sid, &group_sid);
322 DEBUG(3,("Forced group %s for member %s\n",
323 groupname, username));
325 DEBUG(0,("find_forced_group: forced user %s is not a member "
326 "of forced group %s. Disallowing access.\n",
327 username, groupname ));
328 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
332 sid_copy(pgroup_sid, &group_sid);
334 DEBUG(3,("Forced group %s\n", groupname));
337 result = NT_STATUS_OK;
343 /****************************************************************************
344 Create an auth_session_info structure for a connection_struct
345 ****************************************************************************/
347 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
348 TALLOC_CTX *mem_ctx, int snum,
349 struct auth_session_info *session_info,
350 struct auth_session_info **presult)
352 struct auth_session_info *result;
354 if (lp_guest_only(snum)) {
355 return make_session_info_guest(mem_ctx, presult);
359 * This is the normal security != share case where we have a
360 * valid vuid from the session setup. */
362 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
363 if (!lp_guest_ok(snum)) {
364 DEBUG(2, ("guest user (from session setup) "
365 "not permitted to access this share "
366 "(%s)\n", lp_servicename(talloc_tos(), snum)));
367 return NT_STATUS_ACCESS_DENIED;
370 if (!user_ok_token(session_info->unix_info->unix_name,
371 session_info->info->domain_name,
372 session_info->security_token, snum)) {
373 DEBUG(2, ("user '%s' (from session setup) not "
374 "permitted to access this share "
376 session_info->unix_info->unix_name,
377 lp_servicename(talloc_tos(), snum)));
378 return NT_STATUS_ACCESS_DENIED;
382 result = copy_session_info(mem_ctx, session_info);
383 if (result == NULL) {
384 return NT_STATUS_NO_MEMORY;
391 /****************************************************************************
392 Set relevant user and group settings corresponding to force user/group
393 configuration for the given snum.
394 ****************************************************************************/
396 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
400 if (*lp_force_user(talloc_tos(), snum)) {
403 * Replace conn->session_info with a completely faked up one
404 * from the username we are forced into :-)
408 char *sanitized_username;
409 struct auth_session_info *forced_serverinfo;
412 fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), snum), "%S",
413 lp_const_servicename(snum));
415 return NT_STATUS_NO_MEMORY;
418 guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;
420 status = make_session_info_from_username(
424 if (!NT_STATUS_IS_OK(status)) {
428 /* We don't want to replace the original sanitized_username
429 as it is the original user given in the connect attempt.
430 This is used in '%U' substitutions. */
431 sanitized_username = discard_const_p(char,
432 forced_serverinfo->unix_info->sanitized_username);
433 TALLOC_FREE(sanitized_username);
434 forced_serverinfo->unix_info->sanitized_username =
435 talloc_move(forced_serverinfo->unix_info,
436 &conn->session_info->unix_info->sanitized_username);
438 TALLOC_FREE(conn->session_info);
439 conn->session_info = forced_serverinfo;
441 conn->force_user = true;
442 DEBUG(3,("Forced user %s\n", fuser));
446 * If force group is true, then override
447 * any groupid stored for the connecting user.
450 if (*lp_force_group(talloc_tos(), snum)) {
452 status = find_forced_group(
453 conn->force_user, snum, conn->session_info->unix_info->unix_name,
454 &conn->session_info->security_token->sids[1],
455 &conn->session_info->unix_token->gid);
457 if (!NT_STATUS_IS_OK(status)) {
462 * We need to cache this gid, to use within
463 * change_to_user() separately from the conn->session_info
464 * struct. We only use conn->session_info directly if
465 * "force_user" was set.
467 conn->force_group_gid = conn->session_info->unix_token->gid;
473 static NTSTATUS notify_init_sconn(struct smbd_server_connection *sconn)
477 if (sconn->notify_ctx != NULL) {
481 sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx, sconn->ev_ctx,
482 sconn, notify_callback);
483 if (sconn->notify_ctx == NULL) {
484 return NT_STATUS_NO_MEMORY;
487 status = messaging_register(sconn->msg_ctx, sconn,
488 MSG_SMB_NOTIFY_CANCEL_DELETED,
489 smbd_notify_cancel_deleted);
490 if (!NT_STATUS_IS_OK(status)) {
491 DBG_DEBUG("messaging_register failed: %s\n",
493 TALLOC_FREE(sconn->notify_ctx);
497 status = messaging_register(sconn->msg_ctx, sconn,
498 MSG_SMB_NOTIFY_STARTED,
499 smbd_notifyd_restarted);
500 if (!NT_STATUS_IS_OK(status)) {
501 DBG_DEBUG("messaging_register failed: %s\n",
503 messaging_deregister(sconn->msg_ctx,
504 MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
505 TALLOC_FREE(sconn->notify_ctx);
512 /****************************************************************************
513 Make a connection, given the snum to connect to, and the vuser of the
514 connecting user if appropriate.
515 ****************************************************************************/
517 static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
518 connection_struct *conn,
519 int snum, struct user_struct *vuser,
522 struct smbd_server_connection *sconn = xconn->client->sconn;
523 struct smb_filename *smb_fname_cpath = NULL;
526 bool on_err_call_dis_hook = false;
533 status = share_sanity_checks(sconn->remote_address,
534 sconn->remote_hostname,
537 if (NT_STATUS_IS_ERR(status)) {
541 conn->params->service = snum;
543 status = create_connection_session_info(sconn,
544 conn, snum, vuser->session_info,
545 &conn->session_info);
547 if (!NT_STATUS_IS_OK(status)) {
548 DEBUG(1, ("create_connection_session_info failed: %s\n",
553 if (lp_guest_only(snum)) {
554 conn->force_user = true;
557 conn->num_files_open = 0;
558 conn->lastused = conn->lastused_count = time(NULL);
559 conn->printer = (strncmp(dev,"LPT",3) == 0);
560 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
561 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
563 /* Case options for the share. */
564 if (lp_case_sensitive(snum) == Auto) {
565 /* We will be setting this per packet. Set to be case
566 * insensitive for now. */
567 conn->case_sensitive = False;
569 conn->case_sensitive = (bool)lp_case_sensitive(snum);
572 conn->case_preserve = lp_preserve_case(snum);
573 conn->short_case_preserve = lp_short_preserve_case(snum);
575 conn->encrypt_level = lp_smb_encrypt(snum);
576 if (conn->encrypt_level > SMB_SIGNING_OFF) {
577 if (lp_smb_encrypt(-1) == SMB_SIGNING_OFF) {
578 if (conn->encrypt_level == SMB_SIGNING_REQUIRED) {
579 DBG_ERR("Service [%s] requires encryption, but "
580 "it is disabled globally!\n",
581 lp_servicename(talloc_tos(), snum));
582 status = NT_STATUS_ACCESS_DENIED;
585 conn->encrypt_level = SMB_SIGNING_OFF;
589 conn->veto_list = NULL;
590 conn->hide_list = NULL;
591 conn->veto_oplock_list = NULL;
592 conn->aio_write_behind_list = NULL;
594 conn->read_only = lp_read_only(SNUM(conn));
596 status = set_conn_force_user_group(conn, snum);
597 if (!NT_STATUS_IS_OK(status)) {
601 conn->vuid = vuser->vuid;
604 char *s = talloc_sub_advanced(talloc_tos(),
605 lp_servicename(talloc_tos(), SNUM(conn)),
606 conn->session_info->unix_info->unix_name,
608 conn->session_info->unix_token->gid,
609 conn->session_info->unix_info->sanitized_username,
610 conn->session_info->info->domain_name,
611 lp_path(talloc_tos(), snum));
613 status = NT_STATUS_NO_MEMORY;
617 if (!set_conn_connectpath(conn,s)) {
619 status = NT_STATUS_NO_MEMORY;
622 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
623 lp_servicename(talloc_tos(), snum)));
628 * Set up the share security descriptor.
629 * NOTE - we use the *INCOMING USER* session_info
630 * here, as does (indirectly) change_to_user(),
631 * which can be called on any incoming packet.
632 * This way we set up the share access based
633 * on the authenticated user, not the forced
636 * https://bugzilla.samba.org/show_bug.cgi?id=9878
639 status = check_user_share_access(conn,
643 if (!NT_STATUS_IS_OK(status)) {
647 /* Initialise VFS function pointers */
649 if (!smbd_vfs_init(conn)) {
650 DEBUG(0, ("vfs_init failed for service %s\n",
651 lp_servicename(talloc_tos(), snum)));
652 status = NT_STATUS_BAD_NETWORK_NAME;
656 /* ROOT Activities: */
657 /* explicitly check widelinks here so that we can correctly warn
659 widelinks_warning(snum);
662 * Enforce the max connections parameter.
665 if ((lp_max_connections(snum) > 0)
666 && (count_current_connections(lp_servicename(talloc_tos(), SNUM(conn)), True) >=
667 lp_max_connections(snum))) {
669 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
670 lp_max_connections(snum),
671 lp_servicename(talloc_tos(), snum)));
672 status = NT_STATUS_INSUFFICIENT_RESOURCES;
676 /* Invoke VFS make connection hook - this must be the first
677 filesystem operation that we do. */
679 if (SMB_VFS_CONNECT(conn, lp_servicename(talloc_tos(), snum),
680 conn->session_info->unix_info->unix_name) < 0) {
681 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
682 lp_servicename(talloc_tos(), snum), conn->connectpath,
684 status = NT_STATUS_UNSUCCESSFUL;
688 /* Any error exit after here needs to call the disconnect hook. */
689 on_err_call_dis_hook = true;
691 if ((!conn->printer) && (!conn->ipc) &&
692 lp_change_notify()) {
694 status = notify_init_sconn(sconn);
695 if (!NT_STATUS_IS_OK(status)) {
700 if (lp_kernel_oplocks(snum)) {
701 init_kernel_oplocks(conn->sconn);
705 * Fix compatibility issue pointed out by Volker.
706 * We pass the conn->connectpath to the preexec
707 * scripts as a parameter, so attempt to canonicalize
708 * it here before calling the preexec scripts.
709 * We ignore errors here, as it is possible that
710 * the conn->connectpath doesn't exist yet and
711 * the preexec scripts will create them.
714 (void)canonicalize_connect_path(conn);
716 /* Preexecs are done here as they might make the dir we are to ChDir
718 /* execute any "root preexec = " line */
719 if (*lp_root_preexec(talloc_tos(), snum)) {
720 char *cmd = talloc_sub_advanced(talloc_tos(),
721 lp_servicename(talloc_tos(), SNUM(conn)),
722 conn->session_info->unix_info->unix_name,
724 conn->session_info->unix_token->gid,
725 conn->session_info->unix_info->sanitized_username,
726 conn->session_info->info->domain_name,
727 lp_root_preexec(talloc_tos(), snum));
728 DEBUG(5,("cmd=%s\n",cmd));
729 ret = smbrun(cmd, NULL, NULL);
731 if (ret != 0 && lp_root_preexec_close(snum)) {
732 DEBUG(1,("root preexec gave %d - failing "
733 "connection\n", ret));
734 status = NT_STATUS_ACCESS_DENIED;
739 /* USER Activites: */
740 if (!change_to_user(conn, conn->vuid)) {
741 /* No point continuing if they fail the basic checks */
742 DEBUG(0,("Can't become connected user!\n"));
743 status = NT_STATUS_LOGON_FAILURE;
750 /* Remember that a different vuid can connect later without these
753 /* Preexecs are done here as they might make the dir we are to ChDir
756 /* execute any "preexec = " line */
757 if (*lp_preexec(talloc_tos(), snum)) {
758 char *cmd = talloc_sub_advanced(talloc_tos(),
759 lp_servicename(talloc_tos(), SNUM(conn)),
760 conn->session_info->unix_info->unix_name,
762 conn->session_info->unix_token->gid,
763 conn->session_info->unix_info->sanitized_username,
764 conn->session_info->info->domain_name,
765 lp_preexec(talloc_tos(), snum));
766 ret = smbrun(cmd, NULL, NULL);
768 if (ret != 0 && lp_preexec_close(snum)) {
769 DEBUG(1,("preexec gave %d - failing connection\n",
771 status = NT_STATUS_ACCESS_DENIED;
776 #ifdef WITH_FAKE_KASERVER
777 if (lp_afs_share(snum)) {
783 * we've finished with the user stuff - go back to root
784 * so the SMB_VFS_STAT call will only fail on path errors,
785 * not permission problems.
787 change_to_root_user();
788 /* ROOT Activites: */
791 * If widelinks are disallowed we need to canonicalise the connect
792 * path here to ensure we don't have any symlinks in the
793 * connectpath. We will be checking all paths on this connection are
794 * below this directory. We must do this after the VFS init as we
795 * depend on the realpath() pointer in the vfs table. JRA.
797 if (!lp_widelinks(snum)) {
798 if (!canonicalize_connect_path(conn)) {
799 DEBUG(0, ("canonicalize_connect_path failed "
800 "for service %s, path %s\n",
801 lp_servicename(talloc_tos(), snum),
803 status = NT_STATUS_BAD_NETWORK_NAME;
808 /* Add veto/hide lists */
809 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
810 set_namearray( &conn->veto_list,
811 lp_veto_files(talloc_tos(), snum));
812 set_namearray( &conn->hide_list,
813 lp_hide_files(talloc_tos(), snum));
814 set_namearray( &conn->veto_oplock_list,
815 lp_veto_oplock_files(talloc_tos(), snum));
816 set_namearray( &conn->aio_write_behind_list,
817 lp_aio_write_behind(talloc_tos(), snum));
819 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
824 if (smb_fname_cpath == NULL) {
825 status = NT_STATUS_NO_MEMORY;
829 /* win2000 does not check the permissions on the directory
830 during the tree connect, instead relying on permission
831 check during individual operations. To match this behaviour
832 I have disabled this chdir check (tridge) */
833 /* the alternative is just to check the directory exists */
835 if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
836 !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
837 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
838 DEBUG(0,("'%s' is not a directory, when connecting to "
839 "[%s]\n", conn->connectpath,
840 lp_servicename(talloc_tos(), snum)));
842 DEBUG(0,("'%s' does not exist or permission denied "
843 "when connecting to [%s] Error was %s\n",
845 lp_servicename(talloc_tos(), snum),
848 status = NT_STATUS_BAD_NETWORK_NAME;
851 conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
853 talloc_free(conn->origpath);
854 conn->origpath = talloc_strdup(conn, conn->connectpath);
856 /* Figure out the characteristics of the underlying filesystem. This
857 * assumes that all the filesystem mounted withing a share path have
858 * the same characteristics, which is likely but not guaranteed.
861 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
864 * Print out the 'connected as' stuff here as we need
865 * to know the effective uid and gid we will be using
866 * (at least initially).
869 if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
870 dbgtext( "%s (%s) ", get_remote_machine_name(),
871 tsocket_address_string(conn->sconn->remote_address,
873 dbgtext( "%s", srv_is_signing_active(xconn) ? "signed " : "");
874 dbgtext( "connect to service %s ",
875 lp_servicename(talloc_tos(), snum) );
876 dbgtext( "initially as user %s ",
877 conn->session_info->unix_info->unix_name );
878 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
879 dbgtext( "(pid %d)\n", (int)getpid() );
886 TALLOC_FREE(smb_fname_cpath);
887 /* We must exit this function as root. */
888 if (geteuid() != 0) {
889 change_to_root_user();
891 if (on_err_call_dis_hook) {
892 /* Call VFS disconnect hook */
893 SMB_VFS_DISCONNECT(conn);
898 /****************************************************************************
899 Make a connection to a service from SMB1. Internal interface.
900 ****************************************************************************/
902 static connection_struct *make_connection_smb1(struct smb_request *req,
904 int snum, struct user_struct *vuser,
908 struct smbXsrv_tcon *tcon;
910 struct connection_struct *conn;
912 status = smb1srv_tcon_create(req->xconn, now, &tcon);
913 if (!NT_STATUS_IS_OK(status)) {
914 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
920 conn = conn_new(req->sconn);
924 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
925 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
929 conn->cnum = tcon->global->tcon_wire_id;
932 *pstatus = make_connection_snum(req->xconn,
937 if (!NT_STATUS_IS_OK(*pstatus)) {
943 tcon->global->share_name = lp_servicename(tcon->global, SNUM(conn));
944 if (tcon->global->share_name == NULL) {
947 *pstatus = NT_STATUS_NO_MEMORY;
950 tcon->global->session_global_id =
951 vuser->session->global->session_global_id;
953 tcon->compat = talloc_move(tcon, &conn);
954 tcon->status = NT_STATUS_OK;
956 *pstatus = smbXsrv_tcon_update(tcon);
957 if (!NT_STATUS_IS_OK(*pstatus)) {
965 /****************************************************************************
966 Make a connection to a service from SMB2. External SMB2 interface.
967 We must set cnum before claiming connection.
968 ****************************************************************************/
970 connection_struct *make_connection_smb2(struct smbd_smb2_request *req,
971 struct smbXsrv_tcon *tcon,
973 struct user_struct *vuser,
977 struct smbd_server_connection *sconn = req->sconn;
978 connection_struct *conn = conn_new(sconn);
980 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
981 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
985 conn->cnum = tcon->global->tcon_wire_id;
988 *pstatus = make_connection_snum(req->xconn,
993 if (!NT_STATUS_IS_OK(*pstatus)) {
1000 /****************************************************************************
1001 Make a connection to a service. External SMB1 interface.
1004 ****************************************************************************/
1006 connection_struct *make_connection(struct smb_request *req,
1008 const char *service_in,
1009 const char *pdev, uint64_t vuid,
1012 struct smbd_server_connection *sconn = req->sconn;
1014 struct user_struct *vuser = NULL;
1015 char *service = NULL;
1021 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1023 if (!non_root_mode() && (euid = geteuid()) != 0) {
1024 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1025 "(%u)\n", (unsigned int)euid ));
1026 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1029 if (conn_num_open(sconn) > 2047) {
1030 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1034 vuser = get_valid_user_struct(sconn, vuid);
1036 DEBUG(1,("make_connection: refusing to connect with "
1037 "no session setup\n"));
1038 *status = NT_STATUS_ACCESS_DENIED;
1042 /* Logic to try and connect to the correct [homes] share, preferably
1043 without too many getpwnam() lookups. This is particulary nasty for
1044 winbind usernames, where the share name isn't the same as unix
1047 The snum of the homes share is stored on the vuser at session setup
1051 if (strequal(service_in,HOMES_NAME)) {
1052 if (vuser->homes_snum == -1) {
1053 DEBUG(2, ("[homes] share not available for "
1054 "this user because it was not found "
1055 "or created at session setup "
1057 *status = NT_STATUS_BAD_NETWORK_NAME;
1060 DEBUG(5, ("making a connection to [homes] service "
1061 "created at session setup time\n"));
1062 return make_connection_smb1(req, now,
1066 } else if ((vuser->homes_snum != -1)
1067 && strequal(service_in,
1068 lp_servicename(talloc_tos(), vuser->homes_snum))) {
1069 DEBUG(5, ("making a connection to 'homes' service [%s] "
1070 "created at session setup time\n", service_in));
1071 return make_connection_smb1(req, now,
1077 service = talloc_strdup(talloc_tos(), service_in);
1079 *status = NT_STATUS_NO_MEMORY;
1083 if (!strlower_m(service)) {
1084 DEBUG(2, ("strlower_m %s failed\n", service));
1085 *status = NT_STATUS_INVALID_PARAMETER;
1089 snum = find_service(talloc_tos(), service, &service);
1091 *status = NT_STATUS_NO_MEMORY;
1096 if (strequal(service,"IPC$") ||
1097 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1098 DEBUG(3,("refusing IPC connection to %s\n", service));
1099 *status = NT_STATUS_ACCESS_DENIED;
1103 DEBUG(3,("%s (%s) couldn't find service %s\n",
1104 get_remote_machine_name(),
1105 tsocket_address_string(
1106 sconn->remote_address, talloc_tos()),
1108 *status = NT_STATUS_BAD_NETWORK_NAME;
1112 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1113 if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), snum) != '\0')) {
1114 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1115 "(pointing to %s)\n",
1116 service, lp_msdfs_proxy(talloc_tos(), snum)));
1117 *status = NT_STATUS_BAD_NETWORK_NAME;
1121 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1123 return make_connection_smb1(req, now, snum, vuser,
1127 /****************************************************************************
1129 ****************************************************************************/
1131 void close_cnum(connection_struct *conn, uint64_t vuid)
1133 char rootpath[2] = { '/', '\0'};
1134 struct smb_filename root_fname = { .base_name = rootpath };
1136 file_close_conn(conn);
1138 if (!IS_IPC(conn)) {
1139 dptr_closecnum(conn);
1142 change_to_root_user();
1144 DEBUG(IS_IPC(conn)?3:2, ("%s (%s) closed connection to service %s\n",
1145 get_remote_machine_name(),
1146 tsocket_address_string(conn->sconn->remote_address,
1148 lp_servicename(talloc_tos(), SNUM(conn))));
1150 /* make sure we leave the directory available for unmount */
1151 vfs_ChDir(conn, &root_fname);
1153 /* Call VFS disconnect hook */
1154 SMB_VFS_DISCONNECT(conn);
1156 /* execute any "postexec = " line */
1157 if (*lp_postexec(talloc_tos(), SNUM(conn)) &&
1158 change_to_user(conn, vuid)) {
1159 char *cmd = talloc_sub_advanced(talloc_tos(),
1160 lp_servicename(talloc_tos(), SNUM(conn)),
1161 conn->session_info->unix_info->unix_name,
1163 conn->session_info->unix_token->gid,
1164 conn->session_info->unix_info->sanitized_username,
1165 conn->session_info->info->domain_name,
1166 lp_postexec(talloc_tos(), SNUM(conn)));
1167 smbrun(cmd, NULL, NULL);
1169 change_to_root_user();
1172 change_to_root_user();
1173 /* execute any "root postexec = " line */
1174 if (*lp_root_postexec(talloc_tos(), SNUM(conn))) {
1175 char *cmd = talloc_sub_advanced(talloc_tos(),
1176 lp_servicename(talloc_tos(), SNUM(conn)),
1177 conn->session_info->unix_info->unix_name,
1179 conn->session_info->unix_token->gid,
1180 conn->session_info->unix_info->sanitized_username,
1181 conn->session_info->info->domain_name,
1182 lp_root_postexec(talloc_tos(), SNUM(conn)));
1183 smbrun(cmd, NULL, NULL);