diff options
-rw-r--r-- | Makefile.in | 3 | ||||
-rw-r--r-- | authfile.c | 77 | ||||
-rw-r--r-- | authfile.h | 3 | ||||
-rw-r--r-- | krl.c | 16 | ||||
-rw-r--r-- | ssh-add.c | 6 | ||||
-rw-r--r-- | ssh-keygen.c | 48 | ||||
-rw-r--r-- | sshbuf-io.c | 118 | ||||
-rw-r--r-- | sshbuf-misc.c | 2 | ||||
-rw-r--r-- | sshbuf.h | 18 |
9 files changed, 163 insertions, 128 deletions
diff --git a/Makefile.in b/Makefile.in index 963f99fb5..e7549470c 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -109,7 +109,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ | |||
109 | kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ | 109 | kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ |
110 | kexgexc.o kexgexs.o \ | 110 | kexgexc.o kexgexs.o \ |
111 | sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \ | 111 | sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \ |
112 | sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o | 112 | sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ |
113 | sshbuf-io.o | ||
113 | 114 | ||
114 | SKOBJS= ssh-sk-client.o | 115 | SKOBJS= ssh-sk-client.o |
115 | 116 | ||
diff --git a/authfile.c b/authfile.c index bf22d63e8..20b66d9bd 100644 --- a/authfile.c +++ b/authfile.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfile.c,v 1.136 2020/01/02 22:38:33 djm Exp $ */ | 1 | /* $OpenBSD: authfile.c,v 1.137 2020/01/25 23:02:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -55,20 +55,13 @@ | |||
55 | static int | 55 | static int |
56 | sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename) | 56 | sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename) |
57 | { | 57 | { |
58 | int fd, oerrno; | 58 | int r; |
59 | mode_t omask; | ||
59 | 60 | ||
60 | if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) == -1) | 61 | omask = umask(077); |
61 | return SSH_ERR_SYSTEM_ERROR; | 62 | r = sshbuf_write_file(filename, keybuf); |
62 | if (atomicio(vwrite, fd, sshbuf_mutable_ptr(keybuf), | 63 | umask(omask); |
63 | sshbuf_len(keybuf)) != sshbuf_len(keybuf)) { | 64 | return r; |
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 | } | 65 | } |
73 | 66 | ||
74 | int | 67 | int |
@@ -92,49 +85,6 @@ sshkey_save_private(struct sshkey *key, const char *filename, | |||
92 | return r; | 85 | return r; |
93 | } | 86 | } |
94 | 87 | ||
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) == -1) | ||
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? */ | 88 | /* XXX remove error() calls from here? */ |
139 | int | 89 | int |
140 | sshkey_perm_ok(int fd, const char *filename) | 90 | sshkey_perm_ok(int fd, const char *filename) |
@@ -199,11 +149,7 @@ sshkey_load_private_type_fd(int fd, int type, const char *passphrase, | |||
199 | 149 | ||
200 | if (keyp != NULL) | 150 | if (keyp != NULL) |
201 | *keyp = NULL; | 151 | *keyp = NULL; |
202 | if ((buffer = sshbuf_new()) == NULL) { | 152 | if ((r = sshbuf_load_fd(fd, &buffer)) != 0 || |
203 | r = SSH_ERR_ALLOC_FAIL; | ||
204 | goto out; | ||
205 | } | ||
206 | if ((r = sshkey_load_file(fd, buffer)) != 0 || | ||
207 | (r = sshkey_parse_private_fileblob_type(buffer, type, | 153 | (r = sshkey_parse_private_fileblob_type(buffer, type, |
208 | passphrase, keyp, commentp)) != 0) | 154 | passphrase, keyp, commentp)) != 0) |
209 | goto out; | 155 | goto out; |
@@ -234,12 +180,7 @@ sshkey_load_private(const char *filename, const char *passphrase, | |||
234 | r = SSH_ERR_KEY_BAD_PERMISSIONS; | 180 | r = SSH_ERR_KEY_BAD_PERMISSIONS; |
235 | goto out; | 181 | goto out; |
236 | } | 182 | } |
237 | 183 | if ((r = sshbuf_load_fd(fd, &buffer)) != 0 || | |
238 | if ((buffer = sshbuf_new()) == NULL) { | ||
239 | r = SSH_ERR_ALLOC_FAIL; | ||
240 | goto out; | ||
241 | } | ||
242 | if ((r = sshkey_load_file(fd, buffer)) != 0 || | ||
243 | (r = sshkey_parse_private_fileblob(buffer, passphrase, keyp, | 184 | (r = sshkey_parse_private_fileblob(buffer, passphrase, keyp, |
244 | commentp)) != 0) | 185 | commentp)) != 0) |
245 | goto out; | 186 | goto out; |
diff --git a/authfile.h b/authfile.h index a2840cf80..1db067a81 100644 --- a/authfile.h +++ b/authfile.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfile.h,v 1.24 2020/01/02 22:38:33 djm Exp $ */ | 1 | /* $OpenBSD: authfile.h,v 1.25 2020/01/25 23:02:13 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. |
@@ -35,7 +35,6 @@ struct sshkey; | |||
35 | 35 | ||
36 | int sshkey_save_private(struct sshkey *, const char *, | 36 | int sshkey_save_private(struct sshkey *, const char *, |
37 | const char *, const char *, int, const char *, int); | 37 | const char *, const char *, int, const char *, int); |
38 | int sshkey_load_file(int, struct sshbuf *); | ||
39 | int sshkey_load_cert(const char *, struct sshkey **); | 38 | int sshkey_load_cert(const char *, struct sshkey **); |
40 | int sshkey_load_public(const char *, struct sshkey **, char **); | 39 | int sshkey_load_public(const char *, struct sshkey **, char **); |
41 | int sshkey_load_private(const char *, const char *, struct sshkey **, char **); | 40 | int sshkey_load_private(const char *, const char *, struct sshkey **, char **); |
@@ -14,7 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | /* $OpenBSD: krl.c,v 1.46 2019/11/25 00:51:37 djm Exp $ */ | 17 | /* $OpenBSD: krl.c,v 1.47 2020/01/25 23:02:13 djm Exp $ */ |
18 | 18 | ||
19 | #include "includes.h" | 19 | #include "includes.h" |
20 | 20 | ||
@@ -1336,19 +1336,11 @@ ssh_krl_file_contains_key(const char *path, const struct sshkey *key) | |||
1336 | { | 1336 | { |
1337 | struct sshbuf *krlbuf = NULL; | 1337 | struct sshbuf *krlbuf = NULL; |
1338 | struct ssh_krl *krl = NULL; | 1338 | struct ssh_krl *krl = NULL; |
1339 | int oerrno = 0, r, fd; | 1339 | int oerrno = 0, r; |
1340 | 1340 | ||
1341 | if (path == NULL) | 1341 | if (path == NULL) |
1342 | return 0; | 1342 | return 0; |
1343 | 1343 | if ((r = sshbuf_load_file(path, &krlbuf)) != 0) { | |
1344 | if ((krlbuf = sshbuf_new()) == NULL) | ||
1345 | return SSH_ERR_ALLOC_FAIL; | ||
1346 | if ((fd = open(path, O_RDONLY)) == -1) { | ||
1347 | r = SSH_ERR_SYSTEM_ERROR; | ||
1348 | oerrno = errno; | ||
1349 | goto out; | ||
1350 | } | ||
1351 | if ((r = sshkey_load_file(fd, krlbuf)) != 0) { | ||
1352 | oerrno = errno; | 1344 | oerrno = errno; |
1353 | goto out; | 1345 | goto out; |
1354 | } | 1346 | } |
@@ -1357,8 +1349,6 @@ ssh_krl_file_contains_key(const char *path, const struct sshkey *key) | |||
1357 | debug2("%s: checking KRL %s", __func__, path); | 1349 | debug2("%s: checking KRL %s", __func__, path); |
1358 | r = ssh_krl_check_key(krl, key); | 1350 | r = ssh_krl_check_key(krl, key); |
1359 | out: | 1351 | out: |
1360 | if (fd != -1) | ||
1361 | close(fd); | ||
1362 | sshbuf_free(krlbuf); | 1352 | sshbuf_free(krlbuf); |
1363 | ssh_krl_free(krl); | 1353 | ssh_krl_free(krl); |
1364 | if (r != 0) | 1354 | if (r != 0) |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-add.c,v 1.150 2020/01/17 20:13:47 naddy Exp $ */ | 1 | /* $OpenBSD: ssh-add.c,v 1.151 2020/01/25 23:02:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -224,9 +224,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag, | |||
224 | return -1; | 224 | return -1; |
225 | } | 225 | } |
226 | } | 226 | } |
227 | if ((keyblob = sshbuf_new()) == NULL) | 227 | if ((r = sshbuf_load_fd(fd, &keyblob)) != 0) { |
228 | fatal("%s: sshbuf_new failed", __func__); | ||
229 | if ((r = sshkey_load_file(fd, keyblob)) != 0) { | ||
230 | fprintf(stderr, "Error loading key \"%s\": %s\n", | 228 | fprintf(stderr, "Error loading key \"%s\": %s\n", |
231 | filename, ssh_err(r)); | 229 | filename, ssh_err(r)); |
232 | sshbuf_free(keyblob); | 230 | sshbuf_free(keyblob); |
diff --git a/ssh-keygen.c b/ssh-keygen.c index d29f97bb3..29013a20f 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.392 2020/01/25 00:03:36 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.393 2020/01/25 23:02:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -2189,15 +2189,10 @@ static void | |||
2189 | load_krl(const char *path, struct ssh_krl **krlp) | 2189 | load_krl(const char *path, struct ssh_krl **krlp) |
2190 | { | 2190 | { |
2191 | struct sshbuf *krlbuf; | 2191 | struct sshbuf *krlbuf; |
2192 | int r, fd; | 2192 | int r; |
2193 | 2193 | ||
2194 | if ((krlbuf = sshbuf_new()) == NULL) | 2194 | if ((r = sshbuf_load_file(path, &krlbuf)) != 0) |
2195 | fatal("sshbuf_new failed"); | ||
2196 | if ((fd = open(path, O_RDONLY)) == -1) | ||
2197 | fatal("open %s: %s", path, strerror(errno)); | ||
2198 | if ((r = sshkey_load_file(fd, krlbuf)) != 0) | ||
2199 | fatal("Unable to load KRL: %s", ssh_err(r)); | 2195 | fatal("Unable to load KRL: %s", ssh_err(r)); |
2200 | close(fd); | ||
2201 | /* XXX check sigs */ | 2196 | /* XXX check sigs */ |
2202 | if ((r = ssh_krl_from_blob(krlbuf, krlp, NULL, 0)) != 0 || | 2197 | if ((r = ssh_krl_from_blob(krlbuf, krlp, NULL, 0)) != 0 || |
2203 | *krlp == NULL) | 2198 | *krlp == NULL) |
@@ -2399,7 +2394,7 @@ do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path, | |||
2399 | struct ssh_krl *krl; | 2394 | struct ssh_krl *krl; |
2400 | struct stat sb; | 2395 | struct stat sb; |
2401 | struct sshkey *ca = NULL; | 2396 | struct sshkey *ca = NULL; |
2402 | int fd, i, r, wild_ca = 0; | 2397 | int i, r, wild_ca = 0; |
2403 | char *tmp; | 2398 | char *tmp; |
2404 | struct sshbuf *kbuf; | 2399 | struct sshbuf *kbuf; |
2405 | 2400 | ||
@@ -2441,12 +2436,8 @@ do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path, | |||
2441 | fatal("sshbuf_new failed"); | 2436 | fatal("sshbuf_new failed"); |
2442 | if (ssh_krl_to_blob(krl, kbuf, NULL, 0) != 0) | 2437 | if (ssh_krl_to_blob(krl, kbuf, NULL, 0) != 0) |
2443 | fatal("Couldn't generate KRL"); | 2438 | fatal("Couldn't generate KRL"); |
2444 | if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) | 2439 | if ((r = sshbuf_write_file(identity_file, kbuf)) != 0) |
2445 | fatal("open %s: %s", identity_file, strerror(errno)); | ||
2446 | if (atomicio(vwrite, fd, sshbuf_mutable_ptr(kbuf), sshbuf_len(kbuf)) != | ||
2447 | sshbuf_len(kbuf)) | ||
2448 | fatal("write %s: %s", identity_file, strerror(errno)); | 2440 | fatal("write %s: %s", identity_file, strerror(errno)); |
2449 | close(fd); | ||
2450 | sshbuf_free(kbuf); | 2441 | sshbuf_free(kbuf); |
2451 | ssh_krl_free(krl); | 2442 | ssh_krl_free(krl); |
2452 | sshkey_free(ca); | 2443 | sshkey_free(ca); |
@@ -2691,25 +2682,18 @@ static int | |||
2691 | sig_verify(const char *signature, const char *sig_namespace, | 2682 | sig_verify(const char *signature, const char *sig_namespace, |
2692 | const char *principal, const char *allowed_keys, const char *revoked_keys) | 2683 | const char *principal, const char *allowed_keys, const char *revoked_keys) |
2693 | { | 2684 | { |
2694 | int r, ret = -1, sigfd = -1; | 2685 | int r, ret = -1; |
2695 | struct sshbuf *sigbuf = NULL, *abuf = NULL; | 2686 | struct sshbuf *sigbuf = NULL, *abuf = NULL; |
2696 | struct sshkey *sign_key = NULL; | 2687 | struct sshkey *sign_key = NULL; |
2697 | char *fp = NULL; | 2688 | char *fp = NULL; |
2698 | struct sshkey_sig_details *sig_details = NULL; | 2689 | struct sshkey_sig_details *sig_details = NULL; |
2699 | 2690 | ||
2700 | memset(&sig_details, 0, sizeof(sig_details)); | 2691 | memset(&sig_details, 0, sizeof(sig_details)); |
2701 | if ((abuf = sshbuf_new()) == NULL) | 2692 | if ((r = sshbuf_load_file(signature, &abuf)) != 0) { |
2702 | fatal("%s: sshbuf_new() failed", __func__); | ||
2703 | |||
2704 | if ((sigfd = open(signature, O_RDONLY)) < 0) { | ||
2705 | error("Couldn't open signature file %s", signature); | ||
2706 | goto done; | ||
2707 | } | ||
2708 | |||
2709 | if ((r = sshkey_load_file(sigfd, abuf)) != 0) { | ||
2710 | error("Couldn't read signature file: %s", ssh_err(r)); | 2693 | error("Couldn't read signature file: %s", ssh_err(r)); |
2711 | goto done; | 2694 | goto done; |
2712 | } | 2695 | } |
2696 | |||
2713 | if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) { | 2697 | if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) { |
2714 | error("%s: sshsig_armor: %s", __func__, ssh_err(r)); | 2698 | error("%s: sshsig_armor: %s", __func__, ssh_err(r)); |
2715 | goto done; | 2699 | goto done; |
@@ -2765,8 +2749,6 @@ done: | |||
2765 | printf("Could not verify signature.\n"); | 2749 | printf("Could not verify signature.\n"); |
2766 | } | 2750 | } |
2767 | } | 2751 | } |
2768 | if (sigfd != -1) | ||
2769 | close(sigfd); | ||
2770 | sshbuf_free(sigbuf); | 2752 | sshbuf_free(sigbuf); |
2771 | sshbuf_free(abuf); | 2753 | sshbuf_free(abuf); |
2772 | sshkey_free(sign_key); | 2754 | sshkey_free(sign_key); |
@@ -2777,20 +2759,12 @@ done: | |||
2777 | 2759 | ||
2778 | static int | 2760 | static int |
2779 | sig_find_principals(const char *signature, const char *allowed_keys) { | 2761 | sig_find_principals(const char *signature, const char *allowed_keys) { |
2780 | int r, ret = -1, sigfd = -1; | 2762 | int r, ret = -1; |
2781 | struct sshbuf *sigbuf = NULL, *abuf = NULL; | 2763 | struct sshbuf *sigbuf = NULL, *abuf = NULL; |
2782 | struct sshkey *sign_key = NULL; | 2764 | struct sshkey *sign_key = NULL; |
2783 | char *principals = NULL, *cp, *tmp; | 2765 | char *principals = NULL, *cp, *tmp; |
2784 | 2766 | ||
2785 | if ((abuf = sshbuf_new()) == NULL) | 2767 | if ((r = sshbuf_load_file(signature, &abuf)) != 0) { |
2786 | fatal("%s: sshbuf_new() failed", __func__); | ||
2787 | |||
2788 | if ((sigfd = open(signature, O_RDONLY)) < 0) { | ||
2789 | error("Couldn't open signature file %s", signature); | ||
2790 | goto done; | ||
2791 | } | ||
2792 | |||
2793 | if ((r = sshkey_load_file(sigfd, abuf)) != 0) { | ||
2794 | error("Couldn't read signature file: %s", ssh_err(r)); | 2768 | error("Couldn't read signature file: %s", ssh_err(r)); |
2795 | goto done; | 2769 | goto done; |
2796 | } | 2770 | } |
@@ -2819,8 +2793,6 @@ done: | |||
2819 | } else { | 2793 | } else { |
2820 | fprintf(stderr, "No principal matched.\n"); | 2794 | fprintf(stderr, "No principal matched.\n"); |
2821 | } | 2795 | } |
2822 | if (sigfd != -1) | ||
2823 | close(sigfd); | ||
2824 | sshbuf_free(sigbuf); | 2796 | sshbuf_free(sigbuf); |
2825 | sshbuf_free(abuf); | 2797 | sshbuf_free(abuf); |
2826 | sshkey_free(sign_key); | 2798 | sshkey_free(sign_key); |
diff --git a/sshbuf-io.c b/sshbuf-io.c new file mode 100644 index 000000000..65f745858 --- /dev/null +++ b/sshbuf-io.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* $OpenBSD: sshbuf-io.c,v 1.1 2020/01/25 23:02:14 djm Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2011 Damien Miller | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include "includes.h" | ||
19 | |||
20 | #include <sys/types.h> | ||
21 | #include <sys/stat.h> | ||
22 | |||
23 | #include <errno.h> | ||
24 | #include <fcntl.h> | ||
25 | #include <unistd.h> | ||
26 | #include <string.h> | ||
27 | |||
28 | #include "ssherr.h" | ||
29 | #define SSHBUF_INTERNAL | ||
30 | #include "sshbuf.h" | ||
31 | #include "atomicio.h" | ||
32 | |||
33 | /* Load a file from a fd into a buffer */ | ||
34 | int | ||
35 | sshbuf_load_fd(int fd, struct sshbuf **blobp) | ||
36 | { | ||
37 | u_char buf[4096]; | ||
38 | size_t len; | ||
39 | struct stat st; | ||
40 | int r; | ||
41 | struct sshbuf *blob; | ||
42 | |||
43 | *blobp = NULL; | ||
44 | |||
45 | if (fstat(fd, &st) == -1) | ||
46 | return SSH_ERR_SYSTEM_ERROR; | ||
47 | if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && | ||
48 | st.st_size > SSHBUF_SIZE_MAX) | ||
49 | return SSH_ERR_INVALID_FORMAT; | ||
50 | if ((blob = sshbuf_new()) == NULL) | ||
51 | return SSH_ERR_ALLOC_FAIL; | ||
52 | for (;;) { | ||
53 | if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { | ||
54 | if (errno == EPIPE) | ||
55 | break; | ||
56 | r = SSH_ERR_SYSTEM_ERROR; | ||
57 | goto out; | ||
58 | } | ||
59 | if ((r = sshbuf_put(blob, buf, len)) != 0) | ||
60 | goto out; | ||
61 | if (sshbuf_len(blob) > SSHBUF_SIZE_MAX) { | ||
62 | r = SSH_ERR_INVALID_FORMAT; | ||
63 | goto out; | ||
64 | } | ||
65 | } | ||
66 | if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && | ||
67 | st.st_size != (off_t)sshbuf_len(blob)) { | ||
68 | r = SSH_ERR_FILE_CHANGED; | ||
69 | goto out; | ||
70 | } | ||
71 | /* success */ | ||
72 | *blobp = blob; | ||
73 | blob = NULL; /* transferred */ | ||
74 | r = 0; | ||
75 | out: | ||
76 | explicit_bzero(buf, sizeof(buf)); | ||
77 | sshbuf_free(blob); | ||
78 | return r; | ||
79 | } | ||
80 | |||
81 | int | ||
82 | sshbuf_load_file(const char *path, struct sshbuf **bufp) | ||
83 | { | ||
84 | int r, fd, oerrno; | ||
85 | |||
86 | *bufp = NULL; | ||
87 | if ((fd = open(path, O_RDONLY)) == -1) | ||
88 | return SSH_ERR_SYSTEM_ERROR; | ||
89 | if ((r = sshbuf_load_fd(fd, bufp)) != 0) | ||
90 | goto out; | ||
91 | /* success */ | ||
92 | r = 0; | ||
93 | out: | ||
94 | oerrno = errno; | ||
95 | close(fd); | ||
96 | if (r != 0) | ||
97 | errno = oerrno; | ||
98 | return r; | ||
99 | } | ||
100 | |||
101 | int | ||
102 | sshbuf_write_file(const char *path, struct sshbuf *buf) | ||
103 | { | ||
104 | int fd, oerrno; | ||
105 | |||
106 | if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) | ||
107 | return SSH_ERR_SYSTEM_ERROR; | ||
108 | if (atomicio(vwrite, fd, sshbuf_mutable_ptr(buf), | ||
109 | sshbuf_len(buf)) != sshbuf_len(buf) || close(fd) != 0) { | ||
110 | oerrno = errno; | ||
111 | close(fd); | ||
112 | unlink(path); | ||
113 | errno = oerrno; | ||
114 | return SSH_ERR_SYSTEM_ERROR; | ||
115 | } | ||
116 | return 0; | ||
117 | } | ||
118 | |||
diff --git a/sshbuf-misc.c b/sshbuf-misc.c index a73f008b0..739b19f96 100644 --- a/sshbuf-misc.c +++ b/sshbuf-misc.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshbuf-misc.c,v 1.11 2019/07/30 05:04:49 djm Exp $ */ | 1 | /* $OpenBSD: sshbuf-misc.c,v 1.12 2020/01/25 23:02:14 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2011 Damien Miller | 3 | * Copyright (c) 2011 Damien Miller |
4 | * | 4 | * |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshbuf.h,v 1.18 2019/09/06 05:23:55 djm Exp $ */ | 1 | /* $OpenBSD: sshbuf.h,v 1.19 2020/01/25 23:02:14 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2011 Damien Miller | 3 | * Copyright (c) 2011 Damien Miller |
4 | * | 4 | * |
@@ -291,6 +291,22 @@ sshbuf_find(const struct sshbuf *b, size_t start_offset, | |||
291 | */ | 291 | */ |
292 | char *sshbuf_dup_string(struct sshbuf *buf); | 292 | char *sshbuf_dup_string(struct sshbuf *buf); |
293 | 293 | ||
294 | /* | ||
295 | * Fill a buffer from a file descriptor or filename. Both allocate the | ||
296 | * buffer for the caller. | ||
297 | */ | ||
298 | int sshbuf_load_fd(int, struct sshbuf **) | ||
299 | __attribute__((__nonnull__ (2))); | ||
300 | int sshbuf_load_file(const char *, struct sshbuf **) | ||
301 | __attribute__((__nonnull__ (2))); | ||
302 | |||
303 | /* | ||
304 | * Write a buffer to a path, creating/truncating as needed (mode 0644, | ||
305 | * subject to umask). The buffer contents are not modified. | ||
306 | */ | ||
307 | int sshbuf_write_file(const char *path, struct sshbuf *buf) | ||
308 | __attribute__((__nonnull__ (2))); | ||
309 | |||
294 | /* Macros for decoding/encoding integers */ | 310 | /* Macros for decoding/encoding integers */ |
295 | #define PEEK_U64(p) \ | 311 | #define PEEK_U64(p) \ |
296 | (((u_int64_t)(((const u_char *)(p))[0]) << 56) | \ | 312 | (((u_int64_t)(((const u_char *)(p))[0]) << 56) | \ |