]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/gtk+/files/migration.patch
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / gtk+ / files / migration.patch
1 Index: configure.in
2 ===================================================================
3 RCS file: /cvs/gnome/gtk+/configure.in,v
4 retrieving revision 1.419.2.4
5 diff -u -r1.419.2.4 configure.in
6 --- configure.in        8 Feb 2005 21:39:42 -0000       1.419.2.4
7 +++ configure.in        27 Feb 2005 13:10:16 -0000
8 @@ -1495,6 +1495,16 @@
9  GTK_DEP_LIBS="$GDK_EXTRA_LIBS $GTK_DEP_LIBS_FOR_X `$PKG_CONFIG --libs $GDK_PIXBUF_PACKAGES $GDK_PACKAGES $GTK_PACKAGES` $GTK_EXTRA_LIBS $GDK_PIXBUF_EXTRA_LIBS"
10  GTK_DEP_CFLAGS="`$PKG_CONFIG --cflags  gthread-2.0 $GDK_PIXBUF_PACKAGES $GDK_PACKAGES $GTK_PACKAGES` $GDK_PIXBUF_EXTRA_CFLAGS $GDK_EXTRA_CFLAGS $GTK_EXTRA_CFLAGS"
11  
12 +AC_ARG_ENABLE(display-migration,
13 +       [AC_HELP_STRING([--enable-display-migration],
14 +                       [include support for GPE_CHANGE_DISPLAY protocol])],
15 +       enable_migration=yes, enable_migration=no)
16 +if test "$enable_migration" = "yes"; then
17 +       AC_DEFINE([ENABLE_MIGRATION], 1, [Define if display migration is enabled])
18 +       GTK_DEP_LIBS="$GTK_DEP_LIBS -lgcrypt"
19 +fi
20 +AM_CONDITIONAL(ENABLE_MIGRATION, test $enable_migration = "yes")
21 +
22  AC_SUBST(GTK_PACKAGES)
23  AC_SUBST(GTK_EXTRA_LIBS)
24  AC_SUBST(GTK_EXTRA_CFLAGS)
25 Index: gtk/Makefile.am
26 ===================================================================
27 RCS file: /cvs/gnome/gtk+/gtk/Makefile.am,v
28 retrieving revision 1.266.2.1
29 diff -u -r1.266.2.1 Makefile.am
30 --- gtk/Makefile.am     13 Jan 2005 15:18:21 -0000      1.266.2.1
31 +++ gtk/Makefile.am     27 Feb 2005 13:10:17 -0000
32 @@ -520,6 +520,10 @@
33         gtkwindow.c             \
34         xembed.h
35  
36 +if ENABLE_MIGRATION
37 +gtk_c_sources += gtkmigration.c
38 +endif
39 +
40  if OS_UNIX
41  gtk_private_h_sources += gtkfilesystemunix.h
42  gtk_c_sources +=         gtkfilesystemunix.c
43 Index: gtk/gtkmain.c
44 ===================================================================
45 RCS file: /cvs/gnome/gtk+/gtk/gtkmain.c,v
46 retrieving revision 1.255
47 diff -u -r1.255 gtkmain.c
48 --- gtk/gtkmain.c       27 Dec 2004 05:25:15 -0000      1.255
49 +++ gtk/gtkmain.c       27 Feb 2005 13:10:19 -0000
50 @@ -491,6 +491,10 @@
51    _gtk_accel_map_init ();  
52    _gtk_rc_init ();
53  
54 +#ifdef ENABLE_MIGRATION
55 +  gtk_migration_init ();
56 +#endif
57 +
58    /* Set the 'initialized' flag.
59     */
60    gtk_initialized = TRUE;
61 Index: gtk/gtkwindow.c
62 ===================================================================
63 RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
64 retrieving revision 1.281.2.4
65 diff -u -r1.281.2.4 gtkwindow.c
66 --- gtk/gtkwindow.c     21 Feb 2005 04:21:49 -0000      1.281.2.4
67 +++ gtk/gtkwindow.c     27 Feb 2005 13:10:56 -0000
68 @@ -731,6 +731,8 @@
69    add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
70  }
71  
72 +extern void gtk_migration_mark_window (GtkWidget *w);
73 +
74  static void
75  gtk_window_init (GtkWindow *window)
76  {
77 @@ -790,6 +792,10 @@
78                     "event",
79                     G_CALLBACK (gtk_window_event),
80                     NULL);
81 +
82 +#ifdef ENABLE_MIGRATION
83 +  gtk_migration_mark_window (window);
84 +#endif
85  }
86  
87  static void
88 --- /dev/null   2005-02-20 01:07:50.714416160 +0000
89 +++ gtk/gtkmigration.c  2005-02-27 15:05:04.052757352 +0000
90 @@ -0,0 +1,529 @@
91 +/*
92 + * Copyright (C) 2003, 2005 Philip Blundell <philb@gnu.org>
93 + *
94 + * This program is free software; you can redistribute it and/or
95 + * modify it under the terms of the GNU General Public License
96 + * as published by the Free Software Foundation; either version
97 + * 2 of the License, or (at your option) any later version.
98 + */
99 +
100 +#include <stdlib.h>
101 +#include <ctype.h>
102 +#include <libintl.h>
103 +#include <string.h>
104 +#include <assert.h>
105 +
106 +#include <X11/X.h>
107 +#include <X11/Xlib.h>
108 +#include <X11/Xatom.h>
109 +
110 +#include <gcrypt.h>
111 +
112 +#include "gtk.h"
113 +#include "gdk.h"
114 +#include "x11/gdkx.h"
115 +
116 +#define _(x) gettext(x)
117 +
118 +static GdkAtom string_gdkatom, display_change_gdkatom;
119 +static GdkAtom rsa_challenge_gdkatom;
120 +
121 +#define DISPLAY_CHANGE_SUCCESS                 0
122 +#define DISPLAY_CHANGE_UNABLE_TO_CONNECT       1
123 +#define DISPLAY_CHANGE_NO_SUCH_SCREEN          2
124 +#define DISPLAY_CHANGE_AUTHENTICATION_BAD      3
125 +#define DISPLAY_CHANGE_INDETERMINATE_ERROR     4
126 +
127 +static gboolean no_auth;
128 +
129 +static GSList *all_widgets;
130 +
131 +static gboolean gtk_migration_initialised;
132 +
133 +#define CHALLENGE_LEN 64
134 +
135 +gchar *gtk_migration_auth_challenge_string;
136 +
137 +static unsigned char challenge_bytes[CHALLENGE_LEN];
138 +static unsigned long challenge_seq;
139 +
140 +#define hexbyte(x)  ((x) >= 10 ? (x) + 'a' - 10 : (x) + '0')
141 +
142 +struct rsa_key
143 +{
144 +  gcry_mpi_t n, e, d, p, q, u;
145 +};
146 +
147 +static gcry_mpi_t
148 +mpi_from_sexp (gcry_sexp_t r, char *tag)
149 +{
150 +  gcry_sexp_t s = gcry_sexp_find_token (r, tag, 0);
151 +  return gcry_sexp_nth_mpi (s, 1, GCRYMPI_FMT_USG);
152 +}
153 +
154 +static char *
155 +hex_from_mpi (gcry_mpi_t m)
156 +{
157 +  char *buf;
158 +  gcry_mpi_aprint (GCRYMPI_FMT_HEX, (void *)&buf, NULL, m);
159 +  return buf;
160 +}
161 +
162 +static void
163 +gtk_migration_crypt_create_hash (char *display, char *challenge, size_t len, char *result)
164 +{
165 +  size_t dlen = strlen (display);
166 +  gchar *buf = g_malloc (dlen + 1 + len);
167 +  strcpy (buf, display);
168 +  memcpy (buf + dlen + 1, challenge, len);
169 +  gcry_md_hash_buffer (GCRY_MD_SHA1, result, buf, len + dlen + 1);
170 +  g_free (buf);
171 +}
172 +
173 +static int
174 +do_encode_md (const unsigned char *digest, size_t digestlen, int algo,
175 +              unsigned int nbits, gcry_mpi_t *r_val)
176 +{
177 +  int nframe = (nbits+7) / 8;
178 +  unsigned char *frame;
179 +  int i, n;
180 +  unsigned char asn[100];
181 +  size_t asnlen;
182 +
183 +  asnlen = sizeof(asn);
184 +  if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
185 +    return -1;
186 +
187 +  if (digestlen + asnlen + 4  > nframe )
188 +    return -1;
189 +  
190 +  /* We encode the MD in this way:
191 +   *
192 +   *      0  1 PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
193 +   *
194 +   * PAD consists of FF bytes.
195 +   */
196 +  frame = g_malloc (nframe);
197 +  n = 0;
198 +  frame[n++] = 0;
199 +  frame[n++] = 1; /* block type */
200 +  i = nframe - digestlen - asnlen -3 ;
201 +  assert ( i > 1 );
202 +  memset ( frame+n, 0xff, i ); n += i;
203 +  frame[n++] = 0;
204 +  memcpy ( frame+n, asn, asnlen ); n += asnlen;
205 +  memcpy ( frame+n, digest, digestlen ); n += digestlen;
206 +  assert ( n == nframe );
207 +      
208 +  gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, nframe, &nframe);
209 +  g_free (frame);
210 +  return 0;
211 +}
212 +
213 +static gboolean
214 +gtk_migration_crypt_check_signature (struct rsa_key *k, char *hash, char *sigbuf)
215 +{
216 +  gcry_mpi_t mpi, mpi2;
217 +  gcry_sexp_t data, sig, key;
218 +  int rc;
219 +
220 +  do_encode_md (hash, 20, GCRY_MD_SHA1, 1024, &mpi);
221 +
222 +  gcry_sexp_build (&data, NULL, "(data (value %m))", mpi);
223 +  
224 +  gcry_mpi_release (mpi);
225 +
226 +  gcry_sexp_build (&key, NULL, "(public-key (rsa (n %m) (e %m)))", k->n, k->e);
227 +
228 +  if (gcry_mpi_scan (&mpi2, GCRYMPI_FMT_HEX, sigbuf, 0, NULL))
229 +    {
230 +      gcry_sexp_release (data);
231 +      return FALSE;
232 +    }
233 +
234 +  gcry_sexp_build (&sig, NULL, "(sig-val (rsa (s %m)))", mpi2);
235 +
236 +  rc = gcry_pk_verify (sig, data, key);
237 +
238 +  gcry_sexp_release (data);
239 +  gcry_sexp_release (key);
240 +  gcry_sexp_release (sig);
241 +  gcry_mpi_release (mpi2);
242 +
243 +  if (rc)
244 +    return FALSE;
245 +
246 +  return TRUE;
247 +}
248 +
249 +static void 
250 +gtk_migration_auth_update_challenge (void)
251 +{
252 +  int i;
253 +  unsigned char *p;
254 +
255 +  if (gtk_migration_auth_challenge_string == NULL)
256 +    gtk_migration_auth_challenge_string = g_malloc ((CHALLENGE_LEN * 2) + 9);
257 +
258 +  p = gtk_migration_auth_challenge_string;
259 +
260 +  for (i = 0; i < CHALLENGE_LEN; i++)
261 +    {
262 +      *p++ = hexbyte (challenge_bytes[i] >> 4);
263 +      *p++ = hexbyte (challenge_bytes[i] & 15);
264 +    }
265 +  
266 +  sprintf (p, "%08lx", challenge_seq++);
267 +}
268 +
269 +static void
270 +gtk_migration_auth_generate_challenge (void)
271 +{
272 +  gcry_randomize (challenge_bytes, sizeof (challenge_bytes), GCRY_STRONG_RANDOM);
273 +  gtk_migration_auth_update_challenge ();
274 +}
275 +
276 +static struct rsa_key *
277 +parse_pubkey (char *s)
278 +{
279 +  struct rsa_key *r;
280 +  gcry_mpi_t n, e;
281 +  gchar *sp;
282 +
283 +  sp = strtok (s, " \n");
284 +  gcry_mpi_scan (&e, GCRYMPI_FMT_HEX, sp, 0, NULL);
285 +  sp = strtok (NULL, " \n");
286 +  gcry_mpi_scan (&n, GCRYMPI_FMT_HEX, sp, 0, NULL);
287 +
288 +  r = g_malloc0 (sizeof (struct rsa_key));
289 +  r->e = e;
290 +  r->n = n;
291 +  return r;
292 +}
293 +
294 +static struct rsa_key *
295 +lookup_pubkey (u_int32_t id)
296 +{
297 +  const gchar *home_dir = g_get_home_dir ();
298 +  gchar *filename = g_strdup_printf ("%s/.gpe/migrate/public", home_dir);
299 +  FILE *fp = fopen (filename, "r");
300 +  struct rsa_key *r = NULL;
301 +
302 +  if (fp)
303 +    {
304 +      while (!feof (fp))
305 +       {
306 +         char buffer[4096];
307 +         if (fgets (buffer, 4096, fp))
308 +           {
309 +             char *p;
310 +             u_int32_t this_id = strtoul (buffer, &p, 16);
311 +             if (p != buffer && *p == ' ')
312 +               {
313 +#ifdef DEBUG
314 +                 fprintf (stderr, "found id %x\n", this_id);
315 +#endif
316 +                 if (this_id == id)
317 +                   {
318 +                     r = parse_pubkey (++p);
319 +                     break;
320 +                   }
321 +               }
322 +           }
323 +       }
324 +      fclose (fp);
325 +    }
326 +
327 +  g_free (filename);
328 +  return r;
329 +}
330 +
331 +static void
332 +free_pubkey (struct rsa_key *k)
333 +{
334 +  gcry_mpi_release (k->n);
335 +  gcry_mpi_release (k->e);
336 +
337 +  g_free (k);
338 +}
339 +
340 +static gboolean
341 +gtk_migration_auth_validate_request (char *display, char *data)
342 +{
343 +  u_int32_t key_id;
344 +  char *ep;
345 +  char *p;
346 +  struct rsa_key *k;
347 +  char hash[20];
348 +  gboolean rc;
349 +
350 +  p = strchr (data, ' ');
351 +  if (p == NULL)
352 +    return FALSE;
353 +  *p++ = 0;
354 +
355 +  key_id = strtoul (data, &ep, 16);
356 +  if (*ep)
357 +    return FALSE;
358 +
359 +  k = lookup_pubkey (key_id);
360 +  if (k == NULL)
361 +    return FALSE;
362 +
363 +  gtk_migration_crypt_create_hash (display, gtk_migration_auth_challenge_string, 
364 +                          strlen (gtk_migration_auth_challenge_string), hash);
365 +
366 +  rc = gtk_migration_crypt_check_signature (k, hash, p);
367 +
368 +  free_pubkey (k);
369 +
370 +  return rc;
371 +}
372 +
373 +static int
374 +do_change_display (GtkWidget *w, char *display_name)
375 +{
376 +  GdkDisplay *newdisplay;
377 +  guint screen_nr = 1;
378 +  guint i;
379 +
380 +  if (display_name[0] == 0)
381 +    return DISPLAY_CHANGE_INDETERMINATE_ERROR;
382 +
383 +  i = strlen (display_name) - 1;
384 +  while (i > 0 && isdigit (display_name[i]))
385 +    i--;
386 +
387 +  if (display_name[i] == '.')
388 +    {
389 +      screen_nr = atoi (display_name + i + 1);
390 +      display_name[i] = 0;
391 +    }
392 +
393 +  newdisplay = gdk_display_open (display_name);
394 +  if (newdisplay)
395 +    {
396 +      GdkScreen *screen = gdk_display_get_screen (newdisplay, screen_nr);
397 +      if (screen)
398 +       {
399 +         gtk_window_set_screen (GTK_WINDOW (w), screen);
400 +         gdk_display_manager_set_default_display (gdk_display_manager_get (),
401 +                                                  newdisplay);
402 +         return DISPLAY_CHANGE_SUCCESS;
403 +       }
404 +      else
405 +       return DISPLAY_CHANGE_NO_SUCH_SCREEN;
406 +    }
407 +
408 +  return DISPLAY_CHANGE_UNABLE_TO_CONNECT;
409 +}
410 +
411 +static void
412 +set_challenge_on_window (GdkWindow *window)
413 +{
414 +  gdk_property_change (window, rsa_challenge_gdkatom, string_gdkatom,
415 +                      8, GDK_PROP_MODE_REPLACE, gtk_migration_auth_challenge_string, 
416 +                      strlen (gtk_migration_auth_challenge_string));
417 +}
418 +
419 +static void
420 +update_challenge_on_windows (void)
421 +{
422 +  GSList *i;
423 +
424 +  gtk_migration_auth_update_challenge ();
425 +
426 +  for (i = all_widgets; i; i = i->next)
427 +    {
428 +      GtkWidget *w = GTK_WIDGET (i->data);
429 +      if (w->window)
430 +       set_challenge_on_window (w->window);
431 +    }
432 +}
433 +
434 +static void
435 +reset_state (GdkWindow *window)
436 +{
437 +  gdk_property_change (window, display_change_gdkatom, string_gdkatom,
438 +                      8, GDK_PROP_MODE_REPLACE, NULL, 0);
439 +}
440 +
441 +static void
442 +generate_response (GdkDisplay *gdisplay, Display *dpy, Window window, int code)
443 +{
444 +  XClientMessageEvent ev;
445 +  Atom atom = gdk_x11_atom_to_xatom_for_display (gdisplay, 
446 +                                                display_change_gdkatom);
447 +  
448 +  memset (&ev, 0, sizeof (ev));
449 +  
450 +  ev.type = ClientMessage;
451 +  ev.window = window;
452 +  ev.message_type = atom;
453 +  ev.format = 32;
454 +  
455 +  ev.data.l[0] = window;
456 +  ev.data.l[1] = code;
457 +  
458 +  XSendEvent (dpy, DefaultRootWindow (dpy), False, SubstructureNotifyMask, (XEvent *)&ev);
459 +}
460 +
461 +static int
462 +handle_request (GdkWindow *gwindow, char *prop)
463 +{
464 +  GtkWidget *widget;
465 +  char *target, *auth_method, *auth_data;
466 +  char *p;
467 +
468 +  target = prop;
469 +  auth_method = "NULL";
470 +  auth_data = NULL;
471 +
472 +  p = strchr (prop, ' ');
473 +  if (p)
474 +    {
475 +      *p = 0;
476 +      auth_method = ++p;
477 +      
478 +      p = strchr (p, ' ');
479 +      if (p)
480 +       {
481 +         *p = 0;
482 +         auth_data = ++p;
483 +       }
484 +    }
485 +
486 +  if (no_auth == FALSE)
487 +    {
488 +      if (!strcasecmp (auth_method, "null"))
489 +       return DISPLAY_CHANGE_AUTHENTICATION_BAD;
490 +      else if (!strcasecmp (auth_method, "rsa-sig"))
491 +       {
492 +         if (gtk_migration_auth_validate_request (target, auth_data) == FALSE)
493 +           return DISPLAY_CHANGE_AUTHENTICATION_BAD;
494 +       }
495 +      else
496 +       return DISPLAY_CHANGE_AUTHENTICATION_BAD;
497 +    }
498 +
499 +  gdk_window_get_user_data (gwindow, (gpointer*) &widget);
500 +
501 +  if (widget)
502 +    return do_change_display (widget, target);
503 +
504 +  return DISPLAY_CHANGE_INDETERMINATE_ERROR;
505 +}
506 +
507 +static GdkFilterReturn 
508 +filter_func (GdkXEvent *xevp, GdkEvent *ev, gpointer p)
509 +{
510 +  XPropertyEvent *xev = (XPropertyEvent *)xevp;
511 +
512 +  if (xev->type == PropertyNotify)
513 +    {
514 +      GdkDisplay *gdisplay;
515 +      Atom atom;
516 +
517 +      gdisplay = gdk_x11_lookup_xdisplay (xev->display);
518 +      if (gdisplay)
519 +       {
520 +         atom = gdk_x11_atom_to_xatom_for_display (gdisplay, display_change_gdkatom);
521 +
522 +         if (xev->atom == atom)
523 +           {
524 +             GdkWindow *gwindow;
525 +             
526 +             gwindow = gdk_window_lookup_for_display (gdisplay, xev->window);
527 +             
528 +             if (gwindow)
529 +               {
530 +                 GdkAtom actual_type;
531 +                 gint actual_format;
532 +                 gint actual_length;
533 +                 unsigned char *prop = NULL;
534 +                 
535 +                 if (gdk_property_get (gwindow, display_change_gdkatom, string_gdkatom,
536 +                                       0, G_MAXLONG, FALSE, &actual_type, &actual_format,
537 +                                       &actual_length, &prop))
538 +                   {
539 +                     if (actual_length != 0)
540 +                       {
541 +                         if (actual_type == string_gdkatom && actual_length > 8)
542 +                           {
543 +                             gchar *buf = g_malloc (actual_length + 1);
544 +                             int rc;
545 +                             
546 +                             memcpy (buf, prop, actual_length);
547 +                             buf[actual_length] = 0;
548 +                             
549 +                             rc = handle_request (gwindow, buf);
550 +                             
551 +                             g_free (buf);
552 +                             generate_response (gdisplay, xev->display, xev->window, rc);
553 +                             
554 +                             if (rc == DISPLAY_CHANGE_SUCCESS)
555 +                               update_challenge_on_windows ();
556 +                           }
557 +                         
558 +                         reset_state (gwindow);
559 +                       }
560 +                   }
561 +                 
562 +                 if (prop)
563 +                   g_free (prop);
564 +               }
565 +           }
566 +         
567 +         return GDK_FILTER_REMOVE;
568 +       }
569 +    }
570 +
571 +  return GDK_FILTER_CONTINUE;
572 +}
573 +
574 +static void
575 +unrealize_window (GtkWidget *w)
576 +{
577 +  all_widgets = g_slist_remove (all_widgets, w);
578 +}
579 +
580 +void
581 +gtk_migration_mark_window (GtkWidget *w)
582 +{
583 +  if (! gtk_migration_initialised)
584 +    {
585 +      g_warning ("gtk_migration not initialised yet");
586 +      return;
587 +    }
588 +
589 +  if (GTK_WIDGET_REALIZED (w))
590 +    {
591 +      GdkWindow *window = w->window;
592 +      
593 +      gdk_window_add_filter (window, filter_func, NULL);
594 +
595 +      reset_state (window);
596 +      set_challenge_on_window (window);
597 +
598 +      all_widgets = g_slist_append (all_widgets, w);
599 +
600 +      g_signal_connect (G_OBJECT (w), "unrealize", G_CALLBACK (unrealize_window), NULL);
601 +    }
602 +  else
603 +    g_signal_connect (G_OBJECT (w), "realize", G_CALLBACK (gtk_migration_mark_window), NULL);
604 +}
605 +
606 +void
607 +gtk_migration_init (void)
608 +{
609 +  if (getenv ("GPE_DISPLAY_MIGRATION_NO_AUTH") != NULL)
610 +    no_auth = TRUE;
611 +
612 +  string_gdkatom = gdk_atom_intern ("STRING", FALSE);
613 +  display_change_gdkatom = gdk_atom_intern ("_GPE_DISPLAY_CHANGE", FALSE);
614 +  rsa_challenge_gdkatom = gdk_atom_intern ("_GPE_DISPLAY_CHANGE_RSA_CHALLENGE", FALSE);
615 +
616 +  gtk_migration_auth_generate_challenge ();
617 +
618 +  gtk_migration_initialised = TRUE;
619 +}