Coverage Report

Created: 2026-09-01 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssh/sshbuf-io.c
Line
Count
Source
1
/*  $OpenBSD: sshbuf-io.c,v 1.4 2026/07/05 00:16:21 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 (S_ISREG(st.st_mode) && st.st_size > SSHBUF_SIZE_MAX)
47
0
    return SSH_ERR_INVALID_FORMAT;
48
0
  if ((blob = sshbuf_new()) == NULL)
49
0
    return SSH_ERR_ALLOC_FAIL;
50
0
  for (;;) {
51
0
    if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
52
0
      if (errno == EPIPE)
53
0
        break;
54
0
      r = SSH_ERR_SYSTEM_ERROR;
55
0
      goto out;
56
0
    }
57
0
    if ((r = sshbuf_put(blob, buf, len)) != 0)
58
0
      goto out;
59
0
    if (sshbuf_len(blob) > SSHBUF_SIZE_MAX) {
60
0
      r = SSH_ERR_INVALID_FORMAT;
61
0
      goto out;
62
0
    }
63
0
  }
64
0
  if (S_ISREG(st.st_mode) != 0 &&
65
0
      st.st_size != (off_t)sshbuf_len(blob)) {
66
0
    r = SSH_ERR_FILE_CHANGED;
67
0
    goto out;
68
0
  }
69
  /* success */
70
0
  *blobp = blob;
71
0
  blob = NULL; /* transferred */
72
0
  r = 0;
73
0
 out:
74
0
  explicit_bzero(buf, sizeof(buf));
75
0
  sshbuf_free(blob);
76
0
  return r;
77
0
}
78
79
int
80
sshbuf_load_file(const char *path, struct sshbuf **bufp)
81
0
{
82
0
  int r, fd, oerrno;
83
84
0
  *bufp = NULL;
85
0
  if ((fd = open(path, O_RDONLY)) == -1)
86
0
    return SSH_ERR_SYSTEM_ERROR;
87
0
  if ((r = sshbuf_load_fd(fd, bufp)) != 0)
88
0
    goto out;
89
  /* success */
90
0
  r = 0;
91
0
 out:
92
0
  oerrno = errno;
93
0
  close(fd);
94
0
  if (r != 0)
95
0
    errno = oerrno;
96
0
  return r;
97
0
}
98
99
int
100
sshbuf_write_file(const char *path, struct sshbuf *buf)
101
0
{
102
0
  int fd, oerrno;
103
104
0
  if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1)
105
0
    return SSH_ERR_SYSTEM_ERROR;
106
0
  if (atomicio(vwrite, fd, sshbuf_mutable_ptr(buf),
107
0
      sshbuf_len(buf)) != sshbuf_len(buf) || close(fd) != 0) {
108
0
    oerrno = errno;
109
0
    close(fd);
110
0
    unlink(path);
111
0
    errno = oerrno;
112
0
    return SSH_ERR_SYSTEM_ERROR;
113
0
  }
114
0
  return 0;
115
0
}
116