Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CMDGEN.C')
-rw-r--r--CMDGEN.C527
1 files changed, 410 insertions, 117 deletions
diff --git a/CMDGEN.C b/CMDGEN.C
index ef9c2e1c..b12758a1 100644
--- a/CMDGEN.C
+++ b/CMDGEN.C
@@ -130,13 +130,19 @@ void help(void)
" public RFC 4716 / ssh.com public key\n"
" public-openssh OpenSSH public key\n"
" fingerprint output the key fingerprint\n"
+ " cert-info print certificate information\n"
" text output the key components as "
"'name=0x####'\n"
" -o specify output file\n"
" -l equivalent to `-O fingerprint'\n"
" -L equivalent to `-O public-openssh'\n"
" -p equivalent to `-O public'\n"
+ " --cert-info equivalent to `-O cert-info'\n"
" --dump equivalent to `-O text'\n"
+ " -E fptype specify fingerprint output type:\n"
+ " sha256, md5, sha256-cert, md5-cert\n"
+ " --certificate file incorporate a certificate into the key\n"
+ " --remove-certificate remove any certificate from the key\n"
" --reencrypt load a key and save it with fresh "
"encryption\n"
" --old-passphrase file\n"
@@ -214,6 +220,15 @@ static char *readpassphrase(const char *filename)
#define DEFAULT_RSADSA_BITS 2048
+static void spr_error(SeatPromptResult spr)
+{
+ if (spr.kind == SPRK_SW_ABORT) {
+ char *err = spr_get_error_message(spr);
+ fprintf(stderr, "puttygen: unable to read passphrase: %s", err);
+ sfree(err);
+ }
+}
+
/* For Unix in particular, but harmless if this main() is reused elsewhere */
const bool buildinfo_gtk_relevant = false;
@@ -226,7 +241,7 @@ int main(int argc, char **argv)
enum { NOKEYGEN, RSA1, RSA2, DSA, ECDSA, EDDSA } keytype = NOKEYGEN;
char *outfile = NULL, *outfiletmp = NULL;
enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH_AUTO,
- OPENSSH_NEW, SSHCOM, TEXT } outtype = PRIVATE;
+ OPENSSH_NEW, SSHCOM, TEXT, CERTINFO } outtype = PRIVATE;
int bits = -1;
const char *comment = NULL;
char *origcomment = NULL;
@@ -241,6 +256,8 @@ int main(int argc, char **argv)
char *old_passphrase = NULL, *new_passphrase = NULL;
bool load_encrypted;
const char *random_device = NULL;
+ char *certfile = NULL;
+ bool remove_cert = false;
int exit_status = 0;
const PrimeGenerationPolicy *primegen = &primegen_probabilistic;
bool strong_rsa = false;
@@ -286,75 +303,79 @@ int main(int argc, char **argv)
while (*p && *p != '=')
p++; /* find end of option */
if (*p == '=') {
- *p++ = '\0';
- val = p;
+ *p++ = '\0';
+ val = p;
} else
val = NULL;
if (!strcmp(opt, "-help")) {
- if (val) {
- errs = true;
- fprintf(stderr, "puttygen: option `-%s'"
- " expects no argument\n", opt);
- } else {
- help();
- nogo = true;
- }
+ if (val) {
+ errs = true;
+ fprintf(stderr, "puttygen: option `-%s'"
+ " expects no argument\n", opt);
+ } else {
+ help();
+ nogo = true;
+ }
} else if (!strcmp(opt, "-version")) {
- if (val) {
- errs = true;
- fprintf(stderr, "puttygen: option `-%s'"
- " expects no argument\n", opt);
- } else {
- showversion();
- nogo = true;
- }
+ if (val) {
+ errs = true;
+ fprintf(stderr, "puttygen: option `-%s'"
+ " expects no argument\n", opt);
+ } else {
+ showversion();
+ nogo = true;
+ }
} else if (!strcmp(opt, "-pgpfp")) {
- if (val) {
- errs = true;
- fprintf(stderr, "puttygen: option `-%s'"
- " expects no argument\n", opt);
- } else {
- /* support --pgpfp for consistency */
- pgp_fingerprints();
- nogo = true;
- }
+ if (val) {
+ errs = true;
+ fprintf(stderr, "puttygen: option `-%s'"
+ " expects no argument\n", opt);
+ } else {
+ /* support --pgpfp for consistency */
+ pgp_fingerprints();
+ nogo = true;
+ }
} else if (!strcmp(opt, "-old-passphrase")) {
- if (!val && argc > 1)
- --argc, val = *++argv;
- if (!val) {
- errs = true;
- fprintf(stderr, "puttygen: option `-%s'"
- " expects an argument\n", opt);
- } else {
- old_passphrase = readpassphrase(val);
- if (!old_passphrase)
+ if (!val && argc > 1)
+ --argc, val = *++argv;
+ if (!val) {
errs = true;
- }
+ fprintf(stderr, "puttygen: option `-%s'"
+ " expects an argument\n", opt);
+ } else {
+ old_passphrase = readpassphrase(val);
+ if (!old_passphrase)
+ errs = true;
+ }
} else if (!strcmp(opt, "-new-passphrase")) {
- if (!val && argc > 1)
- --argc, val = *++argv;
- if (!val) {
- errs = true;
- fprintf(stderr, "puttygen: option `-%s'"
- " expects an argument\n", opt);
- } else {
- new_passphrase = readpassphrase(val);
- if (!new_passphrase)
+ if (!val && argc > 1)
+ --argc, val = *++argv;
+ if (!val) {
errs = true;
- }
+ fprintf(stderr, "puttygen: option `-%s'"
+ " expects an argument\n", opt);
+ } else {
+ new_passphrase = readpassphrase(val);
+ if (!new_passphrase)
+ errs = true;
+ }
} else if (!strcmp(opt, "-random-device")) {
- if (!val && argc > 1)
- --argc, val = *++argv;
- if (!val) {
- errs = true;
- fprintf(stderr, "puttygen: option `-%s'"
- " expects an argument\n", opt);
- } else {
- random_device = val;
- }
+ if (!val && argc > 1)
+ --argc, val = *++argv;
+ if (!val) {
+ errs = true;
+ fprintf(stderr, "puttygen: option `-%s'"
+ " expects an argument\n", opt);
+ } else {
+ random_device = val;
+ }
} else if (!strcmp(opt, "-dump")) {
outtype = TEXT;
+ } else if (!strcmp(opt, "-cert-info") ||
+ !strcmp(opt, "-certinfo") ||
+ !strcmp(opt, "-cert_info")) {
+ outtype = CERTINFO;
} else if (!strcmp(opt, "-primes")) {
if (!val && argc > 1)
--argc, val = *++argv;
@@ -383,6 +404,18 @@ int main(int argc, char **argv)
}
} else if (!strcmp(opt, "-strong-rsa")) {
strong_rsa = true;
+ } else if (!strcmp(opt, "-certificate")) {
+ if (!val && argc > 1)
+ --argc, val = *++argv;
+ if (!val) {
+ errs = true;
+ fprintf(stderr, "puttygen: option `-%s'"
+ " expects an argument\n", opt);
+ } else {
+ certfile = val;
+ }
+ } else if (!strcmp(opt, "-remove-certificate")) {
+ remove_cert = true;
} else if (!strcmp(opt, "-reencrypt")) {
reencrypt = true;
} else if (!strcmp(opt, "-ppk-param") ||
@@ -461,9 +494,9 @@ int main(int argc, char **argv)
}
}
} else {
- errs = true;
- fprintf(stderr,
- "puttygen: no such option `-%s'\n", opt);
+ errs = true;
+ fprintf(stderr,
+ "puttygen: no such option `-%s'\n", opt);
}
p = NULL;
break;
@@ -569,6 +602,8 @@ int main(int argc, char **argv)
outtype = SSHCOM, sshver = 2;
else if (!strcmp(p, "text"))
outtype = TEXT;
+ else if (!strcmp(p, "cert-info"))
+ outtype = CERTINFO;
else {
fprintf(stderr,
"puttygen: unknown output type `%s'\n", p);
@@ -583,6 +618,10 @@ int main(int argc, char **argv)
fptype = SSH_FPTYPE_MD5;
else if (!strcmp(p, "sha256"))
fptype = SSH_FPTYPE_SHA256;
+ else if (!strcmp(p, "md5-cert"))
+ fptype = SSH_FPTYPE_MD5_CERT;
+ else if (!strcmp(p, "sha256-cert"))
+ fptype = SSH_FPTYPE_SHA256_CERT;
else {
fprintf(stderr, "puttygen: unknown fingerprint "
"type `%s'\n", p);
@@ -790,7 +829,8 @@ int main(int argc, char **argv)
outfiletmp = dupcat(outfile, ".tmp");
}
- if (!change_passphrase && !comment && !reencrypt) {
+ if (!change_passphrase && !comment && !reencrypt && !certfile &&
+ !remove_cert) {
fprintf(stderr, "puttygen: this command would perform no useful"
" action\n");
RETURN(1);
@@ -840,6 +880,26 @@ int main(int argc, char **argv)
RETURN(1);
}
+ /*
+ * Check consistency properties relating to certificates.
+ */
+ if (certfile && !(sshver == 2 && intype_has_private &&
+ outtype_has_private && infile)) {
+ fprintf(stderr, "puttygen: certificates can only be added to "
+ "existing SSH-2 private key files\n");
+ RETURN(1);
+ }
+ if (remove_cert && !(sshver == 2 && infile)) {
+ fprintf(stderr, "puttygen: certificates can only be removed from "
+ "existing SSH-2 key files\n");
+ RETURN(1);
+ }
+ if (certfile && remove_cert) {
+ fprintf(stderr, "puttygen: cannot both add and remove a "
+ "certificate\n");
+ RETURN(1);
+ }
+
/* ------------------------------------------------------------------
* Now we're ready to actually do some stuff.
*/
@@ -878,10 +938,10 @@ int main(int argc, char **argv)
PrimeGenerationContext *pgc = primegen_new_context(primegen);
if (keytype == DSA) {
- struct dss_key *dsskey = snew(struct dss_key);
- dsa_generate(dsskey, bits, pgc, &cmdgen_progress);
+ struct dsa_key *dsakey = snew(struct dsa_key);
+ dsa_generate(dsakey, bits, pgc, &cmdgen_progress);
ssh2key = snew(ssh2_userkey);
- ssh2key->key = &dsskey->sshk;
+ ssh2key->key = &dsakey->sshk;
ssh1key = NULL;
} else if (keytype == ECDSA) {
struct ecdsa_key *ek = snew(struct ecdsa_key);
@@ -941,16 +1001,16 @@ int main(int argc, char **argv)
if (encrypted && load_encrypted) {
if (!old_passphrase) {
prompts_t *p = new_prompts();
- int ret;
+ SeatPromptResult spr;
p->to_server = false;
p->from_server = false;
p->name = dupstr("SSH key passphrase");
add_prompt(p, dupstr("Enter passphrase to load key: "), false);
- ret = console_get_userpass_input(p);
- assert(ret >= 0);
- if (!ret) {
+ spr = console_get_userpass_input(p);
+ assert(spr.kind != SPRK_INCOMPLETE);
+ if (spr_is_abort(spr)) {
free_prompts(p);
- perror("puttygen: unable to read passphrase");
+ spr_error(spr);
RETURN(1);
} else {
old_passphrase = prompt_get_result(p->prompts[0]);
@@ -1073,6 +1133,124 @@ int main(int argc, char **argv)
}
/*
+ * Swap out the public key for a different one, if asked to.
+ */
+ if (certfile) {
+ Filename *certfilename = filename_from_str(certfile);
+ LoadedFile *certfile_lf;
+ const char *error = NULL;
+
+ if (!strcmp(certfile, "-"))
+ certfile_lf = lf_load_keyfile_fp(stdin, &error);
+ else
+ certfile_lf = lf_load_keyfile(certfilename, &error);
+
+ filename_free(certfilename);
+
+ if (!certfile_lf) {
+ fprintf(stderr, "puttygen: unable to load certificate file `%s': "
+ "%s\n", certfile, error);
+ RETURN(1);
+ }
+
+ char *algname = NULL;
+ char *comment = NULL;
+ strbuf *pub = strbuf_new();
+ if (!ppk_loadpub_s(BinarySource_UPCAST(certfile_lf), &algname,
+ BinarySink_UPCAST(pub), &comment, &error)) {
+ fprintf(stderr, "puttygen: unable to load certificate file `%s': "
+ "%s\n", certfile, error);
+ strbuf_free(pub);
+ sfree(algname);
+ sfree(comment);
+ lf_free(certfile_lf);
+ RETURN(1);
+ }
+
+ lf_free(certfile_lf);
+ sfree(comment);
+
+ const ssh_keyalg *alg = find_pubkey_alg(algname);
+ if (!alg) {
+ fprintf(stderr, "puttygen: certificate file `%s' has unsupported "
+ "algorithm name `%s'\n", certfile, algname);
+ strbuf_free(pub);
+ sfree(algname);
+ RETURN(1);
+ }
+
+ sfree(algname);
+
+ /* Check the two public keys match apart from certificates */
+ strbuf *old_basepub = strbuf_new();
+ ssh_key_public_blob(ssh_key_base_key(ssh2key->key),
+ BinarySink_UPCAST(old_basepub));
+
+ ssh_key *new_pubkey = ssh_key_new_pub(alg, ptrlen_from_strbuf(pub));
+ strbuf *new_basepub = strbuf_new();
+ ssh_key_public_blob(ssh_key_base_key(new_pubkey),
+ BinarySink_UPCAST(new_basepub));
+ ssh_key_free(new_pubkey);
+
+ bool match = ptrlen_eq_ptrlen(ptrlen_from_strbuf(old_basepub),
+ ptrlen_from_strbuf(new_basepub));
+ strbuf_free(old_basepub);
+ strbuf_free(new_basepub);
+
+ if (!match) {
+ fprintf(stderr, "puttygen: certificate in `%s' does not match "
+ "public key in `%s'\n", certfile, infile);
+ strbuf_free(pub);
+ RETURN(1);
+ }
+
+ strbuf *priv = strbuf_new_nm();
+ ssh_key_private_blob(ssh2key->key, BinarySink_UPCAST(priv));
+ ssh_key *newkey = ssh_key_new_priv(
+ alg, ptrlen_from_strbuf(pub), ptrlen_from_strbuf(priv));
+ strbuf_free(pub);
+ strbuf_free(priv);
+
+ if (!newkey) {
+ fprintf(stderr, "puttygen: unable to combine certificate in `%s' "
+ "with private key\n", certfile);
+ RETURN(1);
+ }
+
+ ssh_key_free(ssh2key->key);
+ ssh2key->key = newkey;
+ } else if (remove_cert) {
+ /*
+ * Removing a certificate can be meaningfully done to a pure
+ * public key blob, as well as a full key pair.
+ */
+ if (ssh2key) {
+ ssh_key *newkey = ssh_key_clone(ssh_key_base_key(ssh2key->key));
+ ssh_key_free(ssh2key->key);
+ ssh2key->key = newkey;
+ } else if (ssh2blob) {
+ ptrlen algname = pubkey_blob_to_alg_name(
+ ptrlen_from_strbuf(ssh2blob));
+
+ const ssh_keyalg *alg = find_pubkey_alg_len(algname);
+
+ if (!alg) {
+ fprintf(stderr, "puttygen: input file `%s' has unsupported "
+ "algorithm name `%.*s'\n", infile,
+ PTRLEN_PRINTF(algname));
+ RETURN(1);
+ }
+
+ ssh_key *tmpkey = ssh_key_new_pub(
+ alg, ptrlen_from_strbuf(ssh2blob));
+ strbuf_clear(ssh2blob);
+ ssh_key_public_blob(ssh_key_base_key(tmpkey),
+ BinarySink_UPCAST(ssh2blob));
+ ssh_key_free(tmpkey);
+ }
+ }
+
+ /*
* Unless we're changing the passphrase, the old one (if any) is a
* reasonable default.
*/
@@ -1090,18 +1268,18 @@ int main(int argc, char **argv)
if (!new_passphrase && (change_passphrase ||
(keytype != NOKEYGEN && outtype != TEXT))) {
prompts_t *p = new_prompts();
- int ret;
+ SeatPromptResult spr;
p->to_server = false;
p->from_server = false;
p->name = dupstr("New SSH key passphrase");
add_prompt(p, dupstr("Enter passphrase to save key: "), false);
add_prompt(p, dupstr("Re-enter passphrase to verify: "), false);
- ret = console_get_userpass_input(p);
- assert(ret >= 0);
- if (!ret) {
+ spr = console_get_userpass_input(p);
+ assert(spr.kind != SPRK_INCOMPLETE);
+ if (spr_is_abort(spr)) {
free_prompts(p);
- perror("puttygen: unable to read new passphrase");
+ spr_error(spr);
RETURN(1);
} else {
if (strcmp(prompt_get_result_ref(p->prompts[0]),
@@ -1164,29 +1342,29 @@ int main(int argc, char **argv)
FILE *fp;
if (outfile) {
- fp = f_open(outfilename, "w", false);
- if (!fp) {
- fprintf(stderr, "unable to open output file\n");
- exit(1);
- }
+ fp = f_open(outfilename, "w", false);
+ if (!fp) {
+ fprintf(stderr, "unable to open output file\n");
+ exit(1);
+ }
} else {
- fp = stdout;
+ fp = stdout;
}
if (sshver == 1) {
- ssh1_write_pubkey(fp, ssh1key);
+ ssh1_write_pubkey(fp, ssh1key);
} else {
- if (!ssh2blob) {
- assert(ssh2key);
- ssh2blob = strbuf_new();
- ssh_key_public_blob(ssh2key->key, BinarySink_UPCAST(ssh2blob));
- }
-
- ssh2_write_pubkey(fp, ssh2key ? ssh2key->comment : origcomment,
- ssh2blob->s, ssh2blob->len,
- (outtype == PUBLIC ?
- SSH_KEYTYPE_SSH2_PUBLIC_RFC4716 :
- SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH));
+ if (!ssh2blob) {
+ assert(ssh2key);
+ ssh2blob = strbuf_new();
+ ssh_key_public_blob(ssh2key->key, BinarySink_UPCAST(ssh2blob));
+ }
+
+ ssh2_write_pubkey(fp, ssh2key ? ssh2key->comment : origcomment,
+ ssh2blob->s, ssh2blob->len,
+ (outtype == PUBLIC ?
+ SSH_KEYTYPE_SSH2_PUBLIC_RFC4716 :
+ SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH));
}
if (outfile)
@@ -1200,26 +1378,26 @@ int main(int argc, char **argv)
char *fingerprint;
if (sshver == 1) {
- assert(ssh1key);
- fingerprint = rsa_ssh1_fingerprint(ssh1key);
+ assert(ssh1key);
+ fingerprint = rsa_ssh1_fingerprint(ssh1key);
} else {
- if (ssh2key) {
- fingerprint = ssh2_fingerprint(ssh2key->key, fptype);
- } else {
- assert(ssh2blob);
- fingerprint = ssh2_fingerprint_blob(
- ptrlen_from_strbuf(ssh2blob), fptype);
- }
+ if (ssh2key) {
+ fingerprint = ssh2_fingerprint(ssh2key->key, fptype);
+ } else {
+ assert(ssh2blob);
+ fingerprint = ssh2_fingerprint_blob(
+ ptrlen_from_strbuf(ssh2blob), fptype);
+ }
}
if (outfile) {
- fp = f_open(outfilename, "w", false);
- if (!fp) {
- fprintf(stderr, "unable to open output file\n");
- exit(1);
- }
+ fp = f_open(outfilename, "w", false);
+ if (!fp) {
+ fprintf(stderr, "unable to open output file\n");
+ exit(1);
+ }
} else {
- fp = stdout;
+ fp = stdout;
}
fprintf(fp, "%s\n", fingerprint);
if (outfile)
@@ -1271,9 +1449,8 @@ int main(int argc, char **argv)
} else {
assert(ssh2blob);
- BinarySource src[1];
- BinarySource_BARE_INIT_PL(src, ptrlen_from_strbuf(ssh2blob));
- ptrlen algname = get_string(src);
+ ptrlen algname = pubkey_blob_to_alg_name(
+ ptrlen_from_strbuf(ssh2blob));
const ssh_keyalg *alg = find_pubkey_alg_len(algname);
if (!alg) {
fprintf(stderr, "puttygen: cannot extract key components "
@@ -1304,16 +1481,55 @@ int main(int argc, char **argv)
}
for (size_t i = 0; i < kc->ncomponents; i++) {
- if (kc->components[i].is_mp_int) {
- char *hex = mp_get_hex(kc->components[i].mp);
- fprintf(fp, "%s=0x%s\n", kc->components[i].name, hex);
+ key_component *comp = &kc->components[i];
+ fprintf(fp, "%s=", comp->name);
+ switch (comp->type) {
+ case KCT_MPINT: {
+ char *hex = mp_get_hex(comp->mp);
+ fprintf(fp, "0x%s\n", hex);
smemclr(hex, strlen(hex));
sfree(hex);
- } else {
- fprintf(fp, "%s=\"", kc->components[i].name);
- write_c_string_literal(fp, ptrlen_from_asciz(
- kc->components[i].text));
+ break;
+ }
+ case KCT_TEXT:
+ fputs("\"", fp);
+ write_c_string_literal(fp, ptrlen_from_strbuf(comp->str));
fputs("\"\n", fp);
+ break;
+ case KCT_BINARY: {
+ /*
+ * Display format for binary key components is to show
+ * them as base64, with a wrapper so that the actual
+ * printed string is along the lines of
+ * 'b64("aGVsbG8sIHdvcmxkCg==")'.
+ *
+ * That's a compromise between not being too verbose
+ * for a human reader, and still being reasonably
+ * friendly to people pasting the output of this
+ * 'puttygen --dump' option into Python code (which
+ * the format is designed to permit in general).
+ *
+ * Python users pasting a dump containing one of these
+ * will have to define a function 'b64' in advance
+ * which takes a string, which you can do most easily
+ * using this import statement, as seen in
+ * cryptsuite.py:
+ *
+ * from base64 import b64decode as b64
+ */
+ fputs("b64(\"", fp);
+ char b64[4];
+ for (size_t j = 0; j < comp->str->len; j += 3) {
+ size_t len = comp->str->len - j;
+ if (len > 3) len = 3;
+ base64_encode_atom(comp->str->u + j, len, b64);
+ fwrite(b64, 1, 4, fp);
+ }
+ fputs("\")\n", fp);
+ break;
+ }
+ default:
+ unreachable("bad key component type");
}
}
@@ -1322,6 +1538,83 @@ int main(int argc, char **argv)
key_components_free(kc);
break;
}
+
+ case CERTINFO: {
+ if (sshver == 1) {
+ fprintf(stderr, "puttygen: SSH-1 keys cannot contain "
+ "certificates\n");
+ RETURN(1);
+ }
+
+ const ssh_keyalg *alg;
+ ssh_key *sk;
+ bool sk_allocated = false;
+
+ if (ssh2key) {
+ sk = ssh2key->key;
+ alg = ssh_key_alg(sk);
+ } else {
+ assert(ssh2blob);
+ ptrlen algname = pubkey_blob_to_alg_name(
+ ptrlen_from_strbuf(ssh2blob));
+ alg = find_pubkey_alg_len(algname);
+ if (!alg) {
+ fprintf(stderr, "puttygen: cannot extract certificate info "
+ "from public key of unknown type '%.*s'\n",
+ PTRLEN_PRINTF(algname));
+ RETURN(1);
+ }
+ sk = ssh_key_new_pub(alg, ptrlen_from_strbuf(ssh2blob));
+ if (!sk) {
+ fprintf(stderr, "puttygen: unable to decode public key\n");
+ RETURN(1);
+ }
+ sk_allocated = true;
+ }
+
+ if (!alg->is_certificate) {
+ fprintf(stderr, "puttygen: key is not a certificate\n");
+ } else {
+ SeatDialogText *text = ssh_key_cert_info(sk);
+
+ FILE *fp;
+ if (outfile) {
+ fp = f_open(outfilename, "w", false);
+ if (!fp) {
+ fprintf(stderr, "unable to open output file\n");
+ exit(1);
+ }
+ } else {
+ fp = stdout;
+ }
+
+ for (SeatDialogTextItem *item = text->items,
+ *end = item+text->nitems; item < end; item++) {
+ switch (item->type) {
+ case SDT_MORE_INFO_KEY:
+ fprintf(fp, "%s", item->text);
+ break;
+ case SDT_MORE_INFO_VALUE_SHORT:
+ fprintf(fp, ": %s\n", item->text);
+ break;
+ case SDT_MORE_INFO_VALUE_BLOB:
+ fprintf(fp, ":\n%s\n", item->text);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (outfile)
+ fclose(fp);
+
+ seat_dialog_text_free(text);
+ }
+
+ if (sk_allocated)
+ ssh_key_free(sk);
+ break;
+ }
}
out: