1 /* $Id$ */
2 /*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include "test.h"
21 #include <pjlib.h>
22
23
24 #define CERT_DIR "../build/"
25 #if (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_DARWIN) || \
26 (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_APPLE)
27 /* If we use Darwin SSL, use the cert in DER format. */
28 # define CERT_CA_FILE CERT_DIR "cacert.der"
29 #else
30 # define CERT_CA_FILE CERT_DIR "cacert.pem"
31 #endif
32 #define CERT_FILE CERT_DIR "cacert.pem"
33 #define CERT_PRIVKEY_FILE CERT_DIR "privkey.pem"
34 #define CERT_PRIVKEY_PASS "privkeypass"
35
36 #define TEST_LOAD_FROM_FILES 1
37
38 #if INCLUDE_SSLSOCK_TEST
39
40 /* Global vars */
41 static int clients_num;
42
43 struct send_key {
44 pj_ioqueue_op_key_t op_key;
45 };
46
47
get_cipher_list(void)48 static int get_cipher_list(void) {
49 pj_status_t status;
50 pj_ssl_cipher ciphers[PJ_SSL_SOCK_MAX_CIPHERS];
51 unsigned cipher_num;
52 unsigned i;
53
54 cipher_num = PJ_ARRAY_SIZE(ciphers);
55 status = pj_ssl_cipher_get_availables(ciphers, &cipher_num);
56 if (status != PJ_SUCCESS) {
57 app_perror("...FAILED to get available ciphers", status);
58 return status;
59 }
60
61 PJ_LOG(3, ("", "...Found %u ciphers:", cipher_num));
62 for (i = 0; i < cipher_num; ++i) {
63 const char* st;
64 st = pj_ssl_cipher_name(ciphers[i]);
65 if (st == NULL)
66 st = "[Unknown]";
67
68 PJ_LOG(3, ("", "...%3u: 0x%08x=%s", i+1, ciphers[i], st));
69 }
70
71 return PJ_SUCCESS;
72 }
73
74
75 struct test_state
76 {
77 pj_pool_t *pool; /* pool */
78 pj_ioqueue_t *ioqueue; /* ioqueue */
79 pj_bool_t is_server; /* server role flag */
80 pj_bool_t is_verbose; /* verbose flag, e.g: cert info */
81 pj_bool_t echo; /* echo received data */
82 pj_status_t err; /* error flag */
83 pj_size_t sent; /* bytes sent */
84 pj_size_t recv; /* bytes received */
85 pj_uint8_t read_buf[256]; /* read buffer */
86 pj_bool_t done; /* test done flag */
87 char *send_str; /* data to send once connected */
88 pj_size_t send_str_len; /* send data length */
89 pj_bool_t check_echo; /* flag to compare sent & echoed data */
90 const char *check_echo_ptr; /* pointer/cursor for comparing data */
91 struct send_key send_key; /* send op key */
92 };
93
dump_ssl_info(const pj_ssl_sock_info * si)94 static void dump_ssl_info(const pj_ssl_sock_info *si)
95 {
96 const char *tmp_st;
97
98 /* Print cipher name */
99 tmp_st = pj_ssl_cipher_name(si->cipher);
100 if (tmp_st == NULL)
101 tmp_st = "[Unknown]";
102 PJ_LOG(3, ("", ".....Cipher: %s", tmp_st));
103
104 /* Print remote certificate info and verification result */
105 if (si->remote_cert_info && si->remote_cert_info->subject.info.slen)
106 {
107 char buf[2048];
108 const char *verif_msgs[32];
109 unsigned verif_msg_cnt;
110
111 /* Dump remote TLS certificate info */
112 PJ_LOG(3, ("", ".....Remote certificate info:"));
113 pj_ssl_cert_info_dump(si->remote_cert_info, " ", buf, sizeof(buf));
114 PJ_LOG(3,("", "\n%s", buf));
115
116 /* Dump remote TLS certificate verification result */
117 verif_msg_cnt = PJ_ARRAY_SIZE(verif_msgs);
118 pj_ssl_cert_get_verify_status_strings(si->verify_status,
119 verif_msgs, &verif_msg_cnt);
120 PJ_LOG(3,("", ".....Remote certificate verification result: %s",
121 (verif_msg_cnt == 1? verif_msgs[0]:"")));
122 if (verif_msg_cnt > 1) {
123 unsigned i;
124 for (i = 0; i < verif_msg_cnt; ++i)
125 PJ_LOG(3,("", "..... - %s", verif_msgs[i]));
126 }
127 }
128 }
129
130
ssl_on_connect_complete(pj_ssl_sock_t * ssock,pj_status_t status)131 static pj_bool_t ssl_on_connect_complete(pj_ssl_sock_t *ssock,
132 pj_status_t status)
133 {
134 struct test_state *st = (struct test_state*)
135 pj_ssl_sock_get_user_data(ssock);
136 void *read_buf[1];
137 pj_ssl_sock_info info;
138 char buf1[64], buf2[64];
139
140 if (status != PJ_SUCCESS) {
141 app_perror("...ERROR ssl_on_connect_complete()", status);
142 goto on_return;
143 }
144
145 status = pj_ssl_sock_get_info(ssock, &info);
146 if (status != PJ_SUCCESS) {
147 app_perror("...ERROR pj_ssl_sock_get_info()", status);
148 goto on_return;
149 }
150
151 pj_sockaddr_print((pj_sockaddr_t*)&info.local_addr, buf1, sizeof(buf1), 1);
152 pj_sockaddr_print((pj_sockaddr_t*)&info.remote_addr, buf2, sizeof(buf2), 1);
153 PJ_LOG(3, ("", "...Connected %s -> %s!", buf1, buf2));
154
155 if (st->is_verbose)
156 dump_ssl_info(&info);
157
158 /* Start reading data */
159 read_buf[0] = st->read_buf;
160 status = pj_ssl_sock_start_read2(ssock, st->pool, sizeof(st->read_buf), (void**)read_buf, 0);
161 if (status != PJ_SUCCESS) {
162 app_perror("...ERROR pj_ssl_sock_start_read2()", status);
163 goto on_return;
164 }
165
166 /* Start sending data */
167 while (st->sent < st->send_str_len) {
168 pj_ssize_t size;
169
170 size = st->send_str_len - st->sent;
171 status = pj_ssl_sock_send(ssock, (pj_ioqueue_op_key_t*)&st->send_key,
172 st->send_str + st->sent, &size, 0);
173 if (status != PJ_SUCCESS && status != PJ_EPENDING) {
174 app_perror("...ERROR pj_ssl_sock_send()", status);
175 goto on_return;
176 }
177
178 if (status == PJ_SUCCESS) {
179 st->sent += size;
180 } else {
181 if (status == PJ_EPENDING)
182 status = PJ_SUCCESS;
183 break;
184 }
185 }
186
187 on_return:
188 st->err = status;
189
190 if (st->err != PJ_SUCCESS) {
191 pj_ssl_sock_close(ssock);
192 clients_num--;
193 return PJ_FALSE;
194 }
195
196 return PJ_TRUE;
197 }
198
199
ssl_on_accept_complete(pj_ssl_sock_t * ssock,pj_ssl_sock_t * newsock,const pj_sockaddr_t * src_addr,int src_addr_len,pj_status_t accept_status)200 static pj_bool_t ssl_on_accept_complete(pj_ssl_sock_t *ssock,
201 pj_ssl_sock_t *newsock,
202 const pj_sockaddr_t *src_addr,
203 int src_addr_len,
204 pj_status_t accept_status)
205 {
206 struct test_state *parent_st = (struct test_state*)
207 pj_ssl_sock_get_user_data(ssock);
208 struct test_state *st;
209 void *read_buf[1];
210 pj_ssl_sock_info info;
211 char buf[64];
212 pj_status_t status;
213
214 PJ_UNUSED_ARG(src_addr_len);
215
216 if (accept_status != PJ_SUCCESS) {
217 if (newsock) {
218 st = (struct test_state*) pj_ssl_sock_get_user_data(newsock);
219 st->err = accept_status;
220 }
221 return PJ_FALSE;
222 }
223
224 /* Duplicate parent test state to newly accepted test state */
225 st = (struct test_state*)pj_pool_zalloc(parent_st->pool, sizeof(struct test_state));
226 *st = *parent_st;
227 pj_ssl_sock_set_user_data(newsock, st);
228
229 status = pj_ssl_sock_get_info(newsock, &info);
230 if (status != PJ_SUCCESS) {
231 app_perror("...ERROR pj_ssl_sock_get_info()", status);
232 goto on_return;
233 }
234
235 pj_sockaddr_print(src_addr, buf, sizeof(buf), 1);
236 PJ_LOG(3, ("", "...Accepted connection from %s", buf));
237
238 if (st->is_verbose)
239 dump_ssl_info(&info);
240
241 /* Start reading data */
242 read_buf[0] = st->read_buf;
243 status = pj_ssl_sock_start_read2(newsock, st->pool, sizeof(st->read_buf), (void**)read_buf, 0);
244 if (status != PJ_SUCCESS) {
245 app_perror("...ERROR pj_ssl_sock_start_read2()", status);
246 goto on_return;
247 }
248
249 /* Start sending data */
250 while (st->sent < st->send_str_len) {
251 pj_ssize_t size;
252
253 size = st->send_str_len - st->sent;
254 status = pj_ssl_sock_send(newsock, (pj_ioqueue_op_key_t*)&st->send_key,
255 st->send_str + st->sent, &size, 0);
256 if (status != PJ_SUCCESS && status != PJ_EPENDING) {
257 app_perror("...ERROR pj_ssl_sock_send()", status);
258 goto on_return;
259 }
260
261 if (status == PJ_SUCCESS) {
262 st->sent += size;
263 } else {
264 if (status == PJ_EPENDING)
265 status = PJ_SUCCESS;
266 break;
267 }
268 }
269
270 on_return:
271 st->err = status;
272
273 if (st->err != PJ_SUCCESS) {
274 pj_ssl_sock_close(newsock);
275 return PJ_FALSE;
276 }
277
278 return PJ_TRUE;
279 }
280
ssl_on_data_read(pj_ssl_sock_t * ssock,void * data,pj_size_t size,pj_status_t status,pj_size_t * remainder)281 static pj_bool_t ssl_on_data_read(pj_ssl_sock_t *ssock,
282 void *data,
283 pj_size_t size,
284 pj_status_t status,
285 pj_size_t *remainder)
286 {
287 struct test_state *st = (struct test_state*)
288 pj_ssl_sock_get_user_data(ssock);
289
290 PJ_UNUSED_ARG(remainder);
291 PJ_UNUSED_ARG(data);
292
293 if (size > 0) {
294 pj_size_t consumed;
295
296 /* Set random remainder */
297 *remainder = pj_rand() % 100;
298
299 /* Apply zero remainder if:
300 * - remainder is less than size, or
301 * - connection closed/error
302 * - echo/check_eco set
303 */
304 if (*remainder > size || status != PJ_SUCCESS || st->echo || st->check_echo)
305 *remainder = 0;
306
307 consumed = size - *remainder;
308 st->recv += consumed;
309
310 //printf("%.*s", consumed, (char*)data);
311
312 pj_memmove(data, (char*)data + consumed, *remainder);
313
314 /* Echo data when specified to */
315 if (st->echo) {
316 pj_ssize_t size_ = consumed;
317 status = pj_ssl_sock_send(ssock, (pj_ioqueue_op_key_t*)&st->send_key, data, &size_, 0);
318 if (status != PJ_SUCCESS && status != PJ_EPENDING) {
319 app_perror("...ERROR pj_ssl_sock_send()", status);
320 goto on_return;
321 }
322
323 if (status == PJ_SUCCESS) {
324 st->sent += size_;
325 } else if (status == PJ_EPENDING) {
326 status = PJ_SUCCESS;
327 }
328 }
329
330 /* Verify echoed data when specified to */
331 if (st->check_echo) {
332 if (!st->check_echo_ptr)
333 st->check_echo_ptr = st->send_str;
334
335 if (pj_memcmp(st->check_echo_ptr, data, consumed)) {
336 status = PJ_EINVAL;
337 app_perror("...ERROR echoed data not exact", status);
338 goto on_return;
339 }
340 st->check_echo_ptr += consumed;
341
342 /* Echo received completely */
343 if (st->send_str_len == st->recv) {
344 pj_ssl_sock_info info;
345 char buf[64];
346
347 status = pj_ssl_sock_get_info(ssock, &info);
348 if (status != PJ_SUCCESS) {
349 app_perror("...ERROR pj_ssl_sock_get_info()", status);
350 goto on_return;
351 }
352
353 pj_sockaddr_print((pj_sockaddr_t*)&info.local_addr, buf, sizeof(buf), 1);
354 PJ_LOG(3, ("", "...%s successfully recv %d bytes echo", buf, st->recv));
355 st->done = PJ_TRUE;
356 }
357 }
358 }
359
360 if (status != PJ_SUCCESS) {
361 if (status == PJ_EEOF) {
362 status = PJ_SUCCESS;
363 st->done = PJ_TRUE;
364 } else {
365 app_perror("...ERROR ssl_on_data_read()", status);
366 }
367 }
368
369 on_return:
370 st->err = status;
371
372 if (st->err != PJ_SUCCESS || st->done) {
373 pj_ssl_sock_close(ssock);
374 if (!st->is_server)
375 clients_num--;
376 return PJ_FALSE;
377 }
378
379 return PJ_TRUE;
380 }
381
ssl_on_data_sent(pj_ssl_sock_t * ssock,pj_ioqueue_op_key_t * op_key,pj_ssize_t sent)382 static pj_bool_t ssl_on_data_sent(pj_ssl_sock_t *ssock,
383 pj_ioqueue_op_key_t *op_key,
384 pj_ssize_t sent)
385 {
386 struct test_state *st = (struct test_state*)
387 pj_ssl_sock_get_user_data(ssock);
388 PJ_UNUSED_ARG(op_key);
389
390 if (sent < 0) {
391 st->err = (pj_status_t)-sent;
392 } else {
393 st->sent += sent;
394
395 /* Send more if any */
396 while (st->sent < st->send_str_len) {
397 pj_ssize_t size;
398 pj_status_t status;
399
400 size = st->send_str_len - st->sent;
401 status = pj_ssl_sock_send(ssock, (pj_ioqueue_op_key_t*)&st->send_key,
402 st->send_str + st->sent, &size, 0);
403 if (status != PJ_SUCCESS && status != PJ_EPENDING) {
404 app_perror("...ERROR pj_ssl_sock_send()", status);
405 st->err = status;
406 break;
407 }
408
409 if (status == PJ_SUCCESS)
410 st->sent += size;
411 else
412 break;
413 }
414 }
415
416 if (st->err != PJ_SUCCESS) {
417 pj_ssl_sock_close(ssock);
418 if (!st->is_server)
419 clients_num--;
420 return PJ_FALSE;
421 }
422
423 return PJ_TRUE;
424 }
425
426 #define HTTP_SERVER_ADDR "trac.pjsip.org"
427 #define HTTP_SERVER_PORT 443
428 #define HTTP_REQ "GET https://" HTTP_SERVER_ADDR "/ HTTP/1.0\r\n\r\n";
429
https_client_test(unsigned ms_timeout)430 static int https_client_test(unsigned ms_timeout)
431 {
432 pj_pool_t *pool = NULL;
433 pj_ioqueue_t *ioqueue = NULL;
434 pj_timer_heap_t *timer = NULL;
435 pj_ssl_sock_t *ssock = NULL;
436 pj_ssl_sock_param param;
437 pj_status_t status;
438 struct test_state state = {0};
439 pj_sockaddr local_addr, rem_addr;
440 pj_str_t tmp_st;
441
442 pool = pj_pool_create(mem, "https_get", 256, 256, NULL);
443
444 status = pj_ioqueue_create(pool, 4, &ioqueue);
445 if (status != PJ_SUCCESS) {
446 goto on_return;
447 }
448
449 status = pj_timer_heap_create(pool, 4, &timer);
450 if (status != PJ_SUCCESS) {
451 goto on_return;
452 }
453
454 state.pool = pool;
455 state.send_str = HTTP_REQ;
456 state.send_str_len = pj_ansi_strlen(state.send_str);
457 state.is_verbose = PJ_TRUE;
458
459 pj_ssl_sock_param_default(¶m);
460 param.cb.on_connect_complete = &ssl_on_connect_complete;
461 param.cb.on_data_read = &ssl_on_data_read;
462 param.cb.on_data_sent = &ssl_on_data_sent;
463 param.ioqueue = ioqueue;
464 param.user_data = &state;
465 param.server_name = pj_str((char*)HTTP_SERVER_ADDR);
466 param.timer_heap = timer;
467 param.timeout.sec = 0;
468 param.timeout.msec = ms_timeout;
469 param.proto = PJ_SSL_SOCK_PROTO_SSL23;
470 pj_time_val_normalize(¶m.timeout);
471
472 status = pj_ssl_sock_create(pool, ¶m, &ssock);
473 if (status != PJ_SUCCESS) {
474 goto on_return;
475 }
476
477 pj_sockaddr_init(PJ_AF_INET, &local_addr, pj_strset2(&tmp_st, "0.0.0.0"), 0);
478 pj_sockaddr_init(PJ_AF_INET, &rem_addr, pj_strset2(&tmp_st, HTTP_SERVER_ADDR), HTTP_SERVER_PORT);
479 status = pj_ssl_sock_start_connect(ssock, pool, &local_addr, &rem_addr, sizeof(rem_addr));
480 if (status == PJ_SUCCESS) {
481 ssl_on_connect_complete(ssock, PJ_SUCCESS);
482 } else if (status == PJ_EPENDING) {
483 status = PJ_SUCCESS;
484 } else {
485 goto on_return;
486 }
487
488 /* Wait until everything has been sent/received */
489 while (state.err == PJ_SUCCESS && !state.done) {
490 #ifdef PJ_SYMBIAN
491 pj_symbianos_poll(-1, 1000);
492 #else
493 pj_time_val delay = {0, 100};
494 pj_ioqueue_poll(ioqueue, &delay);
495 pj_timer_heap_poll(timer, &delay);
496 #endif
497 }
498
499 if (state.err) {
500 status = state.err;
501 goto on_return;
502 }
503
504 PJ_LOG(3, ("", "...Done!"));
505 PJ_LOG(3, ("", ".....Sent/recv: %d/%d bytes", state.sent, state.recv));
506
507 on_return:
508 if (ssock && !state.err && !state.done)
509 pj_ssl_sock_close(ssock);
510 if (ioqueue)
511 pj_ioqueue_destroy(ioqueue);
512 if (timer)
513 pj_timer_heap_destroy(timer);
514 if (pool)
515 pj_pool_release(pool);
516
517 return status;
518 }
519
520 #if !(defined(TEST_LOAD_FROM_FILES) && TEST_LOAD_FROM_FILES==1)
load_cert_to_buf(pj_pool_t * pool,const pj_str_t * file_name,pj_ssl_cert_buffer * buf)521 static pj_status_t load_cert_to_buf(pj_pool_t *pool, const pj_str_t *file_name,
522 pj_ssl_cert_buffer *buf)
523 {
524 pj_status_t status;
525 pj_oshandle_t fd = 0;
526 pj_ssize_t size = (pj_ssize_t)pj_file_size(file_name->ptr);
527
528 status = pj_file_open(pool, file_name->ptr, PJ_O_RDONLY, &fd);
529 if (status != PJ_SUCCESS)
530 return status;
531
532 buf->ptr = (char*)pj_pool_zalloc(pool, size+1);
533 status = pj_file_read(fd, buf->ptr, &size);
534 buf->slen = size;
535
536 pj_file_close(fd);
537 fd = NULL;
538 return status;
539 }
540 #endif
541
echo_test(pj_ssl_sock_proto srv_proto,pj_ssl_sock_proto cli_proto,pj_ssl_cipher srv_cipher,pj_ssl_cipher cli_cipher,pj_bool_t req_client_cert,pj_bool_t client_provide_cert)542 static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto,
543 pj_ssl_cipher srv_cipher, pj_ssl_cipher cli_cipher,
544 pj_bool_t req_client_cert, pj_bool_t client_provide_cert)
545 {
546 pj_pool_t *pool = NULL;
547 pj_ioqueue_t *ioqueue = NULL;
548 pj_timer_heap_t *timer = NULL;
549 pj_ssl_sock_t *ssock_serv = NULL;
550 pj_ssl_sock_t *ssock_cli = NULL;
551 pj_ssl_sock_param param;
552 struct test_state state_serv = { 0 };
553 struct test_state state_cli = { 0 };
554 pj_sockaddr addr, listen_addr;
555 pj_ssl_cipher ciphers[1];
556 pj_ssl_cert_t *cert = NULL;
557 pj_status_t status;
558
559 pool = pj_pool_create(mem, "ssl_echo", 256, 256, NULL);
560
561 status = pj_ioqueue_create(pool, 4, &ioqueue);
562 if (status != PJ_SUCCESS) {
563 goto on_return;
564 }
565
566 status = pj_timer_heap_create(pool, 4, &timer);
567 if (status != PJ_SUCCESS) {
568 goto on_return;
569 }
570
571 pj_ssl_sock_param_default(¶m);
572 param.cb.on_accept_complete2 = &ssl_on_accept_complete;
573 param.cb.on_connect_complete = &ssl_on_connect_complete;
574 param.cb.on_data_read = &ssl_on_data_read;
575 param.cb.on_data_sent = &ssl_on_data_sent;
576 param.ioqueue = ioqueue;
577 param.timer_heap = timer;
578 param.ciphers = ciphers;
579
580 /* Init default bind address */
581 {
582 pj_str_t tmp_st;
583 pj_sockaddr_init(PJ_AF_INET, &addr, pj_strset2(&tmp_st, "127.0.0.1"), 0);
584 }
585
586 /* === SERVER === */
587 param.proto = srv_proto;
588 param.user_data = &state_serv;
589 param.ciphers_num = (srv_cipher == -1)? 0 : 1;
590 param.require_client_cert = req_client_cert;
591 ciphers[0] = srv_cipher;
592
593 state_serv.pool = pool;
594 state_serv.echo = PJ_TRUE;
595 state_serv.is_server = PJ_TRUE;
596 state_serv.is_verbose = PJ_TRUE;
597
598 status = pj_ssl_sock_create(pool, ¶m, &ssock_serv);
599 if (status != PJ_SUCCESS) {
600 goto on_return;
601 }
602
603 /* Set server cert */
604 {
605 pj_str_t ca_file = pj_str(CERT_CA_FILE);
606 pj_str_t cert_file = pj_str(CERT_FILE);
607 pj_str_t privkey_file = pj_str(CERT_PRIVKEY_FILE);
608 pj_str_t privkey_pass = pj_str(CERT_PRIVKEY_PASS);
609
610 #if (defined(TEST_LOAD_FROM_FILES) && TEST_LOAD_FROM_FILES==1)
611 status = pj_ssl_cert_load_from_files(pool, &ca_file, &cert_file,
612 &privkey_file, &privkey_pass,
613 &cert);
614 #else
615 pj_ssl_cert_buffer ca_buf, cert_buf, privkey_buf;
616
617 status = load_cert_to_buf(pool, &ca_file, &ca_buf);
618 if (status != PJ_SUCCESS) {
619 goto on_return;
620 }
621
622 status = load_cert_to_buf(pool, &cert_file, &cert_buf);
623 if (status != PJ_SUCCESS) {
624 goto on_return;
625 }
626
627 status = load_cert_to_buf(pool, &privkey_file, &privkey_buf);
628 if (status != PJ_SUCCESS) {
629 goto on_return;
630 }
631
632 status = pj_ssl_cert_load_from_buffer(pool, &ca_buf, &cert_buf,
633 &privkey_buf, &privkey_pass,
634 &cert);
635 #endif
636 if (status != PJ_SUCCESS) {
637 goto on_return;
638 }
639
640 status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert);
641 if (status != PJ_SUCCESS) {
642 goto on_return;
643 }
644 }
645
646 status = pj_ssl_sock_start_accept(ssock_serv, pool, &addr, pj_sockaddr_get_len(&addr));
647 if (status != PJ_SUCCESS) {
648 goto on_return;
649 }
650
651 /* Get listener address */
652 {
653 pj_ssl_sock_info info;
654
655 pj_ssl_sock_get_info(ssock_serv, &info);
656 pj_sockaddr_cp(&listen_addr, &info.local_addr);
657 }
658
659 /* === CLIENT === */
660 param.proto = cli_proto;
661 param.user_data = &state_cli;
662 param.ciphers_num = (cli_cipher == -1)? 0 : 1;
663 ciphers[0] = cli_cipher;
664
665 state_cli.pool = pool;
666 state_cli.check_echo = PJ_TRUE;
667 state_cli.is_verbose = PJ_TRUE;
668
669 {
670 pj_time_val now;
671
672 pj_gettimeofday(&now);
673 pj_srand((unsigned)now.sec);
674 state_cli.send_str_len = (pj_rand() % 5 + 1) * 1024 + pj_rand() % 1024;
675 }
676 state_cli.send_str = (char*)pj_pool_alloc(pool, state_cli.send_str_len);
677 {
678 unsigned i;
679 for (i = 0; i < state_cli.send_str_len; ++i)
680 state_cli.send_str[i] = (char)(pj_rand() % 256);
681 }
682
683 status = pj_ssl_sock_create(pool, ¶m, &ssock_cli);
684 if (status != PJ_SUCCESS) {
685 goto on_return;
686 }
687
688 /* Set cert for client */
689 {
690
691 if (!client_provide_cert) {
692 pj_str_t ca_file = pj_str(CERT_CA_FILE);
693 pj_str_t null_str = pj_str("");
694
695 #if (defined(TEST_LOAD_FROM_FILES) && TEST_LOAD_FROM_FILES==1)
696 status = pj_ssl_cert_load_from_files(pool, &ca_file, &null_str,
697 &null_str, &null_str, &cert);
698 #else
699 pj_ssl_cert_buffer null_buf, ca_buf;
700
701 null_buf.slen = 0;
702
703 status = load_cert_to_buf(pool, &ca_file, &ca_buf);
704 if (status != PJ_SUCCESS) {
705 goto on_return;
706 }
707
708 status = pj_ssl_cert_load_from_buffer(pool, &ca_buf, &null_buf,
709 &null_buf, &null_str, &cert);
710 #endif
711 if (status != PJ_SUCCESS) {
712 goto on_return;
713 }
714
715 }
716
717 status = pj_ssl_sock_set_certificate(ssock_cli, pool, cert);
718 if (status != PJ_SUCCESS) {
719 goto on_return;
720 }
721 }
722
723 status = pj_ssl_sock_start_connect(ssock_cli, pool, &addr, &listen_addr, pj_sockaddr_get_len(&addr));
724 if (status == PJ_SUCCESS) {
725 ssl_on_connect_complete(ssock_cli, PJ_SUCCESS);
726 } else if (status == PJ_EPENDING) {
727 status = PJ_SUCCESS;
728 } else {
729 goto on_return;
730 }
731
732 /* Wait until everything has been sent/received or error */
733 while (!state_serv.err && !state_cli.err && !state_serv.done && !state_cli.done)
734 {
735 #ifdef PJ_SYMBIAN
736 pj_symbianos_poll(-1, 1000);
737 #else
738 pj_time_val delay = {0, 100};
739 pj_ioqueue_poll(ioqueue, &delay);
740 #endif
741 }
742
743 /* Clean up sockets */
744 {
745 pj_time_val delay = {0, 100};
746 while (pj_ioqueue_poll(ioqueue, &delay) > 0);
747 }
748
749 if (state_serv.err || state_cli.err) {
750 if (state_serv.err != PJ_SUCCESS)
751 status = state_serv.err;
752 else
753 status = state_cli.err;
754
755 goto on_return;
756 }
757
758 PJ_LOG(3, ("", "...Done!"));
759 PJ_LOG(3, ("", ".....Sent/recv: %d/%d bytes", state_cli.sent, state_cli.recv));
760
761 on_return:
762 #if (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_DARWIN) || \
763 (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_APPLE)
764 if (status != PJ_SUCCESS) {
765 PJ_LOG(3, ("", "Apple SSL requires the private key to be "
766 "inside the Keychain. So double click on "
767 "the file pjlib/build/privkey.p12 to "
768 "place it in the Keychain. "
769 "The password is \"pjsip\"."));
770 }
771 #endif
772
773 if (ssock_serv)
774 pj_ssl_sock_close(ssock_serv);
775 if (ssock_cli && !state_cli.err && !state_cli.done)
776 pj_ssl_sock_close(ssock_cli);
777 if (ioqueue)
778 pj_ioqueue_destroy(ioqueue);
779 if (timer)
780 pj_timer_heap_destroy(timer);
781 if (pool)
782 pj_pool_release(pool);
783
784 return status;
785 }
786
787
asock_on_data_read(pj_activesock_t * asock,void * data,pj_size_t size,pj_status_t status,pj_size_t * remainder)788 static pj_bool_t asock_on_data_read(pj_activesock_t *asock,
789 void *data,
790 pj_size_t size,
791 pj_status_t status,
792 pj_size_t *remainder)
793 {
794 struct test_state *st = (struct test_state*)
795 pj_activesock_get_user_data(asock);
796
797 PJ_UNUSED_ARG(data);
798 PJ_UNUSED_ARG(size);
799 PJ_UNUSED_ARG(remainder);
800
801 if (status != PJ_SUCCESS) {
802 if (status == PJ_EEOF) {
803 status = PJ_SUCCESS;
804 st->done = PJ_TRUE;
805 } else {
806 app_perror("...ERROR asock_on_data_read()", status);
807 }
808 }
809
810 st->err = status;
811
812 if (st->err != PJ_SUCCESS || st->done) {
813 pj_activesock_close(asock);
814 if (!st->is_server)
815 clients_num--;
816 return PJ_FALSE;
817 }
818
819 return PJ_TRUE;
820 }
821
822
asock_on_connect_complete(pj_activesock_t * asock,pj_status_t status)823 static pj_bool_t asock_on_connect_complete(pj_activesock_t *asock,
824 pj_status_t status)
825 {
826 struct test_state *st = (struct test_state*)
827 pj_activesock_get_user_data(asock);
828
829 if (status == PJ_SUCCESS) {
830 void *read_buf[1];
831
832 /* Start reading data */
833 read_buf[0] = st->read_buf;
834 status = pj_activesock_start_read2(asock, st->pool, sizeof(st->read_buf), (void**)read_buf, 0);
835 if (status != PJ_SUCCESS) {
836 app_perror("...ERROR pj_ssl_sock_start_read2()", status);
837 }
838 }
839
840 st->err = status;
841
842 if (st->err != PJ_SUCCESS) {
843 pj_activesock_close(asock);
844 if (!st->is_server)
845 clients_num--;
846 return PJ_FALSE;
847 }
848
849 return PJ_TRUE;
850 }
851
asock_on_accept_complete(pj_activesock_t * asock,pj_sock_t newsock,const pj_sockaddr_t * src_addr,int src_addr_len)852 static pj_bool_t asock_on_accept_complete(pj_activesock_t *asock,
853 pj_sock_t newsock,
854 const pj_sockaddr_t *src_addr,
855 int src_addr_len)
856 {
857 struct test_state *st;
858 void *read_buf[1];
859 pj_activesock_t *new_asock;
860 pj_activesock_cb asock_cb = { 0 };
861 pj_status_t status;
862
863 PJ_UNUSED_ARG(src_addr);
864 PJ_UNUSED_ARG(src_addr_len);
865
866 st = (struct test_state*) pj_activesock_get_user_data(asock);
867
868 asock_cb.on_data_read = &asock_on_data_read;
869 status = pj_activesock_create(st->pool, newsock, pj_SOCK_STREAM(), NULL,
870 st->ioqueue, &asock_cb, st, &new_asock);
871 if (status != PJ_SUCCESS) {
872 goto on_return;
873 }
874
875 /* Start reading data */
876 read_buf[0] = st->read_buf;
877 status = pj_activesock_start_read2(new_asock, st->pool,
878 sizeof(st->read_buf),
879 (void**)read_buf, 0);
880 if (status != PJ_SUCCESS) {
881 app_perror("...ERROR pj_ssl_sock_start_read2()", status);
882 }
883
884 on_return:
885 st->err = status;
886
887 if (st->err != PJ_SUCCESS)
888 pj_activesock_close(new_asock);
889
890 return PJ_TRUE;
891 }
892
893
894 /* Raw TCP socket try to connect to SSL socket server, once
895 * connection established, it will just do nothing, SSL socket
896 * server should be able to close the connection after specified
897 * timeout period (set ms_timeout to 0 to disable timer).
898 */
client_non_ssl(unsigned ms_timeout)899 static int client_non_ssl(unsigned ms_timeout)
900 {
901 pj_pool_t *pool = NULL;
902 pj_ioqueue_t *ioqueue = NULL;
903 pj_timer_heap_t *timer = NULL;
904 pj_ssl_sock_t *ssock_serv = NULL;
905 pj_activesock_t *asock_cli = NULL;
906 pj_activesock_cb asock_cb = { 0 };
907 pj_sock_t sock = PJ_INVALID_SOCKET;
908 pj_ssl_sock_param param;
909 struct test_state state_serv = { 0 };
910 struct test_state state_cli = { 0 };
911 pj_sockaddr listen_addr;
912 pj_ssl_cert_t *cert = NULL;
913 pj_status_t status;
914
915 pool = pj_pool_create(mem, "ssl_accept_raw_tcp", 256, 256, NULL);
916
917 status = pj_ioqueue_create(pool, 4, &ioqueue);
918 if (status != PJ_SUCCESS) {
919 goto on_return;
920 }
921
922 status = pj_timer_heap_create(pool, 4, &timer);
923 if (status != PJ_SUCCESS) {
924 goto on_return;
925 }
926
927 /* Set cert */
928 {
929 pj_str_t ca_file = pj_str(CERT_CA_FILE);
930 pj_str_t cert_file = pj_str(CERT_FILE);
931 pj_str_t privkey_file = pj_str(CERT_PRIVKEY_FILE);
932 pj_str_t privkey_pass = pj_str(CERT_PRIVKEY_PASS);
933
934 #if (defined(TEST_LOAD_FROM_FILES) && TEST_LOAD_FROM_FILES==1)
935 status = pj_ssl_cert_load_from_files(pool, &ca_file, &cert_file,
936 &privkey_file, &privkey_pass,
937 &cert);
938 #else
939 pj_ssl_cert_buffer ca_buf, cert_buf, privkey_buf;
940
941 status = load_cert_to_buf(pool, &ca_file, &ca_buf);
942 if (status != PJ_SUCCESS) {
943 goto on_return;
944 }
945
946 status = load_cert_to_buf(pool, &cert_file, &cert_buf);
947 if (status != PJ_SUCCESS) {
948 goto on_return;
949 }
950
951 status = load_cert_to_buf(pool, &privkey_file, &privkey_buf);
952 if (status != PJ_SUCCESS) {
953 goto on_return;
954 }
955
956 status = pj_ssl_cert_load_from_buffer(pool, &ca_buf, &cert_buf,
957 &privkey_buf, &privkey_pass,
958 &cert);
959 #endif
960 if (status != PJ_SUCCESS) {
961 goto on_return;
962 }
963 }
964
965 pj_ssl_sock_param_default(¶m);
966 param.cb.on_accept_complete2 = &ssl_on_accept_complete;
967 param.cb.on_data_read = &ssl_on_data_read;
968 param.cb.on_data_sent = &ssl_on_data_sent;
969 param.ioqueue = ioqueue;
970 param.timer_heap = timer;
971 param.timeout.sec = 0;
972 param.timeout.msec = ms_timeout;
973 pj_time_val_normalize(¶m.timeout);
974
975 /* SERVER */
976 param.user_data = &state_serv;
977 state_serv.pool = pool;
978 state_serv.is_server = PJ_TRUE;
979 state_serv.is_verbose = PJ_TRUE;
980
981 status = pj_ssl_sock_create(pool, ¶m, &ssock_serv);
982 if (status != PJ_SUCCESS) {
983 goto on_return;
984 }
985
986 status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert);
987 if (status != PJ_SUCCESS) {
988 goto on_return;
989 }
990
991 /* Init bind address */
992 {
993 pj_str_t tmp_st;
994 pj_sockaddr_init(PJ_AF_INET, &listen_addr, pj_strset2(&tmp_st, "127.0.0.1"), 0);
995 }
996
997 status = pj_ssl_sock_start_accept(ssock_serv, pool, &listen_addr, pj_sockaddr_get_len(&listen_addr));
998 if (status != PJ_SUCCESS) {
999 goto on_return;
1000 }
1001
1002 /* Update listener address */
1003 {
1004 pj_ssl_sock_info info;
1005
1006 pj_ssl_sock_get_info(ssock_serv, &info);
1007 pj_sockaddr_cp(&listen_addr, &info.local_addr);
1008 }
1009
1010 /* CLIENT */
1011 state_cli.pool = pool;
1012 status = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &sock);
1013 if (status != PJ_SUCCESS) {
1014 goto on_return;
1015 }
1016
1017 asock_cb.on_connect_complete = &asock_on_connect_complete;
1018 asock_cb.on_data_read = &asock_on_data_read;
1019 status = pj_activesock_create(pool, sock, pj_SOCK_STREAM(), NULL,
1020 ioqueue, &asock_cb, &state_cli, &asock_cli);
1021 if (status != PJ_SUCCESS) {
1022 goto on_return;
1023 }
1024
1025 status = pj_activesock_start_connect(asock_cli, pool, (pj_sockaddr_t*)&listen_addr,
1026 pj_sockaddr_get_len(&listen_addr));
1027 if (status == PJ_SUCCESS) {
1028 asock_on_connect_complete(asock_cli, PJ_SUCCESS);
1029 } else if (status == PJ_EPENDING) {
1030 status = PJ_SUCCESS;
1031 } else {
1032 goto on_return;
1033 }
1034
1035 /* Wait until everything has been sent/received or error */
1036 while (!state_serv.err && !state_cli.err && !state_serv.done && !state_cli.done)
1037 {
1038 #ifdef PJ_SYMBIAN
1039 pj_symbianos_poll(-1, 1000);
1040 #else
1041 pj_time_val delay = {0, 100};
1042 pj_ioqueue_poll(ioqueue, &delay);
1043 pj_timer_heap_poll(timer, &delay);
1044 #endif
1045 }
1046
1047 if (state_serv.err || state_cli.err) {
1048 if (state_serv.err != PJ_SUCCESS)
1049 status = state_serv.err;
1050 else
1051 status = state_cli.err;
1052
1053 goto on_return;
1054 }
1055
1056 PJ_LOG(3, ("", "...Done!"));
1057
1058 on_return:
1059 if (ssock_serv)
1060 pj_ssl_sock_close(ssock_serv);
1061 if (asock_cli && !state_cli.err && !state_cli.done)
1062 pj_activesock_close(asock_cli);
1063 if (timer)
1064 pj_timer_heap_destroy(timer);
1065 if (ioqueue)
1066 pj_ioqueue_destroy(ioqueue);
1067 if (pool)
1068 pj_pool_release(pool);
1069
1070 return status;
1071 }
1072
1073
1074 /* SSL socket try to connect to raw TCP socket server, once
1075 * connection established, SSL socket will try to perform SSL
1076 * handshake. SSL client socket should be able to close the
1077 * connection after specified timeout period (set ms_timeout to
1078 * 0 to disable timer).
1079 */
server_non_ssl(unsigned ms_timeout)1080 static int server_non_ssl(unsigned ms_timeout)
1081 {
1082 pj_pool_t *pool = NULL;
1083 pj_ioqueue_t *ioqueue = NULL;
1084 pj_timer_heap_t *timer = NULL;
1085 pj_activesock_t *asock_serv = NULL;
1086 pj_ssl_sock_t *ssock_cli = NULL;
1087 pj_activesock_cb asock_cb = { 0 };
1088 pj_sock_t sock = PJ_INVALID_SOCKET;
1089 pj_ssl_sock_param param;
1090 struct test_state state_serv = { 0 };
1091 struct test_state state_cli = { 0 };
1092 pj_sockaddr addr, listen_addr;
1093 pj_status_t status;
1094
1095 pool = pj_pool_create(mem, "ssl_connect_raw_tcp", 256, 256, NULL);
1096
1097 status = pj_ioqueue_create(pool, 4, &ioqueue);
1098 if (status != PJ_SUCCESS) {
1099 goto on_return;
1100 }
1101
1102 status = pj_timer_heap_create(pool, 4, &timer);
1103 if (status != PJ_SUCCESS) {
1104 goto on_return;
1105 }
1106
1107 /* SERVER */
1108 state_serv.pool = pool;
1109 state_serv.ioqueue = ioqueue;
1110
1111 status = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &sock);
1112 if (status != PJ_SUCCESS) {
1113 goto on_return;
1114 }
1115
1116 /* Init bind address */
1117 {
1118 pj_str_t tmp_st;
1119 pj_sockaddr_init(PJ_AF_INET, &listen_addr, pj_strset2(&tmp_st, "127.0.0.1"), 0);
1120 }
1121
1122 status = pj_sock_bind(sock, (pj_sockaddr_t*)&listen_addr,
1123 pj_sockaddr_get_len((pj_sockaddr_t*)&listen_addr));
1124 if (status != PJ_SUCCESS) {
1125 goto on_return;
1126 }
1127
1128 status = pj_sock_listen(sock, PJ_SOMAXCONN);
1129 if (status != PJ_SUCCESS) {
1130 goto on_return;
1131 }
1132
1133 asock_cb.on_accept_complete = &asock_on_accept_complete;
1134 status = pj_activesock_create(pool, sock, pj_SOCK_STREAM(), NULL,
1135 ioqueue, &asock_cb, &state_serv, &asock_serv);
1136 if (status != PJ_SUCCESS) {
1137 goto on_return;
1138 }
1139
1140 status = pj_activesock_start_accept(asock_serv, pool);
1141 if (status != PJ_SUCCESS)
1142 goto on_return;
1143
1144 /* Update listener address */
1145 {
1146 int addr_len;
1147
1148 addr_len = sizeof(listen_addr);
1149 pj_sock_getsockname(sock, (pj_sockaddr_t*)&listen_addr, &addr_len);
1150 }
1151
1152 /* CLIENT */
1153 pj_ssl_sock_param_default(¶m);
1154 param.cb.on_connect_complete = &ssl_on_connect_complete;
1155 param.cb.on_data_read = &ssl_on_data_read;
1156 param.cb.on_data_sent = &ssl_on_data_sent;
1157 param.ioqueue = ioqueue;
1158 param.timer_heap = timer;
1159 param.timeout.sec = 0;
1160 param.timeout.msec = ms_timeout;
1161 pj_time_val_normalize(¶m.timeout);
1162 param.user_data = &state_cli;
1163
1164 state_cli.pool = pool;
1165 state_cli.is_server = PJ_FALSE;
1166 state_cli.is_verbose = PJ_TRUE;
1167
1168 status = pj_ssl_sock_create(pool, ¶m, &ssock_cli);
1169 if (status != PJ_SUCCESS) {
1170 goto on_return;
1171 }
1172
1173 /* Init default bind address */
1174 {
1175 pj_str_t tmp_st;
1176 pj_sockaddr_init(PJ_AF_INET, &addr, pj_strset2(&tmp_st, "127.0.0.1"), 0);
1177 }
1178
1179 status = pj_ssl_sock_start_connect(ssock_cli, pool,
1180 (pj_sockaddr_t*)&addr,
1181 (pj_sockaddr_t*)&listen_addr,
1182 pj_sockaddr_get_len(&listen_addr));
1183 if (status != PJ_EPENDING) {
1184 goto on_return;
1185 }
1186
1187 /* Wait until everything has been sent/received or error */
1188 while ((!state_serv.err && !state_serv.done) || (!state_cli.err && !state_cli.done))
1189 {
1190 #ifdef PJ_SYMBIAN
1191 pj_symbianos_poll(-1, 1000);
1192 #else
1193 pj_time_val delay = {0, 100};
1194 pj_ioqueue_poll(ioqueue, &delay);
1195 pj_timer_heap_poll(timer, &delay);
1196 #endif
1197 }
1198
1199 if (state_serv.err || state_cli.err) {
1200 if (state_cli.err != PJ_SUCCESS)
1201 status = state_cli.err;
1202 else
1203 status = state_serv.err;
1204
1205 goto on_return;
1206 }
1207
1208 PJ_LOG(3, ("", "...Done!"));
1209
1210 on_return:
1211 if (asock_serv)
1212 pj_activesock_close(asock_serv);
1213 if (ssock_cli && !state_cli.err && !state_cli.done)
1214 pj_ssl_sock_close(ssock_cli);
1215 if (timer)
1216 pj_timer_heap_destroy(timer);
1217 if (ioqueue)
1218 pj_ioqueue_destroy(ioqueue);
1219 if (pool)
1220 pj_pool_release(pool);
1221
1222 return status;
1223 }
1224
1225
1226 /* Test will perform multiple clients trying to connect to single server.
1227 * Once SSL connection established, echo test will be performed.
1228 */
perf_test(unsigned clients,unsigned ms_handshake_timeout)1229 static int perf_test(unsigned clients, unsigned ms_handshake_timeout)
1230 {
1231 pj_pool_t *pool = NULL;
1232 pj_ioqueue_t *ioqueue = NULL;
1233 pj_timer_heap_t *timer = NULL;
1234 pj_ssl_sock_t *ssock_serv = NULL;
1235 pj_ssl_sock_t **ssock_cli = NULL;
1236 pj_ssl_sock_param param;
1237 struct test_state state_serv = { 0 };
1238 struct test_state *state_cli = NULL;
1239 pj_sockaddr addr, listen_addr;
1240 pj_ssl_cert_t *cert = NULL;
1241 pj_status_t status;
1242 unsigned i, cli_err = 0;
1243 pj_size_t tot_sent = 0, tot_recv = 0;
1244 pj_time_val start;
1245
1246 pool = pj_pool_create(mem, "ssl_perf", 256, 256, NULL);
1247
1248 status = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioqueue);
1249 if (status != PJ_SUCCESS) {
1250 goto on_return;
1251 }
1252
1253 status = pj_timer_heap_create(pool, PJ_IOQUEUE_MAX_HANDLES, &timer);
1254 if (status != PJ_SUCCESS) {
1255 goto on_return;
1256 }
1257
1258 /* Set cert */
1259 {
1260 pj_str_t ca_file = pj_str(CERT_CA_FILE);
1261 pj_str_t cert_file = pj_str(CERT_FILE);
1262 pj_str_t privkey_file = pj_str(CERT_PRIVKEY_FILE);
1263 pj_str_t privkey_pass = pj_str(CERT_PRIVKEY_PASS);
1264
1265 #if (defined(TEST_LOAD_FROM_FILES) && TEST_LOAD_FROM_FILES==1)
1266 status = pj_ssl_cert_load_from_files(pool, &ca_file, &cert_file,
1267 &privkey_file, &privkey_pass,
1268 &cert);
1269 #else
1270 pj_ssl_cert_buffer ca_buf, cert_buf, privkey_buf;
1271
1272 status = load_cert_to_buf(pool, &ca_file, &ca_buf);
1273 if (status != PJ_SUCCESS) {
1274 goto on_return;
1275 }
1276
1277 status = load_cert_to_buf(pool, &cert_file, &cert_buf);
1278 if (status != PJ_SUCCESS) {
1279 goto on_return;
1280 }
1281
1282 status = load_cert_to_buf(pool, &privkey_file, &privkey_buf);
1283 if (status != PJ_SUCCESS) {
1284 goto on_return;
1285 }
1286
1287 status = pj_ssl_cert_load_from_buffer(pool, &ca_buf, &cert_buf,
1288 &privkey_buf, &privkey_pass,
1289 &cert);
1290 #endif
1291 if (status != PJ_SUCCESS) {
1292 goto on_return;
1293 }
1294 }
1295
1296 pj_ssl_sock_param_default(¶m);
1297 param.cb.on_accept_complete2 = &ssl_on_accept_complete;
1298 param.cb.on_connect_complete = &ssl_on_connect_complete;
1299 param.cb.on_data_read = &ssl_on_data_read;
1300 param.cb.on_data_sent = &ssl_on_data_sent;
1301 param.ioqueue = ioqueue;
1302 param.timer_heap = timer;
1303 param.timeout.sec = 0;
1304 param.timeout.msec = ms_handshake_timeout;
1305 pj_time_val_normalize(¶m.timeout);
1306
1307 /* Init default bind address */
1308 {
1309 pj_str_t tmp_st;
1310 pj_sockaddr_init(PJ_AF_INET, &addr, pj_strset2(&tmp_st, "127.0.0.1"), 0);
1311 }
1312
1313 /* SERVER */
1314 param.user_data = &state_serv;
1315
1316 state_serv.pool = pool;
1317 state_serv.echo = PJ_TRUE;
1318 state_serv.is_server = PJ_TRUE;
1319
1320 status = pj_ssl_sock_create(pool, ¶m, &ssock_serv);
1321 if (status != PJ_SUCCESS) {
1322 goto on_return;
1323 }
1324
1325 status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert);
1326 if (status != PJ_SUCCESS) {
1327 goto on_return;
1328 }
1329
1330 status = pj_ssl_sock_start_accept(ssock_serv, pool, &addr, pj_sockaddr_get_len(&addr));
1331 if (status != PJ_SUCCESS) {
1332 goto on_return;
1333 }
1334
1335 /* Get listening address for clients to connect to */
1336 {
1337 pj_ssl_sock_info info;
1338 char buf[64];
1339
1340 pj_ssl_sock_get_info(ssock_serv, &info);
1341 pj_sockaddr_cp(&listen_addr, &info.local_addr);
1342
1343 pj_sockaddr_print((pj_sockaddr_t*)&listen_addr, buf, sizeof(buf), 1);
1344 PJ_LOG(3, ("", "...Listener ready at %s", buf));
1345 }
1346
1347
1348 /* CLIENTS */
1349 clients_num = clients;
1350 param.timeout.sec = 0;
1351 param.timeout.msec = 0;
1352
1353 /* Init random seed */
1354 {
1355 pj_time_val now;
1356
1357 pj_gettimeofday(&now);
1358 pj_srand((unsigned)now.sec);
1359 }
1360
1361 /* Allocate SSL socket pointers and test state */
1362 ssock_cli = (pj_ssl_sock_t**)pj_pool_calloc(pool, clients, sizeof(pj_ssl_sock_t*));
1363 state_cli = (struct test_state*)pj_pool_calloc(pool, clients, sizeof(struct test_state));
1364
1365 /* Get start timestamp */
1366 pj_gettimeofday(&start);
1367
1368 /* Setup clients */
1369 for (i = 0; i < clients; ++i) {
1370 param.user_data = &state_cli[i];
1371
1372 state_cli[i].pool = pool;
1373 state_cli[i].check_echo = PJ_TRUE;
1374 state_cli[i].send_str_len = (pj_rand() % 5 + 1) * 1024 + pj_rand() % 1024;
1375 state_cli[i].send_str = (char*)pj_pool_alloc(pool, state_cli[i].send_str_len);
1376 {
1377 unsigned j;
1378 for (j = 0; j < state_cli[i].send_str_len; ++j)
1379 state_cli[i].send_str[j] = (char)(pj_rand() % 256);
1380 }
1381
1382 status = pj_ssl_sock_create(pool, ¶m, &ssock_cli[i]);
1383 if (status != PJ_SUCCESS) {
1384 app_perror("...ERROR pj_ssl_sock_create()", status);
1385 cli_err++;
1386 clients_num--;
1387 continue;
1388 }
1389
1390 status = pj_ssl_sock_start_connect(ssock_cli[i], pool, &addr, &listen_addr, pj_sockaddr_get_len(&addr));
1391 if (status == PJ_SUCCESS) {
1392 ssl_on_connect_complete(ssock_cli[i], PJ_SUCCESS);
1393 } else if (status == PJ_EPENDING) {
1394 status = PJ_SUCCESS;
1395 } else {
1396 app_perror("...ERROR pj_ssl_sock_create()", status);
1397 pj_ssl_sock_close(ssock_cli[i]);
1398 ssock_cli[i] = NULL;
1399 clients_num--;
1400 cli_err++;
1401 continue;
1402 }
1403
1404 /* Give chance to server to accept this client */
1405 {
1406 unsigned n = 5;
1407
1408 #ifdef PJ_SYMBIAN
1409 while(n && pj_symbianos_poll(-1, 1000))
1410 n--;
1411 #else
1412 pj_time_val delay = {0, 100};
1413 while(n && pj_ioqueue_poll(ioqueue, &delay) > 0)
1414 n--;
1415 #endif
1416 }
1417 }
1418
1419 /* Wait until everything has been sent/received or error */
1420 while (clients_num)
1421 {
1422 #ifdef PJ_SYMBIAN
1423 pj_symbianos_poll(-1, 1000);
1424 #else
1425 pj_time_val delay = {0, 100};
1426 pj_ioqueue_poll(ioqueue, &delay);
1427 pj_timer_heap_poll(timer, &delay);
1428 #endif
1429 }
1430
1431 /* Clean up sockets */
1432 {
1433 pj_time_val delay = {0, 500};
1434 while (pj_ioqueue_poll(ioqueue, &delay) > 0);
1435 }
1436
1437 if (state_serv.err != PJ_SUCCESS) {
1438 status = state_serv.err;
1439 goto on_return;
1440 }
1441
1442 PJ_LOG(3, ("", "...Done!"));
1443
1444 /* SSL setup and data transfer duration */
1445 {
1446 pj_time_val stop;
1447
1448 pj_gettimeofday(&stop);
1449 PJ_TIME_VAL_SUB(stop, start);
1450
1451 PJ_LOG(3, ("", ".....Setup & data transfer duration: %d.%03ds", stop.sec, stop.msec));
1452 }
1453
1454 /* Check clients status */
1455 for (i = 0; i < clients; ++i) {
1456 if (state_cli[i].err != PJ_SUCCESS)
1457 cli_err++;
1458
1459 tot_sent += state_cli[1].sent;
1460 tot_recv += state_cli[1].recv;
1461 }
1462
1463 PJ_LOG(3, ("", ".....Clients: %d (%d errors)", clients, cli_err));
1464 PJ_LOG(3, ("", ".....Total sent/recv: %d/%d bytes", tot_sent, tot_recv));
1465
1466 on_return:
1467 if (ssock_serv)
1468 pj_ssl_sock_close(ssock_serv);
1469
1470 if (ssock_cli && state_cli) {
1471 for (i = 0; i < clients; ++i) {
1472 if (ssock_cli[i] && !state_cli[i].err && !state_cli[i].done)
1473 pj_ssl_sock_close(ssock_cli[i]);
1474 }
1475 }
1476 if (ioqueue)
1477 pj_ioqueue_destroy(ioqueue);
1478 if (pool)
1479 pj_pool_release(pool);
1480
1481 return status;
1482 }
1483
1484 #if 0 && (!defined(PJ_SYMBIAN) || PJ_SYMBIAN==0)
1485 pj_status_t pj_ssl_sock_ossl_test_send_buf(pj_pool_t *pool);
1486 static int ossl_test_send_buf()
1487 {
1488 pj_pool_t *pool;
1489 pj_status_t status;
1490
1491 pool = pj_pool_create(mem, "send_buf", 256, 256, NULL);
1492 status = pj_ssl_sock_ossl_test_send_buf(pool);
1493 pj_pool_release(pool);
1494 return status;
1495 }
1496 #else
ossl_test_send_buf()1497 static int ossl_test_send_buf()
1498 {
1499 return 0;
1500 }
1501 #endif
1502
ssl_sock_test(void)1503 int ssl_sock_test(void)
1504 {
1505 int ret;
1506
1507 PJ_LOG(3,("", "..test ossl send buf"));
1508 ret = ossl_test_send_buf();
1509 if (ret != 0)
1510 return ret;
1511
1512 PJ_LOG(3,("", "..get cipher list test"));
1513 ret = get_cipher_list();
1514 if (ret != 0)
1515 return ret;
1516
1517 PJ_LOG(3,("", "..https client test"));
1518 ret = https_client_test(30000);
1519 // Ignore test result as internet connection may not be available.
1520 //if (ret != 0)
1521 //return ret;
1522
1523 #ifndef PJ_SYMBIAN
1524
1525 /* On Symbian platforms, SSL socket is implemented using CSecureSocket,
1526 * and it hasn't supported server mode, so exclude the following tests,
1527 * which require SSL server, for now.
1528 */
1529
1530 PJ_LOG(3,("", "..echo test w/ TLSv1 and PJ_TLS_RSA_WITH_AES_256_CBC_SHA cipher"));
1531 ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1, PJ_SSL_SOCK_PROTO_TLS1,
1532 PJ_TLS_RSA_WITH_AES_256_CBC_SHA, PJ_TLS_RSA_WITH_AES_256_CBC_SHA,
1533 PJ_FALSE, PJ_FALSE);
1534 if (ret != 0)
1535 return ret;
1536
1537 PJ_LOG(3,("", "..echo test w/ SSLv23 and PJ_TLS_RSA_WITH_AES_256_CBC_SHA cipher"));
1538 ret = echo_test(PJ_SSL_SOCK_PROTO_SSL23, PJ_SSL_SOCK_PROTO_SSL23,
1539 PJ_TLS_RSA_WITH_AES_256_CBC_SHA, PJ_TLS_RSA_WITH_AES_256_CBC_SHA,
1540 PJ_FALSE, PJ_FALSE);
1541 if (ret != 0)
1542 return ret;
1543
1544 PJ_LOG(3,("", "..echo test w/ compatible proto: server TLSv1.2 vs client TLSv1.2"));
1545 ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1_2, PJ_SSL_SOCK_PROTO_TLS1_2,
1546 -1, -1,
1547 PJ_FALSE, PJ_FALSE);
1548 if (ret != 0)
1549 return ret;
1550
1551 PJ_LOG(3,("", "..echo test w/ compatible proto: server TLSv1.2+1.3 vs client TLSv1.3"));
1552 ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1_2 | PJ_SSL_SOCK_PROTO_TLS1_3, PJ_SSL_SOCK_PROTO_TLS1_3,
1553 -1, -1,
1554 PJ_FALSE, PJ_FALSE);
1555 if (ret != 0)
1556 return ret;
1557
1558 PJ_LOG(3,("", "..echo test w/ incompatible proto: server TLSv1 vs client SSL3"));
1559 ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1, PJ_SSL_SOCK_PROTO_SSL3,
1560 PJ_TLS_RSA_WITH_DES_CBC_SHA, PJ_TLS_RSA_WITH_DES_CBC_SHA,
1561 PJ_FALSE, PJ_FALSE);
1562 if (ret == 0)
1563 return PJ_EBUG;
1564
1565 /* We can't set min/max proto for TLS protocol higher than 1.0. */
1566 #if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_DARWIN)
1567 PJ_LOG(3,("", "..echo test w/ incompatible proto: server TLSv1.2 vs client TLSv1.3"));
1568 ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1_2, PJ_SSL_SOCK_PROTO_TLS1_3,
1569 -1, -1,
1570 PJ_FALSE, PJ_FALSE);
1571 if (ret == 0)
1572 return PJ_EBUG;
1573 #endif
1574
1575 /* We can't seem to enable certain ciphers only. SSLSetEnabledCiphers() is
1576 * deprecated and we only have sec_protocol_options_append_tls_ciphersuite(),
1577 * but there's no API to remove certain or all ciphers.
1578 */
1579 #if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_APPLE)
1580 PJ_LOG(3,("", "..echo test w/ incompatible ciphers"));
1581 ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT,
1582 PJ_TLS_RSA_WITH_DES_CBC_SHA, PJ_TLS_RSA_WITH_AES_256_CBC_SHA,
1583 PJ_FALSE, PJ_FALSE);
1584 if (ret == 0)
1585 return PJ_EBUG;
1586 #endif
1587
1588 PJ_LOG(3,("", "..echo test w/ client cert required but not provided"));
1589 ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT,
1590 PJ_TLS_RSA_WITH_AES_256_CBC_SHA, PJ_TLS_RSA_WITH_AES_256_CBC_SHA,
1591 PJ_TRUE, PJ_FALSE);
1592 if (ret == 0)
1593 return PJ_EBUG;
1594
1595 PJ_LOG(3,("", "..echo test w/ client cert required and provided"));
1596 ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT,
1597 PJ_TLS_RSA_WITH_AES_256_CBC_SHA, PJ_TLS_RSA_WITH_AES_256_CBC_SHA,
1598 PJ_TRUE, PJ_TRUE);
1599 if (ret != 0)
1600 return ret;
1601
1602 #if WITH_BENCHMARK
1603 PJ_LOG(3,("", "..performance test"));
1604 ret = perf_test(PJ_IOQUEUE_MAX_HANDLES/2 - 1, 0);
1605 if (ret != 0)
1606 return ret;
1607 #endif
1608
1609 PJ_LOG(3,("", "..client non-SSL (handshake timeout 5 secs)"));
1610 ret = client_non_ssl(5000);
1611 if (ret != PJ_ETIMEDOUT)
1612 return ret;
1613
1614 #endif
1615
1616 PJ_LOG(3,("", "..server non-SSL (handshake timeout 5 secs)"));
1617 ret = server_non_ssl(5000);
1618 if (ret != PJ_ETIMEDOUT)
1619 return ret;
1620
1621 return 0;
1622 }
1623
1624 #else /* INCLUDE_SSLSOCK_TEST */
1625 /* To prevent warning about "translation unit is empty"
1626 * when this test is disabled.
1627 */
1628 int dummy_ssl_sock_test;
1629 #endif /* INCLUDE_SSLSOCK_TEST */
1630
1631