aboutsummaryrefslogtreecommitdiff
path: root/lib/hx509/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hx509/file.c')
-rw-r--r--lib/hx509/file.c105
1 files changed, 95 insertions, 10 deletions
diff --git a/lib/hx509/file.c b/lib/hx509/file.c
index 6f34d3b74a9b..00f723c38bad 100644
--- a/lib/hx509/file.c
+++ b/lib/hx509/file.c
@@ -33,7 +33,7 @@
#include "hx_locl.h"
-int
+HX509_LIB_FUNCTION int HX509_LIB_CALL
_hx509_map_file_os(const char *fn, heim_octet_string *os)
{
size_t length;
@@ -48,13 +48,13 @@ _hx509_map_file_os(const char *fn, heim_octet_string *os)
return ret;
}
-void
+HX509_LIB_FUNCTION void HX509_LIB_CALL
_hx509_unmap_file_os(heim_octet_string *os)
{
rk_xfree(os->data);
}
-int
+HX509_LIB_FUNCTION int HX509_LIB_CALL
_hx509_write_file(const char *fn, const void *data, size_t length)
{
rk_dumpdata(fn, data, length);
@@ -71,7 +71,7 @@ print_pem_stamp(FILE *f, const char *type, const char *str)
fprintf(f, "-----%s %s-----\n", type, str);
}
-int
+HX509_LIB_FUNCTION int HX509_LIB_CALL
hx509_pem_write(hx509_context context, const char *type,
hx509_pem_header *headers, FILE *f,
const void *data, size_t size)
@@ -119,7 +119,7 @@ hx509_pem_write(hx509_context context, const char *type,
*
*/
-int
+HX509_LIB_FUNCTION int HX509_LIB_CALL
hx509_pem_add_header(hx509_pem_header **headers,
const char *header, const char *value)
{
@@ -146,7 +146,7 @@ hx509_pem_add_header(hx509_pem_header **headers,
return 0;
}
-void
+HX509_LIB_FUNCTION void HX509_LIB_CALL
hx509_pem_free_header(hx509_pem_header *headers)
{
hx509_pem_header *h;
@@ -163,7 +163,7 @@ hx509_pem_free_header(hx509_pem_header *headers)
*
*/
-const char *
+HX509_LIB_FUNCTION const char * HX509_LIB_CALL
hx509_pem_find_header(const hx509_pem_header *h, const char *header)
{
while(h) {
@@ -179,7 +179,7 @@ hx509_pem_find_header(const hx509_pem_header *h, const char *header)
*
*/
-int
+HX509_LIB_FUNCTION int HX509_LIB_CALL
hx509_pem_read(hx509_context context,
FILE *f,
hx509_pem_read_func func,
@@ -230,7 +230,7 @@ hx509_pem_read(hx509_context context,
where = INDATA;
goto indata;
}
- /* FALLTHROUGH */
+ HEIM_FALLTHROUGH;
case INHEADER:
if (buf[0] == '\0') {
where = INDATA;
@@ -239,7 +239,7 @@ hx509_pem_read(hx509_context context,
p = strchr(buf, ':');
if (p) {
*p++ = '\0';
- while (isspace((int)*p))
+ while (isspace((unsigned char)*p))
p++;
ret = hx509_pem_add_header(&headers, buf, p);
if (ret)
@@ -300,3 +300,88 @@ hx509_pem_read(hx509_context context,
return ret;
}
+
+/*
+ * On modern systems there's no such thing as scrubbing a file. Not this way
+ * anyways. However, for now we'll cargo-cult this along just as in lib/krb5.
+ */
+static int
+scrub_file(int fd, ssize_t sz)
+{
+ char buf[128];
+
+ memset(buf, 0, sizeof(buf));
+ while (sz > 0) {
+ ssize_t tmp;
+ size_t wr = sizeof(buf) > sz ? (size_t)sz : sizeof(buf);
+
+ tmp = write(fd, buf, wr);
+ if (tmp == -1)
+ return errno;
+ sz -= tmp;
+ }
+#ifdef _MSC_VER
+ return _commit(fd);
+#else
+ return fsync(fd);
+#endif
+}
+
+int
+_hx509_erase_file(hx509_context context, const char *fn)
+{
+ struct stat sb1, sb2;
+ int ret;
+ int fd;
+
+ if (fn == NULL)
+ return 0;
+
+ /* This is based on _krb5_erase_file(), minus file locking */
+ ret = lstat(fn, &sb1);
+ if (ret == -1 && errno == ENOENT)
+ return 0;
+ if (ret == -1) {
+ hx509_set_error_string(context, 0, errno, "hx509_certs_destroy: "
+ "stat of \"%s\": %s", fn, strerror(errno));
+ return errno;
+ }
+
+ fd = open(fn, O_RDWR | O_BINARY | O_CLOEXEC | O_NOFOLLOW);
+ if (fd < 0)
+ return errno == ENOENT ? 0 : errno;
+ rk_cloexec(fd);
+
+ if (unlink(fn) < 0) {
+ ret = errno;
+ (void) close(fd);
+ hx509_set_error_string(context, 0, ret, "hx509_certs_destroy: "
+ "unlinking \"%s\": %s", fn, strerror(ret));
+ return ret;
+ }
+
+ /* check TOCTOU, symlinks */
+ ret = fstat(fd, &sb2);
+ if (ret < 0) {
+ ret = errno;
+ hx509_set_error_string(context, 0, ret, "hx509_certs_destroy: "
+ "fstat of %d, \"%s\": %s", fd, fn,
+ strerror(ret));
+ (void) close(fd);
+ return ret;
+ }
+ if (sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) {
+ (void) close(fd);
+ return EPERM;
+ }
+
+ /* there are still hard links to this file */
+ if (sb2.st_nlink != 0) {
+ close(fd);
+ return 0;
+ }
+
+ ret = scrub_file(fd, sb2.st_size);
+ (void) close(fd);
+ return ret;
+}