Eamon,<br><br>Thanks for the selection patch, I will review it next week and <br>send my comments directly to you.<br><br>I have implemented a much less clean version (hack) of selection <br>redirection for a trusted X server that I am working on, and have
<br>not had trouble with clients  rejecting synthetic requests -- but <br>I have not done much testing with modern X clients so I may be <br>blissfully ignorant of problems.<br><br>One problem, outside the scope of your patch, that I have had
<br>with redirecting selections is caused by the hardcoded default <br>Xt selection timeout. If the selection manager causes the selection<br>reply to be delayed by more that 5000 milliseconds the Xt toolkit <br>will ignore the selection. 
<br><br>This is the code from lib/Xt/Seletion.c that causes the trouble:<br><br>  void _XtSetDefaultSelectionTimeout(<br>        unsigned long *timeout)<br>  {<br>        *timeout = 5000; /* default to 5 seconds */<br>  }
<br><br>I do not have a good solution for the timeout.  My workaround<br>was to add a similar timeout to the selection manager so it<br>can let the user know that the selection might be ignored.<br><br>Pat Kane<br>--------
<br><br><br><div><span class="gmail_quote">On 3/21/07, <b class="gmail_sendername">Eamon Walsh</b> <<a href="mailto:ewalsh@tycho.nsa.gov">ewalsh@tycho.nsa.gov</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
This patch implements support for dealing with selections in XACE.<br>The requirements are to support the usual access check, and also<br>to support redirecting ConvertSelection requests to another client<br>application.<br>
<br>The patch introduces new fields into the Selection structure, destclient<br>and destwindow, and adds an XACE hook in the selection request procs.<br><br>The destclient field is where the SelectionRequest message actually
<br>gets sent when doing a ConvertSelection.  This could be a selection<br>manager application that can send the SelectionRequest on to<br>the real selection owner, actively serve as a middleman, or send a<br>SelectionNotify None back to the requestor to cancel the transfer.
<br><br>The destwindow field is what gets reported as the selection owner from<br>GetSelectionOwner requests.  This could be used to further redirect things<br>to the selection manager.  I'm aware of the XFixes selection events; the
<br>behavior of those is not changed.<br><br>XACE module authors can register for this hook, use the hook arguments<br>to decide whether to redirect, and change the dest field accordingly.<br>Returning FALSE from the hook is a third option, which ignores the
<br>request (sends None back to requestor).<br><br>This patch is based on the description of how selections work from the<br>ICCCM.  There are some details I'm not sure of, such as whether applications<br>will accept a synthetic SelectionRequest as in the example above.
<br><br>Comments?<br><br>--<br> Xext/xace.c         |   11 +++++++++++<br> Xext/xace.h         |   17 +++++++++--------<br> Xext/xacestr.h      |    9 +++++++++<br> dix/dispatch.c      |   25 +++++++++++++++++--------<br>
 include/selection.h |    4 ++++<br> 5 files changed, 50 insertions(+), 16 deletions(-)<br><br>--<br>diff --git a/Xext/xace.c b/Xext/xace.c<br>index ee0f39c..9502b5d 100644<br>--- a/Xext/xace.c<br>+++ b/Xext/xace.c<br>@@ -147,6 +147,17 @@ int XaceHook(int hook, ...)
<br>            prv = &rec.rval;<br>            break;<br>        }<br>+       case XACE_SELECTION_ACCESS: {<br>+           XaceSelectionAccessRec rec = {<br>+               va_arg(ap, ClientPtr),<br>+               va_arg(ap, Selection*),
<br>+               va_arg(ap, Mask),<br>+               TRUE    /* default allow */<br>+           };<br>+           calldata = &rec;<br>+           prv = &rec.rval;<br>+           break;<br>+       }<br>        case XACE_SITE_POLICY: {
<br>            XaceSitePolicyRec rec = {<br>                va_arg(ap, char*),<br>diff --git a/Xext/xace.h b/Xext/xace.h<br>index 7360dae..d3d5a84 100644<br>--- a/Xext/xace.h<br>+++ b/Xext/xace.h<br>@@ -28,7 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<br> #ifdef XACE<br><br> #define XACE_EXTENSION_NAME            "XAccessControlExtension"<br>-#define XACE_MAJOR_VERSION             1<br>+#define XACE_MAJOR_VERSION             2<br> #define XACE_MINOR_VERSION             0
<br><br> #include "pixmap.h"     /* for DrawablePtr */<br>@@ -50,13 +50,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<br> #define XACE_BACKGRND_ACCESS           7<br> #define XACE_EXT_ACCESS                        8
<br> #define XACE_HOSTLIST_ACCESS           9<br>-#define XACE_SITE_POLICY               10<br>-#define XACE_DECLARE_EXT_SECURE                11<br>-#define XACE_AUTH_AVAIL                        12<br>-#define XACE_KEY_AVAIL                 13
<br>-#define XACE_AUDIT_BEGIN               14<br>-#define XACE_AUDIT_END                 15<br>-#define XACE_NUM_HOOKS                 16<br>+#define XACE_SELECTION_ACCESS          10<br>+#define XACE_SITE_POLICY               11
<br>+#define XACE_DECLARE_EXT_SECURE                12<br>+#define XACE_AUTH_AVAIL                        13<br>+#define XACE_KEY_AVAIL                 14<br>+#define XACE_AUDIT_BEGIN               15<br>+#define XACE_AUDIT_END                 16
<br>+#define XACE_NUM_HOOKS                 17<br><br> extern CallbackListPtr XaceHooks[XACE_NUM_HOOKS];<br><br>diff --git a/Xext/xacestr.h b/Xext/xacestr.h<br>index bd30883..edf7b66 100644<br>--- a/Xext/xacestr.h<br>+++ b/Xext/xacestr.h
<br>@@ -27,6 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<br> #include "gcstruct.h"<br> #include "windowstr.h"<br> #include "inputstr.h"<br>+#include "
selection.h"<br> #include "xace.h"<br><br> /* XACE_CORE_DISPATCH */<br>@@ -93,6 +94,14 @@ typedef struct {<br>     int rval;<br> } XaceHostlistAccessRec;<br><br>+/* XACE_SELECTION_ACCESS */<br>+typedef struct {
<br>+    ClientPtr client;<br>+    Selection *selection;<br>+    Mask access_mode;<br>+    int rval;<br>+} XaceSelectionAccessRec;<br>+<br> /* XACE_SITE_POLICY */<br> typedef struct {<br>     char *policyString;<br>diff --git a/dix/dispatch.c b/dix/dispatch.c
<br>index d44687e..e4bc937 100644<br>--- a/dix/dispatch.c<br>+++ b/dix/dispatch.c<br>@@ -1074,11 +1074,16 @@ ProcSetSelectionOwner(register ClientPtr client)<br>            NumCurrentSelections++;<br>            CurrentSelections = newsels;
<br>            CurrentSelections[i].selection = stuff->selection;<br>+           CurrentSelections[i].devPrivates = NULL;<br>        }<br>+       dixFreePrivates(CurrentSelections[i].devPrivates);<br>         CurrentSelections[i].lastTimeChanged = time;
<br>        CurrentSelections[i].window = stuff->window;<br>+       CurrentSelections[i].destwindow = stuff->window;<br>        CurrentSelections[i].pWin = pWin;<br>        CurrentSelections[i].client = (pWin ? client : NullClient);
<br>+       CurrentSelections[i].destclient = (pWin ? client : NullClient);<br>+       CurrentSelections[i].devPrivates = NULL;<br>        if (SelectionCallback)<br>        {<br>            SelectionInfoRec    info;<br>@@ -1113,8 +1118,10 @@ ProcGetSelectionOwner(register ClientPtr client)
<br>         reply.type = X_Reply;<br>        reply.length = 0;<br>        reply.sequenceNumber = client->sequence;<br>-        if (i < NumCurrentSelections)<br>-            reply.owner = CurrentSelections[i].window;
<br>+        if (i < NumCurrentSelections &&<br>+           XaceHook(XACE_SELECTION_ACCESS, client, &CurrentSelections[i],<br>+                    DixReadAccess))<br>+            reply.owner = CurrentSelections[i].destwindow;
<br>         else<br>             reply.owner = None;<br>         WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply);<br>@@ -1153,20 +1160,18 @@ ProcConvertSelection(register ClientPtr client)<br>               CurrentSelections[i].selection != stuff->selection) i++;
<br>        if ((i < NumCurrentSelections) &&<br>            (CurrentSelections[i].window != None) &&<br>-           XaceHook(XACE_RESOURCE_ACCESS, client,<br>-                    CurrentSelections[i].window, RT_WINDOW,
<br>-                    DixReadAccess, CurrentSelections[i].pWin))<br>+           XaceHook(XACE_SELECTION_ACCESS, client, &CurrentSelections[i],<br>+                    DixReadAccess))<br>        {<br>            event.u.u.type
 = SelectionRequest;<br>            event.u.selectionRequest.time = stuff->time;<br>-           event.u.selectionRequest.owner =<br>-                       CurrentSelections[i].window;<br>+           event.u.selectionRequest.owner
 = CurrentSelections[i].window;<br>            event.u.selectionRequest.requestor = stuff->requestor;<br>            event.u.selectionRequest.selection = stuff->selection;<br>            event.u.selectionRequest.target
 = stuff->target;<br>            event.u.selectionRequest.property = stuff->property;<br>            if (TryClientEvents(<br>-               CurrentSelections[i].client, &event, 1, NoEventMask,<br>+               CurrentSelections[i].destclient, &event, 1, NoEventMask,
<br>                NoEventMask /* CantBeFiltered */, NullGrab))<br>                return (client->noClientException);<br>        }<br>@@ -4021,9 +4026,11 @@ DeleteWindowFromAnySelections(WindowPtr pWin)<br>                
info.kind = SelectionWindowDestroy;<br>                CallCallbacks(&SelectionCallback, &info);<br>            }<br>+           dixFreePrivates(CurrentSelections[i].devPrivates);<br>             CurrentSelections[i].pWin = (WindowPtr)NULL;
<br>             CurrentSelections[i].window = None;<br>            CurrentSelections[i].client = NullClient;<br>+           CurrentSelections[i].devPrivates = NULL;<br>        }<br> }<br><br>@@ -4043,9 +4050,11 @@ DeleteClientFromAnySelections(ClientPtr client)
<br>                info.kind = SelectionWindowDestroy;<br>                CallCallbacks(&SelectionCallback, &info);<br>            }<br>+           dixFreePrivates(CurrentSelections[i].devPrivates);<br>             CurrentSelections[i].pWin = (WindowPtr)NULL;
<br>             CurrentSelections[i].window = None;<br>            CurrentSelections[i].client = NullClient;<br>+           CurrentSelections[i].devPrivates = NULL;<br>        }<br> }<br><br>diff --git a/include/selection.h b/include/selection.h
<br>index fbe7cfc..9347376 100644<br>--- a/include/selection.h<br>+++ b/include/selection.h<br>@@ -50,6 +50,7 @@ SOFTWARE.<br> ******************************************************************/<br><br> #include "dixstruct.h
"<br>+#include "privates.h"<br> /*<br>  *<br>  *  Selection data structures<br>@@ -61,6 +62,9 @@ typedef struct _Selection {<br>     Window window;<br>     WindowPtr pWin;<br>     ClientPtr client;<br>+    ClientPtr destclient; /* support for redirection */
<br>+    Window destwindow;    /* support for redirection */<br>+    PrivateRec *devPrivates;<br> } Selection;<br><br> #endif /* SELECTION_H */<br><br>_______________________________________________<br>xorg mailing list<br>
<a href="mailto:xorg@lists.freedesktop.org">xorg@lists.freedesktop.org</a><br><a href="http://lists.freedesktop.org/mailman/listinfo/xorg">http://lists.freedesktop.org/mailman/listinfo/xorg</a><br></blockquote></div><br>