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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 extern userdom_struct current_user_info;
25 static BOOL canonicalize_path(connection_struct *conn, pstring path)
27 #ifdef REALPATH_TAKES_NULL
28 char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL);
32 pstrcpy(path, resolved_name);
33 SAFE_FREE(resolved_name);
37 char resolved_name_buf[PATH_MAX+1];
39 pstring resolved_name_buf;
41 char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf);
45 pstrcpy(path, resolved_name);
47 #endif /* REALPATH_TAKES_NULL */
50 /****************************************************************************
51 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
52 absolute path stating in / and not ending in /.
53 Observent people will notice a similarity between this and check_path_syntax :-).
54 ****************************************************************************/
56 void set_conn_connectpath(connection_struct *conn, const pstring connectpath)
60 const char *s = connectpath;
61 BOOL start_of_name_component = True;
63 *d++ = '/'; /* Always start with root. */
67 /* Eat multiple '/' */
71 if ((d > destname + 1) && (*s != '\0')) {
74 start_of_name_component = True;
78 if (start_of_name_component) {
79 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
80 /* Uh oh - "/../" or "/..\0" ! */
82 /* Go past the ../ or .. */
86 s += 2; /* Go past the .. */
89 /* If we just added a '/' - delete it */
90 if ((d > destname) && (*(d-1) == '/')) {
95 /* Are we at the start ? Can't go back further if so. */
97 *d++ = '/'; /* Can't delete root */
100 /* Go back one level... */
101 /* Decrement d first as d points to the *next* char to write into. */
102 for (d--; d > destname; d--) {
107 /* We're still at the start of a name component, just the previous one. */
109 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
110 /* Component of pathname can't be "." only - skip the '.' . */
124 /* Get the size of the next MB character. */
125 next_codepoint(s,&siz);
146 start_of_name_component = False;
150 /* And must not end in '/' */
151 if (d > destname + 1 && (*(d-1) == '/')) {
155 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
156 lp_servicename(SNUM(conn)), destname ));
158 string_set(&conn->connectpath, destname);
161 /****************************************************************************
162 Load parameters specific to a connection/service.
163 ****************************************************************************/
165 BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir)
167 static connection_struct *last_conn;
168 static uint16 last_flags;
176 conn->lastused_count++;
181 vfs_ChDir(conn,conn->connectpath) != 0 &&
182 vfs_ChDir(conn,conn->origpath) != 0) {
183 DEBUG(0,("chdir (%s) failed\n",
188 if ((conn == last_conn) && (last_flags == flags)) {
195 /* Obey the client case sensitivity requests - only for clients that support it. */
196 switch (lp_casesensitive(snum)) {
199 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
200 enum remote_arch_types ra_type = get_remote_arch();
201 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
202 /* Client can't support per-packet case sensitive pathnames. */
203 conn->case_sensitive = False;
205 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
210 conn->case_sensitive = True;
213 conn->case_sensitive = False;
219 /****************************************************************************
220 Add a home service. Returns the new service number or -1 if fail.
221 ****************************************************************************/
223 int add_home_service(const char *service, const char *username, const char *homedir)
227 if (!service || !homedir)
230 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
234 * If this is a winbindd provided username, remove
235 * the domain component before adding the service.
236 * Log a warning if the "path=" parameter does not
237 * include any macros.
241 const char *p = strchr(service,*lp_winbind_separator());
243 /* We only want the 'user' part of the string */
249 if (!lp_add_home(service, iHomeService, username, homedir)) {
253 return lp_servicenumber(service);
257 static int load_registry_service(const char *servicename)
259 struct registry_key *key;
265 struct registry_value *value;
269 if (!lp_registry_shares()) {
273 if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) {
277 err = reg_open_path(NULL, path, REG_KEY_READ, get_root_nt_token(),
281 if (!W_ERROR_IS_OK(err)) {
285 res = lp_add_service(servicename, -1);
291 W_ERROR_IS_OK(reg_enumvalue(key, key, i, &value_name, &value));
293 switch (value->type) {
296 if (asprintf(&tmp, "%d", value->v.dword) == -1) {
299 lp_do_parameter(res, value_name, tmp);
304 lp_do_parameter(res, value_name, value->v.sz.str);
308 /* Ignore all the rest */
312 TALLOC_FREE(value_name);
316 if (!service_ok(res)) {
317 /* this is actually never reached, since
318 * service_ok only returns False if the service
319 * entry does not have a service name, and we _know_
320 * we do have a service name here... */
330 void load_registry_shares(void)
332 struct registry_key *key;
337 if (!lp_registry_shares()) {
341 err = reg_open_path(NULL, KEY_SMBCONF, REG_KEY_READ,
342 get_root_nt_token(), &key);
343 if (!(W_ERROR_IS_OK(err))) {
347 for (i=0; W_ERROR_IS_OK(reg_enumkey(key, key, i, &name, NULL)); i++) {
348 load_registry_service(name);
357 * Find a service entry.
359 * @param service is modified (to canonical form??)
362 int find_service(fstring service)
366 all_string_sub(service,"\\","/",0);
368 iService = lp_servicenumber(service);
370 /* now handle the special case of a home directory */
372 char *phome_dir = get_user_home_dir(service);
376 * Try mapping the servicename, it may
377 * be a Windows to unix mapped user name.
379 if(map_username(service))
380 phome_dir = get_user_home_dir(service);
383 DEBUG(3,("checking for home directory %s gave %s\n",service,
384 phome_dir?phome_dir:"(NULL)"));
386 iService = add_home_service(service,service /* 'username' */, phome_dir);
389 /* If we still don't have a service, attempt to add it as a printer. */
393 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
394 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
395 if (pcap_printername_ok(service)) {
396 DEBUG(3,("%s is a valid printer name\n", service));
397 DEBUG(3,("adding %s as a printer service\n", service));
398 lp_add_printer(service, iPrinterService);
399 iService = lp_servicenumber(service);
401 DEBUG(0,("failed to add %s as a printer service!\n", service));
404 DEBUG(3,("%s is not a valid printer name\n", service));
409 /* Check for default vfs service? Unsure whether to implement this */
413 /* Is it a usershare service ? */
414 if (iService < 0 && *lp_usershare_path()) {
415 /* Ensure the name is canonicalized. */
417 iService = load_usershare_service(service);
420 /* just possibly it's a default service? */
422 char *pdefservice = lp_defaultservice();
423 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
425 * We need to do a local copy here as lp_defaultservice()
426 * returns one of the rotating lp_string buffers that
427 * could get overwritten by the recursive find_service() call
428 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
431 pstrcpy(defservice, pdefservice);
433 /* Disallow anything except explicit share names. */
434 if (strequal(defservice,HOMES_NAME) ||
435 strequal(defservice, PRINTERS_NAME) ||
436 strequal(defservice, "IPC$")) {
440 iService = find_service(defservice);
442 all_string_sub(service, "_","/",0);
443 iService = lp_add_service(service, iService);
449 iService = load_registry_service(service);
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_static(&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;
656 SET_STAT_INVALID(st);
658 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
664 DEBUG(0,("Couldn't find free connection.\n"));
665 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
669 conn->params->service = snum;
670 conn->nt_user_token = NULL;
672 if (lp_guest_only(snum)) {
673 const char *guestname = lp_guestaccount();
675 char *found_username = NULL;
678 pass = getpwnam_alloc(NULL, guestname);
680 DEBUG(0,("make_connection_snum: Invalid guest "
681 "account %s??\n",guestname));
683 *status = NT_STATUS_NO_SUCH_USER;
686 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
687 &conn->uid, &conn->gid,
689 &conn->nt_user_token);
690 if (!NT_STATUS_IS_OK(status2)) {
696 fstrcpy(user, found_username);
697 string_set(&conn->user,user);
698 conn->force_user = True;
699 TALLOC_FREE(found_username);
701 DEBUG(3,("Guest only user %s\n",user));
704 if (!lp_guest_ok(snum)) {
705 DEBUG(2, ("guest user (from session setup) "
706 "not permitted to access this share "
707 "(%s)\n", lp_servicename(snum)));
709 *status = NT_STATUS_ACCESS_DENIED;
713 if (!user_ok_token(vuser->user.unix_name,
714 vuser->nt_user_token, snum)) {
715 DEBUG(2, ("user '%s' (from session setup) not "
716 "permitted to access this share "
717 "(%s)\n", vuser->user.unix_name,
718 lp_servicename(snum)));
720 *status = NT_STATUS_ACCESS_DENIED;
724 conn->vuid = vuser->vuid;
725 conn->uid = vuser->uid;
726 conn->gid = vuser->gid;
727 string_set(&conn->user,vuser->user.unix_name);
728 fstrcpy(user,vuser->user.unix_name);
729 guest = vuser->guest;
730 } else if (lp_security() == SEC_SHARE) {
732 char *found_username = NULL;
734 /* add it as a possible user name if we
735 are in share mode security */
736 add_session_user(lp_servicename(snum));
737 /* shall we let them in? */
738 if (!authorise_login(snum,user,password,&guest)) {
739 DEBUG( 2, ( "Invalid username/password for [%s]\n",
740 lp_servicename(snum)) );
742 *status = NT_STATUS_WRONG_PASSWORD;
745 pass = Get_Pwnam(user);
746 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
747 &conn->uid, &conn->gid,
749 &conn->nt_user_token);
750 if (!NT_STATUS_IS_OK(status2)) {
755 fstrcpy(user, found_username);
756 string_set(&conn->user,user);
757 TALLOC_FREE(found_username);
758 conn->force_user = True;
760 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
762 *status = NT_STATUS_ACCESS_DENIED;
766 add_session_user(user);
768 safe_strcpy(conn->client_address, client_addr(),
769 sizeof(conn->client_address)-1);
770 conn->num_files_open = 0;
771 conn->lastused = conn->lastused_count = time(NULL);
773 conn->printer = (strncmp(dev,"LPT",3) == 0);
774 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
775 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
778 /* Case options for the share. */
779 if (lp_casesensitive(snum) == Auto) {
780 /* We will be setting this per packet. Set to be case
781 * insensitive for now. */
782 conn->case_sensitive = False;
784 conn->case_sensitive = (BOOL)lp_casesensitive(snum);
787 conn->case_preserve = lp_preservecase(snum);
788 conn->short_case_preserve = lp_shortpreservecase(snum);
790 conn->veto_list = NULL;
791 conn->hide_list = NULL;
792 conn->veto_oplock_list = NULL;
793 string_set(&conn->dirpath,"");
794 string_set(&conn->user,user);
796 conn->read_only = lp_readonly(SNUM(conn));
797 conn->admin_user = False;
800 * If force user is true, then store the given userid and the gid of
801 * the user we're forcing.
802 * For auxiliary groups see below.
805 if (*lp_force_user(snum)) {
808 status2 = find_forced_user(conn,
809 (vuser != NULL) && vuser->guest,
811 if (!NT_STATUS_IS_OK(status2)) {
816 string_set(&conn->user,user);
817 conn->force_user = True;
818 DEBUG(3,("Forced user %s\n",user));
822 * If force group is true, then override
823 * any groupid stored for the connecting user.
826 if (*lp_force_group(snum)) {
830 status2 = find_forced_group(conn->force_user,
832 &group_sid, &conn->gid);
833 if (!NT_STATUS_IS_OK(status2)) {
839 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
841 /* Not force user and not security=share, but force
842 * group. vuser has a token to copy */
844 conn->nt_user_token = dup_nt_token(
845 NULL, vuser->nt_user_token);
846 if (conn->nt_user_token == NULL) {
847 DEBUG(0, ("dup_nt_token failed\n"));
849 *status = NT_STATUS_NO_MEMORY;
854 /* If conn->nt_user_token is still NULL, we have
855 * security=share. This means ignore the SID, as we had no
856 * vuser to copy from */
858 if (conn->nt_user_token != NULL) {
859 /* Overwrite the primary group sid */
860 sid_copy(&conn->nt_user_token->user_sids[1],
864 conn->force_group = True;
867 if (conn->nt_user_token != NULL) {
870 /* We have a share-specific token from force [user|group].
871 * This means we have to create the list of unix groups from
872 * the list of sids. */
877 for (i=0; i<conn->nt_user_token->num_sids; i++) {
879 DOM_SID *sid = &conn->nt_user_token->user_sids[i];
881 if (!sid_to_gid(sid, &gid)) {
882 DEBUG(10, ("Could not convert SID %s to gid, "
884 sid_string_static(sid)));
887 if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
889 DEBUG(0, ("add_gid_to_array_unique failed\n"));
891 *status = NT_STATUS_NO_MEMORY;
899 pstrcpy(s,lp_pathname(snum));
900 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
901 conn->connectpath, conn->gid,
902 get_current_username(),
903 current_user_info.domain,
905 set_conn_connectpath(conn,s);
906 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
907 lp_servicename(snum)));
911 * New code to check if there's a share security descripter
912 * added from NT server manager. This is done after the
913 * smb.conf checks are done as we need a uid and token. JRA.
918 BOOL can_write = False;
919 NT_USER_TOKEN *token = conn->nt_user_token ?
920 conn->nt_user_token :
921 (vuser ? vuser->nt_user_token : NULL);
924 * I don't believe this can happen. But the
925 * logic above is convoluted enough to confuse
926 * automated checkers, so be sure. JRA.
930 DEBUG(0,("make_connection: connection to %s "
931 "denied due to missing "
933 lp_servicename(snum)));
935 *status = NT_STATUS_ACCESS_DENIED;
939 can_write = share_access_check(token,
940 lp_servicename(snum),
944 if (!share_access_check(token,
945 lp_servicename(snum),
947 /* No access, read or write. */
948 DEBUG(0,("make_connection: connection to %s "
949 "denied due to security "
951 lp_servicename(snum)));
953 *status = NT_STATUS_ACCESS_DENIED;
956 conn->read_only = True;
960 /* Initialise VFS function pointers */
962 if (!smbd_vfs_init(conn)) {
963 DEBUG(0, ("vfs_init failed for service %s\n",
964 lp_servicename(snum)));
966 *status = NT_STATUS_BAD_NETWORK_NAME;
971 * If widelinks are disallowed we need to canonicalise the connect
972 * path here to ensure we don't have any symlinks in the
973 * connectpath. We will be checking all paths on this connection are
974 * below this directory. We must do this after the VFS init as we
975 * depend on the realpath() pointer in the vfs table. JRA.
977 if (!lp_widelinks(snum)) {
979 pstrcpy(s,conn->connectpath);
980 canonicalize_path(conn, s);
981 set_conn_connectpath(conn,s);
984 if ((!conn->printer) && (!conn->ipc)) {
985 conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
986 smbd_messaging_context(),
987 smbd_event_context(),
991 /* ROOT Activities: */
992 /* check number of connections */
993 if (!claim_connection(conn,
994 lp_servicename(snum),
995 lp_max_connections(snum),
997 DEBUG(1,("too many connections - rejected\n"));
999 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
1003 /* Preexecs are done here as they might make the dir we are to ChDir
1005 /* execute any "root preexec = " line */
1006 if (*lp_rootpreexec(snum)) {
1008 pstrcpy(cmd,lp_rootpreexec(snum));
1009 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1010 conn->connectpath, conn->gid,
1011 get_current_username(),
1012 current_user_info.domain,
1014 DEBUG(5,("cmd=%s\n",cmd));
1015 ret = smbrun(cmd,NULL);
1016 if (ret != 0 && lp_rootpreexec_close(snum)) {
1017 DEBUG(1,("root preexec gave %d - failing "
1018 "connection\n", ret));
1019 yield_connection(conn, lp_servicename(snum));
1021 *status = NT_STATUS_ACCESS_DENIED;
1026 /* USER Activites: */
1027 if (!change_to_user(conn, conn->vuid)) {
1028 /* No point continuing if they fail the basic checks */
1029 DEBUG(0,("Can't become connected user!\n"));
1030 yield_connection(conn, lp_servicename(snum));
1032 *status = NT_STATUS_LOGON_FAILURE;
1036 /* Remember that a different vuid can connect later without these
1039 /* Preexecs are done here as they might make the dir we are to ChDir
1042 /* execute any "preexec = " line */
1043 if (*lp_preexec(snum)) {
1045 pstrcpy(cmd,lp_preexec(snum));
1046 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1047 conn->connectpath, conn->gid,
1048 get_current_username(),
1049 current_user_info.domain,
1051 ret = smbrun(cmd,NULL);
1052 if (ret != 0 && lp_preexec_close(snum)) {
1053 DEBUG(1,("preexec gave %d - failing connection\n",
1055 change_to_root_user();
1056 yield_connection(conn, lp_servicename(snum));
1058 *status = NT_STATUS_ACCESS_DENIED;
1063 #ifdef WITH_FAKE_KASERVER
1064 if (lp_afs_share(snum)) {
1069 /* Add veto/hide lists */
1070 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1071 set_namearray( &conn->veto_list, lp_veto_files(snum));
1072 set_namearray( &conn->hide_list, lp_hide_files(snum));
1073 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1076 /* Invoke VFS make connection hook - do this before the VFS_STAT call
1077 to allow any filesystems needing user credentials to initialize
1080 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
1081 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1082 change_to_root_user();
1083 yield_connection(conn, lp_servicename(snum));
1085 *status = NT_STATUS_UNSUCCESSFUL;
1089 /* win2000 does not check the permissions on the directory
1090 during the tree connect, instead relying on permission
1091 check during individual operations. To match this behaviour
1092 I have disabled this chdir check (tridge) */
1093 /* the alternative is just to check the directory exists */
1094 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1095 !S_ISDIR(st.st_mode)) {
1096 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1097 DEBUG(0,("'%s' is not a directory, when connecting to "
1098 "[%s]\n", conn->connectpath,
1099 lp_servicename(snum)));
1101 DEBUG(0,("'%s' does not exist or permission denied "
1102 "when connecting to [%s] Error was %s\n",
1103 conn->connectpath, lp_servicename(snum),
1106 change_to_root_user();
1107 /* Call VFS disconnect hook */
1108 SMB_VFS_DISCONNECT(conn);
1109 yield_connection(conn, lp_servicename(snum));
1111 *status = NT_STATUS_BAD_NETWORK_NAME;
1115 string_set(&conn->origpath,conn->connectpath);
1117 #if SOFTLINK_OPTIMISATION
1118 /* resolve any soft links early if possible */
1119 if (vfs_ChDir(conn,conn->connectpath) == 0) {
1121 pstrcpy(s,conn->connectpath);
1123 set_conn_connectpath(conn,s);
1124 vfs_ChDir(conn,conn->connectpath);
1129 * Print out the 'connected as' stuff here as we need
1130 * to know the effective uid and gid we will be using
1131 * (at least initially).
1134 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1135 dbgtext( "%s (%s) ", get_remote_machine_name(),
1136 conn->client_address );
1137 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1138 dbgtext( "connect to service %s ", lp_servicename(snum) );
1139 dbgtext( "initially as user %s ", user );
1140 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1141 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1144 /* we've finished with the user stuff - go back to root */
1145 change_to_root_user();
1149 /***************************************************************************************
1150 Simple wrapper function for make_connection() to include a call to
1152 **************************************************************************************/
1154 connection_struct *make_connection_with_chdir(const char *service_in,
1156 const char *dev, uint16 vuid,
1159 connection_struct *conn = NULL;
1161 conn = make_connection(service_in, password, dev, vuid, status);
1164 * make_connection() does not change the directory for us any more
1165 * so we have to do it as a separate step --jerry
1168 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1169 DEBUG(0,("move_driver_to_download_area: Can't change "
1170 "directory to %s for [print$] (%s)\n",
1171 conn->connectpath,strerror(errno)));
1172 yield_connection(conn, lp_servicename(SNUM(conn)));
1174 *status = NT_STATUS_UNSUCCESSFUL;
1181 /****************************************************************************
1182 Make a connection to a service.
1185 ****************************************************************************/
1187 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
1188 const char *pdev, uint16 vuid,
1192 user_struct *vuser = NULL;
1199 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1201 if (!non_root_mode() && (euid = geteuid()) != 0) {
1202 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1203 "(%u)\n", (unsigned int)euid ));
1204 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1207 if (conn_num_open() > 2047) {
1208 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1212 if(lp_security() != SEC_SHARE) {
1213 vuser = get_valid_user_struct(vuid);
1215 DEBUG(1,("make_connection: refusing to connect with "
1216 "no session setup\n"));
1217 *status = NT_STATUS_ACCESS_DENIED;
1222 /* Logic to try and connect to the correct [homes] share, preferably
1223 without too many getpwnam() lookups. This is particulary nasty for
1224 winbind usernames, where the share name isn't the same as unix
1227 The snum of the homes share is stored on the vuser at session setup
1231 if (strequal(service_in,HOMES_NAME)) {
1232 if(lp_security() != SEC_SHARE) {
1233 DATA_BLOB no_pw = data_blob_null;
1234 if (vuser->homes_snum == -1) {
1235 DEBUG(2, ("[homes] share not available for "
1236 "this user because it was not found "
1237 "or created at session setup "
1239 *status = NT_STATUS_BAD_NETWORK_NAME;
1242 DEBUG(5, ("making a connection to [homes] service "
1243 "created at session setup time\n"));
1244 return make_connection_snum(vuser->homes_snum,
1248 /* Security = share. Try with
1249 * current_user_info.smb_name as the username. */
1250 if (*current_user_info.smb_name) {
1251 fstring unix_username;
1252 fstrcpy(unix_username,
1253 current_user_info.smb_name);
1254 map_username(unix_username);
1255 snum = find_service(unix_username);
1258 DEBUG(5, ("making a connection to 'homes' "
1259 "service %s based on "
1260 "security=share\n", service_in));
1261 return make_connection_snum(snum, NULL,
1266 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1267 && strequal(service_in,
1268 lp_servicename(vuser->homes_snum))) {
1269 DATA_BLOB no_pw = data_blob_null;
1270 DEBUG(5, ("making a connection to 'homes' service [%s] "
1271 "created at session setup time\n", service_in));
1272 return make_connection_snum(vuser->homes_snum,
1277 fstrcpy(service, service_in);
1279 strlower_m(service);
1281 snum = find_service(service);
1284 if (strequal(service,"IPC$") ||
1285 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1286 DEBUG(3,("refusing IPC connection to %s\n", service));
1287 *status = NT_STATUS_ACCESS_DENIED;
1291 DEBUG(0,("%s (%s) couldn't find service %s\n",
1292 get_remote_machine_name(), client_addr(), service));
1293 *status = NT_STATUS_BAD_NETWORK_NAME;
1297 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1298 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1299 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1300 "(pointing to %s)\n",
1301 service, lp_msdfs_proxy(snum)));
1302 *status = NT_STATUS_BAD_NETWORK_NAME;
1306 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1308 return make_connection_snum(snum, vuser,
1313 /****************************************************************************
1315 ****************************************************************************/
1317 void close_cnum(connection_struct *conn, uint16 vuid)
1320 pipe_close_conn(conn);
1322 file_close_conn(conn);
1323 dptr_closecnum(conn);
1326 change_to_root_user();
1328 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1329 get_remote_machine_name(),
1330 conn->client_address,
1331 lp_servicename(SNUM(conn))));
1333 /* Call VFS disconnect hook */
1334 SMB_VFS_DISCONNECT(conn);
1336 yield_connection(conn, lp_servicename(SNUM(conn)));
1338 /* make sure we leave the directory available for unmount */
1339 vfs_ChDir(conn, "/");
1341 /* execute any "postexec = " line */
1342 if (*lp_postexec(SNUM(conn)) &&
1343 change_to_user(conn, vuid)) {
1345 pstrcpy(cmd,lp_postexec(SNUM(conn)));
1346 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1347 conn->connectpath, conn->gid,
1348 get_current_username(),
1349 current_user_info.domain,
1352 change_to_root_user();
1355 change_to_root_user();
1356 /* execute any "root postexec = " line */
1357 if (*lp_rootpostexec(SNUM(conn))) {
1359 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
1360 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1361 conn->connectpath, conn->gid,
1362 get_current_username(),
1363 current_user_info.domain,