1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

Allow cmdgen to read keys from standard input.

This reworks the cmdgen main program so that it loads the input file
into a LoadedFile right at the start, and then every time it needs to
do something with the contents, it calls one of the API functions
taking a BinarySource instead of one taking a Filename.

The usefulness of this is that now we can read from things that aren't
regular files, and can't be rewound or reopened. In particular, the
filename "-" is now taken (per the usual convention) to mean standard
input.

So now you can pipe a public or private key file into cmdgen's
standard input and have it do something useful. For example, I was
recently experimenting with the SFTP-only SSH server that comes with
'proftpd', which keeps its authorized_keys file in RFC 4716 format
instead of the OpenSSH one-liner format, and I found I wanted to do

  grep 'my-key-comment' ~/.ssh/authorized_keys | puttygen -p -

to quickly get hold of my existing public key to put in that file. But
I had to go via a temporary file to make that work, because puttygen
couldn't read from standard input. Next time, it will be able to!
This commit is contained in:
Simon Tatham 2020-02-02 11:41:06 +00:00
parent 36d214c50b
commit 7599a57a33
3 changed files with 35 additions and 14 deletions

View File

@ -215,6 +215,8 @@ int main(int argc, char **argv)
{ {
char *infile = NULL; char *infile = NULL;
Filename *infilename = NULL, *outfilename = NULL; Filename *infilename = NULL, *outfilename = NULL;
LoadedFile *infile_lf = NULL;
BinarySource *infile_bs = NULL;
enum { NOKEYGEN, RSA1, RSA2, DSA, ECDSA, ED25519 } keytype = NOKEYGEN; enum { NOKEYGEN, RSA1, RSA2, DSA, ECDSA, ED25519 } keytype = NOKEYGEN;
char *outfile = NULL, *outfiletmp = NULL; char *outfile = NULL, *outfiletmp = NULL;
enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH_AUTO, enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH_AUTO,
@ -256,7 +258,7 @@ int main(int argc, char **argv)
*/ */
while (--argc) { while (--argc) {
char *p = *++argv; char *p = *++argv;
if (*p == '-') { if (p[0] == '-' && p[1]) {
/* /*
* An option. * An option.
*/ */
@ -562,9 +564,23 @@ int main(int argc, char **argv)
* course of action. * course of action.
*/ */
if (infile) { if (infile) {
infilename = filename_from_str(infile); const char *load_error;
intype = key_type(infilename); infilename = filename_from_str(infile);
if (!strcmp(infile, "-"))
infile_lf = lf_load_keyfile_fp(stdin, &load_error);
else
infile_lf = lf_load_keyfile(infilename, &load_error);
if (!infile_lf) {
fprintf(stderr, "puttygen: unable to load file `%s': %s\n",
infile, load_error);
RETURN(1);
}
infile_bs = BinarySource_UPCAST(infile_lf);
intype = key_type_s(infile_bs);
BinarySource_REWIND(infile_bs);
switch (intype) { switch (intype) {
case SSH_KEYTYPE_UNOPENABLE: case SSH_KEYTYPE_UNOPENABLE:
@ -751,11 +767,13 @@ int main(int argc, char **argv)
* Find out whether the input key is encrypted. * Find out whether the input key is encrypted.
*/ */
if (intype == SSH_KEYTYPE_SSH1) if (intype == SSH_KEYTYPE_SSH1)
encrypted = rsa1_encrypted_f(infilename, &origcomment); encrypted = rsa1_encrypted_s(infile_bs, &origcomment);
else if (intype == SSH_KEYTYPE_SSH2) else if (intype == SSH_KEYTYPE_SSH2)
encrypted = ppk_encrypted_f(infilename, &origcomment); encrypted = ppk_encrypted_s(infile_bs, &origcomment);
else else
encrypted = import_encrypted(infilename, intype, &origcomment); encrypted = import_encrypted_s(infilename, infile_bs,
intype, &origcomment);
BinarySource_REWIND(infile_bs);
/* /*
* If so, ask for a passphrase. * If so, ask for a passphrase.
@ -799,7 +817,7 @@ int main(int argc, char **argv)
blob = strbuf_new(); blob = strbuf_new();
ret = rsa1_loadpub_f(infilename, BinarySink_UPCAST(blob), ret = rsa1_loadpub_s(infile_bs, BinarySink_UPCAST(blob),
&origcomment, &error); &origcomment, &error);
BinarySource_BARE_INIT(src, blob->u, blob->len); BinarySource_BARE_INIT(src, blob->u, blob->len);
get_rsa_ssh1_pub(src, ssh1key, RSA_SSH1_EXPONENT_FIRST); get_rsa_ssh1_pub(src, ssh1key, RSA_SSH1_EXPONENT_FIRST);
@ -811,8 +829,9 @@ int main(int argc, char **argv)
ssh1key->q = NULL; ssh1key->q = NULL;
ssh1key->iqmp = NULL; ssh1key->iqmp = NULL;
} else { } else {
ret = rsa1_load_f(infilename, ssh1key, old_passphrase, &error); ret = rsa1_load_s(infile_bs, ssh1key, old_passphrase, &error);
} }
BinarySource_REWIND(infile_bs);
if (ret > 0) if (ret > 0)
error = NULL; error = NULL;
else if (!error) else if (!error)
@ -826,7 +845,7 @@ int main(int argc, char **argv)
sfree(origcomment); sfree(origcomment);
origcomment = NULL; origcomment = NULL;
ssh2blob = strbuf_new(); ssh2blob = strbuf_new();
if (ppk_loadpub_f(infilename, &ssh2alg, if (ppk_loadpub_s(infile_bs, &ssh2alg,
BinarySink_UPCAST(ssh2blob), BinarySink_UPCAST(ssh2blob),
&origcomment, &error)) { &origcomment, &error)) {
const ssh_keyalg *alg = find_pubkey_alg(ssh2alg); const ssh_keyalg *alg = find_pubkey_alg(ssh2alg);
@ -841,8 +860,9 @@ int main(int argc, char **argv)
} }
sfree(ssh2alg); sfree(ssh2alg);
} else { } else {
ssh2key = ppk_load_f(infilename, old_passphrase, &error); ssh2key = ppk_load_s(infile_bs, old_passphrase, &error);
} }
BinarySource_REWIND(infile_bs);
if ((ssh2key && ssh2key != SSH2_WRONG_PASSPHRASE) || ssh2blob) if ((ssh2key && ssh2key != SSH2_WRONG_PASSPHRASE) || ssh2blob)
error = NULL; error = NULL;
else if (!error) { else if (!error) {
@ -856,7 +876,7 @@ int main(int argc, char **argv)
case SSH_KEYTYPE_OPENSSH_PEM: case SSH_KEYTYPE_OPENSSH_PEM:
case SSH_KEYTYPE_OPENSSH_NEW: case SSH_KEYTYPE_OPENSSH_NEW:
case SSH_KEYTYPE_SSHCOM: case SSH_KEYTYPE_SSHCOM:
ssh2key = import_ssh2(infilename, intype, old_passphrase, &error); ssh2key = import_ssh2_s(infile_bs, intype, old_passphrase, &error);
if (ssh2key) { if (ssh2key) {
if (ssh2key != SSH2_WRONG_PASSPHRASE) if (ssh2key != SSH2_WRONG_PASSPHRASE)
error = NULL; error = NULL;
@ -1105,6 +1125,8 @@ int main(int argc, char **argv)
sfree(origcomment); sfree(origcomment);
if (infilename) if (infilename)
filename_free(infilename); filename_free(infilename);
if (infile_lf)
lf_free(infile_lf);
if (outfilename) if (outfilename)
filename_free(outfilename); filename_free(outfilename);
sfree(outfiletmp); sfree(outfiletmp);

1
ssh.h
View File

@ -1260,6 +1260,7 @@ void ssh2_write_pubkey(FILE *fp, const char *comment,
char *ssh2_fingerprint_blob(ptrlen); char *ssh2_fingerprint_blob(ptrlen);
char *ssh2_fingerprint(ssh_key *key); char *ssh2_fingerprint(ssh_key *key);
int key_type(const Filename *filename); int key_type(const Filename *filename);
int key_type_s(BinarySource *src);
const char *key_type_to_str(int type); const char *key_type_to_str(int type);
bool import_possible(int type); bool import_possible(int type);

View File

@ -146,8 +146,6 @@ LoadedFile *lf_load_keyfile_fp(FILE *fp, const char **errptr)
return lf; return lf;
} }
static int key_type_s(BinarySource *src);
static bool expect_signature(BinarySource *src, ptrlen realsig) static bool expect_signature(BinarySource *src, ptrlen realsig)
{ {
ptrlen thissig = get_data(src, realsig.len); ptrlen thissig = get_data(src, realsig.len);
@ -1678,7 +1676,7 @@ static int key_type_s_internal(BinarySource *src)
return SSH_KEYTYPE_UNKNOWN; /* unrecognised or EOF */ return SSH_KEYTYPE_UNKNOWN; /* unrecognised or EOF */
} }
static int key_type_s(BinarySource *src) int key_type_s(BinarySource *src)
{ {
int toret = key_type_s_internal(src); int toret = key_type_s_internal(src);
BinarySource_REWIND(src); BinarySource_REWIND(src);