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(struct client_address *client_id, int snum,
234 if (!lp_snum_ok(snum) ||
235 !allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
236 client_id->name, client_id->addr)) {
237 return NT_STATUS_ACCESS_DENIED;
240 if (dev[0] == '?' || !dev[0]) {
241 if (lp_print_ok(snum)) {
242 fstrcpy(dev,"LPT1:");
243 } else if (strequal(lp_fstype(snum), "IPC")) {
252 if (lp_print_ok(snum)) {
253 if (!strequal(dev, "LPT1:")) {
254 return NT_STATUS_BAD_DEVICE_TYPE;
256 } else if (strequal(lp_fstype(snum), "IPC")) {
257 if (!strequal(dev, "IPC")) {
258 return NT_STATUS_BAD_DEVICE_TYPE;
260 } else if (!strequal(dev, "A:")) {
261 return NT_STATUS_BAD_DEVICE_TYPE;
264 /* Behave as a printer if we are supposed to */
265 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
266 fstrcpy(dev, "LPT1:");
273 * Go through lookup_name etc to find the force'd group.
275 * Create a new token from src_token, replacing the primary group sid with the
279 static NTSTATUS find_forced_group(bool force_user,
280 int snum, const char *username,
281 struct dom_sid *pgroup_sid,
284 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
285 TALLOC_CTX *frame = talloc_stackframe();
286 struct dom_sid group_sid;
287 enum lsa_SidType type;
289 bool user_must_be_member = False;
292 groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
293 if (groupname == NULL) {
294 DEBUG(1, ("talloc_strdup failed\n"));
295 result = NT_STATUS_NO_MEMORY;
299 if (groupname[0] == '+') {
300 user_must_be_member = True;
304 groupname = talloc_string_sub(talloc_tos(), groupname,
305 "%S", lp_servicename(snum));
306 if (groupname == NULL) {
307 DEBUG(1, ("talloc_string_sub failed\n"));
308 result = NT_STATUS_NO_MEMORY;
312 if (!lookup_name_smbconf(talloc_tos(), groupname,
313 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
314 NULL, NULL, &group_sid, &type)) {
315 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
320 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
321 (type != SID_NAME_WKN_GRP)) {
322 DEBUG(10, ("%s is a %s, not a group\n", groupname,
323 sid_type_lookup(type)));
327 if (!sid_to_gid(&group_sid, &gid)) {
328 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
329 sid_string_dbg(&group_sid), groupname));
334 * If the user has been forced and the forced group starts with a '+',
335 * then we only set the group to be the forced group if the forced
336 * user is a member of that group. Otherwise, the meaning of the '+'
340 if (force_user && user_must_be_member) {
341 if (user_in_group_sid(username, &group_sid)) {
342 sid_copy(pgroup_sid, &group_sid);
344 DEBUG(3,("Forced group %s for member %s\n",
345 groupname, username));
347 DEBUG(0,("find_forced_group: forced user %s is not a member "
348 "of forced group %s. Disallowing access.\n",
349 username, groupname ));
350 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
354 sid_copy(pgroup_sid, &group_sid);
356 DEBUG(3,("Forced group %s\n", groupname));
359 result = NT_STATUS_OK;
365 /****************************************************************************
366 Create an auth_serversupplied_info structure for a connection_struct
367 ****************************************************************************/
369 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
370 TALLOC_CTX *mem_ctx, int snum,
371 struct auth_serversupplied_info *vuid_serverinfo,
373 struct auth_serversupplied_info **presult)
375 if (lp_guest_only(snum)) {
376 return make_server_info_guest(mem_ctx, presult);
379 if (vuid_serverinfo != NULL) {
381 struct auth_serversupplied_info *result;
384 * This is the normal security != share case where we have a
385 * valid vuid from the session setup. */
387 if (vuid_serverinfo->guest) {
388 if (!lp_guest_ok(snum)) {
389 DEBUG(2, ("guest user (from session setup) "
390 "not permitted to access this share "
391 "(%s)\n", lp_servicename(snum)));
392 return NT_STATUS_ACCESS_DENIED;
395 if (!user_ok_token(vuid_serverinfo->unix_name,
396 vuid_serverinfo->info3->base.domain.string,
397 vuid_serverinfo->security_token, snum)) {
398 DEBUG(2, ("user '%s' (from session setup) not "
399 "permitted to access this share "
401 vuid_serverinfo->unix_name,
402 lp_servicename(snum)));
403 return NT_STATUS_ACCESS_DENIED;
407 result = copy_serverinfo(mem_ctx, vuid_serverinfo);
408 if (result == NULL) {
409 return NT_STATUS_NO_MEMORY;
416 if (lp_security() == SEC_SHARE) {
421 /* add the sharename as a possible user name if we
422 are in share mode security */
424 add_session_user(sconn, lp_servicename(snum));
426 /* shall we let them in? */
428 if (!authorise_login(sconn, snum,user,password,&guest)) {
429 DEBUG( 2, ( "Invalid username/password for [%s]\n",
430 lp_servicename(snum)) );
431 return NT_STATUS_WRONG_PASSWORD;
434 return make_session_info_from_username(mem_ctx, user, guest,
438 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
439 return NT_STATUS_ACCESS_DENIED;
442 /****************************************************************************
443 set relavent user and group settings corresponding to force user/group
444 configuration for the given snum.
445 ****************************************************************************/
447 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
451 if (*lp_force_user(snum)) {
454 * Replace conn->session_info with a completely faked up one
455 * from the username we are forced into :-)
459 struct auth_serversupplied_info *forced_serverinfo;
461 fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
462 lp_const_servicename(snum));
464 return NT_STATUS_NO_MEMORY;
467 status = make_session_info_from_username(
468 conn, fuser, conn->session_info->guest,
470 if (!NT_STATUS_IS_OK(status)) {
474 TALLOC_FREE(conn->session_info);
475 conn->session_info = forced_serverinfo;
477 conn->force_user = true;
478 DEBUG(3,("Forced user %s\n", fuser));
482 * If force group is true, then override
483 * any groupid stored for the connecting user.
486 if (*lp_force_group(snum)) {
488 status = find_forced_group(
489 conn->force_user, snum, conn->session_info->unix_name,
490 &conn->session_info->security_token->sids[1],
491 &conn->session_info->utok.gid);
493 if (!NT_STATUS_IS_OK(status)) {
498 * We need to cache this gid, to use within
499 * change_to_user() separately from the conn->session_info
500 * struct. We only use conn->session_info directly if
501 * "force_user" was set.
503 conn->force_group_gid = conn->session_info->utok.gid;
509 /****************************************************************************
510 Make a connection, given the snum to connect to, and the vuser of the
511 connecting user if appropriate.
512 ****************************************************************************/
514 connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
515 int snum, user_struct *vuser,
520 connection_struct *conn = NULL;
521 struct smb_filename *smb_fname_cpath = NULL;
524 bool on_err_call_dis_hook = false;
525 bool claimed_connection = false;
532 *pstatus = share_sanity_checks(&sconn->client_id, snum, dev);
533 if (NT_STATUS_IS_ERR(*pstatus)) {
537 conn = conn_new(sconn);
539 DEBUG(0,("Couldn't find free connection.\n"));
540 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
544 conn->params->service = snum;
546 status = create_connection_session_info(sconn,
547 conn, snum, vuser ? vuser->session_info : NULL, password,
548 &conn->session_info);
550 if (!NT_STATUS_IS_OK(status)) {
551 DEBUG(1, ("create_connection_session_info failed: %s\n",
557 if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
558 conn->force_user = true;
561 add_session_user(sconn, conn->session_info->unix_name);
563 conn->num_files_open = 0;
564 conn->lastused = conn->lastused_count = time(NULL);
566 conn->printer = (strncmp(dev,"LPT",3) == 0);
567 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
568 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
570 /* Case options for the share. */
571 if (lp_casesensitive(snum) == Auto) {
572 /* We will be setting this per packet. Set to be case
573 * insensitive for now. */
574 conn->case_sensitive = False;
576 conn->case_sensitive = (bool)lp_casesensitive(snum);
579 conn->case_preserve = lp_preservecase(snum);
580 conn->short_case_preserve = lp_shortpreservecase(snum);
582 conn->encrypt_level = lp_smb_encrypt(snum);
584 conn->veto_list = NULL;
585 conn->hide_list = NULL;
586 conn->veto_oplock_list = NULL;
587 conn->aio_write_behind_list = NULL;
589 conn->read_only = lp_readonly(SNUM(conn));
591 status = set_conn_force_user_group(conn, snum);
592 if (!NT_STATUS_IS_OK(status)) {
598 conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
601 char *s = talloc_sub_advanced(talloc_tos(),
602 lp_servicename(SNUM(conn)),
603 conn->session_info->unix_name,
605 conn->session_info->utok.gid,
606 conn->session_info->sanitized_username,
607 conn->session_info->info3->base.domain.string,
610 *pstatus = NT_STATUS_NO_MEMORY;
614 if (!set_conn_connectpath(conn,s)) {
616 *pstatus = NT_STATUS_NO_MEMORY;
619 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
620 lp_servicename(snum)));
625 * New code to check if there's a share security descripter
626 * added from NT server manager. This is done after the
627 * smb.conf checks are done as we need a uid and token. JRA.
632 bool can_write = False;
634 can_write = share_access_check(conn->session_info->security_token,
635 lp_servicename(snum),
639 if (!share_access_check(conn->session_info->security_token,
640 lp_servicename(snum),
642 /* No access, read or write. */
643 DEBUG(0,("make_connection: connection to %s "
644 "denied due to security "
646 lp_servicename(snum)));
647 *pstatus = NT_STATUS_ACCESS_DENIED;
650 conn->read_only = True;
654 /* Initialise VFS function pointers */
656 if (!smbd_vfs_init(conn)) {
657 DEBUG(0, ("vfs_init failed for service %s\n",
658 lp_servicename(snum)));
659 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
663 /* ROOT Activities: */
664 /* explicitly check widelinks here so that we can correctly warn
666 widelinks_warning(snum);
669 * Enforce the max connections parameter.
672 if ((lp_max_connections(snum) > 0)
673 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
674 lp_max_connections(snum))) {
676 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
677 lp_max_connections(snum), lp_servicename(snum)));
678 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
683 * Get us an entry in the connections db
685 if (!claim_connection(conn, lp_servicename(snum))) {
686 DEBUG(1, ("Could not store connections entry\n"));
687 *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
690 claimed_connection = true;
692 /* Invoke VFS make connection hook - this must be the first
693 filesystem operation that we do. */
695 if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
696 conn->session_info->unix_name) < 0) {
697 DEBUG(0,("make_connection: VFS make connection failed!\n"));
698 *pstatus = NT_STATUS_UNSUCCESSFUL;
702 /* Any error exit after here needs to call the disconnect hook. */
703 on_err_call_dis_hook = true;
705 if ((!conn->printer) && (!conn->ipc)) {
706 conn->notify_ctx = notify_init(conn,
707 sconn_server_id(sconn),
709 server_event_context(),
714 * Fix compatibility issue pointed out by Volker.
715 * We pass the conn->connectpath to the preexec
716 * scripts as a parameter, so attempt to canonicalize
717 * it here before calling the preexec scripts.
718 * We ignore errors here, as it is possible that
719 * the conn->connectpath doesn't exist yet and
720 * the preexec scripts will create them.
723 (void)canonicalize_connect_path(conn);
725 /* Preexecs are done here as they might make the dir we are to ChDir
727 /* execute any "root preexec = " line */
728 if (*lp_rootpreexec(snum)) {
729 char *cmd = talloc_sub_advanced(talloc_tos(),
730 lp_servicename(SNUM(conn)),
731 conn->session_info->unix_name,
733 conn->session_info->utok.gid,
734 conn->session_info->sanitized_username,
735 conn->session_info->info3->base.domain.string,
736 lp_rootpreexec(snum));
737 DEBUG(5,("cmd=%s\n",cmd));
738 ret = smbrun(cmd,NULL);
740 if (ret != 0 && lp_rootpreexec_close(snum)) {
741 DEBUG(1,("root preexec gave %d - failing "
742 "connection\n", ret));
743 *pstatus = NT_STATUS_ACCESS_DENIED;
748 /* USER Activites: */
749 if (!change_to_user(conn, conn->vuid)) {
750 /* No point continuing if they fail the basic checks */
751 DEBUG(0,("Can't become connected user!\n"));
752 *pstatus = NT_STATUS_LOGON_FAILURE;
759 /* Remember that a different vuid can connect later without these
762 /* Preexecs are done here as they might make the dir we are to ChDir
765 /* execute any "preexec = " line */
766 if (*lp_preexec(snum)) {
767 char *cmd = talloc_sub_advanced(talloc_tos(),
768 lp_servicename(SNUM(conn)),
769 conn->session_info->unix_name,
771 conn->session_info->utok.gid,
772 conn->session_info->sanitized_username,
773 conn->session_info->info3->base.domain.string,
775 ret = smbrun(cmd,NULL);
777 if (ret != 0 && lp_preexec_close(snum)) {
778 DEBUG(1,("preexec gave %d - failing connection\n",
780 *pstatus = NT_STATUS_ACCESS_DENIED;
785 #ifdef WITH_FAKE_KASERVER
786 if (lp_afs_share(snum)) {
792 * we've finished with the user stuff - go back to root
793 * so the SMB_VFS_STAT call will only fail on path errors,
794 * not permission problems.
796 change_to_root_user();
797 /* ROOT Activites: */
800 * If widelinks are disallowed we need to canonicalise the connect
801 * path here to ensure we don't have any symlinks in the
802 * connectpath. We will be checking all paths on this connection are
803 * below this directory. We must do this after the VFS init as we
804 * depend on the realpath() pointer in the vfs table. JRA.
806 if (!lp_widelinks(snum)) {
807 if (!canonicalize_connect_path(conn)) {
808 DEBUG(0, ("canonicalize_connect_path failed "
809 "for service %s, path %s\n",
810 lp_servicename(snum),
812 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
817 /* Add veto/hide lists */
818 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
819 set_namearray( &conn->veto_list, lp_veto_files(snum));
820 set_namearray( &conn->hide_list, lp_hide_files(snum));
821 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
822 set_namearray( &conn->aio_write_behind_list,
823 lp_aio_write_behind(snum));
825 status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
826 NULL, NULL, &smb_fname_cpath);
827 if (!NT_STATUS_IS_OK(status)) {
832 /* win2000 does not check the permissions on the directory
833 during the tree connect, instead relying on permission
834 check during individual operations. To match this behaviour
835 I have disabled this chdir check (tridge) */
836 /* the alternative is just to check the directory exists */
838 if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
839 !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
840 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
841 DEBUG(0,("'%s' is not a directory, when connecting to "
842 "[%s]\n", conn->connectpath,
843 lp_servicename(snum)));
845 DEBUG(0,("'%s' does not exist or permission denied "
846 "when connecting to [%s] Error was %s\n",
847 conn->connectpath, lp_servicename(snum),
850 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
853 conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
855 string_set(&conn->origpath,conn->connectpath);
857 /* Figure out the characteristics of the underlying filesystem. This
858 * assumes that all the filesystem mounted withing a share path have
859 * the same characteristics, which is likely but not guaranteed.
862 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
865 * Print out the 'connected as' stuff here as we need
866 * to know the effective uid and gid we will be using
867 * (at least initially).
870 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
871 dbgtext( "%s (%s) ", get_remote_machine_name(),
872 conn->sconn->client_id.addr );
873 dbgtext( "%s", srv_is_signing_active(sconn) ? "signed " : "");
874 dbgtext( "connect to service %s ", lp_servicename(snum) );
875 dbgtext( "initially as user %s ",
876 conn->session_info->unix_name );
877 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
878 dbgtext( "(pid %d)\n", (int)sys_getpid() );
884 TALLOC_FREE(smb_fname_cpath);
885 /* We must exit this function as root. */
886 if (geteuid() != 0) {
887 change_to_root_user();
889 if (on_err_call_dis_hook) {
890 /* Call VFS disconnect hook */
891 SMB_VFS_DISCONNECT(conn);
893 if (claimed_connection) {
894 yield_connection(conn, lp_servicename(snum));
902 /****************************************************************************
903 Make a connection to a service.
906 ****************************************************************************/
908 connection_struct *make_connection(struct smbd_server_connection *sconn,
909 const char *service_in, DATA_BLOB password,
910 const char *pdev, uint16 vuid,
914 user_struct *vuser = NULL;
915 char *service = NULL;
921 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
923 if (!non_root_mode() && (euid = geteuid()) != 0) {
924 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
925 "(%u)\n", (unsigned int)euid ));
926 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
929 if (conn_num_open(sconn) > 2047) {
930 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
934 if(lp_security() != SEC_SHARE) {
935 vuser = get_valid_user_struct(sconn, vuid);
937 DEBUG(1,("make_connection: refusing to connect with "
938 "no session setup\n"));
939 *status = NT_STATUS_ACCESS_DENIED;
944 /* Logic to try and connect to the correct [homes] share, preferably
945 without too many getpwnam() lookups. This is particulary nasty for
946 winbind usernames, where the share name isn't the same as unix
949 The snum of the homes share is stored on the vuser at session setup
953 if (strequal(service_in,HOMES_NAME)) {
954 if(lp_security() != SEC_SHARE) {
955 DATA_BLOB no_pw = data_blob_null;
956 if (vuser->homes_snum == -1) {
957 DEBUG(2, ("[homes] share not available for "
958 "this user because it was not found "
959 "or created at session setup "
961 *status = NT_STATUS_BAD_NETWORK_NAME;
964 DEBUG(5, ("making a connection to [homes] service "
965 "created at session setup time\n"));
966 return make_connection_snum(sconn,
971 /* Security = share. Try with
972 * current_user_info.smb_name as the username. */
973 if (*current_user_info.smb_name) {
974 char *unix_username = NULL;
975 (void)map_username(talloc_tos(),
976 current_user_info.smb_name,
978 snum = find_service(talloc_tos(),
981 if (!unix_username) {
982 *status = NT_STATUS_NO_MEMORY;
987 DEBUG(5, ("making a connection to 'homes' "
988 "service %s based on "
989 "security=share\n", service_in));
990 return make_connection_snum(sconn,
996 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
997 && strequal(service_in,
998 lp_servicename(vuser->homes_snum))) {
999 DATA_BLOB no_pw = data_blob_null;
1000 DEBUG(5, ("making a connection to 'homes' service [%s] "
1001 "created at session setup time\n", service_in));
1002 return make_connection_snum(sconn,
1008 service = talloc_strdup(talloc_tos(), service_in);
1010 *status = NT_STATUS_NO_MEMORY;
1014 strlower_m(service);
1016 snum = find_service(talloc_tos(), service, &service);
1018 *status = NT_STATUS_NO_MEMORY;
1023 if (strequal(service,"IPC$") ||
1024 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1025 DEBUG(3,("refusing IPC connection to %s\n", service));
1026 *status = NT_STATUS_ACCESS_DENIED;
1030 DEBUG(3,("%s (%s) couldn't find service %s\n",
1031 get_remote_machine_name(),
1032 tsocket_address_string(
1033 sconn->remote_address, talloc_tos()),
1035 *status = NT_STATUS_BAD_NETWORK_NAME;
1039 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1040 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1041 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1042 "(pointing to %s)\n",
1043 service, lp_msdfs_proxy(snum)));
1044 *status = NT_STATUS_BAD_NETWORK_NAME;
1048 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1050 return make_connection_snum(sconn, snum, vuser,
1055 /****************************************************************************
1057 ****************************************************************************/
1059 void close_cnum(connection_struct *conn, uint16 vuid)
1061 file_close_conn(conn);
1063 if (!IS_IPC(conn)) {
1064 dptr_closecnum(conn);
1067 change_to_root_user();
1069 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1070 get_remote_machine_name(),
1071 conn->sconn->client_id.addr,
1072 lp_servicename(SNUM(conn))));
1074 /* Call VFS disconnect hook */
1075 SMB_VFS_DISCONNECT(conn);
1077 yield_connection(conn, lp_servicename(SNUM(conn)));
1079 /* make sure we leave the directory available for unmount */
1080 vfs_ChDir(conn, "/");
1082 /* execute any "postexec = " line */
1083 if (*lp_postexec(SNUM(conn)) &&
1084 change_to_user(conn, vuid)) {
1085 char *cmd = talloc_sub_advanced(talloc_tos(),
1086 lp_servicename(SNUM(conn)),
1087 conn->session_info->unix_name,
1089 conn->session_info->utok.gid,
1090 conn->session_info->sanitized_username,
1091 conn->session_info->info3->base.domain.string,
1092 lp_postexec(SNUM(conn)));
1095 change_to_root_user();
1098 change_to_root_user();
1099 /* execute any "root postexec = " line */
1100 if (*lp_rootpostexec(SNUM(conn))) {
1101 char *cmd = talloc_sub_advanced(talloc_tos(),
1102 lp_servicename(SNUM(conn)),
1103 conn->session_info->unix_name,
1105 conn->session_info->utok.gid,
1106 conn->session_info->sanitized_username,
1107 conn->session_info->info3->base.domain.string,
1108 lp_rootpostexec(SNUM(conn)));