2 Unix SMB/CIFS implementation.
3 service (connection) opening and closing
4 Copyright (C) Andrew Tridgell 1992-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 extern userdom_struct current_user_info;
24 static bool canonicalize_connect_path(connection_struct *conn)
26 #ifdef REALPATH_TAKES_NULL
28 char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,NULL);
32 ret = set_conn_connectpath(conn,resolved_name);
33 SAFE_FREE(resolved_name);
36 char resolved_name_buf[PATH_MAX+1];
37 char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,resolved_name_buf);
41 return set_conn_connectpath(conn,resolved_name);
42 #endif /* REALPATH_TAKES_NULL */
45 /****************************************************************************
46 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
47 absolute path stating in / and not ending in /.
48 Observent people will notice a similarity between this and check_path_syntax :-).
49 ****************************************************************************/
51 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
55 const char *s = connectpath;
56 bool start_of_name_component = true;
58 destname = SMB_STRDUP(connectpath);
64 *d++ = '/'; /* Always start with root. */
68 /* Eat multiple '/' */
72 if ((d > destname + 1) && (*s != '\0')) {
75 start_of_name_component = True;
79 if (start_of_name_component) {
80 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
81 /* Uh oh - "/../" or "/..\0" ! */
83 /* Go past the ../ or .. */
87 s += 2; /* Go past the .. */
90 /* If we just added a '/' - delete it */
91 if ((d > destname) && (*(d-1) == '/')) {
96 /* Are we at the start ? Can't go back further if so. */
98 *d++ = '/'; /* Can't delete root */
101 /* Go back one level... */
102 /* Decrement d first as d points to the *next* char to write into. */
103 for (d--; d > destname; d--) {
108 /* We're still at the start of a name component, just the previous one. */
110 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
111 /* Component of pathname can't be "." only - skip the '.' . */
125 /* Get the size of the next MB character. */
126 next_codepoint(s,&siz);
147 start_of_name_component = false;
151 /* And must not end in '/' */
152 if (d > destname + 1 && (*(d-1) == '/')) {
156 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
157 lp_servicename(SNUM(conn)), destname ));
159 string_set(&conn->connectpath, destname);
164 /****************************************************************************
165 Load parameters specific to a connection/service.
166 ****************************************************************************/
168 bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
170 static connection_struct *last_conn;
171 static uint16 last_flags;
179 conn->lastused_count++;
184 vfs_ChDir(conn,conn->connectpath) != 0 &&
185 vfs_ChDir(conn,conn->origpath) != 0) {
186 DEBUG(0,("chdir (%s) failed\n",
191 if ((conn == last_conn) && (last_flags == flags)) {
198 /* Obey the client case sensitivity requests - only for clients that support it. */
199 switch (lp_casesensitive(snum)) {
202 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
203 enum remote_arch_types ra_type = get_remote_arch();
204 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
205 /* Client can't support per-packet case sensitive pathnames. */
206 conn->case_sensitive = False;
208 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
213 conn->case_sensitive = True;
216 conn->case_sensitive = False;
222 /****************************************************************************
223 Add a home service. Returns the new service number or -1 if fail.
224 ****************************************************************************/
226 int add_home_service(const char *service, const char *username, const char *homedir)
230 if (!service || !homedir)
233 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
237 * If this is a winbindd provided username, remove
238 * the domain component before adding the service.
239 * Log a warning if the "path=" parameter does not
240 * include any macros.
244 const char *p = strchr(service,*lp_winbind_separator());
246 /* We only want the 'user' part of the string */
252 if (!lp_add_home(service, iHomeService, username, homedir)) {
256 return lp_servicenumber(service);
260 static int load_registry_service(const char *servicename)
262 struct registry_key *key;
268 struct registry_value *value;
272 if (!lp_registry_shares()) {
276 if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) {
280 err = reg_open_path(NULL, path, REG_KEY_READ, get_root_nt_token(),
284 if (!W_ERROR_IS_OK(err)) {
288 res = lp_add_service(servicename, -1);
294 W_ERROR_IS_OK(reg_enumvalue(key, key, i, &value_name, &value));
296 switch (value->type) {
299 if (asprintf(&tmp, "%d", value->v.dword) == -1) {
302 lp_do_parameter(res, value_name, tmp);
307 lp_do_parameter(res, value_name, value->v.sz.str);
311 /* Ignore all the rest */
315 TALLOC_FREE(value_name);
325 void load_registry_shares(void)
327 struct registry_key *key;
332 if (!lp_registry_shares()) {
336 err = reg_open_path(NULL, KEY_SMBCONF, REG_KEY_READ,
337 get_root_nt_token(), &key);
338 if (!(W_ERROR_IS_OK(err))) {
342 for (i=0; W_ERROR_IS_OK(reg_enumkey(key, key, i, &name, NULL)); i++) {
343 load_registry_service(name);
352 * Find a service entry.
354 * @param service is modified (to canonical form??)
357 int find_service(fstring service)
360 TALLOC_CTX *frame = talloc_stackframe();
362 all_string_sub(service,"\\","/",0);
364 iService = lp_servicenumber(service);
366 /* now handle the special case of a home directory */
368 char *phome_dir = get_user_home_dir(talloc_tos(), service);
372 * Try mapping the servicename, it may
373 * be a Windows to unix mapped user name.
375 if(map_username(service))
376 phome_dir = get_user_home_dir(
377 talloc_tos(), service);
380 DEBUG(3,("checking for home directory %s gave %s\n",service,
381 phome_dir?phome_dir:"(NULL)"));
383 iService = add_home_service(service,service /* 'username' */, phome_dir);
386 /* If we still don't have a service, attempt to add it as a printer. */
390 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
391 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
392 if (pcap_printername_ok(service)) {
393 DEBUG(3,("%s is a valid printer name\n", service));
394 DEBUG(3,("adding %s as a printer service\n", service));
395 lp_add_printer(service, iPrinterService);
396 iService = lp_servicenumber(service);
398 DEBUG(0,("failed to add %s as a printer service!\n", service));
401 DEBUG(3,("%s is not a valid printer name\n", service));
406 /* Check for default vfs service? Unsure whether to implement this */
411 iService = load_registry_service(service);
414 /* Is it a usershare service ? */
415 if (iService < 0 && *lp_usershare_path()) {
416 /* Ensure the name is canonicalized. */
418 iService = load_usershare_service(service);
421 /* just possibly it's a default service? */
423 char *pdefservice = lp_defaultservice();
424 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
426 * We need to do a local copy here as lp_defaultservice()
427 * returns one of the rotating lp_string buffers that
428 * could get overwritten by the recursive find_service() call
429 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
431 char *defservice = SMB_STRDUP(pdefservice);
437 /* Disallow anything except explicit share names. */
438 if (strequal(defservice,HOMES_NAME) ||
439 strequal(defservice, PRINTERS_NAME) ||
440 strequal(defservice, "IPC$")) {
441 SAFE_FREE(defservice);
445 iService = find_service(defservice);
447 all_string_sub(service, "_","/",0);
448 iService = lp_add_service(service, iService);
450 SAFE_FREE(defservice);
455 if (!VALID_SNUM(iService)) {
456 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
464 DEBUG(3,("find_service() failed to find service %s\n", service));
472 /****************************************************************************
473 do some basic sainity checks on the share.
474 This function modifies dev, ecode.
475 ****************************************************************************/
477 static NTSTATUS share_sanity_checks(int snum, fstring dev)
480 if (!lp_snum_ok(snum) ||
481 !check_access(smbd_server_fd(),
482 lp_hostsallow(snum), lp_hostsdeny(snum))) {
483 return NT_STATUS_ACCESS_DENIED;
486 if (dev[0] == '?' || !dev[0]) {
487 if (lp_print_ok(snum)) {
488 fstrcpy(dev,"LPT1:");
489 } else if (strequal(lp_fstype(snum), "IPC")) {
498 if (lp_print_ok(snum)) {
499 if (!strequal(dev, "LPT1:")) {
500 return NT_STATUS_BAD_DEVICE_TYPE;
502 } else if (strequal(lp_fstype(snum), "IPC")) {
503 if (!strequal(dev, "IPC")) {
504 return NT_STATUS_BAD_DEVICE_TYPE;
506 } else if (!strequal(dev, "A:")) {
507 return NT_STATUS_BAD_DEVICE_TYPE;
510 /* Behave as a printer if we are supposed to */
511 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
512 fstrcpy(dev, "LPT1:");
518 static NTSTATUS find_forced_user(connection_struct *conn, bool vuser_is_guest, fstring username)
520 int snum = conn->params->service;
521 char *fuser, *found_username;
524 if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S",
525 lp_servicename(snum)))) {
526 return NT_STATUS_NO_MEMORY;
529 result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest,
530 &conn->uid, &conn->gid, &found_username,
531 &conn->nt_user_token);
532 if (!NT_STATUS_IS_OK(result)) {
536 fstrcpy(username, found_username);
539 TALLOC_FREE(found_username);
544 * Go through lookup_name etc to find the force'd group.
546 * Create a new token from src_token, replacing the primary group sid with the
550 static NTSTATUS find_forced_group(bool force_user,
551 int snum, const char *username,
555 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
558 enum lsa_SidType type;
560 bool user_must_be_member = False;
563 ZERO_STRUCTP(pgroup_sid);
566 mem_ctx = talloc_new(NULL);
567 if (mem_ctx == NULL) {
568 DEBUG(0, ("talloc_new failed\n"));
569 return NT_STATUS_NO_MEMORY;
572 groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
573 if (groupname == NULL) {
574 DEBUG(1, ("talloc_strdup failed\n"));
575 result = NT_STATUS_NO_MEMORY;
579 if (groupname[0] == '+') {
580 user_must_be_member = True;
584 groupname = talloc_string_sub(mem_ctx, groupname,
585 "%S", lp_servicename(snum));
587 if (!lookup_name_smbconf(mem_ctx, groupname,
588 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
589 NULL, NULL, &group_sid, &type)) {
590 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
595 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
596 (type != SID_NAME_WKN_GRP)) {
597 DEBUG(10, ("%s is a %s, not a group\n", groupname,
598 sid_type_lookup(type)));
602 if (!sid_to_gid(&group_sid, &gid)) {
603 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
604 sid_string_dbg(&group_sid), groupname));
609 * If the user has been forced and the forced group starts with a '+',
610 * then we only set the group to be the forced group if the forced
611 * user is a member of that group. Otherwise, the meaning of the '+'
615 if (force_user && user_must_be_member) {
616 if (user_in_group_sid(username, &group_sid)) {
617 sid_copy(pgroup_sid, &group_sid);
619 DEBUG(3,("Forced group %s for member %s\n",
620 groupname, username));
622 DEBUG(0,("find_forced_group: forced user %s is not a member "
623 "of forced group %s. Disallowing access.\n",
624 username, groupname ));
625 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
629 sid_copy(pgroup_sid, &group_sid);
631 DEBUG(3,("Forced group %s\n", groupname));
634 result = NT_STATUS_OK;
636 TALLOC_FREE(mem_ctx);
640 /****************************************************************************
641 Make a connection, given the snum to connect to, and the vuser of the
642 connecting user if appropriate.
643 ****************************************************************************/
645 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
650 struct passwd *pass = NULL;
652 connection_struct *conn;
657 char addr[INET6_ADDRSTRLEN];
658 bool on_err_call_dis_hook = false;
662 SET_STAT_INVALID(st);
664 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
670 DEBUG(0,("Couldn't find free connection.\n"));
671 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
675 conn->params->service = snum;
676 conn->nt_user_token = NULL;
678 if (lp_guest_only(snum)) {
679 const char *guestname = lp_guestaccount();
681 char *found_username = NULL;
684 pass = getpwnam_alloc(NULL, guestname);
686 DEBUG(0,("make_connection_snum: Invalid guest "
687 "account %s??\n",guestname));
689 *status = NT_STATUS_NO_SUCH_USER;
692 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
693 &conn->uid, &conn->gid,
695 &conn->nt_user_token);
696 if (!NT_STATUS_IS_OK(status2)) {
702 fstrcpy(user, found_username);
703 string_set(&conn->user,user);
704 conn->force_user = True;
705 TALLOC_FREE(found_username);
707 DEBUG(3,("Guest only user %s\n",user));
710 if (!lp_guest_ok(snum)) {
711 DEBUG(2, ("guest user (from session setup) "
712 "not permitted to access this share "
713 "(%s)\n", lp_servicename(snum)));
715 *status = NT_STATUS_ACCESS_DENIED;
719 if (!user_ok_token(vuser->user.unix_name,
720 vuser->nt_user_token, snum)) {
721 DEBUG(2, ("user '%s' (from session setup) not "
722 "permitted to access this share "
723 "(%s)\n", vuser->user.unix_name,
724 lp_servicename(snum)));
726 *status = NT_STATUS_ACCESS_DENIED;
730 conn->vuid = vuser->vuid;
731 conn->uid = vuser->uid;
732 conn->gid = vuser->gid;
733 string_set(&conn->user,vuser->user.unix_name);
734 fstrcpy(user,vuser->user.unix_name);
735 guest = vuser->guest;
736 } else if (lp_security() == SEC_SHARE) {
738 char *found_username = NULL;
740 /* add it as a possible user name if we
741 are in share mode security */
742 add_session_user(lp_servicename(snum));
743 /* shall we let them in? */
744 if (!authorise_login(snum,user,password,&guest)) {
745 DEBUG( 2, ( "Invalid username/password for [%s]\n",
746 lp_servicename(snum)) );
748 *status = NT_STATUS_WRONG_PASSWORD;
751 pass = Get_Pwnam_alloc(talloc_tos(), user);
752 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
753 &conn->uid, &conn->gid,
755 &conn->nt_user_token);
757 if (!NT_STATUS_IS_OK(status2)) {
762 fstrcpy(user, found_username);
763 string_set(&conn->user,user);
764 TALLOC_FREE(found_username);
765 conn->force_user = True;
767 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
769 *status = NT_STATUS_ACCESS_DENIED;
773 add_session_user(user);
775 safe_strcpy(conn->client_address,
776 client_addr(get_client_fd(),addr,sizeof(addr)),
777 sizeof(conn->client_address)-1);
778 conn->num_files_open = 0;
779 conn->lastused = conn->lastused_count = time(NULL);
781 conn->printer = (strncmp(dev,"LPT",3) == 0);
782 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
783 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
786 /* Case options for the share. */
787 if (lp_casesensitive(snum) == Auto) {
788 /* We will be setting this per packet. Set to be case
789 * insensitive for now. */
790 conn->case_sensitive = False;
792 conn->case_sensitive = (bool)lp_casesensitive(snum);
795 conn->case_preserve = lp_preservecase(snum);
796 conn->short_case_preserve = lp_shortpreservecase(snum);
798 conn->encrypt_level = lp_smb_encrypt(snum);
800 conn->veto_list = NULL;
801 conn->hide_list = NULL;
802 conn->veto_oplock_list = NULL;
803 conn->aio_write_behind_list = NULL;
804 string_set(&conn->dirpath,"");
805 string_set(&conn->user,user);
807 conn->read_only = lp_readonly(SNUM(conn));
808 conn->admin_user = False;
811 * If force user is true, then store the given userid and the gid of
812 * the user we're forcing.
813 * For auxiliary groups see below.
816 if (*lp_force_user(snum)) {
819 status2 = find_forced_user(conn,
820 (vuser != NULL) && vuser->guest,
822 if (!NT_STATUS_IS_OK(status2)) {
827 string_set(&conn->user,user);
828 conn->force_user = True;
829 DEBUG(3,("Forced user %s\n",user));
833 * If force group is true, then override
834 * any groupid stored for the connecting user.
837 if (*lp_force_group(snum)) {
841 status2 = find_forced_group(conn->force_user,
843 &group_sid, &conn->gid);
844 if (!NT_STATUS_IS_OK(status2)) {
850 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
852 /* Not force user and not security=share, but force
853 * group. vuser has a token to copy */
855 conn->nt_user_token = dup_nt_token(
856 NULL, vuser->nt_user_token);
857 if (conn->nt_user_token == NULL) {
858 DEBUG(0, ("dup_nt_token failed\n"));
860 *status = NT_STATUS_NO_MEMORY;
865 /* If conn->nt_user_token is still NULL, we have
866 * security=share. This means ignore the SID, as we had no
867 * vuser to copy from */
869 if (conn->nt_user_token != NULL) {
870 /* Overwrite the primary group sid */
871 sid_copy(&conn->nt_user_token->user_sids[1],
875 conn->force_group = True;
878 if (conn->nt_user_token != NULL) {
881 /* We have a share-specific token from force [user|group].
882 * This means we have to create the list of unix groups from
883 * the list of sids. */
888 for (i=0; i<conn->nt_user_token->num_sids; i++) {
890 DOM_SID *sid = &conn->nt_user_token->user_sids[i];
892 if (!sid_to_gid(sid, &gid)) {
893 DEBUG(10, ("Could not convert SID %s to gid, "
895 sid_string_dbg(sid)));
898 if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
900 DEBUG(0, ("add_gid_to_array_unique failed\n"));
902 *status = NT_STATUS_NO_MEMORY;
909 char *s = talloc_sub_advanced(talloc_tos(),
910 lp_servicename(SNUM(conn)), conn->user,
911 conn->connectpath, conn->gid,
912 get_current_username(),
913 current_user_info.domain,
917 *status = NT_STATUS_NO_MEMORY;
921 if (!set_conn_connectpath(conn,s)) {
924 *status = NT_STATUS_NO_MEMORY;
927 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
928 lp_servicename(snum)));
933 * New code to check if there's a share security descripter
934 * added from NT server manager. This is done after the
935 * smb.conf checks are done as we need a uid and token. JRA.
940 bool can_write = False;
941 NT_USER_TOKEN *token = conn->nt_user_token ?
942 conn->nt_user_token :
943 (vuser ? vuser->nt_user_token : NULL);
946 * I don't believe this can happen. But the
947 * logic above is convoluted enough to confuse
948 * automated checkers, so be sure. JRA.
952 DEBUG(0,("make_connection: connection to %s "
953 "denied due to missing "
955 lp_servicename(snum)));
957 *status = NT_STATUS_ACCESS_DENIED;
961 can_write = share_access_check(token,
962 lp_servicename(snum),
966 if (!share_access_check(token,
967 lp_servicename(snum),
969 /* No access, read or write. */
970 DEBUG(0,("make_connection: connection to %s "
971 "denied due to security "
973 lp_servicename(snum)));
975 *status = NT_STATUS_ACCESS_DENIED;
978 conn->read_only = True;
982 /* Initialise VFS function pointers */
984 if (!smbd_vfs_init(conn)) {
985 DEBUG(0, ("vfs_init failed for service %s\n",
986 lp_servicename(snum)));
988 *status = NT_STATUS_BAD_NETWORK_NAME;
993 * If widelinks are disallowed we need to canonicalise the connect
994 * path here to ensure we don't have any symlinks in the
995 * connectpath. We will be checking all paths on this connection are
996 * below this directory. We must do this after the VFS init as we
997 * depend on the realpath() pointer in the vfs table. JRA.
999 if (!lp_widelinks(snum)) {
1000 if (!canonicalize_connect_path(conn)) {
1001 DEBUG(0, ("canonicalize_connect_path failed "
1002 "for service %s, path %s\n",
1003 lp_servicename(snum),
1004 conn->connectpath));
1006 *status = NT_STATUS_BAD_NETWORK_NAME;
1011 if ((!conn->printer) && (!conn->ipc)) {
1012 conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
1013 smbd_messaging_context(),
1014 smbd_event_context(),
1018 /* ROOT Activities: */
1020 * Enforce the max connections parameter.
1023 if ((lp_max_connections(snum) > 0)
1024 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
1025 lp_max_connections(snum))) {
1027 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
1028 lp_max_connections(snum), lp_servicename(snum)));
1030 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
1035 * Get us an entry in the connections db
1037 if (!claim_connection(conn, lp_servicename(snum), 0)) {
1038 DEBUG(1, ("Could not store connections entry\n"));
1040 *status = NT_STATUS_INTERNAL_DB_ERROR;
1044 /* Preexecs are done here as they might make the dir we are to ChDir
1046 /* execute any "root preexec = " line */
1047 if (*lp_rootpreexec(snum)) {
1048 char *cmd = talloc_sub_advanced(talloc_tos(),
1049 lp_servicename(SNUM(conn)), conn->user,
1050 conn->connectpath, conn->gid,
1051 get_current_username(),
1052 current_user_info.domain,
1053 lp_rootpreexec(snum));
1054 DEBUG(5,("cmd=%s\n",cmd));
1055 ret = smbrun(cmd,NULL);
1057 if (ret != 0 && lp_rootpreexec_close(snum)) {
1058 DEBUG(1,("root preexec gave %d - failing "
1059 "connection\n", ret));
1060 yield_connection(conn, lp_servicename(snum));
1062 *status = NT_STATUS_ACCESS_DENIED;
1067 /* USER Activites: */
1068 if (!change_to_user(conn, conn->vuid)) {
1069 /* No point continuing if they fail the basic checks */
1070 DEBUG(0,("Can't become connected user!\n"));
1071 yield_connection(conn, lp_servicename(snum));
1073 *status = NT_STATUS_LOGON_FAILURE;
1077 /* Remember that a different vuid can connect later without these
1080 /* Preexecs are done here as they might make the dir we are to ChDir
1083 /* execute any "preexec = " line */
1084 if (*lp_preexec(snum)) {
1085 char *cmd = talloc_sub_advanced(talloc_tos(),
1086 lp_servicename(SNUM(conn)), conn->user,
1087 conn->connectpath, conn->gid,
1088 get_current_username(),
1089 current_user_info.domain,
1091 ret = smbrun(cmd,NULL);
1093 if (ret != 0 && lp_preexec_close(snum)) {
1094 DEBUG(1,("preexec gave %d - failing connection\n",
1096 *status = NT_STATUS_ACCESS_DENIED;
1101 #ifdef WITH_FAKE_KASERVER
1102 if (lp_afs_share(snum)) {
1107 /* Add veto/hide lists */
1108 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1109 set_namearray( &conn->veto_list, lp_veto_files(snum));
1110 set_namearray( &conn->hide_list, lp_hide_files(snum));
1111 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1114 /* Invoke VFS make connection hook - do this before the VFS_STAT call
1115 to allow any filesystems needing user credentials to initialize
1118 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
1119 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1120 *status = NT_STATUS_UNSUCCESSFUL;
1124 /* Any error exit after here needs to call the disconnect hook. */
1125 on_err_call_dis_hook = true;
1127 /* win2000 does not check the permissions on the directory
1128 during the tree connect, instead relying on permission
1129 check during individual operations. To match this behaviour
1130 I have disabled this chdir check (tridge) */
1131 /* the alternative is just to check the directory exists */
1132 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1133 !S_ISDIR(st.st_mode)) {
1134 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1135 DEBUG(0,("'%s' is not a directory, when connecting to "
1136 "[%s]\n", conn->connectpath,
1137 lp_servicename(snum)));
1139 DEBUG(0,("'%s' does not exist or permission denied "
1140 "when connecting to [%s] Error was %s\n",
1141 conn->connectpath, lp_servicename(snum),
1144 *status = NT_STATUS_BAD_NETWORK_NAME;
1148 string_set(&conn->origpath,conn->connectpath);
1150 #if SOFTLINK_OPTIMISATION
1151 /* resolve any soft links early if possible */
1152 if (vfs_ChDir(conn,conn->connectpath) == 0) {
1153 TALLOC_CTX *ctx = talloc_stackframe();
1154 char *s = vfs_GetWd(ctx,s);
1156 *status = map_nt_error_from_unix(errno);
1160 if (!set_conn_connectpath(conn,s)) {
1161 *status = NT_STATUS_NO_MEMORY;
1165 vfs_ChDir(conn,conn->connectpath);
1170 /* Figure out the characteristics of the underlying filesystem. This
1171 * assumes that all the filesystem mounted withing a share path have
1172 * the same characteristics, which is likely but not guaranteed.
1175 vfs_statvfs_struct svfs;
1177 conn->fs_capabilities =
1178 FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
1180 if (SMB_VFS_STATVFS(conn, conn->connectpath, &svfs) == 0) {
1181 conn->fs_capabilities = svfs.FsCapabilities;
1186 * Print out the 'connected as' stuff here as we need
1187 * to know the effective uid and gid we will be using
1188 * (at least initially).
1191 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1192 dbgtext( "%s (%s) ", get_remote_machine_name(),
1193 conn->client_address );
1194 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1195 dbgtext( "connect to service %s ", lp_servicename(snum) );
1196 dbgtext( "initially as user %s ", user );
1197 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1198 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1201 /* we've finished with the user stuff - go back to root */
1202 change_to_root_user();
1207 change_to_root_user();
1208 if (on_err_call_dis_hook) {
1209 /* Call VFS disconnect hook */
1210 SMB_VFS_DISCONNECT(conn);
1212 yield_connection(conn, lp_servicename(snum));
1217 /***************************************************************************************
1218 Simple wrapper function for make_connection() to include a call to
1220 **************************************************************************************/
1222 connection_struct *make_connection_with_chdir(const char *service_in,
1224 const char *dev, uint16 vuid,
1227 connection_struct *conn = NULL;
1229 conn = make_connection(service_in, password, dev, vuid, status);
1232 * make_connection() does not change the directory for us any more
1233 * so we have to do it as a separate step --jerry
1236 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1237 DEBUG(0,("move_driver_to_download_area: Can't change "
1238 "directory to %s for [print$] (%s)\n",
1239 conn->connectpath,strerror(errno)));
1240 yield_connection(conn, lp_servicename(SNUM(conn)));
1242 *status = NT_STATUS_UNSUCCESSFUL;
1249 /****************************************************************************
1250 Make a connection to a service.
1253 ****************************************************************************/
1255 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
1256 const char *pdev, uint16 vuid,
1260 user_struct *vuser = NULL;
1264 char addr[INET6_ADDRSTRLEN];
1268 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1270 if (!non_root_mode() && (euid = geteuid()) != 0) {
1271 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1272 "(%u)\n", (unsigned int)euid ));
1273 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1276 if (conn_num_open() > 2047) {
1277 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1281 if(lp_security() != SEC_SHARE) {
1282 vuser = get_valid_user_struct(vuid);
1284 DEBUG(1,("make_connection: refusing to connect with "
1285 "no session setup\n"));
1286 *status = NT_STATUS_ACCESS_DENIED;
1291 /* Logic to try and connect to the correct [homes] share, preferably
1292 without too many getpwnam() lookups. This is particulary nasty for
1293 winbind usernames, where the share name isn't the same as unix
1296 The snum of the homes share is stored on the vuser at session setup
1300 if (strequal(service_in,HOMES_NAME)) {
1301 if(lp_security() != SEC_SHARE) {
1302 DATA_BLOB no_pw = data_blob_null;
1303 if (vuser->homes_snum == -1) {
1304 DEBUG(2, ("[homes] share not available for "
1305 "this user because it was not found "
1306 "or created at session setup "
1308 *status = NT_STATUS_BAD_NETWORK_NAME;
1311 DEBUG(5, ("making a connection to [homes] service "
1312 "created at session setup time\n"));
1313 return make_connection_snum(vuser->homes_snum,
1317 /* Security = share. Try with
1318 * current_user_info.smb_name as the username. */
1319 if (*current_user_info.smb_name) {
1320 fstring unix_username;
1321 fstrcpy(unix_username,
1322 current_user_info.smb_name);
1323 map_username(unix_username);
1324 snum = find_service(unix_username);
1327 DEBUG(5, ("making a connection to 'homes' "
1328 "service %s based on "
1329 "security=share\n", service_in));
1330 return make_connection_snum(snum, NULL,
1335 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1336 && strequal(service_in,
1337 lp_servicename(vuser->homes_snum))) {
1338 DATA_BLOB no_pw = data_blob_null;
1339 DEBUG(5, ("making a connection to 'homes' service [%s] "
1340 "created at session setup time\n", service_in));
1341 return make_connection_snum(vuser->homes_snum,
1346 fstrcpy(service, service_in);
1348 strlower_m(service);
1350 snum = find_service(service);
1353 if (strequal(service,"IPC$") ||
1354 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1355 DEBUG(3,("refusing IPC connection to %s\n", service));
1356 *status = NT_STATUS_ACCESS_DENIED;
1360 DEBUG(0,("%s (%s) couldn't find service %s\n",
1361 get_remote_machine_name(),
1362 client_addr(get_client_fd(),addr,sizeof(addr)),
1364 *status = NT_STATUS_BAD_NETWORK_NAME;
1368 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1369 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1370 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1371 "(pointing to %s)\n",
1372 service, lp_msdfs_proxy(snum)));
1373 *status = NT_STATUS_BAD_NETWORK_NAME;
1377 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1379 return make_connection_snum(snum, vuser,
1384 /****************************************************************************
1386 ****************************************************************************/
1388 void close_cnum(connection_struct *conn, uint16 vuid)
1391 pipe_close_conn(conn);
1393 file_close_conn(conn);
1394 dptr_closecnum(conn);
1397 change_to_root_user();
1399 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1400 get_remote_machine_name(),
1401 conn->client_address,
1402 lp_servicename(SNUM(conn))));
1404 /* Call VFS disconnect hook */
1405 SMB_VFS_DISCONNECT(conn);
1407 yield_connection(conn, lp_servicename(SNUM(conn)));
1409 /* make sure we leave the directory available for unmount */
1410 vfs_ChDir(conn, "/");
1412 /* execute any "postexec = " line */
1413 if (*lp_postexec(SNUM(conn)) &&
1414 change_to_user(conn, vuid)) {
1415 char *cmd = talloc_sub_advanced(talloc_tos(),
1416 lp_servicename(SNUM(conn)), conn->user,
1417 conn->connectpath, conn->gid,
1418 get_current_username(),
1419 current_user_info.domain,
1420 lp_postexec(SNUM(conn)));
1423 change_to_root_user();
1426 change_to_root_user();
1427 /* execute any "root postexec = " line */
1428 if (*lp_rootpostexec(SNUM(conn))) {
1429 char *cmd = talloc_sub_advanced(talloc_tos(),
1430 lp_servicename(SNUM(conn)), conn->user,
1431 conn->connectpath, conn->gid,
1432 get_current_username(),
1433 current_user_info.domain,
1434 lp_rootpostexec(SNUM(conn)));