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 |
* Originally developed by Aaron Bannert and Justin Erenkrantz, eBuilt. |
17 |
*/ |
18 |
|
19 |
#include <apr_portable.h> |
20 |
#include <apr_strings.h> |
21 |
|
22 |
#if APR_HAVE_UNISTD_H |
23 |
#include <unistd.h> |
24 |
#endif |
25 |
|
26 |
#include "config.h" |
27 |
#include "flood_profile.h" |
28 |
#include "flood_net.h" |
29 |
#include "flood_net_ssl.h" |
30 |
|
31 |
#if FLOOD_HAS_OPENSSL |
32 |
|
33 |
#define OPENSSL_THREAD_DEFINES |
34 |
#include <openssl/ssl.h> |
35 |
#include <openssl/err.h> |
36 |
#include <openssl/rand.h> |
37 |
|
38 |
struct ssl_socket_t { |
39 |
SSL_CTX *ssl_context; |
40 |
SSL *ssl_connection; |
41 |
flood_socket_t *socket; |
42 |
}; |
43 |
|
44 |
apr_pool_t *ssl_pool; |
45 |
|
46 |
#if APR_HAS_THREADS |
47 |
apr_thread_mutex_t **ssl_locks; |
48 |
|
49 |
typedef struct CRYPTO_dynlock_value { |
50 |
apr_thread_mutex_t *lock; |
51 |
} CRYPTO_dynlock_value; |
52 |
|
53 |
static CRYPTO_dynlock_value *ssl_dyn_create(const char* file, int line) |
54 |
{ |
55 |
CRYPTO_dynlock_value *l; |
56 |
apr_status_t rv; |
57 |
|
58 |
l = apr_palloc(ssl_pool, sizeof(CRYPTO_dynlock_value)); |
59 |
rv = apr_thread_mutex_create(&l->lock, APR_THREAD_MUTEX_DEFAULT, ssl_pool); |
60 |
if (rv != APR_SUCCESS) { |
61 |
/* FIXME: return error here */ |
62 |
} |
63 |
return l; |
64 |
} |
65 |
|
66 |
static void ssl_dyn_lock(int mode, CRYPTO_dynlock_value *l, const char *file, |
67 |
int line) |
68 |
{ |
69 |
if (mode & CRYPTO_LOCK) { |
70 |
apr_thread_mutex_lock(l->lock); |
71 |
} |
72 |
else if (mode & CRYPTO_UNLOCK) { |
73 |
apr_thread_mutex_unlock(l->lock); |
74 |
} |
75 |
} |
76 |
|
77 |
static void ssl_dyn_destroy(CRYPTO_dynlock_value *l, const char *file, |
78 |
int line) |
79 |
{ |
80 |
apr_thread_mutex_destroy(l->lock); |
81 |
} |
82 |
|
83 |
static void ssl_lock(int mode, int n, const char *file, int line) |
84 |
{ |
85 |
if (mode & CRYPTO_LOCK) { |
86 |
apr_thread_mutex_lock(ssl_locks[n]); |
87 |
} |
88 |
else if (mode & CRYPTO_UNLOCK) { |
89 |
apr_thread_mutex_unlock(ssl_locks[n]); |
90 |
} |
91 |
} |
92 |
|
93 |
static unsigned long ssl_id(void) |
94 |
{ |
95 |
/* FIXME: This is lame and not portable. -aaron */ |
96 |
return (unsigned long) apr_os_thread_current(); |
97 |
} |
98 |
#endif |
99 |
|
100 |
/* borrowed from mod_ssl */ |
101 |
static int ssl_rand_choosenum(int l, int h) |
102 |
{ |
103 |
int i; |
104 |
char buf[50]; |
105 |
|
106 |
srand((unsigned int)time(NULL)); |
107 |
apr_snprintf(buf, sizeof(buf), "%.0f", |
108 |
(((double)(rand()%RAND_MAX)/RAND_MAX)*(h-l))); |
109 |
i = atoi(buf)+1; |
110 |
if (i < l) i = l; |
111 |
if (i > h) i = h; |
112 |
return i; |
113 |
} |
114 |
|
115 |
static void load_rand(void) |
116 |
{ |
117 |
unsigned char stackdata[256]; |
118 |
time_t tt; |
119 |
pid_t pid; |
120 |
int l, n; |
121 |
|
122 |
tt = time(NULL); |
123 |
l = sizeof(time_t); |
124 |
RAND_seed((unsigned char *)&tt, l); |
125 |
|
126 |
pid = (pid_t)getpid(); |
127 |
l = sizeof(pid_t); |
128 |
RAND_seed((unsigned char *)&pid, l); |
129 |
|
130 |
n = ssl_rand_choosenum(0, sizeof(stackdata)-128-1); |
131 |
RAND_seed(stackdata+n, 128); |
132 |
} |
133 |
|
134 |
apr_status_t ssl_init_socket(apr_pool_t *pool) |
135 |
{ |
136 |
#if APR_HAS_THREADS |
137 |
int i, numlocks; |
138 |
#endif |
139 |
|
140 |
ssl_pool = pool; |
141 |
|
142 |
SSL_library_init(); |
143 |
OpenSSL_add_ssl_algorithms(); |
144 |
SSL_load_error_strings(); |
145 |
ERR_load_crypto_strings(); |
146 |
#if ! FLOOD_HAS_DEVRAND |
147 |
load_rand(); |
148 |
#endif |
149 |
|
150 |
#if APR_HAS_THREADS |
151 |
numlocks = CRYPTO_num_locks(); |
152 |
ssl_locks = apr_palloc(pool, sizeof(apr_thread_mutex_t*)*numlocks); |
153 |
for (i = 0; i < numlocks; i++) { |
154 |
apr_status_t rv; |
155 |
|
156 |
/* Intraprocess locks don't /need/ a filename... */ |
157 |
rv = apr_thread_mutex_create(&ssl_locks[i], APR_THREAD_MUTEX_DEFAULT, |
158 |
ssl_pool); |
159 |
if (rv != APR_SUCCESS) { |
160 |
/* FIXME: error out here */ |
161 |
} |
162 |
} |
163 |
|
164 |
CRYPTO_set_locking_callback(ssl_lock); |
165 |
CRYPTO_set_id_callback(ssl_id); |
166 |
|
167 |
CRYPTO_set_dynlock_create_callback(ssl_dyn_create); |
168 |
CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock); |
169 |
CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy); |
170 |
#endif |
171 |
|
172 |
return APR_SUCCESS; |
173 |
} |
174 |
|
175 |
void ssl_read_socket_handshake(ssl_socket_t *s); |
176 |
|
177 |
ssl_socket_t* ssl_open_socket(apr_pool_t *pool, request_t *r, |
178 |
apr_status_t *status) |
179 |
{ |
180 |
apr_os_sock_t ossock; |
181 |
int e, sslError; |
182 |
|
183 |
ssl_socket_t *ssl_socket = apr_pcalloc(pool, sizeof(ssl_socket_t)); |
184 |
|
185 |
/* Open our TCP-based connection */ |
186 |
ssl_socket->socket = open_socket(pool, r, status); |
187 |
|
188 |
if (!ssl_socket->socket) |
189 |
return NULL; |
190 |
|
191 |
/* Get the native OS socket. */ |
192 |
apr_os_sock_get(&ossock, ssl_socket->socket->socket); |
193 |
|
194 |
/* Create a local context */ |
195 |
ssl_socket->ssl_context = SSL_CTX_new(SSLv23_client_method()); |
196 |
SSL_CTX_set_options(ssl_socket->ssl_context, SSL_OP_ALL); |
197 |
#ifdef SSL_MODE_AUTO_RETRY |
198 |
/* Not all OpenSSL versions support this. */ |
199 |
SSL_CTX_set_options(ssl_socket->ssl_context, SSL_MODE_AUTO_RETRY); |
200 |
#endif |
201 |
/*SSL_CTX_set_default_verify_paths(ssl_socket->ssl_context);*/ |
202 |
SSL_CTX_load_verify_locations(ssl_socket->ssl_context, NULL, CAPATH); |
203 |
|
204 |
/* Initialize the SSL connection */ |
205 |
ssl_socket->ssl_connection = SSL_new(ssl_socket->ssl_context); |
206 |
SSL_set_connect_state(ssl_socket->ssl_connection); |
207 |
|
208 |
/* Set the descriptors */ |
209 |
SSL_set_fd(ssl_socket->ssl_connection, ossock); |
210 |
e = SSL_connect(ssl_socket->ssl_connection); |
211 |
|
212 |
if (e) |
213 |
{ |
214 |
sslError = SSL_get_error(ssl_socket->ssl_connection, e); |
215 |
|
216 |
switch (sslError) |
217 |
{ |
218 |
case SSL_ERROR_NONE: |
219 |
case SSL_ERROR_WANT_READ: |
220 |
case SSL_ERROR_WANT_WRITE: |
221 |
/* Treat as okay. */ |
222 |
break; |
223 |
default: |
224 |
ERR_print_errors_fp(stderr); |
225 |
return NULL; |
226 |
} |
227 |
} |
228 |
|
229 |
return ssl_socket; |
230 |
} |
231 |
|
232 |
/* close down TCP socket */ |
233 |
void ssl_close_socket(ssl_socket_t *s) |
234 |
{ |
235 |
SSL_free(s->ssl_connection); |
236 |
SSL_CTX_free(s->ssl_context); |
237 |
close_socket(s->socket); |
238 |
} |
239 |
|
240 |
apr_status_t ssl_read_socket(ssl_socket_t *s, char *buf, apr_size_t *buflen) |
241 |
{ |
242 |
apr_status_t e; |
243 |
int sslError; |
244 |
apr_int32_t socketsRead; |
245 |
|
246 |
/* Wait until there is something to read. */ |
247 |
if (SSL_pending(s->ssl_connection) < *buflen) { |
248 |
e = apr_poll(&s->socket->read_pollset, 1, &socketsRead, |
249 |
LOCAL_SOCKET_TIMEOUT); |
250 |
|
251 |
if (socketsRead != 1) |
252 |
return APR_TIMEUP; |
253 |
} |
254 |
|
255 |
e = SSL_read(s->ssl_connection, buf, *buflen); |
256 |
sslError = SSL_get_error(s->ssl_connection, e); |
257 |
|
258 |
switch (sslError) |
259 |
{ |
260 |
case SSL_ERROR_NONE: |
261 |
*buflen = e; |
262 |
break; |
263 |
case SSL_ERROR_WANT_READ: |
264 |
ssl_read_socket(s, buf, buflen); |
265 |
break; |
266 |
case SSL_ERROR_ZERO_RETURN: /* Peer closed connection. */ |
267 |
return APR_EOF; |
268 |
case SSL_ERROR_SYSCALL: /* Look at errno. */ |
269 |
if (errno == 0) |
270 |
return APR_EOF; |
271 |
/* Continue through with the error case. */ |
272 |
case SSL_ERROR_WANT_WRITE: /* Technically, not an error. */ |
273 |
default: |
274 |
ERR_print_errors_fp(stderr); |
275 |
return APR_EGENERAL; |
276 |
} |
277 |
|
278 |
return APR_SUCCESS; |
279 |
} |
280 |
|
281 |
void ssl_read_socket_handshake(ssl_socket_t *s) |
282 |
{ |
283 |
char buf[1]; |
284 |
int buflen = 1; |
285 |
/* Wait until there is something to read. */ |
286 |
apr_int32_t socketsRead; |
287 |
apr_status_t e; |
288 |
e = apr_poll(&s->socket->read_pollset, 1, &socketsRead, |
289 |
LOCAL_SOCKET_TIMEOUT); |
290 |
e = SSL_read(s->ssl_connection, buf, buflen); |
291 |
} |
292 |
|
293 |
/* Write to the socket */ |
294 |
apr_status_t ssl_write_socket(ssl_socket_t *s, request_t *r) |
295 |
{ |
296 |
apr_status_t e; |
297 |
int sslError; |
298 |
|
299 |
/* Returns an error. */ |
300 |
e = SSL_write(s->ssl_connection, r->rbuf, r->rbufsize); |
301 |
|
302 |
sslError = SSL_get_error(s->ssl_connection, e); |
303 |
switch (sslError) |
304 |
{ |
305 |
case SSL_ERROR_NONE: |
306 |
break; |
307 |
case SSL_ERROR_WANT_READ: |
308 |
ssl_read_socket_handshake(s); |
309 |
ssl_write_socket(s, r); |
310 |
break; |
311 |
case SSL_ERROR_WANT_WRITE: |
312 |
break; |
313 |
default: |
314 |
ERR_print_errors_fp(stderr); |
315 |
return APR_EGENERAL; |
316 |
} |
317 |
|
318 |
return APR_SUCCESS; |
319 |
} |
320 |
|
321 |
apr_status_t ssl_check_socket(ssl_socket_t *s, apr_pool_t *pool) |
322 |
{ |
323 |
return check_socket(s->socket, pool); |
324 |
} |
325 |
|
326 |
#else /* FLOOD_HAS_OPENSSL */ |
327 |
|
328 |
apr_status_t ssl_init_socket(apr_pool_t *pool) |
329 |
{ |
330 |
return APR_ENOTIMPL; |
331 |
} |
332 |
|
333 |
ssl_socket_t* ssl_open_socket(apr_pool_t *pool, request_t *r, |
334 |
apr_status_t *status) |
335 |
{ |
336 |
return NULL; |
337 |
} |
338 |
|
339 |
void ssl_close_socket(ssl_socket_t *s) |
340 |
{ |
341 |
} |
342 |
|
343 |
apr_status_t ssl_write_socket(ssl_socket_t *s, request_t *r) |
344 |
{ |
345 |
return APR_ENOTIMPL; |
346 |
} |
347 |
|
348 |
apr_status_t ssl_read_socket(ssl_socket_t *s, char *buf, apr_size_t *buflen) |
349 |
{ |
350 |
return APR_ENOTIMPL; |
351 |
} |
352 |
|
353 |
apr_status_t ssl_check_socket(ssl_socket_t *s, apr_pool_t *pool) |
354 |
{ |
355 |
return APR_ENOTIMPL; |
356 |
} |
357 |
|
358 |
#endif /* FLOOD_HAS_OPENSSL */ |