~ubuntu-branches/ubuntu/lucid/openssh/lucid

1.13.1 by Colin Watson
Import upstream version 4.6p1
1
/* $OpenBSD: authfile.c,v 1.76 2006/08/03 03:34:41 deraadt Exp $ */
1 by Noah Meyerhans
Import upstream version 3.8.1p1
2
/*
3
 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4
 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5
 *                    All rights reserved
6
 * This file contains functions for reading and writing identity files, and
7
 * for reading the passphrase from the user.
8
 *
9
 * As far as I am concerned, the code I have written for this software
10
 * can be used freely for any purpose.  Any derived versions of this
11
 * software must be clearly marked as such, and if the derived work is
12
 * incompatible with the protocol description in the RFC file, it must be
13
 * called by a name other than "ssh" or "Secure Shell".
14
 *
15
 *
16
 * Copyright (c) 2000 Markus Friedl.  All rights reserved.
17
 *
18
 * Redistribution and use in source and binary forms, with or without
19
 * modification, are permitted provided that the following conditions
20
 * are met:
21
 * 1. Redistributions of source code must retain the above copyright
22
 *    notice, this list of conditions and the following disclaimer.
23
 * 2. Redistributions in binary form must reproduce the above copyright
24
 *    notice, this list of conditions and the following disclaimer in the
25
 *    documentation and/or other materials provided with the distribution.
26
 *
27
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
 */
38
39
#include "includes.h"
1.13.1 by Colin Watson
Import upstream version 4.6p1
40
41
#include <sys/types.h>
42
#include <sys/stat.h>
43
#include <sys/param.h>
44
#include <sys/uio.h>
1 by Noah Meyerhans
Import upstream version 3.8.1p1
45
46
#include <openssl/err.h>
47
#include <openssl/evp.h>
48
#include <openssl/pem.h>
49
1.13.1 by Colin Watson
Import upstream version 4.6p1
50
#include <errno.h>
51
#include <fcntl.h>
52
#include <stdarg.h>
53
#include <stdio.h>
54
#include <stdlib.h>
55
#include <string.h>
56
#include <unistd.h>
57
58
#include "xmalloc.h"
1 by Noah Meyerhans
Import upstream version 3.8.1p1
59
#include "cipher.h"
60
#include "buffer.h"
61
#include "key.h"
62
#include "ssh.h"
63
#include "log.h"
64
#include "authfile.h"
65
#include "rsa.h"
1.1.2 by Colin Watson
Import upstream version 4.1p1
66
#include "misc.h"
1.1.3 by Colin Watson
Import upstream version 4.2p1
67
#include "atomicio.h"
35 by Colin Watson
* Resynchronise with Debian. Remaining changes:
68
#include "pathnames.h"
1 by Noah Meyerhans
Import upstream version 3.8.1p1
69
70
/* Version identification string for SSH v1 identity files. */
71
static const char authfile_id_string[] =
72
    "SSH PRIVATE KEY FILE FORMAT 1.1\n";
73
74
/*
75
 * Saves the authentication (private) key in a file, encrypting it with
76
 * passphrase.  The identification of the file (lowest 64 bits of n) will
77
 * precede the key to provide identification of the key without needing a
78
 * passphrase.
79
 */
80
81
static int
82
key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
83
    const char *comment)
84
{
85
	Buffer buffer, encrypted;
86
	u_char buf[100], *cp;
87
	int fd, i, cipher_num;
88
	CipherContext ciphercontext;
89
	Cipher *cipher;
1.1.1 by Colin Watson
Import upstream version 3.9p1
90
	u_int32_t rnd;
1 by Noah Meyerhans
Import upstream version 3.8.1p1
91
92
	/*
93
	 * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
94
	 * to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
95
	 */
96
	cipher_num = (strcmp(passphrase, "") == 0) ?
97
	    SSH_CIPHER_NONE : SSH_AUTHFILE_CIPHER;
98
	if ((cipher = cipher_by_number(cipher_num)) == NULL)
99
		fatal("save_private_key_rsa: bad cipher");
100
101
	/* This buffer is used to built the secret part of the private key. */
102
	buffer_init(&buffer);
103
104
	/* Put checkbytes for checking passphrase validity. */
1.1.1 by Colin Watson
Import upstream version 3.9p1
105
	rnd = arc4random();
106
	buf[0] = rnd & 0xff;
107
	buf[1] = (rnd >> 8) & 0xff;
1 by Noah Meyerhans
Import upstream version 3.8.1p1
108
	buf[2] = buf[0];
109
	buf[3] = buf[1];
110
	buffer_append(&buffer, buf, 4);
111
112
	/*
113
	 * Store the private key (n and e will not be stored because they
114
	 * will be stored in plain text, and storing them also in encrypted
115
	 * format would just give known plaintext).
116
	 */
117
	buffer_put_bignum(&buffer, key->rsa->d);
118
	buffer_put_bignum(&buffer, key->rsa->iqmp);
119
	buffer_put_bignum(&buffer, key->rsa->q);	/* reverse from SSL p */
120
	buffer_put_bignum(&buffer, key->rsa->p);	/* reverse from SSL q */
121
122
	/* Pad the part to be encrypted until its size is a multiple of 8. */
123
	while (buffer_len(&buffer) % 8 != 0)
124
		buffer_put_char(&buffer, 0);
125
126
	/* This buffer will be used to contain the data in the file. */
127
	buffer_init(&encrypted);
128
129
	/* First store keyfile id string. */
130
	for (i = 0; authfile_id_string[i]; i++)
131
		buffer_put_char(&encrypted, authfile_id_string[i]);
132
	buffer_put_char(&encrypted, 0);
133
134
	/* Store cipher type. */
135
	buffer_put_char(&encrypted, cipher_num);
136
	buffer_put_int(&encrypted, 0);	/* For future extension */
137
138
	/* Store public key.  This will be in plain text. */
139
	buffer_put_int(&encrypted, BN_num_bits(key->rsa->n));
140
	buffer_put_bignum(&encrypted, key->rsa->n);
141
	buffer_put_bignum(&encrypted, key->rsa->e);
142
	buffer_put_cstring(&encrypted, comment);
143
144
	/* Allocate space for the private part of the key in the buffer. */
145
	cp = buffer_append_space(&encrypted, buffer_len(&buffer));
146
147
	cipher_set_key_string(&ciphercontext, cipher, passphrase,
148
	    CIPHER_ENCRYPT);
149
	cipher_crypt(&ciphercontext, cp,
150
	    buffer_ptr(&buffer), buffer_len(&buffer));
151
	cipher_cleanup(&ciphercontext);
152
	memset(&ciphercontext, 0, sizeof(ciphercontext));
153
154
	/* Destroy temporary data. */
155
	memset(buf, 0, sizeof(buf));
156
	buffer_free(&buffer);
157
158
	fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
159
	if (fd < 0) {
160
		error("open %s failed: %s.", filename, strerror(errno));
161
		buffer_free(&encrypted);
162
		return 0;
163
	}
1.1.3 by Colin Watson
Import upstream version 4.2p1
164
	if (atomicio(vwrite, fd, buffer_ptr(&encrypted),
165
	    buffer_len(&encrypted)) != buffer_len(&encrypted)) {
1 by Noah Meyerhans
Import upstream version 3.8.1p1
166
		error("write to key file %s failed: %s", filename,
167
		    strerror(errno));
168
		buffer_free(&encrypted);
169
		close(fd);
170
		unlink(filename);
171
		return 0;
172
	}
173
	close(fd);
174
	buffer_free(&encrypted);
175
	return 1;
176
}
177
178
/* save SSH v2 key in OpenSSL PEM format */
179
static int
180
key_save_private_pem(Key *key, const char *filename, const char *_passphrase,
181
    const char *comment)
182
{
183
	FILE *fp;
184
	int fd;
185
	int success = 0;
186
	int len = strlen(_passphrase);
187
	u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
188
	const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
189
190
	if (len > 0 && len <= 4) {
191
		error("passphrase too short: have %d bytes, need > 4", len);
192
		return 0;
193
	}
194
	fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
195
	if (fd < 0) {
196
		error("open %s failed: %s.", filename, strerror(errno));
197
		return 0;
198
	}
199
	fp = fdopen(fd, "w");
1.13.1 by Colin Watson
Import upstream version 4.6p1
200
	if (fp == NULL) {
1 by Noah Meyerhans
Import upstream version 3.8.1p1
201
		error("fdopen %s failed: %s.", filename, strerror(errno));
202
		close(fd);
203
		return 0;
204
	}
205
	switch (key->type) {
206
	case KEY_DSA:
207
		success = PEM_write_DSAPrivateKey(fp, key->dsa,
208
		    cipher, passphrase, len, NULL, NULL);
209
		break;
210
	case KEY_RSA:
211
		success = PEM_write_RSAPrivateKey(fp, key->rsa,
212
		    cipher, passphrase, len, NULL, NULL);
213
		break;
214
	}
215
	fclose(fp);
216
	return success;
217
}
218
219
int
220
key_save_private(Key *key, const char *filename, const char *passphrase,
221
    const char *comment)
222
{
223
	switch (key->type) {
224
	case KEY_RSA1:
225
		return key_save_private_rsa1(key, filename, passphrase,
226
		    comment);
227
	case KEY_DSA:
228
	case KEY_RSA:
229
		return key_save_private_pem(key, filename, passphrase,
230
		    comment);
231
	default:
232
		break;
233
	}
234
	error("key_save_private: cannot save key type %d", key->type);
235
	return 0;
236
}
237
238
/*
239
 * Loads the public part of the ssh v1 key file.  Returns NULL if an error was
240
 * encountered (the file does not exist or is not readable), and the key
241
 * otherwise.
242
 */
243
244
static Key *
245
key_load_public_rsa1(int fd, const char *filename, char **commentp)
246
{
247
	Buffer buffer;
248
	Key *pub;
249
	struct stat st;
250
	char *cp;
1.1.3 by Colin Watson
Import upstream version 4.2p1
251
	u_int i;
1.1.1 by Colin Watson
Import upstream version 3.9p1
252
	size_t len;
1 by Noah Meyerhans
Import upstream version 3.8.1p1
253
254
	if (fstat(fd, &st) < 0) {
255
		error("fstat for key file %.200s failed: %.100s",
256
		    filename, strerror(errno));
257
		return NULL;
258
	}
1.1.2 by Colin Watson
Import upstream version 4.1p1
259
	if (st.st_size > 1*1024*1024) {
260
		error("key file %.200s too large", filename);
261
		return NULL;
262
	}
1.1.1 by Colin Watson
Import upstream version 3.9p1
263
	len = (size_t)st.st_size;		/* truncated */
1 by Noah Meyerhans
Import upstream version 3.8.1p1
264
265
	buffer_init(&buffer);
266
	cp = buffer_append_space(&buffer, len);
267
1.1.3 by Colin Watson
Import upstream version 4.2p1
268
	if (atomicio(read, fd, cp, len) != len) {
1 by Noah Meyerhans
Import upstream version 3.8.1p1
269
		debug("Read from key file %.200s failed: %.100s", filename,
270
		    strerror(errno));
271
		buffer_free(&buffer);
272
		return NULL;
273
	}
274
275
	/* Check that it is at least big enough to contain the ID string. */
276
	if (len < sizeof(authfile_id_string)) {
277
		debug3("Not a RSA1 key file %.200s.", filename);
278
		buffer_free(&buffer);
279
		return NULL;
280
	}
281
	/*
282
	 * Make sure it begins with the id string.  Consume the id string
283
	 * from the buffer.
284
	 */
285
	for (i = 0; i < sizeof(authfile_id_string); i++)
286
		if (buffer_get_char(&buffer) != authfile_id_string[i]) {
287
			debug3("Not a RSA1 key file %.200s.", filename);
288
			buffer_free(&buffer);
289
			return NULL;
290
		}
291
	/* Skip cipher type and reserved data. */
292
	(void) buffer_get_char(&buffer);	/* cipher type */
293
	(void) buffer_get_int(&buffer);		/* reserved */
294
295
	/* Read the public key from the buffer. */
296
	(void) buffer_get_int(&buffer);
297
	pub = key_new(KEY_RSA1);
298
	buffer_get_bignum(&buffer, pub->rsa->n);
299
	buffer_get_bignum(&buffer, pub->rsa->e);
300
	if (commentp)
301
		*commentp = buffer_get_string(&buffer, NULL);
302
	/* The encrypted private part is not parsed by this function. */
303
304
	buffer_free(&buffer);
305
	return pub;
306
}
307
308
/* load public key from private-key file, works only for SSH v1 */
309
Key *
310
key_load_public_type(int type, const char *filename, char **commentp)
311
{
312
	Key *pub;
313
	int fd;
314
315
	if (type == KEY_RSA1) {
316
		fd = open(filename, O_RDONLY);
317
		if (fd < 0)
318
			return NULL;
319
		pub = key_load_public_rsa1(fd, filename, commentp);
320
		close(fd);
321
		return pub;
322
	}
323
	return NULL;
324
}
325
326
/*
327
 * Loads the private key from the file.  Returns 0 if an error is encountered
328
 * (file does not exist or is not readable, or passphrase is bad). This
329
 * initializes the private key.
330
 * Assumes we are called under uid of the owner of the file.
331
 */
332
333
static Key *
334
key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
335
    char **commentp)
336
{
1.1.3 by Colin Watson
Import upstream version 4.2p1
337
	u_int i;
338
	int check1, check2, cipher_type;
1.1.1 by Colin Watson
Import upstream version 3.9p1
339
	size_t len;
1 by Noah Meyerhans
Import upstream version 3.8.1p1
340
	Buffer buffer, decrypted;
341
	u_char *cp;
342
	CipherContext ciphercontext;
343
	Cipher *cipher;
344
	Key *prv = NULL;
345
	struct stat st;
346
347
	if (fstat(fd, &st) < 0) {
348
		error("fstat for key file %.200s failed: %.100s",
349
		    filename, strerror(errno));
350
		close(fd);
351
		return NULL;
352
	}
1.1.1 by Colin Watson
Import upstream version 3.9p1
353
	if (st.st_size > 1*1024*1024) {
1.1.2 by Colin Watson
Import upstream version 4.1p1
354
		error("key file %.200s too large", filename);
1.1.1 by Colin Watson
Import upstream version 3.9p1
355
		close(fd);
356
		return (NULL);
357
	}
358
	len = (size_t)st.st_size;		/* truncated */
1 by Noah Meyerhans
Import upstream version 3.8.1p1
359
360
	buffer_init(&buffer);
361
	cp = buffer_append_space(&buffer, len);
362
1.1.3 by Colin Watson
Import upstream version 4.2p1
363
	if (atomicio(read, fd, cp, len) != len) {
1 by Noah Meyerhans
Import upstream version 3.8.1p1
364
		debug("Read from key file %.200s failed: %.100s", filename,
365
		    strerror(errno));
366
		buffer_free(&buffer);
367
		close(fd);
368
		return NULL;
369
	}
370
371
	/* Check that it is at least big enough to contain the ID string. */
372
	if (len < sizeof(authfile_id_string)) {
373
		debug3("Not a RSA1 key file %.200s.", filename);
374
		buffer_free(&buffer);
375
		close(fd);
376
		return NULL;
377
	}
378
	/*
379
	 * Make sure it begins with the id string.  Consume the id string
380
	 * from the buffer.
381
	 */
382
	for (i = 0; i < sizeof(authfile_id_string); i++)
383
		if (buffer_get_char(&buffer) != authfile_id_string[i]) {
384
			debug3("Not a RSA1 key file %.200s.", filename);
385
			buffer_free(&buffer);
386
			close(fd);
387
			return NULL;
388
		}
389
390
	/* Read cipher type. */
391
	cipher_type = buffer_get_char(&buffer);
392
	(void) buffer_get_int(&buffer);	/* Reserved data. */
393
394
	/* Read the public key from the buffer. */
395
	(void) buffer_get_int(&buffer);
396
	prv = key_new_private(KEY_RSA1);
397
398
	buffer_get_bignum(&buffer, prv->rsa->n);
399
	buffer_get_bignum(&buffer, prv->rsa->e);
400
	if (commentp)
401
		*commentp = buffer_get_string(&buffer, NULL);
402
	else
403
		xfree(buffer_get_string(&buffer, NULL));
404
405
	/* Check that it is a supported cipher. */
406
	cipher = cipher_by_number(cipher_type);
407
	if (cipher == NULL) {
408
		debug("Unsupported cipher %d used in key file %.200s.",
409
		    cipher_type, filename);
410
		buffer_free(&buffer);
411
		goto fail;
412
	}
413
	/* Initialize space for decrypted data. */
414
	buffer_init(&decrypted);
415
	cp = buffer_append_space(&decrypted, buffer_len(&buffer));
416
417
	/* Rest of the buffer is encrypted.  Decrypt it using the passphrase. */
418
	cipher_set_key_string(&ciphercontext, cipher, passphrase,
419
	    CIPHER_DECRYPT);
420
	cipher_crypt(&ciphercontext, cp,
421
	    buffer_ptr(&buffer), buffer_len(&buffer));
422
	cipher_cleanup(&ciphercontext);
423
	memset(&ciphercontext, 0, sizeof(ciphercontext));
424
	buffer_free(&buffer);
425
426
	check1 = buffer_get_char(&decrypted);
427
	check2 = buffer_get_char(&decrypted);
428
	if (check1 != buffer_get_char(&decrypted) ||
429
	    check2 != buffer_get_char(&decrypted)) {
430
		if (strcmp(passphrase, "") != 0)
431
			debug("Bad passphrase supplied for key file %.200s.",
432
			    filename);
433
		/* Bad passphrase. */
434
		buffer_free(&decrypted);
435
		goto fail;
436
	}
437
	/* Read the rest of the private key. */
438
	buffer_get_bignum(&decrypted, prv->rsa->d);
439
	buffer_get_bignum(&decrypted, prv->rsa->iqmp);		/* u */
440
	/* in SSL and SSH v1 p and q are exchanged */
441
	buffer_get_bignum(&decrypted, prv->rsa->q);		/* p */
442
	buffer_get_bignum(&decrypted, prv->rsa->p);		/* q */
443
444
	/* calculate p-1 and q-1 */
445
	rsa_generate_additional_parameters(prv->rsa);
446
447
	buffer_free(&decrypted);
448
449
	/* enable blinding */
450
	if (RSA_blinding_on(prv->rsa, NULL) != 1) {
451
		error("key_load_private_rsa1: RSA_blinding_on failed");
452
		goto fail;
453
	}
454
	close(fd);
455
	return prv;
456
457
fail:
458
	if (commentp)
459
		xfree(*commentp);
460
	close(fd);
461
	key_free(prv);
462
	return NULL;
463
}
464
465
Key *
466
key_load_private_pem(int fd, int type, const char *passphrase,
467
    char **commentp)
468
{
469
	FILE *fp;
470
	EVP_PKEY *pk = NULL;
471
	Key *prv = NULL;
472
	char *name = "<no key>";
473
474
	fp = fdopen(fd, "r");
475
	if (fp == NULL) {
476
		error("fdopen failed: %s", strerror(errno));
477
		close(fd);
478
		return NULL;
479
	}
480
	pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase);
481
	if (pk == NULL) {
482
		debug("PEM_read_PrivateKey failed");
483
		(void)ERR_get_error();
484
	} else if (pk->type == EVP_PKEY_RSA &&
485
	    (type == KEY_UNSPEC||type==KEY_RSA)) {
486
		prv = key_new(KEY_UNSPEC);
487
		prv->rsa = EVP_PKEY_get1_RSA(pk);
488
		prv->type = KEY_RSA;
489
		name = "rsa w/o comment";
490
#ifdef DEBUG_PK
491
		RSA_print_fp(stderr, prv->rsa, 8);
492
#endif
493
		if (RSA_blinding_on(prv->rsa, NULL) != 1) {
494
			error("key_load_private_pem: RSA_blinding_on failed");
495
			key_free(prv);
496
			prv = NULL;
497
		}
498
	} else if (pk->type == EVP_PKEY_DSA &&
499
	    (type == KEY_UNSPEC||type==KEY_DSA)) {
500
		prv = key_new(KEY_UNSPEC);
501
		prv->dsa = EVP_PKEY_get1_DSA(pk);
502
		prv->type = KEY_DSA;
503
		name = "dsa w/o comment";
504
#ifdef DEBUG_PK
505
		DSA_print_fp(stderr, prv->dsa, 8);
506
#endif
507
	} else {
508
		error("PEM_read_PrivateKey: mismatch or "
509
		    "unknown EVP_PKEY save_type %d", pk->save_type);
510
	}
511
	fclose(fp);
512
	if (pk != NULL)
513
		EVP_PKEY_free(pk);
514
	if (prv != NULL && commentp)
515
		*commentp = xstrdup(name);
516
	debug("read PEM private key done: type %s",
517
	    prv ? key_type(prv) : "<unknown>");
518
	return prv;
519
}
520
1.13.1 by Colin Watson
Import upstream version 4.6p1
521
int
1 by Noah Meyerhans
Import upstream version 3.8.1p1
522
key_perm_ok(int fd, const char *filename)
523
{
524
	struct stat st;
525
526
	if (fstat(fd, &st) < 0)
527
		return 0;
528
	/*
529
	 * if a key owned by the user is accessed, then we check the
530
	 * permissions of the file. if the key owned by a different user,
531
	 * then we don't care.
532
	 */
533
#ifdef HAVE_CYGWIN
534
	if (check_ntsec(filename))
535
#endif
536
	if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
537
		error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
538
		error("@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @");
539
		error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
540
		error("Permissions 0%3.3o for '%s' are too open.",
541
		    (u_int)st.st_mode & 0777, filename);
542
		error("It is recommended that your private key files are NOT accessible by others.");
543
		error("This private key will be ignored.");
544
		return 0;
545
	}
546
	return 1;
547
}
548
549
Key *
550
key_load_private_type(int type, const char *filename, const char *passphrase,
1.13.1 by Colin Watson
Import upstream version 4.6p1
551
    char **commentp, int *perm_ok)
1 by Noah Meyerhans
Import upstream version 3.8.1p1
552
{
553
	int fd;
554
555
	fd = open(filename, O_RDONLY);
556
	if (fd < 0)
557
		return NULL;
558
	if (!key_perm_ok(fd, filename)) {
1.13.1 by Colin Watson
Import upstream version 4.6p1
559
		if (perm_ok != NULL)
560
			*perm_ok = 0;
1 by Noah Meyerhans
Import upstream version 3.8.1p1
561
		error("bad permissions: ignore key: %s", filename);
562
		close(fd);
563
		return NULL;
564
	}
1.13.1 by Colin Watson
Import upstream version 4.6p1
565
	if (perm_ok != NULL)
566
		*perm_ok = 1;
1 by Noah Meyerhans
Import upstream version 3.8.1p1
567
	switch (type) {
568
	case KEY_RSA1:
569
		return key_load_private_rsa1(fd, filename, passphrase,
570
		    commentp);
571
		/* closes fd */
572
	case KEY_DSA:
573
	case KEY_RSA:
574
	case KEY_UNSPEC:
575
		return key_load_private_pem(fd, type, passphrase, commentp);
576
		/* closes fd */
577
	default:
578
		close(fd);
579
		break;
580
	}
581
	return NULL;
582
}
583
584
Key *
585
key_load_private(const char *filename, const char *passphrase,
586
    char **commentp)
587
{
588
	Key *pub, *prv;
589
	int fd;
590
591
	fd = open(filename, O_RDONLY);
592
	if (fd < 0)
593
		return NULL;
594
	if (!key_perm_ok(fd, filename)) {
595
		error("bad permissions: ignore key: %s", filename);
596
		close(fd);
597
		return NULL;
598
	}
599
	pub = key_load_public_rsa1(fd, filename, commentp);
600
	lseek(fd, (off_t) 0, SEEK_SET);		/* rewind */
601
	if (pub == NULL) {
602
		/* closes fd */
603
		prv = key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL);
604
		/* use the filename as a comment for PEM */
605
		if (commentp && prv)
606
			*commentp = xstrdup(filename);
607
	} else {
608
		/* it's a SSH v1 key if the public key part is readable */
609
		key_free(pub);
610
		/* closes fd */
611
		prv = key_load_private_rsa1(fd, filename, passphrase, NULL);
612
	}
613
	return prv;
614
}
615
616
static int
617
key_try_load_public(Key *k, const char *filename, char **commentp)
618
{
619
	FILE *f;
1.1.2 by Colin Watson
Import upstream version 4.1p1
620
	char line[SSH_MAX_PUBKEY_BYTES];
1 by Noah Meyerhans
Import upstream version 3.8.1p1
621
	char *cp;
1.1.2 by Colin Watson
Import upstream version 4.1p1
622
	u_long linenum = 0;
1 by Noah Meyerhans
Import upstream version 3.8.1p1
623
624
	f = fopen(filename, "r");
625
	if (f != NULL) {
1.1.2 by Colin Watson
Import upstream version 4.1p1
626
		while (read_keyfile_line(f, filename, line, sizeof(line),
627
			    &linenum) != -1) {
1 by Noah Meyerhans
Import upstream version 3.8.1p1
628
			cp = line;
629
			switch (*cp) {
630
			case '#':
631
			case '\n':
632
			case '\0':
633
				continue;
634
			}
635
			/* Skip leading whitespace. */
636
			for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
637
				;
638
			if (*cp) {
639
				if (key_read(k, &cp) == 1) {
640
					if (commentp)
641
						*commentp=xstrdup(filename);
642
					fclose(f);
643
					return 1;
644
				}
645
			}
646
		}
647
		fclose(f);
648
	}
649
	return 0;
650
}
651
652
/* load public key from ssh v1 private or any pubkey file */
653
Key *
654
key_load_public(const char *filename, char **commentp)
655
{
656
	Key *pub;
657
	char file[MAXPATHLEN];
658
659
	/* try rsa1 private key */
660
	pub = key_load_public_type(KEY_RSA1, filename, commentp);
661
	if (pub != NULL)
662
		return pub;
663
664
	/* try rsa1 public key */
665
	pub = key_new(KEY_RSA1);
666
	if (key_try_load_public(pub, filename, commentp) == 1)
667
		return pub;
668
	key_free(pub);
669
670
	/* try ssh2 public key */
671
	pub = key_new(KEY_UNSPEC);
672
	if (key_try_load_public(pub, filename, commentp) == 1)
673
		return pub;
674
	if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
675
	    (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
676
	    (key_try_load_public(pub, file, commentp) == 1))
677
		return pub;
678
	key_free(pub);
679
	return NULL;
680
}
35 by Colin Watson
* Resynchronise with Debian. Remaining changes:
681
37 by Colin Watson
* Resynchronise with Debian. Remaining changes:
682
/* Scan a blacklist of known-vulnerable keys in blacklist_file. */
683
static int
684
blacklisted_key_in_file(const Key *key, const char *blacklist_file, char **fp)
685
{
35 by Colin Watson
* Resynchronise with Debian. Remaining changes:
686
	int fd = -1;
687
	char *dgst_hex = NULL;
688
	char *dgst_packed = NULL, *p;
689
	int i;
690
	size_t line_len;
691
	struct stat st;
692
	char buf[256];
693
	off_t start, lower, upper;
694
	int ret = 0;
695
696
	debug("Checking blacklist file %s", blacklist_file);
697
	fd = open(blacklist_file, O_RDONLY);
37 by Colin Watson
* Resynchronise with Debian. Remaining changes:
698
	if (fd < 0) {
699
		ret = -1;
35 by Colin Watson
* Resynchronise with Debian. Remaining changes:
700
		goto out;
37 by Colin Watson
* Resynchronise with Debian. Remaining changes:
701
	}
35 by Colin Watson
* Resynchronise with Debian. Remaining changes:
702
703
	dgst_hex = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
704
	/* Remove all colons */
705
	dgst_packed = xcalloc(1, strlen(dgst_hex) + 1);
706
	for (i = 0, p = dgst_packed; dgst_hex[i]; i++)
707
		if (dgst_hex[i] != ':')
708
			*p++ = dgst_hex[i];
709
	/* Only compare least-significant 80 bits (to keep the blacklist
710
	 * size down)
711
	 */
712
	line_len = strlen(dgst_packed + 12);
713
	if (line_len > 32)
714
		goto out;
715
716
	/* Skip leading comments */
717
	start = 0;
718
	for (;;) {
719
		ssize_t r;
720
		char *newline;
721
37 by Colin Watson
* Resynchronise with Debian. Remaining changes:
722
		r = atomicio(read, fd, buf, sizeof(buf));
35 by Colin Watson
* Resynchronise with Debian. Remaining changes:
723
		if (r <= 0)
724
			goto out;
725
		if (buf[0] != '#')
726
			break;
727
37 by Colin Watson
* Resynchronise with Debian. Remaining changes:
728
		newline = memchr(buf, '\n', sizeof(buf));
35 by Colin Watson
* Resynchronise with Debian. Remaining changes:
729
		if (!newline)
730
			goto out;
731
		start += newline + 1 - buf;
732
		if (lseek(fd, start, SEEK_SET) < 0)
733
			goto out;
734
	}
735
736
	/* Initialise binary search record numbers */
737
	if (fstat(fd, &st) < 0)
738
		goto out;
739
	lower = 0;
740
	upper = (st.st_size - start) / (line_len + 1);
741
742
	while (lower != upper) {
743
		off_t cur;
744
		int cmp;
745
746
		cur = lower + (upper - lower) / 2;
747
748
		/* Read this line and compare to digest; this is
749
		 * overflow-safe since cur < max(off_t) / (line_len + 1) */
750
		if (lseek(fd, start + cur * (line_len + 1), SEEK_SET) < 0)
751
			break;
752
		if (atomicio(read, fd, buf, line_len) != line_len)
753
			break;
754
		cmp = memcmp(buf, dgst_packed + 12, line_len);
755
		if (cmp < 0) {
756
			if (cur == lower)
757
				break;
758
			lower = cur;
759
		} else if (cmp > 0) {
760
			if (cur == upper)
761
				break;
762
			upper = cur;
763
		} else {
764
			debug("Found %s in blacklist", dgst_hex);
765
			ret = 1;
766
			break;
767
		}
768
	}
769
770
out:
771
	if (dgst_packed)
772
		xfree(dgst_packed);
37 by Colin Watson
* Resynchronise with Debian. Remaining changes:
773
	if (ret != 1 && dgst_hex) {
35 by Colin Watson
* Resynchronise with Debian. Remaining changes:
774
		xfree(dgst_hex);
37 by Colin Watson
* Resynchronise with Debian. Remaining changes:
775
		dgst_hex = NULL;
776
	}
777
	if (fp)
778
		*fp = dgst_hex;
35 by Colin Watson
* Resynchronise with Debian. Remaining changes:
779
	if (fd >= 0)
780
		close(fd);
37 by Colin Watson
* Resynchronise with Debian. Remaining changes:
781
	return ret;
782
}
783
784
/*
785
 * Scan blacklists of known-vulnerable keys. If a vulnerable key is found,
786
 * its fingerprint is returned in *fp, unless fp is NULL.
787
 */
788
int
789
blacklisted_key(const Key *key, char **fp)
790
{
791
	Key *public;
792
	char *blacklist_file;
793
	int ret, ret2;
794
795
	public = key_demote(key);
796
	if (public->type == KEY_RSA1)
797
		public->type = KEY_RSA;
798
799
	xasprintf(&blacklist_file, "%s.%s-%u",
800
	    _PATH_BLACKLIST, key_type(public), key_size(public));
801
	ret = blacklisted_key_in_file(public, blacklist_file, fp);
802
	xfree(blacklist_file);
803
	if (ret > 0) {
804
		key_free(public);
805
		return ret;
806
	}
807
808
	xasprintf(&blacklist_file, "%s.%s-%u",
809
	    _PATH_BLACKLIST_CONFIG, key_type(public), key_size(public));
810
	ret2 = blacklisted_key_in_file(public, blacklist_file, fp);
811
	xfree(blacklist_file);
812
	if (ret2 > ret)
813
		ret = ret2;
814
815
	key_free(public);
35 by Colin Watson
* Resynchronise with Debian. Remaining changes:
816
	return ret;
817
}