Patch for ssh-keygen to allow conversion of public key to openssh format
Lars Nordin
Lars.Nordin at SDlabs.se
Mon Sep 10 04:54:26 EST 2012
Hi,
I needed to convert a public RSA key to autorized_keys format and found
ssh-keygen lacking this feature.
I made the option -Q publicfile to allow an conversion like
ssh-keygen -Q pubrsa.pem -y
The patch is produced using unified diff and made on latest release.
If you like it and can make a patch for the man-page also!
Regards,
/Lars
-------------- next part --------------
diff -u openssh-6.1p1/authfile.c openssh-6.1p1-lano/authfile.c
--- openssh-6.1p1/authfile.c 2012-02-10 22:19:02.000000000 +0100
+++ openssh-6.1p1-lano/authfile.c 2012-09-08 11:59:08.000000000 +0200
@@ -792,6 +792,58 @@
return 0;
}
+Key *
+key_load_public_pem(char *filename, char **commentp)
+{
+ FILE *fp = NULL;
+ EVP_PKEY *pk = NULL;
+ X509 *x = NULL;
+ Key *pub = NULL;
+ char *name = "<no key>";
+
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ error("fopen of %s failed: %s", filename, strerror(errno));
+ return NULL;
+ }
+ x = PEM_read_X509(fp, NULL, NULL, NULL);
+ if (x == NULL) {
+ debug3("Not X509 format, try public key format");
+ rewind(fp);
+ pk = PEM_read_PUBKEY(fp, NULL, NULL, NULL);
+ } else {
+ pk = X509_get_pubkey(x);
+ }
+ if (pk == NULL) {
+ debug("PEM_read_PUBKEY() file %s failed", filename);
+ debug3("%s", ERR_error_string(ERR_get_error(), NULL));
+ if (x != NULL)
+ X509_free(x);
+ return NULL;
+ } else {
+ pub = key_new(KEY_UNSPEC);
+ pub->rsa = RSAPublicKey_dup(EVP_PKEY_get1_RSA(pk));
+ pub->type = KEY_RSA;
+ name = "rsa w/o comment";
+#ifdef DEBUG_PK
+ RSA_print_fp(stderr, prv->rsa, 8);
+#endif
+ }
+
+ fclose(fp);
+
+ if (pk != NULL)
+ EVP_PKEY_free(pk);
+ if (x != NULL)
+ X509_free(x);
+
+ if (pub != NULL && commentp)
+ *commentp = xstrdup(name);
+ debug("read PEM public key done: type %s",
+ pub ? key_type(pub) : "<unknown>");
+ return pub;
+}
+
/* load public key from ssh v1 private or any pubkey file */
Key *
key_load_public(const char *filename, char **commentp)
@@ -799,6 +851,11 @@
Key *pub;
char file[MAXPATHLEN];
+ /* try PEM public */
+ pub = key_load_public_pem(filename, commentp);
+ if (pub != NULL)
+ return pub;
+
/* try rsa1 private key */
pub = key_load_public_type(KEY_RSA1, filename, commentp);
if (pub != NULL)
diff -u openssh-6.1p1/config.status openssh-6.1p1-lano/config.status
--- openssh-6.1p1/config.status 2012-09-07 11:01:15.000000000 +0200
+++ openssh-6.1p1-lano/config.status 2012-09-08 11:59:38.000000000 +0200
@@ -445,7 +445,7 @@
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
-ac_pwd='/work/src/openssh-6.1p1'
+ac_pwd='/work/src/openssh-6.1p1-lano'
srcdir='.'
INSTALL='/usr/bin/install -c'
AWK='gawk'
Common subdirectories: openssh-6.1p1/contrib and openssh-6.1p1-lano/contrib
Common subdirectories: openssh-6.1p1/openbsd-compat and openssh-6.1p1-lano/openbsd-compat
Common subdirectories: openssh-6.1p1/regress and openssh-6.1p1-lano/regress
Common subdirectories: openssh-6.1p1/scard and openssh-6.1p1-lano/scard
diff -u openssh-6.1p1/ssh-keygen.c openssh-6.1p1-lano/ssh-keygen.c
--- openssh-6.1p1/ssh-keygen.c 2012-07-31 04:20:44.000000000 +0200
+++ openssh-6.1p1-lano/ssh-keygen.c 2012-09-07 09:26:01.000000000 +0200
@@ -141,6 +141,7 @@
} convert_format = FMT_RFC4716;
int print_public = 0;
int print_generic = 0;
+int read_public_only = 0;
char *key_type_name = NULL;
@@ -240,6 +241,13 @@
char *pass;
Key *prv;
+ if (read_public_only) {
+ Key *pub;
+
+ pub = key_load_public(filename, NULL);
+ return pub;
+ }
+
prv = key_load_private(filename, "", NULL);
if (prv == NULL) {
if (identity_passphrase)
@@ -705,7 +713,13 @@
perror(identity_file);
exit(1);
}
- prv = load_identity(identity_file);
+
+ if (read_public_only == 1) {
+ prv = key_load_public(identity_file, NULL);
+ } else {
+ prv = load_identity(identity_file);
+ }
+
if (prv == NULL) {
fprintf(stderr, "load failed\n");
exit(1);
@@ -1963,7 +1977,7 @@
}
while ((opt = getopt(argc, argv, "AegiqpclBHLhvxXyF:b:f:t:D:I:J:j:K:P:"
- "m:N:n:O:C:r:g:R:T:G:M:S:s:a:V:W:z")) != -1) {
+ "m:N:n:O:C:r:g:R:T:G:M:S:s:a:V:W:zQ:")) != -1) {
switch (opt) {
case 'A':
gen_all_hostkeys = 1;
@@ -2129,6 +2143,14 @@
if (BN_hex2bn(&start, optarg) == 0)
fatal("Invalid start point.");
break;
+ case 'Q':
+ if (strlcpy(identity_file, optarg, sizeof(identity_file)) >=
+ sizeof(identity_file))
+ fatal("Identity filename too long");
+ have_identity = 1;
+ print_public = 1;
+ read_public_only = 1;
+ break;
case 'V':
parse_cert_times(optarg);
break;
More information about the openssh-unix-dev
mailing list