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 ZERO_STRUCTP(pgroup_sid);
549 groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
550 if (groupname == NULL) {
551 DEBUG(1, ("talloc_strdup failed\n"));
552 result = NT_STATUS_NO_MEMORY;
556 if (groupname[0] == '+') {
557 user_must_be_member = True;
561 groupname = talloc_string_sub(talloc_tos(), groupname,
562 "%S", lp_servicename(snum));
564 if (!lookup_name_smbconf(talloc_tos(), groupname,
565 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
566 NULL, NULL, &group_sid, &type)) {
567 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
572 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
573 (type != SID_NAME_WKN_GRP)) {
574 DEBUG(10, ("%s is a %s, not a group\n", groupname,
575 sid_type_lookup(type)));
579 if (!sid_to_gid(&group_sid, &gid)) {
580 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
581 sid_string_dbg(&group_sid), groupname));
586 * If the user has been forced and the forced group starts with a '+',
587 * then we only set the group to be the forced group if the forced
588 * user is a member of that group. Otherwise, the meaning of the '+'
592 if (force_user && user_must_be_member) {
593 if (user_in_group_sid(username, &group_sid)) {
594 sid_copy(pgroup_sid, &group_sid);
596 DEBUG(3,("Forced group %s for member %s\n",
597 groupname, username));
599 DEBUG(0,("find_forced_group: forced user %s is not a member "
600 "of forced group %s. Disallowing access.\n",
601 username, groupname ));
602 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
606 sid_copy(pgroup_sid, &group_sid);
608 DEBUG(3,("Forced group %s\n", groupname));
611 result = NT_STATUS_OK;
617 /****************************************************************************
618 Create an auth_serversupplied_info structure for a connection_struct
619 ****************************************************************************/
621 static NTSTATUS create_connection_server_info(TALLOC_CTX *mem_ctx, int snum,
622 struct auth_serversupplied_info *vuid_serverinfo,
624 struct auth_serversupplied_info **presult)
626 if (lp_guest_only(snum)) {
627 return make_server_info_guest(mem_ctx, presult);
630 if (vuid_serverinfo != NULL) {
632 struct auth_serversupplied_info *result;
635 * This is the normal security != share case where we have a
636 * valid vuid from the session setup. */
638 if (vuid_serverinfo->guest) {
639 if (!lp_guest_ok(snum)) {
640 DEBUG(2, ("guest user (from session setup) "
641 "not permitted to access this share "
642 "(%s)\n", lp_servicename(snum)));
643 return NT_STATUS_ACCESS_DENIED;
646 if (!user_ok_token(vuid_serverinfo->unix_name,
647 vuid_serverinfo->ptok, snum)) {
648 DEBUG(2, ("user '%s' (from session setup) not "
649 "permitted to access this share "
651 vuid_serverinfo->unix_name,
652 lp_servicename(snum)));
653 return NT_STATUS_ACCESS_DENIED;
657 result = copy_serverinfo(mem_ctx, vuid_serverinfo);
658 if (result == NULL) {
659 return NT_STATUS_NO_MEMORY;
666 if (lp_security() == SEC_SHARE) {
671 /* add the sharename as a possible user name if we
672 are in share mode security */
674 add_session_user(lp_servicename(snum));
676 /* shall we let them in? */
678 if (!authorise_login(snum,user,password,&guest)) {
679 DEBUG( 2, ( "Invalid username/password for [%s]\n",
680 lp_servicename(snum)) );
681 return NT_STATUS_WRONG_PASSWORD;
684 return make_serverinfo_from_username(mem_ctx, user, guest,
688 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
689 return NT_STATUS_ACCESS_DENIED;
693 /****************************************************************************
694 Make a connection, given the snum to connect to, and the vuser of the
695 connecting user if appropriate.
696 ****************************************************************************/
698 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
703 connection_struct *conn;
707 char addr[INET6_ADDRSTRLEN];
708 bool on_err_call_dis_hook = false;
712 SET_STAT_INVALID(st);
714 if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) {
720 DEBUG(0,("Couldn't find free connection.\n"));
721 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
725 conn->params->service = snum;
726 conn->nt_user_token = NULL;
728 status = create_connection_server_info(
729 conn, snum, vuser ? vuser->server_info : NULL, password,
732 if (!NT_STATUS_IS_OK(status)) {
733 DEBUG(0, ("create_connection_server_info failed: %s\n",
740 if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
741 conn->force_user = true;
745 add_session_user(conn->server_info->unix_name);
747 safe_strcpy(conn->client_address,
748 client_addr(get_client_fd(),addr,sizeof(addr)),
749 sizeof(conn->client_address)-1);
750 conn->num_files_open = 0;
751 conn->lastused = conn->lastused_count = time(NULL);
753 conn->printer = (strncmp(dev,"LPT",3) == 0);
754 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
755 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
758 /* Case options for the share. */
759 if (lp_casesensitive(snum) == Auto) {
760 /* We will be setting this per packet. Set to be case
761 * insensitive for now. */
762 conn->case_sensitive = False;
764 conn->case_sensitive = (bool)lp_casesensitive(snum);
767 conn->case_preserve = lp_preservecase(snum);
768 conn->short_case_preserve = lp_shortpreservecase(snum);
770 conn->encrypt_level = lp_smb_encrypt(snum);
772 conn->veto_list = NULL;
773 conn->hide_list = NULL;
774 conn->veto_oplock_list = NULL;
775 conn->aio_write_behind_list = NULL;
776 string_set(&conn->dirpath,"");
778 conn->read_only = lp_readonly(SNUM(conn));
779 conn->admin_user = False;
782 * If force user is true, then store the given userid and the gid of
783 * the user we're forcing.
784 * For auxiliary groups see below.
787 if (*lp_force_user(snum)) {
789 struct auth_serversupplied_info *forced_serverinfo;
791 fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
792 lp_servicename(snum));
795 *pstatus = NT_STATUS_NO_MEMORY;
799 status = make_serverinfo_from_username(
800 conn, fuser, conn->server_info->guest,
802 if (!NT_STATUS_IS_OK(status)) {
808 TALLOC_FREE(conn->server_info);
809 conn->server_info = forced_serverinfo;
811 conn->force_user = True;
812 DEBUG(3,("Forced user %s\n", fuser));
815 conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
817 conn->uid = conn->server_info->uid;
818 conn->gid = conn->server_info->gid;
819 string_set(&conn->user, conn->server_info->unix_name);
822 * If force group is true, then override
823 * any groupid stored for the connecting user.
826 if (*lp_force_group(snum)) {
829 status = find_forced_group(conn->force_user, snum,
831 &group_sid, &conn->gid);
832 if (!NT_STATUS_IS_OK(status)) {
838 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
840 /* Not force user and not security=share, but force
841 * group. vuser has a token to copy */
843 conn->nt_user_token = dup_nt_token(
844 NULL, vuser->server_info->ptok);
845 if (conn->nt_user_token == NULL) {
846 DEBUG(0, ("dup_nt_token failed\n"));
848 *pstatus = NT_STATUS_NO_MEMORY;
853 /* If conn->nt_user_token is still NULL, we have
854 * security=share. This means ignore the SID, as we had no
855 * vuser to copy from */
857 if (conn->nt_user_token != NULL) {
858 /* Overwrite the primary group sid */
859 sid_copy(&conn->nt_user_token->user_sids[1],
865 if (conn->nt_user_token != NULL) {
868 /* We have a share-specific token from force [user|group].
869 * This means we have to create the list of unix groups from
870 * the list of sids. */
875 for (i=0; i<conn->nt_user_token->num_sids; i++) {
877 DOM_SID *sid = &conn->nt_user_token->user_sids[i];
879 if (!sid_to_gid(sid, &gid)) {
880 DEBUG(10, ("Could not convert SID %s to gid, "
882 sid_string_dbg(sid)));
885 if (!add_gid_to_array_unique(conn, gid, &conn->groups,
887 DEBUG(0, ("add_gid_to_array_unique failed\n"));
889 *pstatus = NT_STATUS_NO_MEMORY;
896 char *s = talloc_sub_advanced(talloc_tos(),
897 lp_servicename(SNUM(conn)), conn->user,
898 conn->connectpath, conn->gid,
899 get_current_username(),
900 current_user_info.domain,
904 *pstatus = NT_STATUS_NO_MEMORY;
908 if (!set_conn_connectpath(conn,s)) {
911 *pstatus = NT_STATUS_NO_MEMORY;
914 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
915 lp_servicename(snum)));
920 * New code to check if there's a share security descripter
921 * added from NT server manager. This is done after the
922 * smb.conf checks are done as we need a uid and token. JRA.
927 bool can_write = False;
928 NT_USER_TOKEN *token = conn->nt_user_token ?
929 conn->nt_user_token :
930 (vuser ? vuser->server_info->ptok : NULL);
933 * I don't believe this can happen. But the
934 * logic above is convoluted enough to confuse
935 * automated checkers, so be sure. JRA.
939 DEBUG(0,("make_connection: connection to %s "
940 "denied due to missing "
942 lp_servicename(snum)));
944 *pstatus = NT_STATUS_ACCESS_DENIED;
948 can_write = share_access_check(token,
949 lp_servicename(snum),
953 if (!share_access_check(token,
954 lp_servicename(snum),
956 /* No access, read or write. */
957 DEBUG(0,("make_connection: connection to %s "
958 "denied due to security "
960 lp_servicename(snum)));
962 *pstatus = NT_STATUS_ACCESS_DENIED;
965 conn->read_only = True;
969 /* Initialise VFS function pointers */
971 if (!smbd_vfs_init(conn)) {
972 DEBUG(0, ("vfs_init failed for service %s\n",
973 lp_servicename(snum)));
975 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
980 * If widelinks are disallowed we need to canonicalise the connect
981 * path here to ensure we don't have any symlinks in the
982 * connectpath. We will be checking all paths on this connection are
983 * below this directory. We must do this after the VFS init as we
984 * depend on the realpath() pointer in the vfs table. JRA.
986 if (!lp_widelinks(snum)) {
987 if (!canonicalize_connect_path(conn)) {
988 DEBUG(0, ("canonicalize_connect_path failed "
989 "for service %s, path %s\n",
990 lp_servicename(snum),
993 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
998 if ((!conn->printer) && (!conn->ipc)) {
999 conn->notify_ctx = notify_init(conn, server_id_self(),
1000 smbd_messaging_context(),
1001 smbd_event_context(),
1005 /* ROOT Activities: */
1007 * Enforce the max connections parameter.
1010 if ((lp_max_connections(snum) > 0)
1011 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
1012 lp_max_connections(snum))) {
1014 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
1015 lp_max_connections(snum), lp_servicename(snum)));
1017 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
1022 * Get us an entry in the connections db
1024 if (!claim_connection(conn, lp_servicename(snum), 0)) {
1025 DEBUG(1, ("Could not store connections entry\n"));
1027 *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
1031 /* Preexecs are done here as they might make the dir we are to ChDir
1033 /* execute any "root preexec = " line */
1034 if (*lp_rootpreexec(snum)) {
1035 char *cmd = talloc_sub_advanced(talloc_tos(),
1036 lp_servicename(SNUM(conn)), conn->user,
1037 conn->connectpath, conn->gid,
1038 get_current_username(),
1039 current_user_info.domain,
1040 lp_rootpreexec(snum));
1041 DEBUG(5,("cmd=%s\n",cmd));
1042 ret = smbrun(cmd,NULL);
1044 if (ret != 0 && lp_rootpreexec_close(snum)) {
1045 DEBUG(1,("root preexec gave %d - failing "
1046 "connection\n", ret));
1047 yield_connection(conn, lp_servicename(snum));
1049 *pstatus = NT_STATUS_ACCESS_DENIED;
1054 /* USER Activites: */
1055 if (!change_to_user(conn, conn->vuid)) {
1056 /* No point continuing if they fail the basic checks */
1057 DEBUG(0,("Can't become connected user!\n"));
1058 yield_connection(conn, lp_servicename(snum));
1060 *pstatus = NT_STATUS_LOGON_FAILURE;
1064 /* Remember that a different vuid can connect later without these
1067 /* Preexecs are done here as they might make the dir we are to ChDir
1070 /* execute any "preexec = " line */
1071 if (*lp_preexec(snum)) {
1072 char *cmd = talloc_sub_advanced(talloc_tos(),
1073 lp_servicename(SNUM(conn)), conn->user,
1074 conn->connectpath, conn->gid,
1075 get_current_username(),
1076 current_user_info.domain,
1078 ret = smbrun(cmd,NULL);
1080 if (ret != 0 && lp_preexec_close(snum)) {
1081 DEBUG(1,("preexec gave %d - failing connection\n",
1083 *pstatus = NT_STATUS_ACCESS_DENIED;
1088 #ifdef WITH_FAKE_KASERVER
1089 if (lp_afs_share(snum)) {
1094 /* Add veto/hide lists */
1095 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1096 set_namearray( &conn->veto_list, lp_veto_files(snum));
1097 set_namearray( &conn->hide_list, lp_hide_files(snum));
1098 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1101 /* Invoke VFS make connection hook - do this before the VFS_STAT call
1102 to allow any filesystems needing user credentials to initialize
1105 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), conn->user) < 0) {
1106 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1107 *pstatus = NT_STATUS_UNSUCCESSFUL;
1111 /* Any error exit after here needs to call the disconnect hook. */
1112 on_err_call_dis_hook = true;
1114 /* win2000 does not check the permissions on the directory
1115 during the tree connect, instead relying on permission
1116 check during individual operations. To match this behaviour
1117 I have disabled this chdir check (tridge) */
1118 /* the alternative is just to check the directory exists */
1119 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1120 !S_ISDIR(st.st_mode)) {
1121 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1122 DEBUG(0,("'%s' is not a directory, when connecting to "
1123 "[%s]\n", conn->connectpath,
1124 lp_servicename(snum)));
1126 DEBUG(0,("'%s' does not exist or permission denied "
1127 "when connecting to [%s] Error was %s\n",
1128 conn->connectpath, lp_servicename(snum),
1131 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1135 string_set(&conn->origpath,conn->connectpath);
1137 #if SOFTLINK_OPTIMISATION
1138 /* resolve any soft links early if possible */
1139 if (vfs_ChDir(conn,conn->connectpath) == 0) {
1140 TALLOC_CTX *ctx = talloc_tos();
1141 char *s = vfs_GetWd(ctx,s);
1143 *status = map_nt_error_from_unix(errno);
1146 if (!set_conn_connectpath(conn,s)) {
1147 *status = NT_STATUS_NO_MEMORY;
1150 vfs_ChDir(conn,conn->connectpath);
1154 /* Figure out the characteristics of the underlying filesystem. This
1155 * assumes that all the filesystem mounted withing a share path have
1156 * the same characteristics, which is likely but not guaranteed.
1159 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
1162 * Print out the 'connected as' stuff here as we need
1163 * to know the effective uid and gid we will be using
1164 * (at least initially).
1167 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1168 dbgtext( "%s (%s) ", get_remote_machine_name(),
1169 conn->client_address );
1170 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1171 dbgtext( "connect to service %s ", lp_servicename(snum) );
1172 dbgtext( "initially as user %s ", conn->user );
1173 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1174 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1177 /* we've finished with the user stuff - go back to root */
1178 change_to_root_user();
1183 change_to_root_user();
1184 if (on_err_call_dis_hook) {
1185 /* Call VFS disconnect hook */
1186 SMB_VFS_DISCONNECT(conn);
1188 yield_connection(conn, lp_servicename(snum));
1193 /***************************************************************************************
1194 Simple wrapper function for make_connection() to include a call to
1196 **************************************************************************************/
1198 connection_struct *make_connection_with_chdir(const char *service_in,
1200 const char *dev, uint16 vuid,
1203 connection_struct *conn = NULL;
1205 conn = make_connection(service_in, password, dev, vuid, status);
1208 * make_connection() does not change the directory for us any more
1209 * so we have to do it as a separate step --jerry
1212 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1213 DEBUG(0,("move_driver_to_download_area: Can't change "
1214 "directory to %s for [print$] (%s)\n",
1215 conn->connectpath,strerror(errno)));
1216 yield_connection(conn, lp_servicename(SNUM(conn)));
1218 *status = NT_STATUS_UNSUCCESSFUL;
1225 /****************************************************************************
1226 Make a connection to a service.
1229 ****************************************************************************/
1231 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
1232 const char *pdev, uint16 vuid,
1236 user_struct *vuser = NULL;
1240 char addr[INET6_ADDRSTRLEN];
1244 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1246 if (!non_root_mode() && (euid = geteuid()) != 0) {
1247 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1248 "(%u)\n", (unsigned int)euid ));
1249 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1252 if (conn_num_open() > 2047) {
1253 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1257 if(lp_security() != SEC_SHARE) {
1258 vuser = get_valid_user_struct(vuid);
1260 DEBUG(1,("make_connection: refusing to connect with "
1261 "no session setup\n"));
1262 *status = NT_STATUS_ACCESS_DENIED;
1267 /* Logic to try and connect to the correct [homes] share, preferably
1268 without too many getpwnam() lookups. This is particulary nasty for
1269 winbind usernames, where the share name isn't the same as unix
1272 The snum of the homes share is stored on the vuser at session setup
1276 if (strequal(service_in,HOMES_NAME)) {
1277 if(lp_security() != SEC_SHARE) {
1278 DATA_BLOB no_pw = data_blob_null;
1279 if (vuser->homes_snum == -1) {
1280 DEBUG(2, ("[homes] share not available for "
1281 "this user because it was not found "
1282 "or created at session setup "
1284 *status = NT_STATUS_BAD_NETWORK_NAME;
1287 DEBUG(5, ("making a connection to [homes] service "
1288 "created at session setup time\n"));
1289 return make_connection_snum(vuser->homes_snum,
1293 /* Security = share. Try with
1294 * current_user_info.smb_name as the username. */
1295 if (*current_user_info.smb_name) {
1296 fstring unix_username;
1297 fstrcpy(unix_username,
1298 current_user_info.smb_name);
1299 map_username(unix_username);
1300 snum = find_service(unix_username);
1303 DEBUG(5, ("making a connection to 'homes' "
1304 "service %s based on "
1305 "security=share\n", service_in));
1306 return make_connection_snum(snum, NULL,
1311 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1312 && strequal(service_in,
1313 lp_servicename(vuser->homes_snum))) {
1314 DATA_BLOB no_pw = data_blob_null;
1315 DEBUG(5, ("making a connection to 'homes' service [%s] "
1316 "created at session setup time\n", service_in));
1317 return make_connection_snum(vuser->homes_snum,
1322 fstrcpy(service, service_in);
1324 strlower_m(service);
1326 snum = find_service(service);
1329 if (strequal(service,"IPC$") ||
1330 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1331 DEBUG(3,("refusing IPC connection to %s\n", service));
1332 *status = NT_STATUS_ACCESS_DENIED;
1336 DEBUG(0,("%s (%s) couldn't find service %s\n",
1337 get_remote_machine_name(),
1338 client_addr(get_client_fd(),addr,sizeof(addr)),
1340 *status = NT_STATUS_BAD_NETWORK_NAME;
1344 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1345 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1346 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1347 "(pointing to %s)\n",
1348 service, lp_msdfs_proxy(snum)));
1349 *status = NT_STATUS_BAD_NETWORK_NAME;
1353 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1355 return make_connection_snum(snum, vuser,
1360 /****************************************************************************
1362 ****************************************************************************/
1364 void close_cnum(connection_struct *conn, uint16 vuid)
1367 pipe_close_conn(conn);
1369 file_close_conn(conn);
1370 dptr_closecnum(conn);
1373 change_to_root_user();
1375 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1376 get_remote_machine_name(),
1377 conn->client_address,
1378 lp_servicename(SNUM(conn))));
1380 /* Call VFS disconnect hook */
1381 SMB_VFS_DISCONNECT(conn);
1383 yield_connection(conn, lp_servicename(SNUM(conn)));
1385 /* make sure we leave the directory available for unmount */
1386 vfs_ChDir(conn, "/");
1388 /* execute any "postexec = " line */
1389 if (*lp_postexec(SNUM(conn)) &&
1390 change_to_user(conn, vuid)) {
1391 char *cmd = talloc_sub_advanced(talloc_tos(),
1392 lp_servicename(SNUM(conn)), conn->user,
1393 conn->connectpath, conn->gid,
1394 get_current_username(),
1395 current_user_info.domain,
1396 lp_postexec(SNUM(conn)));
1399 change_to_root_user();
1402 change_to_root_user();
1403 /* execute any "root postexec = " line */
1404 if (*lp_rootpostexec(SNUM(conn))) {
1405 char *cmd = talloc_sub_advanced(talloc_tos(),
1406 lp_servicename(SNUM(conn)), conn->user,
1407 conn->connectpath, conn->gid,
1408 get_current_username(),
1409 current_user_info.domain,
1410 lp_rootpostexec(SNUM(conn)));