From bb2fc905eb58b9ebdf66e89330599be996821db7 Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Wed, 24 Feb 2010 05:43:34 +0000 Subject: Ticket #1032: - Initial version of server domain name verification: - Updated SSL certificate info, especially identities info - Updated verification mechanism as in the specifications in ticket desc. - Added server domain name info in pjsip_tx_data. - Added alternative API for acquiring transport and creating transport of transport factory to include pjsip_tx_data param. - Server identity match criteria: - full host name match - wild card not accepted - if identity is URI, it must be SIP/SIPS URI - Initial version of transport state notifications: - Added new API to set transport state callback in PJSIP and PJSUA. - Defined states: connected/disconnected, accepted/rejected, verification errors. - Minors: - Updated SSL socket test: dump verification result, test of requiring client cert, and few minors. - Updated test cert to include subjectAltName extensions. - Added SSL certificate dump function. - Updated max number of socket async operations in Symbian sample apps (RSocketServ::Connect()) to 32 (was default 8). git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3106 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib/src/pjlib-test/ssl_sock.c | 213 ++++++++++++++++++++++------------------ 1 file changed, 118 insertions(+), 95 deletions(-) (limited to 'pjlib/src/pjlib-test') diff --git a/pjlib/src/pjlib-test/ssl_sock.c b/pjlib/src/pjlib-test/ssl_sock.c index 8302e8f1..6e0d4515 100644 --- a/pjlib/src/pjlib-test/ssl_sock.c +++ b/pjlib/src/pjlib-test/ssl_sock.c @@ -22,7 +22,7 @@ #define CERT_DIR "../build/" -#define CERT_CA_FILE NULL +#define CERT_CA_FILE CERT_DIR "cacert.pem" #define CERT_FILE CERT_DIR "cacert.pem" #define CERT_PRIVKEY_FILE CERT_DIR "privkey.pem" #define CERT_PRIVKEY_PASS "" @@ -83,26 +83,40 @@ struct test_state struct send_key send_key; /* send op key */ }; -static void dump_cert_info(const char *prefix, const pj_ssl_cert_info *ci) +static void dump_ssl_info(const pj_ssl_sock_info *si) { - const char *wdays[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; - pj_parsed_time pt1; - pj_parsed_time pt2; - - pj_time_decode(&ci->validity_start, &pt1); - pj_time_decode(&ci->validity_end, &pt2); - - PJ_LOG(3, ("", "%sSubject : %.*s", prefix, ci->subject.slen, ci->subject.ptr)); - PJ_LOG(3, ("", "%sIssuer : %.*s", prefix, ci->issuer.slen, ci->issuer.ptr)); - PJ_LOG(3, ("", "%sVersion : v%d", prefix, ci->version)); - PJ_LOG(3, ("", "%sValid from : %s %4d-%02d-%02d %02d:%02d:%02d.%03d %s", - prefix, wdays[pt1.wday], pt1.year, pt1.mon+1, pt1.day, - pt1.hour, pt1.min, pt1.sec, pt1.msec, - (ci->validity_use_gmt? "GMT":""))); - PJ_LOG(3, ("", "%sValid to : %s %4d-%02d-%02d %02d:%02d:%02d.%03d %s", - prefix, wdays[pt2.wday], pt2.year, pt2.mon+1, pt2.day, - pt2.hour, pt2.min, pt2.sec, pt2.msec, - (ci->validity_use_gmt? "GMT":""))); + const char *tmp_st; + + /* Print cipher name */ + tmp_st = pj_ssl_cipher_name(si->cipher); + if (tmp_st == NULL) + tmp_st = "[Unknown]"; + PJ_LOG(3, ("", ".....Cipher: %s", tmp_st)); + + /* Print remote certificate info and verification result */ + if (si->remote_cert_info && si->remote_cert_info->subject.info.slen) + { + char buf[2048]; + const char *verif_msgs[32]; + unsigned verif_msg_cnt; + + /* Dump remote TLS certificate info */ + PJ_LOG(3, ("", ".....Remote certificate info:")); + pj_ssl_cert_info_dump(si->remote_cert_info, " ", buf, sizeof(buf)); + PJ_LOG(3,("", "\n%s", buf)); + + /* Dump remote TLS certificate verification result */ + verif_msg_cnt = PJ_ARRAY_SIZE(verif_msgs); + pj_ssl_cert_verify_error_st(si->verify_status, + verif_msgs, &verif_msg_cnt); + PJ_LOG(3,("", ".....Remote certificate verification result: %s", + (verif_msg_cnt == 1? verif_msgs[0]:""))); + if (verif_msg_cnt > 1) { + unsigned i; + for (i = 0; i < verif_msg_cnt; ++i) + PJ_LOG(3,("", "..... - %s", verif_msgs[i])); + } + } } @@ -130,25 +144,8 @@ static pj_bool_t ssl_on_connect_complete(pj_ssl_sock_t *ssock, pj_sockaddr_print((pj_sockaddr_t*)&info.remote_addr, buf2, sizeof(buf2), 1); PJ_LOG(3, ("", "...Connected %s -> %s!", buf1, buf2)); - if (st->is_verbose) { - const char *tmp_st; - - /* Print cipher name */ - tmp_st = pj_ssl_cipher_name(info.cipher); - if (tmp_st == NULL) - tmp_st = "[Unknown]"; - PJ_LOG(3, ("", ".....Cipher: %s", tmp_st)); - - /* Print certificates info */ - if (info.local_cert_info.subject.slen) { - PJ_LOG(3, ("", ".....Local certificate info:")); - dump_cert_info(".......", &info.local_cert_info); - } - if (info.remote_cert_info.subject.slen) { - PJ_LOG(3, ("", ".....Remote certificate info:")); - dump_cert_info(".......", &info.remote_cert_info); - } - } + if (st->is_verbose) + dump_ssl_info(&info); /* Start reading data */ read_buf[0] = st->read_buf; @@ -198,6 +195,8 @@ static pj_bool_t ssl_on_accept_complete(pj_ssl_sock_t *ssock, pj_ssl_sock_get_user_data(ssock); struct test_state *st; void *read_buf[1]; + pj_ssl_sock_info info; + char buf[64]; pj_status_t status; PJ_UNUSED_ARG(src_addr_len); @@ -207,36 +206,17 @@ static pj_bool_t ssl_on_accept_complete(pj_ssl_sock_t *ssock, *st = *parent_st; pj_ssl_sock_set_user_data(newsock, st); - if (st->is_verbose) { - pj_ssl_sock_info info; - char buf[64]; - const char *tmp_st; - - status = pj_ssl_sock_get_info(newsock, &info); - if (status != PJ_SUCCESS) { - app_perror("...ERROR pj_ssl_sock_get_info()", status); - goto on_return; - } - - pj_sockaddr_print(src_addr, buf, sizeof(buf), 1); - PJ_LOG(3, ("", "...Accepted connection from %s", buf)); + status = pj_ssl_sock_get_info(newsock, &info); + if (status != PJ_SUCCESS) { + app_perror("...ERROR pj_ssl_sock_get_info()", status); + goto on_return; + } - /* Print cipher name */ - tmp_st = pj_ssl_cipher_name(info.cipher); - if (tmp_st == NULL) - tmp_st = "[Unknown]"; - PJ_LOG(3, ("", ".....Cipher: %s", tmp_st)); + pj_sockaddr_print(src_addr, buf, sizeof(buf), 1); + PJ_LOG(3, ("", "...Accepted connection from %s", buf)); - /* Print certificates info */ - if (info.local_cert_info.subject.slen) { - PJ_LOG(3, ("", ".....Local certificate info:")); - dump_cert_info(".......", &info.local_cert_info); - } - if (info.remote_cert_info.subject.slen) { - PJ_LOG(3, ("", ".....Remote certificate info:")); - dump_cert_info(".......", &info.remote_cert_info); - } - } + if (st->is_verbose) + dump_ssl_info(&info); /* Start reading data */ read_buf[0] = st->read_buf; @@ -460,6 +440,7 @@ static int https_client_test(unsigned ms_timeout) param.timer_heap = timer; param.timeout.sec = 0; param.timeout.msec = ms_timeout; + param.proto = PJ_SSL_SOCK_PROTO_SSL23; pj_time_val_normalize(¶m.timeout); status = pj_ssl_sock_create(pool, ¶m, &ssock); @@ -512,7 +493,8 @@ on_return: static int 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_ssl_cipher srv_cipher, pj_ssl_cipher cli_cipher, + pj_bool_t req_client_cert, pj_bool_t client_provide_cert) { pj_pool_t *pool = NULL; pj_ioqueue_t *ioqueue = NULL; @@ -533,21 +515,6 @@ static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto, goto on_return; } - /* Set cert */ - { - pj_str_t tmp1, tmp2, tmp3, tmp4; - - status = pj_ssl_cert_load_from_files(pool, - pj_strset2(&tmp1, (char*)CERT_CA_FILE), - pj_strset2(&tmp2, (char*)CERT_FILE), - pj_strset2(&tmp3, (char*)CERT_PRIVKEY_FILE), - pj_strset2(&tmp4, (char*)CERT_PRIVKEY_PASS), - &cert); - if (status != PJ_SUCCESS) { - goto on_return; - } - } - pj_ssl_sock_param_default(¶m); param.cb.on_accept_complete = &ssl_on_accept_complete; param.cb.on_connect_complete = &ssl_on_connect_complete; @@ -562,10 +529,11 @@ static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto, pj_sockaddr_init(PJ_AF_INET, &addr, pj_strset2(&tmp_st, "127.0.0.1"), 0); } - /* SERVER */ + /* === SERVER === */ param.proto = srv_proto; param.user_data = &state_serv; param.ciphers_num = (srv_cipher == -1)? 0 : 1; + param.require_client_cert = req_client_cert; ciphers[0] = srv_cipher; state_serv.pool = pool; @@ -578,9 +546,24 @@ static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto, goto on_return; } - status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert); - if (status != PJ_SUCCESS) { - goto on_return; + /* Set server cert */ + { + pj_str_t tmp1, tmp2, tmp3, tmp4; + + status = pj_ssl_cert_load_from_files(pool, + pj_strset2(&tmp1, (char*)CERT_CA_FILE), + pj_strset2(&tmp2, (char*)CERT_FILE), + pj_strset2(&tmp3, (char*)CERT_PRIVKEY_FILE), + pj_strset2(&tmp4, (char*)CERT_PRIVKEY_PASS), + &cert); + if (status != PJ_SUCCESS) { + goto on_return; + } + + status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert); + if (status != PJ_SUCCESS) { + goto on_return; + } } status = pj_ssl_sock_start_accept(ssock_serv, pool, &addr, pj_sockaddr_get_len(&addr)); @@ -596,7 +579,7 @@ static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto, pj_sockaddr_cp(&listen_addr, &info.local_addr); } - /* CLIENT */ + /* === CLIENT === */ param.proto = cli_proto; param.user_data = &state_cli; param.ciphers_num = (cli_cipher == -1)? 0 : 1; @@ -625,6 +608,28 @@ static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto, goto on_return; } + /* Set cert for client */ + { + + if (!client_provide_cert) { + pj_str_t tmp1, tmp2; + + pj_strset2(&tmp1, (char*)CERT_CA_FILE); + pj_strset2(&tmp2, NULL); + status = pj_ssl_cert_load_from_files(pool, + &tmp1, &tmp2, &tmp2, &tmp2, + &cert); + if (status != PJ_SUCCESS) { + goto on_return; + } + } + + status = pj_ssl_sock_set_certificate(ssock_cli, pool, cert); + if (status != PJ_SUCCESS) { + goto on_return; + } + } + status = pj_ssl_sock_start_connect(ssock_cli, pool, &addr, &listen_addr, pj_sockaddr_get_len(&addr)); if (status == PJ_SUCCESS) { ssl_on_connect_complete(ssock_cli, PJ_SUCCESS); @@ -1013,6 +1018,9 @@ static int perf_test(unsigned clients, unsigned ms_handshake_timeout) ssock_cli = pj_pool_calloc(pool, clients, sizeof(pj_ssl_sock_t*)); state_cli = pj_pool_calloc(pool, clients, sizeof(struct test_state)); + /* Get start timestamp */ + pj_gettimeofday(&start); + /* Setup clients */ for (i = 0; i < clients; ++i) { param.user_data = &state_cli[i]; @@ -1064,9 +1072,6 @@ static int perf_test(unsigned clients, unsigned ms_handshake_timeout) } } - /* Get start timestamp */ - pj_gettimeofday(&start); - /* Wait until everything has been sent/received or error */ while (clients_num) { @@ -1150,28 +1155,46 @@ int ssl_sock_test(void) PJ_LOG(3,("", "..echo test w/ TLSv1 and TLS_RSA_WITH_DES_CBC_SHA cipher")); ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1, PJ_SSL_SOCK_PROTO_TLS1, - TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA); + TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA, + PJ_FALSE, PJ_FALSE); if (ret != 0) return ret; PJ_LOG(3,("", "..echo test w/ SSLv23 and TLS_RSA_WITH_AES_256_CBC_SHA cipher")); ret = echo_test(PJ_SSL_SOCK_PROTO_SSL23, PJ_SSL_SOCK_PROTO_SSL23, - TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA); + TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, + PJ_FALSE, PJ_FALSE); if (ret != 0) return ret; PJ_LOG(3,("", "..echo test w/ incompatible proto")); ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1, PJ_SSL_SOCK_PROTO_SSL3, - TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA); + TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA, + PJ_FALSE, PJ_FALSE); if (ret == 0) return PJ_EBUG; PJ_LOG(3,("", "..echo test w/ incompatible ciphers")); ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT, - TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA); + TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, + PJ_FALSE, PJ_FALSE); + if (ret == 0) + return PJ_EBUG; + + PJ_LOG(3,("", "..echo test w/ client cert required but not provided")); + ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT, + TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, + PJ_TRUE, PJ_FALSE); if (ret == 0) return PJ_EBUG; + PJ_LOG(3,("", "..echo test w/ client cert required and provided")); + ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT, + TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, + PJ_TRUE, PJ_TRUE); + if (ret != 0) + return ret; + PJ_LOG(3,("", "..client non-SSL (handshake timeout 5 secs)")); ret = client_non_ssl(5000); if (ret != 0) -- cgit v1.2.3