~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to modules/arch/netware/mod_nw_ssl.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
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.
 
15
 */
 
16
 
 
17
/*
 
18
 * mod_tls.c - Apache SSL/TLS module for NetWare by Mike Gardiner.
 
19
 *
 
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.
 
24
 *
 
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.
 
29
 *
 
30
 *  Examples:
 
31
 *
 
32
 *          SecureListen 443 "SSL CertificateIP"
 
33
 *          SecureListen 123.45.67.89:443 mycert
 
34
 */
 
35
 
 
36
#define WS_SSL
 
37
 
 
38
#define  MAX_ADDRESS  512
 
39
#define  MAX_KEY       80
 
40
 
 
41
 
 
42
#include "httpd.h"
 
43
#include "http_config.h"
 
44
#include "http_log.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"
 
51
 
 
52
#include <unilib.h>
 
53
 
 
54
#ifndef SO_TLS_UNCLEAN_SHUTDOWN
 
55
#define SO_TLS_UNCLEAN_SHUTDOWN 0
 
56
#endif
 
57
 
 
58
/* The ssl_var_lookup() optional function retrieves SSL environment
 
59
 * variables. */
 
60
APR_DECLARE_OPTIONAL_FN(char *, ssl_var_lookup,
 
61
                        (apr_pool_t *, server_rec *,
 
62
                         conn_rec *, request_rec *,
 
63
                         char *));
 
64
 
 
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 *));
 
68
 
 
69
/* The ssl_proxy_enable() and ssl_engine_disable() optional functions
 
70
 * are used by mod_proxy to enable use of SSL for outgoing
 
71
 * connections. */
 
72
APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *));
 
73
APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
 
74
 
 
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)
 
79
 
 
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)
 
84
 
 
85
#define strIsEmpty(s)    (s == NULL || s[0] == NUL)
 
86
 
 
87
 
 
88
module AP_MODULE_DECLARE_DATA nwssl_module;
 
89
 
 
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;
 
94
 
 
95
struct seclisten_rec {
 
96
    seclisten_rec *next;
 
97
    struct sockaddr_in local_addr;   /* local IP address and port */
 
98
    int fd;
 
99
    int used;                        /* Only used during restart */
 
100
    char key[MAX_KEY];
 
101
    int mutual;
 
102
    char *addr;
 
103
    apr_port_t port;
 
104
};
 
105
 
 
106
struct seclistenup_rec {
 
107
    seclistenup_rec *next;
 
108
    char key[MAX_KEY];
 
109
    char *addr;
 
110
    apr_port_t port;
 
111
};
 
112
 
 
113
struct NWSSLSrvConfigRec {
 
114
    apr_table_t *sltable;
 
115
    apr_table_t *slutable;
 
116
        apr_pool_t *pPool;
 
117
};
 
118
 
 
119
struct secsocket_data {
 
120
    apr_socket_t* csd;
 
121
    int is_secure;
 
122
};
 
123
 
 
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;
 
129
 
 
130
static ap_listen_rec *nw_old_listeners;
 
131
 
 
132
#define get_nwssl_cfg(srv) (NWSSLSrvConfigRec *) ap_get_module_config(srv->module_config, &nwssl_module)
 
133
 
 
134
 
 
135
static void build_cert_list (apr_pool_t *p)
 
136
{
 
137
    int i;
 
138
    char **rootcerts = (char **)certlist->elts;
 
139
 
 
140
    numcerts = certlist->nelts;
 
141
    certarray = apr_palloc(p, sizeof(unicode_t*)*numcerts);
 
142
 
 
143
    for (i = 0; i < numcerts; ++i) {
 
144
        unicode_t *unistr;
 
145
        unistr = (unicode_t*)apr_palloc(p, strlen(rootcerts[i])*4);
 
146
        loc2uni (UNI_LOCAL_DEFAULT, unistr, rootcerts[i], 0, 2);
 
147
        certarray[i] = unistr;
 
148
    }
 
149
}
 
150
 
 
151
/*
 
152
 * Parses a host of the form <address>[:port]
 
153
 * :port is permitted if 'port' is not NULL
 
154
 */
 
155
static unsigned long parse_addr(const char *w, unsigned short *ports)
 
156
{
 
157
    struct hostent *hep;
 
158
    unsigned long my_addr;
 
159
    char *p;
 
160
 
 
161
    p = strchr(w, ':');
 
162
    if (ports != NULL) {
 
163
        *ports = 0;
 
164
    if (p != NULL && strcmp(p + 1, "*") != 0)
 
165
        *ports = atoi(p + 1);
 
166
    }
 
167
 
 
168
    if (p != NULL)
 
169
        *p = '\0';
 
170
    if (strcmp(w, "*") == 0) {
 
171
        if (p != NULL)
 
172
            *p = ':';
 
173
        return htonl(INADDR_ANY);
 
174
    }
 
175
 
 
176
    my_addr = apr_inet_addr((char *)w);
 
177
    if (my_addr != INADDR_NONE) {
 
178
        if (p != NULL)
 
179
            *p = ':';
 
180
        return my_addr;
 
181
    }
 
182
 
 
183
    hep = gethostbyname(w);
 
184
 
 
185
    if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
 
186
        /* XXX Should be echoing by h_errno the actual failure, no?
 
187
         * ap_log_error would be good here.  Better yet - APRize.
 
188
         */
 
189
        fprintf(stderr, "Cannot resolve host name %s --- exiting!\n", w);
 
190
        exit(1);
 
191
    }
 
192
 
 
193
    if (hep->h_addr_list[1]) {
 
194
        fprintf(stderr, "Host %s has multiple addresses ---\n", w);
 
195
        fprintf(stderr, "you must choose one explicitly for use as\n");
 
196
        fprintf(stderr, "a secure port.  Exiting!!!\n");
 
197
        exit(1);
 
198
    }
 
199
 
 
200
    if (p != NULL)
 
201
        *p = ':';
 
202
 
 
203
    return ((struct in_addr *) (hep->h_addr))->s_addr;
 
204
}
 
205
 
 
206
static int find_secure_listener(seclisten_rec *lr)
 
207
{
 
208
    seclisten_rec *sl;
 
209
 
 
210
    for (sl = ap_seclisteners; sl; sl = sl->next) {
 
211
        if (!memcmp(&sl->local_addr, &lr->local_addr, sizeof(sl->local_addr))) {
 
212
            sl->used = 1;
 
213
            return sl->fd;
 
214
        }
 
215
    }
 
216
    return -1;
 
217
}
 
218
 
 
219
static char *get_port_key(conn_rec *c)
 
220
{
 
221
    seclistenup_rec *sl;
 
222
 
 
223
    for (sl = ap_seclistenersup; sl; sl = sl->next) {
 
224
        if ((sl->port == (c->local_addr)->port) &&
 
225
            ((strcmp(sl->addr, "0.0.0.0") == 0) || (strcmp(sl->addr, c->local_ip) == 0))) {
 
226
            return sl->key;
 
227
        }
 
228
    }
 
229
    return NULL;
 
230
}
 
231
 
 
232
static int make_secure_socket(apr_pool_t *pconf, const struct sockaddr_in *server,
 
233
                              char* key, int mutual, server_rec *sconf)
 
234
{
 
235
    int s;
 
236
    int one = 1;
 
237
    char addr[MAX_ADDRESS];
 
238
    struct sslserveropts opts;
 
239
    unsigned int optParam;
 
240
    WSAPROTOCOL_INFO SecureProtoInfo;
 
241
    int no = 1;
 
242
 
 
243
    if (server->sin_addr.s_addr != htonl(INADDR_ANY))
 
244
        apr_snprintf(addr, sizeof(addr), "address %s port %d",
 
245
            inet_ntoa(server->sin_addr), ntohs(server->sin_port));
 
246
    else
 
247
        apr_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port));
 
248
 
 
249
    /* note that because we're about to slack we don't use psocket */
 
250
    memset(&SecureProtoInfo, 0, sizeof(WSAPROTOCOL_INFO));
 
251
 
 
252
    SecureProtoInfo.iAddressFamily = AF_INET;
 
253
    SecureProtoInfo.iSocketType = SOCK_STREAM;
 
254
    SecureProtoInfo.iProtocol = IPPROTO_TCP;
 
255
    SecureProtoInfo.iSecurityScheme = SECURITY_PROTOCOL_SSL;
 
256
 
 
257
    s = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,
 
258
            (LPWSAPROTOCOL_INFO)&SecureProtoInfo, 0, 0);
 
259
 
 
260
    if (s == INVALID_SOCKET) {
 
261
        ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf,
 
262
                     "make_secure_socket: failed to get a socket for %s",
 
263
                     addr);
 
264
        return -1;
 
265
    }
 
266
 
 
267
    if (!mutual) {
 
268
        optParam = SO_SSL_ENABLE | SO_SSL_SERVER;
 
269
 
 
270
        if (WSAIoctl(s, SO_SSL_SET_FLAGS, (char *)&optParam,
 
271
            sizeof(optParam), NULL, 0, NULL, NULL, NULL)) {
 
272
            ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf,
 
273
                         "make_secure_socket: for %s, WSAIoctl: "
 
274
                         "(SO_SSL_SET_FLAGS)", addr);
 
275
            return -1;
 
276
        }
 
277
    }
 
278
 
 
279
    opts.cert = key;
 
280
    opts.certlen = strlen(key);
 
281
    opts.sidtimeout = 0;
 
282
    opts.sidentries = 0;
 
283
    opts.siddir = NULL;
 
284
 
 
285
    if (WSAIoctl(s, SO_SSL_SET_SERVER, (char *)&opts, sizeof(opts),
 
286
        NULL, 0, NULL, NULL, NULL) != 0) {
 
287
        ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf,
 
288
                     "make_secure_socket: for %s, WSAIoctl: "
 
289
                     "(SO_SSL_SET_SERVER)", addr);
 
290
        return -1;
 
291
    }
 
292
 
 
293
    if (mutual) {
 
294
        optParam = 0x07;  // SO_SSL_AUTH_CLIENT
 
295
 
 
296
        if(WSAIoctl(s, SO_SSL_SET_FLAGS, (char*)&optParam,
 
297
            sizeof(optParam), NULL, 0, NULL, NULL, NULL)) {
 
298
            ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf,
 
299
                         "make_secure_socket: for %s, WSAIoctl: "
 
300
                         "(SO_SSL_SET_FLAGS)", addr);
 
301
            return -1;
 
302
        }
 
303
    }
 
304
 
 
305
    optParam = SO_TLS_UNCLEAN_SHUTDOWN;
 
306
    WSAIoctl(s, SO_SSL_SET_FLAGS, (char *)&optParam, sizeof(optParam),
 
307
             NULL, 0, NULL, NULL, NULL);
 
308
 
 
309
    return s;
 
310
}
 
311
 
 
312
int convert_secure_socket(conn_rec *c, apr_socket_t *csd)
 
313
{
 
314
        int rcode;
 
315
        struct tlsclientopts sWS2Opts;
 
316
        struct nwtlsopts sNWTLSOpts;
 
317
        struct sslserveropts opts;
 
318
    unsigned long ulFlags;
 
319
    SOCKET sock;
 
320
    unicode_t keyFileName[60];
 
321
 
 
322
    apr_os_sock_get(&sock, csd);
 
323
 
 
324
    /* zero out buffers */
 
325
        memset((char *)&sWS2Opts, 0, sizeof(struct tlsclientopts));
 
326
        memset((char *)&sNWTLSOpts, 0, sizeof(struct nwtlsopts));
 
327
 
 
328
    /* turn on ssl for the socket */
 
329
        ulFlags = (numcerts ? SO_TLS_ENABLE : SO_TLS_ENABLE | SO_TLS_BLIND_ACCEPT);
 
330
        rcode = WSAIoctl(sock, SO_TLS_SET_FLAGS, &ulFlags, sizeof(unsigned long),
 
331
                     NULL, 0, NULL, NULL, NULL);
 
332
        if (SOCKET_ERROR == rcode)
 
333
        {
 
334
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
 
335
                     "Error: %d with ioctlsocket(flag SO_TLS_ENABLE)", WSAGetLastError());
 
336
                return rcode;
 
337
        }
 
338
 
 
339
    ulFlags = SO_TLS_UNCLEAN_SHUTDOWN;
 
340
        WSAIoctl(sock, SO_TLS_SET_FLAGS, &ulFlags, sizeof(unsigned long),
 
341
                     NULL, 0, NULL, NULL, NULL);
 
342
 
 
343
    /* setup the socket for SSL */
 
344
    memset (&sWS2Opts, 0, sizeof(sWS2Opts));
 
345
    memset (&sNWTLSOpts, 0, sizeof(sNWTLSOpts));
 
346
    sWS2Opts.options = &sNWTLSOpts;
 
347
 
 
348
    if (numcerts) {
 
349
        sNWTLSOpts.walletProvider = WAL_PROV_DER;   //the wallet provider defined in wdefs.h
 
350
        sNWTLSOpts.TrustedRootList = certarray;     //array of certs in UNICODE format
 
351
        sNWTLSOpts.numElementsInTRList = numcerts;  //number of certs in TRList
 
352
    }
 
353
    else {
 
354
        /* setup the socket for SSL */
 
355
        unicpy(keyFileName, L"SSL CertificateIP");
 
356
        sWS2Opts.wallet = keyFileName;    /* no client certificate */
 
357
        sWS2Opts.walletlen = unilen(keyFileName);
 
358
 
 
359
        sNWTLSOpts.walletProvider = WAL_PROV_KMO;  //the wallet provider defined in wdefs.h
 
360
    }
 
361
 
 
362
    /* make the IOCTL call */
 
363
    rcode = WSAIoctl(sock, SO_TLS_SET_CLIENT, &sWS2Opts,
 
364
                     sizeof(struct tlsclientopts), NULL, 0, NULL,
 
365
                     NULL, NULL);
 
366
 
 
367
    /* make sure that it was successfull */
 
368
        if(SOCKET_ERROR == rcode ){
 
369
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
 
370
                     "Error: %d with ioctl (SO_TLS_SET_CLIENT)", WSAGetLastError());
 
371
        }
 
372
        return rcode;
 
373
}
 
374
 
 
375
int SSLize_Socket(SOCKET socketHnd, char *key, request_rec *r)
 
376
{
 
377
    int rcode;
 
378
    struct tlsserveropts sWS2Opts;
 
379
    struct nwtlsopts    sNWTLSOpts;
 
380
    unicode_t SASKey[512];
 
381
    unsigned long ulFlag;
 
382
 
 
383
    memset((char *)&sWS2Opts, 0, sizeof(struct tlsserveropts));
 
384
    memset((char *)&sNWTLSOpts, 0, sizeof(struct nwtlsopts));
 
385
 
 
386
 
 
387
    ulFlag = SO_TLS_ENABLE;
 
388
    rcode = WSAIoctl(socketHnd, SO_TLS_SET_FLAGS, &ulFlag, sizeof(unsigned long), NULL, 0, NULL, NULL, NULL);
 
389
    if(rcode)
 
390
    {
 
391
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
 
392
                     "Error: %d with WSAIoctl(SO_TLS_SET_FLAGS, SO_TLS_ENABLE)", WSAGetLastError());
 
393
        goto ERR;
 
394
    }
 
395
 
 
396
 
 
397
    ulFlag = SO_TLS_SERVER;
 
398
    rcode = WSAIoctl(socketHnd, SO_TLS_SET_FLAGS, &ulFlag, sizeof(unsigned long),NULL, 0, NULL, NULL, NULL);
 
399
 
 
400
    if(rcode)
 
401
    {
 
402
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
 
403
                     "Error: %d with WSAIoctl(SO_TLS_SET_FLAGS, SO_TLS_SERVER)", WSAGetLastError());
 
404
        goto ERR;
 
405
    }
 
406
 
 
407
    loc2uni(UNI_LOCAL_DEFAULT, SASKey, key, 0, 0);
 
408
 
 
409
    //setup the tlsserveropts struct
 
410
    sWS2Opts.wallet = SASKey;
 
411
    sWS2Opts.walletlen = unilen(SASKey);
 
412
    sWS2Opts.sidtimeout = 0;
 
413
    sWS2Opts.sidentries = 0;
 
414
    sWS2Opts.siddir = NULL;
 
415
    sWS2Opts.options = &sNWTLSOpts;
 
416
 
 
417
    //setup the nwtlsopts structure
 
418
 
 
419
    sNWTLSOpts.walletProvider               = WAL_PROV_KMO;
 
420
    sNWTLSOpts.keysList                     = NULL;
 
421
    sNWTLSOpts.numElementsInKeyList         = 0;
 
422
    sNWTLSOpts.reservedforfutureuse         = NULL;
 
423
    sNWTLSOpts.reservedforfutureCRL         = NULL;
 
424
    sNWTLSOpts.reservedforfutureCRLLen      = 0;
 
425
    sNWTLSOpts.reserved1                    = NULL;
 
426
    sNWTLSOpts.reserved2                    = NULL;
 
427
    sNWTLSOpts.reserved3                    = NULL;
 
428
 
 
429
 
 
430
    rcode = WSAIoctl(socketHnd,
 
431
                     SO_TLS_SET_SERVER,
 
432
                     &sWS2Opts,
 
433
                     sizeof(struct tlsserveropts),
 
434
                     NULL,
 
435
                     0,
 
436
                     NULL,
 
437
                     NULL,
 
438
                     NULL);
 
439
    if(SOCKET_ERROR == rcode) {
 
440
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
 
441
                     "Error: %d with WSAIoctl(SO_TLS_SET_SERVER)", WSAGetLastError());
 
442
        goto ERR;
 
443
    }
 
444
 
 
445
ERR:
 
446
    return rcode;
 
447
}
 
448
 
 
449
static const char *set_secure_listener(cmd_parms *cmd, void *dummy,
 
450
                                       const char *ips, const char* key,
 
451
                                       const char* mutual)
 
452
{
 
453
    NWSSLSrvConfigRec* sc = get_nwssl_cfg(cmd->server);
 
454
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
455
    char *ports, *addr;
 
456
    unsigned short port;
 
457
    seclisten_rec *new;
 
458
    ap_listen_rec **walk;
 
459
    apr_sockaddr_t *sa;
 
460
    int found_listener = 0;
 
461
 
 
462
 
 
463
    if (err != NULL)
 
464
        return err;
 
465
 
 
466
    ports = strchr(ips, ':');
 
467
 
 
468
    if (ports != NULL) {
 
469
        if (ports == ips)
 
470
            return "Missing IP address";
 
471
        else if (ports[1] == '\0')
 
472
            return "Address must end in :<port-number>";
 
473
 
 
474
        *(ports++) = '\0';
 
475
    }
 
476
    else {
 
477
        ports = (char*)ips;
 
478
    }
 
479
 
 
480
    new = apr_pcalloc(cmd->server->process->pool, sizeof(seclisten_rec));
 
481
    new->local_addr.sin_family = AF_INET;
 
482
 
 
483
    if (ports == ips) {
 
484
        new->local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 
485
        addr = apr_pstrdup(cmd->server->process->pool, "0.0.0.0");
 
486
    }
 
487
    else {
 
488
        new->local_addr.sin_addr.s_addr = parse_addr(ips, NULL);
 
489
        addr = apr_pstrdup(cmd->server->process->pool, ips);
 
490
    }
 
491
 
 
492
    port = atoi(ports);
 
493
 
 
494
    if (!port)
 
495
        return "Port must be numeric";
 
496
 
 
497
    /* If the specified addr:port was created previously, put the listen
 
498
       socket record back on the ap_listeners list so that the socket
 
499
       will be reused rather than recreated */
 
500
    for (walk = &nw_old_listeners; *walk;) {
 
501
        sa = (*walk)->bind_addr;
 
502
        if (sa) {
 
503
            ap_listen_rec *new;
 
504
            apr_port_t oldport;
 
505
 
 
506
            oldport = sa->port;
 
507
            /* If both ports are equivalent, then if their names are equivalent,
 
508
             * then we will re-use the existing record.
 
509
             */
 
510
            if (port == oldport &&
 
511
                ((!addr && !sa->hostname) ||
 
512
                 ((addr && sa->hostname) && !strcmp(sa->hostname, addr)))) {
 
513
                new = *walk;
 
514
                *walk = new->next;
 
515
                new->next = ap_listeners;
 
516
                ap_listeners = new;
 
517
                found_listener = 1;
 
518
                continue;
 
519
            }
 
520
        }
 
521
 
 
522
        walk = &(*walk)->next;
 
523
    }
 
524
 
 
525
    apr_table_add(sc->sltable, ports, addr);
 
526
 
 
527
    /* If we found a pre-existing listen socket record, then there
 
528
       is no need to create a new secure listen socket record. */
 
529
    if (found_listener) {
 
530
        return NULL;
 
531
    }
 
532
 
 
533
    new->local_addr.sin_port = htons(port);
 
534
    new->fd = -1;
 
535
    new->used = 0;
 
536
    new->next = ap_seclisteners;
 
537
    strcpy(new->key, key);
 
538
    new->mutual = (mutual) ? 1 : 0;
 
539
    new->addr = addr;
 
540
    new->port = port;
 
541
    ap_seclisteners = new;
 
542
    return NULL;
 
543
}
 
544
 
 
545
static const char *set_secure_upgradeable_listener(cmd_parms *cmd, void *dummy,
 
546
                                       const char *ips, const char* key)
 
547
{
 
548
    NWSSLSrvConfigRec* sc = get_nwssl_cfg(cmd->server);
 
549
    seclistenup_rec *listen_node;
 
550
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
551
    char *ports, *addr;
 
552
    unsigned short port;
 
553
    seclistenup_rec *new;
 
554
 
 
555
    if (err != NULL)
 
556
        return err;
 
557
 
 
558
    ports = strchr(ips, ':');
 
559
 
 
560
    if (ports != NULL) {
 
561
        if (ports == ips)
 
562
            return "Missing IP address";
 
563
        else if (ports[1] == '\0')
 
564
            return "Address must end in :<port-number>";
 
565
 
 
566
        *(ports++) = '\0';
 
567
    }
 
568
    else {
 
569
        ports = (char*)ips;
 
570
    }
 
571
 
 
572
    if (ports == ips) {
 
573
        addr = apr_pstrdup(cmd->pool, "0.0.0.0");
 
574
    }
 
575
    else {
 
576
        addr = apr_pstrdup(cmd->pool, ips);
 
577
    }
 
578
 
 
579
    port = atoi(ports);
 
580
 
 
581
    if (!port)
 
582
        return "Port must be numeric";
 
583
 
 
584
    apr_table_set(sc->slutable, ports, addr);
 
585
 
 
586
    new = apr_pcalloc(cmd->pool, sizeof(seclistenup_rec));
 
587
    new->next = ap_seclistenersup;
 
588
    strcpy(new->key, key);
 
589
    new->addr = addr;
 
590
    new->port = port;
 
591
    ap_seclistenersup = new;
 
592
 
 
593
    return err;
 
594
}
 
595
 
 
596
static apr_status_t nwssl_socket_cleanup(void *data)
 
597
{
 
598
    ap_listen_rec* slr = (ap_listen_rec*)data;
 
599
    ap_listen_rec* lr;
 
600
 
 
601
    /* Remove our secure listener from the listener list */
 
602
    for (lr = ap_listeners; lr; lr = lr->next) {
 
603
        /* slr is at the head of the list */
 
604
        if (lr == slr) {
 
605
            ap_listeners = slr->next;
 
606
            break;
 
607
        }
 
608
        /* slr is somewhere in between or at the end*/
 
609
        if (lr->next == slr) {
 
610
            lr->next = slr->next;
 
611
            break;
 
612
        }
 
613
    }
 
614
    return APR_SUCCESS;
 
615
}
 
616
 
 
617
static const char *set_trusted_certs(cmd_parms *cmd, void *dummy, char *arg)
 
618
{
 
619
    char **ptr = (char **)apr_array_push(certlist);
 
620
 
 
621
    *ptr = apr_pstrdup(cmd->pool, arg);
 
622
    return NULL;
 
623
}
 
624
 
 
625
static int nwssl_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
 
626
                         apr_pool_t *ptemp)
 
627
{
 
628
    seclisten_rec* ap_old_seclisteners;
 
629
    char *ports, *addr;
 
630
    unsigned short port;
 
631
    ap_listen_rec **walk;
 
632
    seclisten_rec **secwalk;
 
633
    apr_sockaddr_t *sa;
 
634
    int found;
 
635
 
 
636
  /* Pull all of the listeners that were created by mod_nw_ssl out of the
 
637
     ap_listeners list so that the normal listen socket processing does
 
638
     automatically close them */
 
639
    nw_old_listeners = NULL;
 
640
    ap_old_seclisteners = NULL;
 
641
 
 
642
    for (secwalk = &ap_seclisteners; *secwalk;) {
 
643
        found = 0;
 
644
        for (walk = &ap_listeners; *walk;) {
 
645
            sa = (*walk)->bind_addr;
 
646
            if (sa) {
 
647
                ap_listen_rec *new;
 
648
                seclisten_rec *secnew;
 
649
                apr_port_t oldport;
 
650
 
 
651
                oldport = sa->port;
 
652
                /* If both ports are equivalent, then if their names are equivalent,
 
653
                 * then we will re-use the existing record.
 
654
                 */
 
655
                if ((*secwalk)->port == oldport &&
 
656
                    ((!(*secwalk)->addr && !sa->hostname) ||
 
657
                     (((*secwalk)->addr && sa->hostname) && !strcmp(sa->hostname, (*secwalk)->addr)))) {
 
658
                    /* Move the listen socket from ap_listeners to nw_old_listeners */
 
659
                    new = *walk;
 
660
                    *walk = new->next;
 
661
                    new->next = nw_old_listeners;
 
662
                    nw_old_listeners = new;
 
663
 
 
664
                    /* Move the secure socket record to ap_old_seclisterners */
 
665
                    secnew = *secwalk;
 
666
                    *secwalk = secnew->next;
 
667
                    secnew->next = ap_old_seclisteners;
 
668
                    ap_old_seclisteners = secnew;
 
669
                    found = 1;
 
670
                    break;
 
671
                }
 
672
            }
 
673
 
 
674
            walk = &(*walk)->next;
 
675
        }
 
676
        if (!found && &(*secwalk)->next) {
 
677
            secwalk = &(*secwalk)->next;
 
678
        }
 
679
    }
 
680
 
 
681
    /* Restore the secure socket records list so that the post config can
 
682
       process all of the sockets normally */
 
683
    ap_seclisteners = ap_old_seclisteners;
 
684
    ap_seclistenersup = NULL;
 
685
    certlist = apr_array_make(pconf, 1, sizeof(char *));
 
686
 
 
687
    /* Now that we have removed all of the mod_nw_ssl created socket records,
 
688
       allow the normal listen socket handling to occur.
 
689
       NOTE: If for any reason mod_nw_ssl is removed as a built-in module,
 
690
       the following call must be put back into the pre-config handler of the
 
691
       MPM.  It is only here to ensure that mod_nw_ssl fixes up the listen
 
692
       socket list before anything else looks at it. */
 
693
    ap_listen_pre_config();
 
694
 
 
695
    return OK;
 
696
}
 
697
 
 
698
static int nwssl_pre_connection(conn_rec *c, void *csd)
 
699
{
 
700
 
 
701
    if (apr_table_get(c->notes, "nwconv-ssl")) {
 
702
        convert_secure_socket(c, (apr_socket_t*)csd);
 
703
    }
 
704
    else {
 
705
        secsocket_data *csd_data = apr_palloc(c->pool, sizeof(secsocket_data));
 
706
 
 
707
        csd_data->csd = (apr_socket_t*)csd;
 
708
        csd_data->is_secure = 0;
 
709
        ap_set_module_config(c->conn_config, &nwssl_module, (void*)csd_data);
 
710
    }
 
711
 
 
712
    return OK;
 
713
}
 
714
 
 
715
static int nwssl_post_config(apr_pool_t *pconf, apr_pool_t *plog,
 
716
                          apr_pool_t *ptemp, server_rec *s)
 
717
{
 
718
    seclisten_rec* sl;
 
719
    ap_listen_rec* lr;
 
720
    apr_socket_t*  sd;
 
721
    apr_status_t status;
 
722
    seclistenup_rec *slu;
 
723
    int found;
 
724
    ap_listen_rec *walk;
 
725
    seclisten_rec *secwalk, *lastsecwalk;
 
726
    apr_sockaddr_t *sa;
 
727
    int found_listener = 0;
 
728
 
 
729
    /* Walk the old listeners list and compare it to the secure
 
730
       listeners list and remove any secure listener records that
 
731
       are not being reused */
 
732
    for (walk = nw_old_listeners; walk; walk = walk->next) {
 
733
        sa = walk->bind_addr;
 
734
        if (sa) {
 
735
            ap_listen_rec *new;
 
736
            apr_port_t oldport;
 
737
 
 
738
            oldport = sa->port;
 
739
            for (secwalk = ap_seclisteners, lastsecwalk = ap_seclisteners; secwalk; secwalk = lastsecwalk->next) {
 
740
                unsigned short port = secwalk->port;
 
741
                char *addr = secwalk->addr;
 
742
                /* If both ports are equivalent, then if their names are equivalent,
 
743
                 * then we will re-use the existing record.
 
744
                 */
 
745
                if (port == oldport &&
 
746
                    ((!addr && !sa->hostname) ||
 
747
                     ((addr && sa->hostname) && !strcmp(sa->hostname, addr)))) {
 
748
                    if (secwalk == ap_seclisteners) {
 
749
                        ap_seclisteners = secwalk->next;
 
750
                    }
 
751
                    else {
 
752
                        lastsecwalk->next = secwalk->next;
 
753
                    }
 
754
                    apr_socket_close(walk->sd);
 
755
                    walk->active = 0;
 
756
                    break;
 
757
                }
 
758
                else {
 
759
                    lastsecwalk = secwalk;
 
760
                }
 
761
            }
 
762
        }
 
763
    }
 
764
 
 
765
    for (sl = ap_seclisteners; sl != NULL; sl = sl->next) {
 
766
        /* If we find a pre-existing listen socket and it has already been
 
767
           created, then no neeed to go any further, just reuse it. */
 
768
        if (((sl->fd = find_secure_listener(sl)) >= 0) && (sl->used)) {
 
769
            continue;
 
770
        }
 
771
 
 
772
        if (sl->fd < 0)
 
773
            sl->fd = make_secure_socket(s->process->pool, &sl->local_addr, sl->key, sl->mutual, s);
 
774
 
 
775
        if (sl->fd >= 0) {
 
776
            apr_os_sock_info_t sock_info;
 
777
 
 
778
            sock_info.os_sock = &(sl->fd);
 
779
            sock_info.local = (struct sockaddr*)&(sl->local_addr);
 
780
            sock_info.remote = NULL;
 
781
            sock_info.family = APR_INET;
 
782
            sock_info.type = SOCK_STREAM;
 
783
 
 
784
            apr_os_sock_make(&sd, &sock_info, s->process->pool);
 
785
 
 
786
            lr = apr_pcalloc(s->process->pool, sizeof(ap_listen_rec));
 
787
 
 
788
            if (lr) {
 
789
                lr->sd = sd;
 
790
                if ((status = apr_sockaddr_info_get(&lr->bind_addr, sl->addr, APR_UNSPEC, sl->port, 0,
 
791
                                              s->process->pool)) != APR_SUCCESS) {
 
792
                    ap_log_perror(APLOG_MARK, APLOG_CRIT, status, pconf,
 
793
                                 "alloc_listener: failed to set up sockaddr for %s:%d", sl->addr, sl->port);
 
794
                    return HTTP_INTERNAL_SERVER_ERROR;
 
795
                }
 
796
                lr->next = ap_listeners;
 
797
                ap_listeners = lr;
 
798
                apr_pool_cleanup_register(s->process->pool, lr, nwssl_socket_cleanup, apr_pool_cleanup_null);
 
799
            }
 
800
        } else {
 
801
            return HTTP_INTERNAL_SERVER_ERROR;
 
802
        }
 
803
    }
 
804
 
 
805
    for (slu = ap_seclistenersup; slu; slu = slu->next) {
 
806
        /* Check the listener list for a matching upgradeable listener */
 
807
        found = 0;
 
808
        for (lr = ap_listeners; lr; lr = lr->next) {
 
809
            if (slu->port == lr->bind_addr->port) {
 
810
                found = 1;
 
811
                break;
 
812
            }
 
813
        }
 
814
        if (!found) {
 
815
            ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, plog,
 
816
                         "No Listen directive found for upgradeable listener %s:%d", slu->addr, slu->port);
 
817
        }
 
818
    }
 
819
 
 
820
    build_cert_list(s->process->pool);
 
821
 
 
822
    return OK;
 
823
}
 
824
 
 
825
static void *nwssl_config_server_create(apr_pool_t *p, server_rec *s)
 
826
{
 
827
    NWSSLSrvConfigRec *new = apr_palloc(p, sizeof(NWSSLSrvConfigRec));
 
828
    new->sltable = apr_table_make(p, 5);
 
829
    new->slutable = apr_table_make(p, 5);
 
830
    return new;
 
831
}
 
832
 
 
833
static void *nwssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
 
834
{
 
835
    NWSSLSrvConfigRec *base = (NWSSLSrvConfigRec *)basev;
 
836
    NWSSLSrvConfigRec *add  = (NWSSLSrvConfigRec *)addv;
 
837
    NWSSLSrvConfigRec *merged  = (NWSSLSrvConfigRec *)apr_palloc(p, sizeof(NWSSLSrvConfigRec));
 
838
    return merged;
 
839
}
 
840
 
 
841
static int compare_ipports(void *rec, const char *key, const char *value)
 
842
{
 
843
    conn_rec *c = (conn_rec*)rec;
 
844
 
 
845
    if (value &&
 
846
        ((strcmp(value, "0.0.0.0") == 0) || (strcmp(value, c->local_ip) == 0)))
 
847
    {
 
848
        return 0;
 
849
    }
 
850
    return 1;
 
851
}
 
852
 
 
853
static int isSecureConnEx (const server_rec *s, const conn_rec *c, const apr_table_t *t)
 
854
{
 
855
    char port[8];
 
856
 
 
857
    itoa((c->local_addr)->port, port, 10);
 
858
    if (!apr_table_do(compare_ipports, (void*)c, t, port, NULL))
 
859
    {
 
860
        return 1;
 
861
    }
 
862
 
 
863
    return 0;
 
864
}
 
865
 
 
866
static int isSecureConn (const server_rec *s, const conn_rec *c)
 
867
{
 
868
    NWSSLSrvConfigRec *sc = get_nwssl_cfg(s);
 
869
 
 
870
    return isSecureConnEx (s, c, sc->sltable);
 
871
}
 
872
 
 
873
static int isSecureConnUpgradeable (const server_rec *s, const conn_rec *c)
 
874
{
 
875
    NWSSLSrvConfigRec *sc = get_nwssl_cfg(s);
 
876
 
 
877
    return isSecureConnEx (s, c, sc->slutable);
 
878
}
 
879
 
 
880
static int isSecure (const request_rec *r)
 
881
{
 
882
        return isSecureConn (r->server, r->connection);
 
883
}
 
884
 
 
885
static int isSecureUpgradeable (const request_rec *r)
 
886
{
 
887
        return isSecureConnUpgradeable (r->server, r->connection);
 
888
}
 
889
 
 
890
static int isSecureUpgraded (const request_rec *r)
 
891
{
 
892
    secsocket_data *csd_data = (secsocket_data*)ap_get_module_config(r->connection->conn_config, &nwssl_module);
 
893
 
 
894
        return csd_data->is_secure;
 
895
}
 
896
 
 
897
static int nwssl_hook_Fixup(request_rec *r)
 
898
{
 
899
    int i;
 
900
 
 
901
    if (!isSecure(r) && !isSecureUpgraded(r))
 
902
        return DECLINED;
 
903
 
 
904
    apr_table_set(r->subprocess_env, "HTTPS", "on");
 
905
 
 
906
    return DECLINED;
 
907
}
 
908
 
 
909
static const char *nwssl_hook_http_scheme(const request_rec *r)
 
910
{
 
911
    if (isSecure(r) && !isSecureUpgraded(r))
 
912
        return "https";
 
913
 
 
914
    return NULL;
 
915
}
 
916
 
 
917
static apr_port_t nwssl_hook_default_port(const request_rec *r)
 
918
{
 
919
    if (isSecure(r))
 
920
        return DEFAULT_HTTPS_PORT;
 
921
 
 
922
    return 0;
 
923
}
 
924
 
 
925
int ssl_proxy_enable(conn_rec *c)
 
926
{
 
927
    apr_table_set(c->notes, "nwconv-ssl", "Y");
 
928
 
 
929
    return 1;
 
930
}
 
931
 
 
932
int ssl_engine_disable(conn_rec *c)
 
933
{
 
934
    return 1;
 
935
}
 
936
 
 
937
static int ssl_is_https(conn_rec *c)
 
938
{
 
939
    secsocket_data *csd_data = (secsocket_data*)ap_get_module_config(c->conn_config, &nwssl_module);
 
940
 
 
941
    return isSecureConn (c->base_server, c) || (csd_data && csd_data->is_secure);
 
942
}
 
943
 
 
944
/* This function must remain safe to use for a non-SSL connection. */
 
945
char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, char *var)
 
946
{
 
947
    NWSSLSrvConfigRec *mc = get_nwssl_cfg(s);
 
948
    const char *result;
 
949
    BOOL resdup;
 
950
    apr_time_exp_t tm;
 
951
 
 
952
    result = NULL;
 
953
    resdup = TRUE;
 
954
 
 
955
    /*
 
956
     * When no pool is given try to find one
 
957
     */
 
958
    if (p == NULL) {
 
959
        if (r != NULL)
 
960
            p = r->pool;
 
961
        else if (c != NULL)
 
962
            p = c->pool;
 
963
        else
 
964
            p = mc->pPool;
 
965
    }
 
966
 
 
967
    /*
 
968
     * Request dependent stuff
 
969
     */
 
970
    if (r != NULL) {
 
971
        switch (var[0]) {
 
972
        case 'H':
 
973
        case 'h':
 
974
            if (strcEQ(var, "HTTP_USER_AGENT"))
 
975
                result = apr_table_get(r->headers_in, "User-Agent");
 
976
            else if (strcEQ(var, "HTTP_REFERER"))
 
977
                result = apr_table_get(r->headers_in, "Referer");
 
978
            else if (strcEQ(var, "HTTP_COOKIE"))
 
979
                result = apr_table_get(r->headers_in, "Cookie");
 
980
            else if (strcEQ(var, "HTTP_FORWARDED"))
 
981
                result = apr_table_get(r->headers_in, "Forwarded");
 
982
            else if (strcEQ(var, "HTTP_HOST"))
 
983
                result = apr_table_get(r->headers_in, "Host");
 
984
            else if (strcEQ(var, "HTTP_PROXY_CONNECTION"))
 
985
                result = apr_table_get(r->headers_in, "Proxy-Connection");
 
986
            else if (strcEQ(var, "HTTP_ACCEPT"))
 
987
                result = apr_table_get(r->headers_in, "Accept");
 
988
            else if (strcEQ(var, "HTTPS")) {
 
989
                if (isSecure(r) || isSecureUpgraded(r))
 
990
                    result = "on";
 
991
                else
 
992
                    result = "off";
 
993
            }
 
994
            else if (strlen(var) > 5 && strcEQn(var, "HTTP:", 5))
 
995
                /* all other headers from which we are still not know about */
 
996
                result = apr_table_get(r->headers_in, var+5);
 
997
            break;
 
998
 
 
999
        case 'R':
 
1000
        case 'r':
 
1001
            if (strcEQ(var, "REQUEST_METHOD"))
 
1002
                result = r->method;
 
1003
            else if (strcEQ(var, "REQUEST_SCHEME"))
 
1004
                result = ap_http_scheme(r);
 
1005
            else if (strcEQ(var, "REQUEST_URI"))
 
1006
                result = r->uri;
 
1007
            else if (strcEQ(var, "REQUEST_FILENAME"))
 
1008
                result = r->filename;
 
1009
            else if (strcEQ(var, "REMOTE_HOST"))
 
1010
                result = ap_get_remote_host(r->connection, r->per_dir_config,
 
1011
                                            REMOTE_NAME, NULL);
 
1012
            else if (strcEQ(var, "REMOTE_IDENT"))
 
1013
                result = ap_get_remote_logname(r);
 
1014
            else if (strcEQ(var, "REMOTE_USER"))
 
1015
                result = r->user;
 
1016
            break;
 
1017
 
 
1018
        case 'S':
 
1019
        case 's':
 
1020
            if (strcEQn(var, "SSL", 3)) break; /* shortcut common case */
 
1021
 
 
1022
            if (strcEQ(var, "SERVER_ADMIN"))
 
1023
                result = r->server->server_admin;
 
1024
            else if (strcEQ(var, "SERVER_NAME"))
 
1025
                result = ap_get_server_name(r);
 
1026
            else if (strcEQ(var, "SERVER_PORT"))
 
1027
                result = apr_psprintf(p, "%u", ap_get_server_port(r));
 
1028
            else if (strcEQ(var, "SERVER_PROTOCOL"))
 
1029
                result = r->protocol;
 
1030
            else if (strcEQ(var, "SCRIPT_FILENAME"))
 
1031
                result = r->filename;
 
1032
            break;
 
1033
 
 
1034
        default:
 
1035
            if (strcEQ(var, "PATH_INFO"))
 
1036
                result = r->path_info;
 
1037
            else if (strcEQ(var, "QUERY_STRING"))
 
1038
                result = r->args;
 
1039
            else if (strcEQ(var, "IS_SUBREQ"))
 
1040
                result = (r->main != NULL ? "true" : "false");
 
1041
            else if (strcEQ(var, "DOCUMENT_ROOT"))
 
1042
                result = ap_document_root(r);
 
1043
            else if (strcEQ(var, "AUTH_TYPE"))
 
1044
                result = r->ap_auth_type;
 
1045
            else if (strcEQ(var, "THE_REQUEST"))
 
1046
                result = r->the_request;
 
1047
            break;
 
1048
        }
 
1049
    }
 
1050
 
 
1051
    /*
 
1052
     * Connection stuff
 
1053
     */
 
1054
    if (result == NULL && c != NULL) {
 
1055
 
 
1056
                /* XXX-Can't get specific SSL info from NetWare */
 
1057
        /* SSLConnRec *sslconn = myConnConfig(c);
 
1058
        if (strlen(var) > 4 && strcEQn(var, "SSL_", 4)
 
1059
            && sslconn && sslconn->ssl)
 
1060
            result = ssl_var_lookup_ssl(p, c, var+4);*/
 
1061
 
 
1062
                if (strlen(var) > 4 && strcEQn(var, "SSL_", 4))
 
1063
                        result = NULL;
 
1064
        else if (strcEQ(var, "REMOTE_ADDR"))
 
1065
            result = c->remote_ip;
 
1066
    }
 
1067
 
 
1068
    /*
 
1069
     * Totally independent stuff
 
1070
     */
 
1071
    if (result == NULL) {
 
1072
        if (strlen(var) > 12 && strcEQn(var, "SSL_VERSION_", 12))
 
1073
                        result = NULL;
 
1074
            /* XXX-Can't get specific SSL info from NetWare */
 
1075
            /*result = ssl_var_lookup_ssl_version(p, var+12);*/
 
1076
        else if (strcEQ(var, "SERVER_SOFTWARE"))
 
1077
            result = ap_get_server_version();
 
1078
        else if (strcEQ(var, "API_VERSION")) {
 
1079
            result = apr_itoa(p, MODULE_MAGIC_NUMBER);
 
1080
            resdup = FALSE;
 
1081
        }
 
1082
        else if (strcEQ(var, "TIME_YEAR")) {
 
1083
            apr_time_exp_lt(&tm, apr_time_now());
 
1084
            result = apr_psprintf(p, "%02d%02d",
 
1085
                                 (tm.tm_year / 100) + 19, tm.tm_year % 100);
 
1086
            resdup = FALSE;
 
1087
        }
 
1088
#define MKTIMESTR(format, tmfield) \
 
1089
            apr_time_exp_lt(&tm, apr_time_now()); \
 
1090
            result = apr_psprintf(p, format, tm.tmfield); \
 
1091
            resdup = FALSE;
 
1092
        else if (strcEQ(var, "TIME_MON")) {
 
1093
            MKTIMESTR("%02d", tm_mon+1)
 
1094
        }
 
1095
        else if (strcEQ(var, "TIME_DAY")) {
 
1096
            MKTIMESTR("%02d", tm_mday)
 
1097
        }
 
1098
        else if (strcEQ(var, "TIME_HOUR")) {
 
1099
            MKTIMESTR("%02d", tm_hour)
 
1100
        }
 
1101
        else if (strcEQ(var, "TIME_MIN")) {
 
1102
            MKTIMESTR("%02d", tm_min)
 
1103
        }
 
1104
        else if (strcEQ(var, "TIME_SEC")) {
 
1105
            MKTIMESTR("%02d", tm_sec)
 
1106
        }
 
1107
        else if (strcEQ(var, "TIME_WDAY")) {
 
1108
            MKTIMESTR("%d", tm_wday)
 
1109
        }
 
1110
        else if (strcEQ(var, "TIME")) {
 
1111
            apr_time_exp_lt(&tm, apr_time_now());
 
1112
            result = apr_psprintf(p,
 
1113
                        "%02d%02d%02d%02d%02d%02d%02d", (tm.tm_year / 100) + 19,
 
1114
                        (tm.tm_year % 100), tm.tm_mon+1, tm.tm_mday,
 
1115
                        tm.tm_hour, tm.tm_min, tm.tm_sec);
 
1116
            resdup = FALSE;
 
1117
        }
 
1118
        /* all other env-variables from the parent Apache process */
 
1119
        else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) {
 
1120
            result = apr_table_get(r->notes, var+4);
 
1121
            if (result == NULL)
 
1122
                result = apr_table_get(r->subprocess_env, var+4);
 
1123
            if (result == NULL)
 
1124
                result = getenv(var+4);
 
1125
        }
 
1126
    }
 
1127
 
 
1128
    if (result != NULL && resdup)
 
1129
        result = apr_pstrdup(p, result);
 
1130
    if (result == NULL)
 
1131
        result = "";
 
1132
    return (char *)result;
 
1133
}
 
1134
 
 
1135
#define SWITCH_STATUS_LINE "HTTP/1.1 101 Switching Protocols"
 
1136
#define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1"
 
1137
#define CONNECTION_HEADER "Connection: Upgrade"
 
1138
 
 
1139
static apr_status_t ssl_io_filter_Upgrade(ap_filter_t *f,
 
1140
                                         apr_bucket_brigade *bb)
 
1141
 
 
1142
{
 
1143
    const char *upgrade;
 
1144
    apr_bucket_brigade *upgradebb;
 
1145
    request_rec *r = f->r;
 
1146
    apr_socket_t *csd = NULL;
 
1147
    char *key;
 
1148
    int ret;
 
1149
    secsocket_data *csd_data;
 
1150
    apr_bucket *b;
 
1151
    apr_status_t rv;
 
1152
 
 
1153
    /* Just remove the filter, if it doesn't work the first time, it won't
 
1154
     * work at all for this request.
 
1155
     */
 
1156
    ap_remove_output_filter(f);
 
1157
 
 
1158
    /* No need to ensure that this is a server with optional SSL, the filter
 
1159
     * is only inserted if that is true.
 
1160
     */
 
1161
 
 
1162
    upgrade = apr_table_get(r->headers_in, "Upgrade");
 
1163
    if (upgrade == NULL
 
1164
        || strcmp(ap_getword(r->pool, &upgrade, ','), "TLS/1.0")) {
 
1165
            /* "Upgrade: TLS/1.0, ..." header not found, don't do Upgrade */
 
1166
        return ap_pass_brigade(f->next, bb);
 
1167
    }
 
1168
 
 
1169
    apr_table_unset(r->headers_out, "Upgrade");
 
1170
 
 
1171
    if (r) {
 
1172
        csd_data = (secsocket_data*)ap_get_module_config(r->connection->conn_config, &nwssl_module);
 
1173
        csd = csd_data->csd;
 
1174
    }
 
1175
    else {
 
1176
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
 
1177
                     "Unable to get upgradeable socket handle");
 
1178
        return ap_pass_brigade(f->next, bb);
 
1179
    }
 
1180
 
 
1181
 
 
1182
    /* Send the interim 101 response. */
 
1183
    upgradebb = apr_brigade_create(r->pool, f->c->bucket_alloc);
 
1184
 
 
1185
    ap_fputstrs(f->next, upgradebb, SWITCH_STATUS_LINE, CRLF,
 
1186
                UPGRADE_HEADER, CRLF, CONNECTION_HEADER, CRLF, CRLF, NULL);
 
1187
 
 
1188
    b = apr_bucket_flush_create(f->c->bucket_alloc);
 
1189
    APR_BRIGADE_INSERT_TAIL(upgradebb, b);
 
1190
 
 
1191
    rv = ap_pass_brigade(f->next, upgradebb);
 
1192
    if (rv) {
 
1193
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
 
1194
                      "could not send interim 101 Upgrade response");
 
1195
        return AP_FILTER_ERROR;
 
1196
    }
 
1197
 
 
1198
    key = get_port_key(r->connection);
 
1199
 
 
1200
    if (csd && key) {
 
1201
        int sockdes;
 
1202
        apr_os_sock_get(&sockdes, csd);
 
1203
 
 
1204
 
 
1205
        ret = SSLize_Socket(sockdes, key, r);
 
1206
        if (!ret) {
 
1207
            csd_data->is_secure = 1;
 
1208
        }
 
1209
    }
 
1210
    else {
 
1211
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
 
1212
                     "Upgradeable socket handle not found");
 
1213
        return AP_FILTER_ERROR;
 
1214
    }
 
1215
 
 
1216
    ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
 
1217
                 "Awaiting re-negotiation handshake");
 
1218
 
 
1219
    /* Now that we have initialized the ssl connection which added the ssl_io_filter,
 
1220
       pass the brigade off to the connection based output filters so that the
 
1221
       request can complete encrypted */
 
1222
    return ap_pass_brigade(f->c->output_filters, bb);
 
1223
}
 
1224
 
 
1225
static void ssl_hook_Insert_Filter(request_rec *r)
 
1226
{
 
1227
    NWSSLSrvConfigRec *sc = get_nwssl_cfg(r->server);
 
1228
 
 
1229
    if (isSecureUpgradeable (r)) {
 
1230
        ap_add_output_filter("UPGRADE_FILTER", NULL, r, r->connection);
 
1231
    }
 
1232
}
 
1233
 
 
1234
static const command_rec nwssl_module_cmds[] =
 
1235
{
 
1236
    AP_INIT_TAKE23("SecureListen", set_secure_listener, NULL, RSRC_CONF,
 
1237
      "specify an address and/or port with a key pair name.\n"
 
1238
      "Optional third parameter of MUTUAL configures the port for mutual authentication."),
 
1239
    AP_INIT_TAKE2("NWSSLUpgradeable", set_secure_upgradeable_listener, NULL, RSRC_CONF,
 
1240
      "specify an address and/or port with a key pair name, that can be upgraded to an SSL connection.\n"
 
1241
      "The address and/or port must have already be defined using a Listen directive."),
 
1242
    AP_INIT_ITERATE("NWSSLTrustedCerts", set_trusted_certs, NULL, RSRC_CONF,
 
1243
        "Adds trusted certificates that are used to create secure connections to proxied servers"),
 
1244
    {NULL}
 
1245
};
 
1246
 
 
1247
static void register_hooks(apr_pool_t *p)
 
1248
{
 
1249
    ap_register_output_filter ("UPGRADE_FILTER", ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5);
 
1250
 
 
1251
    ap_hook_pre_config(nwssl_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
 
1252
    ap_hook_pre_connection(nwssl_pre_connection, NULL, NULL, APR_HOOK_MIDDLE);
 
1253
    ap_hook_post_config(nwssl_post_config, NULL, NULL, APR_HOOK_MIDDLE);
 
1254
    ap_hook_fixups(nwssl_hook_Fixup, NULL, NULL, APR_HOOK_MIDDLE);
 
1255
    ap_hook_http_scheme(nwssl_hook_http_scheme, NULL, NULL, APR_HOOK_MIDDLE);
 
1256
    ap_hook_default_port(nwssl_hook_default_port, NULL, NULL, APR_HOOK_MIDDLE);
 
1257
    ap_hook_insert_filter(ssl_hook_Insert_Filter, NULL, NULL, APR_HOOK_MIDDLE);
 
1258
 
 
1259
    APR_REGISTER_OPTIONAL_FN(ssl_is_https);
 
1260
    APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);
 
1261
 
 
1262
    APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
 
1263
    APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
 
1264
}
 
1265
 
 
1266
module AP_MODULE_DECLARE_DATA nwssl_module =
 
1267
{
 
1268
    STANDARD20_MODULE_STUFF,
 
1269
    NULL,                       /* dir config creater */
 
1270
    NULL,                       /* dir merger --- default is to override */
 
1271
    nwssl_config_server_create, /* server config */
 
1272
    nwssl_config_server_merge,  /* merge server config */
 
1273
    nwssl_module_cmds,          /* command apr_table_t */
 
1274
    register_hooks
 
1275
};
 
1276