From d193a4363591115b2e7a9cd16766f0015924859f Mon Sep 17 00:00:00 2001 From: hno <> Date: Fri, 4 May 2001 19:37:41 +0000 Subject: [PATCH] Support multiple SSL certificates. See http://squid.sourceforge.net/ssl/ for details. Sourceforge tag: ssl-20010504 --- src/cache_cf.cc | 100 +++++++++++++++++++++++++++++++++++++++++++- src/cf.data.pre | 36 +++++----------- src/client_side.cc | 46 ++++++++++++++++---- src/comm_select.cc | 22 +++++----- src/dns_internal.cc | 4 +- src/globals.h | 3 +- src/icp_v2.cc | 4 +- src/main.cc | 8 +--- src/protos.h | 4 +- src/ssl_support.cc | 25 +++++------ src/ssl_support.h | 6 +-- src/structs.h | 13 +++++- src/typedefs.h | 3 +- 13 files changed, 195 insertions(+), 79 deletions(-) diff --git a/src/cache_cf.cc b/src/cache_cf.cc index c36d0d6eb7..563d67a688 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -1,6 +1,6 @@ /* - * $Id: cache_cf.cc,v 1.379 2001/04/20 12:40:25 hno Exp $ + * $Id: cache_cf.cc,v 1.380 2001/05/04 13:37:41 hno Exp $ * * DEBUG: section 3 Configuration File Parsing * AUTHOR: Harvest Derived @@ -85,6 +85,14 @@ static void parse_sockaddr_in_list(sockaddr_in_list **); static void dump_sockaddr_in_list(StoreEntry *, const char *, const sockaddr_in_list *); static void free_sockaddr_in_list(sockaddr_in_list **); static int check_null_sockaddr_in_list(const sockaddr_in_list *); +#if USE_SSL +static void parse_https_port_list(https_port_list **); +static void dump_https_port_list(StoreEntry *, const char *, const https_port_list *); +static void free_https_port_list(https_port_list **); +#if 0 +static int check_null_https_port_list(const https_port_list *); +#endif +#endif /* USE_SSL */ void self_destruct(void) @@ -2052,6 +2060,96 @@ check_null_sockaddr_in_list(const sockaddr_in_list * s) return NULL == s; } +#if USE_SSL +static void +parse_https_port_list(https_port_list ** head) +{ + char *token; + char *t; + char *host; + const struct hostent *hp; + unsigned short port; + https_port_list *s; + token = strtok(NULL, w_space); + if (!token) + self_destruct(); + host = NULL; + port = 0; + if ((t = strchr(token, ':'))) { + /* host:port */ + host = token; + *t = '\0'; + port = (unsigned short) atoi(t + 1); + if (0 == port) + self_destruct(); + } else if ((port = atoi(token)) > 0) { + /* port */ + } else { + self_destruct(); + } + s = xcalloc(1, sizeof(*s)); + s->s.sin_port = htons(port); + if (NULL == host) + s->s.sin_addr = any_addr; + else if (1 == safe_inet_addr(host, &s->s.sin_addr)) + (void) 0; + else if ((hp = gethostbyname(host))) /* dont use ipcache */ + s->s.sin_addr = inaddrFromHostent(hp); + else + self_destruct(); + /* parse options ... */ + while ((token = strtok(NULL, w_space))) { + if (strncmp(token, "cert=", 5) == 0) { + safe_free(s->cert); + s->cert = xstrdup(token + 5); + } else if (strncmp(token, "key=", 4) == 0) { + safe_free(s->key); + s->key = xstrdup(token + 4); + } else { + self_destruct(); + } + } + while (*head) + head = &(*head)->next; + *head = s; +} + +static void +dump_https_port_list(StoreEntry * e, const char *n, const https_port_list * s) +{ + while (s) { + storeAppendPrintf(e, "%s %s:%d cert=\"%s\" key=\"%s\"\n", + n, + inet_ntoa(s->s.sin_addr), + ntohs(s->s.sin_port), + s->cert, + s->key); + s = s->next; + } +} + +static void +free_https_port_list(https_port_list ** head) +{ + https_port_list *s; + while ((s = *head) != NULL) { + *head = s->next; + safe_free(s->cert); + safe_free(s->key); + safe_free(s); + } +} + +#if 0 +static int +check_null_https_port_list(const https_port_list * s) +{ + return NULL == s; +} +#endif + +#endif /* USE_SSL */ + void configFreeMemory(void) { diff --git a/src/cf.data.pre b/src/cf.data.pre index 2f3c202ce4..ddc679d40f 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -1,6 +1,6 @@ # -# $Id: cf.data.pre,v 1.218 2001/04/14 00:25:17 hno Exp $ +# $Id: cf.data.pre,v 1.219 2001/05/04 13:37:41 hno Exp $ # # # SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -86,40 +86,24 @@ DOC_END NAME: https_port IFDEF: USE_SSL -TYPE: sockaddr_in_list +TYPE: https_port_list DEFAULT: none LOC: Config.Sockaddr.https DOC_START - Usage: port - hostname:port - 1.2.3.4:port - - The socket addresses where Squid will listen for HTTPS client - requests. You may specify multiple socket addresses. + Usage: [ip:]port cert=certificate.pem [key=key.pem] + The socket address where Squid will listen for HTTPS client + requests. + This is really only useful for situations where you are running squid in accelerator mode and you want to do the SSL work at the accelerator level. -DOC_END -NAME: ssl_certificate -IFDEF: USE_SSL -TYPE: string -DEFAULT: none -LOC: Config.SSL.certificate -COMMENT: /path/to/certificate -DOC_START - Certificate for use with SSL acceleration. -DOC_END + If key is not specified then the given certificate is assumed to be a + combined certificate and key file. -NAME: ssl_key -IFDEF: USE_SSL -TYPE: string -DEFAULT: none -LOC: Config.SSL.key -COMMENT: /path/to/key -DOC_START - Key for SSL certificate defined in ssl_certificate. + You may specify multiple socket addresses on multiple lines, + each with their own SSL certificate. DOC_END NAME: ssl_version diff --git a/src/client_side.cc b/src/client_side.cc index 7a3cf8df9e..2454e06e74 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side.cc,v 1.536 2001/04/17 22:43:10 hno Exp $ + * $Id: client_side.cc,v 1.537 2001/05/04 13:37:41 hno Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -3155,7 +3155,7 @@ httpAcceptDefer(int fdunused, void *dataunused) void httpAccept(int sock, void *data) { - int *N = data; + int *N = &incoming_sockets_accepted; int fd = -1; ConnStateData *connState = NULL; struct sockaddr_in peer; @@ -3243,11 +3243,19 @@ clientNegotiateSSL(int fd, void *data) commSetSelect(fd, COMM_SELECT_READ, clientReadRequest, conn, 0); } +struct _https_port_data { + SSL_CTX *sslContext; +}; +typedef struct _https_port_data https_port_data; +CBDATA_TYPE(https_port_data); + /* handle a new HTTPS connection */ static void httpsAccept(int sock, void *data) { - int *N = data; + int *N = &incoming_sockets_accepted; + https_port_data *https_port = data; + SSL_CTX *sslContext = https_port->sslContext; int fd = -1; ConnStateData *connState = NULL; struct sockaddr_in peer; @@ -3258,7 +3266,7 @@ httpsAccept(int sock, void *data) #if USE_IDENT static aclCheck_t identChecklist; #endif - commSetSelect(sock, COMM_SELECT_READ, httpsAccept, NULL, 0); + commSetSelect(sock, COMM_SELECT_READ, httpsAccept, https_port, 0); while (max-- && !httpAcceptDefer(sock, NULL)) { memset(&peer, '\0', sizeof(struct sockaddr_in)); memset(&me, '\0', sizeof(struct sockaddr_in)); @@ -3433,7 +3441,7 @@ checkFailureRatio(err_type etype, hier_code hcode) request_failure_ratio = 0.8; /* reset to something less than 1.0 */ } -void +static void clientHttpConnectionsOpen(void) { sockaddr_in_list *s; @@ -3467,7 +3475,15 @@ clientHttpConnectionsOpen(void) fd); HttpSockets[NHttpSockets++] = fd; } -#ifdef USE_SSL +} + +#if USE_SSL +static void +clientHttpsConnectionsOpen(void) +{ + https_port_list *s; + https_port_data *https_port; + int fd; for (s = Config.Sockaddr.https; s; s = s->next) { enter_suid(); fd = comm_open(SOCK_STREAM, @@ -3479,20 +3495,32 @@ clientHttpConnectionsOpen(void) leave_suid(); if (fd < 0) continue; + CBDATA_INIT_TYPE(https_port_data); + https_port = cbdataAlloc(https_port_data); + https_port->sslContext = sslLoadCert(s->cert, s->key); comm_listen(fd); - commSetSelect(fd, COMM_SELECT_READ, httpsAccept, NULL, 0); - /*commSetDefer(fd, httpAcceptDefer, NULL); */ + commSetSelect(fd, COMM_SELECT_READ, httpsAccept, https_port, 0); + commSetDefer(fd, httpAcceptDefer, NULL); debug(1, 1) ("Accepting HTTPS connections at %s, port %d, FD %d.\n", inet_ntoa(s->s.sin_addr), (int) ntohs(s->s.sin_port), fd); HttpSockets[NHttpSockets++] = fd; } +} + +#endif + +void +clientOpenListenSockets(void) +{ + clientHttpConnectionsOpen(); +#if USE_SSL + clientHttpsConnectionsOpen(); #endif if (NHttpSockets < 1) fatal("Cannot open HTTP Port"); } - void clientHttpConnectionsClose(void) { diff --git a/src/comm_select.cc b/src/comm_select.cc index fcb426840d..50cd18e415 100644 --- a/src/comm_select.cc +++ b/src/comm_select.cc @@ -1,6 +1,6 @@ /* - * $Id: comm_select.cc,v 1.49 2001/02/23 20:59:50 hno Exp $ + * $Id: comm_select.cc,v 1.50 2001/05/04 13:37:42 hno Exp $ * * DEBUG: section 5 Socket Functions * @@ -201,10 +201,10 @@ comm_check_incoming_poll_handlers(int nfds, int *fds) { int i; int fd; - int incame = 0; PF *hdl = NULL; int npfds; struct pollfd pfds[3 + MAXHTTPPORTS]; + incoming_sockets_accepted = 0; for (i = npfds = 0; i < nfds; i++) { int events; fd = fds[i]; @@ -227,7 +227,7 @@ comm_check_incoming_poll_handlers(int nfds, int *fds) #endif statCounter.syscalls.polls++; if (poll(pfds, npfds, 0) < 1) - return incame; + return incoming_sockets_accepted; for (i = 0; i < npfds; i++) { int revents; if (((revents = pfds[i].revents) == 0) || ((fd = pfds[i].fd) == -1)) @@ -235,7 +235,7 @@ comm_check_incoming_poll_handlers(int nfds, int *fds) if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { if ((hdl = fd_table[fd].read_handler)) { fd_table[fd].read_handler = NULL; - hdl(fd, &incame); + hdl(fd, fd_table[fd].read_data); } else if (pfds[i].events & POLLRDNORM) debug(5, 1) ("comm_poll_incoming: FD %d NULL read handler\n", fd); @@ -243,13 +243,13 @@ comm_check_incoming_poll_handlers(int nfds, int *fds) if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { if ((hdl = fd_table[fd].write_handler)) { fd_table[fd].write_handler = NULL; - hdl(fd, &incame); + hdl(fd, fd_table[fd].write_data); } else if (pfds[i].events & POLLWRNORM) debug(5, 1) ("comm_poll_incoming: FD %d NULL write_handler\n", fd); } } - return incame; + return incoming_sockets_accepted; } static void @@ -521,13 +521,13 @@ comm_check_incoming_select_handlers(int nfds, int *fds) { int i; int fd; - int incame = 0; int maxfd = 0; PF *hdl = NULL; fd_set read_mask; fd_set write_mask; FD_ZERO(&read_mask); FD_ZERO(&write_mask); + incoming_sockets_accepted = 0; for (i = 0; i < nfds; i++) { fd = fds[i]; if (fd_table[fd].read_handler) { @@ -548,14 +548,14 @@ comm_check_incoming_select_handlers(int nfds, int *fds) #endif statCounter.syscalls.selects++; if (select(maxfd, &read_mask, &write_mask, NULL, &zero_tv) < 1) - return incame; + return incoming_sockets_accepted; for (i = 0; i < nfds; i++) { fd = fds[i]; if (FD_ISSET(fd, &read_mask)) { if ((hdl = fd_table[fd].read_handler) != NULL) { fd_table[fd].read_handler = NULL; commUpdateReadBits(fd, NULL); - hdl(fd, &incame); + hdl(fd, fd_table[fd].read_data); } else { debug(5, 1) ("comm_select_incoming: FD %d NULL read handler\n", fd); @@ -565,14 +565,14 @@ comm_check_incoming_select_handlers(int nfds, int *fds) if ((hdl = fd_table[fd].write_handler) != NULL) { fd_table[fd].write_handler = NULL; commUpdateWriteBits(fd, NULL); - hdl(fd, &incame); + hdl(fd, fd_table[fd].write_data); } else { debug(5, 1) ("comm_select_incoming: FD %d NULL write handler\n", fd); } } } - return incame; + return incoming_sockets_accepted; } static void diff --git a/src/dns_internal.cc b/src/dns_internal.cc index 83d88aeea3..e9f7a75052 100644 --- a/src/dns_internal.cc +++ b/src/dns_internal.cc @@ -1,6 +1,6 @@ /* - * $Id: dns_internal.cc,v 1.37 2001/02/14 20:58:10 hno Exp $ + * $Id: dns_internal.cc,v 1.38 2001/05/04 13:37:42 hno Exp $ * * DEBUG: section 78 DNS lookups; interacts with lib/rfc1035.c * AUTHOR: Duane Wessels @@ -338,7 +338,7 @@ idnsGrokReply(const char *buf, size_t sz) static void idnsRead(int fd, void *data) { - int *N = data; + int *N = &incoming_sockets_accepted; ssize_t len; struct sockaddr_in from; socklen_t from_len; diff --git a/src/globals.h b/src/globals.h index f722460d98..1d87899130 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1,6 +1,6 @@ /* - * $Id: globals.h,v 1.102 2001/04/20 12:40:26 hno Exp $ + * $Id: globals.h,v 1.103 2001/05/04 13:37:42 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -153,3 +153,4 @@ extern int store_pages_max; /* 0 */ extern ssize_t store_maxobjsize; /* -1 */ extern RemovalPolicy *mem_policy; extern hash_table *proxy_auth_username_cache; /* NULL */ +extern int incoming_sockets_accepted; diff --git a/src/icp_v2.cc b/src/icp_v2.cc index cdb55b1d16..0b633945ec 100644 --- a/src/icp_v2.cc +++ b/src/icp_v2.cc @@ -1,6 +1,6 @@ /* - * $Id: icp_v2.cc,v 1.65 2001/01/12 00:37:18 wessels Exp $ + * $Id: icp_v2.cc,v 1.66 2001/05/04 13:37:42 hno Exp $ * * DEBUG: section 12 Internet Cache Protocol * AUTHOR: Duane Wessels @@ -337,7 +337,7 @@ icpPktDump(icp_common_t * pkt) void icpHandleUdp(int sock, void *data) { - int *N = data; + int *N = &incoming_sockets_accepted; struct sockaddr_in from; socklen_t from_len; LOCAL_ARRAY(char, buf, SQUID_UDP_SO_RCVBUF); diff --git a/src/main.cc b/src/main.cc index 1e664e3b38..4f45d4d4cb 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,6 +1,6 @@ /* - * $Id: main.cc,v 1.335 2001/04/14 00:03:23 hno Exp $ + * $Id: main.cc,v 1.336 2001/05/04 13:37:42 hno Exp $ * * DEBUG: section 1 Startup and Main Loop * AUTHOR: Harvest Derived @@ -280,7 +280,7 @@ shut_down(int sig) static void serverConnectionsOpen(void) { - clientHttpConnectionsOpen(); + clientOpenListenSockets(); icpConnectionsOpen(); #if USE_HTCP htcpInit(); @@ -518,10 +518,6 @@ mainInitialize(void) } #if USE_WCCP wccpInit(); -#endif -#if USE_SSL - if (Config.Sockaddr.https) - sslInit(Config.SSL.certificate, Config.SSL.key); #endif serverConnectionsOpen(); if (theOutIcpConnection >= 0) { diff --git a/src/protos.h b/src/protos.h index 7920a5ea50..72dfee7f1f 100644 --- a/src/protos.h +++ b/src/protos.h @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.402 2001/04/14 00:25:18 hno Exp $ + * $Id: protos.h,v 1.403 2001/05/04 13:37:42 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -129,7 +129,7 @@ extern int modifiedSince(StoreEntry *, request_t *); extern char *clientConstructTraceEcho(clientHttpRequest *); extern void clientPurgeRequest(clientHttpRequest *); extern int checkNegativeHit(StoreEntry *); -extern void clientHttpConnectionsOpen(void); +extern void clientOpenListenSockets(void); extern void clientHttpConnectionsClose(void); extern StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t, request_flags); extern int isTcpHit(log_type); diff --git a/src/ssl_support.cc b/src/ssl_support.cc index 0920ad6d55..7fc70cce4f 100644 --- a/src/ssl_support.cc +++ b/src/ssl_support.cc @@ -1,6 +1,6 @@ /* - * $Id: ssl_support.cc,v 1.1 2001/04/14 18:23:41 hno Exp $ + * $Id: ssl_support.cc,v 1.2 2001/05/04 13:37:42 hno Exp $ * * AUTHOR: Benno Rice * DEBUG: section 81 SSL accelerator support @@ -42,8 +42,6 @@ void clientNegotiateSSL(int fd, void *data); void clientReadSSLRequest(int fd, void *data); void connFreeSSL(int fd, void *data); -SSL_CTX *sslContext = NULL; -SSL **ssl_table = NULL; static RSA * ssl_temp_rsa_cb(SSL * ssl, int export, int keylen) @@ -90,14 +88,18 @@ ssl_verify_cb(int ok, X509_STORE_CTX * ctx) return ok; } -void -sslInit(const char *certfile, const char *keyfile) +SSL_CTX * +sslLoadCert(const char *certfile, const char *keyfile) { int ssl_error; SSL_METHOD *method; - SSL_load_error_strings(); - SSLeay_add_ssl_algorithms(); - + SSL_CTX *sslContext; + static int ssl_initialized = 0; + if (!ssl_initialized) { + ssl_initialized = 1; + SSL_load_error_strings(); + SSLeay_add_ssl_algorithms(); + } if (!keyfile) keyfile = certfile; if (!certfile) @@ -163,11 +165,10 @@ sslInit(const char *certfile, const char *keyfile) } debug(81, 9) ("Set client certifying authority list.\n"); SSL_CTX_set_client_CA_list(sslContext, SSL_load_client_CA_file(certfile)); - - ssl_table = xcalloc(Squid_MaxFD, sizeof(SSL *)); + return sslContext; } -int +int ssl_read_method(fd, buf, len) int fd; char *buf; @@ -176,7 +177,7 @@ ssl_read_method(fd, buf, len) return (SSL_read(fd_table[fd].ssl, buf, len)); } -int +int ssl_write_method(fd, buf, len) int fd; const char *buf; diff --git a/src/ssl_support.h b/src/ssl_support.h index dbebf373fa..a6949d12c4 100644 --- a/src/ssl_support.h +++ b/src/ssl_support.h @@ -1,6 +1,6 @@ /* - * $Id: ssl_support.h,v 1.1 2001/04/14 18:23:41 hno Exp $ + * $Id: ssl_support.h,v 1.2 2001/05/04 13:37:42 hno Exp $ * * AUTHOR: Benno Rice * @@ -43,9 +43,7 @@ #include #endif -extern SSL_CTX *sslContext; - -void sslInit(const char *certfile, const char *keyfile); +SSL_CTX *sslLoadCert(const char *certfile, const char *keyfile); int ssl_read_method(int, char *, int); int ssl_write_method(int, const char *, int); diff --git a/src/structs.h b/src/structs.h index de870ad3fb..e7e073bb91 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.388 2001/04/20 12:40:26 hno Exp $ + * $Id: structs.h,v 1.389 2001/05/04 13:37:42 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -292,6 +292,15 @@ struct _sockaddr_in_list { sockaddr_in_list *next; }; +#if USE_SSL +struct _https_port_list { + https_port_list *next; + struct sockaddr_in s; + char *cert; + char *key; +}; + +#endif #if DELAY_POOLS struct _delaySpec { @@ -382,7 +391,7 @@ struct _SquidConfig { struct { sockaddr_in_list *http; #if USE_SSL - sockaddr_in_list *https; + https_port_list *https; #endif } Sockaddr; #if SQUID_SNMP diff --git a/src/typedefs.h b/src/typedefs.h index 45841a1fe7..f91598b52f 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -1,6 +1,6 @@ /* - * $Id: typedefs.h,v 1.126 2001/04/20 12:40:26 hno Exp $ + * $Id: typedefs.h,v 1.127 2001/05/04 13:37:42 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -80,6 +80,7 @@ typedef struct _intrange intrange; typedef struct _ushortlist ushortlist; typedef struct _relist relist; typedef struct _sockaddr_in_list sockaddr_in_list; +typedef struct _https_port_list https_port_list; typedef struct _SquidConfig SquidConfig; typedef struct _SquidConfig2 SquidConfig2; typedef struct _close_handler close_handler; -- 2.47.2