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_path(connection_struct *conn, pstring path)
26 #ifdef REALPATH_TAKES_NULL
27 char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL);
31 pstrcpy(path, resolved_name);
32 SAFE_FREE(resolved_name);
36 char resolved_name_buf[PATH_MAX+1];
38 pstring resolved_name_buf;
40 char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf);
44 pstrcpy(path, resolved_name);
46 #endif /* REALPATH_TAKES_NULL */
49 /****************************************************************************
50 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
51 absolute path stating in / and not ending in /.
52 Observent people will notice a similarity between this and check_path_syntax :-).
53 ****************************************************************************/
55 void set_conn_connectpath(connection_struct *conn, const char *connectpath)
59 const char *s = connectpath;
60 bool start_of_name_component = True;
62 *d++ = '/'; /* Always start with root. */
66 /* Eat multiple '/' */
70 if ((d > destname + 1) && (*s != '\0')) {
73 start_of_name_component = True;
77 if (start_of_name_component) {
78 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
79 /* Uh oh - "/../" or "/..\0" ! */
81 /* Go past the ../ or .. */
85 s += 2; /* Go past the .. */
88 /* If we just added a '/' - delete it */
89 if ((d > destname) && (*(d-1) == '/')) {
94 /* Are we at the start ? Can't go back further if so. */
96 *d++ = '/'; /* Can't delete root */
99 /* Go back one level... */
100 /* Decrement d first as d points to the *next* char to write into. */
101 for (d--; d > destname; d--) {
106 /* We're still at the start of a name component, just the previous one. */
108 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
109 /* Component of pathname can't be "." only - skip the '.' . */
123 /* Get the size of the next MB character. */
124 next_codepoint(s,&siz);
145 start_of_name_component = False;
149 /* And must not end in '/' */
150 if (d > destname + 1 && (*(d-1) == '/')) {
154 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
155 lp_servicename(SNUM(conn)), destname ));
157 string_set(&conn->connectpath, destname);
160 /****************************************************************************
161 Load parameters specific to a connection/service.
162 ****************************************************************************/
164 bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
166 static connection_struct *last_conn;
167 static uint16 last_flags;
175 conn->lastused_count++;
180 vfs_ChDir(conn,conn->connectpath) != 0 &&
181 vfs_ChDir(conn,conn->origpath) != 0) {
182 DEBUG(0,("chdir (%s) failed\n",
187 if ((conn == last_conn) && (last_flags == flags)) {
194 /* Obey the client case sensitivity requests - only for clients that support it. */
195 switch (lp_casesensitive(snum)) {
198 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
199 enum remote_arch_types ra_type = get_remote_arch();
200 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
201 /* Client can't support per-packet case sensitive pathnames. */
202 conn->case_sensitive = False;
204 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
209 conn->case_sensitive = True;
212 conn->case_sensitive = False;
218 /****************************************************************************
219 Add a home service. Returns the new service number or -1 if fail.
220 ****************************************************************************/
222 int add_home_service(const char *service, const char *username, const char *homedir)
226 if (!service || !homedir)
229 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
233 * If this is a winbindd provided username, remove
234 * the domain component before adding the service.
235 * Log a warning if the "path=" parameter does not
236 * include any macros.
240 const char *p = strchr(service,*lp_winbind_separator());
242 /* We only want the 'user' part of the string */
248 if (!lp_add_home(service, iHomeService, username, homedir)) {
252 return lp_servicenumber(service);
256 static int load_registry_service(const char *servicename)
258 struct registry_key *key;
264 struct registry_value *value;
268 if (!lp_registry_shares()) {
272 if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) {
276 err = reg_open_path(NULL, path, REG_KEY_READ, get_root_nt_token(),
280 if (!W_ERROR_IS_OK(err)) {
284 res = lp_add_service(servicename, -1);
290 W_ERROR_IS_OK(reg_enumvalue(key, key, i, &value_name, &value));
292 switch (value->type) {
295 if (asprintf(&tmp, "%d", value->v.dword) == -1) {
298 lp_do_parameter(res, value_name, tmp);
303 lp_do_parameter(res, value_name, value->v.sz.str);
307 /* Ignore all the rest */
311 TALLOC_FREE(value_name);
322 void load_registry_shares(void)
324 struct registry_key *key;
329 if (!lp_registry_shares()) {
333 err = reg_open_path(NULL, KEY_SMBCONF, REG_KEY_READ,
334 get_root_nt_token(), &key);
335 if (!(W_ERROR_IS_OK(err))) {
339 for (i=0; W_ERROR_IS_OK(reg_enumkey(key, key, i, &name, NULL)); i++) {
340 load_registry_service(name);
349 * Find a service entry.
351 * @param service is modified (to canonical form??)
354 int find_service(fstring service)
358 all_string_sub(service,"\\","/",0);
360 iService = lp_servicenumber(service);
362 /* now handle the special case of a home directory */
364 char *phome_dir = get_user_home_dir(service);
368 * Try mapping the servicename, it may
369 * be a Windows to unix mapped user name.
371 if(map_username(service))
372 phome_dir = get_user_home_dir(service);
375 DEBUG(3,("checking for home directory %s gave %s\n",service,
376 phome_dir?phome_dir:"(NULL)"));
378 iService = add_home_service(service,service /* 'username' */, phome_dir);
381 /* If we still don't have a service, attempt to add it as a printer. */
385 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
386 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
387 if (pcap_printername_ok(service)) {
388 DEBUG(3,("%s is a valid printer name\n", service));
389 DEBUG(3,("adding %s as a printer service\n", service));
390 lp_add_printer(service, iPrinterService);
391 iService = lp_servicenumber(service);
393 DEBUG(0,("failed to add %s as a printer service!\n", service));
396 DEBUG(3,("%s is not a valid printer name\n", service));
401 /* Check for default vfs service? Unsure whether to implement this */
406 iService = load_registry_service(service);
409 /* Is it a usershare service ? */
410 if (iService < 0 && *lp_usershare_path()) {
411 /* Ensure the name is canonicalized. */
413 iService = load_usershare_service(service);
416 /* just possibly it's a default service? */
418 char *pdefservice = lp_defaultservice();
419 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
421 * We need to do a local copy here as lp_defaultservice()
422 * returns one of the rotating lp_string buffers that
423 * could get overwritten by the recursive find_service() call
424 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
427 pstrcpy(defservice, pdefservice);
429 /* Disallow anything except explicit share names. */
430 if (strequal(defservice,HOMES_NAME) ||
431 strequal(defservice, PRINTERS_NAME) ||
432 strequal(defservice, "IPC$")) {
436 iService = find_service(defservice);
438 all_string_sub(service, "_","/",0);
439 iService = lp_add_service(service, iService);
445 if (!VALID_SNUM(iService)) {
446 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
454 DEBUG(3,("find_service() failed to find service %s\n", service));
460 /****************************************************************************
461 do some basic sainity checks on the share.
462 This function modifies dev, ecode.
463 ****************************************************************************/
465 static NTSTATUS share_sanity_checks(int snum, fstring dev)
468 if (!lp_snum_ok(snum) ||
469 !check_access(smbd_server_fd(),
470 lp_hostsallow(snum), lp_hostsdeny(snum))) {
471 return NT_STATUS_ACCESS_DENIED;
474 if (dev[0] == '?' || !dev[0]) {
475 if (lp_print_ok(snum)) {
476 fstrcpy(dev,"LPT1:");
477 } else if (strequal(lp_fstype(snum), "IPC")) {
486 if (lp_print_ok(snum)) {
487 if (!strequal(dev, "LPT1:")) {
488 return NT_STATUS_BAD_DEVICE_TYPE;
490 } else if (strequal(lp_fstype(snum), "IPC")) {
491 if (!strequal(dev, "IPC")) {
492 return NT_STATUS_BAD_DEVICE_TYPE;
494 } else if (!strequal(dev, "A:")) {
495 return NT_STATUS_BAD_DEVICE_TYPE;
498 /* Behave as a printer if we are supposed to */
499 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
500 fstrcpy(dev, "LPT1:");
506 static NTSTATUS find_forced_user(connection_struct *conn, bool vuser_is_guest, fstring username)
508 int snum = conn->params->service;
509 char *fuser, *found_username;
512 if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S",
513 lp_servicename(snum)))) {
514 return NT_STATUS_NO_MEMORY;
517 result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest,
518 &conn->uid, &conn->gid, &found_username,
519 &conn->nt_user_token);
520 if (!NT_STATUS_IS_OK(result)) {
524 fstrcpy(username, found_username);
527 TALLOC_FREE(found_username);
532 * Go through lookup_name etc to find the force'd group.
534 * Create a new token from src_token, replacing the primary group sid with the
538 static NTSTATUS find_forced_group(bool force_user,
539 int snum, const char *username,
543 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
546 enum lsa_SidType type;
548 bool user_must_be_member = False;
551 ZERO_STRUCTP(pgroup_sid);
554 mem_ctx = talloc_new(NULL);
555 if (mem_ctx == NULL) {
556 DEBUG(0, ("talloc_new failed\n"));
557 return NT_STATUS_NO_MEMORY;
560 groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
561 if (groupname == NULL) {
562 DEBUG(1, ("talloc_strdup failed\n"));
563 result = NT_STATUS_NO_MEMORY;
567 if (groupname[0] == '+') {
568 user_must_be_member = True;
572 groupname = talloc_string_sub(mem_ctx, groupname,
573 "%S", lp_servicename(snum));
575 if (!lookup_name_smbconf(mem_ctx, groupname,
576 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
577 NULL, NULL, &group_sid, &type)) {
578 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
583 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
584 (type != SID_NAME_WKN_GRP)) {
585 DEBUG(10, ("%s is a %s, not a group\n", groupname,
586 sid_type_lookup(type)));
590 if (!sid_to_gid(&group_sid, &gid)) {
591 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
592 sid_string_static(&group_sid), groupname));
597 * If the user has been forced and the forced group starts with a '+',
598 * then we only set the group to be the forced group if the forced
599 * user is a member of that group. Otherwise, the meaning of the '+'
603 if (force_user && user_must_be_member) {
604 if (user_in_group_sid(username, &group_sid)) {
605 sid_copy(pgroup_sid, &group_sid);
607 DEBUG(3,("Forced group %s for member %s\n",
608 groupname, username));
610 DEBUG(0,("find_forced_group: forced user %s is not a member "
611 "of forced group %s. Disallowing access.\n",
612 username, groupname ));
613 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
617 sid_copy(pgroup_sid, &group_sid);
619 DEBUG(3,("Forced group %s\n", groupname));
622 result = NT_STATUS_OK;
624 TALLOC_FREE(mem_ctx);
628 /****************************************************************************
629 Make a connection, given the snum to connect to, and the vuser of the
630 connecting user if appropriate.
631 ****************************************************************************/
633 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
638 struct passwd *pass = NULL;
640 connection_struct *conn;
645 char addr[INET6_ADDRSTRLEN];
649 SET_STAT_INVALID(st);
651 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
657 DEBUG(0,("Couldn't find free connection.\n"));
658 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
662 conn->params->service = snum;
663 conn->nt_user_token = NULL;
665 if (lp_guest_only(snum)) {
666 const char *guestname = lp_guestaccount();
668 char *found_username = NULL;
671 pass = getpwnam_alloc(NULL, guestname);
673 DEBUG(0,("make_connection_snum: Invalid guest "
674 "account %s??\n",guestname));
676 *status = NT_STATUS_NO_SUCH_USER;
679 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
680 &conn->uid, &conn->gid,
682 &conn->nt_user_token);
683 if (!NT_STATUS_IS_OK(status2)) {
689 fstrcpy(user, found_username);
690 string_set(&conn->user,user);
691 conn->force_user = True;
692 TALLOC_FREE(found_username);
694 DEBUG(3,("Guest only user %s\n",user));
697 if (!lp_guest_ok(snum)) {
698 DEBUG(2, ("guest user (from session setup) "
699 "not permitted to access this share "
700 "(%s)\n", lp_servicename(snum)));
702 *status = NT_STATUS_ACCESS_DENIED;
706 if (!user_ok_token(vuser->user.unix_name,
707 vuser->nt_user_token, snum)) {
708 DEBUG(2, ("user '%s' (from session setup) not "
709 "permitted to access this share "
710 "(%s)\n", vuser->user.unix_name,
711 lp_servicename(snum)));
713 *status = NT_STATUS_ACCESS_DENIED;
717 conn->vuid = vuser->vuid;
718 conn->uid = vuser->uid;
719 conn->gid = vuser->gid;
720 string_set(&conn->user,vuser->user.unix_name);
721 fstrcpy(user,vuser->user.unix_name);
722 guest = vuser->guest;
723 } else if (lp_security() == SEC_SHARE) {
725 char *found_username = NULL;
727 /* add it as a possible user name if we
728 are in share mode security */
729 add_session_user(lp_servicename(snum));
730 /* shall we let them in? */
731 if (!authorise_login(snum,user,password,&guest)) {
732 DEBUG( 2, ( "Invalid username/password for [%s]\n",
733 lp_servicename(snum)) );
735 *status = NT_STATUS_WRONG_PASSWORD;
738 pass = Get_Pwnam(user);
739 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
740 &conn->uid, &conn->gid,
742 &conn->nt_user_token);
743 if (!NT_STATUS_IS_OK(status2)) {
748 fstrcpy(user, found_username);
749 string_set(&conn->user,user);
750 TALLOC_FREE(found_username);
751 conn->force_user = True;
753 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
755 *status = NT_STATUS_ACCESS_DENIED;
759 add_session_user(user);
761 safe_strcpy(conn->client_address,
762 client_addr(get_client_fd(),addr,sizeof(addr)),
763 sizeof(conn->client_address)-1);
764 conn->num_files_open = 0;
765 conn->lastused = conn->lastused_count = time(NULL);
767 conn->printer = (strncmp(dev,"LPT",3) == 0);
768 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
769 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
772 /* Case options for the share. */
773 if (lp_casesensitive(snum) == Auto) {
774 /* We will be setting this per packet. Set to be case
775 * insensitive for now. */
776 conn->case_sensitive = False;
778 conn->case_sensitive = (bool)lp_casesensitive(snum);
781 conn->case_preserve = lp_preservecase(snum);
782 conn->short_case_preserve = lp_shortpreservecase(snum);
784 conn->veto_list = NULL;
785 conn->hide_list = NULL;
786 conn->veto_oplock_list = NULL;
787 conn->aio_write_behind_list = NULL;
788 string_set(&conn->dirpath,"");
789 string_set(&conn->user,user);
791 conn->read_only = lp_readonly(SNUM(conn));
792 conn->admin_user = False;
795 * If force user is true, then store the given userid and the gid of
796 * the user we're forcing.
797 * For auxiliary groups see below.
800 if (*lp_force_user(snum)) {
803 status2 = find_forced_user(conn,
804 (vuser != NULL) && vuser->guest,
806 if (!NT_STATUS_IS_OK(status2)) {
811 string_set(&conn->user,user);
812 conn->force_user = True;
813 DEBUG(3,("Forced user %s\n",user));
817 * If force group is true, then override
818 * any groupid stored for the connecting user.
821 if (*lp_force_group(snum)) {
825 status2 = find_forced_group(conn->force_user,
827 &group_sid, &conn->gid);
828 if (!NT_STATUS_IS_OK(status2)) {
834 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
836 /* Not force user and not security=share, but force
837 * group. vuser has a token to copy */
839 conn->nt_user_token = dup_nt_token(
840 NULL, vuser->nt_user_token);
841 if (conn->nt_user_token == NULL) {
842 DEBUG(0, ("dup_nt_token failed\n"));
844 *status = NT_STATUS_NO_MEMORY;
849 /* If conn->nt_user_token is still NULL, we have
850 * security=share. This means ignore the SID, as we had no
851 * vuser to copy from */
853 if (conn->nt_user_token != NULL) {
854 /* Overwrite the primary group sid */
855 sid_copy(&conn->nt_user_token->user_sids[1],
859 conn->force_group = True;
862 if (conn->nt_user_token != NULL) {
865 /* We have a share-specific token from force [user|group].
866 * This means we have to create the list of unix groups from
867 * the list of sids. */
872 for (i=0; i<conn->nt_user_token->num_sids; i++) {
874 DOM_SID *sid = &conn->nt_user_token->user_sids[i];
876 if (!sid_to_gid(sid, &gid)) {
877 DEBUG(10, ("Could not convert SID %s to gid, "
879 sid_string_static(sid)));
882 if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
884 DEBUG(0, ("add_gid_to_array_unique failed\n"));
886 *status = NT_STATUS_NO_MEMORY;
894 pstrcpy(s,lp_pathname(snum));
895 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
896 conn->connectpath, conn->gid,
897 get_current_username(),
898 current_user_info.domain,
900 set_conn_connectpath(conn,s);
901 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
902 lp_servicename(snum)));
906 * New code to check if there's a share security descripter
907 * added from NT server manager. This is done after the
908 * smb.conf checks are done as we need a uid and token. JRA.
913 bool can_write = False;
914 NT_USER_TOKEN *token = conn->nt_user_token ?
915 conn->nt_user_token :
916 (vuser ? vuser->nt_user_token : NULL);
919 * I don't believe this can happen. But the
920 * logic above is convoluted enough to confuse
921 * automated checkers, so be sure. JRA.
925 DEBUG(0,("make_connection: connection to %s "
926 "denied due to missing "
928 lp_servicename(snum)));
930 *status = NT_STATUS_ACCESS_DENIED;
934 can_write = share_access_check(token,
935 lp_servicename(snum),
939 if (!share_access_check(token,
940 lp_servicename(snum),
942 /* No access, read or write. */
943 DEBUG(0,("make_connection: connection to %s "
944 "denied due to security "
946 lp_servicename(snum)));
948 *status = NT_STATUS_ACCESS_DENIED;
951 conn->read_only = True;
955 /* Initialise VFS function pointers */
957 if (!smbd_vfs_init(conn)) {
958 DEBUG(0, ("vfs_init failed for service %s\n",
959 lp_servicename(snum)));
961 *status = NT_STATUS_BAD_NETWORK_NAME;
966 * If widelinks are disallowed we need to canonicalise the connect
967 * path here to ensure we don't have any symlinks in the
968 * connectpath. We will be checking all paths on this connection are
969 * below this directory. We must do this after the VFS init as we
970 * depend on the realpath() pointer in the vfs table. JRA.
972 if (!lp_widelinks(snum)) {
974 pstrcpy(s,conn->connectpath);
975 canonicalize_path(conn, s);
976 set_conn_connectpath(conn,s);
979 if ((!conn->printer) && (!conn->ipc)) {
980 conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
981 smbd_messaging_context(),
982 smbd_event_context(),
986 /* ROOT Activities: */
988 * Enforce the max connections parameter.
991 if ((lp_max_connections(snum) > 0)
992 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
993 lp_max_connections(snum))) {
995 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
996 lp_max_connections(snum), lp_servicename(snum)));
998 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
1003 * Get us an entry in the connections db
1005 if (!claim_connection(conn, lp_servicename(snum), 0)) {
1006 DEBUG(1, ("Could not store connections entry\n"));
1008 *status = NT_STATUS_INTERNAL_DB_ERROR;
1012 /* Preexecs are done here as they might make the dir we are to ChDir
1014 /* execute any "root preexec = " line */
1015 if (*lp_rootpreexec(snum)) {
1017 pstrcpy(cmd,lp_rootpreexec(snum));
1018 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1019 conn->connectpath, conn->gid,
1020 get_current_username(),
1021 current_user_info.domain,
1023 DEBUG(5,("cmd=%s\n",cmd));
1024 ret = smbrun(cmd,NULL);
1025 if (ret != 0 && lp_rootpreexec_close(snum)) {
1026 DEBUG(1,("root preexec gave %d - failing "
1027 "connection\n", ret));
1028 yield_connection(conn, lp_servicename(snum));
1030 *status = NT_STATUS_ACCESS_DENIED;
1035 /* USER Activites: */
1036 if (!change_to_user(conn, conn->vuid)) {
1037 /* No point continuing if they fail the basic checks */
1038 DEBUG(0,("Can't become connected user!\n"));
1039 yield_connection(conn, lp_servicename(snum));
1041 *status = NT_STATUS_LOGON_FAILURE;
1045 /* Remember that a different vuid can connect later without these
1048 /* Preexecs are done here as they might make the dir we are to ChDir
1051 /* execute any "preexec = " line */
1052 if (*lp_preexec(snum)) {
1054 pstrcpy(cmd,lp_preexec(snum));
1055 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1056 conn->connectpath, conn->gid,
1057 get_current_username(),
1058 current_user_info.domain,
1060 ret = smbrun(cmd,NULL);
1061 if (ret != 0 && lp_preexec_close(snum)) {
1062 DEBUG(1,("preexec gave %d - failing connection\n",
1064 change_to_root_user();
1065 yield_connection(conn, lp_servicename(snum));
1067 *status = NT_STATUS_ACCESS_DENIED;
1072 #ifdef WITH_FAKE_KASERVER
1073 if (lp_afs_share(snum)) {
1078 /* Add veto/hide lists */
1079 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1080 set_namearray( &conn->veto_list, lp_veto_files(snum));
1081 set_namearray( &conn->hide_list, lp_hide_files(snum));
1082 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1085 /* Invoke VFS make connection hook - do this before the VFS_STAT call
1086 to allow any filesystems needing user credentials to initialize
1089 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
1090 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1091 change_to_root_user();
1092 yield_connection(conn, lp_servicename(snum));
1094 *status = NT_STATUS_UNSUCCESSFUL;
1098 /* win2000 does not check the permissions on the directory
1099 during the tree connect, instead relying on permission
1100 check during individual operations. To match this behaviour
1101 I have disabled this chdir check (tridge) */
1102 /* the alternative is just to check the directory exists */
1103 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1104 !S_ISDIR(st.st_mode)) {
1105 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1106 DEBUG(0,("'%s' is not a directory, when connecting to "
1107 "[%s]\n", conn->connectpath,
1108 lp_servicename(snum)));
1110 DEBUG(0,("'%s' does not exist or permission denied "
1111 "when connecting to [%s] Error was %s\n",
1112 conn->connectpath, lp_servicename(snum),
1115 change_to_root_user();
1116 /* Call VFS disconnect hook */
1117 SMB_VFS_DISCONNECT(conn);
1118 yield_connection(conn, lp_servicename(snum));
1120 *status = NT_STATUS_BAD_NETWORK_NAME;
1124 string_set(&conn->origpath,conn->connectpath);
1126 #if SOFTLINK_OPTIMISATION
1127 /* resolve any soft links early if possible */
1128 if (vfs_ChDir(conn,conn->connectpath) == 0) {
1129 TALLOC_CTX *ctx = talloc_stackframe();
1130 char *s = vfs_GetWd(ctx,s);
1132 *status = map_nt_error_from_unix(errno);
1135 set_conn_connectpath(conn,s);
1136 vfs_ChDir(conn,conn->connectpath);
1142 * Print out the 'connected as' stuff here as we need
1143 * to know the effective uid and gid we will be using
1144 * (at least initially).
1147 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1148 dbgtext( "%s (%s) ", get_remote_machine_name(),
1149 conn->client_address );
1150 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1151 dbgtext( "connect to service %s ", lp_servicename(snum) );
1152 dbgtext( "initially as user %s ", user );
1153 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1154 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1157 /* we've finished with the user stuff - go back to root */
1158 change_to_root_user();
1162 /***************************************************************************************
1163 Simple wrapper function for make_connection() to include a call to
1165 **************************************************************************************/
1167 connection_struct *make_connection_with_chdir(const char *service_in,
1169 const char *dev, uint16 vuid,
1172 connection_struct *conn = NULL;
1174 conn = make_connection(service_in, password, dev, vuid, status);
1177 * make_connection() does not change the directory for us any more
1178 * so we have to do it as a separate step --jerry
1181 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1182 DEBUG(0,("move_driver_to_download_area: Can't change "
1183 "directory to %s for [print$] (%s)\n",
1184 conn->connectpath,strerror(errno)));
1185 yield_connection(conn, lp_servicename(SNUM(conn)));
1187 *status = NT_STATUS_UNSUCCESSFUL;
1194 /****************************************************************************
1195 Make a connection to a service.
1198 ****************************************************************************/
1200 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
1201 const char *pdev, uint16 vuid,
1205 user_struct *vuser = NULL;
1209 char addr[INET6_ADDRSTRLEN];
1213 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1215 if (!non_root_mode() && (euid = geteuid()) != 0) {
1216 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1217 "(%u)\n", (unsigned int)euid ));
1218 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1221 if (conn_num_open() > 2047) {
1222 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1226 if(lp_security() != SEC_SHARE) {
1227 vuser = get_valid_user_struct(vuid);
1229 DEBUG(1,("make_connection: refusing to connect with "
1230 "no session setup\n"));
1231 *status = NT_STATUS_ACCESS_DENIED;
1236 /* Logic to try and connect to the correct [homes] share, preferably
1237 without too many getpwnam() lookups. This is particulary nasty for
1238 winbind usernames, where the share name isn't the same as unix
1241 The snum of the homes share is stored on the vuser at session setup
1245 if (strequal(service_in,HOMES_NAME)) {
1246 if(lp_security() != SEC_SHARE) {
1247 DATA_BLOB no_pw = data_blob_null;
1248 if (vuser->homes_snum == -1) {
1249 DEBUG(2, ("[homes] share not available for "
1250 "this user because it was not found "
1251 "or created at session setup "
1253 *status = NT_STATUS_BAD_NETWORK_NAME;
1256 DEBUG(5, ("making a connection to [homes] service "
1257 "created at session setup time\n"));
1258 return make_connection_snum(vuser->homes_snum,
1262 /* Security = share. Try with
1263 * current_user_info.smb_name as the username. */
1264 if (*current_user_info.smb_name) {
1265 fstring unix_username;
1266 fstrcpy(unix_username,
1267 current_user_info.smb_name);
1268 map_username(unix_username);
1269 snum = find_service(unix_username);
1272 DEBUG(5, ("making a connection to 'homes' "
1273 "service %s based on "
1274 "security=share\n", service_in));
1275 return make_connection_snum(snum, NULL,
1280 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1281 && strequal(service_in,
1282 lp_servicename(vuser->homes_snum))) {
1283 DATA_BLOB no_pw = data_blob_null;
1284 DEBUG(5, ("making a connection to 'homes' service [%s] "
1285 "created at session setup time\n", service_in));
1286 return make_connection_snum(vuser->homes_snum,
1291 fstrcpy(service, service_in);
1293 strlower_m(service);
1295 snum = find_service(service);
1298 if (strequal(service,"IPC$") ||
1299 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1300 DEBUG(3,("refusing IPC connection to %s\n", service));
1301 *status = NT_STATUS_ACCESS_DENIED;
1305 DEBUG(0,("%s (%s) couldn't find service %s\n",
1306 get_remote_machine_name(),
1307 client_addr(get_client_fd(),addr,sizeof(addr)),
1309 *status = NT_STATUS_BAD_NETWORK_NAME;
1313 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1314 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1315 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1316 "(pointing to %s)\n",
1317 service, lp_msdfs_proxy(snum)));
1318 *status = NT_STATUS_BAD_NETWORK_NAME;
1322 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1324 return make_connection_snum(snum, vuser,
1329 /****************************************************************************
1331 ****************************************************************************/
1333 void close_cnum(connection_struct *conn, uint16 vuid)
1336 pipe_close_conn(conn);
1338 file_close_conn(conn);
1339 dptr_closecnum(conn);
1342 change_to_root_user();
1344 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1345 get_remote_machine_name(),
1346 conn->client_address,
1347 lp_servicename(SNUM(conn))));
1349 /* Call VFS disconnect hook */
1350 SMB_VFS_DISCONNECT(conn);
1352 yield_connection(conn, lp_servicename(SNUM(conn)));
1354 /* make sure we leave the directory available for unmount */
1355 vfs_ChDir(conn, "/");
1357 /* execute any "postexec = " line */
1358 if (*lp_postexec(SNUM(conn)) &&
1359 change_to_user(conn, vuid)) {
1361 pstrcpy(cmd,lp_postexec(SNUM(conn)));
1362 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1363 conn->connectpath, conn->gid,
1364 get_current_username(),
1365 current_user_info.domain,
1368 change_to_root_user();
1371 change_to_root_user();
1372 /* execute any "root postexec = " line */
1373 if (*lp_rootpostexec(SNUM(conn))) {
1375 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
1376 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1377 conn->connectpath, conn->gid,
1378 get_current_username(),
1379 current_user_info.domain,