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(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
187 conn->connectpath, strerror(errno)));
191 if ((conn == last_conn) && (last_flags == flags)) {
198 /* Obey the client case sensitivity requests - only for clients that support it. */
199 switch (lp_casesensitive(snum)) {
202 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
203 enum remote_arch_types ra_type = get_remote_arch();
204 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
205 /* Client can't support per-packet case sensitive pathnames. */
206 conn->case_sensitive = False;
208 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
213 conn->case_sensitive = True;
216 conn->case_sensitive = False;
222 static int load_registry_service(const char *servicename)
224 if (!lp_registry_shares()) {
228 if ((servicename == NULL) || (*servicename == '\0')) {
232 if (strequal(servicename, GLOBAL_NAME)) {
236 if (!process_registry_service(servicename)) {
240 return lp_servicenumber(servicename);
243 void load_registry_shares(void)
245 DEBUG(8, ("load_registry_shares()\n"));
246 if (!lp_registry_shares()) {
250 process_registry_shares();
255 /****************************************************************************
256 Add a home service. Returns the new service number or -1 if fail.
257 ****************************************************************************/
259 int add_home_service(const char *service, const char *username, const char *homedir)
263 if (!service || !homedir)
266 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
267 if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
273 * If this is a winbindd provided username, remove
274 * the domain component before adding the service.
275 * Log a warning if the "path=" parameter does not
276 * include any macros.
280 const char *p = strchr(service,*lp_winbind_separator());
282 /* We only want the 'user' part of the string */
288 if (!lp_add_home(service, iHomeService, username, homedir)) {
292 return lp_servicenumber(service);
297 * Find a service entry.
299 * @param service is modified (to canonical form??)
302 int find_service(fstring service)
306 all_string_sub(service,"\\","/",0);
308 iService = lp_servicenumber(service);
310 /* now handle the special case of a home directory */
312 char *phome_dir = get_user_home_dir(talloc_tos(), service);
316 * Try mapping the servicename, it may
317 * be a Windows to unix mapped user name.
319 if(map_username(service))
320 phome_dir = get_user_home_dir(
321 talloc_tos(), service);
324 DEBUG(3,("checking for home directory %s gave %s\n",service,
325 phome_dir?phome_dir:"(NULL)"));
327 iService = add_home_service(service,service /* 'username' */, phome_dir);
330 /* If we still don't have a service, attempt to add it as a printer. */
334 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
335 iPrinterService = load_registry_service(PRINTERS_NAME);
337 if (iPrinterService) {
338 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
339 if (pcap_printername_ok(service)) {
340 DEBUG(3,("%s is a valid printer name\n", service));
341 DEBUG(3,("adding %s as a printer service\n", service));
342 lp_add_printer(service, iPrinterService);
343 iService = lp_servicenumber(service);
345 DEBUG(0,("failed to add %s as a printer service!\n", service));
348 DEBUG(3,("%s is not a valid printer name\n", service));
353 /* Check for default vfs service? Unsure whether to implement this */
358 iService = load_registry_service(service);
361 /* Is it a usershare service ? */
362 if (iService < 0 && *lp_usershare_path()) {
363 /* Ensure the name is canonicalized. */
365 iService = load_usershare_service(service);
368 /* just possibly it's a default service? */
370 char *pdefservice = lp_defaultservice();
371 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
373 * We need to do a local copy here as lp_defaultservice()
374 * returns one of the rotating lp_string buffers that
375 * could get overwritten by the recursive find_service() call
376 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
378 char *defservice = SMB_STRDUP(pdefservice);
384 /* Disallow anything except explicit share names. */
385 if (strequal(defservice,HOMES_NAME) ||
386 strequal(defservice, PRINTERS_NAME) ||
387 strequal(defservice, "IPC$")) {
388 SAFE_FREE(defservice);
392 iService = find_service(defservice);
394 all_string_sub(service, "_","/",0);
395 iService = lp_add_service(service, iService);
397 SAFE_FREE(defservice);
402 if (!VALID_SNUM(iService)) {
403 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
411 DEBUG(3,("find_service() failed to find service %s\n", service));
417 /****************************************************************************
418 do some basic sainity checks on the share.
419 This function modifies dev, ecode.
420 ****************************************************************************/
422 static NTSTATUS share_sanity_checks(int snum, fstring dev)
425 if (!lp_snum_ok(snum) ||
426 !check_access(smbd_server_fd(),
427 lp_hostsallow(snum), lp_hostsdeny(snum))) {
428 return NT_STATUS_ACCESS_DENIED;
431 if (dev[0] == '?' || !dev[0]) {
432 if (lp_print_ok(snum)) {
433 fstrcpy(dev,"LPT1:");
434 } else if (strequal(lp_fstype(snum), "IPC")) {
443 if (lp_print_ok(snum)) {
444 if (!strequal(dev, "LPT1:")) {
445 return NT_STATUS_BAD_DEVICE_TYPE;
447 } else if (strequal(lp_fstype(snum), "IPC")) {
448 if (!strequal(dev, "IPC")) {
449 return NT_STATUS_BAD_DEVICE_TYPE;
451 } else if (!strequal(dev, "A:")) {
452 return NT_STATUS_BAD_DEVICE_TYPE;
455 /* Behave as a printer if we are supposed to */
456 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
457 fstrcpy(dev, "LPT1:");
463 static NTSTATUS find_forced_user(connection_struct *conn, bool vuser_is_guest, fstring username)
465 int snum = conn->params->service;
466 char *fuser, *found_username;
469 if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S",
470 lp_servicename(snum)))) {
471 return NT_STATUS_NO_MEMORY;
474 result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest,
475 &conn->uid, &conn->gid, &found_username,
476 &conn->nt_user_token);
477 if (!NT_STATUS_IS_OK(result)) {
481 fstrcpy(username, found_username);
484 TALLOC_FREE(found_username);
489 * Go through lookup_name etc to find the force'd group.
491 * Create a new token from src_token, replacing the primary group sid with the
495 static NTSTATUS find_forced_group(bool force_user,
496 int snum, const char *username,
500 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
503 enum lsa_SidType type;
505 bool user_must_be_member = False;
508 ZERO_STRUCTP(pgroup_sid);
511 mem_ctx = talloc_new(NULL);
512 if (mem_ctx == NULL) {
513 DEBUG(0, ("talloc_new failed\n"));
514 return NT_STATUS_NO_MEMORY;
517 groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
518 if (groupname == NULL) {
519 DEBUG(1, ("talloc_strdup failed\n"));
520 result = NT_STATUS_NO_MEMORY;
524 if (groupname[0] == '+') {
525 user_must_be_member = True;
529 groupname = talloc_string_sub(mem_ctx, groupname,
530 "%S", lp_servicename(snum));
532 if (!lookup_name_smbconf(mem_ctx, groupname,
533 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
534 NULL, NULL, &group_sid, &type)) {
535 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
540 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
541 (type != SID_NAME_WKN_GRP)) {
542 DEBUG(10, ("%s is a %s, not a group\n", groupname,
543 sid_type_lookup(type)));
547 if (!sid_to_gid(&group_sid, &gid)) {
548 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
549 sid_string_dbg(&group_sid), groupname));
554 * If the user has been forced and the forced group starts with a '+',
555 * then we only set the group to be the forced group if the forced
556 * user is a member of that group. Otherwise, the meaning of the '+'
560 if (force_user && user_must_be_member) {
561 if (user_in_group_sid(username, &group_sid)) {
562 sid_copy(pgroup_sid, &group_sid);
564 DEBUG(3,("Forced group %s for member %s\n",
565 groupname, username));
567 DEBUG(0,("find_forced_group: forced user %s is not a member "
568 "of forced group %s. Disallowing access.\n",
569 username, groupname ));
570 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
574 sid_copy(pgroup_sid, &group_sid);
576 DEBUG(3,("Forced group %s\n", groupname));
579 result = NT_STATUS_OK;
581 TALLOC_FREE(mem_ctx);
585 /****************************************************************************
586 Make a connection, given the snum to connect to, and the vuser of the
587 connecting user if appropriate.
588 ****************************************************************************/
590 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
595 struct passwd *pass = NULL;
597 connection_struct *conn;
602 char addr[INET6_ADDRSTRLEN];
603 bool on_err_call_dis_hook = false;
607 SET_STAT_INVALID(st);
609 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
615 DEBUG(0,("Couldn't find free connection.\n"));
616 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
620 conn->params->service = snum;
621 conn->nt_user_token = NULL;
623 if (lp_guest_only(snum)) {
624 const char *guestname = lp_guestaccount();
626 char *found_username = NULL;
629 pass = getpwnam_alloc(talloc_tos(), guestname);
631 DEBUG(0,("make_connection_snum: Invalid guest "
632 "account %s??\n",guestname));
634 *status = NT_STATUS_NO_SUCH_USER;
637 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
638 &conn->uid, &conn->gid,
640 &conn->nt_user_token);
641 if (!NT_STATUS_IS_OK(status2)) {
647 fstrcpy(user, found_username);
648 string_set(&conn->user,user);
649 conn->force_user = True;
650 TALLOC_FREE(found_username);
652 DEBUG(3,("Guest only user %s\n",user));
655 if (!lp_guest_ok(snum)) {
656 DEBUG(2, ("guest user (from session setup) "
657 "not permitted to access this share "
658 "(%s)\n", lp_servicename(snum)));
660 *status = NT_STATUS_ACCESS_DENIED;
664 if (!user_ok_token(vuser->user.unix_name,
665 vuser->nt_user_token, snum)) {
666 DEBUG(2, ("user '%s' (from session setup) not "
667 "permitted to access this share "
668 "(%s)\n", vuser->user.unix_name,
669 lp_servicename(snum)));
671 *status = NT_STATUS_ACCESS_DENIED;
675 conn->vuid = vuser->vuid;
676 conn->uid = vuser->uid;
677 conn->gid = vuser->gid;
678 string_set(&conn->user,vuser->user.unix_name);
679 fstrcpy(user,vuser->user.unix_name);
680 guest = vuser->guest;
681 } else if (lp_security() == SEC_SHARE) {
683 char *found_username = NULL;
685 /* add it as a possible user name if we
686 are in share mode security */
687 add_session_user(lp_servicename(snum));
688 /* shall we let them in? */
689 if (!authorise_login(snum,user,password,&guest)) {
690 DEBUG( 2, ( "Invalid username/password for [%s]\n",
691 lp_servicename(snum)) );
693 *status = NT_STATUS_WRONG_PASSWORD;
696 pass = Get_Pwnam_alloc(talloc_tos(), user);
697 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
698 &conn->uid, &conn->gid,
700 &conn->nt_user_token);
702 if (!NT_STATUS_IS_OK(status2)) {
707 fstrcpy(user, found_username);
708 string_set(&conn->user,user);
709 TALLOC_FREE(found_username);
710 conn->force_user = True;
712 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
714 *status = NT_STATUS_ACCESS_DENIED;
718 add_session_user(user);
720 safe_strcpy(conn->client_address,
721 client_addr(get_client_fd(),addr,sizeof(addr)),
722 sizeof(conn->client_address)-1);
723 conn->num_files_open = 0;
724 conn->lastused = conn->lastused_count = time(NULL);
726 conn->printer = (strncmp(dev,"LPT",3) == 0);
727 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
728 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
731 /* Case options for the share. */
732 if (lp_casesensitive(snum) == Auto) {
733 /* We will be setting this per packet. Set to be case
734 * insensitive for now. */
735 conn->case_sensitive = False;
737 conn->case_sensitive = (bool)lp_casesensitive(snum);
740 conn->case_preserve = lp_preservecase(snum);
741 conn->short_case_preserve = lp_shortpreservecase(snum);
743 conn->encrypt_level = lp_smb_encrypt(snum);
745 conn->veto_list = NULL;
746 conn->hide_list = NULL;
747 conn->veto_oplock_list = NULL;
748 conn->aio_write_behind_list = NULL;
749 string_set(&conn->dirpath,"");
750 string_set(&conn->user,user);
752 conn->read_only = lp_readonly(SNUM(conn));
753 conn->admin_user = False;
756 * If force user is true, then store the given userid and the gid of
757 * the user we're forcing.
758 * For auxiliary groups see below.
761 if (*lp_force_user(snum)) {
764 status2 = find_forced_user(conn,
765 (vuser != NULL) && vuser->guest,
767 if (!NT_STATUS_IS_OK(status2)) {
772 string_set(&conn->user,user);
773 conn->force_user = True;
774 DEBUG(3,("Forced user %s\n",user));
778 * If force group is true, then override
779 * any groupid stored for the connecting user.
782 if (*lp_force_group(snum)) {
786 status2 = find_forced_group(conn->force_user,
788 &group_sid, &conn->gid);
789 if (!NT_STATUS_IS_OK(status2)) {
795 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
797 /* Not force user and not security=share, but force
798 * group. vuser has a token to copy */
800 conn->nt_user_token = dup_nt_token(
801 NULL, vuser->nt_user_token);
802 if (conn->nt_user_token == NULL) {
803 DEBUG(0, ("dup_nt_token failed\n"));
805 *status = NT_STATUS_NO_MEMORY;
810 /* If conn->nt_user_token is still NULL, we have
811 * security=share. This means ignore the SID, as we had no
812 * vuser to copy from */
814 if (conn->nt_user_token != NULL) {
815 /* Overwrite the primary group sid */
816 sid_copy(&conn->nt_user_token->user_sids[1],
820 conn->force_group = True;
823 if (conn->nt_user_token != NULL) {
826 /* We have a share-specific token from force [user|group].
827 * This means we have to create the list of unix groups from
828 * the list of sids. */
833 for (i=0; i<conn->nt_user_token->num_sids; i++) {
835 DOM_SID *sid = &conn->nt_user_token->user_sids[i];
837 if (!sid_to_gid(sid, &gid)) {
838 DEBUG(10, ("Could not convert SID %s to gid, "
840 sid_string_dbg(sid)));
843 if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
845 DEBUG(0, ("add_gid_to_array_unique failed\n"));
847 *status = NT_STATUS_NO_MEMORY;
854 char *s = talloc_sub_advanced(talloc_tos(),
855 lp_servicename(SNUM(conn)), conn->user,
856 conn->connectpath, conn->gid,
857 get_current_username(),
858 current_user_info.domain,
862 *status = NT_STATUS_NO_MEMORY;
866 if (!set_conn_connectpath(conn,s)) {
869 *status = NT_STATUS_NO_MEMORY;
872 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
873 lp_servicename(snum)));
878 * New code to check if there's a share security descripter
879 * added from NT server manager. This is done after the
880 * smb.conf checks are done as we need a uid and token. JRA.
885 bool can_write = False;
886 NT_USER_TOKEN *token = conn->nt_user_token ?
887 conn->nt_user_token :
888 (vuser ? vuser->nt_user_token : NULL);
891 * I don't believe this can happen. But the
892 * logic above is convoluted enough to confuse
893 * automated checkers, so be sure. JRA.
897 DEBUG(0,("make_connection: connection to %s "
898 "denied due to missing "
900 lp_servicename(snum)));
902 *status = NT_STATUS_ACCESS_DENIED;
906 can_write = share_access_check(token,
907 lp_servicename(snum),
911 if (!share_access_check(token,
912 lp_servicename(snum),
914 /* No access, read or write. */
915 DEBUG(0,("make_connection: connection to %s "
916 "denied due to security "
918 lp_servicename(snum)));
920 *status = NT_STATUS_ACCESS_DENIED;
923 conn->read_only = True;
927 /* Initialise VFS function pointers */
929 if (!smbd_vfs_init(conn)) {
930 DEBUG(0, ("vfs_init failed for service %s\n",
931 lp_servicename(snum)));
933 *status = NT_STATUS_BAD_NETWORK_NAME;
938 * If widelinks are disallowed we need to canonicalise the connect
939 * path here to ensure we don't have any symlinks in the
940 * connectpath. We will be checking all paths on this connection are
941 * below this directory. We must do this after the VFS init as we
942 * depend on the realpath() pointer in the vfs table. JRA.
944 if (!lp_widelinks(snum)) {
945 if (!canonicalize_connect_path(conn)) {
946 DEBUG(0, ("canonicalize_connect_path failed "
947 "for service %s, path %s\n",
948 lp_servicename(snum),
951 *status = NT_STATUS_BAD_NETWORK_NAME;
956 if ((!conn->printer) && (!conn->ipc)) {
957 conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
958 smbd_messaging_context(),
959 smbd_event_context(),
963 /* ROOT Activities: */
965 * Enforce the max connections parameter.
968 if ((lp_max_connections(snum) > 0)
969 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
970 lp_max_connections(snum))) {
972 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
973 lp_max_connections(snum), lp_servicename(snum)));
975 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
980 * Get us an entry in the connections db
982 if (!claim_connection(conn, lp_servicename(snum), 0)) {
983 DEBUG(1, ("Could not store connections entry\n"));
985 *status = NT_STATUS_INTERNAL_DB_ERROR;
989 /* Preexecs are done here as they might make the dir we are to ChDir
991 /* execute any "root preexec = " line */
992 if (*lp_rootpreexec(snum)) {
993 char *cmd = talloc_sub_advanced(talloc_tos(),
994 lp_servicename(SNUM(conn)), conn->user,
995 conn->connectpath, conn->gid,
996 get_current_username(),
997 current_user_info.domain,
998 lp_rootpreexec(snum));
999 DEBUG(5,("cmd=%s\n",cmd));
1000 ret = smbrun(cmd,NULL);
1002 if (ret != 0 && lp_rootpreexec_close(snum)) {
1003 DEBUG(1,("root preexec gave %d - failing "
1004 "connection\n", ret));
1005 yield_connection(conn, lp_servicename(snum));
1007 *status = NT_STATUS_ACCESS_DENIED;
1012 /* USER Activites: */
1013 if (!change_to_user(conn, conn->vuid)) {
1014 /* No point continuing if they fail the basic checks */
1015 DEBUG(0,("Can't become connected user!\n"));
1016 yield_connection(conn, lp_servicename(snum));
1018 *status = NT_STATUS_LOGON_FAILURE;
1022 /* Remember that a different vuid can connect later without these
1025 /* Preexecs are done here as they might make the dir we are to ChDir
1028 /* execute any "preexec = " line */
1029 if (*lp_preexec(snum)) {
1030 char *cmd = talloc_sub_advanced(talloc_tos(),
1031 lp_servicename(SNUM(conn)), conn->user,
1032 conn->connectpath, conn->gid,
1033 get_current_username(),
1034 current_user_info.domain,
1036 ret = smbrun(cmd,NULL);
1038 if (ret != 0 && lp_preexec_close(snum)) {
1039 DEBUG(1,("preexec gave %d - failing connection\n",
1041 *status = NT_STATUS_ACCESS_DENIED;
1046 #ifdef WITH_FAKE_KASERVER
1047 if (lp_afs_share(snum)) {
1052 /* Add veto/hide lists */
1053 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1054 set_namearray( &conn->veto_list, lp_veto_files(snum));
1055 set_namearray( &conn->hide_list, lp_hide_files(snum));
1056 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1057 set_namearray( &conn->aio_write_behind_list,
1058 lp_aio_write_behind(snum));
1061 /* Invoke VFS make connection hook - do this before the VFS_STAT call
1062 to allow any filesystems needing user credentials to initialize
1065 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
1066 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1067 *status = NT_STATUS_UNSUCCESSFUL;
1071 /* Any error exit after here needs to call the disconnect hook. */
1072 on_err_call_dis_hook = true;
1074 /* win2000 does not check the permissions on the directory
1075 during the tree connect, instead relying on permission
1076 check during individual operations. To match this behaviour
1077 I have disabled this chdir check (tridge) */
1078 /* the alternative is just to check the directory exists */
1079 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1080 !S_ISDIR(st.st_mode)) {
1081 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1082 DEBUG(0,("'%s' is not a directory, when connecting to "
1083 "[%s]\n", conn->connectpath,
1084 lp_servicename(snum)));
1086 DEBUG(0,("'%s' does not exist or permission denied "
1087 "when connecting to [%s] Error was %s\n",
1088 conn->connectpath, lp_servicename(snum),
1091 *status = NT_STATUS_BAD_NETWORK_NAME;
1095 string_set(&conn->origpath,conn->connectpath);
1097 #if SOFTLINK_OPTIMISATION
1098 /* resolve any soft links early if possible */
1099 if (vfs_ChDir(conn,conn->connectpath) == 0) {
1100 TALLOC_CTX *ctx = talloc_tos();
1101 char *s = vfs_GetWd(ctx,s);
1103 *status = map_nt_error_from_unix(errno);
1106 if (!set_conn_connectpath(conn,s)) {
1107 *status = NT_STATUS_NO_MEMORY;
1110 vfs_ChDir(conn,conn->connectpath);
1114 /* Figure out the characteristics of the underlying filesystem. This
1115 * assumes that all the filesystem mounted withing a share path have
1116 * the same characteristics, which is likely but not guaranteed.
1119 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
1122 * Print out the 'connected as' stuff here as we need
1123 * to know the effective uid and gid we will be using
1124 * (at least initially).
1127 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1128 dbgtext( "%s (%s) ", get_remote_machine_name(),
1129 conn->client_address );
1130 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1131 dbgtext( "connect to service %s ", lp_servicename(snum) );
1132 dbgtext( "initially as user %s ", user );
1133 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1134 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1137 /* we've finished with the user stuff - go back to root */
1138 change_to_root_user();
1143 change_to_root_user();
1144 if (on_err_call_dis_hook) {
1145 /* Call VFS disconnect hook */
1146 SMB_VFS_DISCONNECT(conn);
1148 yield_connection(conn, lp_servicename(snum));
1153 /***************************************************************************************
1154 Simple wrapper function for make_connection() to include a call to
1156 **************************************************************************************/
1158 connection_struct *make_connection_with_chdir(const char *service_in,
1160 const char *dev, uint16 vuid,
1163 connection_struct *conn = NULL;
1165 conn = make_connection(service_in, password, dev, vuid, status);
1168 * make_connection() does not change the directory for us any more
1169 * so we have to do it as a separate step --jerry
1172 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1173 DEBUG(0,("move_driver_to_download_area: Can't change "
1174 "directory to %s for [print$] (%s)\n",
1175 conn->connectpath,strerror(errno)));
1176 yield_connection(conn, lp_servicename(SNUM(conn)));
1178 *status = NT_STATUS_UNSUCCESSFUL;
1185 /****************************************************************************
1186 Make a connection to a service.
1189 ****************************************************************************/
1191 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
1192 const char *pdev, uint16 vuid,
1196 user_struct *vuser = NULL;
1200 char addr[INET6_ADDRSTRLEN];
1204 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1206 if (!non_root_mode() && (euid = geteuid()) != 0) {
1207 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1208 "(%u)\n", (unsigned int)euid ));
1209 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1212 if (conn_num_open() > 2047) {
1213 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1217 if(lp_security() != SEC_SHARE) {
1218 vuser = get_valid_user_struct(vuid);
1220 DEBUG(1,("make_connection: refusing to connect with "
1221 "no session setup\n"));
1222 *status = NT_STATUS_ACCESS_DENIED;
1227 /* Logic to try and connect to the correct [homes] share, preferably
1228 without too many getpwnam() lookups. This is particulary nasty for
1229 winbind usernames, where the share name isn't the same as unix
1232 The snum of the homes share is stored on the vuser at session setup
1236 if (strequal(service_in,HOMES_NAME)) {
1237 if(lp_security() != SEC_SHARE) {
1238 DATA_BLOB no_pw = data_blob_null;
1239 if (vuser->homes_snum == -1) {
1240 DEBUG(2, ("[homes] share not available for "
1241 "this user because it was not found "
1242 "or created at session setup "
1244 *status = NT_STATUS_BAD_NETWORK_NAME;
1247 DEBUG(5, ("making a connection to [homes] service "
1248 "created at session setup time\n"));
1249 return make_connection_snum(vuser->homes_snum,
1253 /* Security = share. Try with
1254 * current_user_info.smb_name as the username. */
1255 if (*current_user_info.smb_name) {
1256 fstring unix_username;
1257 fstrcpy(unix_username,
1258 current_user_info.smb_name);
1259 map_username(unix_username);
1260 snum = find_service(unix_username);
1263 DEBUG(5, ("making a connection to 'homes' "
1264 "service %s based on "
1265 "security=share\n", service_in));
1266 return make_connection_snum(snum, NULL,
1271 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1272 && strequal(service_in,
1273 lp_servicename(vuser->homes_snum))) {
1274 DATA_BLOB no_pw = data_blob_null;
1275 DEBUG(5, ("making a connection to 'homes' service [%s] "
1276 "created at session setup time\n", service_in));
1277 return make_connection_snum(vuser->homes_snum,
1282 fstrcpy(service, service_in);
1284 strlower_m(service);
1286 snum = find_service(service);
1289 if (strequal(service,"IPC$") ||
1290 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1291 DEBUG(3,("refusing IPC connection to %s\n", service));
1292 *status = NT_STATUS_ACCESS_DENIED;
1296 DEBUG(3,("%s (%s) couldn't find service %s\n",
1297 get_remote_machine_name(),
1298 client_addr(get_client_fd(),addr,sizeof(addr)),
1300 *status = NT_STATUS_BAD_NETWORK_NAME;
1304 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1305 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1306 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1307 "(pointing to %s)\n",
1308 service, lp_msdfs_proxy(snum)));
1309 *status = NT_STATUS_BAD_NETWORK_NAME;
1313 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1315 return make_connection_snum(snum, vuser,
1320 /****************************************************************************
1322 ****************************************************************************/
1324 void close_cnum(connection_struct *conn, uint16 vuid)
1327 pipe_close_conn(conn);
1329 file_close_conn(conn);
1330 dptr_closecnum(conn);
1333 change_to_root_user();
1335 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1336 get_remote_machine_name(),
1337 conn->client_address,
1338 lp_servicename(SNUM(conn))));
1340 /* Call VFS disconnect hook */
1341 SMB_VFS_DISCONNECT(conn);
1343 yield_connection(conn, lp_servicename(SNUM(conn)));
1345 /* make sure we leave the directory available for unmount */
1346 vfs_ChDir(conn, "/");
1348 /* execute any "postexec = " line */
1349 if (*lp_postexec(SNUM(conn)) &&
1350 change_to_user(conn, vuid)) {
1351 char *cmd = talloc_sub_advanced(talloc_tos(),
1352 lp_servicename(SNUM(conn)), conn->user,
1353 conn->connectpath, conn->gid,
1354 get_current_username(),
1355 current_user_info.domain,
1356 lp_postexec(SNUM(conn)));
1359 change_to_root_user();
1362 change_to_root_user();
1363 /* execute any "root postexec = " line */
1364 if (*lp_rootpostexec(SNUM(conn))) {
1365 char *cmd = talloc_sub_advanced(talloc_tos(),
1366 lp_servicename(SNUM(conn)), conn->user,
1367 conn->connectpath, conn->gid,
1368 get_current_username(),
1369 current_user_info.domain,
1370 lp_rootpostexec(SNUM(conn)));