blob: 3528fe72b589b8f40d17973255c5aaf79fa57603 [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>
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +000048#include <openssl/x509v3.h>
Nanang Izzuddin006cc012009-10-16 03:06:13 +000049
50
51#ifdef _MSC_VER
52# ifdef _DEBUG
53# pragma comment( lib, "libeay32MTd")
54# pragma comment( lib, "ssleay32MTd")
55#else
56# pragma comment( lib, "libeay32MT")
57# pragma comment( lib, "ssleay32MT")
58# endif
59#endif
60
61
62/*
63 * SSL/TLS state enumeration.
64 */
65enum ssl_state {
66 SSL_STATE_NULL,
67 SSL_STATE_HANDSHAKING,
68 SSL_STATE_ESTABLISHED
69};
70
71/*
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +000072 * Internal timer types.
73 */
74enum timer_id
75{
76 TIMER_NONE,
77 TIMER_HANDSHAKE_TIMEOUT,
78 TIMER_CLOSE
79};
80
81/*
Nanang Izzuddin006cc012009-10-16 03:06:13 +000082 * Structure of SSL socket read buffer.
83 */
84typedef struct read_data_t
85{
86 void *data;
87 pj_size_t len;
88} read_data_t;
89
90/*
91 * Get the offset of pointer to read-buffer of SSL socket from read-buffer
92 * of active socket. Note that both SSL socket and active socket employ
93 * different but correlated read-buffers (as much as async_cnt for each),
94 * and to make it easier/faster to find corresponding SSL socket's read-buffer
95 * from known active socket's read-buffer, the pointer of corresponding
96 * SSL socket's read-buffer is stored right after the end of active socket's
97 * read-buffer.
98 */
99#define OFFSET_OF_READ_DATA_PTR(ssock, asock_rbuf) \
100 (read_data_t**) \
101 ((pj_int8_t*)(asock_rbuf) + \
102 ssock->param.read_buffer_size)
103
104/*
105 * Structure of SSL socket write buffer.
106 */
107typedef struct write_data_t {
108 pj_ioqueue_op_key_t key;
109 pj_size_t record_len;
110 pj_ioqueue_op_key_t *app_key;
111 pj_size_t plain_data_len;
112 pj_size_t data_len;
113 union {
114 char content[1];
115 const char *ptr;
116 } data;
117 unsigned flags;
118} write_data_t;
119
120/*
121 * Structure of SSL socket write state.
122 */
123typedef struct write_state_t {
124 char *buf;
125 pj_size_t max_len;
126 char *start;
127 pj_size_t len;
128 write_data_t *last_data;
129} write_state_t;
130
131/*
132 * Structure of write data pending.
133 */
134typedef struct write_pending_t {
135 PJ_DECL_LIST_MEMBER(struct write_pending_t);
136 write_data_t data;
137} write_pending_t;
138
139/*
140 * Secure socket structure definition.
141 */
142struct pj_ssl_sock_t
143{
144 pj_pool_t *pool;
145 pj_ssl_sock_t *parent;
146 pj_ssl_sock_param param;
147 pj_ssl_cert_t *cert;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000148
149 pj_ssl_cert_info local_cert_info;
150 pj_ssl_cert_info remote_cert_info;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000151
152 pj_bool_t is_server;
153 enum ssl_state ssl_state;
154 pj_ioqueue_op_key_t handshake_op_key;
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +0000155 pj_timer_entry timer;
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000156 pj_status_t verify_status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000157
158 pj_sock_t sock;
159 pj_activesock_t *asock;
160
161 pj_sockaddr local_addr;
162 pj_sockaddr rem_addr;
163 int addr_len;
164
165 pj_bool_t read_started;
166 pj_size_t read_size;
167 pj_uint32_t read_flags;
168 void **asock_rbuf;
169 read_data_t *ssock_rbuf;
170
171 write_state_t write_state;
172 write_pending_t write_pending;
173 write_pending_t write_pending_empty;
174 pj_lock_t *write_mutex; /* protect write BIO and write_state */
175
176 SSL_CTX *ossl_ctx;
177 SSL *ossl_ssl;
178 BIO *ossl_rbio;
179 BIO *ossl_wbio;
180};
181
182
183/*
184 * Certificate/credential structure definition.
185 */
186struct pj_ssl_cert_t
187{
188 pj_str_t CA_file;
189 pj_str_t cert_file;
190 pj_str_t privkey_file;
191 pj_str_t privkey_pass;
192};
193
194
195static pj_status_t flush_delayed_send(pj_ssl_sock_t *ssock);
196
197/*
198 *******************************************************************
199 * Static/internal functions.
200 *******************************************************************
201 */
202
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000203/**
204 * Mapping from OpenSSL error codes to pjlib error space.
205 */
206
207#define PJ_SSL_ERRNO_START (PJ_ERRNO_START_USER + \
208 PJ_ERRNO_SPACE_SIZE*6)
209
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000210#define PJ_SSL_ERRNO_SPACE_SIZE PJ_ERRNO_SPACE_SIZE
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000211
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000212#define STATUS_FROM_SSL_ERR(err, status) { \
213 status = ERR_GET_LIB(err)*300 + ERR_GET_REASON(err);\
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000214 pj_assert(status < PJ_SSL_ERRNO_SPACE_SIZE);\
215 if (status) status += PJ_SSL_ERRNO_START;\
216}
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000217
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000218#define GET_SSL_STATUS(status) { \
219 unsigned long e = ERR_get_error();\
220 STATUS_FROM_SSL_ERR(e, status);\
221}
222
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000223/*
224 * Get error string of OpenSSL.
225 */
226static pj_str_t ssl_strerror(pj_status_t status,
227 char *buf, pj_size_t bufsize)
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000228{
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000229 pj_str_t errstr;
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000230 unsigned long ssl_err = status;
231
232 if (ssl_err) {
233 unsigned long l, r;
234 ssl_err -= PJ_SSL_ERRNO_START;
235 l = ssl_err/300;
236 r = ssl_err%300;
237 ssl_err = ERR_PACK(l, 0, r);
238 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000239
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000240#if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0)
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000241
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000242 {
243 const char *tmp = NULL;
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000244
245 if (ssl_err >= 300)
246 tmp = ERR_reason_error_string(ssl_err);
247 else
248 tmp = X509_verify_cert_error_string(ssl_err);
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000249
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000250 if (tmp) {
251 pj_ansi_strncpy(buf, tmp, bufsize);
252 errstr = pj_str(buf);
253 return errstr;
254 }
255 }
256
257#endif /* PJ_HAS_ERROR_STRING */
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000258
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000259 errstr.ptr = buf;
260 errstr.slen = pj_ansi_snprintf(buf, bufsize,
Benny Prijono0a411e22009-11-10 07:59:45 +0000261 "Unknown OpenSSL error %lu",
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000262 ssl_err);
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000263
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000264 return errstr;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000265}
266
267
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000268/* OpenSSL library initialization counter */
269static int openssl_init_count;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000270static int openssl_reg_strerr;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000271
272/* OpenSSL available ciphers */
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000273static pj_ssl_cipher openssl_ciphers[100];
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000274static unsigned openssl_cipher_num;
275
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000276/* OpenSSL application data index */
277static int sslsock_idx;
278
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000279
280/* Initialize OpenSSL */
281static pj_status_t init_openssl(void)
282{
Nanang Izzuddineef9b8d2009-11-06 13:31:37 +0000283 if (openssl_init_count)
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000284 return PJ_SUCCESS;
285
Nanang Izzuddineef9b8d2009-11-06 13:31:37 +0000286 openssl_init_count = 1;
287
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000288 /* Register error subsystem */
289 if (!openssl_reg_strerr) {
290 pj_status_t status;
291
292 openssl_reg_strerr = 1;
293 status = pj_register_strerror(PJ_SSL_ERRNO_START,
294 PJ_SSL_ERRNO_SPACE_SIZE,
295 &ssl_strerror);
296 pj_assert(status == PJ_SUCCESS);
297 }
298
299 /* Init OpenSSL lib */
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000300 SSL_library_init();
301 SSL_load_error_strings();
302 OpenSSL_add_all_algorithms();
303
304 /* Init available ciphers */
305 if (openssl_cipher_num == 0) {
306 SSL_METHOD *meth = NULL;
307 SSL_CTX *ctx;
308 SSL *ssl;
309 STACK_OF(SSL_CIPHER) *sk_cipher;
310 unsigned i, n;
311
312 meth = (SSL_METHOD*)SSLv23_server_method();
313 if (!meth)
314 meth = (SSL_METHOD*)TLSv1_server_method();
315 if (!meth)
316 meth = (SSL_METHOD*)SSLv3_server_method();
317 if (!meth)
318 meth = (SSL_METHOD*)SSLv2_server_method();
319 pj_assert(meth);
320
321 ctx=SSL_CTX_new(meth);
322 SSL_CTX_set_cipher_list(ctx, "ALL");
323
324 ssl = SSL_new(ctx);
325 sk_cipher = SSL_get_ciphers(ssl);
326
327 n = sk_SSL_CIPHER_num(sk_cipher);
328 if (n > PJ_ARRAY_SIZE(openssl_ciphers))
329 n = PJ_ARRAY_SIZE(openssl_ciphers);
330
331 for (i = 0; i < n; ++i) {
332 SSL_CIPHER *c;
333 c = sk_SSL_CIPHER_value(sk_cipher,i);
334 openssl_ciphers[i] = (pj_ssl_cipher)
335 (pj_uint32_t)c->id & 0x00FFFFFF;
336 //printf("%3u: %08x=%s\n", i+1, c->id, SSL_CIPHER_get_name(c));
337 }
338
339 SSL_free(ssl);
340 SSL_CTX_free(ctx);
341
342 openssl_cipher_num = n;
343 }
344
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000345 /* Create OpenSSL application data index for SSL socket */
346 sslsock_idx = SSL_get_ex_new_index(0, "SSL socket", NULL, NULL, NULL);
347
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000348 return PJ_SUCCESS;
349}
350
351
352/* Shutdown OpenSSL */
353static void shutdown_openssl(void)
354{
Nanang Izzuddineef9b8d2009-11-06 13:31:37 +0000355 PJ_UNUSED_ARG(openssl_init_count);
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000356}
357
358
359/* SSL password callback. */
360static int password_cb(char *buf, int num, int rwflag, void *user_data)
361{
362 pj_ssl_cert_t *cert = (pj_ssl_cert_t*) user_data;
363
364 PJ_UNUSED_ARG(rwflag);
365
366 if(num < cert->privkey_pass.slen)
367 return 0;
368
369 pj_memcpy(buf, cert->privkey_pass.ptr, cert->privkey_pass.slen);
370 return cert->privkey_pass.slen;
371}
372
373
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000374/* SSL password callback. */
375static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
376{
377 pj_ssl_sock_t *ssock;
378 SSL *ossl_ssl;
379 int err;
380
381 /* Get SSL instance */
382 ossl_ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
383 SSL_get_ex_data_X509_STORE_CTX_idx());
384 pj_assert(ossl_ssl);
385
386 /* Get SSL socket instance */
387 ssock = SSL_get_ex_data(ossl_ssl, sslsock_idx);
388 pj_assert(ssock);
389
390 /* Store verification status */
391 err = X509_STORE_CTX_get_error(x509_ctx);
392 switch (err) {
393 case X509_V_OK:
394 break;
395
396 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
397 ssock->verify_status |= PJ_SSL_CERT_EISSUER_NOT_FOUND;
398 break;
399
400 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
401 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
402 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
403 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
404 ssock->verify_status |= PJ_SSL_CERT_EINVALID_FORMAT;
405 break;
406
407 case X509_V_ERR_CERT_NOT_YET_VALID:
408 case X509_V_ERR_CERT_HAS_EXPIRED:
409 ssock->verify_status |= PJ_SSL_CERT_EVALIDITY_PERIOD;
410 break;
411
412 case X509_V_ERR_UNABLE_TO_GET_CRL:
413 case X509_V_ERR_CRL_NOT_YET_VALID:
414 case X509_V_ERR_CRL_HAS_EXPIRED:
415 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
416 case X509_V_ERR_CRL_SIGNATURE_FAILURE:
417 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
418 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
419 ssock->verify_status |= PJ_SSL_CERT_ECRL_FAILURE;
420 break;
421
422 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
423 case X509_V_ERR_CERT_UNTRUSTED:
424 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
425 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
426 ssock->verify_status |= PJ_SSL_CERT_EUNTRUSTED;
427 break;
428
429 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
430 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
431 case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
432 case X509_V_ERR_AKID_SKID_MISMATCH:
433 case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
434 case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
435 ssock->verify_status |= PJ_SSL_CERT_EISSUER_MISMATCH;
436 break;
437
438 case X509_V_ERR_CERT_REVOKED:
439 ssock->verify_status |= PJ_SSL_CERT_EREVOKED;
440 break;
441
442 case X509_V_ERR_INVALID_PURPOSE:
443 case X509_V_ERR_CERT_REJECTED:
444 case X509_V_ERR_INVALID_CA:
445 ssock->verify_status |= PJ_SSL_CERT_EINVALID_PURPOSE;
446 break;
447
448 case X509_V_ERR_CERT_CHAIN_TOO_LONG: /* not really used */
449 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
450 ssock->verify_status |= PJ_SSL_CERT_ECHAIN_TOO_LONG;
451 break;
452
453 /* Unknown errors */
454 case X509_V_ERR_OUT_OF_MEM:
455 default:
456 ssock->verify_status |= PJ_SSL_CERT_EUNKNOWN;
457 break;
458 }
459
460 /* When verification is not requested just return ok here, however
461 * application can still get the verification status.
462 */
463 if (PJ_FALSE == ssock->param.verify_peer)
464 preverify_ok = 1;
465
466 return preverify_ok;
467}
468
469/* Setting SSL sock cipher list */
470static pj_status_t set_cipher_list(pj_ssl_sock_t *ssock);
471
472
473/* Create and initialize new SSL context and instance */
474static pj_status_t create_ssl(pj_ssl_sock_t *ssock)
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000475{
476 SSL_METHOD *ssl_method;
477 SSL_CTX *ctx;
478 pj_ssl_cert_t *cert;
479 int mode, rc;
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000480 pj_status_t status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000481
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000482 pj_assert(ssock);
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000483
484 cert = ssock->cert;
485
486 /* Make sure OpenSSL library has been initialized */
487 init_openssl();
488
489 /* Determine SSL method to use */
490 switch (ssock->param.proto) {
491 case PJ_SSL_SOCK_PROTO_DEFAULT:
492 case PJ_SSL_SOCK_PROTO_TLS1:
493 ssl_method = (SSL_METHOD*)TLSv1_method();
494 break;
495 case PJ_SSL_SOCK_PROTO_SSL2:
496 ssl_method = (SSL_METHOD*)SSLv2_method();
497 break;
498 case PJ_SSL_SOCK_PROTO_SSL3:
499 ssl_method = (SSL_METHOD*)SSLv3_method();
500 break;
501 case PJ_SSL_SOCK_PROTO_SSL23:
502 ssl_method = (SSL_METHOD*)SSLv23_method();
503 break;
Nanang Izzuddin8d759582009-10-28 03:41:34 +0000504 //case PJ_SSL_SOCK_PROTO_DTLS1:
505 //ssl_method = (SSL_METHOD*)DTLSv1_method();
506 //break;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000507 default:
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000508 return PJ_EINVAL;
509 }
510
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000511 /* Create SSL context */
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000512 ctx = SSL_CTX_new(ssl_method);
513 if (ctx == NULL) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000514 GET_SSL_STATUS(status);
515 return status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000516 }
517
518 /* Apply credentials */
519 if (cert) {
520 /* Load CA list if one is specified. */
521 if (cert->CA_file.slen) {
522
523 rc = SSL_CTX_load_verify_locations(ctx, cert->CA_file.ptr, NULL);
524
525 if (rc != 1) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000526 GET_SSL_STATUS(status);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000527 PJ_LOG(1,(ssock->pool->obj_name, "Error loading CA list file "
528 "'%s'", cert->CA_file.ptr));
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000529 SSL_CTX_free(ctx);
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000530 return status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000531 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000532 }
533
534 /* Set password callback */
535 if (cert->privkey_pass.slen) {
536 SSL_CTX_set_default_passwd_cb(ctx, password_cb);
537 SSL_CTX_set_default_passwd_cb_userdata(ctx, cert);
538 }
539
540
541 /* Load certificate if one is specified */
542 if (cert->cert_file.slen) {
543
544 /* Load certificate chain from file into ctx */
545 rc = SSL_CTX_use_certificate_chain_file(ctx, cert->cert_file.ptr);
546
547 if(rc != 1) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000548 GET_SSL_STATUS(status);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000549 PJ_LOG(1,(ssock->pool->obj_name, "Error loading certificate "
550 "chain file '%s'", cert->cert_file.ptr));
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000551 SSL_CTX_free(ctx);
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000552 return status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000553 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000554 }
555
556
557 /* Load private key if one is specified */
558 if (cert->privkey_file.slen) {
559 /* Adds the first private key found in file to ctx */
560 rc = SSL_CTX_use_PrivateKey_file(ctx, cert->privkey_file.ptr,
561 SSL_FILETYPE_PEM);
562
563 if(rc != 1) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000564 GET_SSL_STATUS(status);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000565 PJ_LOG(1,(ssock->pool->obj_name, "Error adding private key "
566 "from '%s'", cert->privkey_file.ptr));
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000567 SSL_CTX_free(ctx);
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000568 return status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000569 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000570 }
571 }
572
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000573 /* Create SSL instance */
574 ssock->ossl_ctx = ctx;
575 ssock->ossl_ssl = SSL_new(ssock->ossl_ctx);
576 if (ssock->ossl_ssl == NULL) {
577 GET_SSL_STATUS(status);
578 return status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000579 }
580
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000581 /* Set SSL sock as application data of SSL instance */
582 SSL_set_ex_data(ssock->ossl_ssl, sslsock_idx, ssock);
583
584 /* SSL verification options */
585 mode = SSL_VERIFY_PEER;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000586 if (ssock->is_server && ssock->param.require_client_cert)
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000587 mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000588
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000589 SSL_set_verify(ssock->ossl_ssl, mode, &verify_cb);
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000590
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000591 /* Set cipher list */
592 status = set_cipher_list(ssock);
593 if (status != PJ_SUCCESS)
594 return status;
595
596 /* Setup SSL BIOs */
597 ssock->ossl_rbio = BIO_new(BIO_s_mem());
598 ssock->ossl_wbio = BIO_new(BIO_s_mem());
599 BIO_set_close(ssock->ossl_rbio, BIO_CLOSE);
600 BIO_set_close(ssock->ossl_wbio, BIO_CLOSE);
601 SSL_set_bio(ssock->ossl_ssl, ssock->ossl_rbio, ssock->ossl_wbio);
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000602
603 return PJ_SUCCESS;
604}
605
606
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000607/* Destroy SSL context and instance */
608static void destroy_ssl(pj_ssl_sock_t *ssock)
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000609{
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000610 /* Destroy SSL instance */
611 if (ssock->ossl_ssl) {
612 SSL_shutdown(ssock->ossl_ssl);
613 SSL_free(ssock->ossl_ssl); /* this will also close BIOs */
614 ssock->ossl_ssl = NULL;
615 }
616
617 /* Destroy SSL context */
618 if (ssock->ossl_ctx) {
619 SSL_CTX_free(ssock->ossl_ctx);
620 ssock->ossl_ctx = NULL;
621 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000622
623 /* Potentially shutdown OpenSSL library if this is the last
624 * context exists.
625 */
626 shutdown_openssl();
627}
628
629
630/* Reset SSL socket state */
631static void reset_ssl_sock_state(pj_ssl_sock_t *ssock)
632{
633 ssock->ssl_state = SSL_STATE_NULL;
634
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000635 destroy_ssl(ssock);
636
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000637 if (ssock->asock) {
638 pj_activesock_close(ssock->asock);
639 ssock->asock = NULL;
640 ssock->sock = PJ_INVALID_SOCKET;
641 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000642 if (ssock->sock != PJ_INVALID_SOCKET) {
643 pj_sock_close(ssock->sock);
644 ssock->sock = PJ_INVALID_SOCKET;
645 }
Nanang Izzuddin6cfc6d52009-10-27 02:21:28 +0000646
647 /* Upon error, OpenSSL may leave any error description in the thread
648 * error queue, which sometime may cause next call to SSL API returning
649 * false error alarm, e.g: in Linux, SSL_CTX_use_certificate_chain_file()
650 * returning false error after a handshake error (in different SSL_CTX!).
651 * For now, just clear thread error queue here.
652 */
653 ERR_clear_error();
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000654}
655
656
657/* Generate cipher list with user preference order in OpenSSL format */
658static pj_status_t set_cipher_list(pj_ssl_sock_t *ssock)
659{
660 char buf[1024];
661 pj_str_t cipher_list;
662 STACK_OF(SSL_CIPHER) *sk_cipher;
663 unsigned i;
664 int j, ret;
665
666 if (ssock->param.ciphers_num == 0)
667 return PJ_SUCCESS;
668
669 pj_strset(&cipher_list, buf, 0);
670
671 /* Set SSL with ALL available ciphers */
672 SSL_set_cipher_list(ssock->ossl_ssl, "ALL");
673
674 /* Generate user specified cipher list in OpenSSL format */
675 sk_cipher = SSL_get_ciphers(ssock->ossl_ssl);
676 for (i = 0; i < ssock->param.ciphers_num; ++i) {
677 for (j = 0; j < sk_SSL_CIPHER_num(sk_cipher); ++j) {
678 SSL_CIPHER *c;
679 c = sk_SSL_CIPHER_value(sk_cipher, j);
680 if (ssock->param.ciphers[i] == (pj_ssl_cipher)
681 ((pj_uint32_t)c->id & 0x00FFFFFF))
682 {
683 const char *c_name;
684
685 c_name = SSL_CIPHER_get_name(c);
686
687 /* Check buffer size */
688 if (cipher_list.slen + pj_ansi_strlen(c_name) + 2 > sizeof(buf)) {
689 pj_assert(!"Insufficient temporary buffer for cipher");
690 return PJ_ETOOMANY;
691 }
692
693 /* Add colon separator */
694 if (cipher_list.slen)
695 pj_strcat2(&cipher_list, ":");
696
697 /* Add the cipher */
698 pj_strcat2(&cipher_list, c_name);
699 break;
700 }
701 }
702 }
703
704 /* Put NULL termination in the generated cipher list */
705 cipher_list.ptr[cipher_list.slen] = '\0';
706
707 /* Finally, set chosen cipher list */
708 ret = SSL_set_cipher_list(ssock->ossl_ssl, buf);
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000709 if (ret < 1) {
710 pj_status_t status;
711 GET_SSL_STATUS(status);
712 return status;
713 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000714
715 return PJ_SUCCESS;
716}
717
718
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000719/* Parse OpenSSL ASN1_TIME to pj_time_val and GMT info */
720static pj_bool_t parse_ossl_asn1_time(pj_time_val *tv, pj_bool_t *gmt,
721 const ASN1_TIME *tm)
722{
723 unsigned long parts[7] = {0};
724 char *p, *end;
725 unsigned len;
726 pj_bool_t utc;
727 pj_parsed_time pt;
728 int i;
729
730 utc = tm->type == V_ASN1_UTCTIME;
731 p = (char*)tm->data;
732 len = tm->length;
733 end = p + len - 1;
734
735 /* GMT */
736 *gmt = (*end == 'Z');
737
738 /* parse parts */
739 for (i = 0; i < 7 && p < end; ++i) {
740 pj_str_t st;
741
742 if (i==0 && !utc) {
743 /* 4 digits year part for non-UTC time format */
744 st.slen = 4;
745 } else if (i==6) {
746 /* fraction of seconds */
747 if (*p == '.') ++p;
748 st.slen = end - p + 1;
749 } else {
750 /* other parts always 2 digits length */
751 st.slen = 2;
752 }
753 st.ptr = p;
754
755 parts[i] = pj_strtoul(&st);
756 p += st.slen;
757 }
758
759 /* encode parts to pj_time_val */
760 pt.year = parts[0];
761 if (utc)
762 pt.year += (pt.year < 50)? 2000:1900;
763 pt.mon = parts[1] - 1;
764 pt.day = parts[2];
765 pt.hour = parts[3];
766 pt.min = parts[4];
767 pt.sec = parts[5];
768 pt.msec = parts[6];
769
770 pj_time_encode(&pt, tv);
771
772 return PJ_TRUE;
773}
774
775
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000776/* Get Common Name field string from a general name string */
777static void get_cn_from_gen_name(const pj_str_t *gen_name, pj_str_t *cn)
778{
779 pj_str_t CN_sign = {"/CN=", 4};
780 char *p, *q;
781
782 pj_bzero(cn, sizeof(cn));
783
784 p = pj_strstr(gen_name, &CN_sign);
785 if (!p)
786 return;
787
788 p += 4; /* shift pointer to value part */
789 pj_strset(cn, p, gen_name->slen - (p - gen_name->ptr));
790 q = pj_strchr(cn, '/');
791 if (q)
792 cn->slen = q - p;
793}
794
795
796/* Get certificate info from OpenSSL X509, in case the certificate info
797 * hal already populated, this function will check if the contents need
798 * to be updated by inspecting the issuer and the serial number.
799 */
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000800static void get_cert_info(pj_pool_t *pool, pj_ssl_cert_info *ci, X509 *x)
801{
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000802 pj_bool_t update_needed;
803 char buf[512];
804 pj_uint8_t serial_no[64] = {0}; /* should be >= sizeof(ci->serial_no) */
805 pj_uint8_t *p;
806 unsigned len;
807 GENERAL_NAMES *names = NULL;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000808
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000809 pj_assert(pool && ci && x);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000810
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000811 /* Get issuer */
812 X509_NAME_oneline(X509_get_issuer_name(x), buf, sizeof(buf));
813
814 /* Get serial no */
815 p = (pj_uint8_t*) M_ASN1_STRING_data(X509_get_serialNumber(x));
816 len = M_ASN1_STRING_length(X509_get_serialNumber(x));
817 if (len > sizeof(ci->serial_no))
818 len = sizeof(ci->serial_no);
819 pj_memcpy(serial_no + sizeof(ci->serial_no) - len, p, len);
820
821 /* Check if the contents need to be updated. */
822 update_needed = pj_strcmp2(&ci->issuer.info, buf) ||
823 pj_memcmp(ci->serial_no, serial_no, sizeof(ci->serial_no));
824 if (!update_needed)
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000825 return;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000826
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000827 /* Update cert info */
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000828
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000829 pj_bzero(ci, sizeof(pj_ssl_cert_info));
830
831 /* Version */
832 ci->version = X509_get_version(x) + 1;
833
834 /* Issuer */
835 pj_strdup2(pool, &ci->issuer.info, buf);
836 get_cn_from_gen_name(&ci->issuer.info, &ci->issuer.cn);
837
838 /* Serial number */
839 pj_memcpy(ci->serial_no, serial_no, sizeof(ci->serial_no));
840
841 /* Subject */
842 pj_strdup2(pool, &ci->subject.info,
843 X509_NAME_oneline(X509_get_subject_name(x),
844 buf, sizeof(buf)));
845 get_cn_from_gen_name(&ci->subject.info, &ci->subject.cn);
846
847 /* Validity */
848 parse_ossl_asn1_time(&ci->validity.start, &ci->validity.gmt,
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000849 X509_get_notBefore(x));
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000850 parse_ossl_asn1_time(&ci->validity.end, &ci->validity.gmt,
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000851 X509_get_notAfter(x));
852
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000853 /* Subject Alternative Name extension */
854 if (ci->version >= 3) {
855 names = (GENERAL_NAMES*) X509_get_ext_d2i(x, NID_subject_alt_name,
856 NULL, NULL);
857 }
858 if (names) {
859 unsigned i, cnt;
860
861 cnt = sk_GENERAL_NAME_num(names);
862 ci->subj_alt_name.entry = pj_pool_calloc(pool, cnt,
863 sizeof(*ci->subj_alt_name.entry));
864
865 for (i = 0; i < cnt; ++i) {
866 unsigned char *p = 0;
867 pj_ssl_cert_name_type type = PJ_SSL_CERT_NAME_UNKNOWN;
868 const GENERAL_NAME *name;
869
870 name = sk_GENERAL_NAME_value(names, i);
871
872 switch (name->type) {
873 case GEN_EMAIL:
874 len = ASN1_STRING_to_UTF8(&p, name->d.ia5);
875 type = PJ_SSL_CERT_NAME_RFC822;
876 break;
877 case GEN_DNS:
878 len = ASN1_STRING_to_UTF8(&p, name->d.ia5);
879 type = PJ_SSL_CERT_NAME_DNS;
880 break;
881 case GEN_URI:
882 len = ASN1_STRING_to_UTF8(&p, name->d.ia5);
883 type = PJ_SSL_CERT_NAME_URI;
884 break;
885 case GEN_IPADD:
886 p = ASN1_STRING_data(name->d.ip);
887 len = ASN1_STRING_length(name->d.ip);
888 type = PJ_SSL_CERT_NAME_IP;
889 break;
890 default:
891 break;
892 }
893
894 if (p && len && type != PJ_SSL_CERT_NAME_UNKNOWN) {
895 ci->subj_alt_name.entry[ci->subj_alt_name.cnt].type = type;
896 if (type == PJ_SSL_CERT_NAME_IP) {
897 int af = pj_AF_INET();
898 if (len == sizeof(pj_in6_addr)) af = pj_AF_INET6();
899 pj_inet_ntop2(af, p, buf, sizeof(buf));
900 pj_strdup2(pool,
901 &ci->subj_alt_name.entry[ci->subj_alt_name.cnt].name,
902 buf);
903 } else {
904 pj_strdup2(pool,
905 &ci->subj_alt_name.entry[ci->subj_alt_name.cnt].name,
906 (char*)p);
907 OPENSSL_free(p);
908 }
909 ci->subj_alt_name.cnt++;
910 }
911 }
912 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000913}
914
915
916/* Update local & remote certificates info. This function should be
917 * called after handshake or renegotiation successfully completed.
918 */
919static void update_certs_info(pj_ssl_sock_t *ssock)
920{
921 X509 *x;
922
923 pj_assert(ssock->ssl_state == SSL_STATE_ESTABLISHED);
924
925 /* Active local certificate */
926 x = SSL_get_certificate(ssock->ossl_ssl);
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000927 if (x) {
928 get_cert_info(ssock->pool, &ssock->local_cert_info, x);
929 /* Don't free local's X509! */
930 } else {
931 pj_bzero(&ssock->local_cert_info, sizeof(pj_ssl_cert_info));
932 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000933
934 /* Active remote certificate */
935 x = SSL_get_peer_certificate(ssock->ossl_ssl);
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000936 if (x) {
937 get_cert_info(ssock->pool, &ssock->remote_cert_info, x);
938 /* Free peer's X509 */
939 X509_free(x);
940 } else {
941 pj_bzero(&ssock->remote_cert_info, sizeof(pj_ssl_cert_info));
942 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000943}
944
945
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000946/* When handshake completed:
947 * - notify application
948 * - if handshake failed, reset SSL state
949 * - return PJ_FALSE when SSL socket instance is destroyed by application.
950 */
951static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock,
952 pj_status_t status)
953{
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000954 /* Cancel handshake timer */
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +0000955 if (ssock->timer.id == TIMER_HANDSHAKE_TIMEOUT) {
956 pj_timer_heap_cancel(ssock->param.timer_heap, &ssock->timer);
957 ssock->timer.id = TIMER_NONE;
958 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000959
960 /* Update certificates info on successful handshake */
961 if (status == PJ_SUCCESS)
962 update_certs_info(ssock);
963
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000964 /* Accepting */
965 if (ssock->is_server) {
966 if (status != PJ_SUCCESS) {
967 /* Handshake failed in accepting, destroy our self silently. */
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +0000968
969 char errmsg[PJ_ERR_MSG_SIZE];
970 char buf[PJ_INET6_ADDRSTRLEN+10];
971
972 pj_strerror(status, errmsg, sizeof(errmsg));
973 PJ_LOG(3,(ssock->pool->obj_name, "Handshake failed in accepting "
974 "%s: %s",
975 pj_sockaddr_print(&ssock->rem_addr, buf, sizeof(buf), 3),
976 errmsg));
977
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +0000978 /* Workaround for ticket #985 */
979#if defined(PJ_WIN32) && PJ_WIN32!=0
980 if (ssock->param.timer_heap) {
981 pj_time_val interval = {0, DELAYED_CLOSE_TIMEOUT};
982
983 reset_ssl_sock_state(ssock);
984
985 ssock->timer.id = TIMER_CLOSE;
986 pj_time_val_normalize(&interval);
987 if (pj_timer_heap_schedule(ssock->param.timer_heap,
988 &ssock->timer, &interval) != 0)
989 {
990 ssock->timer.id = TIMER_NONE;
991 pj_ssl_sock_close(ssock);
992 }
993 } else
994#endif /* PJ_WIN32 */
995 {
996 pj_ssl_sock_close(ssock);
997 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000998 return PJ_FALSE;
999 }
1000 /* Notify application the newly accepted SSL socket */
1001 if (ssock->param.cb.on_accept_complete) {
1002 pj_bool_t ret;
1003 ret = (*ssock->param.cb.on_accept_complete)
1004 (ssock->parent, ssock, (pj_sockaddr_t*)&ssock->rem_addr,
1005 pj_sockaddr_get_len((pj_sockaddr_t*)&ssock->rem_addr));
1006 if (ret == PJ_FALSE)
1007 return PJ_FALSE;
1008 }
1009 }
1010
1011 /* Connecting */
1012 else {
Nanang Izzuddin48747632009-11-20 07:48:41 +00001013 /* On failure, reset SSL socket state first, as app may try to
1014 * reconnect in the callback.
1015 */
1016 if (status != PJ_SUCCESS) {
1017 reset_ssl_sock_state(ssock);
1018 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001019 if (ssock->param.cb.on_connect_complete) {
1020 pj_bool_t ret;
1021 ret = (*ssock->param.cb.on_connect_complete)(ssock, status);
1022 if (ret == PJ_FALSE)
1023 return PJ_FALSE;
1024 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001025 }
1026
1027 return PJ_TRUE;
1028}
1029
1030/* Flush write BIO to network socket. Note that any access to write BIO
1031 * MUST be serialized, so mutex protection must cover any call to OpenSSL
1032 * API (that possibly generate data for write BIO) along with the call to
1033 * this function (flushing all data in write BIO generated by above
1034 * OpenSSL API call).
1035 */
1036static pj_status_t flush_write_bio(pj_ssl_sock_t *ssock,
1037 pj_ioqueue_op_key_t *send_key,
1038 pj_size_t orig_len,
1039 unsigned flags)
1040{
1041 char *data;
1042 pj_ssize_t len;
1043
1044 write_state_t *write_st = &ssock->write_state;
1045 write_data_t *wdata;
1046 pj_size_t avail_len, needed_len, skipped_len = 0;
1047 pj_status_t status;
1048
1049 /* Check if there is data in write BIO, flush it if any */
1050 if (!BIO_pending(ssock->ossl_wbio))
1051 return PJ_SUCCESS;
1052
1053 /* Get data and its length */
1054 len = BIO_get_mem_data(ssock->ossl_wbio, &data);
1055 if (len == 0)
1056 return PJ_SUCCESS;
1057
1058 /* Calculate buffer size needed, and align it to 8 */
1059 needed_len = len + sizeof(write_data_t);
1060 needed_len = ((needed_len + 7) >> 3) << 3;
1061
1062 /* Check buffer availability */
1063 avail_len = write_st->max_len - write_st->len;
1064 if (avail_len < needed_len)
1065 return PJ_ENOMEM;
1066
1067 /* More buffer availability check, note that the write data must be in
1068 * a contigue buffer.
1069 */
1070 if (write_st->len == 0) {
1071
1072 write_st->start = write_st->buf;
1073 wdata = (write_data_t*)write_st->start;
1074
1075 } else {
1076
1077 char *reg1, *reg2;
1078 pj_size_t reg1_len, reg2_len;
1079
1080 /* Unused slots may be wrapped/splitted into two regions, so let's
1081 * analyze them if any region can hold the write data.
1082 */
1083 reg1 = write_st->start + write_st->len;
1084 if (reg1 >= write_st->buf + write_st->max_len)
1085 reg1 -= write_st->max_len;
1086 reg1_len = write_st->max_len - write_st->len;
1087 if (reg1 + reg1_len > write_st->buf + write_st->max_len) {
1088 reg1_len = write_st->buf + write_st->max_len - reg1;
1089 reg2 = write_st->buf;
1090 reg2_len = write_st->start - write_st->buf;
1091 } else {
1092 reg2 = NULL;
1093 reg2_len = 0;
1094 }
1095 avail_len = PJ_MAX(reg1_len, reg2_len);
1096 if (avail_len < needed_len)
1097 return PJ_ENOMEM;
1098
1099 /* Get write data pointer and update buffer length */
1100 if (reg1_len >= needed_len) {
1101 wdata = (write_data_t*)reg1;
1102 } else {
1103 wdata = (write_data_t*)reg2;
1104 /* Unused slot in region 1 is skipped as current write data
1105 * doesn't fit it.
1106 */
1107 skipped_len = reg1_len;
1108 }
1109 }
1110
1111 /* Copy the data and set its properties into the buffer */
1112 pj_bzero(wdata, sizeof(write_data_t));
1113 wdata->app_key = send_key;
1114 wdata->record_len = needed_len;
1115 wdata->data_len = len;
1116 wdata->plain_data_len = orig_len;
1117 wdata->flags = flags;
1118 pj_memcpy(&wdata->data, data, len);
1119
1120 /* Send it */
1121 if (ssock->param.sock_type == pj_SOCK_STREAM()) {
1122 status = pj_activesock_send(ssock->asock, &wdata->key,
1123 wdata->data.content, &len,
1124 flags);
1125 } else {
1126 status = pj_activesock_sendto(ssock->asock, &wdata->key,
1127 wdata->data.content, &len,
1128 flags,
1129 (pj_sockaddr_t*)&ssock->rem_addr,
1130 ssock->addr_len);
1131 }
1132
1133 /* Oh no, EWOULDBLOCK! */
1134 if (status == PJ_STATUS_FROM_OS(OSERR_EWOULDBLOCK)) {
1135 /* Just return PJ_SUCCESS here, the pending data will be sent in next
1136 * call of this function since the data is still stored in write BIO.
1137 */
1138 return PJ_SUCCESS;
1139 }
1140
1141 /* Reset write BIO after flushed */
1142 BIO_reset(ssock->ossl_wbio);
1143
1144 if (status == PJ_EPENDING) {
1145 /* Update write state */
1146 pj_assert(skipped_len==0 || write_st->last_data);
1147 write_st->len += needed_len + skipped_len;
1148 if (write_st->last_data)
1149 write_st->last_data->record_len += skipped_len;
1150 write_st->last_data = wdata;
1151 }
1152
1153 return status;
1154}
1155
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001156
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001157static void on_timer(pj_timer_heap_t *th, struct pj_timer_entry *te)
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001158{
1159 pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)te->user_data;
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001160 int timer_id = te->id;
1161
1162 te->id = TIMER_NONE;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001163
1164 PJ_UNUSED_ARG(th);
1165
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001166 switch (timer_id) {
1167 case TIMER_HANDSHAKE_TIMEOUT:
Nanang Izzuddina7719d32010-03-06 02:04:52 +00001168 PJ_LOG(1,(ssock->pool->obj_name, "SSL timeout after %d.%ds",
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001169 ssock->param.timeout.sec, ssock->param.timeout.msec));
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001170
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001171 on_handshake_complete(ssock, PJ_ETIMEDOUT);
1172 break;
1173 case TIMER_CLOSE:
1174 pj_ssl_sock_close(ssock);
1175 break;
1176 default:
1177 pj_assert(!"Unknown timer");
1178 break;
1179 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001180}
1181
1182
1183/* Asynchronouse handshake */
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001184static pj_status_t do_handshake(pj_ssl_sock_t *ssock)
1185{
1186 pj_status_t status;
1187 int err;
1188
1189 pj_lock_acquire(ssock->write_mutex);
1190
1191 /* Perform SSL handshake */
1192 err = SSL_do_handshake(ssock->ossl_ssl);
1193 if (err < 0) {
1194 err = SSL_get_error(ssock->ossl_ssl, err);
1195 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ)
1196 {
1197 /* Handshake fails */
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00001198 GET_SSL_STATUS(status);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001199 pj_lock_release(ssock->write_mutex);
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00001200 return status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001201 }
1202 }
1203
1204 /* SSL_do_handshake() may put some pending data into SSL write BIO,
1205 * flush it if any.
1206 */
1207 status = flush_write_bio(ssock, &ssock->handshake_op_key, 0, 0);
1208 if (status != PJ_SUCCESS && status != PJ_EPENDING) {
1209 pj_lock_release(ssock->write_mutex);
1210 return status;
1211 }
1212
1213 pj_lock_release(ssock->write_mutex);
1214
1215 /* Check if handshake has been completed */
1216 if (SSL_is_init_finished(ssock->ossl_ssl)) {
1217 ssock->ssl_state = SSL_STATE_ESTABLISHED;
1218 return PJ_SUCCESS;
1219 }
1220
1221 return PJ_EPENDING;
1222}
1223
1224
1225/*
1226 *******************************************************************
1227 * Active socket callbacks.
1228 *******************************************************************
1229 */
1230
1231static pj_bool_t asock_on_data_read (pj_activesock_t *asock,
1232 void *data,
1233 pj_size_t size,
1234 pj_status_t status,
1235 pj_size_t *remainder)
1236{
1237 pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
1238 pj_activesock_get_user_data(asock);
1239 pj_size_t nwritten;
1240
1241 /* Socket error or closed */
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001242 if (data && size > 0) {
1243 /* Consume the whole data */
1244 nwritten = BIO_write(ssock->ossl_rbio, data, size);
1245 if (nwritten < size) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00001246 GET_SSL_STATUS(status);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001247 goto on_error;
1248 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001249 }
1250
1251 /* Check if SSL handshake hasn't finished yet */
1252 if (ssock->ssl_state == SSL_STATE_HANDSHAKING) {
1253 pj_bool_t ret = PJ_TRUE;
1254
1255 if (status == PJ_SUCCESS)
1256 status = do_handshake(ssock);
1257
1258 /* Not pending is either success or failed */
1259 if (status != PJ_EPENDING)
1260 ret = on_handshake_complete(ssock, status);
1261
1262 return ret;
1263 }
1264
1265 /* See if there is any decrypted data for the application */
1266 if (ssock->read_started) {
1267 do {
1268 read_data_t *buf = *(OFFSET_OF_READ_DATA_PTR(ssock, data));
1269 void *data_ = (pj_int8_t*)buf->data + buf->len;
1270 int size_ = ssock->read_size - buf->len;
1271
1272 /* SSL_read() may write some data to BIO write when re-negotiation
1273 * is on progress, so let's protect it with write mutex.
1274 */
1275 pj_lock_acquire(ssock->write_mutex);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001276 size_ = SSL_read(ssock->ossl_ssl, data_, size_);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001277 pj_lock_release(ssock->write_mutex);
1278
1279 if (size_ > 0 || status != PJ_SUCCESS) {
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001280 if (ssock->param.cb.on_data_read) {
1281 pj_bool_t ret;
1282 pj_size_t remainder_ = 0;
1283
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001284 if (size_ > 0)
1285 buf->len += size_;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001286
1287 ret = (*ssock->param.cb.on_data_read)(ssock, buf->data,
1288 buf->len, status,
1289 &remainder_);
1290 if (!ret) {
1291 /* We've been destroyed */
1292 return PJ_FALSE;
1293 }
1294
1295 /* Application may have left some data to be consumed
1296 * later.
1297 */
1298 buf->len = remainder_;
1299 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001300
1301 /* Active socket signalled connection closed/error, this has
1302 * been signalled to the application along with any remaining
1303 * buffer. So, let's just reset SSL socket now.
1304 */
1305 if (status != PJ_SUCCESS) {
1306 reset_ssl_sock_state(ssock);
1307 return PJ_FALSE;
1308 }
1309
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001310 } else {
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001311
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001312 int err = SSL_get_error(ssock->ossl_ssl, size);
1313
1314 /* SSL might just return SSL_ERROR_WANT_READ in
1315 * re-negotiation.
1316 */
1317 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ)
1318 {
1319 /* Reset SSL socket state, then return PJ_FALSE */
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00001320 GET_SSL_STATUS(status);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001321 reset_ssl_sock_state(ssock);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001322 goto on_error;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001323 }
1324
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001325 status = do_handshake(ssock);
1326 if (status == PJ_SUCCESS) {
1327 /* Renegotiation completed */
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001328
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001329 /* Update certificates */
1330 update_certs_info(ssock);
1331
1332 pj_lock_acquire(ssock->write_mutex);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001333 status = flush_delayed_send(ssock);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001334 pj_lock_release(ssock->write_mutex);
1335
1336 if (status != PJ_SUCCESS && status != PJ_EPENDING) {
Benny Prijono7ee05332009-11-09 04:34:50 +00001337 PJ_PERROR(1,(ssock->pool->obj_name, status,
1338 "Failed to flush delayed send"));
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001339 goto on_error;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001340 }
1341 } else if (status != PJ_EPENDING) {
Benny Prijono7ee05332009-11-09 04:34:50 +00001342 PJ_PERROR(1,(ssock->pool->obj_name, status,
1343 "Renegotiation failed"));
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001344 goto on_error;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001345 }
1346
1347 break;
1348 }
1349 } while (1);
1350 }
1351
1352 return PJ_TRUE;
1353
1354on_error:
1355 if (ssock->ssl_state == SSL_STATE_HANDSHAKING)
1356 return on_handshake_complete(ssock, status);
1357
1358 if (ssock->read_started && ssock->param.cb.on_data_read) {
1359 pj_bool_t ret;
1360 ret = (*ssock->param.cb.on_data_read)(ssock, NULL, 0, status,
1361 remainder);
1362 if (!ret) {
1363 /* We've been destroyed */
1364 return PJ_FALSE;
1365 }
1366 }
1367
1368 reset_ssl_sock_state(ssock);
1369 return PJ_FALSE;
1370}
1371
1372
1373static pj_bool_t asock_on_data_sent (pj_activesock_t *asock,
1374 pj_ioqueue_op_key_t *send_key,
1375 pj_ssize_t sent)
1376{
1377 pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
1378 pj_activesock_get_user_data(asock);
1379
1380 PJ_UNUSED_ARG(send_key);
1381 PJ_UNUSED_ARG(sent);
1382
1383 if (ssock->ssl_state == SSL_STATE_HANDSHAKING) {
1384 /* Initial handshaking */
1385 pj_status_t status;
1386
1387 status = do_handshake(ssock);
1388 /* Not pending is either success or failed */
1389 if (status != PJ_EPENDING)
1390 return on_handshake_complete(ssock, status);
1391
1392 } else if (send_key != &ssock->handshake_op_key) {
1393 /* Some data has been sent, notify application */
1394 write_data_t *wdata = (write_data_t*)send_key;
1395 if (ssock->param.cb.on_data_sent) {
1396 pj_bool_t ret;
1397 ret = (*ssock->param.cb.on_data_sent)(ssock, wdata->app_key,
1398 wdata->plain_data_len);
1399 if (!ret) {
1400 /* We've been destroyed */
1401 return PJ_FALSE;
1402 }
1403 }
1404
1405 /* Update write buffer state */
1406 pj_lock_acquire(ssock->write_mutex);
1407 ssock->write_state.start += wdata->record_len;
1408 ssock->write_state.len -= wdata->record_len;
1409 if (ssock->write_state.last_data == wdata) {
1410 pj_assert(ssock->write_state.len == 0);
1411 ssock->write_state.last_data = NULL;
1412 }
1413 pj_lock_release(ssock->write_mutex);
1414
1415 } else {
1416 /* SSL re-negotiation is on-progress, just do nothing */
1417 }
1418
1419 return PJ_TRUE;
1420}
1421
1422
1423static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
1424 pj_sock_t newsock,
1425 const pj_sockaddr_t *src_addr,
1426 int src_addr_len)
1427{
1428 pj_ssl_sock_t *ssock_parent = (pj_ssl_sock_t*)
1429 pj_activesock_get_user_data(asock);
1430 pj_ssl_sock_t *ssock;
1431 pj_activesock_cb asock_cb;
1432 pj_activesock_cfg asock_cfg;
1433 unsigned i;
1434 pj_status_t status;
1435
1436 PJ_UNUSED_ARG(src_addr_len);
1437
1438 /* Create new SSL socket instance */
1439 status = pj_ssl_sock_create(ssock_parent->pool, &ssock_parent->param,
1440 &ssock);
1441 if (status != PJ_SUCCESS)
1442 goto on_return;
1443
1444 /* Update new SSL socket attributes */
1445 ssock->sock = newsock;
1446 ssock->parent = ssock_parent;
1447 ssock->is_server = PJ_TRUE;
1448 if (ssock_parent->cert) {
1449 status = pj_ssl_sock_set_certificate(ssock, ssock->pool,
1450 ssock_parent->cert);
1451 if (status != PJ_SUCCESS)
1452 goto on_return;
1453 }
1454
Benny Prijonoa25bc9d2009-11-09 08:51:34 +00001455 /* Apply QoS, if specified */
1456 status = pj_sock_apply_qos2(ssock->sock, ssock->param.qos_type,
1457 &ssock->param.qos_params, 1,
1458 ssock->pool->obj_name, NULL);
1459 if (status != PJ_SUCCESS && !ssock->param.qos_ignore_error)
1460 goto on_return;
1461
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001462 /* Update local address */
1463 ssock->addr_len = src_addr_len;
1464 status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,
1465 &ssock->addr_len);
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00001466 if (status != PJ_SUCCESS) {
1467 /* This fails on few envs, e.g: win IOCP, just tolerate this and
1468 * use parent local address instead.
1469 */
1470 pj_sockaddr_cp(&ssock->local_addr, &ssock_parent->local_addr);
1471 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001472
1473 /* Set remote address */
1474 pj_sockaddr_cp(&ssock->rem_addr, src_addr);
1475
1476 /* Create SSL context */
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +00001477 status = create_ssl(ssock);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001478 if (status != PJ_SUCCESS)
1479 goto on_return;
1480
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001481 /* Prepare read buffer */
1482 ssock->asock_rbuf = (void**)pj_pool_calloc(ssock->pool,
1483 ssock->param.async_cnt,
1484 sizeof(void*));
1485 for (i = 0; i<ssock->param.async_cnt; ++i) {
1486 ssock->asock_rbuf[i] = (void*) pj_pool_alloc(
1487 ssock->pool,
1488 ssock->param.read_buffer_size +
1489 sizeof(read_data_t*));
1490 }
1491
1492 /* Create active socket */
1493 pj_activesock_cfg_default(&asock_cfg);
1494 asock_cfg.async_cnt = ssock->param.async_cnt;
1495 asock_cfg.concurrency = ssock->param.concurrency;
1496 asock_cfg.whole_data = PJ_TRUE;
1497
1498 pj_bzero(&asock_cb, sizeof(asock_cb));
1499 asock_cb.on_data_read = asock_on_data_read;
1500 asock_cb.on_data_sent = asock_on_data_sent;
1501
1502 status = pj_activesock_create(ssock->pool,
1503 ssock->sock,
1504 ssock->param.sock_type,
1505 &asock_cfg,
1506 ssock->param.ioqueue,
1507 &asock_cb,
1508 ssock,
1509 &ssock->asock);
1510
1511 if (status != PJ_SUCCESS)
1512 goto on_return;
1513
1514 /* Start read */
1515 status = pj_activesock_start_read2(ssock->asock, ssock->pool,
1516 ssock->param.read_buffer_size,
1517 ssock->asock_rbuf,
1518 PJ_IOQUEUE_ALWAYS_ASYNC);
1519 if (status != PJ_SUCCESS)
1520 goto on_return;
1521
1522 /* Prepare write/send state */
1523 pj_assert(ssock->write_state.max_len == 0);
1524 ssock->write_state.buf = (char*)
1525 pj_pool_alloc(ssock->pool,
1526 ssock->param.send_buffer_size);
1527 ssock->write_state.max_len = ssock->param.send_buffer_size;
1528 ssock->write_state.start = ssock->write_state.buf;
1529 ssock->write_state.len = 0;
1530
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001531 /* Start handshake timer */
1532 if (ssock->param.timer_heap && (ssock->param.timeout.sec != 0 ||
1533 ssock->param.timeout.msec != 0))
1534 {
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001535 pj_assert(ssock->timer.id == TIMER_NONE);
1536 ssock->timer.id = TIMER_HANDSHAKE_TIMEOUT;
1537 status = pj_timer_heap_schedule(ssock->param.timer_heap,
1538 &ssock->timer,
1539 &ssock->param.timeout);
1540 if (status != PJ_SUCCESS)
1541 ssock->timer.id = TIMER_NONE;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001542 }
1543
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001544 /* Start SSL handshake */
1545 ssock->ssl_state = SSL_STATE_HANDSHAKING;
1546 SSL_set_accept_state(ssock->ossl_ssl);
1547 status = do_handshake(ssock);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001548
1549on_return:
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00001550 if (ssock && status != PJ_EPENDING)
1551 on_handshake_complete(ssock, status);
1552
1553 /* Must return PJ_TRUE whatever happened, as active socket must
1554 * continue listening.
1555 */
1556 return PJ_TRUE;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001557}
1558
1559
1560static pj_bool_t asock_on_connect_complete (pj_activesock_t *asock,
1561 pj_status_t status)
1562{
1563 pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
1564 pj_activesock_get_user_data(asock);
1565 unsigned i;
1566
1567 if (status != PJ_SUCCESS)
1568 goto on_return;
1569
1570 /* Update local address */
1571 ssock->addr_len = sizeof(pj_sockaddr);
1572 status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,
1573 &ssock->addr_len);
1574 if (status != PJ_SUCCESS)
1575 goto on_return;
1576
1577 /* Create SSL context */
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +00001578 status = create_ssl(ssock);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001579 if (status != PJ_SUCCESS)
1580 goto on_return;
1581
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001582 /* Prepare read buffer */
1583 ssock->asock_rbuf = (void**)pj_pool_calloc(ssock->pool,
1584 ssock->param.async_cnt,
1585 sizeof(void*));
1586 for (i = 0; i<ssock->param.async_cnt; ++i) {
1587 ssock->asock_rbuf[i] = (void*) pj_pool_alloc(
1588 ssock->pool,
1589 ssock->param.read_buffer_size +
1590 sizeof(read_data_t*));
1591 }
1592
1593 /* Start read */
1594 status = pj_activesock_start_read2(ssock->asock, ssock->pool,
1595 ssock->param.read_buffer_size,
1596 ssock->asock_rbuf,
1597 PJ_IOQUEUE_ALWAYS_ASYNC);
1598 if (status != PJ_SUCCESS)
1599 goto on_return;
1600
1601 /* Prepare write/send state */
1602 pj_assert(ssock->write_state.max_len == 0);
1603 ssock->write_state.buf = (char*)
1604 pj_pool_alloc(ssock->pool,
1605 ssock->param.send_buffer_size);
1606 ssock->write_state.max_len = ssock->param.send_buffer_size;
1607 ssock->write_state.start = ssock->write_state.buf;
1608 ssock->write_state.len = 0;
1609
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001610#ifdef SSL_set_tlsext_host_name
1611 /* Set server name to connect */
1612 if (ssock->param.server_name.slen) {
1613 /* Server name is null terminated already */
1614 if (!SSL_set_tlsext_host_name(ssock->ossl_ssl,
1615 ssock->param.server_name.ptr))
1616 {
1617 char err_str[PJ_ERR_MSG_SIZE];
1618
1619 ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
1620 PJ_LOG(3,(ssock->pool->obj_name, "SSL_set_tlsext_host_name() "
1621 "failed: %s", err_str));
1622 }
1623 }
1624#endif
1625
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001626 /* Start SSL handshake */
1627 ssock->ssl_state = SSL_STATE_HANDSHAKING;
1628 SSL_set_connect_state(ssock->ossl_ssl);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001629
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001630 status = do_handshake(ssock);
1631 if (status != PJ_EPENDING)
1632 goto on_return;
1633
1634 return PJ_TRUE;
1635
1636on_return:
1637 return on_handshake_complete(ssock, status);
1638}
1639
1640
1641
1642/*
1643 *******************************************************************
1644 * API
1645 *******************************************************************
1646 */
1647
1648/* Load credentials from files. */
1649PJ_DEF(pj_status_t) pj_ssl_cert_load_from_files (pj_pool_t *pool,
1650 const pj_str_t *CA_file,
1651 const pj_str_t *cert_file,
1652 const pj_str_t *privkey_file,
1653 const pj_str_t *privkey_pass,
1654 pj_ssl_cert_t **p_cert)
1655{
1656 pj_ssl_cert_t *cert;
1657
1658 PJ_ASSERT_RETURN(pool && CA_file && cert_file && privkey_file, PJ_EINVAL);
1659
1660 cert = PJ_POOL_ZALLOC_T(pool, pj_ssl_cert_t);
1661 pj_strdup_with_null(pool, &cert->CA_file, CA_file);
1662 pj_strdup_with_null(pool, &cert->cert_file, cert_file);
1663 pj_strdup_with_null(pool, &cert->privkey_file, privkey_file);
1664 pj_strdup_with_null(pool, &cert->privkey_pass, privkey_pass);
1665
1666 *p_cert = cert;
1667
1668 return PJ_SUCCESS;
1669}
1670
1671
1672/* Set SSL socket credentials. */
1673PJ_DECL(pj_status_t) pj_ssl_sock_set_certificate(
1674 pj_ssl_sock_t *ssock,
1675 pj_pool_t *pool,
1676 const pj_ssl_cert_t *cert)
1677{
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001678 pj_ssl_cert_t *cert_;
1679
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001680 PJ_ASSERT_RETURN(ssock && pool && cert, PJ_EINVAL);
1681
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001682 cert_ = PJ_POOL_ZALLOC_T(pool, pj_ssl_cert_t);
1683 pj_memcpy(cert_, cert, sizeof(cert));
1684 pj_strdup_with_null(pool, &cert_->CA_file, &cert->CA_file);
1685 pj_strdup_with_null(pool, &cert_->cert_file, &cert->cert_file);
1686 pj_strdup_with_null(pool, &cert_->privkey_file, &cert->privkey_file);
1687 pj_strdup_with_null(pool, &cert_->privkey_pass, &cert->privkey_pass);
1688
1689 ssock->cert = cert_;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001690
1691 return PJ_SUCCESS;
1692}
1693
1694
1695/* Get available ciphers. */
1696PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables(pj_ssl_cipher ciphers[],
1697 unsigned *cipher_num)
1698{
1699 unsigned i;
1700
1701 PJ_ASSERT_RETURN(ciphers && cipher_num, PJ_EINVAL);
1702
1703 if (openssl_cipher_num == 0) {
1704 init_openssl();
1705 shutdown_openssl();
1706 }
1707
1708 if (openssl_cipher_num == 0)
1709 return PJ_ENOTFOUND;
1710
1711 *cipher_num = PJ_MIN(*cipher_num, openssl_cipher_num);
1712
1713 for (i = 0; i < *cipher_num; ++i)
1714 ciphers[i] = openssl_ciphers[i];
1715
1716 return PJ_SUCCESS;
1717}
1718
1719
1720/*
1721 * Create SSL socket instance.
1722 */
1723PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool,
1724 const pj_ssl_sock_param *param,
1725 pj_ssl_sock_t **p_ssock)
1726{
1727 pj_ssl_sock_t *ssock;
1728 pj_status_t status;
1729
1730 PJ_ASSERT_RETURN(pool && param && p_ssock, PJ_EINVAL);
1731 PJ_ASSERT_RETURN(param->sock_type == pj_SOCK_STREAM(), PJ_ENOTSUP);
1732
1733 pool = pj_pool_create(pool->factory, "ssl%p", 512, 512, NULL);
1734
1735 /* Create secure socket */
1736 ssock = PJ_POOL_ZALLOC_T(pool, pj_ssl_sock_t);
1737 ssock->pool = pool;
1738 ssock->sock = PJ_INVALID_SOCKET;
1739 ssock->ssl_state = SSL_STATE_NULL;
1740 pj_list_init(&ssock->write_pending);
1741 pj_list_init(&ssock->write_pending_empty);
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001742 pj_timer_entry_init(&ssock->timer, 0, ssock, &on_timer);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001743
1744 /* Create secure socket mutex */
1745 status = pj_lock_create_recursive_mutex(pool, pool->obj_name,
1746 &ssock->write_mutex);
1747 if (status != PJ_SUCCESS)
1748 return status;
1749
1750 /* Init secure socket param */
1751 ssock->param = *param;
1752 ssock->param.read_buffer_size = ((ssock->param.read_buffer_size+7)>>3)<<3;
1753 if (param->ciphers_num > 0) {
1754 unsigned i;
1755 ssock->param.ciphers = (pj_ssl_cipher*)
1756 pj_pool_calloc(pool, param->ciphers_num,
1757 sizeof(pj_ssl_cipher));
1758 for (i = 0; i < param->ciphers_num; ++i)
1759 ssock->param.ciphers[i] = param->ciphers[i];
1760 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001761
1762 /* Server name must be null-terminated */
1763 pj_strdup_with_null(pool, &ssock->param.server_name,
1764 &param->server_name);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001765
1766 /* Finally */
1767 *p_ssock = ssock;
1768
1769 return PJ_SUCCESS;
1770}
1771
1772
1773/*
1774 * Close the secure socket. This will unregister the socket from the
1775 * ioqueue and ultimately close the socket.
1776 */
1777PJ_DEF(pj_status_t) pj_ssl_sock_close(pj_ssl_sock_t *ssock)
1778{
1779 pj_pool_t *pool;
1780
1781 PJ_ASSERT_RETURN(ssock, PJ_EINVAL);
1782
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001783 if (!ssock->pool)
1784 return PJ_SUCCESS;
1785
1786 if (ssock->timer.id != TIMER_NONE) {
1787 pj_timer_heap_cancel(ssock->param.timer_heap, &ssock->timer);
1788 ssock->timer.id = TIMER_NONE;
1789 }
1790
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001791 reset_ssl_sock_state(ssock);
1792 pj_lock_destroy(ssock->write_mutex);
1793
1794 pool = ssock->pool;
1795 ssock->pool = NULL;
1796 if (pool)
1797 pj_pool_release(pool);
1798
1799 return PJ_SUCCESS;
1800}
1801
1802
1803/*
1804 * Associate arbitrary data with the secure socket.
1805 */
1806PJ_DEF(pj_status_t) pj_ssl_sock_set_user_data(pj_ssl_sock_t *ssock,
1807 void *user_data)
1808{
1809 PJ_ASSERT_RETURN(ssock, PJ_EINVAL);
1810
1811 ssock->param.user_data = user_data;
1812 return PJ_SUCCESS;
1813}
1814
1815
1816/*
1817 * Retrieve the user data previously associated with this secure
1818 * socket.
1819 */
1820PJ_DEF(void*) pj_ssl_sock_get_user_data(pj_ssl_sock_t *ssock)
1821{
1822 PJ_ASSERT_RETURN(ssock, NULL);
1823
1824 return ssock->param.user_data;
1825}
1826
1827
1828/*
1829 * Retrieve the local address and port used by specified SSL socket.
1830 */
1831PJ_DEF(pj_status_t) pj_ssl_sock_get_info (pj_ssl_sock_t *ssock,
1832 pj_ssl_sock_info *info)
1833{
1834 pj_bzero(info, sizeof(*info));
1835
1836 /* Established flag */
1837 info->established = (ssock->ssl_state == SSL_STATE_ESTABLISHED);
1838
1839 /* Protocol */
1840 info->proto = ssock->param.proto;
1841
1842 /* Local address */
1843 pj_sockaddr_cp(&info->local_addr, &ssock->local_addr);
1844
1845 if (info->established) {
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001846 const SSL_CIPHER *cipher;
1847
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +00001848 /* Current cipher */
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001849 cipher = SSL_get_current_cipher(ssock->ossl_ssl);
1850 info->cipher = (cipher->id & 0x00FFFFFF);
1851
1852 /* Remote address */
1853 pj_sockaddr_cp(&info->remote_addr, &ssock->rem_addr);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001854
1855 /* Certificates info */
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +00001856 info->local_cert_info = &ssock->local_cert_info;
1857 info->remote_cert_info = &ssock->remote_cert_info;
1858
1859 /* Verification status */
1860 info->verify_status = ssock->verify_status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001861 }
1862
1863 return PJ_SUCCESS;
1864}
1865
1866
1867/*
1868 * Starts read operation on this secure socket.
1869 */
1870PJ_DEF(pj_status_t) pj_ssl_sock_start_read (pj_ssl_sock_t *ssock,
1871 pj_pool_t *pool,
1872 unsigned buff_size,
1873 pj_uint32_t flags)
1874{
1875 void **readbuf;
1876 unsigned i;
1877
1878 PJ_ASSERT_RETURN(ssock && pool && buff_size, PJ_EINVAL);
1879 PJ_ASSERT_RETURN(ssock->ssl_state==SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
1880
1881 readbuf = (void**) pj_pool_calloc(pool, ssock->param.async_cnt,
1882 sizeof(void*));
1883
1884 for (i=0; i<ssock->param.async_cnt; ++i) {
1885 readbuf[i] = pj_pool_alloc(pool, buff_size);
1886 }
1887
1888 return pj_ssl_sock_start_read2(ssock, pool, buff_size,
1889 readbuf, flags);
1890}
1891
1892
1893/*
1894 * Same as #pj_ssl_sock_start_read(), except that the application
1895 * supplies the buffers for the read operation so that the acive socket
1896 * does not have to allocate the buffers.
1897 */
1898PJ_DEF(pj_status_t) pj_ssl_sock_start_read2 (pj_ssl_sock_t *ssock,
1899 pj_pool_t *pool,
1900 unsigned buff_size,
1901 void *readbuf[],
1902 pj_uint32_t flags)
1903{
1904 unsigned i;
1905
1906 PJ_ASSERT_RETURN(ssock && pool && buff_size && readbuf, PJ_EINVAL);
1907 PJ_ASSERT_RETURN(ssock->ssl_state==SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
1908
1909 /* Create SSL socket read buffer */
1910 ssock->ssock_rbuf = (read_data_t*)pj_pool_calloc(pool,
1911 ssock->param.async_cnt,
1912 sizeof(read_data_t));
1913
1914 /* Store SSL socket read buffer pointer in the activesock read buffer */
1915 for (i=0; i<ssock->param.async_cnt; ++i) {
1916 read_data_t **p_ssock_rbuf =
1917 OFFSET_OF_READ_DATA_PTR(ssock, ssock->asock_rbuf[i]);
1918
1919 ssock->ssock_rbuf[i].data = readbuf[i];
1920 ssock->ssock_rbuf[i].len = 0;
1921
1922 *p_ssock_rbuf = &ssock->ssock_rbuf[i];
1923 }
1924
1925 ssock->read_size = buff_size;
1926 ssock->read_started = PJ_TRUE;
1927 ssock->read_flags = flags;
1928
1929 return PJ_SUCCESS;
1930}
1931
1932
1933/*
1934 * Same as pj_ssl_sock_start_read(), except that this function is used
1935 * only for datagram sockets, and it will trigger \a on_data_recvfrom()
1936 * callback instead.
1937 */
1938PJ_DEF(pj_status_t) pj_ssl_sock_start_recvfrom (pj_ssl_sock_t *ssock,
1939 pj_pool_t *pool,
1940 unsigned buff_size,
1941 pj_uint32_t flags)
1942{
1943 PJ_UNUSED_ARG(ssock);
1944 PJ_UNUSED_ARG(pool);
1945 PJ_UNUSED_ARG(buff_size);
1946 PJ_UNUSED_ARG(flags);
1947
1948 return PJ_ENOTSUP;
1949}
1950
1951
1952/*
1953 * Same as #pj_ssl_sock_start_recvfrom() except that the recvfrom()
1954 * operation takes the buffer from the argument rather than creating
1955 * new ones.
1956 */
1957PJ_DEF(pj_status_t) pj_ssl_sock_start_recvfrom2 (pj_ssl_sock_t *ssock,
1958 pj_pool_t *pool,
1959 unsigned buff_size,
1960 void *readbuf[],
1961 pj_uint32_t flags)
1962{
1963 PJ_UNUSED_ARG(ssock);
1964 PJ_UNUSED_ARG(pool);
1965 PJ_UNUSED_ARG(buff_size);
1966 PJ_UNUSED_ARG(readbuf);
1967 PJ_UNUSED_ARG(flags);
1968
1969 return PJ_ENOTSUP;
1970}
1971
1972/* Write plain data to SSL and flush write BIO. Note that accessing
1973 * write BIO must be serialized, so a call to this function must be
1974 * protected by write mutex of SSL socket.
1975 */
1976static pj_status_t ssl_write(pj_ssl_sock_t *ssock,
1977 pj_ioqueue_op_key_t *send_key,
1978 const void *data,
1979 pj_ssize_t size,
1980 unsigned flags)
1981{
1982 pj_status_t status;
1983 int nwritten;
1984
1985 /* Write the plain data to SSL, after SSL encrypts it, write BIO will
1986 * contain the secured data to be sent via socket. Note that re-
1987 * negotitation may be on progress, so sending data should be delayed
1988 * until re-negotiation is completed.
1989 */
1990 nwritten = SSL_write(ssock->ossl_ssl, data, size);
1991
1992 if (nwritten == size) {
1993 /* All data written, flush write BIO to network socket */
1994 status = flush_write_bio(ssock, send_key, size, flags);
1995 } else if (nwritten <= 0) {
1996 /* SSL failed to process the data, it may just that re-negotiation
1997 * is on progress.
1998 */
1999 int err;
2000 err = SSL_get_error(ssock->ossl_ssl, nwritten);
2001 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_NONE) {
2002 /* Re-negotiation is on progress, flush re-negotiation data */
2003 status = flush_write_bio(ssock, &ssock->handshake_op_key, 0, 0);
2004 if (status == PJ_SUCCESS || status == PJ_EPENDING)
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00002005 /* Just return PJ_EBUSY when re-negotiation is on progress */
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002006 status = PJ_EBUSY;
2007 } else {
2008 /* Some problem occured */
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00002009 GET_SSL_STATUS(status);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002010 }
2011 } else {
2012 /* nwritten < *size, shouldn't happen, unless write BIO cannot hold
2013 * the whole secured data, perhaps because of insufficient memory.
2014 */
2015 status = PJ_ENOMEM;
2016 }
2017
2018 return status;
2019}
2020
2021/* Flush delayed data sending in the write pending list. Note that accessing
2022 * write pending list must be serialized, so a call to this function must be
2023 * protected by write mutex of SSL socket.
2024 */
2025static pj_status_t flush_delayed_send(pj_ssl_sock_t *ssock)
2026{
2027 while (!pj_list_empty(&ssock->write_pending)) {
2028 write_pending_t *wp;
2029 pj_status_t status;
2030
2031 wp = ssock->write_pending.next;
2032
2033 status = ssl_write(ssock, &wp->data.key, wp->data.data.ptr,
2034 wp->data.plain_data_len, wp->data.flags);
2035 if (status != PJ_SUCCESS)
2036 return status;
2037
2038 pj_list_erase(wp);
2039 pj_list_push_back(&ssock->write_pending_empty, wp);
2040 }
2041
2042 return PJ_SUCCESS;
2043}
2044
2045/* Sending is delayed, push back the sending data into pending list. Note that
2046 * accessing write pending list must be serialized, so a call to this function
2047 * must be protected by write mutex of SSL socket.
2048 */
2049static pj_status_t delay_send (pj_ssl_sock_t *ssock,
2050 pj_ioqueue_op_key_t *send_key,
2051 const void *data,
2052 pj_ssize_t size,
2053 unsigned flags)
2054{
2055 write_pending_t *wp;
2056
2057 /* Init write pending instance */
2058 if (!pj_list_empty(&ssock->write_pending_empty)) {
2059 wp = ssock->write_pending_empty.next;
2060 pj_list_erase(wp);
2061 } else {
2062 wp = PJ_POOL_ZALLOC_T(ssock->pool, write_pending_t);
2063 }
2064
2065 wp->data.app_key = send_key;
2066 wp->data.plain_data_len = size;
2067 wp->data.data.ptr = data;
2068 wp->data.flags = flags;
2069
2070 pj_list_push_back(&ssock->write_pending, wp);
2071
2072 /* Must return PJ_EPENDING */
2073 return PJ_EPENDING;
2074}
2075
2076/**
2077 * Send data using the socket.
2078 */
2079PJ_DEF(pj_status_t) pj_ssl_sock_send (pj_ssl_sock_t *ssock,
2080 pj_ioqueue_op_key_t *send_key,
2081 const void *data,
2082 pj_ssize_t *size,
2083 unsigned flags)
2084{
2085 pj_status_t status;
2086
2087 PJ_ASSERT_RETURN(ssock && data && size && (*size>0), PJ_EINVAL);
2088 PJ_ASSERT_RETURN(ssock->ssl_state==SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
2089
2090 pj_lock_acquire(ssock->write_mutex);
2091
2092 /* Flush delayed send first. Sending data might be delayed when
2093 * re-negotiation is on-progress.
2094 */
2095 status = flush_delayed_send(ssock);
2096 if (status == PJ_EBUSY) {
2097 /* Re-negotiation is on progress, delay sending */
2098 status = delay_send(ssock, send_key, data, *size, flags);
2099 goto on_return;
2100 } else if (status != PJ_SUCCESS) {
2101 goto on_return;
2102 }
2103
2104 /* Write data to SSL */
2105 status = ssl_write(ssock, send_key, data, *size, flags);
2106 if (status == PJ_EBUSY) {
2107 /* Re-negotiation is on progress, delay sending */
2108 status = delay_send(ssock, send_key, data, *size, flags);
2109 }
2110
2111on_return:
2112 pj_lock_release(ssock->write_mutex);
2113 return status;
2114}
2115
2116
2117/**
2118 * Send datagram using the socket.
2119 */
2120PJ_DEF(pj_status_t) pj_ssl_sock_sendto (pj_ssl_sock_t *ssock,
2121 pj_ioqueue_op_key_t *send_key,
2122 const void *data,
2123 pj_ssize_t *size,
2124 unsigned flags,
2125 const pj_sockaddr_t *addr,
2126 int addr_len)
2127{
2128 PJ_UNUSED_ARG(ssock);
2129 PJ_UNUSED_ARG(send_key);
2130 PJ_UNUSED_ARG(data);
2131 PJ_UNUSED_ARG(size);
2132 PJ_UNUSED_ARG(flags);
2133 PJ_UNUSED_ARG(addr);
2134 PJ_UNUSED_ARG(addr_len);
2135
2136 return PJ_ENOTSUP;
2137}
2138
2139
2140/**
2141 * Starts asynchronous socket accept() operations on this secure socket.
2142 */
2143PJ_DEF(pj_status_t) pj_ssl_sock_start_accept (pj_ssl_sock_t *ssock,
2144 pj_pool_t *pool,
2145 const pj_sockaddr_t *localaddr,
2146 int addr_len)
2147{
2148 pj_activesock_cb asock_cb;
2149 pj_activesock_cfg asock_cfg;
2150 pj_status_t status;
2151
2152 PJ_ASSERT_RETURN(ssock && pool && localaddr && addr_len, PJ_EINVAL);
2153
2154 /* Create socket */
2155 status = pj_sock_socket(ssock->param.sock_af, ssock->param.sock_type, 0,
2156 &ssock->sock);
2157 if (status != PJ_SUCCESS)
2158 goto on_error;
2159
Benny Prijonoa25bc9d2009-11-09 08:51:34 +00002160 /* Apply QoS, if specified */
2161 status = pj_sock_apply_qos2(ssock->sock, ssock->param.qos_type,
2162 &ssock->param.qos_params, 2,
2163 ssock->pool->obj_name, NULL);
2164 if (status != PJ_SUCCESS && !ssock->param.qos_ignore_error)
2165 goto on_error;
2166
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002167 /* Bind socket */
2168 status = pj_sock_bind(ssock->sock, localaddr, addr_len);
2169 if (status != PJ_SUCCESS)
2170 goto on_error;
2171
2172 /* Start listening to the address */
2173 status = pj_sock_listen(ssock->sock, PJ_SOMAXCONN);
2174 if (status != PJ_SUCCESS)
2175 goto on_error;
2176
2177 /* Create active socket */
2178 pj_activesock_cfg_default(&asock_cfg);
2179 asock_cfg.async_cnt = ssock->param.async_cnt;
2180 asock_cfg.concurrency = ssock->param.concurrency;
2181 asock_cfg.whole_data = PJ_TRUE;
2182
2183 pj_bzero(&asock_cb, sizeof(asock_cb));
2184 asock_cb.on_accept_complete = asock_on_accept_complete;
2185
2186 status = pj_activesock_create(pool,
2187 ssock->sock,
2188 ssock->param.sock_type,
2189 &asock_cfg,
2190 ssock->param.ioqueue,
2191 &asock_cb,
2192 ssock,
2193 &ssock->asock);
2194
2195 if (status != PJ_SUCCESS)
2196 goto on_error;
2197
2198 /* Start accepting */
2199 status = pj_activesock_start_accept(ssock->asock, pool);
2200 if (status != PJ_SUCCESS)
2201 goto on_error;
2202
2203 /* Update local address */
2204 ssock->addr_len = addr_len;
2205 status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,
2206 &ssock->addr_len);
2207 if (status != PJ_SUCCESS)
2208 pj_sockaddr_cp(&ssock->local_addr, localaddr);
2209
2210 ssock->is_server = PJ_TRUE;
2211
2212 return PJ_SUCCESS;
2213
2214on_error:
2215 reset_ssl_sock_state(ssock);
2216 return status;
2217}
2218
2219
2220/**
2221 * Starts asynchronous socket connect() operation.
2222 */
2223PJ_DECL(pj_status_t) pj_ssl_sock_start_connect(pj_ssl_sock_t *ssock,
2224 pj_pool_t *pool,
2225 const pj_sockaddr_t *localaddr,
2226 const pj_sockaddr_t *remaddr,
2227 int addr_len)
2228{
2229 pj_activesock_cb asock_cb;
2230 pj_activesock_cfg asock_cfg;
2231 pj_status_t status;
2232
2233 PJ_ASSERT_RETURN(ssock && pool && localaddr && remaddr && addr_len,
2234 PJ_EINVAL);
2235
2236 /* Create socket */
2237 status = pj_sock_socket(ssock->param.sock_af, ssock->param.sock_type, 0,
2238 &ssock->sock);
2239 if (status != PJ_SUCCESS)
2240 goto on_error;
2241
Benny Prijonoa25bc9d2009-11-09 08:51:34 +00002242 /* Apply QoS, if specified */
2243 status = pj_sock_apply_qos2(ssock->sock, ssock->param.qos_type,
2244 &ssock->param.qos_params, 2,
2245 ssock->pool->obj_name, NULL);
2246 if (status != PJ_SUCCESS && !ssock->param.qos_ignore_error)
2247 goto on_error;
2248
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002249 /* Bind socket */
2250 status = pj_sock_bind(ssock->sock, localaddr, addr_len);
2251 if (status != PJ_SUCCESS)
2252 goto on_error;
2253
2254 /* Create active socket */
2255 pj_activesock_cfg_default(&asock_cfg);
2256 asock_cfg.async_cnt = ssock->param.async_cnt;
2257 asock_cfg.concurrency = ssock->param.concurrency;
2258 asock_cfg.whole_data = PJ_TRUE;
2259
2260 pj_bzero(&asock_cb, sizeof(asock_cb));
2261 asock_cb.on_connect_complete = asock_on_connect_complete;
2262 asock_cb.on_data_read = asock_on_data_read;
2263 asock_cb.on_data_sent = asock_on_data_sent;
2264
2265 status = pj_activesock_create(pool,
2266 ssock->sock,
2267 ssock->param.sock_type,
2268 &asock_cfg,
2269 ssock->param.ioqueue,
2270 &asock_cb,
2271 ssock,
2272 &ssock->asock);
2273
2274 if (status != PJ_SUCCESS)
2275 goto on_error;
2276
Nanang Izzuddin48747632009-11-20 07:48:41 +00002277 /* Save remote address */
2278 pj_sockaddr_cp(&ssock->rem_addr, remaddr);
2279
Nanang Izzuddina7719d32010-03-06 02:04:52 +00002280 /* Start timer */
2281 if (ssock->param.timer_heap && (ssock->param.timeout.sec != 0 ||
2282 ssock->param.timeout.msec != 0))
2283 {
2284 pj_assert(ssock->timer.id == TIMER_NONE);
2285 ssock->timer.id = TIMER_HANDSHAKE_TIMEOUT;
2286 status = pj_timer_heap_schedule(ssock->param.timer_heap,
2287 &ssock->timer,
2288 &ssock->param.timeout);
2289 if (status != PJ_SUCCESS)
2290 ssock->timer.id = TIMER_NONE;
2291 }
2292
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002293 status = pj_activesock_start_connect(ssock->asock, pool, remaddr,
2294 addr_len);
2295
2296 if (status == PJ_SUCCESS)
2297 asock_on_connect_complete(ssock->asock, PJ_SUCCESS);
2298 else if (status != PJ_EPENDING)
2299 goto on_error;
2300
2301 /* Update local address */
2302 ssock->addr_len = addr_len;
2303 status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,
2304 &ssock->addr_len);
Nanang Izzuddinb5e025a2009-11-09 13:40:26 +00002305 /* Note that we may not get an IP address here. This can
2306 * happen for example on Windows, where getsockname()
2307 * would return 0.0.0.0 if socket has just started the
2308 * async connect. In this case, just leave the local
2309 * address with 0.0.0.0 for now; it will be updated
2310 * once the socket is established.
2311 */
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002312
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002313 /* Update SSL state */
2314 ssock->is_server = PJ_FALSE;
2315
2316 return PJ_EPENDING;
2317
2318on_error:
2319 reset_ssl_sock_state(ssock);
2320 return status;
2321}
2322
2323
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00002324PJ_DEF(pj_status_t) pj_ssl_sock_renegotiate(pj_ssl_sock_t *ssock)
2325{
2326 int ret;
2327 pj_status_t status;
2328
2329 PJ_ASSERT_RETURN(ssock->ssl_state == SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
2330
2331 if (SSL_renegotiate_pending(ssock->ossl_ssl))
2332 return PJ_EPENDING;
2333
2334 ret = SSL_renegotiate(ssock->ossl_ssl);
2335 if (ret <= 0) {
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00002336 GET_SSL_STATUS(status);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00002337 } else {
2338 status = do_handshake(ssock);
2339 }
2340
2341 return status;
2342}
2343
2344#endif /* PJ_HAS_SSL_SOCK */
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002345