diff options
author | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2004-03-19 14:04:44 +0000 |
---|---|---|
committer | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2004-03-19 14:04:44 +0000 |
commit | 0b9f96e56b22f3d0bd8f9fa95204ba7a9e49683f (patch) | |
tree | 305096d9429011aed372ea12a527d10602e2a847 /sbin/isakmpd | |
parent | 96c309c384e99b742c4307ece38772c4841ffad2 (diff) |
Add missing bits to make already present privsep code work. Enable privsep.
ok ho@ deraadt@ markus@
Diffstat (limited to 'sbin/isakmpd')
-rw-r--r-- | sbin/isakmpd/Makefile | 4 | ||||
-rw-r--r-- | sbin/isakmpd/conf.c | 4 | ||||
-rw-r--r-- | sbin/isakmpd/conf.h | 8 | ||||
-rw-r--r-- | sbin/isakmpd/if.c | 4 | ||||
-rw-r--r-- | sbin/isakmpd/ike_auth.c | 64 | ||||
-rw-r--r-- | sbin/isakmpd/isakmpd.c | 27 | ||||
-rw-r--r-- | sbin/isakmpd/log.c | 7 | ||||
-rw-r--r-- | sbin/isakmpd/monitor.c | 543 | ||||
-rw-r--r-- | sbin/isakmpd/monitor.h | 39 | ||||
-rw-r--r-- | sbin/isakmpd/policy.c | 6 | ||||
-rw-r--r-- | sbin/isakmpd/sa.c | 5 | ||||
-rw-r--r-- | sbin/isakmpd/udp.c | 8 | ||||
-rw-r--r-- | sbin/isakmpd/ui.c | 7 | ||||
-rw-r--r-- | sbin/isakmpd/x509.c | 63 |
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; |