diff options
author | Werner Koch <wk@gnupg.org> | 2002-01-19 18:20:15 +0000 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2002-01-19 18:20:15 +0000 |
commit | c5698a48387a9b7fb252222eb40c42a7c9f76310 (patch) | |
tree | c9a897a17f2b1660beb13aa3a1617f17a5299146 | |
parent | ba6c275d1ad8b7575ac42360c68061373b5c21d5 (diff) | |
download | libassuan-c5698a48387a9b7fb252222eb40c42a7c9f76310.tar.gz |
* 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.
-rw-r--r-- | src/ChangeLog | 19 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/assuan-buffer.c | 56 | ||||
-rw-r--r-- | src/assuan-connect.c | 6 | ||||
-rw-r--r-- | src/assuan-defs.h | 15 | ||||
-rw-r--r-- | src/assuan-handler.c | 4 | ||||
-rw-r--r-- | src/assuan-listen.c | 10 | ||||
-rw-r--r-- | src/assuan-pipe-server.c | 33 | ||||
-rw-r--r-- | src/assuan-socket-server.c | 121 | ||||
-rw-r--r-- | src/assuan-util.c | 54 | ||||
-rw-r--r-- | src/assuan.h | 9 |
11 files changed, 311 insertions, 19 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 87c88fe..3c3fdcd 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -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 diff --git a/src/Makefile.am b/src/Makefile.am index bc14e8f..c4d117e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/assuan-buffer.c b/src/assuan-buffer.c index 399d11d..bd08817 100644 --- a/src/assuan-buffer.c +++ b/src/assuan-buffer.c @@ -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)) diff --git a/src/assuan-connect.c b/src/assuan-connect.c index 613b54a..53b742f 100644 --- a/src/assuan-connect.c +++ b/src/assuan-connect.c @@ -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 diff --git a/src/assuan-defs.h b/src/assuan-defs.h index 07f56e3..d19e6b9 100644 --- a/src/assuan-defs.h +++ b/src/assuan-defs.h @@ -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*/ diff --git a/src/assuan-handler.c b/src/assuan-handler.c index ce7476a..db9749e 100644 --- a/src/assuan-handler.c +++ b/src/assuan-handler.c @@ -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); diff --git a/src/assuan-listen.c b/src/assuan-listen.c index 57fe4b6..db63ad2 100644 --- a/src/assuan-listen.c +++ b/src/assuan-listen.c @@ -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 diff --git a/src/assuan-pipe-server.c b/src/assuan-pipe-server.c index 58f981a..c283a92 100644 --- a/src/assuan-pipe-server.c +++ b/src/assuan-pipe-server.c @@ -24,6 +24,26 @@ #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/src/assuan-socket-server.c b/src/assuan-socket-server.c new file mode 100644 index 0000000..6ad6455 --- /dev/null +++ b/src/assuan-socket-server.c @@ -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; +} + + + + + + + + + + diff --git a/src/assuan-util.c b/src/assuan-util.c index 3eeee9a..96cd68d 100644 --- a/src/assuan-util.c +++ b/src/assuan-util.c @@ -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); + } +} diff --git a/src/assuan.h b/src/assuan.h index 477e2de..3382283 100644 --- a/src/assuan.h +++ b/src/assuan.h @@ -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); |