sshbuf-io.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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. #include "includes.h"
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <errno.h>
  21. #include <fcntl.h>
  22. #include <unistd.h>
  23. #include <string.h>
  24. #include "ssherr.h"
  25. #include "sshbuf.h"
  26. #include "atomicio.h"
  27. /* Load a file from a fd into a buffer */
  28. int
  29. sshbuf_load_fd(int fd, struct sshbuf **blobp)
  30. {
  31. u_char buf[4096];
  32. size_t len;
  33. struct stat st;
  34. int r;
  35. struct sshbuf *blob;
  36. *blobp = NULL;
  37. if (fstat(fd, &st) == -1)
  38. return SSH_ERR_SYSTEM_ERROR;
  39. if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
  40. st.st_size > SSHBUF_SIZE_MAX)
  41. return SSH_ERR_INVALID_FORMAT;
  42. if ((blob = sshbuf_new()) == NULL)
  43. return SSH_ERR_ALLOC_FAIL;
  44. for (;;) {
  45. if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
  46. if (errno == EPIPE)
  47. break;
  48. r = SSH_ERR_SYSTEM_ERROR;
  49. goto out;
  50. }
  51. if ((r = sshbuf_put(blob, buf, len)) != 0)
  52. goto out;
  53. if (sshbuf_len(blob) > SSHBUF_SIZE_MAX) {
  54. r = SSH_ERR_INVALID_FORMAT;
  55. goto out;
  56. }
  57. }
  58. if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
  59. st.st_size != (off_t)sshbuf_len(blob)) {
  60. r = SSH_ERR_FILE_CHANGED;
  61. goto out;
  62. }
  63. /* success */
  64. *blobp = blob;
  65. blob = NULL; /* transferred */
  66. r = 0;
  67. out:
  68. explicit_bzero(buf, sizeof(buf));
  69. sshbuf_free(blob);
  70. return r;
  71. }
  72. int
  73. sshbuf_load_file(const char *path, struct sshbuf **bufp)
  74. {
  75. int r, fd, oerrno;
  76. *bufp = NULL;
  77. if ((fd = open(path, O_RDONLY)) == -1)
  78. return SSH_ERR_SYSTEM_ERROR;
  79. if ((r = sshbuf_load_fd(fd, bufp)) != 0)
  80. goto out;
  81. /* success */
  82. r = 0;
  83. out:
  84. oerrno = errno;
  85. close(fd);
  86. if (r != 0)
  87. errno = oerrno;
  88. return r;
  89. }
  90. int
  91. sshbuf_write_file(const char *path, struct sshbuf *buf)
  92. {
  93. int fd, oerrno;
  94. if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1)
  95. return SSH_ERR_SYSTEM_ERROR;
  96. if (atomicio(vwrite, fd, sshbuf_mutable_ptr(buf),
  97. sshbuf_len(buf)) != sshbuf_len(buf) || close(fd) != 0) {
  98. oerrno = errno;
  99. close(fd);
  100. unlink(path);
  101. errno = oerrno;
  102. return SSH_ERR_SYSTEM_ERROR;
  103. }
  104. return 0;
  105. }