1*bb3c2609Sdjm /* $OpenBSD: sshbuf-io.c,v 1.2 2020/01/25 23:28:06 djm Exp $ */
262af2284Sdjm /*
362af2284Sdjm * Copyright (c) 2011 Damien Miller
462af2284Sdjm *
562af2284Sdjm * Permission to use, copy, modify, and distribute this software for any
662af2284Sdjm * purpose with or without fee is hereby granted, provided that the above
762af2284Sdjm * copyright notice and this permission notice appear in all copies.
862af2284Sdjm *
962af2284Sdjm * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1062af2284Sdjm * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1162af2284Sdjm * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1262af2284Sdjm * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1362af2284Sdjm * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1462af2284Sdjm * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1562af2284Sdjm * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1662af2284Sdjm */
1762af2284Sdjm
1862af2284Sdjm #include <sys/types.h>
1962af2284Sdjm #include <sys/stat.h>
2062af2284Sdjm
2162af2284Sdjm #include <errno.h>
2262af2284Sdjm #include <fcntl.h>
2362af2284Sdjm #include <unistd.h>
2462af2284Sdjm #include <string.h>
2562af2284Sdjm
2662af2284Sdjm #include "ssherr.h"
2762af2284Sdjm #include "sshbuf.h"
2862af2284Sdjm #include "atomicio.h"
2962af2284Sdjm
3062af2284Sdjm /* Load a file from a fd into a buffer */
3162af2284Sdjm int
sshbuf_load_fd(int fd,struct sshbuf ** blobp)3262af2284Sdjm sshbuf_load_fd(int fd, struct sshbuf **blobp)
3362af2284Sdjm {
3462af2284Sdjm u_char buf[4096];
3562af2284Sdjm size_t len;
3662af2284Sdjm struct stat st;
3762af2284Sdjm int r;
3862af2284Sdjm struct sshbuf *blob;
3962af2284Sdjm
4062af2284Sdjm *blobp = NULL;
4162af2284Sdjm
4262af2284Sdjm if (fstat(fd, &st) == -1)
4362af2284Sdjm return SSH_ERR_SYSTEM_ERROR;
4462af2284Sdjm if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
4562af2284Sdjm st.st_size > SSHBUF_SIZE_MAX)
4662af2284Sdjm return SSH_ERR_INVALID_FORMAT;
4762af2284Sdjm if ((blob = sshbuf_new()) == NULL)
4862af2284Sdjm return SSH_ERR_ALLOC_FAIL;
4962af2284Sdjm for (;;) {
5062af2284Sdjm if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
5162af2284Sdjm if (errno == EPIPE)
5262af2284Sdjm break;
5362af2284Sdjm r = SSH_ERR_SYSTEM_ERROR;
5462af2284Sdjm goto out;
5562af2284Sdjm }
5662af2284Sdjm if ((r = sshbuf_put(blob, buf, len)) != 0)
5762af2284Sdjm goto out;
5862af2284Sdjm if (sshbuf_len(blob) > SSHBUF_SIZE_MAX) {
5962af2284Sdjm r = SSH_ERR_INVALID_FORMAT;
6062af2284Sdjm goto out;
6162af2284Sdjm }
6262af2284Sdjm }
6362af2284Sdjm if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
6462af2284Sdjm st.st_size != (off_t)sshbuf_len(blob)) {
6562af2284Sdjm r = SSH_ERR_FILE_CHANGED;
6662af2284Sdjm goto out;
6762af2284Sdjm }
6862af2284Sdjm /* success */
6962af2284Sdjm *blobp = blob;
7062af2284Sdjm blob = NULL; /* transferred */
7162af2284Sdjm r = 0;
7262af2284Sdjm out:
7362af2284Sdjm explicit_bzero(buf, sizeof(buf));
7462af2284Sdjm sshbuf_free(blob);
7562af2284Sdjm return r;
7662af2284Sdjm }
7762af2284Sdjm
7862af2284Sdjm int
sshbuf_load_file(const char * path,struct sshbuf ** bufp)7962af2284Sdjm sshbuf_load_file(const char *path, struct sshbuf **bufp)
8062af2284Sdjm {
8162af2284Sdjm int r, fd, oerrno;
8262af2284Sdjm
8362af2284Sdjm *bufp = NULL;
8462af2284Sdjm if ((fd = open(path, O_RDONLY)) == -1)
8562af2284Sdjm return SSH_ERR_SYSTEM_ERROR;
8662af2284Sdjm if ((r = sshbuf_load_fd(fd, bufp)) != 0)
8762af2284Sdjm goto out;
8862af2284Sdjm /* success */
8962af2284Sdjm r = 0;
9062af2284Sdjm out:
9162af2284Sdjm oerrno = errno;
9262af2284Sdjm close(fd);
9362af2284Sdjm if (r != 0)
9462af2284Sdjm errno = oerrno;
9562af2284Sdjm return r;
9662af2284Sdjm }
9762af2284Sdjm
9862af2284Sdjm int
sshbuf_write_file(const char * path,struct sshbuf * buf)9962af2284Sdjm sshbuf_write_file(const char *path, struct sshbuf *buf)
10062af2284Sdjm {
10162af2284Sdjm int fd, oerrno;
10262af2284Sdjm
10362af2284Sdjm if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1)
10462af2284Sdjm return SSH_ERR_SYSTEM_ERROR;
10562af2284Sdjm if (atomicio(vwrite, fd, sshbuf_mutable_ptr(buf),
10662af2284Sdjm sshbuf_len(buf)) != sshbuf_len(buf) || close(fd) != 0) {
10762af2284Sdjm oerrno = errno;
10862af2284Sdjm close(fd);
10962af2284Sdjm unlink(path);
11062af2284Sdjm errno = oerrno;
11162af2284Sdjm return SSH_ERR_SYSTEM_ERROR;
11262af2284Sdjm }
11362af2284Sdjm return 0;
11462af2284Sdjm }
11562af2284Sdjm
116