[Gpa-commits] r886 - trunk/src

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Wed May 7 13:19:27 CEST 2008


Author: werner
Date: 2008-05-07 13:19:25 +0200 (Wed, 07 May 2008)
New Revision: 886

Modified:
   trunk/src/ChangeLog
   trunk/src/gpakeydeleteop.c
   trunk/src/gpakeyexpireop.c
   trunk/src/gpakeypasswdop.c
   trunk/src/gpakeysignop.c
   trunk/src/gpakeytrustop.c
   trunk/src/gpgmetools.c
   trunk/src/gpgmetools.h
   trunk/src/server.c
   trunk/src/settingsdlg.c
Log:
Cleanups in the server code.
Implemenetd basic server code for verify and decrypt.
Show auto-key-locate options only for newer gpgs.


Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2008-05-06 16:13:33 UTC (rev 885)
+++ trunk/src/ChangeLog	2008-05-07 11:19:25 UTC (rev 886)
@@ -1,3 +1,25 @@
+2008-05-07  Werner Koch  <wk at g10code.com>
+
+	* gpakeydeleteop.c (gpa_key_delete_operation_next): Init ERR.
+
+	* gpgmetools.c (parse_version_number, parse_version_string)
+	(compare_version_strings): New.  Taken from gpgme.
+	(is_gpg_version_at_least): New.
+	* settingsdlg.c (settings_dlg_constructor): Use AKL only if
+	enabled.  Disabled all akl fucntion callers if not.
+
+	* server.c (cmd_session): New command; a stub for now.
+	(cmd_encrypt, cmd_prep_encrypt, cmd_sign): Factor protocol option
+	parsing out to ..
+	(parse_protocol_option): .. new.
+	(cmd_encrypt, cmd_sign): Factor common code out to ..
+	(finish_io_streams, prepare_io_streams): .. new.
+	(translate_io_streams): New.
+	(cmd_decrypt, cont_decrypt): New.
+	(cont_verify, cmd_verify): New.
+	(close_message_fd, cmd_message): New.
+	(my_gpgme_message_read_cb): New.
+
 2008-05-06  Marcus Brinkmann  <marcus at ulysses.g10code.com>
 
 	* gpakeydeleteop.c (gpa_key_delete_operation_next), gpakeysignop.c

Modified: trunk/src/gpakeydeleteop.c
===================================================================
--- trunk/src/gpakeydeleteop.c	2008-05-06 16:13:33 UTC (rev 885)
+++ trunk/src/gpakeydeleteop.c	2008-05-07 11:19:25 UTC (rev 886)
@@ -149,7 +149,8 @@
   gpgme_key_t key;
 
   key = gpa_key_operation_current_key (GPA_KEY_OPERATION (op));
-  
+  g_return_val_if_fail (key, gpg_error (GPG_ERR_CANCELED));
+
   if (! gpa_delete_dialog_run (GPA_OPERATION (op)->window, key))
     return gpg_error (GPG_ERR_CANCELED);
 
@@ -180,7 +181,7 @@
 static void
 gpa_key_delete_operation_next (GpaKeyDeleteOperation *op)
 {
-  gpg_error_t err;
+  gpg_error_t err = 0;
 
   if (GPA_KEY_OPERATION (op)->current)
     {

Modified: trunk/src/gpakeyexpireop.c
===================================================================
--- trunk/src/gpakeyexpireop.c	2008-05-06 16:13:33 UTC (rev 885)
+++ trunk/src/gpakeyexpireop.c	2008-05-07 11:19:25 UTC (rev 886)
@@ -175,6 +175,7 @@
   GDate *date;
 
   key = gpa_key_operation_current_key (GPA_KEY_OPERATION (op));
+  g_return_val_if_fail (key, gpg_error (GPG_ERR_CANCELED));
 
   if (! gpa_expiry_dialog_run (GPA_OPERATION (op)->window, key, &date))
     return gpg_error (GPG_ERR_CANCELED);

Modified: trunk/src/gpakeypasswdop.c
===================================================================
--- trunk/src/gpakeypasswdop.c	2008-05-06 16:13:33 UTC (rev 885)
+++ trunk/src/gpakeypasswdop.c	2008-05-07 11:19:25 UTC (rev 886)
@@ -151,6 +151,7 @@
   gpgme_key_t key;
 
   key = gpa_key_operation_current_key (GPA_KEY_OPERATION (op));
+  g_return_val_if_fail (key, gpg_error (GPG_ERR_CANCELED));
 
   err = gpa_gpgme_edit_passwd_start (GPA_OPERATION(op)->context, key);
   if (err)

Modified: trunk/src/gpakeysignop.c
===================================================================
--- trunk/src/gpakeysignop.c	2008-05-06 16:13:33 UTC (rev 885)
+++ trunk/src/gpakeysignop.c	2008-05-07 11:19:25 UTC (rev 886)
@@ -160,6 +160,8 @@
   gboolean sign_locally = FALSE;
 
   key = gpa_key_operation_current_key (GPA_KEY_OPERATION (op));
+  g_return_val_if_fail (key, gpg_error (GPG_ERR_CANCELED));
+
   if (! gpa_key_sign_run_dialog (GPA_OPERATION (op)->window,
 				 key, &sign_locally))
     return gpg_error (GPG_ERR_CANCELED);

Modified: trunk/src/gpakeytrustop.c
===================================================================
--- trunk/src/gpakeytrustop.c	2008-05-06 16:13:33 UTC (rev 885)
+++ trunk/src/gpakeytrustop.c	2008-05-07 11:19:25 UTC (rev 886)
@@ -154,6 +154,7 @@
   gpgme_validity_t trust;
 
   key = gpa_key_operation_current_key (GPA_KEY_OPERATION (op));
+  g_return_val_if_fail (key, gpg_error (GPG_ERR_CANCELED));
 
   if (! gpa_ownertrust_run_dialog (key, GPA_OPERATION (op)->window, &trust))
     return gpg_error (GPG_ERR_CANCELED);

Modified: trunk/src/gpgmetools.c
===================================================================
--- trunk/src/gpgmetools.c	2008-05-06 16:13:33 UTC (rev 885)
+++ trunk/src/gpgmetools.c	2008-05-07 11:19:25 UTC (rev 886)
@@ -24,6 +24,7 @@
 #include <config.h>
 
 #include <errno.h>
+#include <ctype.h>
 #include "gpa.h"
 #include "gtktools.h"
 #include "gpgmetools.h"
@@ -1064,3 +1065,110 @@
     }
 }
 
+
+
+
+
+/* Read the next number in the version string STR and return it in
+   *NUMBER.  Return a pointer to the tail of STR after parsing, or
+   *NULL if the version string was invalid.  */
+static const char *
+parse_version_number (const char *str, int *number)
+{
+#define MAXVAL ((INT_MAX - 10) / 10)
+  int val = 0;
+
+  /* Leading zeros are not allowed.  */
+  if (*str == '0' && isascii (str[1]) && isdigit (str[1]))
+    return NULL;
+
+  while (isascii (*str) && isdigit (*str) && val <= MAXVAL)
+    {
+      val *= 10;
+      val += *(str++) - '0';
+    }
+  *number = val;
+  return val > MAXVAL ? NULL : str;
+#undef MAXVAL
+}
+
+
+/* Parse the version string STR in the format MAJOR.MINOR.MICRO (for
+   example, 9.3.2) and return the components in MAJOR, MINOR and MICRO
+   as integers.  The function returns the tail of the string that
+   follows the version number.  This might be te empty string if there
+   is nothing following the version number, or a patchlevel.  The
+   function returns NULL if the version string is not valid.  */
+static const char *
+parse_version_string (const char *str, int *major, int *minor, int *micro)
+{
+  str = parse_version_number (str, major);
+  if (!str || *str != '.')
+    return NULL;
+  str++;
+
+  str = parse_version_number (str, minor);
+  if (!str || *str != '.')
+    return NULL;
+  str++;
+
+  str = parse_version_number (str, micro);
+  if (!str)
+    return NULL;
+
+  /* A patchlevel might follow.  */
+  return str;
+}
+
+
+/* Return true if MY_VERSION is at least REQ_VERSION, and false
+   otherwise.  */
+static int
+compare_version_strings (const char *my_version,
+			 const char *rq_version)
+{
+  int my_major, my_minor, my_micro;
+  int rq_major, rq_minor, rq_micro;
+  const char *my_plvl, *rq_plvl;
+
+  if (!rq_version)
+    return 1;
+  if (!my_version)
+    return 0;
+
+  my_plvl = parse_version_string (my_version, &my_major, &my_minor, &my_micro);
+  if (!my_plvl)
+    return 0;
+
+  rq_plvl = parse_version_string (rq_version, &rq_major, &rq_minor, &rq_micro);
+  if (!rq_plvl)
+    return 0;
+
+  if (my_major > rq_major
+      || (my_major == rq_major && my_minor > rq_minor)
+      || (my_major == rq_major && my_minor == rq_minor 
+	  && my_micro > rq_micro)
+      || (my_major == rq_major && my_minor == rq_minor
+	  && my_micro == rq_micro && strcmp (my_plvl, rq_plvl) >= 0))
+    return 1;
+
+  return 0;
+}
+
+
+/* Return true if the gpg engine has at least version NEED_VERSION.  */
+int
+is_gpg_version_at_least (const char *need_version)
+{
+  gpgme_engine_info_t engine;
+  
+  gpgme_get_engine_info (&engine);
+  while (engine)
+    {
+      if (engine->protocol == GPGME_PROTOCOL_OpenPGP)
+        return compare_version_strings (engine->version, need_version);
+      engine = engine->next;
+    }
+  return 0; /* No gpg-engine available. */
+}
+

Modified: trunk/src/gpgmetools.h
===================================================================
--- trunk/src/gpgmetools.h	2008-05-06 16:13:33 UTC (rev 885)
+++ trunk/src/gpgmetools.h	2008-05-07 11:19:25 UTC (rev 886)
@@ -188,5 +188,8 @@
 /* Release all keys in the array KEYS as weel as ARRY itself.  */
 void gpa_gpgme_release_keyarray (gpgme_key_t *keys);
 
+/* Return true if the gpg engine has at least version NEED_VERSION.  */
+int is_gpg_version_at_least (const char *need_version);
 
-#endif
+
+#endif /*GPGMETOOLS_H*/

Modified: trunk/src/server.c
===================================================================
--- trunk/src/server.c	2008-05-06 16:13:33 UTC (rev 885)
+++ trunk/src/server.c	2008-05-07 11:19:25 UTC (rev 886)
@@ -67,9 +67,13 @@
   int input_fd;
   int output_fd;
 
+  /* Fiel descriptor set with the MESSAGE command.  */
+  int message_fd;
+
   /* Channels used with the gpgme callbacks.  */
   GIOChannel *input_channel;
   GIOChannel *output_channel;
+  GIOChannel *message_channel;
 
   /* List of collected recipients.  */
   GSList *recipients;
@@ -101,7 +105,12 @@
 static assuan_sock_nonce_t socket_nonce;
 
 
+/* Forward declarations.  */
+static void run_server_continuation (assuan_context_t ctx, gpg_error_t err);
 
+
+
+
 
 static int
 not_finished (conn_ctrl_t ctrl)
@@ -233,6 +242,44 @@
     NULL
   };
 
+static ssize_t
+my_gpgme_message_read_cb (void *opaque, void *buffer, size_t size)
+{
+  conn_ctrl_t ctrl = opaque;
+  GIOStatus  status;
+  size_t nread;
+  int retval;
+
+  status = g_io_channel_read_chars (ctrl->message_channel, buffer, size,
+                                    &nread, NULL);
+  if (status == G_IO_STATUS_AGAIN
+      || (status == G_IO_STATUS_NORMAL && !nread))
+    {
+      errno = EAGAIN;
+      retval = -1;
+    }
+  else if (status == G_IO_STATUS_NORMAL)
+    retval = (int)nread;
+  else if (status == G_IO_STATUS_EOF)
+    retval = 0;
+  else
+    {
+      errno = EIO;
+      retval = -1;
+    }
+
+  return retval;
+}
+
+static struct gpgme_data_cbs my_gpgme_message_cbs =
+  { 
+    my_gpgme_message_read_cb,
+    NULL,
+    NULL,
+    NULL
+  };
+
+
 
 /* Release the recipients stored in the connection context. */
 static void
@@ -269,10 +316,209 @@
   ctrl->selected_protocol = GPGME_PROTOCOL_UNKNOWN;
 }
 
+
+/* Helper to parse an protocol option.  */
+static gpg_error_t
+parse_protocol_option (assuan_context_t ctx, char *line, int mandatory,
+                       gpgme_protocol_t *r_protocol)
+{
+  *r_protocol = GPGME_PROTOCOL_UNKNOWN;
+  if (has_option (line, "--protocol=OpenPGP"))
+    *r_protocol = GPGME_PROTOCOL_OpenPGP;
+  else if (has_option (line, "--protocol=CMS"))
+    *r_protocol = GPGME_PROTOCOL_CMS;
+  else if (has_option_name (line, "--protocol"))
+    return set_error (GPG_ERR_ASS_PARAMETER, "invalid protocol");
+  else if (mandatory)
+    return set_error (GPG_ERR_ASS_PARAMETER, "no protocol specified");
+
+  return 0;
+}
+
+
+static void 
+close_message_fd (conn_ctrl_t ctrl)
+{
+  if (ctrl->message_fd != -1)
+    {
+      close (ctrl->message_fd);
+      ctrl->message_fd = -1;
+    }
+}
+
+
+static void
+finish_io_streams (assuan_context_t ctx,
+                   gpgme_data_t *r_input_data, gpgme_data_t *r_output_data,
+                   gpgme_data_t *r_message_data)
+{
+  conn_ctrl_t ctrl = assuan_get_pointer (ctx);
+
+  if (r_input_data)
+    gpgme_data_release (*r_input_data); 
+  if (r_output_data)
+    gpgme_data_release (*r_output_data);
+  if (r_message_data)
+    gpgme_data_release (*r_message_data); 
+  if (ctrl->input_channel)
+    {
+      g_io_channel_shutdown (ctrl->input_channel, 0, NULL);
+      ctrl->input_channel = NULL;
+    }
+  if (ctrl->output_channel)
+    {
+      g_io_channel_shutdown (ctrl->output_channel, 0, NULL);
+      ctrl->output_channel = NULL;
+    }
+  if (ctrl->message_channel)
+    {
+      g_io_channel_shutdown (ctrl->message_channel, 0, NULL);
+      ctrl->message_channel = NULL;
+    }
+}
+
+
+/* Translate the input and output file descriptors and return an error
+   if they are not set.  */
+static gpg_error_t
+translate_io_streams (assuan_context_t ctx)
+{
+  conn_ctrl_t ctrl = assuan_get_pointer (ctx);
+
+  ctrl->input_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
+  if (ctrl->input_fd == -1)
+    return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
+  ctrl->output_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
+  if (ctrl->output_fd == -1)
+    return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
+  return 0;
+}
+
+
+static gpg_error_t
+prepare_io_streams (assuan_context_t ctx,
+                    gpgme_data_t *r_input_data, gpgme_data_t *r_output_data,
+                    gpgme_data_t *r_message_data)
+{
+  gpg_error_t err;
+  conn_ctrl_t ctrl = assuan_get_pointer (ctx);
+
+  if (r_input_data)
+    *r_input_data = NULL;
+  if (r_output_data)
+    *r_output_data = NULL;
+  if (r_message_data)
+    *r_message_data = NULL;
+
+  if (ctrl->input_fd != -1 && r_input_data)
+    {
+#ifdef HAVE_W32_SYSTEM
+      ctrl->input_channel = g_io_channel_win32_new_fd (ctrl->input_fd);
+#else
+      ctrl->input_channel = g_io_channel_unix_new (ctrl->input_fd);
+#endif
+      if (!ctrl->input_channel)
+        {
+          g_debug ("error creating input channel");
+          err = gpg_error (GPG_ERR_EIO);
+          goto leave;
+        }
+      g_io_channel_set_encoding (ctrl->input_channel, NULL, NULL);
+      g_io_channel_set_buffered (ctrl->input_channel, FALSE);
+    }
+
+  if (ctrl->output_fd != -1 && r_output_data)
+    {
+#ifdef HAVE_W32_SYSTEM
+      ctrl->output_channel = g_io_channel_win32_new_fd (ctrl->output_fd);
+#else
+      ctrl->output_channel = g_io_channel_unix_new (ctrl->output_fd);
+#endif
+      if (!ctrl->output_channel)
+        {
+          g_debug ("error creating output channel");
+          err = gpg_error (GPG_ERR_EIO);
+          goto leave;
+        }
+      g_io_channel_set_encoding (ctrl->output_channel, NULL, NULL);
+      g_io_channel_set_buffered (ctrl->output_channel, FALSE);
+    }
+
+  if (ctrl->message_fd != -1 && r_message_data)
+    {
+#ifdef HAVE_W32_SYSTEM
+      ctrl->message_channel = g_io_channel_win32_new_fd (ctrl->message_fd);
+#else
+      ctrl->message_channel = g_io_channel_unix_new (ctrl->message_fd);
+#endif
+      if (!ctrl->message_channel)
+        {
+          g_debug ("error creating message channel");
+          err = gpg_error (GPG_ERR_EIO);
+          goto leave;
+        }
+      g_io_channel_set_encoding (ctrl->message_channel, NULL, NULL);
+      g_io_channel_set_buffered (ctrl->message_channel, FALSE);
+    }
+
+  if (ctrl->input_fd != -1 && r_input_data)
+    {
+      err = gpgme_data_new_from_cbs (r_input_data, &my_gpgme_data_cbs, ctrl);
+      if (err)
+        goto leave;
+    }
+  if (ctrl->output_fd != -1 && r_output_data)
+    {
+      err = gpgme_data_new_from_cbs (r_output_data, &my_gpgme_data_cbs, ctrl);
+      if (err)
+        goto leave;
+    }
+  if (ctrl->message_fd != -1 && r_message_data)
+    {
+      err = gpgme_data_new_from_cbs (r_message_data,
+                                     &my_gpgme_message_cbs, ctrl);
+      if (err)
+        goto leave;
+    }
+
+ leave:
+  if (err)
+    finish_io_streams (ctx, r_input_data, r_output_data, r_message_data);
+  return err;
+}
+
+
 
-/* Forward declaration.  */
-static void run_server_continuation (assuan_context_t ctx, gpg_error_t err);
+/* SESSION <number> [<string>]
 
+   The NUMBER is an arbitrary value, a server may use to associate
+   simultaneous running sessions.  It is a 32 bit unsigned integer
+   with 0 as a special value indicating that no session association
+   shall be done.
+
+   If STRING is given, the server may use this as the title of a
+   window or, in the case of an email operation, to extract the
+   sender's address. The string may contain spaces; thus no
+   plus-escaping is used.
+
+   This command may be used at any time and overrides the effect of
+   the last command.  A RESET command undoes the effect of this
+   command.
+*/
+static int
+cmd_session (assuan_context_t ctx, char *line)
+{
+  gpg_error_t err = 0;
+
+  line = skip_options (line);
+
+  /* FIXME implement the command.  */
+
+  return assuan_process_done (ctx, err);
+}
+
+
+
 /*  RECIPIENT <recipient>
 
   Set the recipient for the encryption.  <recipient> is an RFC2822
@@ -295,7 +541,35 @@
 }
 
 
+
+/* MESSAGE FD=<n>
 
+   Set the file descriptor to read a message which is used with
+   detached signatures.
+ */
+static int 
+cmd_message (assuan_context_t ctx, char *line)
+{
+  conn_ctrl_t ctrl = assuan_get_pointer (ctx);
+  gpg_error_t err;;
+  assuan_fd_t sysfd;
+  int fd;
+
+  err = assuan_command_parse_fd (ctx, line, &sysfd);
+  if (!err)
+    {
+      fd = translate_sys2libc_fd (sysfd, 0);
+      if (fd == -1)
+        err = set_error (GPG_ERR_ASS_NO_INPUT, NULL);
+      else
+        ctrl->message_fd = fd;
+    }
+  return assuan_process_done (ctx, err);
+}
+
+
+
+
 
 /* Continuation for cmd_encrypt.  */
 static void
@@ -306,16 +580,7 @@
   g_debug ("cont_encrypt called with with ERR=%s <%s>",
            gpg_strerror (err), gpg_strsource (err));
 
-  if (ctrl->input_channel)
-    {
-      g_io_channel_shutdown (ctrl->input_channel, 0, NULL);
-      ctrl->input_channel = NULL;
-    }
-  if (ctrl->output_channel)
-    {
-      g_io_channel_shutdown (ctrl->output_channel, 0, NULL);
-      ctrl->output_channel = NULL;
-    }
+  finish_io_streams (ctx, NULL, NULL, NULL);
   if (!err)
     release_recipients (ctrl);
   assuan_process_done (ctx, err);
@@ -336,26 +601,14 @@
   gpgme_data_t input_data = NULL;
   gpgme_data_t output_data = NULL;
 
+  err = parse_protocol_option (ctx, line, 1, &protocol);
+  if (err)
+    goto leave;
 
-  if (has_option (line, "--protocol=OpenPGP"))
-    protocol = GPGME_PROTOCOL_OpenPGP;
-  else if (has_option (line, "--protocol=CMS"))
-    protocol = GPGME_PROTOCOL_CMS;
-  else if (has_option_name (line, "--protocol"))
-    {
-      err = set_error (GPG_ERR_ASS_PARAMETER, "invalid protocol");
-      goto leave;
-    }
-  else 
-    {
-      err = set_error (GPG_ERR_ASS_PARAMETER, "no protocol specified");
-      goto leave;
-    }
-
   if (protocol != ctrl->selected_protocol)
     {
       if (ctrl->selected_protocol != GPGME_PROTOCOL_UNKNOWN)
-        g_debug ("note: protocol does not macth the one from PREP_ENCRYPT");
+        g_debug ("note: protocol does not match the one from PREP_ENCRYPT");
       reset_prepared_keys (ctrl);
     }
 
@@ -366,52 +619,10 @@
       goto leave;
     }
 
-  ctrl->input_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
-  if (ctrl->input_fd == -1)
-    {
-      err = set_error (GPG_ERR_ASS_NO_INPUT, NULL);
-      goto leave;
-    }
-  ctrl->output_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
-  if (ctrl->output_fd == -1)
-    {
-      err = set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
-      goto leave;
-    }
-
-#ifdef HAVE_W32_SYSTEM
-  ctrl->input_channel = g_io_channel_win32_new_fd (ctrl->input_fd);
-#else
-  ctrl->input_channel = g_io_channel_unix_new (ctrl->input_fd);
-#endif
-  if (!ctrl->input_channel)
-    {
-      g_debug ("error creating input channel");
-      err = GPG_ERR_EIO;
-      goto leave;
-    }
-  g_io_channel_set_encoding (ctrl->input_channel, NULL, NULL);
-  g_io_channel_set_buffered (ctrl->input_channel, FALSE);
-
-#ifdef HAVE_W32_SYSTEM
-  ctrl->output_channel = g_io_channel_win32_new_fd (ctrl->output_fd);
-#else
-  ctrl->output_channel = g_io_channel_unix_new (ctrl->output_fd);
-#endif
-  if (!ctrl->output_channel)
-    {
-      g_debug ("error creating output channel");
-      err = GPG_ERR_EIO;
-      goto leave;
-    }
-  g_io_channel_set_encoding (ctrl->output_channel, NULL, NULL);
-  g_io_channel_set_buffered (ctrl->output_channel, FALSE);
-
-
-  err = gpgme_data_new_from_cbs (&input_data, &my_gpgme_data_cbs, ctrl);
+  err = translate_io_streams (ctx);
   if (err)
     goto leave;
-  err = gpgme_data_new_from_cbs (&output_data, &my_gpgme_data_cbs, ctrl);
+  err = prepare_io_streams (ctx, &input_data, &output_data, NULL);
   if (err)
     goto leave;
 
@@ -431,18 +642,8 @@
   return not_finished (ctrl);
 
  leave:
-  gpgme_data_release (input_data); 
-  gpgme_data_release (output_data);
-  if (ctrl->input_channel)
-    {
-      g_io_channel_shutdown (ctrl->input_channel, 0, NULL);
-      ctrl->input_channel = NULL;
-    }
-  if (ctrl->output_channel)
-    {
-      g_io_channel_shutdown (ctrl->output_channel, 0, NULL);
-      ctrl->output_channel = NULL;
-    }
+  finish_io_streams (ctx, &input_data, &output_data, NULL);
+  close_message_fd (ctrl);
   assuan_close_input_fd (ctx);
   assuan_close_output_fd (ctx);
   return assuan_process_done (ctx, err);
@@ -489,18 +690,12 @@
 {
   conn_ctrl_t ctrl = assuan_get_pointer (ctx);
   gpg_error_t err;
-  gpgme_protocol_t protocol = GPGME_PROTOCOL_UNKNOWN;
+  gpgme_protocol_t protocol;
   GpaStreamEncryptOperation *op;
 
-  if (has_option (line, "--protocol=OpenPGP"))
-    protocol = GPGME_PROTOCOL_OpenPGP;
-  else if (has_option (line, "--protocol=CMS"))
-    protocol = GPGME_PROTOCOL_CMS;
-  else if (has_option_name (line, "--protocol"))
-    {
-      err = set_error (GPG_ERR_ASS_PARAMETER, "invalid protocol");
-      goto leave;
-    }
+  err = parse_protocol_option (ctx, line, 0, &protocol);
+  if (err)
+    goto leave;
 
   line = skip_options (line);
   if (*line)
@@ -577,16 +772,7 @@
   g_debug ("cont_sign called with with ERR=%s <%s>",
            gpg_strerror (err), gpg_strsource (err));
 
-  if (ctrl->input_channel)
-    {
-      g_io_channel_shutdown (ctrl->input_channel, 0, NULL);
-      ctrl->input_channel = NULL;
-    }
-  if (ctrl->output_channel)
-    {
-      g_io_channel_shutdown (ctrl->output_channel, 0, NULL);
-      ctrl->output_channel = NULL;
-    }
+  finish_io_streams (ctx, NULL, NULL, NULL);
   if (!err)
     {
       xfree (ctrl->sender);
@@ -605,26 +791,15 @@
 {
   conn_ctrl_t ctrl = assuan_get_pointer (ctx);
   gpg_error_t err;
-  gpgme_protocol_t protocol = 0;
+  gpgme_protocol_t protocol;
   gboolean detached;
   GpaStreamSignOperation *op;
   gpgme_data_t input_data = NULL;
   gpgme_data_t output_data = NULL;
 
-  if (has_option (line, "--protocol=OpenPGP"))
-    protocol = GPGME_PROTOCOL_OpenPGP;
-  else if (has_option (line, "--protocol=CMS"))
-    protocol = GPGME_PROTOCOL_CMS;
-  else if (has_option_name (line, "--protocol"))
-    {
-      err = set_error (GPG_ERR_ASS_PARAMETER, "invalid protocol");
-      goto leave;
-    }
-  else 
-    {
-      err = set_error (GPG_ERR_ASS_PARAMETER, "no protocol specified");
-      goto leave;
-    }
+  err = parse_protocol_option (ctx, line, 1, &protocol);
+  if (err)
+    goto leave;
 
   detached = has_option (line, "--detached");
 
@@ -635,58 +810,101 @@
       goto leave;
     }
 
-  ctrl->input_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
-  if (ctrl->input_fd == -1)
-    {
-      err = set_error (GPG_ERR_ASS_NO_INPUT, NULL);
-      goto leave;
-    }
-  ctrl->output_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
-  if (ctrl->output_fd == -1)
-    {
-      err = set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
-      goto leave;
-    }
+  err = translate_io_streams (ctx);
+  if (err)
+    goto leave;
+  err = prepare_io_streams (ctx, &input_data, &output_data, NULL);
+  if (err)
+    goto leave;
 
-#ifdef HAVE_W32_SYSTEM
-  ctrl->input_channel = g_io_channel_win32_new_fd (ctrl->input_fd);
-#else
-  ctrl->input_channel = g_io_channel_unix_new (ctrl->input_fd);
-#endif
-  if (!ctrl->input_channel)
+  ctrl->cont_cmd = cont_sign;
+  op = gpa_stream_sign_operation_new (NULL, input_data, output_data,
+                                      ctrl->sender, protocol, detached);
+  input_data = output_data = NULL;
+  g_signal_connect_swapped (G_OBJECT (op), "completed",
+			    G_CALLBACK (run_server_continuation), ctx);
+  g_signal_connect (G_OBJECT (op), "completed",
+                    G_CALLBACK (g_object_unref), NULL);
+  g_signal_connect_swapped (G_OBJECT (op), "status",
+			    G_CALLBACK (assuan_write_status), ctx);
+
+  return not_finished (ctrl);
+
+ leave:
+  finish_io_streams (ctx, &input_data, &output_data, NULL);
+  close_message_fd (ctrl);
+  assuan_close_input_fd (ctx);
+  assuan_close_output_fd (ctx);
+  return assuan_process_done (ctx, err);
+}
+
+
+
+/* Continuation for cmd_decrypt.  */
+static void
+cont_decrypt (assuan_context_t ctx, gpg_error_t err)
+{
+  conn_ctrl_t ctrl = assuan_get_pointer (ctx);
+
+  g_debug ("cont_decrypt called with with ERR=%s <%s>",
+           gpg_strerror (err), gpg_strsource (err));
+
+  finish_io_streams (ctx, NULL, NULL, NULL);
+  if (!err)
     {
-      g_debug ("error creating input channel");
-      err = GPG_ERR_EIO;
-      goto leave;
+      xfree (ctrl->sender);
+      ctrl->sender = NULL;
     }
-  g_io_channel_set_encoding (ctrl->input_channel, NULL, NULL);
-  g_io_channel_set_buffered (ctrl->input_channel, FALSE);
+  assuan_process_done (ctx, err);
+}
 
-#ifdef HAVE_W32_SYSTEM
-  ctrl->output_channel = g_io_channel_win32_new_fd (ctrl->output_fd);
-#else
-  ctrl->output_channel = g_io_channel_unix_new (ctrl->output_fd);
-#endif
-  if (!ctrl->output_channel)
+
+/* DECRYPT --protocol=OpenPGP|CMS [--no-verify]
+
+   Decrypt a message given by the source set with the INPUT command
+   and write the plaintext to the sink set with the OUTPUT command.
+
+   If the option --no-verify is given, the server should not try to
+   verify a signature, in case the input data is an OpenPGP combined
+   message.
+*/
+static int 
+cmd_decrypt (assuan_context_t ctx, char *line)
+{
+  conn_ctrl_t ctrl = assuan_get_pointer (ctx);
+  gpg_error_t err;
+  gpgme_protocol_t protocol = 0;
+  int no_verify;
+  GpaStreamSignOperation *op;  /* Fixme: use GpaStreamDecryptOperatio!!!*/
+  gpgme_data_t input_data = NULL;
+  gpgme_data_t output_data = NULL;
+
+  err = parse_protocol_option (ctx, line, 1, &protocol);
+  if (err)
+    goto leave;
+
+  no_verify= has_option (line, "--no-verify");
+
+  line = skip_options (line);
+  if (*line)
     {
-      g_debug ("error creating output channel");
-      err = GPG_ERR_EIO;
+      err = set_error (GPG_ERR_ASS_SYNTAX, NULL);
       goto leave;
     }
-  g_io_channel_set_encoding (ctrl->output_channel, NULL, NULL);
-  g_io_channel_set_buffered (ctrl->output_channel, FALSE);
 
-
-  err = gpgme_data_new_from_cbs (&input_data, &my_gpgme_data_cbs, ctrl);
+  err = translate_io_streams (ctx);
   if (err)
     goto leave;
-  err = gpgme_data_new_from_cbs (&output_data, &my_gpgme_data_cbs, ctrl);
+  err = prepare_io_streams (ctx, &input_data, &output_data, NULL);
   if (err)
     goto leave;
 
-  ctrl->cont_cmd = cont_sign;
+  ctrl->cont_cmd = cont_decrypt;
+
+#warning  FIXME:  Use decrypt.
   op = gpa_stream_sign_operation_new (NULL, input_data, output_data,
-                                      ctrl->sender, protocol, detached);
+                                      ctrl->sender, protocol, 1);
+
   input_data = output_data = NULL;
   g_signal_connect_swapped (G_OBJECT (op), "completed",
 			    G_CALLBACK (run_server_continuation), ctx);
@@ -698,18 +916,146 @@
   return not_finished (ctrl);
 
  leave:
-  gpgme_data_release (input_data); 
-  gpgme_data_release (output_data);
-  if (ctrl->input_channel)
+  finish_io_streams (ctx, &input_data, &output_data, NULL);
+  close_message_fd (ctrl);
+  assuan_close_input_fd (ctx);
+  assuan_close_output_fd (ctx);
+  return assuan_process_done (ctx, err);
+}
+
+
+
+
+/* Continuation for cmd_verify.  */
+static void
+cont_verify (assuan_context_t ctx, gpg_error_t err)
+{
+  conn_ctrl_t ctrl = assuan_get_pointer (ctx);
+
+  g_debug ("cont_verify called with with ERR=%s <%s>",
+           gpg_strerror (err), gpg_strsource (err));
+
+  finish_io_streams (ctx, NULL, NULL, NULL);
+  if (!err)
     {
-      g_io_channel_shutdown (ctrl->input_channel, 0, NULL);
-      ctrl->input_channel = NULL;
+      xfree (ctrl->sender);
+      ctrl->sender = NULL;
     }
-  if (ctrl->output_channel)
+  assuan_process_done (ctx, err);
+}
+
+
+/* VERIFY --protocol=OpenPGP|CMS [--silent]
+
+   Verify a message.  Depending on the combination of the
+   sources/sinks set by the commands MESSAGE, INPUT and OUTPUT, the
+   verification mode is selected like this:
+
+   MESSAGE and INPUT
+     This indicates a detached signature.  Output data is not applicable.
+
+   INPUT 
+     This indicates an opaque signature.  As no output command has
+     been given, we are only required to check the signature.
+
+   INPUT and OUTPUT
+     This indicates an opaque signature.  We write the signed data to
+     the file descriptor set by the OUTPUT command.  This data is even
+     written if the signature can't be verified.
+
+   With the option --silent we won't display any dialog; this is for
+   example used by the client to get the content of an opaque signed
+   message.  Sending the follwoing status message is mandatory before
+   sending the OK response:
+
+      SIGSTATUS <flag> <displaystring>
+
+   Defines FLAGS are:
+
+      none
+        The message has a signature but it could not not be verified
+        due to a missing key.
+
+      green
+        The signature is fully valid.
+
+      yellow
+        The signature is valid but additional information was shown
+        regarding the validity of the key.
+
+      red
+        The signature is not valid. 
+
+   The DISPLAYSTRING is a percent-and-plus-encoded string with a short
+   human readable description of the status.
+*/
+static int 
+cmd_verify (assuan_context_t ctx, char *line)
+{
+  conn_ctrl_t ctrl = assuan_get_pointer (ctx);
+  gpg_error_t err;
+  gpgme_protocol_t protocol = 0;
+  int silent;
+  GpaStreamSignOperation *op;  /* Fixme: use GpaStreamDecryptOperatio!!!*/
+  gpgme_data_t input_data = NULL;
+  gpgme_data_t output_data = NULL;
+  gpgme_data_t message_data = NULL;
+
+  err = parse_protocol_option (ctx, line, 1, &protocol);
+  if (err)
+    goto leave;
+
+  silent = has_option (line, "--silent");
+
+  line = skip_options (line);
+  if (*line)
     {
-      g_io_channel_shutdown (ctrl->output_channel, 0, NULL);
-      ctrl->output_channel = NULL;
+      err = set_error (GPG_ERR_ASS_SYNTAX, NULL);
+      goto leave;
     }
+
+  /* Note: We can't use translate_io_streams becuase that returns an
+     error if one is not opened but that is not an error here.  */
+  ctrl->input_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
+  ctrl->output_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
+  if (ctrl->message_fd != -1 && ctrl->input_fd != -1 
+      && ctrl->output_fd == -1)
+    ; /* Mode = detached. */
+  else if (ctrl->message_fd == -1 && ctrl->input_fd != -1 
+           && ctrl->output_fd == -1)
+    ; /* Mode = opaque. */
+  else if (ctrl->message_fd == -1 && ctrl->input_fd != -1 
+           && ctrl->output_fd != -1)
+    ; /* Mode = opaque with output. */
+  else
+    {
+      err = set_error (GPG_ERR_CONFLICT, "invalid verify mode");
+      goto leave;
+    }
+  
+  err = prepare_io_streams (ctx, &input_data, &output_data, &message_data);
+  if (err)
+    goto leave;
+
+  ctrl->cont_cmd = cont_decrypt;
+
+#warning  FIXME:  Use verify.
+  op = gpa_stream_sign_operation_new (NULL, input_data, output_data,
+                                      ctrl->sender, protocol, 1);
+
+  input_data = output_data = message_data = NULL;
+  g_signal_connect_swapped (G_OBJECT (op), "completed",
+			    G_CALLBACK (run_server_continuation), ctx);
+  g_signal_connect (G_OBJECT (op), "completed",
+                    G_CALLBACK (g_object_unref), NULL);
+  g_signal_connect_swapped (G_OBJECT (op), "status",
+			    G_CALLBACK (assuan_write_status), ctx);
+
+  return not_finished (ctrl);
+
+ leave:
+  finish_io_streams (ctx, &input_data, &output_data, &message_data);
+  close_message_fd (ctrl);
   assuan_close_input_fd (ctx);
   assuan_close_output_fd (ctx);
   return assuan_process_done (ctx, err);
@@ -775,16 +1121,8 @@
   release_recipients (ctrl);
   xfree (ctrl->sender);
   ctrl->sender = NULL;
-  if (ctrl->input_channel)
-    {
-      g_io_channel_shutdown (ctrl->input_channel, 0, NULL);
-      ctrl->input_channel = NULL;
-    }
-  if (ctrl->output_channel)
-    {
-      g_io_channel_shutdown (ctrl->output_channel, 0, NULL);
-      ctrl->output_channel = NULL;
-    }
+  finish_io_streams (ctx, NULL, NULL, NULL);
+  close_message_fd (ctrl);
   assuan_close_input_fd (ctx);
   assuan_close_output_fd (ctx);
   if (ctrl->gpa_op)
@@ -805,13 +1143,17 @@
     const char *name;
     int (*handler)(assuan_context_t, char *line);
   } table[] = {
+    { "SESSION",   cmd_session },
     { "RECIPIENT", cmd_recipient },
     { "INPUT",     NULL },
     { "OUTPUT",    NULL },
+    { "MESSAGE",   cmd_message },
     { "ENCRYPT",   cmd_encrypt },
     { "PREP_ENCRYPT", cmd_prep_encrypt },
     { "SENDER",    cmd_sender },
     { "SIGN",      cmd_sign   },
+    { "DECRYPT",   cmd_decrypt },
+    { "VERIFY",    cmd_verify },
     { "START_KEYMANAGER", cmd_start_keymanager },
     { "GETINFO",   cmd_getinfo },
     { NULL }
@@ -859,6 +1201,7 @@
   assuan_set_pointer (ctx, ctrl);
   assuan_set_log_stream (ctx, stderr);
   assuan_register_reset_notify (ctx, reset_notify);
+  ctrl->message_fd = -1;
 
   connection_counter++;
   return ctx;

Modified: trunk/src/settingsdlg.c
===================================================================
--- trunk/src/settingsdlg.c	2008-05-06 16:13:33 UTC (rev 885)
+++ trunk/src/settingsdlg.c	2008-05-07 11:19:25 UTC (rev 886)
@@ -84,7 +84,9 @@
 
   /* Data for the auto-key-locate frame.  */
   struct {
-    GtkWidget *frame;
+    int enabled;  /* True if the AKL feature is enabled.  */
+
+    GtkWidget *frame;   
     GtkComboBox *methods;
     GtkWidget *addr_hbox;
     GtkEntry  *addr_entry;
@@ -162,12 +164,14 @@
   if (gpa_options_get_show_advanced_options (options))
     {
       gtk_widget_show_all (dialog->keyserver.frame);
-      gtk_widget_show_all (dialog->akl.frame);
+      if (dialog->akl.enabled)
+        gtk_widget_show_all (dialog->akl.frame);
     }
   else
     {
       gtk_widget_hide_all (dialog->keyserver.frame);
-      gtk_widget_hide_all (dialog->akl.frame);
+      if (dialog->akl.enabled)
+        gtk_widget_hide_all (dialog->akl.frame);
     }
 }
 
@@ -677,7 +681,8 @@
   gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
                                      GTK_RESPONSE_APPLY, newstate);
 
-  gtk_widget_set_sensitive (dialog->akl.addr_hbox, dialog->akl.require_addr);
+  if (dialog->akl.enabled)
+    gtk_widget_set_sensitive (dialog->akl.addr_hbox, dialog->akl.require_addr);
 }
 
 
@@ -706,7 +711,8 @@
                       gpa_options_get_default_keyserver (options));
 
   /* AKL section. */
-  parse_akl (dialog);
+  if (dialog->akl.enabled)
+    parse_akl (dialog);
 
 
   update_modified (dialog, 0);
@@ -737,7 +743,7 @@
       return -1;
     }
                         
-  if ((errwdg = check_akl (dialog)))
+  if ( dialog->akl.enabled && (errwdg = check_akl (dialog)))
     {
       gpa_window_error 
         (_("The data given for \"Auto key locate\" is not valid."),
@@ -753,8 +759,9 @@
   gpa_options_set_default_keyserver (gpa_options_get_instance (), 
                                      dialog->keyserver.url);
 
-
-  if (dialog->akl.method_idx == -1)
+  if (!dialog->akl.enabled)
+    ; 
+  else if (dialog->akl.method_idx == -1)
     ; /* oops: none selected.  */
   else if (!akl_table[dialog->akl.method_idx].list)
     {
@@ -904,9 +911,13 @@
                       FALSE, FALSE, 0);
 
   /* The auto key locate section.  */
-  frame = auto_key_locate_frame (dialog);
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame,
-                      FALSE, FALSE, 0);
+  dialog->akl.enabled = is_gpg_version_at_least ("2.0.10");
+  if (dialog->akl.enabled)
+    {
+      frame = auto_key_locate_frame (dialog);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame,
+                          FALSE, FALSE, 0);
+    }
 
   /* Connect the response signal.  */
   g_signal_connect (GTK_OBJECT (dialog), "response", 



More information about the Gpa-commits mailing list