route: ensure RTM_IFINFO is sent first when bring interface down/up
[dragonfly.git] / crypto / openssh / authfile.c
1 /* $OpenBSD: authfile.c,v 1.131 2018/09/21 12:20:12 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 "misc.h"
46 #include "atomicio.h"
47 #include "sshkey.h"
48 #include "sshbuf.h"
49 #include "ssherr.h"
50 #include "krl.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, sshbuf_mutable_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, 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
138 /* XXX remove error() calls from here? */
139 int
140 sshkey_perm_ok(int fd, const char *filename)
141 {
142         struct stat st;
143
144         if (fstat(fd, &st) < 0)
145                 return SSH_ERR_SYSTEM_ERROR;
146         /*
147          * if a key owned by the user is accessed, then we check the
148          * permissions of the file. if the key owned by a different user,
149          * then we don't care.
150          */
151 #ifdef HAVE_CYGWIN
152         if (check_ntsec(filename))
153 #endif
154         if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
155                 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
156                 error("@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @");
157                 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
158                 error("Permissions 0%3.3o for '%s' are too open.",
159                     (u_int)st.st_mode & 0777, filename);
160                 error("It is required that your private key files are NOT accessible by others.");
161                 error("This private key will be ignored.");
162                 return SSH_ERR_KEY_BAD_PERMISSIONS;
163         }
164         return 0;
165 }
166
167 /* XXX kill perm_ok now that we have SSH_ERR_KEY_BAD_PERMISSIONS? */
168 int
169 sshkey_load_private_type(int type, const char *filename, const char *passphrase,
170     struct sshkey **keyp, char **commentp, int *perm_ok)
171 {
172         int fd, r;
173
174         if (keyp != NULL)
175                 *keyp = NULL;
176         if (commentp != NULL)
177                 *commentp = NULL;
178
179         if ((fd = open(filename, O_RDONLY)) < 0) {
180                 if (perm_ok != NULL)
181                         *perm_ok = 0;
182                 return SSH_ERR_SYSTEM_ERROR;
183         }
184         if (sshkey_perm_ok(fd, filename) != 0) {
185                 if (perm_ok != NULL)
186                         *perm_ok = 0;
187                 r = SSH_ERR_KEY_BAD_PERMISSIONS;
188                 goto out;
189         }
190         if (perm_ok != NULL)
191                 *perm_ok = 1;
192
193         r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp);
194         if (r == 0 && keyp && *keyp)
195                 r = sshkey_set_filename(*keyp, filename);
196  out:
197         close(fd);
198         return r;
199 }
200
201 int
202 sshkey_load_private_type_fd(int fd, int type, const char *passphrase,
203     struct sshkey **keyp, char **commentp)
204 {
205         struct sshbuf *buffer = NULL;
206         int r;
207
208         if (keyp != NULL)
209                 *keyp = NULL;
210         if ((buffer = sshbuf_new()) == NULL) {
211                 r = SSH_ERR_ALLOC_FAIL;
212                 goto out;
213         }
214         if ((r = sshkey_load_file(fd, buffer)) != 0 ||
215             (r = sshkey_parse_private_fileblob_type(buffer, type,
216             passphrase, keyp, commentp)) != 0)
217                 goto out;
218
219         /* success */
220         r = 0;
221  out:
222         sshbuf_free(buffer);
223         return r;
224 }
225
226 /* XXX this is almost identical to sshkey_load_private_type() */
227 int
228 sshkey_load_private(const char *filename, const char *passphrase,
229     struct sshkey **keyp, char **commentp)
230 {
231         struct sshbuf *buffer = NULL;
232         int r, fd;
233
234         if (keyp != NULL)
235                 *keyp = NULL;
236         if (commentp != NULL)
237                 *commentp = NULL;
238
239         if ((fd = open(filename, O_RDONLY)) < 0)
240                 return SSH_ERR_SYSTEM_ERROR;
241         if (sshkey_perm_ok(fd, filename) != 0) {
242                 r = SSH_ERR_KEY_BAD_PERMISSIONS;
243                 goto out;
244         }
245
246         if ((buffer = sshbuf_new()) == NULL) {
247                 r = SSH_ERR_ALLOC_FAIL;
248                 goto out;
249         }
250         if ((r = sshkey_load_file(fd, buffer)) != 0 ||
251             (r = sshkey_parse_private_fileblob(buffer, passphrase, keyp,
252             commentp)) != 0)
253                 goto out;
254         if (keyp && *keyp &&
255             (r = sshkey_set_filename(*keyp, filename)) != 0)
256                 goto out;
257         r = 0;
258  out:
259         close(fd);
260         sshbuf_free(buffer);
261         return r;
262 }
263
264 static int
265 sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp)
266 {
267         FILE *f;
268         char *line = NULL, *cp;
269         size_t linesize = 0;
270         int r;
271
272         if (commentp != NULL)
273                 *commentp = NULL;
274         if ((f = fopen(filename, "r")) == NULL)
275                 return SSH_ERR_SYSTEM_ERROR;
276         while (getline(&line, &linesize, f) != -1) {
277                 cp = line;
278                 switch (*cp) {
279                 case '#':
280                 case '\n':
281                 case '\0':
282                         continue;
283                 }
284                 /* Abort loading if this looks like a private key */
285                 if (strncmp(cp, "-----BEGIN", 10) == 0 ||
286                     strcmp(cp, "SSH PRIVATE KEY FILE") == 0)
287                         break;
288                 /* Skip leading whitespace. */
289                 for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
290                         ;
291                 if (*cp) {
292                         if ((r = sshkey_read(k, &cp)) == 0) {
293                                 cp[strcspn(cp, "\r\n")] = '\0';
294                                 if (commentp) {
295                                         *commentp = strdup(*cp ?
296                                             cp : filename);
297                                         if (*commentp == NULL)
298                                                 r = SSH_ERR_ALLOC_FAIL;
299                                 }
300                                 free(line);
301                                 fclose(f);
302                                 return r;
303                         }
304                 }
305         }
306         free(line);
307         fclose(f);
308         return SSH_ERR_INVALID_FORMAT;
309 }
310
311 /* load public key from any pubkey file */
312 int
313 sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp)
314 {
315         struct sshkey *pub = NULL;
316         char *file = NULL;
317         int r;
318
319         if (keyp != NULL)
320                 *keyp = NULL;
321         if (commentp != NULL)
322                 *commentp = NULL;
323
324         if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
325                 return SSH_ERR_ALLOC_FAIL;
326         if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
327                 if (keyp != NULL) {
328                         *keyp = pub;
329                         pub = NULL;
330                 }
331                 r = 0;
332                 goto out;
333         }
334         sshkey_free(pub);
335
336         /* try .pub suffix */
337         if (asprintf(&file, "%s.pub", filename) == -1)
338                 return SSH_ERR_ALLOC_FAIL;
339         if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
340                 r = SSH_ERR_ALLOC_FAIL;
341                 goto out;
342         }
343         if ((r = sshkey_try_load_public(pub, file, commentp)) == 0) {
344                 if (keyp != NULL) {
345                         *keyp = pub;
346                         pub = NULL;
347                 }
348                 r = 0;
349         }
350  out:
351         free(file);
352         sshkey_free(pub);
353         return r;
354 }
355
356 /* Load the certificate associated with the named private key */
357 int
358 sshkey_load_cert(const char *filename, struct sshkey **keyp)
359 {
360         struct sshkey *pub = NULL;
361         char *file = NULL;
362         int r = SSH_ERR_INTERNAL_ERROR;
363
364         if (keyp != NULL)
365                 *keyp = NULL;
366
367         if (asprintf(&file, "%s-cert.pub", filename) == -1)
368                 return SSH_ERR_ALLOC_FAIL;
369
370         if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
371                 goto out;
372         }
373         if ((r = sshkey_try_load_public(pub, file, NULL)) != 0)
374                 goto out;
375         /* success */
376         if (keyp != NULL) {
377                 *keyp = pub;
378                 pub = NULL;
379         }
380         r = 0;
381  out:
382         free(file);
383         sshkey_free(pub);
384         return r;
385 }
386
387 /* Load private key and certificate */
388 int
389 sshkey_load_private_cert(int type, const char *filename, const char *passphrase,
390     struct sshkey **keyp, int *perm_ok)
391 {
392         struct sshkey *key = NULL, *cert = NULL;
393         int r;
394
395         if (keyp != NULL)
396                 *keyp = NULL;
397
398         switch (type) {
399 #ifdef WITH_OPENSSL
400         case KEY_RSA:
401         case KEY_DSA:
402         case KEY_ECDSA:
403 #endif /* WITH_OPENSSL */
404         case KEY_ED25519:
405         case KEY_XMSS:
406         case KEY_UNSPEC:
407                 break;
408         default:
409                 return SSH_ERR_KEY_TYPE_UNKNOWN;
410         }
411
412         if ((r = sshkey_load_private_type(type, filename,
413             passphrase, &key, NULL, perm_ok)) != 0 ||
414             (r = sshkey_load_cert(filename, &cert)) != 0)
415                 goto out;
416
417         /* Make sure the private key matches the certificate */
418         if (sshkey_equal_public(key, cert) == 0) {
419                 r = SSH_ERR_KEY_CERT_MISMATCH;
420                 goto out;
421         }
422
423         if ((r = sshkey_to_certified(key)) != 0 ||
424             (r = sshkey_cert_copy(cert, key)) != 0)
425                 goto out;
426         r = 0;
427         if (keyp != NULL) {
428                 *keyp = key;
429                 key = NULL;
430         }
431  out:
432         sshkey_free(key);
433         sshkey_free(cert);
434         return r;
435 }
436
437 /*
438  * Returns success if the specified "key" is listed in the file "filename",
439  * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error.
440  * If "strict_type" is set then the key type must match exactly,
441  * otherwise a comparison that ignores certficiate data is performed.
442  * If "check_ca" is set and "key" is a certificate, then its CA key is
443  * also checked and sshkey_in_file() will return success if either is found.
444  */
445 int
446 sshkey_in_file(struct sshkey *key, const char *filename, int strict_type,
447     int check_ca)
448 {
449         FILE *f;
450         char *line = NULL, *cp;
451         size_t linesize = 0;
452         int r = 0;
453         struct sshkey *pub = NULL;
454
455         int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) =
456             strict_type ?  sshkey_equal : sshkey_equal_public;
457
458         if ((f = fopen(filename, "r")) == NULL)
459                 return SSH_ERR_SYSTEM_ERROR;
460
461         while (getline(&line, &linesize, f) != -1) {
462                 sshkey_free(pub);
463                 pub = NULL;
464                 cp = line;
465
466                 /* Skip leading whitespace. */
467                 for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
468                         ;
469
470                 /* Skip comments and empty lines */
471                 switch (*cp) {
472                 case '#':
473                 case '\n':
474                 case '\0':
475                         continue;
476                 }
477
478                 if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
479                         r = SSH_ERR_ALLOC_FAIL;
480                         goto out;
481                 }
482                 switch (r = sshkey_read(pub, &cp)) {
483                 case 0:
484                         break;
485                 case SSH_ERR_KEY_LENGTH:
486                         continue;
487                 default:
488                         goto out;
489                 }
490                 if (sshkey_compare(key, pub) ||
491                     (check_ca && sshkey_is_cert(key) &&
492                     sshkey_compare(key->cert->signature_key, pub))) {
493                         r = 0;
494                         goto out;
495                 }
496         }
497         r = SSH_ERR_KEY_NOT_FOUND;
498  out:
499         free(line);
500         sshkey_free(pub);
501         fclose(f);
502         return r;
503 }
504
505 /*
506  * Checks whether the specified key is revoked, returning 0 if not,
507  * SSH_ERR_KEY_REVOKED if it is or another error code if something
508  * unexpected happened.
509  * This will check both the key and, if it is a certificate, its CA key too.
510  * "revoked_keys_file" may be a KRL or a one-per-line list of public keys.
511  */
512 int
513 sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file)
514 {
515         int r;
516
517         r = ssh_krl_file_contains_key(revoked_keys_file, key);
518         /* If this was not a KRL to begin with then continue below */
519         if (r != SSH_ERR_KRL_BAD_MAGIC)
520                 return r;
521
522         /*
523          * If the file is not a KRL or we can't handle KRLs then attempt to
524          * parse the file as a flat list of keys.
525          */
526         switch ((r = sshkey_in_file(key, revoked_keys_file, 0, 1))) {
527         case 0:
528                 /* Key found => revoked */
529                 return SSH_ERR_KEY_REVOKED;
530         case SSH_ERR_KEY_NOT_FOUND:
531                 /* Key not found => not revoked */
532                 return 0;
533         default:
534                 /* Some other error occurred */
535                 return r;
536         }
537 }
538