From: David Griffith Date: Sun, 7 May 2023 18:38:01 +0000 (-0700) Subject: Restricted x11 no-prompt file access to current dir or restricted path. X-Git-Url: https://scope-eye.net/git/?a=commitdiff_plain;h=8b84c6b6e6bc09a3de410071ee676a6a589ae0dc;p=liskon_frotz.git Restricted x11 no-prompt file access to current dir or restricted path. This necessarily required implementing the -R option (restricted read/write). --- diff --git a/doc/xfrotz.6 b/doc/xfrotz.6 index 0b72b28..31e7309 100644 --- a/doc/xfrotz.6 +++ b/doc/xfrotz.6 @@ -95,6 +95,22 @@ Enable branching on the .I @piracy opcode. This opcode is seldom used. .TP +.B \-R +(class \fBRestricted\fP, name \fBrestricted\fP) +Restricted read/write. Reading and writing files will be restricted +only to the provided path. Ordinarily xfrotz will write or read its +saves, transcripts, and move recordings in whatever path or directory +the user provides when the +.B SAVE, +.B SCRIPT, +or +.B RECORDING +commands are given. This can be undesirable if xfrotz is run in a +restricted environment, by a front end, or by a chatbot. This option will +cause xfrotz to write or read only to the provided path and nowhere else. +Then the controlling process can then watch that directory for changes +and need not worry about someone scribbling or snooping who-knows-where. +.TP .B \-rm (class \fBMargin\fP, name \fBrightMargin\fP) Sets the right margin. diff --git a/src/x11/x_init.c b/src/x11/x_init.c index 3695d64..5b063f8 100644 --- a/src/x11/x_init.c +++ b/src/x11/x_init.c @@ -226,6 +226,7 @@ void os_process_arguments(int argc, char *argv[]) {"+e", ".ignoreErrors", XrmoptionNoArg, (void *)"false"}, {"-p", ".piracy", XrmoptionNoArg, (void *)"true"}, {"+p", ".piracy", XrmoptionNoArg, (void *)"false"}, + {"-R", ".restricted", XrmoptionSepArg, (void *)NULL}, {"-t", ".tandy", XrmoptionNoArg, (void *)"true"}, {"+t", ".tandy", XrmoptionNoArg, (void *)"false"}, {"-u", ".undoSlots", XrmoptionSepArg, (void *)NULL}, @@ -271,6 +272,8 @@ void os_process_arguments(int argc, char *argv[]) &f_setup.ignore_errors}, {".Piracy", ".piracy", parse_boolean, &f_setup.piracy}, + {".Restricted", ".restricted", parse_string, + &f_setup.restricted_path}, {".Tandy", ".tandy", parse_boolean, &f_setup.tandy}, {".UndoSlots", ".undoSlots", parse_int, diff --git a/src/x11/x_input.c b/src/x11/x_input.c index 7950754..a5fa1cc 100644 --- a/src/x11/x_input.c +++ b/src/x11/x_input.c @@ -29,6 +29,7 @@ #define XK_MISCELLANY #include #undef XK_MISCELLANY +#include #include #include #include @@ -240,9 +241,15 @@ char *os_read_file_name(const char *default_name, int flag) int saved_replay = istream_replay; int saved_record = ostream_record; char file_name[FILENAME_MAX + 1]; + int i; + char *tempname; zchar answer[4]; + char path_separator[2]; char *ext; + path_separator[0] = PATH_SEPARATOR; + path_separator[1] = 0; + /* Turn off playback and recording temporarily */ istream_replay = 0; ostream_record = 0; @@ -258,8 +265,40 @@ char *os_read_file_name(const char *default_name, int flag) } /* Use the default name if nothing was typed */ - if (file_name[0] == 0) - strcpy(file_name, default_name); + if (file_name[0] == 0) { + /* If FILE_NO_PROMPT, restrict to currect directory. */ + /* If FILE_NO_PROMPT and using restricted path, then */ + /* nothing more needs to be done to restrict the */ + /* file access there. */ + if (flag == FILE_NO_PROMPT && f_setup.restricted_path == NULL) { + tempname = basename((char *)default_name); + strncpy(file_name, tempname, FILENAME_MAX); + } else + strcpy(file_name, default_name); + } + + /* If we're restricted to one directory, strip any leading path left + * over from a previous call to os_read_file_name(), then prepend + * the prescribed path to the filename. Hostile leading paths won't + * get this far. Instead we return failure a few lines above here if + * someone tries it. + */ + if (f_setup.restricted_path != NULL) { + for (i = strlen(file_name); i > 0; i--) { + if (file_name[i] == PATH_SEPARATOR) { + i++; + break; + } + } + tempname = strdup(file_name + i); + strncpy(file_name, f_setup.restricted_path, FILENAME_MAX); + + /* Make sure the final character is the path separator. */ + if (file_name[strlen(file_name)-1] != PATH_SEPARATOR) { + strncat(file_name, path_separator, FILENAME_MAX - strlen(file_name) - 2); + } + strncat(file_name, tempname, strlen(file_name) - strlen(tempname) - 1); + } if (flag == FILE_NO_PROMPT) { ext = strrchr(file_name, '.');