|
William Pitcock |
c17d73 |
#define _GNU_SOURCE
|
|
William Pitcock |
c17d73 |
#include <stdio.h>
|
|
William Pitcock |
c17d73 |
#include <stdbool.h>
|
|
William Pitcock |
c17d73 |
#include <string.h>
|
|
William Pitcock |
c17d73 |
#include <stdlib.h>
|
|
William Pitcock |
c17d73 |
#include <dirent.h>
|
|
William Pitcock |
c17d73 |
#include <unistd.h>
|
|
William Pitcock |
c17d73 |
#include <fcntl.h>
|
|
William Pitcock |
c17d73 |
#include <errno.h>
|
|
William Pitcock |
c17d73 |
#include <limits.h>
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
#include <sys/stat.h>
|
|
William Pitcock |
c17d73 |
#include <sys/sendfile.h>
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
|
William Pitcock |
c17d73 |
|
|
Ørjan Malde |
52092e |
#ifndef SYMLINK_MAX
|
|
Ørjan Malde |
52092e |
#ifdef _POSIX_SYMLINK_MAX
|
|
Ørjan Malde |
52092e |
#define SYMLINK_MAX _POSIX_SYMLINK_MAX
|
|
Ørjan Malde |
52092e |
#else
|
|
Ørjan Malde |
52092e |
#define SYMLINK_MAX 255
|
|
Ørjan Malde |
52092e |
#endif
|
|
Ørjan Malde |
52092e |
#endif
|
|
Ørjan Malde |
52092e |
|
|
William Pitcock |
c17d73 |
#define CERTSDIR "/usr/share/ca-certificates/"
|
|
William Pitcock |
c17d73 |
#define LOCALCERTSDIR "/usr/local/share/ca-certificates/"
|
|
William Pitcock |
c17d73 |
#define ETCCERTSDIR "/etc/ssl/certs/"
|
|
William Pitcock |
c17d73 |
#define CERTBUNDLE "ca-certificates.crt"
|
|
William Pitcock |
c17d73 |
#define CERTSCONF "/etc/ca-certificates.conf"
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
static const char *last_component(const char *path)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
const char *c = strrchr(path, '/');
|
|
William Pitcock |
c17d73 |
if (c) return c + 1;
|
|
William Pitcock |
c17d73 |
return path;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
static bool str_begins(const char* str, const char* prefix)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
return !strncmp(str, prefix, strlen(prefix));
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
struct hash_item {
|
|
William Pitcock |
c17d73 |
struct hash_item *next;
|
|
William Pitcock |
c17d73 |
char *key;
|
|
William Pitcock |
c17d73 |
char *value;
|
|
William Pitcock |
c17d73 |
};
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
struct hash {
|
|
William Pitcock |
c17d73 |
struct hash_item *items[256];
|
|
William Pitcock |
c17d73 |
};
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
static unsigned int hash_string(const char *str)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
unsigned long h = 5381;
|
|
William Pitcock |
c17d73 |
for (; *str; str++)
|
|
William Pitcock |
c17d73 |
h = (h << 5) + h + *str;
|
|
William Pitcock |
c17d73 |
return h;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
static void hash_init(struct hash *h)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
memset(h, 0, sizeof *h);
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
static struct hash_item *hash_get(struct hash *h, const char *key)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
unsigned int bucket = hash_string(key) % ARRAY_SIZE(h->items);
|
|
William Pitcock |
c17d73 |
struct hash_item *item;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
for (item = h->items[bucket]; item; item = item->next)
|
|
William Pitcock |
c17d73 |
if (strcmp(item->key, key) == 0)
|
|
William Pitcock |
c17d73 |
return item;
|
|
William Pitcock |
c17d73 |
return NULL;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
static void hash_foreach(struct hash *h, void (*cb)(struct hash_item *))
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
struct hash_item *item;
|
|
James Larrowe |
b007d0 |
size_t i;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
for (i = 0; i < ARRAY_SIZE(h->items); i++) {
|
|
William Pitcock |
c17d73 |
for (item = h->items[i]; item; item = item->next)
|
|
William Pitcock |
c17d73 |
cb(item);
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
static bool hash_add(struct hash *h, const char *key, const char *value)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
unsigned int bucket = hash_string(key) % ARRAY_SIZE(h->items);
|
|
William Pitcock |
c17d73 |
size_t keylen = strlen(key), valuelen = strlen(value);
|
|
William Pitcock |
c17d73 |
struct hash_item *i;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
i = malloc(sizeof(struct hash_item) + keylen + 1 + valuelen + 1);
|
|
William Pitcock |
c17d73 |
if (!i)
|
|
William Pitcock |
c17d73 |
return false;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
i->key = (char*)(i+1);
|
|
William Pitcock |
c17d73 |
strcpy(i->key, key);
|
|
William Pitcock |
c17d73 |
i->value = i->key + keylen + 1;
|
|
William Pitcock |
c17d73 |
strcpy(i->value, value);
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
i->next = h->items[bucket];
|
|
William Pitcock |
c17d73 |
h->items[bucket] = i;
|
|
William Pitcock |
c17d73 |
return true;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
static ssize_t
|
|
William Pitcock |
c17d73 |
buffered_copyfd(int in_fd, int out_fd, ssize_t in_size)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
const size_t bufsize = 8192;
|
|
William Pitcock |
c17d73 |
char *buf = NULL;
|
|
James Larrowe |
b007d0 |
ssize_t r = 0, w = 0, copied = 0, n;
|
|
William Pitcock |
c17d73 |
if ((buf = malloc(bufsize)) == NULL)
|
|
William Pitcock |
c17d73 |
return -1;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
while (r < in_size && (n = read(in_fd, buf, bufsize))) {
|
|
William Pitcock |
c17d73 |
if (n == -1) {
|
|
William Pitcock |
c17d73 |
if (errno == EINTR)
|
|
William Pitcock |
c17d73 |
continue;
|
|
William Pitcock |
c17d73 |
break;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
r = n;
|
|
William Pitcock |
c17d73 |
w = 0;
|
|
William Pitcock |
c17d73 |
while (w < r && (n = write(out_fd, buf + w, (r - w)))) {
|
|
William Pitcock |
c17d73 |
if (n == -1) {
|
|
William Pitcock |
c17d73 |
if (errno == EINTR)
|
|
William Pitcock |
c17d73 |
continue;
|
|
William Pitcock |
c17d73 |
break;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
w += n;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
copied += w;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
free(buf);
|
|
William Pitcock |
c17d73 |
return copied;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
static bool
|
|
William Pitcock |
c17d73 |
copyfile(const char* source, int output)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
off_t bytes = 0;
|
|
William Pitcock |
c17d73 |
struct stat fileinfo = {0};
|
|
William Pitcock |
c17d73 |
ssize_t result;
|
|
William Pitcock |
c17d73 |
int in_fd;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
if ((in_fd = open(source, O_RDONLY)) == -1)
|
|
William Pitcock |
c17d73 |
return false;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
if (fstat(in_fd, &fileinfo) < 0) {
|
|
William Pitcock |
c17d73 |
close(in_fd);
|
|
William Pitcock |
c17d73 |
return false;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
result = sendfile(output, in_fd, &bytes, fileinfo.st_size);
|
|
William Pitcock |
c17d73 |
if ((result == -1) && (errno == EINVAL || errno == ENOSYS))
|
|
William Pitcock |
c17d73 |
result = buffered_copyfd(in_fd, output, fileinfo.st_size);
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
close(in_fd);
|
|
William Pitcock |
c17d73 |
return fileinfo.st_size == result;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
typedef void (*proc_path)(const char *fullpath, struct hash *, int);
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
static void proc_localglobaldir(const char *fullpath, struct hash *h, int tmpfile_fd)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
const char *fname = last_component(fullpath);
|
|
William Pitcock |
c17d73 |
size_t flen = strlen(fname);
|
|
William Pitcock |
c17d73 |
char *s, *actual_file = NULL;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
/* Snip off the .crt suffix */
|
|
William Pitcock |
c17d73 |
if (flen > 4 && strcmp(&fname[flen-4], ".crt") == 0)
|
|
William Pitcock |
c17d73 |
flen -= 4;
|
|
William Pitcock |
c17d73 |
|
|
James Larrowe |
b007d0 |
if (flen > INT_MAX) {
|
|
James Larrowe |
b007d0 |
fprintf(stderr, "File name too long: %zu\n", flen);
|
|
James Larrowe |
b007d0 |
return;
|
|
James Larrowe |
b007d0 |
}
|
|
James Larrowe |
b007d0 |
|
|
William Pitcock |
c17d73 |
if (asprintf(&actual_file, "%s%.*s%s",
|
|
William Pitcock |
c17d73 |
"ca-cert-",
|
|
James Larrowe |
b007d0 |
(int)flen, fname,
|
|
William Pitcock |
c17d73 |
".pem") == -1) {
|
|
William Pitcock |
c17d73 |
fprintf(stderr, "Cannot open path: %s\n", fullpath);
|
|
William Pitcock |
c17d73 |
return;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
for (s = actual_file; *s; s++) {
|
|
William Pitcock |
c17d73 |
switch(*s) {
|
|
William Pitcock |
c17d73 |
case ',':
|
|
William Pitcock |
c17d73 |
case ' ':
|
|
William Pitcock |
c17d73 |
*s = '_';
|
|
William Pitcock |
c17d73 |
break;
|
|
William Pitcock |
c17d73 |
case ')':
|
|
William Pitcock |
c17d73 |
case '(':
|
|
William Pitcock |
c17d73 |
*s = '=';
|
|
William Pitcock |
c17d73 |
break;
|
|
William Pitcock |
c17d73 |
default:
|
|
William Pitcock |
c17d73 |
break;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
if (!hash_add(h, actual_file, fullpath))
|
|
William Pitcock |
c17d73 |
fprintf(stderr, "Warning! Cannot hash: %s\n", fullpath);
|
|
William Pitcock |
c17d73 |
if (!copyfile(fullpath, tmpfile_fd))
|
|
William Pitcock |
c17d73 |
fprintf(stderr, "Warning! Cannot copy to bundle: %s\n", fullpath);
|
|
William Pitcock |
c17d73 |
free(actual_file);
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
static void proc_etccertsdir(const char* fullpath, struct hash* h, int tmpfile_fd)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
char linktarget[SYMLINK_MAX];
|
|
William Pitcock |
c17d73 |
ssize_t linklen;
|
|
William Pitcock |
c17d73 |
|
|
James Larrowe |
b007d0 |
(void)tmpfile_fd;
|
|
James Larrowe |
b007d0 |
|
|
William Pitcock |
c17d73 |
linklen = readlink(fullpath, linktarget, sizeof(linktarget)-1);
|
|
William Pitcock |
c17d73 |
if (linklen < 0)
|
|
William Pitcock |
c17d73 |
return;
|
|
William Pitcock |
c17d73 |
linktarget[linklen] = 0;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
struct hash_item *item = hash_get(h, last_component(fullpath));
|
|
William Pitcock |
c17d73 |
if (!item) {
|
|
William Pitcock |
c17d73 |
/* Symlink exists but is not wanted
|
|
William Pitcock |
c17d73 |
* Delete it if it points to 'our' directory
|
|
William Pitcock |
c17d73 |
*/
|
|
William Pitcock |
c17d73 |
if (str_begins(linktarget, CERTSDIR) || str_begins(linktarget, LOCALCERTSDIR))
|
|
William Pitcock |
c17d73 |
unlink(fullpath);
|
|
William Pitcock |
c17d73 |
} else if (strcmp(linktarget, item->value) != 0) {
|
|
William Pitcock |
c17d73 |
/* Symlink exists but points wrong */
|
|
William Pitcock |
c17d73 |
unlink(fullpath);
|
|
William Pitcock |
c17d73 |
if (symlink(item->value, fullpath) < 0)
|
|
William Pitcock |
c17d73 |
fprintf(stderr, "Warning! Cannot update symlink %s -> %s\n", item->value, fullpath);
|
|
William Pitcock |
c17d73 |
item->value = 0;
|
|
William Pitcock |
c17d73 |
} else {
|
|
William Pitcock |
c17d73 |
/* Symlink exists and is ok */
|
|
William Pitcock |
c17d73 |
item->value = 0;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
static bool read_global_ca_list(const char* file, struct hash* d, int tmpfile_fd)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
FILE * fp = fopen(file, "r");
|
|
William Pitcock |
c17d73 |
if (fp == NULL)
|
|
William Pitcock |
c17d73 |
return false;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
char * line = NULL;
|
|
William Pitcock |
c17d73 |
size_t len = 0;
|
|
William Pitcock |
c17d73 |
ssize_t read;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
while ((read = getline(&line, &len, fp)) != -1) {
|
|
William Pitcock |
c17d73 |
/* getline returns number of bytes in buffer, and buffer
|
|
William Pitcock |
c17d73 |
* contains delimeter if it was found */
|
|
William Pitcock |
c17d73 |
if (read > 0 && line[read-1] == '\n')
|
|
William Pitcock |
c17d73 |
line[read-1] = 0;
|
|
William Pitcock |
c17d73 |
if (str_begins(line, "#") || str_begins(line, "!"))
|
|
William Pitcock |
c17d73 |
continue;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
char* fullpath = 0;
|
|
William Pitcock |
c17d73 |
if (asprintf(&fullpath,"%s%s", CERTSDIR, line) != -1) {
|
|
William Pitcock |
c17d73 |
proc_localglobaldir(fullpath, d, tmpfile_fd);
|
|
William Pitcock |
c17d73 |
free(fullpath);
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
fclose(fp);
|
|
William Pitcock |
c17d73 |
free(line);
|
|
William Pitcock |
c17d73 |
return true;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
static bool dir_readfiles(struct hash* d, const char* path,
|
|
William Pitcock |
c17d73 |
proc_path path_processor,
|
|
William Pitcock |
c17d73 |
int tmpfile_fd)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
DIR *dp = opendir(path);
|
|
William Pitcock |
c17d73 |
if (!dp)
|
|
William Pitcock |
c17d73 |
return false;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
struct dirent *dirp;
|
|
William Pitcock |
c17d73 |
while ((dirp = readdir(dp)) != NULL) {
|
|
William Pitcock |
c17d73 |
if (str_begins(dirp->d_name, "."))
|
|
William Pitcock |
c17d73 |
continue;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
char* fullpath = 0;
|
|
William Pitcock |
c17d73 |
if (asprintf(&fullpath, "%s%s", path, dirp->d_name) != -1) {
|
|
William Pitcock |
69215d |
path_processor(fullpath, d, tmpfile_fd);
|
|
William Pitcock |
c17d73 |
free(fullpath);
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
return closedir(dp) == 0;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
static void update_ca_symlink(struct hash_item *item)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
if (!item->value)
|
|
William Pitcock |
c17d73 |
return;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
char* newpath = 0;
|
|
William Pitcock |
c17d73 |
bool build_str = asprintf(&newpath, "%s%s", ETCCERTSDIR, item->key);
|
|
William Pitcock |
c17d73 |
if (!build_str || symlink(item->value, newpath) == -1)
|
|
William Pitcock |
c17d73 |
fprintf(stderr, "Warning! Cannot symlink %s -> %s\n",
|
|
William Pitcock |
c17d73 |
item->value, newpath);
|
|
William Pitcock |
c17d73 |
free(newpath);
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
James Larrowe |
b007d0 |
int main(void)
|
|
William Pitcock |
c17d73 |
{
|
|
William Pitcock |
c17d73 |
struct hash _calinks, *calinks = &_calinks;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
const char* bundle = "bundleXXXXXX";
|
|
William Pitcock |
c17d73 |
char* tmpfile = 0;
|
|
William Pitcock |
c17d73 |
if (asprintf(&tmpfile, "%s%s", ETCCERTSDIR, bundle) == -1)
|
|
William Pitcock |
c17d73 |
return 1;
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
int fd = mkstemp(tmpfile);
|
|
William Pitcock |
c17d73 |
if (fd == -1) {
|
|
William Pitcock |
c17d73 |
fprintf(stderr, "Failed to open temporary file %s for ca bundle\n", tmpfile);
|
|
William Pitcock |
c17d73 |
return 1;
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
fchmod(fd, 0644);
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
hash_init(calinks);
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
/* Handle global CA certs from config file */
|
|
William Pitcock |
c17d73 |
read_global_ca_list(CERTSCONF, calinks, fd);
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
/* Handle local CA certificates */
|
|
William Pitcock |
69215d |
dir_readfiles(calinks, LOCALCERTSDIR, &proc_localglobaldir, fd);
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
/* Update etc cert dir for additions and deletions*/
|
|
William Pitcock |
69215d |
dir_readfiles(calinks, ETCCERTSDIR, &proc_etccertsdir, fd);
|
|
William Pitcock |
c17d73 |
hash_foreach(calinks, update_ca_symlink);
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
/* Update hashes and the bundle */
|
|
William Pitcock |
c17d73 |
if (fd != -1) {
|
|
William Pitcock |
c17d73 |
close(fd);
|
|
William Pitcock |
c17d73 |
char* newcertname = 0;
|
|
William Pitcock |
c17d73 |
if (asprintf(&newcertname, "%s%s", ETCCERTSDIR, CERTBUNDLE) != -1) {
|
|
William Pitcock |
c17d73 |
rename(tmpfile, newcertname);
|
|
William Pitcock |
c17d73 |
free(newcertname);
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
}
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
free(tmpfile);
|
|
William Pitcock |
c17d73 |
|
|
|
a41afd |
/* Execute c_rehash */
|
|
|
a41afd |
static char *const exec_args[] = {"c_rehash", ETCCERTSDIR, 0};
|
|
|
a41afd |
execv("/usr/bin/c_rehash", exec_args);
|
|
|
a41afd |
execv("/bin/c_rehash", exec_args);
|
|
|
a41afd |
perror("c_rehash");
|
|
William Pitcock |
c17d73 |
|
|
William Pitcock |
c17d73 |
return 1;
|
|
William Pitcock |
c17d73 |
}
|