1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * mod_tls.c - Apache SSL/TLS module for NetWare by Mike Gardiner.
20 * This module gives Apache the ability to do SSL/TLS with a minimum amount
21 * of effort. All of the SSL/TLS logic is already on NetWare versions 5 and
22 * above and is interfaced through WinSock on NetWare. As you can see in
23 * the code below SSL/TLS sockets can be created with three WinSock calls.
25 * To load, simply place the module in the modules directory under the main
26 * apache tree. Then add a "SecureListen" with two arguments. The first
27 * argument is an address and/or port. The second argument is the key pair
28 * name as created in ConsoleOne.
32 * SecureListen 443 "SSL CertificateIP"
33 * SecureListen 123.45.67.89:443 mycert
38 #define MAX_ADDRESS 512
43 #include "http_config.h"
45 #include "http_protocol.h"
46 #include "http_core.h"
47 #include "ap_listen.h"
48 #include "apr_strings.h"
49 #include "apr_portable.h"
50 #include "apr_optional.h"
54 #ifndef SO_TLS_UNCLEAN_SHUTDOWN
55 #define SO_TLS_UNCLEAN_SHUTDOWN 0
58 /* The ssl_var_lookup() optional function retrieves SSL environment
60 APR_DECLARE_OPTIONAL_FN(char *, ssl_var_lookup,
61 (apr_pool_t *, server_rec *,
62 conn_rec *, request_rec *,
65 /* An optional function which returns non-zero if the given connection
66 * is using SSL/TLS. */
67 APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));
69 /* The ssl_proxy_enable() and ssl_engine_disable() optional functions
70 * are used by mod_proxy to enable use of SSL for outgoing
72 APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *));
73 APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
75 #define strEQ(s1,s2) (strcmp(s1,s2) == 0)
76 #define strNE(s1,s2) (strcmp(s1,s2) != 0)
77 #define strEQn(s1,s2,n) (strncmp(s1,s2,n) == 0)
78 #define strNEn(s1,s2,n) (strncmp(s1,s2,n) != 0)
80 #define strcEQ(s1,s2) (strcasecmp(s1,s2) == 0)
81 #define strcNE(s1,s2) (strcasecmp(s1,s2) != 0)
82 #define strcEQn(s1,s2,n) (strncasecmp(s1,s2,n) == 0)
83 #define strcNEn(s1,s2,n) (strncasecmp(s1,s2,n) != 0)
85 #define strIsEmpty(s) (s == NULL || s[0] == NUL)
88 module AP_MODULE_DECLARE_DATA nwssl_module;
90 typedef struct NWSSLSrvConfigRec NWSSLSrvConfigRec;
91 typedef struct seclisten_rec seclisten_rec;
92 typedef struct seclistenup_rec seclistenup_rec;
93 typedef struct secsocket_data secsocket_data;
95 struct seclisten_rec {
97 struct sockaddr_in local_addr; /* local IP address and port */
99 int used; /* Only used during restart */
106 struct seclistenup_rec {
107 seclistenup_rec *next;
113 struct NWSSLSrvConfigRec {
114 apr_table_t *sltable;
115 apr_table_t *slutable;
119 struct secsocket_data {
124 static apr_array_header_t *certlist = NULL;
125 static unicode_t** certarray = NULL;
126 static int numcerts = 0;
127 static seclisten_rec* ap_seclisteners = NULL;
128 static seclistenup_rec* ap_seclistenersup = NULL;
130 #define get_nwssl_cfg(srv) (NWSSLSrvConfigRec *) ap_get_module_config(srv->module_config, &nwssl_module)
133 static void build_cert_list (apr_pool_t *p)
136 char **rootcerts = (char **)certlist->elts;
138 numcerts = certlist->nelts;
139 certarray = apr_palloc(p, sizeof(unicode_t*)*numcerts);
141 for (i = 0; i < numcerts; ++i) {
143 unistr = (unicode_t*)apr_palloc(p, strlen(rootcerts[i])*4);
144 loc2uni (UNI_LOCAL_DEFAULT, unistr, rootcerts[i], 0, 2);
145 certarray[i] = unistr;
150 * Parses a host of the form <address>[:port]
151 * :port is permitted if 'port' is not NULL
153 static unsigned long parse_addr(const char *w, unsigned short *ports)
156 unsigned long my_addr;
162 if (p != NULL && strcmp(p + 1, "*") != 0)
163 *ports = atoi(p + 1);
168 if (strcmp(w, "*") == 0) {
171 return htonl(INADDR_ANY);
174 my_addr = apr_inet_addr((char *)w);
175 if (my_addr != INADDR_NONE) {
181 hep = gethostbyname(w);
183 if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
184 /* XXX Should be echoing by h_errno the actual failure, no?
185 * ap_log_error would be good here. Better yet - APRize.
187 fprintf(stderr, "Cannot resolve host name %s --- exiting!\n", w);
191 if (hep->h_addr_list[1]) {
192 fprintf(stderr, "Host %s has multiple addresses ---\n", w);
193 fprintf(stderr, "you must choose one explicitly for use as\n");
194 fprintf(stderr, "a secure port. Exiting!!!\n");
201 return ((struct in_addr *) (hep->h_addr))->s_addr;
204 static int find_secure_listener(seclisten_rec *lr)
208 for (sl = ap_seclisteners; sl; sl = sl->next) {
209 if (!memcmp(&sl->local_addr, &lr->local_addr, sizeof(sl->local_addr))) {
217 static char *get_port_key(conn_rec *c)
221 for (sl = ap_seclistenersup; sl; sl = sl->next) {
222 if ((sl->port == (c->local_addr)->port) &&
223 ((strcmp(sl->addr, "0.0.0.0") == 0) || (strcmp(sl->addr, c->local_ip) == 0))) {
230 static int make_secure_socket(apr_pool_t *pconf, const struct sockaddr_in *server,
231 char* key, int mutual, server_rec *sconf)
235 char addr[MAX_ADDRESS];
236 struct sslserveropts opts;
237 unsigned int optParam;
238 WSAPROTOCOL_INFO SecureProtoInfo;
241 if (server->sin_addr.s_addr != htonl(INADDR_ANY))
242 apr_snprintf(addr, sizeof(addr), "address %s port %d",
243 inet_ntoa(server->sin_addr), ntohs(server->sin_port));
245 apr_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port));
247 /* note that because we're about to slack we don't use psocket */
248 memset(&SecureProtoInfo, 0, sizeof(WSAPROTOCOL_INFO));
250 SecureProtoInfo.iAddressFamily = AF_INET;
251 SecureProtoInfo.iSocketType = SOCK_STREAM;
252 SecureProtoInfo.iProtocol = IPPROTO_TCP;
253 SecureProtoInfo.iSecurityScheme = SECURITY_PROTOCOL_SSL;
255 s = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,
256 (LPWSAPROTOCOL_INFO)&SecureProtoInfo, 0, 0);
258 if (s == INVALID_SOCKET) {
259 ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf,
260 "make_secure_socket: failed to get a socket for %s",
266 optParam = SO_SSL_ENABLE | SO_SSL_SERVER;
268 if (WSAIoctl(s, SO_SSL_SET_FLAGS, (char *)&optParam,
269 sizeof(optParam), NULL, 0, NULL, NULL, NULL)) {
270 ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf,
271 "make_secure_socket: for %s, WSAIoctl: "
272 "(SO_SSL_SET_FLAGS)", addr);
278 opts.certlen = strlen(key);
283 if (WSAIoctl(s, SO_SSL_SET_SERVER, (char *)&opts, sizeof(opts),
284 NULL, 0, NULL, NULL, NULL) != 0) {
285 ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf,
286 "make_secure_socket: for %s, WSAIoctl: "
287 "(SO_SSL_SET_SERVER)", addr);
292 optParam = 0x07; // SO_SSL_AUTH_CLIENT
294 if(WSAIoctl(s, SO_SSL_SET_FLAGS, (char*)&optParam,
295 sizeof(optParam), NULL, 0, NULL, NULL, NULL)) {
296 ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf,
297 "make_secure_socket: for %s, WSAIoctl: "
298 "(SO_SSL_SET_FLAGS)", addr);
303 optParam = SO_TLS_UNCLEAN_SHUTDOWN;
304 WSAIoctl(s, SO_SSL_SET_FLAGS, (char *)&optParam, sizeof(optParam),
305 NULL, 0, NULL, NULL, NULL);
310 int convert_secure_socket(conn_rec *c, apr_socket_t *csd)
313 struct tlsclientopts sWS2Opts;
314 struct nwtlsopts sNWTLSOpts;
315 struct sslserveropts opts;
316 unsigned long ulFlags;
318 unicode_t keyFileName[60];
320 apr_os_sock_get(&sock, csd);
322 /* zero out buffers */
323 memset((char *)&sWS2Opts, 0, sizeof(struct tlsclientopts));
324 memset((char *)&sNWTLSOpts, 0, sizeof(struct nwtlsopts));
326 /* turn on ssl for the socket */
327 ulFlags = (numcerts ? SO_TLS_ENABLE : SO_TLS_ENABLE | SO_TLS_BLIND_ACCEPT);
328 rcode = WSAIoctl(sock, SO_TLS_SET_FLAGS, &ulFlags, sizeof(unsigned long),
329 NULL, 0, NULL, NULL, NULL);
330 if (SOCKET_ERROR == rcode)
332 ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
333 "Error: %d with ioctlsocket(flag SO_TLS_ENABLE)", WSAGetLastError());
337 ulFlags = SO_TLS_UNCLEAN_SHUTDOWN;
338 WSAIoctl(sock, SO_TLS_SET_FLAGS, &ulFlags, sizeof(unsigned long),
339 NULL, 0, NULL, NULL, NULL);
341 /* setup the socket for SSL */
342 memset (&sWS2Opts, 0, sizeof(sWS2Opts));
343 memset (&sNWTLSOpts, 0, sizeof(sNWTLSOpts));
344 sWS2Opts.options = &sNWTLSOpts;
347 sNWTLSOpts.walletProvider = WAL_PROV_DER; //the wallet provider defined in wdefs.h
348 sNWTLSOpts.TrustedRootList = certarray; //array of certs in UNICODE format
349 sNWTLSOpts.numElementsInTRList = numcerts; //number of certs in TRList
352 /* setup the socket for SSL */
353 unicpy(keyFileName, L"SSL CertificateIP");
354 sWS2Opts.wallet = keyFileName; /* no client certificate */
355 sWS2Opts.walletlen = unilen(keyFileName);
357 sNWTLSOpts.walletProvider = WAL_PROV_KMO; //the wallet provider defined in wdefs.h
360 /* make the IOCTL call */
361 rcode = WSAIoctl(sock, SO_TLS_SET_CLIENT, &sWS2Opts,
362 sizeof(struct tlsclientopts), NULL, 0, NULL,
365 /* make sure that it was successfull */
366 if(SOCKET_ERROR == rcode ){
367 ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
368 "Error: %d with ioctl (SO_TLS_SET_CLIENT)", WSAGetLastError());
373 int SSLize_Socket(SOCKET socketHnd, char *key, request_rec *r)
376 struct tlsserveropts sWS2Opts;
377 struct nwtlsopts sNWTLSOpts;
378 unicode_t SASKey[512];
379 unsigned long ulFlag;
381 memset((char *)&sWS2Opts, 0, sizeof(struct tlsserveropts));
382 memset((char *)&sNWTLSOpts, 0, sizeof(struct nwtlsopts));
385 ulFlag = SO_TLS_ENABLE;
386 rcode = WSAIoctl(socketHnd, SO_TLS_SET_FLAGS, &ulFlag, sizeof(unsigned long), NULL, 0, NULL, NULL, NULL);
389 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
390 "Error: %d with WSAIoctl(SO_TLS_SET_FLAGS, SO_TLS_ENABLE)", WSAGetLastError());
395 ulFlag = SO_TLS_SERVER;
396 rcode = WSAIoctl(socketHnd, SO_TLS_SET_FLAGS, &ulFlag, sizeof(unsigned long),NULL, 0, NULL, NULL, NULL);
400 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
401 "Error: %d with WSAIoctl(SO_TLS_SET_FLAGS, SO_TLS_SERVER)", WSAGetLastError());
405 loc2uni(UNI_LOCAL_DEFAULT, SASKey, key, 0, 0);
407 //setup the tlsserveropts struct
408 sWS2Opts.wallet = SASKey;
409 sWS2Opts.walletlen = unilen(SASKey);
410 sWS2Opts.sidtimeout = 0;
411 sWS2Opts.sidentries = 0;
412 sWS2Opts.siddir = NULL;
413 sWS2Opts.options = &sNWTLSOpts;
415 //setup the nwtlsopts structure
417 sNWTLSOpts.walletProvider = WAL_PROV_KMO;
418 sNWTLSOpts.keysList = NULL;
419 sNWTLSOpts.numElementsInKeyList = 0;
420 sNWTLSOpts.reservedforfutureuse = NULL;
421 sNWTLSOpts.reservedforfutureCRL = NULL;
422 sNWTLSOpts.reservedforfutureCRLLen = 0;
423 sNWTLSOpts.reserved1 = NULL;
424 sNWTLSOpts.reserved2 = NULL;
425 sNWTLSOpts.reserved3 = NULL;
428 rcode = WSAIoctl(socketHnd,
431 sizeof(struct tlsserveropts),
437 if(SOCKET_ERROR == rcode) {
438 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
439 "Error: %d with WSAIoctl(SO_TLS_SET_SERVER)", WSAGetLastError());
447 static const char *set_secure_listener(cmd_parms *cmd, void *dummy,
448 const char *ips, const char* key,
451 NWSSLSrvConfigRec* sc = get_nwssl_cfg(cmd->server);
452 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
461 ports = strchr(ips, ':');
465 return "Missing IP address";
466 else if (ports[1] == '\0')
467 return "Address must end in :<port-number>";
475 new = apr_pcalloc(cmd->pool, sizeof(seclisten_rec));
476 new->local_addr.sin_family = AF_INET;
479 new->local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
480 addr = apr_pstrdup(cmd->pool, "0.0.0.0");
483 new->local_addr.sin_addr.s_addr = parse_addr(ips, NULL);
484 addr = apr_pstrdup(cmd->pool, ips);
490 return "Port must be numeric";
492 apr_table_add(sc->sltable, ports, addr);
494 new->local_addr.sin_port = htons(port);
497 new->next = ap_seclisteners;
498 strcpy(new->key, key);
499 new->mutual = (mutual) ? 1 : 0;
502 ap_seclisteners = new;
506 static const char *set_secure_upgradeable_listener(cmd_parms *cmd, void *dummy,
507 const char *ips, const char* key)
509 NWSSLSrvConfigRec* sc = get_nwssl_cfg(cmd->server);
510 seclistenup_rec *listen_node;
511 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
514 seclistenup_rec *new;
519 ports = strchr(ips, ':');
523 return "Missing IP address";
524 else if (ports[1] == '\0')
525 return "Address must end in :<port-number>";
534 addr = apr_pstrdup(cmd->pool, "0.0.0.0");
537 addr = apr_pstrdup(cmd->pool, ips);
543 return "Port must be numeric";
545 apr_table_set(sc->slutable, ports, addr);
547 new = apr_pcalloc(cmd->pool, sizeof(seclistenup_rec));
548 new->next = ap_seclistenersup;
549 strcpy(new->key, key);
552 ap_seclistenersup = new;
557 static apr_status_t nwssl_socket_cleanup(void *data)
559 ap_listen_rec* slr = (ap_listen_rec*)data;
562 /* Remove our secure listener from the listener list */
563 for (lr = ap_listeners; lr; lr = lr->next) {
564 /* slr is at the head of the list */
566 ap_listeners = slr->next;
569 /* slr is somewhere in between or at the end*/
570 if (lr->next == slr) {
571 lr->next = slr->next;
578 static const char *set_trusted_certs(cmd_parms *cmd, void *dummy, char *arg)
580 char **ptr = (char **)apr_array_push(certlist);
582 *ptr = apr_pstrdup(cmd->pool, arg);
586 static int nwssl_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
589 ap_seclisteners = NULL;
590 ap_seclistenersup = NULL;
591 certlist = apr_array_make(pconf, 1, sizeof(char *));
596 static int nwssl_pre_connection(conn_rec *c, void *csd)
599 if (apr_table_get(c->notes, "nwconv-ssl")) {
600 convert_secure_socket(c, (apr_socket_t*)csd);
603 secsocket_data *csd_data = apr_palloc(c->pool, sizeof(secsocket_data));
605 csd_data->csd = (apr_socket_t*)csd;
606 csd_data->is_secure = 0;
607 ap_set_module_config(c->conn_config, &nwssl_module, (void*)csd_data);
613 static int nwssl_post_config(apr_pool_t *pconf, apr_pool_t *plog,
614 apr_pool_t *ptemp, server_rec *s)
620 seclistenup_rec *slu;
623 for (sl = ap_seclisteners; sl != NULL; sl = sl->next) {
624 sl->fd = find_secure_listener(sl);
627 sl->fd = make_secure_socket(pconf, &sl->local_addr, sl->key, sl->mutual, s);
630 apr_os_sock_info_t sock_info;
632 sock_info.os_sock = &(sl->fd);
633 sock_info.local = (struct sockaddr*)&(sl->local_addr);
634 sock_info.remote = NULL;
635 sock_info.family = APR_INET;
636 sock_info.type = SOCK_STREAM;
638 apr_os_sock_make(&sd, &sock_info, pconf);
640 lr = apr_pcalloc(pconf, sizeof(ap_listen_rec));
644 if ((status = apr_sockaddr_info_get(&lr->bind_addr, sl->addr, APR_UNSPEC, sl->port, 0,
645 pconf)) != APR_SUCCESS) {
646 ap_log_perror(APLOG_MARK, APLOG_CRIT, status, pconf,
647 "alloc_listener: failed to set up sockaddr for %s:%d", sl->addr, sl->port);
648 return HTTP_INTERNAL_SERVER_ERROR;
650 lr->next = ap_listeners;
652 apr_pool_cleanup_register(pconf, lr, nwssl_socket_cleanup, apr_pool_cleanup_null);
655 return HTTP_INTERNAL_SERVER_ERROR;
659 for (slu = ap_seclistenersup; slu; slu = slu->next) {
660 /* Check the listener list for a matching upgradeable listener */
662 for (lr = ap_listeners; lr; lr = lr->next) {
663 if (slu->port == lr->bind_addr->port) {
669 ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, plog,
670 "No Listen directive found for upgradeable listener %s:%d", slu->addr, slu->port);
674 build_cert_list(pconf);
679 static void *nwssl_config_server_create(apr_pool_t *p, server_rec *s)
681 NWSSLSrvConfigRec *new = apr_palloc(p, sizeof(NWSSLSrvConfigRec));
682 new->sltable = apr_table_make(p, 5);
683 new->slutable = apr_table_make(p, 5);
687 static void *nwssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
689 NWSSLSrvConfigRec *base = (NWSSLSrvConfigRec *)basev;
690 NWSSLSrvConfigRec *add = (NWSSLSrvConfigRec *)addv;
691 NWSSLSrvConfigRec *merged = (NWSSLSrvConfigRec *)apr_palloc(p, sizeof(NWSSLSrvConfigRec));
695 static int compare_ipports(void *rec, const char *key, const char *value)
697 conn_rec *c = (conn_rec*)rec;
700 ((strcmp(value, "0.0.0.0") == 0) || (strcmp(value, c->local_ip) == 0)))
707 static int isSecureConnEx (const server_rec *s, const conn_rec *c, const apr_table_t *t)
711 itoa((c->local_addr)->port, port, 10);
712 if (!apr_table_do(compare_ipports, (void*)c, t, port, NULL))
720 static int isSecureConn (const server_rec *s, const conn_rec *c)
722 NWSSLSrvConfigRec *sc = get_nwssl_cfg(s);
724 return isSecureConnEx (s, c, sc->sltable);
727 static int isSecureConnUpgradeable (const server_rec *s, const conn_rec *c)
729 NWSSLSrvConfigRec *sc = get_nwssl_cfg(s);
731 return isSecureConnEx (s, c, sc->slutable);
734 static int isSecure (const request_rec *r)
736 return isSecureConn (r->server, r->connection);
739 static int isSecureUpgradeable (const request_rec *r)
741 return isSecureConnUpgradeable (r->server, r->connection);
744 static int isSecureUpgraded (const request_rec *r)
746 secsocket_data *csd_data = (secsocket_data*)ap_get_module_config(r->connection->conn_config, &nwssl_module);
748 return csd_data->is_secure;
751 static int nwssl_hook_Fixup(request_rec *r)
755 if (!isSecure(r) && !isSecureUpgraded(r))
758 apr_table_set(r->subprocess_env, "HTTPS", "on");
763 static const char *nwssl_hook_http_method (const request_rec *r)
765 if (isSecure(r) && !isSecureUpgraded(r))
771 static apr_port_t nwssl_hook_default_port(const request_rec *r)
774 return DEFAULT_HTTPS_PORT;
779 int ssl_proxy_enable(conn_rec *c)
781 apr_table_set(c->notes, "nwconv-ssl", "Y");
786 int ssl_engine_disable(conn_rec *c)
791 static int ssl_is_https(conn_rec *c)
793 secsocket_data *csd_data = (secsocket_data*)ap_get_module_config(c->conn_config, &nwssl_module);
795 return isSecureConn (c->base_server, c) || (csd_data && csd_data->is_secure);
798 /* This function must remain safe to use for a non-SSL connection. */
799 char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, char *var)
801 NWSSLSrvConfigRec *mc = get_nwssl_cfg(s);
810 * When no pool is given try to find one
822 * Request dependent stuff
828 if (strcEQ(var, "HTTP_USER_AGENT"))
829 result = apr_table_get(r->headers_in, "User-Agent");
830 else if (strcEQ(var, "HTTP_REFERER"))
831 result = apr_table_get(r->headers_in, "Referer");
832 else if (strcEQ(var, "HTTP_COOKIE"))
833 result = apr_table_get(r->headers_in, "Cookie");
834 else if (strcEQ(var, "HTTP_FORWARDED"))
835 result = apr_table_get(r->headers_in, "Forwarded");
836 else if (strcEQ(var, "HTTP_HOST"))
837 result = apr_table_get(r->headers_in, "Host");
838 else if (strcEQ(var, "HTTP_PROXY_CONNECTION"))
839 result = apr_table_get(r->headers_in, "Proxy-Connection");
840 else if (strcEQ(var, "HTTP_ACCEPT"))
841 result = apr_table_get(r->headers_in, "Accept");
842 else if (strcEQ(var, "HTTPS")) {
843 if (isSecure(r) || isSecureUpgraded(r))
848 else if (strlen(var) > 5 && strcEQn(var, "HTTP:", 5))
849 /* all other headers from which we are still not know about */
850 result = apr_table_get(r->headers_in, var+5);
855 if (strcEQ(var, "REQUEST_METHOD"))
857 else if (strcEQ(var, "REQUEST_SCHEME"))
858 result = ap_http_method(r);
859 else if (strcEQ(var, "REQUEST_URI"))
861 else if (strcEQ(var, "REQUEST_FILENAME"))
862 result = r->filename;
863 else if (strcEQ(var, "REMOTE_HOST"))
864 result = ap_get_remote_host(r->connection, r->per_dir_config,
866 else if (strcEQ(var, "REMOTE_IDENT"))
867 result = ap_get_remote_logname(r);
868 else if (strcEQ(var, "REMOTE_USER"))
874 if (strcEQn(var, "SSL", 3)) break; /* shortcut common case */
876 if (strcEQ(var, "SERVER_ADMIN"))
877 result = r->server->server_admin;
878 else if (strcEQ(var, "SERVER_NAME"))
879 result = ap_get_server_name(r);
880 else if (strcEQ(var, "SERVER_PORT"))
881 result = apr_psprintf(p, "%u", ap_get_server_port(r));
882 else if (strcEQ(var, "SERVER_PROTOCOL"))
883 result = r->protocol;
884 else if (strcEQ(var, "SCRIPT_FILENAME"))
885 result = r->filename;
889 if (strcEQ(var, "PATH_INFO"))
890 result = r->path_info;
891 else if (strcEQ(var, "QUERY_STRING"))
893 else if (strcEQ(var, "IS_SUBREQ"))
894 result = (r->main != NULL ? "true" : "false");
895 else if (strcEQ(var, "DOCUMENT_ROOT"))
896 result = ap_document_root(r);
897 else if (strcEQ(var, "AUTH_TYPE"))
898 result = r->ap_auth_type;
899 else if (strcEQ(var, "THE_REQUEST"))
900 result = r->the_request;
908 if (result == NULL && c != NULL) {
910 /* XXX-Can't get specific SSL info from NetWare */
911 /* SSLConnRec *sslconn = myConnConfig(c);
912 if (strlen(var) > 4 && strcEQn(var, "SSL_", 4)
913 && sslconn && sslconn->ssl)
914 result = ssl_var_lookup_ssl(p, c, var+4);*/
916 if (strlen(var) > 4 && strcEQn(var, "SSL_", 4))
918 else if (strcEQ(var, "REMOTE_ADDR"))
919 result = c->remote_ip;
923 * Totally independent stuff
925 if (result == NULL) {
926 if (strlen(var) > 12 && strcEQn(var, "SSL_VERSION_", 12))
928 /* XXX-Can't get specific SSL info from NetWare */
929 /*result = ssl_var_lookup_ssl_version(p, var+12);*/
930 else if (strcEQ(var, "SERVER_SOFTWARE"))
931 result = ap_get_server_version();
932 else if (strcEQ(var, "API_VERSION")) {
933 result = apr_itoa(p, MODULE_MAGIC_NUMBER);
936 else if (strcEQ(var, "TIME_YEAR")) {
937 apr_time_exp_lt(&tm, apr_time_now());
938 result = apr_psprintf(p, "%02d%02d",
939 (tm.tm_year / 100) + 19, tm.tm_year % 100);
942 #define MKTIMESTR(format, tmfield) \
943 apr_time_exp_lt(&tm, apr_time_now()); \
944 result = apr_psprintf(p, format, tm.tmfield); \
946 else if (strcEQ(var, "TIME_MON")) {
947 MKTIMESTR("%02d", tm_mon+1)
949 else if (strcEQ(var, "TIME_DAY")) {
950 MKTIMESTR("%02d", tm_mday)
952 else if (strcEQ(var, "TIME_HOUR")) {
953 MKTIMESTR("%02d", tm_hour)
955 else if (strcEQ(var, "TIME_MIN")) {
956 MKTIMESTR("%02d", tm_min)
958 else if (strcEQ(var, "TIME_SEC")) {
959 MKTIMESTR("%02d", tm_sec)
961 else if (strcEQ(var, "TIME_WDAY")) {
962 MKTIMESTR("%d", tm_wday)
964 else if (strcEQ(var, "TIME")) {
965 apr_time_exp_lt(&tm, apr_time_now());
966 result = apr_psprintf(p,
967 "%02d%02d%02d%02d%02d%02d%02d", (tm.tm_year / 100) + 19,
968 (tm.tm_year % 100), tm.tm_mon+1, tm.tm_mday,
969 tm.tm_hour, tm.tm_min, tm.tm_sec);
972 /* all other env-variables from the parent Apache process */
973 else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) {
974 result = apr_table_get(r->notes, var+4);
976 result = apr_table_get(r->subprocess_env, var+4);
978 result = getenv(var+4);
982 if (result != NULL && resdup)
983 result = apr_pstrdup(p, result);
986 return (char *)result;
989 static apr_status_t ssl_io_filter_Upgrade(ap_filter_t *f,
990 apr_bucket_brigade *bb)
993 #define SWITCH_STATUS_LINE "HTTP/1.1 101 Switching Protocols"
994 #define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1"
995 #define CONNECTION_HEADER "Connection: Upgrade"
997 const char *connection;
998 apr_bucket_brigade *upgradebb;
999 request_rec *r = f->r;
1000 apr_socket_t *csd = NULL;
1002 unicode_t keyFileName[512];
1007 secsocket_data *csd_data;
1009 /* Just remove the filter, if it doesn't work the first time, it won't
1010 * work at all for this request.
1012 ap_remove_output_filter(f);
1014 /* No need to ensure that this is a server with optional SSL, the filter
1015 * is only inserted if that is true.
1018 upgrade = apr_table_get(r->headers_in, "Upgrade");
1019 if (upgrade == NULL) {
1020 return ap_pass_brigade(f->next, bb);
1022 token_string = apr_pstrdup(r->pool,upgrade);
1023 token = apr_strtok(token_string,", ",&token_state);
1024 while (token && strcmp(token,"TLS/1.0")) {
1025 apr_strtok(NULL,", ",&token_state);
1027 // "Upgrade: TLS/1.0" header not found, don't do Upgrade
1029 return ap_pass_brigade(f->next, bb);
1032 connection = apr_table_get(r->headers_in, "Connection");
1033 token_string = apr_pstrdup(r->pool,connection);
1034 token = apr_strtok(token_string,",",&token_state);
1035 while (token && strcmp(token,"Upgrade")) {
1036 apr_strtok(NULL,",",&token_state);
1038 // "Connection: Upgrade" header not found, don't do Upgrade
1040 return ap_pass_brigade(f->next, bb);
1043 apr_table_unset(r->headers_out, "Upgrade");
1046 csd_data = (secsocket_data*)ap_get_module_config(r->connection->conn_config, &nwssl_module);
1047 csd = csd_data->csd;
1050 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
1051 "Unable to get upgradeable socket handle");
1052 return ap_pass_brigade(f->next, bb);
1056 if (r->method_number == M_OPTIONS) {
1057 apr_bucket *b = NULL;
1058 /* This is a mandatory SSL upgrade. */
1060 upgradebb = apr_brigade_create(r->pool, f->c->bucket_alloc);
1062 ap_fputstrs(f->next, upgradebb, SWITCH_STATUS_LINE, CRLF,
1063 UPGRADE_HEADER, CRLF, CONNECTION_HEADER, CRLF, CRLF, NULL);
1065 b = apr_bucket_flush_create(f->c->bucket_alloc);
1066 APR_BRIGADE_INSERT_TAIL(upgradebb, b);
1067 ap_pass_brigade(f->next, upgradebb);
1070 /* This is optional, and should be configurable, for now don't bother
1073 return ap_pass_brigade(f->next, bb);
1076 key = get_port_key(r->connection);
1080 apr_os_sock_get(&sockdes, csd);
1083 ret = SSLize_Socket(sockdes, key, r);
1085 csd_data->is_secure = 1;
1089 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
1090 "Upgradeable socket handle not found");
1091 return ap_pass_brigade(f->next, bb);
1094 ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
1095 "Awaiting re-negotiation handshake");
1097 return ap_pass_brigade(f->next, bb);
1100 static void ssl_hook_Insert_Filter(request_rec *r)
1102 NWSSLSrvConfigRec *sc = get_nwssl_cfg(r->server);
1104 if (isSecureUpgradeable (r)) {
1105 ap_add_output_filter("UPGRADE_FILTER", NULL, r, r->connection);
1109 static const command_rec nwssl_module_cmds[] =
1111 AP_INIT_TAKE23("SecureListen", set_secure_listener, NULL, RSRC_CONF,
1112 "specify an address and/or port with a key pair name.\n"
1113 "Optional third parameter of MUTUAL configures the port for mutual authentication."),
1114 AP_INIT_TAKE2("NWSSLUpgradeable", set_secure_upgradeable_listener, NULL, RSRC_CONF,
1115 "specify an address and/or port with a key pair name, that can be upgraded to an SSL connection.\n"
1116 "The address and/or port must have already be defined using a Listen directive."),
1117 AP_INIT_ITERATE("NWSSLTrustedCerts", set_trusted_certs, NULL, RSRC_CONF,
1118 "Adds trusted certificates that are used to create secure connections to proxied servers"),
1122 static void register_hooks(apr_pool_t *p)
1124 ap_register_output_filter ("UPGRADE_FILTER", ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5);
1126 ap_hook_pre_config(nwssl_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
1127 ap_hook_pre_connection(nwssl_pre_connection, NULL, NULL, APR_HOOK_MIDDLE);
1128 ap_hook_post_config(nwssl_post_config, NULL, NULL, APR_HOOK_MIDDLE);
1129 ap_hook_fixups(nwssl_hook_Fixup, NULL, NULL, APR_HOOK_MIDDLE);
1130 ap_hook_http_method(nwssl_hook_http_method, NULL,NULL, APR_HOOK_MIDDLE);
1131 ap_hook_default_port (nwssl_hook_default_port, NULL,NULL, APR_HOOK_MIDDLE);
1132 ap_hook_insert_filter (ssl_hook_Insert_Filter, NULL,NULL, APR_HOOK_MIDDLE);
1134 APR_REGISTER_OPTIONAL_FN(ssl_is_https);
1135 APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);
1137 APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
1138 APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
1141 module AP_MODULE_DECLARE_DATA nwssl_module =
1143 STANDARD20_MODULE_STUFF,
1144 NULL, /* dir config creater */
1145 NULL, /* dir merger --- default is to override */
1146 nwssl_config_server_create, /* server config */
1147 nwssl_config_server_merge, /* merge server config */
1148 nwssl_module_cmds, /* command apr_table_t */