📄 mod_nw_ssl.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 WS_SSL#define MAX_ADDRESS 512#define MAX_KEY 80#include "httpd.h"#include "http_config.h"#include "http_log.h"#include "http_protocol.h"#include "http_core.h"#include "ap_listen.h"#include "apr_strings.h"#include "apr_portable.h"#include "apr_optional.h"#include <unilib.h>#ifndef SO_TLS_UNCLEAN_SHUTDOWN#define SO_TLS_UNCLEAN_SHUTDOWN 0#endif/* The ssl_var_lookup() optional function retrieves SSL environment * variables. */APR_DECLARE_OPTIONAL_FN(char *, ssl_var_lookup, (apr_pool_t *, server_rec *, conn_rec *, request_rec *, char *));/* An optional function which returns non-zero if the given connection * is using SSL/TLS. */APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));/* The ssl_proxy_enable() and ssl_engine_disable() optional functions * are used by mod_proxy to enable use of SSL for outgoing * connections. */APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *));APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));#define strEQ(s1,s2) (strcmp(s1,s2) == 0)#define strNE(s1,s2) (strcmp(s1,s2) != 0)#define strEQn(s1,s2,n) (strncmp(s1,s2,n) == 0)#define strNEn(s1,s2,n) (strncmp(s1,s2,n) != 0)#define strcEQ(s1,s2) (strcasecmp(s1,s2) == 0)#define strcNE(s1,s2) (strcasecmp(s1,s2) != 0)#define strcEQn(s1,s2,n) (strncasecmp(s1,s2,n) == 0)#define strcNEn(s1,s2,n) (strncasecmp(s1,s2,n) != 0)#define strIsEmpty(s) (s == NULL || s[0] == NUL)module AP_MODULE_DECLARE_DATA nwssl_module;typedef struct NWSSLSrvConfigRec NWSSLSrvConfigRec;typedef struct seclisten_rec seclisten_rec;typedef struct seclistenup_rec seclistenup_rec;typedef struct secsocket_data secsocket_data;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; char *addr; apr_port_t port;};struct seclistenup_rec { seclistenup_rec *next; char key[MAX_KEY]; char *addr; apr_port_t port;};struct NWSSLSrvConfigRec { apr_table_t *sltable; apr_table_t *slutable; apr_pool_t *pPool;};struct secsocket_data { apr_socket_t* csd; int is_secure;};static apr_array_header_t *certlist = NULL;static unicode_t** certarray = NULL;static int numcerts = 0;static seclisten_rec* ap_seclisteners = NULL;static seclistenup_rec* ap_seclistenersup = NULL;#define get_nwssl_cfg(srv) (NWSSLSrvConfigRec *) ap_get_module_config(srv->module_config, &nwssl_module)static void build_cert_list (apr_pool_t *p){ int i; char **rootcerts = (char **)certlist->elts; numcerts = certlist->nelts; certarray = apr_palloc(p, sizeof(unicode_t*)*numcerts); for (i = 0; i < numcerts; ++i) { unicode_t *unistr; unistr = (unicode_t*)apr_palloc(p, strlen(rootcerts[i])*4); loc2uni (UNI_LOCAL_DEFAULT, unistr, rootcerts[i], 0, 2); certarray[i] = unistr; }}/* * Parses a host of the form <address>[:port] * :port is permitted if 'port' is not NULL */static unsigned long parse_addr(const char *w, unsigned short *ports){ struct hostent *hep; unsigned long my_addr; char *p; p = strchr(w, ':'); if (ports != NULL) { *ports = 0; if (p != NULL && strcmp(p + 1, "*") != 0) *ports = atoi(p + 1); } if (p != NULL) *p = '\0'; if (strcmp(w, "*") == 0) { if (p != NULL) *p = ':'; return htonl(INADDR_ANY); } my_addr = apr_inet_addr((char *)w); if (my_addr != INADDR_NONE) { if (p != NULL) *p = ':'; return my_addr; } hep = gethostbyname(w); if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) { /* XXX Should be echoing by h_errno the actual failure, no? * ap_log_error would be good here. Better yet - APRize. */ fprintf(stderr, "Cannot resolve host name %s --- exiting!\n", w); exit(1); } if (hep->h_addr_list[1]) { fprintf(stderr, "Host %s has multiple addresses ---\n", w); fprintf(stderr, "you must choose one explicitly for use as\n"); fprintf(stderr, "a secure port. Exiting!!!\n"); exit(1); } if (p != NULL) *p = ':'; return ((struct in_addr *) (hep->h_addr))->s_addr;}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 char *get_port_key(conn_rec *c){ seclistenup_rec *sl; for (sl = ap_seclistenersup; sl; sl = sl->next) { if ((sl->port == (c->local_addr)->port) && ((strcmp(sl->addr, "0.0.0.0") == 0) || (strcmp(sl->addr, c->local_ip) == 0))) { return sl->key; } } return NULL;}static int make_secure_socket(apr_pool_t *pconf, const struct sockaddr_in *server, char* key, int mutual, server_rec *sconf){ int s; int one = 1; char addr[MAX_ADDRESS]; struct sslserveropts opts; unsigned int optParam; WSAPROTOCOL_INFO SecureProtoInfo; int no = 1; if (server->sin_addr.s_addr != htonl(INADDR_ANY)) apr_snprintf(addr, sizeof(addr), "address %s port %d", inet_ntoa(server->sin_addr), ntohs(server->sin_port)); else apr_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port)); /* note that because we're about to slack we don't use psocket */ 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) { ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf, "make_secure_socket: failed to get a socket for %s", addr); 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)) { ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf, "make_secure_socket: for %s, WSAIoctl: " "(SO_SSL_SET_FLAGS)", addr); 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) { ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf, "make_secure_socket: for %s, WSAIoctl: " "(SO_SSL_SET_SERVER)", addr); 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)) { ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf, "make_secure_socket: for %s, WSAIoctl: " "(SO_SSL_SET_FLAGS)", addr); return -1; } } optParam = SO_TLS_UNCLEAN_SHUTDOWN; WSAIoctl(s, SO_SSL_SET_FLAGS, (char *)&optParam, sizeof(optParam), NULL, 0, NULL, NULL, NULL); return s;}int convert_secure_socket(conn_rec *c, apr_socket_t *csd){ int rcode; struct tlsclientopts sWS2Opts; struct nwtlsopts sNWTLSOpts; struct sslserveropts opts; unsigned long ulFlags; SOCKET sock; unicode_t keyFileName[60]; apr_os_sock_get(&sock, csd); /* zero out buffers */ memset((char *)&sWS2Opts, 0, sizeof(struct tlsclientopts)); memset((char *)&sNWTLSOpts, 0, sizeof(struct nwtlsopts)); /* turn on ssl for the socket */ ulFlags = (numcerts ? SO_TLS_ENABLE : SO_TLS_ENABLE | SO_TLS_BLIND_ACCEPT); rcode = WSAIoctl(sock, SO_TLS_SET_FLAGS, &ulFlags, sizeof(unsigned long), NULL, 0, NULL, NULL, NULL); if (SOCKET_ERROR == rcode) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server, "Error: %d with ioctlsocket(flag SO_TLS_ENABLE)", WSAGetLastError()); return rcode; } ulFlags = SO_TLS_UNCLEAN_SHUTDOWN; WSAIoctl(sock, SO_TLS_SET_FLAGS, &ulFlags, sizeof(unsigned long), NULL, 0, NULL, NULL, NULL); /* setup the socket for SSL */ memset (&sWS2Opts, 0, sizeof(sWS2Opts)); memset (&sNWTLSOpts, 0, sizeof(sNWTLSOpts)); sWS2Opts.options = &sNWTLSOpts; if (numcerts) { sNWTLSOpts.walletProvider = WAL_PROV_DER; //the wallet provider defined in wdefs.h sNWTLSOpts.TrustedRootList = certarray; //array of certs in UNICODE format sNWTLSOpts.numElementsInTRList = numcerts; //number of certs in TRList } else { /* setup the socket for SSL */ unicpy(keyFileName, L"SSL CertificateIP"); sWS2Opts.wallet = keyFileName; /* no client certificate */ sWS2Opts.walletlen = unilen(keyFileName); sNWTLSOpts.walletProvider = WAL_PROV_KMO; //the wallet provider defined in wdefs.h } /* make the IOCTL call */ rcode = WSAIoctl(sock, SO_TLS_SET_CLIENT, &sWS2Opts, sizeof(struct tlsclientopts), NULL, 0, NULL, NULL, NULL); /* make sure that it was successfull */ if(SOCKET_ERROR == rcode ){ ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server, "Error: %d with ioctl (SO_TLS_SET_CLIENT)", WSAGetLastError()); } return rcode;}int SSLize_Socket(SOCKET socketHnd, char *key, request_rec *r){ int rcode; struct tlsserveropts sWS2Opts; struct nwtlsopts sNWTLSOpts; unicode_t SASKey[512]; unsigned long ulFlag; memset((char *)&sWS2Opts, 0, sizeof(struct tlsserveropts)); memset((char *)&sNWTLSOpts, 0, sizeof(struct nwtlsopts));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -