Re: Call-return interface for file choosers? (and: security using powerboxes)

Federico Mena Quintero <federico ximian com> wrote:

> On Sat, 2005-11-19 at 12:57 +0000, Mark Seaborn wrote:
> > Obviously the interface wasn't designed with this in mind.  It is a
> > shame that Gtk doesn't also provide a simpler file chooser interface
> > that omits control over the dialog box while it is open.  (Contrast
> > this with Qt and Windows, which do offer such call-return style
> > interfaces.)
> GtkFileChooserIface is more or less what you want --- it's the way the
> current file-chooser-as-GtkDialog is implemented, and you conceivably
> create an object that implements that interface, but that is not a
> widget.

I thought I could implement GtkFileChooserIface, but I ran into some

GtkFileChooserIface is defined in gtkfilechooserprivate.h, but that
isn't installed into /usr/include.  So to build my implementation of
GtkFileChooserIface, I would need to provide my own copy of
gtkfilechooserprivate.h.  But this in turn #includes gtkfilesystem.h
-- again, not installed in /usr/include because it's not a public

There is a further problem with the dependency on GtkFileSystem.  If
you look at GtkFileChooserIface's set_current_folder method, there is
a difference between the method as defined in the vtable, and the
public API function for calling the method:

       gboolean  (*set_current_folder)     (GtkFileChooser    *chooser,
                                            const GtkFilePath *path,
                                            GError           **error);
   gboolean gtk_file_chooser_set_current_folder
                                            (GtkFileChooser *chooser,
                                             const gchar *filename);

I would rather re-implement the public API function, which takes a
normal string, rather than the method in the vtable, which takes a
GtkFilePath object, which is defined by GtkFileSystem.

I don't really want to get involved with GtkFileSystem, because it
isn't documented.  Also, as an interface it seems rather odd, because
it deals with pathnames and bookmarks in the same interface.

I'm using an LD_PRELOADed shared library to implement my patch, so
replacing GtkFileChooserIface's public API functions such as
gtk_file_chooser_set_current_folder() is doable.

To replace GtkFileChooserDialog, I have created a class that inherits
from GtkObject and nothing else.  This means I have to intercept a
number of functions that operate on types that GtkFileChooserDialog is
normally derived from:

 * gtk_widget_show()
 * gtk_widget_show_all()
   These check for the powerbox as a special case, and send the
   powerbox open message to the other process.

 * gtk_dialog_run()
   Similar: it sends the powerbox open message, and runs an event
   loop until it receives the reply.

 * gtk_message_dialog_new():

   This is the nastiest one.  I am testing the powerbox code with
   Leafpad, which uses gtk_message_dialog_new() to open an overwrite
   confirmation dialog box with the "file save" dialog box as its
   parent window.

   Unfortunately, gtk_message_dialog_new() requires that its "parent"
   argument is either NULL or a GtkWindow.  My powerbox type does not
   inherit from GtkWindow, so passing that as the parent causes
   gtk_message_dialog_new() to do nothing.  This stops Leafpad from
   being able to save the file, since it never receives the
   confirmation from the user.

   This is frustrating because gtk_message_dialog_new() works when
   there is no parent, when NULL is given.  I really want it to treat
   a non-GtkWindow the same as NULL.

   My solution is to copy the code for gtk_message_dialog_new() into
   my LD_PRELOADed library, and change its test for GtkWindow.  This
   works for this one case, but I expect similar problems will crop up
   with other Gtk functions when I test the powerbox patch with other

> I wonder if you could do most of what you want by creating your own
> implementation of GtkFileSystem, delegating all requests to a separate
> process.  If the app tries to access /home/user/.ssh, the file system
> implementation would return a GError to indicate that you don't have
> permission.

That addresses a different problem -- actually one I've already
solved.  You're talking about limiting the process's access to files.
My restricted execution environment (Plash) deals with that.  The
classical approach is to intercept system calls (such as "open"), but
Linux doesn't provide an efficient, portable and secure way to do
that.  Instead, Plash limits a process's authority by chroot()ing it
(so the "open" system call can't do anything significant), but it
replaces glibc so that the open() *library* call does an RPC to a
server process, which can accept or refuse requests.

So this similar to what you suggest, but it's done at the level of
glibc and POSIX, not Gtk.

If the application does open("~/sensitive-file.txt"), the restricted
environment has the technical ability to accept or refuse the request,
but on what basis can it make that decision?  If the application
implements a file chooser itself, the system has no basis for
deciding.  It doesn't know whether the user entered the filename
"~/sensitive-file.txt" or not.  The only thing the system can do it
ask for confirmation, "Is is okay for app <foo> to access
~/sensitive-file.txt?".  But that is not usable: it just trains the
user to press OK.

This is why the file chooser has to be implemented in a separate,
trusted process.

> Alternatively, please see the proposal to implement a form of lock-down
> for GtkFileChooser:

I think I saw this before.  This kind of lock-down has a different
goal to what I'm doing.  The locked-down file chooser aims to restrict
what the user can do, and the restrictions are implemented in the

The powerbox scheme that I'm implementing is almost the opposite: It
aims to limit what the application process can do, so that it is in
line with what the user expects.  The powerbox file chooser is
necessarily implemented outside the application, and it is an agent of
the user.


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]