aboutsummaryrefslogtreecommitdiffstats
path: root/sm/server.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sm/server.c245
1 files changed, 243 insertions, 2 deletions
diff --git a/sm/server.c b/sm/server.c
index c3b9f1559..c44de16da 100644
--- a/sm/server.c
+++ b/sm/server.c
@@ -30,6 +30,18 @@
#include "../assuan/assuan.h"
#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
+#define digitp(a) ((a) >= '0' && (a) <= '9')
+
+
+/* The filepointer for status message used in non-server mode */
+static FILE *statusfp;
+
+/* Data used to assuciate an Assuan context with local server data */
+struct server_local_s {
+ ASSUAN_CONTEXT assuan_ctx;
+ int message_fd;
+};
+
/* RECIPIENT <userID>
@@ -104,12 +116,13 @@ cmd_decrypt (ASSUAN_CONTEXT ctx, char *line)
static int
cmd_verify (ASSUAN_CONTEXT ctx, char *line)
{
+ CTRL ctrl = assuan_get_pointer (ctx);
int fd = assuan_get_input_fd (ctx);
if (fd == -1)
return set_error (No_Input, NULL);
- gpgsm_verify (fd, -1);
+ gpgsm_verify (assuan_get_pointer (ctx), fd, ctrl->server_local->message_fd);
return 0;
}
@@ -141,8 +154,34 @@ cmd_import (ASSUAN_CONTEXT ctx, char *line)
if (fd == -1)
return set_error (No_Input, NULL);
- gpgsm_import (fd);
+ gpgsm_import (assuan_get_pointer (ctx), fd);
+
+ return 0;
+}
+
+/* MESSAGE FD=<n>
+
+ Set the file descriptor to read a message which is used with
+ detached signatures */
+static int
+cmd_message (ASSUAN_CONTEXT ctx, char *line)
+{
+ char *endp;
+ int fd;
+ CTRL ctrl = assuan_get_pointer (ctx);
+
+ if (strncmp (line, "FD=", 3))
+ return set_error (Syntax_Error, "FD=<n> expected");
+ line += 3;
+ if (!digitp (*line))
+ return set_error (Syntax_Error, "number required");
+ fd = strtoul (line, &endp, 10);
+ if (*endp)
+ return set_error (Syntax_Error, "garbage found");
+ if (fd == -1)
+ return set_error (No_Input, NULL);
+ ctrl->server_local->message_fd = fd;
return 0;
}
@@ -166,6 +205,7 @@ register_commands (ASSUAN_CONTEXT ctx)
{ "IMPORT", 0, cmd_import },
{ "", ASSUAN_CMD_INPUT, NULL },
{ "", ASSUAN_CMD_OUTPUT, NULL },
+ { "MESSAGE", 0, cmd_message },
{ NULL }
};
int i, j, rc;
@@ -189,6 +229,9 @@ gpgsm_server (void)
int rc;
int filedes[2];
ASSUAN_CONTEXT ctx;
+ struct server_control_s ctrl;
+
+ memset (&ctrl, 0, sizeof ctrl);
/* For now we use a simple pipe based server so that we can work
from scripts. We will later add options to run as a daemon and
@@ -210,6 +253,11 @@ gpgsm_server (void)
gpgsm_exit (2);
}
+ assuan_set_pointer (ctx, &ctrl);
+ ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
+ ctrl.server_local->assuan_ctx = ctx;
+ ctrl.server_local->message_fd = -1;
+
log_info ("Assuan started\n");
for (;;)
{
@@ -238,6 +286,199 @@ gpgsm_server (void)
}
+static const char *
+get_status_string ( int no )
+{
+ const char *s;
+
+ switch (no)
+ {
+ case STATUS_ENTER : s = "ENTER"; break;
+ case STATUS_LEAVE : s = "LEAVE"; break;
+ case STATUS_ABORT : s = "ABORT"; break;
+ case STATUS_GOODSIG: s = "GOODSIG"; break;
+ case STATUS_SIGEXPIRED: s = "SIGEXPIRED"; break;
+ case STATUS_KEYREVOKED: s = "KEYREVOKED"; break;
+ case STATUS_BADSIG : s = "BADSIG"; break;
+ case STATUS_ERRSIG : s = "ERRSIG"; break;
+ case STATUS_BADARMOR : s = "BADARMOR"; break;
+ case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA"; break;
+ case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED"; break;
+ case STATUS_TRUST_NEVER : s = "TRUST_NEVER"; break;
+ case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL"; break;
+ case STATUS_TRUST_FULLY : s = "TRUST_FULLY"; break;
+ case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE"; break;
+ case STATUS_GET_BOOL : s = "GET_BOOL"; break;
+ case STATUS_GET_LINE : s = "GET_LINE"; break;
+ case STATUS_GET_HIDDEN : s = "GET_HIDDEN"; break;
+ case STATUS_GOT_IT : s = "GOT_IT"; break;
+ case STATUS_SHM_INFO : s = "SHM_INFO"; break;
+ case STATUS_SHM_GET : s = "SHM_GET"; break;
+ case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL"; break;
+ case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN"; break;
+ case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE"; break;
+ case STATUS_VALIDSIG : s = "VALIDSIG"; break;
+ case STATUS_SIG_ID : s = "SIG_ID"; break;
+ case STATUS_ENC_TO : s = "ENC_TO"; break;
+ case STATUS_NODATA : s = "NODATA"; break;
+ case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE"; break;
+ case STATUS_NO_PUBKEY : s = "NO_PUBKEY"; break;
+ case STATUS_NO_SECKEY : s = "NO_SECKEY"; break;
+ case STATUS_NEED_PASSPHRASE_SYM: s = "NEED_PASSPHRASE_SYM"; break;
+ case STATUS_DECRYPTION_FAILED: s = "DECRYPTION_FAILED"; break;
+ case STATUS_DECRYPTION_OKAY: s = "DECRYPTION_OKAY"; break;
+ case STATUS_MISSING_PASSPHRASE: s = "MISSING_PASSPHRASE"; break;
+ case STATUS_GOOD_PASSPHRASE : s = "GOOD_PASSPHRASE"; break;
+ case STATUS_GOODMDC : s = "GOODMDC"; break;
+ case STATUS_BADMDC : s = "BADMDC"; break;
+ case STATUS_ERRMDC : s = "ERRMDC"; break;
+ case STATUS_IMPORTED : s = "IMPORTED"; break;
+ case STATUS_IMPORT_RES : s = "IMPORT_RES"; break;
+ case STATUS_FILE_START : s = "FILE_START"; break;
+ case STATUS_FILE_DONE : s = "FILE_DONE"; break;
+ case STATUS_FILE_ERROR : s = "FILE_ERROR"; break;
+ case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION"; break;
+ case STATUS_END_DECRYPTION : s = "END_DECRYPTION"; break;
+ case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION"; break;
+ case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION"; break;
+ case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM"; break;
+ case STATUS_PROGRESS : s = "PROGRESS"; break;
+ case STATUS_SIG_CREATED : s = "SIG_CREATED"; break;
+ case STATUS_SESSION_KEY : s = "SESSION_KEY"; break;
+ case STATUS_NOTATION_NAME : s = "NOTATION_NAME" ; break;
+ case STATUS_NOTATION_DATA : s = "NOTATION_DATA" ; break;
+ case STATUS_POLICY_URL : s = "POLICY_URL" ; break;
+ case STATUS_BEGIN_STREAM : s = "BEGIN_STREAM"; break;
+ case STATUS_END_STREAM : s = "END_STREAM"; break;
+ case STATUS_KEY_CREATED : s = "KEY_CREATED"; break;
+ case STATUS_UNEXPECTED : s = "UNEXPECTED"; break;
+ case STATUS_INV_RECP : s = "INV_RECP"; break;
+ case STATUS_NO_RECP : s = "NO_RECP"; break;
+ case STATUS_ALREADY_SIGNED : s = "ALREADY_SIGNED"; break;
+ default: s = "?"; break;
+ }
+ return s;
+}
+
+
+
+void
+gpgsm_status (CTRL ctrl, int no, const char *text)
+{
+ if (ctrl->no_server)
+ {
+ if (ctrl->status_fd == -1)
+ return; /* no status wanted */
+ if (!statusfp)
+ {
+ if (ctrl->status_fd == 1)
+ statusfp = stdout;
+ else if (ctrl->status_fd == 2)
+ statusfp = stderr;
+ else
+ statusfp = fdopen (ctrl->status_fd, "w");
+
+ if (!statusfp)
+ {
+ log_fatal ("can't open fd %d for status output: %s\n",
+ ctrl->status_fd, strerror(errno));
+ }
+ }
+
+ fputs ("[GNUPG:] ", statusfp);
+ fputs (get_status_string (no), statusfp);
+
+ if (text)
+ {
+ putc ( ' ', statusfp );
+ for (; *text; text++)
+ {
+ if (*text == '\n')
+ fputs ( "\\n", statusfp );
+ else if (*text == '\r')
+ fputs ( "\\r", statusfp );
+ else
+ putc ( *(const byte *)text, statusfp );
+ }
+ }
+ putc ('\n', statusfp);
+ fflush (statusfp);
+ }
+ else
+ {
+ ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx;
+
+ assuan_write_status (ctx, get_status_string (no), text);
+ }
+}
+
+
+#if 0
+/*
+ * Write a status line with a buffer using %XX escapes. If WRAP is >
+ * 0 wrap the line after this length. If STRING is not NULL it will
+ * be prepended to the buffer, no escaping is done for string.
+ * A wrap of -1 forces spaces not to be encoded as %20.
+ */
+void
+write_status_text_and_buffer ( int no, const char *string,
+ const char *buffer, size_t len, int wrap )
+{
+ const char *s, *text;
+ int esc, first;
+ int lower_limit = ' ';
+ size_t n, count, dowrap;
+
+ if( !statusfp )
+ return; /* not enabled */
+
+ if (wrap == -1) {
+ lower_limit--;
+ wrap = 0;
+ }
+
+ text = get_status_string (no);
+ count = dowrap = first = 1;
+ do {
+ if (dowrap) {
+ fprintf (statusfp, "[GNUPG:] %s ", text );
+ count = dowrap = 0;
+ if (first && string) {
+ fputs (string, statusfp);
+ count += strlen (string);
+ }
+ first = 0;
+ }
+ for (esc=0, s=buffer, n=len; n && !esc; s++, n-- ) {
+ if ( *s == '%' || *(const byte*)s <= lower_limit
+ || *(const byte*)s == 127 )
+ esc = 1;
+ if ( wrap && ++count > wrap ) {
+ dowrap=1;
+ break;
+ }
+ }
+ if (esc) {
+ s--; n++;
+ }
+ if (s != buffer)
+ fwrite (buffer, s-buffer, 1, statusfp );
+ if ( esc ) {
+ fprintf (statusfp, "%%%02X", *(const byte*)s );
+ s++; n--;
+ }
+ buffer = s;
+ len = n;
+ if ( dowrap && len )
+ putc ( '\n', statusfp );
+ } while ( len );
+
+ putc ('\n',statusfp);
+ fflush (statusfp);
+}
+#endif
+
+