blob: 7fe0c4359e585a00609ded4727a9f811e030deb2 [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:
1168 PJ_LOG(1,(ssock->pool->obj_name, "SSL handshake timeout after %d.%ds",
1169 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 /* Start handshake timer */
1611 if (ssock->param.timer_heap && (ssock->param.timeout.sec != 0 ||
1612 ssock->param.timeout.msec != 0))
1613 {
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001614 pj_assert(ssock->timer.id == TIMER_NONE);
1615 ssock->timer.id = TIMER_HANDSHAKE_TIMEOUT;
1616 status = pj_timer_heap_schedule(ssock->param.timer_heap,
1617 &ssock->timer,
1618 &ssock->param.timeout);
1619 if (status != PJ_SUCCESS)
1620 ssock->timer.id = TIMER_NONE;
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001621 }
1622
1623#ifdef SSL_set_tlsext_host_name
1624 /* Set server name to connect */
1625 if (ssock->param.server_name.slen) {
1626 /* Server name is null terminated already */
1627 if (!SSL_set_tlsext_host_name(ssock->ossl_ssl,
1628 ssock->param.server_name.ptr))
1629 {
1630 char err_str[PJ_ERR_MSG_SIZE];
1631
1632 ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
1633 PJ_LOG(3,(ssock->pool->obj_name, "SSL_set_tlsext_host_name() "
1634 "failed: %s", err_str));
1635 }
1636 }
1637#endif
1638
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001639 /* Start SSL handshake */
1640 ssock->ssl_state = SSL_STATE_HANDSHAKING;
1641 SSL_set_connect_state(ssock->ossl_ssl);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001642
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001643 status = do_handshake(ssock);
1644 if (status != PJ_EPENDING)
1645 goto on_return;
1646
1647 return PJ_TRUE;
1648
1649on_return:
1650 return on_handshake_complete(ssock, status);
1651}
1652
1653
1654
1655/*
1656 *******************************************************************
1657 * API
1658 *******************************************************************
1659 */
1660
1661/* Load credentials from files. */
1662PJ_DEF(pj_status_t) pj_ssl_cert_load_from_files (pj_pool_t *pool,
1663 const pj_str_t *CA_file,
1664 const pj_str_t *cert_file,
1665 const pj_str_t *privkey_file,
1666 const pj_str_t *privkey_pass,
1667 pj_ssl_cert_t **p_cert)
1668{
1669 pj_ssl_cert_t *cert;
1670
1671 PJ_ASSERT_RETURN(pool && CA_file && cert_file && privkey_file, PJ_EINVAL);
1672
1673 cert = PJ_POOL_ZALLOC_T(pool, pj_ssl_cert_t);
1674 pj_strdup_with_null(pool, &cert->CA_file, CA_file);
1675 pj_strdup_with_null(pool, &cert->cert_file, cert_file);
1676 pj_strdup_with_null(pool, &cert->privkey_file, privkey_file);
1677 pj_strdup_with_null(pool, &cert->privkey_pass, privkey_pass);
1678
1679 *p_cert = cert;
1680
1681 return PJ_SUCCESS;
1682}
1683
1684
1685/* Set SSL socket credentials. */
1686PJ_DECL(pj_status_t) pj_ssl_sock_set_certificate(
1687 pj_ssl_sock_t *ssock,
1688 pj_pool_t *pool,
1689 const pj_ssl_cert_t *cert)
1690{
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001691 pj_ssl_cert_t *cert_;
1692
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001693 PJ_ASSERT_RETURN(ssock && pool && cert, PJ_EINVAL);
1694
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001695 cert_ = PJ_POOL_ZALLOC_T(pool, pj_ssl_cert_t);
1696 pj_memcpy(cert_, cert, sizeof(cert));
1697 pj_strdup_with_null(pool, &cert_->CA_file, &cert->CA_file);
1698 pj_strdup_with_null(pool, &cert_->cert_file, &cert->cert_file);
1699 pj_strdup_with_null(pool, &cert_->privkey_file, &cert->privkey_file);
1700 pj_strdup_with_null(pool, &cert_->privkey_pass, &cert->privkey_pass);
1701
1702 ssock->cert = cert_;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001703
1704 return PJ_SUCCESS;
1705}
1706
1707
1708/* Get available ciphers. */
1709PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables(pj_ssl_cipher ciphers[],
1710 unsigned *cipher_num)
1711{
1712 unsigned i;
1713
1714 PJ_ASSERT_RETURN(ciphers && cipher_num, PJ_EINVAL);
1715
1716 if (openssl_cipher_num == 0) {
1717 init_openssl();
1718 shutdown_openssl();
1719 }
1720
1721 if (openssl_cipher_num == 0)
1722 return PJ_ENOTFOUND;
1723
1724 *cipher_num = PJ_MIN(*cipher_num, openssl_cipher_num);
1725
1726 for (i = 0; i < *cipher_num; ++i)
1727 ciphers[i] = openssl_ciphers[i];
1728
1729 return PJ_SUCCESS;
1730}
1731
1732
1733/*
1734 * Create SSL socket instance.
1735 */
1736PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool,
1737 const pj_ssl_sock_param *param,
1738 pj_ssl_sock_t **p_ssock)
1739{
1740 pj_ssl_sock_t *ssock;
1741 pj_status_t status;
1742
1743 PJ_ASSERT_RETURN(pool && param && p_ssock, PJ_EINVAL);
1744 PJ_ASSERT_RETURN(param->sock_type == pj_SOCK_STREAM(), PJ_ENOTSUP);
1745
1746 pool = pj_pool_create(pool->factory, "ssl%p", 512, 512, NULL);
1747
1748 /* Create secure socket */
1749 ssock = PJ_POOL_ZALLOC_T(pool, pj_ssl_sock_t);
1750 ssock->pool = pool;
1751 ssock->sock = PJ_INVALID_SOCKET;
1752 ssock->ssl_state = SSL_STATE_NULL;
1753 pj_list_init(&ssock->write_pending);
1754 pj_list_init(&ssock->write_pending_empty);
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001755 pj_timer_entry_init(&ssock->timer, 0, ssock, &on_timer);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001756
1757 /* Create secure socket mutex */
1758 status = pj_lock_create_recursive_mutex(pool, pool->obj_name,
1759 &ssock->write_mutex);
1760 if (status != PJ_SUCCESS)
1761 return status;
1762
1763 /* Init secure socket param */
1764 ssock->param = *param;
1765 ssock->param.read_buffer_size = ((ssock->param.read_buffer_size+7)>>3)<<3;
1766 if (param->ciphers_num > 0) {
1767 unsigned i;
1768 ssock->param.ciphers = (pj_ssl_cipher*)
1769 pj_pool_calloc(pool, param->ciphers_num,
1770 sizeof(pj_ssl_cipher));
1771 for (i = 0; i < param->ciphers_num; ++i)
1772 ssock->param.ciphers[i] = param->ciphers[i];
1773 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001774
1775 /* Server name must be null-terminated */
1776 pj_strdup_with_null(pool, &ssock->param.server_name,
1777 &param->server_name);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001778
1779 /* Finally */
1780 *p_ssock = ssock;
1781
1782 return PJ_SUCCESS;
1783}
1784
1785
1786/*
1787 * Close the secure socket. This will unregister the socket from the
1788 * ioqueue and ultimately close the socket.
1789 */
1790PJ_DEF(pj_status_t) pj_ssl_sock_close(pj_ssl_sock_t *ssock)
1791{
1792 pj_pool_t *pool;
1793
1794 PJ_ASSERT_RETURN(ssock, PJ_EINVAL);
1795
Nanang Izzuddin8e5f6342009-11-06 08:01:59 +00001796 if (!ssock->pool)
1797 return PJ_SUCCESS;
1798
1799 if (ssock->timer.id != TIMER_NONE) {
1800 pj_timer_heap_cancel(ssock->param.timer_heap, &ssock->timer);
1801 ssock->timer.id = TIMER_NONE;
1802 }
1803
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001804 reset_ssl_sock_state(ssock);
1805 pj_lock_destroy(ssock->write_mutex);
1806
1807 pool = ssock->pool;
1808 ssock->pool = NULL;
1809 if (pool)
1810 pj_pool_release(pool);
1811
1812 return PJ_SUCCESS;
1813}
1814
1815
1816/*
1817 * Associate arbitrary data with the secure socket.
1818 */
1819PJ_DEF(pj_status_t) pj_ssl_sock_set_user_data(pj_ssl_sock_t *ssock,
1820 void *user_data)
1821{
1822 PJ_ASSERT_RETURN(ssock, PJ_EINVAL);
1823
1824 ssock->param.user_data = user_data;
1825 return PJ_SUCCESS;
1826}
1827
1828
1829/*
1830 * Retrieve the user data previously associated with this secure
1831 * socket.
1832 */
1833PJ_DEF(void*) pj_ssl_sock_get_user_data(pj_ssl_sock_t *ssock)
1834{
1835 PJ_ASSERT_RETURN(ssock, NULL);
1836
1837 return ssock->param.user_data;
1838}
1839
1840
1841/*
1842 * Retrieve the local address and port used by specified SSL socket.
1843 */
1844PJ_DEF(pj_status_t) pj_ssl_sock_get_info (pj_ssl_sock_t *ssock,
1845 pj_ssl_sock_info *info)
1846{
1847 pj_bzero(info, sizeof(*info));
1848
1849 /* Established flag */
1850 info->established = (ssock->ssl_state == SSL_STATE_ESTABLISHED);
1851
1852 /* Protocol */
1853 info->proto = ssock->param.proto;
1854
1855 /* Local address */
1856 pj_sockaddr_cp(&info->local_addr, &ssock->local_addr);
1857
1858 if (info->established) {
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001859 const SSL_CIPHER *cipher;
1860
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +00001861 /* Current cipher */
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001862 cipher = SSL_get_current_cipher(ssock->ossl_ssl);
1863 info->cipher = (cipher->id & 0x00FFFFFF);
1864
1865 /* Remote address */
1866 pj_sockaddr_cp(&info->remote_addr, &ssock->rem_addr);
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001867
1868 /* Certificates info */
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +00001869 info->local_cert_info = &ssock->local_cert_info;
1870 info->remote_cert_info = &ssock->remote_cert_info;
1871
1872 /* Verification status */
1873 info->verify_status = ssock->verify_status;
Nanang Izzuddin006cc012009-10-16 03:06:13 +00001874 }
1875
1876 return PJ_SUCCESS;
1877}
1878
1879
1880/*
1881 * Starts read operation on this secure socket.
1882 */
1883PJ_DEF(pj_status_t) pj_ssl_sock_start_read (pj_ssl_sock_t *ssock,
1884 pj_pool_t *pool,
1885 unsigned buff_size,
1886 pj_uint32_t flags)
1887{
1888 void **readbuf;
1889 unsigned i;
1890
1891 PJ_ASSERT_RETURN(ssock && pool && buff_size, PJ_EINVAL);
1892 PJ_ASSERT_RETURN(ssock->ssl_state==SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
1893
1894 readbuf = (void**) pj_pool_calloc(pool, ssock->param.async_cnt,
1895 sizeof(void*));
1896
1897 for (i=0; i<ssock->param.async_cnt; ++i) {
1898 readbuf[i] = pj_pool_alloc(pool, buff_size);
1899 }
1900
1901 return pj_ssl_sock_start_read2(ssock, pool, buff_size,
1902 readbuf, flags);
1903}
1904
1905
1906/*
1907 * Same as #pj_ssl_sock_start_read(), except that the application
1908 * supplies the buffers for the read operation so that the acive socket
1909 * does not have to allocate the buffers.
1910 */
1911PJ_DEF(pj_status_t) pj_ssl_sock_start_read2 (pj_ssl_sock_t *ssock,
1912 pj_pool_t *pool,
1913 unsigned buff_size,
1914 void *readbuf[],
1915 pj_uint32_t flags)
1916{
1917 unsigned i;
1918
1919 PJ_ASSERT_RETURN(ssock && pool && buff_size && readbuf, PJ_EINVAL);
1920 PJ_ASSERT_RETURN(ssock->ssl_state==SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
1921
1922 /* Create SSL socket read buffer */
1923 ssock->ssock_rbuf = (read_data_t*)pj_pool_calloc(pool,
1924 ssock->param.async_cnt,
1925 sizeof(read_data_t));
1926
1927 /* Store SSL socket read buffer pointer in the activesock read buffer */
1928 for (i=0; i<ssock->param.async_cnt; ++i) {
1929 read_data_t **p_ssock_rbuf =
1930 OFFSET_OF_READ_DATA_PTR(ssock, ssock->asock_rbuf[i]);
1931
1932 ssock->ssock_rbuf[i].data = readbuf[i];
1933 ssock->ssock_rbuf[i].len = 0;
1934
1935 *p_ssock_rbuf = &ssock->ssock_rbuf[i];
1936 }
1937
1938 ssock->read_size = buff_size;
1939 ssock->read_started = PJ_TRUE;
1940 ssock->read_flags = flags;
1941
1942 return PJ_SUCCESS;
1943}
1944
1945
1946/*
1947 * Same as pj_ssl_sock_start_read(), except that this function is used
1948 * only for datagram sockets, and it will trigger \a on_data_recvfrom()
1949 * callback instead.
1950 */
1951PJ_DEF(pj_status_t) pj_ssl_sock_start_recvfrom (pj_ssl_sock_t *ssock,
1952 pj_pool_t *pool,
1953 unsigned buff_size,
1954 pj_uint32_t flags)
1955{
1956 PJ_UNUSED_ARG(ssock);
1957 PJ_UNUSED_ARG(pool);
1958 PJ_UNUSED_ARG(buff_size);
1959 PJ_UNUSED_ARG(flags);
1960
1961 return PJ_ENOTSUP;
1962}
1963
1964
1965/*
1966 * Same as #pj_ssl_sock_start_recvfrom() except that the recvfrom()
1967 * operation takes the buffer from the argument rather than creating
1968 * new ones.
1969 */
1970PJ_DEF(pj_status_t) pj_ssl_sock_start_recvfrom2 (pj_ssl_sock_t *ssock,
1971 pj_pool_t *pool,
1972 unsigned buff_size,
1973 void *readbuf[],
1974 pj_uint32_t flags)
1975{
1976 PJ_UNUSED_ARG(ssock);
1977 PJ_UNUSED_ARG(pool);
1978 PJ_UNUSED_ARG(buff_size);
1979 PJ_UNUSED_ARG(readbuf);
1980 PJ_UNUSED_ARG(flags);
1981
1982 return PJ_ENOTSUP;
1983}
1984
1985/* Write plain data to SSL and flush write BIO. Note that accessing
1986 * write BIO must be serialized, so a call to this function must be
1987 * protected by write mutex of SSL socket.
1988 */
1989static pj_status_t ssl_write(pj_ssl_sock_t *ssock,
1990 pj_ioqueue_op_key_t *send_key,
1991 const void *data,
1992 pj_ssize_t size,
1993 unsigned flags)
1994{
1995 pj_status_t status;
1996 int nwritten;
1997
1998 /* Write the plain data to SSL, after SSL encrypts it, write BIO will
1999 * contain the secured data to be sent via socket. Note that re-
2000 * negotitation may be on progress, so sending data should be delayed
2001 * until re-negotiation is completed.
2002 */
2003 nwritten = SSL_write(ssock->ossl_ssl, data, size);
2004
2005 if (nwritten == size) {
2006 /* All data written, flush write BIO to network socket */
2007 status = flush_write_bio(ssock, send_key, size, flags);
2008 } else if (nwritten <= 0) {
2009 /* SSL failed to process the data, it may just that re-negotiation
2010 * is on progress.
2011 */
2012 int err;
2013 err = SSL_get_error(ssock->ossl_ssl, nwritten);
2014 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_NONE) {
2015 /* Re-negotiation is on progress, flush re-negotiation data */
2016 status = flush_write_bio(ssock, &ssock->handshake_op_key, 0, 0);
2017 if (status == PJ_SUCCESS || status == PJ_EPENDING)
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00002018 /* Just return PJ_EBUSY when re-negotiation is on progress */
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002019 status = PJ_EBUSY;
2020 } else {
2021 /* Some problem occured */
Nanang Izzuddin2d0f8fe2009-11-04 17:08:32 +00002022 GET_SSL_STATUS(status);
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002023 }
2024 } else {
2025 /* nwritten < *size, shouldn't happen, unless write BIO cannot hold
2026 * the whole secured data, perhaps because of insufficient memory.
2027 */
2028 status = PJ_ENOMEM;
2029 }
2030
2031 return status;
2032}
2033
2034/* Flush delayed data sending in the write pending list. Note that accessing
2035 * write pending list must be serialized, so a call to this function must be
2036 * protected by write mutex of SSL socket.
2037 */
2038static pj_status_t flush_delayed_send(pj_ssl_sock_t *ssock)
2039{
2040 while (!pj_list_empty(&ssock->write_pending)) {
2041 write_pending_t *wp;
2042 pj_status_t status;
2043
2044 wp = ssock->write_pending.next;
2045
2046 status = ssl_write(ssock, &wp->data.key, wp->data.data.ptr,
2047 wp->data.plain_data_len, wp->data.flags);
2048 if (status != PJ_SUCCESS)
2049 return status;
2050
2051 pj_list_erase(wp);
2052 pj_list_push_back(&ssock->write_pending_empty, wp);
2053 }
2054
2055 return PJ_SUCCESS;
2056}
2057
2058/* Sending is delayed, push back the sending data into pending list. Note that
2059 * accessing write pending list must be serialized, so a call to this function
2060 * must be protected by write mutex of SSL socket.
2061 */
2062static pj_status_t delay_send (pj_ssl_sock_t *ssock,
2063 pj_ioqueue_op_key_t *send_key,
2064 const void *data,
2065 pj_ssize_t size,
2066 unsigned flags)
2067{
2068 write_pending_t *wp;
2069
2070 /* Init write pending instance */
2071 if (!pj_list_empty(&ssock->write_pending_empty)) {
2072 wp = ssock->write_pending_empty.next;
2073 pj_list_erase(wp);
2074 } else {
2075 wp = PJ_POOL_ZALLOC_T(ssock->pool, write_pending_t);
2076 }
2077
2078 wp->data.app_key = send_key;
2079 wp->data.plain_data_len = size;
2080 wp->data.data.ptr = data;
2081 wp->data.flags = flags;
2082
2083 pj_list_push_back(&ssock->write_pending, wp);
2084
2085 /* Must return PJ_EPENDING */
2086 return PJ_EPENDING;
2087}
2088
2089/**
2090 * Send data using the socket.
2091 */
2092PJ_DEF(pj_status_t) pj_ssl_sock_send (pj_ssl_sock_t *ssock,
2093 pj_ioqueue_op_key_t *send_key,
2094 const void *data,
2095 pj_ssize_t *size,
2096 unsigned flags)
2097{
2098 pj_status_t status;
2099
2100 PJ_ASSERT_RETURN(ssock && data && size && (*size>0), PJ_EINVAL);
2101 PJ_ASSERT_RETURN(ssock->ssl_state==SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
2102
2103 pj_lock_acquire(ssock->write_mutex);
2104
2105 /* Flush delayed send first. Sending data might be delayed when
2106 * re-negotiation is on-progress.
2107 */
2108 status = flush_delayed_send(ssock);
2109 if (status == PJ_EBUSY) {
2110 /* Re-negotiation is on progress, delay sending */
2111 status = delay_send(ssock, send_key, data, *size, flags);
2112 goto on_return;
2113 } else if (status != PJ_SUCCESS) {
2114 goto on_return;
2115 }
2116
2117 /* Write data to SSL */
2118 status = ssl_write(ssock, send_key, data, *size, flags);
2119 if (status == PJ_EBUSY) {
2120 /* Re-negotiation is on progress, delay sending */
2121 status = delay_send(ssock, send_key, data, *size, flags);
2122 }
2123
2124on_return:
2125 pj_lock_release(ssock->write_mutex);
2126 return status;
2127}
2128
2129
2130/**
2131 * Send datagram using the socket.
2132 */
2133PJ_DEF(pj_status_t) pj_ssl_sock_sendto (pj_ssl_sock_t *ssock,
2134 pj_ioqueue_op_key_t *send_key,
2135 const void *data,
2136 pj_ssize_t *size,
2137 unsigned flags,
2138 const pj_sockaddr_t *addr,
2139 int addr_len)
2140{
2141 PJ_UNUSED_ARG(ssock);
2142 PJ_UNUSED_ARG(send_key);
2143 PJ_UNUSED_ARG(data);
2144 PJ_UNUSED_ARG(size);
2145 PJ_UNUSED_ARG(flags);
2146 PJ_UNUSED_ARG(addr);
2147 PJ_UNUSED_ARG(addr_len);
2148
2149 return PJ_ENOTSUP;
2150}
2151
2152
2153/**
2154 * Starts asynchronous socket accept() operations on this secure socket.
2155 */
2156PJ_DEF(pj_status_t) pj_ssl_sock_start_accept (pj_ssl_sock_t *ssock,
2157 pj_pool_t *pool,
2158 const pj_sockaddr_t *localaddr,
2159 int addr_len)
2160{
2161 pj_activesock_cb asock_cb;
2162 pj_activesock_cfg asock_cfg;
2163 pj_status_t status;
2164
2165 PJ_ASSERT_RETURN(ssock && pool && localaddr && addr_len, PJ_EINVAL);
2166
2167 /* Create socket */
2168 status = pj_sock_socket(ssock->param.sock_af, ssock->param.sock_type, 0,
2169 &ssock->sock);
2170 if (status != PJ_SUCCESS)
2171 goto on_error;
2172
Benny Prijonoa25bc9d2009-11-09 08:51:34 +00002173 /* Apply QoS, if specified */
2174 status = pj_sock_apply_qos2(ssock->sock, ssock->param.qos_type,
2175 &ssock->param.qos_params, 2,
2176 ssock->pool->obj_name, NULL);
2177 if (status != PJ_SUCCESS && !ssock->param.qos_ignore_error)
2178 goto on_error;
2179
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002180 /* Bind socket */
2181 status = pj_sock_bind(ssock->sock, localaddr, addr_len);
2182 if (status != PJ_SUCCESS)
2183 goto on_error;
2184
2185 /* Start listening to the address */
2186 status = pj_sock_listen(ssock->sock, PJ_SOMAXCONN);
2187 if (status != PJ_SUCCESS)
2188 goto on_error;
2189
2190 /* Create active socket */
2191 pj_activesock_cfg_default(&asock_cfg);
2192 asock_cfg.async_cnt = ssock->param.async_cnt;
2193 asock_cfg.concurrency = ssock->param.concurrency;
2194 asock_cfg.whole_data = PJ_TRUE;
2195
2196 pj_bzero(&asock_cb, sizeof(asock_cb));
2197 asock_cb.on_accept_complete = asock_on_accept_complete;
2198
2199 status = pj_activesock_create(pool,
2200 ssock->sock,
2201 ssock->param.sock_type,
2202 &asock_cfg,
2203 ssock->param.ioqueue,
2204 &asock_cb,
2205 ssock,
2206 &ssock->asock);
2207
2208 if (status != PJ_SUCCESS)
2209 goto on_error;
2210
2211 /* Start accepting */
2212 status = pj_activesock_start_accept(ssock->asock, pool);
2213 if (status != PJ_SUCCESS)
2214 goto on_error;
2215
2216 /* Update local address */
2217 ssock->addr_len = addr_len;
2218 status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,
2219 &ssock->addr_len);
2220 if (status != PJ_SUCCESS)
2221 pj_sockaddr_cp(&ssock->local_addr, localaddr);
2222
2223 ssock->is_server = PJ_TRUE;
2224
2225 return PJ_SUCCESS;
2226
2227on_error:
2228 reset_ssl_sock_state(ssock);
2229 return status;
2230}
2231
2232
2233/**
2234 * Starts asynchronous socket connect() operation.
2235 */
2236PJ_DECL(pj_status_t) pj_ssl_sock_start_connect(pj_ssl_sock_t *ssock,
2237 pj_pool_t *pool,
2238 const pj_sockaddr_t *localaddr,
2239 const pj_sockaddr_t *remaddr,
2240 int addr_len)
2241{
2242 pj_activesock_cb asock_cb;
2243 pj_activesock_cfg asock_cfg;
2244 pj_status_t status;
2245
2246 PJ_ASSERT_RETURN(ssock && pool && localaddr && remaddr && addr_len,
2247 PJ_EINVAL);
2248
2249 /* Create socket */
2250 status = pj_sock_socket(ssock->param.sock_af, ssock->param.sock_type, 0,
2251 &ssock->sock);
2252 if (status != PJ_SUCCESS)
2253 goto on_error;
2254
Benny Prijonoa25bc9d2009-11-09 08:51:34 +00002255 /* Apply QoS, if specified */
2256 status = pj_sock_apply_qos2(ssock->sock, ssock->param.qos_type,
2257 &ssock->param.qos_params, 2,
2258 ssock->pool->obj_name, NULL);
2259 if (status != PJ_SUCCESS && !ssock->param.qos_ignore_error)
2260 goto on_error;
2261
Nanang Izzuddin006cc012009-10-16 03:06:13 +00002262 /* Bind socket */
2263 status = pj_sock_bind(ssock->sock, localaddr, addr_len);
2264 if (status != PJ_SUCCESS)
2265 goto on_error;
2266
2267 /* Create active socket */
2268 pj_activesock_cfg_default(&asock_cfg);
2269 asock_cfg.async_cnt = ssock->param.async_cnt;
2270 asock_cfg.concurrency = ssock->param.concurrency;
2271 asock_cfg.whole_data = PJ_TRUE;
2272
2273 pj_bzero(&asock_cb, sizeof(asock_cb));
2274 asock_cb.on_connect_complete = asock_on_connect_complete;
2275 asock_cb.on_data_read = asock_on_data_read;
2276 asock_cb.on_data_sent = asock_on_data_sent;
2277
2278 status = pj_activesock_create(pool,
2279 ssock->sock,
2280 ssock->param.sock_type,
2281 &asock_cfg,
2282 ssock->param.ioqueue,
2283 &asock_cb,
2284 ssock,
2285 &ssock->asock);
2286
2287 if (status != PJ_SUCCESS)
2288 goto on_error;
2289
Nanang Izzuddin48747632009-11-20 07:48:41 +00002290 /* Save remote address */
2291 pj_sockaddr_cp(&ssock->rem_addr, remaddr);
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