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 DBG_DEBUG("service %s, connectpath = %s\n",
69 lp_const_servicename(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 /****************************************************************************
172 do some basic sainity checks on the share.
173 This function modifies dev, ecode.
174 ****************************************************************************/
176 static NTSTATUS
share_sanity_checks(const struct tsocket_address
*remote_address
,
183 raddr
= tsocket_address_inet_addr_string(remote_address
,
186 return NT_STATUS_NO_MEMORY
;
189 if (!lp_snum_ok(snum
) ||
190 !allow_access(lp_hosts_deny(snum
), lp_hosts_allow(snum
),
192 return NT_STATUS_ACCESS_DENIED
;
195 if (dev
[0] == '?' || !dev
[0]) {
196 if (lp_printable(snum
)) {
197 fstrcpy(dev
,"LPT1:");
198 } else if (strequal(lp_fstype(snum
), "IPC")) {
205 if (!strupper_m(dev
)) {
206 DEBUG(2,("strupper_m %s failed\n", dev
));
207 return NT_STATUS_INVALID_PARAMETER
;
210 if (lp_printable(snum
)) {
211 if (!strequal(dev
, "LPT1:")) {
212 return NT_STATUS_BAD_DEVICE_TYPE
;
214 } else if (strequal(lp_fstype(snum
), "IPC")) {
215 if (!strequal(dev
, "IPC")) {
216 return NT_STATUS_BAD_DEVICE_TYPE
;
218 } else if (!strequal(dev
, "A:")) {
219 return NT_STATUS_BAD_DEVICE_TYPE
;
222 /* Behave as a printer if we are supposed to */
223 if (lp_printable(snum
) && (strcmp(dev
, "A:") == 0)) {
224 fstrcpy(dev
, "LPT1:");
231 * Go through lookup_name etc to find the force'd group.
233 * Create a new token from src_token, replacing the primary group sid with the
237 static NTSTATUS
find_forced_group(bool force_user
,
238 int snum
, const char *username
,
239 struct dom_sid
*pgroup_sid
,
242 NTSTATUS result
= NT_STATUS_NO_SUCH_GROUP
;
243 TALLOC_CTX
*frame
= talloc_stackframe();
244 struct dom_sid group_sid
;
245 enum lsa_SidType type
;
247 bool user_must_be_member
= False
;
250 groupname
= lp_force_group(talloc_tos(), snum
);
251 if (groupname
== NULL
) {
252 DEBUG(1, ("talloc_strdup failed\n"));
253 result
= NT_STATUS_NO_MEMORY
;
257 if (groupname
[0] == '+') {
258 user_must_be_member
= True
;
262 groupname
= talloc_string_sub(talloc_tos(), groupname
,
263 "%S", lp_const_servicename(snum
));
264 if (groupname
== NULL
) {
265 DEBUG(1, ("talloc_string_sub failed\n"));
266 result
= NT_STATUS_NO_MEMORY
;
270 if (!lookup_name_smbconf(talloc_tos(), groupname
,
271 LOOKUP_NAME_ALL
|LOOKUP_NAME_GROUP
,
272 NULL
, NULL
, &group_sid
, &type
)) {
273 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
278 if ((type
!= SID_NAME_DOM_GRP
) && (type
!= SID_NAME_ALIAS
) &&
279 (type
!= SID_NAME_WKN_GRP
)) {
280 DEBUG(10, ("%s is a %s, not a group\n", groupname
,
281 sid_type_lookup(type
)));
285 if (!sid_to_gid(&group_sid
, &gid
)) {
286 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
287 sid_string_dbg(&group_sid
), groupname
));
292 * If the user has been forced and the forced group starts with a '+',
293 * then we only set the group to be the forced group if the forced
294 * user is a member of that group. Otherwise, the meaning of the '+'
298 if (force_user
&& user_must_be_member
) {
299 if (user_in_group_sid(username
, &group_sid
)) {
300 sid_copy(pgroup_sid
, &group_sid
);
302 DEBUG(3,("Forced group %s for member %s\n",
303 groupname
, username
));
305 DEBUG(0,("find_forced_group: forced user %s is not a member "
306 "of forced group %s. Disallowing access.\n",
307 username
, groupname
));
308 result
= NT_STATUS_MEMBER_NOT_IN_GROUP
;
312 sid_copy(pgroup_sid
, &group_sid
);
314 DEBUG(3,("Forced group %s\n", groupname
));
317 result
= NT_STATUS_OK
;
323 /****************************************************************************
324 Create an auth_session_info structure for a connection_struct
325 ****************************************************************************/
327 static NTSTATUS
create_connection_session_info(struct smbd_server_connection
*sconn
,
328 TALLOC_CTX
*mem_ctx
, int snum
,
329 struct auth_session_info
*session_info
,
330 struct auth_session_info
**presult
)
332 struct auth_session_info
*result
;
334 if (lp_guest_only(snum
)) {
335 return make_session_info_guest(mem_ctx
, presult
);
339 * This is the normal security != share case where we have a
340 * valid vuid from the session setup. */
342 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
343 if (!lp_guest_ok(snum
)) {
344 DBG_WARNING("guest user (from session setup) "
345 "not permitted to access this share "
346 "(%s)\n", lp_const_servicename(snum
));
347 return NT_STATUS_ACCESS_DENIED
;
350 if (!user_ok_token(session_info
->unix_info
->unix_name
,
351 session_info
->info
->domain_name
,
352 session_info
->security_token
, snum
)) {
353 DBG_WARNING("user '%s' (from session setup) not "
354 "permitted to access this share "
356 session_info
->unix_info
->unix_name
,
357 lp_const_servicename(snum
));
358 return NT_STATUS_ACCESS_DENIED
;
362 result
= copy_session_info(mem_ctx
, session_info
);
363 if (result
== NULL
) {
364 return NT_STATUS_NO_MEMORY
;
371 /****************************************************************************
372 Set relevant user and group settings corresponding to force user/group
373 configuration for the given snum.
374 ****************************************************************************/
376 NTSTATUS
set_conn_force_user_group(connection_struct
*conn
, int snum
)
380 if (*lp_force_user(talloc_tos(), snum
)) {
383 * Replace conn->session_info with a completely faked up one
384 * from the username we are forced into :-)
388 char *sanitized_username
;
389 struct auth_session_info
*forced_serverinfo
;
392 fuser
= talloc_string_sub(conn
, lp_force_user(talloc_tos(), snum
), "%S",
393 lp_const_servicename(snum
));
395 return NT_STATUS_NO_MEMORY
;
398 guest
= security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
;
400 status
= make_session_info_from_username(
404 if (!NT_STATUS_IS_OK(status
)) {
408 /* We don't want to replace the original sanitized_username
409 as it is the original user given in the connect attempt.
410 This is used in '%U' substitutions. */
411 sanitized_username
= discard_const_p(char,
412 forced_serverinfo
->unix_info
->sanitized_username
);
413 TALLOC_FREE(sanitized_username
);
414 forced_serverinfo
->unix_info
->sanitized_username
=
415 talloc_move(forced_serverinfo
->unix_info
,
416 &conn
->session_info
->unix_info
->sanitized_username
);
418 TALLOC_FREE(conn
->session_info
);
419 conn
->session_info
= forced_serverinfo
;
421 conn
->force_user
= true;
422 DEBUG(3,("Forced user %s\n", fuser
));
426 * If force group is true, then override
427 * any groupid stored for the connecting user.
430 if (*lp_force_group(talloc_tos(), snum
)) {
432 status
= find_forced_group(
433 conn
->force_user
, snum
, conn
->session_info
->unix_info
->unix_name
,
434 &conn
->session_info
->security_token
->sids
[1],
435 &conn
->session_info
->unix_token
->gid
);
437 if (!NT_STATUS_IS_OK(status
)) {
442 * We need to cache this gid, to use within
443 * change_to_user() separately from the conn->session_info
444 * struct. We only use conn->session_info directly if
445 * "force_user" was set.
447 conn
->force_group_gid
= conn
->session_info
->unix_token
->gid
;
453 static NTSTATUS
notify_init_sconn(struct smbd_server_connection
*sconn
)
457 if (sconn
->notify_ctx
!= NULL
) {
461 sconn
->notify_ctx
= notify_init(sconn
, sconn
->msg_ctx
,
462 sconn
, notify_callback
);
463 if (sconn
->notify_ctx
== NULL
) {
464 return NT_STATUS_NO_MEMORY
;
467 status
= messaging_register(sconn
->msg_ctx
, sconn
,
468 MSG_SMB_NOTIFY_CANCEL_DELETED
,
469 smbd_notify_cancel_deleted
);
470 if (!NT_STATUS_IS_OK(status
)) {
471 DBG_DEBUG("messaging_register failed: %s\n",
473 TALLOC_FREE(sconn
->notify_ctx
);
477 status
= messaging_register(sconn
->msg_ctx
, sconn
,
478 MSG_SMB_NOTIFY_STARTED
,
479 smbd_notifyd_restarted
);
480 if (!NT_STATUS_IS_OK(status
)) {
481 DBG_DEBUG("messaging_register failed: %s\n",
483 messaging_deregister(sconn
->msg_ctx
,
484 MSG_SMB_NOTIFY_CANCEL_DELETED
, sconn
);
485 TALLOC_FREE(sconn
->notify_ctx
);
492 /****************************************************************************
493 Make a connection, given the snum to connect to, and the vuser of the
494 connecting user if appropriate.
495 ****************************************************************************/
497 static NTSTATUS
make_connection_snum(struct smbXsrv_connection
*xconn
,
498 connection_struct
*conn
,
499 int snum
, struct user_struct
*vuser
,
502 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
503 struct smb_filename
*smb_fname_cpath
= NULL
;
506 bool on_err_call_dis_hook
= false;
513 status
= share_sanity_checks(sconn
->remote_address
,
514 sconn
->remote_hostname
,
517 if (NT_STATUS_IS_ERR(status
)) {
521 conn
->params
->service
= snum
;
523 status
= create_connection_session_info(sconn
,
524 conn
, snum
, vuser
->session_info
,
525 &conn
->session_info
);
527 if (!NT_STATUS_IS_OK(status
)) {
528 DEBUG(1, ("create_connection_session_info failed: %s\n",
533 if (lp_guest_only(snum
)) {
534 conn
->force_user
= true;
537 conn
->num_files_open
= 0;
538 conn
->lastused
= conn
->lastused_count
= time(NULL
);
539 conn
->printer
= (strncmp(dev
,"LPT",3) == 0);
540 conn
->ipc
= ( (strncmp(dev
,"IPC",3) == 0) ||
541 ( lp_enable_asu_support() && strequal(dev
,"ADMIN$")) );
543 /* Case options for the share. */
544 if (lp_case_sensitive(snum
) == Auto
) {
545 /* We will be setting this per packet. Set to be case
546 * insensitive for now. */
547 conn
->case_sensitive
= False
;
549 conn
->case_sensitive
= (bool)lp_case_sensitive(snum
);
552 conn
->case_preserve
= lp_preserve_case(snum
);
553 conn
->short_case_preserve
= lp_short_preserve_case(snum
);
555 conn
->encrypt_level
= lp_smb_encrypt(snum
);
556 if (conn
->encrypt_level
> SMB_SIGNING_OFF
) {
557 if (lp_smb_encrypt(-1) == SMB_SIGNING_OFF
) {
558 if (conn
->encrypt_level
== SMB_SIGNING_REQUIRED
) {
559 DBG_ERR("Service [%s] requires encryption, but "
560 "it is disabled globally!\n",
561 lp_const_servicename(snum
));
562 status
= NT_STATUS_ACCESS_DENIED
;
565 conn
->encrypt_level
= SMB_SIGNING_OFF
;
569 conn
->veto_list
= NULL
;
570 conn
->hide_list
= NULL
;
571 conn
->veto_oplock_list
= NULL
;
572 conn
->aio_write_behind_list
= NULL
;
574 conn
->read_only
= lp_read_only(SNUM(conn
));
576 status
= set_conn_force_user_group(conn
, snum
);
577 if (!NT_STATUS_IS_OK(status
)) {
581 conn
->vuid
= vuser
->vuid
;
584 char *s
= talloc_sub_advanced(talloc_tos(),
585 lp_const_servicename(SNUM(conn
)),
586 conn
->session_info
->unix_info
->unix_name
,
588 conn
->session_info
->unix_token
->gid
,
589 conn
->session_info
->unix_info
->sanitized_username
,
590 conn
->session_info
->info
->domain_name
,
591 lp_path(talloc_tos(), snum
));
593 status
= NT_STATUS_NO_MEMORY
;
597 if (!set_conn_connectpath(conn
,s
)) {
599 status
= NT_STATUS_NO_MEMORY
;
602 DBG_NOTICE("Connect path is '%s' for service [%s]\n", s
,
603 lp_const_servicename(snum
));
608 * Set up the share security descriptor.
609 * NOTE - we use the *INCOMING USER* session_info
610 * here, as does (indirectly) change_to_user(),
611 * which can be called on any incoming packet.
612 * This way we set up the share access based
613 * on the authenticated user, not the forced
616 * https://bugzilla.samba.org/show_bug.cgi?id=9878
619 status
= check_user_share_access(conn
,
623 if (!NT_STATUS_IS_OK(status
)) {
627 /* Initialise VFS function pointers */
629 if (!smbd_vfs_init(conn
)) {
630 DBG_ERR("vfs_init failed for service %s\n",
631 lp_const_servicename(snum
));
632 status
= NT_STATUS_BAD_NETWORK_NAME
;
636 /* ROOT Activities: */
637 /* explicitly check widelinks here so that we can correctly warn
639 widelinks_warning(snum
);
642 * Enforce the max connections parameter.
645 if ((lp_max_connections(snum
) > 0)
646 && (count_current_connections(lp_const_servicename(SNUM(conn
)), true) >=
647 lp_max_connections(snum
))) {
649 DBG_WARNING("Max connections (%d) exceeded for %s\n",
650 lp_max_connections(snum
),
651 lp_const_servicename(snum
));
652 status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
656 /* Invoke VFS make connection hook - this must be the first
657 filesystem operation that we do. */
659 if (SMB_VFS_CONNECT(conn
, lp_const_servicename(snum
),
660 conn
->session_info
->unix_info
->unix_name
) < 0) {
661 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
662 lp_const_servicename(snum
), conn
->connectpath
,
664 status
= NT_STATUS_UNSUCCESSFUL
;
668 /* Any error exit after here needs to call the disconnect hook. */
669 on_err_call_dis_hook
= true;
671 if ((!conn
->printer
) && (!conn
->ipc
) &&
672 lp_change_notify()) {
674 status
= notify_init_sconn(sconn
);
675 if (!NT_STATUS_IS_OK(status
)) {
680 if (lp_kernel_oplocks(snum
)) {
681 init_kernel_oplocks(conn
->sconn
);
685 * Fix compatibility issue pointed out by Volker.
686 * We pass the conn->connectpath to the preexec
687 * scripts as a parameter, so attempt to canonicalize
688 * it here before calling the preexec scripts.
689 * We ignore errors here, as it is possible that
690 * the conn->connectpath doesn't exist yet and
691 * the preexec scripts will create them.
694 (void)canonicalize_connect_path(conn
);
696 /* Preexecs are done here as they might make the dir we are to ChDir
698 /* execute any "root preexec = " line */
699 if (*lp_root_preexec(talloc_tos(), snum
)) {
700 char *cmd
= talloc_sub_advanced(talloc_tos(),
701 lp_const_servicename(SNUM(conn
)),
702 conn
->session_info
->unix_info
->unix_name
,
704 conn
->session_info
->unix_token
->gid
,
705 conn
->session_info
->unix_info
->sanitized_username
,
706 conn
->session_info
->info
->domain_name
,
707 lp_root_preexec(talloc_tos(), snum
));
708 DEBUG(5,("cmd=%s\n",cmd
));
709 ret
= smbrun(cmd
, NULL
, NULL
);
711 if (ret
!= 0 && lp_root_preexec_close(snum
)) {
712 DEBUG(1,("root preexec gave %d - failing "
713 "connection\n", ret
));
714 status
= NT_STATUS_ACCESS_DENIED
;
719 /* USER Activites: */
720 if (!change_to_user(conn
, conn
->vuid
)) {
721 /* No point continuing if they fail the basic checks */
722 DEBUG(0,("Can't become connected user!\n"));
723 status
= NT_STATUS_LOGON_FAILURE
;
730 /* Remember that a different vuid can connect later without these
733 /* Preexecs are done here as they might make the dir we are to ChDir
736 /* execute any "preexec = " line */
737 if (*lp_preexec(talloc_tos(), snum
)) {
738 char *cmd
= talloc_sub_advanced(talloc_tos(),
739 lp_const_servicename(SNUM(conn
)),
740 conn
->session_info
->unix_info
->unix_name
,
742 conn
->session_info
->unix_token
->gid
,
743 conn
->session_info
->unix_info
->sanitized_username
,
744 conn
->session_info
->info
->domain_name
,
745 lp_preexec(talloc_tos(), snum
));
746 ret
= smbrun(cmd
, NULL
, NULL
);
748 if (ret
!= 0 && lp_preexec_close(snum
)) {
749 DEBUG(1,("preexec gave %d - failing connection\n",
751 status
= NT_STATUS_ACCESS_DENIED
;
756 #ifdef WITH_FAKE_KASERVER
757 if (lp_afs_share(snum
)) {
763 * we've finished with the user stuff - go back to root
764 * so the SMB_VFS_STAT call will only fail on path errors,
765 * not permission problems.
767 change_to_root_user();
768 /* ROOT Activites: */
771 * If widelinks are disallowed we need to canonicalise the connect
772 * path here to ensure we don't have any symlinks in the
773 * connectpath. We will be checking all paths on this connection are
774 * below this directory. We must do this after the VFS init as we
775 * depend on the realpath() pointer in the vfs table. JRA.
777 if (!lp_widelinks(snum
)) {
778 if (!canonicalize_connect_path(conn
)) {
779 DBG_ERR("canonicalize_connect_path failed "
780 "for service %s, path %s\n",
781 lp_const_servicename(snum
),
783 status
= NT_STATUS_BAD_NETWORK_NAME
;
788 /* Add veto/hide lists */
789 if (!IS_IPC(conn
) && !IS_PRINT(conn
)) {
790 set_namearray( &conn
->veto_list
,
791 lp_veto_files(talloc_tos(), snum
));
792 set_namearray( &conn
->hide_list
,
793 lp_hide_files(talloc_tos(), snum
));
794 set_namearray( &conn
->veto_oplock_list
,
795 lp_veto_oplock_files(talloc_tos(), snum
));
796 set_namearray( &conn
->aio_write_behind_list
,
797 lp_aio_write_behind(talloc_tos(), snum
));
799 smb_fname_cpath
= synthetic_smb_fname(talloc_tos(),
804 if (smb_fname_cpath
== NULL
) {
805 status
= NT_STATUS_NO_MEMORY
;
809 /* win2000 does not check the permissions on the directory
810 during the tree connect, instead relying on permission
811 check during individual operations. To match this behaviour
812 I have disabled this chdir check (tridge) */
813 /* the alternative is just to check the directory exists */
815 if ((ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
)) != 0 ||
816 !S_ISDIR(smb_fname_cpath
->st
.st_ex_mode
)) {
817 if (ret
== 0 && !S_ISDIR(smb_fname_cpath
->st
.st_ex_mode
)) {
818 DBG_ERR("'%s' is not a directory, when connecting to "
819 "[%s]\n", conn
->connectpath
,
820 lp_const_servicename(snum
));
822 DBG_ERR("'%s' does not exist or permission denied "
823 "when connecting to [%s] Error was %s\n",
825 lp_const_servicename(snum
),
828 status
= NT_STATUS_BAD_NETWORK_NAME
;
831 conn
->base_share_dev
= smb_fname_cpath
->st
.st_ex_dev
;
833 talloc_free(conn
->origpath
);
834 conn
->origpath
= talloc_strdup(conn
, conn
->connectpath
);
836 /* Figure out the characteristics of the underlying filesystem. This
837 * assumes that all the filesystem mounted withing a share path have
838 * the same characteristics, which is likely but not guaranteed.
841 conn
->fs_capabilities
= SMB_VFS_FS_CAPABILITIES(conn
, &conn
->ts_res
);
844 * Print out the 'connected as' stuff here as we need
845 * to know the effective uid and gid we will be using
846 * (at least initially).
849 if( DEBUGLVL( IS_IPC(conn
) ? 3 : 2 ) ) {
850 dbgtext( "%s (%s) ", get_remote_machine_name(),
851 tsocket_address_string(conn
->sconn
->remote_address
,
853 dbgtext( "%s", srv_is_signing_active(xconn
) ? "signed " : "");
854 dbgtext( "connect to service %s ",
855 lp_const_servicename(snum
) );
856 dbgtext( "initially as user %s ",
857 conn
->session_info
->unix_info
->unix_name
);
858 dbgtext( "(uid=%d, gid=%d) ", (int)effuid
, (int)effgid
);
859 dbgtext( "(pid %d)\n", (int)getpid() );
862 conn
->tcon_done
= true;
867 TALLOC_FREE(smb_fname_cpath
);
868 /* We must exit this function as root. */
869 if (geteuid() != 0) {
870 change_to_root_user();
872 if (on_err_call_dis_hook
) {
873 /* Call VFS disconnect hook */
874 SMB_VFS_DISCONNECT(conn
);
879 /****************************************************************************
880 Make a connection to a service from SMB1. Internal interface.
881 ****************************************************************************/
883 static connection_struct
*make_connection_smb1(struct smb_request
*req
,
885 int snum
, struct user_struct
*vuser
,
889 struct smbXsrv_tcon
*tcon
;
891 struct connection_struct
*conn
;
893 status
= smb1srv_tcon_create(req
->xconn
, now
, &tcon
);
894 if (!NT_STATUS_IS_OK(status
)) {
895 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
901 conn
= conn_new(req
->sconn
);
905 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
906 *pstatus
= NT_STATUS_INSUFFICIENT_RESOURCES
;
910 conn
->cnum
= tcon
->global
->tcon_wire_id
;
913 *pstatus
= make_connection_snum(req
->xconn
,
918 if (!NT_STATUS_IS_OK(*pstatus
)) {
924 tcon
->global
->share_name
= lp_servicename(tcon
->global
, SNUM(conn
));
925 if (tcon
->global
->share_name
== NULL
) {
928 *pstatus
= NT_STATUS_NO_MEMORY
;
931 tcon
->global
->session_global_id
=
932 vuser
->session
->global
->session_global_id
;
934 tcon
->compat
= talloc_move(tcon
, &conn
);
935 tcon
->status
= NT_STATUS_OK
;
937 *pstatus
= smbXsrv_tcon_update(tcon
);
938 if (!NT_STATUS_IS_OK(*pstatus
)) {
946 /****************************************************************************
947 Make a connection to a service from SMB2. External SMB2 interface.
948 We must set cnum before claiming connection.
949 ****************************************************************************/
951 connection_struct
*make_connection_smb2(struct smbd_smb2_request
*req
,
952 struct smbXsrv_tcon
*tcon
,
954 struct user_struct
*vuser
,
958 struct smbd_server_connection
*sconn
= req
->sconn
;
959 connection_struct
*conn
= conn_new(sconn
);
961 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
962 *pstatus
= NT_STATUS_INSUFFICIENT_RESOURCES
;
966 conn
->cnum
= tcon
->global
->tcon_wire_id
;
969 *pstatus
= make_connection_snum(req
->xconn
,
974 if (!NT_STATUS_IS_OK(*pstatus
)) {
981 /****************************************************************************
982 Make a connection to a service. External SMB1 interface.
985 ****************************************************************************/
987 connection_struct
*make_connection(struct smb_request
*req
,
989 const char *service_in
,
990 const char *pdev
, uint64_t vuid
,
993 struct smbd_server_connection
*sconn
= req
->sconn
;
995 struct user_struct
*vuser
= NULL
;
996 char *service
= NULL
;
1002 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1004 if (!non_root_mode() && (euid
= geteuid()) != 0) {
1005 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1006 "(%u)\n", (unsigned int)euid
));
1007 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1010 if (conn_num_open(sconn
) > 2047) {
1011 *status
= NT_STATUS_INSUFF_SERVER_RESOURCES
;
1015 vuser
= get_valid_user_struct(sconn
, vuid
);
1017 DEBUG(1,("make_connection: refusing to connect with "
1018 "no session setup\n"));
1019 *status
= NT_STATUS_ACCESS_DENIED
;
1023 /* Logic to try and connect to the correct [homes] share, preferably
1024 without too many getpwnam() lookups. This is particulary nasty for
1025 winbind usernames, where the share name isn't the same as unix
1028 The snum of the homes share is stored on the vuser at session setup
1032 if (strequal(service_in
,HOMES_NAME
)) {
1033 if (vuser
->homes_snum
== -1) {
1034 DEBUG(2, ("[homes] share not available for "
1035 "this user because it was not found "
1036 "or created at session setup "
1038 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1041 DEBUG(5, ("making a connection to [homes] service "
1042 "created at session setup time\n"));
1043 return make_connection_smb1(req
, now
,
1047 } else if ((vuser
->homes_snum
!= -1)
1048 && strequal(service_in
,
1049 lp_const_servicename(vuser
->homes_snum
))) {
1050 DEBUG(5, ("making a connection to 'homes' service [%s] "
1051 "created at session setup time\n", service_in
));
1052 return make_connection_smb1(req
, now
,
1058 service
= talloc_strdup(talloc_tos(), service_in
);
1060 *status
= NT_STATUS_NO_MEMORY
;
1064 if (!strlower_m(service
)) {
1065 DEBUG(2, ("strlower_m %s failed\n", service
));
1066 *status
= NT_STATUS_INVALID_PARAMETER
;
1070 snum
= find_service(talloc_tos(), service
, &service
);
1072 *status
= NT_STATUS_NO_MEMORY
;
1077 if (strequal(service
,"IPC$") ||
1078 (lp_enable_asu_support() && strequal(service
,"ADMIN$"))) {
1079 DEBUG(3,("refusing IPC connection to %s\n", service
));
1080 *status
= NT_STATUS_ACCESS_DENIED
;
1084 DEBUG(3,("%s (%s) couldn't find service %s\n",
1085 get_remote_machine_name(),
1086 tsocket_address_string(
1087 sconn
->remote_address
, talloc_tos()),
1089 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1093 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1094 if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), snum
) != '\0')) {
1095 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1096 "(pointing to %s)\n",
1097 service
, lp_msdfs_proxy(talloc_tos(), snum
)));
1098 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1102 DEBUG(5, ("making a connection to 'normal' service %s\n", service
));
1104 return make_connection_smb1(req
, now
, snum
, vuser
,
1108 /****************************************************************************
1110 ****************************************************************************/
1112 void close_cnum(connection_struct
*conn
, uint64_t vuid
)
1114 char rootpath
[2] = { '/', '\0'};
1115 struct smb_filename root_fname
= { .base_name
= rootpath
};
1117 file_close_conn(conn
);
1119 if (!IS_IPC(conn
)) {
1120 dptr_closecnum(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(), SNUM(conn
)) &&
1139 change_to_user(conn
, vuid
)) {
1140 char *cmd
= talloc_sub_advanced(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(), 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(), SNUM(conn
))) {
1156 char *cmd
= talloc_sub_advanced(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(), SNUM(conn
)));
1164 smbrun(cmd
, NULL
, NULL
);