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 /****************************************************************************
26 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
27 absolute path stating in / and not ending in /.
28 Observent people will notice a similarity between this and check_path_syntax :-).
29 ****************************************************************************/
31 void set_conn_connectpath(connection_struct *conn, const pstring connectpath)
35 const char *s = connectpath;
36 BOOL start_of_name_component = True;
38 *d++ = '/'; /* Always start with root. */
42 /* Eat multiple '/' */
46 if ((d > destname + 1) && (*s != '\0')) {
49 start_of_name_component = True;
53 if (start_of_name_component) {
54 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
55 /* Uh oh - "/../" or "/..\0" ! */
57 /* Go past the ../ or .. */
61 s += 2; /* Go past the .. */
64 /* If we just added a '/' - delete it */
65 if ((d > destname) && (*(d-1) == '/')) {
70 /* Are we at the start ? Can't go back further if so. */
72 *d++ = '/'; /* Can't delete root */
75 /* Go back one level... */
76 /* Decrement d first as d points to the *next* char to write into. */
77 for (d--; d > destname; d--) {
82 /* We're still at the start of a name component, just the previous one. */
84 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
85 /* Component of pathname can't be "." only - skip the '.' . */
99 /* Get the size of the next MB character. */
100 next_codepoint(s,&siz);
121 start_of_name_component = False;
125 /* And must not end in '/' */
126 if (d > destname + 1 && (*(d-1) == '/')) {
130 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
131 lp_servicename(SNUM(conn)), destname ));
133 string_set(&conn->connectpath, destname);
136 /****************************************************************************
137 Load parameters specific to a connection/service.
138 ****************************************************************************/
140 BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir)
142 static connection_struct *last_conn;
143 static uint16 last_flags;
151 conn->lastused_count++;
156 vfs_ChDir(conn,conn->connectpath) != 0 &&
157 vfs_ChDir(conn,conn->origpath) != 0) {
158 DEBUG(0,("chdir (%s) failed\n",
163 if ((conn == last_conn) && (last_flags == flags)) {
170 /* Obey the client case sensitivity requests - only for clients that support it. */
171 switch (lp_casesensitive(snum)) {
174 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
175 enum remote_arch_types ra_type = get_remote_arch();
176 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
177 /* Client can't support per-packet case sensitive pathnames. */
178 conn->case_sensitive = False;
180 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
185 conn->case_sensitive = True;
188 conn->case_sensitive = False;
194 /****************************************************************************
195 Add a home service. Returns the new service number or -1 if fail.
196 ****************************************************************************/
198 int add_home_service(const char *service, const char *username, const char *homedir)
202 if (!service || !homedir)
205 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
209 * If this is a winbindd provided username, remove
210 * the domain component before adding the service.
211 * Log a warning if the "path=" parameter does not
212 * include any macros.
216 const char *p = strchr(service,*lp_winbind_separator());
218 /* We only want the 'user' part of the string */
224 if (!lp_add_home(service, iHomeService, username, homedir)) {
228 return lp_servicenumber(service);
234 * Find a service entry.
236 * @param service is modified (to canonical form??)
239 int find_service(fstring service)
243 all_string_sub(service,"\\","/",0);
245 iService = lp_servicenumber(service);
247 /* now handle the special case of a home directory */
249 char *phome_dir = get_user_home_dir(service);
253 * Try mapping the servicename, it may
254 * be a Windows to unix mapped user name.
256 if(map_username(service))
257 phome_dir = get_user_home_dir(service);
260 DEBUG(3,("checking for home directory %s gave %s\n",service,
261 phome_dir?phome_dir:"(NULL)"));
263 iService = add_home_service(service,service /* 'username' */, phome_dir);
266 /* If we still don't have a service, attempt to add it as a printer. */
270 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
271 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
272 if (pcap_printername_ok(service)) {
273 DEBUG(3,("%s is a valid printer name\n", service));
274 DEBUG(3,("adding %s as a printer service\n", service));
275 lp_add_printer(service, iPrinterService);
276 iService = lp_servicenumber(service);
278 DEBUG(0,("failed to add %s as a printer service!\n", service));
281 DEBUG(3,("%s is not a valid printer name\n", service));
286 /* Check for default vfs service? Unsure whether to implement this */
290 /* just possibly it's a default service? */
292 char *pdefservice = lp_defaultservice();
293 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
295 * We need to do a local copy here as lp_defaultservice()
296 * returns one of the rotating lp_string buffers that
297 * could get overwritten by the recursive find_service() call
298 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
301 pstrcpy(defservice, pdefservice);
302 iService = find_service(defservice);
304 all_string_sub(service, "_","/",0);
305 iService = lp_add_service(service, iService);
310 /* Is it a usershare service ? */
311 if (iService < 0 && *lp_usershare_path()) {
312 /* Ensure the name is canonicalized. */
314 iService = load_usershare_service(service);
318 if (!VALID_SNUM(iService)) {
319 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
325 DEBUG(3,("find_service() failed to find service %s\n", service));
331 /****************************************************************************
332 do some basic sainity checks on the share.
333 This function modifies dev, ecode.
334 ****************************************************************************/
336 static NTSTATUS share_sanity_checks(int snum, fstring dev)
339 if (!lp_snum_ok(snum) ||
340 !check_access(smbd_server_fd(),
341 lp_hostsallow(snum), lp_hostsdeny(snum))) {
342 return NT_STATUS_ACCESS_DENIED;
345 if (dev[0] == '?' || !dev[0]) {
346 if (lp_print_ok(snum)) {
347 fstrcpy(dev,"LPT1:");
348 } else if (strequal(lp_fstype(snum), "IPC")) {
357 if (lp_print_ok(snum)) {
358 if (!strequal(dev, "LPT1:")) {
359 return NT_STATUS_BAD_DEVICE_TYPE;
361 } else if (strequal(lp_fstype(snum), "IPC")) {
362 if (!strequal(dev, "IPC")) {
363 return NT_STATUS_BAD_DEVICE_TYPE;
365 } else if (!strequal(dev, "A:")) {
366 return NT_STATUS_BAD_DEVICE_TYPE;
369 /* Behave as a printer if we are supposed to */
370 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
371 fstrcpy(dev, "LPT1:");
377 static NTSTATUS find_forced_user(int snum, BOOL vuser_is_guest,
378 uid_t *uid, gid_t *gid, fstring username,
379 struct nt_user_token **token)
382 char *fuser, *found_username;
383 struct nt_user_token *tmp_token;
386 if (!(mem_ctx = talloc_new(NULL))) {
387 DEBUG(0, ("talloc_new failed\n"));
388 return NT_STATUS_NO_MEMORY;
391 if (!(fuser = talloc_string_sub(mem_ctx, lp_force_user(snum), "%S",
392 lp_servicename(snum)))) {
393 TALLOC_FREE(mem_ctx);
394 return NT_STATUS_NO_MEMORY;
398 result = create_token_from_username(mem_ctx, fuser, vuser_is_guest,
399 uid, gid, &found_username,
401 if (!NT_STATUS_IS_OK(result)) {
402 TALLOC_FREE(mem_ctx);
406 if (!(*token = dup_nt_token(NULL, tmp_token))) {
407 TALLOC_FREE(mem_ctx);
408 return NT_STATUS_NO_MEMORY;
411 fstrcpy(username, found_username);
413 TALLOC_FREE(mem_ctx);
418 * Go through lookup_name etc to find the force'd group.
420 * Create a new token from src_token, replacing the primary group sid with the
424 static NTSTATUS find_forced_group(BOOL force_user,
425 int snum, const char *username,
429 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
432 enum lsa_SidType type;
434 BOOL user_must_be_member = False;
437 mem_ctx = talloc_new(NULL);
438 if (mem_ctx == NULL) {
439 DEBUG(0, ("talloc_new failed\n"));
440 return NT_STATUS_NO_MEMORY;
443 groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
444 if (groupname == NULL) {
445 DEBUG(1, ("talloc_strdup failed\n"));
446 result = NT_STATUS_NO_MEMORY;
450 if (groupname[0] == '+') {
451 user_must_be_member = True;
455 groupname = talloc_string_sub(mem_ctx, groupname,
456 "%S", lp_servicename(snum));
458 if (!lookup_name_smbconf(mem_ctx, groupname,
459 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
460 NULL, NULL, &group_sid, &type)) {
461 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
466 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
467 (type != SID_NAME_WKN_GRP)) {
468 DEBUG(10, ("%s is a %s, not a group\n", groupname,
469 sid_type_lookup(type)));
473 if (!sid_to_gid(&group_sid, &gid)) {
474 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
475 sid_string_static(&group_sid), groupname));
480 * If the user has been forced and the forced group starts with a '+',
481 * then we only set the group to be the forced group if the forced
482 * user is a member of that group. Otherwise, the meaning of the '+'
486 if (force_user && user_must_be_member) {
487 if (user_in_group_sid(username, &group_sid)) {
488 sid_copy(pgroup_sid, &group_sid);
490 DEBUG(3,("Forced group %s for member %s\n",
491 groupname, username));
494 sid_copy(pgroup_sid, &group_sid);
496 DEBUG(3,("Forced group %s\n", groupname));
499 result = NT_STATUS_OK;
501 TALLOC_FREE(mem_ctx);
505 /****************************************************************************
506 Make a connection, given the snum to connect to, and the vuser of the
507 connecting user if appropriate.
508 ****************************************************************************/
510 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
515 struct passwd *pass = NULL;
517 connection_struct *conn;
525 SET_STAT_INVALID(st);
527 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
533 DEBUG(0,("Couldn't find free connection.\n"));
534 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
538 conn->nt_user_token = NULL;
540 if (lp_guest_only(snum)) {
541 const char *guestname = lp_guestaccount();
543 char *found_username;
545 pass = getpwnam_alloc(NULL, guestname);
547 DEBUG(0,("make_connection_snum: Invalid guest "
548 "account %s??\n",guestname));
550 *status = NT_STATUS_NO_SUCH_USER;
553 status2 = create_token_from_username(NULL, pass->pw_name, True,
554 &conn->uid, &conn->gid,
556 &conn->nt_user_token);
557 if (!NT_STATUS_IS_OK(status2)) {
562 fstrcpy(user, found_username);
563 string_set(&conn->user,user);
564 conn->force_user = True;
566 DEBUG(3,("Guest only user %s\n",user));
569 if (!lp_guest_ok(snum)) {
570 DEBUG(2, ("guest user (from session setup) "
571 "not permitted to access this share "
572 "(%s)\n", lp_servicename(snum)));
574 *status = NT_STATUS_ACCESS_DENIED;
578 if (!user_ok_token(vuser->user.unix_name,
579 vuser->nt_user_token, snum)) {
580 DEBUG(2, ("user '%s' (from session setup) not "
581 "permitted to access this share "
582 "(%s)\n", vuser->user.unix_name,
583 lp_servicename(snum)));
585 *status = NT_STATUS_ACCESS_DENIED;
589 conn->vuid = vuser->vuid;
590 conn->uid = vuser->uid;
591 conn->gid = vuser->gid;
592 string_set(&conn->user,vuser->user.unix_name);
593 fstrcpy(user,vuser->user.unix_name);
594 guest = vuser->guest;
595 } else if (lp_security() == SEC_SHARE) {
597 char *found_username;
598 /* add it as a possible user name if we
599 are in share mode security */
600 add_session_user(lp_servicename(snum));
601 /* shall we let them in? */
602 if (!authorise_login(snum,user,password,&guest)) {
603 DEBUG( 2, ( "Invalid username/password for [%s]\n",
604 lp_servicename(snum)) );
606 *status = NT_STATUS_WRONG_PASSWORD;
609 pass = Get_Pwnam(user);
610 status2 = create_token_from_username(NULL, pass->pw_name, True,
611 &conn->uid, &conn->gid,
613 &conn->nt_user_token);
614 if (!NT_STATUS_IS_OK(status2)) {
619 fstrcpy(user, found_username);
620 string_set(&conn->user,user);
621 conn->force_user = True;
623 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
625 *status = NT_STATUS_ACCESS_DENIED;
629 add_session_user(user);
631 safe_strcpy(conn->client_address, client_addr(),
632 sizeof(conn->client_address)-1);
633 conn->num_files_open = 0;
634 conn->lastused = conn->lastused_count = time(NULL);
635 conn->params->service = snum;
637 conn->printer = (strncmp(dev,"LPT",3) == 0);
638 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
639 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
642 /* Case options for the share. */
643 if (lp_casesensitive(snum) == Auto) {
644 /* We will be setting this per packet. Set to be case
645 * insensitive for now. */
646 conn->case_sensitive = False;
648 conn->case_sensitive = (BOOL)lp_casesensitive(snum);
651 conn->case_preserve = lp_preservecase(snum);
652 conn->short_case_preserve = lp_shortpreservecase(snum);
654 conn->veto_list = NULL;
655 conn->hide_list = NULL;
656 conn->veto_oplock_list = NULL;
657 conn->aio_write_behind_list = NULL;
658 string_set(&conn->dirpath,"");
659 string_set(&conn->user,user);
661 conn->read_only = lp_readonly(SNUM(conn));
662 conn->admin_user = False;
665 * If force user is true, then store the given userid and the gid of
666 * the user we're forcing.
667 * For auxiliary groups see below.
670 if (*lp_force_user(snum)) {
673 status2 = find_forced_user(snum,
674 (vuser != NULL) && vuser->guest,
675 &conn->uid, &conn->gid, user,
676 &conn->nt_user_token);
677 if (!NT_STATUS_IS_OK(status2)) {
682 string_set(&conn->user,user);
683 conn->force_user = True;
684 DEBUG(3,("Forced user %s\n",user));
688 * If force group is true, then override
689 * any groupid stored for the connecting user.
692 if (*lp_force_group(snum)) {
696 status2 = find_forced_group(conn->force_user,
698 &group_sid, &conn->gid);
699 if (!NT_STATUS_IS_OK(status2)) {
705 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
707 /* Not force user and not security=share, but force
708 * group. vuser has a token to copy */
710 conn->nt_user_token = dup_nt_token(
711 NULL, vuser->nt_user_token);
712 if (conn->nt_user_token == NULL) {
713 DEBUG(0, ("dup_nt_token failed\n"));
715 *status = NT_STATUS_NO_MEMORY;
720 /* If conn->nt_user_token is still NULL, we have
721 * security=share. This means ignore the SID, as we had no
722 * vuser to copy from */
724 if (conn->nt_user_token != NULL) {
725 /* Overwrite the primary group sid */
726 sid_copy(&conn->nt_user_token->user_sids[1],
730 conn->force_group = True;
733 if (conn->nt_user_token != NULL) {
736 /* We have a share-specific token from force [user|group].
737 * This means we have to create the list of unix groups from
738 * the list of sids. */
743 for (i=0; i<conn->nt_user_token->num_sids; i++) {
745 DOM_SID *sid = &conn->nt_user_token->user_sids[i];
747 if (!sid_to_gid(sid, &gid)) {
748 DEBUG(10, ("Could not convert SID %s to gid, "
750 sid_string_static(sid)));
753 add_gid_to_array_unique(NULL, gid, &conn->groups,
760 pstrcpy(s,lp_pathname(snum));
761 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
762 conn->connectpath, conn->gid,
763 get_current_username(),
764 current_user_info.domain,
766 set_conn_connectpath(conn,s);
767 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
768 lp_servicename(snum)));
772 * New code to check if there's a share security descripter
773 * added from NT server manager. This is done after the
774 * smb.conf checks are done as we need a uid and token. JRA.
779 NT_USER_TOKEN *token = conn->nt_user_token ?
780 conn->nt_user_token : vuser->nt_user_token;
782 BOOL can_write = share_access_check(token,
783 lp_servicename(snum),
787 if (!share_access_check(token,
788 lp_servicename(snum),
790 /* No access, read or write. */
791 DEBUG(0,("make_connection: connection to %s "
792 "denied due to security "
794 lp_servicename(snum)));
796 *status = NT_STATUS_ACCESS_DENIED;
799 conn->read_only = True;
803 /* Initialise VFS function pointers */
805 if (!smbd_vfs_init(conn)) {
806 DEBUG(0, ("vfs_init failed for service %s\n",
807 lp_servicename(snum)));
809 *status = NT_STATUS_BAD_NETWORK_NAME;
814 * If widelinks are disallowed we need to canonicalise the connect
815 * path here to ensure we don't have any symlinks in the
816 * connectpath. We will be checking all paths on this connection are
817 * below this directory. We must do this after the VFS init as we
818 * depend on the realpath() pointer in the vfs table. JRA.
820 if (!lp_widelinks(snum)) {
822 pstrcpy(s,conn->connectpath);
823 canonicalize_path(conn, s);
824 set_conn_connectpath(conn,s);
827 /* ROOT Activities: */
828 /* check number of connections */
829 if (!claim_connection(conn,
830 lp_servicename(snum),
831 lp_max_connections(snum),
833 DEBUG(1,("too many connections - rejected\n"));
835 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
839 /* Preexecs are done here as they might make the dir we are to ChDir
841 /* execute any "root preexec = " line */
842 if (*lp_rootpreexec(snum)) {
844 pstrcpy(cmd,lp_rootpreexec(snum));
845 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
846 conn->connectpath, conn->gid,
847 get_current_username(),
848 current_user_info.domain,
850 DEBUG(5,("cmd=%s\n",cmd));
851 ret = smbrun(cmd,NULL);
852 if (ret != 0 && lp_rootpreexec_close(snum)) {
853 DEBUG(1,("root preexec gave %d - failing "
854 "connection\n", ret));
855 yield_connection(conn, lp_servicename(snum));
857 *status = NT_STATUS_ACCESS_DENIED;
862 /* USER Activites: */
863 if (!change_to_user(conn, conn->vuid)) {
864 /* No point continuing if they fail the basic checks */
865 DEBUG(0,("Can't become connected user!\n"));
866 yield_connection(conn, lp_servicename(snum));
868 *status = NT_STATUS_LOGON_FAILURE;
872 /* Remember that a different vuid can connect later without these
875 /* Preexecs are done here as they might make the dir we are to ChDir
878 /* execute any "preexec = " line */
879 if (*lp_preexec(snum)) {
881 pstrcpy(cmd,lp_preexec(snum));
882 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
883 conn->connectpath, conn->gid,
884 get_current_username(),
885 current_user_info.domain,
887 ret = smbrun(cmd,NULL);
888 if (ret != 0 && lp_preexec_close(snum)) {
889 DEBUG(1,("preexec gave %d - failing connection\n",
891 change_to_root_user();
892 yield_connection(conn, lp_servicename(snum));
894 *status = NT_STATUS_ACCESS_DENIED;
899 #ifdef WITH_FAKE_KASERVER
900 if (lp_afs_share(snum)) {
905 /* Add veto/hide lists */
906 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
907 set_namearray( &conn->veto_list, lp_veto_files(snum));
908 set_namearray( &conn->hide_list, lp_hide_files(snum));
909 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
912 /* Invoke VFS make connection hook - do this before the VFS_STAT call
913 to allow any filesystems needing user credentials to initialize
916 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
917 DEBUG(0,("make_connection: VFS make connection failed!\n"));
918 change_to_root_user();
919 yield_connection(conn, lp_servicename(snum));
921 *status = NT_STATUS_UNSUCCESSFUL;
925 /* win2000 does not check the permissions on the directory
926 during the tree connect, instead relying on permission
927 check during individual operations. To match this behaviour
928 I have disabled this chdir check (tridge) */
929 /* the alternative is just to check the directory exists */
930 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
931 !S_ISDIR(st.st_mode)) {
932 if (ret == 0 && !S_ISDIR(st.st_mode)) {
933 DEBUG(0,("'%s' is not a directory, when connecting to "
934 "[%s]\n", conn->connectpath,
935 lp_servicename(snum)));
937 DEBUG(0,("'%s' does not exist or permission denied "
938 "when connecting to [%s] Error was %s\n",
939 conn->connectpath, lp_servicename(snum),
942 change_to_root_user();
943 /* Call VFS disconnect hook */
944 SMB_VFS_DISCONNECT(conn);
945 yield_connection(conn, lp_servicename(snum));
947 *status = NT_STATUS_BAD_NETWORK_NAME;
951 string_set(&conn->origpath,conn->connectpath);
953 #if SOFTLINK_OPTIMISATION
954 /* resolve any soft links early if possible */
955 if (vfs_ChDir(conn,conn->connectpath) == 0) {
957 pstrcpy(s,conn->connectpath);
959 set_conn_connectpath(conn,s);
960 vfs_ChDir(conn,conn->connectpath);
965 * Print out the 'connected as' stuff here as we need
966 * to know the effective uid and gid we will be using
967 * (at least initially).
970 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
971 dbgtext( "%s (%s) ", get_remote_machine_name(),
972 conn->client_address );
973 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
974 dbgtext( "connect to service %s ", lp_servicename(snum) );
975 dbgtext( "initially as user %s ", user );
976 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
977 dbgtext( "(pid %d)\n", (int)sys_getpid() );
980 /* Setup the minimum value for a change notify wait time (seconds). */
981 set_change_notify_timeout(lp_change_notify_timeout(snum));
983 /* we've finished with the user stuff - go back to root */
984 change_to_root_user();
988 /***************************************************************************************
989 Simple wrapper function for make_connection() to include a call to
991 **************************************************************************************/
993 connection_struct *make_connection_with_chdir(const char *service_in,
995 const char *dev, uint16 vuid,
998 connection_struct *conn = NULL;
1000 conn = make_connection(service_in, password, dev, vuid, status);
1003 * make_connection() does not change the directory for us any more
1004 * so we have to do it as a separate step --jerry
1007 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1008 DEBUG(0,("move_driver_to_download_area: Can't change "
1009 "directory to %s for [print$] (%s)\n",
1010 conn->connectpath,strerror(errno)));
1011 yield_connection(conn, lp_servicename(SNUM(conn)));
1013 *status = NT_STATUS_UNSUCCESSFUL;
1020 /****************************************************************************
1021 Make a connection to a service.
1024 ****************************************************************************/
1026 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
1027 const char *pdev, uint16 vuid,
1031 user_struct *vuser = NULL;
1038 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1040 if (!non_root_mode() && (euid = geteuid()) != 0) {
1041 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1042 "(%u)\n", (unsigned int)euid ));
1043 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1046 if (conn_num_open() > 2047) {
1047 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1051 if(lp_security() != SEC_SHARE) {
1052 vuser = get_valid_user_struct(vuid);
1054 DEBUG(1,("make_connection: refusing to connect with "
1055 "no session setup\n"));
1056 *status = NT_STATUS_ACCESS_DENIED;
1061 /* Logic to try and connect to the correct [homes] share, preferably
1062 without too many getpwnam() lookups. This is particulary nasty for
1063 winbind usernames, where the share name isn't the same as unix
1066 The snum of the homes share is stored on the vuser at session setup
1070 if (strequal(service_in,HOMES_NAME)) {
1071 if(lp_security() != SEC_SHARE) {
1072 DATA_BLOB no_pw = data_blob(NULL, 0);
1073 if (vuser->homes_snum == -1) {
1074 DEBUG(2, ("[homes] share not available for "
1075 "this user because it was not found "
1076 "or created at session setup "
1078 *status = NT_STATUS_BAD_NETWORK_NAME;
1081 DEBUG(5, ("making a connection to [homes] service "
1082 "created at session setup time\n"));
1083 return make_connection_snum(vuser->homes_snum,
1087 /* Security = share. Try with
1088 * current_user_info.smb_name as the username. */
1089 if (*current_user_info.smb_name) {
1090 fstring unix_username;
1091 fstrcpy(unix_username,
1092 current_user_info.smb_name);
1093 map_username(unix_username);
1094 snum = find_service(unix_username);
1097 DEBUG(5, ("making a connection to 'homes' "
1098 "service %s based on "
1099 "security=share\n", service_in));
1100 return make_connection_snum(snum, NULL,
1105 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1106 && strequal(service_in,
1107 lp_servicename(vuser->homes_snum))) {
1108 DATA_BLOB no_pw = data_blob(NULL, 0);
1109 DEBUG(5, ("making a connection to 'homes' service [%s] "
1110 "created at session setup time\n", service_in));
1111 return make_connection_snum(vuser->homes_snum,
1116 fstrcpy(service, service_in);
1118 strlower_m(service);
1120 snum = find_service(service);
1123 if (strequal(service,"IPC$") ||
1124 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1125 DEBUG(3,("refusing IPC connection to %s\n", service));
1126 *status = NT_STATUS_ACCESS_DENIED;
1130 DEBUG(0,("%s (%s) couldn't find service %s\n",
1131 get_remote_machine_name(), client_addr(), service));
1132 *status = NT_STATUS_BAD_NETWORK_NAME;
1136 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1137 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1138 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1139 "(pointing to %s)\n",
1140 service, lp_msdfs_proxy(snum)));
1141 *status = NT_STATUS_BAD_NETWORK_NAME;
1145 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1147 return make_connection_snum(snum, vuser,
1152 /****************************************************************************
1154 ****************************************************************************/
1156 void close_cnum(connection_struct *conn, uint16 vuid)
1159 pipe_close_conn(conn);
1161 file_close_conn(conn);
1162 dptr_closecnum(conn);
1165 change_to_root_user();
1167 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1168 get_remote_machine_name(),
1169 conn->client_address,
1170 lp_servicename(SNUM(conn))));
1172 /* Call VFS disconnect hook */
1173 SMB_VFS_DISCONNECT(conn);
1175 yield_connection(conn, lp_servicename(SNUM(conn)));
1177 /* make sure we leave the directory available for unmount */
1178 vfs_ChDir(conn, "/");
1180 /* execute any "postexec = " line */
1181 if (*lp_postexec(SNUM(conn)) &&
1182 change_to_user(conn, vuid)) {
1184 pstrcpy(cmd,lp_postexec(SNUM(conn)));
1185 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1186 conn->connectpath, conn->gid,
1187 get_current_username(),
1188 current_user_info.domain,
1191 change_to_root_user();
1194 change_to_root_user();
1195 /* execute any "root postexec = " line */
1196 if (*lp_rootpostexec(SNUM(conn))) {
1198 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
1199 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1200 conn->connectpath, conn->gid,
1201 get_current_username(),
1202 current_user_info.domain,