* assuan-buffer.c (_assuan_read_line): Add output logging.
authorWerner Koch <wk@gnupg.org>
Sat, 19 Jan 2002 18:20:15 +0000 (18:20 +0000)
committerWerner Koch <wk@gnupg.org>
Sat, 19 Jan 2002 18:20:15 +0000 (18:20 +0000)
(assuan_write_line): Ditto.
(_assuan_cookie_write_data): Ditto.
(_assuan_cookie_write_flush): Ditto.
* assuan-util.c (_assuan_log_print_buffer): New.
(assuan_set_log_stream): New.
(assuan_begin_confidential): New.
(assuan_end_confidential): New.

* assuan-defs.h: Add a few handler variables.
* assuan-pipe-server.c (assuan_deinit_pipe_server): Removed.
(deinit_pipe_server): New.
(assuan_deinit_server): New.  Changed all callers to use this.
* assuan-listen.c (assuan_accept): Use the accept handler.
* assuan-handler.c (process_request): Use the close Handler.
* assuan-socket-server.c: New.

assuan/ChangeLog
assuan/Makefile.am
assuan/assuan-buffer.c
assuan/assuan-connect.c
assuan/assuan-defs.h
assuan/assuan-handler.c
assuan/assuan-listen.c
assuan/assuan-pipe-server.c
assuan/assuan-socket-server.c [new file with mode: 0644]
assuan/assuan-util.c
assuan/assuan.h

index 87c88fe..3c3fdcd 100644 (file)
@@ -1,3 +1,22 @@
+2002-01-19  Werner Koch  <wk@gnupg.org>
+
+       * assuan-buffer.c (_assuan_read_line): Add output logging.
+       (assuan_write_line): Ditto.
+       (_assuan_cookie_write_data): Ditto.
+       (_assuan_cookie_write_flush): Ditto.
+       * assuan-util.c (_assuan_log_print_buffer): New.
+       (assuan_set_log_stream): New.
+       (assuan_begin_confidential): New.
+       (assuan_end_confidential): New.
+
+       * assuan-defs.h: Add a few handler variables.
+       * assuan-pipe-server.c (assuan_deinit_pipe_server): Removed.
+       (deinit_pipe_server): New.
+       (assuan_deinit_server): New.  Changed all callers to use this.
+       * assuan-listen.c (assuan_accept): Use the accept handler.
+       * assuan-handler.c (process_request): Use the close Handler.
+       * assuan-socket-server.c: New.
+
 2002-01-14  Werner Koch  <wk@gnupg.org>
 
        * assuan-client.c (_assuan_read_from_server): Skip spaces after
index bc14e8f..c4d117e 100644 (file)
@@ -38,7 +38,8 @@ libassuan_a_SOURCES = \
        assuan-listen.c \
        assuan-connect.c \
        assuan-client.c \
-       assuan-pipe-server.c 
+       assuan-pipe-server.c \
+       assuan-socket-server.c 
 
 
 assuan-errors.c : assuan.h
index 399d11d..bd08817 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <config.h>
 #include <stdlib.h>
+#include <string.h>
 #include <stdio.h>
 #include <errno.h>
 #include <unistd.h>
@@ -119,10 +120,17 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
     rc = readline (ctx->inbound.fd, line, LINELENGTH,
                    &nread, &ctx->inbound.eof);
   if (rc)
-    return ASSUAN_Read_Error;
+    {
+      if (ctx->log_fp)
+        fprintf (ctx->log_fp, "%p <- [Error: %s]\n",
+                 ctx, strerror (errno)); 
+      return ASSUAN_Read_Error;
+    }
   if (!nread)
     {
       assert (ctx->inbound.eof);
+      if (ctx->log_fp)
+        fprintf (ctx->log_fp, "%p <- [EOF]\n", ctx); 
       return -1; 
     }
 
@@ -153,10 +161,23 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
             n--;
           line[n] = 0;
           ctx->inbound.linelen = n;
+          if (ctx->log_fp)
+            {
+              fprintf (ctx->log_fp, "%p <- ", ctx); 
+              if (ctx->confidential)
+                fputs ("[Confidential data not shown]", ctx->log_fp);
+              else
+                _assuan_log_print_buffer (ctx->log_fp, 
+                                          ctx->inbound.line,
+                                          ctx->inbound.linelen);
+              putc ('\n', ctx->log_fp);
+            }
           return 0;
         }
     }
 
+  if (ctx->log_fp)
+    fprintf (ctx->log_fp, "%p <- [Invalid line]\n", ctx);
   *line = 0;
   ctx->inbound.linelen = 0;
   return ctx->inbound.eof? ASSUAN_Line_Not_Terminated : ASSUAN_Line_Too_Long;
@@ -206,6 +227,17 @@ assuan_write_line (ASSUAN_CONTEXT ctx, const char *line )
     return ASSUAN_Invalid_Value;
 
   /* fixme: we should do some kind of line buffering */
+  if (ctx->log_fp)
+    {
+      fprintf (ctx->log_fp, "%p -> ", ctx); 
+      if (ctx->confidential)
+        fputs ("[Confidential data not shown]", ctx->log_fp);
+      else
+        _assuan_log_print_buffer (ctx->log_fp, 
+                                  line, strlen (line));
+      putc ('\n', ctx->log_fp);
+    }
+
   rc = writen (ctx->outbound.fd, line, strlen(line));
   if (rc)
     rc = ASSUAN_Write_Error;
@@ -266,6 +298,17 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size)
       
       if (linelen >= LINELENGTH-2-2)
         {
+          if (ctx->log_fp)
+            {
+              fprintf (ctx->log_fp, "%p -> ", ctx); 
+              if (ctx->confidential)
+                fputs ("[Confidential data not shown]", ctx->log_fp);
+              else 
+                _assuan_log_print_buffer (ctx->log_fp, 
+                                          ctx->outbound.data.line,
+                                          linelen);
+              putc ('\n', ctx->log_fp);
+            }
           *line++ = '\n';
           linelen++;
           if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen))
@@ -300,6 +343,17 @@ _assuan_cookie_write_flush (void *cookie)
   line += linelen;
   if (linelen)
     {
+      if (ctx->log_fp)
+        {
+          fprintf (ctx->log_fp, "%p -> ", ctx); 
+          if (ctx->confidential)
+            fputs ("[Confidential data not shown]", ctx->log_fp);
+          else
+            _assuan_log_print_buffer (ctx->log_fp, 
+                                      ctx->outbound.data.line,
+                                      linelen);
+          putc ('\n', ctx->log_fp);
+            }
       *line++ = '\n';
       linelen++;
       if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen))
index 613b54a..53b742f 100644 (file)
@@ -133,7 +133,7 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[],
       close (rp[1]);
       close (wp[0]);
       close (wp[1]);
-      assuan_deinit_pipe_server (*ctx);  /* FIXME: Common code should be factored out.  */
+      assuan_deinit_server (*ctx);  /* FIXME: Common code should be factored out.  */
       return ASSUAN_General_Error;
     }
 
@@ -221,7 +221,7 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[],
     {
       if ((*ctx)->pid != -1)
         waitpid ((*ctx)->pid, NULL, 0);  /* FIXME Check return value.  */
-      assuan_deinit_pipe_server (*ctx);  /* FIXME: Common code should be factored out.  */
+      assuan_deinit_server (*ctx);  /* FIXME: Common code should be factored out.  */
     }
 
   return err;
@@ -234,7 +234,7 @@ assuan_pipe_disconnect (ASSUAN_CONTEXT ctx)
   close (ctx->inbound.fd);
   close (ctx->outbound.fd);
   waitpid (ctx->pid, NULL, 0);  /* FIXME Check return value.  */
-  assuan_deinit_pipe_server (ctx);
+  assuan_deinit_server (ctx);
 }
 
 pid_t
index 07f56e3..d19e6b9 100644 (file)
@@ -35,7 +35,9 @@ struct cmdtbl_s {
 struct assuan_context_s {
   AssuanError err_no;
   const char *err_str;
+  int os_errno;  /* last system error number used with certain error codes*/
 
+  int confidential;
   int is_server;  /* set if this is context belongs to a server */
   int in_inquire;
   char *hello_line;
@@ -43,6 +45,8 @@ struct assuan_context_s {
   
   void *user_pointer;  /* for assuan_[gs]et_pointer () */
 
+  FILE *log_fp;
+
   struct {
     int fd;
     int eof;
@@ -69,7 +73,12 @@ struct assuan_context_s {
 
   int pipe_mode;  /* We are in pipe mode, i.e. we can handle just one
                      connection and must terminate then */
-  pid_t pid;   /* In pipe mode, the pid of the child server process.  */
+  pid_t pid;     /* In pipe mode, the pid of the child server process.  */
+  int listen_fd;  /* The fd we are listening on (used by socket servers) */
+
+  void (*deinit_handler)(ASSUAN_CONTEXT);  
+  int (*accept_handler)(ASSUAN_CONTEXT);
+  int (*finish_handler)(ASSUAN_CONTEXT);
 
   struct cmdtbl_s *cmdtbl;
   size_t cmdtbl_used; /* used entries */
@@ -85,8 +94,6 @@ struct assuan_context_s {
   int input_fd;   /* set by INPUT command */
   int output_fd;  /* set by OUTPUT command */
 
-
-
 };
 
 
@@ -115,6 +122,8 @@ void  _assuan_free (void *p);
 
 #define set_error(c,e,t) assuan_set_error ((c), ASSUAN_ ## e, (t))
 
+void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t  length);
+
 
 #endif /*ASSUAN_DEFS_H*/
 
index ce7476a..db9749e 100644 (file)
@@ -387,12 +387,13 @@ process_request (ASSUAN_CONTEXT ctx)
   else if (rc == -1)
     { /* No error checking because the peer may have already disconnect */ 
       assuan_write_line (ctx, "OK closing connection");
+      ctx->finish_handler (ctx);
     }
   else 
     {
       char errline[256];
 
-      if (rc < 100)
+        if (rc < 100)
         sprintf (errline, "ERR %d server fault (%.50s)",
                  ASSUAN_Server_Fault, assuan_strerror (rc));
       else
@@ -405,6 +406,7 @@ process_request (ASSUAN_CONTEXT ctx)
       rc = assuan_write_line (ctx, errline);
     }
 
+  ctx->confidential = 0;
   if (ctx->okay_line)
     {
       xfree (ctx->okay_line);
index 57fe4b6..db63ad2 100644 (file)
@@ -69,15 +69,13 @@ assuan_accept (ASSUAN_CONTEXT ctx)
   if (!ctx)
     return ASSUAN_Invalid_Value;
 
-  /* fixme: cancel existing connection */
   if (ctx->pipe_mode > 1)
     return -1; /* second invocation for pipemode -> terminate */
+  ctx->finish_handler (ctx);
 
-  if (!ctx->pipe_mode)
-    {
-
-      /* fixme: wait for request */
-    }
+  rc = ctx->accept_handler (ctx);
+  if (rc)
+    return rc;
 
   /* send the hello */
   rc = assuan_write_line (ctx, ctx->hello_line? ctx->hello_line
index 58f981a..c283a92 100644 (file)
 
 #include "assuan-defs.h"
 
+static void
+deinit_pipe_server (ASSUAN_CONTEXT ctx)
+{
+  /* nothing to do for this simple server */
+}
+
+static int
+accept_connection (ASSUAN_CONTEXT ctx)
+{
+  /* This is a NOP for a pipe server */
+  return 0;
+}
+
+static int
+finish_connection (ASSUAN_CONTEXT ctx)
+{
+  /* This is a NOP for a pipe server */
+  return 0;
+}
+
 
 int
 assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
@@ -43,6 +63,10 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
   ctx->outbound.fd = filedes[1];
 
   ctx->pipe_mode = 1;
+  ctx->listen_fd = -1;
+  ctx->deinit_handler = deinit_pipe_server;
+  ctx->accept_handler = accept_connection;
+  ctx->finish_handler = finish_connection;
 
   rc = _assuan_register_std_commands (ctx);
   if (rc)
@@ -52,11 +76,16 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
   return rc;
 }
 
+
 void
-assuan_deinit_pipe_server (ASSUAN_CONTEXT ctx)
+assuan_deinit_server (ASSUAN_CONTEXT ctx)
 {
   if (ctx)
     {
+      /* We use this function pointer to avoid linking other server
+         when not needed but still allow for a generic deinit function */
+      ctx->deinit_handler (ctx);
+      ctx->deinit_handler = NULL;
       xfree (ctx->hello_line);
       xfree (ctx->okay_line);
       xfree (ctx);
@@ -70,5 +99,3 @@ assuan_deinit_pipe_server (ASSUAN_CONTEXT ctx)
 
 
 
-
-
diff --git a/assuan/assuan-socket-server.c b/assuan/assuan-socket-server.c
new file mode 100644 (file)
index 0000000..6ad6455
--- /dev/null
@@ -0,0 +1,121 @@
+/* assuan-socket-server.c - Assuan socket based server
+ *     Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "assuan-defs.h"
+
+static int
+accept_connection (ASSUAN_CONTEXT ctx)
+{
+  int fd;
+  struct sockaddr_un clnt_addr;
+  size_t len = sizeof clnt_addr;
+
+  fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len );
+  if (fd == -1)
+    {
+      ctx->os_errno = errno;
+      return ASSUAN_Accept_Failed;
+    }
+
+  ctx->inbound.fd = fd;
+  ctx->inbound.eof = 0;
+  ctx->inbound.linelen = 0;
+  ctx->inbound.attic.linelen = 0;
+  ctx->inbound.attic.pending = 0;
+
+  ctx->outbound.fd = fd;
+  ctx->outbound.data.linelen = 0;
+  ctx->outbound.data.error = 0;
+  
+  ctx->confidential = 0;
+
+  return 0;
+}
+
+static int
+finish_connection (ASSUAN_CONTEXT ctx)
+{
+  if (ctx->inbound.fd != -1)
+    {
+      close (ctx->inbound.fd);
+    }
+  ctx->inbound.fd = -1;
+  ctx->outbound.fd = -1;
+  return 0;
+}
+
+
+static void
+deinit_socket_server (ASSUAN_CONTEXT ctx)
+{
+  finish_connection (ctx);
+}
+
+
+
+/* Initialize a server for the socket LISTEN_FD which has already be
+   put into listen mode */
+int
+assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd)
+{
+  ASSUAN_CONTEXT ctx;
+  int rc;
+
+  *r_ctx = NULL;
+  ctx = xtrycalloc (1, sizeof *ctx);
+  if (!ctx)
+    return ASSUAN_Out_Of_Core;
+  ctx->is_server = 1;
+  ctx->input_fd = -1;
+  ctx->output_fd = -1;
+
+  ctx->inbound.fd = -1;
+  ctx->outbound.fd = -1;
+
+  ctx->listen_fd = listen_fd;
+  ctx->deinit_handler = deinit_socket_server;
+  ctx->accept_handler = accept_connection;
+  ctx->finish_handler = finish_connection;
+
+  rc = _assuan_register_std_commands (ctx);
+  if (rc)
+    xfree (ctx);
+  else
+    *r_ctx = ctx;
+  return rc;
+}
+
+
+
+
+
+
+
+
+
+
index 3eeee9a..96cd68d 100644 (file)
@@ -96,3 +96,57 @@ assuan_get_pointer (ASSUAN_CONTEXT ctx)
   return ctx? ctx->user_pointer : NULL;
 }
 
+
+void
+assuan_set_log_stream (ASSUAN_CONTEXT ctx, FILE *fp)
+{
+  if (ctx)
+    {
+      if (ctx->log_fp)
+        fflush (ctx->log_fp);
+      ctx->log_fp = fp;
+    }
+}
+
+
+void
+assuan_begin_confidential (ASSUAN_CONTEXT ctx)
+{
+  if (ctx)
+    {
+      ctx->confidential = 1;
+    }
+}
+
+void
+assuan_end_confidential (ASSUAN_CONTEXT ctx)
+{
+  if (ctx)
+    {
+      ctx->confidential = 0;
+    }
+}
+
+void
+_assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length)
+{
+  const unsigned char *s;
+  int n;
+
+  for (n=length,s=buffer; n; n--, s++)
+    {
+      if (*s < ' ' || (*s >= 0x7f && *s <= 0xa0))
+        break;
+    }
+  s = buffer;
+  if (!n && *s != '[')
+    fwrite (buffer, length, 1, fp);
+  else
+    {
+      putc ('[', fp);
+      for (n=0; n < length; n++, s++)
+          fprintf (fp, " %02x", *s);
+      putc (' ', fp);
+      putc (']', fp);
+    }
+}
index 477e2de..3382283 100644 (file)
@@ -47,6 +47,7 @@ typedef enum {
   ASSUAN_No_Data_Callback = 12,
   ASSUAN_No_Inquire_Callback = 13,
   ASSUAN_Connect_Failed = 14,
+  ASSUAN_Accept_Failed = 15,
 
   /* error codes above 99 are meant as status codes */
   ASSUAN_Not_Implemented = 100,
@@ -146,7 +147,10 @@ AssuanError assuan_close_output_fd (ASSUAN_CONTEXT ctx);
 
 /*-- assuan-pipe-server.c --*/
 int assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]);
-void assuan_deinit_pipe_server (ASSUAN_CONTEXT ctx);
+void assuan_deinit_server (ASSUAN_CONTEXT ctx);
+
+/*-- assuan-socket-server.c --*/
+int assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd);
 
 
 /*-- assuan-connect.c --*/
@@ -182,10 +186,13 @@ AssuanError assuan_send_data (ASSUAN_CONTEXT ctx,
 void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
                                void *(*new_realloc_func)(void *p, size_t n),
                                void (*new_free_func)(void*) );
+void assuan_set_log_stream (ASSUAN_CONTEXT ctx, FILE *fp);
 int assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text);
 void assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer);
 void *assuan_get_pointer (ASSUAN_CONTEXT ctx);
 
+void assuan_begin_confidential (ASSUAN_CONTEXT ctx);
+void assuan_end_confidential (ASSUAN_CONTEXT ctx);
 
 /*-- assuan-errors.c (built) --*/
 const char *assuan_strerror (AssuanError err);