#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;
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);
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)
if (length > ENCODE_LINE_LENGTH)
length = ENCODE_LINE_LENGTH;
- l = base64_encode(p, length, &line);
+ l = rk_base64_encode(p, length, &line);
if (l < 0) {
hx509_set_error_string(context, 0, ENOMEM,
"malloc - out of memory");
*
*/
-int
+HX509_LIB_FUNCTION int HX509_LIB_CALL
hx509_pem_add_header(hx509_pem_header **headers,
const char *header, const char *value)
{
return 0;
}
-void
+HX509_LIB_FUNCTION void HX509_LIB_CALL
hx509_pem_free_header(hx509_pem_header *headers)
{
hx509_pem_header *h;
*
*/
-const char *
+HX509_LIB_FUNCTION const char * HX509_LIB_CALL
hx509_pem_find_header(const hx509_pem_header *h, const char *header)
{
while(h) {
*
*/
-int
+HX509_LIB_FUNCTION int HX509_LIB_CALL
hx509_pem_read(hx509_context context,
FILE *f,
hx509_pem_read_func func,
where = INDATA;
goto indata;
}
- /* FALLTHOUGH */
+ /* FALLTHROUGH */
case INHEADER:
if (buf[0] == '\0') {
where = INDATA;
}
p = emalloc(i);
- i = base64_decode(buf, p);
+ i = rk_base64_decode(buf, p);
if (i < 0) {
free(p);
goto out;
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, ret, "hx509_certs_destroy: "
+ "stat of \"%s\": %s", fn, strerror(ret));
+ return errno;
+ }
+
+ fd = open(fn, O_RDWR | O_BINARY | O_CLOEXEC | O_NOFOLLOW);
+ rk_cloexec(fd);
+ if (ret == -1 && errno == ENOENT)
+ return 0;
+ if (ret == -1)
+ return errno;
+
+ 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;
+}