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"
35 static bool canonicalize_connect_path(connection_struct *conn)
38 char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath);
42 ret = set_conn_connectpath(conn,resolved_name);
43 SAFE_FREE(resolved_name);
47 /****************************************************************************
48 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
49 absolute path stating in / and not ending in /.
50 Observent people will notice a similarity between this and check_path_syntax :-).
51 ****************************************************************************/
53 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
57 const char *s = connectpath;
58 bool start_of_name_component = true;
60 if (connectpath == NULL || connectpath[0] == '\0') {
64 /* Allocate for strlen + '\0' + possible leading '/' */
65 destname = (char *)talloc_size(conn, strlen(connectpath) + 2);
71 *d++ = '/'; /* Always start with root. */
75 /* Eat multiple '/' */
79 if ((d > destname + 1) && (*s != '\0')) {
82 start_of_name_component = True;
86 if (start_of_name_component) {
87 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
88 /* Uh oh - "/../" or "/..\0" ! */
90 /* Go past the ../ or .. */
94 s += 2; /* Go past the .. */
97 /* If we just added a '/' - delete it */
98 if ((d > destname) && (*(d-1) == '/')) {
103 /* Are we at the start ? Can't go back further if so. */
105 *d++ = '/'; /* Can't delete root */
108 /* Go back one level... */
109 /* Decrement d first as d points to the *next* char to write into. */
110 for (d--; d > destname; d--) {
115 /* We're still at the start of a name component, just the previous one. */
117 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
118 /* Component of pathname can't be "." only - skip the '.' . */
132 /* Get the size of the next MB character. */
133 next_codepoint(s,&siz);
154 start_of_name_component = false;
158 /* And must not end in '/' */
159 if (d > destname + 1 && (*(d-1) == '/')) {
163 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
164 lp_servicename(talloc_tos(), SNUM(conn)), destname ));
166 talloc_free(conn->connectpath);
167 conn->connectpath = destname;
168 /* Ensure conn->cwd is initialized - start as conn->connectpath. */
169 TALLOC_FREE(conn->cwd);
170 conn->cwd = talloc_strdup(conn, conn->connectpath);
177 /****************************************************************************
178 Load parameters specific to a connection/service.
179 ****************************************************************************/
181 bool set_current_service(connection_struct *conn, uint16_t flags, bool do_chdir)
184 enum remote_arch_types ra_type;
191 conn->lastused_count++;
196 vfs_ChDir(conn,conn->connectpath) != 0 &&
197 vfs_ChDir(conn,conn->origpath) != 0) {
198 DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
199 conn->connectpath, strerror(errno)));
203 if ((conn == last_conn) && (last_flags == flags)) {
211 * Obey the client case sensitivity requests - only for clients that
213 switch (lp_case_sensitive(snum)) {
216 * We need this uglyness due to DOS/Win9x clients that lie
217 * about case insensitivity. */
218 ra_type = get_remote_arch();
219 if (conn->sconn->using_smb2) {
220 conn->case_sensitive = false;
221 } else if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
223 * Client can't support per-packet case sensitive
225 conn->case_sensitive = false;
227 conn->case_sensitive =
228 !(flags & FLAG_CASELESS_PATHNAMES);
232 conn->case_sensitive = true;
235 conn->case_sensitive = false;
241 /****************************************************************************
242 do some basic sainity checks on the share.
243 This function modifies dev, ecode.
244 ****************************************************************************/
246 static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
253 raddr = tsocket_address_inet_addr_string(remote_address,
256 return NT_STATUS_NO_MEMORY;
259 if (!lp_snum_ok(snum) ||
260 !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
262 return NT_STATUS_ACCESS_DENIED;
265 if (dev[0] == '?' || !dev[0]) {
266 if (lp_printable(snum)) {
267 fstrcpy(dev,"LPT1:");
268 } else if (strequal(lp_fstype(snum), "IPC")) {
275 if (!strupper_m(dev)) {
276 DEBUG(2,("strupper_m %s failed\n", dev));
277 return NT_STATUS_INVALID_PARAMETER;
280 if (lp_printable(snum)) {
281 if (!strequal(dev, "LPT1:")) {
282 return NT_STATUS_BAD_DEVICE_TYPE;
284 } else if (strequal(lp_fstype(snum), "IPC")) {
285 if (!strequal(dev, "IPC")) {
286 return NT_STATUS_BAD_DEVICE_TYPE;
288 } else if (!strequal(dev, "A:")) {
289 return NT_STATUS_BAD_DEVICE_TYPE;
292 /* Behave as a printer if we are supposed to */
293 if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) {
294 fstrcpy(dev, "LPT1:");
301 * Go through lookup_name etc to find the force'd group.
303 * Create a new token from src_token, replacing the primary group sid with the
307 static NTSTATUS find_forced_group(bool force_user,
308 int snum, const char *username,
309 struct dom_sid *pgroup_sid,
312 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
313 TALLOC_CTX *frame = talloc_stackframe();
314 struct dom_sid group_sid;
315 enum lsa_SidType type;
317 bool user_must_be_member = False;
320 groupname = lp_force_group(talloc_tos(), snum);
321 if (groupname == NULL) {
322 DEBUG(1, ("talloc_strdup failed\n"));
323 result = NT_STATUS_NO_MEMORY;
327 if (groupname[0] == '+') {
328 user_must_be_member = True;
332 groupname = talloc_string_sub(talloc_tos(), groupname,
333 "%S", lp_servicename(talloc_tos(), snum));
334 if (groupname == NULL) {
335 DEBUG(1, ("talloc_string_sub failed\n"));
336 result = NT_STATUS_NO_MEMORY;
340 if (!lookup_name_smbconf(talloc_tos(), groupname,
341 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
342 NULL, NULL, &group_sid, &type)) {
343 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
348 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
349 (type != SID_NAME_WKN_GRP)) {
350 DEBUG(10, ("%s is a %s, not a group\n", groupname,
351 sid_type_lookup(type)));
355 if (!sid_to_gid(&group_sid, &gid)) {
356 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
357 sid_string_dbg(&group_sid), groupname));
362 * If the user has been forced and the forced group starts with a '+',
363 * then we only set the group to be the forced group if the forced
364 * user is a member of that group. Otherwise, the meaning of the '+'
368 if (force_user && user_must_be_member) {
369 if (user_in_group_sid(username, &group_sid)) {
370 sid_copy(pgroup_sid, &group_sid);
372 DEBUG(3,("Forced group %s for member %s\n",
373 groupname, username));
375 DEBUG(0,("find_forced_group: forced user %s is not a member "
376 "of forced group %s. Disallowing access.\n",
377 username, groupname ));
378 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
382 sid_copy(pgroup_sid, &group_sid);
384 DEBUG(3,("Forced group %s\n", groupname));
387 result = NT_STATUS_OK;
393 /****************************************************************************
394 Create an auth_session_info structure for a connection_struct
395 ****************************************************************************/
397 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
398 TALLOC_CTX *mem_ctx, int snum,
399 struct auth_session_info *session_info,
400 struct auth_session_info **presult)
402 struct auth_session_info *result;
404 if (lp_guest_only(snum)) {
405 return make_session_info_guest(mem_ctx, presult);
409 * This is the normal security != share case where we have a
410 * valid vuid from the session setup. */
412 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
413 if (!lp_guest_ok(snum)) {
414 DEBUG(2, ("guest user (from session setup) "
415 "not permitted to access this share "
416 "(%s)\n", lp_servicename(talloc_tos(), snum)));
417 return NT_STATUS_ACCESS_DENIED;
420 if (!user_ok_token(session_info->unix_info->unix_name,
421 session_info->info->domain_name,
422 session_info->security_token, snum)) {
423 DEBUG(2, ("user '%s' (from session setup) not "
424 "permitted to access this share "
426 session_info->unix_info->unix_name,
427 lp_servicename(talloc_tos(), snum)));
428 return NT_STATUS_ACCESS_DENIED;
432 result = copy_session_info(mem_ctx, session_info);
433 if (result == NULL) {
434 return NT_STATUS_NO_MEMORY;
441 /****************************************************************************
442 Set relevant user and group settings corresponding to force user/group
443 configuration for the given snum.
444 ****************************************************************************/
446 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
450 if (*lp_force_user(talloc_tos(), snum)) {
453 * Replace conn->session_info with a completely faked up one
454 * from the username we are forced into :-)
458 char *sanitized_username;
459 struct auth_session_info *forced_serverinfo;
462 fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), snum), "%S",
463 lp_const_servicename(snum));
465 return NT_STATUS_NO_MEMORY;
468 guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;
470 status = make_session_info_from_username(
474 if (!NT_STATUS_IS_OK(status)) {
478 /* We don't want to replace the original sanitized_username
479 as it is the original user given in the connect attempt.
480 This is used in '%U' substitutions. */
481 sanitized_username = discard_const_p(char,
482 forced_serverinfo->unix_info->sanitized_username);
483 TALLOC_FREE(sanitized_username);
484 forced_serverinfo->unix_info->sanitized_username =
485 talloc_move(forced_serverinfo->unix_info,
486 &conn->session_info->unix_info->sanitized_username);
488 TALLOC_FREE(conn->session_info);
489 conn->session_info = forced_serverinfo;
491 conn->force_user = true;
492 DEBUG(3,("Forced user %s\n", fuser));
496 * If force group is true, then override
497 * any groupid stored for the connecting user.
500 if (*lp_force_group(talloc_tos(), snum)) {
502 status = find_forced_group(
503 conn->force_user, snum, conn->session_info->unix_info->unix_name,
504 &conn->session_info->security_token->sids[1],
505 &conn->session_info->unix_token->gid);
507 if (!NT_STATUS_IS_OK(status)) {
512 * We need to cache this gid, to use within
513 * change_to_user() separately from the conn->session_info
514 * struct. We only use conn->session_info directly if
515 * "force_user" was set.
517 conn->force_group_gid = conn->session_info->unix_token->gid;
523 static NTSTATUS notify_init_sconn(struct smbd_server_connection *sconn)
527 if (sconn->notify_ctx != NULL) {
531 sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx, sconn->ev_ctx,
532 sconn, notify_callback);
533 if (sconn->notify_ctx == NULL) {
534 return NT_STATUS_NO_MEMORY;
537 status = messaging_register(sconn->msg_ctx, sconn,
538 MSG_SMB_NOTIFY_CANCEL_DELETED,
539 smbd_notify_cancel_deleted);
540 if (!NT_STATUS_IS_OK(status)) {
541 DBG_DEBUG("messaging_register failed: %s\n",
543 TALLOC_FREE(sconn->notify_ctx);
547 status = messaging_register(sconn->msg_ctx, sconn,
548 MSG_SMB_NOTIFY_STARTED,
549 smbd_notifyd_restarted);
550 if (!NT_STATUS_IS_OK(status)) {
551 DBG_DEBUG("messaging_register failed: %s\n",
553 messaging_deregister(sconn->msg_ctx,
554 MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
555 TALLOC_FREE(sconn->notify_ctx);
562 /****************************************************************************
563 Make a connection, given the snum to connect to, and the vuser of the
564 connecting user if appropriate.
565 ****************************************************************************/
567 static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
568 connection_struct *conn,
569 int snum, struct user_struct *vuser,
572 struct smbd_server_connection *sconn = xconn->client->sconn;
573 struct smb_filename *smb_fname_cpath = NULL;
576 bool on_err_call_dis_hook = false;
583 status = share_sanity_checks(sconn->remote_address,
584 sconn->remote_hostname,
587 if (NT_STATUS_IS_ERR(status)) {
591 conn->params->service = snum;
593 status = create_connection_session_info(sconn,
594 conn, snum, vuser->session_info,
595 &conn->session_info);
597 if (!NT_STATUS_IS_OK(status)) {
598 DEBUG(1, ("create_connection_session_info failed: %s\n",
603 if (lp_guest_only(snum)) {
604 conn->force_user = true;
607 conn->num_files_open = 0;
608 conn->lastused = conn->lastused_count = time(NULL);
609 conn->printer = (strncmp(dev,"LPT",3) == 0);
610 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
611 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
613 /* Case options for the share. */
614 if (lp_case_sensitive(snum) == Auto) {
615 /* We will be setting this per packet. Set to be case
616 * insensitive for now. */
617 conn->case_sensitive = False;
619 conn->case_sensitive = (bool)lp_case_sensitive(snum);
622 conn->case_preserve = lp_preserve_case(snum);
623 conn->short_case_preserve = lp_short_preserve_case(snum);
625 conn->encrypt_level = lp_smb_encrypt(snum);
626 if (conn->encrypt_level > SMB_SIGNING_OFF) {
627 if (lp_smb_encrypt(-1) == SMB_SIGNING_OFF) {
628 if (conn->encrypt_level == SMB_SIGNING_REQUIRED) {
629 DBG_ERR("Service [%s] requires encryption, but "
630 "it is disabled globally!\n",
631 lp_servicename(talloc_tos(), snum));
632 status = NT_STATUS_ACCESS_DENIED;
635 conn->encrypt_level = SMB_SIGNING_OFF;
639 conn->veto_list = NULL;
640 conn->hide_list = NULL;
641 conn->veto_oplock_list = NULL;
642 conn->aio_write_behind_list = NULL;
644 conn->read_only = lp_read_only(SNUM(conn));
646 status = set_conn_force_user_group(conn, snum);
647 if (!NT_STATUS_IS_OK(status)) {
651 conn->vuid = vuser->vuid;
654 char *s = talloc_sub_advanced(talloc_tos(),
655 lp_servicename(talloc_tos(), SNUM(conn)),
656 conn->session_info->unix_info->unix_name,
658 conn->session_info->unix_token->gid,
659 conn->session_info->unix_info->sanitized_username,
660 conn->session_info->info->domain_name,
661 lp_path(talloc_tos(), snum));
663 status = NT_STATUS_NO_MEMORY;
667 if (!set_conn_connectpath(conn,s)) {
669 status = NT_STATUS_NO_MEMORY;
672 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
673 lp_servicename(talloc_tos(), snum)));
678 * Set up the share security descriptor.
679 * NOTE - we use the *INCOMING USER* session_info
680 * here, as does (indirectly) change_to_user(),
681 * which can be called on any incoming packet.
682 * This way we set up the share access based
683 * on the authenticated user, not the forced
686 * https://bugzilla.samba.org/show_bug.cgi?id=9878
689 status = check_user_share_access(conn,
693 if (!NT_STATUS_IS_OK(status)) {
697 /* Initialise VFS function pointers */
699 if (!smbd_vfs_init(conn)) {
700 DEBUG(0, ("vfs_init failed for service %s\n",
701 lp_servicename(talloc_tos(), snum)));
702 status = NT_STATUS_BAD_NETWORK_NAME;
706 /* ROOT Activities: */
707 /* explicitly check widelinks here so that we can correctly warn
709 widelinks_warning(snum);
712 * Enforce the max connections parameter.
715 if ((lp_max_connections(snum) > 0)
716 && (count_current_connections(lp_servicename(talloc_tos(), SNUM(conn)), True) >=
717 lp_max_connections(snum))) {
719 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
720 lp_max_connections(snum),
721 lp_servicename(talloc_tos(), snum)));
722 status = NT_STATUS_INSUFFICIENT_RESOURCES;
726 /* Invoke VFS make connection hook - this must be the first
727 filesystem operation that we do. */
729 if (SMB_VFS_CONNECT(conn, lp_servicename(talloc_tos(), snum),
730 conn->session_info->unix_info->unix_name) < 0) {
731 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
732 lp_servicename(talloc_tos(), snum), conn->connectpath,
734 status = NT_STATUS_UNSUCCESSFUL;
738 /* Any error exit after here needs to call the disconnect hook. */
739 on_err_call_dis_hook = true;
741 if ((!conn->printer) && (!conn->ipc) &&
742 lp_change_notify()) {
744 status = notify_init_sconn(sconn);
745 if (!NT_STATUS_IS_OK(status)) {
750 if (lp_kernel_oplocks(snum)) {
751 init_kernel_oplocks(conn->sconn);
755 * Fix compatibility issue pointed out by Volker.
756 * We pass the conn->connectpath to the preexec
757 * scripts as a parameter, so attempt to canonicalize
758 * it here before calling the preexec scripts.
759 * We ignore errors here, as it is possible that
760 * the conn->connectpath doesn't exist yet and
761 * the preexec scripts will create them.
764 (void)canonicalize_connect_path(conn);
766 /* Preexecs are done here as they might make the dir we are to ChDir
768 /* execute any "root preexec = " line */
769 if (*lp_root_preexec(talloc_tos(), snum)) {
770 char *cmd = talloc_sub_advanced(talloc_tos(),
771 lp_servicename(talloc_tos(), SNUM(conn)),
772 conn->session_info->unix_info->unix_name,
774 conn->session_info->unix_token->gid,
775 conn->session_info->unix_info->sanitized_username,
776 conn->session_info->info->domain_name,
777 lp_root_preexec(talloc_tos(), snum));
778 DEBUG(5,("cmd=%s\n",cmd));
779 ret = smbrun(cmd, NULL, NULL);
781 if (ret != 0 && lp_root_preexec_close(snum)) {
782 DEBUG(1,("root preexec gave %d - failing "
783 "connection\n", ret));
784 status = NT_STATUS_ACCESS_DENIED;
789 /* USER Activites: */
790 if (!change_to_user(conn, conn->vuid)) {
791 /* No point continuing if they fail the basic checks */
792 DEBUG(0,("Can't become connected user!\n"));
793 status = NT_STATUS_LOGON_FAILURE;
800 /* Remember that a different vuid can connect later without these
803 /* Preexecs are done here as they might make the dir we are to ChDir
806 /* execute any "preexec = " line */
807 if (*lp_preexec(talloc_tos(), snum)) {
808 char *cmd = talloc_sub_advanced(talloc_tos(),
809 lp_servicename(talloc_tos(), SNUM(conn)),
810 conn->session_info->unix_info->unix_name,
812 conn->session_info->unix_token->gid,
813 conn->session_info->unix_info->sanitized_username,
814 conn->session_info->info->domain_name,
815 lp_preexec(talloc_tos(), snum));
816 ret = smbrun(cmd, NULL, NULL);
818 if (ret != 0 && lp_preexec_close(snum)) {
819 DEBUG(1,("preexec gave %d - failing connection\n",
821 status = NT_STATUS_ACCESS_DENIED;
826 #ifdef WITH_FAKE_KASERVER
827 if (lp_afs_share(snum)) {
833 * we've finished with the user stuff - go back to root
834 * so the SMB_VFS_STAT call will only fail on path errors,
835 * not permission problems.
837 change_to_root_user();
838 /* ROOT Activites: */
841 * If widelinks are disallowed we need to canonicalise the connect
842 * path here to ensure we don't have any symlinks in the
843 * connectpath. We will be checking all paths on this connection are
844 * below this directory. We must do this after the VFS init as we
845 * depend on the realpath() pointer in the vfs table. JRA.
847 if (!lp_widelinks(snum)) {
848 if (!canonicalize_connect_path(conn)) {
849 DEBUG(0, ("canonicalize_connect_path failed "
850 "for service %s, path %s\n",
851 lp_servicename(talloc_tos(), snum),
853 status = NT_STATUS_BAD_NETWORK_NAME;
858 /* Add veto/hide lists */
859 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
860 set_namearray( &conn->veto_list,
861 lp_veto_files(talloc_tos(), snum));
862 set_namearray( &conn->hide_list,
863 lp_hide_files(talloc_tos(), snum));
864 set_namearray( &conn->veto_oplock_list,
865 lp_veto_oplock_files(talloc_tos(), snum));
866 set_namearray( &conn->aio_write_behind_list,
867 lp_aio_write_behind(talloc_tos(), snum));
869 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
874 if (smb_fname_cpath == NULL) {
875 status = NT_STATUS_NO_MEMORY;
879 /* win2000 does not check the permissions on the directory
880 during the tree connect, instead relying on permission
881 check during individual operations. To match this behaviour
882 I have disabled this chdir check (tridge) */
883 /* the alternative is just to check the directory exists */
885 if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
886 !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
887 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
888 DEBUG(0,("'%s' is not a directory, when connecting to "
889 "[%s]\n", conn->connectpath,
890 lp_servicename(talloc_tos(), snum)));
892 DEBUG(0,("'%s' does not exist or permission denied "
893 "when connecting to [%s] Error was %s\n",
895 lp_servicename(talloc_tos(), snum),
898 status = NT_STATUS_BAD_NETWORK_NAME;
901 conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
903 talloc_free(conn->origpath);
904 conn->origpath = talloc_strdup(conn, conn->connectpath);
906 /* Figure out the characteristics of the underlying filesystem. This
907 * assumes that all the filesystem mounted withing a share path have
908 * the same characteristics, which is likely but not guaranteed.
911 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
914 * Print out the 'connected as' stuff here as we need
915 * to know the effective uid and gid we will be using
916 * (at least initially).
919 if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
920 dbgtext( "%s (%s) ", get_remote_machine_name(),
921 tsocket_address_string(conn->sconn->remote_address,
923 dbgtext( "%s", srv_is_signing_active(xconn) ? "signed " : "");
924 dbgtext( "connect to service %s ",
925 lp_servicename(talloc_tos(), snum) );
926 dbgtext( "initially as user %s ",
927 conn->session_info->unix_info->unix_name );
928 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
929 dbgtext( "(pid %d)\n", (int)getpid() );
936 TALLOC_FREE(smb_fname_cpath);
937 /* We must exit this function as root. */
938 if (geteuid() != 0) {
939 change_to_root_user();
941 if (on_err_call_dis_hook) {
942 /* Call VFS disconnect hook */
943 SMB_VFS_DISCONNECT(conn);
948 /****************************************************************************
949 Make a connection to a service from SMB1. Internal interface.
950 ****************************************************************************/
952 static connection_struct *make_connection_smb1(struct smb_request *req,
954 int snum, struct user_struct *vuser,
958 struct smbXsrv_tcon *tcon;
960 struct connection_struct *conn;
962 status = smb1srv_tcon_create(req->xconn, now, &tcon);
963 if (!NT_STATUS_IS_OK(status)) {
964 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
970 conn = conn_new(req->sconn);
974 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
975 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
979 conn->cnum = tcon->global->tcon_wire_id;
982 *pstatus = make_connection_snum(req->xconn,
987 if (!NT_STATUS_IS_OK(*pstatus)) {
993 tcon->global->share_name = lp_servicename(tcon->global, SNUM(conn));
994 if (tcon->global->share_name == NULL) {
997 *pstatus = NT_STATUS_NO_MEMORY;
1000 tcon->global->session_global_id =
1001 vuser->session->global->session_global_id;
1003 tcon->compat = talloc_move(tcon, &conn);
1004 tcon->status = NT_STATUS_OK;
1006 *pstatus = smbXsrv_tcon_update(tcon);
1007 if (!NT_STATUS_IS_OK(*pstatus)) {
1012 return tcon->compat;
1015 /****************************************************************************
1016 Make a connection to a service from SMB2. External SMB2 interface.
1017 We must set cnum before claiming connection.
1018 ****************************************************************************/
1020 connection_struct *make_connection_smb2(struct smbd_smb2_request *req,
1021 struct smbXsrv_tcon *tcon,
1023 struct user_struct *vuser,
1027 struct smbd_server_connection *sconn = req->sconn;
1028 connection_struct *conn = conn_new(sconn);
1030 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
1031 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
1035 conn->cnum = tcon->global->tcon_wire_id;
1038 *pstatus = make_connection_snum(req->xconn,
1043 if (!NT_STATUS_IS_OK(*pstatus)) {
1050 /****************************************************************************
1051 Make a connection to a service. External SMB1 interface.
1054 ****************************************************************************/
1056 connection_struct *make_connection(struct smb_request *req,
1058 const char *service_in,
1059 const char *pdev, uint64_t vuid,
1062 struct smbd_server_connection *sconn = req->sconn;
1064 struct user_struct *vuser = NULL;
1065 char *service = NULL;
1071 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1073 if (!non_root_mode() && (euid = geteuid()) != 0) {
1074 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1075 "(%u)\n", (unsigned int)euid ));
1076 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1079 if (conn_num_open(sconn) > 2047) {
1080 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1084 vuser = get_valid_user_struct(sconn, vuid);
1086 DEBUG(1,("make_connection: refusing to connect with "
1087 "no session setup\n"));
1088 *status = NT_STATUS_ACCESS_DENIED;
1092 /* Logic to try and connect to the correct [homes] share, preferably
1093 without too many getpwnam() lookups. This is particulary nasty for
1094 winbind usernames, where the share name isn't the same as unix
1097 The snum of the homes share is stored on the vuser at session setup
1101 if (strequal(service_in,HOMES_NAME)) {
1102 if (vuser->homes_snum == -1) {
1103 DEBUG(2, ("[homes] share not available for "
1104 "this user because it was not found "
1105 "or created at session setup "
1107 *status = NT_STATUS_BAD_NETWORK_NAME;
1110 DEBUG(5, ("making a connection to [homes] service "
1111 "created at session setup time\n"));
1112 return make_connection_smb1(req, now,
1116 } else if ((vuser->homes_snum != -1)
1117 && strequal(service_in,
1118 lp_servicename(talloc_tos(), vuser->homes_snum))) {
1119 DEBUG(5, ("making a connection to 'homes' service [%s] "
1120 "created at session setup time\n", service_in));
1121 return make_connection_smb1(req, now,
1127 service = talloc_strdup(talloc_tos(), service_in);
1129 *status = NT_STATUS_NO_MEMORY;
1133 if (!strlower_m(service)) {
1134 DEBUG(2, ("strlower_m %s failed\n", service));
1135 *status = NT_STATUS_INVALID_PARAMETER;
1139 snum = find_service(talloc_tos(), service, &service);
1141 *status = NT_STATUS_NO_MEMORY;
1146 if (strequal(service,"IPC$") ||
1147 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1148 DEBUG(3,("refusing IPC connection to %s\n", service));
1149 *status = NT_STATUS_ACCESS_DENIED;
1153 DEBUG(3,("%s (%s) couldn't find service %s\n",
1154 get_remote_machine_name(),
1155 tsocket_address_string(
1156 sconn->remote_address, talloc_tos()),
1158 *status = NT_STATUS_BAD_NETWORK_NAME;
1162 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1163 if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), snum) != '\0')) {
1164 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1165 "(pointing to %s)\n",
1166 service, lp_msdfs_proxy(talloc_tos(), snum)));
1167 *status = NT_STATUS_BAD_NETWORK_NAME;
1171 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1173 return make_connection_smb1(req, now, snum, vuser,
1177 /****************************************************************************
1179 ****************************************************************************/
1181 void close_cnum(connection_struct *conn, uint64_t vuid)
1183 file_close_conn(conn);
1185 if (!IS_IPC(conn)) {
1186 dptr_closecnum(conn);
1189 change_to_root_user();
1191 DEBUG(IS_IPC(conn)?3:2, ("%s (%s) closed connection to service %s\n",
1192 get_remote_machine_name(),
1193 tsocket_address_string(conn->sconn->remote_address,
1195 lp_servicename(talloc_tos(), SNUM(conn))));
1197 /* make sure we leave the directory available for unmount */
1198 vfs_ChDir(conn, "/");
1200 /* Call VFS disconnect hook */
1201 SMB_VFS_DISCONNECT(conn);
1203 /* execute any "postexec = " line */
1204 if (*lp_postexec(talloc_tos(), SNUM(conn)) &&
1205 change_to_user(conn, vuid)) {
1206 char *cmd = talloc_sub_advanced(talloc_tos(),
1207 lp_servicename(talloc_tos(), SNUM(conn)),
1208 conn->session_info->unix_info->unix_name,
1210 conn->session_info->unix_token->gid,
1211 conn->session_info->unix_info->sanitized_username,
1212 conn->session_info->info->domain_name,
1213 lp_postexec(talloc_tos(), SNUM(conn)));
1214 smbrun(cmd, NULL, NULL);
1216 change_to_root_user();
1219 change_to_root_user();
1220 /* execute any "root postexec = " line */
1221 if (*lp_root_postexec(talloc_tos(), SNUM(conn))) {
1222 char *cmd = talloc_sub_advanced(talloc_tos(),
1223 lp_servicename(talloc_tos(), SNUM(conn)),
1224 conn->session_info->unix_info->unix_name,
1226 conn->session_info->unix_token->gid,
1227 conn->session_info->unix_info->sanitized_username,
1228 conn->session_info->info->domain_name,
1229 lp_root_postexec(talloc_tos(), SNUM(conn)));
1230 smbrun(cmd, NULL, NULL);