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 extern userdom_struct current_user_info
;
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 *)SMB_MALLOC(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(SNUM(conn
)), destname
));
166 string_set(&conn
->connectpath
, destname
);
171 /****************************************************************************
172 Load parameters specific to a connection/service.
173 ****************************************************************************/
175 bool set_current_service(connection_struct
*conn
, uint16 flags
, bool do_chdir
)
184 conn
->lastused_count
++;
189 vfs_ChDir(conn
,conn
->connectpath
) != 0 &&
190 vfs_ChDir(conn
,conn
->origpath
) != 0) {
191 DEBUG(((errno
!=EACCES
)?0:3),("chdir (%s) failed, reason: %s\n",
192 conn
->connectpath
, strerror(errno
)));
196 if ((conn
== last_conn
) && (last_flags
== flags
)) {
203 /* Obey the client case sensitivity requests - only for clients that support it. */
204 switch (lp_casesensitive(snum
)) {
207 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
208 enum remote_arch_types ra_type
= get_remote_arch();
209 if ((ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
210 /* Client can't support per-packet case sensitive pathnames. */
211 conn
->case_sensitive
= False
;
213 conn
->case_sensitive
= !(flags
& FLAG_CASELESS_PATHNAMES
);
218 conn
->case_sensitive
= True
;
221 conn
->case_sensitive
= False
;
227 /****************************************************************************
228 do some basic sainity checks on the share.
229 This function modifies dev, ecode.
230 ****************************************************************************/
232 static NTSTATUS
share_sanity_checks(const struct tsocket_address
*remote_address
,
239 raddr
= tsocket_address_inet_addr_string(remote_address
,
242 return NT_STATUS_NO_MEMORY
;
245 if (!lp_snum_ok(snum
) ||
246 !allow_access(lp_hostsdeny(snum
), lp_hostsallow(snum
),
248 return NT_STATUS_ACCESS_DENIED
;
251 if (dev
[0] == '?' || !dev
[0]) {
252 if (lp_print_ok(snum
)) {
253 fstrcpy(dev
,"LPT1:");
254 } else if (strequal(lp_fstype(snum
), "IPC")) {
263 if (lp_print_ok(snum
)) {
264 if (!strequal(dev
, "LPT1:")) {
265 return NT_STATUS_BAD_DEVICE_TYPE
;
267 } else if (strequal(lp_fstype(snum
), "IPC")) {
268 if (!strequal(dev
, "IPC")) {
269 return NT_STATUS_BAD_DEVICE_TYPE
;
271 } else if (!strequal(dev
, "A:")) {
272 return NT_STATUS_BAD_DEVICE_TYPE
;
275 /* Behave as a printer if we are supposed to */
276 if (lp_print_ok(snum
) && (strcmp(dev
, "A:") == 0)) {
277 fstrcpy(dev
, "LPT1:");
284 * Go through lookup_name etc to find the force'd group.
286 * Create a new token from src_token, replacing the primary group sid with the
290 static NTSTATUS
find_forced_group(bool force_user
,
291 int snum
, const char *username
,
292 struct dom_sid
*pgroup_sid
,
295 NTSTATUS result
= NT_STATUS_NO_SUCH_GROUP
;
296 TALLOC_CTX
*frame
= talloc_stackframe();
297 struct dom_sid group_sid
;
298 enum lsa_SidType type
;
300 bool user_must_be_member
= False
;
303 groupname
= talloc_strdup(talloc_tos(), lp_force_group(snum
));
304 if (groupname
== NULL
) {
305 DEBUG(1, ("talloc_strdup failed\n"));
306 result
= NT_STATUS_NO_MEMORY
;
310 if (groupname
[0] == '+') {
311 user_must_be_member
= True
;
315 groupname
= talloc_string_sub(talloc_tos(), groupname
,
316 "%S", lp_servicename(snum
));
317 if (groupname
== NULL
) {
318 DEBUG(1, ("talloc_string_sub failed\n"));
319 result
= NT_STATUS_NO_MEMORY
;
323 if (!lookup_name_smbconf(talloc_tos(), groupname
,
324 LOOKUP_NAME_ALL
|LOOKUP_NAME_GROUP
,
325 NULL
, NULL
, &group_sid
, &type
)) {
326 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
331 if ((type
!= SID_NAME_DOM_GRP
) && (type
!= SID_NAME_ALIAS
) &&
332 (type
!= SID_NAME_WKN_GRP
)) {
333 DEBUG(10, ("%s is a %s, not a group\n", groupname
,
334 sid_type_lookup(type
)));
338 if (!sid_to_gid(&group_sid
, &gid
)) {
339 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
340 sid_string_dbg(&group_sid
), groupname
));
345 * If the user has been forced and the forced group starts with a '+',
346 * then we only set the group to be the forced group if the forced
347 * user is a member of that group. Otherwise, the meaning of the '+'
351 if (force_user
&& user_must_be_member
) {
352 if (user_in_group_sid(username
, &group_sid
)) {
353 sid_copy(pgroup_sid
, &group_sid
);
355 DEBUG(3,("Forced group %s for member %s\n",
356 groupname
, username
));
358 DEBUG(0,("find_forced_group: forced user %s is not a member "
359 "of forced group %s. Disallowing access.\n",
360 username
, groupname
));
361 result
= NT_STATUS_MEMBER_NOT_IN_GROUP
;
365 sid_copy(pgroup_sid
, &group_sid
);
367 DEBUG(3,("Forced group %s\n", groupname
));
370 result
= NT_STATUS_OK
;
376 /****************************************************************************
377 Create an auth_session_info structure for a connection_struct
378 ****************************************************************************/
380 static NTSTATUS
create_connection_session_info(struct smbd_server_connection
*sconn
,
381 TALLOC_CTX
*mem_ctx
, int snum
,
382 struct auth_session_info
*vuid_serverinfo
,
384 struct auth_session_info
**presult
)
386 if (lp_guest_only(snum
)) {
387 return make_session_info_guest(mem_ctx
, presult
);
390 if (vuid_serverinfo
!= NULL
) {
392 struct auth_session_info
*result
;
395 * This is the normal security != share case where we have a
396 * valid vuid from the session setup. */
398 if (security_session_user_level(vuid_serverinfo
, NULL
) < SECURITY_USER
) {
399 if (!lp_guest_ok(snum
)) {
400 DEBUG(2, ("guest user (from session setup) "
401 "not permitted to access this share "
402 "(%s)\n", lp_servicename(snum
)));
403 return NT_STATUS_ACCESS_DENIED
;
406 if (!user_ok_token(vuid_serverinfo
->unix_info
->unix_name
,
407 vuid_serverinfo
->info
->domain_name
,
408 vuid_serverinfo
->security_token
, snum
)) {
409 DEBUG(2, ("user '%s' (from session setup) not "
410 "permitted to access this share "
412 vuid_serverinfo
->unix_info
->unix_name
,
413 lp_servicename(snum
)));
414 return NT_STATUS_ACCESS_DENIED
;
418 result
= copy_session_info(mem_ctx
, vuid_serverinfo
);
419 if (result
== NULL
) {
420 return NT_STATUS_NO_MEMORY
;
427 if (lp_security() == SEC_SHARE
) {
432 /* add the sharename as a possible user name if we
433 are in share mode security */
435 add_session_user(sconn
, lp_servicename(snum
));
437 /* shall we let them in? */
439 if (!authorise_login(sconn
, snum
,user
,password
,&guest
)) {
440 DEBUG( 2, ( "Invalid username/password for [%s]\n",
441 lp_servicename(snum
)) );
442 return NT_STATUS_WRONG_PASSWORD
;
445 return make_session_info_from_username(mem_ctx
, user
, guest
,
449 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
450 return NT_STATUS_ACCESS_DENIED
;
453 /****************************************************************************
454 set relavent user and group settings corresponding to force user/group
455 configuration for the given snum.
456 ****************************************************************************/
458 NTSTATUS
set_conn_force_user_group(connection_struct
*conn
, int snum
)
462 if (*lp_force_user(snum
)) {
465 * Replace conn->session_info with a completely faked up one
466 * from the username we are forced into :-)
470 struct auth_session_info
*forced_serverinfo
;
473 fuser
= talloc_string_sub(conn
, lp_force_user(snum
), "%S",
474 lp_const_servicename(snum
));
476 return NT_STATUS_NO_MEMORY
;
479 guest
= security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
;
481 status
= make_session_info_from_username(
485 if (!NT_STATUS_IS_OK(status
)) {
489 TALLOC_FREE(conn
->session_info
);
490 conn
->session_info
= forced_serverinfo
;
492 conn
->force_user
= true;
493 DEBUG(3,("Forced user %s\n", fuser
));
497 * If force group is true, then override
498 * any groupid stored for the connecting user.
501 if (*lp_force_group(snum
)) {
503 status
= find_forced_group(
504 conn
->force_user
, snum
, conn
->session_info
->unix_info
->unix_name
,
505 &conn
->session_info
->security_token
->sids
[1],
506 &conn
->session_info
->unix_token
->gid
);
508 if (!NT_STATUS_IS_OK(status
)) {
513 * We need to cache this gid, to use within
514 * change_to_user() separately from the conn->session_info
515 * struct. We only use conn->session_info directly if
516 * "force_user" was set.
518 conn
->force_group_gid
= conn
->session_info
->unix_token
->gid
;
524 /****************************************************************************
525 Make a connection, given the snum to connect to, and the vuser of the
526 connecting user if appropriate.
527 ****************************************************************************/
529 connection_struct
*make_connection_snum(struct smbd_server_connection
*sconn
,
530 int snum
, user_struct
*vuser
,
535 connection_struct
*conn
= NULL
;
536 struct smb_filename
*smb_fname_cpath
= NULL
;
539 bool on_err_call_dis_hook
= false;
540 bool claimed_connection
= false;
547 *pstatus
= share_sanity_checks(sconn
->remote_address
,
548 sconn
->remote_hostname
,
551 if (NT_STATUS_IS_ERR(*pstatus
)) {
555 conn
= conn_new(sconn
);
557 DEBUG(0,("Couldn't find free connection.\n"));
558 *pstatus
= NT_STATUS_INSUFFICIENT_RESOURCES
;
562 conn
->params
->service
= snum
;
564 status
= create_connection_session_info(sconn
,
565 conn
, snum
, vuser
? vuser
->session_info
: NULL
, password
,
566 &conn
->session_info
);
568 if (!NT_STATUS_IS_OK(status
)) {
569 DEBUG(1, ("create_connection_session_info failed: %s\n",
575 if ((lp_guest_only(snum
)) || (lp_security() == SEC_SHARE
)) {
576 conn
->force_user
= true;
579 add_session_user(sconn
, conn
->session_info
->unix_info
->unix_name
);
581 conn
->num_files_open
= 0;
582 conn
->lastused
= conn
->lastused_count
= time(NULL
);
584 conn
->printer
= (strncmp(dev
,"LPT",3) == 0);
585 conn
->ipc
= ( (strncmp(dev
,"IPC",3) == 0) ||
586 ( lp_enable_asu_support() && strequal(dev
,"ADMIN$")) );
588 /* Case options for the share. */
589 if (lp_casesensitive(snum
) == Auto
) {
590 /* We will be setting this per packet. Set to be case
591 * insensitive for now. */
592 conn
->case_sensitive
= False
;
594 conn
->case_sensitive
= (bool)lp_casesensitive(snum
);
597 conn
->case_preserve
= lp_preservecase(snum
);
598 conn
->short_case_preserve
= lp_shortpreservecase(snum
);
600 conn
->encrypt_level
= lp_smb_encrypt(snum
);
602 conn
->veto_list
= NULL
;
603 conn
->hide_list
= NULL
;
604 conn
->veto_oplock_list
= NULL
;
605 conn
->aio_write_behind_list
= NULL
;
607 conn
->read_only
= lp_readonly(SNUM(conn
));
609 status
= set_conn_force_user_group(conn
, snum
);
610 if (!NT_STATUS_IS_OK(status
)) {
616 conn
->vuid
= (vuser
!= NULL
) ? vuser
->vuid
: UID_FIELD_INVALID
;
619 char *s
= talloc_sub_advanced(talloc_tos(),
620 lp_servicename(SNUM(conn
)),
621 conn
->session_info
->unix_info
->unix_name
,
623 conn
->session_info
->unix_token
->gid
,
624 conn
->session_info
->unix_info
->sanitized_username
,
625 conn
->session_info
->info
->domain_name
,
628 *pstatus
= NT_STATUS_NO_MEMORY
;
632 if (!set_conn_connectpath(conn
,s
)) {
634 *pstatus
= NT_STATUS_NO_MEMORY
;
637 DEBUG(3,("Connect path is '%s' for service [%s]\n",s
,
638 lp_servicename(snum
)));
643 * New code to check if there's a share security descripter
644 * added from NT server manager. This is done after the
645 * smb.conf checks are done as we need a uid and token. JRA.
649 share_access_check(conn
->session_info
->security_token
,
650 lp_servicename(snum
), MAXIMUM_ALLOWED_ACCESS
,
651 &conn
->share_access
);
653 if ((conn
->share_access
& FILE_WRITE_DATA
) == 0) {
654 if ((conn
->share_access
& FILE_READ_DATA
) == 0) {
655 /* No access, read or write. */
656 DEBUG(0,("make_connection: connection to %s "
657 "denied due to security "
659 lp_servicename(snum
)));
660 *pstatus
= NT_STATUS_ACCESS_DENIED
;
663 conn
->read_only
= True
;
666 /* Initialise VFS function pointers */
668 if (!smbd_vfs_init(conn
)) {
669 DEBUG(0, ("vfs_init failed for service %s\n",
670 lp_servicename(snum
)));
671 *pstatus
= NT_STATUS_BAD_NETWORK_NAME
;
675 /* ROOT Activities: */
676 /* explicitly check widelinks here so that we can correctly warn
678 widelinks_warning(snum
);
681 * Enforce the max connections parameter.
684 if ((lp_max_connections(snum
) > 0)
685 && (count_current_connections(lp_servicename(SNUM(conn
)), True
) >=
686 lp_max_connections(snum
))) {
688 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
689 lp_max_connections(snum
), lp_servicename(snum
)));
690 *pstatus
= NT_STATUS_INSUFFICIENT_RESOURCES
;
695 * Get us an entry in the connections db
697 if (!claim_connection(conn
, lp_servicename(snum
))) {
698 DEBUG(1, ("Could not store connections entry\n"));
699 *pstatus
= NT_STATUS_INTERNAL_DB_ERROR
;
702 claimed_connection
= true;
704 /* Invoke VFS make connection hook - this must be the first
705 filesystem operation that we do. */
707 if (SMB_VFS_CONNECT(conn
, lp_servicename(snum
),
708 conn
->session_info
->unix_info
->unix_name
) < 0) {
709 DEBUG(0,("make_connection: VFS make connection failed!\n"));
710 *pstatus
= NT_STATUS_UNSUCCESSFUL
;
714 /* Any error exit after here needs to call the disconnect hook. */
715 on_err_call_dis_hook
= true;
717 if ((!conn
->printer
) && (!conn
->ipc
)) {
718 conn
->notify_ctx
= notify_init(conn
,
719 sconn_server_id(sconn
),
721 server_event_context(),
726 * Fix compatibility issue pointed out by Volker.
727 * We pass the conn->connectpath to the preexec
728 * scripts as a parameter, so attempt to canonicalize
729 * it here before calling the preexec scripts.
730 * We ignore errors here, as it is possible that
731 * the conn->connectpath doesn't exist yet and
732 * the preexec scripts will create them.
735 (void)canonicalize_connect_path(conn
);
737 /* Preexecs are done here as they might make the dir we are to ChDir
739 /* execute any "root preexec = " line */
740 if (*lp_rootpreexec(snum
)) {
741 char *cmd
= talloc_sub_advanced(talloc_tos(),
742 lp_servicename(SNUM(conn
)),
743 conn
->session_info
->unix_info
->unix_name
,
745 conn
->session_info
->unix_token
->gid
,
746 conn
->session_info
->unix_info
->sanitized_username
,
747 conn
->session_info
->info
->domain_name
,
748 lp_rootpreexec(snum
));
749 DEBUG(5,("cmd=%s\n",cmd
));
750 ret
= smbrun(cmd
,NULL
);
752 if (ret
!= 0 && lp_rootpreexec_close(snum
)) {
753 DEBUG(1,("root preexec gave %d - failing "
754 "connection\n", ret
));
755 *pstatus
= NT_STATUS_ACCESS_DENIED
;
760 /* USER Activites: */
761 if (!change_to_user(conn
, conn
->vuid
)) {
762 /* No point continuing if they fail the basic checks */
763 DEBUG(0,("Can't become connected user!\n"));
764 *pstatus
= NT_STATUS_LOGON_FAILURE
;
771 /* Remember that a different vuid can connect later without these
774 /* Preexecs are done here as they might make the dir we are to ChDir
777 /* execute any "preexec = " line */
778 if (*lp_preexec(snum
)) {
779 char *cmd
= talloc_sub_advanced(talloc_tos(),
780 lp_servicename(SNUM(conn
)),
781 conn
->session_info
->unix_info
->unix_name
,
783 conn
->session_info
->unix_token
->gid
,
784 conn
->session_info
->unix_info
->sanitized_username
,
785 conn
->session_info
->info
->domain_name
,
787 ret
= smbrun(cmd
,NULL
);
789 if (ret
!= 0 && lp_preexec_close(snum
)) {
790 DEBUG(1,("preexec gave %d - failing connection\n",
792 *pstatus
= NT_STATUS_ACCESS_DENIED
;
797 #ifdef WITH_FAKE_KASERVER
798 if (lp_afs_share(snum
)) {
804 * we've finished with the user stuff - go back to root
805 * so the SMB_VFS_STAT call will only fail on path errors,
806 * not permission problems.
808 change_to_root_user();
809 /* ROOT Activites: */
812 * If widelinks are disallowed we need to canonicalise the connect
813 * path here to ensure we don't have any symlinks in the
814 * connectpath. We will be checking all paths on this connection are
815 * below this directory. We must do this after the VFS init as we
816 * depend on the realpath() pointer in the vfs table. JRA.
818 if (!lp_widelinks(snum
)) {
819 if (!canonicalize_connect_path(conn
)) {
820 DEBUG(0, ("canonicalize_connect_path failed "
821 "for service %s, path %s\n",
822 lp_servicename(snum
),
824 *pstatus
= NT_STATUS_BAD_NETWORK_NAME
;
829 /* Add veto/hide lists */
830 if (!IS_IPC(conn
) && !IS_PRINT(conn
)) {
831 set_namearray( &conn
->veto_list
, lp_veto_files(snum
));
832 set_namearray( &conn
->hide_list
, lp_hide_files(snum
));
833 set_namearray( &conn
->veto_oplock_list
, lp_veto_oplocks(snum
));
834 set_namearray( &conn
->aio_write_behind_list
,
835 lp_aio_write_behind(snum
));
837 status
= create_synthetic_smb_fname(talloc_tos(), conn
->connectpath
,
838 NULL
, NULL
, &smb_fname_cpath
);
839 if (!NT_STATUS_IS_OK(status
)) {
844 /* win2000 does not check the permissions on the directory
845 during the tree connect, instead relying on permission
846 check during individual operations. To match this behaviour
847 I have disabled this chdir check (tridge) */
848 /* the alternative is just to check the directory exists */
850 if ((ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
)) != 0 ||
851 !S_ISDIR(smb_fname_cpath
->st
.st_ex_mode
)) {
852 if (ret
== 0 && !S_ISDIR(smb_fname_cpath
->st
.st_ex_mode
)) {
853 DEBUG(0,("'%s' is not a directory, when connecting to "
854 "[%s]\n", conn
->connectpath
,
855 lp_servicename(snum
)));
857 DEBUG(0,("'%s' does not exist or permission denied "
858 "when connecting to [%s] Error was %s\n",
859 conn
->connectpath
, lp_servicename(snum
),
862 *pstatus
= NT_STATUS_BAD_NETWORK_NAME
;
865 conn
->base_share_dev
= smb_fname_cpath
->st
.st_ex_dev
;
867 string_set(&conn
->origpath
,conn
->connectpath
);
869 /* Figure out the characteristics of the underlying filesystem. This
870 * assumes that all the filesystem mounted withing a share path have
871 * the same characteristics, which is likely but not guaranteed.
874 conn
->fs_capabilities
= SMB_VFS_FS_CAPABILITIES(conn
, &conn
->ts_res
);
877 * Print out the 'connected as' stuff here as we need
878 * to know the effective uid and gid we will be using
879 * (at least initially).
882 if( DEBUGLVL( IS_IPC(conn
) ? 3 : 1 ) ) {
883 dbgtext( "%s (%s) ", get_remote_machine_name(),
884 tsocket_address_string(conn
->sconn
->remote_address
,
886 dbgtext( "%s", srv_is_signing_active(sconn
) ? "signed " : "");
887 dbgtext( "connect to service %s ", lp_servicename(snum
) );
888 dbgtext( "initially as user %s ",
889 conn
->session_info
->unix_info
->unix_name
);
890 dbgtext( "(uid=%d, gid=%d) ", (int)effuid
, (int)effgid
);
891 dbgtext( "(pid %d)\n", (int)sys_getpid() );
897 TALLOC_FREE(smb_fname_cpath
);
898 /* We must exit this function as root. */
899 if (geteuid() != 0) {
900 change_to_root_user();
902 if (on_err_call_dis_hook
) {
903 /* Call VFS disconnect hook */
904 SMB_VFS_DISCONNECT(conn
);
906 if (claimed_connection
) {
907 yield_connection(conn
, lp_servicename(snum
));
915 /****************************************************************************
916 Make a connection to a service.
919 ****************************************************************************/
921 connection_struct
*make_connection(struct smbd_server_connection
*sconn
,
922 const char *service_in
, DATA_BLOB password
,
923 const char *pdev
, uint16 vuid
,
927 user_struct
*vuser
= NULL
;
928 char *service
= NULL
;
934 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
936 if (!non_root_mode() && (euid
= geteuid()) != 0) {
937 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
938 "(%u)\n", (unsigned int)euid
));
939 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
942 if (conn_num_open(sconn
) > 2047) {
943 *status
= NT_STATUS_INSUFF_SERVER_RESOURCES
;
947 if(lp_security() != SEC_SHARE
) {
948 vuser
= get_valid_user_struct(sconn
, vuid
);
950 DEBUG(1,("make_connection: refusing to connect with "
951 "no session setup\n"));
952 *status
= NT_STATUS_ACCESS_DENIED
;
957 /* Logic to try and connect to the correct [homes] share, preferably
958 without too many getpwnam() lookups. This is particulary nasty for
959 winbind usernames, where the share name isn't the same as unix
962 The snum of the homes share is stored on the vuser at session setup
966 if (strequal(service_in
,HOMES_NAME
)) {
967 if(lp_security() != SEC_SHARE
) {
968 DATA_BLOB no_pw
= data_blob_null
;
969 if (vuser
->homes_snum
== -1) {
970 DEBUG(2, ("[homes] share not available for "
971 "this user because it was not found "
972 "or created at session setup "
974 *status
= NT_STATUS_BAD_NETWORK_NAME
;
977 DEBUG(5, ("making a connection to [homes] service "
978 "created at session setup time\n"));
979 return make_connection_snum(sconn
,
984 /* Security = share. Try with
985 * current_user_info.smb_name as the username. */
986 if (*current_user_info
.smb_name
) {
987 char *unix_username
= NULL
;
988 (void)map_username(talloc_tos(),
989 current_user_info
.smb_name
,
991 snum
= find_service(talloc_tos(),
994 if (!unix_username
) {
995 *status
= NT_STATUS_NO_MEMORY
;
1000 DEBUG(5, ("making a connection to 'homes' "
1001 "service %s based on "
1002 "security=share\n", service_in
));
1003 return make_connection_snum(sconn
,
1009 } else if ((lp_security() != SEC_SHARE
) && (vuser
->homes_snum
!= -1)
1010 && strequal(service_in
,
1011 lp_servicename(vuser
->homes_snum
))) {
1012 DATA_BLOB no_pw
= data_blob_null
;
1013 DEBUG(5, ("making a connection to 'homes' service [%s] "
1014 "created at session setup time\n", service_in
));
1015 return make_connection_snum(sconn
,
1021 service
= talloc_strdup(talloc_tos(), service_in
);
1023 *status
= NT_STATUS_NO_MEMORY
;
1027 strlower_m(service
);
1029 snum
= find_service(talloc_tos(), service
, &service
);
1031 *status
= NT_STATUS_NO_MEMORY
;
1036 if (strequal(service
,"IPC$") ||
1037 (lp_enable_asu_support() && strequal(service
,"ADMIN$"))) {
1038 DEBUG(3,("refusing IPC connection to %s\n", service
));
1039 *status
= NT_STATUS_ACCESS_DENIED
;
1043 DEBUG(3,("%s (%s) couldn't find service %s\n",
1044 get_remote_machine_name(),
1045 tsocket_address_string(
1046 sconn
->remote_address
, talloc_tos()),
1048 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1052 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1053 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum
) != '\0')) {
1054 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1055 "(pointing to %s)\n",
1056 service
, lp_msdfs_proxy(snum
)));
1057 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1061 DEBUG(5, ("making a connection to 'normal' service %s\n", service
));
1063 return make_connection_snum(sconn
, snum
, vuser
,
1068 /****************************************************************************
1070 ****************************************************************************/
1072 void close_cnum(connection_struct
*conn
, uint16 vuid
)
1074 file_close_conn(conn
);
1076 if (!IS_IPC(conn
)) {
1077 dptr_closecnum(conn
);
1080 change_to_root_user();
1082 DEBUG(IS_IPC(conn
)?3:1, ("%s (%s) closed connection to service %s\n",
1083 get_remote_machine_name(),
1084 tsocket_address_string(conn
->sconn
->remote_address
,
1086 lp_servicename(SNUM(conn
))));
1088 /* Call VFS disconnect hook */
1089 SMB_VFS_DISCONNECT(conn
);
1091 yield_connection(conn
, lp_servicename(SNUM(conn
)));
1093 /* make sure we leave the directory available for unmount */
1094 vfs_ChDir(conn
, "/");
1096 /* execute any "postexec = " line */
1097 if (*lp_postexec(SNUM(conn
)) &&
1098 change_to_user(conn
, vuid
)) {
1099 char *cmd
= talloc_sub_advanced(talloc_tos(),
1100 lp_servicename(SNUM(conn
)),
1101 conn
->session_info
->unix_info
->unix_name
,
1103 conn
->session_info
->unix_token
->gid
,
1104 conn
->session_info
->unix_info
->sanitized_username
,
1105 conn
->session_info
->info
->domain_name
,
1106 lp_postexec(SNUM(conn
)));
1109 change_to_root_user();
1112 change_to_root_user();
1113 /* execute any "root postexec = " line */
1114 if (*lp_rootpostexec(SNUM(conn
))) {
1115 char *cmd
= talloc_sub_advanced(talloc_tos(),
1116 lp_servicename(SNUM(conn
)),
1117 conn
->session_info
->unix_info
->unix_name
,
1119 conn
->session_info
->unix_token
->gid
,
1120 conn
->session_info
->unix_info
->sanitized_username
,
1121 conn
->session_info
->info
->domain_name
,
1122 lp_rootpostexec(SNUM(conn
)));