diff options
Diffstat (limited to 'source/smbd/service.c')
-rw-r--r-- | source/smbd/service.c | 616 |
1 files changed, 222 insertions, 394 deletions
diff --git a/source/smbd/service.c b/source/smbd/service.c index a8a590da804..4a02967866b 100644 --- a/source/smbd/service.c +++ b/source/smbd/service.c @@ -1,5 +1,6 @@ /* - Unix SMB/CIFS implementation. + Unix SMB/Netbios implementation. + Version 1.9. service (connection) opening and closing Copyright (C) Andrew Tridgell 1992-1998 @@ -20,6 +21,8 @@ #include "includes.h" +#define CHECK_PATH_ON_TCONX 1 + extern struct timeval smb_last_time; extern int case_default; extern BOOL case_preserve; @@ -27,7 +30,9 @@ extern BOOL short_case_preserve; extern BOOL case_mangle; extern BOOL case_sensitive; extern BOOL use_mangled_map; +extern fstring remote_machine; extern userdom_struct current_user_info; +extern fstring remote_machine; /**************************************************************************** @@ -36,7 +41,6 @@ extern userdom_struct current_user_info; BOOL set_current_service(connection_struct *conn,BOOL do_chdir) { - extern char magic_char; static connection_struct *last_conn; int snum; @@ -67,7 +71,6 @@ BOOL set_current_service(connection_struct *conn,BOOL do_chdir) short_case_preserve = lp_shortpreservecase(snum); case_mangle = lp_casemangle(snum); case_sensitive = lp_casesensitive(snum); - magic_char = lp_magicchar(snum); use_mangled_map = (*lp_mangled_map(snum) ? True:False); return(True); } @@ -76,9 +79,12 @@ BOOL set_current_service(connection_struct *conn,BOOL do_chdir) Add a home service. Returns the new service number or -1 if fail. ****************************************************************************/ -int add_home_service(const char *service, const char *username, const char *homedir) +int add_home_service(char *service, char *homedir) { int iHomeService; + int iService; + fstring new_service; + char *usr_p = NULL; if (!service || !homedir) return -1; @@ -93,30 +99,22 @@ int add_home_service(const char *service, const char *username, const char *home * include any macros. */ - { - const char *p = strchr(service,*lp_winbind_separator()); + fstrcpy(new_service, service); - /* We only want the 'user' part of the string */ - if (p) { - service = p + 1; - } - } + if ((usr_p = strchr(service,*lp_winbind_separator())) != NULL) + fstrcpy(new_service, usr_p+1); - if (!lp_add_home(service, iHomeService, username, homedir)) { - return -1; - } - - return lp_servicenumber(service); + lp_add_home(new_service,iHomeService,homedir); + iService = lp_servicenumber(new_service); + return iService; } +/**************************************************************************** + Find a service entry. service is always in dos codepage. +****************************************************************************/ -/** - * Find a service entry. service is always in dos codepage. - * - * @param service is modified (to canonical form??) - **/ -int find_service(fstring service) +int find_service(char *service) { int iService; @@ -127,7 +125,7 @@ int find_service(fstring service) /* now handle the special case of a home directory */ if (iService < 0) { - char *phome_dir = get_user_home_dir(service); + char *phome_dir = get_user_service_home_dir(service); if(!phome_dir) { @@ -136,13 +134,13 @@ int find_service(fstring service) * be a Windows to unix mapped user name. */ if(map_username(service)) - phome_dir = get_user_home_dir(service); + phome_dir = get_user_service_home_dir(service); } DEBUG(3,("checking for home directory %s gave %s\n",service, phome_dir?phome_dir:"(NULL)")); - iService = add_home_service(service,service /* 'username' */, phome_dir); + iService = add_home_service(service,phome_dir); } /* If we still don't have a service, attempt to add it as a printer. */ @@ -160,7 +158,7 @@ int find_service(fstring service) { DEBUG(3,("%s is a valid printer name\n", service)); DEBUG(3,("adding %s as a printer service\n", service)); - lp_add_printer(service, iPrinterService); + lp_add_printer(service,iPrinterService); iService = lp_servicenumber(service); if (iService < 0) DEBUG(0,("failed to add %s as a printer service!\n", service)); @@ -194,8 +192,8 @@ int find_service(fstring service) iService = find_service(defservice); if (iService >= 0) { - all_string_sub(service, "_","/",0); - iService = lp_add_service(service, iService); + all_string_sub(service,"_","/",0); + iService = lp_add_service(service,iService); } } } @@ -203,7 +201,7 @@ int find_service(fstring service) if (iService >= 0) if (!VALID_SNUM(iService)) { - DEBUG(0,("Invalid snum %d for %s\n",iService, service)); + DEBUG(0,("Invalid snum %d for %s\n",iService,service)); iService = -1; } @@ -215,23 +213,89 @@ int find_service(fstring service) /**************************************************************************** - do some basic sainity checks on the share. - This function modifies dev, ecode. + Make a connection to a service. This function is designed to be called + AS ROOT and will return to being root on exit ! Modified current_user conn + and vuid elements. ****************************************************************************/ -static NTSTATUS share_sanity_checks(int snum, pstring dev) + +connection_struct *make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid, int *ecode) { - + int snum; + struct passwd *pass = NULL; + BOOL guest = False; + BOOL force = False; + connection_struct *conn; +#if !CHECK_PATH_ON_TCONX + struct stat st; +#endif + uid_t euid; + int ret; + + /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */ + + if (!non_root_mode() && ((euid = geteuid()) != 0)) { + DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid )); + smb_panic("make_connection: PANIC ERROR. Called as nonroot\n"); + } + + strlower(service); + + snum = find_service(service); + if (snum < 0) { + if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) { + DEBUG(3,("refusing IPC connection\n")); + *ecode = ERRnoipc; + return NULL; + } + + DEBUG(0,("%s (%s) couldn't find service %s\n", + remote_machine, client_addr(), service)); + *ecode = ERRnosuchshare; + return NULL; + } + + if (strequal(service,HOMES_NAME)) { + if (*user && Get_Pwnam(user,True)) { + fstring dos_username; + fstrcpy(dos_username, user); + unix_to_dos(dos_username); + return(make_connection(dos_username,user,password, + pwlen,dev,vuid,ecode)); + } + + if(lp_security() != SEC_SHARE) { + if (validated_username(vuid)) { + fstring dos_username; + fstrcpy(user,validated_username(vuid)); + fstrcpy(dos_username, user); + unix_to_dos(dos_username); + return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode)); + } + } else { + /* Security = share. Try with current_user_info.smb_name + * as the username. */ + if(*current_user_info.smb_name) { + fstring dos_username; + fstrcpy(user,current_user_info.smb_name); + fstrcpy(dos_username, user); + unix_to_dos(dos_username); + return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode)); + } + } + } + if (!lp_snum_ok(snum) || !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum))) { - return NT_STATUS_ACCESS_DENIED; + *ecode = ERRaccess; + return NULL; } /* you can only connect to the IPC$ service as an ipc device */ - if (strequal(lp_fstype(snum), "IPC")) + if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) pstrcpy(dev,"IPC"); - if (dev[0] == '?' || !dev[0]) { + if (*dev == '?' || !*dev) { if (lp_print_ok(snum)) { pstrcpy(dev,"LPT1:"); } else { @@ -243,7 +307,8 @@ static NTSTATUS share_sanity_checks(int snum, pstring dev) strupper(dev); if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) { DEBUG(1,("Attempt to connect to non-printer as a printer\n")); - return NT_STATUS_BAD_DEVICE_TYPE; + *ecode = ERRinvdevice; + return NULL; } /* Behave as a printer if we are supposed to */ @@ -251,168 +316,81 @@ static NTSTATUS share_sanity_checks(int snum, pstring dev) pstrcpy(dev, "LPT1:"); } - return NT_STATUS_OK; -} - + /* lowercase the user name */ + strlower(user); -/**************************************************************************** - readonly share? -****************************************************************************/ -static void set_read_only(connection_struct *conn) -{ - char **list; - char *service = lp_servicename(conn->service); - conn->read_only = lp_readonly(conn->service); + /* add it as a possible user name if we + are in share mode security */ + if (lp_security() == SEC_SHARE) { + add_session_user(service); + } - if (!service) return; - str_list_copy(&list, lp_readlist(conn->service)); - if (list) { - if (!str_list_substitute(list, "%S", service)) { - DEBUG(0, ("ERROR: read list substitution failed\n")); - } - if (user_in_list(conn->user, list)) - conn->read_only = True; - str_list_free(&list); + /* shall we let them in? */ + if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) { + DEBUG( 2, ( "Invalid username/password for %s [%s]\n", service, user ) ); + *ecode = ERRbadpw; + return NULL; } - - str_list_copy(&list, lp_writelist(conn->service)); - if (list) { - if (!str_list_substitute(list, "%S", service)) { - DEBUG(0, ("ERROR: write list substitution failed\n")); - } - if (user_in_list(conn->user, list)) - conn->read_only = False; - str_list_free(&list); + + add_session_user(user); + + conn = conn_new(); + if (!conn) { + DEBUG(0,("Couldn't find free connection.\n")); + *ecode = ERRnoresource; + return NULL; } -} + /* find out some info about the user */ + pass = smb_getpwnam(user,True); + + if (pass == NULL) { + DEBUG(0,( "Couldn't find account %s\n",user)); + *ecode = ERRbaduid; + conn_free(conn); + return NULL; + } + + conn->read_only = lp_readonly(snum); + + { + pstring list; + StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1); + pstring_sub(list,"%S",service); + + if (user_in_list(user,list)) + conn->read_only = True; + + StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1); + pstring_sub(list,"%S",service); + + if (user_in_list(user,list)) + conn->read_only = False; + } -/**************************************************************************** - admin user check -****************************************************************************/ -static void set_admin_user(connection_struct *conn) -{ /* admin user check */ /* JRA - original code denied admin user if the share was marked read_only. Changed as I don't think this is needed, but old code left in case there is a problem here. */ - if (user_in_list(conn->user,lp_admin_users(conn->service)) + if (user_in_list(user,lp_admin_users(snum)) #if 0 && !conn->read_only #endif ) { conn->admin_user = True; - conn->force_user = True; /* Admin users are effectivly 'forced' */ - DEBUG(0,("%s logged in as admin user (root privileges)\n",conn->user)); + DEBUG(0,("%s logged in as admin user (root privileges)\n",user)); } else { conn->admin_user = False; } - -#if 0 /* This done later, for now */ - /* admin users always run as uid=0 */ - if (conn->admin_user) { - conn->uid = 0; - } -#endif -} - -/**************************************************************************** - Make a connection, given the snum to connect to, and the vuser of the - connecting user if appropriate. -****************************************************************************/ - -static connection_struct *make_connection_snum(int snum, user_struct *vuser, - DATA_BLOB password, - char *dev, NTSTATUS *status) -{ - struct passwd *pass = NULL; - BOOL guest = False; - connection_struct *conn; - struct stat st; - fstring user; - *user = 0; - - if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) { - return NULL; - } - - conn = conn_new(); - if (!conn) { - DEBUG(0,("Couldn't find free connection.\n")); - *status = NT_STATUS_INSUFFICIENT_RESOURCES; - return NULL; - } - - if (lp_guest_only(snum)) { - const char *guestname = lp_guestaccount(); - guest = True; - pass = getpwnam_alloc(guestname); - if (!pass) { - DEBUG(0,("authorise_login: Invalid guest account %s??\n",guestname)); - conn_free(conn); - *status = NT_STATUS_NO_SUCH_USER; - return NULL; - } - fstrcpy(user,pass->pw_name); - conn->force_user = True; - string_set(&conn->user,pass->pw_name); - passwd_free(&pass); - DEBUG(3,("Guest only user %s\n",user)); - } else if (vuser) { - if (vuser->guest) { - if (!lp_guest_ok(snum)) { - DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)", lp_servicename(snum))); - conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; - return NULL; - } - } else { - if (!user_ok(vuser->user.unix_name, snum)) { - DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)", vuser->user.unix_name, lp_servicename(snum))); - conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; - return NULL; - } - } - conn->vuid = vuser->vuid; - conn->uid = vuser->uid; - conn->gid = vuser->gid; - string_set(&conn->user,vuser->user.unix_name); - fstrcpy(user,vuser->user.unix_name); - guest = vuser->guest; - } else if (lp_security() == SEC_SHARE) { - /* add it as a possible user name if we - are in share mode security */ - add_session_user(lp_servicename(snum)); - /* shall we let them in? */ - if (!authorise_login(snum,user,password,&guest)) { - DEBUG( 2, ( "Invalid username/password for [%s]\n", - lp_servicename(snum)) ); - conn_free(conn); - *status = NT_STATUS_WRONG_PASSWORD; - return NULL; - } - pass = Get_Pwnam(user); - conn->force_user = True; - conn->uid = pass->pw_uid; - conn->gid = pass->pw_gid; - string_set(&conn->user, pass->pw_name); - fstrcpy(user, pass->pw_name); - - } else { - DEBUG(0, ("invalid VUID (vuser) but not in security=share\n")); - conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; - return NULL; - } - - add_session_user(user); - - safe_strcpy(conn->client_address, client_addr(), - sizeof(conn->client_address)-1); + + conn->force_user = force; + conn->vuid = vuid; + conn->uid = pass->pw_uid; + conn->gid = pass->pw_gid; + safe_strcpy(conn->client_address, client_addr(), sizeof(conn->client_address)-1); conn->num_files_open = 0; conn->lastused = time(NULL); conn->service = snum; @@ -427,13 +405,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, string_set(&conn->user,user); conn->nt_user_token = NULL; - set_read_only(conn); - - set_admin_user(conn); - /* * If force user is true, then store the - * given userid and also the groups + * given userid and also the primary groupid * of the user we're forcing. */ @@ -443,21 +417,18 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstrcpy(fuser,lp_force_user(snum)); /* Allow %S to be used by force user. */ - pstring_sub(fuser,"%S",lp_servicename(snum)); + pstring_sub(fuser,"%S",service); - pass2 = (struct passwd *)Get_Pwnam(fuser); + pass2 = (struct passwd *)Get_Pwnam(fuser,True); if (pass2) { conn->uid = pass2->pw_uid; conn->gid = pass2->pw_gid; - string_set(&conn->user,pass2->pw_name); - fstrcpy(user,pass2->pw_name); + string_set(&conn->user,fuser); + fstrcpy(user,fuser); conn->force_user = True; - DEBUG(3,("Forced user %s\n",user)); + DEBUG(3,("Forced user %s\n",fuser)); } else { DEBUG(1,("Couldn't find user %s\n",fuser)); - conn_free(conn); - *status = NT_STATUS_NO_SUCH_USER; - return NULL; } } @@ -479,7 +450,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, BOOL user_must_be_member = False; StrnCpy(tmp_gname,lp_force_group(snum),sizeof(pstring)-1); - + if (tmp_gname[0] == '+') { user_must_be_member = True; StrnCpy(gname,&tmp_gname[1],sizeof(pstring)-2); @@ -487,11 +458,10 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, StrnCpy(gname,tmp_gname,sizeof(pstring)-1); } /* default service may be a group name */ - pstring_sub(gname,"%S",lp_servicename(snum)); + pstring_sub(gname,"%S",service); gid = nametogid(gname); if (gid != (gid_t)-1) { - /* * If the user has been forced and the forced group starts * with a '+', then we only set the group to be the forced @@ -507,12 +477,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->gid = gid; DEBUG(3,("Forced group %s\n",gname)); } - conn->force_group = True; } else { DEBUG(1,("Couldn't find group %s\n",gname)); - conn_free(conn); - *status = NT_STATUS_NO_SUCH_GROUP; - return NULL; } } #endif /* HAVE_GETGRNAM */ @@ -522,42 +488,50 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstrcpy(s,lp_pathname(snum)); standard_sub_conn(conn,s,sizeof(s)); string_set(&conn->connectpath,s); - DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum))); + DEBUG(3,("Connect path is %s\n",s)); } - if (conn->force_user || conn->force_group) { + /* groups stuff added by ih */ + conn->ngroups = 0; + conn->groups = NULL; + + /* Find all the groups this uid is in and + store them. Used by change_to_user() */ + initialise_groups(conn->user, conn->uid, conn->gid); + get_current_groups(conn->gid, &conn->ngroups,&conn->groups); - /* groups stuff added by ih */ - conn->ngroups = 0; - conn->groups = NULL; - - /* Find all the groups this uid is in and - store them. Used by change_to_user() */ - initialise_groups(conn->user, conn->uid, conn->gid); - get_current_groups(conn->gid, &conn->ngroups,&conn->groups); + /* check number of connections */ + if (!claim_connection(conn, + lp_servicename(SNUM(conn)), + lp_max_connections(SNUM(conn)), + False)) { + DEBUG(1,("too many connections - rejected\n")); + *ecode = ERRnoresource; + conn_free(conn); + return NULL; + } - conn->nt_user_token = create_nt_token(conn->uid, conn->gid, - conn->ngroups, conn->groups, - guest); - } + conn->nt_user_token = create_nt_token(conn->uid, conn->gid, + conn->ngroups, conn->groups, + guest, NULL); /* * New code to check if there's a share security descripter * added from NT server manager. This is done after the * smb.conf checks are done as we need a uid and token. JRA. - * */ { - BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA); + BOOL can_write = share_access_check(conn, snum, vuid, FILE_WRITE_DATA); if (!can_write) { - if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) { + if (!share_access_check(conn, snum, vuid, FILE_READ_DATA)) { /* No access, read or write. */ + *ecode = ERRaccess; DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n", - lp_servicename(snum))); + service )); + yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; return NULL; } else { conn->read_only = True; @@ -567,71 +541,57 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Initialise VFS function pointers */ if (!smbd_vfs_init(conn)) { - DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn)))); + DEBUG(0, ("smbd_vfs_init failed for service %s\n", lp_servicename(SNUM(conn)))); + yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; return NULL; } -/* ROOT Activities: */ - /* check number of connections */ - if (!claim_connection(conn, - lp_servicename(SNUM(conn)), - lp_max_connections(SNUM(conn)), - False,0)) { - DEBUG(1,("too many connections - rejected\n")); - conn_free(conn); - *status = NT_STATUS_INSUFFICIENT_RESOURCES; - return NULL; - } - - /* Preexecs are done here as they might make the dir we are to ChDir to below */ /* execute any "root preexec = " line */ if (*lp_rootpreexec(SNUM(conn))) { - int ret; pstring cmd; pstrcpy(cmd,lp_rootpreexec(SNUM(conn))); standard_sub_conn(conn,cmd,sizeof(cmd)); DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) { - DEBUG(1,("root preexec gave %d - failing connection\n", ret)); + DEBUG(1,("preexec gave %d - failing connection\n", ret)); yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; + *ecode = ERRsrverror; return NULL; } } - -/* USER Activites: */ + if (!change_to_user(conn, conn->vuid)) { - /* No point continuing if they fail the basic checks */ DEBUG(0,("Can't become connected user!\n")); + yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); - *status = NT_STATUS_LOGON_FAILURE; + *ecode = ERRbadpw; return NULL; } - /* Remember that a different vuid can connect later without these checks... */ - - /* Preexecs are done here as they might make the dir we are to ChDir to below */ /* execute any "preexec = " line */ if (*lp_preexec(SNUM(conn))) { - int ret; pstring cmd; pstrcpy(cmd,lp_preexec(SNUM(conn))); standard_sub_conn(conn,cmd,sizeof(cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_preexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); - change_to_root_user(); yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; + *ecode = ERRsrverror; return NULL; } } - + + /* + * FIXME!!!! Reenabled this code since it current;y breaks + * move_driver_to_download_area() by keeping the root path + * of the connection at /tmp. I'll work on a real fix, but this + * will keep people happy for a temporary meaure. --jerry + */ #if CHECK_PATH_ON_TCONX /* win2000 does not check the permissions on the directory during the tree connect, instead relying on permission @@ -639,22 +599,22 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, I have disabled this chdir check (tridge) */ if (vfs_ChDir(conn,conn->connectpath) != 0) { DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n", - get_remote_machine_name(), conn->client_address, + remote_machine, conn->client_address, conn->connectpath,strerror(errno))); change_to_root_user(); yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); - *status = NT_STATUS_BAD_NETWORK_NAME; + *ecode = ERRnosuchshare; return NULL; } #else /* the alternative is just to check the directory exists */ if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { - DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn)))); + DEBUG(0,("%s is not a directory\n", conn->connectpath)); change_to_root_user(); yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); - *status = NT_STATUS_BAD_NETWORK_NAME; + *ecode = ERRnosuchshare; return NULL; } #endif @@ -674,18 +634,20 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* * Print out the 'connected as' stuff here as we need - * to know the effective uid and gid we will be using - * (at least initially). + * to know the effective uid and gid we will be using. */ if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { - dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address ); + dbgtext( "%s (%s) ", remote_machine, conn->client_address ); dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); - dbgtext( "initially as user %s ", user ); + dbgtext( "as user %s ", user ); dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); dbgtext( "(pid %d)\n", (int)sys_getpid() ); } + /* we've finished with the sensitive stuff */ + change_to_root_user(); + /* Add veto/hide lists */ if (!IS_IPC(conn) && !IS_PRINT(conn)) { set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn))); @@ -696,153 +658,18 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Invoke VFS make connection hook */ if (conn->vfs_ops.connect) { - if (conn->vfs_ops.connect(conn, lp_servicename(snum), user) < 0) { - DEBUG(0,("make_connection: VFS make connection failed!\n")); - change_to_root_user(); - conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("calling vfs_ops.connect for service %s (options = %s)\n", service, lp_vfs_options(SNUM(conn)) )); + if (conn->vfs_ops.connect(conn, service, user) < 0) return NULL; - } } - - /* we've finished with the user stuff - go back to root */ - change_to_root_user(); return(conn); } -/*************************************************************************************** - Simple wrapper function for make_connection() to include a call to - vfs_chdir() - **************************************************************************************/ - -connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password, - char *dev, uint16 vuid, NTSTATUS *status) -{ - connection_struct *conn = NULL; - - conn = make_connection(service_in, password, dev, vuid, status); - - /* - * make_connection() does not change the directory for us any more - * so we have to do it as a separate step --jerry - */ - - if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) { - DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n", - conn->connectpath,strerror(errno))); - yield_connection(conn, lp_servicename(SNUM(conn))); - conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; - return NULL; - } - - return conn; -} - /**************************************************************************** - Make a connection to a service. - * - * @param service + Close a cnum ****************************************************************************/ -connection_struct *make_connection(const char *service_in, DATA_BLOB password, - char *dev, uint16 vuid, NTSTATUS *status) -{ - uid_t euid; - user_struct *vuser = NULL; - pstring service; - int snum = -1; - - /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */ - if (!non_root_mode() && (euid = geteuid()) != 0) { - DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid )); - smb_panic("make_connection: PANIC ERROR. Called as nonroot\n"); - } - - if(lp_security() != SEC_SHARE) { - vuser = get_valid_user_struct(vuid); - if (!vuser) { - DEBUG(1,("make_connection: refusing to connect with no session setup\n")); - *status = NT_STATUS_ACCESS_DENIED; - return NULL; - } - } - - /* Logic to try and connect to the correct [homes] share, preferably without too many - getpwnam() lookups. This is particulary nasty for winbind usernames, where the - share name isn't the same as unix username. - - The snum of the homes share is stored on the vuser at session setup time. - */ - - if (strequal(service_in,HOMES_NAME)) { - if(lp_security() != SEC_SHARE) { - DATA_BLOB no_pw = data_blob(NULL, 0); - if (vuser->homes_snum == -1) { - DEBUG(2, ("[homes] share not available for this user becouse it was not found or created at session setup time\n")); - *status = NT_STATUS_BAD_NETWORK_NAME; - return NULL; - } - DEBUG(5, ("making a connection to [homes] service created at session setup time\n")); - return make_connection_snum(vuser->homes_snum, - vuser, no_pw, - dev, status); - } else { - /* Security = share. Try with current_user_info.smb_name - * as the username. */ - if (*current_user_info.smb_name) { - fstring unix_username; - fstrcpy(unix_username, - current_user_info.smb_name); - map_username(unix_username); - snum = find_service(unix_username); - } - if (snum != -1) { - DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in)); - return make_connection_snum(snum, NULL, - password, - dev, status); - } - } - } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1) - && strequal(service_in, lp_servicename(vuser->homes_snum))) { - DATA_BLOB no_pw = data_blob(NULL, 0); - DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in)); - return make_connection_snum(vuser->homes_snum, - vuser, no_pw, - dev, status); - } - - pstrcpy(service, service_in); - - strlower(service); - - snum = find_service(service); - - if (snum < 0) { - if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) { - DEBUG(3,("refusing IPC connection to %s\n", service)); - *status = NT_STATUS_ACCESS_DENIED; - return NULL; - } - - DEBUG(0,("%s (%s) couldn't find service %s\n", - get_remote_machine_name(), client_addr(), service)); - *status = NT_STATUS_BAD_NETWORK_NAME; - return NULL; - } - - DEBUG(5, ("making a connection to 'normal' service %s\n", service)); - - return make_connection_snum(snum, vuser, - password, - dev, status); -} - -/**************************************************************************** -close a cnum -****************************************************************************/ void close_cnum(connection_struct *conn, uint16 vuid) { DirCacheFlush(SNUM(conn)); @@ -850,7 +677,7 @@ void close_cnum(connection_struct *conn, uint16 vuid) change_to_root_user(); DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", - get_remote_machine_name(),conn->client_address, + remote_machine,conn->client_address, lp_servicename(SNUM(conn)))); if (conn->vfs_ops.disconnect != NULL) { @@ -873,7 +700,6 @@ void close_cnum(connection_struct *conn, uint16 vuid) pstrcpy(cmd,lp_postexec(SNUM(conn))); standard_sub_conn(conn,cmd,sizeof(cmd)); smbrun(cmd,NULL); - change_to_root_user(); } change_to_root_user(); @@ -890,3 +716,5 @@ void close_cnum(connection_struct *conn, uint16 vuid) conn_free(conn); } + + |