diff -urP apache_1.2b8/conf/httpsd.conf-dist apache_1.2b8+ssl/conf/httpsd.conf-dist --- apache_1.2b8/conf/httpsd.conf-dist Thu Jan 1 01:00:00 1970 +++ apache_1.2b8+ssl/conf/httpsd.conf-dist Wed Apr 9 10:52:29 1997 @@ -0,0 +1,232 @@ +# This is the main server configuration file. See URL http://www.apache.org/ +# for instructions. + +# Do NOT simply read the instructions in here without understanding +# what they do, if you are unsure consult the online docs. You have been +# warned. + +# Originally by Rob McCool + +# ServerType is either inetd, or standalone. + +ServerType standalone + +# If you are running from inetd, go to "ServerAdmin". + +# Port: The port the standalone listens to. For ports < 1023, you will +# need httpd to be run as root initially. + +Port 80 + +# HostnameLookups: Log the names of clients or just their IP numbers +# e.g. www.apache.org (on) or 204.62.129.132 (off) +HostnameLookups on + +# If you wish httpd to run as a different user or group, you must run +# httpd as root initially and it will switch. + +# User/Group: The name (or #number) of the user/group to run httpd as. +# On SCO (ODT 3) use User nouser and Group nogroup +User nobody +Group #-1 + +# The following directive disables keepalives and HTTP header flushes for +# Netscape 2.x and browsers which spoof it. There are known problems with +# these + +BrowserMatch Mozilla/2 nokeepalive + +# ServerAdmin: Your address, where problems with the server should be +# e-mailed. + +ServerAdmin you@your.address + +# ServerRoot: The directory the server's config, error, and log files +# are kept in + +ServerRoot /usr/local/etc/httpd + +# BindAddress: You can support virtual hosts with this option. This option +# is used to tell the server which IP address to listen to. It can either +# contain "*", an IP address, or a fully qualified Internet domain name. +# See also the VirtualHost directive. + +#BindAddress * + +# ErrorLog: The location of the error log file. If this does not start +# with /, ServerRoot is prepended to it. + +ErrorLog logs/error_log + +# TransferLog: The location of the transfer log file. If this does not +# start with /, ServerRoot is prepended to it. + +TransferLog logs/access_log + +# PidFile: The file the server should log its pid to +PidFile logs/httpd.pid + +# ScoreBoardFile: File used to store internal server process information +ScoreBoardFile logs/apache_status + +# ServerName allows you to set a host name which is sent back to clients for +# your server if it's different than the one the program would get (i.e. use +# "www" instead of the host's real name). +# +# Note: You cannot just invent host names and hope they work. The name you +# define here must be a valid DNS name for your host. If you don't understand +# this, ask your network administrator. + +#ServerName new.host.name + +# CacheNegotiatedDocs: By default, Apache sends Pragma: no-cache with each +# document that was negotiated on the basis of content. This asks proxy +# servers not to cache the document. Uncommenting the following line disables +# this behavior, and proxies will be allowed to cache the documents. + +#CacheNegotiatedDocs + +# Timeout: The number of seconds before receives and sends time out + +Timeout 300 + +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. + +KeepAlive On + +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We reccomend you leave this number high, for maximum performance. + +MaxKeepAliveRequests 100 + +# KeepAliveTimeout: Number of seconds to wait for the next request + +KeepAliveTimeout 15 + +# Server-pool size regulation. Rather than making you guess how many +# server processes you need, Apache dynamically adapts to the load it +# sees --- that is, it tries to maintain enough server processes to +# handle the current load, plus a few spare servers to handle transient +# load spikes (e.g., multiple simultaneous requests from a single +# Netscape browser). + +# It does this by periodically checking how many servers are waiting +# for a request. If there are fewer than MinSpareServers, it creates +# a new spare. If there are more than MaxSpareServers, some of the +# spares die off. These values are probably OK for most sites --- + +MinSpareServers 5 +MaxSpareServers 10 + +# Number of servers to start --- should be a reasonable ballpark figure. + +StartServers 5 + +# Limit on total number of servers running, i.e., limit on the number +# of clients who can simultaneously connect --- if this limit is ever +# reached, clients will be LOCKED OUT, so it should NOT BE SET TOO LOW. +# It is intended mainly as a brake to keep a runaway server from taking +# Unix with it as it spirals down... + +MaxClients 150 + +# MaxRequestsPerChild: the number of requests each child process is +# allowed to process before the child dies. +# The child will exit so as to avoid problems after prolonged use when +# Apache (and maybe the libraries it uses) leak. On most systems, this +# isn't really needed, but a few (such as Solaris) do have notable leaks +# in the libraries. + +MaxRequestsPerChild 30 + +# Proxy Server directives. Uncomment the following line to +# enable the proxy server: + +#ProxyRequests On + +# To enable the cache as well, edit and uncomment the following lines: + +#CacheRoot /usr/local/etc/httpd/proxy +#CacheSize 5 +#CacheGcInterval 4 +#CacheMaxExpire 24 +#CacheLastModifiedFactor 0.1 +#CacheDefaultExpire 1 +#NoCache a_domain.com another_domain.edu joes.garage_sale.com + +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, in addition to the default. See also the VirtualHost command + +#Listen 3000 +#Listen 12.34.56.78:80 + +# Note that all SSL options can apply to virtual hosts. + +# Disable SSL. Useful in combination with virtual hosts. +#SSLDisable + +# Set the CA certificate verification path (must be PEM encoded). +# (in addition to getenv("SSL_CERT_DIR"), I think). +#SSLCACertificatePath /usr/local/etc/httpd/conf + +# Set the CA certificate verification file (must be PEM encoded). +# (in addition to getenv("SSL_CERT_FILE"), I think). +#SSLCACertificateFile /usr/local/etc/httpd/conf/your.pem + +# Point SSLCertificateFile at a PEM encoded certificate. +# If the certificate is encrypted, then you will be prompted for a pass phrase. +# Note that a kill -1 will prompt again. +# A test certificate can be generated with "make certificate". +#SSLCertificateFile /usr/local/etc/httpd/conf/your.pem + +# If the key is not combined with the certificate, use this directive to +# point at the key file. If this starts with a '/' it specifies an absolute +# path, otherwise it is relative to the default certificate area. That is, it +# means "/private/". +#SSLCertificateKeyFile /usr/local/etc/httpd/conf/your.key + +# Set SSLVerifyClient to: +# 0 if no certicate is required +# 1 if the client may present a valid certificate +# 2 if the client must present a valid certificate +# 3 if the client may present a valid certificate but it is not required to +# have a valid CA +SSLVerifyClient 0 +# How deeply to verify before deciding they don't have a valid certificate +SSLVerifyDepth 10 + +# Translate the client X509 into a Basic authorisation. This means that the +# standard Auth/DBMAuth methods can be used for access control. The user name +# is the "one line" version of the client's X509 certificate. Note that no +# password is obtained from the user. Every entry in the user file needs this +# password: xxj31ZMTZzkVA. See the code for further explanation. +SSLFakeBasicAuth + +# A home for miscellaneous rubbish generated by SSL. Much of it is duplicated +# in the error log file. +SSLLogFile /tmp/ssl.log + +# New and undocumented directives +#SSLRequiredCiphers +#SSLRequireCipher +#SSLBanCipher + +# VirtualHost: Allows the daemon to respond to requests for more than one +# server address, if your server machine is configured to accept IP packets +# for multiple addresses. This can be accomplished with the ifconfig +# alias flag, or through kernel patches like VIF. + +# Any httpd.conf or srm.conf directive may go into a VirtualHost command. +# See alto the BindAddress entry. + +# +#ServerAdmin webmaster@host.some_domain.com +#DocumentRoot /www/docs/host.some_domain.com +#ServerName host.some_domain.com +#ErrorLog logs/host.some_domain.com-error_log +#TransferLog logs/host.some_domain.com-access_log +# + + diff -urP apache_1.2b8/src/Configuration apache_1.2b8+ssl/src/Configuration --- apache_1.2b8/src/Configuration Tue Apr 8 05:53:05 1997 +++ apache_1.2b8+ssl/src/Configuration Wed Apr 9 10:52:29 1997 @@ -50,6 +50,11 @@ OPTIM=-O2 #RANLIB= +# +# SSL Related stuff +# +SSL_DIR= /usr/local/ssl + ################################################################ # Rules configuration # @@ -57,7 +62,7 @@ # functions. The format is: Rule RULE=value # # At present, only the following RULES are known: WANTHSREGEX, SOCKS4, -# STATUS and IRIXNIS. +# STATUS, SSL and IRIXNIS. # # For all Rules, if set to "yes", then Configure knows we want that # capability and does what is required to add it in. If set to "default" @@ -75,6 +80,12 @@ # to 'yes'. If the status module is not included, having STATUS # set to 'yes' has no impact. # +# SSL: +# If Configure determines that you are using the SSL module, +# it will automatically enable full ssl support if set to 'yes'. +# If the ssl module is not included, having SSL set to 'yes' has +# no impact. +# # IRIXNIS: # Only takes effect if Configure determines that you are running # SGI IRIX. If you are, and you are using NIS, you should set this @@ -84,6 +95,7 @@ Rule STATUS=yes Rule SOCKS4=no Rule IRIXNIS=no +Rule SSL=yes # The following rules should be set automatically by Configure. However, if # they are not set by Configure (because we don't know the correct value for @@ -220,6 +232,11 @@ ## allows other modules to be loaded in at runtime, # Module dld_module mod_dld.o + +# Apache inverts the module list. SSL must go first to fake +# basic authorization. So, uncomment this line to add SSL. + +# Module ssl_module mod_ssl.o ## mod_usertrack.c is the new name for mod_cookies.c. This module ## uses Netscape cookies to automatically construct and log accurate diff -urP apache_1.2b8/src/Configuration.tmpl apache_1.2b8+ssl/src/Configuration.tmpl --- apache_1.2b8/src/Configuration.tmpl Tue Mar 25 05:58:00 1997 +++ apache_1.2b8+ssl/src/Configuration.tmpl Wed Apr 9 10:52:30 1997 @@ -50,6 +50,11 @@ OPTIM=-O2 #RANLIB= +# +# SSL Related stuff +# +SSL_DIR= /usr/local/ssl + ################################################################ # Rules configuration # @@ -57,7 +62,7 @@ # functions. The format is: Rule RULE=value # # At present, only the following RULES are known: WANTHSREGEX, SOCKS4, -# STATUS and IRIXNIS. +# STATUS, SSL and IRIXNIS. # # For all Rules, if set to "yes", then Configure knows we want that # capability and does what is required to add it in. If set to "default" @@ -75,6 +80,12 @@ # to 'yes'. If the status module is not included, having STATUS # set to 'yes' has no impact. # +# SSL: +# If Configure determines that you are using the SSL module, +# it will automatically enable full ssl support if set to 'yes'. +# If the ssl module is not included, having SSL set to 'yes' has +# no impact. +# # IRIXNIS: # Only takes effect if Configure determines that you are running # SGI IRIX. If you are, and you are using NIS, you should set this @@ -84,6 +95,7 @@ Rule STATUS=yes Rule SOCKS4=no Rule IRIXNIS=no +Rule SSL=yes # The following rules should be set automatically by Configure. However, if # they are not set by Configure (because we don't know the correct value for @@ -220,6 +232,11 @@ ## allows other modules to be loaded in at runtime, # Module dld_module mod_dld.o + +# Apache inverts the module list. SSL must go first to fake +# basic authorization. So, uncomment this line to add SSL. + +# Module ssl_module mod_ssl.o ## mod_usertrack.c is the new name for mod_cookies.c. This module ## uses Netscape cookies to automatically construct and log accurate diff -urP apache_1.2b8/src/Configure apache_1.2b8+ssl/src/Configure --- apache_1.2b8/src/Configure Mon Apr 7 11:44:17 1997 +++ apache_1.2b8+ssl/src/Configure Wed Apr 9 10:52:30 1997 @@ -133,6 +133,7 @@ RULE_STATUS=`./helpers/CutRule STATUS $file` RULE_SOCKS4=`./helpers/CutRule SOCKS4 $file` RULE_IRIXNIS=`./helpers/CutRule IRIXNIS $file` +RULE_SSL=`./helpers/CutRule SSL $file` # # Now we determine the OS/Platform automagically, thanks to @@ -509,6 +510,21 @@ if grep "$STAT_MOD" Makefile > /dev/null; then if [ "$RULE_STATUS" = "yes" ]; then CFLAGS="$CFLAGS -DSTATUS" + fi +fi + +# +# Are they using the SSL module? If so, check +# for SSL rule... +# NOTE: We assume that if they are using SSL, then they've +# set SSL_DIR to the proper location. +# +SSL_MOD="mod_ssl" +if grep "$SSL_MOD" Makefile > /dev/null; then + if [ "$RULE_SSL" = "yes" ]; then + CFLAGS="$CFLAGS -DAPACHE_SSL -DSERVER_SUBVERSION=\\\"JPM/0.5-ssl\\\"" + INCLUDES="$INCLUDES -I\$(SSL_DIR)/include" + LIBS="$LIBS -L\$(SSL_DIR)/lib -lssl -lcrypto" fi fi diff -urP apache_1.2b8/src/Makefile.tmpl apache_1.2b8+ssl/src/Makefile.tmpl --- apache_1.2b8/src/Makefile.tmpl Mon Mar 24 23:49:09 1997 +++ apache_1.2b8+ssl/src/Makefile.tmpl Wed Apr 9 10:52:30 1997 @@ -30,6 +30,14 @@ httpd: $(REGLIB) $(OBJS) $(CC) $(LFLAGS) -o httpd $(OBJS) $(REGLIB) $(LIBS) +certificate: + $(SSL_DIR)/bin/ssleay req \ + -config $(SSL_DIR)/lib/ssleay.cnf \ + -new -x509 -nodes -out ../conf/httpsd.pem \ + -keyout ../conf/httpsd.pem; \ + ln -sf ../conf/httpsd.pem ../conf/`$(SSL_DIR)/bin/ssleay \ + x509 -noout -hash < ../conf/httpsd.pem`.0 + regex/libregex.a: (cd regex; $(MAKE) lib CC=$(CC) AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)') @@ -114,6 +122,7 @@ util_script.h scoreboard.h mod_userdir.o: httpd.h http_config.h mod_usertrack.o: httpd.h http_config.h http_core.h +mod_ssl.o: httpd.h http_config.h modules.o: httpd.h http_config.h rfc1413.o: httpd.h http_log.h rfc1413.h util.o: httpd.h http_conf_globals.h diff -urP apache_1.2b8/src/buff.c apache_1.2b8+ssl/src/buff.c --- apache_1.2b8/src/buff.c Tue Mar 4 22:44:38 1997 +++ apache_1.2b8+ssl/src/buff.c Wed Apr 9 10:52:30 1997 @@ -139,6 +139,11 @@ fb->fd = -1; fb->fd_in = -1; +#ifdef APACHE_SSL + fb->ssl = NULL; + fb->szClientX509 = NULL; +#endif + return fb; } @@ -159,7 +164,7 @@ { fb->bytes_sent = *(const long int *)optval - (long int)fb->outcnt;; return 0; - } else + } else { errno = EINVAL; return -1; @@ -320,7 +325,13 @@ } } do { +#ifdef APACHE_SSL + rv = (fb->ssl == NULL) + ? read( fb->fd_in, buf, nbyte) + : SSL_read(fb->ssl, buf, nbyte); +#else rv = read( fb->fd_in, buf, nbyte ); +#endif } while ( rv == -1 && errno == EINTR ); return( rv ); } @@ -609,12 +620,18 @@ * This is *seriously broken* if used on a non-blocking fd. It will poll. */ static int -write_it_all( int fd, const void *buf, int nbyte ) { +write_it_all( BUFF *fb, const void *buf, int nbyte ) { int i; while( nbyte > 0 ) { - i = write( fd, buf, nbyte ); +#ifdef APACHE_SSL + i = (fb->ssl == NULL) + ? write( fb->fd, buf, nbyte ) + : SSL_write( fb->ssl, buf, nbyte ); +#else + i = write( fb->fd, buf, nbyte ); +#endif if( i == -1 ) { if( errno != EAGAIN && errno != EINTR ) { return( -1 ); @@ -643,19 +660,26 @@ int i, rv; #endif - if( !(fb->flags & B_CHUNK) ) return write( fb->fd, buf, nbyte ); + if( !(fb->flags & B_CHUNK) ) +#ifdef APACHE_SSL + return (fb->ssl == NULL) + ? write(fb->fd, buf, nbyte) + : SSL_write(fb->ssl, buf, nbyte); +#else + return write( fb->fd, buf, nbyte ); +#endif #ifdef NO_WRITEV /* without writev() this has poor performance, too bad */ ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012", nbyte); - if( write_it_all(fb->fd, chunksize, strlen(chunksize)) == -1 ) { + if( write_it_all(fb, chunksize, strlen(chunksize)) == -1 ) { return( -1 ); } - if( write_it_all(fb->fd, buf, nbyte) == -1 ) { + if( write_it_all(fb, buf, nbyte) == -1 ) { return( -1 ); } - if( write_it_all(fb->fd, "\015\012", 2) == -1 ) { + if( write_it_all(fb, "\015\012", 2) == -1 ) { return( -1 ); } return( nbyte ); @@ -757,10 +781,16 @@ /* it is just too painful to try to re-cram the buffer while * chunking */ - i = write_it_all( fb->fd, fb->outbase, fb->outcnt ) + i = write_it_all( fb, fb->outbase, fb->outcnt ) ? -1 : fb->outcnt; } else { +#ifdef APACHE_SSL + do i = (fb->ssl == NULL) + ? write(fb->fd, fb->outbase, fb->outcnt) + : SSL_write(fb->ssl, fb->outbase, fb->outcnt); +#else do i = write(fb->fd, fb->outbase, fb->outcnt); +#endif while (i == -1 && errno == EINTR); } if (i > 0) fb->bytes_sent += i; @@ -845,7 +875,13 @@ while (fb->outcnt > 0) { /* the buffer must be full */ +#ifdef APACHE_SSL + do i = (fb->ssl == NULL) + ? write(fb->fd, fb->outbase, fb->outcnt) + : SSL_write(fb->ssl, fb->outbase, fb->outcnt); +#else do i = write(fb->fd, fb->outbase, fb->outcnt); +#endif while (i == -1 && errno == EINTR); if (i > 0) fb->bytes_sent += i; if (i == 0) @@ -898,6 +934,13 @@ fb->flags |= B_EOF | B_EOUT; fb->fd = -1; fb->fd_in = -1; + +#ifdef APACHE_SSL + if (fb->ssl != NULL) { + SSL_free(fb->ssl); + fb->ssl = NULL; + } +#endif if (rc1 != 0) return rc1; else if (rc2 != 0) return rc2; diff -urP apache_1.2b8/src/buff.h apache_1.2b8+ssl/src/buff.h --- apache_1.2b8/src/buff.h Mon Feb 10 16:49:54 1997 +++ apache_1.2b8+ssl/src/buff.h Wed Apr 9 10:52:30 1997 @@ -52,6 +52,10 @@ #include +#ifdef APACHE_SSL +#include "ssl.h" +#endif + /* Reading is buffered */ #define B_RD (1) /* Writing is buffered */ @@ -94,6 +98,13 @@ /* could also put pointers to the basic I/O routines here */ int fd; /* the file descriptor */ int fd_in; /* input file descriptor, if different */ + +#ifdef APACHE_SSL + /* Add some context for SSL */ + SSL *ssl; + char *szClientX509; + int nVerifyError; +#endif }; /* Options to bset/getopt */ diff -urP apache_1.2b8/src/http_config.c apache_1.2b8+ssl/src/http_config.c --- apache_1.2b8/src/http_config.c Sun Mar 23 00:51:01 1997 +++ apache_1.2b8+ssl/src/http_config.c Wed Apr 9 10:52:30 1997 @@ -1044,7 +1044,11 @@ { server_rec *s = (server_rec *)pcalloc (p, sizeof (server_rec)); +#ifdef APACHE_SSL + s->port = 0; /* actual value depends on SSLDisabled */ +#else s->port = DEFAULT_PORT; +#endif s->server_admin = DEFAULT_ADMIN; s->server_hostname = NULL; s->error_fname = DEFAULT_ERRORLOG; @@ -1083,6 +1087,8 @@ process_resource_config (s, s->access_confname, p, ptemp); fixup_virtual_hosts (p, s); + + default_server_hostnames(s); for (m = top_module; m; m = m->next) if (m->init) diff -urP apache_1.2b8/src/http_main.c apache_1.2b8+ssl/src/http_main.c --- apache_1.2b8/src/http_main.c Mon Apr 7 11:59:50 1997 +++ apache_1.2b8+ssl/src/http_main.c Wed Apr 9 10:52:30 1997 @@ -1834,6 +1834,16 @@ (struct sockaddr_in *)&sa_server, child_num); +#ifdef APACHE_SSL + /* + * This returns false if the connection cannot be setup, + * so maybe we should do something with this here... + * however it also blocks the BUFF connections + * so the next bit should fall out anyway! + */ + ApacheSSLSetupConnection(current_conn); +#endif + /* * Read and process each request found on our connection * until no requests are left or we decide to close. @@ -2056,6 +2066,7 @@ { struct sockaddr_in sa_server; int saved_sd; + static int bFirst = 1; standalone = 1; sd = listenmaxfd = -1; @@ -2097,16 +2108,21 @@ copy_listeners(pconf); saved_sd=sd; restart_time = time(NULL); - clear_pool (pconf); - ptrans = make_sub_pool (pconf); - - server_conf = read_config(pconf, ptrans, server_confname); + if(!bFirst) + { + clear_pool (pconf); + ptrans = make_sub_pool (pconf); + server_conf = read_config(pconf, ptrans, server_confname); + } + else + bFirst = 0; + open_logs(server_conf, pconf); set_group_privs(); accept_mutex_init(pconf); reinit_scoreboard(pconf); - default_server_hostnames (server_conf); + /* default_server_hostnames (server_conf);*/ if (listeners == NULL) { if(!is_graceful) { @@ -2267,7 +2283,7 @@ server_conf = read_config (pconf, ptrans, server_confname); if(standalone) { - clear_pool (pconf); /* standalone_main rereads... */ + /* clear_pool (pconf); /* standalone_main rereads... */ standalone_main(argc, argv); } else { diff -urP apache_1.2b8/src/http_protocol.c apache_1.2b8+ssl/src/http_protocol.c --- apache_1.2b8/src/http_protocol.c Mon Apr 7 12:58:39 1997 +++ apache_1.2b8+ssl/src/http_protocol.c Wed Apr 9 10:54:44 1997 @@ -550,9 +550,10 @@ int i, port; /* This routine parses full URLs, if they match the server */ - if (strncmp(uri, "http://", 7)) return uri; - name = pstrdup(r->pool, uri + 7); - + if (strncmp(uri,http_method_str(r),http_method_len(r))) + return uri; + name = pstrdup(r->pool, uri + http_method_len(r)); + /* Find the hostname, assuming a valid request */ i = ind(name, '/'); name[i] = '\0'; @@ -560,7 +561,7 @@ /* Find the port */ host = getword_nc(r->pool, &name, ':'); if (*name) port = atoi(name); - else port = 80; + else port = default_port(r); /* Make sure ports patch */ if (port != r->server->port) return uri; @@ -674,7 +675,7 @@ static void check_hostalias (request_rec *r) { const char *hostname=r->hostname; char *host = getword(r->pool, &hostname, ':'); /* Get rid of port */ - int port = (*hostname) ? atoi(hostname) : 80; + int port = (*hostname) ? atoi(hostname) : default_port(r); server_rec *s; int l; @@ -700,7 +701,7 @@ if ((!strcasecmp(host, s->server_hostname)) && (port == s->port)) { r->server = r->connection->server = s; - if (r->hostlen && !strncmp(r->uri, "http://", 7)) { + if (r->hostlen && !strncmp(r->uri, http_method_str(r), http_method_len(r))) { r->uri += r->hostlen; parse_uri(r, r->uri); } @@ -710,7 +711,7 @@ for( sar = s->addrs; sar; sar = sar->next ) { if( !strcasecmp( sar->virthost, host ) ) { r->server = r->connection->server = s; - if( r->hostlen && !strncmp( r->uri, "http://", 7) ) { + if (r->hostlen && !strncmp( r->uri, http_method_str(r), http_method_len(r)) ) { r->uri += r->hostlen; r->proxyreq = 0; } diff -urP apache_1.2b8/src/httpd.h apache_1.2b8+ssl/src/httpd.h --- apache_1.2b8/src/httpd.h Tue Apr 8 05:49:32 1997 +++ apache_1.2b8+ssl/src/httpd.h Wed Apr 9 10:52:31 1997 @@ -95,9 +95,24 @@ */ -/* -------------- Port number for server running standalone --------------- */ +/* -------------- Port number and protocol for server running standalone -- */ -#define DEFAULT_PORT 80 +#ifdef APACHE_SSL +#define HTTP_PORT 80 +#define HTTPS_PORT 443 +#define default_port(r) ((r)->connection->client->ssl ? HTTPS_PORT : HTTP_PORT) +#define is_default_port(port,r) ((port) == default_port(r)) +#define http_method(r) ((r)->connection->client->ssl ? "https" : "http") +#define http_method_str(r) ((r)->connection->client->ssl ? "https://" : "http://") +#define http_method_len(r) ((r)->connection->client->ssl ? 8 : 7) +#else +#define DEFAULT_PORT 80 +#define default_port(r) DEFAULT_PORT +#define is_default_port(port,r) ((port) == DEFAULT_PORT) +#define http_method(r) "http" +#define http_method_str(r) "http://" +#define http_method_len(r) 7 +#endif /* --------- Default user name and group name running standalone ---------- */ /* --- These may be specified as numbers by placing a # before a number --- */ @@ -666,7 +681,7 @@ #define escape_uri(ppool,path) os_escape_path(ppool,path,1) extern char *escape_html(pool *p, const char *s); char *construct_server(pool *p, const char *hostname, int port); -char *construct_url (pool *p, const char *path, const server_rec *s); +char *construct_url (pool *p, const char *path, const request_rec *r); char *escape_shell_cmd (pool *p, const char *s); int count_dirs(const char *path); @@ -703,3 +718,7 @@ unsigned long get_virthost_addr (const char *hostname, short int *port); extern time_t restart_time; + +#ifdef APACHE_SSL +int ApacheSSLSetupConnection(conn_rec * conn); +#endif diff -urP apache_1.2b8/src/md5.h apache_1.2b8+ssl/src/md5.h --- apache_1.2b8/src/md5.h Wed Jan 1 19:10:23 1997 +++ apache_1.2b8+ssl/src/md5.h Wed Apr 9 10:52:31 1997 @@ -91,9 +91,9 @@ UINT4 state[4]; /* state (ABCD) */ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ -} MD5_CTX; +} APACHE_MD5_CTX; -extern void MD5Init(MD5_CTX *context); -extern void MD5Update(MD5_CTX *context, const unsigned char *input, +extern void MD5Init(APACHE_MD5_CTX *context); +extern void MD5Update(APACHE_MD5_CTX *context, const unsigned char *input, unsigned int inputLen); -extern void MD5Final(unsigned char digest[16], MD5_CTX *context); +extern void MD5Final(unsigned char digest[16], APACHE_MD5_CTX *context); diff -urP apache_1.2b8/src/md5c.c apache_1.2b8+ssl/src/md5c.c --- apache_1.2b8/src/md5c.c Wed Jan 1 19:10:24 1997 +++ apache_1.2b8+ssl/src/md5c.c Wed Apr 9 10:52:31 1997 @@ -158,7 +158,7 @@ /* MD5 initialization. Begins an MD5 operation, writing a new context. */ void -MD5Init(MD5_CTX *context) +MD5Init(APACHE_MD5_CTX *context) { context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */ @@ -173,7 +173,7 @@ context. */ void -MD5Update(MD5_CTX *context, const unsigned char *input, unsigned int inputLen) +MD5Update(APACHE_MD5_CTX *context, const unsigned char *input, unsigned int inputLen) { unsigned int i, index, partLen; @@ -209,7 +209,7 @@ the message digest and zeroizing the context. */ void -MD5Final(unsigned char digest[16], MD5_CTX *context) +MD5Final(unsigned char digest[16], APACHE_MD5_CTX *context) { unsigned char bits[8]; unsigned int index, padLen; diff -urP apache_1.2b8/src/mod_dir.c apache_1.2b8+ssl/src/mod_dir.c --- apache_1.2b8/src/mod_dir.c Sun Apr 6 09:43:41 1997 +++ apache_1.2b8+ssl/src/mod_dir.c Wed Apr 9 10:52:31 1997 @@ -791,7 +791,7 @@ "/", NULL); table_set (r->headers_out, "Location", - construct_url(r->pool, ifile, r->server)); + construct_url(r->pool, ifile, r)); return HTTP_MOVED_PERMANENTLY; } diff -urP apache_1.2b8/src/mod_imap.c apache_1.2b8+ssl/src/mod_imap.c --- apache_1.2b8/src/mod_imap.c Sun Apr 6 09:43:41 1997 +++ apache_1.2b8+ssl/src/mod_imap.c Wed Apr 9 10:52:31 1997 @@ -367,13 +367,13 @@ char my_base[SMALLBUF] = {'\0'}; if ( ! strcasecmp(value, "map" ) || ! strcasecmp(value, "menu") ) { - if (r->server->port == 80 ) { + if (is_default_port(r->server->port, r)) { ap_snprintf(url, SMALLBUF, - "http://%s%s", r->server->server_hostname, r->uri); + "%s://%s%s", http_method(r), r->server->server_hostname, r->uri); } else { - ap_snprintf(url, SMALLBUF, "http://%s:%d%s", r->server->server_hostname, - r->server->port, r->uri); + ap_snprintf(url, SMALLBUF, "%s://%s:%d%s", http_method(r), + r->server->server_hostname, r->server->port, r->uri); } return; } @@ -411,11 +411,12 @@ url[SMALLBUF-1] = '\0'; } else { - if (r->server->port == 80 ) { - ap_snprintf(url, SMALLBUF, "http://%s/", r->server->server_hostname); + if (is_default_port(r->server->port, r)) { + ap_snprintf(url, SMALLBUF, "%s://%s/", http_method(r), + r->server->server_hostname); } - if (r->server->port != 80 ) { - ap_snprintf(url, SMALLBUF, "http://%s:%d/", + if (is_default_port(r->server->port, r)) { + ap_snprintf(url, SMALLBUF, "%s://%s:%d/", http_method(r), r->server->server_hostname, r->server->port); } /* no base, no value: pick a simple default */ } diff -urP apache_1.2b8/src/mod_log_config.c apache_1.2b8+ssl/src/mod_log_config.c --- apache_1.2b8/src/mod_log_config.c Sun Mar 23 00:51:02 1997 +++ apache_1.2b8+ssl/src/mod_log_config.c Wed Apr 9 10:52:31 1997 @@ -130,6 +130,13 @@ * %...U: the URL path requested. * %...v: the name of the server (i.e. which virtual host?) * + * Additional SSL directives: + * + * %...{cipher}c: cipher used (SSL_get_cipher) + * %...{clientcert}c: client certificate information + * %...{errcode}c: X509 verify error code + * %...{errstr}c: X509 verify error string + * * The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can * indicate conditions for inclusion of the item (which will cause it * to be replaced with '-' if the condition is not met). Note that @@ -339,6 +346,33 @@ ap_snprintf(pidnum, sizeof(pidnum), "%ld", (long)getpid()); return pstrdup(r->pool, pidnum); } + +#ifdef APACHE_SSL +char *log_ssl_info(request_rec *r, char *a) +{ + if (strcmp(a, "cipher") == 0) + return SSL_get_cipher(r->connection->client->ssl); + + if (strcmp(a, "clientcert") == 0) + return r->connection->client->szClientX509; + + if (strcmp(a, "errcode") == 0) + if (r->connection->client->nVerifyError) { + char str[MAX_STRING_LEN]; + ap_snprintf(str, sizeof(str), "%d", r->connection->client->nVerifyError); + return pstrdup(r->pool,str); + } + else return NULL; + + if (strcmp(a, "errstr") == 0) + if (r->connection->client->nVerifyError) + return X509_cert_verify_error_string(r->connection->client->nVerifyError); + else return NULL; + + return NULL; +} +#endif + /***************************************************************** * * Parsing the log format string @@ -366,6 +400,9 @@ { 'v', log_virtual_host, 0 }, { 'p', log_server_port, 0 }, { 'P', log_child_pid, 0 }, +#ifdef APACHE_SSL + { 'c', log_ssl_info, 0 }, +#endif { '\0' } }; diff -urP apache_1.2b8/src/mod_rewrite.c apache_1.2b8+ssl/src/mod_rewrite.c --- apache_1.2b8/src/mod_rewrite.c Sat Mar 29 02:55:57 1997 +++ apache_1.2b8+ssl/src/mod_rewrite.c Wed Apr 9 11:02:03 1997 @@ -877,12 +877,7 @@ /* add the canonical URI of this URL */ thisserver = r->server->server_hostname; -#ifdef APACHE_SSL - if (((!r->connection->client->ssl) && (r->server->port == 80)) || - ((r->connection->client->ssl) && (r->server->port == 443))) -#else - if (r->server->port == 80) -#endif + if (is_default_port(r->server->port, r)) thisport = ""; else { ap_snprintf(buf, sizeof(buf), ":%d", r->server->port); @@ -891,11 +886,7 @@ thisurl = table_get(r->subprocess_env, ENVVAR_SCRIPT_URL); /* set the variable */ -#ifdef APACHE_SSL - var = pstrcat(r->pool, http_method(r), "://", thisserver, thisport, thisurl, NULL); -#else - var = pstrcat(r->pool, "http://", thisserver, thisport, thisurl, NULL); -#endif + var = pstrcat(r->pool, http_method_str(r), thisserver, thisport, thisurl, NULL); table_set(r->subprocess_env, ENVVAR_SCRIPT_URI, pstrdup(r->pool, var)); @@ -1617,27 +1608,15 @@ && !(strlen(r->filename) > 6 && strncmp(r->filename, "ftp://", 6) == 0) ) { -#ifdef APACHE_SSL - if ((!r->connection->client->ssl && r->server->port == 80) || - ( r->connection->client->ssl && r->server->port == 443) ) -#else - if (r->server->port == 80) -#endif + if (is_default_port(r->server->port, r)) port[0] = '\0'; else ap_snprintf(port, sizeof(port), ":%d", r->server->port); if (r->filename[0] == '/') -#ifdef APACHE_SSL - ap_snprintf(newuri, sizeof(newuri), "%s://%s%s%s", http_method(r), r->server->server_hostname, port, r->filename); -#else - ap_snprintf(newuri, sizeof(newuri), "http://%s%s%s", r->server->server_hostname, port, r->filename); -#endif - else -#ifdef APACHE_SSL - ap_snprintf(newuri, sizeof(newuri), "%s://%s%s/%s", http_method(r), r->server->server_hostname, port, r->filename); -#else - ap_snprintf(newuri, sizeof(newuri), "http://%s%s/%s", r->server->server_hostname, port, r->filename); -#endif + ap_snprintf(newuri, sizeof(newuri), "%s%s%s%s", http_method_str(r), r->server->server_hostname, port, r->filename); + else + ap_snprintf(newuri, sizeof(newuri), "%s%s%s/%s", http_method_str(r), r->server->server_hostname, port, r->filename); + if (perdir == NULL) rewritelog(r, 2, "prepare forced redirect %s -> %s", r->filename, newuri); else @@ -1815,24 +1794,13 @@ char buf[MAX_STRING_LEN]; char *olduri; -#ifdef APACHE_SSL - if ( (!r->connection->client->ssl && - strncmp(r->filename, "http://", 7) == 0) - || (r->connection->client->ssl && - strncmp(r->filename, "https://", 8) == 0)) { -#else - if (strncmp(r->filename, "http://", 7) == 0) { -#endif + if (strncmp(r->filename, http_method_str(r), http_method)len(r)) == 0) { /* there was really a rewrite to a remote path */ olduri = pstrdup(r->pool, r->filename); /* save for logging */ /* cut the hostname and port out of the URI */ -#ifdef APACHE_SSL - strncpy(buf, r->filename+strlen(http_method(r))+3, sizeof(buf)-1); -#else - strncpy(buf, r->filename+7, sizeof(buf)-1); -#endif + strncpy(buf, r->filename+http_method_len(r), sizeof(buf)-1); EOS_PARANOIA(buf); hostp = buf; for (cp = hostp; *cp != '\0' && *cp != '/' && *cp != ':'; cp++) @@ -1860,7 +1828,7 @@ EOS_PARANOIA(host); *cp = '/'; /* set port */ - port = 80; + port = default_port(r); /* set remaining url */ url = cp; } @@ -1869,7 +1837,7 @@ strncpy(host, hostp, sizeof(host)-1); EOS_PARANOIA(host); /* set port */ - port = 80; + port = default_port(r); /* set remaining url */ url = "/"; } diff -urP apache_1.2b8/src/mod_rewrite.c.rej apache_1.2b8+ssl/src/mod_rewrite.c.rej --- apache_1.2b8/src/mod_rewrite.c.rej Thu Jan 1 01:00:00 1970 +++ apache_1.2b8+ssl/src/mod_rewrite.c.rej Wed Apr 9 10:52:32 1997 @@ -0,0 +1,182 @@ +*************** +*** 935,958 **** + rewritelog(r, 1, "go-ahead with proxy request %s [OK]", r->filename); + return OK; + } +- #ifdef APACHE_SSL +- else if ( (!r->connection->client->ssl && +- strlen(r->filename) > 7 && +- strncmp(r->filename, "http://", 7) == 0) +- || (r->connection->client->ssl && +- strlen(r->filename) > 8 && +- strncmp(r->filename, "https://", 8) == 0) ) { +- #else +- else if (strlen(r->filename) > 7 && +- strncmp(r->filename, "http://", 7) == 0) { +- #endif + /* it was finally rewritten to a remote path */ + +- #ifdef APACHE_SSL +- for (cp = r->filename+strlen(http_method(r))+3; *cp != '/' && *cp != '\0'; cp++) +- #else +- for (cp = r->filename+7; *cp != '/' && *cp != '\0'; cp++) +- #endif + ; + if (*cp != '\0') { + rewritelog(r, 1, "escaping %s for redirect", r->filename); +--- 926,936 ---- + rewritelog(r, 1, "go-ahead with proxy request %s [OK]", r->filename); + return OK; + } ++ else if (strlen(r->filename) > http_method_len(r) && ++ strncmp(r->filename, http_method_str(r)) == 0) { + /* it was finally rewritten to a remote path */ + ++ for (cp = r->filename+http_method_len(r); *cp != '/' && *cp != '\0'; cp++) + ; + if (*cp != '\0') { + rewritelog(r, 1, "escaping %s for redirect", r->filename); +*************** +*** 1160,1187 **** + rewritelog(r, 1, "[per-dir %s] go-ahead with proxy request %s [OK]", dconf->directory, r->filename); + return OK; + } +- #ifdef APACHE_SSL +- else if ( (!r->connection->client->ssl && +- strlen(r->filename) > 7 && +- strncmp(r->filename, "http://", 7) == 0) +- || (r->connection->client->ssl && +- strlen(r->filename) > 8 && +- strncmp(r->filename, "https://", 8) == 0) ) { +- #else +- else if (strlen(r->filename) > 7 && +- strncmp(r->filename, "http://", 7) == 0) { +- #endif + /* it was finally rewritten to a remote path */ + + /* because we are in a per-dir context + first try to replace the directory with its base-URL + if there is a base-URL available */ + if (dconf->baseurl != NULL) { +- #ifdef APACHE_SSL +- if ((cp = strchr(r->filename+strlen(http_method(r))+3, '/')) != NULL) { +- #else +- if ((cp = strchr(r->filename+7, '/')) != NULL) { +- #endif + rewritelog(r, 2, "[per-dir %s] trying to replace prefix %s with %s", dconf->directory, dconf->directory, dconf->baseurl); + cp2 = subst_prefix_path(r, cp, dconf->directory, dconf->baseurl); + if (strcmp(cp2, cp) != 0) { +--- 1138,1152 ---- + rewritelog(r, 1, "[per-dir %s] go-ahead with proxy request %s [OK]", dconf->directory, r->filename); + return OK; + } ++ else if (strlen(r->filename) > http_method_len(r) && ++ strncmp(r->filename, http_method_str(r)) == 0) { + /* it was finally rewritten to a remote path */ + + /* because we are in a per-dir context + first try to replace the directory with its base-URL + if there is a base-URL available */ + if (dconf->baseurl != NULL) { ++ if ((cp = strchr(r->filename+http_method_len(r), '/')) != NULL) { + rewritelog(r, 2, "[per-dir %s] trying to replace prefix %s with %s", dconf->directory, dconf->directory, dconf->baseurl); + cp2 = subst_prefix_path(r, cp, dconf->directory, dconf->baseurl); + if (strcmp(cp2, cp) != 0) { +*************** +*** 1192,1202 **** + } + + /* now prepare the redirect... */ +- #ifdef APACHE_SSL +- for (cp = r->filename+strlen(http_method(r))+3; *cp != '/' && *cp != '\0'; cp++) +- #else +- for (cp = r->filename+7; *cp != '/' && *cp != '\0'; cp++) +- #endif + ; + if (*cp != '\0') { + rewritelog(r, 1, "[per-dir %s] escaping %s for redirect", dconf->directory, r->filename); +--- 1157,1163 ---- + } + + /* now prepare the redirect... */ ++ for (cp = r->filename+http_method_len(r); *cp != '/' && *cp != '\0'; cp++) + ; + if (*cp != '\0') { + rewritelog(r, 1, "[per-dir %s] escaping %s for redirect", dconf->directory, r->filename); +*************** +*** 1523,1536 **** + } + + /* if this is a implicit redirect in a per-dir rule */ +- #ifdef APACHE_SSL +- if (perdir != NULL && ( (!r->connection->client->ssl && +- strncmp(output, "http://", 7) == 0) +- || (r->connection->client->ssl && +- strncmp(output, "https://", 8) == 0) )) { +- #else +- if (perdir != NULL && strncmp(output, "http://", 7) == 0) { +- #endif + if (p->flags & RULEFLAG_NOTMATCH) { + strncpy(newuri, output, sizeof(newuri)-1); + EOS_PARANOIA(newuri); +--- 1484,1490 ---- + } + + /* if this is a implicit redirect in a per-dir rule */ ++ if (perdir != NULL && strncmp(output, http_method_str(r), http_method_len(r)) == 0) { + if (p->flags & RULEFLAG_NOTMATCH) { + strncpy(newuri, output, sizeof(newuri)-1); + EOS_PARANOIA(newuri); +*************** +*** 1609,1643 **** + /* if we are forced to do a explicit redirect by [R] flag + finally prefix the new URI with http:// explicitly */ + if (flags & RULEFLAG_FORCEREDIRECT) { +- #ifdef APACHE_SSL +- if ( (!r->connection->client->ssl && +- strncmp(r->filename, "http://", 7) != 0) || +- (r->connection->client->ssl && +- strncmp(r->filename, "https://", 8) != 0)) { +- #else +- if (strncmp(r->filename, "http://", 7) != 0) { +- #endif +- #ifdef APACHE_SSL +- if ((!r->connection->client->ssl && r->server->port == 80) || +- ( r->connection->client->ssl && r->server->port == 443) ) +- #else +- if (r->server->port == 80) +- #endif + port[0] = '\0'; + else + ap_snprintf(port, sizeof(port), ":%d", r->server->port); + if (r->filename[0] == '/') +- #ifdef APACHE_SSL +- ap_snprintf(newuri, sizeof(newuri), "%s://%s%s%s", http_method(r), r->server->server_hostname, port, r->filename); +- #else +- ap_snprintf(newuri, sizeof(newuri), "http://%s%s%s", r->server->server_hostname, port, r->filename); +- #endif + else +- #ifdef APACHE_SSL +- ap_snprintf(newuri, sizeof(newuri), "%s://%s%s/%s", http_method(r), r->server->server_hostname, port, r->filename); +- #else +- ap_snprintf(newuri, sizeof(newuri), "http://%s%s/%s", r->server->server_hostname, port, r->filename); +- #endif + if (perdir == NULL) + rewritelog(r, 2, "prepare forced redirect %s -> %s", r->filename, newuri); + else +--- 1563,1577 ---- + /* if we are forced to do a explicit redirect by [R] flag + finally prefix the new URI with http:// explicitly */ + if (flags & RULEFLAG_FORCEREDIRECT) { ++ if (strncmp(r->filename, http_method_str(r), http_method_len(r)) != 0) { ++ if (is_default_port(r->server->port, r)) + port[0] = '\0'; + else + ap_snprintf(port, sizeof(port), ":%d", r->server->port); + if (r->filename[0] == '/') ++ ap_snprintf(newuri, sizeof(newuri), "%s%s%s%s", http_method_str(r), r->server->server_hostname, port, r->filename); + else ++ ap_snprintf(newuri, sizeof(newuri), "%s%s%s/%s", http_method_str(r), r->server->server_hostname, port, r->filename); + if (perdir == NULL) + rewritelog(r, 2, "prepare forced redirect %s -> %s", r->filename, newuri); + else diff -urP apache_1.2b8/src/mod_ssl.c apache_1.2b8+ssl/src/mod_ssl.c --- apache_1.2b8/src/mod_ssl.c Thu Jan 1 01:00:00 1970 +++ apache_1.2b8+ssl/src/mod_ssl.c Wed Apr 9 10:52:32 1997 @@ -0,0 +1,698 @@ +/* ==================================================================== + * Copyright (c) 1995,6 Ben Laurie. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by Ben Laurie + * for use in the Apache-SSL HTTP server project." + * + * 4. The name "Apache-SSL Server" must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 5. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Ben Laurie + * for use in the Apache-SSL HTTP server project." + * + * THIS SOFTWARE IS PROVIDED BY BEN LAURIE ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BEN LAURIE OR + * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This software consists of patches to the Apache HTTP server interfacing it + * to SSLeay. + * For more information on Apache-SSL, contact Ben Laurie . + * + * For more information on Apache see http://www.apache.org. + * + * For more information on SSLeay see http://www.psy.uq.oz.au/~ftp/Crypto/. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" + +#if SSLEAY_VERSION_NUMBER < 0x600 +#define ERR_print_errors_fp ERR_print_errors +#endif + +typedef enum { + VERIFY_NONE = 0, + VERIFY_OPTIONAL = 1, + VERIFY_REQUIRE = 2, + VERIFY_OPTIONAL_NO_CA = 3, +} VerifyType; + +typedef struct { + int bDisabled; + + char *szCertificateFile; + char *szKeyFile; + char *szCACertificatePath; + char *szCACertificateFile; + char *szLogFile; + char *szReqCiphers; + FILE *fileLogFile; + int nVerifyDepth; + VerifyType nVerifyClient; + + X509 *px509Certificate; + RSA *prsaKey; + + SSL_CTX *pSSLCtx; + + int bFakeBasicAuth; +} SSLConfigRec; + +typedef struct { + /* 1) If cipher is banned, refuse */ + /* 2) If RequiredCiphers is NULL, accept */ + /* 3) If the cipher isn't required, refuse */ + + table *tbRequiredCiphers; + table *tbBannedCiphers; +} SSLDirConfigRec; + +extern module ssl_module; + +static conn_rec *SSLVerifyConn; + +static +int SSLCheckCipher(request_rec *r) +{ + char *cipher; + SSLDirConfigRec *rec = (SSLDirConfigRec *)get_module_config(r->per_dir_config, &ssl_module); + SSLConfigRec *pConfig = (SSLConfigRec *)get_module_config(r->server->module_config, &ssl_module); + + /* Check to see if SSL is on */ + if (pConfig->bDisabled) + return DECLINED; + + cipher = SSL_get_cipher(r->connection->client->ssl); + + if (table_get(rec->tbBannedCiphers, cipher)) { + char *buf; + + buf = pstrcat(r->pool, "Cipher ", cipher, " is forbidden", NULL); + log_reason(buf, r->filename, r); + return FORBIDDEN; + } + if (table_get(rec->tbRequiredCiphers, cipher)) + return OK; + + if (rec->tbRequiredCiphers->nelts == 0) + return OK; + else { + char *buf; + + buf = pstrcat(r->pool, "Cipher ", cipher, " is not on the permitted list", + NULL); + log_reason(buf, r->filename, r); + return FORBIDDEN; + } +} + +int SSLFixups(request_rec *r) +{ + table *e = r->subprocess_env; + int keysize = 0; + int secretkeysize = 0; + char buf[MAX_STRING_LEN]; + char *cipher; + + SSLConfigRec *pConfig = (SSLConfigRec *)get_module_config(r->server->module_config, &ssl_module); + + /* Check to see if SSL is on */ + if (pConfig->bDisabled) + return DECLINED; + + cipher = SSL_get_cipher(r->connection->client->ssl); + table_set(e, "HTTPS", "on"); + table_set(e, "HTTPS_CIPHER", cipher); + + if (!strcmp(cipher, SSL_TXT_NULL_WITH_MD5)) + keysize = secretkeysize = 0; + else if (!strcmp(cipher, SSL_TXT_RC4_128_WITH_MD5)) + keysize = secretkeysize = 128; + else if (!strcmp(cipher, SSL_TXT_RC4_128_EXPORT40_WITH_MD5)) { + keysize = 128; + secretkeysize = 40; + } + else if (!strcmp(cipher, SSL_TXT_RC2_128_CBC_WITH_MD5)) + keysize = secretkeysize = 128; + else if (!strcmp(cipher, SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5)) { + keysize = 128; + secretkeysize = 40; + } + else if (!strcmp(cipher, SSL_TXT_IDEA_128_CBC_WITH_MD5)) + keysize = secretkeysize = 128; + else if (!strcmp(cipher, SSL_TXT_DES_64_CBC_WITH_MD5)) + keysize = secretkeysize = 64; + else if (!strcmp(cipher, SSL_TXT_DES_64_CBC_WITH_SHA)) + keysize = secretkeysize = 64; + else if (!strcmp(cipher, SSL_TXT_DES_192_EDE3_CBC_WITH_MD5)) + keysize = secretkeysize = 192; + else if (!strcmp(cipher, SSL_TXT_DES_192_EDE3_CBC_WITH_SHA)) + keysize = secretkeysize = 192; + else if (!strcmp(cipher, SSL2_TXT_DES_64_CFB64_WITH_MD5_1)) + keysize = secretkeysize = 64; + else if (!strcmp(cipher, SSL2_TXT_NULL)) + keysize = secretkeysize = 0; + + ap_snprintf(buf, sizeof(buf), "%d", keysize); + table_set(e, "HTTPS_KEYSIZE", buf); + + ap_snprintf(buf, sizeof(buf), "%d", secretkeysize); + table_set(e, "HTTPS_SECRETKEYSIZE", buf); + + if (r->connection->client->szClientX509) + table_set(e, "SSL_CLIENT_DN", r->connection->client->szClientX509); + + return OK; +} + +static +void SSLLogError(server_rec *s) +{ + unsigned long l; + char buf[MAX_STRING_LEN]; + + /* Print out error messages */ + while ((l = ERR_get_error())) { + ERR_error_string(l, buf); + log_error(buf, s); + } +} + +static +void *CreateSSLServerConfig(pool *p, server_rec *s) +{ + SSLConfigRec *rec = pcalloc(p, sizeof(SSLConfigRec)); + + rec->bDisabled = 0; + rec->szCertificateFile = NULL; + rec->szKeyFile = NULL; + rec->szLogFile = NULL; + rec->nVerifyDepth = 0; + rec->nVerifyClient = VERIFY_NONE; + rec->px509Certificate = NULL; + rec->prsaKey = NULL; + rec->bFakeBasicAuth = 0; + + return rec; +} + +static +void *CreateSSLDirConfig(pool *p, char *dummy) +{ + SSLDirConfigRec *rec = pcalloc(p, sizeof(SSLDirConfigRec)); + + rec->tbRequiredCiphers = make_table(p, 4); + rec->tbBannedCiphers = make_table(p, 4); + + return rec; +} + +static +void *MergeSSLDirConfig(pool *p, void *basev, void *addv) +{ + SSLDirConfigRec *base = (SSLDirConfigRec *)basev; + SSLDirConfigRec *add = (SSLDirConfigRec *)addv; + SSLDirConfigRec *new = (SSLDirConfigRec *)palloc(p, sizeof(SSLDirConfigRec)); + + new->tbRequiredCiphers = overlay_tables(p, add->tbRequiredCiphers, + base->tbRequiredCiphers); + new->tbBannedCiphers = overlay_tables(p, add->tbBannedCiphers, + base->tbBannedCiphers); + return new; +} + +static +void InitSSLServer(server_rec *s, pool *p) +{ + FILE *fp; + char szPath[MAX_STRING_LEN]; + + /* Init SSL */ + SSL_load_error_strings(); + ERR_load_crypto_strings(); + SSL_debug("/tmp/ssldebug"); + + /* Iterate over each (virtual) server */ + for (; s; s = s->next) { + SSLConfigRec *pConfig = get_module_config(s->module_config, &ssl_module); + + if (pConfig->bDisabled) { + if (!s->port) + s->port = HTTP_PORT; + fprintf(stderr, "SSL disabled for server %s:%d\n", + s->server_hostname, s->port); + continue; + } + + if (!s->port) + s->port = HTTPS_PORT; + + if (!pConfig->szCertificateFile) { + fprintf(stderr, "No SSL Certificate set for server %s:%d\n", + s->server_hostname, s->port); + exit(1); + } + if (!pConfig->szLogFile) { + fprintf(stderr, "Required SSLLogFile missing\n"); + exit(1); + } + if (pConfig->nVerifyClient < 0 || pConfig->nVerifyClient > VERIFY_OPTIONAL_NO_CA) { + fprintf(stderr, "Bad value for SSLVerifyClient (%d)\n", pConfig->nVerifyClient); + exit(1); + } + + pConfig->fileLogFile = fopen(pConfig->szLogFile, "a"); + setbuf(pConfig->fileLogFile, NULL); + if (!pConfig->fileLogFile) { + perror(pConfig->szLogFile); + exit(1); + } + + if (pConfig->px509Certificate) { + fprintf(stderr, "Attempt to reinitialise SSL for server %s, ignored\n", + s->server_hostname); + continue; + } + + fprintf(stderr, "Reading certificate and key for server %s:%d\n", + s->server_hostname, s->port); + + pConfig->pSSLCtx = SSL_CTX_new(); + + if (pConfig->szReqCiphers != NULL) { + if (!SSL_CTX_set_cipher_list(pConfig->pSSLCtx, pConfig->szReqCiphers)) { + fprintf(stderr, "unable to set ciphers\n"); + ERR_print_errors_fp(stderr); + SSLLogError(s); + } + } + + if (!SSL_load_verify_locations(pConfig->pSSLCtx, + pConfig->szCACertificateFile, + pConfig->szCACertificatePath) + || !SSL_set_default_verify_paths(pConfig->pSSLCtx)) { + fprintf(stderr, "error seting default verify locations\n"); + ERR_print_errors_fp(stderr); + exit(1); + } + + fp = fopen(pConfig->szCertificateFile, "r"); + if (!fp) { + sprintf(szPath, "%s/%s", X509_get_default_cert_dir(), + pConfig->szCertificateFile); + fp = fopen(szPath, "r"); + if (!fp) { + fprintf(stderr, "Can't open certificate file %s, nor %s\n", + pConfig->szCertificateFile, szPath); + exit(1); + } + } + else + strcpy(szPath, pConfig->szCertificateFile); /* in case it also contains the key */ + + pConfig->px509Certificate = X509_new(); + if (!PEM_read_X509(fp, &pConfig->px509Certificate, NULL)) { + fprintf(stderr, "Error reading server certificate file %s: ", szPath); + ERR_print_errors_fp(stderr); + exit(1); + } + fclose(fp); + + if (pConfig->szKeyFile) + if (pConfig->szKeyFile[0] == '/') + strcpy(szPath, pConfig->szKeyFile); + else + sprintf(szPath, "%s/private/%s", X509_get_default_cert_area(), + pConfig->szKeyFile); + + /* Otherwise the path already contains the name of the certificate file */ + fp = fopen(szPath, "r"); + if (!fp) { + fprintf(stderr, "Can't open key file %s\n", szPath); + perror(szPath); + exit(1); + } + + pConfig->prsaKey = RSA_new(); + if (!PEM_read_RSAPrivateKey(fp, &pConfig->prsaKey, NULL)) { + fprintf(stderr, "Error reading private key file %s: ", szPath); + ERR_print_errors_fp(stderr); + exit(1); + } + fclose(fp); + } +} + +static +const char *set_server_string_slot(cmd_parms * cmd, char *struct_ptr, char *arg) +{ + /* This one should be pretty generic... */ + char *pConfig = get_module_config(cmd->server->module_config, &ssl_module); + + int offset = (int)cmd->info; + *(char **)(pConfig + offset) = arg; + return NULL; +} + +static +const char *set_server_int_slot(cmd_parms * cmd, char *struct_ptr, char *arg) +{ + /* This one should be pretty generic... */ + char *pConfig = get_module_config(cmd->server->module_config, &ssl_module); + + int offset = (int)cmd->info; + *(int *)(pConfig + offset) = atoi(arg); + return NULL; +} + +static +const char *SSLRequireCipher(cmd_parms * cmd, SSLDirConfigRec *rec, char *cipher) +{ + table_set(rec->tbRequiredCiphers, cipher, "Required"); + return NULL; +} + +static +const char *SSLBanCipher(cmd_parms * cmd, SSLDirConfigRec *rec, char *cipher) +{ + table_set(rec->tbBannedCiphers, cipher, "Banned"); + return NULL; +} + +command_rec ssl_cmds[] = +{ + {"SSLDisable", set_server_int_slot, + (void *)XtOffsetOf(SSLConfigRec, bDisabled), RSRC_CONF, NO_ARGS, + "Enable SSL"}, + {"SSLCertificateFile", set_server_string_slot, + (void *)XtOffsetOf(SSLConfigRec, szCertificateFile), RSRC_CONF, TAKE1, + "PEM certificate file"}, + {"SSLCertificateKeyFile", set_server_string_slot, + (void *)XtOffsetOf(SSLConfigRec, szKeyFile), RSRC_CONF, TAKE1, + "Certificate private key file (assumed to be SSLCertificateFile if absent)"}, + {"SSLCACertificatePath", set_server_string_slot, + (void *)XtOffsetOf(SSLConfigRec, szCACertificatePath), RSRC_CONF, TAKE1, + "CA Certificate path (taken from SSL_CERT_DIR if absent)"}, + {"SSLCACertificateFile", set_server_string_slot, + (void *)XtOffsetOf(SSLConfigRec, szCACertificateFile), RSRC_CONF, TAKE1, + "CA Certificate file (taken from SSL_CERT_FILE if absent)"}, + {"SSLVerifyDepth", set_server_int_slot, + (void *)XtOffsetOf(SSLConfigRec, nVerifyDepth), RSRC_CONF, TAKE1, + "Verify depth (default 0)"}, + {"SSLVerifyClient", set_server_int_slot, + (void *)XtOffsetOf(SSLConfigRec, nVerifyClient), RSRC_CONF, TAKE1, + "Verify client (0=no,1=optional,2=required"}, + {"SSLFakeBasicAuth", set_server_int_slot, + (void *)XtOffsetOf(SSLConfigRec, bFakeBasicAuth), RSRC_CONF, NO_ARGS, + "Translate client X509 into a user name"}, + {"SSLLogFile", set_server_string_slot, + (void *)XtOffsetOf(SSLConfigRec, szLogFile), RSRC_CONF, TAKE1, + "Place to dump all SSL messages that have no better home"}, + {"SSLRequiredCiphers", set_server_string_slot, + (void *)XtOffsetOf(SSLConfigRec, szReqCiphers), RSRC_CONF, TAKE1, + "Colon-delimited list of required ciphers"}, + /* Per Directory */ + {"SSLRequireCipher", SSLRequireCipher, NULL, OR_FILEINFO, ITERATE, + "add a cipher to the per directory list of required ciphers"}, + {"SSLBanCipher", SSLBanCipher, NULL, OR_FILEINFO, ITERATE, + "add a cipher to the per directory list of banned ciphers"}, + {NULL}, +}; + +static +const char six2pr[64 + 1] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +void uuencode(char *szTo, const char *szFrom) +{ + const unsigned char *s; + + for (s = (const unsigned char *)szFrom; *s; s += 3) { + *szTo++ = six2pr[s[0] >> 2]; + *szTo++ = six2pr[(s[0] << 4 | s[1] >> 4) & 0x3f]; + if (!s[0]) + break; + *szTo++ = six2pr[(s[1] << 2 | s[2] >> 6) & 0x3f]; + if (!s[1]) + break; + *szTo++ = six2pr[s[2] & 0x3f]; + if (!s[2]) + break; + } + *szTo++ = '\0'; +} + +/* + Fake a Basic authentication from the X509 client certificate. + + This must be run fairly early on to prevent a real authentication from + occuring, in particular it must be run before anything else that authenticates + a user. + + This means that the Module statement for this module should be LAST in the + Configuration file. + */ + +static +int FakeBasicAuth(request_rec *r) +{ + SSLConfigRec *pConfig = get_module_config(r->server->module_config, &ssl_module); + char b1[MAX_STRING_LEN], b2[MAX_STRING_LEN]; + + if (!pConfig->bFakeBasicAuth) + return DECLINED; + if (r->connection->user) + return DECLINED; + if (!r->connection->client->szClientX509) + return DECLINED; + /* + Fake a password - which one would be immaterial, as, it seems, an empty + password in the users file would match ALL incoming passwords, if only we + were using the standard crypt library routine. Unfortunately, SSLeay + "fixes" a "bug" in crypt and thus prevents blank passwords from working. + (IMHO what they really fix is a bug in the users of the code - failing to + program correctly for shadow passwords). + We need, therefore, to provide a password. This password can be matched by + adding the string "xxj31ZMTZzkVA" as the password in the user file. + */ + sprintf(b1, "%s:password", r->connection->client->szClientX509); + uuencode(b2, b1); + sprintf(b1, "Basic %s", b2); + table_set(r->headers_in, "Authorization", b1); + return DECLINED; +} + +int ApacheSSLVerifyCallback(int ok, X509 * xs, X509 * xi, int depth, int error) +{ + char *s; + SSLConfigRec *pConfig = get_module_config(SSLVerifyConn->server->module_config, &ssl_module); + + s = (char *)X509_NAME_oneline(X509_get_subject_name(xs)); + if (s == NULL) { + ERR_print_errors_fp(pConfig->fileLogFile); + return 0; + } + if (depth == 0) + SSLVerifyConn->client->szClientX509 = pstrdup(SSLVerifyConn->pool, s); + + fprintf(pConfig->fileLogFile, "depth=%d %s\n", depth, s); + free(s); + if (error == VERIFY_ERR_UNABLE_TO_GET_ISSUER) { + if (pConfig->nVerifyClient == VERIFY_OPTIONAL_NO_CA) { + fprintf(pConfig->fileLogFile, "no issuer, returning OK\n"); + return 1; + } + s = (char *)X509_NAME_oneline(X509_get_issuer_name(xs)); + if (s == NULL) { + fprintf(pConfig->fileLogFile, "verify error\n"); + ERR_print_errors_fp(pConfig->fileLogFile); + SSLLogError(SSLVerifyConn->server); + return 0; + } + fprintf(pConfig->fileLogFile, "issuer= %s\n", s); + free(s); + } + if (!ok) { + fprintf(pConfig->fileLogFile, "verify error:num=%d:%s\n", error, + X509_cert_verify_error_string(error)); + SSLLogError(SSLVerifyConn->server); + SSLVerifyConn->client->szClientX509 = NULL; + } + if (depth >= pConfig->nVerifyDepth) { + fprintf(pConfig->fileLogFile, "Verify depth exceeded\n"); + log_error("Verify depth exceeded", SSLVerifyConn->server); + ok = 0; + } + fprintf(pConfig->fileLogFile, "verify return:%d\n", ok); + return (ok); +} + +static +int ApacheSSLSetCertStuff(conn_rec * conn) +{ + SSLConfigRec *pConfig = get_module_config(conn->server->module_config, + &ssl_module); + SSL *con = conn->client->ssl; + char *cert_file = pConfig->szCertificateFile; + +/* PEM_set_getkey_callback(ApacheSSLKeyCallback); */ + if (cert_file != NULL) { + if (SSL_use_certificate(con, pConfig->px509Certificate) <= 0) { + fprintf(pConfig->fileLogFile, "unable to set certificate\n"); + ERR_print_errors_fp(pConfig->fileLogFile); + SSLLogError(conn->server); + return 0; + } + if (SSL_use_RSAPrivateKey(con, pConfig->prsaKey) <= 0) { + fprintf(pConfig->fileLogFile, "unable to set private key\n"); + ERR_print_errors_fp(pConfig->fileLogFile); + SSLLogError(conn->server); + return 0; + } + } + return 1; +} + +void ApacheSSLSetupVerify(conn_rec * conn) +{ + SSLConfigRec *pConfig = get_module_config(conn->server->module_config, &ssl_module); + int nVerify = 0; + + conn->client->szClientX509 = NULL; + + SSLVerifyConn = conn; + + switch (pConfig->nVerifyClient) { + case VERIFY_REQUIRE: + nVerify |= SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + break; + + case VERIFY_OPTIONAL: + case VERIFY_OPTIONAL_NO_CA: + nVerify |= SSL_VERIFY_PEER; + break; + case VERIFY_NONE: + break; + } + + conn->client->nVerifyError = VERIFY_OK; + +/* Why call this twice?? Ben */ + SSL_set_verify(conn->client->ssl, nVerify, ApacheSSLVerifyCallback); + if (!ApacheSSLSetCertStuff(conn)) { + fprintf(pConfig->fileLogFile, "ApacheSSLSetCertStuff failed\n"); + log_error("ApacheSSLSetCertStuff failed", conn->server); + exit(1); + } + SSL_set_verify(conn->client->ssl, nVerify, ApacheSSLVerifyCallback); +} + +int ApacheSSLSetupConnection(conn_rec * conn) +{ + server_rec *srvr = conn->server; + BUFF *fb = conn->client; + SSLConfigRec *pConfig = get_module_config(srvr->module_config, + &ssl_module); + + if (pConfig->bDisabled) { + fb->ssl = NULL; + return 1; + } + + SSLVerifyConn = conn; + fb->ssl = SSL_new(pConfig->pSSLCtx); + SSL_set_fd(fb->ssl, fb->fd); + + ApacheSSLSetupVerify(conn); + + while (!SSL_is_init_finished(fb->ssl)) { + int ret = SSL_accept(fb->ssl); + if (ret <= 0) { + log_error("SSL_Accept failed", srvr); + SSLLogError(srvr); + fb->flags |= B_EOF | B_EOUT; + return 0; + } + + if (conn->client->nVerifyError != VERIFY_OK) { + log_error("Verification failed", conn->server); + SSLLogError(srvr); + fb->flags |= B_EOF | B_EOUT; + return 0; + } + + if (pConfig->nVerifyClient == VERIFY_REQUIRE && !conn->client->szClientX509) { + log_error("No client certificate", conn->server); + SSLLogError(conn->server); + return 0; + } + fprintf(pConfig->fileLogFile, "CIPHER is %s\n", SSL_get_cipher(conn->client->ssl)); + fflush(pConfig->fileLogFile); + } + + /* This should be safe.... so I'll use it */ + SSL_set_read_ahead(fb->ssl, 1); + + SSLVerifyConn = NULL; + + return 1; +} + +module ssl_module = +{ + STANDARD_MODULE_STUFF, + InitSSLServer, /* initializer */ + CreateSSLDirConfig, /* dir config creater */ + MergeSSLDirConfig, /* dir merger --- default is to override */ + CreateSSLServerConfig, /* server config */ + NULL, /* merge server config */ + ssl_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + FakeBasicAuth, /* check_user_id */ + NULL, /* check auth */ + SSLCheckCipher, /* check access */ + NULL, /* type_checker */ + SSLFixups, /* fixups */ + NULL, /* logger */ +}; diff -urP apache_1.2b8/src/util.c apache_1.2b8+ssl/src/util.c --- apache_1.2b8/src/util.c Sun Mar 23 00:51:04 1997 +++ apache_1.2b8+ssl/src/util.c Wed Apr 9 10:52:32 1997 @@ -782,21 +782,16 @@ else return OK; } -char *construct_server(pool *p, const char *hostname, int port) { +char *construct_url(pool *p, const char *uri, const request_rec *r) { + const server_rec *s = r->server; char portnum[22]; /* Long enough, even if port > 16 bits for some reason */ - - if (port == 80) - return (char *)hostname; - else { - ap_snprintf (portnum, sizeof(portnum), "%d", port); - return pstrcat (p, hostname, ":", portnum, NULL); - } -} -char *construct_url(pool *p, const char *uri, const server_rec *s) { - return pstrcat (p, "http://", - construct_server(p, s->server_hostname, s->port), + if (is_default_port(s->port, r)) portnum[0] = '\0'; + else ap_snprintf (portnum, sizeof(portnum), ":%d", s->port); + + return pstrcat (p, http_method_str(r), + s->server_hostname, portnum, uri, NULL); } diff -urP apache_1.2b8/src/util_md5.c apache_1.2b8+ssl/src/util_md5.c --- apache_1.2b8/src/util_md5.c Wed Jan 1 19:10:46 1997 +++ apache_1.2b8+ssl/src/util_md5.c Wed Apr 9 10:52:32 1997 @@ -84,7 +84,7 @@ char *md5 (pool *p, unsigned char *string) { - MD5_CTX my_md5; + APACHE_MD5_CTX my_md5; unsigned char hash[16]; char *r, result[33]; int i; @@ -149,7 +149,7 @@ static char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -char *md5contextTo64(pool *a, MD5_CTX *context) +char *md5contextTo64(pool *a, APACHE_MD5_CTX *context) { unsigned char digest[18]; char *encodedDigest; @@ -176,7 +176,7 @@ char *md5digest(pool *p, FILE *infile) { - MD5_CTX context; + APACHE_MD5_CTX context; unsigned char buf[1000]; long length = 0; int nbytes; diff -urP apache_1.2b8/src/util_md5.h apache_1.2b8+ssl/src/util_md5.h --- apache_1.2b8/src/util_md5.h Wed Jan 1 19:10:46 1997 +++ apache_1.2b8+ssl/src/util_md5.h Wed Apr 9 10:52:32 1997 @@ -53,6 +53,6 @@ #include "md5.h" char *md5(pool *a, unsigned char *string); -char *md5contextTo64(pool *p, MD5_CTX *context); +char *md5contextTo64(pool *p, APACHE_MD5_CTX *context); char *md5digest(pool *p, FILE *infile);