hx509: add hx509_certs_destroy()
This commit is contained in:
@@ -300,3 +300,90 @@ hx509_pem_read(hx509_context context,
|
|||||||
|
|
||||||
return ret;
|
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;
|
||||||
|
}
|
||||||
|
@@ -70,6 +70,13 @@
|
|||||||
|
|
||||||
#include <der.h>
|
#include <der.h>
|
||||||
|
|
||||||
|
#ifndef O_CLOEXEC
|
||||||
|
#define O_CLOEXEC 0
|
||||||
|
#endif
|
||||||
|
#ifndef O_BINARY
|
||||||
|
#define O_BINARY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We use OpenSSL for EC, but to do this we need to disable cross-references
|
* We use OpenSSL for EC, but to do this we need to disable cross-references
|
||||||
* between OpenSSL and hcrypto bn.h and such. Source files that use OpenSSL EC
|
* between OpenSSL and hcrypto bn.h and such. Source files that use OpenSSL EC
|
||||||
@@ -180,6 +187,7 @@ struct hx509_keyset_ops {
|
|||||||
void *, int (*)(void *, const char *), void *);
|
void *, int (*)(void *, const char *), void *);
|
||||||
int (*getkeys)(hx509_context, hx509_certs, void *, hx509_private_key **);
|
int (*getkeys)(hx509_context, hx509_certs, void *, hx509_private_key **);
|
||||||
int (*addkey)(hx509_context, hx509_certs, void *, hx509_private_key);
|
int (*addkey)(hx509_context, hx509_certs, void *, hx509_private_key);
|
||||||
|
int (*destroy)(hx509_context, hx509_certs, void *);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _hx509_password {
|
struct _hx509_password {
|
||||||
|
@@ -168,6 +168,33 @@ hx509_certs_init(hx509_context context,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys and frees a hx509 certificate store.
|
||||||
|
*
|
||||||
|
* @param context A hx509 context
|
||||||
|
* @param certs A store to destroy
|
||||||
|
*
|
||||||
|
* @return Returns an hx509 error code.
|
||||||
|
*
|
||||||
|
* @ingroup hx509_keyset
|
||||||
|
*/
|
||||||
|
|
||||||
|
HX509_LIB_FUNCTION int HX509_LIB_CALL
|
||||||
|
hx509_certs_destroy(hx509_context context,
|
||||||
|
hx509_certs *certs)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (*certs) {
|
||||||
|
if ((*certs)->ops->destroy)
|
||||||
|
ret = ((*certs)->ops->destroy)(context, *certs, (*certs)->ops_data);
|
||||||
|
else
|
||||||
|
ret = ENOTSUP;
|
||||||
|
}
|
||||||
|
hx509_certs_free(certs);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the certificate store to stable storage.
|
* Write the certificate store to stable storage.
|
||||||
*
|
*
|
||||||
|
@@ -220,6 +220,7 @@ static struct hx509_keyset_ops keyset_dir = {
|
|||||||
dir_iter_end,
|
dir_iter_end,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -664,6 +664,15 @@ file_addkey(hx509_context context,
|
|||||||
return _hx509_certs_keys_add(context, ksf->certs, key);
|
return _hx509_certs_keys_add(context, ksf->certs, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
file_destroy(hx509_context context,
|
||||||
|
hx509_certs certs,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct ks_file *ksf = data;
|
||||||
|
return _hx509_erase_file(context, ksf->fn);
|
||||||
|
}
|
||||||
|
|
||||||
static struct hx509_keyset_ops keyset_file = {
|
static struct hx509_keyset_ops keyset_file = {
|
||||||
"FILE",
|
"FILE",
|
||||||
0,
|
0,
|
||||||
@@ -677,7 +686,8 @@ static struct hx509_keyset_ops keyset_file = {
|
|||||||
file_iter_end,
|
file_iter_end,
|
||||||
NULL,
|
NULL,
|
||||||
file_getkeys,
|
file_getkeys,
|
||||||
file_addkey
|
file_addkey,
|
||||||
|
file_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct hx509_keyset_ops keyset_pemfile = {
|
static struct hx509_keyset_ops keyset_pemfile = {
|
||||||
@@ -693,7 +703,8 @@ static struct hx509_keyset_ops keyset_pemfile = {
|
|||||||
file_iter_end,
|
file_iter_end,
|
||||||
NULL,
|
NULL,
|
||||||
file_getkeys,
|
file_getkeys,
|
||||||
file_addkey
|
file_addkey,
|
||||||
|
file_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct hx509_keyset_ops keyset_derfile = {
|
static struct hx509_keyset_ops keyset_derfile = {
|
||||||
@@ -709,7 +720,8 @@ static struct hx509_keyset_ops keyset_derfile = {
|
|||||||
file_iter_end,
|
file_iter_end,
|
||||||
NULL,
|
NULL,
|
||||||
file_getkeys,
|
file_getkeys,
|
||||||
file_addkey
|
file_addkey,
|
||||||
|
file_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -599,6 +599,7 @@ struct hx509_keyset_ops keyset_keychain = {
|
|||||||
keychain_iter_end,
|
keychain_iter_end,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -213,7 +213,8 @@ static struct hx509_keyset_ops keyset_mem = {
|
|||||||
mem_iter_end,
|
mem_iter_end,
|
||||||
NULL,
|
NULL,
|
||||||
mem_getkeys,
|
mem_getkeys,
|
||||||
mem_addkey
|
mem_addkey,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
HX509_LIB_FUNCTION void HX509_LIB_CALL
|
HX509_LIB_FUNCTION void HX509_LIB_CALL
|
||||||
|
@@ -90,6 +90,7 @@ struct hx509_keyset_ops keyset_null = {
|
|||||||
null_iter_end,
|
null_iter_end,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1208,6 +1208,7 @@ static struct hx509_keyset_ops keyset_pkcs11 = {
|
|||||||
p11_iter_end,
|
p11_iter_end,
|
||||||
p11_printinfo,
|
p11_printinfo,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -697,6 +697,13 @@ p12_iter_end(hx509_context context,
|
|||||||
return hx509_certs_end_seq(context, p12->certs, cursor);
|
return hx509_certs_end_seq(context, p12->certs, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
p12_destroy(hx509_context context, hx509_certs certs, void *data)
|
||||||
|
{
|
||||||
|
struct ks_pkcs12 *p12 = data;
|
||||||
|
return _hx509_erase_file(context, p12->fn);
|
||||||
|
}
|
||||||
|
|
||||||
static struct hx509_keyset_ops keyset_pkcs12 = {
|
static struct hx509_keyset_ops keyset_pkcs12 = {
|
||||||
"PKCS12",
|
"PKCS12",
|
||||||
0,
|
0,
|
||||||
@@ -710,7 +717,8 @@ static struct hx509_keyset_ops keyset_pkcs12 = {
|
|||||||
p12_iter_end,
|
p12_iter_end,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL
|
NULL,
|
||||||
|
p12_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
HX509_LIB_FUNCTION void HX509_LIB_CALL
|
HX509_LIB_FUNCTION void HX509_LIB_CALL
|
||||||
|
@@ -92,6 +92,7 @@ EXPORTS
|
|||||||
hx509_cert_set_friendly_name
|
hx509_cert_set_friendly_name
|
||||||
hx509_certs_add
|
hx509_certs_add
|
||||||
hx509_certs_append
|
hx509_certs_append
|
||||||
|
hx509_certs_destroy
|
||||||
hx509_certs_end_seq
|
hx509_certs_end_seq
|
||||||
hx509_certs_ref
|
hx509_certs_ref
|
||||||
hx509_certs_filter
|
hx509_certs_filter
|
||||||
|
@@ -88,6 +88,7 @@ HEIMDAL_X509_1.2 {
|
|||||||
hx509_certs_add;
|
hx509_certs_add;
|
||||||
hx509_certs_append;
|
hx509_certs_append;
|
||||||
hx509_certs_end_seq;
|
hx509_certs_end_seq;
|
||||||
|
hx509_certs_destroy;
|
||||||
hx509_certs_ref;
|
hx509_certs_ref;
|
||||||
hx509_certs_filter;
|
hx509_certs_filter;
|
||||||
hx509_certs_find;
|
hx509_certs_find;
|
||||||
|
Reference in New Issue
Block a user