blob: 3b0e86fe8ae295e47ea0d723cee79dccbb4d6a73 [file] [log] [blame]
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001/* $Id$ */
2/*
3 * Copyright (C) 2009 Teluu Inc. (http://www.teluu.com)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/ssl_sock.h>
20#include <pj/activesock.h>
21#include <pj/compat/socket.h>
22#include <pj/assert.h>
23#include <pj/errno.h>
24#include <pj/list.h>
25#include <pj/lock.h>
26#include <pj/log.h>
27#include <pj/math.h>
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +000028#include <pj/os.h>
Nanang Izzuddin006cc012009-10-16 03:06:13 +000029#include <pj/pool.h>
30#include <pj/string.h>
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +000031#include <pj/timer.h>
Nanang Izzuddin006cc012009-10-16 03:06:13 +000032
33
34/* Only build when PJ_HAS_SSL_SOCK is enabled */
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +000035#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK!=0
Nanang Izzuddin006cc012009-10-16 03:06:13 +000036
37#define THIS_FILE "ssl_sock_ossl.c"
38
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +000039/* Workaround for ticket #985 */
40#define DELAYED_CLOSE_TIMEOUT 200
41
Nanang Izzuddin006cc012009-10-16 03:06:13 +000042/*
43 * Include OpenSSL headers
44 */
45#include <openssl/bio.h>
46#include <openssl/ssl.h>
47#include <openssl/err.h>
48
49
50#ifdef _MSC_VER
51# ifdef _DEBUG
52# pragma comment( lib, "libeay32MTd")
53# pragma comment( lib, "ssleay32MTd")
54#else
55# pragma comment( lib, "libeay32MT")
56# pragma comment( lib, "ssleay32MT")
57# endif
58#endif
59
60
61/*
62 * SSL/TLS state enumeration.
63 */
64enum ssl_state {
65 SSL_STATE_NULL,
66 SSL_STATE_HANDSHAKING,
67 SSL_STATE_ESTABLISHED
68};
69
70/*
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +000071 * Internal timer types.
72 */
73enum timer_id
74{
75 TIMER_NONE,
76 TIMER_HANDSHAKE_TIMEOUT,
77 TIMER_CLOSE
78};
79
80/*
Nanang Izzuddin006cc012009-10-16 03:06:13 +000081 * Structure of SSL socket read buffer.
82 */
83typedef struct read_data_t
84{
85 void *data;
86 pj_size_t len;
87} read_data_t;
88
89/*
90 * Get the offset of pointer to read-buffer of SSL socket from read-buffer
91 * of active socket. Note that both SSL socket and active socket employ
92 * different but correlated read-buffers (as much as async_cnt for each),
93 * and to make it easier/faster to find corresponding SSL socket's read-buffer
94 * from known active socket's read-buffer, the pointer of corresponding
95 * SSL socket's read-buffer is stored right after the end of active socket's
96 * read-buffer.
97 */
98#define OFFSET_OF_READ_DATA_PTR(ssock, asock_rbuf) \
99 (read_data_t**) \
100 ((pj_int8_t*)(asock_rbuf) + \
101 ssock->param.read_buffer_size)
102
103/*
104 * Structure of SSL socket write buffer.
105 */
106typedef struct write_data_t {
107 pj_ioqueue_op_key_t key;
108 pj_size_t record_len;
109 pj_ioqueue_op_key_t *app_key;
110 pj_size_t plain_data_len;
111 pj_size_t data_len;
112 union {
113 char content[1];
114 const char *ptr;
115 } data;
116 unsigned flags;
117} write_data_t;
118
119/*
120 * Structure of SSL socket write state.
121 */
122typedef struct write_state_t {
123 char *buf;
124 pj_size_t max_len;
125 char *start;
126 pj_size_t len;
127 write_data_t *last_data;
128} write_state_t;
129
130/*
131 * Structure of write data pending.
132 */
133typedef struct write_pending_t {
134 PJ_DECL_LIST_MEMBER(struct write_pending_t);
135 write_data_t data;
136} write_pending_t;
137
138/*
139 * Secure socket structure definition.
140 */
141struct pj_ssl_sock_t
142{
143 pj_pool_t *pool;
144 pj_ssl_sock_t *parent;
145 pj_ssl_sock_param param;
146 pj_ssl_cert_t *cert;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000147
148 pj_ssl_cert_info local_cert_info;
149 pj_ssl_cert_info remote_cert_info;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000150
151 pj_bool_t is_server;
152 enum ssl_state ssl_state;
153 pj_ioqueue_op_key_t handshake_op_key;
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +0000154 pj_timer_entry timer;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000155
156 pj_sock_t sock;
157 pj_activesock_t *asock;
158
159 pj_sockaddr local_addr;
160 pj_sockaddr rem_addr;
161 int addr_len;
162
163 pj_bool_t read_started;
164 pj_size_t read_size;
165 pj_uint32_t read_flags;
166 void **asock_rbuf;
167 read_data_t *ssock_rbuf;
168
169 write_state_t write_state;
170 write_pending_t write_pending;
171 write_pending_t write_pending_empty;
172 pj_lock_t *write_mutex; /* protect write BIO and write_state */
173
174 SSL_CTX *ossl_ctx;
175 SSL *ossl_ssl;
176 BIO *ossl_rbio;
177 BIO *ossl_wbio;
178};
179
180
181/*
182 * Certificate/credential structure definition.
183 */
184struct pj_ssl_cert_t
185{
186 pj_str_t CA_file;
187 pj_str_t cert_file;
188 pj_str_t privkey_file;
189 pj_str_t privkey_pass;
190};
191
192
193static pj_status_t flush_delayed_send(pj_ssl_sock_t *ssock);
194
195/*
196 *******************************************************************
197 * Static/internal functions.
198 *******************************************************************
199 */
200
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000201/**
202 * Mapping from OpenSSL error codes to pjlib error space.
203 */
204
205#define PJ_SSL_ERRNO_START (PJ_ERRNO_START_USER + \
206 PJ_ERRNO_SPACE_SIZE*6)
207
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000208#define PJ_SSL_ERRNO_SPACE_SIZE PJ_ERRNO_SPACE_SIZE
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000209
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000210#define GET_SSL_STATUS(status) { \
211 unsigned long e = ERR_get_error();\
212 status = ERR_GET_LIB(e)*300 + ERR_GET_REASON(e);\
213 pj_assert(status < PJ_SSL_ERRNO_SPACE_SIZE);\
214 if (status) status += PJ_SSL_ERRNO_START;\
215}
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000216
217/*
218 * Get error string of OpenSSL.
219 */
220static pj_str_t ssl_strerror(pj_status_t status,
221 char *buf, pj_size_t bufsize)
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000222{
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000223 pj_str_t errstr;
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000224 unsigned long ssl_err = status;
225
226 if (ssl_err) {
227 unsigned long l, r;
228 ssl_err -= PJ_SSL_ERRNO_START;
229 l = ssl_err/300;
230 r = ssl_err%300;
231 ssl_err = ERR_PACK(l, 0, r);
232 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000233
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000234#if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0)
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000235
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000236 {
237 const char *tmp = NULL;
238 tmp = ERR_reason_error_string(ssl_err);
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000239
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000240 if (tmp) {
241 pj_ansi_strncpy(buf, tmp, bufsize);
242 errstr = pj_str(buf);
243 return errstr;
244 }
245 }
246
247#endif /* PJ_HAS_ERROR_STRING */
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000248
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000249 errstr.ptr = buf;
250 errstr.slen = pj_ansi_snprintf(buf, bufsize,
Benny Prijono0a411e22009-11-10 07:59:45 +0000251 "Unknown OpenSSL error %lu",
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000252 ssl_err);
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000253
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000254 return errstr;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000255}
256
257
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000258/* OpenSSL library initialization counter */
259static int openssl_init_count;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000260static int openssl_reg_strerr;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000261
262/* OpenSSL available ciphers */
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000263static pj_ssl_cipher openssl_ciphers[100];
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000264static unsigned openssl_cipher_num;
265
266
267/* Initialize OpenSSL */
268static pj_status_t init_openssl(void)
269{
Nanang Izzuddineef9b8d2009-11-06 13:31:37 +0000270 if (openssl_init_count)
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000271 return PJ_SUCCESS;
272
Nanang Izzuddineef9b8d2009-11-06 13:31:37 +0000273 openssl_init_count = 1;
274
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000275 /* Register error subsystem */
276 if (!openssl_reg_strerr) {
277 pj_status_t status;
278
279 openssl_reg_strerr = 1;
280 status = pj_register_strerror(PJ_SSL_ERRNO_START,
281 PJ_SSL_ERRNO_SPACE_SIZE,
282 &ssl_strerror);
283 pj_assert(status == PJ_SUCCESS);
284 }
285
286 /* Init OpenSSL lib */
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000287 SSL_library_init();
288 SSL_load_error_strings();
289 OpenSSL_add_all_algorithms();
290
291 /* Init available ciphers */
292 if (openssl_cipher_num == 0) {
293 SSL_METHOD *meth = NULL;
294 SSL_CTX *ctx;
295 SSL *ssl;
296 STACK_OF(SSL_CIPHER) *sk_cipher;
297 unsigned i, n;
298
299 meth = (SSL_METHOD*)SSLv23_server_method();
300 if (!meth)
301 meth = (SSL_METHOD*)TLSv1_server_method();
302 if (!meth)
303 meth = (SSL_METHOD*)SSLv3_server_method();
304 if (!meth)
305 meth = (SSL_METHOD*)SSLv2_server_method();
306 pj_assert(meth);
307
308 ctx=SSL_CTX_new(meth);
309 SSL_CTX_set_cipher_list(ctx, "ALL");
310
311 ssl = SSL_new(ctx);
312 sk_cipher = SSL_get_ciphers(ssl);
313
314 n = sk_SSL_CIPHER_num(sk_cipher);
315 if (n > PJ_ARRAY_SIZE(openssl_ciphers))
316 n = PJ_ARRAY_SIZE(openssl_ciphers);
317
318 for (i = 0; i < n; ++i) {
319 SSL_CIPHER *c;
320 c = sk_SSL_CIPHER_value(sk_cipher,i);
321 openssl_ciphers[i] = (pj_ssl_cipher)
322 (pj_uint32_t)c->id & 0x00FFFFFF;
323 //printf("%3u: %08x=%s\n", i+1, c->id, SSL_CIPHER_get_name(c));
324 }
325
326 SSL_free(ssl);
327 SSL_CTX_free(ctx);
328
329 openssl_cipher_num = n;
330 }
331
332 return PJ_SUCCESS;
333}
334
335
336/* Shutdown OpenSSL */
337static void shutdown_openssl(void)
338{
Nanang Izzuddineef9b8d2009-11-06 13:31:37 +0000339 PJ_UNUSED_ARG(openssl_init_count);
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000340}
341
342
343/* SSL password callback. */
344static int password_cb(char *buf, int num, int rwflag, void *user_data)
345{
346 pj_ssl_cert_t *cert = (pj_ssl_cert_t*) user_data;
347
348 PJ_UNUSED_ARG(rwflag);
349
350 if(num < cert->privkey_pass.slen)
351 return 0;
352
353 pj_memcpy(buf, cert->privkey_pass.ptr, cert->privkey_pass.slen);
354 return cert->privkey_pass.slen;
355}
356
357
358/* Create and initialize new SSL context */
359static pj_status_t create_ssl_ctx(pj_ssl_sock_t *ssock, SSL_CTX **p_ctx)
360{
361 SSL_METHOD *ssl_method;
362 SSL_CTX *ctx;
363 pj_ssl_cert_t *cert;
364 int mode, rc;
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000365 pj_status_t status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000366
367 pj_assert(ssock && p_ctx);
368
369 cert = ssock->cert;
370
371 /* Make sure OpenSSL library has been initialized */
372 init_openssl();
373
374 /* Determine SSL method to use */
375 switch (ssock->param.proto) {
376 case PJ_SSL_SOCK_PROTO_DEFAULT:
377 case PJ_SSL_SOCK_PROTO_TLS1:
378 ssl_method = (SSL_METHOD*)TLSv1_method();
379 break;
380 case PJ_SSL_SOCK_PROTO_SSL2:
381 ssl_method = (SSL_METHOD*)SSLv2_method();
382 break;
383 case PJ_SSL_SOCK_PROTO_SSL3:
384 ssl_method = (SSL_METHOD*)SSLv3_method();
385 break;
386 case PJ_SSL_SOCK_PROTO_SSL23:
387 ssl_method = (SSL_METHOD*)SSLv23_method();
388 break;
Nanang Izzuddin8d759582009-10-28 03:41:34 +0000389 //case PJ_SSL_SOCK_PROTO_DTLS1:
390 //ssl_method = (SSL_METHOD*)DTLSv1_method();
391 //break;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000392 default:
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000393 return PJ_EINVAL;
394 }
395
396 /* Create SSL context for the listener */
397 ctx = SSL_CTX_new(ssl_method);
398 if (ctx == NULL) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000399 GET_SSL_STATUS(status);
400 return status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000401 }
402
403 /* Apply credentials */
404 if (cert) {
405 /* Load CA list if one is specified. */
406 if (cert->CA_file.slen) {
407
408 rc = SSL_CTX_load_verify_locations(ctx, cert->CA_file.ptr, NULL);
409
410 if (rc != 1) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000411 GET_SSL_STATUS(status);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000412 PJ_LOG(1,(ssock->pool->obj_name, "Error loading CA list file "
413 "'%s'", cert->CA_file.ptr));
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000414 SSL_CTX_free(ctx);
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000415 return status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000416 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000417 }
418
419 /* Set password callback */
420 if (cert->privkey_pass.slen) {
421 SSL_CTX_set_default_passwd_cb(ctx, password_cb);
422 SSL_CTX_set_default_passwd_cb_userdata(ctx, cert);
423 }
424
425
426 /* Load certificate if one is specified */
427 if (cert->cert_file.slen) {
428
429 /* Load certificate chain from file into ctx */
430 rc = SSL_CTX_use_certificate_chain_file(ctx, cert->cert_file.ptr);
431
432 if(rc != 1) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000433 GET_SSL_STATUS(status);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000434 PJ_LOG(1,(ssock->pool->obj_name, "Error loading certificate "
435 "chain file '%s'", cert->cert_file.ptr));
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000436 SSL_CTX_free(ctx);
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000437 return status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000438 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000439 }
440
441
442 /* Load private key if one is specified */
443 if (cert->privkey_file.slen) {
444 /* Adds the first private key found in file to ctx */
445 rc = SSL_CTX_use_PrivateKey_file(ctx, cert->privkey_file.ptr,
446 SSL_FILETYPE_PEM);
447
448 if(rc != 1) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000449 GET_SSL_STATUS(status);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000450 PJ_LOG(1,(ssock->pool->obj_name, "Error adding private key "
451 "from '%s'", cert->privkey_file.ptr));
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000452 SSL_CTX_free(ctx);
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000453 return status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000454 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000455 }
456 }
457
458
459 /* SSL verification options */
460 if (ssock->param.verify_peer) {
461 mode = SSL_VERIFY_PEER;
462 } else {
463 mode = SSL_VERIFY_NONE;
464 }
465
466 if (ssock->is_server && ssock->param.require_client_cert)
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000467 mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_PEER;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000468
469 SSL_CTX_set_verify(ctx, mode, NULL);
470
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000471 *p_ctx = ctx;
472
473 return PJ_SUCCESS;
474}
475
476
477/* Destroy SSL context */
478static void destroy_ssl_ctx(SSL_CTX *ctx)
479{
480 SSL_CTX_free(ctx);
481
482 /* Potentially shutdown OpenSSL library if this is the last
483 * context exists.
484 */
485 shutdown_openssl();
486}
487
488
489/* Reset SSL socket state */
490static void reset_ssl_sock_state(pj_ssl_sock_t *ssock)
491{
492 ssock->ssl_state = SSL_STATE_NULL;
493
494 if (ssock->ossl_ssl) {
495 SSL_shutdown(ssock->ossl_ssl);
496 SSL_free(ssock->ossl_ssl); /* this will also close BIOs */
497 ssock->ossl_ssl = NULL;
498 }
499 if (ssock->ossl_ctx) {
500 destroy_ssl_ctx(ssock->ossl_ctx);
501 ssock->ossl_ctx = NULL;
502 }
503 if (ssock->asock) {
504 pj_activesock_close(ssock->asock);
505 ssock->asock = NULL;
506 ssock->sock = PJ_INVALID_SOCKET;
507 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000508 if (ssock->sock != PJ_INVALID_SOCKET) {
509 pj_sock_close(ssock->sock);
510 ssock->sock = PJ_INVALID_SOCKET;
511 }
Nanang Izzuddin6cfc6d52009-10-27 02:21:28 +0000512
513 /* Upon error, OpenSSL may leave any error description in the thread
514 * error queue, which sometime may cause next call to SSL API returning
515 * false error alarm, e.g: in Linux, SSL_CTX_use_certificate_chain_file()
516 * returning false error after a handshake error (in different SSL_CTX!).
517 * For now, just clear thread error queue here.
518 */
519 ERR_clear_error();
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000520}
521
522
523/* Generate cipher list with user preference order in OpenSSL format */
524static pj_status_t set_cipher_list(pj_ssl_sock_t *ssock)
525{
526 char buf[1024];
527 pj_str_t cipher_list;
528 STACK_OF(SSL_CIPHER) *sk_cipher;
529 unsigned i;
530 int j, ret;
531
532 if (ssock->param.ciphers_num == 0)
533 return PJ_SUCCESS;
534
535 pj_strset(&cipher_list, buf, 0);
536
537 /* Set SSL with ALL available ciphers */
538 SSL_set_cipher_list(ssock->ossl_ssl, "ALL");
539
540 /* Generate user specified cipher list in OpenSSL format */
541 sk_cipher = SSL_get_ciphers(ssock->ossl_ssl);
542 for (i = 0; i < ssock->param.ciphers_num; ++i) {
543 for (j = 0; j < sk_SSL_CIPHER_num(sk_cipher); ++j) {
544 SSL_CIPHER *c;
545 c = sk_SSL_CIPHER_value(sk_cipher, j);
546 if (ssock->param.ciphers[i] == (pj_ssl_cipher)
547 ((pj_uint32_t)c->id & 0x00FFFFFF))
548 {
549 const char *c_name;
550
551 c_name = SSL_CIPHER_get_name(c);
552
553 /* Check buffer size */
554 if (cipher_list.slen + pj_ansi_strlen(c_name) + 2 > sizeof(buf)) {
555 pj_assert(!"Insufficient temporary buffer for cipher");
556 return PJ_ETOOMANY;
557 }
558
559 /* Add colon separator */
560 if (cipher_list.slen)
561 pj_strcat2(&cipher_list, ":");
562
563 /* Add the cipher */
564 pj_strcat2(&cipher_list, c_name);
565 break;
566 }
567 }
568 }
569
570 /* Put NULL termination in the generated cipher list */
571 cipher_list.ptr[cipher_list.slen] = '\0';
572
573 /* Finally, set chosen cipher list */
574 ret = SSL_set_cipher_list(ssock->ossl_ssl, buf);
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000575 if (ret < 1) {
576 pj_status_t status;
577 GET_SSL_STATUS(status);
578 return status;
579 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000580
581 return PJ_SUCCESS;
582}
583
584
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000585/* Parse OpenSSL ASN1_TIME to pj_time_val and GMT info */
586static pj_bool_t parse_ossl_asn1_time(pj_time_val *tv, pj_bool_t *gmt,
587 const ASN1_TIME *tm)
588{
589 unsigned long parts[7] = {0};
590 char *p, *end;
591 unsigned len;
592 pj_bool_t utc;
593 pj_parsed_time pt;
594 int i;
595
596 utc = tm->type == V_ASN1_UTCTIME;
597 p = (char*)tm->data;
598 len = tm->length;
599 end = p + len - 1;
600
601 /* GMT */
602 *gmt = (*end == 'Z');
603
604 /* parse parts */
605 for (i = 0; i < 7 && p < end; ++i) {
606 pj_str_t st;
607
608 if (i==0 && !utc) {
609 /* 4 digits year part for non-UTC time format */
610 st.slen = 4;
611 } else if (i==6) {
612 /* fraction of seconds */
613 if (*p == '.') ++p;
614 st.slen = end - p + 1;
615 } else {
616 /* other parts always 2 digits length */
617 st.slen = 2;
618 }
619 st.ptr = p;
620
621 parts[i] = pj_strtoul(&st);
622 p += st.slen;
623 }
624
625 /* encode parts to pj_time_val */
626 pt.year = parts[0];
627 if (utc)
628 pt.year += (pt.year < 50)? 2000:1900;
629 pt.mon = parts[1] - 1;
630 pt.day = parts[2];
631 pt.hour = parts[3];
632 pt.min = parts[4];
633 pt.sec = parts[5];
634 pt.msec = parts[6];
635
636 pj_time_encode(&pt, tv);
637
638 return PJ_TRUE;
639}
640
641
642/* Get certificate info from OpenSSL X509 */
643static void get_cert_info(pj_pool_t *pool, pj_ssl_cert_info *ci, X509 *x)
644{
645 pj_ssl_cert_info info;
646 char buf1[256];
647 char buf2[256];
648
649 pj_assert(pool && ci);
650
651 if (!x) {
652 pj_bzero(ci, sizeof(pj_ssl_cert_info));
653 return;
654 }
655
656 pj_bzero(&info, sizeof(info));
657
658 /* Populate cert info */
659 info.subject = pj_str(X509_NAME_oneline(X509_get_subject_name(x),buf1,
660 sizeof(buf1)));
661 info.issuer = pj_str(X509_NAME_oneline(X509_get_issuer_name(x), buf2,
662 sizeof(buf2)));
663 info.version = X509_get_version(x) + 1;
664 parse_ossl_asn1_time(&info.validity_start, &info.validity_use_gmt,
665 X509_get_notBefore(x));
666 parse_ossl_asn1_time(&info.validity_end, &info.validity_use_gmt,
667 X509_get_notAfter(x));
668
669 /* Update certificate info */
670 if (pj_strcmp(&ci->subject, &info.subject))
671 pj_strdup(pool, &ci->subject, &info.subject);
672 if (pj_strcmp(&ci->issuer, &info.issuer))
673 pj_strdup(pool, &ci->issuer, &info.issuer);
674 ci->version = info.version;
675 ci->validity_start = info.validity_start;
676 ci->validity_end = info.validity_end;
677 ci->validity_use_gmt = info.validity_use_gmt;
678}
679
680
681/* Update local & remote certificates info. This function should be
682 * called after handshake or renegotiation successfully completed.
683 */
684static void update_certs_info(pj_ssl_sock_t *ssock)
685{
686 X509 *x;
687
688 pj_assert(ssock->ssl_state == SSL_STATE_ESTABLISHED);
689
690 /* Active local certificate */
691 x = SSL_get_certificate(ssock->ossl_ssl);
692 get_cert_info(ssock->pool, &ssock->local_cert_info, x);
693 /* Don't free local's X509! */
694
695 /* Active remote certificate */
696 x = SSL_get_peer_certificate(ssock->ossl_ssl);
697 get_cert_info(ssock->pool, &ssock->remote_cert_info, x);
698 /* Free peer's X509 */
699 X509_free(x);
700}
701
702
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000703/* When handshake completed:
704 * - notify application
705 * - if handshake failed, reset SSL state
706 * - return PJ_FALSE when SSL socket instance is destroyed by application.
707 */
708static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock,
709 pj_status_t status)
710{
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000711 /* Cancel handshake timer */
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +0000712 if (ssock->timer.id == TIMER_HANDSHAKE_TIMEOUT) {
713 pj_timer_heap_cancel(ssock->param.timer_heap, &ssock->timer);
714 ssock->timer.id = TIMER_NONE;
715 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000716
717 /* Update certificates info on successful handshake */
718 if (status == PJ_SUCCESS)
719 update_certs_info(ssock);
720
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000721 /* Accepting */
722 if (ssock->is_server) {
723 if (status != PJ_SUCCESS) {
724 /* Handshake failed in accepting, destroy our self silently. */
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000725
726 char errmsg[PJ_ERR_MSG_SIZE];
727 char buf[PJ_INET6_ADDRSTRLEN+10];
728
729 pj_strerror(status, errmsg, sizeof(errmsg));
730 PJ_LOG(3,(ssock->pool->obj_name, "Handshake failed in accepting "
731 "%s: %s",
732 pj_sockaddr_print(&ssock->rem_addr, buf, sizeof(buf), 3),
733 errmsg));
734
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +0000735 /* Workaround for ticket #985 */
736#if defined(PJ_WIN32) && PJ_WIN32!=0
737 if (ssock->param.timer_heap) {
738 pj_time_val interval = {0, DELAYED_CLOSE_TIMEOUT};
739
740 reset_ssl_sock_state(ssock);
741
742 ssock->timer.id = TIMER_CLOSE;
743 pj_time_val_normalize(&interval);
744 if (pj_timer_heap_schedule(ssock->param.timer_heap,
745 &ssock->timer, &interval) != 0)
746 {
747 ssock->timer.id = TIMER_NONE;
748 pj_ssl_sock_close(ssock);
749 }
750 } else
751#endif /* PJ_WIN32 */
752 {
753 pj_ssl_sock_close(ssock);
754 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000755 return PJ_FALSE;
756 }
757 /* Notify application the newly accepted SSL socket */
758 if (ssock->param.cb.on_accept_complete) {
759 pj_bool_t ret;
760 ret = (*ssock->param.cb.on_accept_complete)
761 (ssock->parent, ssock, (pj_sockaddr_t*)&ssock->rem_addr,
762 pj_sockaddr_get_len((pj_sockaddr_t*)&ssock->rem_addr));
763 if (ret == PJ_FALSE)
764 return PJ_FALSE;
765 }
766 }
767
768 /* Connecting */
769 else {
Nanang Izzuddin48747632009-11-20 07:48:41 +0000770 /* On failure, reset SSL socket state first, as app may try to
771 * reconnect in the callback.
772 */
773 if (status != PJ_SUCCESS) {
774 reset_ssl_sock_state(ssock);
775 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000776 if (ssock->param.cb.on_connect_complete) {
777 pj_bool_t ret;
778 ret = (*ssock->param.cb.on_connect_complete)(ssock, status);
779 if (ret == PJ_FALSE)
780 return PJ_FALSE;
781 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000782 }
783
784 return PJ_TRUE;
785}
786
787/* Flush write BIO to network socket. Note that any access to write BIO
788 * MUST be serialized, so mutex protection must cover any call to OpenSSL
789 * API (that possibly generate data for write BIO) along with the call to
790 * this function (flushing all data in write BIO generated by above
791 * OpenSSL API call).
792 */
793static pj_status_t flush_write_bio(pj_ssl_sock_t *ssock,
794 pj_ioqueue_op_key_t *send_key,
795 pj_size_t orig_len,
796 unsigned flags)
797{
798 char *data;
799 pj_ssize_t len;
800
801 write_state_t *write_st = &ssock->write_state;
802 write_data_t *wdata;
803 pj_size_t avail_len, needed_len, skipped_len = 0;
804 pj_status_t status;
805
806 /* Check if there is data in write BIO, flush it if any */
807 if (!BIO_pending(ssock->ossl_wbio))
808 return PJ_SUCCESS;
809
810 /* Get data and its length */
811 len = BIO_get_mem_data(ssock->ossl_wbio, &data);
812 if (len == 0)
813 return PJ_SUCCESS;
814
815 /* Calculate buffer size needed, and align it to 8 */
816 needed_len = len + sizeof(write_data_t);
817 needed_len = ((needed_len + 7) >> 3) << 3;
818
819 /* Check buffer availability */
820 avail_len = write_st->max_len - write_st->len;
821 if (avail_len < needed_len)
822 return PJ_ENOMEM;
823
824 /* More buffer availability check, note that the write data must be in
825 * a contigue buffer.
826 */
827 if (write_st->len == 0) {
828
829 write_st->start = write_st->buf;
830 wdata = (write_data_t*)write_st->start;
831
832 } else {
833
834 char *reg1, *reg2;
835 pj_size_t reg1_len, reg2_len;
836
837 /* Unused slots may be wrapped/splitted into two regions, so let's
838 * analyze them if any region can hold the write data.
839 */
840 reg1 = write_st->start + write_st->len;
841 if (reg1 >= write_st->buf + write_st->max_len)
842 reg1 -= write_st->max_len;
843 reg1_len = write_st->max_len - write_st->len;
844 if (reg1 + reg1_len > write_st->buf + write_st->max_len) {
845 reg1_len = write_st->buf + write_st->max_len - reg1;
846 reg2 = write_st->buf;
847 reg2_len = write_st->start - write_st->buf;
848 } else {
849 reg2 = NULL;
850 reg2_len = 0;
851 }
852 avail_len = PJ_MAX(reg1_len, reg2_len);
853 if (avail_len < needed_len)
854 return PJ_ENOMEM;
855
856 /* Get write data pointer and update buffer length */
857 if (reg1_len >= needed_len) {
858 wdata = (write_data_t*)reg1;
859 } else {
860 wdata = (write_data_t*)reg2;
861 /* Unused slot in region 1 is skipped as current write data
862 * doesn't fit it.
863 */
864 skipped_len = reg1_len;
865 }
866 }
867
868 /* Copy the data and set its properties into the buffer */
869 pj_bzero(wdata, sizeof(write_data_t));
870 wdata->app_key = send_key;
871 wdata->record_len = needed_len;
872 wdata->data_len = len;
873 wdata->plain_data_len = orig_len;
874 wdata->flags = flags;
875 pj_memcpy(&wdata->data, data, len);
876
877 /* Send it */
878 if (ssock->param.sock_type == pj_SOCK_STREAM()) {
879 status = pj_activesock_send(ssock->asock, &wdata->key,
880 wdata->data.content, &len,
881 flags);
882 } else {
883 status = pj_activesock_sendto(ssock->asock, &wdata->key,
884 wdata->data.content, &len,
885 flags,
886 (pj_sockaddr_t*)&ssock->rem_addr,
887 ssock->addr_len);
888 }
889
890 /* Oh no, EWOULDBLOCK! */
891 if (status == PJ_STATUS_FROM_OS(OSERR_EWOULDBLOCK)) {
892 /* Just return PJ_SUCCESS here, the pending data will be sent in next
893 * call of this function since the data is still stored in write BIO.
894 */
895 return PJ_SUCCESS;
896 }
897
898 /* Reset write BIO after flushed */
899 BIO_reset(ssock->ossl_wbio);
900
901 if (status == PJ_EPENDING) {
902 /* Update write state */
903 pj_assert(skipped_len==0 || write_st->last_data);
904 write_st->len += needed_len + skipped_len;
905 if (write_st->last_data)
906 write_st->last_data->record_len += skipped_len;
907 write_st->last_data = wdata;
908 }
909
910 return status;
911}
912
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000913
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +0000914static void on_timer(pj_timer_heap_t *th, struct pj_timer_entry *te)
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000915{
916 pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)te->user_data;
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +0000917 int timer_id = te->id;
918
919 te->id = TIMER_NONE;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000920
921 PJ_UNUSED_ARG(th);
922
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +0000923 switch (timer_id) {
924 case TIMER_HANDSHAKE_TIMEOUT:
925 PJ_LOG(1,(ssock->pool->obj_name, "SSL handshake timeout after %d.%ds",
926 ssock->param.timeout.sec, ssock->param.timeout.msec));
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000927
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +0000928 on_handshake_complete(ssock, PJ_ETIMEDOUT);
929 break;
930 case TIMER_CLOSE:
931 pj_ssl_sock_close(ssock);
932 break;
933 default:
934 pj_assert(!"Unknown timer");
935 break;
936 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000937}
938
939
940/* Asynchronouse handshake */
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000941static pj_status_t do_handshake(pj_ssl_sock_t *ssock)
942{
943 pj_status_t status;
944 int err;
945
946 pj_lock_acquire(ssock->write_mutex);
947
948 /* Perform SSL handshake */
949 err = SSL_do_handshake(ssock->ossl_ssl);
950 if (err < 0) {
951 err = SSL_get_error(ssock->ossl_ssl, err);
952 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ)
953 {
954 /* Handshake fails */
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000955 GET_SSL_STATUS(status);
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000956 pj_lock_release(ssock->write_mutex);
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000957 return status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000958 }
959 }
960
961 /* SSL_do_handshake() may put some pending data into SSL write BIO,
962 * flush it if any.
963 */
964 status = flush_write_bio(ssock, &ssock->handshake_op_key, 0, 0);
965 if (status != PJ_SUCCESS && status != PJ_EPENDING) {
966 pj_lock_release(ssock->write_mutex);
967 return status;
968 }
969
970 pj_lock_release(ssock->write_mutex);
971
972 /* Check if handshake has been completed */
973 if (SSL_is_init_finished(ssock->ossl_ssl)) {
974 ssock->ssl_state = SSL_STATE_ESTABLISHED;
975 return PJ_SUCCESS;
976 }
977
978 return PJ_EPENDING;
979}
980
981
982/*
983 *******************************************************************
984 * Active socket callbacks.
985 *******************************************************************
986 */
987
988static pj_bool_t asock_on_data_read (pj_activesock_t *asock,
989 void *data,
990 pj_size_t size,
991 pj_status_t status,
992 pj_size_t *remainder)
993{
994 pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
995 pj_activesock_get_user_data(asock);
996 pj_size_t nwritten;
997
998 /* Socket error or closed */
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000999 if (data && size > 0) {
1000 /* Consume the whole data */
1001 nwritten = BIO_write(ssock->ossl_rbio, data, size);
1002 if (nwritten < size) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00001003 GET_SSL_STATUS(status);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001004 goto on_error;
1005 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001006 }
1007
1008 /* Check if SSL handshake hasn't finished yet */
1009 if (ssock->ssl_state == SSL_STATE_HANDSHAKING) {
1010 pj_bool_t ret = PJ_TRUE;
1011
1012 if (status == PJ_SUCCESS)
1013 status = do_handshake(ssock);
1014
1015 /* Not pending is either success or failed */
1016 if (status != PJ_EPENDING)
1017 ret = on_handshake_complete(ssock, status);
1018
1019 return ret;
1020 }
1021
1022 /* See if there is any decrypted data for the application */
1023 if (ssock->read_started) {
1024 do {
1025 read_data_t *buf = *(OFFSET_OF_READ_DATA_PTR(ssock, data));
1026 void *data_ = (pj_int8_t*)buf->data + buf->len;
1027 int size_ = ssock->read_size - buf->len;
1028
1029 /* SSL_read() may write some data to BIO write when re-negotiation
1030 * is on progress, so let's protect it with write mutex.
1031 */
1032 pj_lock_acquire(ssock->write_mutex);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001033 size_ = SSL_read(ssock->ossl_ssl, data_, size_);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001034 pj_lock_release(ssock->write_mutex);
1035
1036 if (size_ > 0 || status != PJ_SUCCESS) {
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001037 if (ssock->param.cb.on_data_read) {
1038 pj_bool_t ret;
1039 pj_size_t remainder_ = 0;
1040
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001041 if (size_ > 0)
1042 buf->len += size_;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001043
1044 ret = (*ssock->param.cb.on_data_read)(ssock, buf->data,
1045 buf->len, status,
1046 &remainder_);
1047 if (!ret) {
1048 /* We've been destroyed */
1049 return PJ_FALSE;
1050 }
1051
1052 /* Application may have left some data to be consumed
1053 * later.
1054 */
1055 buf->len = remainder_;
1056 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001057
1058 /* Active socket signalled connection closed/error, this has
1059 * been signalled to the application along with any remaining
1060 * buffer. So, let's just reset SSL socket now.
1061 */
1062 if (status != PJ_SUCCESS) {
1063 reset_ssl_sock_state(ssock);
1064 return PJ_FALSE;
1065 }
1066
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001067 } else {
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001068
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001069 int err = SSL_get_error(ssock->ossl_ssl, size);
1070
1071 /* SSL might just return SSL_ERROR_WANT_READ in
1072 * re-negotiation.
1073 */
1074 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ)
1075 {
1076 /* Reset SSL socket state, then return PJ_FALSE */
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00001077 GET_SSL_STATUS(status);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001078 reset_ssl_sock_state(ssock);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001079 goto on_error;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001080 }
1081
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001082 status = do_handshake(ssock);
1083 if (status == PJ_SUCCESS) {
1084 /* Renegotiation completed */
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001085
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001086 /* Update certificates */
1087 update_certs_info(ssock);
1088
1089 pj_lock_acquire(ssock->write_mutex);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001090 status = flush_delayed_send(ssock);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001091 pj_lock_release(ssock->write_mutex);
1092
1093 if (status != PJ_SUCCESS && status != PJ_EPENDING) {
Benny Prijono7ee05332009-11-09 04:34:50 +00001094 PJ_PERROR(1,(ssock->pool->obj_name, status,
1095 "Failed to flush delayed send"));
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001096 goto on_error;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001097 }
1098 } else if (status != PJ_EPENDING) {
Benny Prijono7ee05332009-11-09 04:34:50 +00001099 PJ_PERROR(1,(ssock->pool->obj_name, status,
1100 "Renegotiation failed"));
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001101 goto on_error;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001102 }
1103
1104 break;
1105 }
1106 } while (1);
1107 }
1108
1109 return PJ_TRUE;
1110
1111on_error:
1112 if (ssock->ssl_state == SSL_STATE_HANDSHAKING)
1113 return on_handshake_complete(ssock, status);
1114
1115 if (ssock->read_started && ssock->param.cb.on_data_read) {
1116 pj_bool_t ret;
1117 ret = (*ssock->param.cb.on_data_read)(ssock, NULL, 0, status,
1118 remainder);
1119 if (!ret) {
1120 /* We've been destroyed */
1121 return PJ_FALSE;
1122 }
1123 }
1124
1125 reset_ssl_sock_state(ssock);
1126 return PJ_FALSE;
1127}
1128
1129
1130static pj_bool_t asock_on_data_sent (pj_activesock_t *asock,
1131 pj_ioqueue_op_key_t *send_key,
1132 pj_ssize_t sent)
1133{
1134 pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
1135 pj_activesock_get_user_data(asock);
1136
1137 PJ_UNUSED_ARG(send_key);
1138 PJ_UNUSED_ARG(sent);
1139
1140 if (ssock->ssl_state == SSL_STATE_HANDSHAKING) {
1141 /* Initial handshaking */
1142 pj_status_t status;
1143
1144 status = do_handshake(ssock);
1145 /* Not pending is either success or failed */
1146 if (status != PJ_EPENDING)
1147 return on_handshake_complete(ssock, status);
1148
1149 } else if (send_key != &ssock->handshake_op_key) {
1150 /* Some data has been sent, notify application */
1151 write_data_t *wdata = (write_data_t*)send_key;
1152 if (ssock->param.cb.on_data_sent) {
1153 pj_bool_t ret;
1154 ret = (*ssock->param.cb.on_data_sent)(ssock, wdata->app_key,
1155 wdata->plain_data_len);
1156 if (!ret) {
1157 /* We've been destroyed */
1158 return PJ_FALSE;
1159 }
1160 }
1161
1162 /* Update write buffer state */
1163 pj_lock_acquire(ssock->write_mutex);
1164 ssock->write_state.start += wdata->record_len;
1165 ssock->write_state.len -= wdata->record_len;
1166 if (ssock->write_state.last_data == wdata) {
1167 pj_assert(ssock->write_state.len == 0);
1168 ssock->write_state.last_data = NULL;
1169 }
1170 pj_lock_release(ssock->write_mutex);
1171
1172 } else {
1173 /* SSL re-negotiation is on-progress, just do nothing */
1174 }
1175
1176 return PJ_TRUE;
1177}
1178
1179
1180static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
1181 pj_sock_t newsock,
1182 const pj_sockaddr_t *src_addr,
1183 int src_addr_len)
1184{
1185 pj_ssl_sock_t *ssock_parent = (pj_ssl_sock_t*)
1186 pj_activesock_get_user_data(asock);
1187 pj_ssl_sock_t *ssock;
1188 pj_activesock_cb asock_cb;
1189 pj_activesock_cfg asock_cfg;
1190 unsigned i;
1191 pj_status_t status;
1192
1193 PJ_UNUSED_ARG(src_addr_len);
1194
1195 /* Create new SSL socket instance */
1196 status = pj_ssl_sock_create(ssock_parent->pool, &ssock_parent->param,
1197 &ssock);
1198 if (status != PJ_SUCCESS)
1199 goto on_return;
1200
1201 /* Update new SSL socket attributes */
1202 ssock->sock = newsock;
1203 ssock->parent = ssock_parent;
1204 ssock->is_server = PJ_TRUE;
1205 if (ssock_parent->cert) {
1206 status = pj_ssl_sock_set_certificate(ssock, ssock->pool,
1207 ssock_parent->cert);
1208 if (status != PJ_SUCCESS)
1209 goto on_return;
1210 }
1211
Benny Prijonoa25bc9d2009-11-09 08:51:34 +00001212 /* Apply QoS, if specified */
1213 status = pj_sock_apply_qos2(ssock->sock, ssock->param.qos_type,
1214 &ssock->param.qos_params, 1,
1215 ssock->pool->obj_name, NULL);
1216 if (status != PJ_SUCCESS && !ssock->param.qos_ignore_error)
1217 goto on_return;
1218
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001219 /* Update local address */
1220 ssock->addr_len = src_addr_len;
1221 status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,
1222 &ssock->addr_len);
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00001223 if (status != PJ_SUCCESS) {
1224 /* This fails on few envs, e.g: win IOCP, just tolerate this and
1225 * use parent local address instead.
1226 */
1227 pj_sockaddr_cp(&ssock->local_addr, &ssock_parent->local_addr);
1228 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001229
1230 /* Set remote address */
1231 pj_sockaddr_cp(&ssock->rem_addr, src_addr);
1232
1233 /* Create SSL context */
1234 status = create_ssl_ctx(ssock, &ssock->ossl_ctx);
1235 if (status != PJ_SUCCESS)
1236 goto on_return;
1237
1238 /* Create SSL instance */
1239 ssock->ossl_ssl = SSL_new(ssock->ossl_ctx);
1240 if (ssock->ossl_ssl == NULL) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00001241 GET_SSL_STATUS(status);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001242 goto on_return;
1243 }
1244
1245 /* Set cipher list */
1246 status = set_cipher_list(ssock);
1247 if (status != PJ_SUCCESS)
1248 goto on_return;
1249
1250 /* Setup SSL BIOs */
1251 ssock->ossl_rbio = BIO_new(BIO_s_mem());
1252 ssock->ossl_wbio = BIO_new(BIO_s_mem());
1253 BIO_set_close(ssock->ossl_rbio, BIO_CLOSE);
1254 BIO_set_close(ssock->ossl_wbio, BIO_CLOSE);
1255 SSL_set_bio(ssock->ossl_ssl, ssock->ossl_rbio, ssock->ossl_wbio);
1256
1257 /* Prepare read buffer */
1258 ssock->asock_rbuf = (void**)pj_pool_calloc(ssock->pool,
1259 ssock->param.async_cnt,
1260 sizeof(void*));
1261 for (i = 0; i<ssock->param.async_cnt; ++i) {
1262 ssock->asock_rbuf[i] = (void*) pj_pool_alloc(
1263 ssock->pool,
1264 ssock->param.read_buffer_size +
1265 sizeof(read_data_t*));
1266 }
1267
1268 /* Create active socket */
1269 pj_activesock_cfg_default(&asock_cfg);
1270 asock_cfg.async_cnt = ssock->param.async_cnt;
1271 asock_cfg.concurrency = ssock->param.concurrency;
1272 asock_cfg.whole_data = PJ_TRUE;
1273
1274 pj_bzero(&asock_cb, sizeof(asock_cb));
1275 asock_cb.on_data_read = asock_on_data_read;
1276 asock_cb.on_data_sent = asock_on_data_sent;
1277
1278 status = pj_activesock_create(ssock->pool,
1279 ssock->sock,
1280 ssock->param.sock_type,
1281 &asock_cfg,
1282 ssock->param.ioqueue,
1283 &asock_cb,
1284 ssock,
1285 &ssock->asock);
1286
1287 if (status != PJ_SUCCESS)
1288 goto on_return;
1289
1290 /* Start read */
1291 status = pj_activesock_start_read2(ssock->asock, ssock->pool,
1292 ssock->param.read_buffer_size,
1293 ssock->asock_rbuf,
1294 PJ_IOQUEUE_ALWAYS_ASYNC);
1295 if (status != PJ_SUCCESS)
1296 goto on_return;
1297
1298 /* Prepare write/send state */
1299 pj_assert(ssock->write_state.max_len == 0);
1300 ssock->write_state.buf = (char*)
1301 pj_pool_alloc(ssock->pool,
1302 ssock->param.send_buffer_size);
1303 ssock->write_state.max_len = ssock->param.send_buffer_size;
1304 ssock->write_state.start = ssock->write_state.buf;
1305 ssock->write_state.len = 0;
1306
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001307 /* Start handshake timer */
1308 if (ssock->param.timer_heap && (ssock->param.timeout.sec != 0 ||
1309 ssock->param.timeout.msec != 0))
1310 {
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001311 pj_assert(ssock->timer.id == TIMER_NONE);
1312 ssock->timer.id = TIMER_HANDSHAKE_TIMEOUT;
1313 status = pj_timer_heap_schedule(ssock->param.timer_heap,
1314 &ssock->timer,
1315 &ssock->param.timeout);
1316 if (status != PJ_SUCCESS)
1317 ssock->timer.id = TIMER_NONE;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001318 }
1319
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001320 /* Start SSL handshake */
1321 ssock->ssl_state = SSL_STATE_HANDSHAKING;
1322 SSL_set_accept_state(ssock->ossl_ssl);
1323 status = do_handshake(ssock);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001324
1325on_return:
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00001326 if (ssock && status != PJ_EPENDING)
1327 on_handshake_complete(ssock, status);
1328
1329 /* Must return PJ_TRUE whatever happened, as active socket must
1330 * continue listening.
1331 */
1332 return PJ_TRUE;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001333}
1334
1335
1336static pj_bool_t asock_on_connect_complete (pj_activesock_t *asock,
1337 pj_status_t status)
1338{
1339 pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
1340 pj_activesock_get_user_data(asock);
1341 unsigned i;
1342
1343 if (status != PJ_SUCCESS)
1344 goto on_return;
1345
1346 /* Update local address */
1347 ssock->addr_len = sizeof(pj_sockaddr);
1348 status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,
1349 &ssock->addr_len);
1350 if (status != PJ_SUCCESS)
1351 goto on_return;
1352
1353 /* Create SSL context */
1354 status = create_ssl_ctx(ssock, &ssock->ossl_ctx);
1355 if (status != PJ_SUCCESS)
1356 goto on_return;
1357
1358 /* Create SSL instance */
1359 ssock->ossl_ssl = SSL_new(ssock->ossl_ctx);
1360 if (ssock->ossl_ssl == NULL) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00001361 GET_SSL_STATUS(status);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001362 goto on_return;
1363 }
1364
1365 /* Set cipher list */
1366 status = set_cipher_list(ssock);
1367 if (status != PJ_SUCCESS)
1368 goto on_return;
1369
1370 /* Setup SSL BIOs */
1371 ssock->ossl_rbio = BIO_new(BIO_s_mem());
1372 ssock->ossl_wbio = BIO_new(BIO_s_mem());
1373 BIO_set_close(ssock->ossl_rbio, BIO_CLOSE);
1374 BIO_set_close(ssock->ossl_wbio, BIO_CLOSE);
1375 SSL_set_bio(ssock->ossl_ssl, ssock->ossl_rbio, ssock->ossl_wbio);
1376
1377 /* Prepare read buffer */
1378 ssock->asock_rbuf = (void**)pj_pool_calloc(ssock->pool,
1379 ssock->param.async_cnt,
1380 sizeof(void*));
1381 for (i = 0; i<ssock->param.async_cnt; ++i) {
1382 ssock->asock_rbuf[i] = (void*) pj_pool_alloc(
1383 ssock->pool,
1384 ssock->param.read_buffer_size +
1385 sizeof(read_data_t*));
1386 }
1387
1388 /* Start read */
1389 status = pj_activesock_start_read2(ssock->asock, ssock->pool,
1390 ssock->param.read_buffer_size,
1391 ssock->asock_rbuf,
1392 PJ_IOQUEUE_ALWAYS_ASYNC);
1393 if (status != PJ_SUCCESS)
1394 goto on_return;
1395
1396 /* Prepare write/send state */
1397 pj_assert(ssock->write_state.max_len == 0);
1398 ssock->write_state.buf = (char*)
1399 pj_pool_alloc(ssock->pool,
1400 ssock->param.send_buffer_size);
1401 ssock->write_state.max_len = ssock->param.send_buffer_size;
1402 ssock->write_state.start = ssock->write_state.buf;
1403 ssock->write_state.len = 0;
1404
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001405 /* Start handshake timer */
1406 if (ssock->param.timer_heap && (ssock->param.timeout.sec != 0 ||
1407 ssock->param.timeout.msec != 0))
1408 {
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001409 pj_assert(ssock->timer.id == TIMER_NONE);
1410 ssock->timer.id = TIMER_HANDSHAKE_TIMEOUT;
1411 status = pj_timer_heap_schedule(ssock->param.timer_heap,
1412 &ssock->timer,
1413 &ssock->param.timeout);
1414 if (status != PJ_SUCCESS)
1415 ssock->timer.id = TIMER_NONE;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001416 }
1417
1418#ifdef SSL_set_tlsext_host_name
1419 /* Set server name to connect */
1420 if (ssock->param.server_name.slen) {
1421 /* Server name is null terminated already */
1422 if (!SSL_set_tlsext_host_name(ssock->ossl_ssl,
1423 ssock->param.server_name.ptr))
1424 {
1425 char err_str[PJ_ERR_MSG_SIZE];
1426
1427 ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
1428 PJ_LOG(3,(ssock->pool->obj_name, "SSL_set_tlsext_host_name() "
1429 "failed: %s", err_str));
1430 }
1431 }
1432#endif
1433
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001434 /* Start SSL handshake */
1435 ssock->ssl_state = SSL_STATE_HANDSHAKING;
1436 SSL_set_connect_state(ssock->ossl_ssl);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001437
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001438 status = do_handshake(ssock);
1439 if (status != PJ_EPENDING)
1440 goto on_return;
1441
1442 return PJ_TRUE;
1443
1444on_return:
1445 return on_handshake_complete(ssock, status);
1446}
1447
1448
1449
1450/*
1451 *******************************************************************
1452 * API
1453 *******************************************************************
1454 */
1455
1456/* Load credentials from files. */
1457PJ_DEF(pj_status_t) pj_ssl_cert_load_from_files (pj_pool_t *pool,
1458 const pj_str_t *CA_file,
1459 const pj_str_t *cert_file,
1460 const pj_str_t *privkey_file,
1461 const pj_str_t *privkey_pass,
1462 pj_ssl_cert_t **p_cert)
1463{
1464 pj_ssl_cert_t *cert;
1465
1466 PJ_ASSERT_RETURN(pool && CA_file && cert_file && privkey_file, PJ_EINVAL);
1467
1468 cert = PJ_POOL_ZALLOC_T(pool, pj_ssl_cert_t);
1469 pj_strdup_with_null(pool, &cert->CA_file, CA_file);
1470 pj_strdup_with_null(pool, &cert->cert_file, cert_file);
1471 pj_strdup_with_null(pool, &cert->privkey_file, privkey_file);
1472 pj_strdup_with_null(pool, &cert->privkey_pass, privkey_pass);
1473
1474 *p_cert = cert;
1475
1476 return PJ_SUCCESS;
1477}
1478
1479
1480/* Set SSL socket credentials. */
1481PJ_DECL(pj_status_t) pj_ssl_sock_set_certificate(
1482 pj_ssl_sock_t *ssock,
1483 pj_pool_t *pool,
1484 const pj_ssl_cert_t *cert)
1485{
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001486 pj_ssl_cert_t *cert_;
1487
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001488 PJ_ASSERT_RETURN(ssock && pool && cert, PJ_EINVAL);
1489
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001490 cert_ = PJ_POOL_ZALLOC_T(pool, pj_ssl_cert_t);
1491 pj_memcpy(cert_, cert, sizeof(cert));
1492 pj_strdup_with_null(pool, &cert_->CA_file, &cert->CA_file);
1493 pj_strdup_with_null(pool, &cert_->cert_file, &cert->cert_file);
1494 pj_strdup_with_null(pool, &cert_->privkey_file, &cert->privkey_file);
1495 pj_strdup_with_null(pool, &cert_->privkey_pass, &cert->privkey_pass);
1496
1497 ssock->cert = cert_;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001498
1499 return PJ_SUCCESS;
1500}
1501
1502
1503/* Get available ciphers. */
1504PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables(pj_ssl_cipher ciphers[],
1505 unsigned *cipher_num)
1506{
1507 unsigned i;
1508
1509 PJ_ASSERT_RETURN(ciphers && cipher_num, PJ_EINVAL);
1510
1511 if (openssl_cipher_num == 0) {
1512 init_openssl();
1513 shutdown_openssl();
1514 }
1515
1516 if (openssl_cipher_num == 0)
1517 return PJ_ENOTFOUND;
1518
1519 *cipher_num = PJ_MIN(*cipher_num, openssl_cipher_num);
1520
1521 for (i = 0; i < *cipher_num; ++i)
1522 ciphers[i] = openssl_ciphers[i];
1523
1524 return PJ_SUCCESS;
1525}
1526
1527
1528/*
1529 * Create SSL socket instance.
1530 */
1531PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool,
1532 const pj_ssl_sock_param *param,
1533 pj_ssl_sock_t **p_ssock)
1534{
1535 pj_ssl_sock_t *ssock;
1536 pj_status_t status;
1537
1538 PJ_ASSERT_RETURN(pool && param && p_ssock, PJ_EINVAL);
1539 PJ_ASSERT_RETURN(param->sock_type == pj_SOCK_STREAM(), PJ_ENOTSUP);
1540
1541 pool = pj_pool_create(pool->factory, "ssl%p", 512, 512, NULL);
1542
1543 /* Create secure socket */
1544 ssock = PJ_POOL_ZALLOC_T(pool, pj_ssl_sock_t);
1545 ssock->pool = pool;
1546 ssock->sock = PJ_INVALID_SOCKET;
1547 ssock->ssl_state = SSL_STATE_NULL;
1548 pj_list_init(&ssock->write_pending);
1549 pj_list_init(&ssock->write_pending_empty);
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001550 pj_timer_entry_init(&ssock->timer, 0, ssock, &on_timer);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001551
1552 /* Create secure socket mutex */
1553 status = pj_lock_create_recursive_mutex(pool, pool->obj_name,
1554 &ssock->write_mutex);
1555 if (status != PJ_SUCCESS)
1556 return status;
1557
1558 /* Init secure socket param */
1559 ssock->param = *param;
1560 ssock->param.read_buffer_size = ((ssock->param.read_buffer_size+7)>>3)<<3;
1561 if (param->ciphers_num > 0) {
1562 unsigned i;
1563 ssock->param.ciphers = (pj_ssl_cipher*)
1564 pj_pool_calloc(pool, param->ciphers_num,
1565 sizeof(pj_ssl_cipher));
1566 for (i = 0; i < param->ciphers_num; ++i)
1567 ssock->param.ciphers[i] = param->ciphers[i];
1568 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001569
1570 /* Server name must be null-terminated */
1571 pj_strdup_with_null(pool, &ssock->param.server_name,
1572 &param->server_name);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001573
1574 /* Finally */
1575 *p_ssock = ssock;
1576
1577 return PJ_SUCCESS;
1578}
1579
1580
1581/*
1582 * Close the secure socket. This will unregister the socket from the
1583 * ioqueue and ultimately close the socket.
1584 */
1585PJ_DEF(pj_status_t) pj_ssl_sock_close(pj_ssl_sock_t *ssock)
1586{
1587 pj_pool_t *pool;
1588
1589 PJ_ASSERT_RETURN(ssock, PJ_EINVAL);
1590
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001591 if (!ssock->pool)
1592 return PJ_SUCCESS;
1593
1594 if (ssock->timer.id != TIMER_NONE) {
1595 pj_timer_heap_cancel(ssock->param.timer_heap, &ssock->timer);
1596 ssock->timer.id = TIMER_NONE;
1597 }
1598
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001599 reset_ssl_sock_state(ssock);
1600 pj_lock_destroy(ssock->write_mutex);
1601
1602 pool = ssock->pool;
1603 ssock->pool = NULL;
1604 if (pool)
1605 pj_pool_release(pool);
1606
1607 return PJ_SUCCESS;
1608}
1609
1610
1611/*
1612 * Associate arbitrary data with the secure socket.
1613 */
1614PJ_DEF(pj_status_t) pj_ssl_sock_set_user_data(pj_ssl_sock_t *ssock,
1615 void *user_data)
1616{
1617 PJ_ASSERT_RETURN(ssock, PJ_EINVAL);
1618
1619 ssock->param.user_data = user_data;
1620 return PJ_SUCCESS;
1621}
1622
1623
1624/*
1625 * Retrieve the user data previously associated with this secure
1626 * socket.
1627 */
1628PJ_DEF(void*) pj_ssl_sock_get_user_data(pj_ssl_sock_t *ssock)
1629{
1630 PJ_ASSERT_RETURN(ssock, NULL);
1631
1632 return ssock->param.user_data;
1633}
1634
1635
1636/*
1637 * Retrieve the local address and port used by specified SSL socket.
1638 */
1639PJ_DEF(pj_status_t) pj_ssl_sock_get_info (pj_ssl_sock_t *ssock,
1640 pj_ssl_sock_info *info)
1641{
1642 pj_bzero(info, sizeof(*info));
1643
1644 /* Established flag */
1645 info->established = (ssock->ssl_state == SSL_STATE_ESTABLISHED);
1646
1647 /* Protocol */
1648 info->proto = ssock->param.proto;
1649
1650 /* Local address */
1651 pj_sockaddr_cp(&info->local_addr, &ssock->local_addr);
1652
1653 if (info->established) {
1654 /* Current cipher */
1655 const SSL_CIPHER *cipher;
1656
1657 cipher = SSL_get_current_cipher(ssock->ossl_ssl);
1658 info->cipher = (cipher->id & 0x00FFFFFF);
1659
1660 /* Remote address */
1661 pj_sockaddr_cp(&info->remote_addr, &ssock->rem_addr);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001662
1663 /* Certificates info */
1664 info->local_cert_info = ssock->local_cert_info;
1665 info->remote_cert_info = ssock->remote_cert_info;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001666 }
1667
1668 return PJ_SUCCESS;
1669}
1670
1671
1672/*
1673 * Starts read operation on this secure socket.
1674 */
1675PJ_DEF(pj_status_t) pj_ssl_sock_start_read (pj_ssl_sock_t *ssock,
1676 pj_pool_t *pool,
1677 unsigned buff_size,
1678 pj_uint32_t flags)
1679{
1680 void **readbuf;
1681 unsigned i;
1682
1683 PJ_ASSERT_RETURN(ssock && pool && buff_size, PJ_EINVAL);
1684 PJ_ASSERT_RETURN(ssock->ssl_state==SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
1685
1686 readbuf = (void**) pj_pool_calloc(pool, ssock->param.async_cnt,
1687 sizeof(void*));
1688
1689 for (i=0; i<ssock->param.async_cnt; ++i) {
1690 readbuf[i] = pj_pool_alloc(pool, buff_size);
1691 }
1692
1693 return pj_ssl_sock_start_read2(ssock, pool, buff_size,
1694 readbuf, flags);
1695}
1696
1697
1698/*
1699 * Same as #pj_ssl_sock_start_read(), except that the application
1700 * supplies the buffers for the read operation so that the acive socket
1701 * does not have to allocate the buffers.
1702 */
1703PJ_DEF(pj_status_t) pj_ssl_sock_start_read2 (pj_ssl_sock_t *ssock,
1704 pj_pool_t *pool,
1705 unsigned buff_size,
1706 void *readbuf[],
1707 pj_uint32_t flags)
1708{
1709 unsigned i;
1710
1711 PJ_ASSERT_RETURN(ssock && pool && buff_size && readbuf, PJ_EINVAL);
1712 PJ_ASSERT_RETURN(ssock->ssl_state==SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
1713
1714 /* Create SSL socket read buffer */
1715 ssock->ssock_rbuf = (read_data_t*)pj_pool_calloc(pool,
1716 ssock->param.async_cnt,
1717 sizeof(read_data_t));
1718
1719 /* Store SSL socket read buffer pointer in the activesock read buffer */
1720 for (i=0; i<ssock->param.async_cnt; ++i) {
1721 read_data_t **p_ssock_rbuf =
1722 OFFSET_OF_READ_DATA_PTR(ssock, ssock->asock_rbuf[i]);
1723
1724 ssock->ssock_rbuf[i].data = readbuf[i];
1725 ssock->ssock_rbuf[i].len = 0;
1726
1727 *p_ssock_rbuf = &ssock->ssock_rbuf[i];
1728 }
1729
1730 ssock->read_size = buff_size;
1731 ssock->read_started = PJ_TRUE;
1732 ssock->read_flags = flags;
1733
1734 return PJ_SUCCESS;
1735}
1736
1737
1738/*
1739 * Same as pj_ssl_sock_start_read(), except that this function is used
1740 * only for datagram sockets, and it will trigger \a on_data_recvfrom()
1741 * callback instead.
1742 */
1743PJ_DEF(pj_status_t) pj_ssl_sock_start_recvfrom (pj_ssl_sock_t *ssock,
1744 pj_pool_t *pool,
1745 unsigned buff_size,
1746 pj_uint32_t flags)
1747{
1748 PJ_UNUSED_ARG(ssock);
1749 PJ_UNUSED_ARG(pool);
1750 PJ_UNUSED_ARG(buff_size);
1751 PJ_UNUSED_ARG(flags);
1752
1753 return PJ_ENOTSUP;
1754}
1755
1756
1757/*
1758 * Same as #pj_ssl_sock_start_recvfrom() except that the recvfrom()
1759 * operation takes the buffer from the argument rather than creating
1760 * new ones.
1761 */
1762PJ_DEF(pj_status_t) pj_ssl_sock_start_recvfrom2 (pj_ssl_sock_t *ssock,
1763 pj_pool_t *pool,
1764 unsigned buff_size,
1765 void *readbuf[],
1766 pj_uint32_t flags)
1767{
1768 PJ_UNUSED_ARG(ssock);
1769 PJ_UNUSED_ARG(pool);
1770 PJ_UNUSED_ARG(buff_size);
1771 PJ_UNUSED_ARG(readbuf);
1772 PJ_UNUSED_ARG(flags);
1773
1774 return PJ_ENOTSUP;
1775}
1776
1777/* Write plain data to SSL and flush write BIO. Note that accessing
1778 * write BIO must be serialized, so a call to this function must be
1779 * protected by write mutex of SSL socket.
1780 */
1781static pj_status_t ssl_write(pj_ssl_sock_t *ssock,
1782 pj_ioqueue_op_key_t *send_key,
1783 const void *data,
1784 pj_ssize_t size,
1785 unsigned flags)
1786{
1787 pj_status_t status;
1788 int nwritten;
1789
1790 /* Write the plain data to SSL, after SSL encrypts it, write BIO will
1791 * contain the secured data to be sent via socket. Note that re-
1792 * negotitation may be on progress, so sending data should be delayed
1793 * until re-negotiation is completed.
1794 */
1795 nwritten = SSL_write(ssock->ossl_ssl, data, size);
1796
1797 if (nwritten == size) {
1798 /* All data written, flush write BIO to network socket */
1799 status = flush_write_bio(ssock, send_key, size, flags);
1800 } else if (nwritten <= 0) {
1801 /* SSL failed to process the data, it may just that re-negotiation
1802 * is on progress.
1803 */
1804 int err;
1805 err = SSL_get_error(ssock->ossl_ssl, nwritten);
1806 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_NONE) {
1807 /* Re-negotiation is on progress, flush re-negotiation data */
1808 status = flush_write_bio(ssock, &ssock->handshake_op_key, 0, 0);
1809 if (status == PJ_SUCCESS || status == PJ_EPENDING)
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001810 /* Just return PJ_EBUSY when re-negotiation is on progress */
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001811 status = PJ_EBUSY;
1812 } else {
1813 /* Some problem occured */
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00001814 GET_SSL_STATUS(status);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001815 }
1816 } else {
1817 /* nwritten < *size, shouldn't happen, unless write BIO cannot hold
1818 * the whole secured data, perhaps because of insufficient memory.
1819 */
1820 status = PJ_ENOMEM;
1821 }
1822
1823 return status;
1824}
1825
1826/* Flush delayed data sending in the write pending list. Note that accessing
1827 * write pending list must be serialized, so a call to this function must be
1828 * protected by write mutex of SSL socket.
1829 */
1830static pj_status_t flush_delayed_send(pj_ssl_sock_t *ssock)
1831{
1832 while (!pj_list_empty(&ssock->write_pending)) {
1833 write_pending_t *wp;
1834 pj_status_t status;
1835
1836 wp = ssock->write_pending.next;
1837
1838 status = ssl_write(ssock, &wp->data.key, wp->data.data.ptr,
1839 wp->data.plain_data_len, wp->data.flags);
1840 if (status != PJ_SUCCESS)
1841 return status;
1842
1843 pj_list_erase(wp);
1844 pj_list_push_back(&ssock->write_pending_empty, wp);
1845 }
1846
1847 return PJ_SUCCESS;
1848}
1849
1850/* Sending is delayed, push back the sending data into pending list. Note that
1851 * accessing write pending list must be serialized, so a call to this function
1852 * must be protected by write mutex of SSL socket.
1853 */
1854static pj_status_t delay_send (pj_ssl_sock_t *ssock,
1855 pj_ioqueue_op_key_t *send_key,
1856 const void *data,
1857 pj_ssize_t size,
1858 unsigned flags)
1859{
1860 write_pending_t *wp;
1861
1862 /* Init write pending instance */
1863 if (!pj_list_empty(&ssock->write_pending_empty)) {
1864 wp = ssock->write_pending_empty.next;
1865 pj_list_erase(wp);
1866 } else {
1867 wp = PJ_POOL_ZALLOC_T(ssock->pool, write_pending_t);
1868 }
1869
1870 wp->data.app_key = send_key;
1871 wp->data.plain_data_len = size;
1872 wp->data.data.ptr = data;
1873 wp->data.flags = flags;
1874
1875 pj_list_push_back(&ssock->write_pending, wp);
1876
1877 /* Must return PJ_EPENDING */
1878 return PJ_EPENDING;
1879}
1880
1881/**
1882 * Send data using the socket.
1883 */
1884PJ_DEF(pj_status_t) pj_ssl_sock_send (pj_ssl_sock_t *ssock,
1885 pj_ioqueue_op_key_t *send_key,
1886 const void *data,
1887 pj_ssize_t *size,
1888 unsigned flags)
1889{
1890 pj_status_t status;
1891
1892 PJ_ASSERT_RETURN(ssock && data && size && (*size>0), PJ_EINVAL);
1893 PJ_ASSERT_RETURN(ssock->ssl_state==SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
1894
1895 pj_lock_acquire(ssock->write_mutex);
1896
1897 /* Flush delayed send first. Sending data might be delayed when
1898 * re-negotiation is on-progress.
1899 */
1900 status = flush_delayed_send(ssock);
1901 if (status == PJ_EBUSY) {
1902 /* Re-negotiation is on progress, delay sending */
1903 status = delay_send(ssock, send_key, data, *size, flags);
1904 goto on_return;
1905 } else if (status != PJ_SUCCESS) {
1906 goto on_return;
1907 }
1908
1909 /* Write data to SSL */
1910 status = ssl_write(ssock, send_key, data, *size, flags);
1911 if (status == PJ_EBUSY) {
1912 /* Re-negotiation is on progress, delay sending */
1913 status = delay_send(ssock, send_key, data, *size, flags);
1914 }
1915
1916on_return:
1917 pj_lock_release(ssock->write_mutex);
1918 return status;
1919}
1920
1921
1922/**
1923 * Send datagram using the socket.
1924 */
1925PJ_DEF(pj_status_t) pj_ssl_sock_sendto (pj_ssl_sock_t *ssock,
1926 pj_ioqueue_op_key_t *send_key,
1927 const void *data,
1928 pj_ssize_t *size,
1929 unsigned flags,
1930 const pj_sockaddr_t *addr,
1931 int addr_len)
1932{
1933 PJ_UNUSED_ARG(ssock);
1934 PJ_UNUSED_ARG(send_key);
1935 PJ_UNUSED_ARG(data);
1936 PJ_UNUSED_ARG(size);
1937 PJ_UNUSED_ARG(flags);
1938 PJ_UNUSED_ARG(addr);
1939 PJ_UNUSED_ARG(addr_len);
1940
1941 return PJ_ENOTSUP;
1942}
1943
1944
1945/**
1946 * Starts asynchronous socket accept() operations on this secure socket.
1947 */
1948PJ_DEF(pj_status_t) pj_ssl_sock_start_accept (pj_ssl_sock_t *ssock,
1949 pj_pool_t *pool,
1950 const pj_sockaddr_t *localaddr,
1951 int addr_len)
1952{
1953 pj_activesock_cb asock_cb;
1954 pj_activesock_cfg asock_cfg;
1955 pj_status_t status;
1956
1957 PJ_ASSERT_RETURN(ssock && pool && localaddr && addr_len, PJ_EINVAL);
1958
1959 /* Create socket */
1960 status = pj_sock_socket(ssock->param.sock_af, ssock->param.sock_type, 0,
1961 &ssock->sock);
1962 if (status != PJ_SUCCESS)
1963 goto on_error;
1964
Benny Prijonoa25bc9d2009-11-09 08:51:34 +00001965 /* Apply QoS, if specified */
1966 status = pj_sock_apply_qos2(ssock->sock, ssock->param.qos_type,
1967 &ssock->param.qos_params, 2,
1968 ssock->pool->obj_name, NULL);
1969 if (status != PJ_SUCCESS && !ssock->param.qos_ignore_error)
1970 goto on_error;
1971
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001972 /* Bind socket */
1973 status = pj_sock_bind(ssock->sock, localaddr, addr_len);
1974 if (status != PJ_SUCCESS)
1975 goto on_error;
1976
1977 /* Start listening to the address */
1978 status = pj_sock_listen(ssock->sock, PJ_SOMAXCONN);
1979 if (status != PJ_SUCCESS)
1980 goto on_error;
1981
1982 /* Create active socket */
1983 pj_activesock_cfg_default(&asock_cfg);
1984 asock_cfg.async_cnt = ssock->param.async_cnt;
1985 asock_cfg.concurrency = ssock->param.concurrency;
1986 asock_cfg.whole_data = PJ_TRUE;
1987
1988 pj_bzero(&asock_cb, sizeof(asock_cb));
1989 asock_cb.on_accept_complete = asock_on_accept_complete;
1990
1991 status = pj_activesock_create(pool,
1992 ssock->sock,
1993 ssock->param.sock_type,
1994 &asock_cfg,
1995 ssock->param.ioqueue,
1996 &asock_cb,
1997 ssock,
1998 &ssock->asock);
1999
2000 if (status != PJ_SUCCESS)
2001 goto on_error;
2002
2003 /* Start accepting */
2004 status = pj_activesock_start_accept(ssock->asock, pool);
2005 if (status != PJ_SUCCESS)
2006 goto on_error;
2007
2008 /* Update local address */
2009 ssock->addr_len = addr_len;
2010 status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,
2011 &ssock->addr_len);
2012 if (status != PJ_SUCCESS)
2013 pj_sockaddr_cp(&ssock->local_addr, localaddr);
2014
2015 ssock->is_server = PJ_TRUE;
2016
2017 return PJ_SUCCESS;
2018
2019on_error:
2020 reset_ssl_sock_state(ssock);
2021 return status;
2022}
2023
2024
2025/**
2026 * Starts asynchronous socket connect() operation.
2027 */
2028PJ_DECL(pj_status_t) pj_ssl_sock_start_connect(pj_ssl_sock_t *ssock,
2029 pj_pool_t *pool,
2030 const pj_sockaddr_t *localaddr,
2031 const pj_sockaddr_t *remaddr,
2032 int addr_len)
2033{
2034 pj_activesock_cb asock_cb;
2035 pj_activesock_cfg asock_cfg;
2036 pj_status_t status;
2037
2038 PJ_ASSERT_RETURN(ssock && pool && localaddr && remaddr && addr_len,
2039 PJ_EINVAL);
2040
2041 /* Create socket */
2042 status = pj_sock_socket(ssock->param.sock_af, ssock->param.sock_type, 0,
2043 &ssock->sock);
2044 if (status != PJ_SUCCESS)
2045 goto on_error;
2046
Benny Prijonoa25bc9d2009-11-09 08:51:34 +00002047 /* Apply QoS, if specified */
2048 status = pj_sock_apply_qos2(ssock->sock, ssock->param.qos_type,
2049 &ssock->param.qos_params, 2,
2050 ssock->pool->obj_name, NULL);
2051 if (status != PJ_SUCCESS && !ssock->param.qos_ignore_error)
2052 goto on_error;
2053
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002054 /* Bind socket */
2055 status = pj_sock_bind(ssock->sock, localaddr, addr_len);
2056 if (status != PJ_SUCCESS)
2057 goto on_error;
2058
2059 /* Create active socket */
2060 pj_activesock_cfg_default(&asock_cfg);
2061 asock_cfg.async_cnt = ssock->param.async_cnt;
2062 asock_cfg.concurrency = ssock->param.concurrency;
2063 asock_cfg.whole_data = PJ_TRUE;
2064
2065 pj_bzero(&asock_cb, sizeof(asock_cb));
2066 asock_cb.on_connect_complete = asock_on_connect_complete;
2067 asock_cb.on_data_read = asock_on_data_read;
2068 asock_cb.on_data_sent = asock_on_data_sent;
2069
2070 status = pj_activesock_create(pool,
2071 ssock->sock,
2072 ssock->param.sock_type,
2073 &asock_cfg,
2074 ssock->param.ioqueue,
2075 &asock_cb,
2076 ssock,
2077 &ssock->asock);
2078
2079 if (status != PJ_SUCCESS)
2080 goto on_error;
2081
Nanang Izzuddin48747632009-11-20 07:48:41 +00002082 /* Save remote address */
2083 pj_sockaddr_cp(&ssock->rem_addr, remaddr);
2084
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002085 status = pj_activesock_start_connect(ssock->asock, pool, remaddr,
2086 addr_len);
2087
2088 if (status == PJ_SUCCESS)
2089 asock_on_connect_complete(ssock->asock, PJ_SUCCESS);
2090 else if (status != PJ_EPENDING)
2091 goto on_error;
2092
2093 /* Update local address */
2094 ssock->addr_len = addr_len;
2095 status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,
2096 &ssock->addr_len);
Nanang Izzuddinb5e025a2009-11-09 13:40:26 +00002097 /* Note that we may not get an IP address here. This can
2098 * happen for example on Windows, where getsockname()
2099 * would return 0.0.0.0 if socket has just started the
2100 * async connect. In this case, just leave the local
2101 * address with 0.0.0.0 for now; it will be updated
2102 * once the socket is established.
2103 */
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002104
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002105 /* Update SSL state */
2106 ssock->is_server = PJ_FALSE;
2107
2108 return PJ_EPENDING;
2109
2110on_error:
2111 reset_ssl_sock_state(ssock);
2112 return status;
2113}
2114
2115
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00002116PJ_DEF(pj_status_t) pj_ssl_sock_renegotiate(pj_ssl_sock_t *ssock)
2117{
2118 int ret;
2119 pj_status_t status;
2120
2121 PJ_ASSERT_RETURN(ssock->ssl_state == SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
2122
2123 if (SSL_renegotiate_pending(ssock->ossl_ssl))
2124 return PJ_EPENDING;
2125
2126 ret = SSL_renegotiate(ssock->ossl_ssl);
2127 if (ret <= 0) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00002128 GET_SSL_STATUS(status);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00002129 } else {
2130 status = do_handshake(ssock);
2131 }
2132
2133 return status;
2134}
2135
2136#endif /* PJ_HAS_SSL_SOCK */
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002137