diff --git a/README b/README index 6a5637fb..d1ee926c 100644 --- a/README +++ b/README @@ -273,7 +273,8 @@ description: dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile] [-lang languagefile] [-machine machinetype] [-noconsole] - [-startmapper] [-noautoexec] [-scaler scaler | -forcescaler scaler] + [-startmapper] [-noautoexec] [-securemode] + [-scaler scaler | -forcescaler scaler] dosbox -version @@ -318,6 +319,11 @@ dosbox -version -noautoexec Skips the [autoexec] section of the loaded configuration file. + -securemode + Same as -noautoexec, but adds config.com -securemode at the + bottom of AUTOEXEC.BAT (which in turn disables any changes to how + the drives are mounted inside DOSBox) + -scaler scaler Uses the scaler specified by "scaler". See the DOSBox configuration file for the available scalers. @@ -469,6 +475,7 @@ MEM CONFIG -writeconf localfile CONFIG -writelang localfile +CONFIG -securemode CONFIG -set "section property=value" CONFIG -get "section property" @@ -491,6 +498,12 @@ CONFIG -get "section property" The language file controls all visible output of the internal commands and the internal DOS. + -securemode + Switches DOSBox to a more secure mode. In this mode the internal + commands MOUNT, IMGMOUNT and BOOT won't work. It's not possible either + to create a new configfile or languagefile in this mode. + (Warning you can only undo this mode by restarting DOSBox.) + -set "section property=value" CONFIG will attempt to set the property to new value. At this moment CONFIG can not report whether the command succeeded or not. diff --git a/docs/dosbox.1 b/docs/dosbox.1 index cefa7018..c895bbbe 100644 --- a/docs/dosbox.1 +++ b/docs/dosbox.1 @@ -8,6 +8,7 @@ dosbox \- an x86/DOS emulator with sound/graphics .B [\-fullscreen] .B [\-startmapper] .B [\-noautoexec] +.B [\-securemode] .BI "[\-scaler " scaler ] .BI "[\-forcescaler " scaler ] .BI "[\-conf " configfile ] @@ -41,6 +42,13 @@ A summary of options is included below. .B \-noautoexec Skips the [autoexec] section of the loaded configuration file. .TP +.B \-securemode +.RB "Same as " \-noautoexec ", but adds " "config.com \-securemode" +at the end of +.I AUTOEXEC.BAT +(which in turn disables any changes to how the drives are mounted +.RB "inside " dosbox ) +.TP .BI \-scaler " scaler" .RI "Uses the graphical scaler specified by " scaler ". See the configuration" file for the available scalers @@ -67,7 +75,7 @@ wish to execute on startup. Multiple .IR langfile . .TP .B \-exit -.BR dosbox " will close itself when the DOS program specified by " file "ends." +.BR dosbox " will close itself when the DOS program specified by "file " ends." .TP .BI \-machine " machinetype .RB "Setup " dosbox " to emulate a specific type of machine." @@ -153,9 +161,19 @@ Display the amount of free memory .TP .B CONFIG [\-writeconf] [\-writelang] file .LP +.B CONFIG -securemode +.LP .RB "Write the current configuration or language settings to " file , which is located on the local filesystem. Not a mounted drive in .BR dosbox . +.TP +.B \-securemode +.RB Switches dosbox " to a more secure mode. In this mode the" +.RI "internal commands " MOUNT ", " IMGMOUNT " and " BOOT " won\'t work." +It\'s not possible +either to create a new configfile or languagefile in this mode. +(Warning you can only undo this mode by restarting +.BR dosbox .) .LP The configuration file controls various settings of .BR dosbox ": The amount of emulated memory," diff --git a/include/programs.h b/include/programs.h index 3cee7b4d..750b37b7 100644 --- a/include/programs.h +++ b/include/programs.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: programs.h,v 1.15 2008-01-19 11:02:29 qbix79 Exp $ */ +/* $Id: programs.h,v 1.16 2008-03-02 11:13:46 qbix79 Exp $ */ #ifndef DOSBOX_PROGRAMS_H #define DOSBOX_PROGRAMS_H @@ -77,6 +77,7 @@ public: Bitu GetEnvCount(void); bool SetEnv(const char * entry,const char * new_string); void WriteOut(const char * format,...); /* Write to standard output */ + void ChangeToLongCmd(); }; diff --git a/include/setup.h b/include/setup.h index fa7bdec0..7e7131f4 100644 --- a/include/setup.h +++ b/include/setup.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: setup.h,v 1.32 2008-02-10 11:14:02 qbix79 Exp $ */ +/* $Id: setup.h,v 1.33 2008-03-02 11:13:46 qbix79 Exp $ */ #ifndef DOSBOX_SETUP_H #define DOSBOX_SETUP_H @@ -300,8 +300,9 @@ private: typedef std::list::const_iterator const_it; typedef std::list::const_reverse_iterator const_reverse_it; void (* _start_function)(void); + bool secure_mode; //Sandbox mode public: - Config(CommandLine * cmd):cmdline(cmd){} + Config(CommandLine * cmd):cmdline(cmd),secure_mode(false){} ~Config(); Section_line * AddSection_line(char const * const _name,void (*_initfunction)(Section*)); @@ -318,6 +319,8 @@ public: void PrintConfig(char const * const configfilename) const; bool ParseConfigFile(char const * const configfilename); void ParseEnv(char ** envp); + bool SecureMode() const { return secure_mode; } + void SwitchToSecureMode() { secure_mode = true; }//can't be undone }; class Module_base { diff --git a/include/shell.h b/include/shell.h index 32032f9d..0080e949 100644 --- a/include/shell.h +++ b/include/shell.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell.h,v 1.22 2007-10-28 10:58:49 qbix79 Exp $ */ +/* $Id: shell.h,v 1.23 2008-03-02 11:13:46 qbix79 Exp $ */ #ifndef DOSBOX_SHELL_H #define DOSBOX_SHELL_H @@ -39,8 +39,11 @@ extern Bitu call_shellstop; /* first_shell is used to add and delete stuff from the shell env * by "external" programs. (config) */ extern Program * first_shell; -class DOS_Shell; +/* command_slashc indicates that the next commands are being run from command /c. Remove parameters for internal .COM files */ +extern bool command_slashc; + +class DOS_Shell; class BatchFile { public: diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index 60c6cd33..3d9056c9 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_programs.cpp,v 1.82 2008-01-19 11:02:29 qbix79 Exp $ */ +/* $Id: dos_programs.cpp,v 1.83 2008-03-02 11:13:46 qbix79 Exp $ */ #include "dosbox.h" #include @@ -72,6 +72,7 @@ static void ResolveHomedir(std::string & temp_line) { } } + class MOUNT : public Program { public: void Run(void) @@ -80,11 +81,32 @@ public: std::string label; std::string umount; + //Hack To allow long commandlines + ChangeToLongCmd(); + /* Parse the command line */ + /* if the command line is empty show current mounts */ + if (!cmd->GetCount()) { + WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_1")); + for (int d=0;dGetInfo()); + } + } + return; + } + + /* In secure mode don't allow people to change mount points. + * Neither mount nor unmount */ + if(control->SecureMode()) { + WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW")); + return; + } + /* Check for unmounting */ if (cmd->FindString("-u",umount,false)) { umount[0] = toupper(umount[0]); int i_drive = umount[0]-'A'; - if(i_drive < DOS_DRIVES && Drives[i_drive]) { + if(i_drive < DOS_DRIVES && i_drive >= 0 && Drives[i_drive]) { switch (DriveManager::UnmountDrive(i_drive)) { case 0: Drives[i_drive] = 0; @@ -115,18 +137,6 @@ public: return; } - /* Parse the command line */ - /* if the command line is empty show current mounts */ - if (!cmd->GetCount()) { - WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_1")); - for (int d=0;dGetInfo()); - } - } - return; - } - std::string type="dir"; cmd->FindString("-t",type,true); bool iscdrom = (type =="cdrom"); //Used for mscdex bug cdrom label name emulation @@ -492,6 +502,15 @@ private: public: void Run(void) { + //Hack To allow long commandlines + ChangeToLongCmd(); + /* In secure mode don't allow people to boot stuff. + * They might try to corrupt the data on it */ + if(control->SecureMode()) { + WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW")); + return; + } + FILE *usefile_1=NULL; FILE *usefile_2=NULL; Bitu i; @@ -946,8 +965,15 @@ static void INTRO_ProgramStart(Program * * make) { class IMGMOUNT : public Program { public: - void Run(void) - { + void Run(void) { + //Hack To allow long commandlines + ChangeToLongCmd(); + /* In secure mode don't allow people to change imgmount points. + * Neither mount nor unmount */ + if(control->SecureMode()) { + WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW")); + return; + } DOS_Drive * newdrive; imageDisk * newImage; Bit32u imagesize; @@ -959,7 +985,7 @@ public: if (cmd->FindString("-u",umount,false)) { umount[0] = toupper(umount[0]); int i_drive = umount[0]-'A'; - if (i_drive < DOS_DRIVES && Drives[i_drive]) { + if (i_drive < DOS_DRIVES && i_drive >= 0 && Drives[i_drive]) { switch (DriveManager::UnmountDrive(i_drive)) { case 0: Drives[i_drive] = 0; diff --git a/src/misc/programs.cpp b/src/misc/programs.cpp index 79d28b3e..451a2e24 100644 --- a/src/misc/programs.cpp +++ b/src/misc/programs.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: programs.cpp,v 1.30 2008-02-10 11:14:03 qbix79 Exp $ */ +/* $Id: programs.cpp,v 1.31 2008-03-02 11:13:46 qbix79 Exp $ */ #include #include @@ -106,6 +106,18 @@ Program::Program() { cmd = new CommandLine(filename,tail.buffer); } +extern std::string full_arguments; + +void Program::ChangeToLongCmd() { + CommandLine* temp = 0; + //If command_slashc => then don't pass any parameters to the internal .COM files + if(command_slashc) temp = new CommandLine(cmd->GetFileName(),""); + else temp = new CommandLine(cmd->GetFileName(),full_arguments.c_str()); + delete cmd; + cmd = temp; + full_arguments.assign(""); //Clear so it gets even more save +} + void Program::WriteOut(const char * format,...) { char buf[2048]; va_list msg; @@ -207,6 +219,11 @@ void CONFIG::Run(void) { FILE * f; if (cmd->FindString("-writeconf",temp_line,true) || cmd->FindString("-wc",temp_line,true)) { + /* In secure mode don't allow a new configfile to be created */ + if(control->SecureMode()) { + WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW")); + return; + } f=fopen(temp_line.c_str(),"wb+"); if (!f) { WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str()); @@ -218,6 +235,12 @@ void CONFIG::Run(void) { } if (cmd->FindString("-writelang",temp_line,true) ||cmd->FindString("-wl",temp_line,true)) { + /* In secure mode don't allow a new languagefile to be created + * Who knows which kind of file we would overwriting. */ + if(control->SecureMode()) { + WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW")); + return; + } f=fopen(temp_line.c_str(),"wb+"); if (!f) { WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str()); @@ -228,6 +251,13 @@ void CONFIG::Run(void) { return; } + /* Code for switching to secure mode */ + if(cmd->FindExist("-securemode",true)) { + control->SwitchToSecureMode(); + WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_ON")); + return; + } + /* Code for getting the current configuration. * * Official format: config -get "section property" * * As a bonus it will set %CONFIG% to this value as well */ @@ -250,7 +280,7 @@ void CONFIG::Run(void) { return; } std::string val = sec->GetPropValue(prop.c_str()); - if(val != NO_SUCH_PROPERTY) { + if(val == NO_SUCH_PROPERTY) { WriteOut(MSG_Get("PROGRAM_CONFIG_NO_PROPERTY"),prop.c_str(),temp_line.c_str()); return; } @@ -338,6 +368,8 @@ void PROGRAMS_Init(Section* /*sec*/) { MSG_Add("PROGRAM_CONFIG_FILE_ERROR","Can't open file %s\n"); MSG_Add("PROGRAM_CONFIG_USAGE","Config tool:\nUse -writeconf filename to write the current config.\nUse -writelang filename to write the current language strings.\n"); + MSG_Add("PROGRAM_CONFIG_SECURE_ON","Switched to secure mode.\n"); + MSG_Add("PROGRAM_CONFIG_SECURE_DISALLOW","This operation is not permitted in secure mode.\n"); MSG_Add("PROGRAM_CONFIG_SECTION_ERROR","Section %s doesn't exist.\n"); MSG_Add("PROGRAM_CONFIG_PROPERTY_ERROR","No such section or property.\n"); MSG_Add("PROGRAM_CONFIG_NO_PROPERTY","There is no property %s in section %s.\n"); diff --git a/src/shell/shell.cpp b/src/shell/shell.cpp index 3b0ece22..2e6276b5 100644 --- a/src/shell/shell.cpp +++ b/src/shell/shell.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell.cpp,v 1.88 2007-08-17 17:58:46 qbix79 Exp $ */ +/* $Id: shell.cpp,v 1.89 2008-03-02 11:13:47 qbix79 Exp $ */ #include #include @@ -28,6 +28,7 @@ #include "callback.h" #include "support.h" + Bitu call_shellstop; /* Larger scope so shell_del autoexec can use it to * remove things from the environment */ @@ -278,16 +279,22 @@ void DOS_Shell::RunInternal(void) return; } +bool command_slashc = false; void DOS_Shell::Run(void) { char input_line[CMD_MAXLINE] = {0}; std::string line; if (cmd->FindStringRemain("/C",line)) { + //command_slashc indicates that the following commands are run with command /c. Forbid parameters to mount. + //command_allready_set prevents against command /c "command /c command" + bool command_allready_set = command_slashc; + command_slashc = true; strcpy(input_line,line.c_str()); DOS_Shell temp; temp.echo = echo; temp.ParseLine(input_line); //for *.exe *.com |*.bat creates the bf needed by runinternal; temp.RunInternal(); // exits when no bf is found. + if(!command_allready_set) command_slashc = false; return; } /* Start a normal shell and check for a first command init */ @@ -333,7 +340,7 @@ void DOS_Shell::SyntaxError(void) { class AUTOEXEC:public Module_base { private: - AutoexecObject autoexec[16]; + AutoexecObject autoexec[17]; AutoexecObject autoexec_echo; public: AUTOEXEC(Section* configuration):Module_base(configuration) { @@ -341,9 +348,12 @@ public: std::string line; Section_line * section=static_cast(configuration); - /* add stuff from the configfile unless -noautexec is specified. */ - char * extra=const_cast(section->data.c_str()); - if (extra && !control->cmdline->FindExist("-noautoexec",true)) { + /* Check -securemode switch to disable mount/imgmount/boot after running autoexec.bat */ + bool secure = control->cmdline->FindExist("-securemode",true); + + /* add stuff from the configfile unless -noautexec or -securemode is specified. */ + char * extra = const_cast(section->data.c_str()); + if (extra && !secure && !control->cmdline->FindExist("-noautoexec",true)) { /* detect if "echo off" is the first line */ bool echo_off = !strncasecmp(extra,"echo off",8); if (!echo_off) echo_off = !strncasecmp(extra,"@echo off",9); @@ -372,7 +382,10 @@ public: /* Check for first command being a directory or file */ char buffer[CROSS_LEN]; char cross_filesplit[2] = {CROSS_FILESPLIT , 0}; - if (control->cmdline->FindCommand(1,line)) { + /* Combining -securemode and no parameter leaves you with a lovely Z:\. */ + if ( !control->cmdline->FindCommand(1,line) ) { + if ( secure ) autoexec[12].Install("z:\\config.com -securemode"); + } else { struct stat test; strcpy(buffer,line.c_str()); if (stat(buffer,&test)){ @@ -384,6 +397,7 @@ public: if (test.st_mode & S_IFDIR) { autoexec[12].Install(std::string("MOUNT C \"") + buffer + "\""); autoexec[13].Install("C:"); + if(secure) autoexec[14].Install("z:\\config.com -securemode"); } else { char* name = strrchr(buffer,CROSS_FILESPLIT); if (!name) { //Only a filename @@ -401,16 +415,19 @@ public: autoexec[13].Install("C:"); upcase(name); if(strstr(name,".BAT") != 0) { + if(secure) autoexec[14].Install("z:\\config.com -securemode"); /* BATch files are called else exit will not work */ - autoexec[14].Install(std::string("CALL ") + name); + autoexec[15].Install(std::string("CALL ") + name); } else if((strstr(name,".IMG") != 0) || (strstr(name,".IMA") !=0)) { + //No secure mode here as boot is destructive and enabling securemode disables boot /* Boot image files */ - autoexec[14].Install(std::string("BOOT ") + name); + autoexec[15].Install(std::string("BOOT ") + name); } else { - autoexec[14].Install(name); + if(secure) autoexec[14].Install("z:\\config.com -securemode"); + autoexec[15].Install(name); } - if(addexit) autoexec[15].Install("exit"); + if(addexit) autoexec[16].Install("exit"); } } nomount: diff --git a/src/shell/shell_misc.cpp b/src/shell/shell_misc.cpp index 4a023f3f..f2dc58b3 100644 --- a/src/shell/shell_misc.cpp +++ b/src/shell/shell_misc.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell_misc.cpp,v 1.51 2007-08-22 11:21:28 qbix79 Exp $ */ +/* $Id: shell_misc.cpp,v 1.52 2008-03-02 11:13:47 qbix79 Exp $ */ #include #include @@ -354,6 +354,7 @@ void DOS_Shell::InputCommand(char * line) { if (l_completion.size()) l_completion.clear(); } +std::string full_arguments = ""; bool DOS_Shell::Execute(char * name,char * args) { /* return true => don't check for hardware changes in do_command * return false => check for hardware changes in do_command */ @@ -438,7 +439,7 @@ bool DOS_Shell::Execute(char * name,char * args) { if(strcasecmp(extension, ".com") !=0) { if(strcasecmp(extension, ".exe") !=0) return false; - } + } /* Run the .exe or .com file from the shell */ /* Allocate some stack space for tables in physical memory */ reg_sp-=0x200; @@ -448,6 +449,10 @@ bool DOS_Shell::Execute(char * name,char * args) { //Add a filename RealPt file_name=RealMakeSeg(ss,reg_sp+0x20); MEM_BlockWrite(Real2Phys(file_name),fullname,strlen(fullname)+1); + + /* HACK: Store full commandline for mount and imgmount */ + full_arguments.assign(line); + /* Fill the command line */ CommandTail cmdtail; cmdtail.count = 0;