summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
Diffstat (limited to 'sbin')
-rw-r--r--sbin/isakmpd/Makefile4
-rw-r--r--sbin/isakmpd/conf.c4
-rw-r--r--sbin/isakmpd/conf.h8
-rw-r--r--sbin/isakmpd/if.c4
-rw-r--r--sbin/isakmpd/ike_auth.c64
-rw-r--r--sbin/isakmpd/isakmpd.c27
-rw-r--r--sbin/isakmpd/log.c7
-rw-r--r--sbin/isakmpd/monitor.c543
-rw-r--r--sbin/isakmpd/monitor.h39
-rw-r--r--sbin/isakmpd/policy.c6
-rw-r--r--sbin/isakmpd/sa.c5
-rw-r--r--sbin/isakmpd/udp.c8
-rw-r--r--sbin/isakmpd/ui.c7
-rw-r--r--sbin/isakmpd/x509.c63
14 files changed, 639 insertions, 150 deletions
diff --git a/sbin/isakmpd/Makefile b/sbin/isakmpd/Makefile
index eaae2825d05..1a740e9d80a 100644
--- a/sbin/isakmpd/Makefile
+++ b/sbin/isakmpd/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.50 2003/08/28 14:43:35 markus Exp $
+# $OpenBSD: Makefile,v 1.51 2004/03/19 14:04:43 hshoexer Exp $
# $EOM: Makefile,v 1.78 2000/10/15 21:33:42 niklas Exp $
#
@@ -50,7 +50,7 @@ OS= openbsd
#FEATURES+= rawkey isakmp_cfg dnssec privsep
FEATURES= tripledes des blowfish cast aes
FEATURES+= policy x509 ec aggressive debug
-FEATURES+= rawkey isakmp_cfg
+FEATURES+= rawkey isakmp_cfg privsep
.PATH: ${.CURDIR}/sysdep/${OS}
diff --git a/sbin/isakmpd/conf.c b/sbin/isakmpd/conf.c
index de4e2144579..bb929315f38 100644
--- a/sbin/isakmpd/conf.c
+++ b/sbin/isakmpd/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.61 2004/02/27 19:07:16 hshoexer Exp $ */
+/* $OpenBSD: conf.c,v 1.62 2004/03/19 14:04:43 hshoexer Exp $ */
/* $EOM: conf.c,v 1.48 2000/12/04 02:04:29 angelos Exp $ */
/*
@@ -585,7 +585,7 @@ conf_reinit (void)
char *new_conf_addr = 0;
struct stat sb;
- if ((stat (conf_path, &sb) == 0) || (errno != ENOENT))
+ if ((monitor_stat (conf_path, &sb) == 0) || (errno != ENOENT))
{
if (check_file_secrecy (conf_path, &sz))
return;
diff --git a/sbin/isakmpd/conf.h b/sbin/isakmpd/conf.h
index fd886311498..e46d4c30046 100644
--- a/sbin/isakmpd/conf.h
+++ b/sbin/isakmpd/conf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.h,v 1.24 2003/06/03 14:28:16 ho Exp $ */
+/* $OpenBSD: conf.h,v 1.25 2004/03/19 14:04:43 hshoexer Exp $ */
/* $EOM: conf.h,v 1.13 2000/09/18 00:01:47 ho Exp $ */
/*
@@ -38,11 +38,7 @@
#include <sys/socket.h>
#include <stdio.h>
-#if !defined (USE_PRIVSEP)
-# define ISAKMPD_ROOT "/etc/isakmpd/"
-#else
-# define ISAKMPD_ROOT ""
-#endif
+#define ISAKMPD_ROOT "/etc/isakmpd/"
#define CONFIG_FILE ISAKMPD_ROOT "isakmpd.conf"
diff --git a/sbin/isakmpd/if.c b/sbin/isakmpd/if.c
index 3794928f7c0..ab67ae42f01 100644
--- a/sbin/isakmpd/if.c
+++ b/sbin/isakmpd/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.16 2003/11/06 16:12:07 ho Exp $ */
+/* $OpenBSD: if.c,v 1.17 2004/03/19 14:04:43 hshoexer Exp $ */
/* $EOM: if.c,v 1.12 1999/10/01 13:45:20 niklas Exp $ */
/*
@@ -65,7 +65,7 @@ siocgifconf (struct ifconf *ifcp)
caddr_t buf, new_buf;
/* Get a socket to ask for the network interface configurations. */
- s = socket (AF_INET, SOCK_DGRAM, 0);
+ s = monitor_socket (AF_INET, SOCK_DGRAM, 0);
if (s == -1)
{
log_error ("siocgifconf: socket (AF_INET, SOCK_DGRAM, 0) failed");
diff --git a/sbin/isakmpd/ike_auth.c b/sbin/isakmpd/ike_auth.c
index bbd5453e381..05e0c2245c9 100644
--- a/sbin/isakmpd/ike_auth.c
+++ b/sbin/isakmpd/ike_auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ike_auth.c,v 1.82 2004/03/17 11:10:06 ho Exp $ */
+/* $OpenBSD: ike_auth.c,v 1.83 2004/03/19 14:04:43 hshoexer Exp $ */
/* $EOM: ike_auth.c,v 1.59 2000/11/21 00:21:31 angelos Exp $ */
/*
@@ -143,7 +143,11 @@ ike_auth_get_key (int type, char *id, char *local_id, size_t *keylen)
#if defined (USE_X509) || defined (USE_KEYNOTE)
char *keyfile;
#if defined (USE_X509)
+#if defined (USE_PRIVSEP)
+ FILE *keyfp;
+#else
BIO *keyh;
+#endif
RSA *rsakey;
size_t fsize;
#endif
@@ -223,14 +227,14 @@ ike_auth_get_key (int type, char *id, char *local_id, size_t *keylen)
PRIVATE_KEY_FILE);
keyfile = privkeyfile;
- if (stat (keyfile, &sb) < 0)
+ if (monitor_stat (keyfile, &sb) < 0)
{
free (keyfile);
goto ignorekeynote;
}
size = (size_t)sb.st_size;
- fd = open (keyfile, O_RDONLY, 0);
+ fd = monitor_open (keyfile, O_RDONLY, 0);
if (fd < 0)
{
log_print ("ike_auth_get_key: failed opening \"%s\"", keyfile);
@@ -296,6 +300,20 @@ ike_auth_get_key (int type, char *id, char *local_id, size_t *keylen)
if (check_file_secrecy (keyfile, &fsize))
return 0;
+#if defined (USE_PRIVSEP)
+ keyfp = monitor_fopen (keyfile, "r");
+ if (!keyfp)
+ {
+ log_print ("ike_auth_get_key: failed opening \"%s\"", keyfile);
+ return 0;
+ }
+#if SSLEAY_VERSION_NUMBER >= 0x00904100L
+ rsakey = PEM_read_RSAPrivateKey (keyfp, NULL, NULL, NULL);
+#else
+ rsakey = PEM_read_RSAPrivateKey (keyfp, NULL, NULL);
+#endif
+ fclose (keyfp);
+#else
keyh = BIO_new (BIO_s_file ());
if (keyh == NULL)
{
@@ -318,6 +336,8 @@ ike_auth_get_key (int type, char *id, char *local_id, size_t *keylen)
rsakey = PEM_read_bio_RSAPrivateKey (keyh, NULL, NULL);
#endif
BIO_free (keyh);
+#endif /* USE_PRIVSEP */
+
if (!rsakey)
{
log_print ("ike_auth_get_key: PEM_read_bio_RSAPrivateKey failed");
@@ -1052,13 +1072,6 @@ rsa_sig_encode_hash (struct message *msg)
"SA acquisition subsystem");
return 0;
}
-#if defined (USE_PRIVSEP)
- {
- /* With USE_PRIVSEP, the sent_key should be a key number. */
- void *key = sent_key;
- sent_key = monitor_RSA_upload_key (key);
- }
-#endif
}
else /* Try through the regular means. */
{
@@ -1094,12 +1107,8 @@ rsa_sig_encode_hash (struct message *msg)
return 0;
}
-#if defined (USE_PRIVSEP)
- sent_key = monitor_RSA_get_private_key (exchange->name, (char *)buf2);
-#else
sent_key = ike_auth_get_key (IKE_AUTH_RSA_SIG, exchange->name,
(char *)buf2, 0);
-#endif
free (buf2);
/* Did we find a key? */
@@ -1110,14 +1119,12 @@ rsa_sig_encode_hash (struct message *msg)
}
}
-#if !defined (USE_PRIVSEP)
/* Enable RSA blinding. */
if (RSA_blinding_on (sent_key, NULL) != 1)
{
log_error ("rsa_sig_encode_hash: RSA_blinding_on () failed.");
return -1;
}
-#endif
/* XXX hashsize is not necessarily prf->blocksize. */
buf = malloc (hashsize);
@@ -1138,7 +1145,6 @@ rsa_sig_encode_hash (struct message *msg)
initiator ? 'I' : 'R');
LOG_DBG_BUF ((LOG_MISC, 80, header, buf, hashsize));
-#if !defined (USE_PRIVSEP)
data = malloc (RSA_size (sent_key));
if (!data)
{
@@ -1149,17 +1155,13 @@ rsa_sig_encode_hash (struct message *msg)
datalen = RSA_private_encrypt (hashsize, buf, data, sent_key,
RSA_PKCS1_PADDING);
-#else
- datalen = monitor_RSA_private_encrypt (hashsize, buf, &data, sent_key,
- RSA_PKCS1_PADDING);
-#endif /* USE_PRIVSEP */
if (datalen == -1)
{
log_print ("rsa_sig_encode_hash: RSA_private_encrypt () failed");
if (data)
free (data);
free (buf);
- monitor_RSA_free (sent_key);
+ RSA_free (sent_key);
return -1;
}
@@ -1233,7 +1235,11 @@ get_raw_key_from_file (int type, u_int8_t *id, size_t id_len, RSA **rsa)
char filename[FILENAME_MAX];
char *fstr;
struct stat st;
+#if defined (USE_PRIVSEP)
+ FILE *keyfp;
+#else
BIO *bio;
+#endif
if (type != IKE_AUTH_RSA_SIG) /* XXX More types? */
{
@@ -1262,8 +1268,19 @@ get_raw_key_from_file (int type, u_int8_t *id, size_t id_len, RSA **rsa)
free (fstr);
/* If the file does not exist, fail silently. */
- if (stat (filename, &st) == 0)
+ if (monitor_stat (filename, &st) == 0)
{
+#if defined (USE_PRIVSEP)
+ keyfp = monitor_fopen (filename, "r");
+ if (!keyfp)
+ {
+ log_error ("get_raw_key_from_file: monitor_fopen (\"%s\", \"r\") "
+ "failed", filename);
+ return -1;
+ }
+ *rsa = PEM_read_RSA_PUBKEY (keyfp, NULL, NULL, NULL);
+ fclose (keyfp);
+#else
bio = BIO_new (BIO_s_file ());
if (!bio)
{
@@ -1281,6 +1298,7 @@ get_raw_key_from_file (int type, u_int8_t *id, size_t id_len, RSA **rsa)
filename));
*rsa = PEM_read_bio_RSA_PUBKEY (bio, NULL, NULL, NULL);
BIO_free (bio);
+#endif /* USE_PRIVSEP */
}
else
LOG_DBG ((LOG_NEGOTIATION, 50, "get_raw_key_from_file: file %s not found",
diff --git a/sbin/isakmpd/isakmpd.c b/sbin/isakmpd/isakmpd.c
index d7e5f7c1005..ec6a0cd0351 100644
--- a/sbin/isakmpd/isakmpd.c
+++ b/sbin/isakmpd/isakmpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isakmpd.c,v 1.57 2004/02/19 15:35:16 hshoexer Exp $ */
+/* $OpenBSD: isakmpd.c,v 1.58 2004/03/19 14:04:43 hshoexer Exp $ */
/* $EOM: isakmpd.c,v 1.54 2000/10/05 09:28:22 niklas Exp $ */
/*
@@ -363,11 +363,16 @@ main (int argc, char *argv[])
size_t mask_size;
struct timeval tv, *timeout;
+ closefrom (STDERR_FILENO + 1);
+
/* Make sure init() won't alloc fd 0, 1 or 2, as daemon() will close them. */
for (n = 0; n <= 2; n++)
if (fcntl (n, F_GETFL, 0) == -1 && errno == EBADF)
(void)open ("/dev/null", n ? O_WRONLY : O_RDONLY, 0);
+ for (n = 1; n < _NSIG; n++)
+ signal (n, SIG_DFL);
+
/* Log cmd line parsing and initialization errors to stderr. */
log_to (stderr);
parse_args (argc, argv);
@@ -381,15 +386,15 @@ main (int argc, char *argv[])
if (debug == 1) /* i.e '-dd' will skip this. */
signal (SIGINT, daemon_shutdown_now);
+ /* Daemonize before forking unpriv'ed child */
+ if (!debug)
+ if (daemon (0, 0))
+ log_fatal ("main: daemon (0, 0) failed");
+
#if defined (USE_PRIVSEP)
if (monitor_init ())
{
- /* The parent, with privileges. */
- if (!debug)
- if (daemon (0, 0))
- log_fatal ("main [priv]: daemon (0, 0) failed");
-
- /* Enter infinite monitor loop. */
+ /* The parent, with privileges enters infinite monitor loop. */
monitor_loop (debug);
exit (0); /* Never reached. */
}
@@ -399,10 +404,6 @@ main (int argc, char *argv[])
init ();
- if (!debug)
- if (daemon (0, 0))
- log_fatal ("main: daemon (0, 0) failed");
-
write_pid_file ();
/* Reinitialize on HUP reception. */
@@ -430,6 +431,10 @@ main (int argc, char *argv[])
if (!wfds)
log_fatal ("main: malloc (%lu) failed", (unsigned long)mask_size);
+#if defined (USE_PRIVSEP)
+ monitor_init_done();
+#endif
+
while (1)
{
/* If someone has sent SIGHUP to us, reconfigure. */
diff --git a/sbin/isakmpd/log.c b/sbin/isakmpd/log.c
index fcc9c217841..5aea77ef993 100644
--- a/sbin/isakmpd/log.c
+++ b/sbin/isakmpd/log.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.c,v 1.40 2004/02/25 16:01:28 hshoexer Exp $ */
+/* $OpenBSD: log.c,v 1.41 2004/03/19 14:04:43 hshoexer Exp $ */
/* $EOM: log.c,v 1.30 2000/09/29 08:19:23 niklas Exp $ */
/*
@@ -427,7 +427,12 @@ log_packet_init (char *newname)
}
/* Does the file already exist? XXX lstat() or stat()? */
+#if defined (USE_PRIVSEP)
+ /* XXX This is a fstat! */
+ if (monitor_stat (pcaplog_file, &st) == 0)
+#else
if (lstat (pcaplog_file, &st) == 0)
+#endif
{
/* Sanity checks. */
if ((st.st_mode & S_IFMT) != S_IFREG)
diff --git a/sbin/isakmpd/monitor.c b/sbin/isakmpd/monitor.c
index 49983820dc4..3120054a343 100644
--- a/sbin/isakmpd/monitor.c
+++ b/sbin/isakmpd/monitor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.12 2004/03/15 16:34:28 hshoexer Exp $ */
+/* $OpenBSD: monitor.c,v 1.13 2004/03/19 14:04:43 hshoexer Exp $ */
/*
* Copyright (c) 2003 Håkan Olsson. All rights reserved.
@@ -30,6 +30,7 @@
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
+#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
@@ -57,7 +58,11 @@ struct monitor_state
} m_state;
volatile sig_atomic_t sigchlded = 0;
+volatile sig_atomic_t monitor_sighupped = 0;
extern volatile sig_atomic_t sigtermed;
+static volatile sig_atomic_t cur_state = STATE_INIT;
+
+extern char *ui_fifo;
/* Private functions. */
int m_write_int32 (int, int32_t);
@@ -66,12 +71,16 @@ int m_read_int32 (int, int32_t *);
int m_read_raw (int, char *, size_t);
void m_flush (int);
-void m_priv_getfd (int);
-void m_priv_getsocket (int);
-void m_priv_setsockopt (int);
-void m_priv_bind (int);
-void m_priv_mkfifo (int);
-void m_priv_local_sanitize_path (char *, size_t, int);
+static void m_priv_getfd (int);
+static void m_priv_getsocket (int);
+static void m_priv_setsockopt (int);
+static void m_priv_bind (int);
+static void m_priv_mkfifo (int);
+static int m_priv_local_sanitize_path (char *, size_t, int);
+static int m_priv_check_sockopt (int, int);
+static int m_priv_check_bind (const struct sockaddr *, socklen_t);
+static void m_priv_increase_state (int);
+static void m_priv_test_state (int);
/*
* Public functions, unprivileged.
@@ -127,14 +136,9 @@ int
monitor_open (const char *path, int flags, mode_t mode)
{
int fd, mode32 = (int32_t) mode;
+ int32_t err;
char realpath[MAXPATHLEN];
- if (m_state.pid)
- {
- /* Called from the parent, i.e already privileged. */
- return open (path, flags, mode);
- }
-
if (path[0] == '/')
strlcpy (realpath, path, sizeof realpath);
else
@@ -153,12 +157,21 @@ monitor_open (const char *path, int flags, mode_t mode)
if (m_write_int32 (m_state.s, mode32))
goto errout;
+ if (m_read_int32 (m_state.s, &err))
+ goto errout;
+
+ if (err != 0)
+ {
+ errno = (int)err;
+ return -1;
+ }
/* Wait for response. */
fd = mm_receive_fd (m_state.s);
if (fd < 0)
{
- log_error ("monitor_open: open(\"%s\") failed", path);
+ log_error ("monitor_open: mm_receive_fd () failed: %s",
+ strerror (errno));
return -1;
}
@@ -173,7 +186,7 @@ FILE *
monitor_fopen (const char *path, const char *mode)
{
FILE *fp;
- int fd, flags = 0, umask = 0;
+ int fd, flags = 0, mask, saved_errno;
/* Only the child process is supposed to run this. */
if (m_state.pid)
@@ -194,7 +207,9 @@ monitor_fopen (const char *path, const char *mode)
log_fatal ("monitor_fopen: bad call");
}
- fd = monitor_open (path, flags, umask);
+ mask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+
+ fd = monitor_open (path, flags, mask);
if (fd < 0)
return NULL;
@@ -203,7 +218,9 @@ monitor_fopen (const char *path, const char *mode)
if (!fp)
{
log_error ("monitor_fopen: fdopen() failed");
+ saved_errno = errno;
close (fd);
+ errno = saved_errno;
return NULL;
}
@@ -215,12 +232,10 @@ monitor_stat (const char *path, struct stat *sb)
{
int fd, r, saved_errno;
- fd = monitor_open (path, O_RDONLY, 0);
+ /* O_NONBLOCK is needed for stat'ing fifos. */
+ fd = monitor_open (path, O_RDONLY | O_NONBLOCK, 0);
if (fd < 0)
- {
- errno = EACCES; /* A good guess? */
return -1;
- }
r = fstat (fd, sb);
saved_errno = errno;
@@ -233,6 +248,7 @@ int
monitor_socket (int domain, int type, int protocol)
{
int s;
+ int32_t err;
if (m_write_int32 (m_state.s, MONITOR_GET_SOCKET))
goto errout;
@@ -246,9 +262,23 @@ monitor_socket (int domain, int type, int protocol)
if (m_write_int32 (m_state.s, (int32_t)protocol))
goto errout;
+ if (m_read_int32 (m_state.s, &err))
+ goto errout;
+
+ if (err != 0)
+ {
+ errno = (int)err;
+ return -1;
+ }
/* Read result. */
s = mm_receive_fd (m_state.s);
+ if (s < 0)
+ {
+ log_error ("monitor_socket: mm_receive_fd () failed: %s",
+ strerror (errno));
+ return -1;
+ }
return s;
@@ -261,11 +291,12 @@ int
monitor_setsockopt (int s, int level, int optname, const void *optval,
socklen_t optlen)
{
- int ret;
+ int32_t ret, err;
if (m_write_int32 (m_state.s, MONITOR_SETSOCKOPT))
goto errout;
- mm_send_fd (m_state.s, s); /* XXX? */
+ if (mm_send_fd (m_state.s, s))
+ goto errout;
if (m_write_int32 (m_state.s, (int32_t)level))
goto errout;
@@ -276,10 +307,16 @@ monitor_setsockopt (int s, int level, int optname, const void *optval,
if (m_write_raw (m_state.s, (char *)optval, (size_t)optlen))
goto errout;
+ if (m_read_int32 (m_state.s, &err))
+ goto errout;
+
+ if (err != 0)
+ errno = (int)err;
+
if (m_read_int32 (m_state.s, &ret))
goto errout;
- return ret;
+ return (int)ret;
errout:
log_print ("monitor_setsockopt: read/write error");
@@ -289,21 +326,28 @@ monitor_setsockopt (int s, int level, int optname, const void *optval,
int
monitor_bind (int s, const struct sockaddr *name, socklen_t namelen)
{
- int ret;
+ int32_t ret, err;
if (m_write_int32 (m_state.s, MONITOR_BIND))
goto errout;
- mm_send_fd (m_state.s, s);
+ if (mm_send_fd (m_state.s, s))
+ goto errout;
if (m_write_int32 (m_state.s, (int32_t)namelen))
goto errout;
if (m_write_raw (m_state.s, (char *)name, (size_t)namelen))
goto errout;
+ if (m_read_int32 (m_state.s, &err))
+ goto errout;
+
+ if (err != 0)
+ errno = (int)err;
+
if (m_read_int32 (m_state.s, &ret))
goto errout;
- return ret;
+ return (int)ret;
errout:
log_print ("monitor_bind: read/write error");
@@ -313,7 +357,7 @@ monitor_bind (int s, const struct sockaddr *name, socklen_t namelen)
int
monitor_mkfifo (const char *path, mode_t mode)
{
- int32_t ret;
+ int32_t ret, err;
char realpath[MAXPATHLEN];
/* Only the child process is supposed to run this. */
@@ -335,6 +379,12 @@ monitor_mkfifo (const char *path, mode_t mode)
if (m_write_int32 (m_state.s, ret))
goto errout;
+ if (m_read_int32 (m_state.s, &err))
+ goto errout;
+
+ if (err != 0)
+ errno = (int)err;
+
if (m_read_int32 (m_state.s, &ret))
goto errout;
@@ -345,23 +395,151 @@ monitor_mkfifo (const char *path, mode_t mode)
return -1;
}
+struct monitor_dirents *
+monitor_opendir (const char *path)
+{
+ char *buf, *cp;
+ size_t bufsize;
+ int fd, nbytes, entries;
+ long base;
+ struct stat sb;
+ struct dirent *dp;
+ struct monitor_dirents *direntries;
+
+ fd = monitor_open (path, 0, O_RDONLY);
+ if (fd < 0)
+ {
+ log_error ("monitor_opendir: opendir(\"%s\") failed", path);
+ return NULL;
+ }
+
+ /* Now build a list with all dirents from fd. */
+ if (fstat (fd, &sb) < 0)
+ {
+ (void)close (fd);
+ return NULL;
+ }
+
+ if (!S_ISDIR (sb.st_mode))
+ {
+ (void)close (fd);
+ errno = EACCES;
+ return NULL;
+ }
+
+ bufsize = sb.st_size;
+ if (bufsize < sb.st_blksize)
+ bufsize = sb.st_blksize;
+
+ buf = calloc (bufsize, sizeof (char));
+ if (buf == NULL)
+ {
+ (void)close (fd);
+ errno = EACCES;
+ return NULL;
+ }
+
+ nbytes = getdirentries (fd, buf, bufsize, &base);
+ if (nbytes <= 0)
+ {
+ (void)close (fd);
+ free (buf);
+ errno = EACCES;
+ return NULL;
+ }
+ (void)close (fd);
+
+ for (entries = 0, cp = buf; cp < buf + nbytes; )
+ {
+ dp = (struct dirent *)cp;
+ cp += dp->d_reclen;
+ entries++;
+ }
+
+ direntries = calloc (1, sizeof (struct monitor_dirents));
+ if (direntries == NULL)
+ {
+ free (buf);
+ errno = EACCES;
+ return NULL;
+ }
+
+ direntries->dirents = calloc (entries + 1, sizeof (struct dirent *));
+ if (direntries->dirents == NULL)
+ {
+ free (buf);
+ free (direntries);
+ errno = EACCES;
+ return NULL;
+ }
+ direntries->current = 0;
+
+ for (entries = 0, cp = buf; cp < buf + nbytes; )
+ {
+ dp = (struct dirent *)cp;
+ direntries->dirents[entries++] = dp;
+ cp += dp->d_reclen;
+ }
+ direntries->dirents[entries] = NULL;
+
+ return direntries;
+}
+
+struct dirent *
+monitor_readdir (struct monitor_dirents *direntries)
+{
+ if (direntries->dirents[direntries->current] != NULL)
+ return direntries->dirents[direntries->current++];
+
+ return NULL;
+}
+
+int
+monitor_closedir (struct monitor_dirents *direntries)
+{
+ free (direntries->dirents);
+ free (direntries);
+
+ return 0;
+}
+
+void
+monitor_init_done (void)
+{
+ if (m_write_int32 (m_state.s, MONITOR_INIT_DONE))
+ log_print ("monitor_init_done: read/write error");
+
+ return;
+}
+
/*
* Start of code running with privileges (the monitor process).
*/
-/* Help function for monitor_loop(). */
+/* Help functions for monitor_loop(). */
static void
monitor_got_sigchld (int sig)
{
sigchlded = 1;
}
+static void
+sig_pass_to_chld(int sig)
+{
+ int oerrno = errno;
+
+ if (m_state.pid != -1)
+ kill(m_state.pid, sig);
+ errno = oerrno;
+}
+
/* This function is where the privileged process waits(loops) indefinitely. */
void
monitor_loop (int debugging)
{
+ pid_t pid;
fd_set *fds;
- int n, maxfd, shutdown = 0;
+ int n, maxfd;
if (!debugging)
log_to (0);
@@ -379,7 +557,12 @@ monitor_loop (int debugging)
/* If the child dies, we should shutdown also. */
signal (SIGCHLD, monitor_got_sigchld);
- while (!shutdown)
+ /* SIGHUP, SIGUSR1 and SIGUSR2 will be forwarded to child. */
+ signal (SIGHUP, sig_pass_to_chld);
+ signal (SIGUSR1, sig_pass_to_chld);
+ signal (SIGUSR2, sig_pass_to_chld);
+
+ while (cur_state < STATE_QUIT)
{
/*
* Currently, there is no need for us to hang around if the child
@@ -387,12 +570,30 @@ monitor_loop (int debugging)
*/
if (sigtermed || sigchlded)
{
+ if (sigtermed)
+ kill (m_state.pid, SIGTERM);
+
if (sigchlded)
- wait (&n);
- shutdown++;
+ {
+ do
+ {
+ pid = waitpid (m_state.pid, &n, WNOHANG);
+ }
+ while (pid == -1 && errno == EINTR);
+
+ if (pid == m_state.pid && (WIFEXITED (n) || WIFSIGNALED (n)))
+ m_priv_increase_state (STATE_QUIT);
+ }
+
break;
}
+ if (monitor_sighupped)
+ {
+ kill (m_state.pid, SIGHUP);
+ monitor_sighupped = 0;
+ }
+
FD_ZERO (fds);
FD_SET (m_state.s, fds);
@@ -419,23 +620,38 @@ monitor_loop (int debugging)
break;
case MONITOR_GET_SOCKET:
+ LOG_DBG ((LOG_MISC, 80, "%s: MONITOR_GET_SOCKET", __func__));
+ m_priv_test_state (STATE_INIT);
m_priv_getsocket (m_state.s);
break;
case MONITOR_SETSOCKOPT:
+ LOG_DBG ((LOG_MISC, 80, "%s: MONITOR_SETSOCKOPT", __func__));
+ m_priv_test_state (STATE_INIT);
m_priv_setsockopt (m_state.s);
break;
case MONITOR_BIND:
+ LOG_DBG ((LOG_MISC, 80, "%s: MONITOR_BIND", __func__));
+ m_priv_test_state (STATE_INIT);
m_priv_bind (m_state.s);
break;
case MONITOR_MKFIFO:
+ LOG_DBG ((LOG_MISC, 80, "%s: MONITOR_MKFIFO", __func__));
+ m_priv_test_state (STATE_INIT);
m_priv_mkfifo (m_state.s);
break;
+ case MONITOR_INIT_DONE:
+ LOG_DBG ((LOG_MISC, 80, "%s: MONITOR_INIT_DONE", __func__));
+ m_priv_test_state (STATE_INIT);
+ m_priv_increase_state (STATE_RUNNING);
+ break;
+
case MONITOR_SHUTDOWN:
- shutdown++;
+ LOG_DBG ((LOG_MISC, 80, "%s: MONITOR_SHUTDOWN", __func__));
+ m_priv_increase_state (STATE_QUIT);
break;
default:
@@ -449,11 +665,11 @@ monitor_loop (int debugging)
}
/* Privileged: called by monitor_loop. */
-void
+static void
m_priv_getfd (int s)
{
char path[MAXPATHLEN];
- int32_t v;
+ int32_t v, err;
int flags;
mode_t mode;
@@ -476,10 +692,23 @@ m_priv_getfd (int s)
goto errout;
mode = (mode_t)v;
- m_priv_local_sanitize_path (path, sizeof path, flags);
+ if (m_priv_local_sanitize_path (path, sizeof path, flags) != 0)
+ {
+ err = EACCES;
+ v = -1;
+ }
+ else
+ {
+ err = 0;
+ v = (int32_t)open (path, flags, mode);
+ if (v < 0)
+ err = (int32_t)errno;
+ }
- v = (int32_t)open (path, flags, mode);
- if (mm_send_fd (s, v))
+ if (m_write_int32 (s, err))
+ goto errout;
+
+ if (v > 0 && mm_send_fd (s, v))
{
close (v);
goto errout;
@@ -493,11 +722,11 @@ m_priv_getfd (int s)
}
/* Privileged: called by monitor_loop. */
-void
+static void
m_priv_getsocket (int s)
{
int domain, type, protocol;
- int32_t v;
+ int32_t v, err;
if (m_read_int32 (s, &v))
goto errout;
@@ -511,8 +740,15 @@ m_priv_getsocket (int s)
goto errout;
protocol = (int)v;
+ err = 0;
v = (int32_t)socket (domain, type, protocol);
- if (mm_send_fd (s, v))
+ if (v < 0)
+ err = (int32_t)errno;
+
+ if (m_write_int32 (s, err))
+ goto errout;
+
+ if (v > 0 && mm_send_fd (s, v))
{
close (v);
goto errout;
@@ -526,13 +762,13 @@ m_priv_getsocket (int s)
}
/* Privileged: called by monitor_loop. */
-void
+static void
m_priv_setsockopt (int s)
{
int sock, level, optname;
char *optval = 0;
socklen_t optlen;
- int32_t v;
+ int32_t v, err;
sock = mm_receive_fd (s);
if (sock < 0)
@@ -554,9 +790,25 @@ m_priv_setsockopt (int s)
if (m_read_raw (s, optval, optlen))
goto errout;
- v = (int32_t) setsockopt (sock, level, optname, optval, optlen);
+ if (m_priv_check_sockopt (level, optname) != 0)
+ {
+ err = EACCES;
+ v = -1;
+ }
+ else
+ {
+ err = 0;
+ v = (int32_t) setsockopt (sock, level, optname, optval, optlen);
+ if (v < 0)
+ err = (int32_t)errno;
+ }
+
close (sock);
sock = -1;
+
+ if (m_write_int32 (s, err))
+ goto errout;
+
if (m_write_int32 (s, v))
goto errout;
@@ -573,13 +825,13 @@ m_priv_setsockopt (int s)
}
/* Privileged: called by monitor_loop. */
-void
+static void
m_priv_bind (int s)
{
int sock;
struct sockaddr *name = 0;
socklen_t namelen;
- int32_t v;
+ int32_t v, err;
sock = mm_receive_fd (s);
if (sock < 0)
@@ -596,13 +848,29 @@ m_priv_bind (int s)
if (m_read_raw (s, (char *)name, (size_t)namelen))
goto errout;
- v = (int32_t)bind (sock, name, namelen);
- if (v < 0)
- log_error ("m_priv_bind: bind(%d,%p,%d) returned %d",
- sock, name, namelen, v);
+ if (m_priv_check_bind (name, namelen) != 0)
+ {
+ err = EACCES;
+ v = -1;
+ }
+ else
+ {
+ err = 0;
+ v = (int32_t)bind (sock, name, namelen);
+ if (v < 0)
+ {
+ log_error ("m_priv_bind: bind(%d,%p,%d) returned %d",
+ sock, name, namelen, v);
+ err = (int32_t)errno;
+ }
+ }
close (sock);
sock = -1;
+
+ if (m_write_int32 (s, err))
+ goto errout;
+
if (m_write_int32 (s, v))
goto errout;
@@ -619,26 +887,45 @@ m_priv_bind (int s)
}
/* Privileged: called by monitor_loop. */
-void
+static void
m_priv_mkfifo (int s)
{
- char name[MAXPATHLEN];
+ char path[MAXPATHLEN];
mode_t mode;
- int32_t v;
+ int32_t v, err;
- if (m_read_raw (s, name, MAXPATHLEN))
+ if (m_read_raw (s, path, MAXPATHLEN))
goto errout;
if (m_read_int32 (s, &v))
goto errout;
mode = (mode_t)v;
- /* XXX Sanity checks for 'name'. */
+ /*
+ * ui_fifo is set before creation of the unpriv'ed child. So path should
+ * exactly match ui_fifo. It's also restricted to /var/run.
+ */
+ if (m_priv_local_sanitize_path (path, sizeof path, O_RDWR) != 0 ||
+ strncmp (ui_fifo, path, strlen (ui_fifo)))
+ {
+ err = EACCES;
+ v = -1;
+ }
+ else
+ {
+ unlink (path); /* XXX See ui.c:ui_init() */
+
+ err = 0;
+ v = (int32_t)mkfifo (path, mode);
+ if (v)
+ {
+ log_error ("m_priv_mkfifo: mkfifo(\"%s\", %o) failed", path, mode);
+ err = (int32_t)errno;
+ }
+ }
- unlink (name); /* XXX See ui.c:ui_init() */
- v = (int32_t)mkfifo (name, mode);
- if (v)
- log_error ("m_priv_mkfifo: mkfifo(\"%s\", %d) failed", name, mode);
+ if (m_write_int32 (s, err))
+ goto errout;
if (m_write_int32 (s, v))
goto errout;
@@ -709,22 +996,18 @@ m_flush (int s)
}
/* Check that path/mode is permitted. */
-void
+static int
m_priv_local_sanitize_path (char *path, size_t pmax, int flags)
{
char *p;
/*
- * Basically, we only permit paths starting with
+ * We only permit paths starting with
* /etc/isakmpd/ (read only)
- * /var/run/
- * /var/tmp
- * /tmp
- *
- * XXX This is an interim measure only.
+ * /var/run/ (rw)
*/
- if (strlen (path) < sizeof "/tmp")
+ if (strlen (path) < strlen ("/var/run/"))
goto bad_path;
/* Any path containing '..' is invalid. */
@@ -735,21 +1018,131 @@ m_priv_local_sanitize_path (char *path, size_t pmax, int flags)
/* For any write-mode, only a few paths are permitted. */
if ((flags & O_ACCMODE) != O_RDONLY)
{
- if (strncmp ("/var/run/", path, sizeof "/var/run") == 0 ||
- strncmp ("/var/tmp/", path, sizeof "/var/tmp") == 0 ||
- strncmp ("/tmp/", path, sizeof "/tmp") == 0)
- return;
+ if (strncmp ("/var/run/", path, strlen ("/var/run/")) == 0)
+ return 0;
goto bad_path;
}
- /* Any other paths are read-only. */
- if (strncmp (ISAKMPD_ROOT, path, strlen (ISAKMPD_ROOT)) == 0)
- return;
+ /* Any other path is read-only. */
+ if (strncmp (ISAKMPD_ROOT, path, strlen (ISAKMPD_ROOT)) == 0 ||
+ strncmp ("/var/run/", path, strlen ("/var/run/")) == 0)
+ return 0;
bad_path:
log_print ("m_priv_local_sanitize_path: illegal path \"%.1023s\", "
"replaced with \"/dev/null\"", path);
strlcpy (path, "/dev/null", pmax);
- return;
+ return 1;
+}
+
+/* Check setsockopt */
+static int
+m_priv_check_sockopt (int level, int name)
+{
+ switch (level)
+ {
+ /* These are allowed */
+ case SOL_SOCKET:
+ case IPPROTO_IP:
+ case IPPROTO_IPV6:
+ break;
+
+ default:
+ log_print ("m_priv_check_sockopt: Illegal level %d", level);
+ return 1;
+ }
+
+ switch (name)
+ {
+ /* These are allowed */
+ case SO_REUSEPORT:
+ case SO_REUSEADDR:
+ case IP_AUTH_LEVEL:
+ case IP_ESP_TRANS_LEVEL:
+ case IP_ESP_NETWORK_LEVEL:
+ case IP_IPCOMP_LEVEL:
+ case IPV6_AUTH_LEVEL:
+ case IPV6_ESP_TRANS_LEVEL:
+ case IPV6_ESP_NETWORK_LEVEL:
+ case IPV6_IPCOMP_LEVEL:
+ break;
+
+ default:
+ log_print ("m_priv_check_sockopt: Illegal option name %d", name);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Check bind */
+static int
+m_priv_check_bind (const struct sockaddr *sa, socklen_t salen)
+{
+ in_port_t port;
+
+ if (sa == NULL)
+ {
+ log_print ("NULL address");
+ return 1;
+ }
+
+ if (sa->sa_len != salen)
+ {
+ log_print ("Length mismatch: %d %d", (int) sa->sa_len, (int) salen);
+ return 1;
+ }
+
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ if (salen != sizeof (struct sockaddr_in))
+ {
+ log_print ("Invalid inet address length");
+ return 1;
+ }
+ port = ((const struct sockaddr_in *)sa)->sin_port;
+ break;
+ case AF_INET6:
+ if (salen != sizeof (struct sockaddr_in6))
+ {
+ log_print ("Invalid inet6 address length");
+ return 1;
+ }
+ port = ((const struct sockaddr_in6 *)sa)->sin6_port;
+ break;
+ default:
+ log_print ("Unknown address family");
+ return 1;
+ }
+
+ port = ntohs(port);
+
+ if (port != ISAKMP_PORT_DEFAULT && port < 1024)
+ {
+ log_print ("Disallowed port %u", port);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Increase state into less permissive mode */
+static void
+m_priv_increase_state (int state)
+{
+ if (state <= cur_state)
+ log_print ("m_priv_increase_state: attempt to decrase state or match "
+ "current state");
+ if (state < STATE_INIT || state > STATE_QUIT)
+ log_print ("m_priv_increase_state: attempt to switch to invalid state");
+ cur_state = state;
}
+static void
+m_priv_test_state (int state)
+{
+ if (cur_state != state)
+ log_print ("m_priv_test_state: Illegal state: %d != %d", cur_state, state);
+ return;
+}
diff --git a/sbin/isakmpd/monitor.h b/sbin/isakmpd/monitor.h
index 106cc78ecb5..b76af5318ed 100644
--- a/sbin/isakmpd/monitor.h
+++ b/sbin/isakmpd/monitor.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.h,v 1.6 2004/03/15 16:29:00 hshoexer Exp $ */
+/* $OpenBSD: monitor.h,v 1.7 2004/03/19 14:04:43 hshoexer Exp $ */
/*
* Copyright (c) 2003 Håkan Olsson. All rights reserved.
@@ -24,11 +24,20 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef _MONITOR_H_
+#define _MONITOR_H_
+
#if defined (USE_PRIVSEP)
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
#include <stdio.h>
#define ISAKMPD_PRIVSEP_USER "_isakmpd"
+#define ISAKMP_PORT_DEFAULT 500
+
enum monitor_reqtypes
{
MONITOR_GET_FD,
@@ -36,7 +45,20 @@ enum monitor_reqtypes
MONITOR_SETSOCKOPT,
MONITOR_BIND,
MONITOR_MKFIFO,
- MONITOR_SHUTDOWN,
+ MONITOR_INIT_DONE,
+ MONITOR_SHUTDOWN
+};
+
+enum priv_state {
+ STATE_INIT, /* just started */
+ STATE_RUNNING, /* running */
+ STATE_QUIT /* shutting down */
+};
+
+struct monitor_dirents
+{
+ int current;
+ struct dirent **dirents;
};
pid_t monitor_init (void);
@@ -45,7 +67,6 @@ void monitor_loop (int);
int mm_send_fd (int, int);
int mm_receive_fd (int);
-struct stat;
FILE *monitor_fopen (const char *, const char *);
int monitor_open (const char *, int, mode_t);
int monitor_stat (const char *, struct stat *);
@@ -53,6 +74,10 @@ int monitor_socket (int, int, int);
int monitor_setsockopt (int, int, int, const void *, socklen_t);
int monitor_bind (int, const struct sockaddr *, socklen_t);
int monitor_mkfifo (const char *, mode_t);
+struct monitor_dirents *monitor_opendir (const char *);
+struct dirent *monitor_readdir (struct monitor_dirents *);
+int monitor_closedir (struct monitor_dirents *);
+void monitor_init_done (void);
#else /* !USE_PRIVSEP */
@@ -63,9 +88,9 @@ int monitor_mkfifo (const char *, mode_t);
#define monitor_setsockopt setsockopt
#define monitor_bind bind
#define monitor_mkfifo mkfifo
-
-#if defined (USE_X509)
-#define monitor_RSA_free RSA_free
-#endif
+#define monitor_opendir opendir
+#define monitor_readdir readdir
+#define monitor_closedir closedir
#endif /* USE_PRIVSEP */
+#endif /* _MONITOR_H_ */
diff --git a/sbin/isakmpd/policy.c b/sbin/isakmpd/policy.c
index a33e155092a..6bccf75bdf5 100644
--- a/sbin/isakmpd/policy.c
+++ b/sbin/isakmpd/policy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: policy.c,v 1.67 2003/11/06 16:12:08 ho Exp $ */
+/* $OpenBSD: policy.c,v 1.68 2004/03/19 14:04:43 hshoexer Exp $ */
/* $EOM: policy.c,v 1.49 2000/10/24 13:33:39 niklas Exp $ */
/*
@@ -2100,7 +2100,7 @@ keynote_cert_obtain (u_int8_t *id, size_t id_len, void *data, u_int8_t **cert,
return 0;
}
- if (stat (file, &sb) < 0)
+ if (monitor_stat (file, &sb) < 0)
{
LOG_DBG ((LOG_POLICY, 30, "keynote_cert_obtain: failed to stat \"%s\"",
file));
@@ -2118,7 +2118,7 @@ keynote_cert_obtain (u_int8_t *id, size_t id_len, void *data, u_int8_t **cert,
return 0;
}
- fd = open (file, O_RDONLY, 0);
+ fd = monitor_open (file, O_RDONLY, 0);
if (fd < 0)
{
LOG_DBG ((LOG_POLICY, 30, "keynote_cert_obtain: failed to open \"%s\"",
diff --git a/sbin/isakmpd/sa.c b/sbin/isakmpd/sa.c
index 2efee3cb374..7e1c60f580c 100644
--- a/sbin/isakmpd/sa.c
+++ b/sbin/isakmpd/sa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sa.c,v 1.76 2004/02/27 10:16:26 ho Exp $ */
+/* $OpenBSD: sa.c,v 1.77 2004/03/19 14:04:43 hshoexer Exp $ */
/* $EOM: sa.c,v 1.112 2000/12/12 00:22:52 niklas Exp $ */
/*
@@ -51,6 +51,7 @@
#include "isakmp.h"
#include "log.h"
#include "message.h"
+#include "monitor.h"
#include "sa.h"
#include "timer.h"
#include "transport.h"
@@ -693,7 +694,7 @@ sa_report_all (void)
struct sa *sa;
/* Open SA_FILE. */
- fd = fopen (SA_FILE, "w");
+ fd = monitor_fopen (SA_FILE, "w");
/* Start sa_config_report. */
for (i = 0; i <= bucket_mask; i++)
diff --git a/sbin/isakmpd/udp.c b/sbin/isakmpd/udp.c
index 8abdaf4c03b..3de891d4111 100644
--- a/sbin/isakmpd/udp.c
+++ b/sbin/isakmpd/udp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp.c,v 1.65 2003/09/26 11:29:11 cedric Exp $ */
+/* $OpenBSD: udp.c,v 1.66 2004/03/19 14:04:43 hshoexer Exp $ */
/* $EOM: udp.c,v 1.57 2001/01/26 10:09:57 niklas Exp $ */
/*
@@ -142,7 +142,7 @@ udp_make (struct sockaddr *laddr)
return 0;
}
- s = socket (laddr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+ s = monitor_socket (laddr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
if (s == -1)
{
log_error ("udp_make: socket (%d, %d, %d)", laddr->sa_family, SOCK_DGRAM,
@@ -174,7 +174,7 @@ udp_make (struct sockaddr *laddr)
* sending from it make sure it is entirely reuseable with SO_REUSEPORT.
*/
on = 1;
- if (setsockopt (s, SOL_SOCKET,
+ if (monitor_setsockopt (s, SOL_SOCKET,
wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR,
(void *)&on, sizeof on) == -1)
{
@@ -363,7 +363,7 @@ udp_bind_if (char *ifname, struct sockaddr *if_addr, void *arg)
}
/* Don't bother with interfaces that are down. */
- s = socket (if_addr->sa_family, SOCK_DGRAM, 0);
+ s = monitor_socket (if_addr->sa_family, SOCK_DGRAM, 0);
if (s == -1)
{
log_error ("udp_bind_if: socket (%d, SOCK_DGRAM, 0) failed",
diff --git a/sbin/isakmpd/ui.c b/sbin/isakmpd/ui.c
index b7373f64a80..538703a4ee4 100644
--- a/sbin/isakmpd/ui.c
+++ b/sbin/isakmpd/ui.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ui.c,v 1.35 2003/11/06 16:12:08 ho Exp $ */
+/* $OpenBSD: ui.c,v 1.36 2004/03/19 14:04:43 hshoexer Exp $ */
/* $EOM: ui.c,v 1.43 2000/10/05 09:25:12 niklas Exp $ */
/*
@@ -77,7 +77,12 @@ ui_init (void)
else
{
/* Don't overwrite a file, i.e '-f /etc/isakmpd/isakmpd.conf'. */
+#if defined (USE_PRIVSEP)
+ /* XXX This is a fstat! */
+ if (monitor_stat (ui_fifo, &st) == 0)
+#else
if (lstat (ui_fifo, &st) == 0)
+#endif
if ((st.st_mode & S_IFMT) == S_IFREG)
{
errno = EEXIST;
diff --git a/sbin/isakmpd/x509.c b/sbin/isakmpd/x509.c
index 8ced242f989..1c01eb46271 100644
--- a/sbin/isakmpd/x509.c
+++ b/sbin/isakmpd/x509.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: x509.c,v 1.85 2004/01/06 00:09:19 hshoexer Exp $ */
+/* $OpenBSD: x509.c,v 1.86 2004/03/19 14:04:43 hshoexer Exp $ */
/* $EOM: x509.c,v 1.54 2001/01/16 18:42:16 ho Exp $ */
/*
@@ -59,6 +59,7 @@
#include "ipsec.h"
#include "log.h"
#include "math_mp.h"
+#include "monitor.h"
#include "policy.h"
#include "sa.h"
#include "util.h"
@@ -656,9 +657,14 @@ x509_hash_enter (X509 *cert)
int
x509_read_from_dir (X509_STORE *ctx, char *name, int hash)
{
- DIR *dir;
struct dirent *file;
+#if defined (USE_PRIVSEP)
+ struct monitor_dirents *dir;
+ FILE *certfp;
+#else
+ DIR *dir;
BIO *certh;
+#endif
X509 *cert;
char fullname[PATH_MAX];
int off, size;
@@ -672,7 +678,7 @@ x509_read_from_dir (X509_STORE *ctx, char *name, int hash)
LOG_DBG ((LOG_CRYPTO, 40, "x509_read_from_dir: reading certs from %s",
name));
- dir = opendir (name);
+ dir = monitor_opendir (name);
if (!dir)
{
LOG_DBG ((LOG_CRYPTO, 10, "x509_read_from_dir: opendir (\"%s\") failed: "
@@ -684,7 +690,7 @@ x509_read_from_dir (X509_STORE *ctx, char *name, int hash)
off = strlen (fullname);
size = sizeof fullname - off;
- while ((file = readdir (dir)) != NULL)
+ while ((file = monitor_readdir (dir)) != NULL)
{
strlcpy (fullname + off, file->d_name, size);
@@ -697,13 +703,29 @@ x509_read_from_dir (X509_STORE *ctx, char *name, int hash)
{
struct stat sb;
- if (stat (fullname, &sb) == -1 || !(sb.st_mode & S_IFREG))
+ if (monitor_stat (fullname, &sb) == -1 || !(sb.st_mode & S_IFREG))
continue;
}
LOG_DBG ((LOG_CRYPTO, 60, "x509_read_from_dir: reading certificate %s",
file->d_name));
+#if defined (USE_PRIVSEP)
+ certfp = monitor_fopen (fullname, "r");
+ if (!certfp)
+ {
+ log_error ("x509_read_from_dir: monitor_fopen (\"%s\", \"r\") failed",
+ fullname);
+ continue;
+ }
+
+#if SSLEAY_VERSION_NUMBER >= 0x00904100L
+ cert = PEM_read_X509 (certfp, NULL, NULL, NULL);
+#else
+ cert = PEM_read_X509 (certfp, NULL, NULL);
+#endif
+ fclose (certfp);
+#else
certh = BIO_new (BIO_s_file ());
if (!certh)
{
@@ -726,6 +748,7 @@ x509_read_from_dir (X509_STORE *ctx, char *name, int hash)
cert = PEM_read_bio_X509 (certh, NULL, NULL);
#endif
BIO_free (certh);
+#endif /* USE_PRIVSEP */
if (cert == NULL)
{
log_print ("x509_read_from_dir: PEM_read_bio_X509 failed for %s",
@@ -751,7 +774,7 @@ x509_read_from_dir (X509_STORE *ctx, char *name, int hash)
file->d_name);
}
- closedir (dir);
+ monitor_closedir (dir);
return 1;
}
@@ -761,9 +784,14 @@ int
x509_read_crls_from_dir (X509_STORE *ctx, char *name)
{
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
- DIR *dir;
struct dirent *file;
+#if defined (USE_PRIVSEP)
+ struct monitor_dirents *dir;
+ FILE *crlfp;
+#else
+ DIR *dir;
BIO *crlh;
+#endif
X509_CRL *crl;
char fullname[PATH_MAX];
int off, size;
@@ -777,7 +805,7 @@ x509_read_crls_from_dir (X509_STORE *ctx, char *name)
LOG_DBG ((LOG_CRYPTO, 40, "x509_read_crls_from_dir: reading CRLs from %s",
name));
- dir = opendir (name);
+ dir = monitor_opendir (name);
if (!dir)
{
LOG_DBG ((LOG_CRYPTO, 10, "x509_read_crls_from_dir: opendir (\"%s\") "
@@ -789,7 +817,7 @@ x509_read_crls_from_dir (X509_STORE *ctx, char *name)
off = strlen (fullname);
size = sizeof fullname - off;
- while ((file = readdir (dir)) != NULL)
+ while ((file = monitor_readdir (dir)) != NULL)
{
strlcpy (fullname + off, file->d_name, size);
@@ -802,13 +830,25 @@ x509_read_crls_from_dir (X509_STORE *ctx, char *name)
{
struct stat sb;
- if (stat (fullname, &sb) == -1 || !(sb.st_mode & S_IFREG))
+ if (monitor_stat (fullname, &sb) == -1 || !(sb.st_mode & S_IFREG))
continue;
}
LOG_DBG ((LOG_CRYPTO, 60, "x509_read_crls_from_dir: reading CRL %s",
file->d_name));
+#if defined (USE_PRIVSEP)
+ crlfp = monitor_fopen (fullname, "r");
+ if (!crlfp)
+ {
+ log_error ("x509_read_crls_from_dir: monitor_fopen (\"%s\", \"r\") "
+ "failed", fullname);
+ continue;
+ }
+
+ crl = PEM_read_X509_CRL (crlfp, NULL, NULL, NULL);
+ fclose (crlfp);
+#else
crlh = BIO_new (BIO_s_file ());
if (!crlh)
{
@@ -828,6 +868,7 @@ x509_read_crls_from_dir (X509_STORE *ctx, char *name)
crl = PEM_read_bio_X509_CRL (crlh, NULL, NULL, NULL);
BIO_free (crlh);
+#endif /* USE_PRIVSEP */
if (crl == NULL)
{
log_print ("x509_read_crls_from_dir: "
@@ -852,7 +893,7 @@ x509_read_crls_from_dir (X509_STORE *ctx, char *name)
X509_STORE_set_flags (ctx, X509_V_FLAG_CRL_CHECK);
}
- closedir (dir);
+ monitor_closedir (dir);
#endif /* OPENSSL_VERSION_NUMBER >= 0x00907000L */
return 1;