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 "smbd/smbd.h"
23 #include "smbd/globals.h"
24 #include "../librpc/gen_ndr/netlogon.h"
25 #include "../libcli/security/security.h"
26 #include "printing/pcap.h"
27 #include "passdb/lookup_sid.h"
30 extern userdom_struct current_user_info;
32 static bool canonicalize_connect_path(connection_struct *conn)
35 char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath);
39 ret = set_conn_connectpath(conn,resolved_name);
40 SAFE_FREE(resolved_name);
44 /****************************************************************************
45 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
46 absolute path stating in / and not ending in /.
47 Observent people will notice a similarity between this and check_path_syntax :-).
48 ****************************************************************************/
50 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
54 const char *s = connectpath;
55 bool start_of_name_component = true;
57 if (connectpath == NULL || connectpath[0] == '\0') {
61 /* Allocate for strlen + '\0' + possible leading '/' */
62 destname = (char *)SMB_MALLOC(strlen(connectpath) + 2);
68 *d++ = '/'; /* Always start with root. */
72 /* Eat multiple '/' */
76 if ((d > destname + 1) && (*s != '\0')) {
79 start_of_name_component = True;
83 if (start_of_name_component) {
84 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
85 /* Uh oh - "/../" or "/..\0" ! */
87 /* Go past the ../ or .. */
91 s += 2; /* Go past the .. */
94 /* If we just added a '/' - delete it */
95 if ((d > destname) && (*(d-1) == '/')) {
100 /* Are we at the start ? Can't go back further if so. */
102 *d++ = '/'; /* Can't delete root */
105 /* Go back one level... */
106 /* Decrement d first as d points to the *next* char to write into. */
107 for (d--; d > destname; d--) {
112 /* We're still at the start of a name component, just the previous one. */
114 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
115 /* Component of pathname can't be "." only - skip the '.' . */
129 /* Get the size of the next MB character. */
130 next_codepoint(s,&siz);
151 start_of_name_component = false;
155 /* And must not end in '/' */
156 if (d > destname + 1 && (*(d-1) == '/')) {
160 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
161 lp_servicename(SNUM(conn)), destname ));
163 string_set(&conn->connectpath, destname);
168 /****************************************************************************
169 Load parameters specific to a connection/service.
170 ****************************************************************************/
172 bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
181 conn->lastused_count++;
186 vfs_ChDir(conn,conn->connectpath) != 0 &&
187 vfs_ChDir(conn,conn->origpath) != 0) {
188 DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
189 conn->connectpath, strerror(errno)));
193 if ((conn == last_conn) && (last_flags == flags)) {
200 /* Obey the client case sensitivity requests - only for clients that support it. */
201 switch (lp_casesensitive(snum)) {
204 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
205 enum remote_arch_types ra_type = get_remote_arch();
206 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
207 /* Client can't support per-packet case sensitive pathnames. */
208 conn->case_sensitive = False;
210 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
215 conn->case_sensitive = True;
218 conn->case_sensitive = False;
224 static int load_registry_service(const char *servicename)
226 if (!lp_registry_shares()) {
230 if ((servicename == NULL) || (*servicename == '\0')) {
234 if (strequal(servicename, GLOBAL_NAME)) {
238 if (!process_registry_service(servicename)) {
242 return lp_servicenumber(servicename);
245 void load_registry_shares(void)
247 DEBUG(8, ("load_registry_shares()\n"));
248 if (!lp_registry_shares()) {
252 process_registry_shares();
257 /****************************************************************************
258 Add a home service. Returns the new service number or -1 if fail.
259 ****************************************************************************/
261 int add_home_service(const char *service, const char *username, const char *homedir)
265 if (!service || !homedir || homedir[0] == '\0')
268 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
269 if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
275 * If this is a winbindd provided username, remove
276 * the domain component before adding the service.
277 * Log a warning if the "path=" parameter does not
278 * include any macros.
282 const char *p = strchr(service,*lp_winbind_separator());
284 /* We only want the 'user' part of the string */
290 if (!lp_add_home(service, iHomeService, username, homedir)) {
294 return lp_servicenumber(service);
299 * Find a service entry.
301 * @param service is modified (to canonical form??)
304 int find_service(TALLOC_CTX *ctx, const char *service_in, char **p_service_out)
312 /* First make a copy. */
313 *p_service_out = talloc_strdup(ctx, service_in);
314 if (!*p_service_out) {
318 all_string_sub(*p_service_out,"\\","/",0);
320 iService = lp_servicenumber(*p_service_out);
322 /* now handle the special case of a home directory */
324 char *phome_dir = get_user_home_dir(ctx, *p_service_out);
328 * Try mapping the servicename, it may
329 * be a Windows to unix mapped user name.
331 if(map_username(ctx, *p_service_out, p_service_out)) {
332 if (*p_service_out == NULL) {
336 phome_dir = get_user_home_dir(
337 ctx, *p_service_out);
341 DEBUG(3,("checking for home directory %s gave %s\n",*p_service_out,
342 phome_dir?phome_dir:"(NULL)"));
344 iService = add_home_service(*p_service_out,*p_service_out /* 'username' */, phome_dir);
347 /* If we still don't have a service, attempt to add it as a printer. */
351 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
352 iPrinterService = load_registry_service(PRINTERS_NAME);
354 if (iPrinterService >= 0) {
355 DEBUG(3,("checking whether %s is a valid printer name...\n",
357 if (pcap_printername_ok(*p_service_out)) {
358 DEBUG(3,("%s is a valid printer name\n",
360 DEBUG(3,("adding %s as a printer service\n",
362 lp_add_printer(*p_service_out, iPrinterService);
363 iService = lp_servicenumber(*p_service_out);
365 DEBUG(0,("failed to add %s as a printer service!\n",
369 DEBUG(3,("%s is not a valid printer name\n",
375 /* Check for default vfs service? Unsure whether to implement this */
380 iService = load_registry_service(*p_service_out);
383 /* Is it a usershare service ? */
384 if (iService < 0 && *lp_usershare_path()) {
385 /* Ensure the name is canonicalized. */
386 strlower_m(*p_service_out);
387 iService = load_usershare_service(*p_service_out);
390 /* just possibly it's a default service? */
392 char *pdefservice = lp_defaultservice();
395 !strequal(pdefservice, *p_service_out)
396 && !strstr_m(*p_service_out,"..")) {
398 * We need to do a local copy here as lp_defaultservice()
399 * returns one of the rotating lp_string buffers that
400 * could get overwritten by the recursive find_service() call
401 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
403 char *defservice = talloc_strdup(ctx, pdefservice);
409 /* Disallow anything except explicit share names. */
410 if (strequal(defservice,HOMES_NAME) ||
411 strequal(defservice, PRINTERS_NAME) ||
412 strequal(defservice, "IPC$")) {
413 TALLOC_FREE(defservice);
417 iService = find_service(ctx, defservice, p_service_out);
418 if (!*p_service_out) {
419 TALLOC_FREE(defservice);
424 all_string_sub(*p_service_out, "_","/",0);
425 iService = lp_add_service(*p_service_out, iService);
427 TALLOC_FREE(defservice);
432 if (!VALID_SNUM(iService)) {
433 DEBUG(0,("Invalid snum %d for %s\n",iService,
442 DEBUG(3,("find_service() failed to find service %s\n",
450 /****************************************************************************
451 do some basic sainity checks on the share.
452 This function modifies dev, ecode.
453 ****************************************************************************/
455 static NTSTATUS share_sanity_checks(struct client_address *client_id, int snum,
458 if (!lp_snum_ok(snum) ||
459 !allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
460 client_id->name, client_id->addr)) {
461 return NT_STATUS_ACCESS_DENIED;
464 if (dev[0] == '?' || !dev[0]) {
465 if (lp_print_ok(snum)) {
466 fstrcpy(dev,"LPT1:");
467 } else if (strequal(lp_fstype(snum), "IPC")) {
476 if (lp_print_ok(snum)) {
477 if (!strequal(dev, "LPT1:")) {
478 return NT_STATUS_BAD_DEVICE_TYPE;
480 } else if (strequal(lp_fstype(snum), "IPC")) {
481 if (!strequal(dev, "IPC")) {
482 return NT_STATUS_BAD_DEVICE_TYPE;
484 } else if (!strequal(dev, "A:")) {
485 return NT_STATUS_BAD_DEVICE_TYPE;
488 /* Behave as a printer if we are supposed to */
489 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
490 fstrcpy(dev, "LPT1:");
497 * Go through lookup_name etc to find the force'd group.
499 * Create a new token from src_token, replacing the primary group sid with the
503 static NTSTATUS find_forced_group(bool force_user,
504 int snum, const char *username,
505 struct dom_sid *pgroup_sid,
508 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
509 TALLOC_CTX *frame = talloc_stackframe();
510 struct dom_sid group_sid;
511 enum lsa_SidType type;
513 bool user_must_be_member = False;
516 groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
517 if (groupname == NULL) {
518 DEBUG(1, ("talloc_strdup failed\n"));
519 result = NT_STATUS_NO_MEMORY;
523 if (groupname[0] == '+') {
524 user_must_be_member = True;
528 groupname = talloc_string_sub(talloc_tos(), groupname,
529 "%S", lp_servicename(snum));
530 if (groupname == NULL) {
531 DEBUG(1, ("talloc_string_sub failed\n"));
532 result = NT_STATUS_NO_MEMORY;
536 if (!lookup_name_smbconf(talloc_tos(), groupname,
537 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
538 NULL, NULL, &group_sid, &type)) {
539 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
544 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
545 (type != SID_NAME_WKN_GRP)) {
546 DEBUG(10, ("%s is a %s, not a group\n", groupname,
547 sid_type_lookup(type)));
551 if (!sid_to_gid(&group_sid, &gid)) {
552 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
553 sid_string_dbg(&group_sid), groupname));
558 * If the user has been forced and the forced group starts with a '+',
559 * then we only set the group to be the forced group if the forced
560 * user is a member of that group. Otherwise, the meaning of the '+'
564 if (force_user && user_must_be_member) {
565 if (user_in_group_sid(username, &group_sid)) {
566 sid_copy(pgroup_sid, &group_sid);
568 DEBUG(3,("Forced group %s for member %s\n",
569 groupname, username));
571 DEBUG(0,("find_forced_group: forced user %s is not a member "
572 "of forced group %s. Disallowing access.\n",
573 username, groupname ));
574 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
578 sid_copy(pgroup_sid, &group_sid);
580 DEBUG(3,("Forced group %s\n", groupname));
583 result = NT_STATUS_OK;
589 /****************************************************************************
590 Create an auth_serversupplied_info structure for a connection_struct
591 ****************************************************************************/
593 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
594 TALLOC_CTX *mem_ctx, int snum,
595 struct auth_serversupplied_info *vuid_serverinfo,
597 struct auth_serversupplied_info **presult)
599 if (lp_guest_only(snum)) {
600 return make_server_info_guest(mem_ctx, presult);
603 if (vuid_serverinfo != NULL) {
605 struct auth_serversupplied_info *result;
608 * This is the normal security != share case where we have a
609 * valid vuid from the session setup. */
611 if (vuid_serverinfo->guest) {
612 if (!lp_guest_ok(snum)) {
613 DEBUG(2, ("guest user (from session setup) "
614 "not permitted to access this share "
615 "(%s)\n", lp_servicename(snum)));
616 return NT_STATUS_ACCESS_DENIED;
619 if (!user_ok_token(vuid_serverinfo->unix_name,
620 vuid_serverinfo->info3->base.domain.string,
621 vuid_serverinfo->security_token, snum)) {
622 DEBUG(2, ("user '%s' (from session setup) not "
623 "permitted to access this share "
625 vuid_serverinfo->unix_name,
626 lp_servicename(snum)));
627 return NT_STATUS_ACCESS_DENIED;
631 result = copy_serverinfo(mem_ctx, vuid_serverinfo);
632 if (result == NULL) {
633 return NT_STATUS_NO_MEMORY;
640 if (lp_security() == SEC_SHARE) {
645 /* add the sharename as a possible user name if we
646 are in share mode security */
648 add_session_user(sconn, lp_servicename(snum));
650 /* shall we let them in? */
652 if (!authorise_login(sconn, snum,user,password,&guest)) {
653 DEBUG( 2, ( "Invalid username/password for [%s]\n",
654 lp_servicename(snum)) );
655 return NT_STATUS_WRONG_PASSWORD;
658 return make_serverinfo_from_username(mem_ctx, user, guest,
662 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
663 return NT_STATUS_ACCESS_DENIED;
666 /****************************************************************************
667 set relavent user and group settings corresponding to force user/group
668 configuration for the given snum.
669 ****************************************************************************/
671 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
675 if (*lp_force_user(snum)) {
678 * Replace conn->session_info with a completely faked up one
679 * from the username we are forced into :-)
683 struct auth_serversupplied_info *forced_serverinfo;
685 fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
686 lp_const_servicename(snum));
688 return NT_STATUS_NO_MEMORY;
691 status = make_serverinfo_from_username(
692 conn, fuser, conn->session_info->guest,
694 if (!NT_STATUS_IS_OK(status)) {
698 TALLOC_FREE(conn->session_info);
699 conn->session_info = forced_serverinfo;
701 conn->force_user = true;
702 DEBUG(3,("Forced user %s\n", fuser));
706 * If force group is true, then override
707 * any groupid stored for the connecting user.
710 if (*lp_force_group(snum)) {
712 status = find_forced_group(
713 conn->force_user, snum, conn->session_info->unix_name,
714 &conn->session_info->security_token->sids[1],
715 &conn->session_info->utok.gid);
717 if (!NT_STATUS_IS_OK(status)) {
722 * We need to cache this gid, to use within
723 * change_to_user() separately from the conn->session_info
724 * struct. We only use conn->session_info directly if
725 * "force_user" was set.
727 conn->force_group_gid = conn->session_info->utok.gid;
733 /****************************************************************************
734 Make a connection, given the snum to connect to, and the vuser of the
735 connecting user if appropriate.
736 ****************************************************************************/
738 connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
739 int snum, user_struct *vuser,
744 connection_struct *conn = NULL;
745 struct smb_filename *smb_fname_cpath = NULL;
748 bool on_err_call_dis_hook = false;
749 bool claimed_connection = false;
756 *pstatus = share_sanity_checks(&sconn->client_id, snum, dev);
757 if (NT_STATUS_IS_ERR(*pstatus)) {
761 conn = conn_new(sconn);
763 DEBUG(0,("Couldn't find free connection.\n"));
764 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
768 conn->params->service = snum;
770 status = create_connection_session_info(sconn,
771 conn, snum, vuser ? vuser->session_info : NULL, password,
772 &conn->session_info);
774 if (!NT_STATUS_IS_OK(status)) {
775 DEBUG(1, ("create_connection_session_info failed: %s\n",
781 if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
782 conn->force_user = true;
785 add_session_user(sconn, conn->session_info->unix_name);
787 conn->num_files_open = 0;
788 conn->lastused = conn->lastused_count = time(NULL);
790 conn->printer = (strncmp(dev,"LPT",3) == 0);
791 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
792 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
794 /* Case options for the share. */
795 if (lp_casesensitive(snum) == Auto) {
796 /* We will be setting this per packet. Set to be case
797 * insensitive for now. */
798 conn->case_sensitive = False;
800 conn->case_sensitive = (bool)lp_casesensitive(snum);
803 conn->case_preserve = lp_preservecase(snum);
804 conn->short_case_preserve = lp_shortpreservecase(snum);
806 conn->encrypt_level = lp_smb_encrypt(snum);
808 conn->veto_list = NULL;
809 conn->hide_list = NULL;
810 conn->veto_oplock_list = NULL;
811 conn->aio_write_behind_list = NULL;
813 conn->read_only = lp_readonly(SNUM(conn));
815 status = set_conn_force_user_group(conn, snum);
816 if (!NT_STATUS_IS_OK(status)) {
822 conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
825 char *s = talloc_sub_advanced(talloc_tos(),
826 lp_servicename(SNUM(conn)),
827 conn->session_info->unix_name,
829 conn->session_info->utok.gid,
830 conn->session_info->sanitized_username,
831 conn->session_info->info3->base.domain.string,
834 *pstatus = NT_STATUS_NO_MEMORY;
838 if (!set_conn_connectpath(conn,s)) {
840 *pstatus = NT_STATUS_NO_MEMORY;
843 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
844 lp_servicename(snum)));
849 * New code to check if there's a share security descripter
850 * added from NT server manager. This is done after the
851 * smb.conf checks are done as we need a uid and token. JRA.
856 bool can_write = False;
858 can_write = share_access_check(conn->session_info->security_token,
859 lp_servicename(snum),
863 if (!share_access_check(conn->session_info->security_token,
864 lp_servicename(snum),
866 /* No access, read or write. */
867 DEBUG(0,("make_connection: connection to %s "
868 "denied due to security "
870 lp_servicename(snum)));
871 *pstatus = NT_STATUS_ACCESS_DENIED;
874 conn->read_only = True;
878 /* Initialise VFS function pointers */
880 if (!smbd_vfs_init(conn)) {
881 DEBUG(0, ("vfs_init failed for service %s\n",
882 lp_servicename(snum)));
883 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
887 /* ROOT Activities: */
888 /* explicitly check widelinks here so that we can correctly warn
890 widelinks_warning(snum);
893 * Enforce the max connections parameter.
896 if ((lp_max_connections(snum) > 0)
897 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
898 lp_max_connections(snum))) {
900 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
901 lp_max_connections(snum), lp_servicename(snum)));
902 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
907 * Get us an entry in the connections db
909 if (!claim_connection(conn, lp_servicename(snum))) {
910 DEBUG(1, ("Could not store connections entry\n"));
911 *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
914 claimed_connection = true;
916 /* Invoke VFS make connection hook - this must be the first
917 filesystem operation that we do. */
919 if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
920 conn->session_info->unix_name) < 0) {
921 DEBUG(0,("make_connection: VFS make connection failed!\n"));
922 *pstatus = NT_STATUS_UNSUCCESSFUL;
926 /* Any error exit after here needs to call the disconnect hook. */
927 on_err_call_dis_hook = true;
929 if ((!conn->printer) && (!conn->ipc)) {
930 conn->notify_ctx = notify_init(conn,
931 sconn_server_id(sconn),
933 smbd_event_context(),
938 * Fix compatibility issue pointed out by Volker.
939 * We pass the conn->connectpath to the preexec
940 * scripts as a parameter, so attempt to canonicalize
941 * it here before calling the preexec scripts.
942 * We ignore errors here, as it is possible that
943 * the conn->connectpath doesn't exist yet and
944 * the preexec scripts will create them.
947 (void)canonicalize_connect_path(conn);
949 /* Preexecs are done here as they might make the dir we are to ChDir
951 /* execute any "root preexec = " line */
952 if (*lp_rootpreexec(snum)) {
953 char *cmd = talloc_sub_advanced(talloc_tos(),
954 lp_servicename(SNUM(conn)),
955 conn->session_info->unix_name,
957 conn->session_info->utok.gid,
958 conn->session_info->sanitized_username,
959 conn->session_info->info3->base.domain.string,
960 lp_rootpreexec(snum));
961 DEBUG(5,("cmd=%s\n",cmd));
962 ret = smbrun(cmd,NULL);
964 if (ret != 0 && lp_rootpreexec_close(snum)) {
965 DEBUG(1,("root preexec gave %d - failing "
966 "connection\n", ret));
967 *pstatus = NT_STATUS_ACCESS_DENIED;
972 /* USER Activites: */
973 if (!change_to_user(conn, conn->vuid)) {
974 /* No point continuing if they fail the basic checks */
975 DEBUG(0,("Can't become connected user!\n"));
976 *pstatus = NT_STATUS_LOGON_FAILURE;
983 /* Remember that a different vuid can connect later without these
986 /* Preexecs are done here as they might make the dir we are to ChDir
989 /* execute any "preexec = " line */
990 if (*lp_preexec(snum)) {
991 char *cmd = talloc_sub_advanced(talloc_tos(),
992 lp_servicename(SNUM(conn)),
993 conn->session_info->unix_name,
995 conn->session_info->utok.gid,
996 conn->session_info->sanitized_username,
997 conn->session_info->info3->base.domain.string,
999 ret = smbrun(cmd,NULL);
1001 if (ret != 0 && lp_preexec_close(snum)) {
1002 DEBUG(1,("preexec gave %d - failing connection\n",
1004 *pstatus = NT_STATUS_ACCESS_DENIED;
1009 #ifdef WITH_FAKE_KASERVER
1010 if (lp_afs_share(snum)) {
1016 * we've finished with the user stuff - go back to root
1017 * so the SMB_VFS_STAT call will only fail on path errors,
1018 * not permission problems.
1020 change_to_root_user();
1021 /* ROOT Activites: */
1024 * If widelinks are disallowed we need to canonicalise the connect
1025 * path here to ensure we don't have any symlinks in the
1026 * connectpath. We will be checking all paths on this connection are
1027 * below this directory. We must do this after the VFS init as we
1028 * depend on the realpath() pointer in the vfs table. JRA.
1030 if (!lp_widelinks(snum)) {
1031 if (!canonicalize_connect_path(conn)) {
1032 DEBUG(0, ("canonicalize_connect_path failed "
1033 "for service %s, path %s\n",
1034 lp_servicename(snum),
1035 conn->connectpath));
1036 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1041 /* Add veto/hide lists */
1042 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1043 set_namearray( &conn->veto_list, lp_veto_files(snum));
1044 set_namearray( &conn->hide_list, lp_hide_files(snum));
1045 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1046 set_namearray( &conn->aio_write_behind_list,
1047 lp_aio_write_behind(snum));
1049 status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
1050 NULL, NULL, &smb_fname_cpath);
1051 if (!NT_STATUS_IS_OK(status)) {
1056 /* win2000 does not check the permissions on the directory
1057 during the tree connect, instead relying on permission
1058 check during individual operations. To match this behaviour
1059 I have disabled this chdir check (tridge) */
1060 /* the alternative is just to check the directory exists */
1062 if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
1063 !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1064 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1065 DEBUG(0,("'%s' is not a directory, when connecting to "
1066 "[%s]\n", conn->connectpath,
1067 lp_servicename(snum)));
1069 DEBUG(0,("'%s' does not exist or permission denied "
1070 "when connecting to [%s] Error was %s\n",
1071 conn->connectpath, lp_servicename(snum),
1074 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1077 conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
1079 string_set(&conn->origpath,conn->connectpath);
1081 /* Figure out the characteristics of the underlying filesystem. This
1082 * assumes that all the filesystem mounted withing a share path have
1083 * the same characteristics, which is likely but not guaranteed.
1086 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
1089 * Print out the 'connected as' stuff here as we need
1090 * to know the effective uid and gid we will be using
1091 * (at least initially).
1094 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1095 dbgtext( "%s (%s) ", get_remote_machine_name(),
1096 conn->sconn->client_id.addr );
1097 dbgtext( "%s", srv_is_signing_active(sconn) ? "signed " : "");
1098 dbgtext( "connect to service %s ", lp_servicename(snum) );
1099 dbgtext( "initially as user %s ",
1100 conn->session_info->unix_name );
1101 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
1102 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1108 TALLOC_FREE(smb_fname_cpath);
1109 /* We must exit this function as root. */
1110 if (geteuid() != 0) {
1111 change_to_root_user();
1113 if (on_err_call_dis_hook) {
1114 /* Call VFS disconnect hook */
1115 SMB_VFS_DISCONNECT(conn);
1117 if (claimed_connection) {
1118 yield_connection(conn, lp_servicename(snum));
1126 /****************************************************************************
1127 Make a connection to a service.
1130 ****************************************************************************/
1132 connection_struct *make_connection(struct smbd_server_connection *sconn,
1133 const char *service_in, DATA_BLOB password,
1134 const char *pdev, uint16 vuid,
1138 user_struct *vuser = NULL;
1139 char *service = NULL;
1145 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1147 if (!non_root_mode() && (euid = geteuid()) != 0) {
1148 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1149 "(%u)\n", (unsigned int)euid ));
1150 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1153 if (conn_num_open(sconn) > 2047) {
1154 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1158 if(lp_security() != SEC_SHARE) {
1159 vuser = get_valid_user_struct(sconn, vuid);
1161 DEBUG(1,("make_connection: refusing to connect with "
1162 "no session setup\n"));
1163 *status = NT_STATUS_ACCESS_DENIED;
1168 /* Logic to try and connect to the correct [homes] share, preferably
1169 without too many getpwnam() lookups. This is particulary nasty for
1170 winbind usernames, where the share name isn't the same as unix
1173 The snum of the homes share is stored on the vuser at session setup
1177 if (strequal(service_in,HOMES_NAME)) {
1178 if(lp_security() != SEC_SHARE) {
1179 DATA_BLOB no_pw = data_blob_null;
1180 if (vuser->homes_snum == -1) {
1181 DEBUG(2, ("[homes] share not available for "
1182 "this user because it was not found "
1183 "or created at session setup "
1185 *status = NT_STATUS_BAD_NETWORK_NAME;
1188 DEBUG(5, ("making a connection to [homes] service "
1189 "created at session setup time\n"));
1190 return make_connection_snum(sconn,
1195 /* Security = share. Try with
1196 * current_user_info.smb_name as the username. */
1197 if (*current_user_info.smb_name) {
1198 char *unix_username = NULL;
1199 (void)map_username(talloc_tos(),
1200 current_user_info.smb_name,
1202 snum = find_service(talloc_tos(),
1205 if (!unix_username) {
1206 *status = NT_STATUS_NO_MEMORY;
1211 DEBUG(5, ("making a connection to 'homes' "
1212 "service %s based on "
1213 "security=share\n", service_in));
1214 return make_connection_snum(sconn,
1220 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1221 && strequal(service_in,
1222 lp_servicename(vuser->homes_snum))) {
1223 DATA_BLOB no_pw = data_blob_null;
1224 DEBUG(5, ("making a connection to 'homes' service [%s] "
1225 "created at session setup time\n", service_in));
1226 return make_connection_snum(sconn,
1232 service = talloc_strdup(talloc_tos(), service_in);
1234 *status = NT_STATUS_NO_MEMORY;
1238 strlower_m(service);
1240 snum = find_service(talloc_tos(), service, &service);
1242 *status = NT_STATUS_NO_MEMORY;
1247 if (strequal(service,"IPC$") ||
1248 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1249 DEBUG(3,("refusing IPC connection to %s\n", service));
1250 *status = NT_STATUS_ACCESS_DENIED;
1254 DEBUG(3,("%s (%s) couldn't find service %s\n",
1255 get_remote_machine_name(),
1256 tsocket_address_string(
1257 sconn->remote_address, talloc_tos()),
1259 *status = NT_STATUS_BAD_NETWORK_NAME;
1263 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1264 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1265 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1266 "(pointing to %s)\n",
1267 service, lp_msdfs_proxy(snum)));
1268 *status = NT_STATUS_BAD_NETWORK_NAME;
1272 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1274 return make_connection_snum(sconn, snum, vuser,
1279 /****************************************************************************
1281 ****************************************************************************/
1283 void close_cnum(connection_struct *conn, uint16 vuid)
1285 file_close_conn(conn);
1287 if (!IS_IPC(conn)) {
1288 dptr_closecnum(conn);
1291 change_to_root_user();
1293 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1294 get_remote_machine_name(),
1295 conn->sconn->client_id.addr,
1296 lp_servicename(SNUM(conn))));
1298 /* Call VFS disconnect hook */
1299 SMB_VFS_DISCONNECT(conn);
1301 yield_connection(conn, lp_servicename(SNUM(conn)));
1303 /* make sure we leave the directory available for unmount */
1304 vfs_ChDir(conn, "/");
1306 /* execute any "postexec = " line */
1307 if (*lp_postexec(SNUM(conn)) &&
1308 change_to_user(conn, vuid)) {
1309 char *cmd = talloc_sub_advanced(talloc_tos(),
1310 lp_servicename(SNUM(conn)),
1311 conn->session_info->unix_name,
1313 conn->session_info->utok.gid,
1314 conn->session_info->sanitized_username,
1315 conn->session_info->info3->base.domain.string,
1316 lp_postexec(SNUM(conn)));
1319 change_to_root_user();
1322 change_to_root_user();
1323 /* execute any "root postexec = " line */
1324 if (*lp_rootpostexec(SNUM(conn))) {
1325 char *cmd = talloc_sub_advanced(talloc_tos(),
1326 lp_servicename(SNUM(conn)),
1327 conn->session_info->unix_name,
1329 conn->session_info->utok.gid,
1330 conn->session_info->sanitized_username,
1331 conn->session_info->info3->base.domain.string,
1332 lp_rootpostexec(SNUM(conn)));