Coverage Report

Created: 2025-06-20 06:25

/src/openssh/sshbuf-io.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: sshbuf-io.c,v 1.2 2020/01/25 23:28:06 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
#include "sshbuf.h"
30
#include "atomicio.h"
31
32
/* Load a file from a fd into a buffer */
33
int
34
sshbuf_load_fd(int fd, struct sshbuf **blobp)
35
0
{
36
0
  u_char buf[4096];
37
0
  size_t len;
38
0
  struct stat st;
39
0
  int r;
40
0
  struct sshbuf *blob;
41
42
0
  *blobp = NULL;
43
44
0
  if (fstat(fd, &st) == -1)
45
0
    return SSH_ERR_SYSTEM_ERROR;
46
0
  if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
47
0
      st.st_size > SSHBUF_SIZE_MAX)
48
0
    return SSH_ERR_INVALID_FORMAT;
49
0
  if ((blob = sshbuf_new()) == NULL)
50
0
    return SSH_ERR_ALLOC_FAIL;
51
0
  for (;;) {
52
0
    if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
53
0
      if (errno == EPIPE)
54
0
        break;
55
0
      r = SSH_ERR_SYSTEM_ERROR;
56
0
      goto out;
57
0
    }
58
0
    if ((r = sshbuf_put(blob, buf, len)) != 0)
59
0
      goto out;
60
0
    if (sshbuf_len(blob) > SSHBUF_SIZE_MAX) {
61
0
      r = SSH_ERR_INVALID_FORMAT;
62
0
      goto out;
63
0
    }
64
0
  }
65
0
  if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
66
0
      st.st_size != (off_t)sshbuf_len(blob)) {
67
0
    r = SSH_ERR_FILE_CHANGED;
68
0
    goto out;
69
0
  }
70
  /* success */
71
0
  *blobp = blob;
72
0
  blob = NULL; /* transferred */
73
0
  r = 0;
74
0
 out:
75
0
  explicit_bzero(buf, sizeof(buf));
76
0
  sshbuf_free(blob);
77
0
  return r;
78
0
}
79
80
int
81
sshbuf_load_file(const char *path, struct sshbuf **bufp)
82
0
{
83
0
  int r, fd, oerrno;
84
85
0
  *bufp = NULL;
86
0
  if ((fd = open(path, O_RDONLY)) == -1)
87
0
    return SSH_ERR_SYSTEM_ERROR;
88
0
  if ((r = sshbuf_load_fd(fd, bufp)) != 0)
89
0
    goto out;
90
  /* success */
91
0
  r = 0;
92
0
 out:
93
0
  oerrno = errno;
94
0
  close(fd);
95
0
  if (r != 0)
96
0
    errno = oerrno;
97
0
  return r;
98
0
}
99
100
int
101
sshbuf_write_file(const char *path, struct sshbuf *buf)
102
0
{
103
0
  int fd, oerrno;
104
105
0
  if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1)
106
0
    return SSH_ERR_SYSTEM_ERROR;
107
0
  if (atomicio(vwrite, fd, sshbuf_mutable_ptr(buf),
108
0
      sshbuf_len(buf)) != sshbuf_len(buf) || close(fd) != 0) {
109
0
    oerrno = errno;
110
0
    close(fd);
111
0
    unlink(path);
112
0
    errno = oerrno;
113
0
    return SSH_ERR_SYSTEM_ERROR;
114
0
  }
115
0
  return 0;
116
0
}
117