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/>.
22 extern userdom_struct current_user_info;
24 static bool canonicalize_connect_path(connection_struct *conn)
26 #ifdef REALPATH_TAKES_NULL
28 char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,NULL);
32 ret = set_conn_connectpath(conn,resolved_name);
33 SAFE_FREE(resolved_name);
36 char resolved_name_buf[PATH_MAX+1];
37 char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,resolved_name_buf);
41 return set_conn_connectpath(conn,resolved_name);
42 #endif /* REALPATH_TAKES_NULL */
45 /****************************************************************************
46 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
47 absolute path stating in / and not ending in /.
48 Observent people will notice a similarity between this and check_path_syntax :-).
49 ****************************************************************************/
51 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
55 const char *s = connectpath;
56 bool start_of_name_component = true;
58 destname = SMB_STRDUP(connectpath);
64 *d++ = '/'; /* Always start with root. */
68 /* Eat multiple '/' */
72 if ((d > destname + 1) && (*s != '\0')) {
75 start_of_name_component = True;
79 if (start_of_name_component) {
80 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
81 /* Uh oh - "/../" or "/..\0" ! */
83 /* Go past the ../ or .. */
87 s += 2; /* Go past the .. */
90 /* If we just added a '/' - delete it */
91 if ((d > destname) && (*(d-1) == '/')) {
96 /* Are we at the start ? Can't go back further if so. */
98 *d++ = '/'; /* Can't delete root */
101 /* Go back one level... */
102 /* Decrement d first as d points to the *next* char to write into. */
103 for (d--; d > destname; d--) {
108 /* We're still at the start of a name component, just the previous one. */
110 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
111 /* Component of pathname can't be "." only - skip the '.' . */
125 /* Get the size of the next MB character. */
126 next_codepoint(s,&siz);
147 start_of_name_component = false;
151 /* And must not end in '/' */
152 if (d > destname + 1 && (*(d-1) == '/')) {
156 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
157 lp_servicename(SNUM(conn)), destname ));
159 string_set(&conn->connectpath, destname);
164 /****************************************************************************
165 Load parameters specific to a connection/service.
166 ****************************************************************************/
168 bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
170 static connection_struct *last_conn;
171 static uint16 last_flags;
179 conn->lastused_count++;
184 vfs_ChDir(conn,conn->connectpath) != 0 &&
185 vfs_ChDir(conn,conn->origpath) != 0) {
186 DEBUG(0,("chdir (%s) failed\n",
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 struct registry_key *key;
230 struct registry_value *value;
234 if (!lp_registry_shares()) {
238 if (strequal(servicename, GLOBAL_NAME)) {
242 if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) {
246 err = reg_open_path(NULL, path, REG_KEY_READ, get_root_nt_token(),
250 if (!W_ERROR_IS_OK(err)) {
254 res = lp_add_service(servicename, -1);
260 W_ERROR_IS_OK(reg_enumvalue(key, key, i, &value_name, &value));
262 switch (value->type) {
265 if (asprintf(&tmp, "%d", value->v.dword) == -1) {
268 lp_do_parameter(res, value_name, tmp);
273 lp_do_parameter(res, value_name, value->v.sz.str);
277 /* Ignore all the rest */
281 TALLOC_FREE(value_name);
291 void load_registry_shares(void)
293 struct registry_key *key;
298 DEBUG(8, ("load_registry_shares()\n"));
299 if (!lp_registry_shares()) {
303 err = reg_open_path(NULL, KEY_SMBCONF, REG_KEY_READ,
304 get_root_nt_token(), &key);
305 if (!(W_ERROR_IS_OK(err))) {
309 for (i=0; W_ERROR_IS_OK(reg_enumkey(key, key, i, &name, NULL)); i++) {
310 load_registry_service(name);
318 /****************************************************************************
319 Add a home service. Returns the new service number or -1 if fail.
320 ****************************************************************************/
322 int add_home_service(const char *service, const char *username, const char *homedir)
326 if (!service || !homedir)
329 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
330 if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
336 * If this is a winbindd provided username, remove
337 * the domain component before adding the service.
338 * Log a warning if the "path=" parameter does not
339 * include any macros.
343 const char *p = strchr(service,*lp_winbind_separator());
345 /* We only want the 'user' part of the string */
351 if (!lp_add_home(service, iHomeService, username, homedir)) {
355 return lp_servicenumber(service);
360 * Find a service entry.
362 * @param service is modified (to canonical form??)
365 int find_service(fstring service)
369 all_string_sub(service,"\\","/",0);
371 iService = lp_servicenumber(service);
373 /* now handle the special case of a home directory */
375 char *phome_dir = get_user_home_dir(talloc_tos(), service);
379 * Try mapping the servicename, it may
380 * be a Windows to unix mapped user name.
382 if(map_username(service))
383 phome_dir = get_user_home_dir(
384 talloc_tos(), service);
387 DEBUG(3,("checking for home directory %s gave %s\n",service,
388 phome_dir?phome_dir:"(NULL)"));
390 iService = add_home_service(service,service /* 'username' */, phome_dir);
393 /* If we still don't have a service, attempt to add it as a printer. */
397 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
398 iPrinterService = load_registry_service(PRINTERS_NAME);
400 if (iPrinterService) {
401 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
402 if (pcap_printername_ok(service)) {
403 DEBUG(3,("%s is a valid printer name\n", service));
404 DEBUG(3,("adding %s as a printer service\n", service));
405 lp_add_printer(service, iPrinterService);
406 iService = lp_servicenumber(service);
408 DEBUG(0,("failed to add %s as a printer service!\n", service));
411 DEBUG(3,("%s is not a valid printer name\n", service));
416 /* Check for default vfs service? Unsure whether to implement this */
421 iService = load_registry_service(service);
424 /* Is it a usershare service ? */
425 if (iService < 0 && *lp_usershare_path()) {
426 /* Ensure the name is canonicalized. */
428 iService = load_usershare_service(service);
431 /* just possibly it's a default service? */
433 char *pdefservice = lp_defaultservice();
434 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
436 * We need to do a local copy here as lp_defaultservice()
437 * returns one of the rotating lp_string buffers that
438 * could get overwritten by the recursive find_service() call
439 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
441 char *defservice = SMB_STRDUP(pdefservice);
447 /* Disallow anything except explicit share names. */
448 if (strequal(defservice,HOMES_NAME) ||
449 strequal(defservice, PRINTERS_NAME) ||
450 strequal(defservice, "IPC$")) {
451 SAFE_FREE(defservice);
455 iService = find_service(defservice);
457 all_string_sub(service, "_","/",0);
458 iService = lp_add_service(service, iService);
460 SAFE_FREE(defservice);
465 if (!VALID_SNUM(iService)) {
466 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
474 DEBUG(3,("find_service() failed to find service %s\n", service));
480 /****************************************************************************
481 do some basic sainity checks on the share.
482 This function modifies dev, ecode.
483 ****************************************************************************/
485 static NTSTATUS share_sanity_checks(int snum, fstring dev)
488 if (!lp_snum_ok(snum) ||
489 !check_access(smbd_server_fd(),
490 lp_hostsallow(snum), lp_hostsdeny(snum))) {
491 return NT_STATUS_ACCESS_DENIED;
494 if (dev[0] == '?' || !dev[0]) {
495 if (lp_print_ok(snum)) {
496 fstrcpy(dev,"LPT1:");
497 } else if (strequal(lp_fstype(snum), "IPC")) {
506 if (lp_print_ok(snum)) {
507 if (!strequal(dev, "LPT1:")) {
508 return NT_STATUS_BAD_DEVICE_TYPE;
510 } else if (strequal(lp_fstype(snum), "IPC")) {
511 if (!strequal(dev, "IPC")) {
512 return NT_STATUS_BAD_DEVICE_TYPE;
514 } else if (!strequal(dev, "A:")) {
515 return NT_STATUS_BAD_DEVICE_TYPE;
518 /* Behave as a printer if we are supposed to */
519 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
520 fstrcpy(dev, "LPT1:");
527 * Go through lookup_name etc to find the force'd group.
529 * Create a new token from src_token, replacing the primary group sid with the
533 static NTSTATUS find_forced_group(bool force_user,
534 int snum, const char *username,
538 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
539 TALLOC_CTX *frame = talloc_stackframe();
541 enum lsa_SidType type;
543 bool user_must_be_member = False;
546 groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
547 if (groupname == NULL) {
548 DEBUG(1, ("talloc_strdup failed\n"));
549 result = NT_STATUS_NO_MEMORY;
553 if (groupname[0] == '+') {
554 user_must_be_member = True;
558 groupname = talloc_string_sub(talloc_tos(), groupname,
559 "%S", lp_servicename(snum));
561 if (!lookup_name_smbconf(talloc_tos(), groupname,
562 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
563 NULL, NULL, &group_sid, &type)) {
564 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
569 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
570 (type != SID_NAME_WKN_GRP)) {
571 DEBUG(10, ("%s is a %s, not a group\n", groupname,
572 sid_type_lookup(type)));
576 if (!sid_to_gid(&group_sid, &gid)) {
577 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
578 sid_string_dbg(&group_sid), groupname));
583 * If the user has been forced and the forced group starts with a '+',
584 * then we only set the group to be the forced group if the forced
585 * user is a member of that group. Otherwise, the meaning of the '+'
589 if (force_user && user_must_be_member) {
590 if (user_in_group_sid(username, &group_sid)) {
591 sid_copy(pgroup_sid, &group_sid);
593 DEBUG(3,("Forced group %s for member %s\n",
594 groupname, username));
596 DEBUG(0,("find_forced_group: forced user %s is not a member "
597 "of forced group %s. Disallowing access.\n",
598 username, groupname ));
599 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
603 sid_copy(pgroup_sid, &group_sid);
605 DEBUG(3,("Forced group %s\n", groupname));
608 result = NT_STATUS_OK;
614 /****************************************************************************
615 Create an auth_serversupplied_info structure for a connection_struct
616 ****************************************************************************/
618 static NTSTATUS create_connection_server_info(TALLOC_CTX *mem_ctx, int snum,
619 struct auth_serversupplied_info *vuid_serverinfo,
621 struct auth_serversupplied_info **presult)
623 if (lp_guest_only(snum)) {
624 return make_server_info_guest(mem_ctx, presult);
627 if (vuid_serverinfo != NULL) {
629 struct auth_serversupplied_info *result;
632 * This is the normal security != share case where we have a
633 * valid vuid from the session setup. */
635 if (vuid_serverinfo->guest) {
636 if (!lp_guest_ok(snum)) {
637 DEBUG(2, ("guest user (from session setup) "
638 "not permitted to access this share "
639 "(%s)\n", lp_servicename(snum)));
640 return NT_STATUS_ACCESS_DENIED;
643 if (!user_ok_token(vuid_serverinfo->unix_name,
644 vuid_serverinfo->ptok, snum)) {
645 DEBUG(2, ("user '%s' (from session setup) not "
646 "permitted to access this share "
648 vuid_serverinfo->unix_name,
649 lp_servicename(snum)));
650 return NT_STATUS_ACCESS_DENIED;
654 result = copy_serverinfo(mem_ctx, vuid_serverinfo);
655 if (result == NULL) {
656 return NT_STATUS_NO_MEMORY;
663 if (lp_security() == SEC_SHARE) {
668 /* add the sharename as a possible user name if we
669 are in share mode security */
671 add_session_user(lp_servicename(snum));
673 /* shall we let them in? */
675 if (!authorise_login(snum,user,password,&guest)) {
676 DEBUG( 2, ( "Invalid username/password for [%s]\n",
677 lp_servicename(snum)) );
678 return NT_STATUS_WRONG_PASSWORD;
681 return make_serverinfo_from_username(mem_ctx, user, guest,
685 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
686 return NT_STATUS_ACCESS_DENIED;
690 /****************************************************************************
691 Make a connection, given the snum to connect to, and the vuser of the
692 connecting user if appropriate.
693 ****************************************************************************/
695 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
700 connection_struct *conn;
704 char addr[INET6_ADDRSTRLEN];
705 bool on_err_call_dis_hook = false;
709 SET_STAT_INVALID(st);
711 if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) {
717 DEBUG(0,("Couldn't find free connection.\n"));
718 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
722 conn->params->service = snum;
723 conn->nt_user_token = NULL;
725 status = create_connection_server_info(
726 conn, snum, vuser ? vuser->server_info : NULL, password,
729 if (!NT_STATUS_IS_OK(status)) {
730 DEBUG(0, ("create_connection_server_info failed: %s\n",
737 if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
738 conn->force_user = true;
742 add_session_user(conn->server_info->unix_name);
744 safe_strcpy(conn->client_address,
745 client_addr(get_client_fd(),addr,sizeof(addr)),
746 sizeof(conn->client_address)-1);
747 conn->num_files_open = 0;
748 conn->lastused = conn->lastused_count = time(NULL);
750 conn->printer = (strncmp(dev,"LPT",3) == 0);
751 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
752 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
755 /* Case options for the share. */
756 if (lp_casesensitive(snum) == Auto) {
757 /* We will be setting this per packet. Set to be case
758 * insensitive for now. */
759 conn->case_sensitive = False;
761 conn->case_sensitive = (bool)lp_casesensitive(snum);
764 conn->case_preserve = lp_preservecase(snum);
765 conn->short_case_preserve = lp_shortpreservecase(snum);
767 conn->encrypt_level = lp_smb_encrypt(snum);
769 conn->veto_list = NULL;
770 conn->hide_list = NULL;
771 conn->veto_oplock_list = NULL;
772 conn->aio_write_behind_list = NULL;
773 string_set(&conn->dirpath,"");
775 conn->read_only = lp_readonly(SNUM(conn));
776 conn->admin_user = False;
779 * If force user is true, then store the given userid and the gid of
780 * the user we're forcing.
781 * For auxiliary groups see below.
784 if (*lp_force_user(snum)) {
786 struct auth_serversupplied_info *forced_serverinfo;
788 fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
789 lp_servicename(snum));
792 *pstatus = NT_STATUS_NO_MEMORY;
796 status = make_serverinfo_from_username(
797 conn, fuser, conn->server_info->guest,
799 if (!NT_STATUS_IS_OK(status)) {
805 TALLOC_FREE(conn->server_info);
806 conn->server_info = forced_serverinfo;
808 conn->force_user = True;
809 DEBUG(3,("Forced user %s\n", fuser));
812 conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
814 conn->uid = conn->server_info->uid;
815 conn->gid = conn->server_info->gid;
816 string_set(&conn->user, conn->server_info->unix_name);
819 * If force group is true, then override
820 * any groupid stored for the connecting user.
823 if (*lp_force_group(snum)) {
826 status = find_forced_group(conn->force_user, snum,
828 &group_sid, &conn->gid);
829 if (!NT_STATUS_IS_OK(status)) {
835 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
837 /* Not force user and not security=share, but force
838 * group. vuser has a token to copy */
840 conn->nt_user_token = dup_nt_token(
841 NULL, vuser->server_info->ptok);
842 if (conn->nt_user_token == NULL) {
843 DEBUG(0, ("dup_nt_token failed\n"));
845 *pstatus = NT_STATUS_NO_MEMORY;
850 /* If conn->nt_user_token is still NULL, we have
851 * security=share. This means ignore the SID, as we had no
852 * vuser to copy from */
854 if (conn->nt_user_token != NULL) {
855 /* Overwrite the primary group sid */
856 sid_copy(&conn->nt_user_token->user_sids[1],
862 if (conn->nt_user_token != NULL) {
865 /* We have a share-specific token from force [user|group].
866 * This means we have to create the list of unix groups from
867 * the list of sids. */
872 for (i=0; i<conn->nt_user_token->num_sids; i++) {
874 DOM_SID *sid = &conn->nt_user_token->user_sids[i];
876 if (!sid_to_gid(sid, &gid)) {
877 DEBUG(10, ("Could not convert SID %s to gid, "
879 sid_string_dbg(sid)));
882 if (!add_gid_to_array_unique(conn, gid, &conn->groups,
884 DEBUG(0, ("add_gid_to_array_unique failed\n"));
886 *pstatus = NT_STATUS_NO_MEMORY;
893 char *s = talloc_sub_advanced(talloc_tos(),
894 lp_servicename(SNUM(conn)), conn->user,
895 conn->connectpath, conn->gid,
896 get_current_username(),
897 current_user_info.domain,
901 *pstatus = NT_STATUS_NO_MEMORY;
905 if (!set_conn_connectpath(conn,s)) {
908 *pstatus = NT_STATUS_NO_MEMORY;
911 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
912 lp_servicename(snum)));
917 * New code to check if there's a share security descripter
918 * added from NT server manager. This is done after the
919 * smb.conf checks are done as we need a uid and token. JRA.
924 bool can_write = False;
925 NT_USER_TOKEN *token = conn->nt_user_token ?
926 conn->nt_user_token :
927 (vuser ? vuser->server_info->ptok : NULL);
930 * I don't believe this can happen. But the
931 * logic above is convoluted enough to confuse
932 * automated checkers, so be sure. JRA.
936 DEBUG(0,("make_connection: connection to %s "
937 "denied due to missing "
939 lp_servicename(snum)));
941 *pstatus = NT_STATUS_ACCESS_DENIED;
945 can_write = share_access_check(token,
946 lp_servicename(snum),
950 if (!share_access_check(token,
951 lp_servicename(snum),
953 /* No access, read or write. */
954 DEBUG(0,("make_connection: connection to %s "
955 "denied due to security "
957 lp_servicename(snum)));
959 *pstatus = NT_STATUS_ACCESS_DENIED;
962 conn->read_only = True;
966 /* Initialise VFS function pointers */
968 if (!smbd_vfs_init(conn)) {
969 DEBUG(0, ("vfs_init failed for service %s\n",
970 lp_servicename(snum)));
972 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
977 * If widelinks are disallowed we need to canonicalise the connect
978 * path here to ensure we don't have any symlinks in the
979 * connectpath. We will be checking all paths on this connection are
980 * below this directory. We must do this after the VFS init as we
981 * depend on the realpath() pointer in the vfs table. JRA.
983 if (!lp_widelinks(snum)) {
984 if (!canonicalize_connect_path(conn)) {
985 DEBUG(0, ("canonicalize_connect_path failed "
986 "for service %s, path %s\n",
987 lp_servicename(snum),
990 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
995 if ((!conn->printer) && (!conn->ipc)) {
996 conn->notify_ctx = notify_init(conn, server_id_self(),
997 smbd_messaging_context(),
998 smbd_event_context(),
1002 /* ROOT Activities: */
1004 * Enforce the max connections parameter.
1007 if ((lp_max_connections(snum) > 0)
1008 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
1009 lp_max_connections(snum))) {
1011 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
1012 lp_max_connections(snum), lp_servicename(snum)));
1014 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
1019 * Get us an entry in the connections db
1021 if (!claim_connection(conn, lp_servicename(snum), 0)) {
1022 DEBUG(1, ("Could not store connections entry\n"));
1024 *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
1028 /* Preexecs are done here as they might make the dir we are to ChDir
1030 /* execute any "root preexec = " line */
1031 if (*lp_rootpreexec(snum)) {
1032 char *cmd = talloc_sub_advanced(talloc_tos(),
1033 lp_servicename(SNUM(conn)), conn->user,
1034 conn->connectpath, conn->gid,
1035 get_current_username(),
1036 current_user_info.domain,
1037 lp_rootpreexec(snum));
1038 DEBUG(5,("cmd=%s\n",cmd));
1039 ret = smbrun(cmd,NULL);
1041 if (ret != 0 && lp_rootpreexec_close(snum)) {
1042 DEBUG(1,("root preexec gave %d - failing "
1043 "connection\n", ret));
1044 yield_connection(conn, lp_servicename(snum));
1046 *pstatus = NT_STATUS_ACCESS_DENIED;
1051 /* USER Activites: */
1052 if (!change_to_user(conn, conn->vuid)) {
1053 /* No point continuing if they fail the basic checks */
1054 DEBUG(0,("Can't become connected user!\n"));
1055 yield_connection(conn, lp_servicename(snum));
1057 *pstatus = NT_STATUS_LOGON_FAILURE;
1061 /* Remember that a different vuid can connect later without these
1064 /* Preexecs are done here as they might make the dir we are to ChDir
1067 /* execute any "preexec = " line */
1068 if (*lp_preexec(snum)) {
1069 char *cmd = talloc_sub_advanced(talloc_tos(),
1070 lp_servicename(SNUM(conn)), conn->user,
1071 conn->connectpath, conn->gid,
1072 get_current_username(),
1073 current_user_info.domain,
1075 ret = smbrun(cmd,NULL);
1077 if (ret != 0 && lp_preexec_close(snum)) {
1078 DEBUG(1,("preexec gave %d - failing connection\n",
1080 *pstatus = NT_STATUS_ACCESS_DENIED;
1085 #ifdef WITH_FAKE_KASERVER
1086 if (lp_afs_share(snum)) {
1091 /* Add veto/hide lists */
1092 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1093 set_namearray( &conn->veto_list, lp_veto_files(snum));
1094 set_namearray( &conn->hide_list, lp_hide_files(snum));
1095 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1098 /* Invoke VFS make connection hook - do this before the VFS_STAT call
1099 to allow any filesystems needing user credentials to initialize
1102 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), conn->user) < 0) {
1103 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1104 *pstatus = NT_STATUS_UNSUCCESSFUL;
1108 /* Any error exit after here needs to call the disconnect hook. */
1109 on_err_call_dis_hook = true;
1111 /* win2000 does not check the permissions on the directory
1112 during the tree connect, instead relying on permission
1113 check during individual operations. To match this behaviour
1114 I have disabled this chdir check (tridge) */
1115 /* the alternative is just to check the directory exists */
1116 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1117 !S_ISDIR(st.st_mode)) {
1118 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1119 DEBUG(0,("'%s' is not a directory, when connecting to "
1120 "[%s]\n", conn->connectpath,
1121 lp_servicename(snum)));
1123 DEBUG(0,("'%s' does not exist or permission denied "
1124 "when connecting to [%s] Error was %s\n",
1125 conn->connectpath, lp_servicename(snum),
1128 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1132 string_set(&conn->origpath,conn->connectpath);
1134 #if SOFTLINK_OPTIMISATION
1135 /* resolve any soft links early if possible */
1136 if (vfs_ChDir(conn,conn->connectpath) == 0) {
1137 TALLOC_CTX *ctx = talloc_tos();
1138 char *s = vfs_GetWd(ctx,s);
1140 *status = map_nt_error_from_unix(errno);
1143 if (!set_conn_connectpath(conn,s)) {
1144 *status = NT_STATUS_NO_MEMORY;
1147 vfs_ChDir(conn,conn->connectpath);
1151 /* Figure out the characteristics of the underlying filesystem. This
1152 * assumes that all the filesystem mounted withing a share path have
1153 * the same characteristics, which is likely but not guaranteed.
1156 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
1159 * Print out the 'connected as' stuff here as we need
1160 * to know the effective uid and gid we will be using
1161 * (at least initially).
1164 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1165 dbgtext( "%s (%s) ", get_remote_machine_name(),
1166 conn->client_address );
1167 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1168 dbgtext( "connect to service %s ", lp_servicename(snum) );
1169 dbgtext( "initially as user %s ", conn->user );
1170 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1171 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1174 /* we've finished with the user stuff - go back to root */
1175 change_to_root_user();
1180 change_to_root_user();
1181 if (on_err_call_dis_hook) {
1182 /* Call VFS disconnect hook */
1183 SMB_VFS_DISCONNECT(conn);
1185 yield_connection(conn, lp_servicename(snum));
1190 /***************************************************************************************
1191 Simple wrapper function for make_connection() to include a call to
1193 **************************************************************************************/
1195 connection_struct *make_connection_with_chdir(const char *service_in,
1197 const char *dev, uint16 vuid,
1200 connection_struct *conn = NULL;
1202 conn = make_connection(service_in, password, dev, vuid, status);
1205 * make_connection() does not change the directory for us any more
1206 * so we have to do it as a separate step --jerry
1209 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1210 DEBUG(0,("move_driver_to_download_area: Can't change "
1211 "directory to %s for [print$] (%s)\n",
1212 conn->connectpath,strerror(errno)));
1213 yield_connection(conn, lp_servicename(SNUM(conn)));
1215 *status = NT_STATUS_UNSUCCESSFUL;
1222 /****************************************************************************
1223 Make a connection to a service.
1226 ****************************************************************************/
1228 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
1229 const char *pdev, uint16 vuid,
1233 user_struct *vuser = NULL;
1237 char addr[INET6_ADDRSTRLEN];
1241 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1243 if (!non_root_mode() && (euid = geteuid()) != 0) {
1244 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1245 "(%u)\n", (unsigned int)euid ));
1246 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1249 if (conn_num_open() > 2047) {
1250 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1254 if(lp_security() != SEC_SHARE) {
1255 vuser = get_valid_user_struct(vuid);
1257 DEBUG(1,("make_connection: refusing to connect with "
1258 "no session setup\n"));
1259 *status = NT_STATUS_ACCESS_DENIED;
1264 /* Logic to try and connect to the correct [homes] share, preferably
1265 without too many getpwnam() lookups. This is particulary nasty for
1266 winbind usernames, where the share name isn't the same as unix
1269 The snum of the homes share is stored on the vuser at session setup
1273 if (strequal(service_in,HOMES_NAME)) {
1274 if(lp_security() != SEC_SHARE) {
1275 DATA_BLOB no_pw = data_blob_null;
1276 if (vuser->homes_snum == -1) {
1277 DEBUG(2, ("[homes] share not available for "
1278 "this user because it was not found "
1279 "or created at session setup "
1281 *status = NT_STATUS_BAD_NETWORK_NAME;
1284 DEBUG(5, ("making a connection to [homes] service "
1285 "created at session setup time\n"));
1286 return make_connection_snum(vuser->homes_snum,
1290 /* Security = share. Try with
1291 * current_user_info.smb_name as the username. */
1292 if (*current_user_info.smb_name) {
1293 fstring unix_username;
1294 fstrcpy(unix_username,
1295 current_user_info.smb_name);
1296 map_username(unix_username);
1297 snum = find_service(unix_username);
1300 DEBUG(5, ("making a connection to 'homes' "
1301 "service %s based on "
1302 "security=share\n", service_in));
1303 return make_connection_snum(snum, NULL,
1308 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1309 && strequal(service_in,
1310 lp_servicename(vuser->homes_snum))) {
1311 DATA_BLOB no_pw = data_blob_null;
1312 DEBUG(5, ("making a connection to 'homes' service [%s] "
1313 "created at session setup time\n", service_in));
1314 return make_connection_snum(vuser->homes_snum,
1319 fstrcpy(service, service_in);
1321 strlower_m(service);
1323 snum = find_service(service);
1326 if (strequal(service,"IPC$") ||
1327 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1328 DEBUG(3,("refusing IPC connection to %s\n", service));
1329 *status = NT_STATUS_ACCESS_DENIED;
1333 DEBUG(0,("%s (%s) couldn't find service %s\n",
1334 get_remote_machine_name(),
1335 client_addr(get_client_fd(),addr,sizeof(addr)),
1337 *status = NT_STATUS_BAD_NETWORK_NAME;
1341 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1342 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1343 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1344 "(pointing to %s)\n",
1345 service, lp_msdfs_proxy(snum)));
1346 *status = NT_STATUS_BAD_NETWORK_NAME;
1350 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1352 return make_connection_snum(snum, vuser,
1357 /****************************************************************************
1359 ****************************************************************************/
1361 void close_cnum(connection_struct *conn, uint16 vuid)
1364 pipe_close_conn(conn);
1366 file_close_conn(conn);
1367 dptr_closecnum(conn);
1370 change_to_root_user();
1372 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1373 get_remote_machine_name(),
1374 conn->client_address,
1375 lp_servicename(SNUM(conn))));
1377 /* Call VFS disconnect hook */
1378 SMB_VFS_DISCONNECT(conn);
1380 yield_connection(conn, lp_servicename(SNUM(conn)));
1382 /* make sure we leave the directory available for unmount */
1383 vfs_ChDir(conn, "/");
1385 /* execute any "postexec = " line */
1386 if (*lp_postexec(SNUM(conn)) &&
1387 change_to_user(conn, vuid)) {
1388 char *cmd = talloc_sub_advanced(talloc_tos(),
1389 lp_servicename(SNUM(conn)), conn->user,
1390 conn->connectpath, conn->gid,
1391 get_current_username(),
1392 current_user_info.domain,
1393 lp_postexec(SNUM(conn)));
1396 change_to_root_user();
1399 change_to_root_user();
1400 /* execute any "root postexec = " line */
1401 if (*lp_rootpostexec(SNUM(conn))) {
1402 char *cmd = talloc_sub_advanced(talloc_tos(),
1403 lp_servicename(SNUM(conn)), conn->user,
1404 conn->connectpath, conn->gid,
1405 get_current_username(),
1406 current_user_info.domain,
1407 lp_rootpostexec(SNUM(conn)));