diff options
author | Hakan Olsson <ho@cvs.openbsd.org> | 2003-05-18 19:37:48 +0000 |
---|---|---|
committer | Hakan Olsson <ho@cvs.openbsd.org> | 2003-05-18 19:37:48 +0000 |
commit | c7dbb2513f201e339a478971b6b83aad177e05e9 (patch) | |
tree | e00b77ea29ed11af23d89b74ddb453ee32cdaf7b | |
parent | 83f54bd6f28f561dfb8e52c42c2d6fd9859cca77 (diff) |
More isakmpd privsep work. X509 private keys are now kept in the privileged
process only. Various cleanup and bugfixes.
markus@ ok
-rw-r--r-- | sbin/isakmpd/conf.c | 4 | ||||
-rw-r--r-- | sbin/isakmpd/ike_auth.c | 141 | ||||
-rw-r--r-- | sbin/isakmpd/isakmpd.c | 6 | ||||
-rw-r--r-- | sbin/isakmpd/log.c | 6 | ||||
-rw-r--r-- | sbin/isakmpd/monitor.c | 541 | ||||
-rw-r--r-- | sbin/isakmpd/monitor.h | 30 | ||||
-rw-r--r-- | sbin/isakmpd/monitor_fdpass.c | 5 | ||||
-rw-r--r-- | sbin/isakmpd/pf_key_v2.c | 4 | ||||
-rw-r--r-- | sbin/isakmpd/policy.c | 4 |
9 files changed, 574 insertions, 167 deletions
diff --git a/sbin/isakmpd/conf.c b/sbin/isakmpd/conf.c index 41c56087050..865c0d56cb0 100644 --- a/sbin/isakmpd/conf.c +++ b/sbin/isakmpd/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.52 2003/05/15 00:28:53 ho Exp $ */ +/* $OpenBSD: conf.c,v 1.53 2003/05/18 19:37:46 ho Exp $ */ /* $EOM: conf.c,v 1.48 2000/12/04 02:04:29 angelos Exp $ */ /* @@ -611,7 +611,7 @@ conf_reinit (void) fd, new_conf_addr, (unsigned long)sz); goto fail; } - monitor_close (fd); + close (fd); trans = conf_begin (); diff --git a/sbin/isakmpd/ike_auth.c b/sbin/isakmpd/ike_auth.c index f1ffbaa823e..d7f24977828 100644 --- a/sbin/isakmpd/ike_auth.c +++ b/sbin/isakmpd/ike_auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ike_auth.c,v 1.73 2003/05/15 03:20:28 ho Exp $ */ +/* $OpenBSD: ike_auth.c,v 1.74 2003/05/18 19:37:46 ho Exp $ */ /* $EOM: ike_auth.c,v 1.59 2000/11/21 00:21:31 angelos Exp $ */ /* @@ -151,10 +151,6 @@ ike_auth_get_key (int type, char *id, char *local_id, size_t *keylen) BIO *keyh; RSA *rsakey; size_t fsize; -#if defined (USE_PRIVSEP) - int fd; - char *fdata; -#endif #endif #endif @@ -296,51 +292,6 @@ 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) - /* XXX Try to find a better solution. */ - keyh = BIO_new (BIO_s_mem ()); - if (keyh == NULL) - { - log_print ("ike_auth_get_key: " - "BIO_new (BIO_s_mem ()) failed"); - return 0; - } - fd = monitor_open (keyfile, O_RDONLY, 0); - if (fd < 0) - { - log_print ("ike_auth_get_key: open(\"%s\") failed", keyfile); - BIO_free (keyh); - return 0; - } - fdata = (char *)malloc (fsize); - if (!fdata) - { - log_error ("ike_auth_get_get: malloc (%d) failed", fsize); - monitor_close (fd); - BIO_free (keyh); - return 0; - } - if (read (fd, fdata, fsize) != fsize) - { - log_error ("ike_auth_get_key: short read"); - monitor_close (fd); - BIO_free (keyh); - memset (fdata, 0, fsize); - free (fdata); - return 0; - } - monitor_close (fd); - if (BIO_write (keyh, fdata, fsize) == -1) - { - log_print ("ike_auth_get_key: BIO_read () failed"); - BIO_free (keyh); - memset (fdata, 0, fsize); - free (fdata); - return 0; - } - memset (fdata, 0, fsize); - free (fdata); -#else keyh = BIO_new (BIO_s_file ()); if (keyh == NULL) { @@ -356,7 +307,6 @@ ike_auth_get_key (int type, char *id, char *local_id, size_t *keylen) BIO_free (keyh); return 0; } -#endif /* USE_PRIVSEP */ #if SSLEAY_VERSION_NUMBER >= 0x00904100L rsakey = PEM_read_bio_RSAPrivateKey (keyh, NULL, NULL, NULL); @@ -964,7 +914,6 @@ rsa_sig_encode_hash (struct message *msg) u_int8_t *id; size_t id_len; int idtype; - int sent_keytype; void *sent_key; id = initiator ? exchange->id_i : exchange->id_r; @@ -1075,38 +1024,6 @@ rsa_sig_encode_hash (struct message *msg) skipcert: - switch (id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ]) - { - case IPSEC_ID_IPV4_ADDR: - case IPSEC_ID_IPV6_ADDR: - util_ntoa ((char **)&buf2, - id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ] == IPSEC_ID_IPV4_ADDR - ? AF_INET : AF_INET6, - id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); - if (!buf2) - return 0; - break; - - case IPSEC_ID_FQDN: - case IPSEC_ID_USER_FQDN: - buf2 = calloc (id_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1, - sizeof (char)); - if (!buf2) - { - log_print ("rsa_sig_encode_hash: malloc (%lu) failed", - (unsigned long)id_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1); - return 0; - } - memcpy (buf2, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, - id_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); - break; - - /* XXX Support more ID types? */ - default: - buf2 = 0; - break; - } - /* Again, we may have these from the kernel */ buf = (u_int8_t *)conf_get_str (exchange->name, "PKAuthentication"); if (buf) @@ -1119,7 +1036,6 @@ rsa_sig_encode_hash (struct message *msg) return 0; } - sent_keytype = ISAKMP_KEY_RSA; sent_key = key_internalize (ISAKMP_KEY_RSA, ISAKMP_KEYTYPE_PRIVATE, data, datalen); if (!sent_key) @@ -1128,11 +1044,54 @@ 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. */ { + switch (id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ]) + { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: + util_ntoa ((char **)&buf2, + id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ] == IPSEC_ID_IPV4_ADDR + ? AF_INET : AF_INET6, + id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); + if (!buf2) + return 0; + break; + + case IPSEC_ID_FQDN: + case IPSEC_ID_USER_FQDN: + buf2 = calloc (id_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1, + sizeof (char)); + if (!buf2) + { + log_print ("rsa_sig_encode_hash: malloc (%lu) failed", + (unsigned long)id_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1); + return 0; + } + memcpy (buf2, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + id_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); + break; + + /* XXX Support more ID types? */ + default: + buf2 = 0; + 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? */ @@ -1141,16 +1100,16 @@ rsa_sig_encode_hash (struct message *msg) log_print ("rsa_sig_encode_hash: could not get private key"); return -1; } - - sent_keytype = ISAKMP_KEY_RSA; } +#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); @@ -1170,6 +1129,7 @@ rsa_sig_encode_hash (struct message *msg) snprintf (header, 80, "rsa_sig_encode_hash: HASH_%c", initiator ? 'I' : 'R'); LOG_DBG_BUF ((LOG_MISC, 80, header, buf, hashsize)); +#if !defined (USE_PRIVSEP) data = malloc (RSA_size (sent_key)); if (!data) { @@ -1180,10 +1140,17 @@ 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); return -1; } diff --git a/sbin/isakmpd/isakmpd.c b/sbin/isakmpd/isakmpd.c index e70d6a90618..0022701e016 100644 --- a/sbin/isakmpd/isakmpd.c +++ b/sbin/isakmpd/isakmpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isakmpd.c,v 1.51 2003/05/15 00:28:53 ho Exp $ */ +/* $OpenBSD: isakmpd.c,v 1.52 2003/05/18 19:37:46 ho Exp $ */ /* $EOM: isakmpd.c,v 1.54 2000/10/05 09:28:22 niklas Exp $ */ /* @@ -253,7 +253,7 @@ report (void) log_to (rfp); ui_report ("r"); log_to (old); - monitor_fclose (rfp); + fclose (rfp); sigusr1ed = 0; } @@ -348,7 +348,7 @@ write_pid_file (void) { /* XXX Error checking! */ fprintf (fp, "%ld\n", (long) getpid ()); - monitor_fclose (fp); + fclose (fp); } else log_fatal ("main: fopen (\"%s\", \"w\") failed", pid_file); diff --git a/sbin/isakmpd/log.c b/sbin/isakmpd/log.c index 7c2c54f423c..3707abeb0fc 100644 --- a/sbin/isakmpd/log.c +++ b/sbin/isakmpd/log.c @@ -1,4 +1,4 @@ -/* $OpenBSD: log.c,v 1.31 2003/05/15 00:28:53 ho Exp $ */ +/* $OpenBSD: log.c,v 1.32 2003/05/18 19:37:46 ho Exp $ */ /* $EOM: log.c,v 1.30 2000/09/29 08:19:23 niklas Exp $ */ /* @@ -186,7 +186,7 @@ _log_print (int error, int syslog_level, const char *fmt, va_list ap, if (fileno (log_output) != -1 && fileno (stdout) == fileno (log_output)) fclose (stdout); - fclose (log_output); /* XXX monitor_fclose ? */ + fclose (log_output); /* Fallback to syslog. */ log_to (0); @@ -437,7 +437,7 @@ log_packet_stop (void) /* Stop capture. */ if (packet_log) { - monitor_fclose (packet_log); + fclose (packet_log); log_print ("log_packet_stop: stopped capture"); } packet_log = 0; diff --git a/sbin/isakmpd/monitor.c b/sbin/isakmpd/monitor.c index fb6645047be..a36a49c0a27 100644 --- a/sbin/isakmpd/monitor.c +++ b/sbin/isakmpd/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.3 2003/05/15 02:04:45 ho Exp $ */ +/* $OpenBSD: monitor.c,v 1.4 2003/05/18 19:37:46 ho Exp $ */ /* * Copyright (c) 2003 Håkan Olsson. All rights reserved. @@ -40,8 +40,19 @@ #include <string.h> #include <unistd.h> +#if defined (USE_POLICY) +#include <regex.h> +#include <keynote.h> +#endif + +#include "conf.h" #include "log.h" #include "monitor.h" +#include "policy.h" +#include "util.h" +#if defined (USE_X509) +#include "x509.h" +#endif struct monitor_state { @@ -65,7 +76,17 @@ void m_priv_getsocket (int); void m_priv_setsockopt (int); void m_priv_bind (int); void m_priv_mkfifo (int); -void m_priv_close (int); + +#if defined (USE_X509) +void m_priv_rsa_getkey (int); +void m_priv_rsa_freekey (int); +void m_priv_rsa_uploadkey (int); +void m_priv_rsa_encrypt (int); + +int32_t m_priv_local_addkey (RSA *); +RSA *m_priv_local_getkey (int32_t); +void m_priv_local_deletekey (int32_t); +#endif /* USE_X509 */ /* * Public functions, unprivileged. @@ -91,7 +112,7 @@ monitor_init (void) m_state.s = p[m_state.pid ? 1 : 0]; strlcpy (m_state.root, pw->pw_dir, sizeof m_state.root); - LOG_DBG ((LOG_SYSDEP, 95, "monitor_init: pid %d my fd %d", m_state.pid, + LOG_DBG ((LOG_SYSDEP, 30, "monitor_init: pid %d my fd %d", m_state.pid, m_state.s)); /* The child process should drop privileges now. */ @@ -124,11 +145,11 @@ monitor_open (const char *path, int flags, mode_t mode) int fd, mode32 = (int32_t) mode; char realpath[MAXPATHLEN]; - /* Only the child process is supposed to run this. */ if (m_state.pid) - log_fatal ("[priv] bad call to monitor_open"); - - LOG_DBG ((LOG_SYSDEP, 95, "monitor_open: enter")); + { + /* Called from the parent, i.e already privileged. */ + return open (path, flags, mode); + } if (path[0] == '/') strlcpy (realpath, path, sizeof realpath); @@ -156,7 +177,6 @@ monitor_open (const char *path, int flags, mode_t mode) log_error ("monitor_open: open(\"%s\") failed", path); return -1; } - LOG_DBG ((LOG_SYSDEP, 95, "monitor_open: got fd %d", fd)); return fd; @@ -171,8 +191,6 @@ monitor_fopen (const char *path, const char *mode) FILE *fp; int fd, flags = 0, umask = 0; - LOG_DBG ((LOG_SYSDEP, 95, "monitor_fopen: enter")); - /* Only the child process is supposed to run this. */ if (m_state.pid) log_fatal ("[priv] bad call to monitor_fopen"); @@ -213,8 +231,6 @@ monitor_stat (const char *path, struct stat *sb) { int fd, r, saved_errno; - LOG_DBG ((LOG_SYSDEP, 95, "monitor_stat: enter")); - fd = monitor_open (path, O_RDONLY, 0); if (fd < 0) { @@ -224,7 +240,7 @@ monitor_stat (const char *path, struct stat *sb) r = fstat (fd, sb); saved_errno = errno; - monitor_close (fd); + close (fd); errno = saved_errno; return r; } @@ -234,8 +250,6 @@ monitor_socket (int domain, int type, int protocol) { int s; - LOG_DBG ((LOG_SYSDEP, 95, "monitor_socket: enter")); - if (m_write_int32 (m_state.s, MONITOR_GET_SOCKET)) goto errout; @@ -252,7 +266,6 @@ monitor_socket (int domain, int type, int protocol) /* Read result. */ s = mm_receive_fd (m_state.s); - LOG_DBG ((LOG_SYSDEP, 95, "monitor_socket: return fd %d", s)); return s; errout: @@ -266,11 +279,9 @@ monitor_setsockopt (int s, int level, int optname, const void *optval, { int ret; - LOG_DBG ((LOG_SYSDEP, 95, "monitor_setsockopt: enter")); - if (m_write_int32 (m_state.s, MONITOR_SETSOCKOPT)) goto errout; - mm_send_fd (m_state.s, s); + mm_send_fd (m_state.s, s); /* XXX? */ if (m_write_int32 (m_state.s, (int32_t)level)) goto errout; @@ -296,8 +307,6 @@ monitor_bind (int s, const struct sockaddr *name, socklen_t namelen) { int ret; - LOG_DBG ((LOG_SYSDEP, 95, "monitor_bind: enter")); - if (m_write_int32 (m_state.s, MONITOR_BIND)) goto errout; mm_send_fd (m_state.s, s); @@ -327,8 +336,6 @@ monitor_mkfifo (const char *path, mode_t mode) if (m_state.pid) log_fatal ("[priv] bad call to monitor_mkfifo"); - LOG_DBG ((LOG_SYSDEP, 95, "monitor_mkfifo: enter")); - if (path[0] == '/') strlcpy (realpath, path, sizeof realpath); else @@ -354,38 +361,134 @@ monitor_mkfifo (const char *path, mode_t mode) return -1; } -int -monitor_close (int s) +#if defined (USE_X509) +/* Called by rsa_sig_encode_hash, the code that gets a key from ACQUIRE. */ +char * +monitor_RSA_upload_key (char *k_raw) { - if (m_write_int32 (m_state.s, MONITOR_CLOSE)) + RSA *rsa = (RSA *)k_raw; + int32_t v; + + if (m_write_int32 (m_state.s, MONITOR_RSA_UPLOADKEY)) goto errout; - mm_send_fd (m_state.s, s); + /* XXX - incomplete */ + if (m_write_raw (m_state.s, k_raw, 0)) + goto errout; + + RSA_free (rsa); - return close (s); + if (m_read_int32 (m_state.s, &v)) + goto errout; + + return (char *)v; errout: - log_print ("monitor_close: write error"); - return close (s); + log_print ("monitor_RSA_upload_key: read/write error"); + return 0; +} + +char * +monitor_RSA_get_private_key (char *id, char *local_id) +{ + char *confval; + int32_t v; + + if (m_write_int32 (m_state.s, MONITOR_RSA_GETKEY)) + goto errout; + + /* + * The privileged process will call ike_auth_get_key, so we need to + * to collect some current configuration data for it. + */ + confval = conf_get_str ("KeyNote", "Credential-directory"); + if (!confval) + m_write_int32 (m_state.s, 0); + else + m_write_raw (m_state.s, confval, strlen (confval) + 1); + + confval = conf_get_str ("X509-certificates", "Private-key"); + if (!confval) + m_write_int32 (m_state.s, 0); + else + m_write_raw (m_state.s, confval, strlen (confval) + 1); + + /* Next, the required arguments. */ + if (m_write_raw (m_state.s, id, strlen (id) + 1)) + goto errout; + if (m_write_raw (m_state.s, local_id, strlen (local_id) + 1)) + goto errout; + + /* Now, read the results. */ + if (m_read_int32 (m_state.s, &v)) + goto errout; + + return (char *)v; + + errout: + log_print ("monitor_RSA_upload_key: read/write error"); + return 0; } int -monitor_fclose (FILE *fp) +monitor_RSA_private_encrypt (int hashsize, unsigned char *hash, + unsigned char **sigdata, void *rkey, int padtype) { - int fd = fileno (fp); + int32_t v; + char *data = 0; + int datalen; + + *sigdata = 0; + + if (m_write_int32 (m_state.s, MONITOR_RSA_ENCRYPT)) + goto errout; + + if (m_write_int32 (m_state.s, (int32_t)hashsize)) + goto errout; + + if (m_write_raw (m_state.s, hash, hashsize)) + goto errout; + + if (m_write_int32 (m_state.s, (int32_t)rkey)) + goto errout; + + if (m_write_int32 (m_state.s, (int32_t)padtype)) + goto errout; + + /* Read results. */ + if (m_read_int32 (m_state.s, &v)) + goto errout; + datalen = (int)v; + + if (datalen == -1) + goto errout; - if (m_write_int32 (m_state.s, MONITOR_CLOSE)) + data = (char *)malloc (datalen); + if (!data) goto errout; - mm_send_fd (m_state.s, fd); + if (m_read_raw (m_state.s, data, datalen)) + goto errout; - return fclose (fp); + *sigdata = data; + return datalen; errout: - log_print ("monitor_fclose: write error"); - return fclose (fp); + if (data) + free (data); + return -1; } +void +monitor_RSA_free (void *key) +{ + if (m_write_int32 (m_state.s, MONITOR_RSA_FREEKEY) == 0) + m_write_int32 (m_state.s, (int32_t)key); + + return; +} +#endif /* USE_X509 */ + /* * Start of code running with privileges (the monitor process). */ @@ -437,9 +540,7 @@ monitor_loop (int debugging) FD_ZERO (fds); FD_SET (m_state.s, fds); - LOG_DBG ((LOG_SYSDEP, 95, "monitor_loop: waiting for select()")); n = select (maxfd, fds, NULL, NULL, NULL); - LOG_DBG ((LOG_SYSDEP, 95, "monitor_loop: select returned %d", n)); if (n == -1) { if (errno != EINTR) @@ -477,14 +578,29 @@ monitor_loop (int debugging) m_priv_mkfifo (m_state.s); break; - case MONITOR_CLOSE: - m_priv_close (m_state.s); - break; - case MONITOR_SHUTDOWN: shutdown++; break; +#if defined (USE_X509) + case MONITOR_RSA_UPLOADKEY: + /* XXX Not implemented yet. */ + /* m_priv_rsa_uploadkey (m_state.s); */ + break; + + case MONITOR_RSA_GETKEY: + m_priv_rsa_getkey (m_state.s); + break; + + case MONITOR_RSA_ENCRYPT: + m_priv_rsa_encrypt (m_state.s); + break; + + case MONITOR_RSA_FREEKEY: + m_priv_rsa_freekey (m_state.s); + break; +#endif + default: log_print ("monitor_loop: got unknown code %d", msgcode); } @@ -512,8 +628,6 @@ m_priv_getfd (int s) * u_int32_t mode */ - LOG_DBG ((LOG_SYSDEP, 95, "m_priv_getfd: enter")); - if (m_read_raw (s, path, MAXPATHLEN)) goto errout; @@ -528,7 +642,12 @@ m_priv_getfd (int s) /* XXX Sanity checks */ v = (int32_t)open (path, flags, mode); - mm_send_fd (s, v); + if (mm_send_fd (s, v)) + { + close (v); + goto errout; + } + close (v); return; errout: @@ -543,8 +662,6 @@ m_priv_getsocket (int s) int domain, type, protocol; int32_t v; - LOG_DBG ((LOG_SYSDEP, 95, "m_priv_getsocket: enter")); - if (m_read_int32 (s, &v)) goto errout; domain = (int)v; @@ -558,7 +675,12 @@ m_priv_getsocket (int s) protocol = (int)v; v = (int32_t)socket (domain, type, protocol); - mm_send_fd (s, v); + if (mm_send_fd (s, v)) + { + close (v); + goto errout; + } + close (v); return; errout: @@ -594,6 +716,7 @@ m_priv_setsockopt (int s) goto errout; v = (int32_t) setsockopt (sock, level, optname, optval, optlen); + close (sock); if (m_write_int32 (s, v)) goto errout; @@ -616,8 +739,6 @@ m_priv_bind (int s) socklen_t namelen; int32_t v; - LOG_DBG ((LOG_SYSDEP, 95, "m_priv_bind: enter")); - sock = mm_receive_fd (s); if (m_read_int32 (s, &v)) @@ -632,6 +753,11 @@ m_priv_bind (int s) 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); + + close (sock); if (m_write_int32 (s, v)) goto errout; @@ -653,8 +779,6 @@ m_priv_mkfifo (int s) mode_t mode; int32_t v; - LOG_DBG ((LOG_SYSDEP, 95, "m_priv_mkfifo: enter")); - if (m_read_raw (s, name, MAXPATHLEN)) goto errout; @@ -679,20 +803,242 @@ m_priv_mkfifo (int s) return; } -/* Privileged: called by monitor_loop. */ +#if defined (USE_X509) void -m_priv_close (int s) +m_priv_rsa_getkey (int s) { - int sock, r; + char cred_dir[MAXPATHLEN], pkey_path[MAXPATHLEN], pbuf[MAXPATHLEN]; + char id[MAXPATHLEN],local_id[MAXPATHLEN]; /* XXX MAXPATHLEN? */ + size_t fsize; + int32_t keyno; + RSA *rsakey = 0; + BIO *keyh; + + cred_dir[0] = pkey_path[0] = id[0] = local_id[0] = 0; + if (m_read_raw (s, pbuf, sizeof pbuf)) + goto errout; + if (pbuf[0] == '/') + strlcpy (cred_dir, pbuf, sizeof cred_dir); + else + snprintf (cred_dir, sizeof cred_dir, "%s/%s", m_state.root, pbuf); - sock = mm_receive_fd (s); - r = close (sock); + if (m_read_raw (s, pbuf, sizeof pbuf)) + goto errout; + if (pbuf[0] == '/') + strlcpy (pkey_path, pbuf, sizeof pkey_path); + else + snprintf (pkey_path, sizeof pkey_path, "%s/%s", m_state.root, pbuf); + + if (m_read_raw (s, id, sizeof id)) + goto errout; + if (m_read_raw (s, local_id, sizeof local_id)) + goto errout; - LOG_DBG ((LOG_SYSDEP, 95, "m_priv_close: closing fd %d, ret %d", sock, r)); + /* This is basically a copy of ike_auth_get_key (). */ +#if defined (USE_KEYNOTE) + if (local_id[0] && cred_dir[0]) + { + struct stat sb; + struct keynote_deckey dc; + char *privkeyfile, *buf2, *buf; + int fd, pkflen; + size_t size; + + pkflen = strlen (cred_dir) + strlen (local_id) + + sizeof PRIVATE_KEY_FILE + sizeof "//" - 1; + privkeyfile = calloc (pkflen, sizeof (char)); + if (!privkeyfile) + { + log_print ("m_priv_rsa_getkey: failed to allocate %d bytes", pkflen); + goto errout; + } + snprintf (privkeyfile, pkflen, "%s/%s/%s", cred_dir, local_id, + PRIVATE_KEY_FILE); + + if (stat (privkeyfile, &sb) < 0) + { + free (privkeyfile); + goto ignorekeynote; + } + size = (size_t)sb.st_size; + + fd = open (privkeyfile, O_RDONLY, 0); + if (fd < 0) + { + log_print ("m_priv_rsa_getkey: failed opening \"%s\"", privkeyfile); + free (privkeyfile); + goto errout; + } + + buf = calloc (size + 1, sizeof (char)); + if (!buf) + { + log_print ("m_priv_rsa_getkey: failed allocating %lu bytes", + (unsigned long)size + 1); + free (privkeyfile); + goto errout; + } + + if (read (fd, buf, size) != size) + { + free (buf); + log_print ("m_priv_rsa_getkey: " + "failed reading %lu bytes from \"%s\"", + (unsigned long)size, privkeyfile); + free (privkeyfile); + goto errout; + } + + close (fd); + + /* Parse private key string */ + buf2 = kn_get_string (buf); + free (buf); + + if (kn_decode_key (&dc, buf2, KEYNOTE_PRIVATE_KEY) == -1) + { + free (buf2); + log_print ("m_priv_rsa_getkey: failed decoding key in \"%s\"", + privkeyfile); + free (privkeyfile); + goto errout; + } + + free (buf2); + + if (dc.dec_algorithm != KEYNOTE_ALGORITHM_RSA) + { + log_print ("m_priv_rsa_getkey: wrong algorithm type %d in \"%s\"", + dc.dec_algorithm, privkeyfile); + free (privkeyfile); + kn_free_key (&dc); + goto errout; + } + + free (privkeyfile); + rsakey = dc.dec_key; + } + ignorekeynote: +#endif /* USE_KEYNOTE */ + + /* XXX I do not really like to call this from here. */ + if (check_file_secrecy (pkey_path, &fsize)) + goto errout; + + keyh = BIO_new (BIO_s_file ()); + if (keyh == NULL) + { + log_print ("m_priv_rsa_getkey: " + "BIO_new (BIO_s_file ()) failed"); + goto errout; + } + if (BIO_read_filename (keyh, pkey_path) == -1) + { + log_print ("m_priv_rsa_getkey: " + "BIO_read_filename (keyh, \"%s\") failed", + pkey_path); + BIO_free (keyh); + goto errout; + } + +#if SSLEAY_VERSION_NUMBER >= 0x00904100L + rsakey = PEM_read_bio_RSAPrivateKey (keyh, NULL, NULL, NULL); +#else + rsakey = PEM_read_bio_RSAPrivateKey (keyh, NULL, NULL); +#endif + BIO_free (keyh); + if (!rsakey) + { + log_print ("m_priv_rsa_getkey: PEM_read_bio_RSAPrivateKey failed"); + goto errout; + } + + /* Enable RSA blinding. */ + if (RSA_blinding_on (rsakey, NULL) != 1) + { + log_error ("m_priv_rsa_getkey: RSA_blinding_on () failed"); + goto errout; + } + + keyno = m_priv_local_addkey (rsakey); + m_write_int32 (s, keyno); + return; + + errout: + m_write_int32 (s, -1); + if (rsakey) + RSA_free (rsakey); return; } +void +m_priv_rsa_encrypt (int s) +{ + int32_t hashsize, padtype, datalen; + char *hash = 0, *data = 0; + RSA *key; + int32_t v; + + if (m_read_int32 (s, &hashsize)) + goto errout; + + hash = (char *)malloc (hashsize); + if (!hash) + goto errout; + + if (m_read_raw (s, hash, hashsize)) + goto errout; + + if (m_read_int32 (s, &v)) + goto errout; + + if (m_read_int32 (s, &padtype)) + goto errout; + + key = m_priv_local_getkey (v); + if (!key) + goto errout; + + data = (char *)malloc (RSA_size (key)); + if (!data) + goto errout; + + datalen = RSA_private_encrypt (hashsize, hash, data, key, padtype); + if (datalen == -1) + { + log_print ("m_priv_rsa_encrypt: RSA_private_encrypt () failed"); + goto errout; + } + + if (m_write_int32 (s, datalen)) + goto errout; + + if (m_write_raw (s, data, datalen)) + goto errout; + + free (hash); + free (data); + return; + + errout: + m_write_int32 (s, -1); + if (data) + free (data); + if (hash) + free (hash); + return; +} + +void +m_priv_rsa_freekey (int s) +{ + int32_t keyno; + if (m_read_int32 (s, &keyno) == 0) + m_priv_local_deletekey (keyno); +} +#endif /* USE_X509 */ + /* * Help functions, used by both privileged and unprivileged code */ @@ -746,9 +1092,82 @@ m_flush (int s) u_int8_t tmp; int one = 1; - LOG_DBG ((LOG_SYSDEP, 95, "m_flush: fd %d enter", s)); ioctl (s, FIONBIO, &one); /* Non-blocking */ while (read (s, &tmp, 1) > 0) ; ioctl (s, FIONBIO, 0); /* Blocking */ - LOG_DBG ((LOG_SYSDEP, 95, "m_flush: fd %d done", s)); } + +#if defined (USE_X509) +/* Privileged process RSA key storage help functions. */ +struct m_key_storage +{ + RSA *key; + int32_t keyno; + struct m_key_storage *next; +} *keylist = 0; + +int32_t +m_priv_local_addkey (RSA *key) +{ + struct m_key_storage *n, *k; + + n = (struct m_key_storage *)calloc (1, sizeof (struct m_key_storage)); + if (!n) + return 0; + + if (!keylist) + { + keylist = n; + n->keyno = 1; + } + else + { + for (k = keylist; k->next; k = k->next) ; + k->next = n; + n->keyno = k->keyno + 1; /* XXX 2^31 keys? */ + } + + n->key = key; + return n->keyno; +} + +RSA * +m_priv_local_getkey (int32_t keyno) +{ + struct m_key_storage *k; + + for (k = keylist; k; k = k->next) + if (k->keyno == keyno) + return k->key; + return 0; +} + +void +m_priv_local_deletekey (int32_t keyno) +{ + struct m_key_storage *k; + + if (keylist->keyno == keyno) + { + k = keylist; + keylist = keylist->next; + } + else + for (k = keylist; k->next; k = k->next) + if (k->next->keyno == keyno) + { + struct m_key_storage *s = k->next; + k->next = k->next->next; + k = s; + break; + } + + if (k) + { + RSA_free (k->key); + free (k); + } + + return; +} +#endif /* USE_X509 */ diff --git a/sbin/isakmpd/monitor.h b/sbin/isakmpd/monitor.h index 358b3ba54b0..d91b0614842 100644 --- a/sbin/isakmpd/monitor.h +++ b/sbin/isakmpd/monitor.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.h,v 1.2 2003/05/17 17:39:26 ho Exp $ */ +/* $OpenBSD: monitor.h,v 1.3 2003/05/18 19:37:46 ho Exp $ */ /* * Copyright (c) 2003 Håkan Olsson. All rights reserved. @@ -38,8 +38,13 @@ enum monitor_reqtypes MONITOR_SETSOCKOPT, MONITOR_BIND, MONITOR_MKFIFO, - MONITOR_CLOSE, MONITOR_SHUTDOWN, +#if defined (USE_X509) + MONITOR_RSA_UPLOADKEY, + MONITOR_RSA_GETKEY, + MONITOR_RSA_ENCRYPT, + MONITOR_RSA_FREEKEY, +#endif }; pid_t monitor_init (void); @@ -56,9 +61,17 @@ 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); -int monitor_close (int); -int monitor_fclose (FILE *); -#else + +#if defined (USE_X509) +char *monitor_RSA_upload_key (char *); +char *monitor_RSA_get_private_key (char *, char *); +int monitor_RSA_private_encrypt (int, unsigned char *, unsigned char **, + void *, int); +void monitor_RSA_free (void *); +#endif + +#else /* !USE_PRIVSEP */ + #define monitor_fopen fopen #define monitor_open open #define monitor_stat stat @@ -66,6 +79,9 @@ int monitor_fclose (FILE *); #define monitor_setsockopt setsockopt #define monitor_bind bind #define monitor_mkfifo mkfifo -#define monitor_close close -#define monitor_fclose fclose + +#if defined (USE_X509) +#define monitor_RSA_free RSA_free #endif + +#endif /* USE_PRIVSEP */ diff --git a/sbin/isakmpd/monitor_fdpass.c b/sbin/isakmpd/monitor_fdpass.c index 6a5cfff228f..e7f7f96bfba 100644 --- a/sbin/isakmpd/monitor_fdpass.c +++ b/sbin/isakmpd/monitor_fdpass.c @@ -41,6 +41,8 @@ mm_send_fd (int socket, int fd) char ch = '\0'; ssize_t n; + LOG_DBG ((LOG_SYSDEP, 90, "mm_send_fd: send %d", fd)); + memset(&msg, 0, sizeof msg); msg.msg_control = (caddr_t)tmp; msg.msg_controllen = CMSG_LEN (sizeof (int)); @@ -107,5 +109,8 @@ mm_receive_fd (int socket) return -1; } fd = (*(int *)CMSG_DATA (cmsg)); + + LOG_DBG ((LOG_SYSDEP, 90, "mm_receive_fd: recv %d", fd)); + return fd; } diff --git a/sbin/isakmpd/pf_key_v2.c b/sbin/isakmpd/pf_key_v2.c index 46c10126b04..412d601150f 100644 --- a/sbin/isakmpd/pf_key_v2.c +++ b/sbin/isakmpd/pf_key_v2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_key_v2.c,v 1.130 2003/05/18 18:16:34 ho Exp $ */ +/* $OpenBSD: pf_key_v2.c,v 1.131 2003/05/18 19:37:46 ho Exp $ */ /* $EOM: pf_key_v2.c,v 1.79 2000/12/12 00:33:19 niklas Exp $ */ /* @@ -623,7 +623,7 @@ pf_key_v2_open (void) cleanup: if (pf_key_v2_socket != -1) { - monitor_close (pf_key_v2_socket); + close (pf_key_v2_socket); pf_key_v2_socket = -1; } if (ret) diff --git a/sbin/isakmpd/policy.c b/sbin/isakmpd/policy.c index 12b1e5581fa..50d2261f30e 100644 --- a/sbin/isakmpd/policy.c +++ b/sbin/isakmpd/policy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: policy.c,v 1.61 2003/05/15 00:28:53 ho Exp $ */ +/* $OpenBSD: policy.c,v 1.62 2003/05/18 19:37:47 ho Exp $ */ /* $EOM: policy.c,v 1.49 2000/10/24 13:33:39 niklas Exp $ */ /* @@ -1829,7 +1829,7 @@ policy_init (void) } /* We're done with this. */ - monitor_close (fd); + close (fd); /* Parse buffer, break up into individual policies. */ asserts = kn_read_asserts (ptr, sz, &i); |