netinet{,6}: Assert in{,6}_inithead() are only used for system routing tables.
[dragonfly.git] / crypto / openssh / authfile.c
1 /* $OpenBSD: authfile.c,v 1.107 2014/06/24 01:13:21 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/param.h>
31 #include <sys/uio.h>
32
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <stdio.h>
36 #include <stdarg.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #include "cipher.h"
42 #include "key.h"
43 #include "ssh.h"
44 #include "log.h"
45 #include "authfile.h"
46 #include "rsa.h"
47 #include "misc.h"
48 #include "atomicio.h"
49 #include "sshbuf.h"
50 #include "ssherr.h"
51
52 #define MAX_KEY_FILE_SIZE       (1024 * 1024)
53
54 /* Save a key blob to a file */
55 static int
56 sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename)
57 {
58         int fd, oerrno;
59
60         if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0)
61                 return SSH_ERR_SYSTEM_ERROR;
62         if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(keybuf),
63             sshbuf_len(keybuf)) != sshbuf_len(keybuf)) {
64                 oerrno = errno;
65                 close(fd);
66                 unlink(filename);
67                 errno = oerrno;
68                 return SSH_ERR_SYSTEM_ERROR;
69         }
70         close(fd);
71         return 0;
72 }
73
74 int
75 sshkey_save_private(struct sshkey *key, const char *filename,
76     const char *passphrase, const char *comment,
77     int force_new_format, const char *new_format_cipher, int new_format_rounds)
78 {
79         struct sshbuf *keyblob = NULL;
80         int r;
81
82         if ((keyblob = sshbuf_new()) == NULL)
83                 return SSH_ERR_ALLOC_FAIL;
84         if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment,
85             force_new_format, new_format_cipher, new_format_rounds)) != 0)
86                 goto out;
87         if ((r = sshkey_save_private_blob(keyblob, filename)) != 0)
88                 goto out;
89         r = 0;
90  out:
91         sshbuf_free(keyblob);
92         return r;
93 }
94
95 /* Load a key from a fd into a buffer */
96 int
97 sshkey_load_file(int fd, const char *filename, struct sshbuf *blob)
98 {
99         u_char buf[1024];
100         size_t len;
101         struct stat st;
102         int r;
103
104         if (fstat(fd, &st) < 0)
105                 return SSH_ERR_SYSTEM_ERROR;
106         if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
107             st.st_size > MAX_KEY_FILE_SIZE)
108                 return SSH_ERR_INVALID_FORMAT;
109         for (;;) {
110                 if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
111                         if (errno == EPIPE)
112                                 break;
113                         r = SSH_ERR_SYSTEM_ERROR;
114                         goto out;
115                 }
116                 if ((r = sshbuf_put(blob, buf, len)) != 0)
117                         goto out;
118                 if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) {
119                         r = SSH_ERR_INVALID_FORMAT;
120                         goto out;
121                 }
122         }
123         if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
124             st.st_size != (off_t)sshbuf_len(blob)) {
125                 r = SSH_ERR_FILE_CHANGED;
126                 goto out;
127         }
128         r = 0;
129
130  out:
131         explicit_bzero(buf, sizeof(buf));
132         if (r != 0)
133                 sshbuf_reset(blob);
134         return r;
135 }
136
137 #ifdef WITH_SSH1
138 /*
139  * Loads the public part of the ssh v1 key file.  Returns NULL if an error was
140  * encountered (the file does not exist or is not readable), and the key
141  * otherwise.
142  */
143 static int
144 sshkey_load_public_rsa1(int fd, const char *filename,
145     struct sshkey **keyp, char **commentp)
146 {
147         struct sshbuf *b = NULL;
148         int r;
149
150         *keyp = NULL;
151         if (commentp != NULL)
152                 *commentp = NULL;
153
154         if ((b = sshbuf_new()) == NULL)
155                 return SSH_ERR_ALLOC_FAIL;
156         if ((r = sshkey_load_file(fd, filename, b)) != 0)
157                 goto out;
158         if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0)
159                 goto out;
160         r = 0;
161  out:
162         sshbuf_free(b);
163         return r;
164 }
165 #endif /* WITH_SSH1 */
166
167 #ifdef WITH_OPENSSL
168 /* XXX Deprecate? */
169 int
170 sshkey_load_private_pem(int fd, int type, const char *passphrase,
171     struct sshkey **keyp, char **commentp)
172 {
173         struct sshbuf *buffer = NULL;
174         int r;
175
176         *keyp = NULL;
177         if (commentp != NULL)
178                 *commentp = NULL;
179
180         if ((buffer = sshbuf_new()) == NULL)
181                 return SSH_ERR_ALLOC_FAIL;
182         if ((r = sshkey_load_file(fd, NULL, buffer)) != 0)
183                 goto out;
184         if ((r = sshkey_parse_private_pem_fileblob(buffer, type, passphrase,
185             keyp, commentp)) != 0)
186                 goto out;
187         r = 0;
188  out:
189         sshbuf_free(buffer);
190         return r;
191 }
192 #endif /* WITH_OPENSSL */
193
194 /* XXX remove error() calls from here? */
195 int
196 sshkey_perm_ok(int fd, const char *filename)
197 {
198         struct stat st;
199
200         if (fstat(fd, &st) < 0)
201                 return SSH_ERR_SYSTEM_ERROR;
202         /*
203          * if a key owned by the user is accessed, then we check the
204          * permissions of the file. if the key owned by a different user,
205          * then we don't care.
206          */
207 #ifdef HAVE_CYGWIN
208         if (check_ntsec(filename))
209 #endif
210         if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
211                 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
212                 error("@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @");
213                 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
214                 error("Permissions 0%3.3o for '%s' are too open.",
215                     (u_int)st.st_mode & 0777, filename);
216                 error("It is recommended that your private key files are NOT accessible by others.");
217                 error("This private key will be ignored.");
218                 return SSH_ERR_KEY_BAD_PERMISSIONS;
219         }
220         return 0;
221 }
222
223 /* XXX kill perm_ok now that we have SSH_ERR_KEY_BAD_PERMISSIONS? */
224 int
225 sshkey_load_private_type(int type, const char *filename, const char *passphrase,
226     struct sshkey **keyp, char **commentp, int *perm_ok)
227 {
228         int fd, r;
229         struct sshbuf *buffer = NULL;
230
231         *keyp = NULL;
232         if (commentp != NULL)
233                 *commentp = NULL;
234
235         if ((fd = open(filename, O_RDONLY)) < 0) {
236                 if (perm_ok != NULL)
237                         *perm_ok = 0;
238                 return SSH_ERR_SYSTEM_ERROR;
239         }
240         if (sshkey_perm_ok(fd, filename) != 0) {
241                 if (perm_ok != NULL)
242                         *perm_ok = 0;
243                 r = SSH_ERR_KEY_BAD_PERMISSIONS;
244                 goto out;
245         }
246         if (perm_ok != NULL)
247                 *perm_ok = 1;
248
249         if ((buffer = sshbuf_new()) == NULL) {
250                 r = SSH_ERR_ALLOC_FAIL;
251                 goto out;
252         }
253         if ((r = sshkey_load_file(fd, filename, buffer)) != 0)
254                 goto out;
255         if ((r = sshkey_parse_private_fileblob_type(buffer, type, passphrase,
256             keyp, commentp)) != 0)
257                 goto out;
258         r = 0;
259  out:
260         close(fd);
261         if (buffer != NULL)
262                 sshbuf_free(buffer);
263         return r;
264 }
265
266 /* XXX this is almost identical to sshkey_load_private_type() */
267 int
268 sshkey_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         *keyp = NULL;
275         if (commentp != NULL)
276                 *commentp = NULL;
277
278         if ((fd = open(filename, O_RDONLY)) < 0)
279                 return SSH_ERR_SYSTEM_ERROR;
280         if (sshkey_perm_ok(fd, filename) != 0) {
281                 r = SSH_ERR_KEY_BAD_PERMISSIONS;
282                 goto out;
283         }
284
285         if ((buffer = sshbuf_new()) == NULL) {
286                 r = SSH_ERR_ALLOC_FAIL;
287                 goto out;
288         }
289         if ((r = sshkey_load_file(fd, filename, buffer)) != 0 ||
290             (r = sshkey_parse_private_fileblob(buffer, passphrase, filename,
291             keyp, commentp)) != 0)
292                 goto out;
293         r = 0;
294  out:
295         close(fd);
296         if (buffer != NULL)
297                 sshbuf_free(buffer);
298         return r;
299 }
300
301 static int
302 sshkey_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 */
349 int
350 sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp)
351 {
352         struct sshkey *pub = NULL;
353         char file[MAXPATHLEN];
354         int r, fd;
355
356         if (keyp != NULL)
357                 *keyp = NULL;
358         if (commentp != NULL)
359                 *commentp = NULL;
360
361         if ((fd = open(filename, O_RDONLY)) < 0)
362                 goto skip;
363 #ifdef WITH_SSH1
364         /* try rsa1 private key */
365         r = sshkey_load_public_rsa1(fd, filename, keyp, commentp);
366         close(fd);
367         switch (r) {
368         case SSH_ERR_INTERNAL_ERROR:
369         case SSH_ERR_ALLOC_FAIL:
370         case SSH_ERR_INVALID_ARGUMENT:
371         case SSH_ERR_SYSTEM_ERROR:
372         case 0:
373                 return r;
374         }
375 #endif /* WITH_SSH1 */
376
377         /* try ssh2 public key */
378         if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
379                 return SSH_ERR_ALLOC_FAIL;
380         if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
381                 if (keyp != NULL)
382                         *keyp = pub;
383                 return 0;
384         }
385         sshkey_free(pub);
386
387 #ifdef WITH_SSH1
388         /* try rsa1 public key */
389         if ((pub = sshkey_new(KEY_RSA1)) == NULL)
390                 return SSH_ERR_ALLOC_FAIL;
391         if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
392                 if (keyp != NULL)
393                         *keyp = pub;
394                 return 0;
395         }
396         sshkey_free(pub);
397 #endif /* WITH_SSH1 */
398
399  skip:
400         /* try .pub suffix */
401         if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
402                 return SSH_ERR_ALLOC_FAIL;
403         r = SSH_ERR_ALLOC_FAIL; /* in case strlcpy or strlcat fail */
404         if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
405             (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
406             (r = sshkey_try_load_public(pub, file, commentp)) == 0) {
407                 if (keyp != NULL)
408                         *keyp = pub;
409                 return 0;
410         }
411         sshkey_free(pub);
412         return r;
413 }
414
415 /* Load the certificate associated with the named private key */
416 int
417 sshkey_load_cert(const char *filename, struct sshkey **keyp)
418 {
419         struct sshkey *pub = NULL;
420         char *file = NULL;
421         int r = SSH_ERR_INTERNAL_ERROR;
422
423         *keyp = NULL;
424
425         if (asprintf(&file, "%s-cert.pub", filename) == -1)
426                 return SSH_ERR_ALLOC_FAIL;
427
428         if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
429                 goto out;
430         }
431         if ((r = sshkey_try_load_public(pub, file, NULL)) != 0)
432                 goto out;
433
434         *keyp = pub;
435         pub = NULL;
436         r = 0;
437
438  out:
439         if (file != NULL)
440                 free(file);
441         if (pub != NULL)
442                 sshkey_free(pub);
443         return r;
444 }
445
446 /* Load private key and certificate */
447 int
448 sshkey_load_private_cert(int type, const char *filename, const char *passphrase,
449     struct sshkey **keyp, int *perm_ok)
450 {
451         struct sshkey *key = NULL, *cert = NULL;
452         int r;
453
454         *keyp = NULL;
455
456         switch (type) {
457 #ifdef WITH_OPENSSL
458         case KEY_RSA:
459         case KEY_DSA:
460         case KEY_ECDSA:
461         case KEY_ED25519:
462 #endif /* WITH_OPENSSL */
463         case KEY_UNSPEC:
464                 break;
465         default:
466                 return SSH_ERR_KEY_TYPE_UNKNOWN;
467         }
468
469         if ((r = sshkey_load_private_type(type, filename,
470             passphrase, &key, NULL, perm_ok)) != 0 ||
471             (r = sshkey_load_cert(filename, &cert)) != 0)
472                 goto out;
473
474         /* Make sure the private key matches the certificate */
475         if (sshkey_equal_public(key, cert) == 0) {
476                 r = SSH_ERR_KEY_CERT_MISMATCH;
477                 goto out;
478         }
479
480         if ((r = sshkey_to_certified(key, sshkey_cert_is_legacy(cert))) != 0 ||
481             (r = sshkey_cert_copy(cert, key)) != 0)
482                 goto out;
483         r = 0;
484         *keyp = key;
485         key = NULL;
486  out:
487         if (key != NULL)
488                 sshkey_free(key);
489         if (cert != NULL)
490                 sshkey_free(cert);
491         return r;
492 }
493
494 /*
495  * Returns success if the specified "key" is listed in the file "filename",
496  * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error.
497  * If strict_type is set then the key type must match exactly,
498  * otherwise a comparison that ignores certficiate data is performed.
499  */
500 int
501 sshkey_in_file(struct sshkey *key, const char *filename, int strict_type)
502 {
503         FILE *f;
504         char line[SSH_MAX_PUBKEY_BYTES];
505         char *cp;
506         u_long linenum = 0;
507         int r = 0;
508         struct sshkey *pub = NULL;
509         int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) =
510             strict_type ?  sshkey_equal : sshkey_equal_public;
511
512         if ((f = fopen(filename, "r")) == NULL) {
513                 if (errno == ENOENT)
514                         return SSH_ERR_KEY_NOT_FOUND;
515                 else
516                         return SSH_ERR_SYSTEM_ERROR;
517         }
518
519         while (read_keyfile_line(f, filename, line, sizeof(line),
520             &linenum) != -1) {
521                 cp = line;
522
523                 /* Skip leading whitespace. */
524                 for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
525                         ;
526
527                 /* Skip comments and empty lines */
528                 switch (*cp) {
529                 case '#':
530                 case '\n':
531                 case '\0':
532                         continue;
533                 }
534
535                 if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
536                         r = SSH_ERR_ALLOC_FAIL;
537                         goto out;
538                 }
539                 if ((r = sshkey_read(pub, &cp)) != 0)
540                         goto out;
541                 if (sshkey_compare(key, pub)) {
542                         r = 0;
543                         goto out;
544                 }
545                 sshkey_free(pub);
546                 pub = NULL;
547         }
548         r = SSH_ERR_KEY_NOT_FOUND;
549  out:
550         if (pub != NULL)
551                 sshkey_free(pub);
552         fclose(f);
553         return r;
554 }
555