1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +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;
Filename *infilename = NULL, *outfilename = NULL;
LoadedFile *infile_lf = NULL;
BinarySource *infile_bs = NULL;
enum { NOKEYGEN, RSA1, RSA2, DSA, ECDSA, ED25519 } keytype = NOKEYGEN;
char *outfile = NULL, *outfiletmp = NULL;
enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH_AUTO,
@ -256,7 +258,7 @@ int main(int argc, char **argv)
*/
while (--argc) {
char *p = *++argv;
if (*p == '-') {
if (p[0] == '-' && p[1]) {
/*
* An option.
*/
@ -562,9 +564,23 @@ int main(int argc, char **argv)
* course of action.
*/
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) {
case SSH_KEYTYPE_UNOPENABLE:
@ -751,11 +767,13 @@ int main(int argc, char **argv)
* Find out whether the input key is encrypted.
*/
if (intype == SSH_KEYTYPE_SSH1)
encrypted = rsa1_encrypted_f(infilename, &origcomment);
encrypted = rsa1_encrypted_s(infile_bs, &origcomment);
else if (intype == SSH_KEYTYPE_SSH2)
encrypted = ppk_encrypted_f(infilename, &origcomment);
encrypted = ppk_encrypted_s(infile_bs, &origcomment);
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.
@ -799,7 +817,7 @@ int main(int argc, char **argv)
blob = strbuf_new();
ret = rsa1_loadpub_f(infilename, BinarySink_UPCAST(blob),
ret = rsa1_loadpub_s(infile_bs, BinarySink_UPCAST(blob),
&origcomment, &error);
BinarySource_BARE_INIT(src, blob->u, blob->len);
get_rsa_ssh1_pub(src, ssh1key, RSA_SSH1_EXPONENT_FIRST);
@ -811,8 +829,9 @@ int main(int argc, char **argv)
ssh1key->q = NULL;
ssh1key->iqmp = NULL;
} 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)
error = NULL;
else if (!error)
@ -826,7 +845,7 @@ int main(int argc, char **argv)
sfree(origcomment);
origcomment = NULL;
ssh2blob = strbuf_new();
if (ppk_loadpub_f(infilename, &ssh2alg,
if (ppk_loadpub_s(infile_bs, &ssh2alg,
BinarySink_UPCAST(ssh2blob),
&origcomment, &error)) {
const ssh_keyalg *alg = find_pubkey_alg(ssh2alg);
@ -841,8 +860,9 @@ int main(int argc, char **argv)
}
sfree(ssh2alg);
} 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)
error = NULL;
else if (!error) {
@ -856,7 +876,7 @@ int main(int argc, char **argv)
case SSH_KEYTYPE_OPENSSH_PEM:
case SSH_KEYTYPE_OPENSSH_NEW:
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 != SSH2_WRONG_PASSPHRASE)
error = NULL;
@ -1105,6 +1125,8 @@ int main(int argc, char **argv)
sfree(origcomment);
if (infilename)
filename_free(infilename);
if (infile_lf)
lf_free(infile_lf);
if (outfilename)
filename_free(outfilename);
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(ssh_key *key);
int key_type(const Filename *filename);
int key_type_s(BinarySource *src);
const char *key_type_to_str(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;
}
static int key_type_s(BinarySource *src);
static bool expect_signature(BinarySource *src, ptrlen realsig)
{
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 */
}
static int key_type_s(BinarySource *src)
int key_type_s(BinarySource *src)
{
int toret = key_type_s_internal(src);
BinarySource_REWIND(src);