summaryrefslogtreecommitdiff
path: root/ssh-keygen.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-keygen.c')
-rw-r--r--ssh-keygen.c149
1 files changed, 109 insertions, 40 deletions
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 64fadc7a1..04a9b939a 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.160 2007/01/21 01:41:54 stevesk Exp $ */
1/* 2/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -12,28 +13,44 @@
12 */ 13 */
13 14
14#include "includes.h" 15#include "includes.h"
15RCSID("$OpenBSD: ssh-keygen.c,v 1.135 2005/11/29 02:04:55 dtucker Exp $"); 16
17#include <sys/types.h>
18#include <sys/socket.h>
19#include <sys/stat.h>
20#include <sys/param.h>
16 21
17#include <openssl/evp.h> 22#include <openssl/evp.h>
18#include <openssl/pem.h> 23#include <openssl/pem.h>
19 24
25#include <errno.h>
26#include <fcntl.h>
27#include <netdb.h>
28#ifdef HAVE_PATHS_H
29# include <paths.h>
30#endif
31#include <pwd.h>
32#include <stdarg.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
37
20#include "xmalloc.h" 38#include "xmalloc.h"
21#include "key.h" 39#include "key.h"
22#include "rsa.h" 40#include "rsa.h"
23#include "authfile.h" 41#include "authfile.h"
24#include "uuencode.h" 42#include "uuencode.h"
25#include "buffer.h" 43#include "buffer.h"
26#include "bufaux.h"
27#include "pathnames.h" 44#include "pathnames.h"
28#include "log.h" 45#include "log.h"
29#include "misc.h" 46#include "misc.h"
30#include "match.h" 47#include "match.h"
31#include "hostfile.h" 48#include "hostfile.h"
49#include "dns.h"
32 50
33#ifdef SMARTCARD 51#ifdef SMARTCARD
34#include "scard.h" 52#include "scard.h"
35#endif 53#endif
36#include "dns.h"
37 54
38/* Number of bits in the RSA/DSA key. This value can be set on the command line. */ 55/* Number of bits in the RSA/DSA key. This value can be set on the command line. */
39#define DEFAULT_BITS 2048 56#define DEFAULT_BITS 2048
@@ -103,7 +120,7 @@ ask_filename(struct passwd *pw, const char *prompt)
103 120
104 if (key_type_name == NULL) 121 if (key_type_name == NULL)
105 name = _PATH_SSH_CLIENT_ID_RSA; 122 name = _PATH_SSH_CLIENT_ID_RSA;
106 else 123 else {
107 switch (key_type_from_name(key_type_name)) { 124 switch (key_type_from_name(key_type_name)) {
108 case KEY_RSA1: 125 case KEY_RSA1:
109 name = _PATH_SSH_CLIENT_IDENTITY; 126 name = _PATH_SSH_CLIENT_IDENTITY;
@@ -119,7 +136,7 @@ ask_filename(struct passwd *pw, const char *prompt)
119 exit(1); 136 exit(1);
120 break; 137 break;
121 } 138 }
122 139 }
123 snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name); 140 snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name);
124 fprintf(stderr, "%s (%s): ", prompt, identity_file); 141 fprintf(stderr, "%s (%s): ", prompt, identity_file);
125 if (fgets(buf, sizeof(buf), stdin) == NULL) 142 if (fgets(buf, sizeof(buf), stdin) == NULL)
@@ -205,7 +222,8 @@ buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
205 if (buffer_len(b) < bytes) 222 if (buffer_len(b) < bytes)
206 fatal("buffer_get_bignum_bits: input buffer too small: " 223 fatal("buffer_get_bignum_bits: input buffer too small: "
207 "need %d have %d", bytes, buffer_len(b)); 224 "need %d have %d", bytes, buffer_len(b));
208 BN_bin2bn(buffer_ptr(b), bytes, value); 225 if (BN_bin2bn(buffer_ptr(b), bytes, value) == NULL)
226 fatal("buffer_get_bignum_bits: BN_bin2bn failed");
209 buffer_consume(b, bytes); 227 buffer_consume(b, bytes);
210} 228}
211 229
@@ -223,7 +241,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
223 buffer_init(&b); 241 buffer_init(&b);
224 buffer_append(&b, blob, blen); 242 buffer_append(&b, blob, blen);
225 243
226 magic = buffer_get_int(&b); 244 magic = buffer_get_int(&b);
227 if (magic != SSH_COM_PRIVATE_KEY_MAGIC) { 245 if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
228 error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC); 246 error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
229 buffer_free(&b); 247 buffer_free(&b);
@@ -235,7 +253,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
235 i2 = buffer_get_int(&b); 253 i2 = buffer_get_int(&b);
236 i3 = buffer_get_int(&b); 254 i3 = buffer_get_int(&b);
237 i4 = buffer_get_int(&b); 255 i4 = buffer_get_int(&b);
238 debug("ignore (%d %d %d %d)", i1,i2,i3,i4); 256 debug("ignore (%d %d %d %d)", i1, i2, i3, i4);
239 if (strcmp(cipher, "none") != 0) { 257 if (strcmp(cipher, "none") != 0) {
240 error("unsupported cipher %s", cipher); 258 error("unsupported cipher %s", cipher);
241 xfree(cipher); 259 xfree(cipher);
@@ -266,7 +284,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
266 buffer_get_bignum_bits(&b, key->dsa->priv_key); 284 buffer_get_bignum_bits(&b, key->dsa->priv_key);
267 break; 285 break;
268 case KEY_RSA: 286 case KEY_RSA:
269 e = buffer_get_char(&b); 287 e = buffer_get_char(&b);
270 debug("e %lx", e); 288 debug("e %lx", e);
271 if (e < 30) { 289 if (e < 30) {
272 e <<= 8; 290 e <<= 8;
@@ -302,13 +320,43 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
302 return key; 320 return key;
303} 321}
304 322
323static int
324get_line(FILE *fp, char *line, size_t len)
325{
326 int c;
327 size_t pos = 0;
328
329 line[0] = '\0';
330 while ((c = fgetc(fp)) != EOF) {
331 if (pos >= len - 1) {
332 fprintf(stderr, "input line too long.\n");
333 exit(1);
334 }
335 switch (c) {
336 case '\r':
337 c = fgetc(fp);
338 if (c != EOF && c != '\n' && ungetc(c, fp) == EOF) {
339 fprintf(stderr, "unget: %s\n", strerror(errno));
340 exit(1);
341 }
342 return pos;
343 case '\n':
344 return pos;
345 }
346 line[pos++] = c;
347 line[pos] = '\0';
348 }
349 /* We reached EOF */
350 return -1;
351}
352
305static void 353static void
306do_convert_from_ssh2(struct passwd *pw) 354do_convert_from_ssh2(struct passwd *pw)
307{ 355{
308 Key *k; 356 Key *k;
309 int blen; 357 int blen;
310 u_int len; 358 u_int len;
311 char line[1024], *p; 359 char line[1024];
312 u_char blob[8096]; 360 u_char blob[8096];
313 char encoded[8096]; 361 char encoded[8096];
314 struct stat st; 362 struct stat st;
@@ -327,12 +375,8 @@ do_convert_from_ssh2(struct passwd *pw)
327 exit(1); 375 exit(1);
328 } 376 }
329 encoded[0] = '\0'; 377 encoded[0] = '\0';
330 while (fgets(line, sizeof(line), fp)) { 378 while ((blen = get_line(fp, line, sizeof(line))) != -1) {
331 if (!(p = strchr(line, '\n'))) { 379 if (line[blen - 1] == '\\')
332 fprintf(stderr, "input line too long.\n");
333 exit(1);
334 }
335 if (p > line && p[-1] == '\\')
336 escaped++; 380 escaped++;
337 if (strncmp(line, "----", 4) == 0 || 381 if (strncmp(line, "----", 4) == 0 ||
338 strstr(line, ": ") != NULL) { 382 strstr(line, ": ") != NULL) {
@@ -349,7 +393,6 @@ do_convert_from_ssh2(struct passwd *pw)
349 /* fprintf(stderr, "escaped: %s", line); */ 393 /* fprintf(stderr, "escaped: %s", line); */
350 continue; 394 continue;
351 } 395 }
352 *p = '\0';
353 strlcat(encoded, line, sizeof(encoded)); 396 strlcat(encoded, line, sizeof(encoded));
354 } 397 }
355 len = strlen(encoded); 398 len = strlen(encoded);
@@ -485,8 +528,10 @@ do_fingerprint(struct passwd *pw)
485 xfree(fp); 528 xfree(fp);
486 exit(0); 529 exit(0);
487 } 530 }
488 if (comment) 531 if (comment) {
489 xfree(comment); 532 xfree(comment);
533 comment = NULL;
534 }
490 535
491 f = fopen(identity_file, "r"); 536 f = fopen(identity_file, "r");
492 if (f != NULL) { 537 if (f != NULL) {
@@ -508,7 +553,7 @@ do_fingerprint(struct passwd *pw)
508 for (cp = line; *cp == ' ' || *cp == '\t'; cp++) 553 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
509 ; 554 ;
510 if (!*cp || *cp == '\n' || *cp == '#') 555 if (!*cp || *cp == '\n' || *cp == '#')
511 continue ; 556 continue;
512 i = strtol(cp, &ep, 10); 557 i = strtol(cp, &ep, 10);
513 if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) { 558 if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
514 int quoted = 0; 559 int quoted = 0;
@@ -832,30 +877,32 @@ do_change_passphrase(struct passwd *pw)
832/* 877/*
833 * Print the SSHFP RR. 878 * Print the SSHFP RR.
834 */ 879 */
835static void 880static int
836do_print_resource_record(struct passwd *pw, char *hname) 881do_print_resource_record(struct passwd *pw, char *fname, char *hname)
837{ 882{
838 Key *public; 883 Key *public;
839 char *comment = NULL; 884 char *comment = NULL;
840 struct stat st; 885 struct stat st;
841 886
842 if (!have_identity) 887 if (fname == NULL)
843 ask_filename(pw, "Enter file in which the key is"); 888 ask_filename(pw, "Enter file in which the key is");
844 if (stat(identity_file, &st) < 0) { 889 if (stat(fname, &st) < 0) {
845 perror(identity_file); 890 if (errno == ENOENT)
891 return 0;
892 perror(fname);
846 exit(1); 893 exit(1);
847 } 894 }
848 public = key_load_public(identity_file, &comment); 895 public = key_load_public(fname, &comment);
849 if (public != NULL) { 896 if (public != NULL) {
850 export_dns_rr(hname, public, stdout, print_generic); 897 export_dns_rr(hname, public, stdout, print_generic);
851 key_free(public); 898 key_free(public);
852 xfree(comment); 899 xfree(comment);
853 exit(0); 900 return 1;
854 } 901 }
855 if (comment) 902 if (comment)
856 xfree(comment); 903 xfree(comment);
857 904
858 printf("failed to read v2 public key from %s.\n", identity_file); 905 printf("failed to read v2 public key from %s.\n", fname);
859 exit(1); 906 exit(1);
860} 907}
861 908
@@ -969,13 +1016,13 @@ usage(void)
969#ifdef SMARTCARD 1016#ifdef SMARTCARD
970 fprintf(stderr, " -D reader Download public key from smartcard.\n"); 1017 fprintf(stderr, " -D reader Download public key from smartcard.\n");
971#endif /* SMARTCARD */ 1018#endif /* SMARTCARD */
972 fprintf(stderr, " -e Convert OpenSSH to IETF SECSH key file.\n"); 1019 fprintf(stderr, " -e Convert OpenSSH to RFC 4716 key file.\n");
973 fprintf(stderr, " -F hostname Find hostname in known hosts file.\n"); 1020 fprintf(stderr, " -F hostname Find hostname in known hosts file.\n");
974 fprintf(stderr, " -f filename Filename of the key file.\n"); 1021 fprintf(stderr, " -f filename Filename of the key file.\n");
975 fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n"); 1022 fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n");
976 fprintf(stderr, " -g Use generic DNS resource record format.\n"); 1023 fprintf(stderr, " -g Use generic DNS resource record format.\n");
977 fprintf(stderr, " -H Hash names in known_hosts file.\n"); 1024 fprintf(stderr, " -H Hash names in known_hosts file.\n");
978 fprintf(stderr, " -i Convert IETF SECSH to OpenSSH key file.\n"); 1025 fprintf(stderr, " -i Convert RFC 4716 to OpenSSH key file.\n");
979 fprintf(stderr, " -l Show fingerprint of key file.\n"); 1026 fprintf(stderr, " -l Show fingerprint of key file.\n");
980 fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n"); 1027 fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n");
981 fprintf(stderr, " -N phrase Provide new passphrase.\n"); 1028 fprintf(stderr, " -N phrase Provide new passphrase.\n");
@@ -1001,7 +1048,7 @@ usage(void)
1001 * Main program for key management. 1048 * Main program for key management.
1002 */ 1049 */
1003int 1050int
1004main(int ac, char **av) 1051main(int argc, char **argv)
1005{ 1052{
1006 char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; 1053 char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
1007 char out_file[MAXPATHLEN], *reader_id = NULL; 1054 char out_file[MAXPATHLEN], *reader_id = NULL;
@@ -1023,10 +1070,10 @@ main(int ac, char **av)
1023 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 1070 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
1024 sanitise_stdfd(); 1071 sanitise_stdfd();
1025 1072
1026 __progname = ssh_get_progname(av[0]); 1073 __progname = ssh_get_progname(argv[0]);
1027 1074
1028 SSLeay_add_all_algorithms(); 1075 SSLeay_add_all_algorithms();
1029 log_init(av[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); 1076 log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
1030 1077
1031 init_rng(); 1078 init_rng();
1032 seed_rng(); 1079 seed_rng();
@@ -1042,11 +1089,11 @@ main(int ac, char **av)
1042 exit(1); 1089 exit(1);
1043 } 1090 }
1044 1091
1045 while ((opt = getopt(ac, av, 1092 while ((opt = getopt(argc, argv,
1046 "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) { 1093 "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
1047 switch (opt) { 1094 switch (opt) {
1048 case 'b': 1095 case 'b':
1049 bits = strtonum(optarg, 768, 32768, &errstr); 1096 bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
1050 if (errstr) 1097 if (errstr)
1051 fatal("Bits has bad value %s (%s)", 1098 fatal("Bits has bad value %s (%s)",
1052 optarg, errstr); 1099 optarg, errstr);
@@ -1116,6 +1163,7 @@ main(int ac, char **av)
1116 break; 1163 break;
1117 case 'D': 1164 case 'D':
1118 download = 1; 1165 download = 1;
1166 /*FALLTHROUGH*/
1119 case 'U': 1167 case 'U':
1120 reader_id = optarg; 1168 reader_id = optarg;
1121 break; 1169 break;
@@ -1132,19 +1180,20 @@ main(int ac, char **av)
1132 rr_hostname = optarg; 1180 rr_hostname = optarg;
1133 break; 1181 break;
1134 case 'W': 1182 case 'W':
1135 generator_wanted = strtonum(optarg, 1, UINT_MAX, &errstr); 1183 generator_wanted = (u_int32_t)strtonum(optarg, 1,
1184 UINT_MAX, &errstr);
1136 if (errstr) 1185 if (errstr)
1137 fatal("Desired generator has bad value: %s (%s)", 1186 fatal("Desired generator has bad value: %s (%s)",
1138 optarg, errstr); 1187 optarg, errstr);
1139 break; 1188 break;
1140 case 'a': 1189 case 'a':
1141 trials = strtonum(optarg, 1, UINT_MAX, &errstr); 1190 trials = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
1142 if (errstr) 1191 if (errstr)
1143 fatal("Invalid number of trials: %s (%s)", 1192 fatal("Invalid number of trials: %s (%s)",
1144 optarg, errstr); 1193 optarg, errstr);
1145 break; 1194 break;
1146 case 'M': 1195 case 'M':
1147 memory = strtonum(optarg, 1, UINT_MAX, &errstr); 1196 memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
1148 if (errstr) { 1197 if (errstr) {
1149 fatal("Memory limit is %s: %s", errstr, optarg); 1198 fatal("Memory limit is %s: %s", errstr, optarg);
1150 } 1199 }
@@ -1173,9 +1222,9 @@ main(int ac, char **av)
1173 } 1222 }
1174 1223
1175 /* reinit */ 1224 /* reinit */
1176 log_init(av[0], log_level, SYSLOG_FACILITY_USER, 1); 1225 log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1);
1177 1226
1178 if (optind < ac) { 1227 if (optind < argc) {
1179 printf("Too many arguments.\n"); 1228 printf("Too many arguments.\n");
1180 usage(); 1229 usage();
1181 } 1230 }
@@ -1198,7 +1247,27 @@ main(int ac, char **av)
1198 if (print_public) 1247 if (print_public)
1199 do_print_public(pw); 1248 do_print_public(pw);
1200 if (rr_hostname != NULL) { 1249 if (rr_hostname != NULL) {
1201 do_print_resource_record(pw, rr_hostname); 1250 unsigned int n = 0;
1251
1252 if (have_identity) {
1253 n = do_print_resource_record(pw,
1254 identity_file, rr_hostname);
1255 if (n == 0) {
1256 perror(identity_file);
1257 exit(1);
1258 }
1259 exit(0);
1260 } else {
1261
1262 n += do_print_resource_record(pw,
1263 _PATH_HOST_RSA_KEY_FILE, rr_hostname);
1264 n += do_print_resource_record(pw,
1265 _PATH_HOST_DSA_KEY_FILE, rr_hostname);
1266
1267 if (n == 0)
1268 fatal("no keys found.");
1269 exit(0);
1270 }
1202 } 1271 }
1203 if (reader_id != NULL) { 1272 if (reader_id != NULL) {
1204#ifdef SMARTCARD 1273#ifdef SMARTCARD