X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=main.c;h=d6bac685399c090749c50eeb33e80b4ad735b6ce;hb=29b46325c50f7b767d1027c817c4e050806f2aa1;hp=782e33766eaa9470a1f778b8885b6c61be29b3a6;hpb=0e9fcae8b7434972a6ae2d76a79136c24305d7c5;p=monkeysphere.git diff --git a/main.c b/main.c index 782e337..d6bac68 100644 --- a/main.c +++ b/main.c @@ -1,191 +1,230 @@ -#include +#include "gnutls-helpers.h" + #include #include -#include -#include -#include -#include -#include -#include -#include - -void err(const char* fmt, ...) { - static FILE* STDERR = NULL; - va_list ap; - - if (NULL == STDERR) - STDERR = fdopen(STDERR_FILENO, "a"); - va_start(ap, fmt); - vfprintf(STDERR, fmt, ap); - va_end(ap); -} +/* + Author: Daniel Kahn Gillmor + Date: Tue, 01 Apr 2008 + License: GPL v3 or later -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; -} + monkeysphere private key translator: execute this with an GPG + secret key on stdin (at the moment, only passphraseless RSA keys + work). -/* 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; -} + It will spit out a PEM-encoded version of the key on stdout, which + can be fed into ssh-add like this: -/* 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 = NULL; - if (bufsize > d->size) { - bufsize = 1024; - if (gnutls_realloc(d->data, bufsize) == NULL) { - err("out of memory!\n"); - return -1; - } - d->size = bufsize; - } else { - bufsize = d->size; + gpg --export-secret-keys $KEYID | monkeysphere | ssh-add -c /dev/stdin + + Requirements: I've only built this so far with GnuTLS v2.3.4 -- + version 2.2.0 does not contain the appropriate pieces. + + Notes: gpgkey2ssh doesn't seem to provide the same public + keys. Mighty weird! + +0 wt215@squeak:~/monkeysphere$ gpg --export-secret-keys 1DCDF89F | ~dkg/src/monkeysphere/monkeysphere | ssh-add -c /dev/stdin +gnutls version: 2.3.4 +OpenPGP RSA Key, with 1024 bits +Identity added: /dev/stdin (/dev/stdin) +The user has to confirm each use of the key +0 wt215@squeak:~/monkeysphere$ ssh-add -L +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9gWQqfrnhQKDQnND/3eOexpddE64J+1zp9fcyCje7H5LKclb6DBV2HS6WgW32PJhIzvP+fYZM3dzXea3fpv14y1SicXiRBDgF9SnsNA1qWn2RyzkLcKy7PmM0PDYtU1oiLTcQj/xkWcqW2sLKHT/WW+vZP5XP7RMGN/yWNMfE2Q== /dev/stdin +0 wt215@squeak:~/monkeysphere$ gpgkey2ssh 1DCDF89F +ssh-rsa AAAAB3NzaC1yc2EAAACBAL2BZCp+ueFAoNCc0P/d457Gl10Trgn7XOn19zIKN7sfkspyVvoMFXYdLpaBbfY8mEjO8/59hkzd3Nd5rd+m/XjLVKJxeJEEOAX1Kew0DWpafZHLOQtwrLs+YzQ8Ni1TWiItNxCP/GRZypbawsodP9Zb69k/lc/tEwY3/JY0x8TZAAAAAwEAAQ== COMMENT +0 wt215@squeak:~/monkeysphere$ + + */ + + +int convert_pgp_to_x509(gnutls_x509_privkey_t* output, gnutls_datum_t* input) { + gnutls_openpgp_privkey_t pgp_privkey; + gnutls_datum_t m, e, d, p, q, u, g, y, x; + gnutls_pk_algorithm_t pgp_algo; + unsigned int pgp_bits; + int ret; + + init_datum(&m); + init_datum(&e); + init_datum(&d); + init_datum(&p); + init_datum(&q); + init_datum(&u); + init_datum(&g); + init_datum(&y); + init_datum(&x); + + if (ret = gnutls_openpgp_privkey_init(&pgp_privkey), ret) { + err("Failed to initialized OpenPGP private key (error: %d)\n", ret); + return 1; } - f = fdopen(fd, "r"); - while (!feof(f) && !ferror(f)) { - if (len == bufsize) { - /* allocate more space by doubling: */ - bufsize *= 2; - if (gnutls_realloc(d->data, bufsize) == NULL) { - err("out of memory!\n"); - return -1; - }; - d->size = bufsize; - } - len += fread(d->data + len, 1, bufsize - len, f); + + + /* format could be either: GNUTLS_OPENPGP_FMT_RAW, + 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, input, 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, input, GNUTLS_OPENPGP_FMT_BASE64, NULL, 0), ret) + err("failed to import the OpenPGP private key in BASE64 format (error: %d)\n", ret); } - if (ferror(f)) { - err("Error reading from fd %d\n", fd); - return -1; + + 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; } - /* touch up buffer size to match reality: */ - gnutls_realloc(d->data, len); - d->size = len; - return 0; -} + 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_x509_privkey_import_rsa_raw (*output, &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; + } -/* 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; + ret = gnutls_x509_privkey_import_dsa_raw (*output, &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; } - 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; + ret = gnutls_x509_privkey_fix(*output); + if (ret != 0) { + err("failed to fix up the private key in X.509 format (error: %d)\n", ret); + 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); + gnutls_openpgp_privkey_deinit(pgp_privkey); return 0; } - -int main(int argc, char* argv[]) { - const char* version = NULL; - +int convert_x509_to_pgp(gnutls_openpgp_privkey_t* output, gnutls_datum_t* input) { gnutls_x509_privkey_t x509_privkey; - gnutls_datum_t data; + gnutls_datum_t m, e, d, p, q, u, g, y, x; + gnutls_pk_algorithm_t x509_algo; int ret; - /* - const char *certfile, *keyfile; - gnutls_certificate_credentials_t pgp_creds; - */ - gnutls_datum_t m, e, d, p, q, u; - gnutls_x509_crt_t crt; + init_datum(&m); + init_datum(&e); + init_datum(&d); + init_datum(&p); + init_datum(&q); + init_datum(&u); + init_datum(&g); + init_datum(&y); + init_datum(&x); - 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_datum(&data); - - if (ret = gnutls_global_init(), ret) { - err("Failed to do gnutls_global_init() (error: %d)\n", ret); + if (ret = gnutls_x509_privkey_init(&x509_privkey), ret) { + err("Failed to initialized X.509 private key (error: %d)\n", ret); return 1; } + /* format could be either: GNUTLS_X509_FMT_DER, + GNUTLS_X509_FMT_PEM; if MONKEYSPHERE_DER is set, use DER, + otherwise, use PEM: */ - version = gnutls_check_version(NULL); + if (getenv("MONKEYSPHERE_DER")) { + err("assuming DER formatted private keys\n"); + if (ret = gnutls_x509_privkey_import(x509_privkey, input, GNUTLS_X509_FMT_DER), ret) + err("failed to import the X.509 private key in DER format (error: %d)\n", ret); + } else { + err("assuming PEM formatted private keys\n"); + if (ret = gnutls_x509_privkey_import (x509_privkey, input, GNUTLS_X509_FMT_PEM), ret) + err("failed to import the X.509 private key in PEM format (error: %d)\n", ret); + } - if (version) - printf("gnutls version: %s\n", version); - else { - printf("no version found!\n"); + x509_algo = gnutls_x509_privkey_get_pk_algorithm(x509_privkey); + if (x509_algo < 0) { + err("failed to get X.509 key algorithm (error: %d)\n", x509_algo); return 1; } + if (x509_algo == GNUTLS_PK_RSA) { + err("X.509 RSA Key\n"); + ret = gnutls_x509_privkey_export_rsa_raw(x509_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; + } - if (ret = gnutls_x509_privkey_init(&x509_privkey), ret) { - err("Failed to initialize X.509 private key (error: %d)\n", ret); + /* ret = gnutls_openpgp_privkey_import_rsa_raw (*output, &m, &e, &d, &p, &q, &u); */ + ret = GNUTLS_E_UNIMPLEMENTED_FEATURE; + if (GNUTLS_E_SUCCESS != ret) { + err ("failed to import RSA key parameters (error: %d)\n", ret); + return 1; + } + } else if (x509_algo == GNUTLS_PK_DSA) { + err("X.509 DSA Key\n"); + ret = gnutls_x509_privkey_export_dsa_raw(x509_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_openpgp_privkey_import_dsa_raw (*output, &p, &q, &g, &y, &x); */ + ret = GNUTLS_E_UNIMPLEMENTED_FEATURE; + 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", x509_algo); return 1; } + + gnutls_x509_privkey_deinit(x509_privkey); + return 0; +} - if (ret = gnutls_openpgp_privkey_init(&pgp_privkey), ret) { - err("Failed to initialized OpenPGP private key (error: %d)\n", ret); + +int main(int argc, char* argv[]) { + gnutls_datum_t data; + int ret; + gnutls_x509_privkey_t x509_privkey; + + char output_data[10240]; + size_t ods = sizeof(output_data); + + init_gnutls(); + + init_datum(&data); + + /* slurp in the private key from stdin */ + if (ret = set_datum_fd(&data, 0), ret) { + err("didn't read file descriptor 0\n"); return 1; } - /* how do we initialize data? */ - /* reading from the file descriptor doesn't work right yet: - if (ret = set_datum_fd(&data, 0), ret) { - err("didn't read file descriptor 0\n"); - return 1; - } - */ + /* Or, instead, read in key from a file name: if (ret = set_datum_file(&data, argv[1]), ret) { err("didn't read file '%s'\n", argv[1]); return 1; } +*/ /* treat the passed file as an X.509 private key, and extract its component values: */ @@ -206,39 +245,27 @@ 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; - } - 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); + + if (ret = gnutls_x509_privkey_init(&x509_privkey), ret) { + err("Failed to initialize X.509 private key (error: %d)\n", ret); return 1; } - - printf("OpenPGP RSA Key, with %d bits\n", pgp_bits); + if (ret = convert_pgp_to_x509(&x509_privkey, &data), ret) { + return ret; + } - ret = gnutls_x509_privkey_export (pgp_privkey, + ret = gnutls_x509_privkey_export (x509_privkey, GNUTLS_X509_FMT_PEM, output_data, &ods); printf("ret: %u; ods: %u;\n", ret, ods); if (ret == 0) { - write(0, output_data, ods); + write(1, output_data, ods); } gnutls_x509_privkey_deinit(x509_privkey); - gnutls_openpgp_privkey_deinit(pgp_privkey); gnutls_global_deinit(); return 0; }