summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sm/ChangeLog6
-rw-r--r--sm/Makefile.am2
-rw-r--r--sm/base64.c401
-rw-r--r--sm/encrypt.c256
-rw-r--r--sm/gpgsm.c6
-rw-r--r--sm/gpgsm.h21
-rw-r--r--sm/import.c233
-rw-r--r--sm/server.c69
-rw-r--r--sm/sign.c37
-rw-r--r--sm/verify.c82
10 files changed, 782 insertions, 331 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog
index f0d7c2fe2..9ca988635 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,3 +1,9 @@
+2001-11-27 Werner Koch <wk@gnupg.org>
+
+ * base64.c: New. Changed all other functions to use this instead
+ of direct creation of ksba_reader/writer.
+ * gpgsm.c (main): Set ctrl.auto_encoding unless --no-armor is used.
+
2001-11-26 Werner Koch <wk@gnupg.org>
* gpgsm.c: New option --agent-program
diff --git a/sm/Makefile.am b/sm/Makefile.am
index c6aecdb5b..fbfe31af4 100644
--- a/sm/Makefile.am
+++ b/sm/Makefile.am
@@ -31,12 +31,14 @@ gpgsm_SOURCES = \
server.c \
call-agent.c \
fingerprint.c \
+ base64.c \
certdump.c \
certcheck.c \
certpath.c \
keylist.c \
verify.c \
sign.c \
+ encrypt.c \
import.c
diff --git a/sm/base64.c b/sm/base64.c
new file mode 100644
index 000000000..f60015dd7
--- /dev/null
+++ b/sm/base64.c
@@ -0,0 +1,401 @@
+/* base64.c
+ * Copyright (C) 2001 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <assert.h>
+
+#include <ksba.h>
+
+#include "gpgsm.h"
+#include "i18n.h"
+
+
+/* data used by the reader callbacks */
+struct reader_cb_parm_s {
+ FILE *fp;
+ unsigned char line[1024];
+ int linelen;
+ int readpos;
+ int have_lf;
+ unsigned long line_counter;
+
+ int autodetect; /* try to detect the input encoding */
+ int assume_pem; /* assume input encoding is PEM */
+ int assume_base64; /* assume inpout is base64 encoded */
+
+ int identified;
+ int is_pem;
+ int stop_seen;
+
+ struct {
+ int idx;
+ unsigned char val;
+ int stop_seen;
+ } base64;
+};
+
+
+struct base64_context_s {
+ struct reader_cb_parm_s rparm;
+};
+
+
+/* The base-64 character list */
+static unsigned char bintoasc[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+/* The reverse base-64 list */
+static unsigned char asctobin[256] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+ 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
+ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+ 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff
+};
+
+
+
+static int
+base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
+{
+ struct reader_cb_parm_s *parm = cb_value;
+ size_t n;
+ int c, c2;
+
+ *nread = 0;
+ if (!buffer)
+ return -1; /* not supported */
+
+ next:
+ if (!parm->linelen)
+ {
+ /* read an entire line or up to the size of the buffer */
+ parm->line_counter++;
+ parm->have_lf = 0;
+ for (n=0; n < DIM(parm->line);)
+ {
+ c = getc (parm->fp);
+ if (c == EOF)
+ {
+ if (ferror (parm->fp))
+ return -1;
+ break;
+ }
+ parm->line[n++] = c;
+ if (c == '\n')
+ {
+ parm->have_lf = 1;
+ /* FIXME: we need to skip overlong lines while detecting
+ the dashed lines */
+ break;
+ }
+ }
+ parm->linelen = n;
+ if (!n)
+ return -1; /* eof */
+ parm->readpos = 0;
+ }
+
+ if (!parm->identified)
+ {
+ if (parm->line_counter == 1 && !parm->have_lf)
+ {
+ /* first line too long - assume DER encoding */
+ parm->is_pem = 0;
+ }
+ else if (parm->line_counter == 1 && parm->linelen && *parm->line == 0x30)
+ {
+ /* the very first bytes does pretty much look like a SEQUENCE tag*/
+ parm->is_pem = 0;
+ }
+ else if ( parm->have_lf && !strncmp (parm->line, "-----BEGIN ", 11)
+ && strncmp (parm->line+11, "PGP ", 4) )
+ {
+ /* Fixme: we must only compare if the line really starts at
+ the beginning */
+ parm->is_pem = 1;
+ parm->linelen = parm->readpos = 0;
+ }
+ else
+ {
+ parm->linelen = parm->readpos = 0;
+ goto next;
+ }
+ parm->identified = 1;
+ parm->base64.stop_seen = 0;
+ parm->base64.idx = 0;
+ }
+
+
+ n = 0;
+ if (parm->is_pem)
+ {
+ if (parm->have_lf && !strncmp (parm->line, "-----END ", 9))
+ {
+ parm->identified = 0;
+ parm->linelen = parm->readpos = 0;
+ /* let us return 0 */
+ }
+ else if (parm->stop_seen)
+ { /* skip the rest of the line */
+ parm->linelen = parm->readpos = 0;
+ }
+ else
+ {
+ int idx = parm->base64.idx;
+ unsigned char val = parm->base64.val;
+
+ while (n < count && parm->readpos < parm->linelen )
+ {
+ c = parm->line[parm->readpos++];
+ if (c == '\n' || c == ' ' || c == '\r' || c == '\t')
+ continue;
+ if (c == '=')
+ { /* pad character: stop */
+ if (idx == 1)
+ buffer[n++] = val;
+ parm->stop_seen = 1;
+ break;
+ }
+ if( (c = asctobin[(c2=c)]) == 255 )
+ {
+ log_error (_("invalid radix64 character %02x skipped\n"),
+ c2);
+ continue;
+ }
+ switch (idx)
+ {
+ case 0:
+ val = c << 2;
+ break;
+ case 1:
+ val |= (c>>4)&3;
+ buffer[n++] = val;
+ val = (c<<4)&0xf0;
+ break;
+ case 2:
+ val |= (c>>2)&15;
+ buffer[n++] = val;
+ val = (c<<6)&0xc0;
+ break;
+ case 3:
+ val |= c&0x3f;
+ buffer[n++] = val;
+ break;
+ }
+ idx = (idx+1) % 4;
+ }
+ if (parm->readpos == parm->linelen)
+ parm->linelen = parm->readpos = 0;
+
+ parm->base64.idx = idx;
+ parm->base64.val = val;
+ }
+ }
+ else
+ { /* DER encoded */
+ while (n < count && parm->readpos < parm->linelen)
+ buffer[n++] = parm->line[parm->readpos++];
+ if (parm->readpos == parm->linelen)
+ parm->linelen = parm->readpos = 0;
+ }
+
+ *nread = n;
+ return 0;
+}
+
+
+
+static int
+simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
+{
+ struct reader_cb_parm_s *parm = cb_value;
+ size_t n;
+ int c = 0;
+
+ *nread = 0;
+ if (!buffer)
+ return -1; /* not supported */
+
+ for (n=0; n < count; n++)
+ {
+ c = getc (parm->fp);
+ if (c == EOF)
+ {
+ if ( ferror (parm->fp) )
+ return -1;
+ if (n)
+ break; /* return what we have before an EOF */
+ return -1;
+ }
+ *(byte *)buffer++ = c;
+ }
+
+ *nread = n;
+ return 0;
+}
+
+
+
+
+
+/* Create a reader for the given file descriptor. Depending on the
+ control information an input decoding is automagically choosen.
+ The function returns a Base64Context object which must be passed to
+ the gpgme_destroy_reader function. The created KsbaReader object
+ is also returned, but the caller must not call the
+ ksba_reader_release function on. */
+int
+gpgsm_create_reader (Base64Context *ctx,
+ CTRL ctrl, FILE *fp, KsbaReader *r_reader)
+{
+ int rc;
+ KsbaReader r;
+
+ *r_reader = NULL;
+ *ctx = xtrycalloc (1, sizeof **ctx);
+ if (!*ctx)
+ return seterr (Out_Of_Core);
+
+ r = ksba_reader_new ();
+ if (!r)
+ {
+ xfree (*ctx); *ctx = NULL;
+ return seterr (Out_Of_Core);
+ }
+
+ (*ctx)->rparm.fp = fp;
+ if (ctrl->is_pem)
+ {
+ (*ctx)->rparm.assume_pem = 1;
+ (*ctx)->rparm.assume_base64 = 1;
+ rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->rparm);
+ }
+ else if (ctrl->is_base64)
+ {
+ (*ctx)->rparm.assume_base64 = 1;
+ rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->rparm);
+ }
+ else if (ctrl->autodetect_encoding)
+ {
+ (*ctx)->rparm.autodetect = 1;
+ rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->rparm);
+ }
+ else
+ rc = ksba_reader_set_cb (r, simple_reader_cb, &(*ctx)->rparm);
+
+ if (rc)
+ {
+ ksba_reader_release (r);
+ xfree (*ctx); *ctx = NULL;
+ return map_ksba_err (rc);
+ }
+
+ *r_reader = r;
+ return 0;
+}
+
+
+void
+gpgsm_destroy_reader (Base64Context ctx)
+{
+ xfree (ctx);
+}
+
+
+
+/* Create a writer for the given stream. Depending on the control
+ information an output encoding is automagically choosen. The
+ function returns a Base64Context object which must be passed to the
+ gpgme_destroy_writer function. The created KsbaWriter object is
+ also returned, but the caller must not call the ksba_reader_release
+ function on. */
+int
+gpgsm_create_writer (Base64Context *ctx,
+ CTRL ctrl, FILE *fp, KsbaWriter *r_writer)
+{
+ int rc;
+ KsbaWriter w;
+
+ *r_writer = NULL;
+ *ctx = xtrycalloc (1, sizeof **ctx);
+ if (!*ctx)
+ return seterr (Out_Of_Core);
+
+ w = ksba_writer_new ();
+ if (!w)
+ {
+ xfree (*ctx); *ctx = NULL;
+ return seterr (Out_Of_Core);
+ }
+
+ if (ctrl->create_pem || ctrl->create_base64)
+ {
+ return seterr (Not_Implemented);
+ }
+ else
+ rc = ksba_writer_set_file (w, fp);
+
+ if (rc)
+ {
+ ksba_writer_release (w);
+ xfree (*ctx); *ctx = NULL;
+ return map_ksba_err (rc);
+ }
+
+ *r_writer = w;
+ return 0;
+}
+
+
+void
+gpgsm_destroy_writer (Base64Context ctx)
+{
+ xfree (ctx);
+}
+
+
+
+
+
diff --git a/sm/encrypt.c b/sm/encrypt.c
new file mode 100644
index 000000000..2b30463bb
--- /dev/null
+++ b/sm/encrypt.c
@@ -0,0 +1,256 @@
+/* encrypt.c - Encrypt a message
+ * Copyright (C) 2001 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <assert.h>
+
+#include <gcrypt.h>
+#include <ksba.h>
+
+#include "gpgsm.h"
+#include "keydb.h"
+#include "i18n.h"
+
+
+KsbaCert
+get_default_recipient (void)
+{
+ return NULL;
+}
+
+
+
+/* Perform an encrypt operation.
+
+ Encrypt the data received on DATA-FD and write it to OUT_FP. The
+ recipients are hardwired for now. */
+int
+gpgsm_encrypt (CTRL ctrl, int data_fd, FILE *out_fp)
+{
+ int i, rc;
+ Base64Context b64reader = NULL;
+ Base64Context b64writer = NULL;
+ KsbaError err;
+ KsbaWriter writer;
+ KsbaReader reader;
+ KsbaCMS cms = NULL;
+ KsbaStopReason stopreason;
+ KsbaCert cert;
+ KEYDB_HANDLE kh = NULL;
+ GCRY_MD_HD data_md = NULL;
+ int signer;
+ const char *algoid;
+ FILE *data_fp = NULL;
+ int algo;
+
+
+ kh = keydb_new (0);
+ if (!kh)
+ {
+ log_error (_("failed to allocated keyDB handle\n"));
+ rc = GNUPG_General_Error;
+ goto leave;
+ }
+
+ data_fp = fdopen ( dup (data_fd), "rb");
+ if (!data_fp)
+ {
+ log_error ("fdopen() failed: %s\n", strerror (errno));
+ rc = seterr (IO_Error);
+ goto leave;
+ }
+
+ rc = gpgsm_create_reader (&b64reader, ctrl, data_fp, &reader);
+ if (rc)
+ {
+ log_error ("can't create reader: %s\n", gnupg_strerror (rc));
+ goto leave;
+ }
+
+ rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
+ if (rc)
+ {
+ log_error ("can't create writer: %s\n", gnupg_strerror (rc));
+ goto leave;
+ }
+
+ cms = ksba_cms_new ();
+ if (!cms)
+ {
+ rc = seterr (Out_Of_Core);
+ goto leave;
+ }
+
+ err = ksba_cms_set_reader_writer (cms, reader, writer);
+ if (err)
+ {
+ log_debug ("ksba_cms_set_reader_writer failed: %s\n",
+ ksba_strerror (err));
+ rc = map_ksba_err (err);
+ goto leave;
+ }
+
+ /* We are going to create signed data with data as encap. content */
+ err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA);
+ if (!err)
+ err = ksba_cms_set_content_type (cms, 1, KSBA_CT_ENCRYPTED_DATA);
+ if (err)
+ {
+ log_debug ("ksba_cms_set_content_type failed: %s\n",
+ ksba_strerror (err));
+ rc = map_ksba_err (err);
+ goto leave;
+ }
+
+
+ /* gather certificates of recipients and store them in the CMS object */
+ cert = get_default_recipient ();
+ if (!cert)
+ {
+ log_error ("no default recipient found\n");
+ rc = seterr (General_Error);
+ goto leave;
+ }
+/* err = ksba_cms_add_signer (cms, cert); */
+/* if (err) */
+/* { */
+/* log_debug ("ksba_cms_add_signer failed: %s\n", ksba_strerror (err)); */
+/* rc = map_ksba_err (err); */
+/* goto leave; */
+/* } */
+ cert = NULL; /* cms does now own the certificate */
+
+ /* Set the hash algorithm we are going to use */
+ err = ksba_cms_add_digest_algo (cms, "1.3.14.3.2.26" /*SHA-1*/);
+ if (err)
+ {
+ log_debug ("ksba_cms_add_digest_algo failed: %s\n", ksba_strerror (err));
+ rc = map_ksba_err (err);
+ goto leave;
+ }
+
+ /* Prepare hashing (actually we are figuring out what we have set above)*/
+ data_md = gcry_md_open (0, 0);
+ if (!data_md)
+ {
+ rc = map_gcry_err (gcry_errno());
+ log_error ("md_open failed: %s\n", gcry_strerror (-1));
+ goto leave;
+ }
+ for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
+ {
+ algo = gcry_md_map_name (algoid);
+ if (!algo)
+ {
+ log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?");
+ rc = GNUPG_Bug;
+ goto leave;
+ }
+ gcry_md_enable (data_md, algo);
+ }
+
+ signer = 0;
+ do
+ {
+ err = ksba_cms_build (cms, &stopreason);
+ if (err)
+ {
+ log_debug ("ksba_cms_build failed: %s\n", ksba_strerror (err));
+ rc = map_ksba_err (err);
+ goto leave;
+ }
+ log_debug ("ksba_cms_build - stop reason %d\n", stopreason);
+
+ if (stopreason == KSBA_SR_BEGIN_DATA)
+ {
+ }
+ else if (stopreason == KSBA_SR_NEED_SIG)
+ { /* calculate the signature for all signers */
+ GCRY_MD_HD md;
+
+ algo = GCRY_MD_SHA1;
+ signer = 0;
+ md = gcry_md_open (algo, 0);
+ if (!md)
+ {
+ log_error ("md_open failed: %s\n", gcry_strerror (-1));
+ goto leave;
+ }
+ ksba_cms_set_hash_function (cms, HASH_FNC, md);
+ rc = ksba_cms_hash_signed_attrs (cms, signer);
+ if (rc)
+ {
+ log_debug ("hashing signed attrs failed: %s\n",
+ ksba_strerror (rc));
+ gcry_md_close (md);
+ goto leave;
+ }
+
+ { /* This is all an temporary hack */
+ char *sigval;
+
+ cert = NULL;
+ if (!cert)
+ {
+ log_error ("oops - failed to get cert again\n");
+ rc = seterr (General_Error);
+ goto leave;
+ }
+
+ sigval = NULL;
+ rc = gpgsm_create_cms_signature (cert, md, algo, &sigval);
+ if (rc)
+ {
+ ksba_cert_release (cert);
+ goto leave;
+ }
+
+ err = ksba_cms_set_sig_val (cms, signer, sigval);
+ xfree (sigval);
+ if (err)
+ {
+ log_error ("failed to store the signature: %s\n",
+ ksba_strerror (err));
+ rc = map_ksba_err (err);
+ goto leave;
+ }
+ }
+ }
+ }
+ while (stopreason != KSBA_SR_READY);
+
+ log_info ("signature created\n");
+
+ leave:
+ ksba_cms_release (cms);
+ gpgsm_destroy_writer (b64writer);
+ gpgsm_destroy_reader (b64reader);
+ keydb_release (kh);
+ gcry_md_close (data_md);
+ if (data_fp)
+ fclose (data_fp);
+ return rc;
+}
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index 0b6b7c237..f6cf4aeef 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -591,6 +591,7 @@ main ( int argc, char **argv)
memset (&ctrl, 0, sizeof ctrl);
ctrl.no_server = 1;
ctrl.status_fd = -1; /* not status output */
+ ctrl.autodetect_encoding = 1;
/* set the default option file */
if (default_config )
@@ -661,7 +662,10 @@ main ( int argc, char **argv)
case aVerify: set_cmd (&cmd, aVerify); break;
case oArmor: opt.armor = 1; opt.no_armor=0; break;
- case oNoArmor: opt.no_armor=1; opt.armor=0; break;
+ case oNoArmor:
+ ctrl.autodetect_encoding = 0;
+ opt.no_armor=1; opt.armor=0;
+ break;
case oOutput: opt.outfile = pargs.r.ret_str; break;
case oQuiet: opt.quiet = 1; break;
case oNoTTY: /* fixme:tty_no_terminal(1);*/ break;
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 00ae32e00..916a2cd38 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -45,7 +45,7 @@ struct {
int fingerprint; /* list fingerprints in all key listings */
- int armor; /* force base64 armoring */
+ int armor; /* force base64 armoring (see also ctrl.with_base64) */
int no_armor; /* don't try to figure out whether data is base64 armored*/
int def_cipher_algo; /* cipher algorithm to use if nothing else is know */
@@ -89,9 +89,20 @@ struct server_control_s {
int status_fd; /* only for non-server mode */
struct server_local_s *server_local;
int with_colons; /* use column delimited output format */
+
+ int autodetect_encoding; /* try to detect the input encoding */
+ int is_pem; /* Is in PEM format */
+ int is_base64; /* is in plain base-64 format */
+
+ int create_base64; /* Create base64 encoded output */
+ int create_pem; /* create PEM output */
+
};
typedef struct server_control_s *CTRL;
+/* data structure osed in base64.c */
+typedef struct base64_context_s *Base64Context;
+
/*-- gpgsm.c --*/
void gpgsm_exit (int rc);
@@ -107,6 +118,14 @@ char *gpgsm_get_fingerprint_hexstring (KsbaCert cert, int algo);
char *gpgsm_get_keygrip (KsbaCert cert, char *array);
char *gpgsm_get_keygrip_hexstring (KsbaCert cert);
+/*-- base64.c --*/
+int gpgsm_create_reader (Base64Context *ctx,
+ CTRL ctrl, FILE *fp, KsbaReader *r_reader);
+void gpgsm_destroy_reader (Base64Context ctx);
+int gpgsm_create_writer (Base64Context *ctx,
+ CTRL ctrl, FILE *fp, KsbaWriter *r_writer);
+void gpgsm_destroy_writer (Base64Context ctx);
+
/*-- certdump.c --*/
void gpgsm_dump_cert (const char *text, KsbaCert cert);
diff --git a/sm/import.c b/sm/import.c
index fc628a6f1..0e9618ca8 100644
--- a/sm/import.c
+++ b/sm/import.c
@@ -34,208 +34,6 @@
#include "keydb.h"
#include "i18n.h"
-struct reader_cb_parm_s {
- FILE *fp;
- unsigned char line[1024];
- int linelen;
- int readpos;
- int have_lf;
- unsigned long line_counter;
-
- int identified;
- int is_pem;
- int stop_seen;
-
- struct {
- int idx;
- unsigned char val;
- int stop_seen;
- } base64;
-
-
-};
-
-/* static unsigned char bintoasc[] = */
-/* "ABCDEFGHIJKLMNOPQRSTUVWXYZ" */
-/* "abcdefghijklmnopqrstuvwxyz" */
-/* "0123456789+/"; */
-
-static unsigned char asctobin[256] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
- 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
- 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
- 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
- 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff
-};
-
-
-
-static int
-reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
-{
- struct reader_cb_parm_s *parm = cb_value;
- size_t n;
- int c, c2;
-
- *nread = 0;
- if (!buffer)
- return -1; /* not supported */
-
- next:
- if (!parm->linelen)
- {
- /* read an entire line or up to the size of the buffer */
- parm->line_counter++;
- parm->have_lf = 0;
- for (n=0; n < DIM(parm->line);)
- {
- c = getc (parm->fp);
- if (c == EOF)
- {
- if (ferror (parm->fp))
- return -1;
- break;
- }
- parm->line[n++] = c;
- if (c == '\n')
- {
- parm->have_lf = 1;
- /* FIXME: we need to skip overlong lines while detecting
- the dashed lines */
- break;
- }
- }
- parm->linelen = n;
- if (!n)
- return -1; /* eof */
- parm->readpos = 0;
- }
-
- if (!parm->identified)
- {
- if (parm->line_counter == 1 && !parm->have_lf)
- {
- /* first line too long - assume DER encoding */
- parm->is_pem = 0;
- }
- else if (parm->line_counter == 1 && parm->linelen && *parm->line == 0x30)
- {
- /* the very first bytes does pretty much look like a SEQUENCE tag*/
- parm->is_pem = 0;
- }
- else if ( parm->have_lf && !strncmp (parm->line, "-----BEGIN ", 11)
- && strncmp (parm->line+11, "PGP ", 4) )
- {
- /* Fixme: we must only compare if the line really starts at
- the beginning */
- parm->is_pem = 1;
- parm->linelen = parm->readpos = 0;
- }
- else
- {
- parm->linelen = parm->readpos = 0;
- goto next;
- }
- parm->identified = 1;
- parm->base64.stop_seen = 0;
- parm->base64.idx = 0;
- }
-
-
- n = 0;
- if (parm->is_pem)
- {
- if (parm->have_lf && !strncmp (parm->line, "-----END ", 9))
- {
- parm->identified = 0;
- parm->linelen = parm->readpos = 0;
- /* let us return 0 */
- }
- else if (parm->stop_seen)
- { /* skip the rest of the line */
- parm->linelen = parm->readpos = 0;
- }
- else
- {
- int idx = parm->base64.idx;
- unsigned char val = parm->base64.val;
-
- while (n < count && parm->readpos < parm->linelen )
- {
- c = parm->line[parm->readpos++];
- if (c == '\n' || c == ' ' || c == '\r' || c == '\t')
- continue;
- if (c == '=')
- { /* pad character: stop */
- if (idx == 1)
- buffer[n++] = val;
- parm->stop_seen = 1;
- break;
- }
- if( (c = asctobin[(c2=c)]) == 255 )
- {
- log_error (_("invalid radix64 character %02x skipped\n"),
- c2);
- continue;
- }
- switch (idx)
- {
- case 0:
- val = c << 2;
- break;
- case 1:
- val |= (c>>4)&3;
- buffer[n++] = val;
- val = (c<<4)&0xf0;
- break;
- case 2:
- val |= (c>>2)&15;
- buffer[n++] = val;
- val = (c<<6)&0xc0;
- break;
- case 3:
- val |= c&0x3f;
- buffer[n++] = val;
- break;
- }
- idx = (idx+1) % 4;
- }
- if (parm->readpos == parm->linelen)
- parm->linelen = parm->readpos = 0;
-
- parm->base64.idx = idx;
- parm->base64.val = val;
- }
- }
- else
- { /* DER encoded */
- while (n < count && parm->readpos < parm->linelen)
- buffer[n++] = parm->line[parm->readpos++];
- if (parm->readpos == parm->linelen)
- parm->linelen = parm->readpos = 0;
- }
-
- *nread = n;
- return 0;
-}
-
static void
store_cert (KsbaCert cert)
@@ -268,34 +66,23 @@ int
gpgsm_import (CTRL ctrl, int in_fd)
{
int rc;
- KsbaReader reader = NULL;
+ Base64Context b64reader = NULL;
+ KsbaReader reader;
KsbaCert cert = NULL;
- struct reader_cb_parm_s rparm;
-
- memset (&rparm, 0, sizeof rparm);
+ FILE *fp = NULL;
- rparm.fp = fdopen ( dup (in_fd), "rb");
- if (!rparm.fp)
+ fp = fdopen ( dup (in_fd), "rb");
+ if (!fp)
{
log_error ("fdopen() failed: %s\n", strerror (errno));
rc = seterr (IO_Error);
goto leave;
}
- /* setup a skaba reader which uses a callback function so that we can
- strip off a base64 encoding when necessary */
- reader = ksba_reader_new ();
- if (!reader)
- {
- rc = seterr (Out_Of_Core);
- goto leave;
- }
-
- rc = ksba_reader_set_cb (reader, reader_cb, &rparm );
+ rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader);
if (rc)
{
- ksba_reader_release (reader);
- rc = map_ksba_err (rc);
+ log_error ("can't create reader: %s\n", gnupg_strerror (rc));
goto leave;
}
@@ -318,9 +105,9 @@ gpgsm_import (CTRL ctrl, int in_fd)
leave:
ksba_cert_release (cert);
- ksba_reader_release (reader);
- if (rparm.fp)
- fclose (rparm.fp);
+ gpgsm_destroy_reader (b64reader);
+ if (fp)
+ fclose (fp);
return rc;
}
diff --git a/sm/server.c b/sm/server.c
index e83506049..f4bb409f5 100644
--- a/sm/server.c
+++ b/sm/server.c
@@ -81,6 +81,43 @@ rc_to_assuan_status (int rc)
}
+static void
+reset_notify (ASSUAN_CONTEXT ctx)
+{
+}
+
+
+static void
+input_notify (ASSUAN_CONTEXT ctx, const char *line)
+{
+ CTRL ctrl = assuan_get_pointer (ctx);
+
+ ctrl->autodetect_encoding = 0;
+ ctrl->is_pem = 0;
+ ctrl->is_base64 = 0;
+ if (strstr (line, "--armor"))
+ ctrl->is_pem = 1;
+ else if (strstr (line, "--base64"))
+ ctrl->is_base64 = 1;
+ else if (strstr (line, "--binary"))
+ ;
+ else
+ ctrl->autodetect_encoding = 0;
+}
+
+static void
+output_notify (ASSUAN_CONTEXT ctx, const char *line)
+{
+ CTRL ctrl = assuan_get_pointer (ctx);
+
+ ctrl->create_pem = 0;
+ ctrl->create_base64 = 0;
+ if (strstr (line, "--armor"))
+ ctrl->create_pem = 1;
+ else if (strstr (line, "--base64"))
+ ctrl->create_base64 = 1; /* just the raw output */
+}
+
/* RECIPIENT <userID>
@@ -103,7 +140,7 @@ cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
}
-/* ENCRYPT [armor]
+/* ENCRYPT
Do the actual encryption process. Takes the plaintext from the INPUT
command, writes to the ciphertext to the file descriptor set with
@@ -115,16 +152,28 @@ cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
This command should in general not fail, as all necessary checks
have been done while setting the recipients. The input and output
- pipes are closed.
-
- The optional armor parameter may be used to request base64 encoded
- output. */
+ pipes are closed. */
static int
cmd_encrypt (ASSUAN_CONTEXT ctx, char *line)
{
-
+ int inp_fd, out_fd;
+ FILE *out_fp;
+ int rc;
- return set_error (Not_Implemented, "fixme");
+ inp_fd = assuan_get_input_fd (ctx);
+ if (inp_fd == -1)
+ return set_error (No_Input, NULL);
+ out_fd = assuan_get_output_fd (ctx);
+ if (out_fd == -1)
+ return set_error (No_Output, NULL);
+
+ out_fp = fdopen ( dup(out_fd), "w");
+ if (!out_fp)
+ return set_error (General_Error, "fdopen() failed");
+ rc = gpgsm_encrypt (assuan_get_pointer (ctx), inp_fd, out_fp);
+ fclose (out_fp);
+
+ return rc_to_assuan_status (rc);
}
/* DECRYPT
@@ -172,7 +221,7 @@ cmd_verify (ASSUAN_CONTEXT ctx, char *line)
/* SIGN [--detached]
Sign the data set with the INPUT command and write it to the sink
- set by OUTPUT. with "--detached" specified, a detached signature is
+ set by OUTPUT. With "--detached" specified, a detached signature is
created (surprise). */
static int
cmd_sign (ASSUAN_CONTEXT ctx, char *line)
@@ -330,6 +379,10 @@ gpgsm_server (void)
gpgsm_exit (2);
}
+ assuan_register_reset_notify (ctx, reset_notify);
+ assuan_register_input_notify (ctx, input_notify);
+ assuan_register_output_notify (ctx, output_notify);
+
assuan_set_pointer (ctx, &ctrl);
ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
ctrl.server_local->assuan_ctx = ctx;
diff --git a/sm/sign.c b/sm/sign.c
index a246511e3..42f409a7d 100644
--- a/sm/sign.c
+++ b/sm/sign.c
@@ -35,14 +35,6 @@
#include "i18n.h"
-
-
-struct reader_cb_parm_s {
- FILE *fp;
-};
-
-
-
static void
hash_data (int fd, GCRY_MD_HD md)
{
@@ -112,19 +104,17 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
{
int i, rc;
KsbaError err;
- KsbaWriter writer = NULL;
+ Base64Context b64writer = NULL;
+ KsbaWriter writer;
KsbaCMS cms = NULL;
KsbaStopReason stopreason;
KsbaCert cert;
KEYDB_HANDLE kh = NULL;
GCRY_MD_HD data_md = NULL;
- struct reader_cb_parm_s rparm;
int signer;
const char *algoid;
int algo;
- memset (&rparm, 0, sizeof rparm);
-
if (!detached)
{
rc = seterr (Not_Implemented);
@@ -140,25 +130,10 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
goto leave;
}
- rparm.fp = fdopen ( dup (data_fd), "rb");
- if (!rparm.fp)
- {
- log_error ("fdopen() failed: %s\n", strerror (errno));
- rc = seterr (IO_Error);
- goto leave;
- }
-
- writer = ksba_writer_new ();
- if (!writer)
- {
- rc = seterr (Out_Of_Core);
- goto leave;
- }
- rc = ksba_writer_set_file (writer, out_fp);
+ rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
if (rc)
{
- ksba_writer_release (writer);
- rc = map_ksba_err (rc);
+ log_error ("can't create writer: %s\n", gnupg_strerror (rc));
goto leave;
}
@@ -357,10 +332,8 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
leave:
ksba_cms_release (cms);
- ksba_writer_release (writer);
+ gpgsm_destroy_writer (b64writer);
keydb_release (kh);
gcry_md_close (data_md);
- if (rparm.fp)
- fclose (rparm.fp);
return rc;
}
diff --git a/sm/verify.c b/sm/verify.c
index 5b3a5a848..6f4a1d2c0 100644
--- a/sm/verify.c
+++ b/sm/verify.c
@@ -34,11 +34,6 @@
#include "keydb.h"
#include "i18n.h"
-struct reader_cb_parm_s {
- FILE *fp;
-};
-
-
/* FIXME: Move this to jnlib */
static char *
strtimestamp (time_t atime)
@@ -46,9 +41,9 @@ strtimestamp (time_t atime)
char *buffer = xmalloc (15);
if (atime < 0)
- {
- strcpy (buffer, "????" "-??" "-??");
- }
+ strcpy (buffer, "????" "-??" "-??");
+ else if (!atime)
+ strcpy (buffer, "none");
else
{
struct tm *tp;
@@ -62,38 +57,6 @@ strtimestamp (time_t atime)
-
-/* FIXME: We need to write a generic reader callback which should be able
- to detect and convert base-64 */
-static int
-reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
-{
- struct reader_cb_parm_s *parm = cb_value;
- size_t n;
- int c = 0;
-
- *nread = 0;
- if (!buffer)
- return -1; /* not supported */
-
- for (n=0; n < count; n++)
- {
- c = getc (parm->fp);
- if (c == EOF)
- {
- if ( ferror (parm->fp) )
- return -1;
- if (n)
- break; /* return what we have before an EOF */
- return -1;
- }
- *(byte *)buffer++ = c;
- }
-
- *nread = n;
- return 0;
-}
-
/* fixme: duplicated from import.c */
static void
store_cert (KsbaCert cert)
@@ -192,21 +155,19 @@ int
gpgsm_verify (CTRL ctrl, int in_fd, int data_fd)
{
int i, rc;
+ Base64Context b64reader = NULL;
KsbaError err;
- KsbaReader reader = NULL;
- KsbaWriter writer = NULL;
+ KsbaReader reader;
KsbaCMS cms = NULL;
KsbaStopReason stopreason;
KsbaCert cert;
KEYDB_HANDLE kh;
GCRY_MD_HD data_md = NULL;
- struct reader_cb_parm_s rparm;
int signer;
const char *algoid;
int algo;
int is_detached;
-
- memset (&rparm, 0, sizeof rparm);
+ FILE *fp = NULL;
kh = keydb_new (0);
if (!kh)
@@ -217,29 +178,18 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd)
}
- rparm.fp = fdopen ( dup (in_fd), "rb");
- if (!rparm.fp)
+ fp = fdopen ( dup (in_fd), "rb");
+ if (!fp)
{
log_error ("fdopen() failed: %s\n", strerror (errno));
rc = seterr (IO_Error);
goto leave;
}
- /* setup a skaba reader which uses a callback function so that we can
- strip off a base64 encoding when necessary */
- reader = ksba_reader_new ();
- writer = ksba_writer_new ();
- if (!reader || !writer)
- {
- rc = seterr (Out_Of_Core);
- goto leave;
- }
-
- rc = ksba_reader_set_cb (reader, reader_cb, &rparm );
+ rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader);
if (rc)
{
- ksba_reader_release (reader);
- rc = map_ksba_err (rc);
+ log_error ("can't create reader: %s\n", gnupg_strerror (rc));
goto leave;
}
@@ -250,7 +200,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd)
goto leave;
}
- err = ksba_cms_set_reader_writer (cms, reader, writer);
+ err = ksba_cms_set_reader_writer (cms, reader, NULL);
if (err)
{
log_debug ("ksba_cms_set_reader_writer failed: %s\n",
@@ -454,9 +404,9 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd)
char *buf, *fpr, *tstr;
fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- tstr = strtimestamp ( 42 /*fixme: get right time */);
+ tstr = strtimestamp (sigtime);
buf = xmalloc ( strlen(fpr) + strlen (tstr) + 100);
- sprintf (buf, "%s %s %lu", fpr, tstr, (unsigned long)42 );
+ sprintf (buf, "%s %s %lu", fpr, tstr, (unsigned long)sigtime );
xfree (tstr);
xfree (fpr);
gpgsm_status (ctrl, STATUS_VALIDSIG, buf);
@@ -498,11 +448,11 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd)
leave:
ksba_cms_release (cms);
- ksba_reader_release (reader);
+ gpgsm_destroy_reader (b64reader);
keydb_release (kh);
gcry_md_close (data_md);
- if (rparm.fp)
- fclose (rparm.fp);
+ if (fp)
+ fclose (fp);
return rc;
}