mod_nw_ssl.c revision b9c702facf0e6ec00f9a777a8a896e906a01ecd9
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Copyright 2001-2004 Apache Software Foundation
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Licensed under the Apache License, Version 2.0 (the "License");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * you may not use this file except in compliance with the License.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * You may obtain a copy of the License at
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * http://www.apache.org/licenses/LICENSE-2.0
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Unless required by applicable law or agreed to in writing, software
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * distributed under the License is distributed on an "AS IS" BASIS,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * See the License for the specific language governing permissions and
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * limitations under the License.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * mod_tls.c - Apache SSL/TLS module for NetWare by Mike Gardiner.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * This module gives Apache the ability to do SSL/TLS with a minimum amount
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * of effort. All of the SSL/TLS logic is already on NetWare versions 5 and
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * above and is interfaced through WinSock on NetWare. As you can see in
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * the code below SSL/TLS sockets can be created with three WinSock calls.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * To load, simply place the module in the modules directory under the main
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * apache tree. Then add a "SecureListen" with two arguments. The first
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * argument is an address and/or port. The second argument is the key pair
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * name as created in ConsoleOne.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Examples:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * SecureListen 443 "SSL CertificateIP"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * SecureListen 123.45.67.89:443 mycert
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define WS_SSL
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define MAX_ADDRESS 512
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define MAX_KEY 80
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "httpd.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "http_config.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "http_log.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "ap_listen.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "apr_strings.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "apr_portable.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "apr_optional.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#ifndef SO_TLS_UNCLEAN_SHUTDOWN
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define SO_TLS_UNCLEAN_SHUTDOWN 0
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#endif
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesAPR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesAPR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesmodule AP_MODULE_DECLARE_DATA nwssl_module;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholestypedef struct NWSSLSrvConfigRec NWSSLSrvConfigRec;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholestypedef struct seclisten_rec seclisten_rec;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstruct seclisten_rec {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes seclisten_rec *next;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes struct sockaddr_in local_addr; /* local IP address and port */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int fd;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int used; /* Only used during restart */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char key[MAX_KEY];
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int mutual;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *addr;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int port;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes};
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstruct NWSSLSrvConfigRec {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_table_t *sltable;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes};
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_array_header_t *certlist = NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic unicode_t** certarray = NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int numcerts = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic seclisten_rec* ap_seclisteners = NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define get_nwssl_cfg(srv) (NWSSLSrvConfigRec *) ap_get_module_config(srv->module_config, &nwssl_module)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void build_cert_list (apr_pool_t *p)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int i;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char **rootcerts = (char **)certlist->elts;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes numcerts = certlist->nelts;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes certarray = apr_palloc(p, sizeof(unicode_t*)*numcerts);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (i = 0; i < numcerts; ++i) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unicode_t *unistr;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unistr = (unicode_t*)apr_palloc(p, strlen(rootcerts[i])*4);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes loc2uni (UNI_LOCAL_DEFAULT, unistr, rootcerts[i], 0, 2);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes certarray[i] = unistr;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Parses a host of the form <address>[:port]
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * :port is permitted if 'port' is not NULL
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic unsigned long parse_addr(const char *w, unsigned short *ports)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes struct hostent *hep;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned long my_addr;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *p;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes p = strchr(w, ':');
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (ports != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *ports = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (p != NULL && strcmp(p + 1, "*") != 0)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *ports = atoi(p + 1);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (p != NULL)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *p = '\0';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (strcmp(w, "*") == 0) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (p != NULL)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *p = ':';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return htonl(INADDR_ANY);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes my_addr = apr_inet_addr((char *)w);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (my_addr != INADDR_NONE) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (p != NULL)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *p = ':';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return my_addr;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes hep = gethostbyname(w);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* XXX Should be echoing by h_errno the actual failure, no?
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * ap_log_error would be good here. Better yet - APRize.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fprintf(stderr, "Cannot resolve host name %s --- exiting!\n", w);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes exit(1);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (hep->h_addr_list[1]) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fprintf(stderr, "Host %s has multiple addresses ---\n", w);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fprintf(stderr, "you must choose one explicitly for use as\n");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fprintf(stderr, "a secure port. Exiting!!!\n");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes exit(1);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (p != NULL)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *p = ':';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return ((struct in_addr *) (hep->h_addr))->s_addr;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int find_secure_listener(seclisten_rec *lr)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes seclisten_rec *sl;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (sl = ap_seclisteners; sl; sl = sl->next) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (!memcmp(&sl->local_addr, &lr->local_addr, sizeof(sl->local_addr))) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sl->used = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return sl->fd;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return -1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int make_secure_socket(apr_pool_t *pconf, const struct sockaddr_in *server,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char* key, int mutual, server_rec *sconf)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int s;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int one = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char addr[MAX_ADDRESS];
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes struct sslserveropts opts;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int optParam;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes WSAPROTOCOL_INFO SecureProtoInfo;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int no = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (server->sin_addr.s_addr != htonl(INADDR_ANY))
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_snprintf(addr, sizeof(addr), "address %s port %d",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes inet_ntoa(server->sin_addr), ntohs(server->sin_port));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* note that because we're about to slack we don't use psocket */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes memset(&SecureProtoInfo, 0, sizeof(WSAPROTOCOL_INFO));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SecureProtoInfo.iAddressFamily = AF_INET;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SecureProtoInfo.iSocketType = SOCK_STREAM;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SecureProtoInfo.iProtocol = IPPROTO_TCP;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SecureProtoInfo.iSecurityScheme = SECURITY_PROTOCOL_SSL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (LPWSAPROTOCOL_INFO)&SecureProtoInfo, 0, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (s == INVALID_SOCKET) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_netos_error(), sconf,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "make_secure_socket: failed to get a socket for %s",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes addr);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return -1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (!mutual) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes optParam = SO_SSL_ENABLE | SO_SSL_SERVER;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (WSAIoctl(s, SO_SSL_SET_FLAGS, (char *)&optParam,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sizeof(optParam), NULL, 0, NULL, NULL, NULL)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_netos_error(), sconf,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "make_secure_socket: for %s, WSAIoctl: "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "(SO_SSL_SET_FLAGS)", addr);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return -1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes opts.cert = key;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes opts.certlen = strlen(key);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes opts.sidtimeout = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes opts.sidentries = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes opts.siddir = NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (WSAIoctl(s, SO_SSL_SET_SERVER, (char *)&opts, sizeof(opts),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NULL, 0, NULL, NULL, NULL) != 0) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_netos_error(), sconf,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "make_secure_socket: for %s, WSAIoctl: "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "(SO_SSL_SET_SERVER)", addr);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return -1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (mutual) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes optParam = 0x07; // SO_SSL_AUTH_CLIENT
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if(WSAIoctl(s, SO_SSL_SET_FLAGS, (char*)&optParam,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sizeof(optParam), NULL, 0, NULL, NULL, NULL)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_netos_error(), sconf,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "make_secure_socket: for %s, WSAIoctl: "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "(SO_SSL_SET_FLAGS)", addr);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return -1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes optParam = SO_TLS_UNCLEAN_SHUTDOWN;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes WSAIoctl(s, SO_SSL_SET_FLAGS, (char *)&optParam, sizeof(optParam),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NULL, 0, NULL, NULL, NULL);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return s;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesint convert_secure_socket(conn_rec *c, apr_socket_t *csd)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int rcode;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes struct tlsclientopts sWS2Opts;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes struct nwtlsopts sNWTLSOpts;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes struct sslserveropts opts;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned long ulFlags;
e18ba90a1e610b43062e90cfa8bf0c1edcad7a49bnicholes SOCKET sock;
e18ba90a1e610b43062e90cfa8bf0c1edcad7a49bnicholes unicode_t keyFileName[60];
e18ba90a1e610b43062e90cfa8bf0c1edcad7a49bnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_os_sock_get(&sock, csd);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* zero out buffers */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes memset((char *)&sWS2Opts, 0, sizeof(struct tlsclientopts));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes memset((char *)&sNWTLSOpts, 0, sizeof(struct nwtlsopts));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* turn on ssl for the socket */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ulFlags = (numcerts ? SO_TLS_ENABLE : SO_TLS_ENABLE | SO_TLS_BLIND_ACCEPT);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rcode = WSAIoctl(sock, SO_TLS_SET_FLAGS, &ulFlags, sizeof(unsigned long),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NULL, 0, NULL, NULL, NULL);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (SOCKET_ERROR == rcode)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Error: %d with ioctlsocket(flag SO_TLS_ENABLE)", WSAGetLastError());
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return rcode;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ulFlags = SO_TLS_UNCLEAN_SHUTDOWN;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes WSAIoctl(sock, SO_TLS_SET_FLAGS, &ulFlags, sizeof(unsigned long),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NULL, 0, NULL, NULL, NULL);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* setup the socket for SSL */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes memset (&sWS2Opts, 0, sizeof(sWS2Opts));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes memset (&sNWTLSOpts, 0, sizeof(sNWTLSOpts));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sWS2Opts.options = &sNWTLSOpts;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (numcerts) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sNWTLSOpts.walletProvider = WAL_PROV_DER; //the wallet provider defined in wdefs.h
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sNWTLSOpts.TrustedRootList = certarray; //array of certs in UNICODE format
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sNWTLSOpts.numElementsInTRList = numcerts; //number of certs in TRList
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* setup the socket for SSL */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unicpy(keyFileName, L"SSL CertificateIP");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sWS2Opts.wallet = keyFileName; /* no client certificate */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sWS2Opts.walletlen = unilen(keyFileName);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sNWTLSOpts.walletProvider = WAL_PROV_KMO; //the wallet provider defined in wdefs.h
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* make the IOCTL call */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rcode = WSAIoctl(sock, SO_TLS_SET_CLIENT, &sWS2Opts,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sizeof(struct tlsclientopts), NULL, 0, NULL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NULL, NULL);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* make sure that it was successfull */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if(SOCKET_ERROR == rcode ){
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Error: %d with ioctl (SO_TLS_SET_CLIENT)", WSAGetLastError());
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return rcode;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char *set_secure_listener(cmd_parms *cmd, void *dummy,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *ips, const char* key,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char* mutual)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NWSSLSrvConfigRec* sc = get_nwssl_cfg(cmd->server);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *ports, *addr;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned short port;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes seclisten_rec *new;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (err != NULL)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return err;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ports = strchr(ips, ':');
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (ports != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (ports == ips)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return "Missing IP address";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else if (ports[1] == '\0')
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return "Address must end in :<port-number>";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *(ports++) = '\0';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ports = (char*)ips;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new = apr_pcalloc(cmd->pool, sizeof(seclisten_rec));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new->local_addr.sin_family = AF_INET;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (ports == ips) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new->local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes addr = apr_pstrdup(cmd->pool, "0.0.0.0");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new->local_addr.sin_addr.s_addr = parse_addr(ips, NULL);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes addr = apr_pstrdup(cmd->pool, ips);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes port = atoi(ports);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (!port)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return "Port must be numeric";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_table_set(sc->sltable, ports, "T");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new->local_addr.sin_port = htons(port);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new->fd = -1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new->used = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new->next = ap_seclisteners;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes strcpy(new->key, key);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new->mutual = (mutual) ? 1 : 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new->addr = addr;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new->port = port;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_seclisteners = new;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t nwssl_socket_cleanup(void *data)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_listen_rec* slr = (ap_listen_rec*)data;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_listen_rec* lr;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Remove our secure listener from the listener list */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (lr = ap_listeners; lr; lr = lr->next) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* slr is at the head of the list */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (lr == slr) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_listeners = slr->next;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* slr is somewhere in between or at the end*/
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (lr->next == slr) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes lr->next = slr->next;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return APR_SUCCESS;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char *set_trusted_certs(cmd_parms *cmd, void *dummy, char *arg)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char **ptr = (char **)apr_array_push(certlist);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *ptr = apr_pstrdup(cmd->pool, arg);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int nwssl_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_pool_t *ptemp)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_seclisteners = NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes certlist = apr_array_make(pconf, 1, sizeof(char *));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return OK;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int nwssl_pre_connection(conn_rec *c, void *csd)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (apr_table_get(c->notes, "nwconv-ssl")) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes convert_secure_socket(c, (apr_socket_t*)csd);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return OK;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int nwssl_post_config(apr_pool_t *pconf, apr_pool_t *plog,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_pool_t *ptemp, server_rec *s)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes seclisten_rec* sl;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_listen_rec* lr;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_socket_t* sd;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_status_t status;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (sl = ap_seclisteners; sl != NULL; sl = sl->next) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sl->fd = find_secure_listener(sl);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (sl->fd < 0)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sl->fd = make_secure_socket(pconf, &sl->local_addr, sl->key, sl->mutual, s);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (sl->fd >= 0) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_os_sock_info_t sock_info;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sock_info.os_sock = &(sl->fd);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sock_info.local = (struct sockaddr*)&(sl->local_addr);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sock_info.remote = NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sock_info.family = APR_INET;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sock_info.type = SOCK_STREAM;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_os_sock_make(&sd, &sock_info, pconf);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes lr = apr_pcalloc(pconf, sizeof(ap_listen_rec));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (lr) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes lr->sd = sd;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((status = apr_sockaddr_info_get(&lr->bind_addr, sl->addr, APR_UNSPEC, sl->port, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes pconf)) != APR_SUCCESS) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_perror(APLOG_MARK, APLOG_CRIT, status, pconf,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "alloc_listener: failed to set up sockaddr for %s:%d", sl->addr, sl->port);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return HTTP_INTERNAL_SERVER_ERROR;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes lr->next = ap_listeners;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_listeners = lr;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_pool_cleanup_register(pconf, lr, nwssl_socket_cleanup, apr_pool_cleanup_null);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes } else {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return HTTP_INTERNAL_SERVER_ERROR;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes build_cert_list(pconf);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return OK;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void *nwssl_config_server_create(apr_pool_t *p, server_rec *s)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NWSSLSrvConfigRec *new = apr_palloc(p, sizeof(NWSSLSrvConfigRec));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new->sltable = apr_table_make(p, 5);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return new;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void *nwssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NWSSLSrvConfigRec *base = (NWSSLSrvConfigRec *)basev;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NWSSLSrvConfigRec *add = (NWSSLSrvConfigRec *)addv;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NWSSLSrvConfigRec *merged = (NWSSLSrvConfigRec *)apr_palloc(p, sizeof(NWSSLSrvConfigRec));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return merged;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int isSecure (const request_rec *r)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NWSSLSrvConfigRec *sc = get_nwssl_cfg(r->server);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *s_secure = NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char port[8];
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int ret = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes itoa(((r->connection)->local_addr)->port, port, 10);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s_secure = apr_table_get(sc->sltable, port);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (s_secure)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ret = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return ret;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int nwssl_hook_Fixup(request_rec *r)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int i;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (!isSecure(r))
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return DECLINED;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_table_set(r->subprocess_env, "HTTPS", "on");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return DECLINED;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char *nwssl_hook_http_method (const request_rec *r)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (isSecure(r))
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return "https";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_port_t nwssl_hook_default_port(const request_rec *r)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (isSecure(r))
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return DEFAULT_HTTPS_PORT;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesint ssl_proxy_enable(conn_rec *c)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_table_set(c->notes, "nwconv-ssl", "Y");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesint ssl_engine_disable(conn_rec *c)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const command_rec nwssl_module_cmds[] =
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes AP_INIT_TAKE23("SecureListen", set_secure_listener, NULL, RSRC_CONF,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "specify an address and/or port with a key pair name.\n"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Optional third parameter of MUTUAL configures the port for mutual authentication."),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes AP_INIT_ITERATE("NWSSLTrustedCerts", set_trusted_certs, NULL, RSRC_CONF,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Adds trusted certificates that are used to create secure connections to proxied servers"),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes {NULL}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes};
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void register_hooks(apr_pool_t *p)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_pre_config(nwssl_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_pre_connection(nwssl_pre_connection, NULL, NULL, APR_HOOK_MIDDLE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_post_config(nwssl_post_config, NULL, NULL, APR_HOOK_MIDDLE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_fixups(nwssl_hook_Fixup, NULL, NULL, APR_HOOK_MIDDLE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_http_method(nwssl_hook_http_method, NULL,NULL, APR_HOOK_MIDDLE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_default_port (nwssl_hook_default_port, NULL,NULL, APR_HOOK_MIDDLE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesmodule AP_MODULE_DECLARE_DATA nwssl_module =
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes STANDARD20_MODULE_STUFF,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NULL, /* dir config creater */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NULL, /* dir merger --- default is to override */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes nwssl_config_server_create, /* server config */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes nwssl_config_server_merge, /* merge server config */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes nwssl_module_cmds, /* command apr_table_t */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes register_hooks
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes};
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes