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"
36 #include "lib/util/string_wrappers.h"
37 #include "source3/lib/substitute.h"
39 bool canonicalize_connect_path(connection_struct
*conn
)
42 struct smb_filename con_fname
= { .base_name
= conn
->connectpath
};
43 struct smb_filename
*resolved_fname
= SMB_VFS_REALPATH(conn
, talloc_tos(),
45 if (resolved_fname
== NULL
) {
48 ret
= set_conn_connectpath(conn
,resolved_fname
->base_name
);
49 TALLOC_FREE(resolved_fname
);
53 /****************************************************************************
54 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
55 absolute path stating in / and not ending in /.
56 ****************************************************************************/
58 bool set_conn_connectpath(connection_struct
*conn
, const char *connectpath
)
62 if (connectpath
== NULL
|| connectpath
[0] == '\0') {
66 destname
= canonicalize_absolute_path(conn
, connectpath
);
67 if (destname
== NULL
) {
71 DBG_DEBUG("service %s, connectpath = %s\n",
72 lp_const_servicename(SNUM(conn
)), destname
);
74 talloc_free(conn
->connectpath
);
75 conn
->connectpath
= destname
;
77 * Ensure conn->cwd_fsp->fsp_name is initialized.
78 * start as conn->connectpath.
80 TALLOC_FREE(conn
->cwd_fsp
->fsp_name
);
81 conn
->cwd_fsp
->fsp_name
= synthetic_smb_fname(conn
,
87 if (conn
->cwd_fsp
->fsp_name
== NULL
) {
93 bool chdir_current_service(connection_struct
*conn
)
95 const struct smb_filename connectpath_fname
= {
96 .base_name
= conn
->connectpath
,
99 char *utok_str
= NULL
;
102 conn
->lastused_count
++;
104 ret
= vfs_ChDir(conn
, &connectpath_fname
);
110 utok_str
= utok_string(talloc_tos(),
111 conn
->session_info
->unix_token
);
112 if (utok_str
== NULL
) {
117 DBG_ERR("vfs_ChDir(%s) failed: %s. Current token: %s\n",
119 strerror(saved_errno
),
122 if (saved_errno
!= 0) {
128 /****************************************************************************
129 do some basic sainity checks on the share.
130 This function modifies dev, ecode.
131 ****************************************************************************/
133 static NTSTATUS
share_sanity_checks(const struct tsocket_address
*local_address
,
134 const struct tsocket_address
*remote_address
,
141 if (!lp_allow_local_address(snum
, local_address
)) {
144 laddr
= tsocket_address_inet_addr_string(
145 local_address
, talloc_tos());
147 return NT_STATUS_NO_MEMORY
;
150 raddr
= tsocket_address_inet_addr_string(
151 remote_address
, laddr
);
154 return NT_STATUS_NO_MEMORY
;
157 DBG_ERR("Denied connection from %s (%s) to \\\\%s\\%s\n",
158 rhost
, raddr
, laddr
, lp_const_servicename(snum
));
161 return NT_STATUS_BAD_NETWORK_NAME
;
164 raddr
= tsocket_address_inet_addr_string(remote_address
,
167 return NT_STATUS_NO_MEMORY
;
170 if (!lp_snum_ok(snum
) ||
171 !allow_access(lp_hosts_deny(snum
), lp_hosts_allow(snum
),
173 return NT_STATUS_ACCESS_DENIED
;
176 if (dev
[0] == '?' || !dev
[0]) {
177 if (lp_printable(snum
)) {
178 fstrcpy(dev
,"LPT1:");
179 } else if (strequal(lp_fstype(snum
), "IPC")) {
186 if (!strupper_m(dev
)) {
187 DBG_WARNING("strupper_m %s failed\n", dev
);
188 return NT_STATUS_INVALID_PARAMETER
;
191 if (lp_printable(snum
)) {
192 if (!strequal(dev
, "LPT1:")) {
193 return NT_STATUS_BAD_DEVICE_TYPE
;
195 } else if (strequal(lp_fstype(snum
), "IPC")) {
196 if (!strequal(dev
, "IPC")) {
197 return NT_STATUS_BAD_DEVICE_TYPE
;
199 } else if (!strequal(dev
, "A:")) {
200 return NT_STATUS_BAD_DEVICE_TYPE
;
203 /* Behave as a printer if we are supposed to */
204 if (lp_printable(snum
) && (strcmp(dev
, "A:") == 0)) {
205 fstrcpy(dev
, "LPT1:");
212 * Go through lookup_name etc to find the force'd group.
214 * Create a new token from src_token, replacing the primary group sid with the
218 static NTSTATUS
find_forced_group(bool force_user
,
219 int snum
, const char *username
,
220 struct dom_sid
*pgroup_sid
,
223 NTSTATUS result
= NT_STATUS_NO_SUCH_GROUP
;
224 TALLOC_CTX
*frame
= talloc_stackframe();
225 const struct loadparm_substitution
*lp_sub
=
226 loadparm_s3_global_substitution();
227 struct dom_sid group_sid
;
228 enum lsa_SidType type
;
230 bool user_must_be_member
= False
;
233 groupname
= lp_force_group(talloc_tos(), lp_sub
, snum
);
234 if (groupname
== NULL
) {
235 DBG_WARNING("talloc_strdup failed\n");
236 result
= NT_STATUS_NO_MEMORY
;
240 if (groupname
[0] == '+') {
241 user_must_be_member
= True
;
245 groupname
= talloc_string_sub(talloc_tos(), groupname
,
246 "%S", lp_const_servicename(snum
));
247 if (groupname
== NULL
) {
248 DBG_WARNING("talloc_string_sub failed\n");
249 result
= NT_STATUS_NO_MEMORY
;
253 if (!lookup_name_smbconf(talloc_tos(), groupname
,
254 LOOKUP_NAME_ALL
|LOOKUP_NAME_GROUP
,
255 NULL
, NULL
, &group_sid
, &type
)) {
256 DBG_DEBUG("lookup_name_smbconf(%s) failed\n",
261 if ((type
!= SID_NAME_DOM_GRP
) && (type
!= SID_NAME_ALIAS
) &&
262 (type
!= SID_NAME_WKN_GRP
)) {
263 DBG_DEBUG("%s is a %s, not a group\n", groupname
,
264 sid_type_lookup(type
));
268 if (!sid_to_gid(&group_sid
, &gid
)) {
269 struct dom_sid_buf buf
;
270 DBG_DEBUG("sid_to_gid(%s) for %s failed\n",
271 dom_sid_str_buf(&group_sid
, &buf
), groupname
);
276 * If the user has been forced and the forced group starts with a '+',
277 * then we only set the group to be the forced group if the forced
278 * user is a member of that group. Otherwise, the meaning of the '+'
282 if (force_user
&& user_must_be_member
) {
283 if (user_in_group_sid(username
, &group_sid
)) {
284 sid_copy(pgroup_sid
, &group_sid
);
286 DBG_INFO("Forced group %s for member %s\n",
287 groupname
, username
);
289 DBG_ERR("find_forced_group: forced user %s is not a member "
290 "of forced group %s. Disallowing access.\n",
291 username
, groupname
);
292 result
= NT_STATUS_MEMBER_NOT_IN_GROUP
;
296 sid_copy(pgroup_sid
, &group_sid
);
298 DBG_INFO("Forced group %s\n", groupname
);
301 result
= NT_STATUS_OK
;
307 /****************************************************************************
308 Create an auth_session_info structure for a connection_struct
309 ****************************************************************************/
311 static NTSTATUS
create_connection_session_info(struct smbd_server_connection
*sconn
,
312 TALLOC_CTX
*mem_ctx
, int snum
,
313 struct auth_session_info
*session_info
,
314 struct auth_session_info
**presult
)
316 struct auth_session_info
*result
;
318 if (lp_guest_only(snum
)) {
319 return make_session_info_guest(mem_ctx
, presult
);
323 * This is the normal security != share case where we have a
324 * valid vuid from the session setup. */
326 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
327 if (!lp_guest_ok(snum
)) {
328 DBG_WARNING("guest user (from session setup) "
329 "not permitted to access this share "
330 "(%s)\n", lp_const_servicename(snum
));
331 return NT_STATUS_ACCESS_DENIED
;
334 if (!user_ok_token(session_info
->unix_info
->unix_name
,
335 session_info
->info
->domain_name
,
336 session_info
->security_token
, snum
)) {
337 DBG_WARNING("user '%s' (from session setup) not "
338 "permitted to access this share "
340 session_info
->unix_info
->unix_name
,
341 lp_const_servicename(snum
));
342 return NT_STATUS_ACCESS_DENIED
;
346 result
= copy_session_info(mem_ctx
, session_info
);
347 if (result
== NULL
) {
348 return NT_STATUS_NO_MEMORY
;
355 /****************************************************************************
356 Set relevant user and group settings corresponding to force user/group
357 configuration for the given snum.
358 ****************************************************************************/
360 NTSTATUS
set_conn_force_user_group(connection_struct
*conn
, int snum
)
362 const struct loadparm_substitution
*lp_sub
=
363 loadparm_s3_global_substitution();
366 if (*lp_force_user(talloc_tos(), lp_sub
, snum
)) {
369 * Replace conn->session_info with a completely faked up one
370 * from the username we are forced into :-)
374 char *sanitized_username
;
375 struct auth_session_info
*forced_serverinfo
;
378 fuser
= talloc_string_sub(conn
, lp_force_user(talloc_tos(), lp_sub
, snum
), "%S",
379 lp_const_servicename(snum
));
381 return NT_STATUS_NO_MEMORY
;
384 guest
= security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
;
386 status
= make_session_info_from_username(
390 if (!NT_STATUS_IS_OK(status
)) {
394 /* We don't want to replace the original sanitized_username
395 as it is the original user given in the connect attempt.
396 This is used in '%U' substitutions. */
397 sanitized_username
= discard_const_p(char,
398 forced_serverinfo
->unix_info
->sanitized_username
);
399 TALLOC_FREE(sanitized_username
);
400 forced_serverinfo
->unix_info
->sanitized_username
=
401 talloc_move(forced_serverinfo
->unix_info
,
402 &conn
->session_info
->unix_info
->sanitized_username
);
404 TALLOC_FREE(conn
->session_info
);
405 conn
->session_info
= forced_serverinfo
;
407 conn
->force_user
= true;
408 DBG_INFO("Forced user %s\n", fuser
);
412 * If force group is true, then override
413 * any groupid stored for the connecting user.
416 if (*lp_force_group(talloc_tos(), lp_sub
, snum
)) {
418 status
= find_forced_group(
419 conn
->force_user
, snum
, conn
->session_info
->unix_info
->unix_name
,
420 &conn
->session_info
->security_token
->sids
[1],
421 &conn
->session_info
->unix_token
->gid
);
423 if (!NT_STATUS_IS_OK(status
)) {
428 * We need to cache this gid, to use within
429 * change_to_user() separately from the conn->session_info
430 * struct. We only use conn->session_info directly if
431 * "force_user" was set.
433 conn
->force_group_gid
= conn
->session_info
->unix_token
->gid
;
439 static NTSTATUS
notify_init_sconn(struct smbd_server_connection
*sconn
)
443 if (sconn
->notify_ctx
!= NULL
) {
447 sconn
->notify_ctx
= notify_init(sconn
, sconn
->msg_ctx
,
448 sconn
, notify_callback
);
449 if (sconn
->notify_ctx
== NULL
) {
450 return NT_STATUS_NO_MEMORY
;
453 status
= messaging_register(sconn
->msg_ctx
, sconn
,
454 MSG_SMB_NOTIFY_CANCEL_DELETED
,
455 smbd_notify_cancel_deleted
);
456 if (!NT_STATUS_IS_OK(status
)) {
457 DBG_DEBUG("messaging_register failed: %s\n",
459 TALLOC_FREE(sconn
->notify_ctx
);
463 status
= messaging_register(sconn
->msg_ctx
, sconn
,
464 MSG_SMB_NOTIFY_STARTED
,
465 smbd_notifyd_restarted
);
466 if (!NT_STATUS_IS_OK(status
)) {
467 DBG_DEBUG("messaging_register failed: %s\n",
469 messaging_deregister(sconn
->msg_ctx
,
470 MSG_SMB_NOTIFY_CANCEL_DELETED
, sconn
);
471 TALLOC_FREE(sconn
->notify_ctx
);
478 /****************************************************************************
479 Make a connection, given the snum to connect to, and the vuser of the
480 connecting user if appropriate.
481 ****************************************************************************/
483 NTSTATUS
make_connection_snum(struct smbXsrv_connection
*xconn
,
484 connection_struct
*conn
,
486 struct smbXsrv_session
*session
,
489 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
490 const struct loadparm_substitution
*lp_sub
=
491 loadparm_s3_global_substitution();
492 struct smb_filename
*smb_fname_cpath
= NULL
;
495 bool on_err_call_dis_hook
= false;
503 status
= share_sanity_checks(sconn
->local_address
,
504 sconn
->remote_address
,
505 sconn
->remote_hostname
,
508 if (NT_STATUS_IS_ERR(status
)) {
512 conn
->params
->service
= snum
;
514 status
= create_connection_session_info(sconn
,
515 conn
, snum
, session
->global
->auth_session_info
,
516 &conn
->session_info
);
518 if (!NT_STATUS_IS_OK(status
)) {
519 DBG_WARNING("create_connection_session_info failed: %s\n",
524 if (lp_guest_only(snum
)) {
525 conn
->force_user
= true;
528 conn
->num_files_open
= 0;
529 conn
->lastused
= conn
->lastused_count
= time(NULL
);
530 conn
->printer
= (strncmp(dev
,"LPT",3) == 0);
531 conn
->ipc
= ( (strncmp(dev
,"IPC",3) == 0) ||
532 ( lp_enable_asu_support() && strequal(dev
,"ADMIN$")) );
534 /* Case options for the share. */
535 conn_setup_case_options(conn
);
537 conn
->encrypt_level
= lp_server_smb_encrypt(snum
);
538 if (conn
->encrypt_level
> SMB_ENCRYPTION_OFF
) {
539 if (lp_server_smb_encrypt(-1) == SMB_ENCRYPTION_OFF
) {
540 if (conn
->encrypt_level
== SMB_ENCRYPTION_REQUIRED
) {
541 DBG_ERR("Service [%s] requires encryption, but "
542 "it is disabled globally!\n",
543 lp_const_servicename(snum
));
544 status
= NT_STATUS_ACCESS_DENIED
;
547 conn
->encrypt_level
= SMB_ENCRYPTION_OFF
;
551 conn
->veto_list
= NULL
;
552 conn
->hide_list
= NULL
;
553 conn
->veto_oplock_list
= NULL
;
554 conn
->aio_write_behind_list
= NULL
;
556 conn
->read_only
= lp_read_only(SNUM(conn
));
558 status
= set_conn_force_user_group(conn
, snum
);
559 if (!NT_STATUS_IS_OK(status
)) {
563 conn
->vuid
= session
->global
->session_wire_id
;
566 char *s
= talloc_sub_full(talloc_tos(),
567 lp_const_servicename(SNUM(conn
)),
568 conn
->session_info
->unix_info
->unix_name
,
570 conn
->session_info
->unix_token
->gid
,
571 conn
->session_info
->unix_info
->sanitized_username
,
572 conn
->session_info
->info
->domain_name
,
573 lp_path(talloc_tos(), lp_sub
, snum
));
575 status
= NT_STATUS_NO_MEMORY
;
579 if (!set_conn_connectpath(conn
,s
)) {
581 status
= NT_STATUS_NO_MEMORY
;
584 DBG_NOTICE("Connect path is '%s' for service [%s]\n", s
,
585 lp_const_servicename(snum
));
590 * Set up the share security descriptor.
591 * NOTE - we use the *INCOMING USER* session_info
592 * here, as does (indirectly) change_to_user(),
593 * which can be called on any incoming packet.
594 * This way we set up the share access based
595 * on the authenticated user, not the forced
598 * https://bugzilla.samba.org/show_bug.cgi?id=9878
601 status
= check_user_share_access(conn
,
602 session
->global
->auth_session_info
,
605 if (!NT_STATUS_IS_OK(status
)) {
609 /* Initialise VFS function pointers */
611 if (!smbd_vfs_init(conn
)) {
612 DBG_ERR("vfs_init failed for service %s\n",
613 lp_const_servicename(snum
));
614 status
= NT_STATUS_BAD_NETWORK_NAME
;
618 /* ROOT Activities: */
619 /* explicitly check widelinks here so that we can correctly warn
621 widelinks_warning(snum
);
623 /* Invoke VFS make connection hook - this must be the first
624 filesystem operation that we do. */
626 if (SMB_VFS_CONNECT(conn
, lp_const_servicename(snum
),
627 conn
->session_info
->unix_info
->unix_name
) < 0) {
628 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
629 lp_const_servicename(snum
), conn
->connectpath
,
631 status
= NT_STATUS_UNSUCCESSFUL
;
635 /* Any error exit after here needs to call the disconnect hook. */
636 on_err_call_dis_hook
= true;
638 if ((!conn
->printer
) && (!conn
->ipc
) &&
639 lp_change_notify()) {
641 status
= notify_init_sconn(sconn
);
642 if (!NT_STATUS_IS_OK(status
)) {
647 if (lp_kernel_oplocks(snum
)) {
648 init_kernel_oplocks(conn
->sconn
);
652 * Fix compatibility issue pointed out by Volker.
653 * We pass the conn->connectpath to the preexec
654 * scripts as a parameter, so attempt to canonicalize
655 * it here before calling the preexec scripts.
656 * We ignore errors here, as it is possible that
657 * the conn->connectpath doesn't exist yet and
658 * the preexec scripts will create them.
661 (void)canonicalize_connect_path(conn
);
663 /* Preexecs are done here as they might make the dir we are to ChDir
665 /* execute any "root preexec = " line */
666 if (*lp_root_preexec(talloc_tos(), lp_sub
, snum
)) {
667 char *cmd
= talloc_sub_full(talloc_tos(),
668 lp_const_servicename(SNUM(conn
)),
669 conn
->session_info
->unix_info
->unix_name
,
671 conn
->session_info
->unix_token
->gid
,
672 conn
->session_info
->unix_info
->sanitized_username
,
673 conn
->session_info
->info
->domain_name
,
674 lp_root_preexec(talloc_tos(), lp_sub
, snum
));
675 DBG_INFO("cmd=%s\n",cmd
);
676 ret
= smbrun(cmd
, NULL
, NULL
);
678 if (ret
!= 0 && lp_root_preexec_close(snum
)) {
679 DBG_WARNING("root preexec gave %d - failing "
680 "connection\n", ret
);
681 status
= NT_STATUS_ACCESS_DENIED
;
686 /* USER Activities: */
687 if (!change_to_user_and_service(conn
, conn
->vuid
)) {
688 /* No point continuing if they fail the basic checks */
689 DBG_ERR("Can't become connected user!\n");
690 status
= NT_STATUS_LOGON_FAILURE
;
697 /* Remember that a different vuid can connect later without these
700 /* Preexecs are done here as they might make the dir we are to ChDir
703 /* execute any "preexec = " line */
704 if (*lp_preexec(talloc_tos(), lp_sub
, snum
)) {
705 char *cmd
= talloc_sub_full(talloc_tos(),
706 lp_const_servicename(SNUM(conn
)),
707 conn
->session_info
->unix_info
->unix_name
,
709 conn
->session_info
->unix_token
->gid
,
710 conn
->session_info
->unix_info
->sanitized_username
,
711 conn
->session_info
->info
->domain_name
,
712 lp_preexec(talloc_tos(), lp_sub
, snum
));
713 ret
= smbrun(cmd
, NULL
, NULL
);
715 if (ret
!= 0 && lp_preexec_close(snum
)) {
716 DBG_WARNING("preexec gave %d - failing connection\n",
718 status
= NT_STATUS_ACCESS_DENIED
;
723 #ifdef WITH_FAKE_KASERVER
724 if (lp_afs_share(snum
)) {
730 * we've finished with the user stuff - go back to root
731 * so the SMB_VFS_STAT call will only fail on path errors,
732 * not permission problems.
734 change_to_root_user();
735 /* ROOT Activities: */
738 * Canonicalise the connect
739 * path here to ensure we don't have any symlinks in the
740 * connectpath. We will be checking all paths on this connection are
741 * below this directory. We must do this after the VFS init as we
742 * depend on the realpath() pointer in the vfs table. JRA.
744 ok
= canonicalize_connect_path(conn
);
746 DBG_ERR("canonicalize_connect_path failed "
747 "for service %s, path %s\n",
748 lp_const_servicename(snum
),
750 status
= NT_STATUS_BAD_NETWORK_NAME
;
754 /* Add veto/hide lists */
755 if (!IS_IPC(conn
) && !IS_PRINT(conn
)) {
756 ok
= set_namearray(conn
,
757 lp_veto_oplock_files(talloc_tos(), lp_sub
, snum
),
758 &conn
->veto_oplock_list
);
760 status
= NT_STATUS_NO_MEMORY
;
763 ok
= set_namearray(conn
,
764 lp_aio_write_behind(talloc_tos(), lp_sub
, snum
),
765 &conn
->aio_write_behind_list
);
767 status
= NT_STATUS_NO_MEMORY
;
771 smb_fname_cpath
= synthetic_smb_fname(talloc_tos(),
777 if (smb_fname_cpath
== NULL
) {
778 status
= NT_STATUS_NO_MEMORY
;
782 /* win2000 does not check the permissions on the directory
783 during the tree connect, instead relying on permission
784 check during individual operations. To match this behaviour
785 I have disabled this chdir check (tridge) */
786 /* the alternative is just to check the directory exists */
788 ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
);
790 DBG_ERR("'%s' does not exist or permission denied "
791 "when connecting to [%s] Error was %s\n",
793 lp_const_servicename(snum
),
795 status
= NT_STATUS_BAD_NETWORK_NAME
;
799 if (!S_ISDIR(smb_fname_cpath
->st
.st_ex_mode
)) {
800 DBG_ERR("'%s' is not a directory, when connecting to "
803 lp_const_servicename(snum
));
804 status
= NT_STATUS_BAD_NETWORK_NAME
;
808 conn
->base_share_dev
= smb_fname_cpath
->st
.st_ex_dev
;
810 /* Figure out the characteristics of the underlying filesystem. This
811 * assumes that all the filesystem mounted within a share path have
812 * the same characteristics, which is likely but not guaranteed.
816 conn
->fs_capabilities
= SMB_VFS_FS_CAPABILITIES(conn
, &conn
->ts_res
);
819 * Print out the 'connected as' stuff here as we need
820 * to know the effective uid and gid we will be using
821 * (at least initially).
824 if( DEBUGLVL( IS_IPC(conn
) ? DBGLVL_INFO
: DBGLVL_NOTICE
) ) {
827 dbgtext( "%s (%s) ", get_remote_machine_name(),
828 tsocket_address_string(conn
->sconn
->remote_address
,
830 #if defined(WITH_SMB1SERVER)
831 if (conn_using_smb2(sconn
)) {
833 signing_active
= smb2_signing_key_valid(
834 session
->global
->encryption_key
);
835 #if defined(WITH_SMB1SERVER)
837 signing_active
= smb1_srv_is_signing_active(xconn
);
840 dbgtext( "%s", signing_active
? "signed " : "");
841 dbgtext( "connect to service %s ",
842 lp_const_servicename(snum
) );
843 dbgtext( "initially as user %s ",
844 conn
->session_info
->unix_info
->unix_name
);
845 dbgtext( "(uid=%d, gid=%d) ", (int)effuid
, (int)effgid
);
846 dbgtext( "(pid %d)\n", (int)getpid() );
849 conn
->tcon_done
= true;
854 TALLOC_FREE(smb_fname_cpath
);
855 /* We must exit this function as root. */
856 if (geteuid() != 0) {
857 change_to_root_user();
859 if (on_err_call_dis_hook
) {
860 /* Call VFS disconnect hook */
861 SMB_VFS_DISCONNECT(conn
);
866 /****************************************************************************
867 Make a connection to a service from SMB2. External SMB2 interface.
868 We must set cnum before claiming connection.
869 ****************************************************************************/
871 connection_struct
*make_connection_smb2(struct smbd_smb2_request
*req
,
872 struct smbXsrv_tcon
*tcon
,
877 struct smbd_server_connection
*sconn
= req
->sconn
;
878 connection_struct
*conn
= conn_new(sconn
);
880 DBG_ERR("make_connection_smb2: Couldn't find free connection.\n");
881 *pstatus
= NT_STATUS_INSUFFICIENT_RESOURCES
;
885 conn
->cnum
= tcon
->global
->tcon_wire_id
;
888 *pstatus
= make_connection_snum(req
->xconn
,
893 if (!NT_STATUS_IS_OK(*pstatus
)) {
900 /****************************************************************************
902 ****************************************************************************/
904 void close_cnum(connection_struct
*conn
,
906 enum file_close_type close_type
)
908 char rootpath
[2] = { '/', '\0'};
909 struct smb_filename root_fname
= { .base_name
= rootpath
};
910 const struct loadparm_substitution
*lp_sub
=
911 loadparm_s3_global_substitution();
913 file_close_conn(conn
, close_type
);
915 change_to_root_user();
917 DEBUG(IS_IPC(conn
)?DBGLVL_INFO
:DBGLVL_NOTICE
, ("%s (%s) closed connection to service %s\n",
918 get_remote_machine_name(),
919 tsocket_address_string(conn
->sconn
->remote_address
,
921 lp_const_servicename(SNUM(conn
))));
923 /* make sure we leave the directory available for unmount */
924 vfs_ChDir(conn
, &root_fname
);
926 /* Call VFS disconnect hook */
927 SMB_VFS_DISCONNECT(conn
);
929 /* execute any "postexec = " line */
930 if (*lp_postexec(talloc_tos(), lp_sub
, SNUM(conn
)) &&
931 change_to_user_and_service(conn
, vuid
)) {
932 char *cmd
= talloc_sub_full(talloc_tos(),
933 lp_const_servicename(SNUM(conn
)),
934 conn
->session_info
->unix_info
->unix_name
,
936 conn
->session_info
->unix_token
->gid
,
937 conn
->session_info
->unix_info
->sanitized_username
,
938 conn
->session_info
->info
->domain_name
,
939 lp_postexec(talloc_tos(), lp_sub
, SNUM(conn
)));
940 smbrun(cmd
, NULL
, NULL
);
942 change_to_root_user();
945 change_to_root_user();
946 /* execute any "root postexec = " line */
947 if (*lp_root_postexec(talloc_tos(), lp_sub
, SNUM(conn
))) {
948 char *cmd
= talloc_sub_full(talloc_tos(),
949 lp_const_servicename(SNUM(conn
)),
950 conn
->session_info
->unix_info
->unix_name
,
952 conn
->session_info
->unix_token
->gid
,
953 conn
->session_info
->unix_info
->sanitized_username
,
954 conn
->session_info
->info
->domain_name
,
955 lp_root_postexec(talloc_tos(), lp_sub
, SNUM(conn
)));
956 smbrun(cmd
, NULL
, NULL
);