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 if (!lp_registry_shares()) {
302 err = reg_open_path(NULL, KEY_SMBCONF, REG_KEY_READ,
303 get_root_nt_token(), &key);
304 if (!(W_ERROR_IS_OK(err))) {
308 for (i=0; W_ERROR_IS_OK(reg_enumkey(key, key, i, &name, NULL)); i++) {
309 load_registry_service(name);
317 /****************************************************************************
318 Add a home service. Returns the new service number or -1 if fail.
319 ****************************************************************************/
321 int add_home_service(const char *service, const char *username, const char *homedir)
325 if (!service || !homedir)
328 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
329 if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
335 * If this is a winbindd provided username, remove
336 * the domain component before adding the service.
337 * Log a warning if the "path=" parameter does not
338 * include any macros.
342 const char *p = strchr(service,*lp_winbind_separator());
344 /* We only want the 'user' part of the string */
350 if (!lp_add_home(service, iHomeService, username, homedir)) {
354 return lp_servicenumber(service);
359 * Find a service entry.
361 * @param service is modified (to canonical form??)
364 int find_service(fstring service)
368 all_string_sub(service,"\\","/",0);
370 iService = lp_servicenumber(service);
372 /* now handle the special case of a home directory */
374 char *phome_dir = get_user_home_dir(talloc_tos(), service);
378 * Try mapping the servicename, it may
379 * be a Windows to unix mapped user name.
381 if(map_username(service))
382 phome_dir = get_user_home_dir(
383 talloc_tos(), service);
386 DEBUG(3,("checking for home directory %s gave %s\n",service,
387 phome_dir?phome_dir:"(NULL)"));
389 iService = add_home_service(service,service /* 'username' */, phome_dir);
392 /* If we still don't have a service, attempt to add it as a printer. */
396 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
397 iPrinterService = load_registry_service(PRINTERS_NAME);
399 if (iPrinterService) {
400 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
401 if (pcap_printername_ok(service)) {
402 DEBUG(3,("%s is a valid printer name\n", service));
403 DEBUG(3,("adding %s as a printer service\n", service));
404 lp_add_printer(service, iPrinterService);
405 iService = lp_servicenumber(service);
407 DEBUG(0,("failed to add %s as a printer service!\n", service));
410 DEBUG(3,("%s is not a valid printer name\n", service));
415 /* Check for default vfs service? Unsure whether to implement this */
420 iService = load_registry_service(service);
423 /* Is it a usershare service ? */
424 if (iService < 0 && *lp_usershare_path()) {
425 /* Ensure the name is canonicalized. */
427 iService = load_usershare_service(service);
430 /* just possibly it's a default service? */
432 char *pdefservice = lp_defaultservice();
433 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
435 * We need to do a local copy here as lp_defaultservice()
436 * returns one of the rotating lp_string buffers that
437 * could get overwritten by the recursive find_service() call
438 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
440 char *defservice = SMB_STRDUP(pdefservice);
446 /* Disallow anything except explicit share names. */
447 if (strequal(defservice,HOMES_NAME) ||
448 strequal(defservice, PRINTERS_NAME) ||
449 strequal(defservice, "IPC$")) {
450 SAFE_FREE(defservice);
454 iService = find_service(defservice);
456 all_string_sub(service, "_","/",0);
457 iService = lp_add_service(service, iService);
459 SAFE_FREE(defservice);
464 if (!VALID_SNUM(iService)) {
465 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
473 DEBUG(3,("find_service() failed to find service %s\n", service));
479 /****************************************************************************
480 do some basic sainity checks on the share.
481 This function modifies dev, ecode.
482 ****************************************************************************/
484 static NTSTATUS share_sanity_checks(int snum, fstring dev)
487 if (!lp_snum_ok(snum) ||
488 !check_access(smbd_server_fd(),
489 lp_hostsallow(snum), lp_hostsdeny(snum))) {
490 return NT_STATUS_ACCESS_DENIED;
493 if (dev[0] == '?' || !dev[0]) {
494 if (lp_print_ok(snum)) {
495 fstrcpy(dev,"LPT1:");
496 } else if (strequal(lp_fstype(snum), "IPC")) {
505 if (lp_print_ok(snum)) {
506 if (!strequal(dev, "LPT1:")) {
507 return NT_STATUS_BAD_DEVICE_TYPE;
509 } else if (strequal(lp_fstype(snum), "IPC")) {
510 if (!strequal(dev, "IPC")) {
511 return NT_STATUS_BAD_DEVICE_TYPE;
513 } else if (!strequal(dev, "A:")) {
514 return NT_STATUS_BAD_DEVICE_TYPE;
517 /* Behave as a printer if we are supposed to */
518 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
519 fstrcpy(dev, "LPT1:");
525 static NTSTATUS find_forced_user(connection_struct *conn, bool vuser_is_guest, fstring username)
527 int snum = conn->params->service;
528 char *fuser, *found_username;
531 if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S",
532 lp_servicename(snum)))) {
533 return NT_STATUS_NO_MEMORY;
536 result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest,
537 &conn->uid, &conn->gid, &found_username,
538 &conn->nt_user_token);
539 if (!NT_STATUS_IS_OK(result)) {
543 fstrcpy(username, found_username);
546 TALLOC_FREE(found_username);
551 * Go through lookup_name etc to find the force'd group.
553 * Create a new token from src_token, replacing the primary group sid with the
557 static NTSTATUS find_forced_group(bool force_user,
558 int snum, const char *username,
562 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
565 enum lsa_SidType type;
567 bool user_must_be_member = False;
570 ZERO_STRUCTP(pgroup_sid);
573 mem_ctx = talloc_new(NULL);
574 if (mem_ctx == NULL) {
575 DEBUG(0, ("talloc_new failed\n"));
576 return NT_STATUS_NO_MEMORY;
579 groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
580 if (groupname == NULL) {
581 DEBUG(1, ("talloc_strdup failed\n"));
582 result = NT_STATUS_NO_MEMORY;
586 if (groupname[0] == '+') {
587 user_must_be_member = True;
591 groupname = talloc_string_sub(mem_ctx, groupname,
592 "%S", lp_servicename(snum));
594 if (!lookup_name_smbconf(mem_ctx, groupname,
595 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
596 NULL, NULL, &group_sid, &type)) {
597 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
602 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
603 (type != SID_NAME_WKN_GRP)) {
604 DEBUG(10, ("%s is a %s, not a group\n", groupname,
605 sid_type_lookup(type)));
609 if (!sid_to_gid(&group_sid, &gid)) {
610 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
611 sid_string_dbg(&group_sid), groupname));
616 * If the user has been forced and the forced group starts with a '+',
617 * then we only set the group to be the forced group if the forced
618 * user is a member of that group. Otherwise, the meaning of the '+'
622 if (force_user && user_must_be_member) {
623 if (user_in_group_sid(username, &group_sid)) {
624 sid_copy(pgroup_sid, &group_sid);
626 DEBUG(3,("Forced group %s for member %s\n",
627 groupname, username));
629 DEBUG(0,("find_forced_group: forced user %s is not a member "
630 "of forced group %s. Disallowing access.\n",
631 username, groupname ));
632 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
636 sid_copy(pgroup_sid, &group_sid);
638 DEBUG(3,("Forced group %s\n", groupname));
641 result = NT_STATUS_OK;
643 TALLOC_FREE(mem_ctx);
647 /****************************************************************************
648 Make a connection, given the snum to connect to, and the vuser of the
649 connecting user if appropriate.
650 ****************************************************************************/
652 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
657 struct passwd *pass = NULL;
659 connection_struct *conn;
664 char addr[INET6_ADDRSTRLEN];
665 bool on_err_call_dis_hook = false;
669 SET_STAT_INVALID(st);
671 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
677 DEBUG(0,("Couldn't find free connection.\n"));
678 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
682 conn->params->service = snum;
683 conn->nt_user_token = NULL;
685 if (lp_guest_only(snum)) {
686 const char *guestname = lp_guestaccount();
688 char *found_username = NULL;
691 pass = getpwnam_alloc(NULL, guestname);
693 DEBUG(0,("make_connection_snum: Invalid guest "
694 "account %s??\n",guestname));
696 *status = NT_STATUS_NO_SUCH_USER;
699 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
700 &conn->uid, &conn->gid,
702 &conn->nt_user_token);
703 if (!NT_STATUS_IS_OK(status2)) {
709 fstrcpy(user, found_username);
710 string_set(&conn->user,user);
711 conn->force_user = True;
712 TALLOC_FREE(found_username);
714 DEBUG(3,("Guest only user %s\n",user));
717 if (!lp_guest_ok(snum)) {
718 DEBUG(2, ("guest user (from session setup) "
719 "not permitted to access this share "
720 "(%s)\n", lp_servicename(snum)));
722 *status = NT_STATUS_ACCESS_DENIED;
726 if (!user_ok_token(vuser->user.unix_name,
727 vuser->nt_user_token, snum)) {
728 DEBUG(2, ("user '%s' (from session setup) not "
729 "permitted to access this share "
730 "(%s)\n", vuser->user.unix_name,
731 lp_servicename(snum)));
733 *status = NT_STATUS_ACCESS_DENIED;
737 conn->vuid = vuser->vuid;
738 conn->uid = vuser->uid;
739 conn->gid = vuser->gid;
740 string_set(&conn->user,vuser->user.unix_name);
741 fstrcpy(user,vuser->user.unix_name);
742 guest = vuser->guest;
743 } else if (lp_security() == SEC_SHARE) {
745 char *found_username = NULL;
747 /* add it as a possible user name if we
748 are in share mode security */
749 add_session_user(lp_servicename(snum));
750 /* shall we let them in? */
751 if (!authorise_login(snum,user,password,&guest)) {
752 DEBUG( 2, ( "Invalid username/password for [%s]\n",
753 lp_servicename(snum)) );
755 *status = NT_STATUS_WRONG_PASSWORD;
758 pass = Get_Pwnam_alloc(talloc_tos(), user);
759 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
760 &conn->uid, &conn->gid,
762 &conn->nt_user_token);
764 if (!NT_STATUS_IS_OK(status2)) {
769 fstrcpy(user, found_username);
770 string_set(&conn->user,user);
771 TALLOC_FREE(found_username);
772 conn->force_user = True;
774 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
776 *status = NT_STATUS_ACCESS_DENIED;
780 add_session_user(user);
782 safe_strcpy(conn->client_address,
783 client_addr(get_client_fd(),addr,sizeof(addr)),
784 sizeof(conn->client_address)-1);
785 conn->num_files_open = 0;
786 conn->lastused = conn->lastused_count = time(NULL);
788 conn->printer = (strncmp(dev,"LPT",3) == 0);
789 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
790 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
793 /* Case options for the share. */
794 if (lp_casesensitive(snum) == Auto) {
795 /* We will be setting this per packet. Set to be case
796 * insensitive for now. */
797 conn->case_sensitive = False;
799 conn->case_sensitive = (bool)lp_casesensitive(snum);
802 conn->case_preserve = lp_preservecase(snum);
803 conn->short_case_preserve = lp_shortpreservecase(snum);
805 conn->encrypt_level = lp_smb_encrypt(snum);
807 conn->veto_list = NULL;
808 conn->hide_list = NULL;
809 conn->veto_oplock_list = NULL;
810 conn->aio_write_behind_list = NULL;
811 string_set(&conn->dirpath,"");
812 string_set(&conn->user,user);
814 conn->read_only = lp_readonly(SNUM(conn));
815 conn->admin_user = False;
818 * If force user is true, then store the given userid and the gid of
819 * the user we're forcing.
820 * For auxiliary groups see below.
823 if (*lp_force_user(snum)) {
826 status2 = find_forced_user(conn,
827 (vuser != NULL) && vuser->guest,
829 if (!NT_STATUS_IS_OK(status2)) {
834 string_set(&conn->user,user);
835 conn->force_user = True;
836 DEBUG(3,("Forced user %s\n",user));
840 * If force group is true, then override
841 * any groupid stored for the connecting user.
844 if (*lp_force_group(snum)) {
848 status2 = find_forced_group(conn->force_user,
850 &group_sid, &conn->gid);
851 if (!NT_STATUS_IS_OK(status2)) {
857 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
859 /* Not force user and not security=share, but force
860 * group. vuser has a token to copy */
862 conn->nt_user_token = dup_nt_token(
863 NULL, vuser->nt_user_token);
864 if (conn->nt_user_token == NULL) {
865 DEBUG(0, ("dup_nt_token failed\n"));
867 *status = NT_STATUS_NO_MEMORY;
872 /* If conn->nt_user_token is still NULL, we have
873 * security=share. This means ignore the SID, as we had no
874 * vuser to copy from */
876 if (conn->nt_user_token != NULL) {
877 /* Overwrite the primary group sid */
878 sid_copy(&conn->nt_user_token->user_sids[1],
882 conn->force_group = True;
885 if (conn->nt_user_token != NULL) {
888 /* We have a share-specific token from force [user|group].
889 * This means we have to create the list of unix groups from
890 * the list of sids. */
895 for (i=0; i<conn->nt_user_token->num_sids; i++) {
897 DOM_SID *sid = &conn->nt_user_token->user_sids[i];
899 if (!sid_to_gid(sid, &gid)) {
900 DEBUG(10, ("Could not convert SID %s to gid, "
902 sid_string_dbg(sid)));
905 if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
907 DEBUG(0, ("add_gid_to_array_unique failed\n"));
909 *status = NT_STATUS_NO_MEMORY;
916 char *s = talloc_sub_advanced(talloc_tos(),
917 lp_servicename(SNUM(conn)), conn->user,
918 conn->connectpath, conn->gid,
919 get_current_username(),
920 current_user_info.domain,
924 *status = NT_STATUS_NO_MEMORY;
928 if (!set_conn_connectpath(conn,s)) {
931 *status = NT_STATUS_NO_MEMORY;
934 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
935 lp_servicename(snum)));
940 * New code to check if there's a share security descripter
941 * added from NT server manager. This is done after the
942 * smb.conf checks are done as we need a uid and token. JRA.
947 bool can_write = False;
948 NT_USER_TOKEN *token = conn->nt_user_token ?
949 conn->nt_user_token :
950 (vuser ? vuser->nt_user_token : NULL);
953 * I don't believe this can happen. But the
954 * logic above is convoluted enough to confuse
955 * automated checkers, so be sure. JRA.
959 DEBUG(0,("make_connection: connection to %s "
960 "denied due to missing "
962 lp_servicename(snum)));
964 *status = NT_STATUS_ACCESS_DENIED;
968 can_write = share_access_check(token,
969 lp_servicename(snum),
973 if (!share_access_check(token,
974 lp_servicename(snum),
976 /* No access, read or write. */
977 DEBUG(0,("make_connection: connection to %s "
978 "denied due to security "
980 lp_servicename(snum)));
982 *status = NT_STATUS_ACCESS_DENIED;
985 conn->read_only = True;
989 /* Initialise VFS function pointers */
991 if (!smbd_vfs_init(conn)) {
992 DEBUG(0, ("vfs_init failed for service %s\n",
993 lp_servicename(snum)));
995 *status = NT_STATUS_BAD_NETWORK_NAME;
1000 * If widelinks are disallowed we need to canonicalise the connect
1001 * path here to ensure we don't have any symlinks in the
1002 * connectpath. We will be checking all paths on this connection are
1003 * below this directory. We must do this after the VFS init as we
1004 * depend on the realpath() pointer in the vfs table. JRA.
1006 if (!lp_widelinks(snum)) {
1007 if (!canonicalize_connect_path(conn)) {
1008 DEBUG(0, ("canonicalize_connect_path failed "
1009 "for service %s, path %s\n",
1010 lp_servicename(snum),
1011 conn->connectpath));
1013 *status = NT_STATUS_BAD_NETWORK_NAME;
1018 if ((!conn->printer) && (!conn->ipc)) {
1019 conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
1020 smbd_messaging_context(),
1021 smbd_event_context(),
1025 /* ROOT Activities: */
1027 * Enforce the max connections parameter.
1030 if ((lp_max_connections(snum) > 0)
1031 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
1032 lp_max_connections(snum))) {
1034 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
1035 lp_max_connections(snum), lp_servicename(snum)));
1037 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
1042 * Get us an entry in the connections db
1044 if (!claim_connection(conn, lp_servicename(snum), 0)) {
1045 DEBUG(1, ("Could not store connections entry\n"));
1047 *status = NT_STATUS_INTERNAL_DB_ERROR;
1051 /* Preexecs are done here as they might make the dir we are to ChDir
1053 /* execute any "root preexec = " line */
1054 if (*lp_rootpreexec(snum)) {
1055 char *cmd = talloc_sub_advanced(talloc_tos(),
1056 lp_servicename(SNUM(conn)), conn->user,
1057 conn->connectpath, conn->gid,
1058 get_current_username(),
1059 current_user_info.domain,
1060 lp_rootpreexec(snum));
1061 DEBUG(5,("cmd=%s\n",cmd));
1062 ret = smbrun(cmd,NULL);
1064 if (ret != 0 && lp_rootpreexec_close(snum)) {
1065 DEBUG(1,("root preexec gave %d - failing "
1066 "connection\n", ret));
1067 yield_connection(conn, lp_servicename(snum));
1069 *status = NT_STATUS_ACCESS_DENIED;
1074 /* USER Activites: */
1075 if (!change_to_user(conn, conn->vuid)) {
1076 /* No point continuing if they fail the basic checks */
1077 DEBUG(0,("Can't become connected user!\n"));
1078 yield_connection(conn, lp_servicename(snum));
1080 *status = NT_STATUS_LOGON_FAILURE;
1084 /* Remember that a different vuid can connect later without these
1087 /* Preexecs are done here as they might make the dir we are to ChDir
1090 /* execute any "preexec = " line */
1091 if (*lp_preexec(snum)) {
1092 char *cmd = talloc_sub_advanced(talloc_tos(),
1093 lp_servicename(SNUM(conn)), conn->user,
1094 conn->connectpath, conn->gid,
1095 get_current_username(),
1096 current_user_info.domain,
1098 ret = smbrun(cmd,NULL);
1100 if (ret != 0 && lp_preexec_close(snum)) {
1101 DEBUG(1,("preexec gave %d - failing connection\n",
1103 *status = NT_STATUS_ACCESS_DENIED;
1108 #ifdef WITH_FAKE_KASERVER
1109 if (lp_afs_share(snum)) {
1114 /* Add veto/hide lists */
1115 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1116 set_namearray( &conn->veto_list, lp_veto_files(snum));
1117 set_namearray( &conn->hide_list, lp_hide_files(snum));
1118 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1121 /* Invoke VFS make connection hook - do this before the VFS_STAT call
1122 to allow any filesystems needing user credentials to initialize
1125 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
1126 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1127 *status = NT_STATUS_UNSUCCESSFUL;
1131 /* Any error exit after here needs to call the disconnect hook. */
1132 on_err_call_dis_hook = true;
1134 /* win2000 does not check the permissions on the directory
1135 during the tree connect, instead relying on permission
1136 check during individual operations. To match this behaviour
1137 I have disabled this chdir check (tridge) */
1138 /* the alternative is just to check the directory exists */
1139 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1140 !S_ISDIR(st.st_mode)) {
1141 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1142 DEBUG(0,("'%s' is not a directory, when connecting to "
1143 "[%s]\n", conn->connectpath,
1144 lp_servicename(snum)));
1146 DEBUG(0,("'%s' does not exist or permission denied "
1147 "when connecting to [%s] Error was %s\n",
1148 conn->connectpath, lp_servicename(snum),
1151 *status = NT_STATUS_BAD_NETWORK_NAME;
1155 string_set(&conn->origpath,conn->connectpath);
1157 #if SOFTLINK_OPTIMISATION
1158 /* resolve any soft links early if possible */
1159 if (vfs_ChDir(conn,conn->connectpath) == 0) {
1160 TALLOC_CTX *ctx = talloc_tos();
1161 char *s = vfs_GetWd(ctx,s);
1163 *status = map_nt_error_from_unix(errno);
1166 if (!set_conn_connectpath(conn,s)) {
1167 *status = NT_STATUS_NO_MEMORY;
1170 vfs_ChDir(conn,conn->connectpath);
1174 /* Figure out the characteristics of the underlying filesystem. This
1175 * assumes that all the filesystem mounted withing a share path have
1176 * the same characteristics, which is likely but not guaranteed.
1179 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
1182 * Print out the 'connected as' stuff here as we need
1183 * to know the effective uid and gid we will be using
1184 * (at least initially).
1187 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1188 dbgtext( "%s (%s) ", get_remote_machine_name(),
1189 conn->client_address );
1190 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1191 dbgtext( "connect to service %s ", lp_servicename(snum) );
1192 dbgtext( "initially as user %s ", user );
1193 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1194 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1197 /* we've finished with the user stuff - go back to root */
1198 change_to_root_user();
1203 change_to_root_user();
1204 if (on_err_call_dis_hook) {
1205 /* Call VFS disconnect hook */
1206 SMB_VFS_DISCONNECT(conn);
1208 yield_connection(conn, lp_servicename(snum));
1213 /***************************************************************************************
1214 Simple wrapper function for make_connection() to include a call to
1216 **************************************************************************************/
1218 connection_struct *make_connection_with_chdir(const char *service_in,
1220 const char *dev, uint16 vuid,
1223 connection_struct *conn = NULL;
1225 conn = make_connection(service_in, password, dev, vuid, status);
1228 * make_connection() does not change the directory for us any more
1229 * so we have to do it as a separate step --jerry
1232 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1233 DEBUG(0,("move_driver_to_download_area: Can't change "
1234 "directory to %s for [print$] (%s)\n",
1235 conn->connectpath,strerror(errno)));
1236 yield_connection(conn, lp_servicename(SNUM(conn)));
1238 *status = NT_STATUS_UNSUCCESSFUL;
1245 /****************************************************************************
1246 Make a connection to a service.
1249 ****************************************************************************/
1251 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
1252 const char *pdev, uint16 vuid,
1256 user_struct *vuser = NULL;
1260 char addr[INET6_ADDRSTRLEN];
1264 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1266 if (!non_root_mode() && (euid = geteuid()) != 0) {
1267 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1268 "(%u)\n", (unsigned int)euid ));
1269 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1272 if (conn_num_open() > 2047) {
1273 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1277 if(lp_security() != SEC_SHARE) {
1278 vuser = get_valid_user_struct(vuid);
1280 DEBUG(1,("make_connection: refusing to connect with "
1281 "no session setup\n"));
1282 *status = NT_STATUS_ACCESS_DENIED;
1287 /* Logic to try and connect to the correct [homes] share, preferably
1288 without too many getpwnam() lookups. This is particulary nasty for
1289 winbind usernames, where the share name isn't the same as unix
1292 The snum of the homes share is stored on the vuser at session setup
1296 if (strequal(service_in,HOMES_NAME)) {
1297 if(lp_security() != SEC_SHARE) {
1298 DATA_BLOB no_pw = data_blob_null;
1299 if (vuser->homes_snum == -1) {
1300 DEBUG(2, ("[homes] share not available for "
1301 "this user because it was not found "
1302 "or created at session setup "
1304 *status = NT_STATUS_BAD_NETWORK_NAME;
1307 DEBUG(5, ("making a connection to [homes] service "
1308 "created at session setup time\n"));
1309 return make_connection_snum(vuser->homes_snum,
1313 /* Security = share. Try with
1314 * current_user_info.smb_name as the username. */
1315 if (*current_user_info.smb_name) {
1316 fstring unix_username;
1317 fstrcpy(unix_username,
1318 current_user_info.smb_name);
1319 map_username(unix_username);
1320 snum = find_service(unix_username);
1323 DEBUG(5, ("making a connection to 'homes' "
1324 "service %s based on "
1325 "security=share\n", service_in));
1326 return make_connection_snum(snum, NULL,
1331 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1332 && strequal(service_in,
1333 lp_servicename(vuser->homes_snum))) {
1334 DATA_BLOB no_pw = data_blob_null;
1335 DEBUG(5, ("making a connection to 'homes' service [%s] "
1336 "created at session setup time\n", service_in));
1337 return make_connection_snum(vuser->homes_snum,
1342 fstrcpy(service, service_in);
1344 strlower_m(service);
1346 snum = find_service(service);
1349 if (strequal(service,"IPC$") ||
1350 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1351 DEBUG(3,("refusing IPC connection to %s\n", service));
1352 *status = NT_STATUS_ACCESS_DENIED;
1356 DEBUG(0,("%s (%s) couldn't find service %s\n",
1357 get_remote_machine_name(),
1358 client_addr(get_client_fd(),addr,sizeof(addr)),
1360 *status = NT_STATUS_BAD_NETWORK_NAME;
1364 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1365 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1366 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1367 "(pointing to %s)\n",
1368 service, lp_msdfs_proxy(snum)));
1369 *status = NT_STATUS_BAD_NETWORK_NAME;
1373 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1375 return make_connection_snum(snum, vuser,
1380 /****************************************************************************
1382 ****************************************************************************/
1384 void close_cnum(connection_struct *conn, uint16 vuid)
1387 pipe_close_conn(conn);
1389 file_close_conn(conn);
1390 dptr_closecnum(conn);
1393 change_to_root_user();
1395 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1396 get_remote_machine_name(),
1397 conn->client_address,
1398 lp_servicename(SNUM(conn))));
1400 /* Call VFS disconnect hook */
1401 SMB_VFS_DISCONNECT(conn);
1403 yield_connection(conn, lp_servicename(SNUM(conn)));
1405 /* make sure we leave the directory available for unmount */
1406 vfs_ChDir(conn, "/");
1408 /* execute any "postexec = " line */
1409 if (*lp_postexec(SNUM(conn)) &&
1410 change_to_user(conn, vuid)) {
1411 char *cmd = talloc_sub_advanced(talloc_tos(),
1412 lp_servicename(SNUM(conn)), conn->user,
1413 conn->connectpath, conn->gid,
1414 get_current_username(),
1415 current_user_info.domain,
1416 lp_postexec(SNUM(conn)));
1419 change_to_root_user();
1422 change_to_root_user();
1423 /* execute any "root postexec = " line */
1424 if (*lp_rootpostexec(SNUM(conn))) {
1425 char *cmd = talloc_sub_advanced(talloc_tos(),
1426 lp_servicename(SNUM(conn)), conn->user,
1427 conn->connectpath, conn->gid,
1428 get_current_username(),
1429 current_user_info.domain,
1430 lp_rootpostexec(SNUM(conn)));