int main(int argc, char **argv) { Filename *infilename = NULL; int intype = SSH_KEYTYPE_UNOPENABLE; int encrypted = 0; char* origcomment = 0; char* line = 0; char* passphrase = 0; struct ssh2_userkey *ssh2key = NULL; char* fingerprint = 0; printf("fzputtygen\n"); printf("Copyright (C) 2008-2016 Tim Kosse\n"); printf("Based on PuTTY's puttygen\n"); printf("Copyright (C) 1997-2015 Simon Tatham and the PuTTY team\n"); printf("Converts private SSH keys into PuTTY's format.\n"); printf("This program is used by FileZilla and not intended to be used directly.\n"); printf("Use the puttygen tool from PuTTY for a human-usable tool.\n"); printf("\n"); fflush(stdout); while (1) { sfree(line); line = fgetline(stdin); if (!line || !*line || *line == '\n') break; line[strlen(line) - 1] = 0; char* cmd = line, *args = line; while (*args) { if (*args == ' ') { *(args++) = 0; break; } args++; } if (!*args) args = 0; if (!strcmp(cmd, "file")) { char const* ret = NULL; if (ssh2key) { ssh2key->alg->freekey(ssh2key->data); sfree(ssh2key); ssh2key = 0; } sfree(passphrase); passphrase = 0; sfree(fingerprint); fingerprint = 0; if (!args) { fzprintf(sftpError, "No argument given"); continue; } if (infilename) { filename_free(infilename); } infilename = filename_from_str(args); intype = key_type(infilename); switch (intype) { case SSH_KEYTYPE_SSH1: ret = "incompatible"; intype = SSH_KEYTYPE_UNOPENABLE; break; case SSH_KEYTYPE_SSH2: ret = "ok"; encrypted = ssh2_userkey_encrypted(infilename, &origcomment); break; case SSH_KEYTYPE_UNKNOWN: case SSH_KEYTYPE_UNOPENABLE: default: ret = "error"; intype = SSH_KEYTYPE_UNOPENABLE; break; case SSH_KEYTYPE_OPENSSH_PEM: case SSH_KEYTYPE_OPENSSH_NEW: case SSH_KEYTYPE_SSHCOM: encrypted = import_encrypted(infilename, intype, &origcomment); ret = encrypted ? "convertible" : "ok"; break; } fzprintf(sftpReply, "%s", ret); } else if (!strcmp(cmd, "encrypted")) { if (intype == SSH_KEYTYPE_UNOPENABLE) { fzprintf(sftpError, "No key file opened"); continue; } fzprintf(sftpReply, "%d", encrypted ? 1 : 0); } else if (!strcmp(cmd, "comment")) { if (intype == SSH_KEYTYPE_UNOPENABLE) { fzprintf(sftpError, "No key file opened"); continue; } if (ssh2key && ssh2key->comment) { fzprintf(sftpReply, "%s", ssh2key->comment); } else if (origcomment) fzprintf(sftpReply, "%s", origcomment); else fzprintf(sftpReply, ""); } else if (!strcmp(cmd, "password")) { const char* error = NULL; if (!args) { fzprintf(sftpError, "No argument given"); continue; } if (intype == SSH_KEYTYPE_UNOPENABLE) { fzprintf(sftpError, "No key file opened"); continue; } if (!encrypted) { fzprintf(sftpError, "File is not encrypted"); continue; } if (ssh2key) { fzprintf(sftpError, "Already opened file"); continue; } sfree(passphrase); passphrase = strdup(args); switch (intype) { case SSH_KEYTYPE_SSH2: ssh2key = ssh2_load_userkey(infilename, passphrase, &error); break; case SSH_KEYTYPE_OPENSSH_PEM: case SSH_KEYTYPE_OPENSSH_NEW: case SSH_KEYTYPE_SSHCOM: ssh2key = import_ssh2(infilename, intype, passphrase, &error); break; default: break; } if (ssh2key == SSH2_WRONG_PASSPHRASE) { error = "wrong passphrase"; ssh2key = 0; } if (ssh2key) { error = NULL; } else if (!error) { error = "unknown error"; } if (error) fzprintf(sftpError, "Error loading file: %s", error); else fzprintf(sftpReply, ""); } else if (!strcmp(cmd, "fingerprint")) { const char* error = 0; if (!fingerprint) { if (ssh2key) { fingerprint = ssh2_fingerprint(ssh2key->alg, ssh2key->data); } else { switch (intype) { case SSH_KEYTYPE_SSH2: { void* ssh2blob; int bloblen = 0; char* comment = NULL; ssh2blob = ssh2_userkey_loadpub(infilename, 0, &bloblen, &comment, &error); if (ssh2blob) { fingerprint = ssh2_fingerprint_blob(ssh2blob, bloblen); sfree(ssh2blob); } else if (!error) { error = "unknown error"; } if (comment) { sfree(origcomment); origcomment = comment; } break; } case SSH_KEYTYPE_OPENSSH_PEM: case SSH_KEYTYPE_OPENSSH_NEW: case SSH_KEYTYPE_SSHCOM: ssh2key = import_ssh2(infilename, intype, "", &error); if (ssh2key) { if (ssh2key != SSH2_WRONG_PASSPHRASE) { error = NULL; fingerprint = ssh2_fingerprint(ssh2key->alg, ssh2key->data); } else { ssh2key = NULL; error = "wrong passphrase"; } } else if (!error) error = "unknown error"; break; default: error = "No file loaded"; break; } } } if (!fingerprint && !error) { error = "Could not get fingerprint"; } if (error) fzprintf(sftpError, "Error loading file: %s", error); else fzprintf(sftpReply, "%s", fingerprint); } else if (!strcmp(cmd, "write")) { Filename* outfilename; int ret; if (!args) { fzprintf(sftpError, "No argument given"); continue; } if (!ssh2key) { fzprintf(sftpError, "No key loaded"); continue; } outfilename = filename_from_str(args); ret = ssh2_save_userkey(outfilename, ssh2key, passphrase); if (!ret) { fzprintf(sftpError, "Unable to save SSH-2 private key"); continue; } filename_free(outfilename); fzprintf(sftpReply, ""); } else fzprintf(sftpError, "Unknown command"); } if (infilename) { filename_free(infilename); } sfree(line); sfree(passphrase); if (ssh2key) { ssh2key->alg->freekey(ssh2key->data); sfree(ssh2key); } sfree(fingerprint); sfree(origcomment); return 0; }
int main(int argc, char **argv) { int *fdlist; int fd; int i, fdstate; size_t fdsize; unsigned long now; ssh_key **hostkeys = NULL; size_t nhostkeys = 0, hostkeysize = 0; RSAKey *hostkey1 = NULL; AuthPolicy ap; Conf *conf = conf_new(); load_open_settings(NULL, conf); ap.kbdint_state = 0; ap.ssh1keys = NULL; ap.ssh2keys = NULL; if (argc <= 1) { /* * We're going to terminate with an error message below, * because there are no host keys. But we'll display the help * as additional standard-error output, if nothing else so * that people see the giant safety warning. */ show_help(stderr); fputc('\n', stderr); } while (--argc > 0) { const char *arg = *++argv; const char *val; if (!strcmp(arg, "--help")) { show_help(stdout); exit(0); } else if (!strcmp(arg, "--version")) { show_version_and_exit(); } else if (!strcmp(arg, "--verbose") || !strcmp(arg, "-v")) { verbose = true; } else if (longoptarg(arg, "--hostkey", &val, &argc, &argv)) { Filename *keyfile; int keytype; const char *error; keyfile = filename_from_str(val); keytype = key_type(keyfile); if (keytype == SSH_KEYTYPE_SSH2) { ssh2_userkey *uk; ssh_key *key; uk = ssh2_load_userkey(keyfile, NULL, &error); filename_free(keyfile); if (!uk || !uk->key) { fprintf(stderr, "%s: unable to load host key '%s': " "%s\n", appname, val, error); exit(1); } char *invalid = ssh_key_invalid(uk->key, 0); if (invalid) { fprintf(stderr, "%s: host key '%s' is unusable: " "%s\n", appname, val, invalid); exit(1); } key = uk->key; sfree(uk->comment); sfree(uk); for (i = 0; i < nhostkeys; i++) if (ssh_key_alg(hostkeys[i]) == ssh_key_alg(key)) { fprintf(stderr, "%s: host key '%s' duplicates key " "type %s\n", appname, val, ssh_key_alg(key)->ssh_id); exit(1); } sgrowarray(hostkeys, hostkeysize, nhostkeys); hostkeys[nhostkeys++] = key; } else if (keytype == SSH_KEYTYPE_SSH1) { if (hostkey1) { fprintf(stderr, "%s: host key '%s' is a redundant " "SSH-1 host key\n", appname, val); exit(1); } hostkey1 = snew(RSAKey); if (!rsa_ssh1_loadkey(keyfile, hostkey1, NULL, &error)) { fprintf(stderr, "%s: unable to load host key '%s': " "%s\n", appname, val, error); exit(1); } } else { fprintf(stderr, "%s: '%s' is not loadable as a " "private key (%s)", appname, val, key_type_to_str(keytype)); exit(1); } } else if (longoptarg(arg, "--userkey", &val, &argc, &argv)) { Filename *keyfile; int keytype; const char *error; keyfile = filename_from_str(val); keytype = key_type(keyfile); if (keytype == SSH_KEYTYPE_SSH2_PUBLIC_RFC4716 || keytype == SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH) { strbuf *sb = strbuf_new(); struct AuthPolicy_ssh2_pubkey *node; void *blob; if (!ssh2_userkey_loadpub(keyfile, NULL, BinarySink_UPCAST(sb), NULL, &error)) { fprintf(stderr, "%s: unable to load user key '%s': " "%s\n", appname, val, error); exit(1); } node = snew_plus(struct AuthPolicy_ssh2_pubkey, sb->len); blob = snew_plus_get_aux(node); memcpy(blob, sb->u, sb->len); node->public_blob = make_ptrlen(blob, sb->len); node->next = ap.ssh2keys; ap.ssh2keys = node; strbuf_free(sb); } else if (keytype == SSH_KEYTYPE_SSH1_PUBLIC) {