# SSHv1 to SSHv2 RSA keys converter diff --git a/openssh-6.4p1/converter/Makefile b/openssh-6.4p1/converter/Makefile new file mode 100644 --- /dev/null +++ b/openssh-6.4p1/converter/Makefile @@ -0,0 +1,17 @@ + +bindir=/usr/bin +mandir=/usr/share/man + +all : ssh-keyconverter + +ssh-keyconverter.o: ssh-keyconverter.c ../key.h ../authfile.h ../misc.h ../xmalloc.h + gcc $(CFLAGS) $(RPM_OPT_FLAGS) -c -I../ $< -o $@ + +ssh-keyconverter: ssh-keyconverter.o ../libssh.a ../openbsd-compat/libopenbsd-compat.a + gcc $< $(LDFLAGS) $(RPM_OPT_FLAGS) -L../ -L../openbsd-compat/ -lcrypto -lssh -lopenbsd-compat -lcrypto -lssh -lopenbsd-compat -lpam -ldl -lwrap -lutil -lz -lnsl -lcrypt -lssl -o $@ + +install: ssh-keyconverter ssh-keyconverter.1 + if [ ! -d $(DESTDIR)$(bindir) ]; then install -d -m 755 $(DESTDIR)$(bindir); fi + install -m 755 ssh-keyconverter $(DESTDIR)$(bindir) + if [ ! -d $(DESTDIR)$(mandir)/man1 ]; then install -d -m 755 $(DESTDIR)$(mandir)/man1; fi + install -m 644 ssh-keyconverter.1 $(DESTDIR)$(mandir)/man1 diff --git a/openssh-6.4p1/converter/ssh-keyconverter.1 b/openssh-6.4p1/converter/ssh-keyconverter.1 new file mode 100644 --- /dev/null +++ b/openssh-6.4p1/converter/ssh-keyconverter.1 @@ -0,0 +1,155 @@ +.\" Manpage for ssh-keyconverter +.\" +.Dd February 2, 2002 +.Dt SSH-KEYCONVER 1 +.Os +.Sh NAME +.Nm ssh-keyconvert +.Nd convert ssh v1 keys and authorization files +.Sh SYNOPSIS +.Nm ssh-keyconvert +.Op Fl k +.Op Fl o Ar output_file +.Ar identity_file ... +.Nm ssh-keyconvert +.Op Fl a +.Op Fl o Ar output_file +.Ar authorization_file ... +.Sh DESCRIPTION +.Nm +converts RSA public and private keys used for public key based +user authentication with protocol version 1 to the format +used with protocol version 2. +.Pp +When using RSA user authentication with SSH protocol version 1, +the client uses the private key from +.Pa $HOME/.ssh/identity +to provide its identity to the server. The server grants or denies +access based on whether the public part of this key is listed in +.Pa $HOME/.ssh/authorized_keys . +.Pp +SSH protocol version 2 supports both DSA and RSA keys, but the +way RSA keys are stored are differently. On the client, the default +file name is +.Pa .ssh/id_rsa +rather than +.Pa .ssh/identity , +and the file's format is different as well. On the server, the +public porting of the key can still be stored in +.Pa .ssh/authorized_keys , +but the key notation has changed as well. +Therefore, when switching from protocol version 1 +to version 2, you either have to create a new identity key using +.Xr ssh-keygen 1 +and add that key to the server's +.Pa authorized_keys +file, or you need to convert your keys using +.Nm ssh-keyconvert . +.Pp +By default, +.Nm +will try to guess the type of file that is to be converted. +If it fails to guess correctly, you can tell if what type of +conversion to perform by specifying the +.Fl k +option to convert the private key, or the +.Fl a +option to convert an authorisation file. +.Pp +When converting your private keys stored in +.Pa .ssh/identity , +.Nm +will read the private key, prompting you for the pass phrase +if the key is protected by a pass phrase. If the +.Fl o +option is given, it will write the private key to the specified +file, using version 2 syntax. If the key was protected by a +pass phrase, it will use the same pass phrase to protect the new +file. +It will also write the public portion of the key to a second file, +using the specified file name with +.Dq .pub +appended. +If the +.Fl o +option was not given, private and public key will be written to +.Pa id_rsa +and +.Pa id_rsa.pub , +respectively, relative to the directory of the input key file. +.Pp +If the destination file already exists, +.Nm +will prompt the user for confirmation before overwriting the +file, unless the +.Fl f +option is given. +.Pp +When converting your +.Pa authorized_keys +file, +.Nm +will ignore any keys in SSH version 2 format. Any public keys +in version 1 format will be converted and appended to the output file +using the new syntax. If the +.Fl o +option is given, keys are appended to the specified file. If it +is not given, +.Nm +will append all keys to the input file. +.Pp +Note that +.Nm +does not check for duplicate keys, so if you run it on +.Pa .ssh/authorized_keys +more several times, the converted keys will show up several times. +.Sh OPTIONS +.Bl -tag -width Ds +.It Fl k +Convert private key file(s). The default is to guess the +type of file that should be converted. +.It Fl a +Convert +.Pa authorized_keys +file(s). The default is to guess the +type of file that should be converted. +.It Fl o Ar outfile +Specify the name of the output file. +When converting an authorization file, all public keys will +be appended to this file. +For private key conversion, the private and public components of +the key will be stored in +.Pa outfile +and +.Pa outfile.pub , +respectively. +Note that since every key must be stored in a separate file, you +cannot use this option when you specify several input files. +.It Fl f +When converting a key file, and the output file already exists, +.Nm +will ask the user whether to overwrite the file. Using this option +forces overwriting. +.El +.Sh AUTHORS +OpenSSH is a derivative of the original and free +ssh 1.2.12 release by Tatu Ylonen. +Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, +Theo de Raadt and Dug Song +removed many bugs, re-added newer features and +created OpenSSH. +.Nm +was contributed by Olaf Kirch. +.Sh SEE ALSO +.Xr ssh 1 , +.Xr ssh-add 1 , +.Xr ssh-agent 1 , +.Xr sshd 8 +.Rs +.%A J. Galbraith +.%A R. Thayer +.%T "SECSH Public Key File Format" +.%N draft-ietf-secsh-publickeyfile-01.txt +.%D March 2001 +.%O work in progress material +.Re diff --git a/openssh-6.4p1/converter/ssh-keyconverter.c b/openssh-6.4p1/converter/ssh-keyconverter.c new file mode 100644 --- /dev/null +++ b/openssh-6.4p1/converter/ssh-keyconverter.c @@ -0,0 +1,345 @@ +/* + * SSH v1 to v2 RSA key converter. + * + * Instead of a manpage: + * + * ssh-keyconverter ~/.ssh/identity + * will put the old RSA key in ~/.ssh/id_rsa and id_rsa.pub + * If a "-o foofah" is given, the keys will be written to + * foofah and foofah.pub, respectively. + * + * ssh-keyconverter ~/.ssh/authorized_keys + * will convert all old RSA keys and add them to the + * input file. The -o foofah option will direct + * output to a different file. + * (Note that it's harmless to specify the same file + * as input and output, as ssh-keyconverter will ignore + * any v2 keys, and output is always appended, never + * replacing the original file). + * + * To compile: + * + * gcc -g -Wall -o ssh-keyconverter converter.c \ + * -L. -Lopenbsd-compat/ -lssh -lopenbsd-compat -lssh \ + * -lpam -ldl -lwrap -lutil -lz -lnsl \ + * -Wl,-Bstatic -lcrypto -Wl,-dy + * + * Enjoy. --okir + */ + +#include +#include +#include +#include +#include +#include "key.h" +#include "authfile.h" +#include "misc.h" +#include "xmalloc.h" + +#define TYPE_KEY 0 +#define TYPE_AUTHKEYS 1 + +#define PASSPHRASE_ATTEMPTS 3 + +static int opt_verbose = 0; +static int opt_force = 0; + +static void convert(int, const char *, const char *); +static void convert_private_key(const char *, const char *); +static void convert_authorized_keys(const char *, const char *); +static int fileok(const char *, char *, size_t); +static int guess_type(const char *); + +int +main(int argc, char **argv) +{ + int opt_type = -1; + char *opt_outfile = NULL; + int c; + + while ((c = getopt(argc, argv, "afko:")) != -1) { + switch (c) { + case 'a': + opt_type = TYPE_AUTHKEYS; + break; + case 'f': + opt_force = 1; + break; + case 'k': + opt_type = TYPE_KEY; + break; + case 'o': + opt_outfile = optarg; + break; + case 'v': + opt_verbose++; + break; + default: + fprintf(stderr, + "usage: ssh-keyconvert [-a | -k] " + "[-o filename] [-v] ...\n"); + exit(1); + } + } + + /* Warning, nanny code follows */ +#if 0 + if (opt_outfile && (argc - optind) > 1 && opt_type != TYPE_AUTHKEY) { + fprintf(stderr, + "Output file ambiguous: more than two " + "input files given. Abort.\n"); + exit(1); + } +#endif + + if (optind == argc) { + fprintf(stderr, + "Missing input file(s).\n"); + exit(1); + } + + for (; optind < argc; optind++) { + char *name = argv[optind]; + int type; + + if ((type = opt_type) < 0) + type = guess_type(name); + convert(type, name, opt_outfile); + } + + return 0; +} + +static void +convert(int type, const char *iname, const char *oname) +{ + if (type == TYPE_KEY) { + convert_private_key(iname, oname); + } else if (type == TYPE_AUTHKEYS) { + convert_authorized_keys(iname, oname); + } else { + fprintf(stderr, + "Conversion type not yet implemented.\n"); + exit(1); + } +} + +static void +convert_private_key(const char *iname, const char *oname) +{ + char prompt[1024], privname[PATH_MAX], pubname[PATH_MAX]; + char *comment = NULL, *passphrase; + Key *key = NULL, *pk = NULL; + int i; + FILE *pf = NULL; + + passphrase = xstrdup(""); + snprintf(prompt, sizeof(prompt), + "Enter passphrase for key '%.100s': ",iname); + for (i = 0; !key && i < PASSPHRASE_ATTEMPTS; i++) { + if (i) { + /* Zap old pass phrase */ + memset(passphrase, 0, strlen(passphrase)); + free(passphrase); + + /* Get a pass phrase from the user */ + passphrase = read_passphrase(prompt, 0); + } + key = key_load_private(iname, passphrase, &comment); + if (!key && i) + printf("Bad passphrase, please try again.\n"); + } + + if (oname != NULL) { + strcpy(privname, oname); + } else { + const char *s; + + if ((s = strrchr(iname, '/')) != NULL) { + int n = s + 1 - iname; + + strncpy(privname, iname, n); + privname[n++] = '\0'; + } + strcat(privname, "id_rsa"); + } + + if (!fileok("private", privname, sizeof(privname))) + goto out; + + sprintf(pubname, "%s.pub", privname); + if (!fileok("public", pubname, sizeof(pubname))) + goto out; + + /* "convert" from RSA1 to RSA */ + key->type = KEY_RSA; + pk = key_from_private(key); + + /* Now write the key in earnest */ + if (!key_save_private(key, privname, passphrase, comment)) { + fprintf(stderr, + "Failed to save private key to %s: %m.\n", privname); + goto out; + } + + if (!(pf = fopen(pubname, "w"))) { + fprintf(stderr, + "Failed to save public key to %s: %m.\n", pubname); + goto out; + } + if (!key_write(pk, pf)) { + fprintf(stderr, + "Failed to save public key to %s: %m.\n", pubname); + goto out; + } + if (comment) + fprintf(pf, " %s\n", comment); + +out: + memset(passphrase, 0, strlen(passphrase)); + free(passphrase); + if (key) + key_free(key); + if (pk) + key_free(pk); + if (pf) + fclose(pf); +} + +static void +convert_authorized_keys(const char *iname, const char *oname) +{ + char line[1024]; + FILE *ifp, *ofp; + Key *key; + + if (!(ifp = fopen(iname, "r"))) { + perror(iname); + exit(1); + } + + if (oname == NULL) + oname = iname; + + if (!strcmp(oname, "-")) { + ofp = stdout; + } else { + if ((ofp = fopen(oname, "a")) == NULL) { + perror(oname); + exit(1); + } + } + setlinebuf(ofp); + +#define whitespace(c) ((c) == ' ' || (c) == '\t') + while (fgets(line, sizeof(line), ifp) != NULL) { + char *cp = line, *options = NULL; + + while (whitespace(*cp)) + cp++; + if (!*cp || *cp == '\n' || *cp == '#') + continue; + + key = key_new(KEY_RSA1); + if (key_read(key, &cp) != 1) { + /* Skip options, if any */ + int quoted = 0; + + options = cp; + for (; *cp && (quoted || !whitespace(*cp)); cp++) { + if (cp[0] == '\\' && cp[1] == '"') + ++cp; + else if (*cp == '"') + quoted = !quoted; + } + if (quoted) + goto next; + *cp++ = '\0'; + while (whitespace(*cp)) + cp++; + if (key_read(key, &cp) != 1) + goto next; + } + + if (options) + fprintf(ofp, "%s ", options); + /* "convert" from RSA1 to RSA */ + key->type = KEY_RSA; + key_write(key, ofp); + fputs(cp, ofp); + key_free(key); + + next: + ; + } +} + +/* if file exists, ask user whether to overwrite it */ +static int +fileok(const char *what, char *filename, size_t size) +{ + char buffer[PATH_MAX]; + int n; + +checkagain: + if (access(filename, F_OK) < 0) + return 1; + printf("%s key file %s already exists.\n", what, filename); + if (opt_force) { + printf("Overwriting because of -f option...\n"); + return 1; + } + +tryagain: + printf("Please enter a different filename, " + "or return to overwrite: "); + fflush(stdout); + + n = read(0, buffer, sizeof(buffer)-1); + if (n <= 0) + printf("\n"); + if (n < 0) { + perror("read failed"); + exit(1); + } + if (n == 0) { + fprintf(stderr, "EOF from standard input. Bye.\n"); + exit(1); + } + buffer[n] = '\0'; + while (n && buffer[n-1] == '\n') + buffer[--n] = '\0'; + if (n == 0) + return 1; + if (n >= size) { + fprintf(stderr, "Filename too long.\n"); + goto tryagain; + } + strcpy(filename, buffer); + goto checkagain; +} + +/* + * Guess the type of file to be converted. + * XXX: should look at the file; v1 key files + * start with "SSH PRIVATE KEY FILE" + */ +static int +guess_type(const char *name) +{ + printf("%s... ", name); + if (strstr(name, "identity")) { + printf("looks like a key file\n"); + return TYPE_KEY; + } + if (strstr(name, "authorized_keys")) { + printf("looks like an authorized_keys file\n"); + return TYPE_AUTHKEYS; + } + + if (opt_verbose) + printf("unable to identify."); + fprintf(stderr, "Please specify the file type for %s. Abort.\n", name); + exit(1); +}