GNUPG-1-9-BRANCH gnupg/tools (ChangeLog Makefile.am gpgkey2ssh.c)
cvs user mo
cvs at cvs.gnupg.org
Sat May 28 15:22:42 CEST 2005
Date: Saturday, May 28, 2005 @ 15:43:21
Author: mo
Path: /cvs/gnupg/gnupg/tools
Tag: GNUPG-1-9-BRANCH
Added: gpgkey2ssh.c
Modified: ChangeLog Makefile.am
2005-05-28 Moritz Schulte <moritz at g10code.com>
* gpgkey2ssh.c: New file.
* Makefile.am (bin_PROGRAMS): Added gpgkey2ssh.
--------------+
ChangeLog | 5
Makefile.am | 5
gpgkey2ssh.c | 294 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 303 insertions(+), 1 deletion(-)
Index: gnupg/tools/ChangeLog
diff -u gnupg/tools/ChangeLog:1.25.2.75 gnupg/tools/ChangeLog:1.25.2.76
--- gnupg/tools/ChangeLog:1.25.2.75 Fri May 20 22:39:35 2005
+++ gnupg/tools/ChangeLog Sat May 28 15:43:21 2005
@@ -1,3 +1,8 @@
+2005-05-28 Moritz Schulte <moritz at g10code.com>
+
+ * gpgkey2ssh.c: New file.
+ * Makefile.am (bin_PROGRAMS): Added gpgkey2ssh.
+
2005-05-20 Werner Koch <wk at g10code.com>
* gpg-connect-agent.c (add_definq, show_definq, clear_definq)
Index: gnupg/tools/Makefile.am
diff -u gnupg/tools/Makefile.am:1.31.2.14 gnupg/tools/Makefile.am:1.31.2.15
--- gnupg/tools/Makefile.am:1.31.2.14 Fri Apr 15 03:33:46 2005
+++ gnupg/tools/Makefile.am Sat May 28 15:43:21 2005
@@ -36,7 +36,7 @@
symcryptrun =
endif
-bin_PROGRAMS = gpgconf gpg-connect-agent ${symcryptrun}
+bin_PROGRAMS = gpgconf gpg-connect-agent gpgkey2ssh ${symcryptrun}
if !HAVE_W32_SYSTEM
bin_PROGRAMS += watchgnupg
endif
@@ -56,3 +56,6 @@
gpg_connect_agent_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \
$(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL)
+gpgkey2ssh_SOURCES = gpgkey2ssh.c
+gpgkey2ssh_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS)
+gpgkey2ssh_LDADD = ../common/libcommon.a $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS)
Index: gnupg/tools/gpgkey2ssh.c
diff -u /dev/null gnupg/tools/gpgkey2ssh.c:1.1.2.1
--- /dev/null Sat May 28 15:43:21 2005
+++ gnupg/tools/gpgkey2ssh.c Sat May 28 15:43:21 2005
@@ -0,0 +1,294 @@
+/* gpgkey2ssh.c - Converter ...
+ Copyright (C) 2005 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 <gcrypt.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "util.h"
+
+
+
+typedef struct pkdbuf
+{
+ unsigned char *buffer;
+ size_t buffer_n;
+} pkdbuf_t;
+
+
+
+/* Retrieve the public key material for the RSA key, whose fingerprint
+ is FPR, from gpg output, which can be read through the stream FP.
+ The RSA modulus will be stored at the address of M and MLEN, the
+ public exponent at E and ELEN. Returns zero on success, an error
+ code on failure. Caller must release the allocated buffers at M
+ and E if the function returns success. */
+static gpg_error_t
+retrieve_key_material (FILE *fp, const char *hexkeyid, int *algorithm_id,
+ pkdbuf_t **pkdbuf, size_t *pkdbuf_n)
+{
+ pkdbuf_t *pkdbuf_new;
+ pkdbuf_t *pkdbuf_tmp;
+ size_t pkdbuf_new_n;
+ gcry_error_t err = 0;
+ char *line = NULL; /* read_line() buffer. */
+ size_t line_size = 0; /* Helper for for read_line. */
+ int found_key = 0; /* Helper to find a matching key. */
+ int id;
+ unsigned char *buffer;
+ size_t buffer_n;
+ int i;
+
+ pkdbuf_new = NULL;
+ pkdbuf_new_n = 0;
+ id = 0;
+
+ /* Loop over all records until we have found the subkey
+ corresponsing to the fingerprint. Inm general the first record
+ should be the pub record, but we don't rely on that. Given that
+ we only need to look at one key, it is sufficient to compare the
+ keyid so that we don't need to look at "fpr" records. */
+ for (;;)
+ {
+ char *p;
+ char *fields[6];
+ int nfields;
+ size_t max_length;
+ gcry_mpi_t mpi;
+
+ max_length = 4096;
+ i = read_line (fp, &line, &line_size, &max_length);
+ if (!i)
+ break; /* EOF. */
+ if (i < 0)
+ {
+ err = gpg_error_from_errno (errno);
+ goto leave; /* Error. */
+ }
+ if (!max_length)
+ {
+ err = gpg_error (GPG_ERR_TRUNCATED);
+ goto leave; /* Line truncated - we better stop processing. */
+ }
+
+ /* Parse the line into fields. */
+ for (nfields=0, p=line; p && nfields < DIM (fields); nfields++)
+ {
+ fields[nfields] = p;
+ p = strchr (p, ':');
+ if (p)
+ *(p++) = 0;
+ }
+ if (!nfields)
+ continue; /* No fields at all - skip line. */
+
+ if (!found_key)
+ {
+ if ( (!strcmp (fields[0], "sub") || !strcmp (fields[0], "pub") )
+ && nfields > 4 &&
+ (((strlen (hexkeyid) == 8)
+ && (strlen (fields[4]) == 16)
+ && (! strcmp (fields[4] + 8, hexkeyid)))
+ || ((strlen (hexkeyid) == 16)
+ && (! strcmp (fields[4], hexkeyid)))))
+ {
+ found_key = 1;
+ /* Save algorithm ID. */
+ id = atoi (fields[3]);
+ }
+ continue;
+ }
+
+ if ( !strcmp (fields[0], "sub") || !strcmp (fields[0], "pub") )
+ break; /* Next key - stop. */
+
+ if ( strcmp (fields[0], "pkd") )
+ continue; /* Not a key data record. */
+
+ /* FIXME, necessary? */
+
+ i = atoi (fields[1]);
+ if ((nfields < 4) || (i < 0))
+ {
+ err = gpg_error (GPG_ERR_GENERAL);
+ goto leave;
+ }
+
+ err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_HEX, fields[3], 0, NULL);
+ if (err)
+ mpi = NULL;
+
+ err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &buffer, &buffer_n, mpi);
+ gcry_mpi_release (mpi);
+ if (err)
+ goto leave;
+
+ pkdbuf_tmp = xrealloc (pkdbuf_new, sizeof (*pkdbuf_new) * (pkdbuf_new_n + 1));
+ if (pkdbuf_new != pkdbuf_tmp)
+ pkdbuf_new = pkdbuf_tmp;
+ pkdbuf_new[pkdbuf_new_n].buffer = buffer;
+ pkdbuf_new[pkdbuf_new_n].buffer_n = buffer_n;
+ pkdbuf_new_n++;
+ }
+
+ *algorithm_id = id;
+ *pkdbuf = pkdbuf_new;
+ *pkdbuf_n = pkdbuf_new_n;
+
+ leave:
+
+ if (err)
+ if (pkdbuf_new)
+ {
+ for (i = 0; i < pkdbuf_new_n; i++)
+ xfree (pkdbuf_new[i].buffer);
+ xfree (pkdbuf_new);
+ }
+ xfree (line);
+
+ return err;
+}
+
+
+
+int
+key_to_blob (unsigned char **blob, size_t *blob_n, const char *identifier, ...)
+{
+ unsigned char *blob_new;
+ size_t blob_new_n;
+ unsigned char uint32_buffer[4];
+ u32 identifier_n;
+ FILE *stream;
+ va_list ap;
+ int ret;
+ pkdbuf_t *pkd;
+
+ stream = tmpfile ();
+ assert (stream);
+
+ identifier_n = strlen (identifier);
+ uint32_buffer[0] = identifier_n >> 24;
+ uint32_buffer[1] = identifier_n >> 16;
+ uint32_buffer[2] = identifier_n >> 8;
+ uint32_buffer[3] = identifier_n >> 0;
+ ret = fwrite (uint32_buffer, sizeof (uint32_buffer), 1, stream);
+ assert (ret == 1);
+ ret = fwrite (identifier, identifier_n, 1, stream);
+ assert (ret == 1);
+
+ va_start (ap, identifier);
+ while (1)
+ {
+ pkd = va_arg (ap, pkdbuf_t *);
+ if (! pkd)
+ break;
+
+ uint32_buffer[0] = pkd->buffer_n >> 24;
+ uint32_buffer[1] = pkd->buffer_n >> 16;
+ uint32_buffer[2] = pkd->buffer_n >> 8;
+ uint32_buffer[3] = pkd->buffer_n >> 0;
+ ret = fwrite (uint32_buffer, sizeof (uint32_buffer), 1, stream);
+ assert (ret == 1);
+ ret = fwrite (pkd->buffer, pkd->buffer_n, 1, stream);
+ assert (ret == 1);
+ }
+
+ blob_new_n = ftell (stream);
+ rewind (stream);
+
+ blob_new = xmalloc (blob_new_n);
+ ret = fread (blob_new, blob_new_n, 1, stream);
+ assert (ret == 1);
+
+ *blob = blob_new;
+ *blob_n = blob_new_n;
+
+ fclose (stream);
+
+ return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ const char *keyid;
+ int algorithm_id;
+ pkdbuf_t *pkdbuf;
+ size_t pkdbuf_n;
+ char *command;
+ FILE *fp;
+ int ret;
+ gcry_error_t err;
+ unsigned char *blob;
+ size_t blob_n;
+ struct b64state b64_state;
+ const char *identifier;
+
+ pkdbuf = NULL;
+ pkdbuf_n = 0;
+
+ assert (argc == 2);
+
+ keyid = argv[1];
+
+ ret = asprintf (&command,
+ "gpg --list-keys --with-colons --with-key-data '%s'",
+ keyid);
+ assert (ret > 0);
+
+ fp = popen (command, "r");
+ assert (fp);
+
+ err = retrieve_key_material (fp, keyid, &algorithm_id, &pkdbuf, &pkdbuf_n);
+ assert (! err);
+ assert ((algorithm_id == 1) || (algorithm_id == 17));
+
+ if (algorithm_id == 1)
+ {
+ identifier = "ssh-rsa";
+ ret = key_to_blob (&blob, &blob_n, identifier,
+ &pkdbuf[0], &pkdbuf[1], NULL);
+ }
+ else if (algorithm_id == 17)
+ {
+ identifier = "ssh-dsa";
+ ret = key_to_blob (&blob, &blob_n, identifier,
+ &pkdbuf[0], &pkdbuf[1], &pkdbuf[2], &pkdbuf[3], NULL);
+ }
+ assert (! ret);
+
+ printf ("%s ", identifier);
+
+ err = b64enc_start (&b64_state, stdout, "");
+ assert (! err);
+ err = b64enc_write (&b64_state, blob, blob_n);
+ assert (! err);
+ err = b64enc_finish (&b64_state);
+ assert (! err);
+
+ printf (" COMMENT\n");
+
+ return 0;
+}
More information about the Gnupg-commits
mailing list