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 /****************************************************************************
94 Load parameters specific to a connection/service.
95 ****************************************************************************/
97 void set_current_case_sensitive(connection_struct
*conn
, uint16_t flags
)
100 enum remote_arch_types ra_type
;
102 SMB_ASSERT(conn
!= NULL
);
106 if ((conn
== last_conn
) && (last_flags
== flags
)) {
114 * Obey the client case sensitivity requests - only for clients that
116 switch (lp_case_sensitive(snum
)) {
119 * We need this uglyness due to DOS/Win9x clients that lie
120 * about case insensitivity. */
121 ra_type
= get_remote_arch();
122 if (conn
->sconn
->using_smb2
) {
123 conn
->case_sensitive
= false;
124 } else if ((ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
126 * Client can't support per-packet case sensitive
128 conn
->case_sensitive
= false;
130 conn
->case_sensitive
=
131 !(flags
& FLAG_CASELESS_PATHNAMES
);
135 conn
->case_sensitive
= true;
138 conn
->case_sensitive
= false;
144 bool chdir_current_service(connection_struct
*conn
)
146 const struct smb_filename connectpath_fname
= {
147 .base_name
= conn
->connectpath
,
150 char *utok_str
= NULL
;
153 conn
->lastused_count
++;
155 ret
= vfs_ChDir(conn
, &connectpath_fname
);
161 utok_str
= utok_string(talloc_tos(),
162 conn
->session_info
->unix_token
);
163 if (utok_str
== NULL
) {
168 DBG_ERR("vfs_ChDir(%s) failed: %s. Current token: %s\n",
170 strerror(saved_errno
),
173 if (saved_errno
!= 0) {
179 /****************************************************************************
180 do some basic sainity checks on the share.
181 This function modifies dev, ecode.
182 ****************************************************************************/
184 static NTSTATUS
share_sanity_checks(const struct tsocket_address
*remote_address
,
191 raddr
= tsocket_address_inet_addr_string(remote_address
,
194 return NT_STATUS_NO_MEMORY
;
197 if (!lp_snum_ok(snum
) ||
198 !allow_access(lp_hosts_deny(snum
), lp_hosts_allow(snum
),
200 return NT_STATUS_ACCESS_DENIED
;
203 if (dev
[0] == '?' || !dev
[0]) {
204 if (lp_printable(snum
)) {
205 fstrcpy(dev
,"LPT1:");
206 } else if (strequal(lp_fstype(snum
), "IPC")) {
213 if (!strupper_m(dev
)) {
214 DEBUG(2,("strupper_m %s failed\n", dev
));
215 return NT_STATUS_INVALID_PARAMETER
;
218 if (lp_printable(snum
)) {
219 if (!strequal(dev
, "LPT1:")) {
220 return NT_STATUS_BAD_DEVICE_TYPE
;
222 } else if (strequal(lp_fstype(snum
), "IPC")) {
223 if (!strequal(dev
, "IPC")) {
224 return NT_STATUS_BAD_DEVICE_TYPE
;
226 } else if (!strequal(dev
, "A:")) {
227 return NT_STATUS_BAD_DEVICE_TYPE
;
230 /* Behave as a printer if we are supposed to */
231 if (lp_printable(snum
) && (strcmp(dev
, "A:") == 0)) {
232 fstrcpy(dev
, "LPT1:");
239 * Go through lookup_name etc to find the force'd group.
241 * Create a new token from src_token, replacing the primary group sid with the
245 static NTSTATUS
find_forced_group(bool force_user
,
246 int snum
, const char *username
,
247 struct dom_sid
*pgroup_sid
,
250 NTSTATUS result
= NT_STATUS_NO_SUCH_GROUP
;
251 TALLOC_CTX
*frame
= talloc_stackframe();
252 const struct loadparm_substitution
*lp_sub
=
253 loadparm_s3_global_substitution();
254 struct dom_sid group_sid
;
255 enum lsa_SidType type
;
257 bool user_must_be_member
= False
;
260 groupname
= lp_force_group(talloc_tos(), lp_sub
, snum
);
261 if (groupname
== NULL
) {
262 DEBUG(1, ("talloc_strdup failed\n"));
263 result
= NT_STATUS_NO_MEMORY
;
267 if (groupname
[0] == '+') {
268 user_must_be_member
= True
;
272 groupname
= talloc_string_sub(talloc_tos(), groupname
,
273 "%S", lp_const_servicename(snum
));
274 if (groupname
== NULL
) {
275 DEBUG(1, ("talloc_string_sub failed\n"));
276 result
= NT_STATUS_NO_MEMORY
;
280 if (!lookup_name_smbconf(talloc_tos(), groupname
,
281 LOOKUP_NAME_ALL
|LOOKUP_NAME_GROUP
,
282 NULL
, NULL
, &group_sid
, &type
)) {
283 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
288 if ((type
!= SID_NAME_DOM_GRP
) && (type
!= SID_NAME_ALIAS
) &&
289 (type
!= SID_NAME_WKN_GRP
)) {
290 DEBUG(10, ("%s is a %s, not a group\n", groupname
,
291 sid_type_lookup(type
)));
295 if (!sid_to_gid(&group_sid
, &gid
)) {
296 struct dom_sid_buf buf
;
297 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
298 dom_sid_str_buf(&group_sid
, &buf
), groupname
));
303 * If the user has been forced and the forced group starts with a '+',
304 * then we only set the group to be the forced group if the forced
305 * user is a member of that group. Otherwise, the meaning of the '+'
309 if (force_user
&& user_must_be_member
) {
310 if (user_in_group_sid(username
, &group_sid
)) {
311 sid_copy(pgroup_sid
, &group_sid
);
313 DEBUG(3,("Forced group %s for member %s\n",
314 groupname
, username
));
316 DEBUG(0,("find_forced_group: forced user %s is not a member "
317 "of forced group %s. Disallowing access.\n",
318 username
, groupname
));
319 result
= NT_STATUS_MEMBER_NOT_IN_GROUP
;
323 sid_copy(pgroup_sid
, &group_sid
);
325 DEBUG(3,("Forced group %s\n", groupname
));
328 result
= NT_STATUS_OK
;
334 /****************************************************************************
335 Create an auth_session_info structure for a connection_struct
336 ****************************************************************************/
338 static NTSTATUS
create_connection_session_info(struct smbd_server_connection
*sconn
,
339 TALLOC_CTX
*mem_ctx
, int snum
,
340 struct auth_session_info
*session_info
,
341 struct auth_session_info
**presult
)
343 struct auth_session_info
*result
;
345 if (lp_guest_only(snum
)) {
346 return make_session_info_guest(mem_ctx
, presult
);
350 * This is the normal security != share case where we have a
351 * valid vuid from the session setup. */
353 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
354 if (!lp_guest_ok(snum
)) {
355 DBG_WARNING("guest user (from session setup) "
356 "not permitted to access this share "
357 "(%s)\n", lp_const_servicename(snum
));
358 return NT_STATUS_ACCESS_DENIED
;
361 if (!user_ok_token(session_info
->unix_info
->unix_name
,
362 session_info
->info
->domain_name
,
363 session_info
->security_token
, snum
)) {
364 DBG_WARNING("user '%s' (from session setup) not "
365 "permitted to access this share "
367 session_info
->unix_info
->unix_name
,
368 lp_const_servicename(snum
));
369 return NT_STATUS_ACCESS_DENIED
;
373 result
= copy_session_info(mem_ctx
, session_info
);
374 if (result
== NULL
) {
375 return NT_STATUS_NO_MEMORY
;
382 /****************************************************************************
383 Set relevant user and group settings corresponding to force user/group
384 configuration for the given snum.
385 ****************************************************************************/
387 NTSTATUS
set_conn_force_user_group(connection_struct
*conn
, int snum
)
389 const struct loadparm_substitution
*lp_sub
=
390 loadparm_s3_global_substitution();
393 if (*lp_force_user(talloc_tos(), lp_sub
, snum
)) {
396 * Replace conn->session_info with a completely faked up one
397 * from the username we are forced into :-)
401 char *sanitized_username
;
402 struct auth_session_info
*forced_serverinfo
;
405 fuser
= talloc_string_sub(conn
, lp_force_user(talloc_tos(), lp_sub
, snum
), "%S",
406 lp_const_servicename(snum
));
408 return NT_STATUS_NO_MEMORY
;
411 guest
= security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
;
413 status
= make_session_info_from_username(
417 if (!NT_STATUS_IS_OK(status
)) {
421 /* We don't want to replace the original sanitized_username
422 as it is the original user given in the connect attempt.
423 This is used in '%U' substitutions. */
424 sanitized_username
= discard_const_p(char,
425 forced_serverinfo
->unix_info
->sanitized_username
);
426 TALLOC_FREE(sanitized_username
);
427 forced_serverinfo
->unix_info
->sanitized_username
=
428 talloc_move(forced_serverinfo
->unix_info
,
429 &conn
->session_info
->unix_info
->sanitized_username
);
431 TALLOC_FREE(conn
->session_info
);
432 conn
->session_info
= forced_serverinfo
;
434 conn
->force_user
= true;
435 DEBUG(3,("Forced user %s\n", fuser
));
439 * If force group is true, then override
440 * any groupid stored for the connecting user.
443 if (*lp_force_group(talloc_tos(), lp_sub
, snum
)) {
445 status
= find_forced_group(
446 conn
->force_user
, snum
, conn
->session_info
->unix_info
->unix_name
,
447 &conn
->session_info
->security_token
->sids
[1],
448 &conn
->session_info
->unix_token
->gid
);
450 if (!NT_STATUS_IS_OK(status
)) {
455 * We need to cache this gid, to use within
456 * change_to_user() separately from the conn->session_info
457 * struct. We only use conn->session_info directly if
458 * "force_user" was set.
460 conn
->force_group_gid
= conn
->session_info
->unix_token
->gid
;
466 static NTSTATUS
notify_init_sconn(struct smbd_server_connection
*sconn
)
470 if (sconn
->notify_ctx
!= NULL
) {
474 sconn
->notify_ctx
= notify_init(sconn
, sconn
->msg_ctx
,
475 sconn
, notify_callback
);
476 if (sconn
->notify_ctx
== NULL
) {
477 return NT_STATUS_NO_MEMORY
;
480 status
= messaging_register(sconn
->msg_ctx
, sconn
,
481 MSG_SMB_NOTIFY_CANCEL_DELETED
,
482 smbd_notify_cancel_deleted
);
483 if (!NT_STATUS_IS_OK(status
)) {
484 DBG_DEBUG("messaging_register failed: %s\n",
486 TALLOC_FREE(sconn
->notify_ctx
);
490 status
= messaging_register(sconn
->msg_ctx
, sconn
,
491 MSG_SMB_NOTIFY_STARTED
,
492 smbd_notifyd_restarted
);
493 if (!NT_STATUS_IS_OK(status
)) {
494 DBG_DEBUG("messaging_register failed: %s\n",
496 messaging_deregister(sconn
->msg_ctx
,
497 MSG_SMB_NOTIFY_CANCEL_DELETED
, sconn
);
498 TALLOC_FREE(sconn
->notify_ctx
);
505 /****************************************************************************
506 Make a connection, given the snum to connect to, and the vuser of the
507 connecting user if appropriate.
508 ****************************************************************************/
510 static NTSTATUS
make_connection_snum(struct smbXsrv_connection
*xconn
,
511 connection_struct
*conn
,
513 struct smbXsrv_session
*session
,
516 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
517 const struct loadparm_substitution
*lp_sub
=
518 loadparm_s3_global_substitution();
519 struct smb_filename
*smb_fname_cpath
= NULL
;
522 bool on_err_call_dis_hook
= false;
530 status
= share_sanity_checks(sconn
->remote_address
,
531 sconn
->remote_hostname
,
534 if (NT_STATUS_IS_ERR(status
)) {
538 conn
->params
->service
= snum
;
540 status
= create_connection_session_info(sconn
,
541 conn
, snum
, session
->global
->auth_session_info
,
542 &conn
->session_info
);
544 if (!NT_STATUS_IS_OK(status
)) {
545 DEBUG(1, ("create_connection_session_info failed: %s\n",
550 if (lp_guest_only(snum
)) {
551 conn
->force_user
= true;
554 conn
->num_files_open
= 0;
555 conn
->lastused
= conn
->lastused_count
= time(NULL
);
556 conn
->printer
= (strncmp(dev
,"LPT",3) == 0);
557 conn
->ipc
= ( (strncmp(dev
,"IPC",3) == 0) ||
558 ( lp_enable_asu_support() && strequal(dev
,"ADMIN$")) );
560 /* Case options for the share. */
561 conn_setup_case_options(conn
);
563 conn
->encrypt_level
= lp_server_smb_encrypt(snum
);
564 if (conn
->encrypt_level
> SMB_ENCRYPTION_OFF
) {
565 if (lp_server_smb_encrypt(-1) == SMB_ENCRYPTION_OFF
) {
566 if (conn
->encrypt_level
== SMB_ENCRYPTION_REQUIRED
) {
567 DBG_ERR("Service [%s] requires encryption, but "
568 "it is disabled globally!\n",
569 lp_const_servicename(snum
));
570 status
= NT_STATUS_ACCESS_DENIED
;
573 conn
->encrypt_level
= SMB_ENCRYPTION_OFF
;
577 conn
->veto_list
= NULL
;
578 conn
->hide_list
= NULL
;
579 conn
->veto_oplock_list
= NULL
;
580 conn
->aio_write_behind_list
= NULL
;
582 conn
->read_only
= lp_read_only(SNUM(conn
));
584 status
= set_conn_force_user_group(conn
, snum
);
585 if (!NT_STATUS_IS_OK(status
)) {
589 conn
->vuid
= session
->global
->session_wire_id
;
592 char *s
= talloc_sub_full(talloc_tos(),
593 lp_const_servicename(SNUM(conn
)),
594 conn
->session_info
->unix_info
->unix_name
,
596 conn
->session_info
->unix_token
->gid
,
597 conn
->session_info
->unix_info
->sanitized_username
,
598 conn
->session_info
->info
->domain_name
,
599 lp_path(talloc_tos(), lp_sub
, snum
));
601 status
= NT_STATUS_NO_MEMORY
;
605 if (!set_conn_connectpath(conn
,s
)) {
607 status
= NT_STATUS_NO_MEMORY
;
610 DBG_NOTICE("Connect path is '%s' for service [%s]\n", s
,
611 lp_const_servicename(snum
));
616 * Set up the share security descriptor.
617 * NOTE - we use the *INCOMING USER* session_info
618 * here, as does (indirectly) change_to_user(),
619 * which can be called on any incoming packet.
620 * This way we set up the share access based
621 * on the authenticated user, not the forced
624 * https://bugzilla.samba.org/show_bug.cgi?id=9878
627 status
= check_user_share_access(conn
,
628 session
->global
->auth_session_info
,
631 if (!NT_STATUS_IS_OK(status
)) {
635 /* Initialise VFS function pointers */
637 if (!smbd_vfs_init(conn
)) {
638 DBG_ERR("vfs_init failed for service %s\n",
639 lp_const_servicename(snum
));
640 status
= NT_STATUS_BAD_NETWORK_NAME
;
644 /* ROOT Activities: */
645 /* explicitly check widelinks here so that we can correctly warn
647 widelinks_warning(snum
);
650 * Enforce the max connections parameter.
653 if ((lp_max_connections(snum
) > 0)
654 && (count_current_connections(lp_const_servicename(SNUM(conn
)), true) >=
655 lp_max_connections(snum
))) {
657 DBG_WARNING("Max connections (%d) exceeded for %s\n",
658 lp_max_connections(snum
),
659 lp_const_servicename(snum
));
660 status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
664 /* Invoke VFS make connection hook - this must be the first
665 filesystem operation that we do. */
667 if (SMB_VFS_CONNECT(conn
, lp_const_servicename(snum
),
668 conn
->session_info
->unix_info
->unix_name
) < 0) {
669 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
670 lp_const_servicename(snum
), conn
->connectpath
,
672 status
= NT_STATUS_UNSUCCESSFUL
;
676 /* Any error exit after here needs to call the disconnect hook. */
677 on_err_call_dis_hook
= true;
679 if ((!conn
->printer
) && (!conn
->ipc
) &&
680 lp_change_notify()) {
682 status
= notify_init_sconn(sconn
);
683 if (!NT_STATUS_IS_OK(status
)) {
688 if (lp_kernel_oplocks(snum
)) {
689 init_kernel_oplocks(conn
->sconn
);
693 * Fix compatibility issue pointed out by Volker.
694 * We pass the conn->connectpath to the preexec
695 * scripts as a parameter, so attempt to canonicalize
696 * it here before calling the preexec scripts.
697 * We ignore errors here, as it is possible that
698 * the conn->connectpath doesn't exist yet and
699 * the preexec scripts will create them.
702 (void)canonicalize_connect_path(conn
);
704 /* Preexecs are done here as they might make the dir we are to ChDir
706 /* execute any "root preexec = " line */
707 if (*lp_root_preexec(talloc_tos(), lp_sub
, snum
)) {
708 char *cmd
= talloc_sub_full(talloc_tos(),
709 lp_const_servicename(SNUM(conn
)),
710 conn
->session_info
->unix_info
->unix_name
,
712 conn
->session_info
->unix_token
->gid
,
713 conn
->session_info
->unix_info
->sanitized_username
,
714 conn
->session_info
->info
->domain_name
,
715 lp_root_preexec(talloc_tos(), lp_sub
, snum
));
716 DEBUG(5,("cmd=%s\n",cmd
));
717 ret
= smbrun(cmd
, NULL
, NULL
);
719 if (ret
!= 0 && lp_root_preexec_close(snum
)) {
720 DEBUG(1,("root preexec gave %d - failing "
721 "connection\n", ret
));
722 status
= NT_STATUS_ACCESS_DENIED
;
727 /* USER Activites: */
728 if (!change_to_user_and_service(conn
, conn
->vuid
)) {
729 /* No point continuing if they fail the basic checks */
730 DEBUG(0,("Can't become connected user!\n"));
731 status
= NT_STATUS_LOGON_FAILURE
;
738 /* Remember that a different vuid can connect later without these
741 /* Preexecs are done here as they might make the dir we are to ChDir
744 /* execute any "preexec = " line */
745 if (*lp_preexec(talloc_tos(), lp_sub
, snum
)) {
746 char *cmd
= talloc_sub_full(talloc_tos(),
747 lp_const_servicename(SNUM(conn
)),
748 conn
->session_info
->unix_info
->unix_name
,
750 conn
->session_info
->unix_token
->gid
,
751 conn
->session_info
->unix_info
->sanitized_username
,
752 conn
->session_info
->info
->domain_name
,
753 lp_preexec(talloc_tos(), lp_sub
, snum
));
754 ret
= smbrun(cmd
, NULL
, NULL
);
756 if (ret
!= 0 && lp_preexec_close(snum
)) {
757 DEBUG(1,("preexec gave %d - failing connection\n",
759 status
= NT_STATUS_ACCESS_DENIED
;
764 #ifdef WITH_FAKE_KASERVER
765 if (lp_afs_share(snum
)) {
771 * we've finished with the user stuff - go back to root
772 * so the SMB_VFS_STAT call will only fail on path errors,
773 * not permission problems.
775 change_to_root_user();
776 /* ROOT Activites: */
779 * Canonicalise the connect
780 * path here to ensure we don't have any symlinks in the
781 * connectpath. We will be checking all paths on this connection are
782 * below this directory. We must do this after the VFS init as we
783 * depend on the realpath() pointer in the vfs table. JRA.
785 ok
= canonicalize_connect_path(conn
);
787 DBG_ERR("canonicalize_connect_path failed "
788 "for service %s, path %s\n",
789 lp_const_servicename(snum
),
791 status
= NT_STATUS_BAD_NETWORK_NAME
;
795 /* Add veto/hide lists */
796 if (!IS_IPC(conn
) && !IS_PRINT(conn
)) {
797 set_namearray( &conn
->veto_list
,
798 lp_veto_files(talloc_tos(), lp_sub
, snum
));
799 set_namearray( &conn
->hide_list
,
800 lp_hide_files(talloc_tos(), lp_sub
, snum
));
801 set_namearray( &conn
->veto_oplock_list
,
802 lp_veto_oplock_files(talloc_tos(), lp_sub
, snum
));
803 set_namearray( &conn
->aio_write_behind_list
,
804 lp_aio_write_behind(talloc_tos(), lp_sub
, snum
));
806 smb_fname_cpath
= synthetic_smb_fname(talloc_tos(),
812 if (smb_fname_cpath
== NULL
) {
813 status
= NT_STATUS_NO_MEMORY
;
817 /* win2000 does not check the permissions on the directory
818 during the tree connect, instead relying on permission
819 check during individual operations. To match this behaviour
820 I have disabled this chdir check (tridge) */
821 /* the alternative is just to check the directory exists */
823 if ((ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
)) != 0 ||
824 !S_ISDIR(smb_fname_cpath
->st
.st_ex_mode
)) {
825 if (ret
== 0 && !S_ISDIR(smb_fname_cpath
->st
.st_ex_mode
)) {
826 DBG_ERR("'%s' is not a directory, when connecting to "
827 "[%s]\n", conn
->connectpath
,
828 lp_const_servicename(snum
));
830 DBG_ERR("'%s' does not exist or permission denied "
831 "when connecting to [%s] Error was %s\n",
833 lp_const_servicename(snum
),
836 status
= NT_STATUS_BAD_NETWORK_NAME
;
839 conn
->base_share_dev
= smb_fname_cpath
->st
.st_ex_dev
;
841 /* Figure out the characteristics of the underlying filesystem. This
842 * assumes that all the filesystem mounted within a share path have
843 * the same characteristics, which is likely but not guaranteed.
846 conn
->fs_capabilities
= SMB_VFS_FS_CAPABILITIES(conn
, &conn
->ts_res
);
849 * Print out the 'connected as' stuff here as we need
850 * to know the effective uid and gid we will be using
851 * (at least initially).
854 if( DEBUGLVL( IS_IPC(conn
) ? 3 : 2 ) ) {
855 dbgtext( "%s (%s) ", get_remote_machine_name(),
856 tsocket_address_string(conn
->sconn
->remote_address
,
858 dbgtext( "%s", srv_is_signing_active(xconn
) ? "signed " : "");
859 dbgtext( "connect to service %s ",
860 lp_const_servicename(snum
) );
861 dbgtext( "initially as user %s ",
862 conn
->session_info
->unix_info
->unix_name
);
863 dbgtext( "(uid=%d, gid=%d) ", (int)effuid
, (int)effgid
);
864 dbgtext( "(pid %d)\n", (int)getpid() );
867 conn
->tcon_done
= true;
872 TALLOC_FREE(smb_fname_cpath
);
873 /* We must exit this function as root. */
874 if (geteuid() != 0) {
875 change_to_root_user();
877 if (on_err_call_dis_hook
) {
878 /* Call VFS disconnect hook */
879 SMB_VFS_DISCONNECT(conn
);
884 /****************************************************************************
885 Make a connection to a service from SMB1. Internal interface.
886 ****************************************************************************/
888 static connection_struct
*make_connection_smb1(struct smb_request
*req
,
894 const struct loadparm_substitution
*lp_sub
=
895 loadparm_s3_global_substitution();
896 struct smbXsrv_tcon
*tcon
;
898 struct connection_struct
*conn
;
900 status
= smb1srv_tcon_create(req
->xconn
, now
, &tcon
);
901 if (!NT_STATUS_IS_OK(status
)) {
902 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
908 conn
= conn_new(req
->sconn
);
912 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
913 *pstatus
= NT_STATUS_INSUFFICIENT_RESOURCES
;
917 conn
->cnum
= tcon
->global
->tcon_wire_id
;
920 *pstatus
= make_connection_snum(req
->xconn
,
925 if (!NT_STATUS_IS_OK(*pstatus
)) {
931 tcon
->global
->share_name
= lp_servicename(tcon
->global
, lp_sub
, SNUM(conn
));
932 if (tcon
->global
->share_name
== NULL
) {
935 *pstatus
= NT_STATUS_NO_MEMORY
;
938 tcon
->global
->session_global_id
=
939 req
->session
->global
->session_global_id
;
941 tcon
->compat
= talloc_move(tcon
, &conn
);
942 tcon
->status
= NT_STATUS_OK
;
944 *pstatus
= smbXsrv_tcon_update(tcon
);
945 if (!NT_STATUS_IS_OK(*pstatus
)) {
953 /****************************************************************************
954 Make a connection to a service from SMB2. External SMB2 interface.
955 We must set cnum before claiming connection.
956 ****************************************************************************/
958 connection_struct
*make_connection_smb2(struct smbd_smb2_request
*req
,
959 struct smbXsrv_tcon
*tcon
,
964 struct smbd_server_connection
*sconn
= req
->sconn
;
965 connection_struct
*conn
= conn_new(sconn
);
967 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
968 *pstatus
= NT_STATUS_INSUFFICIENT_RESOURCES
;
972 conn
->cnum
= tcon
->global
->tcon_wire_id
;
975 *pstatus
= make_connection_snum(req
->xconn
,
980 if (!NT_STATUS_IS_OK(*pstatus
)) {
987 /****************************************************************************
988 Make a connection to a service. External SMB1 interface.
991 ****************************************************************************/
993 connection_struct
*make_connection(struct smb_request
*req
,
995 const char *service_in
,
996 const char *pdev
, uint64_t vuid
,
999 struct smbd_server_connection
*sconn
= req
->sconn
;
1000 struct smbXsrv_session
*session
= req
->session
;
1001 const struct loadparm_substitution
*lp_sub
=
1002 loadparm_s3_global_substitution();
1004 char *service
= NULL
;
1010 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1012 if (!non_root_mode() && (euid
= geteuid()) != 0) {
1013 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1014 "(%u)\n", (unsigned int)euid
));
1015 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1018 if (conn_num_open(sconn
) > 2047) {
1019 *status
= NT_STATUS_INSUFF_SERVER_RESOURCES
;
1023 if (session
== NULL
) {
1024 DEBUG(1,("make_connection: refusing to connect with "
1025 "no session setup\n"));
1026 *status
= NT_STATUS_ACCESS_DENIED
;
1030 /* Logic to try and connect to the correct [homes] share, preferably
1031 without too many getpwnam() lookups. This is particulary nasty for
1032 winbind usernames, where the share name isn't the same as unix
1036 if (strequal(service_in
,HOMES_NAME
)) {
1037 if (session
->homes_snum
== -1) {
1038 DEBUG(2, ("[homes] share not available for "
1039 "this user because it was not found "
1040 "or created at session setup "
1042 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1045 DEBUG(5, ("making a connection to [homes] service "
1046 "created at session setup time\n"));
1047 return make_connection_smb1(req
, now
,
1048 session
->homes_snum
,
1050 } else if ((session
->homes_snum
!= -1)
1051 && strequal(service_in
,
1052 lp_const_servicename(session
->homes_snum
))) {
1053 DEBUG(5, ("making a connection to 'homes' service [%s] "
1054 "created at session setup time\n", service_in
));
1055 return make_connection_smb1(req
, now
,
1056 session
->homes_snum
,
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(), lp_sub
, snum
) != '\0')) {
1097 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1098 "(pointing to %s)\n",
1099 service
, lp_msdfs_proxy(talloc_tos(), lp_sub
, 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
,
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
};
1118 const struct loadparm_substitution
*lp_sub
=
1119 loadparm_s3_global_substitution();
1121 file_close_conn(conn
);
1123 change_to_root_user();
1125 DEBUG(IS_IPC(conn
)?3:2, ("%s (%s) closed connection to service %s\n",
1126 get_remote_machine_name(),
1127 tsocket_address_string(conn
->sconn
->remote_address
,
1129 lp_const_servicename(SNUM(conn
))));
1131 /* make sure we leave the directory available for unmount */
1132 vfs_ChDir(conn
, &root_fname
);
1134 /* Call VFS disconnect hook */
1135 SMB_VFS_DISCONNECT(conn
);
1137 /* execute any "postexec = " line */
1138 if (*lp_postexec(talloc_tos(), lp_sub
, SNUM(conn
)) &&
1139 change_to_user_and_service(conn
, vuid
)) {
1140 char *cmd
= talloc_sub_full(talloc_tos(),
1141 lp_const_servicename(SNUM(conn
)),
1142 conn
->session_info
->unix_info
->unix_name
,
1144 conn
->session_info
->unix_token
->gid
,
1145 conn
->session_info
->unix_info
->sanitized_username
,
1146 conn
->session_info
->info
->domain_name
,
1147 lp_postexec(talloc_tos(), lp_sub
, SNUM(conn
)));
1148 smbrun(cmd
, NULL
, NULL
);
1150 change_to_root_user();
1153 change_to_root_user();
1154 /* execute any "root postexec = " line */
1155 if (*lp_root_postexec(talloc_tos(), lp_sub
, SNUM(conn
))) {
1156 char *cmd
= talloc_sub_full(talloc_tos(),
1157 lp_const_servicename(SNUM(conn
)),
1158 conn
->session_info
->unix_info
->unix_name
,
1160 conn
->session_info
->unix_token
->gid
,
1161 conn
->session_info
->unix_info
->sanitized_username
,
1162 conn
->session_info
->info
->domain_name
,
1163 lp_root_postexec(talloc_tos(), lp_sub
, SNUM(conn
)));
1164 smbrun(cmd
, NULL
, NULL
);