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/globals.h"
23 #include "../librpc/gen_ndr/netlogon.h"
24 #include "../libcli/security/security.h"
25 #include "printing/pcap.h"
26 #include "passdb/lookup_sid.h"
28 extern userdom_struct current_user_info;
30 static bool canonicalize_connect_path(connection_struct *conn)
33 char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath);
37 ret = set_conn_connectpath(conn,resolved_name);
38 SAFE_FREE(resolved_name);
42 /****************************************************************************
43 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
44 absolute path stating in / and not ending in /.
45 Observent people will notice a similarity between this and check_path_syntax :-).
46 ****************************************************************************/
48 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
52 const char *s = connectpath;
53 bool start_of_name_component = true;
55 if (connectpath == NULL || connectpath[0] == '\0') {
59 /* Allocate for strlen + '\0' + possible leading '/' */
60 destname = (char *)SMB_MALLOC(strlen(connectpath) + 2);
66 *d++ = '/'; /* Always start with root. */
70 /* Eat multiple '/' */
74 if ((d > destname + 1) && (*s != '\0')) {
77 start_of_name_component = True;
81 if (start_of_name_component) {
82 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
83 /* Uh oh - "/../" or "/..\0" ! */
85 /* Go past the ../ or .. */
89 s += 2; /* Go past the .. */
92 /* If we just added a '/' - delete it */
93 if ((d > destname) && (*(d-1) == '/')) {
98 /* Are we at the start ? Can't go back further if so. */
100 *d++ = '/'; /* Can't delete root */
103 /* Go back one level... */
104 /* Decrement d first as d points to the *next* char to write into. */
105 for (d--; d > destname; d--) {
110 /* We're still at the start of a name component, just the previous one. */
112 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
113 /* Component of pathname can't be "." only - skip the '.' . */
127 /* Get the size of the next MB character. */
128 next_codepoint(s,&siz);
149 start_of_name_component = false;
153 /* And must not end in '/' */
154 if (d > destname + 1 && (*(d-1) == '/')) {
158 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
159 lp_servicename(SNUM(conn)), destname ));
161 string_set(&conn->connectpath, destname);
166 /****************************************************************************
167 Load parameters specific to a connection/service.
168 ****************************************************************************/
170 bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
179 conn->lastused_count++;
184 vfs_ChDir(conn,conn->connectpath) != 0 &&
185 vfs_ChDir(conn,conn->origpath) != 0) {
186 DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
187 conn->connectpath, strerror(errno)));
191 if ((conn == last_conn) && (last_flags == flags)) {
198 /* Obey the client case sensitivity requests - only for clients that support it. */
199 switch (lp_casesensitive(snum)) {
202 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
203 enum remote_arch_types ra_type = get_remote_arch();
204 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
205 /* Client can't support per-packet case sensitive pathnames. */
206 conn->case_sensitive = False;
208 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
213 conn->case_sensitive = True;
216 conn->case_sensitive = False;
222 static int load_registry_service(const char *servicename)
224 if (!lp_registry_shares()) {
228 if ((servicename == NULL) || (*servicename == '\0')) {
232 if (strequal(servicename, GLOBAL_NAME)) {
236 if (!process_registry_service(servicename)) {
240 return lp_servicenumber(servicename);
243 void load_registry_shares(void)
245 DEBUG(8, ("load_registry_shares()\n"));
246 if (!lp_registry_shares()) {
250 process_registry_shares();
255 /****************************************************************************
256 Add a home service. Returns the new service number or -1 if fail.
257 ****************************************************************************/
259 int add_home_service(const char *service, const char *username, const char *homedir)
263 if (!service || !homedir || homedir[0] == '\0')
266 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
267 if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
273 * If this is a winbindd provided username, remove
274 * the domain component before adding the service.
275 * Log a warning if the "path=" parameter does not
276 * include any macros.
280 const char *p = strchr(service,*lp_winbind_separator());
282 /* We only want the 'user' part of the string */
288 if (!lp_add_home(service, iHomeService, username, homedir)) {
292 return lp_servicenumber(service);
297 * Find a service entry.
299 * @param service is modified (to canonical form??)
302 int find_service(TALLOC_CTX *ctx, const char *service_in, char **p_service_out)
310 /* First make a copy. */
311 *p_service_out = talloc_strdup(ctx, service_in);
312 if (!*p_service_out) {
316 all_string_sub(*p_service_out,"\\","/",0);
318 iService = lp_servicenumber(*p_service_out);
320 /* now handle the special case of a home directory */
322 char *phome_dir = get_user_home_dir(ctx, *p_service_out);
326 * Try mapping the servicename, it may
327 * be a Windows to unix mapped user name.
329 if(map_username(ctx, *p_service_out, p_service_out)) {
330 if (*p_service_out == NULL) {
334 phome_dir = get_user_home_dir(
335 ctx, *p_service_out);
339 DEBUG(3,("checking for home directory %s gave %s\n",*p_service_out,
340 phome_dir?phome_dir:"(NULL)"));
342 iService = add_home_service(*p_service_out,*p_service_out /* 'username' */, phome_dir);
345 /* If we still don't have a service, attempt to add it as a printer. */
349 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
350 iPrinterService = load_registry_service(PRINTERS_NAME);
352 if (iPrinterService >= 0) {
353 DEBUG(3,("checking whether %s is a valid printer name...\n",
355 if (pcap_printername_ok(*p_service_out)) {
356 DEBUG(3,("%s is a valid printer name\n",
358 DEBUG(3,("adding %s as a printer service\n",
360 lp_add_printer(*p_service_out, iPrinterService);
361 iService = lp_servicenumber(*p_service_out);
363 DEBUG(0,("failed to add %s as a printer service!\n",
367 DEBUG(3,("%s is not a valid printer name\n",
373 /* Check for default vfs service? Unsure whether to implement this */
378 iService = load_registry_service(*p_service_out);
381 /* Is it a usershare service ? */
382 if (iService < 0 && *lp_usershare_path()) {
383 /* Ensure the name is canonicalized. */
384 strlower_m(*p_service_out);
385 iService = load_usershare_service(*p_service_out);
388 /* just possibly it's a default service? */
390 char *pdefservice = lp_defaultservice();
393 !strequal(pdefservice, *p_service_out)
394 && !strstr_m(*p_service_out,"..")) {
396 * We need to do a local copy here as lp_defaultservice()
397 * returns one of the rotating lp_string buffers that
398 * could get overwritten by the recursive find_service() call
399 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
401 char *defservice = talloc_strdup(ctx, pdefservice);
407 /* Disallow anything except explicit share names. */
408 if (strequal(defservice,HOMES_NAME) ||
409 strequal(defservice, PRINTERS_NAME) ||
410 strequal(defservice, "IPC$")) {
411 TALLOC_FREE(defservice);
415 iService = find_service(ctx, defservice, p_service_out);
416 if (!*p_service_out) {
417 TALLOC_FREE(defservice);
422 all_string_sub(*p_service_out, "_","/",0);
423 iService = lp_add_service(*p_service_out, iService);
425 TALLOC_FREE(defservice);
430 if (!VALID_SNUM(iService)) {
431 DEBUG(0,("Invalid snum %d for %s\n",iService,
440 DEBUG(3,("find_service() failed to find service %s\n",
448 /****************************************************************************
449 do some basic sainity checks on the share.
450 This function modifies dev, ecode.
451 ****************************************************************************/
453 static NTSTATUS share_sanity_checks(struct client_address *client_id, int snum,
456 if (!lp_snum_ok(snum) ||
457 !allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
458 client_id->name, client_id->addr)) {
459 return NT_STATUS_ACCESS_DENIED;
462 if (dev[0] == '?' || !dev[0]) {
463 if (lp_print_ok(snum)) {
464 fstrcpy(dev,"LPT1:");
465 } else if (strequal(lp_fstype(snum), "IPC")) {
474 if (lp_print_ok(snum)) {
475 if (!strequal(dev, "LPT1:")) {
476 return NT_STATUS_BAD_DEVICE_TYPE;
478 } else if (strequal(lp_fstype(snum), "IPC")) {
479 if (!strequal(dev, "IPC")) {
480 return NT_STATUS_BAD_DEVICE_TYPE;
482 } else if (!strequal(dev, "A:")) {
483 return NT_STATUS_BAD_DEVICE_TYPE;
486 /* Behave as a printer if we are supposed to */
487 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
488 fstrcpy(dev, "LPT1:");
495 * Go through lookup_name etc to find the force'd group.
497 * Create a new token from src_token, replacing the primary group sid with the
501 static NTSTATUS find_forced_group(bool force_user,
502 int snum, const char *username,
503 struct dom_sid *pgroup_sid,
506 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
507 TALLOC_CTX *frame = talloc_stackframe();
508 struct dom_sid group_sid;
509 enum lsa_SidType type;
511 bool user_must_be_member = False;
514 groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
515 if (groupname == NULL) {
516 DEBUG(1, ("talloc_strdup failed\n"));
517 result = NT_STATUS_NO_MEMORY;
521 if (groupname[0] == '+') {
522 user_must_be_member = True;
526 groupname = talloc_string_sub(talloc_tos(), groupname,
527 "%S", lp_servicename(snum));
528 if (groupname == NULL) {
529 DEBUG(1, ("talloc_string_sub failed\n"));
530 result = NT_STATUS_NO_MEMORY;
534 if (!lookup_name_smbconf(talloc_tos(), groupname,
535 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
536 NULL, NULL, &group_sid, &type)) {
537 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
542 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
543 (type != SID_NAME_WKN_GRP)) {
544 DEBUG(10, ("%s is a %s, not a group\n", groupname,
545 sid_type_lookup(type)));
549 if (!sid_to_gid(&group_sid, &gid)) {
550 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
551 sid_string_dbg(&group_sid), groupname));
556 * If the user has been forced and the forced group starts with a '+',
557 * then we only set the group to be the forced group if the forced
558 * user is a member of that group. Otherwise, the meaning of the '+'
562 if (force_user && user_must_be_member) {
563 if (user_in_group_sid(username, &group_sid)) {
564 sid_copy(pgroup_sid, &group_sid);
566 DEBUG(3,("Forced group %s for member %s\n",
567 groupname, username));
569 DEBUG(0,("find_forced_group: forced user %s is not a member "
570 "of forced group %s. Disallowing access.\n",
571 username, groupname ));
572 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
576 sid_copy(pgroup_sid, &group_sid);
578 DEBUG(3,("Forced group %s\n", groupname));
581 result = NT_STATUS_OK;
587 /****************************************************************************
588 Create an auth_serversupplied_info structure for a connection_struct
589 ****************************************************************************/
591 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
592 TALLOC_CTX *mem_ctx, int snum,
593 struct auth_serversupplied_info *vuid_serverinfo,
595 struct auth_serversupplied_info **presult)
597 if (lp_guest_only(snum)) {
598 return make_server_info_guest(mem_ctx, presult);
601 if (vuid_serverinfo != NULL) {
603 struct auth_serversupplied_info *result;
606 * This is the normal security != share case where we have a
607 * valid vuid from the session setup. */
609 if (vuid_serverinfo->guest) {
610 if (!lp_guest_ok(snum)) {
611 DEBUG(2, ("guest user (from session setup) "
612 "not permitted to access this share "
613 "(%s)\n", lp_servicename(snum)));
614 return NT_STATUS_ACCESS_DENIED;
617 if (!user_ok_token(vuid_serverinfo->unix_name,
618 vuid_serverinfo->info3->base.domain.string,
619 vuid_serverinfo->security_token, snum)) {
620 DEBUG(2, ("user '%s' (from session setup) not "
621 "permitted to access this share "
623 vuid_serverinfo->unix_name,
624 lp_servicename(snum)));
625 return NT_STATUS_ACCESS_DENIED;
629 result = copy_serverinfo(mem_ctx, vuid_serverinfo);
630 if (result == NULL) {
631 return NT_STATUS_NO_MEMORY;
638 if (lp_security() == SEC_SHARE) {
643 /* add the sharename as a possible user name if we
644 are in share mode security */
646 add_session_user(sconn, lp_servicename(snum));
648 /* shall we let them in? */
650 if (!authorise_login(sconn, snum,user,password,&guest)) {
651 DEBUG( 2, ( "Invalid username/password for [%s]\n",
652 lp_servicename(snum)) );
653 return NT_STATUS_WRONG_PASSWORD;
656 return make_serverinfo_from_username(mem_ctx, user, guest,
660 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
661 return NT_STATUS_ACCESS_DENIED;
664 /****************************************************************************
665 set relavent user and group settings corresponding to force user/group
666 configuration for the given snum.
667 ****************************************************************************/
669 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
673 if (*lp_force_user(snum)) {
676 * Replace conn->session_info with a completely faked up one
677 * from the username we are forced into :-)
681 struct auth_serversupplied_info *forced_serverinfo;
683 fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
684 lp_const_servicename(snum));
686 return NT_STATUS_NO_MEMORY;
689 status = make_serverinfo_from_username(
690 conn, fuser, conn->session_info->guest,
692 if (!NT_STATUS_IS_OK(status)) {
696 TALLOC_FREE(conn->session_info);
697 conn->session_info = forced_serverinfo;
699 conn->force_user = true;
700 DEBUG(3,("Forced user %s\n", fuser));
704 * If force group is true, then override
705 * any groupid stored for the connecting user.
708 if (*lp_force_group(snum)) {
710 status = find_forced_group(
711 conn->force_user, snum, conn->session_info->unix_name,
712 &conn->session_info->security_token->sids[1],
713 &conn->session_info->utok.gid);
715 if (!NT_STATUS_IS_OK(status)) {
720 * We need to cache this gid, to use within
721 * change_to_user() separately from the conn->session_info
722 * struct. We only use conn->session_info directly if
723 * "force_user" was set.
725 conn->force_group_gid = conn->session_info->utok.gid;
731 /****************************************************************************
732 Make a connection, given the snum to connect to, and the vuser of the
733 connecting user if appropriate.
734 ****************************************************************************/
736 connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
737 int snum, user_struct *vuser,
742 connection_struct *conn = NULL;
743 struct smb_filename *smb_fname_cpath = NULL;
746 bool on_err_call_dis_hook = false;
747 bool claimed_connection = false;
754 *pstatus = share_sanity_checks(&sconn->client_id, snum, dev);
755 if (NT_STATUS_IS_ERR(*pstatus)) {
759 conn = conn_new(sconn);
761 DEBUG(0,("Couldn't find free connection.\n"));
762 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
766 conn->params->service = snum;
768 status = create_connection_session_info(sconn,
769 conn, snum, vuser ? vuser->session_info : NULL, password,
770 &conn->session_info);
772 if (!NT_STATUS_IS_OK(status)) {
773 DEBUG(1, ("create_connection_session_info failed: %s\n",
779 if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
780 conn->force_user = true;
783 add_session_user(sconn, conn->session_info->unix_name);
785 conn->num_files_open = 0;
786 conn->lastused = conn->lastused_count = time(NULL);
788 conn->printer = (strncmp(dev,"LPT",3) == 0);
789 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
790 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
792 /* Case options for the share. */
793 if (lp_casesensitive(snum) == Auto) {
794 /* We will be setting this per packet. Set to be case
795 * insensitive for now. */
796 conn->case_sensitive = False;
798 conn->case_sensitive = (bool)lp_casesensitive(snum);
801 conn->case_preserve = lp_preservecase(snum);
802 conn->short_case_preserve = lp_shortpreservecase(snum);
804 conn->encrypt_level = lp_smb_encrypt(snum);
806 conn->veto_list = NULL;
807 conn->hide_list = NULL;
808 conn->veto_oplock_list = NULL;
809 conn->aio_write_behind_list = NULL;
811 conn->read_only = lp_readonly(SNUM(conn));
813 status = set_conn_force_user_group(conn, snum);
814 if (!NT_STATUS_IS_OK(status)) {
820 conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
823 char *s = talloc_sub_advanced(talloc_tos(),
824 lp_servicename(SNUM(conn)),
825 conn->session_info->unix_name,
827 conn->session_info->utok.gid,
828 conn->session_info->sanitized_username,
829 conn->session_info->info3->base.domain.string,
832 *pstatus = NT_STATUS_NO_MEMORY;
836 if (!set_conn_connectpath(conn,s)) {
838 *pstatus = NT_STATUS_NO_MEMORY;
841 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
842 lp_servicename(snum)));
847 * New code to check if there's a share security descripter
848 * added from NT server manager. This is done after the
849 * smb.conf checks are done as we need a uid and token. JRA.
854 bool can_write = False;
856 can_write = share_access_check(conn->session_info->security_token,
857 lp_servicename(snum),
861 if (!share_access_check(conn->session_info->security_token,
862 lp_servicename(snum),
864 /* No access, read or write. */
865 DEBUG(0,("make_connection: connection to %s "
866 "denied due to security "
868 lp_servicename(snum)));
869 *pstatus = NT_STATUS_ACCESS_DENIED;
872 conn->read_only = True;
876 /* Initialise VFS function pointers */
878 if (!smbd_vfs_init(conn)) {
879 DEBUG(0, ("vfs_init failed for service %s\n",
880 lp_servicename(snum)));
881 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
885 /* ROOT Activities: */
886 /* explicitly check widelinks here so that we can correctly warn
888 widelinks_warning(snum);
891 * Enforce the max connections parameter.
894 if ((lp_max_connections(snum) > 0)
895 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
896 lp_max_connections(snum))) {
898 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
899 lp_max_connections(snum), lp_servicename(snum)));
900 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
905 * Get us an entry in the connections db
907 if (!claim_connection(conn, lp_servicename(snum))) {
908 DEBUG(1, ("Could not store connections entry\n"));
909 *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
912 claimed_connection = true;
914 /* Invoke VFS make connection hook - this must be the first
915 filesystem operation that we do. */
917 if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
918 conn->session_info->unix_name) < 0) {
919 DEBUG(0,("make_connection: VFS make connection failed!\n"));
920 *pstatus = NT_STATUS_UNSUCCESSFUL;
924 /* Any error exit after here needs to call the disconnect hook. */
925 on_err_call_dis_hook = true;
927 if ((!conn->printer) && (!conn->ipc)) {
928 conn->notify_ctx = notify_init(conn,
929 sconn_server_id(sconn),
931 smbd_event_context(),
936 * Fix compatibility issue pointed out by Volker.
937 * We pass the conn->connectpath to the preexec
938 * scripts as a parameter, so attempt to canonicalize
939 * it here before calling the preexec scripts.
940 * We ignore errors here, as it is possible that
941 * the conn->connectpath doesn't exist yet and
942 * the preexec scripts will create them.
945 (void)canonicalize_connect_path(conn);
947 /* Preexecs are done here as they might make the dir we are to ChDir
949 /* execute any "root preexec = " line */
950 if (*lp_rootpreexec(snum)) {
951 char *cmd = talloc_sub_advanced(talloc_tos(),
952 lp_servicename(SNUM(conn)),
953 conn->session_info->unix_name,
955 conn->session_info->utok.gid,
956 conn->session_info->sanitized_username,
957 conn->session_info->info3->base.domain.string,
958 lp_rootpreexec(snum));
959 DEBUG(5,("cmd=%s\n",cmd));
960 ret = smbrun(cmd,NULL);
962 if (ret != 0 && lp_rootpreexec_close(snum)) {
963 DEBUG(1,("root preexec gave %d - failing "
964 "connection\n", ret));
965 *pstatus = NT_STATUS_ACCESS_DENIED;
970 /* USER Activites: */
971 if (!change_to_user(conn, conn->vuid)) {
972 /* No point continuing if they fail the basic checks */
973 DEBUG(0,("Can't become connected user!\n"));
974 *pstatus = NT_STATUS_LOGON_FAILURE;
981 /* Remember that a different vuid can connect later without these
984 /* Preexecs are done here as they might make the dir we are to ChDir
987 /* execute any "preexec = " line */
988 if (*lp_preexec(snum)) {
989 char *cmd = talloc_sub_advanced(talloc_tos(),
990 lp_servicename(SNUM(conn)),
991 conn->session_info->unix_name,
993 conn->session_info->utok.gid,
994 conn->session_info->sanitized_username,
995 conn->session_info->info3->base.domain.string,
997 ret = smbrun(cmd,NULL);
999 if (ret != 0 && lp_preexec_close(snum)) {
1000 DEBUG(1,("preexec gave %d - failing connection\n",
1002 *pstatus = NT_STATUS_ACCESS_DENIED;
1007 #ifdef WITH_FAKE_KASERVER
1008 if (lp_afs_share(snum)) {
1014 * we've finished with the user stuff - go back to root
1015 * so the SMB_VFS_STAT call will only fail on path errors,
1016 * not permission problems.
1018 change_to_root_user();
1019 /* ROOT Activites: */
1022 * If widelinks are disallowed we need to canonicalise the connect
1023 * path here to ensure we don't have any symlinks in the
1024 * connectpath. We will be checking all paths on this connection are
1025 * below this directory. We must do this after the VFS init as we
1026 * depend on the realpath() pointer in the vfs table. JRA.
1028 if (!lp_widelinks(snum)) {
1029 if (!canonicalize_connect_path(conn)) {
1030 DEBUG(0, ("canonicalize_connect_path failed "
1031 "for service %s, path %s\n",
1032 lp_servicename(snum),
1033 conn->connectpath));
1034 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1039 /* Add veto/hide lists */
1040 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1041 set_namearray( &conn->veto_list, lp_veto_files(snum));
1042 set_namearray( &conn->hide_list, lp_hide_files(snum));
1043 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1044 set_namearray( &conn->aio_write_behind_list,
1045 lp_aio_write_behind(snum));
1047 status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
1048 NULL, NULL, &smb_fname_cpath);
1049 if (!NT_STATUS_IS_OK(status)) {
1054 /* win2000 does not check the permissions on the directory
1055 during the tree connect, instead relying on permission
1056 check during individual operations. To match this behaviour
1057 I have disabled this chdir check (tridge) */
1058 /* the alternative is just to check the directory exists */
1060 if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
1061 !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1062 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1063 DEBUG(0,("'%s' is not a directory, when connecting to "
1064 "[%s]\n", conn->connectpath,
1065 lp_servicename(snum)));
1067 DEBUG(0,("'%s' does not exist or permission denied "
1068 "when connecting to [%s] Error was %s\n",
1069 conn->connectpath, lp_servicename(snum),
1072 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1075 conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
1077 string_set(&conn->origpath,conn->connectpath);
1079 /* Figure out the characteristics of the underlying filesystem. This
1080 * assumes that all the filesystem mounted withing a share path have
1081 * the same characteristics, which is likely but not guaranteed.
1084 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
1087 * Print out the 'connected as' stuff here as we need
1088 * to know the effective uid and gid we will be using
1089 * (at least initially).
1092 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1093 dbgtext( "%s (%s) ", get_remote_machine_name(),
1094 conn->sconn->client_id.addr );
1095 dbgtext( "%s", srv_is_signing_active(sconn) ? "signed " : "");
1096 dbgtext( "connect to service %s ", lp_servicename(snum) );
1097 dbgtext( "initially as user %s ",
1098 conn->session_info->unix_name );
1099 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
1100 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1106 TALLOC_FREE(smb_fname_cpath);
1107 /* We must exit this function as root. */
1108 if (geteuid() != 0) {
1109 change_to_root_user();
1111 if (on_err_call_dis_hook) {
1112 /* Call VFS disconnect hook */
1113 SMB_VFS_DISCONNECT(conn);
1115 if (claimed_connection) {
1116 yield_connection(conn, lp_servicename(snum));
1124 /****************************************************************************
1125 Make a connection to a service.
1128 ****************************************************************************/
1130 connection_struct *make_connection(struct smbd_server_connection *sconn,
1131 const char *service_in, DATA_BLOB password,
1132 const char *pdev, uint16 vuid,
1136 user_struct *vuser = NULL;
1137 char *service = NULL;
1143 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1145 if (!non_root_mode() && (euid = geteuid()) != 0) {
1146 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1147 "(%u)\n", (unsigned int)euid ));
1148 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1151 if (conn_num_open(sconn) > 2047) {
1152 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1156 if(lp_security() != SEC_SHARE) {
1157 vuser = get_valid_user_struct(sconn, vuid);
1159 DEBUG(1,("make_connection: refusing to connect with "
1160 "no session setup\n"));
1161 *status = NT_STATUS_ACCESS_DENIED;
1166 /* Logic to try and connect to the correct [homes] share, preferably
1167 without too many getpwnam() lookups. This is particulary nasty for
1168 winbind usernames, where the share name isn't the same as unix
1171 The snum of the homes share is stored on the vuser at session setup
1175 if (strequal(service_in,HOMES_NAME)) {
1176 if(lp_security() != SEC_SHARE) {
1177 DATA_BLOB no_pw = data_blob_null;
1178 if (vuser->homes_snum == -1) {
1179 DEBUG(2, ("[homes] share not available for "
1180 "this user because it was not found "
1181 "or created at session setup "
1183 *status = NT_STATUS_BAD_NETWORK_NAME;
1186 DEBUG(5, ("making a connection to [homes] service "
1187 "created at session setup time\n"));
1188 return make_connection_snum(sconn,
1193 /* Security = share. Try with
1194 * current_user_info.smb_name as the username. */
1195 if (*current_user_info.smb_name) {
1196 char *unix_username = NULL;
1197 (void)map_username(talloc_tos(),
1198 current_user_info.smb_name,
1200 snum = find_service(talloc_tos(),
1203 if (!unix_username) {
1204 *status = NT_STATUS_NO_MEMORY;
1209 DEBUG(5, ("making a connection to 'homes' "
1210 "service %s based on "
1211 "security=share\n", service_in));
1212 return make_connection_snum(sconn,
1218 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1219 && strequal(service_in,
1220 lp_servicename(vuser->homes_snum))) {
1221 DATA_BLOB no_pw = data_blob_null;
1222 DEBUG(5, ("making a connection to 'homes' service [%s] "
1223 "created at session setup time\n", service_in));
1224 return make_connection_snum(sconn,
1230 service = talloc_strdup(talloc_tos(), service_in);
1232 *status = NT_STATUS_NO_MEMORY;
1236 strlower_m(service);
1238 snum = find_service(talloc_tos(), service, &service);
1240 *status = NT_STATUS_NO_MEMORY;
1245 if (strequal(service,"IPC$") ||
1246 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1247 DEBUG(3,("refusing IPC connection to %s\n", service));
1248 *status = NT_STATUS_ACCESS_DENIED;
1252 DEBUG(3,("%s (%s) couldn't find service %s\n",
1253 get_remote_machine_name(),
1254 tsocket_address_string(
1255 sconn->remote_address, talloc_tos()),
1257 *status = NT_STATUS_BAD_NETWORK_NAME;
1261 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1262 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1263 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1264 "(pointing to %s)\n",
1265 service, lp_msdfs_proxy(snum)));
1266 *status = NT_STATUS_BAD_NETWORK_NAME;
1270 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1272 return make_connection_snum(sconn, snum, vuser,
1277 /****************************************************************************
1279 ****************************************************************************/
1281 void close_cnum(connection_struct *conn, uint16 vuid)
1283 file_close_conn(conn);
1285 if (!IS_IPC(conn)) {
1286 dptr_closecnum(conn);
1289 change_to_root_user();
1291 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1292 get_remote_machine_name(),
1293 conn->sconn->client_id.addr,
1294 lp_servicename(SNUM(conn))));
1296 /* Call VFS disconnect hook */
1297 SMB_VFS_DISCONNECT(conn);
1299 yield_connection(conn, lp_servicename(SNUM(conn)));
1301 /* make sure we leave the directory available for unmount */
1302 vfs_ChDir(conn, "/");
1304 /* execute any "postexec = " line */
1305 if (*lp_postexec(SNUM(conn)) &&
1306 change_to_user(conn, vuid)) {
1307 char *cmd = talloc_sub_advanced(talloc_tos(),
1308 lp_servicename(SNUM(conn)),
1309 conn->session_info->unix_name,
1311 conn->session_info->utok.gid,
1312 conn->session_info->sanitized_username,
1313 conn->session_info->info3->base.domain.string,
1314 lp_postexec(SNUM(conn)));
1317 change_to_root_user();
1320 change_to_root_user();
1321 /* execute any "root postexec = " line */
1322 if (*lp_rootpostexec(SNUM(conn))) {
1323 char *cmd = talloc_sub_advanced(talloc_tos(),
1324 lp_servicename(SNUM(conn)),
1325 conn->session_info->unix_name,
1327 conn->session_info->utok.gid,
1328 conn->session_info->sanitized_username,
1329 conn->session_info->info3->base.domain.string,
1330 lp_rootpostexec(SNUM(conn)));