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 /****************************************************************************
223 Add a home service. Returns the new service number or -1 if fail.
224 ****************************************************************************/
226 int add_home_service(const char *service, const char *username, const char *homedir)
230 if (!service || !homedir)
233 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
237 * If this is a winbindd provided username, remove
238 * the domain component before adding the service.
239 * Log a warning if the "path=" parameter does not
240 * include any macros.
244 const char *p = strchr(service,*lp_winbind_separator());
246 /* We only want the 'user' part of the string */
252 if (!lp_add_home(service, iHomeService, username, homedir)) {
256 return lp_servicenumber(service);
260 static int load_registry_service(const char *servicename)
262 struct registry_key *key;
268 struct registry_value *value;
272 if (!lp_registry_shares()) {
276 if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) {
280 err = reg_open_path(NULL, path, REG_KEY_READ, get_root_nt_token(),
284 if (!W_ERROR_IS_OK(err)) {
288 res = lp_add_service(servicename, -1);
294 W_ERROR_IS_OK(reg_enumvalue(key, key, i, &value_name, &value));
296 switch (value->type) {
299 if (asprintf(&tmp, "%d", value->v.dword) == -1) {
302 lp_do_parameter(res, value_name, tmp);
307 lp_do_parameter(res, value_name, value->v.sz.str);
311 /* Ignore all the rest */
315 TALLOC_FREE(value_name);
325 void load_registry_shares(void)
327 struct registry_key *key;
332 if (!lp_registry_shares()) {
336 err = reg_open_path(NULL, KEY_SMBCONF, REG_KEY_READ,
337 get_root_nt_token(), &key);
338 if (!(W_ERROR_IS_OK(err))) {
342 for (i=0; W_ERROR_IS_OK(reg_enumkey(key, key, i, &name, NULL)); i++) {
343 load_registry_service(name);
352 * Find a service entry.
354 * @param service is modified (to canonical form??)
357 int find_service(fstring service)
361 all_string_sub(service,"\\","/",0);
363 iService = lp_servicenumber(service);
365 /* now handle the special case of a home directory */
367 char *phome_dir = get_user_home_dir(service);
371 * Try mapping the servicename, it may
372 * be a Windows to unix mapped user name.
374 if(map_username(service))
375 phome_dir = get_user_home_dir(service);
378 DEBUG(3,("checking for home directory %s gave %s\n",service,
379 phome_dir?phome_dir:"(NULL)"));
381 iService = add_home_service(service,service /* 'username' */, phome_dir);
384 /* If we still don't have a service, attempt to add it as a printer. */
388 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
389 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
390 if (pcap_printername_ok(service)) {
391 DEBUG(3,("%s is a valid printer name\n", service));
392 DEBUG(3,("adding %s as a printer service\n", service));
393 lp_add_printer(service, iPrinterService);
394 iService = lp_servicenumber(service);
396 DEBUG(0,("failed to add %s as a printer service!\n", service));
399 DEBUG(3,("%s is not a valid printer name\n", service));
404 /* Check for default vfs service? Unsure whether to implement this */
409 iService = load_registry_service(service);
412 /* Is it a usershare service ? */
413 if (iService < 0 && *lp_usershare_path()) {
414 /* Ensure the name is canonicalized. */
416 iService = load_usershare_service(service);
419 /* just possibly it's a default service? */
421 char *pdefservice = lp_defaultservice();
422 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
424 * We need to do a local copy here as lp_defaultservice()
425 * returns one of the rotating lp_string buffers that
426 * could get overwritten by the recursive find_service() call
427 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
429 char *defservice = SMB_STRDUP(pdefservice);
435 /* Disallow anything except explicit share names. */
436 if (strequal(defservice,HOMES_NAME) ||
437 strequal(defservice, PRINTERS_NAME) ||
438 strequal(defservice, "IPC$")) {
439 SAFE_FREE(defservice);
443 iService = find_service(defservice);
445 all_string_sub(service, "_","/",0);
446 iService = lp_add_service(service, iService);
448 SAFE_FREE(defservice);
453 if (!VALID_SNUM(iService)) {
454 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
462 DEBUG(3,("find_service() failed to find service %s\n", service));
468 /****************************************************************************
469 do some basic sainity checks on the share.
470 This function modifies dev, ecode.
471 ****************************************************************************/
473 static NTSTATUS share_sanity_checks(int snum, fstring dev)
476 if (!lp_snum_ok(snum) ||
477 !check_access(smbd_server_fd(),
478 lp_hostsallow(snum), lp_hostsdeny(snum))) {
479 return NT_STATUS_ACCESS_DENIED;
482 if (dev[0] == '?' || !dev[0]) {
483 if (lp_print_ok(snum)) {
484 fstrcpy(dev,"LPT1:");
485 } else if (strequal(lp_fstype(snum), "IPC")) {
494 if (lp_print_ok(snum)) {
495 if (!strequal(dev, "LPT1:")) {
496 return NT_STATUS_BAD_DEVICE_TYPE;
498 } else if (strequal(lp_fstype(snum), "IPC")) {
499 if (!strequal(dev, "IPC")) {
500 return NT_STATUS_BAD_DEVICE_TYPE;
502 } else if (!strequal(dev, "A:")) {
503 return NT_STATUS_BAD_DEVICE_TYPE;
506 /* Behave as a printer if we are supposed to */
507 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
508 fstrcpy(dev, "LPT1:");
514 static NTSTATUS find_forced_user(connection_struct *conn, bool vuser_is_guest, fstring username)
516 int snum = conn->params->service;
517 char *fuser, *found_username;
520 if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S",
521 lp_servicename(snum)))) {
522 return NT_STATUS_NO_MEMORY;
525 result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest,
526 &conn->uid, &conn->gid, &found_username,
527 &conn->nt_user_token);
528 if (!NT_STATUS_IS_OK(result)) {
532 fstrcpy(username, found_username);
535 TALLOC_FREE(found_username);
540 * Go through lookup_name etc to find the force'd group.
542 * Create a new token from src_token, replacing the primary group sid with the
546 static NTSTATUS find_forced_group(bool force_user,
547 int snum, const char *username,
551 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
554 enum lsa_SidType type;
556 bool user_must_be_member = False;
559 ZERO_STRUCTP(pgroup_sid);
562 mem_ctx = talloc_new(NULL);
563 if (mem_ctx == NULL) {
564 DEBUG(0, ("talloc_new failed\n"));
565 return NT_STATUS_NO_MEMORY;
568 groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
569 if (groupname == NULL) {
570 DEBUG(1, ("talloc_strdup failed\n"));
571 result = NT_STATUS_NO_MEMORY;
575 if (groupname[0] == '+') {
576 user_must_be_member = True;
580 groupname = talloc_string_sub(mem_ctx, groupname,
581 "%S", lp_servicename(snum));
583 if (!lookup_name_smbconf(mem_ctx, groupname,
584 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
585 NULL, NULL, &group_sid, &type)) {
586 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
591 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
592 (type != SID_NAME_WKN_GRP)) {
593 DEBUG(10, ("%s is a %s, not a group\n", groupname,
594 sid_type_lookup(type)));
598 if (!sid_to_gid(&group_sid, &gid)) {
599 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
600 sid_string_dbg(&group_sid), groupname));
605 * If the user has been forced and the forced group starts with a '+',
606 * then we only set the group to be the forced group if the forced
607 * user is a member of that group. Otherwise, the meaning of the '+'
611 if (force_user && user_must_be_member) {
612 if (user_in_group_sid(username, &group_sid)) {
613 sid_copy(pgroup_sid, &group_sid);
615 DEBUG(3,("Forced group %s for member %s\n",
616 groupname, username));
618 DEBUG(0,("find_forced_group: forced user %s is not a member "
619 "of forced group %s. Disallowing access.\n",
620 username, groupname ));
621 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
625 sid_copy(pgroup_sid, &group_sid);
627 DEBUG(3,("Forced group %s\n", groupname));
630 result = NT_STATUS_OK;
632 TALLOC_FREE(mem_ctx);
636 /****************************************************************************
637 Make a connection, given the snum to connect to, and the vuser of the
638 connecting user if appropriate.
639 ****************************************************************************/
641 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
646 struct passwd *pass = NULL;
648 connection_struct *conn;
653 char addr[INET6_ADDRSTRLEN];
654 bool on_err_call_dis_hook = false;
658 SET_STAT_INVALID(st);
660 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
666 DEBUG(0,("Couldn't find free connection.\n"));
667 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
671 conn->params->service = snum;
672 conn->nt_user_token = NULL;
674 if (lp_guest_only(snum)) {
675 const char *guestname = lp_guestaccount();
677 char *found_username = NULL;
680 pass = getpwnam_alloc(NULL, guestname);
682 DEBUG(0,("make_connection_snum: Invalid guest "
683 "account %s??\n",guestname));
685 *status = NT_STATUS_NO_SUCH_USER;
688 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
689 &conn->uid, &conn->gid,
691 &conn->nt_user_token);
692 if (!NT_STATUS_IS_OK(status2)) {
698 fstrcpy(user, found_username);
699 string_set(&conn->user,user);
700 conn->force_user = True;
701 TALLOC_FREE(found_username);
703 DEBUG(3,("Guest only user %s\n",user));
706 if (!lp_guest_ok(snum)) {
707 DEBUG(2, ("guest user (from session setup) "
708 "not permitted to access this share "
709 "(%s)\n", lp_servicename(snum)));
711 *status = NT_STATUS_ACCESS_DENIED;
715 if (!user_ok_token(vuser->user.unix_name,
716 vuser->nt_user_token, snum)) {
717 DEBUG(2, ("user '%s' (from session setup) not "
718 "permitted to access this share "
719 "(%s)\n", vuser->user.unix_name,
720 lp_servicename(snum)));
722 *status = NT_STATUS_ACCESS_DENIED;
726 conn->vuid = vuser->vuid;
727 conn->uid = vuser->uid;
728 conn->gid = vuser->gid;
729 string_set(&conn->user,vuser->user.unix_name);
730 fstrcpy(user,vuser->user.unix_name);
731 guest = vuser->guest;
732 } else if (lp_security() == SEC_SHARE) {
734 char *found_username = NULL;
736 /* add it as a possible user name if we
737 are in share mode security */
738 add_session_user(lp_servicename(snum));
739 /* shall we let them in? */
740 if (!authorise_login(snum,user,password,&guest)) {
741 DEBUG( 2, ( "Invalid username/password for [%s]\n",
742 lp_servicename(snum)) );
744 *status = NT_STATUS_WRONG_PASSWORD;
747 pass = Get_Pwnam(user);
748 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
749 &conn->uid, &conn->gid,
751 &conn->nt_user_token);
752 if (!NT_STATUS_IS_OK(status2)) {
757 fstrcpy(user, found_username);
758 string_set(&conn->user,user);
759 TALLOC_FREE(found_username);
760 conn->force_user = True;
762 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
764 *status = NT_STATUS_ACCESS_DENIED;
768 add_session_user(user);
770 safe_strcpy(conn->client_address,
771 client_addr(get_client_fd(),addr,sizeof(addr)),
772 sizeof(conn->client_address)-1);
773 conn->num_files_open = 0;
774 conn->lastused = conn->lastused_count = time(NULL);
776 conn->printer = (strncmp(dev,"LPT",3) == 0);
777 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
778 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
781 /* Case options for the share. */
782 if (lp_casesensitive(snum) == Auto) {
783 /* We will be setting this per packet. Set to be case
784 * insensitive for now. */
785 conn->case_sensitive = False;
787 conn->case_sensitive = (bool)lp_casesensitive(snum);
790 conn->case_preserve = lp_preservecase(snum);
791 conn->short_case_preserve = lp_shortpreservecase(snum);
793 conn->veto_list = NULL;
794 conn->hide_list = NULL;
795 conn->veto_oplock_list = NULL;
796 conn->aio_write_behind_list = NULL;
797 string_set(&conn->dirpath,"");
798 string_set(&conn->user,user);
800 conn->read_only = lp_readonly(SNUM(conn));
801 conn->admin_user = False;
804 * If force user is true, then store the given userid and the gid of
805 * the user we're forcing.
806 * For auxiliary groups see below.
809 if (*lp_force_user(snum)) {
812 status2 = find_forced_user(conn,
813 (vuser != NULL) && vuser->guest,
815 if (!NT_STATUS_IS_OK(status2)) {
820 string_set(&conn->user,user);
821 conn->force_user = True;
822 DEBUG(3,("Forced user %s\n",user));
826 * If force group is true, then override
827 * any groupid stored for the connecting user.
830 if (*lp_force_group(snum)) {
834 status2 = find_forced_group(conn->force_user,
836 &group_sid, &conn->gid);
837 if (!NT_STATUS_IS_OK(status2)) {
843 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
845 /* Not force user and not security=share, but force
846 * group. vuser has a token to copy */
848 conn->nt_user_token = dup_nt_token(
849 NULL, vuser->nt_user_token);
850 if (conn->nt_user_token == NULL) {
851 DEBUG(0, ("dup_nt_token failed\n"));
853 *status = NT_STATUS_NO_MEMORY;
858 /* If conn->nt_user_token is still NULL, we have
859 * security=share. This means ignore the SID, as we had no
860 * vuser to copy from */
862 if (conn->nt_user_token != NULL) {
863 /* Overwrite the primary group sid */
864 sid_copy(&conn->nt_user_token->user_sids[1],
868 conn->force_group = True;
871 if (conn->nt_user_token != NULL) {
874 /* We have a share-specific token from force [user|group].
875 * This means we have to create the list of unix groups from
876 * the list of sids. */
881 for (i=0; i<conn->nt_user_token->num_sids; i++) {
883 DOM_SID *sid = &conn->nt_user_token->user_sids[i];
885 if (!sid_to_gid(sid, &gid)) {
886 DEBUG(10, ("Could not convert SID %s to gid, "
888 sid_string_dbg(sid)));
891 if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
893 DEBUG(0, ("add_gid_to_array_unique failed\n"));
895 *status = NT_STATUS_NO_MEMORY;
902 char *s = talloc_sub_advanced(talloc_tos(),
903 lp_servicename(SNUM(conn)), conn->user,
904 conn->connectpath, conn->gid,
905 get_current_username(),
906 current_user_info.domain,
910 *status = NT_STATUS_NO_MEMORY;
914 if (!set_conn_connectpath(conn,s)) {
917 *status = NT_STATUS_NO_MEMORY;
920 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
921 lp_servicename(snum)));
926 * New code to check if there's a share security descripter
927 * added from NT server manager. This is done after the
928 * smb.conf checks are done as we need a uid and token. JRA.
933 bool can_write = False;
934 NT_USER_TOKEN *token = conn->nt_user_token ?
935 conn->nt_user_token :
936 (vuser ? vuser->nt_user_token : NULL);
939 * I don't believe this can happen. But the
940 * logic above is convoluted enough to confuse
941 * automated checkers, so be sure. JRA.
945 DEBUG(0,("make_connection: connection to %s "
946 "denied due to missing "
948 lp_servicename(snum)));
950 *status = NT_STATUS_ACCESS_DENIED;
954 can_write = share_access_check(token,
955 lp_servicename(snum),
959 if (!share_access_check(token,
960 lp_servicename(snum),
962 /* No access, read or write. */
963 DEBUG(0,("make_connection: connection to %s "
964 "denied due to security "
966 lp_servicename(snum)));
968 *status = NT_STATUS_ACCESS_DENIED;
971 conn->read_only = True;
975 /* Initialise VFS function pointers */
977 if (!smbd_vfs_init(conn)) {
978 DEBUG(0, ("vfs_init failed for service %s\n",
979 lp_servicename(snum)));
981 *status = NT_STATUS_BAD_NETWORK_NAME;
986 * If widelinks are disallowed we need to canonicalise the connect
987 * path here to ensure we don't have any symlinks in the
988 * connectpath. We will be checking all paths on this connection are
989 * below this directory. We must do this after the VFS init as we
990 * depend on the realpath() pointer in the vfs table. JRA.
992 if (!lp_widelinks(snum)) {
993 if (!canonicalize_connect_path(conn)) {
994 DEBUG(0, ("canonicalize_connect_path failed "
995 "for service %s, path %s\n",
996 lp_servicename(snum),
999 *status = NT_STATUS_BAD_NETWORK_NAME;
1004 if ((!conn->printer) && (!conn->ipc)) {
1005 conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
1006 smbd_messaging_context(),
1007 smbd_event_context(),
1011 /* ROOT Activities: */
1013 * Enforce the max connections parameter.
1016 if ((lp_max_connections(snum) > 0)
1017 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
1018 lp_max_connections(snum))) {
1020 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
1021 lp_max_connections(snum), lp_servicename(snum)));
1023 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
1028 * Get us an entry in the connections db
1030 if (!claim_connection(conn, lp_servicename(snum), 0)) {
1031 DEBUG(1, ("Could not store connections entry\n"));
1033 *status = NT_STATUS_INTERNAL_DB_ERROR;
1037 /* Preexecs are done here as they might make the dir we are to ChDir
1039 /* execute any "root preexec = " line */
1040 if (*lp_rootpreexec(snum)) {
1041 char *cmd = talloc_sub_advanced(talloc_tos(),
1042 lp_servicename(SNUM(conn)), conn->user,
1043 conn->connectpath, conn->gid,
1044 get_current_username(),
1045 current_user_info.domain,
1046 lp_rootpreexec(snum));
1047 DEBUG(5,("cmd=%s\n",cmd));
1048 ret = smbrun(cmd,NULL);
1050 if (ret != 0 && lp_rootpreexec_close(snum)) {
1051 DEBUG(1,("root preexec gave %d - failing "
1052 "connection\n", ret));
1053 yield_connection(conn, lp_servicename(snum));
1055 *status = NT_STATUS_ACCESS_DENIED;
1060 /* USER Activites: */
1061 if (!change_to_user(conn, conn->vuid)) {
1062 /* No point continuing if they fail the basic checks */
1063 DEBUG(0,("Can't become connected user!\n"));
1064 yield_connection(conn, lp_servicename(snum));
1066 *status = NT_STATUS_LOGON_FAILURE;
1070 /* Remember that a different vuid can connect later without these
1073 /* Preexecs are done here as they might make the dir we are to ChDir
1076 /* execute any "preexec = " line */
1077 if (*lp_preexec(snum)) {
1078 char *cmd = talloc_sub_advanced(talloc_tos(),
1079 lp_servicename(SNUM(conn)), conn->user,
1080 conn->connectpath, conn->gid,
1081 get_current_username(),
1082 current_user_info.domain,
1084 ret = smbrun(cmd,NULL);
1086 if (ret != 0 && lp_preexec_close(snum)) {
1087 DEBUG(1,("preexec gave %d - failing connection\n",
1089 *status = NT_STATUS_ACCESS_DENIED;
1094 #ifdef WITH_FAKE_KASERVER
1095 if (lp_afs_share(snum)) {
1100 /* Add veto/hide lists */
1101 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1102 set_namearray( &conn->veto_list, lp_veto_files(snum));
1103 set_namearray( &conn->hide_list, lp_hide_files(snum));
1104 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1107 /* Invoke VFS make connection hook - do this before the VFS_STAT call
1108 to allow any filesystems needing user credentials to initialize
1111 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
1112 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1113 *status = NT_STATUS_UNSUCCESSFUL;
1117 /* Any error exit after here needs to call the disconnect hook. */
1118 on_err_call_dis_hook = true;
1120 /* win2000 does not check the permissions on the directory
1121 during the tree connect, instead relying on permission
1122 check during individual operations. To match this behaviour
1123 I have disabled this chdir check (tridge) */
1124 /* the alternative is just to check the directory exists */
1125 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1126 !S_ISDIR(st.st_mode)) {
1127 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1128 DEBUG(0,("'%s' is not a directory, when connecting to "
1129 "[%s]\n", conn->connectpath,
1130 lp_servicename(snum)));
1132 DEBUG(0,("'%s' does not exist or permission denied "
1133 "when connecting to [%s] Error was %s\n",
1134 conn->connectpath, lp_servicename(snum),
1137 *status = NT_STATUS_BAD_NETWORK_NAME;
1141 string_set(&conn->origpath,conn->connectpath);
1143 #if SOFTLINK_OPTIMISATION
1144 /* resolve any soft links early if possible */
1145 if (vfs_ChDir(conn,conn->connectpath) == 0) {
1146 TALLOC_CTX *ctx = talloc_stackframe();
1147 char *s = vfs_GetWd(ctx,s);
1149 *status = map_nt_error_from_unix(errno);
1153 if (!set_conn_connectpath(conn,s)) {
1154 *status = NT_STATUS_NO_MEMORY;
1158 vfs_ChDir(conn,conn->connectpath);
1164 * Print out the 'connected as' stuff here as we need
1165 * to know the effective uid and gid we will be using
1166 * (at least initially).
1169 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1170 dbgtext( "%s (%s) ", get_remote_machine_name(),
1171 conn->client_address );
1172 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1173 dbgtext( "connect to service %s ", lp_servicename(snum) );
1174 dbgtext( "initially as user %s ", user );
1175 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1176 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1179 /* we've finished with the user stuff - go back to root */
1180 change_to_root_user();
1185 change_to_root_user();
1186 if (on_err_call_dis_hook) {
1187 /* Call VFS disconnect hook */
1188 SMB_VFS_DISCONNECT(conn);
1190 yield_connection(conn, lp_servicename(snum));
1195 /***************************************************************************************
1196 Simple wrapper function for make_connection() to include a call to
1198 **************************************************************************************/
1200 connection_struct *make_connection_with_chdir(const char *service_in,
1202 const char *dev, uint16 vuid,
1205 connection_struct *conn = NULL;
1207 conn = make_connection(service_in, password, dev, vuid, status);
1210 * make_connection() does not change the directory for us any more
1211 * so we have to do it as a separate step --jerry
1214 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1215 DEBUG(0,("move_driver_to_download_area: Can't change "
1216 "directory to %s for [print$] (%s)\n",
1217 conn->connectpath,strerror(errno)));
1218 yield_connection(conn, lp_servicename(SNUM(conn)));
1220 *status = NT_STATUS_UNSUCCESSFUL;
1227 /****************************************************************************
1228 Make a connection to a service.
1231 ****************************************************************************/
1233 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
1234 const char *pdev, uint16 vuid,
1238 user_struct *vuser = NULL;
1242 char addr[INET6_ADDRSTRLEN];
1246 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1248 if (!non_root_mode() && (euid = geteuid()) != 0) {
1249 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1250 "(%u)\n", (unsigned int)euid ));
1251 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1254 if (conn_num_open() > 2047) {
1255 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1259 if(lp_security() != SEC_SHARE) {
1260 vuser = get_valid_user_struct(vuid);
1262 DEBUG(1,("make_connection: refusing to connect with "
1263 "no session setup\n"));
1264 *status = NT_STATUS_ACCESS_DENIED;
1269 /* Logic to try and connect to the correct [homes] share, preferably
1270 without too many getpwnam() lookups. This is particulary nasty for
1271 winbind usernames, where the share name isn't the same as unix
1274 The snum of the homes share is stored on the vuser at session setup
1278 if (strequal(service_in,HOMES_NAME)) {
1279 if(lp_security() != SEC_SHARE) {
1280 DATA_BLOB no_pw = data_blob_null;
1281 if (vuser->homes_snum == -1) {
1282 DEBUG(2, ("[homes] share not available for "
1283 "this user because it was not found "
1284 "or created at session setup "
1286 *status = NT_STATUS_BAD_NETWORK_NAME;
1289 DEBUG(5, ("making a connection to [homes] service "
1290 "created at session setup time\n"));
1291 return make_connection_snum(vuser->homes_snum,
1295 /* Security = share. Try with
1296 * current_user_info.smb_name as the username. */
1297 if (*current_user_info.smb_name) {
1298 fstring unix_username;
1299 fstrcpy(unix_username,
1300 current_user_info.smb_name);
1301 map_username(unix_username);
1302 snum = find_service(unix_username);
1305 DEBUG(5, ("making a connection to 'homes' "
1306 "service %s based on "
1307 "security=share\n", service_in));
1308 return make_connection_snum(snum, NULL,
1313 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1314 && strequal(service_in,
1315 lp_servicename(vuser->homes_snum))) {
1316 DATA_BLOB no_pw = data_blob_null;
1317 DEBUG(5, ("making a connection to 'homes' service [%s] "
1318 "created at session setup time\n", service_in));
1319 return make_connection_snum(vuser->homes_snum,
1324 fstrcpy(service, service_in);
1326 strlower_m(service);
1328 snum = find_service(service);
1331 if (strequal(service,"IPC$") ||
1332 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1333 DEBUG(3,("refusing IPC connection to %s\n", service));
1334 *status = NT_STATUS_ACCESS_DENIED;
1338 DEBUG(0,("%s (%s) couldn't find service %s\n",
1339 get_remote_machine_name(),
1340 client_addr(get_client_fd(),addr,sizeof(addr)),
1342 *status = NT_STATUS_BAD_NETWORK_NAME;
1346 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1347 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1348 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1349 "(pointing to %s)\n",
1350 service, lp_msdfs_proxy(snum)));
1351 *status = NT_STATUS_BAD_NETWORK_NAME;
1355 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1357 return make_connection_snum(snum, vuser,
1362 /****************************************************************************
1364 ****************************************************************************/
1366 void close_cnum(connection_struct *conn, uint16 vuid)
1369 pipe_close_conn(conn);
1371 file_close_conn(conn);
1372 dptr_closecnum(conn);
1375 change_to_root_user();
1377 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1378 get_remote_machine_name(),
1379 conn->client_address,
1380 lp_servicename(SNUM(conn))));
1382 /* Call VFS disconnect hook */
1383 SMB_VFS_DISCONNECT(conn);
1385 yield_connection(conn, lp_servicename(SNUM(conn)));
1387 /* make sure we leave the directory available for unmount */
1388 vfs_ChDir(conn, "/");
1390 /* execute any "postexec = " line */
1391 if (*lp_postexec(SNUM(conn)) &&
1392 change_to_user(conn, vuid)) {
1393 char *cmd = talloc_sub_advanced(talloc_tos(),
1394 lp_servicename(SNUM(conn)), conn->user,
1395 conn->connectpath, conn->gid,
1396 get_current_username(),
1397 current_user_info.domain,
1398 lp_postexec(SNUM(conn)));
1401 change_to_root_user();
1404 change_to_root_user();
1405 /* execute any "root postexec = " line */
1406 if (*lp_rootpostexec(SNUM(conn))) {
1407 char *cmd = talloc_sub_advanced(talloc_tos(),
1408 lp_servicename(SNUM(conn)), conn->user,
1409 conn->connectpath, conn->gid,
1410 get_current_username(),
1411 current_user_info.domain,
1412 lp_rootpostexec(SNUM(conn)));