From c0237a1f045d14a54fe9a999543cb83385ac7dd6 Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Tue, 31 Dec 2019 18:30:04 +0100 Subject: Limiting file access for Fl_Preferences. Added Fl_Preferences::file_access() and various flags that make it possible to limit or completely deny file access to the preferences system, either for the core library or for the application or both. --- src/Fl.cxx | 6 +- src/Fl_File_Chooser.cxx | 2 +- src/Fl_File_Chooser.fl | 2 +- src/Fl_Preferences.cxx | 81 ++++++++++++++++++++++-- src/drivers/Android/Fl_Android_System_Driver.cxx | 4 +- src/drivers/Darwin/Fl_Darwin_System_Driver.cxx | 2 +- src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx | 2 +- src/drivers/X11/Fl_X11_System_Driver.cxx | 2 +- src/print_panel.cxx | 5 +- 9 files changed, 90 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/Fl.cxx b/src/Fl.cxx index 0a4e22ee9..13bd308f1 100644 --- a/src/Fl.cxx +++ b/src/Fl.cxx @@ -1850,7 +1850,7 @@ bool Fl::option(Fl_Option opt) if (!options_read_) { int tmp; { // first, read the system wide preferences - Fl_Preferences prefs(Fl_Preferences::SYSTEM, "fltk.org", "fltk"); + Fl_Preferences prefs(Fl_Preferences::CORE_SYSTEM, "fltk.org", "fltk"); Fl_Preferences opt_prefs(prefs, "options"); opt_prefs.get("ArrowFocus", tmp, 0); // default: off options_[OPTION_ARROW_FOCUS] = tmp; @@ -1874,7 +1874,7 @@ bool Fl::option(Fl_Option opt) } { // next, check the user preferences // override system options only, if the option is set ( >= 0 ) - Fl_Preferences prefs(Fl_Preferences::USER, "fltk.org", "fltk"); + Fl_Preferences prefs(Fl_Preferences::CORE_USER, "fltk.org", "fltk"); Fl_Preferences opt_prefs(prefs, "options"); opt_prefs.get("ArrowFocus", tmp, -1); if (tmp >= 0) options_[OPTION_ARROW_FOCUS] = tmp; @@ -1896,7 +1896,7 @@ bool Fl::option(Fl_Option opt) opt_prefs.get("ShowZoomFactor", tmp, -1); if (tmp >= 0) options_[OPTION_SHOW_SCALING] = tmp; } - { // now, if the developer has registered this app, we could as for per-application preferences + { // now, if the developer has registered this app, we could ask for per-application preferences } options_read_ = 1; } diff --git a/src/Fl_File_Chooser.cxx b/src/Fl_File_Chooser.cxx index 4b0d27f82..43bdc9733 100644 --- a/src/Fl_File_Chooser.cxx +++ b/src/Fl_File_Chooser.cxx @@ -168,7 +168,7 @@ void Fl_File_Chooser::cb_favOkButton(Fl_Return_Button* o, void* v) { Fl_File_Chooser::Fl_File_Chooser(const char *d, const char *p, int t, const char *title) { if (!prefs_) { - prefs_ = new Fl_Preferences(Fl_Preferences::USER, "fltk.org", "filechooser"); + prefs_ = new Fl_Preferences(Fl_Preferences::CORE_USER, "fltk.org", "filechooser"); } Fl_Group *prev_current = Fl_Group::current(); { window = new Fl_Double_Window(490, 380, "Choose File"); diff --git a/src/Fl_File_Chooser.fl b/src/Fl_File_Chooser.fl index fca0a32f3..4cbf3a9fc 100644 --- a/src/Fl_File_Chooser.fl +++ b/src/Fl_File_Chooser.fl @@ -70,7 +70,7 @@ class FL_EXPORT Fl_File_Chooser {open } Function {Fl_File_Chooser(const char *d, const char *p, int t, const char *title)} {} { code {if (!prefs_) { - prefs_ = new Fl_Preferences(Fl_Preferences::USER, "fltk.org", "filechooser"); + prefs_ = new Fl_Preferences(Fl_Preferences::CORE_USER, "fltk.org", "filechooser"); }} {} code {Fl_Group *prev_current = Fl_Group::current();} {} Fl_Window window { diff --git a/src/Fl_Preferences.cxx b/src/Fl_Preferences.cxx index 48e77bc24..424f0bc87 100644 --- a/src/Fl_Preferences.cxx +++ b/src/Fl_Preferences.cxx @@ -32,6 +32,7 @@ char Fl_Preferences::nameBuffer[128]; char Fl_Preferences::uuidBuffer[40]; Fl_Preferences *Fl_Preferences::runtimePrefs = 0; +unsigned int Fl_Preferences::fileAccess_ = Fl_Preferences::ALL; /** Returns a UUID as generated by the system. @@ -49,6 +50,53 @@ const char *Fl_Preferences::newUUID() { return uuidBuffer; } +/** + Tell the FLTK Preferences system which files in the file system it may read, create, or write. + + The FLTK core library will try to read or even create or write preference files when calling Fl::option(), + Fl_File_Chooser, the printing panel, and possibly some other internal function. If your applications wants + to keep FLTK from touching the file system, call this function before making any other FLTK calls: + + \code + // neiter FLTK nor the app may read, create, or write preference files + Fl_Preferences::file_access( Fl_Preferences::NONE ); + \endcode + + or + + \code + // FLTK may not read, create, or write preference files, but the application may + Fl_Preferences::file_access( Fl_Preferences::APP_OK ); + \endcode + + All flags can be combined using an OR operator. If flags are not set, that specifc access to the file system + will not be allowed. By default, all access is granted. To clear one or more flags from the default setting, us: + \code + Fl_Preferences::file_access( Fl_Preferences::file_access() + &~ Fl_Preferences::SYSTEM_WRITE ); + \endcode + + If preferences are created using a filename (instead of Fl_Preferences::USER or Fl_Preferences::SYSTEM), + file access is handled as if the Fl_Preferences::USER flag was set. + + \see Fl_Preferences::NONE and others for a list of flags. + \see Fl_Preferences::file_access() + */ +void Fl_Preferences::file_access(unsigned int flags) +{ + fileAccess_ = flags; +} + +/** + Return the current file access permissions for the FLTK Preferences system. + + \see Fl_Preferences::file_access(unsigned int) + */ +unsigned int Fl_Preferences::file_access() +{ + return fileAccess_; +} + /** The constructor creates a group that manages name/value pairs and child groups. Groups are ready for reading and writing at any time. @@ -807,8 +855,9 @@ Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, Root root, const char : prefs_(prefs), filename_(0L), vendor_(0L), - application_(0L) { - + application_(0L), + root_(root) +{ char *filename = Fl::system_driver()->preference_rootnode(prefs, root, vendor, application); filename_ = filename ? strdup(filename) : 0L; vendor_ = strdup(vendor); @@ -822,7 +871,9 @@ Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, const char *path, con : prefs_(prefs), filename_(0L), vendor_(0L), - application_(0L) { + application_(0L), + root_(Fl_Preferences::USER) +{ if (!vendor) vendor = "unknown"; @@ -845,7 +896,9 @@ Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs ) : prefs_(prefs), filename_(0L), vendor_(0L), - application_(0L) { + application_(0L), + root_(Fl_Preferences::USER) +{ } // destroy the root node and all depending nodes @@ -871,7 +924,19 @@ Fl_Preferences::RootNode::~RootNode() { // read a preferences file and construct the group tree and with all entry leafs int Fl_Preferences::RootNode::read() { if (!filename_) // RUNTIME preferences - return -1; + return -1; + if ( (root_ & Fl_Preferences::CORE) && !(fileAccess_ & Fl_Preferences::CORE_READ_OK) ) { + prefs_->node->clearDirtyFlags(); + return -1; + } + if ( ((root_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::USER) && !(fileAccess_ & Fl_Preferences::USER_READ_OK) ) { + prefs_->node->clearDirtyFlags(); + return -1; + } + if ( ((root_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::SYSTEM) && !(fileAccess_ & Fl_Preferences::SYSTEM_READ_OK) ) { + prefs_->node->clearDirtyFlags(); + return -1; + } char buf[1024]; FILE *f = fl_fopen( filename_, "rb" ); if ( !f ) @@ -909,6 +974,12 @@ int Fl_Preferences::RootNode::read() { int Fl_Preferences::RootNode::write() { if (!filename_) // RUNTIME preferences return -1; + if ( (root_ & Fl_Preferences::CORE) && !(fileAccess_ & Fl_Preferences::CORE_WRITE_OK) ) + return -1; + if ( ((root_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::USER) && !(fileAccess_ & Fl_Preferences::USER_WRITE_OK) ) + return -1; + if ( ((root_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::SYSTEM) && !(fileAccess_ & Fl_Preferences::SYSTEM_WRITE_OK) ) + return -1; fl_make_path_for_file(filename_); FILE *f = fl_fopen( filename_, "wb" ); if ( !f ) diff --git a/src/drivers/Android/Fl_Android_System_Driver.cxx b/src/drivers/Android/Fl_Android_System_Driver.cxx index 5619be496..0c7185370 100644 --- a/src/drivers/Android/Fl_Android_System_Driver.cxx +++ b/src/drivers/Android/Fl_Android_System_Driver.cxx @@ -842,8 +842,8 @@ char *Fl_WinAPI_System_Driver::preference_rootnode(Fl_Preferences *prefs, Fl_Pre DWORD type, nn; LONG err; HKEY key; - - switch (root) { + + switch (root&Fl_Preferences::ROOT_MASK) { case Fl_Preferences::SYSTEM: err = RegOpenKeyW( HKEY_LOCAL_MACHINE, FLPREFS_RESOURCEW, &key ); if (err == ERROR_SUCCESS) { diff --git a/src/drivers/Darwin/Fl_Darwin_System_Driver.cxx b/src/drivers/Darwin/Fl_Darwin_System_Driver.cxx index 0a30de81d..754f29342 100644 --- a/src/drivers/Darwin/Fl_Darwin_System_Driver.cxx +++ b/src/drivers/Darwin/Fl_Darwin_System_Driver.cxx @@ -249,7 +249,7 @@ char *Fl_Darwin_System_Driver::preference_rootnode(Fl_Preferences *prefs, Fl_Pre // TODO: verify that this is the Apple sanctioned way of finding these folders // (On Windows, this frequently leads to issues with internationalized systems) // Carbon: err = FindFolder( kLocalDomain, kPreferencesFolderType, 1, &spec.vRefNum, &spec.parID ); - switch (root) { + switch (root&Fl_Preferences::ROOT_MASK) { case Fl_Preferences::SYSTEM: strcpy(filename, "/Library/Preferences"); break; diff --git a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx index f2b56e0e0..dc7960e62 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx +++ b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx @@ -834,7 +834,7 @@ char *Fl_WinAPI_System_Driver::preference_rootnode(Fl_Preferences *prefs, Fl_Pre LONG err; HKEY key; - switch (root) { + switch (root&Fl_Preferences::ROOT_MASK) { case Fl_Preferences::SYSTEM: err = RegOpenKeyW( HKEY_LOCAL_MACHINE, FLPREFS_RESOURCEW, &key ); if (err == ERROR_SUCCESS) { diff --git a/src/drivers/X11/Fl_X11_System_Driver.cxx b/src/drivers/X11/Fl_X11_System_Driver.cxx index 89902b463..b84aba8ea 100644 --- a/src/drivers/X11/Fl_X11_System_Driver.cxx +++ b/src/drivers/X11/Fl_X11_System_Driver.cxx @@ -399,7 +399,7 @@ char *Fl_X11_System_Driver::preference_rootnode(Fl_Preferences *prefs, Fl_Prefer { static char filename[ FL_PATH_MAX ]; filename[0] = 0; const char *e; - switch (root) { + switch (root&Fl_Preferences::ROOT_MASK) { case Fl_Preferences::USER: if ((e = getenv("HOME")) != NULL) { strlcpy(filename, e, sizeof(filename)); diff --git a/src/print_panel.cxx b/src/print_panel.cxx index 4508c9c23..b5fc1d5aa 100644 --- a/src/print_panel.cxx +++ b/src/print_panel.cxx @@ -39,7 +39,6 @@ #include #include -static Fl_Preferences print_prefs(Fl_Preferences::USER, "fltk.org", "printers"); static Fl_Double_Window *print_panel=(Fl_Double_Window *)0; static Fl_Group *print_panel_controls=(Fl_Group *)0; static Fl_Choice *print_choice=(Fl_Choice *)0; @@ -225,6 +224,8 @@ static void cb_Save(Fl_Return_Button*, void*) { int val; const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); + Fl_Preferences print_prefs(Fl_Preferences::CORE_USER, "fltk.org", "printers"); + snprintf(name, sizeof(name), "%s/page_size", printer == NULL ? "" : printer); print_prefs.set(name, print_page_size->value()); @@ -610,6 +611,8 @@ void print_update_status() { char name[1024]; int val; + Fl_Preferences print_prefs(Fl_Preferences::CORE_USER, "fltk.org", "printers"); + snprintf(name, sizeof(name), "%s/page_size", printer == NULL ? "" : printer); print_prefs.get(name, val, 1); print_page_size->value(val); -- cgit v1.2.3