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 "../lib/tsocket/tsocket.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../librpc/gen_ndr/netlogon.h"
26 #include "../libcli/security/security.h"
27 #include "printing/pcap.h"
28 #include "passdb/lookup_sid.h"
30 #include "lib/param/loadparm.h"
32 extern userdom_struct current_user_info
;
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 *)SMB_MALLOC(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(SNUM(conn
)), destname
));
165 string_set(&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(snum
), "IPC")) {
262 if (lp_print_ok(snum
)) {
263 if (!strequal(dev
, "LPT1:")) {
264 return NT_STATUS_BAD_DEVICE_TYPE
;
266 } else if (strequal(lp_fstype(snum
), "IPC")) {
267 if (!strequal(dev
, "IPC")) {
268 return NT_STATUS_BAD_DEVICE_TYPE
;
270 } else if (!strequal(dev
, "A:")) {
271 return NT_STATUS_BAD_DEVICE_TYPE
;
274 /* Behave as a printer if we are supposed to */
275 if (lp_print_ok(snum
) && (strcmp(dev
, "A:") == 0)) {
276 fstrcpy(dev
, "LPT1:");
283 * Go through lookup_name etc to find the force'd group.
285 * Create a new token from src_token, replacing the primary group sid with the
289 static NTSTATUS
find_forced_group(bool force_user
,
290 int snum
, const char *username
,
291 struct dom_sid
*pgroup_sid
,
294 NTSTATUS result
= NT_STATUS_NO_SUCH_GROUP
;
295 TALLOC_CTX
*frame
= talloc_stackframe();
296 struct dom_sid group_sid
;
297 enum lsa_SidType type
;
299 bool user_must_be_member
= False
;
302 groupname
= talloc_strdup(talloc_tos(), lp_force_group(snum
));
303 if (groupname
== NULL
) {
304 DEBUG(1, ("talloc_strdup failed\n"));
305 result
= NT_STATUS_NO_MEMORY
;
309 if (groupname
[0] == '+') {
310 user_must_be_member
= True
;
314 groupname
= talloc_string_sub(talloc_tos(), groupname
,
315 "%S", lp_servicename(snum
));
316 if (groupname
== NULL
) {
317 DEBUG(1, ("talloc_string_sub failed\n"));
318 result
= NT_STATUS_NO_MEMORY
;
322 if (!lookup_name_smbconf(talloc_tos(), groupname
,
323 LOOKUP_NAME_ALL
|LOOKUP_NAME_GROUP
,
324 NULL
, NULL
, &group_sid
, &type
)) {
325 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
330 if ((type
!= SID_NAME_DOM_GRP
) && (type
!= SID_NAME_ALIAS
) &&
331 (type
!= SID_NAME_WKN_GRP
)) {
332 DEBUG(10, ("%s is a %s, not a group\n", groupname
,
333 sid_type_lookup(type
)));
337 if (!sid_to_gid(&group_sid
, &gid
)) {
338 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
339 sid_string_dbg(&group_sid
), groupname
));
344 * If the user has been forced and the forced group starts with a '+',
345 * then we only set the group to be the forced group if the forced
346 * user is a member of that group. Otherwise, the meaning of the '+'
350 if (force_user
&& user_must_be_member
) {
351 if (user_in_group_sid(username
, &group_sid
)) {
352 sid_copy(pgroup_sid
, &group_sid
);
354 DEBUG(3,("Forced group %s for member %s\n",
355 groupname
, username
));
357 DEBUG(0,("find_forced_group: forced user %s is not a member "
358 "of forced group %s. Disallowing access.\n",
359 username
, groupname
));
360 result
= NT_STATUS_MEMBER_NOT_IN_GROUP
;
364 sid_copy(pgroup_sid
, &group_sid
);
366 DEBUG(3,("Forced group %s\n", groupname
));
369 result
= NT_STATUS_OK
;
375 /****************************************************************************
376 Create an auth_session_info structure for a connection_struct
377 ****************************************************************************/
379 static NTSTATUS
create_connection_session_info(struct smbd_server_connection
*sconn
,
380 TALLOC_CTX
*mem_ctx
, int snum
,
381 struct auth_session_info
*vuid_serverinfo
,
383 struct auth_session_info
**presult
)
385 if (lp_guest_only(snum
)) {
386 return make_session_info_guest(mem_ctx
, presult
);
389 if (vuid_serverinfo
!= NULL
) {
391 struct auth_session_info
*result
;
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(vuid_serverinfo
, 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(snum
)));
402 return NT_STATUS_ACCESS_DENIED
;
405 if (!user_ok_token(vuid_serverinfo
->unix_info
->unix_name
,
406 vuid_serverinfo
->info
->domain_name
,
407 vuid_serverinfo
->security_token
, snum
)) {
408 DEBUG(2, ("user '%s' (from session setup) not "
409 "permitted to access this share "
411 vuid_serverinfo
->unix_info
->unix_name
,
412 lp_servicename(snum
)));
413 return NT_STATUS_ACCESS_DENIED
;
417 result
= copy_session_info(mem_ctx
, vuid_serverinfo
);
418 if (result
== NULL
) {
419 return NT_STATUS_NO_MEMORY
;
426 if (lp_security() == SEC_SHARE
) {
431 /* add the sharename as a possible user name if we
432 are in share mode security */
434 add_session_user(sconn
, lp_servicename(snum
));
436 /* shall we let them in? */
438 if (!authorise_login(sconn
, snum
,user
,password
,&guest
)) {
439 DEBUG( 2, ( "Invalid username/password for [%s]\n",
440 lp_servicename(snum
)) );
441 return NT_STATUS_WRONG_PASSWORD
;
444 return make_session_info_from_username(mem_ctx
, user
, guest
,
448 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
449 return NT_STATUS_ACCESS_DENIED
;
452 /****************************************************************************
453 set relavent user and group settings corresponding to force user/group
454 configuration for the given snum.
455 ****************************************************************************/
457 NTSTATUS
set_conn_force_user_group(connection_struct
*conn
, int snum
)
461 if (*lp_force_user(snum
)) {
464 * Replace conn->session_info with a completely faked up one
465 * from the username we are forced into :-)
469 struct auth_session_info
*forced_serverinfo
;
472 fuser
= talloc_string_sub(conn
, lp_force_user(snum
), "%S",
473 lp_const_servicename(snum
));
475 return NT_STATUS_NO_MEMORY
;
478 guest
= security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
;
480 status
= make_session_info_from_username(
484 if (!NT_STATUS_IS_OK(status
)) {
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(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 /****************************************************************************
524 Make a connection, given the snum to connect to, and the vuser of the
525 connecting user if appropriate.
526 ****************************************************************************/
528 connection_struct
*make_connection_snum(struct smbd_server_connection
*sconn
,
529 int snum
, user_struct
*vuser
,
534 connection_struct
*conn
= NULL
;
535 struct smb_filename
*smb_fname_cpath
= NULL
;
538 bool on_err_call_dis_hook
= false;
539 bool claimed_connection
= false;
546 *pstatus
= share_sanity_checks(sconn
->remote_address
,
547 sconn
->remote_hostname
,
550 if (NT_STATUS_IS_ERR(*pstatus
)) {
554 conn
= conn_new(sconn
);
556 DEBUG(0,("Couldn't find free connection.\n"));
557 *pstatus
= NT_STATUS_INSUFFICIENT_RESOURCES
;
561 conn
->params
->service
= snum
;
563 status
= create_connection_session_info(sconn
,
564 conn
, snum
, vuser
? vuser
->session_info
: NULL
, password
,
565 &conn
->session_info
);
567 if (!NT_STATUS_IS_OK(status
)) {
568 DEBUG(1, ("create_connection_session_info failed: %s\n",
574 if ((lp_guest_only(snum
)) || (lp_security() == SEC_SHARE
)) {
575 conn
->force_user
= true;
578 add_session_user(sconn
, conn
->session_info
->unix_info
->unix_name
);
580 conn
->num_files_open
= 0;
581 conn
->lastused
= conn
->lastused_count
= time(NULL
);
583 conn
->printer
= (strncmp(dev
,"LPT",3) == 0);
584 conn
->ipc
= ( (strncmp(dev
,"IPC",3) == 0) ||
585 ( lp_enable_asu_support() && strequal(dev
,"ADMIN$")) );
587 /* Case options for the share. */
588 if (lp_casesensitive(snum
) == Auto
) {
589 /* We will be setting this per packet. Set to be case
590 * insensitive for now. */
591 conn
->case_sensitive
= False
;
593 conn
->case_sensitive
= (bool)lp_casesensitive(snum
);
596 conn
->case_preserve
= lp_preservecase(snum
);
597 conn
->short_case_preserve
= lp_shortpreservecase(snum
);
599 conn
->encrypt_level
= lp_smb_encrypt(snum
);
601 conn
->veto_list
= NULL
;
602 conn
->hide_list
= NULL
;
603 conn
->veto_oplock_list
= NULL
;
604 conn
->aio_write_behind_list
= NULL
;
606 conn
->read_only
= lp_readonly(SNUM(conn
));
608 status
= set_conn_force_user_group(conn
, snum
);
609 if (!NT_STATUS_IS_OK(status
)) {
615 conn
->vuid
= (vuser
!= NULL
) ? vuser
->vuid
: UID_FIELD_INVALID
;
618 char *s
= talloc_sub_advanced(talloc_tos(),
619 lp_servicename(SNUM(conn
)),
620 conn
->session_info
->unix_info
->unix_name
,
622 conn
->session_info
->unix_token
->gid
,
623 conn
->session_info
->unix_info
->sanitized_username
,
624 conn
->session_info
->info
->domain_name
,
627 *pstatus
= NT_STATUS_NO_MEMORY
;
631 if (!set_conn_connectpath(conn
,s
)) {
633 *pstatus
= NT_STATUS_NO_MEMORY
;
636 DEBUG(3,("Connect path is '%s' for service [%s]\n",s
,
637 lp_servicename(snum
)));
642 * New code to check if there's a share security descripter
643 * added from NT server manager. This is done after the
644 * smb.conf checks are done as we need a uid and token. JRA.
648 share_access_check(conn
->session_info
->security_token
,
649 lp_servicename(snum
), MAXIMUM_ALLOWED_ACCESS
,
650 &conn
->share_access
);
652 if ((conn
->share_access
& FILE_WRITE_DATA
) == 0) {
653 if ((conn
->share_access
& FILE_READ_DATA
) == 0) {
654 /* No access, read or write. */
655 DEBUG(0,("make_connection: connection to %s "
656 "denied due to security "
658 lp_servicename(snum
)));
659 *pstatus
= NT_STATUS_ACCESS_DENIED
;
662 conn
->read_only
= True
;
665 /* Initialise VFS function pointers */
667 if (!smbd_vfs_init(conn
)) {
668 DEBUG(0, ("vfs_init failed for service %s\n",
669 lp_servicename(snum
)));
670 *pstatus
= NT_STATUS_BAD_NETWORK_NAME
;
674 /* ROOT Activities: */
675 /* explicitly check widelinks here so that we can correctly warn
677 widelinks_warning(snum
);
680 * Enforce the max connections parameter.
683 if ((lp_max_connections(snum
) > 0)
684 && (count_current_connections(lp_servicename(SNUM(conn
)), True
) >=
685 lp_max_connections(snum
))) {
687 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
688 lp_max_connections(snum
), lp_servicename(snum
)));
689 *pstatus
= NT_STATUS_INSUFFICIENT_RESOURCES
;
694 * Get us an entry in the connections db
696 if (!claim_connection(conn
, lp_servicename(snum
))) {
697 DEBUG(1, ("Could not store connections entry\n"));
698 *pstatus
= NT_STATUS_INTERNAL_DB_ERROR
;
701 claimed_connection
= true;
703 /* Invoke VFS make connection hook - this must be the first
704 filesystem operation that we do. */
706 if (SMB_VFS_CONNECT(conn
, lp_servicename(snum
),
707 conn
->session_info
->unix_info
->unix_name
) < 0) {
708 DEBUG(0,("make_connection: VFS make connection failed!\n"));
709 *pstatus
= NT_STATUS_UNSUCCESSFUL
;
713 /* Any error exit after here needs to call the disconnect hook. */
714 on_err_call_dis_hook
= true;
716 if ((!conn
->printer
) && (!conn
->ipc
)) {
717 conn
->notify_ctx
= notify_init(conn
,
718 sconn_server_id(sconn
),
720 server_event_context(),
725 * Fix compatibility issue pointed out by Volker.
726 * We pass the conn->connectpath to the preexec
727 * scripts as a parameter, so attempt to canonicalize
728 * it here before calling the preexec scripts.
729 * We ignore errors here, as it is possible that
730 * the conn->connectpath doesn't exist yet and
731 * the preexec scripts will create them.
734 (void)canonicalize_connect_path(conn
);
736 /* Preexecs are done here as they might make the dir we are to ChDir
738 /* execute any "root preexec = " line */
739 if (*lp_rootpreexec(snum
)) {
740 char *cmd
= talloc_sub_advanced(talloc_tos(),
741 lp_servicename(SNUM(conn
)),
742 conn
->session_info
->unix_info
->unix_name
,
744 conn
->session_info
->unix_token
->gid
,
745 conn
->session_info
->unix_info
->sanitized_username
,
746 conn
->session_info
->info
->domain_name
,
747 lp_rootpreexec(snum
));
748 DEBUG(5,("cmd=%s\n",cmd
));
749 ret
= smbrun(cmd
,NULL
);
751 if (ret
!= 0 && lp_rootpreexec_close(snum
)) {
752 DEBUG(1,("root preexec gave %d - failing "
753 "connection\n", ret
));
754 *pstatus
= NT_STATUS_ACCESS_DENIED
;
759 /* USER Activites: */
760 if (!change_to_user(conn
, conn
->vuid
)) {
761 /* No point continuing if they fail the basic checks */
762 DEBUG(0,("Can't become connected user!\n"));
763 *pstatus
= NT_STATUS_LOGON_FAILURE
;
770 /* Remember that a different vuid can connect later without these
773 /* Preexecs are done here as they might make the dir we are to ChDir
776 /* execute any "preexec = " line */
777 if (*lp_preexec(snum
)) {
778 char *cmd
= talloc_sub_advanced(talloc_tos(),
779 lp_servicename(SNUM(conn
)),
780 conn
->session_info
->unix_info
->unix_name
,
782 conn
->session_info
->unix_token
->gid
,
783 conn
->session_info
->unix_info
->sanitized_username
,
784 conn
->session_info
->info
->domain_name
,
786 ret
= smbrun(cmd
,NULL
);
788 if (ret
!= 0 && lp_preexec_close(snum
)) {
789 DEBUG(1,("preexec gave %d - failing connection\n",
791 *pstatus
= NT_STATUS_ACCESS_DENIED
;
796 #ifdef WITH_FAKE_KASERVER
797 if (lp_afs_share(snum
)) {
803 * we've finished with the user stuff - go back to root
804 * so the SMB_VFS_STAT call will only fail on path errors,
805 * not permission problems.
807 change_to_root_user();
808 /* ROOT Activites: */
811 * If widelinks are disallowed we need to canonicalise the connect
812 * path here to ensure we don't have any symlinks in the
813 * connectpath. We will be checking all paths on this connection are
814 * below this directory. We must do this after the VFS init as we
815 * depend on the realpath() pointer in the vfs table. JRA.
817 if (!lp_widelinks(snum
)) {
818 if (!canonicalize_connect_path(conn
)) {
819 DEBUG(0, ("canonicalize_connect_path failed "
820 "for service %s, path %s\n",
821 lp_servicename(snum
),
823 *pstatus
= NT_STATUS_BAD_NETWORK_NAME
;
828 /* Add veto/hide lists */
829 if (!IS_IPC(conn
) && !IS_PRINT(conn
)) {
830 set_namearray( &conn
->veto_list
, lp_veto_files(snum
));
831 set_namearray( &conn
->hide_list
, lp_hide_files(snum
));
832 set_namearray( &conn
->veto_oplock_list
, lp_veto_oplocks(snum
));
833 set_namearray( &conn
->aio_write_behind_list
,
834 lp_aio_write_behind(snum
));
836 status
= create_synthetic_smb_fname(talloc_tos(), conn
->connectpath
,
837 NULL
, NULL
, &smb_fname_cpath
);
838 if (!NT_STATUS_IS_OK(status
)) {
843 /* win2000 does not check the permissions on the directory
844 during the tree connect, instead relying on permission
845 check during individual operations. To match this behaviour
846 I have disabled this chdir check (tridge) */
847 /* the alternative is just to check the directory exists */
849 if ((ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
)) != 0 ||
850 !S_ISDIR(smb_fname_cpath
->st
.st_ex_mode
)) {
851 if (ret
== 0 && !S_ISDIR(smb_fname_cpath
->st
.st_ex_mode
)) {
852 DEBUG(0,("'%s' is not a directory, when connecting to "
853 "[%s]\n", conn
->connectpath
,
854 lp_servicename(snum
)));
856 DEBUG(0,("'%s' does not exist or permission denied "
857 "when connecting to [%s] Error was %s\n",
858 conn
->connectpath
, lp_servicename(snum
),
861 *pstatus
= NT_STATUS_BAD_NETWORK_NAME
;
864 conn
->base_share_dev
= smb_fname_cpath
->st
.st_ex_dev
;
866 string_set(&conn
->origpath
,conn
->connectpath
);
868 /* Figure out the characteristics of the underlying filesystem. This
869 * assumes that all the filesystem mounted withing a share path have
870 * the same characteristics, which is likely but not guaranteed.
873 conn
->fs_capabilities
= SMB_VFS_FS_CAPABILITIES(conn
, &conn
->ts_res
);
876 * Print out the 'connected as' stuff here as we need
877 * to know the effective uid and gid we will be using
878 * (at least initially).
881 if( DEBUGLVL( IS_IPC(conn
) ? 3 : 1 ) ) {
882 dbgtext( "%s (%s) ", get_remote_machine_name(),
883 tsocket_address_string(conn
->sconn
->remote_address
,
885 dbgtext( "%s", srv_is_signing_active(sconn
) ? "signed " : "");
886 dbgtext( "connect to service %s ", lp_servicename(snum
) );
887 dbgtext( "initially as user %s ",
888 conn
->session_info
->unix_info
->unix_name
);
889 dbgtext( "(uid=%d, gid=%d) ", (int)effuid
, (int)effgid
);
890 dbgtext( "(pid %d)\n", (int)sys_getpid() );
896 TALLOC_FREE(smb_fname_cpath
);
897 /* We must exit this function as root. */
898 if (geteuid() != 0) {
899 change_to_root_user();
901 if (on_err_call_dis_hook
) {
902 /* Call VFS disconnect hook */
903 SMB_VFS_DISCONNECT(conn
);
905 if (claimed_connection
) {
906 yield_connection(conn
, lp_servicename(snum
));
914 /****************************************************************************
915 Make a connection to a service.
918 ****************************************************************************/
920 connection_struct
*make_connection(struct smbd_server_connection
*sconn
,
921 const char *service_in
, DATA_BLOB password
,
922 const char *pdev
, uint16 vuid
,
926 user_struct
*vuser
= NULL
;
927 char *service
= NULL
;
933 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
935 if (!non_root_mode() && (euid
= geteuid()) != 0) {
936 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
937 "(%u)\n", (unsigned int)euid
));
938 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
941 if (conn_num_open(sconn
) > 2047) {
942 *status
= NT_STATUS_INSUFF_SERVER_RESOURCES
;
946 if(lp_security() != SEC_SHARE
) {
947 vuser
= get_valid_user_struct(sconn
, vuid
);
949 DEBUG(1,("make_connection: refusing to connect with "
950 "no session setup\n"));
951 *status
= NT_STATUS_ACCESS_DENIED
;
956 /* Logic to try and connect to the correct [homes] share, preferably
957 without too many getpwnam() lookups. This is particulary nasty for
958 winbind usernames, where the share name isn't the same as unix
961 The snum of the homes share is stored on the vuser at session setup
965 if (strequal(service_in
,HOMES_NAME
)) {
966 if(lp_security() != SEC_SHARE
) {
967 DATA_BLOB no_pw
= data_blob_null
;
968 if (vuser
->homes_snum
== -1) {
969 DEBUG(2, ("[homes] share not available for "
970 "this user because it was not found "
971 "or created at session setup "
973 *status
= NT_STATUS_BAD_NETWORK_NAME
;
976 DEBUG(5, ("making a connection to [homes] service "
977 "created at session setup time\n"));
978 return make_connection_snum(sconn
,
983 /* Security = share. Try with
984 * current_user_info.smb_name as the username. */
985 if (*current_user_info
.smb_name
) {
986 char *unix_username
= NULL
;
987 (void)map_username(talloc_tos(),
988 current_user_info
.smb_name
,
990 snum
= find_service(talloc_tos(),
993 if (!unix_username
) {
994 *status
= NT_STATUS_NO_MEMORY
;
999 DEBUG(5, ("making a connection to 'homes' "
1000 "service %s based on "
1001 "security=share\n", service_in
));
1002 return make_connection_snum(sconn
,
1008 } else if ((lp_security() != SEC_SHARE
) && (vuser
->homes_snum
!= -1)
1009 && strequal(service_in
,
1010 lp_servicename(vuser
->homes_snum
))) {
1011 DATA_BLOB no_pw
= data_blob_null
;
1012 DEBUG(5, ("making a connection to 'homes' service [%s] "
1013 "created at session setup time\n", service_in
));
1014 return make_connection_snum(sconn
,
1020 service
= talloc_strdup(talloc_tos(), service_in
);
1022 *status
= NT_STATUS_NO_MEMORY
;
1026 strlower_m(service
);
1028 snum
= find_service(talloc_tos(), service
, &service
);
1030 *status
= NT_STATUS_NO_MEMORY
;
1035 if (strequal(service
,"IPC$") ||
1036 (lp_enable_asu_support() && strequal(service
,"ADMIN$"))) {
1037 DEBUG(3,("refusing IPC connection to %s\n", service
));
1038 *status
= NT_STATUS_ACCESS_DENIED
;
1042 DEBUG(3,("%s (%s) couldn't find service %s\n",
1043 get_remote_machine_name(),
1044 tsocket_address_string(
1045 sconn
->remote_address
, talloc_tos()),
1047 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1051 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1052 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum
) != '\0')) {
1053 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1054 "(pointing to %s)\n",
1055 service
, lp_msdfs_proxy(snum
)));
1056 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1060 DEBUG(5, ("making a connection to 'normal' service %s\n", service
));
1062 return make_connection_snum(sconn
, snum
, vuser
,
1067 /****************************************************************************
1069 ****************************************************************************/
1071 void close_cnum(connection_struct
*conn
, uint16 vuid
)
1073 file_close_conn(conn
);
1075 if (!IS_IPC(conn
)) {
1076 dptr_closecnum(conn
);
1079 change_to_root_user();
1081 DEBUG(IS_IPC(conn
)?3:1, ("%s (%s) closed connection to service %s\n",
1082 get_remote_machine_name(),
1083 tsocket_address_string(conn
->sconn
->remote_address
,
1085 lp_servicename(SNUM(conn
))));
1087 /* Call VFS disconnect hook */
1088 SMB_VFS_DISCONNECT(conn
);
1090 yield_connection(conn
, lp_servicename(SNUM(conn
)));
1092 /* make sure we leave the directory available for unmount */
1093 vfs_ChDir(conn
, "/");
1095 /* execute any "postexec = " line */
1096 if (*lp_postexec(SNUM(conn
)) &&
1097 change_to_user(conn
, vuid
)) {
1098 char *cmd
= talloc_sub_advanced(talloc_tos(),
1099 lp_servicename(SNUM(conn
)),
1100 conn
->session_info
->unix_info
->unix_name
,
1102 conn
->session_info
->unix_token
->gid
,
1103 conn
->session_info
->unix_info
->sanitized_username
,
1104 conn
->session_info
->info
->domain_name
,
1105 lp_postexec(SNUM(conn
)));
1108 change_to_root_user();
1111 change_to_root_user();
1112 /* execute any "root postexec = " line */
1113 if (*lp_rootpostexec(SNUM(conn
))) {
1114 char *cmd
= talloc_sub_advanced(talloc_tos(),
1115 lp_servicename(SNUM(conn
)),
1116 conn
->session_info
->unix_info
->unix_name
,
1118 conn
->session_info
->unix_token
->gid
,
1119 conn
->session_info
->unix_info
->sanitized_username
,
1120 conn
->session_info
->info
->domain_name
,
1121 lp_rootpostexec(SNUM(conn
)));