📄 mod_tls.c
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * mod_tls.c - Apache SSL/TLS module for NetWare by Mike Gardiner. * * This module gives Apache the ability to do SSL/TLS with a minimum amount * of effort. All of the SSL/TLS logic is already on NetWare versions 5 and * above and is interfaced through WinSock on NetWare. As you can see in * the code below SSL/TLS sockets can be created with three WinSock calls. * * To load, simply place the module in the modules directory under the main * apache tree. Then add a "SecureListen" with two arguments. The first * argument is an address and/or port. The second argument is the key pair * name as created in ConsoleOne. * * Examples: * * SecureListen 443 "SSL CertificateIP" * SecureListen 123.45.67.89:443 mycert */#define CORE_PRIVATE#define WS_SSL#define MAX_ADDRESS 512#define MAX_KEY 80#include "httpd.h"#include "http_config.h"#include "http_conf_globals.h"#include "http_log.h"#include "http_main.h"module MODULE_VAR_EXPORT tls_module;typedef struct TLSSrvConfigRec TLSSrvConfigRec;typedef struct seclisten_rec seclisten_rec;static fd_set listenfds;struct seclisten_rec { seclisten_rec *next; struct sockaddr_in local_addr; /* local IP address and port */ int fd; int used; /* Only used during restart */ char key[MAX_KEY]; int mutual;};struct TLSSrvConfigRec { table *sltable;};static seclisten_rec* ap_seclisteners = NULL;#define get_tls_cfg(srv) (TLSSrvConfigRec *) ap_get_module_config(srv->module_config, &tls_module)static int find_secure_listener(seclisten_rec *lr){ seclisten_rec *sl; for (sl = ap_seclisteners; sl; sl = sl->next) { if (!memcmp(&sl->local_addr, &lr->local_addr, sizeof(sl->local_addr))) { sl->used = 1; return sl->fd; } } return -1;}static int make_secure_socket(pool *p, const struct sockaddr_in *server, char* key, int mutual, server_rec *server_conf){ int s; int one = 1; char addr[MAX_ADDRESS]; struct sslserveropts opts; struct linger li; unsigned int optParam; WSAPROTOCOL_INFO SecureProtoInfo; int no = 1; if (server->sin_addr.s_addr != htonl(INADDR_ANY)) ap_snprintf(addr, sizeof(addr), "address %s port %d", inet_ntoa(server->sin_addr), ntohs(server->sin_port)); else ap_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port)); /* note that because we're about to slack we don't use psocket */ ap_block_alarms(); memset(&SecureProtoInfo, 0, sizeof(WSAPROTOCOL_INFO)); SecureProtoInfo.iAddressFamily = AF_INET; SecureProtoInfo.iSocketType = SOCK_STREAM; SecureProtoInfo.iProtocol = IPPROTO_TCP; SecureProtoInfo.iSecurityScheme = SECURITY_PROTOCOL_SSL; s = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, (LPWSAPROTOCOL_INFO)&SecureProtoInfo, 0, 0); if (s == INVALID_SOCKET) { errno = WSAGetLastError(); ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf, "make_secure_socket: failed to get a socket for %s", addr); ap_unblock_alarms(); return -1; } if (!mutual) { optParam = SO_SSL_ENABLE | SO_SSL_SERVER; if (WSAIoctl(s, SO_SSL_SET_FLAGS, (char *)&optParam, sizeof(optParam), NULL, 0, NULL, NULL, NULL)) { errno = WSAGetLastError(); ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf, "make_secure_socket: for %s, WSAIoctl: (SO_SSL_SET_FLAGS)", addr); ap_unblock_alarms(); return -1; } } opts.cert = key; opts.certlen = strlen(key); opts.sidtimeout = 0; opts.sidentries = 0; opts.siddir = NULL; if (WSAIoctl(s, SO_SSL_SET_SERVER, (char *)&opts, sizeof(opts), NULL, 0, NULL, NULL, NULL) != 0) { errno = WSAGetLastError(); ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf, "make_secure_socket: for %s, WSAIoctl: (SO_SSL_SET_SERVER)", addr); ap_unblock_alarms(); return -1; } if (mutual) { optParam = 0x07; // SO_SSL_AUTH_CLIENT if(WSAIoctl(s, SO_SSL_SET_FLAGS, (char*)&optParam, sizeof(optParam), NULL, 0, NULL, NULL, NULL)) { errno = WSAGetLastError(); ap_log_error( APLOG_MARK, APLOG_CRIT, server_conf, "make_secure_socket: for %s, WSAIoctl: (SO_SSL_SET_FLAGS)", addr ); ap_unblock_alarms(); return -1; } } if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(int)) < 0) { errno = WSAGetLastError(); ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf, "make_secure_socket: for %s, setsockopt: (SO_REUSEADDR)", addr); ap_unblock_alarms(); return -1; } one = 1;#ifdef SO_KEEPALIVE if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(int)) < 0) { errno = WSAGetLastError(); ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf, "make_secure_socket: for %s, setsockopt: (SO_KEEPALIVE)", addr);#endif ap_unblock_alarms(); return -1; } if (server_conf->send_buffer_size) { if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *) &server_conf->send_buffer_size, sizeof(int)) < 0) { errno = WSAGetLastError(); ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "make_secure_socket: failed to set SendBufferSize for %s, " "using default", addr); ap_unblock_alarms(); return -1; } } if (bind(s, (struct sockaddr *) server, sizeof(struct sockaddr_in)) == -1) { errno = WSAGetLastError(); ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf, "make_secure_socket: could not bind to %s", addr); ap_unblock_alarms(); return -1; } if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &no, sizeof(int)) < 0) { errno = WSAGetLastError(); ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "setsockopt: (TCP_NODELAY)"); } if (listen(s, ap_listenbacklog) == -1) { errno = WSAGetLastError(); ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "make_secure_socket: unable to listen for connections on %s", addr); ap_unblock_alarms(); return -1; } ap_unblock_alarms(); return s;}static const char *set_secure_listener(cmd_parms *cmd, void *dummy, char *ips, char* key, char* mutual){ TLSSrvConfigRec* sc = get_tls_cfg(cmd->server); const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); char *ports; unsigned short port; seclisten_rec *new; if (err != NULL) return err; ports = strchr(ips, ':'); if (ports != NULL) { if (ports == ips) return "Missing IP address"; else if (ports[1] == '\0') return "Address must end in :<port-number>"; *(ports++) = '\0'; } else { ports = ips; } new = ap_pcalloc(cmd->pool, sizeof(seclisten_rec)); new->local_addr.sin_family = AF_INET; if (ports == ips) new->local_addr.sin_addr.s_addr = htonl(INADDR_ANY); else new->local_addr.sin_addr.s_addr = ap_get_virthost_addr(ips, NULL); port = atoi(ports); if (!port) return "Port must be numeric"; ap_table_set(sc->sltable, ports, "T"); new->local_addr.sin_port = htons(port); new->fd = -1; new->used = 0; new->next = ap_seclisteners; strcpy(new->key, key); new->mutual = (mutual) ? 1 : 0; ap_seclisteners = new; return NULL;}static void InitTLS(server_rec *s, pool *p){ seclisten_rec* sl; listen_rec* lr; for (sl = ap_seclisteners; sl != NULL; sl = sl->next) { sl->fd = find_secure_listener(sl); if (sl->fd < 0) sl->fd = make_secure_socket(p, &sl->local_addr, sl->key, sl->mutual, s); else ap_note_cleanups_for_socket(p, sl->fd); if (sl->fd >= 0) { FD_SET(sl->fd, &listenfds); ap_note_cleanups_for_socket(p, sl->fd); lr = ap_pcalloc(p, sizeof(listen_rec)); if (lr) { lr->local_addr = sl->local_addr; lr->used = 0; lr->fd = sl->fd; lr->next = ap_listeners; ap_listeners = lr; } } else { clean_parent_exit(1); } } }void *tls_config_server_create(pool *p, server_rec *s){ TLSSrvConfigRec *new = ap_palloc(p, sizeof(TLSSrvConfigRec)); new->sltable = ap_make_table(p, 5); return new;}void *tls_config_server_merge(pool *p, void *basev, void *addv){ TLSSrvConfigRec *base = (TLSSrvConfigRec *)basev; TLSSrvConfigRec *add = (TLSSrvConfigRec *)addv; TLSSrvConfigRec *merged = (TLSSrvConfigRec *)ap_palloc(p, sizeof(TLSSrvConfigRec)); return merged;}int tls_hook_Fixup(request_rec *r){ TLSSrvConfigRec *sc = get_tls_cfg(r->server); table *e = r->subprocess_env; const char *s_secure; char port[8]; /* For some reason r->server->port always return 80 rather than * the current port. So for now we will get it straight from * the horses mouth. */ /* itoa(r->server->port, port, 10); */ itoa(ntohs(((r->connection)->local_addr).sin_port), port, 10); s_secure = ap_table_get(sc->sltable, port); if (!s_secure) return DECLINED; ap_table_set(e, "HTTPS", "on"); return DECLINED;}static const command_rec tls_module_cmds[] = { { "SecureListen", set_secure_listener, NULL, RSRC_CONF, TAKE23, "specify an address and/or port with a key pair name.\n" "Optional third parameter of MUTUAL configures the port for mutual authentication."}, { NULL }};module MODULE_VAR_EXPORT tls_module ={ STANDARD_MODULE_STUFF, InitTLS, /* initializer */ NULL, /* dir config creater */ NULL, /* dir merger --- default is to override */ tls_config_server_create, /* server config */ tls_config_server_merge, /* merge server config */ tls_module_cmds, /* command table */ NULL, /* handlers */ NULL, /* filename translation */ NULL, /* check_user_id */ NULL, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ NULL, /* fixups */ NULL, /* logger */ NULL, /* header parser */ NULL, /* child_init */ NULL, /* child_exit */ tls_hook_Fixup /* post read request */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -