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 "smbd/globals.h"
22 #include "../librpc/gen_ndr/netlogon.h"
23 #include "../libcli/security/security.h"
25 extern userdom_struct current_user_info;
27 static bool canonicalize_connect_path(connection_struct *conn)
29 #ifdef REALPATH_TAKES_NULL
31 char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,NULL);
35 ret = set_conn_connectpath(conn,resolved_name);
36 SAFE_FREE(resolved_name);
39 char resolved_name_buf[PATH_MAX+1];
40 char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,resolved_name_buf);
44 return set_conn_connectpath(conn,resolved_name);
45 #endif /* REALPATH_TAKES_NULL */
48 /****************************************************************************
49 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
50 absolute path stating in / and not ending in /.
51 Observent people will notice a similarity between this and check_path_syntax :-).
52 ****************************************************************************/
54 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
58 const char *s = connectpath;
59 bool start_of_name_component = true;
61 if (connectpath == NULL || connectpath[0] == '\0') {
65 /* Allocate for strlen + '\0' + possible leading '/' */
66 destname = (char *)SMB_MALLOC(strlen(connectpath) + 2);
72 *d++ = '/'; /* Always start with root. */
76 /* Eat multiple '/' */
80 if ((d > destname + 1) && (*s != '\0')) {
83 start_of_name_component = True;
87 if (start_of_name_component) {
88 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
89 /* Uh oh - "/../" or "/..\0" ! */
91 /* Go past the ../ or .. */
95 s += 2; /* Go past the .. */
98 /* If we just added a '/' - delete it */
99 if ((d > destname) && (*(d-1) == '/')) {
104 /* Are we at the start ? Can't go back further if so. */
106 *d++ = '/'; /* Can't delete root */
109 /* Go back one level... */
110 /* Decrement d first as d points to the *next* char to write into. */
111 for (d--; d > destname; d--) {
116 /* We're still at the start of a name component, just the previous one. */
118 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
119 /* Component of pathname can't be "." only - skip the '.' . */
133 /* Get the size of the next MB character. */
134 next_codepoint(s,&siz);
155 start_of_name_component = false;
159 /* And must not end in '/' */
160 if (d > destname + 1 && (*(d-1) == '/')) {
164 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
165 lp_servicename(SNUM(conn)), destname ));
167 string_set(&conn->connectpath, destname);
172 /****************************************************************************
173 Load parameters specific to a connection/service.
174 ****************************************************************************/
176 bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
185 conn->lastused_count++;
190 vfs_ChDir(conn,conn->connectpath) != 0 &&
191 vfs_ChDir(conn,conn->origpath) != 0) {
192 DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
193 conn->connectpath, strerror(errno)));
197 if ((conn == last_conn) && (last_flags == flags)) {
204 /* Obey the client case sensitivity requests - only for clients that support it. */
205 switch (lp_casesensitive(snum)) {
208 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
209 enum remote_arch_types ra_type = get_remote_arch();
210 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
211 /* Client can't support per-packet case sensitive pathnames. */
212 conn->case_sensitive = False;
214 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
219 conn->case_sensitive = True;
222 conn->case_sensitive = False;
228 static int load_registry_service(const char *servicename)
230 if (!lp_registry_shares()) {
234 if ((servicename == NULL) || (*servicename == '\0')) {
238 if (strequal(servicename, GLOBAL_NAME)) {
242 if (!process_registry_service(servicename)) {
246 return lp_servicenumber(servicename);
249 void load_registry_shares(void)
251 DEBUG(8, ("load_registry_shares()\n"));
252 if (!lp_registry_shares()) {
256 process_registry_shares();
261 /****************************************************************************
262 Add a home service. Returns the new service number or -1 if fail.
263 ****************************************************************************/
265 int add_home_service(const char *service, const char *username, const char *homedir)
269 if (!service || !homedir || homedir[0] == '\0')
272 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
273 if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
279 * If this is a winbindd provided username, remove
280 * the domain component before adding the service.
281 * Log a warning if the "path=" parameter does not
282 * include any macros.
286 const char *p = strchr(service,*lp_winbind_separator());
288 /* We only want the 'user' part of the string */
294 if (!lp_add_home(service, iHomeService, username, homedir)) {
298 return lp_servicenumber(service);
303 * Find a service entry.
305 * @param service is modified (to canonical form??)
308 int find_service(TALLOC_CTX *ctx, const char *service_in, char **p_service_out)
316 /* First make a copy. */
317 *p_service_out = talloc_strdup(ctx, service_in);
318 if (!*p_service_out) {
322 all_string_sub(*p_service_out,"\\","/",0);
324 iService = lp_servicenumber(*p_service_out);
326 /* now handle the special case of a home directory */
328 char *phome_dir = get_user_home_dir(ctx, *p_service_out);
332 * Try mapping the servicename, it may
333 * be a Windows to unix mapped user name.
335 if(map_username(ctx, *p_service_out, p_service_out)) {
336 if (*p_service_out == NULL) {
340 phome_dir = get_user_home_dir(
341 ctx, *p_service_out);
345 DEBUG(3,("checking for home directory %s gave %s\n",*p_service_out,
346 phome_dir?phome_dir:"(NULL)"));
348 iService = add_home_service(*p_service_out,*p_service_out /* 'username' */, phome_dir);
351 /* If we still don't have a service, attempt to add it as a printer. */
355 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
356 iPrinterService = load_registry_service(PRINTERS_NAME);
358 if (iPrinterService >= 0) {
359 DEBUG(3,("checking whether %s is a valid printer name...\n",
361 if (pcap_printername_ok(*p_service_out)) {
362 DEBUG(3,("%s is a valid printer name\n",
364 DEBUG(3,("adding %s as a printer service\n",
366 lp_add_printer(*p_service_out, iPrinterService);
367 iService = lp_servicenumber(*p_service_out);
369 DEBUG(0,("failed to add %s as a printer service!\n",
373 DEBUG(3,("%s is not a valid printer name\n",
379 /* Check for default vfs service? Unsure whether to implement this */
384 iService = load_registry_service(*p_service_out);
387 /* Is it a usershare service ? */
388 if (iService < 0 && *lp_usershare_path()) {
389 /* Ensure the name is canonicalized. */
390 strlower_m(*p_service_out);
391 iService = load_usershare_service(*p_service_out);
394 /* just possibly it's a default service? */
396 char *pdefservice = lp_defaultservice();
399 !strequal(pdefservice, *p_service_out)
400 && !strstr_m(*p_service_out,"..")) {
402 * We need to do a local copy here as lp_defaultservice()
403 * returns one of the rotating lp_string buffers that
404 * could get overwritten by the recursive find_service() call
405 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
407 char *defservice = talloc_strdup(ctx, pdefservice);
413 /* Disallow anything except explicit share names. */
414 if (strequal(defservice,HOMES_NAME) ||
415 strequal(defservice, PRINTERS_NAME) ||
416 strequal(defservice, "IPC$")) {
417 TALLOC_FREE(defservice);
421 iService = find_service(ctx, defservice, p_service_out);
422 if (!*p_service_out) {
423 TALLOC_FREE(defservice);
428 all_string_sub(*p_service_out, "_","/",0);
429 iService = lp_add_service(*p_service_out, iService);
431 TALLOC_FREE(defservice);
436 if (!VALID_SNUM(iService)) {
437 DEBUG(0,("Invalid snum %d for %s\n",iService,
446 DEBUG(3,("find_service() failed to find service %s\n",
454 /****************************************************************************
455 do some basic sainity checks on the share.
456 This function modifies dev, ecode.
457 ****************************************************************************/
459 static NTSTATUS share_sanity_checks(struct client_address *client_id, int snum,
462 if (!lp_snum_ok(snum) ||
463 !allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
464 client_id->name, client_id->addr)) {
465 return NT_STATUS_ACCESS_DENIED;
468 if (dev[0] == '?' || !dev[0]) {
469 if (lp_print_ok(snum)) {
470 fstrcpy(dev,"LPT1:");
471 } else if (strequal(lp_fstype(snum), "IPC")) {
480 if (lp_print_ok(snum)) {
481 if (!strequal(dev, "LPT1:")) {
482 return NT_STATUS_BAD_DEVICE_TYPE;
484 } else if (strequal(lp_fstype(snum), "IPC")) {
485 if (!strequal(dev, "IPC")) {
486 return NT_STATUS_BAD_DEVICE_TYPE;
488 } else if (!strequal(dev, "A:")) {
489 return NT_STATUS_BAD_DEVICE_TYPE;
492 /* Behave as a printer if we are supposed to */
493 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
494 fstrcpy(dev, "LPT1:");
501 * Go through lookup_name etc to find the force'd group.
503 * Create a new token from src_token, replacing the primary group sid with the
507 static NTSTATUS find_forced_group(bool force_user,
508 int snum, const char *username,
509 struct dom_sid *pgroup_sid,
512 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
513 TALLOC_CTX *frame = talloc_stackframe();
514 struct dom_sid group_sid;
515 enum lsa_SidType type;
517 bool user_must_be_member = False;
520 groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
521 if (groupname == NULL) {
522 DEBUG(1, ("talloc_strdup failed\n"));
523 result = NT_STATUS_NO_MEMORY;
527 if (groupname[0] == '+') {
528 user_must_be_member = True;
532 groupname = talloc_string_sub(talloc_tos(), groupname,
533 "%S", lp_servicename(snum));
534 if (groupname == NULL) {
535 DEBUG(1, ("talloc_string_sub failed\n"));
536 result = NT_STATUS_NO_MEMORY;
540 if (!lookup_name_smbconf(talloc_tos(), groupname,
541 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
542 NULL, NULL, &group_sid, &type)) {
543 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
548 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
549 (type != SID_NAME_WKN_GRP)) {
550 DEBUG(10, ("%s is a %s, not a group\n", groupname,
551 sid_type_lookup(type)));
555 if (!sid_to_gid(&group_sid, &gid)) {
556 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
557 sid_string_dbg(&group_sid), groupname));
562 * If the user has been forced and the forced group starts with a '+',
563 * then we only set the group to be the forced group if the forced
564 * user is a member of that group. Otherwise, the meaning of the '+'
568 if (force_user && user_must_be_member) {
569 if (user_in_group_sid(username, &group_sid)) {
570 sid_copy(pgroup_sid, &group_sid);
572 DEBUG(3,("Forced group %s for member %s\n",
573 groupname, username));
575 DEBUG(0,("find_forced_group: forced user %s is not a member "
576 "of forced group %s. Disallowing access.\n",
577 username, groupname ));
578 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
582 sid_copy(pgroup_sid, &group_sid);
584 DEBUG(3,("Forced group %s\n", groupname));
587 result = NT_STATUS_OK;
593 /****************************************************************************
594 Create an auth_serversupplied_info structure for a connection_struct
595 ****************************************************************************/
597 static NTSTATUS create_connection_server_info(struct smbd_server_connection *sconn,
598 TALLOC_CTX *mem_ctx, int snum,
599 struct auth_serversupplied_info *vuid_serverinfo,
601 struct auth_serversupplied_info **presult)
603 if (lp_guest_only(snum)) {
604 return make_server_info_guest(mem_ctx, presult);
607 if (vuid_serverinfo != NULL) {
609 struct auth_serversupplied_info *result;
612 * This is the normal security != share case where we have a
613 * valid vuid from the session setup. */
615 if (vuid_serverinfo->guest) {
616 if (!lp_guest_ok(snum)) {
617 DEBUG(2, ("guest user (from session setup) "
618 "not permitted to access this share "
619 "(%s)\n", lp_servicename(snum)));
620 return NT_STATUS_ACCESS_DENIED;
623 if (!user_ok_token(vuid_serverinfo->unix_name,
624 vuid_serverinfo->info3->base.domain.string,
625 vuid_serverinfo->ptok, snum)) {
626 DEBUG(2, ("user '%s' (from session setup) not "
627 "permitted to access this share "
629 vuid_serverinfo->unix_name,
630 lp_servicename(snum)));
631 return NT_STATUS_ACCESS_DENIED;
635 result = copy_serverinfo(mem_ctx, vuid_serverinfo);
636 if (result == NULL) {
637 return NT_STATUS_NO_MEMORY;
644 if (lp_security() == SEC_SHARE) {
649 /* add the sharename as a possible user name if we
650 are in share mode security */
652 add_session_user(sconn, lp_servicename(snum));
654 /* shall we let them in? */
656 if (!authorise_login(sconn, snum,user,password,&guest)) {
657 DEBUG( 2, ( "Invalid username/password for [%s]\n",
658 lp_servicename(snum)) );
659 return NT_STATUS_WRONG_PASSWORD;
662 return make_serverinfo_from_username(mem_ctx, user, guest,
666 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
667 return NT_STATUS_ACCESS_DENIED;
671 /****************************************************************************
672 Make a connection, given the snum to connect to, and the vuser of the
673 connecting user if appropriate.
674 ****************************************************************************/
676 connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
677 int snum, user_struct *vuser,
682 connection_struct *conn = NULL;
683 struct smb_filename *smb_fname_cpath = NULL;
686 bool on_err_call_dis_hook = false;
687 bool claimed_connection = false;
694 *pstatus = share_sanity_checks(&sconn->client_id, snum, dev);
695 if (NT_STATUS_IS_ERR(*pstatus)) {
699 conn = conn_new(sconn);
701 DEBUG(0,("Couldn't find free connection.\n"));
702 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
706 conn->params->service = snum;
708 status = create_connection_server_info(sconn,
709 conn, snum, vuser ? vuser->server_info : NULL, password,
712 if (!NT_STATUS_IS_OK(status)) {
713 DEBUG(1, ("create_connection_server_info failed: %s\n",
719 if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
720 conn->force_user = true;
723 add_session_user(sconn, conn->server_info->unix_name);
725 conn->num_files_open = 0;
726 conn->lastused = conn->lastused_count = time(NULL);
728 conn->printer = (strncmp(dev,"LPT",3) == 0);
729 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
730 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
732 /* Case options for the share. */
733 if (lp_casesensitive(snum) == Auto) {
734 /* We will be setting this per packet. Set to be case
735 * insensitive for now. */
736 conn->case_sensitive = False;
738 conn->case_sensitive = (bool)lp_casesensitive(snum);
741 conn->case_preserve = lp_preservecase(snum);
742 conn->short_case_preserve = lp_shortpreservecase(snum);
744 conn->encrypt_level = lp_smb_encrypt(snum);
746 conn->veto_list = NULL;
747 conn->hide_list = NULL;
748 conn->veto_oplock_list = NULL;
749 conn->aio_write_behind_list = NULL;
751 conn->read_only = lp_readonly(SNUM(conn));
753 if (*lp_force_user(snum)) {
756 * Replace conn->server_info with a completely faked up one
757 * from the username we are forced into :-)
761 struct auth_serversupplied_info *forced_serverinfo;
763 fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
764 lp_servicename(snum));
766 *pstatus = NT_STATUS_NO_MEMORY;
770 status = make_serverinfo_from_username(
771 conn, fuser, conn->server_info->guest,
773 if (!NT_STATUS_IS_OK(status)) {
778 TALLOC_FREE(conn->server_info);
779 conn->server_info = forced_serverinfo;
781 conn->force_user = True;
782 DEBUG(3,("Forced user %s\n", fuser));
786 * If force group is true, then override
787 * any groupid stored for the connecting user.
790 if (*lp_force_group(snum)) {
792 status = find_forced_group(
793 conn->force_user, snum, conn->server_info->unix_name,
794 &conn->server_info->ptok->sids[1],
795 &conn->server_info->utok.gid);
797 if (!NT_STATUS_IS_OK(status)) {
803 * We need to cache this gid, to use within
804 * change_to_user() separately from the conn->server_info
805 * struct. We only use conn->server_info directly if
806 * "force_user" was set.
808 conn->force_group_gid = conn->server_info->utok.gid;
811 conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
814 char *s = talloc_sub_advanced(talloc_tos(),
815 lp_servicename(SNUM(conn)),
816 conn->server_info->unix_name,
818 conn->server_info->utok.gid,
819 conn->server_info->sanitized_username,
820 conn->server_info->info3->base.domain.string,
823 *pstatus = NT_STATUS_NO_MEMORY;
827 if (!set_conn_connectpath(conn,s)) {
829 *pstatus = NT_STATUS_NO_MEMORY;
832 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
833 lp_servicename(snum)));
838 * New code to check if there's a share security descripter
839 * added from NT server manager. This is done after the
840 * smb.conf checks are done as we need a uid and token. JRA.
845 bool can_write = False;
847 can_write = share_access_check(conn->server_info->ptok,
848 lp_servicename(snum),
852 if (!share_access_check(conn->server_info->ptok,
853 lp_servicename(snum),
855 /* No access, read or write. */
856 DEBUG(0,("make_connection: connection to %s "
857 "denied due to security "
859 lp_servicename(snum)));
860 *pstatus = NT_STATUS_ACCESS_DENIED;
863 conn->read_only = True;
867 /* Initialise VFS function pointers */
869 if (!smbd_vfs_init(conn)) {
870 DEBUG(0, ("vfs_init failed for service %s\n",
871 lp_servicename(snum)));
872 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
876 /* ROOT Activities: */
877 /* explicitly check widelinks here so that we can correctly warn
879 widelinks_warning(snum);
882 * Enforce the max connections parameter.
885 if ((lp_max_connections(snum) > 0)
886 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
887 lp_max_connections(snum))) {
889 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
890 lp_max_connections(snum), lp_servicename(snum)));
891 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
896 * Get us an entry in the connections db
898 if (!claim_connection(conn, lp_servicename(snum))) {
899 DEBUG(1, ("Could not store connections entry\n"));
900 *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
903 claimed_connection = true;
905 /* Invoke VFS make connection hook - this must be the first
906 filesystem operation that we do. */
908 if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
909 conn->server_info->unix_name) < 0) {
910 DEBUG(0,("make_connection: VFS make connection failed!\n"));
911 *pstatus = NT_STATUS_UNSUCCESSFUL;
915 /* Any error exit after here needs to call the disconnect hook. */
916 on_err_call_dis_hook = true;
918 if ((!conn->printer) && (!conn->ipc)) {
919 conn->notify_ctx = notify_init(conn,
920 sconn_server_id(sconn),
922 smbd_event_context(),
927 * Fix compatibility issue pointed out by Volker.
928 * We pass the conn->connectpath to the preexec
929 * scripts as a parameter, so attempt to canonicalize
930 * it here before calling the preexec scripts.
931 * We ignore errors here, as it is possible that
932 * the conn->connectpath doesn't exist yet and
933 * the preexec scripts will create them.
936 (void)canonicalize_connect_path(conn);
938 /* Preexecs are done here as they might make the dir we are to ChDir
940 /* execute any "root preexec = " line */
941 if (*lp_rootpreexec(snum)) {
942 char *cmd = talloc_sub_advanced(talloc_tos(),
943 lp_servicename(SNUM(conn)),
944 conn->server_info->unix_name,
946 conn->server_info->utok.gid,
947 conn->server_info->sanitized_username,
948 conn->server_info->info3->base.domain.string,
949 lp_rootpreexec(snum));
950 DEBUG(5,("cmd=%s\n",cmd));
951 ret = smbrun(cmd,NULL);
953 if (ret != 0 && lp_rootpreexec_close(snum)) {
954 DEBUG(1,("root preexec gave %d - failing "
955 "connection\n", ret));
956 *pstatus = NT_STATUS_ACCESS_DENIED;
961 /* USER Activites: */
962 if (!change_to_user(conn, conn->vuid)) {
963 /* No point continuing if they fail the basic checks */
964 DEBUG(0,("Can't become connected user!\n"));
965 *pstatus = NT_STATUS_LOGON_FAILURE;
972 /* Remember that a different vuid can connect later without these
975 /* Preexecs are done here as they might make the dir we are to ChDir
978 /* execute any "preexec = " line */
979 if (*lp_preexec(snum)) {
980 char *cmd = talloc_sub_advanced(talloc_tos(),
981 lp_servicename(SNUM(conn)),
982 conn->server_info->unix_name,
984 conn->server_info->utok.gid,
985 conn->server_info->sanitized_username,
986 conn->server_info->info3->base.domain.string,
988 ret = smbrun(cmd,NULL);
990 if (ret != 0 && lp_preexec_close(snum)) {
991 DEBUG(1,("preexec gave %d - failing connection\n",
993 *pstatus = NT_STATUS_ACCESS_DENIED;
998 #ifdef WITH_FAKE_KASERVER
999 if (lp_afs_share(snum)) {
1005 * we've finished with the user stuff - go back to root
1006 * so the SMB_VFS_STAT call will only fail on path errors,
1007 * not permission problems.
1009 change_to_root_user();
1010 /* ROOT Activites: */
1013 * If widelinks are disallowed we need to canonicalise the connect
1014 * path here to ensure we don't have any symlinks in the
1015 * connectpath. We will be checking all paths on this connection are
1016 * below this directory. We must do this after the VFS init as we
1017 * depend on the realpath() pointer in the vfs table. JRA.
1019 if (!lp_widelinks(snum)) {
1020 if (!canonicalize_connect_path(conn)) {
1021 DEBUG(0, ("canonicalize_connect_path failed "
1022 "for service %s, path %s\n",
1023 lp_servicename(snum),
1024 conn->connectpath));
1025 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1030 /* Add veto/hide lists */
1031 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1032 set_namearray( &conn->veto_list, lp_veto_files(snum));
1033 set_namearray( &conn->hide_list, lp_hide_files(snum));
1034 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1035 set_namearray( &conn->aio_write_behind_list,
1036 lp_aio_write_behind(snum));
1038 status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
1039 NULL, NULL, &smb_fname_cpath);
1040 if (!NT_STATUS_IS_OK(status)) {
1045 /* win2000 does not check the permissions on the directory
1046 during the tree connect, instead relying on permission
1047 check during individual operations. To match this behaviour
1048 I have disabled this chdir check (tridge) */
1049 /* the alternative is just to check the directory exists */
1051 if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
1052 !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1053 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1054 DEBUG(0,("'%s' is not a directory, when connecting to "
1055 "[%s]\n", conn->connectpath,
1056 lp_servicename(snum)));
1058 DEBUG(0,("'%s' does not exist or permission denied "
1059 "when connecting to [%s] Error was %s\n",
1060 conn->connectpath, lp_servicename(snum),
1063 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1066 conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
1068 string_set(&conn->origpath,conn->connectpath);
1070 /* Figure out the characteristics of the underlying filesystem. This
1071 * assumes that all the filesystem mounted withing a share path have
1072 * the same characteristics, which is likely but not guaranteed.
1075 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
1078 * Print out the 'connected as' stuff here as we need
1079 * to know the effective uid and gid we will be using
1080 * (at least initially).
1083 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1084 dbgtext( "%s (%s) ", get_remote_machine_name(),
1085 conn->sconn->client_id.addr );
1086 dbgtext( "%s", srv_is_signing_active(sconn) ? "signed " : "");
1087 dbgtext( "connect to service %s ", lp_servicename(snum) );
1088 dbgtext( "initially as user %s ",
1089 conn->server_info->unix_name );
1090 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
1091 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1097 TALLOC_FREE(smb_fname_cpath);
1098 /* We must exit this function as root. */
1099 if (geteuid() != 0) {
1100 change_to_root_user();
1102 if (on_err_call_dis_hook) {
1103 /* Call VFS disconnect hook */
1104 SMB_VFS_DISCONNECT(conn);
1106 if (claimed_connection) {
1107 yield_connection(conn, lp_servicename(snum));
1115 /****************************************************************************
1116 Make a connection to a service.
1119 ****************************************************************************/
1121 connection_struct *make_connection(struct smbd_server_connection *sconn,
1122 const char *service_in, DATA_BLOB password,
1123 const char *pdev, uint16 vuid,
1127 user_struct *vuser = NULL;
1128 char *service = NULL;
1134 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1136 if (!non_root_mode() && (euid = geteuid()) != 0) {
1137 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1138 "(%u)\n", (unsigned int)euid ));
1139 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1142 if (conn_num_open(sconn) > 2047) {
1143 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1147 if(lp_security() != SEC_SHARE) {
1148 vuser = get_valid_user_struct(sconn, vuid);
1150 DEBUG(1,("make_connection: refusing to connect with "
1151 "no session setup\n"));
1152 *status = NT_STATUS_ACCESS_DENIED;
1157 /* Logic to try and connect to the correct [homes] share, preferably
1158 without too many getpwnam() lookups. This is particulary nasty for
1159 winbind usernames, where the share name isn't the same as unix
1162 The snum of the homes share is stored on the vuser at session setup
1166 if (strequal(service_in,HOMES_NAME)) {
1167 if(lp_security() != SEC_SHARE) {
1168 DATA_BLOB no_pw = data_blob_null;
1169 if (vuser->homes_snum == -1) {
1170 DEBUG(2, ("[homes] share not available for "
1171 "this user because it was not found "
1172 "or created at session setup "
1174 *status = NT_STATUS_BAD_NETWORK_NAME;
1177 DEBUG(5, ("making a connection to [homes] service "
1178 "created at session setup time\n"));
1179 return make_connection_snum(sconn,
1184 /* Security = share. Try with
1185 * current_user_info.smb_name as the username. */
1186 if (*current_user_info.smb_name) {
1187 char *unix_username = NULL;
1188 (void)map_username(talloc_tos(),
1189 current_user_info.smb_name,
1191 snum = find_service(talloc_tos(),
1194 if (!unix_username) {
1195 *status = NT_STATUS_NO_MEMORY;
1200 DEBUG(5, ("making a connection to 'homes' "
1201 "service %s based on "
1202 "security=share\n", service_in));
1203 return make_connection_snum(sconn,
1209 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1210 && strequal(service_in,
1211 lp_servicename(vuser->homes_snum))) {
1212 DATA_BLOB no_pw = data_blob_null;
1213 DEBUG(5, ("making a connection to 'homes' service [%s] "
1214 "created at session setup time\n", service_in));
1215 return make_connection_snum(sconn,
1221 service = talloc_strdup(talloc_tos(), service_in);
1223 *status = NT_STATUS_NO_MEMORY;
1227 strlower_m(service);
1229 snum = find_service(talloc_tos(), service, &service);
1231 *status = NT_STATUS_NO_MEMORY;
1236 if (strequal(service,"IPC$") ||
1237 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1238 DEBUG(3,("refusing IPC connection to %s\n", service));
1239 *status = NT_STATUS_ACCESS_DENIED;
1243 DEBUG(3,("%s (%s) couldn't find service %s\n",
1244 get_remote_machine_name(),
1245 tsocket_address_string(
1246 sconn->remote_address, talloc_tos()),
1248 *status = NT_STATUS_BAD_NETWORK_NAME;
1252 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1253 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1254 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1255 "(pointing to %s)\n",
1256 service, lp_msdfs_proxy(snum)));
1257 *status = NT_STATUS_BAD_NETWORK_NAME;
1261 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1263 return make_connection_snum(sconn, snum, vuser,
1268 /****************************************************************************
1270 ****************************************************************************/
1272 void close_cnum(connection_struct *conn, uint16 vuid)
1274 file_close_conn(conn);
1276 if (!IS_IPC(conn)) {
1277 dptr_closecnum(conn);
1280 change_to_root_user();
1282 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1283 get_remote_machine_name(),
1284 conn->sconn->client_id.addr,
1285 lp_servicename(SNUM(conn))));
1287 /* Call VFS disconnect hook */
1288 SMB_VFS_DISCONNECT(conn);
1290 yield_connection(conn, lp_servicename(SNUM(conn)));
1292 /* make sure we leave the directory available for unmount */
1293 vfs_ChDir(conn, "/");
1295 /* execute any "postexec = " line */
1296 if (*lp_postexec(SNUM(conn)) &&
1297 change_to_user(conn, vuid)) {
1298 char *cmd = talloc_sub_advanced(talloc_tos(),
1299 lp_servicename(SNUM(conn)),
1300 conn->server_info->unix_name,
1302 conn->server_info->utok.gid,
1303 conn->server_info->sanitized_username,
1304 conn->server_info->info3->base.domain.string,
1305 lp_postexec(SNUM(conn)));
1308 change_to_root_user();
1311 change_to_root_user();
1312 /* execute any "root postexec = " line */
1313 if (*lp_rootpostexec(SNUM(conn))) {
1314 char *cmd = talloc_sub_advanced(talloc_tos(),
1315 lp_servicename(SNUM(conn)),
1316 conn->server_info->unix_name,
1318 conn->server_info->utok.gid,
1319 conn->server_info->sanitized_username,
1320 conn->server_info->info3->base.domain.string,
1321 lp_rootpostexec(SNUM(conn)));