authfile.c revision 323134
1/* $OpenBSD: authfile.c,v 1.122 2016/11/25 23:24:45 djm Exp $ */
2/*
3 * Copyright (c) 2000, 2013 Markus Friedl.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "includes.h"
27
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <sys/uio.h>
31
32#include <errno.h>
33#include <fcntl.h>
34#include <stdio.h>
35#include <stdarg.h>
36#include <stdlib.h>
37#include <string.h>
38#include <unistd.h>
39#include <limits.h>
40
41#include "cipher.h"
42#include "ssh.h"
43#include "log.h"
44#include "authfile.h"
45#include "rsa.h"
46#include "misc.h"
47#include "atomicio.h"
48#include "sshkey.h"
49#include "sshbuf.h"
50#include "ssherr.h"
51#include "krl.h"
52
53#define MAX_KEY_FILE_SIZE	(1024 * 1024)
54
55/* Save a key blob to a file */
56static int
57sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename)
58{
59	int fd, oerrno;
60
61	if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0)
62		return SSH_ERR_SYSTEM_ERROR;
63	if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(keybuf),
64	    sshbuf_len(keybuf)) != sshbuf_len(keybuf)) {
65		oerrno = errno;
66		close(fd);
67		unlink(filename);
68		errno = oerrno;
69		return SSH_ERR_SYSTEM_ERROR;
70	}
71	close(fd);
72	return 0;
73}
74
75int
76sshkey_save_private(struct sshkey *key, const char *filename,
77    const char *passphrase, const char *comment,
78    int force_new_format, const char *new_format_cipher, int new_format_rounds)
79{
80	struct sshbuf *keyblob = NULL;
81	int r;
82
83	if ((keyblob = sshbuf_new()) == NULL)
84		return SSH_ERR_ALLOC_FAIL;
85	if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment,
86	    force_new_format, new_format_cipher, new_format_rounds)) != 0)
87		goto out;
88	if ((r = sshkey_save_private_blob(keyblob, filename)) != 0)
89		goto out;
90	r = 0;
91 out:
92	sshbuf_free(keyblob);
93	return r;
94}
95
96/* Load a key from a fd into a buffer */
97int
98sshkey_load_file(int fd, struct sshbuf *blob)
99{
100	u_char buf[1024];
101	size_t len;
102	struct stat st;
103	int r, dontmax = 0;
104
105	if (fstat(fd, &st) < 0)
106		return SSH_ERR_SYSTEM_ERROR;
107	if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
108	    st.st_size > MAX_KEY_FILE_SIZE)
109		return SSH_ERR_INVALID_FORMAT;
110	/*
111	 * Pre-allocate the buffer used for the key contents and clamp its
112	 * maximum size. This ensures that key contents are never leaked via
113	 * implicit realloc() in the sshbuf code.
114	 */
115	if ((st.st_mode & S_IFREG) == 0 || st.st_size <= 0) {
116		st.st_size = 64*1024; /* 64k should be enough for anyone :) */
117		dontmax = 1;
118	}
119	if ((r = sshbuf_allocate(blob, st.st_size)) != 0 ||
120	    (dontmax && (r = sshbuf_set_max_size(blob, st.st_size)) != 0))
121		return r;
122	for (;;) {
123		if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
124			if (errno == EPIPE)
125				break;
126			r = SSH_ERR_SYSTEM_ERROR;
127			goto out;
128		}
129		if ((r = sshbuf_put(blob, buf, len)) != 0)
130			goto out;
131		if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) {
132			r = SSH_ERR_INVALID_FORMAT;
133			goto out;
134		}
135	}
136	if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
137	    st.st_size != (off_t)sshbuf_len(blob)) {
138		r = SSH_ERR_FILE_CHANGED;
139		goto out;
140	}
141	r = 0;
142
143 out:
144	explicit_bzero(buf, sizeof(buf));
145	if (r != 0)
146		sshbuf_reset(blob);
147	return r;
148}
149
150#ifdef WITH_SSH1
151/*
152 * Loads the public part of the ssh v1 key file.  Returns NULL if an error was
153 * encountered (the file does not exist or is not readable), and the key
154 * otherwise.
155 */
156static int
157sshkey_load_public_rsa1(int fd, struct sshkey **keyp, char **commentp)
158{
159	struct sshbuf *b = NULL;
160	int r;
161
162	if (keyp != NULL)
163		*keyp = NULL;
164	if (commentp != NULL)
165		*commentp = NULL;
166
167	if ((b = sshbuf_new()) == NULL)
168		return SSH_ERR_ALLOC_FAIL;
169	if ((r = sshkey_load_file(fd, b)) != 0)
170		goto out;
171	if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0)
172		goto out;
173	r = 0;
174 out:
175	sshbuf_free(b);
176	return r;
177}
178#endif /* WITH_SSH1 */
179
180/* XXX remove error() calls from here? */
181int
182sshkey_perm_ok(int fd, const char *filename)
183{
184	struct stat st;
185
186	if (fstat(fd, &st) < 0)
187		return SSH_ERR_SYSTEM_ERROR;
188	/*
189	 * if a key owned by the user is accessed, then we check the
190	 * permissions of the file. if the key owned by a different user,
191	 * then we don't care.
192	 */
193#ifdef HAVE_CYGWIN
194	if (check_ntsec(filename))
195#endif
196	if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
197		error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
198		error("@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @");
199		error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
200		error("Permissions 0%3.3o for '%s' are too open.",
201		    (u_int)st.st_mode & 0777, filename);
202		error("It is required that your private key files are NOT accessible by others.");
203		error("This private key will be ignored.");
204		return SSH_ERR_KEY_BAD_PERMISSIONS;
205	}
206	return 0;
207}
208
209/* XXX kill perm_ok now that we have SSH_ERR_KEY_BAD_PERMISSIONS? */
210int
211sshkey_load_private_type(int type, const char *filename, const char *passphrase,
212    struct sshkey **keyp, char **commentp, int *perm_ok)
213{
214	int fd, r;
215
216	if (keyp != NULL)
217		*keyp = NULL;
218	if (commentp != NULL)
219		*commentp = NULL;
220
221	if ((fd = open(filename, O_RDONLY)) < 0) {
222		if (perm_ok != NULL)
223			*perm_ok = 0;
224		return SSH_ERR_SYSTEM_ERROR;
225	}
226	if (sshkey_perm_ok(fd, filename) != 0) {
227		if (perm_ok != NULL)
228			*perm_ok = 0;
229		r = SSH_ERR_KEY_BAD_PERMISSIONS;
230		goto out;
231	}
232	if (perm_ok != NULL)
233		*perm_ok = 1;
234
235	r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp);
236 out:
237	close(fd);
238	return r;
239}
240
241int
242sshkey_load_private_type_fd(int fd, int type, const char *passphrase,
243    struct sshkey **keyp, char **commentp)
244{
245	struct sshbuf *buffer = NULL;
246	int r;
247
248	if (keyp != NULL)
249		*keyp = NULL;
250	if ((buffer = sshbuf_new()) == NULL) {
251		r = SSH_ERR_ALLOC_FAIL;
252		goto out;
253	}
254	if ((r = sshkey_load_file(fd, buffer)) != 0 ||
255	    (r = sshkey_parse_private_fileblob_type(buffer, type,
256	    passphrase, keyp, commentp)) != 0)
257		goto out;
258
259	/* success */
260	r = 0;
261 out:
262	sshbuf_free(buffer);
263	return r;
264}
265
266/* XXX this is almost identical to sshkey_load_private_type() */
267int
268sshkey_load_private(const char *filename, const char *passphrase,
269    struct sshkey **keyp, char **commentp)
270{
271	struct sshbuf *buffer = NULL;
272	int r, fd;
273
274	if (keyp != NULL)
275		*keyp = NULL;
276	if (commentp != NULL)
277		*commentp = NULL;
278
279	if ((fd = open(filename, O_RDONLY)) < 0)
280		return SSH_ERR_SYSTEM_ERROR;
281	if (sshkey_perm_ok(fd, filename) != 0) {
282		r = SSH_ERR_KEY_BAD_PERMISSIONS;
283		goto out;
284	}
285
286	if ((buffer = sshbuf_new()) == NULL) {
287		r = SSH_ERR_ALLOC_FAIL;
288		goto out;
289	}
290	if ((r = sshkey_load_file(fd, buffer)) != 0 ||
291	    (r = sshkey_parse_private_fileblob(buffer, passphrase, keyp,
292	    commentp)) != 0)
293		goto out;
294	r = 0;
295 out:
296	close(fd);
297	sshbuf_free(buffer);
298	return r;
299}
300
301static int
302sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp)
303{
304	FILE *f;
305	char line[SSH_MAX_PUBKEY_BYTES];
306	char *cp;
307	u_long linenum = 0;
308	int r;
309
310	if (commentp != NULL)
311		*commentp = NULL;
312	if ((f = fopen(filename, "r")) == NULL)
313		return SSH_ERR_SYSTEM_ERROR;
314	while (read_keyfile_line(f, filename, line, sizeof(line),
315		    &linenum) != -1) {
316		cp = line;
317		switch (*cp) {
318		case '#':
319		case '\n':
320		case '\0':
321			continue;
322		}
323		/* Abort loading if this looks like a private key */
324		if (strncmp(cp, "-----BEGIN", 10) == 0 ||
325		    strcmp(cp, "SSH PRIVATE KEY FILE") == 0)
326			break;
327		/* Skip leading whitespace. */
328		for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
329			;
330		if (*cp) {
331			if ((r = sshkey_read(k, &cp)) == 0) {
332				cp[strcspn(cp, "\r\n")] = '\0';
333				if (commentp) {
334					*commentp = strdup(*cp ?
335					    cp : filename);
336					if (*commentp == NULL)
337						r = SSH_ERR_ALLOC_FAIL;
338				}
339				fclose(f);
340				return r;
341			}
342		}
343	}
344	fclose(f);
345	return SSH_ERR_INVALID_FORMAT;
346}
347
348/* load public key from ssh v1 private or any pubkey file */
349int
350sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp)
351{
352	struct sshkey *pub = NULL;
353	char file[PATH_MAX];
354	int r, fd;
355
356	if (keyp != NULL)
357		*keyp = NULL;
358	if (commentp != NULL)
359		*commentp = NULL;
360
361	/* XXX should load file once and attempt to parse each format */
362
363	if ((fd = open(filename, O_RDONLY)) < 0)
364		goto skip;
365#ifdef WITH_SSH1
366	/* try rsa1 private key */
367	r = sshkey_load_public_rsa1(fd, keyp, commentp);
368	close(fd);
369	switch (r) {
370	case SSH_ERR_INTERNAL_ERROR:
371	case SSH_ERR_ALLOC_FAIL:
372	case SSH_ERR_INVALID_ARGUMENT:
373	case SSH_ERR_SYSTEM_ERROR:
374	case 0:
375		return r;
376	}
377#else /* WITH_SSH1 */
378	close(fd);
379#endif /* WITH_SSH1 */
380
381	/* try ssh2 public key */
382	if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
383		return SSH_ERR_ALLOC_FAIL;
384	if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
385		if (keyp != NULL)
386			*keyp = pub;
387		return 0;
388	}
389	sshkey_free(pub);
390
391#ifdef WITH_SSH1
392	/* try rsa1 public key */
393	if ((pub = sshkey_new(KEY_RSA1)) == NULL)
394		return SSH_ERR_ALLOC_FAIL;
395	if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
396		if (keyp != NULL)
397			*keyp = pub;
398		return 0;
399	}
400	sshkey_free(pub);
401#endif /* WITH_SSH1 */
402
403 skip:
404	/* try .pub suffix */
405	if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
406		return SSH_ERR_ALLOC_FAIL;
407	r = SSH_ERR_ALLOC_FAIL;	/* in case strlcpy or strlcat fail */
408	if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
409	    (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
410	    (r = sshkey_try_load_public(pub, file, commentp)) == 0) {
411		if (keyp != NULL)
412			*keyp = pub;
413		return 0;
414	}
415	sshkey_free(pub);
416
417	return r;
418}
419
420/* Load the certificate associated with the named private key */
421int
422sshkey_load_cert(const char *filename, struct sshkey **keyp)
423{
424	struct sshkey *pub = NULL;
425	char *file = NULL;
426	int r = SSH_ERR_INTERNAL_ERROR;
427
428	if (keyp != NULL)
429		*keyp = NULL;
430
431	if (asprintf(&file, "%s-cert.pub", filename) == -1)
432		return SSH_ERR_ALLOC_FAIL;
433
434	if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
435		goto out;
436	}
437	if ((r = sshkey_try_load_public(pub, file, NULL)) != 0)
438		goto out;
439	/* success */
440	if (keyp != NULL) {
441		*keyp = pub;
442		pub = NULL;
443	}
444	r = 0;
445 out:
446	free(file);
447	sshkey_free(pub);
448	return r;
449}
450
451/* Load private key and certificate */
452int
453sshkey_load_private_cert(int type, const char *filename, const char *passphrase,
454    struct sshkey **keyp, int *perm_ok)
455{
456	struct sshkey *key = NULL, *cert = NULL;
457	int r;
458
459	if (keyp != NULL)
460		*keyp = NULL;
461
462	switch (type) {
463#ifdef WITH_OPENSSL
464	case KEY_RSA:
465	case KEY_DSA:
466	case KEY_ECDSA:
467#endif /* WITH_OPENSSL */
468	case KEY_ED25519:
469	case KEY_UNSPEC:
470		break;
471	default:
472		return SSH_ERR_KEY_TYPE_UNKNOWN;
473	}
474
475	if ((r = sshkey_load_private_type(type, filename,
476	    passphrase, &key, NULL, perm_ok)) != 0 ||
477	    (r = sshkey_load_cert(filename, &cert)) != 0)
478		goto out;
479
480	/* Make sure the private key matches the certificate */
481	if (sshkey_equal_public(key, cert) == 0) {
482		r = SSH_ERR_KEY_CERT_MISMATCH;
483		goto out;
484	}
485
486	if ((r = sshkey_to_certified(key)) != 0 ||
487	    (r = sshkey_cert_copy(cert, key)) != 0)
488		goto out;
489	r = 0;
490	if (keyp != NULL) {
491		*keyp = key;
492		key = NULL;
493	}
494 out:
495	sshkey_free(key);
496	sshkey_free(cert);
497	return r;
498}
499
500/*
501 * Returns success if the specified "key" is listed in the file "filename",
502 * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error.
503 * If "strict_type" is set then the key type must match exactly,
504 * otherwise a comparison that ignores certficiate data is performed.
505 * If "check_ca" is set and "key" is a certificate, then its CA key is
506 * also checked and sshkey_in_file() will return success if either is found.
507 */
508int
509sshkey_in_file(struct sshkey *key, const char *filename, int strict_type,
510    int check_ca)
511{
512	FILE *f;
513	char line[SSH_MAX_PUBKEY_BYTES];
514	char *cp;
515	u_long linenum = 0;
516	int r = 0;
517	struct sshkey *pub = NULL;
518	int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) =
519	    strict_type ?  sshkey_equal : sshkey_equal_public;
520
521	if ((f = fopen(filename, "r")) == NULL)
522		return SSH_ERR_SYSTEM_ERROR;
523
524	while (read_keyfile_line(f, filename, line, sizeof(line),
525	    &linenum) != -1) {
526		cp = line;
527
528		/* Skip leading whitespace. */
529		for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
530			;
531
532		/* Skip comments and empty lines */
533		switch (*cp) {
534		case '#':
535		case '\n':
536		case '\0':
537			continue;
538		}
539
540		if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
541			r = SSH_ERR_ALLOC_FAIL;
542			goto out;
543		}
544		if ((r = sshkey_read(pub, &cp)) != 0)
545			goto out;
546		if (sshkey_compare(key, pub) ||
547		    (check_ca && sshkey_is_cert(key) &&
548		    sshkey_compare(key->cert->signature_key, pub))) {
549			r = 0;
550			goto out;
551		}
552		sshkey_free(pub);
553		pub = NULL;
554	}
555	r = SSH_ERR_KEY_NOT_FOUND;
556 out:
557	sshkey_free(pub);
558	fclose(f);
559	return r;
560}
561
562/*
563 * Checks whether the specified key is revoked, returning 0 if not,
564 * SSH_ERR_KEY_REVOKED if it is or another error code if something
565 * unexpected happened.
566 * This will check both the key and, if it is a certificate, its CA key too.
567 * "revoked_keys_file" may be a KRL or a one-per-line list of public keys.
568 */
569int
570sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file)
571{
572	int r;
573
574	r = ssh_krl_file_contains_key(revoked_keys_file, key);
575	/* If this was not a KRL to begin with then continue below */
576	if (r != SSH_ERR_KRL_BAD_MAGIC)
577		return r;
578
579	/*
580	 * If the file is not a KRL or we can't handle KRLs then attempt to
581	 * parse the file as a flat list of keys.
582	 */
583	switch ((r = sshkey_in_file(key, revoked_keys_file, 0, 1))) {
584	case 0:
585		/* Key found => revoked */
586		return SSH_ERR_KEY_REVOKED;
587	case SSH_ERR_KEY_NOT_FOUND:
588		/* Key not found => not revoked */
589		return 0;
590	default:
591		/* Some other error occurred */
592		return r;
593	}
594}
595
596