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"
34 static bool canonicalize_connect_path(connection_struct
*conn
)
37 char *resolved_name
= SMB_VFS_REALPATH(conn
,conn
->connectpath
);
41 ret
= set_conn_connectpath(conn
,resolved_name
);
42 SAFE_FREE(resolved_name
);
46 /****************************************************************************
47 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
48 absolute path stating in / and not ending in /.
49 Observent people will notice a similarity between this and check_path_syntax :-).
50 ****************************************************************************/
52 bool set_conn_connectpath(connection_struct
*conn
, const char *connectpath
)
56 const char *s
= connectpath
;
57 bool start_of_name_component
= true;
59 if (connectpath
== NULL
|| connectpath
[0] == '\0') {
63 /* Allocate for strlen + '\0' + possible leading '/' */
64 destname
= (char *)talloc_size(conn
, strlen(connectpath
) + 2);
70 *d
++ = '/'; /* Always start with root. */
74 /* Eat multiple '/' */
78 if ((d
> destname
+ 1) && (*s
!= '\0')) {
81 start_of_name_component
= True
;
85 if (start_of_name_component
) {
86 if ((s
[0] == '.') && (s
[1] == '.') && (s
[2] == '/' || s
[2] == '\0')) {
87 /* Uh oh - "/../" or "/..\0" ! */
89 /* Go past the ../ or .. */
93 s
+= 2; /* Go past the .. */
96 /* If we just added a '/' - delete it */
97 if ((d
> destname
) && (*(d
-1) == '/')) {
102 /* Are we at the start ? Can't go back further if so. */
104 *d
++ = '/'; /* Can't delete root */
107 /* Go back one level... */
108 /* Decrement d first as d points to the *next* char to write into. */
109 for (d
--; d
> destname
; d
--) {
114 /* We're still at the start of a name component, just the previous one. */
116 } else if ((s
[0] == '.') && ((s
[1] == '\0') || s
[1] == '/')) {
117 /* Component of pathname can't be "." only - skip the '.' . */
131 /* Get the size of the next MB character. */
132 next_codepoint(s
,&siz
);
153 start_of_name_component
= false;
157 /* And must not end in '/' */
158 if (d
> destname
+ 1 && (*(d
-1) == '/')) {
162 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
163 lp_servicename(talloc_tos(), SNUM(conn
)), destname
));
165 talloc_free(conn
->connectpath
);
166 conn
->connectpath
= destname
;
170 /****************************************************************************
171 Load parameters specific to a connection/service.
172 ****************************************************************************/
174 bool set_current_service(connection_struct
*conn
, uint16 flags
, bool do_chdir
)
183 conn
->lastused_count
++;
188 vfs_ChDir(conn
,conn
->connectpath
) != 0 &&
189 vfs_ChDir(conn
,conn
->origpath
) != 0) {
190 DEBUG(((errno
!=EACCES
)?0:3),("chdir (%s) failed, reason: %s\n",
191 conn
->connectpath
, strerror(errno
)));
195 if ((conn
== last_conn
) && (last_flags
== flags
)) {
202 /* Obey the client case sensitivity requests - only for clients that support it. */
203 switch (lp_casesensitive(snum
)) {
206 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
207 enum remote_arch_types ra_type
= get_remote_arch();
208 if ((ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
209 /* Client can't support per-packet case sensitive pathnames. */
210 conn
->case_sensitive
= False
;
212 conn
->case_sensitive
= !(flags
& FLAG_CASELESS_PATHNAMES
);
217 conn
->case_sensitive
= True
;
220 conn
->case_sensitive
= False
;
226 /****************************************************************************
227 do some basic sainity checks on the share.
228 This function modifies dev, ecode.
229 ****************************************************************************/
231 static NTSTATUS
share_sanity_checks(const struct tsocket_address
*remote_address
,
238 raddr
= tsocket_address_inet_addr_string(remote_address
,
241 return NT_STATUS_NO_MEMORY
;
244 if (!lp_snum_ok(snum
) ||
245 !allow_access(lp_hostsdeny(snum
), lp_hostsallow(snum
),
247 return NT_STATUS_ACCESS_DENIED
;
250 if (dev
[0] == '?' || !dev
[0]) {
251 if (lp_print_ok(snum
)) {
252 fstrcpy(dev
,"LPT1:");
253 } else if (strequal(lp_fstype(talloc_tos(), snum
), "IPC")) {
260 if (!strupper_m(dev
)) {
261 DEBUG(2,("strupper_m %s failed\n", dev
));
262 return NT_STATUS_INVALID_PARAMETER
;
265 if (lp_print_ok(snum
)) {
266 if (!strequal(dev
, "LPT1:")) {
267 return NT_STATUS_BAD_DEVICE_TYPE
;
269 } else if (strequal(lp_fstype(talloc_tos(), snum
), "IPC")) {
270 if (!strequal(dev
, "IPC")) {
271 return NT_STATUS_BAD_DEVICE_TYPE
;
273 } else if (!strequal(dev
, "A:")) {
274 return NT_STATUS_BAD_DEVICE_TYPE
;
277 /* Behave as a printer if we are supposed to */
278 if (lp_print_ok(snum
) && (strcmp(dev
, "A:") == 0)) {
279 fstrcpy(dev
, "LPT1:");
286 * Go through lookup_name etc to find the force'd group.
288 * Create a new token from src_token, replacing the primary group sid with the
292 static NTSTATUS
find_forced_group(bool force_user
,
293 int snum
, const char *username
,
294 struct dom_sid
*pgroup_sid
,
297 NTSTATUS result
= NT_STATUS_NO_SUCH_GROUP
;
298 TALLOC_CTX
*frame
= talloc_stackframe();
299 struct dom_sid group_sid
;
300 enum lsa_SidType type
;
302 bool user_must_be_member
= False
;
305 groupname
= lp_force_group(talloc_tos(), snum
);
306 if (groupname
== NULL
) {
307 DEBUG(1, ("talloc_strdup failed\n"));
308 result
= NT_STATUS_NO_MEMORY
;
312 if (groupname
[0] == '+') {
313 user_must_be_member
= True
;
317 groupname
= talloc_string_sub(talloc_tos(), groupname
,
318 "%S", lp_servicename(talloc_tos(), snum
));
319 if (groupname
== NULL
) {
320 DEBUG(1, ("talloc_string_sub failed\n"));
321 result
= NT_STATUS_NO_MEMORY
;
325 if (!lookup_name_smbconf(talloc_tos(), groupname
,
326 LOOKUP_NAME_ALL
|LOOKUP_NAME_GROUP
,
327 NULL
, NULL
, &group_sid
, &type
)) {
328 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
333 if ((type
!= SID_NAME_DOM_GRP
) && (type
!= SID_NAME_ALIAS
) &&
334 (type
!= SID_NAME_WKN_GRP
)) {
335 DEBUG(10, ("%s is a %s, not a group\n", groupname
,
336 sid_type_lookup(type
)));
340 if (!sid_to_gid(&group_sid
, &gid
)) {
341 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
342 sid_string_dbg(&group_sid
), groupname
));
347 * If the user has been forced and the forced group starts with a '+',
348 * then we only set the group to be the forced group if the forced
349 * user is a member of that group. Otherwise, the meaning of the '+'
353 if (force_user
&& user_must_be_member
) {
354 if (user_in_group_sid(username
, &group_sid
)) {
355 sid_copy(pgroup_sid
, &group_sid
);
357 DEBUG(3,("Forced group %s for member %s\n",
358 groupname
, username
));
360 DEBUG(0,("find_forced_group: forced user %s is not a member "
361 "of forced group %s. Disallowing access.\n",
362 username
, groupname
));
363 result
= NT_STATUS_MEMBER_NOT_IN_GROUP
;
367 sid_copy(pgroup_sid
, &group_sid
);
369 DEBUG(3,("Forced group %s\n", groupname
));
372 result
= NT_STATUS_OK
;
378 /****************************************************************************
379 Create an auth_session_info structure for a connection_struct
380 ****************************************************************************/
382 static NTSTATUS
create_connection_session_info(struct smbd_server_connection
*sconn
,
383 TALLOC_CTX
*mem_ctx
, int snum
,
384 struct auth_session_info
*session_info
,
385 struct auth_session_info
**presult
)
387 struct auth_session_info
*result
;
389 if (lp_guest_only(snum
)) {
390 return make_session_info_guest(mem_ctx
, presult
);
394 * This is the normal security != share case where we have a
395 * valid vuid from the session setup. */
397 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
398 if (!lp_guest_ok(snum
)) {
399 DEBUG(2, ("guest user (from session setup) "
400 "not permitted to access this share "
401 "(%s)\n", lp_servicename(talloc_tos(), snum
)));
402 return NT_STATUS_ACCESS_DENIED
;
405 if (!user_ok_token(session_info
->unix_info
->unix_name
,
406 session_info
->info
->domain_name
,
407 session_info
->security_token
, snum
)) {
408 DEBUG(2, ("user '%s' (from session setup) not "
409 "permitted to access this share "
411 session_info
->unix_info
->unix_name
,
412 lp_servicename(talloc_tos(), snum
)));
413 return NT_STATUS_ACCESS_DENIED
;
417 result
= copy_session_info(mem_ctx
, session_info
);
418 if (result
== NULL
) {
419 return NT_STATUS_NO_MEMORY
;
426 /****************************************************************************
427 set relavent user and group settings corresponding to force user/group
428 configuration for the given snum.
429 ****************************************************************************/
431 NTSTATUS
set_conn_force_user_group(connection_struct
*conn
, int snum
)
435 if (*lp_force_user(talloc_tos(), snum
)) {
438 * Replace conn->session_info with a completely faked up one
439 * from the username we are forced into :-)
443 char *sanitized_username
;
444 struct auth_session_info
*forced_serverinfo
;
447 fuser
= talloc_string_sub(conn
, lp_force_user(talloc_tos(), snum
), "%S",
448 lp_const_servicename(snum
));
450 return NT_STATUS_NO_MEMORY
;
453 guest
= security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
;
455 status
= make_session_info_from_username(
459 if (!NT_STATUS_IS_OK(status
)) {
463 /* We don't want to replace the original sanitized_username
464 as it is the original user given in the connect attempt.
465 This is used in '%U' substitutions. */
466 sanitized_username
= discard_const_p(char,
467 forced_serverinfo
->unix_info
->sanitized_username
);
468 TALLOC_FREE(sanitized_username
);
469 forced_serverinfo
->unix_info
->sanitized_username
=
470 talloc_move(forced_serverinfo
->unix_info
,
471 &conn
->session_info
->unix_info
->sanitized_username
);
473 TALLOC_FREE(conn
->session_info
);
474 conn
->session_info
= forced_serverinfo
;
476 conn
->force_user
= true;
477 DEBUG(3,("Forced user %s\n", fuser
));
481 * If force group is true, then override
482 * any groupid stored for the connecting user.
485 if (*lp_force_group(talloc_tos(), snum
)) {
487 status
= find_forced_group(
488 conn
->force_user
, snum
, conn
->session_info
->unix_info
->unix_name
,
489 &conn
->session_info
->security_token
->sids
[1],
490 &conn
->session_info
->unix_token
->gid
);
492 if (!NT_STATUS_IS_OK(status
)) {
497 * We need to cache this gid, to use within
498 * change_to_user() separately from the conn->session_info
499 * struct. We only use conn->session_info directly if
500 * "force_user" was set.
502 conn
->force_group_gid
= conn
->session_info
->unix_token
->gid
;
508 /****************************************************************************
509 Setup the share access mask for a connection.
510 ****************************************************************************/
512 static void create_share_access_mask(connection_struct
*conn
, int snum
)
514 const struct security_token
*token
= conn
->session_info
->security_token
;
516 share_access_check(token
,
517 lp_servicename(talloc_tos(), snum
),
518 MAXIMUM_ALLOWED_ACCESS
,
519 &conn
->share_access
);
521 if (security_token_has_privilege(token
, SEC_PRIV_SECURITY
)) {
522 conn
->share_access
|= SEC_FLAG_SYSTEM_SECURITY
;
524 if (security_token_has_privilege(token
, SEC_PRIV_RESTORE
)) {
525 conn
->share_access
|= (SEC_RIGHTS_PRIV_RESTORE
);
527 if (security_token_has_privilege(token
, SEC_PRIV_BACKUP
)) {
528 conn
->share_access
|= (SEC_RIGHTS_PRIV_BACKUP
);
530 if (security_token_has_privilege(token
, SEC_PRIV_TAKE_OWNERSHIP
)) {
531 conn
->share_access
|= (SEC_STD_WRITE_OWNER
);
535 /****************************************************************************
536 Make a connection, given the snum to connect to, and the vuser of the
537 connecting user if appropriate.
538 ****************************************************************************/
540 static NTSTATUS
make_connection_snum(struct smbd_server_connection
*sconn
,
541 connection_struct
*conn
,
542 int snum
, struct user_struct
*vuser
,
545 struct smb_filename
*smb_fname_cpath
= NULL
;
548 bool on_err_call_dis_hook
= false;
549 bool claimed_connection
= false;
556 status
= share_sanity_checks(sconn
->remote_address
,
557 sconn
->remote_hostname
,
560 if (NT_STATUS_IS_ERR(status
)) {
564 conn
->params
->service
= snum
;
566 status
= create_connection_session_info(sconn
,
567 conn
, snum
, vuser
->session_info
,
568 &conn
->session_info
);
570 if (!NT_STATUS_IS_OK(status
)) {
571 DEBUG(1, ("create_connection_session_info failed: %s\n",
576 if (lp_guest_only(snum
)) {
577 conn
->force_user
= true;
580 conn
->num_files_open
= 0;
581 conn
->lastused
= conn
->lastused_count
= time(NULL
);
582 conn
->printer
= (strncmp(dev
,"LPT",3) == 0);
583 conn
->ipc
= ( (strncmp(dev
,"IPC",3) == 0) ||
584 ( lp_enable_asu_support() && strequal(dev
,"ADMIN$")) );
586 /* Case options for the share. */
587 if (lp_casesensitive(snum
) == Auto
) {
588 /* We will be setting this per packet. Set to be case
589 * insensitive for now. */
590 conn
->case_sensitive
= False
;
592 conn
->case_sensitive
= (bool)lp_casesensitive(snum
);
595 conn
->case_preserve
= lp_preservecase(snum
);
596 conn
->short_case_preserve
= lp_shortpreservecase(snum
);
598 conn
->encrypt_level
= lp_smb_encrypt(snum
);
600 conn
->veto_list
= NULL
;
601 conn
->hide_list
= NULL
;
602 conn
->veto_oplock_list
= NULL
;
603 conn
->aio_write_behind_list
= NULL
;
605 conn
->read_only
= lp_readonly(SNUM(conn
));
607 status
= set_conn_force_user_group(conn
, snum
);
608 if (!NT_STATUS_IS_OK(status
)) {
612 conn
->vuid
= vuser
->vuid
;
615 char *s
= talloc_sub_advanced(talloc_tos(),
616 lp_servicename(talloc_tos(), SNUM(conn
)),
617 conn
->session_info
->unix_info
->unix_name
,
619 conn
->session_info
->unix_token
->gid
,
620 conn
->session_info
->unix_info
->sanitized_username
,
621 conn
->session_info
->info
->domain_name
,
622 lp_pathname(talloc_tos(), snum
));
624 status
= NT_STATUS_NO_MEMORY
;
628 if (!set_conn_connectpath(conn
,s
)) {
630 status
= NT_STATUS_NO_MEMORY
;
633 DEBUG(3,("Connect path is '%s' for service [%s]\n",s
,
634 lp_servicename(talloc_tos(), snum
)));
639 * New code to check if there's a share security descripter
640 * added from NT server manager. This is done after the
641 * smb.conf checks are done as we need a uid and token. JRA.
645 create_share_access_mask(conn
, snum
);
647 if ((conn
->share_access
& FILE_WRITE_DATA
) == 0) {
648 if ((conn
->share_access
& FILE_READ_DATA
) == 0) {
649 /* No access, read or write. */
650 DEBUG(0,("make_connection: connection to %s "
651 "denied due to security "
653 lp_servicename(talloc_tos(), snum
)));
654 status
= NT_STATUS_ACCESS_DENIED
;
657 conn
->read_only
= True
;
660 /* Initialise VFS function pointers */
662 if (!smbd_vfs_init(conn
)) {
663 DEBUG(0, ("vfs_init failed for service %s\n",
664 lp_servicename(talloc_tos(), snum
)));
665 status
= NT_STATUS_BAD_NETWORK_NAME
;
669 /* ROOT Activities: */
670 /* explicitly check widelinks here so that we can correctly warn
672 widelinks_warning(snum
);
675 * Enforce the max connections parameter.
678 if ((lp_max_connections(snum
) > 0)
679 && (count_current_connections(lp_servicename(talloc_tos(), SNUM(conn
)), True
) >=
680 lp_max_connections(snum
))) {
682 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
683 lp_max_connections(snum
),
684 lp_servicename(talloc_tos(), snum
)));
685 status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
690 * Get us an entry in the connections db
692 if (!claim_connection(conn
, lp_servicename(talloc_tos(), snum
))) {
693 DEBUG(1, ("Could not store connections entry\n"));
694 status
= NT_STATUS_INTERNAL_DB_ERROR
;
697 claimed_connection
= true;
699 /* Invoke VFS make connection hook - this must be the first
700 filesystem operation that we do. */
702 if (SMB_VFS_CONNECT(conn
, lp_servicename(talloc_tos(), snum
),
703 conn
->session_info
->unix_info
->unix_name
) < 0) {
704 DEBUG(0,("make_connection: VFS make connection failed!\n"));
705 status
= NT_STATUS_UNSUCCESSFUL
;
709 /* Any error exit after here needs to call the disconnect hook. */
710 on_err_call_dis_hook
= true;
712 if ((!conn
->printer
) && (!conn
->ipc
) &&
713 lp_change_notify(conn
->params
)) {
714 if (sconn
->notify_ctx
== NULL
) {
715 sconn
->notify_ctx
= notify_init(
716 sconn
, sconn
->msg_ctx
, sconn
->ev_ctx
);
718 if (sconn
->sys_notify_ctx
== NULL
) {
719 sconn
->sys_notify_ctx
= sys_notify_context_create(
720 sconn
, sconn
->ev_ctx
);
724 if (lp_kernel_oplocks(snum
)) {
725 init_kernel_oplocks(conn
->sconn
);
729 * Fix compatibility issue pointed out by Volker.
730 * We pass the conn->connectpath to the preexec
731 * scripts as a parameter, so attempt to canonicalize
732 * it here before calling the preexec scripts.
733 * We ignore errors here, as it is possible that
734 * the conn->connectpath doesn't exist yet and
735 * the preexec scripts will create them.
738 (void)canonicalize_connect_path(conn
);
740 /* Preexecs are done here as they might make the dir we are to ChDir
742 /* execute any "root preexec = " line */
743 if (*lp_rootpreexec(talloc_tos(), snum
)) {
744 char *cmd
= talloc_sub_advanced(talloc_tos(),
745 lp_servicename(talloc_tos(), SNUM(conn
)),
746 conn
->session_info
->unix_info
->unix_name
,
748 conn
->session_info
->unix_token
->gid
,
749 conn
->session_info
->unix_info
->sanitized_username
,
750 conn
->session_info
->info
->domain_name
,
751 lp_rootpreexec(talloc_tos(), snum
));
752 DEBUG(5,("cmd=%s\n",cmd
));
753 ret
= smbrun(cmd
,NULL
);
755 if (ret
!= 0 && lp_rootpreexec_close(snum
)) {
756 DEBUG(1,("root preexec gave %d - failing "
757 "connection\n", ret
));
758 status
= NT_STATUS_ACCESS_DENIED
;
763 /* USER Activites: */
764 if (!change_to_user(conn
, conn
->vuid
)) {
765 /* No point continuing if they fail the basic checks */
766 DEBUG(0,("Can't become connected user!\n"));
767 status
= NT_STATUS_LOGON_FAILURE
;
774 /* Remember that a different vuid can connect later without these
777 /* Preexecs are done here as they might make the dir we are to ChDir
780 /* execute any "preexec = " line */
781 if (*lp_preexec(talloc_tos(), snum
)) {
782 char *cmd
= talloc_sub_advanced(talloc_tos(),
783 lp_servicename(talloc_tos(), SNUM(conn
)),
784 conn
->session_info
->unix_info
->unix_name
,
786 conn
->session_info
->unix_token
->gid
,
787 conn
->session_info
->unix_info
->sanitized_username
,
788 conn
->session_info
->info
->domain_name
,
789 lp_preexec(talloc_tos(), snum
));
790 ret
= smbrun(cmd
,NULL
);
792 if (ret
!= 0 && lp_preexec_close(snum
)) {
793 DEBUG(1,("preexec gave %d - failing connection\n",
795 status
= NT_STATUS_ACCESS_DENIED
;
800 #ifdef WITH_FAKE_KASERVER
801 if (lp_afs_share(snum
)) {
807 * we've finished with the user stuff - go back to root
808 * so the SMB_VFS_STAT call will only fail on path errors,
809 * not permission problems.
811 change_to_root_user();
812 /* ROOT Activites: */
815 * If widelinks are disallowed we need to canonicalise the connect
816 * path here to ensure we don't have any symlinks in the
817 * connectpath. We will be checking all paths on this connection are
818 * below this directory. We must do this after the VFS init as we
819 * depend on the realpath() pointer in the vfs table. JRA.
821 if (!lp_widelinks(snum
)) {
822 if (!canonicalize_connect_path(conn
)) {
823 DEBUG(0, ("canonicalize_connect_path failed "
824 "for service %s, path %s\n",
825 lp_servicename(talloc_tos(), snum
),
827 status
= NT_STATUS_BAD_NETWORK_NAME
;
832 /* Add veto/hide lists */
833 if (!IS_IPC(conn
) && !IS_PRINT(conn
)) {
834 set_namearray( &conn
->veto_list
,
835 lp_veto_files(talloc_tos(), snum
));
836 set_namearray( &conn
->hide_list
,
837 lp_hide_files(talloc_tos(), snum
));
838 set_namearray( &conn
->veto_oplock_list
,
839 lp_veto_oplocks(talloc_tos(), snum
));
840 set_namearray( &conn
->aio_write_behind_list
,
841 lp_aio_write_behind(talloc_tos(), snum
));
843 status
= create_synthetic_smb_fname(talloc_tos(), conn
->connectpath
,
844 NULL
, NULL
, &smb_fname_cpath
);
845 if (!NT_STATUS_IS_OK(status
)) {
849 /* win2000 does not check the permissions on the directory
850 during the tree connect, instead relying on permission
851 check during individual operations. To match this behaviour
852 I have disabled this chdir check (tridge) */
853 /* the alternative is just to check the directory exists */
855 if ((ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
)) != 0 ||
856 !S_ISDIR(smb_fname_cpath
->st
.st_ex_mode
)) {
857 if (ret
== 0 && !S_ISDIR(smb_fname_cpath
->st
.st_ex_mode
)) {
858 DEBUG(0,("'%s' is not a directory, when connecting to "
859 "[%s]\n", conn
->connectpath
,
860 lp_servicename(talloc_tos(), snum
)));
862 DEBUG(0,("'%s' does not exist or permission denied "
863 "when connecting to [%s] Error was %s\n",
865 lp_servicename(talloc_tos(), snum
),
868 status
= NT_STATUS_BAD_NETWORK_NAME
;
871 conn
->base_share_dev
= smb_fname_cpath
->st
.st_ex_dev
;
873 talloc_free(conn
->origpath
);
874 conn
->origpath
= talloc_strdup(conn
, conn
->connectpath
);
876 /* Figure out the characteristics of the underlying filesystem. This
877 * assumes that all the filesystem mounted withing a share path have
878 * the same characteristics, which is likely but not guaranteed.
881 conn
->fs_capabilities
= SMB_VFS_FS_CAPABILITIES(conn
, &conn
->ts_res
);
884 * Print out the 'connected as' stuff here as we need
885 * to know the effective uid and gid we will be using
886 * (at least initially).
889 if( DEBUGLVL( IS_IPC(conn
) ? 3 : 1 ) ) {
890 dbgtext( "%s (%s) ", get_remote_machine_name(),
891 tsocket_address_string(conn
->sconn
->remote_address
,
893 dbgtext( "%s", srv_is_signing_active(sconn
) ? "signed " : "");
894 dbgtext( "connect to service %s ",
895 lp_servicename(talloc_tos(), snum
) );
896 dbgtext( "initially as user %s ",
897 conn
->session_info
->unix_info
->unix_name
);
898 dbgtext( "(uid=%d, gid=%d) ", (int)effuid
, (int)effgid
);
899 dbgtext( "(pid %d)\n", (int)getpid() );
906 TALLOC_FREE(smb_fname_cpath
);
907 /* We must exit this function as root. */
908 if (geteuid() != 0) {
909 change_to_root_user();
911 if (on_err_call_dis_hook
) {
912 /* Call VFS disconnect hook */
913 SMB_VFS_DISCONNECT(conn
);
915 if (claimed_connection
) {
916 yield_connection(conn
, lp_servicename(talloc_tos(), snum
));
921 /****************************************************************************
922 Make a connection to a service from SMB1. Internal interface.
923 ****************************************************************************/
925 static connection_struct
*make_connection_smb1(struct smbd_server_connection
*sconn
,
926 int snum
, struct user_struct
*vuser
,
930 struct smbXsrv_tcon
*tcon
;
933 struct connection_struct
*conn
;
935 status
= smb1srv_tcon_create(sconn
->conn
, now
, &tcon
);
936 if (!NT_STATUS_IS_OK(status
)) {
937 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
943 conn
= conn_new(sconn
);
947 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
948 *pstatus
= NT_STATUS_INSUFFICIENT_RESOURCES
;
952 conn
->cnum
= tcon
->global
->tcon_wire_id
;
955 *pstatus
= make_connection_snum(sconn
,
960 if (!NT_STATUS_IS_OK(*pstatus
)) {
966 tcon
->global
->share_name
= lp_servicename(tcon
->global
, SNUM(conn
));
967 if (tcon
->global
->share_name
== NULL
) {
970 *pstatus
= NT_STATUS_NO_MEMORY
;
974 tcon
->compat
= talloc_move(tcon
, &conn
);
975 tcon
->status
= NT_STATUS_OK
;
977 *pstatus
= smbXsrv_tcon_update(tcon
);
978 if (!NT_STATUS_IS_OK(*pstatus
)) {
986 /****************************************************************************
987 Make a connection to a service from SMB2. External SMB2 interface.
988 We must set cnum before claiming connection.
989 ****************************************************************************/
991 connection_struct
*make_connection_smb2(struct smbd_server_connection
*sconn
,
992 struct smbXsrv_tcon
*tcon
,
994 struct user_struct
*vuser
,
998 connection_struct
*conn
= conn_new(sconn
);
1000 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
1001 *pstatus
= NT_STATUS_INSUFFICIENT_RESOURCES
;
1005 conn
->cnum
= tcon
->global
->tcon_wire_id
;
1008 *pstatus
= make_connection_snum(sconn
,
1013 if (!NT_STATUS_IS_OK(*pstatus
)) {
1020 /****************************************************************************
1021 Make a connection to a service. External SMB1 interface.
1024 ****************************************************************************/
1026 connection_struct
*make_connection(struct smbd_server_connection
*sconn
,
1027 const char *service_in
,
1028 const char *pdev
, uint64_t vuid
,
1032 struct user_struct
*vuser
= NULL
;
1033 char *service
= NULL
;
1039 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1041 if (!non_root_mode() && (euid
= geteuid()) != 0) {
1042 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1043 "(%u)\n", (unsigned int)euid
));
1044 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1047 if (conn_num_open(sconn
) > 2047) {
1048 *status
= NT_STATUS_INSUFF_SERVER_RESOURCES
;
1052 vuser
= get_valid_user_struct(sconn
, vuid
);
1054 DEBUG(1,("make_connection: refusing to connect with "
1055 "no session setup\n"));
1056 *status
= NT_STATUS_ACCESS_DENIED
;
1060 /* Logic to try and connect to the correct [homes] share, preferably
1061 without too many getpwnam() lookups. This is particulary nasty for
1062 winbind usernames, where the share name isn't the same as unix
1065 The snum of the homes share is stored on the vuser at session setup
1069 if (strequal(service_in
,HOMES_NAME
)) {
1070 if (vuser
->homes_snum
== -1) {
1071 DEBUG(2, ("[homes] share not available for "
1072 "this user because it was not found "
1073 "or created at session setup "
1075 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1078 DEBUG(5, ("making a connection to [homes] service "
1079 "created at session setup time\n"));
1080 return make_connection_smb1(sconn
,
1084 } else if ((vuser
->homes_snum
!= -1)
1085 && strequal(service_in
,
1086 lp_servicename(talloc_tos(), vuser
->homes_snum
))) {
1087 DEBUG(5, ("making a connection to 'homes' service [%s] "
1088 "created at session setup time\n", service_in
));
1089 return make_connection_smb1(sconn
,
1095 service
= talloc_strdup(talloc_tos(), service_in
);
1097 *status
= NT_STATUS_NO_MEMORY
;
1101 strlower_m(service
);
1103 snum
= find_service(talloc_tos(), service
, &service
);
1105 *status
= NT_STATUS_NO_MEMORY
;
1110 if (strequal(service
,"IPC$") ||
1111 (lp_enable_asu_support() && strequal(service
,"ADMIN$"))) {
1112 DEBUG(3,("refusing IPC connection to %s\n", service
));
1113 *status
= NT_STATUS_ACCESS_DENIED
;
1117 DEBUG(3,("%s (%s) couldn't find service %s\n",
1118 get_remote_machine_name(),
1119 tsocket_address_string(
1120 sconn
->remote_address
, talloc_tos()),
1122 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1126 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1127 if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), snum
) != '\0')) {
1128 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1129 "(pointing to %s)\n",
1130 service
, lp_msdfs_proxy(talloc_tos(), snum
)));
1131 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1135 DEBUG(5, ("making a connection to 'normal' service %s\n", service
));
1137 return make_connection_smb1(sconn
, snum
, vuser
,
1141 /****************************************************************************
1143 ****************************************************************************/
1145 void close_cnum(connection_struct
*conn
, uint64_t vuid
)
1147 file_close_conn(conn
);
1149 if (!IS_IPC(conn
)) {
1150 dptr_closecnum(conn
);
1153 change_to_root_user();
1155 DEBUG(IS_IPC(conn
)?3:1, ("%s (%s) closed connection to service %s\n",
1156 get_remote_machine_name(),
1157 tsocket_address_string(conn
->sconn
->remote_address
,
1159 lp_servicename(talloc_tos(), SNUM(conn
))));
1161 /* Call VFS disconnect hook */
1162 SMB_VFS_DISCONNECT(conn
);
1164 yield_connection(conn
, lp_servicename(talloc_tos(), SNUM(conn
)));
1166 /* make sure we leave the directory available for unmount */
1167 vfs_ChDir(conn
, "/");
1169 /* execute any "postexec = " line */
1170 if (*lp_postexec(talloc_tos(), SNUM(conn
)) &&
1171 change_to_user(conn
, vuid
)) {
1172 char *cmd
= talloc_sub_advanced(talloc_tos(),
1173 lp_servicename(talloc_tos(), SNUM(conn
)),
1174 conn
->session_info
->unix_info
->unix_name
,
1176 conn
->session_info
->unix_token
->gid
,
1177 conn
->session_info
->unix_info
->sanitized_username
,
1178 conn
->session_info
->info
->domain_name
,
1179 lp_postexec(talloc_tos(), SNUM(conn
)));
1182 change_to_root_user();
1185 change_to_root_user();
1186 /* execute any "root postexec = " line */
1187 if (*lp_rootpostexec(talloc_tos(), SNUM(conn
))) {
1188 char *cmd
= talloc_sub_advanced(talloc_tos(),
1189 lp_servicename(talloc_tos(), SNUM(conn
)),
1190 conn
->session_info
->unix_info
->unix_name
,
1192 conn
->session_info
->unix_token
->gid
,
1193 conn
->session_info
->unix_info
->sanitized_username
,
1194 conn
->session_info
->info
->domain_name
,
1195 lp_rootpostexec(talloc_tos(), SNUM(conn
)));