xref: /openbsd-src/usr.bin/ssh/authfile.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*
2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  * This file contains functions for reading and writing identity files, and
6  * for reading the passphrase from the user.
7  *
8  * As far as I am concerned, the code I have written for this software
9  * can be used freely for any purpose.  Any derived versions of this
10  * software must be clearly marked as such, and if the derived work is
11  * incompatible with the protocol description in the RFC file, it must be
12  * called by a name other than "ssh" or "Secure Shell".
13  *
14  *
15  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  *    notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #include "includes.h"
39 RCSID("$OpenBSD: authfile.c,v 1.37 2001/06/23 15:12:17 itojun Exp $");
40 
41 #include <openssl/err.h>
42 #include <openssl/evp.h>
43 #include <openssl/pem.h>
44 
45 #include "cipher.h"
46 #include "xmalloc.h"
47 #include "buffer.h"
48 #include "bufaux.h"
49 #include "key.h"
50 #include "ssh.h"
51 #include "log.h"
52 #include "authfile.h"
53 
54 /* Version identification string for SSH v1 identity files. */
55 static const char authfile_id_string[] =
56     "SSH PRIVATE KEY FILE FORMAT 1.1\n";
57 
58 /*
59  * Saves the authentication (private) key in a file, encrypting it with
60  * passphrase.  The identification of the file (lowest 64 bits of n) will
61  * precede the key to provide identification of the key without needing a
62  * passphrase.
63  */
64 
65 static int
66 key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
67     const char *comment)
68 {
69 	Buffer buffer, encrypted;
70 	char buf[100], *cp;
71 	int fd, i;
72 	CipherContext ciphercontext;
73 	Cipher *cipher;
74 	u_int32_t rand;
75 
76 	/*
77 	 * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
78 	 * to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
79 	 */
80 	if (strcmp(passphrase, "") == 0)
81 		cipher = cipher_by_number(SSH_CIPHER_NONE);
82 	else
83 		cipher = cipher_by_number(SSH_AUTHFILE_CIPHER);
84 	if (cipher == NULL)
85 		fatal("save_private_key_rsa: bad cipher");
86 
87 	/* This buffer is used to built the secret part of the private key. */
88 	buffer_init(&buffer);
89 
90 	/* Put checkbytes for checking passphrase validity. */
91 	rand = arc4random();
92 	buf[0] = rand & 0xff;
93 	buf[1] = (rand >> 8) & 0xff;
94 	buf[2] = buf[0];
95 	buf[3] = buf[1];
96 	buffer_append(&buffer, buf, 4);
97 
98 	/*
99 	 * Store the private key (n and e will not be stored because they
100 	 * will be stored in plain text, and storing them also in encrypted
101 	 * format would just give known plaintext).
102 	 */
103 	buffer_put_bignum(&buffer, key->rsa->d);
104 	buffer_put_bignum(&buffer, key->rsa->iqmp);
105 	buffer_put_bignum(&buffer, key->rsa->q);	/* reverse from SSL p */
106 	buffer_put_bignum(&buffer, key->rsa->p);	/* reverse from SSL q */
107 
108 	/* Pad the part to be encrypted until its size is a multiple of 8. */
109 	while (buffer_len(&buffer) % 8 != 0)
110 		buffer_put_char(&buffer, 0);
111 
112 	/* This buffer will be used to contain the data in the file. */
113 	buffer_init(&encrypted);
114 
115 	/* First store keyfile id string. */
116 	for (i = 0; authfile_id_string[i]; i++)
117 		buffer_put_char(&encrypted, authfile_id_string[i]);
118 	buffer_put_char(&encrypted, 0);
119 
120 	/* Store cipher type. */
121 	buffer_put_char(&encrypted, cipher->number);
122 	buffer_put_int(&encrypted, 0);	/* For future extension */
123 
124 	/* Store public key.  This will be in plain text. */
125 	buffer_put_int(&encrypted, BN_num_bits(key->rsa->n));
126 	buffer_put_bignum(&encrypted, key->rsa->n);
127 	buffer_put_bignum(&encrypted, key->rsa->e);
128 	buffer_put_cstring(&encrypted, comment);
129 
130 	/* Allocate space for the private part of the key in the buffer. */
131 	buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
132 
133 	cipher_set_key_string(&ciphercontext, cipher, passphrase);
134 	cipher_encrypt(&ciphercontext, (u_char *) cp,
135 	    (u_char *) buffer_ptr(&buffer), buffer_len(&buffer));
136 	memset(&ciphercontext, 0, sizeof(ciphercontext));
137 
138 	/* Destroy temporary data. */
139 	memset(buf, 0, sizeof(buf));
140 	buffer_free(&buffer);
141 
142 	fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
143 	if (fd < 0) {
144 		error("open %s failed: %s.", filename, strerror(errno));
145 		return 0;
146 	}
147 	if (write(fd, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
148 	    buffer_len(&encrypted)) {
149 		error("write to key file %s failed: %s", filename,
150 		      strerror(errno));
151 		buffer_free(&encrypted);
152 		close(fd);
153 		unlink(filename);
154 		return 0;
155 	}
156 	close(fd);
157 	buffer_free(&encrypted);
158 	return 1;
159 }
160 
161 /* save SSH v2 key in OpenSSL PEM format */
162 static int
163 key_save_private_pem(Key *key, const char *filename, const char *_passphrase,
164     const char *comment)
165 {
166 	FILE *fp;
167 	int fd;
168 	int success = 0;
169 	int len = strlen(_passphrase);
170 	char *passphrase = (len > 0) ? (char *)_passphrase : NULL;
171 	EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
172 
173 	if (len > 0 && len <= 4) {
174 		error("passphrase too short: have %d bytes, need > 4", len);
175 		return 0;
176 	}
177 	fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
178 	if (fd < 0) {
179 		error("open %s failed: %s.", filename, strerror(errno));
180 		return 0;
181 	}
182 	fp = fdopen(fd, "w");
183 	if (fp == NULL ) {
184 		error("fdopen %s failed: %s.", filename, strerror(errno));
185 		close(fd);
186 		return 0;
187 	}
188 	switch (key->type) {
189 	case KEY_DSA:
190 		success = PEM_write_DSAPrivateKey(fp, key->dsa,
191 		    cipher, passphrase, len, NULL, NULL);
192 		break;
193 	case KEY_RSA:
194 		success = PEM_write_RSAPrivateKey(fp, key->rsa,
195 		    cipher, passphrase, len, NULL, NULL);
196 		break;
197 	}
198 	fclose(fp);
199 	return success;
200 }
201 
202 int
203 key_save_private(Key *key, const char *filename, const char *passphrase,
204     const char *comment)
205 {
206 	switch (key->type) {
207 	case KEY_RSA1:
208 		return key_save_private_rsa1(key, filename, passphrase,
209 		    comment);
210 		break;
211 	case KEY_DSA:
212 	case KEY_RSA:
213 		return key_save_private_pem(key, filename, passphrase,
214 		    comment);
215 		break;
216 	default:
217 		break;
218 	}
219 	error("key_save_private: cannot save key type %d", key->type);
220 	return 0;
221 }
222 
223 /*
224  * Loads the public part of the ssh v1 key file.  Returns NULL if an error was
225  * encountered (the file does not exist or is not readable), and the key
226  * otherwise.
227  */
228 
229 static Key *
230 key_load_public_rsa1(int fd, const char *filename, char **commentp)
231 {
232 	Buffer buffer;
233 	Key *pub;
234 	char *cp;
235 	int i;
236 	off_t len;
237 
238 	len = lseek(fd, (off_t) 0, SEEK_END);
239 	lseek(fd, (off_t) 0, SEEK_SET);
240 
241 	buffer_init(&buffer);
242 	buffer_append_space(&buffer, &cp, len);
243 
244 	if (read(fd, cp, (size_t) len) != (size_t) len) {
245 		debug("Read from key file %.200s failed: %.100s", filename,
246 		    strerror(errno));
247 		buffer_free(&buffer);
248 		return NULL;
249 	}
250 
251 	/* Check that it is at least big enough to contain the ID string. */
252 	if (len < sizeof(authfile_id_string)) {
253 		debug3("No RSA1 key file %.200s.", filename);
254 		buffer_free(&buffer);
255 		return NULL;
256 	}
257 	/*
258 	 * Make sure it begins with the id string.  Consume the id string
259 	 * from the buffer.
260 	 */
261 	for (i = 0; i < sizeof(authfile_id_string); i++)
262 		if (buffer_get_char(&buffer) != authfile_id_string[i]) {
263 			debug3("No RSA1 key file %.200s.", filename);
264 			buffer_free(&buffer);
265 			return NULL;
266 		}
267 	/* Skip cipher type and reserved data. */
268 	(void) buffer_get_char(&buffer);	/* cipher type */
269 	(void) buffer_get_int(&buffer);		/* reserved */
270 
271 	/* Read the public key from the buffer. */
272 	buffer_get_int(&buffer);
273 	pub = key_new(KEY_RSA1);
274 	buffer_get_bignum(&buffer, pub->rsa->n);
275 	buffer_get_bignum(&buffer, pub->rsa->e);
276 	if (commentp)
277 		*commentp = buffer_get_string(&buffer, NULL);
278 	/* The encrypted private part is not parsed by this function. */
279 
280 	buffer_free(&buffer);
281 	return pub;
282 }
283 
284 /* load public key from private-key file, works only for SSH v1 */
285 Key *
286 key_load_public_type(int type, const char *filename, char **commentp)
287 {
288 	Key *pub;
289 	int fd;
290 
291 	if (type == KEY_RSA1) {
292 		fd = open(filename, O_RDONLY);
293 		if (fd < 0)
294 			return NULL;
295 		pub = key_load_public_rsa1(fd, filename, commentp);
296 		close(fd);
297 		return pub;
298 	}
299 	return NULL;
300 }
301 
302 /*
303  * Loads the private key from the file.  Returns 0 if an error is encountered
304  * (file does not exist or is not readable, or passphrase is bad). This
305  * initializes the private key.
306  * Assumes we are called under uid of the owner of the file.
307  */
308 
309 static Key *
310 key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
311     char **commentp)
312 {
313 	int i, check1, check2, cipher_type;
314 	off_t len;
315 	Buffer buffer, decrypted;
316 	char *cp;
317 	CipherContext ciphercontext;
318 	Cipher *cipher;
319 	BN_CTX *ctx;
320 	BIGNUM *aux;
321 	Key *prv = NULL;
322 
323 	len = lseek(fd, (off_t) 0, SEEK_END);
324 	lseek(fd, (off_t) 0, SEEK_SET);
325 
326 	buffer_init(&buffer);
327 	buffer_append_space(&buffer, &cp, len);
328 
329 	if (read(fd, cp, (size_t) len) != (size_t) len) {
330 		debug("Read from key file %.200s failed: %.100s", filename,
331 		    strerror(errno));
332 		buffer_free(&buffer);
333 		close(fd);
334 		return NULL;
335 	}
336 
337 	/* Check that it is at least big enough to contain the ID string. */
338 	if (len < sizeof(authfile_id_string)) {
339 		debug3("No RSA1 key file %.200s.", filename);
340 		buffer_free(&buffer);
341 		close(fd);
342 		return NULL;
343 	}
344 	/*
345 	 * Make sure it begins with the id string.  Consume the id string
346 	 * from the buffer.
347 	 */
348 	for (i = 0; i < sizeof(authfile_id_string); i++)
349 		if (buffer_get_char(&buffer) != authfile_id_string[i]) {
350 			debug3("No RSA1 key file %.200s.", filename);
351 			buffer_free(&buffer);
352 			close(fd);
353 			return NULL;
354 		}
355 
356 	/* Read cipher type. */
357 	cipher_type = buffer_get_char(&buffer);
358 	(void) buffer_get_int(&buffer);	/* Reserved data. */
359 
360 	/* Read the public key from the buffer. */
361 	buffer_get_int(&buffer);
362 	prv = key_new_private(KEY_RSA1);
363 
364 	buffer_get_bignum(&buffer, prv->rsa->n);
365 	buffer_get_bignum(&buffer, prv->rsa->e);
366 	if (commentp)
367 		*commentp = buffer_get_string(&buffer, NULL);
368 	else
369 		xfree(buffer_get_string(&buffer, NULL));
370 
371 	/* Check that it is a supported cipher. */
372 	cipher = cipher_by_number(cipher_type);
373 	if (cipher == NULL) {
374 		debug("Unsupported cipher %d used in key file %.200s.",
375 		    cipher_type, filename);
376 		buffer_free(&buffer);
377 		goto fail;
378 	}
379 	/* Initialize space for decrypted data. */
380 	buffer_init(&decrypted);
381 	buffer_append_space(&decrypted, &cp, buffer_len(&buffer));
382 
383 	/* Rest of the buffer is encrypted.  Decrypt it using the passphrase. */
384 	cipher_set_key_string(&ciphercontext, cipher, passphrase);
385 	cipher_decrypt(&ciphercontext, (u_char *) cp,
386 	    (u_char *) buffer_ptr(&buffer), buffer_len(&buffer));
387 	memset(&ciphercontext, 0, sizeof(ciphercontext));
388 	buffer_free(&buffer);
389 
390 	check1 = buffer_get_char(&decrypted);
391 	check2 = buffer_get_char(&decrypted);
392 	if (check1 != buffer_get_char(&decrypted) ||
393 	    check2 != buffer_get_char(&decrypted)) {
394 		if (strcmp(passphrase, "") != 0)
395 			debug("Bad passphrase supplied for key file %.200s.",
396 			    filename);
397 		/* Bad passphrase. */
398 		buffer_free(&decrypted);
399 		goto fail;
400 	}
401 	/* Read the rest of the private key. */
402 	buffer_get_bignum(&decrypted, prv->rsa->d);
403 	buffer_get_bignum(&decrypted, prv->rsa->iqmp);		/* u */
404 	/* in SSL and SSH v1 p and q are exchanged */
405 	buffer_get_bignum(&decrypted, prv->rsa->q);		/* p */
406 	buffer_get_bignum(&decrypted, prv->rsa->p);		/* q */
407 
408 	/* calculate p-1 and q-1 */
409 	ctx = BN_CTX_new();
410 	aux = BN_new();
411 
412 	BN_sub(aux, prv->rsa->q, BN_value_one());
413 	BN_mod(prv->rsa->dmq1, prv->rsa->d, aux, ctx);
414 
415 	BN_sub(aux, prv->rsa->p, BN_value_one());
416 	BN_mod(prv->rsa->dmp1, prv->rsa->d, aux, ctx);
417 
418 	BN_clear_free(aux);
419 	BN_CTX_free(ctx);
420 
421 	buffer_free(&decrypted);
422 	close(fd);
423 	return prv;
424 
425 fail:
426 	if (commentp)
427 		xfree(*commentp);
428 	close(fd);
429 	key_free(prv);
430 	return NULL;
431 }
432 
433 static Key *
434 key_load_private_pem(int fd, int type, const char *passphrase,
435     char **commentp)
436 {
437 	FILE *fp;
438 	EVP_PKEY *pk = NULL;
439 	Key *prv = NULL;
440 	char *name = "<no key>";
441 
442 	fp = fdopen(fd, "r");
443 	if (fp == NULL) {
444 		error("fdopen failed: %s", strerror(errno));
445 		close(fd);
446 		return NULL;
447 	}
448 	pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase);
449 	if (pk == NULL) {
450 		debug("PEM_read_PrivateKey failed");
451 		(void)ERR_get_error();
452 	} else if (pk->type == EVP_PKEY_RSA &&
453 	     (type == KEY_UNSPEC||type==KEY_RSA)) {
454 		prv = key_new(KEY_UNSPEC);
455 		prv->rsa = EVP_PKEY_get1_RSA(pk);
456 		prv->type = KEY_RSA;
457 		name = "rsa w/o comment";
458 #ifdef DEBUG_PK
459 		RSA_print_fp(stderr, prv->rsa, 8);
460 #endif
461 	} else if (pk->type == EVP_PKEY_DSA &&
462 	     (type == KEY_UNSPEC||type==KEY_DSA)) {
463 		prv = key_new(KEY_UNSPEC);
464 		prv->dsa = EVP_PKEY_get1_DSA(pk);
465 		prv->type = KEY_DSA;
466 		name = "dsa w/o comment";
467 #ifdef DEBUG_PK
468 		DSA_print_fp(stderr, prv->dsa, 8);
469 #endif
470 	} else {
471 		error("PEM_read_PrivateKey: mismatch or "
472 		    "unknown EVP_PKEY save_type %d", pk->save_type);
473 	}
474 	fclose(fp);
475 	if (pk != NULL)
476 		EVP_PKEY_free(pk);
477 	if (prv != NULL && commentp)
478 		*commentp = xstrdup(name);
479 	debug("read PEM private key done: type %s",
480 	    prv ? key_type(prv) : "<unknown>");
481 	return prv;
482 }
483 
484 static int
485 key_perm_ok(int fd, const char *filename)
486 {
487 	struct stat st;
488 
489 	/* check owner and modes */
490 	if (fstat(fd, &st) < 0 ||
491 	    (st.st_uid != 0 && getuid() != 0 && st.st_uid != getuid()) ||
492 	    (st.st_mode & 077) != 0) {
493 		close(fd);
494 		error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
495 		error("@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @");
496 		error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
497 		error("Bad ownership or mode(0%3.3o) for '%s'.",
498 		    st.st_mode & 0777, filename);
499 		error("It is recommended that your private key files are NOT accessible by others.");
500 		error("This private key will be ignored.");
501 		return 0;
502 	}
503 	return 1;
504 }
505 
506 Key *
507 key_load_private_type(int type, const char *filename, const char *passphrase,
508     char **commentp)
509 {
510 	int fd;
511 
512 	fd = open(filename, O_RDONLY);
513 	if (fd < 0)
514 		return NULL;
515 	if (!key_perm_ok(fd, filename)) {
516 		error("bad permissions: ignore key: %s", filename);
517 		close(fd);
518 		return NULL;
519 	}
520 	switch (type) {
521 	case KEY_RSA1:
522 		return key_load_private_rsa1(fd, filename, passphrase,
523 		    commentp);
524 		/* closes fd */
525 		break;
526 	case KEY_DSA:
527 	case KEY_RSA:
528 	case KEY_UNSPEC:
529 		return key_load_private_pem(fd, type, passphrase, commentp);
530 		/* closes fd */
531 		break;
532 	default:
533 		close(fd);
534 		break;
535 	}
536 	return NULL;
537 }
538 
539 Key *
540 key_load_private(const char *filename, const char *passphrase,
541     char **commentp)
542 {
543 	Key *pub, *prv;
544 	int fd;
545 
546 	fd = open(filename, O_RDONLY);
547 	if (fd < 0)
548 		return NULL;
549 	if (!key_perm_ok(fd, filename)) {
550 		error("bad permissions: ignore key: %s", filename);
551 		close(fd);
552 		return NULL;
553 	}
554 	pub = key_load_public_rsa1(fd, filename, commentp);
555 	lseek(fd, (off_t) 0, SEEK_SET);		/* rewind */
556 	if (pub == NULL) {
557 		/* closes fd */
558 		prv = key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL);
559 		/* use the filename as a comment for PEM */
560 		if (commentp && prv)
561 			*commentp = xstrdup(filename);
562 	} else {
563 		/* it's a SSH v1 key if the public key part is readable */
564 		key_free(pub);
565 		/* closes fd */
566 		prv = key_load_private_rsa1(fd, filename, passphrase, NULL);
567 	}
568 	return prv;
569 }
570 
571 static int
572 key_try_load_public(Key *k, const char *filename, char **commentp)
573 {
574 	FILE *f;
575 	char line[4096];
576 	char *cp;
577 
578 	f = fopen(filename, "r");
579 	if (f != NULL) {
580 		while (fgets(line, sizeof(line), f)) {
581 			line[sizeof(line)-1] = '\0';
582 			cp = line;
583 			switch(*cp){
584 			case '#':
585 			case '\n':
586 			case '\0':
587 				continue;
588 			}
589 			/* Skip leading whitespace. */
590 			for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
591 				;
592 			if (*cp) {
593 				if (key_read(k, &cp) == 1) {
594 					if (commentp)
595 						*commentp=xstrdup(filename);
596 					fclose(f);
597 					return 1;
598 				}
599 			}
600 		}
601 		fclose(f);
602 	}
603 	return 0;
604 }
605 
606 /* load public key from ssh v1 private or any pubkey file */
607 Key *
608 key_load_public(const char *filename, char **commentp)
609 {
610 	Key *pub;
611 	char file[MAXPATHLEN];
612 
613 	pub = key_load_public_type(KEY_RSA1, filename, commentp);
614 	if (pub != NULL)
615 		return pub;
616 	pub = key_new(KEY_UNSPEC);
617 	if (key_try_load_public(pub, filename, commentp) == 1)
618 		return pub;
619 	if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
620 	    (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
621 	    (key_try_load_public(pub, file, commentp) == 1))
622 		return pub;
623 	key_free(pub);
624 	return NULL;
625 }
626