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(&param);
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(&param.timeout);
471 
472     status = pj_ssl_sock_create(pool, &param, &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(&param);
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, &param, &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, &param, &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(&param);
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(&param.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, &param, &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(&param);
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(&param.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, &param, &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(&param);
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(&param.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, &param, &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, &param, &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