broke out gnutls business into a helper file in preparation for new projects.
[monkeysphere.git] / main.c
diff --git a/main.c b/main.c
index 8c3129db65dc90a969ae65d4bf655cab565716b9..638666baabe416ec4c0dcdcbe528db373763bb96 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,23 +1,16 @@
-#include <gnutls/gnutls.h>
+#include "gnutls-helpers.h"
+
 #include <gnutls/openpgp.h>
 #include <gnutls/x509.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdarg.h>
 
 /* 
    Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
    Date: Tue, 01 Apr 2008
    License: GPL v3 or later
 
-   monkeysphere private key translator: execute this with an
-   ASCII-armored private RSA key on stdin (at the moment, only
-   passphraseless keys work).
+   monkeysphere private key translator: execute this with an GPG
+   secret key on stdin (at the moment, only passphraseless RSA keys
+   work).
 
    It will spit out a PEM-encoded version of the key on stdout, which
    can be fed into ssh-add like this:
@@ -44,170 +37,43 @@ ssh-rsa AAAAB3NzaC1yc2EAAACBAL2BZCp+ueFAoNCc0P/d457Gl10Trgn7XOn19zIKN7sfkspyVvoM
  */
 
 
-void err(const char* fmt, ...) {
-  va_list ap;
-  va_start(ap, fmt);
-  vfprintf(stderr, fmt, ap);
-  va_end(ap);
-}
-
-
-void init_datum(gnutls_datum_t* d) {
-  d->data = NULL;
-  d->size = 0;
-}
-void free_datum(gnutls_datum_t* d) {
-  gnutls_free(d->data);
-  d->data = NULL;
-  d->size = 0;
-}
-
-/* read the passed-in string, store in a single datum */
-int set_datum_string(gnutls_datum_t* d, const char* s) {
-  unsigned int x = strlen(s)+1;
-  unsigned char* c = NULL;
-
-  c = gnutls_realloc(d->data, x);
-  if (NULL == c)
-    return -1;
-  d->data = c;
-  d->size = x;
-  memcpy(d->data, s, x);
-  return 0;
-}
-
-/* read the passed-in file descriptor until EOF, store in a single
-   datum */
-int set_datum_fd(gnutls_datum_t* d, int fd) {
-  unsigned int bufsize = 1024;
-  unsigned int len = 0;
-
-  FILE* f = fdopen(fd, "r");
-  if (bufsize > d->size) {
-    bufsize = 1024;
-    d->data = gnutls_realloc(d->data, bufsize);
-    if (d->data == NULL) {
-      err("out of memory!\n");
-      return -1;
-    }
-    d->size = bufsize;
-  } else {
-    bufsize = d->size;
-  }
-  f = fdopen(fd, "r");
-  if (NULL == f) {
-    err("could not fdopen FD %d\n", fd);
-  }
-  clearerr(f);
-  while (!feof(f) && !ferror(f)) { 
-    if (len == bufsize) {
-      /* allocate more space by doubling: */
-      bufsize *= 2;
-      d->data = gnutls_realloc(d->data, bufsize);
-      if (d->data == NULL) {
-       err("out of memory!\n"); 
-       return -1;
-      };
-      d->size = bufsize;
-    }
-    len += fread(d->data + len, 1, bufsize - len, f);
-    /*     err("read %d bytes\n", len); */
-  }
-  if (ferror(f)) {
-    err("Error reading from fd %d (error: %d) (error: %d '%s')\n", fd, ferror(f), errno, strerror(errno));
-    return -1;
-  }
-    
-  /* touch up buffer size to match reality: */
-  d->data = gnutls_realloc(d->data, len);
-  d->size = len;
-  return 0;
-}
-
-/* read the file indicated (by na1me) in the fname parameter.  store
-   its entire contents in a single datum. */
-int set_datum_file(gnutls_datum_t* d, const char* fname) {
-  struct stat sbuf;
-  unsigned char* c = NULL;
-  FILE* file = NULL;
-  size_t x = 0;
-
-  if (0 != stat(fname, &sbuf)) {
-    err("failed to stat '%s'\n", fname);
-    return -1;
-  }
-  
-  c = gnutls_realloc(d->data, sbuf.st_size);
-  if (NULL == c) {
-    err("failed to allocate %d bytes for '%s'\n", sbuf.st_size, fname);
-    return -1;
-  }
-
-  d->data = c;
-  d->size = sbuf.st_size;
-  file = fopen(fname, "r");
-  if (NULL == file) {
-    err("failed to open '%s' for reading\n",  fname);
-    return -1;
-  }
-
-  x = fread(d->data, d->size, 1, file);
-  if (x != 1) {
-    err("tried to read %d bytes, read %d instead from '%s'\n", d->size, x, fname);
-    fclose(file);
-    return -1;
-  }
-  fclose(file);
-  return 0;
-}
-
 
 int main(int argc, char* argv[]) {
-  const char* version = NULL;
-
   gnutls_x509_privkey_t x509_privkey;
-  gnutls_datum_t data;
+  gnutls_datum_t data, test, clean;
   int ret;
 
   /*  
       const char *certfile, *keyfile;
       gnutls_certificate_credentials_t pgp_creds;
   */
-  gnutls_datum_t m, e, d, p, q, u;
+  gnutls_datum_t m, e, d, p, q, u, g, y, x;
+
   /*  gnutls_x509_crt_t crt; */
 
   gnutls_openpgp_privkey_t pgp_privkey;
-  gnutls_openpgp_crt_fmt_t pgp_format;
   gnutls_pk_algorithm_t pgp_algo;
   unsigned int pgp_bits;
 
   char output_data[10240];
   size_t ods = sizeof(output_data);
 
+  init_gnutls();
+  
   init_datum(&data);
+  init_datum(&test);
+  init_datum(&clean);
   init_datum(&m);
   init_datum(&e);
   init_datum(&d);
   init_datum(&p);
   init_datum(&q);
   init_datum(&u);
-
-  if (ret = gnutls_global_init(), ret) {
-    err("Failed to do gnutls_global_init() (error: %d)\n", ret);
-    return 1;
-  }
+  init_datum(&g);
+  init_datum(&y);
+  init_datum(&x);
 
 
-
-  version = gnutls_check_version(NULL);
-
-  if (version) 
-    err("gnutls version: %s\n", version);
-  else {
-    err("no version found!\n");
-    return 1;
-  }
-
   if (ret = gnutls_x509_privkey_init(&x509_privkey), ret) {
     err("Failed to initialize X.509 private key (error: %d)\n", ret);
     return 1;
@@ -250,39 +116,55 @@ int main(int argc, char* argv[]) {
 /*     write(0, output_data, ods); */
 /*   } */
 
-  
   /* format could be either: GNUTLS_OPENPGP_FMT_RAW,
-     GNUTLS_OPENPGP_FMT_BASE64 */
-  pgp_format = GNUTLS_OPENPGP_FMT_RAW;
-  if (ret = gnutls_openpgp_privkey_import (pgp_privkey, &data, pgp_format, NULL, 0), ret) {
-    err("failed to import the OpenPGP private key (error: %d)\n", ret);
-    return 1;
+     GNUTLS_OPENPGP_FMT_BASE64; if MONKEYSPHERE_RAW is set, use RAW,
+     otherwise, use BASE64: */
+
+  if (getenv("MONKEYSPHERE_RAW")) {
+    err("assuming RAW formatted private keys\n");
+    if (ret = gnutls_openpgp_privkey_import(pgp_privkey, &data, GNUTLS_OPENPGP_FMT_RAW, NULL, 0), ret)
+      err("failed to import the OpenPGP private key in RAW format (error: %d)\n", ret);
+  } else {
+    err("assuming BASE64 formatted private keys\n");
+    if (ret = gnutls_openpgp_privkey_import (pgp_privkey, &data, GNUTLS_OPENPGP_FMT_BASE64, NULL, 0), ret)
+      err("failed to import the OpenPGP private key in BASE64 format (error: %d)\n", ret);
   }
+
   pgp_algo = gnutls_openpgp_privkey_get_pk_algorithm(pgp_privkey, &pgp_bits);
   if (pgp_algo < 0) {
     err("failed to get OpenPGP key algorithm (error: %d)\n", pgp_algo);
     return 1;
   }
-  if (pgp_algo != GNUTLS_PK_RSA) {
-    err("OpenPGP Key was not RSA (actual algorithm was: %d)\n", pgp_algo);
-    return 1;
-  }
-  
-  err("OpenPGP RSA Key, with %d bits\n", pgp_bits);
-
+  if (pgp_algo == GNUTLS_PK_RSA) {
+    err("OpenPGP RSA Key, with %d bits\n", pgp_bits);
+    ret = gnutls_openpgp_privkey_export_rsa_raw(pgp_privkey, &m, &e, &d, &p, &q, &u);
+    if (GNUTLS_E_SUCCESS != ret) {
+      err ("failed to export RSA key parameters (error: %d)\n", ret);
+      return 1;
+    }
 
-  ret = gnutls_openpgp_privkey_export_rsa_raw(pgp_privkey, &m, &e, &d, &p, &q, &u);
-  if (GNUTLS_E_SUCCESS != ret) {
-    err ("failed to export RSA key parameters (error: %0x)\n", ret);
-    return 1;
-  }
+    ret = gnutls_x509_privkey_import_rsa_raw (x509_privkey, &m, &e, &d, &p, &q, &u); 
+    if (GNUTLS_E_SUCCESS != ret) {
+      err ("failed to import RSA key parameters (error: %d)\n", ret);
+      return 1;
+    }
+  } else if (pgp_algo == GNUTLS_PK_DSA) {
+    err("OpenPGP DSA Key, with %d bits\n", pgp_bits);
+    ret = gnutls_openpgp_privkey_export_dsa_raw(pgp_privkey, &p, &q, &g, &y, &x);
+    if (GNUTLS_E_SUCCESS != ret) {
+      err ("failed to export DSA key parameters (error: %d)\n", ret);
+      return 1;
+    }
 
-  ret = gnutls_x509_privkey_import_rsa_raw (x509_privkey, &m, &e, &d, &p, &q, &u); 
-  if (GNUTLS_E_SUCCESS != ret) {
-    err ("failed to import RSA key parameters (error: %d)\n", ret);
+    ret = gnutls_x509_privkey_import_dsa_raw (x509_privkey, &p, &q, &g, &y, &x); 
+    if (GNUTLS_E_SUCCESS != ret) {
+      err ("failed to import DSA key parameters (error: %d)\n", ret);
+      return 1;
+    }
+  } else {
+    err("OpenPGP Key was not RSA or DSA -- can't deal! (actual algorithm was: %d)\n", pgp_algo);
     return 1;
   }
-  /* const gnutls_datum_t * m, const gnutls_datum_t * e, const gnutls_datum_t * d, const gnutls_datum_t * p, const gnutls_datum_t * q, const gnutls_datum_t * u); */
   
   ret = gnutls_x509_privkey_fix(x509_privkey);
   if (ret != 0) {