Ignore:
Timestamp:
Feb 24, 2010 5:43:34 AM (14 years ago)
Author:
nanang
Message:

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).
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c

    r3039 r3106  
    2525#include <pj/ssl_sock.h> 
    2626#include <pj/assert.h> 
     27#include <pj/hash.h> 
    2728#include <pj/lock.h> 
    2829#include <pj/log.h> 
     
    8182    pjsip_transport          base; 
    8283    pj_bool_t                is_server; 
     84    pj_str_t                 remote_name; 
    8385 
    8486    pj_bool_t                is_registered; 
     
    8789    pj_ssl_sock_t           *ssock; 
    8890    pj_bool_t                has_pending_connect; 
     91    pj_bool_t                verify_server; 
    8992 
    9093    /* Keep-alive timer. */ 
     
    136139                                        const pj_sockaddr *rem_addr, 
    137140                                        int addr_len, 
     141                                        pjsip_tx_data *tdata, 
    138142                                        pjsip_transport **transport); 
    139143 
     
    145149                              const pj_sockaddr_in *local, 
    146150                              const pj_sockaddr_in *remote, 
     151                              const pj_str_t *remote_name, 
    147152                              struct tls_transport **p_tls); 
    148153 
     
    169174} 
    170175 
     176 
     177static void tls_init_shutdown(struct tls_transport *tls, pj_status_t status) 
     178{ 
     179    pjsip_tp_state_callback *state_cb; 
     180 
     181    if (tls->close_reason == PJ_SUCCESS) 
     182        tls->close_reason = status; 
     183 
     184    if (tls->base.is_shutdown) 
     185        return; 
     186 
     187    /* Notify application of transport disconnected state */ 
     188    state_cb = pjsip_tpmgr_get_status_cb(tls->base.tpmgr); 
     189    if (state_cb) { 
     190        pjsip_transport_state_info state_info; 
     191 
     192        pj_bzero(&state_info, sizeof(state_info)); 
     193        state_info.status = tls->close_reason; 
     194        (*state_cb)(&tls->base, PJSIP_TP_STATE_DISCONNECTED, &state_info); 
     195    } 
     196 
     197    /* We can not destroy the transport since high level objects may 
     198     * still keep reference to this transport. So we can only  
     199     * instruct transport manager to gracefully start the shutdown 
     200     * procedure for this transport. 
     201     */ 
     202    pjsip_transport_shutdown(&tls->base); 
     203} 
    171204 
    172205 
     
    244277    ssock_param.ioqueue = pjsip_endpt_get_ioqueue(endpt); 
    245278    ssock_param.require_client_cert = listener->tls_setting.require_client_cert; 
    246     ssock_param.server_name = listener->tls_setting.server_name; 
    247279    ssock_param.timeout = listener->tls_setting.timeout; 
    248280    ssock_param.user_data = listener; 
    249     ssock_param.verify_peer = listener->tls_setting.verify_client; 
     281    ssock_param.verify_peer = PJ_FALSE; /* avoid SSL socket closing the socket 
     282                                         * due to verification error */ 
    250283    if (ssock_param.send_buffer_size < PJSIP_MAX_PKT_LEN) 
    251284        ssock_param.send_buffer_size = PJSIP_MAX_PKT_LEN; 
     
    372405    listener->endpt = endpt; 
    373406    listener->tpmgr = pjsip_endpt_get_tpmgr(endpt); 
    374     listener->factory.create_transport = lis_create_transport; 
     407    listener->factory.create_transport2 = lis_create_transport; 
    375408    listener->factory.destroy = lis_destroy; 
    376409    listener->is_registered = PJ_TRUE; 
     
    481514                               const pj_sockaddr_in *local, 
    482515                               const pj_sockaddr_in *remote, 
     516                               const pj_str_t *remote_name, 
    483517                               struct tls_transport **p_tls) 
    484518{ 
     
    502536    tls = PJ_POOL_ZALLOC_T(pool, struct tls_transport); 
    503537    tls->is_server = is_server; 
     538    tls->verify_server = listener->tls_setting.verify_server; 
    504539    pj_list_init(&tls->delayed_list); 
    505540    tls->base.pool = pool; 
     
    518553    } 
    519554 
     555    if (remote_name) 
     556        pj_strdup(pool, &tls->remote_name, remote_name); 
     557 
    520558    tls->base.key.type = PJSIP_TRANSPORT_TLS; 
    521559    pj_memcpy(&tls->base.key.rem_addr, remote, sizeof(pj_sockaddr_in)); 
     560    tls->base.key.hname = pj_hash_calc_tolower(0, (char*)tls->remote_name.ptr, 
     561                                               &tls->remote_name); 
    522562    tls->base.type_name = "tls"; 
    523563    tls->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_TLS); 
     
    770810                                        const pj_sockaddr *rem_addr, 
    771811                                        int addr_len, 
     812                                        pjsip_tx_data *tdata, 
    772813                                        pjsip_transport **p_transport) 
    773814{ 
     
    778819    pj_ssl_sock_param ssock_param; 
    779820    pj_sockaddr_in local_addr; 
     821    pj_str_t remote_name; 
    780822    pj_status_t status; 
    781823 
     
    794836                                   POOL_TP_INIT, POOL_TP_INC); 
    795837    PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); 
     838 
     839    /* Get remote host name from tdata */ 
     840    if (tdata) 
     841        remote_name = tdata->dest_info.name; 
     842    else 
     843        pj_bzero(&remote_name, sizeof(remote_name)); 
    796844 
    797845    /* Build SSL socket param */ 
     
    802850    ssock_param.async_cnt = 1; 
    803851    ssock_param.ioqueue = pjsip_endpt_get_ioqueue(listener->endpt); 
    804     PJ_TODO(set_proper_servername_based_on_target); 
    805852    PJ_TODO(synchronize_tls_cipher_type_with_ssl_sock_cipher_type); 
    806     ssock_param.server_name = listener->tls_setting.server_name; 
     853    ssock_param.server_name = remote_name; 
    807854    ssock_param.timeout = listener->tls_setting.timeout; 
    808855    ssock_param.user_data = NULL; /* pending, must be set later */ 
    809     ssock_param.verify_peer = listener->tls_setting.verify_server; 
     856    ssock_param.verify_peer = PJ_FALSE; /* avoid SSL socket closing the socket 
     857                                         * due to verification error */ 
    810858    if (ssock_param.send_buffer_size < PJSIP_MAX_PKT_LEN) 
    811859        ssock_param.send_buffer_size = PJSIP_MAX_PKT_LEN; 
     
    851899    /* Create the transport descriptor */ 
    852900    status = tls_create(listener, pool, ssock, PJ_FALSE, &local_addr,  
    853                         (pj_sockaddr_in*)rem_addr, &tls); 
     901                        (pj_sockaddr_in*)rem_addr, &remote_name, &tls); 
    854902    if (status != PJ_SUCCESS) 
    855903        return status; 
     
    929977    struct tls_listener *listener; 
    930978    struct tls_transport *tls; 
     979    pj_ssl_sock_info ssl_info; 
    931980    char addr[PJ_INET6_ADDRSTRLEN+10]; 
    932981    pj_status_t status; 
     982 
     983    pjsip_tp_state_callback *state_cb; 
     984    pj_bool_t tls_verif_ignored; 
    933985 
    934986    PJ_UNUSED_ARG(src_addr_len); 
     
    947999              new_ssock)); 
    9481000 
     1001    /* Retrieve SSL socket info, close the socket if this is failed 
     1002     * as the SSL socket info availability is rather critical here. 
     1003     */ 
     1004    status = pj_ssl_sock_get_info(new_ssock, &ssl_info); 
     1005    if (status != PJ_SUCCESS) { 
     1006        pj_ssl_sock_close(new_ssock); 
     1007        return PJ_TRUE; 
     1008    } 
     1009 
    9491010    /*  
    9501011     * Incoming connection! 
     
    9531014    status = tls_create( listener, NULL, new_ssock, PJ_TRUE, 
    9541015                         (const pj_sockaddr_in*)&listener->factory.local_addr, 
    955                          (const pj_sockaddr_in*)src_addr, &tls); 
     1016                         (const pj_sockaddr_in*)src_addr, NULL, &tls); 
    9561017     
    957     if (status == PJ_SUCCESS) { 
    958         /* Set the "pending" SSL socket user data */ 
    959         pj_ssl_sock_set_user_data(new_ssock, tls); 
    960  
    961         status = tls_start_read(tls); 
    962         if (status != PJ_SUCCESS) { 
    963             PJ_LOG(3,(tls->base.obj_name, "New transport cancelled")); 
    964             tls_destroy(&tls->base, status); 
     1018    if (status != PJ_SUCCESS) 
     1019        return PJ_TRUE; 
     1020 
     1021    /* Set the "pending" SSL socket user data */ 
     1022    pj_ssl_sock_set_user_data(new_ssock, tls); 
     1023 
     1024    tls_verif_ignored = !listener->tls_setting.verify_client; 
     1025 
     1026    /* Notify transport state to application */ 
     1027    state_cb = pjsip_tpmgr_get_status_cb(tls->base.tpmgr); 
     1028    if (state_cb) { 
     1029        pjsip_transport_state_info state_info; 
     1030        pjsip_tls_state_info tls_info; 
     1031        pj_uint32_t tp_state = 0; 
     1032 
     1033        /* Init transport state notification callback */ 
     1034        pj_bzero(&tls_info, sizeof(tls_info)); 
     1035        pj_bzero(&state_info, sizeof(state_info)); 
     1036 
     1037        /* Set transport state based on verification status */ 
     1038        if (ssl_info.verify_status) { 
     1039            state_info.status = PJSIP_TLS_EACCEPT; 
     1040            tp_state |= PJSIP_TP_STATE_TLS_VERIF_ERROR; 
     1041            if (listener->tls_setting.verify_client) 
     1042                tp_state |= PJSIP_TP_STATE_REJECTED; 
     1043            else 
     1044                tp_state |= PJSIP_TP_STATE_ACCEPTED; 
    9651045        } else { 
    966             /* Start keep-alive timer */ 
    967             if (PJSIP_TCP_KEEP_ALIVE_INTERVAL) { 
    968                 pj_time_val delay = {PJSIP_TCP_KEEP_ALIVE_INTERVAL, 0}; 
    969                 pjsip_endpt_schedule_timer(listener->endpt,  
    970                                            &tls->ka_timer,  
    971                                            &delay); 
    972                 tls->ka_timer.id = PJ_TRUE; 
    973                 pj_gettimeofday(&tls->last_activity); 
    974             } 
     1046            tp_state |= PJSIP_TP_STATE_ACCEPTED; 
     1047        } 
     1048 
     1049        tls_info.ssl_sock_info = &ssl_info; 
     1050        state_info.ext_info = &tls_info; 
     1051 
     1052        tls_verif_ignored = (*state_cb)(&tls->base, tp_state, &state_info); 
     1053    } 
     1054 
     1055    /* Transport should be destroyed when there is TLS verification error 
     1056     * and application doesn't want to ignore it. 
     1057     */ 
     1058    if (ssl_info.verify_status &&  
     1059        (listener->tls_setting.verify_client || !tls_verif_ignored)) 
     1060    { 
     1061        tls_destroy(&tls->base, PJSIP_TLS_EACCEPT); 
     1062        return PJ_TRUE; 
     1063    } 
     1064 
     1065    status = tls_start_read(tls); 
     1066    if (status != PJ_SUCCESS) { 
     1067        PJ_LOG(3,(tls->base.obj_name, "New transport cancelled")); 
     1068        tls_init_shutdown(tls, status); 
     1069        tls_destroy(&tls->base, status); 
     1070    } else { 
     1071        /* Start keep-alive timer */ 
     1072        if (PJSIP_TCP_KEEP_ALIVE_INTERVAL) { 
     1073            pj_time_val delay = {PJSIP_TCP_KEEP_ALIVE_INTERVAL, 0}; 
     1074            pjsip_endpt_schedule_timer(listener->endpt,  
     1075                                       &tls->ka_timer,  
     1076                                       &delay); 
     1077            tls->ka_timer.id = PJ_TRUE; 
     1078            pj_gettimeofday(&tls->last_activity); 
    9751079        } 
    9761080    } 
     
    10201124        status = (bytes_sent == 0) ? PJ_RETURN_OS_ERROR(OSERR_ENOTCONN) : 
    10211125                                     -bytes_sent; 
    1022         if (tls->close_reason==PJ_SUCCESS) tls->close_reason = status; 
    1023         pjsip_transport_shutdown(&tls->base); 
     1126 
     1127        tls_init_shutdown(tls, status); 
    10241128 
    10251129        return PJ_FALSE; 
     
    11161220                if (status == PJ_SUCCESS)  
    11171221                    status = PJ_RETURN_OS_ERROR(OSERR_ENOTCONN); 
    1118                 if (tls->close_reason==PJ_SUCCESS) tls->close_reason = status; 
    1119                 pjsip_transport_shutdown(&tls->base); 
     1222 
     1223                tls_init_shutdown(tls, status); 
    11201224            } 
    11211225        } 
     
    12051309        /* Transport is closed */ 
    12061310        PJ_LOG(4,(tls->base.obj_name, "TLS connection closed")); 
    1207          
    1208         /* We can not destroy the transport since high level objects may 
    1209          * still keep reference to this transport. So we can only  
    1210          * instruct transport manager to gracefully start the shutdown 
    1211          * procedure for this transport. 
    1212          */ 
    1213         if (tls->close_reason==PJ_SUCCESS)  
    1214             tls->close_reason = status; 
    1215         pjsip_transport_shutdown(&tls->base); 
     1311 
     1312        tls_init_shutdown(tls, status); 
    12161313 
    12171314        return PJ_FALSE; 
     
    12331330{ 
    12341331    struct tls_transport *tls; 
    1235     pj_ssl_sock_info info; 
    1236      
     1332    pj_ssl_sock_info ssl_info; 
     1333    pj_sockaddr_in addr, *tp_addr; 
     1334 
     1335    pjsip_tp_state_callback *state_cb; 
     1336    pj_bool_t tls_verif_ignored; 
     1337 
    12371338    tls = (struct tls_transport*) pj_ssl_sock_get_user_data(ssock); 
    12381339 
     
    12551356        } 
    12561357 
    1257         /* We can not destroy the transport since high level objects may 
    1258          * still keep reference to this transport. So we can only  
    1259          * instruct transport manager to gracefully start the shutdown 
    1260          * procedure for this transport. 
    1261          */ 
    1262         if (tls->close_reason==PJ_SUCCESS) tls->close_reason = status; 
    1263         pjsip_transport_shutdown(&tls->base); 
    1264         return PJ_FALSE; 
    1265     } 
     1358        goto on_error; 
     1359    } 
     1360 
     1361    /* Retrieve SSL socket info, shutdown the transport if this is failed 
     1362     * as the SSL socket info availability is rather critical here. 
     1363     */ 
     1364    status = pj_ssl_sock_get_info(tls->ssock, &ssl_info); 
     1365    if (status != PJ_SUCCESS) 
     1366        goto on_error; 
    12661367 
    12671368    /* Update (again) local address, just in case local address currently 
     
    12691370     * on some systems, like old Win32 probably?). 
    12701371     */ 
    1271  
    1272     /* Retrieve the bound address */ 
    1273     status = pj_ssl_sock_get_info(tls->ssock, &info); 
    1274     if (status == PJ_SUCCESS) { 
    1275         pj_sockaddr_in addr; 
    1276         pj_sockaddr_in *tp_addr = (pj_sockaddr_in*)&tls->base.local_addr; 
    1277          
    1278         pj_sockaddr_cp((pj_sockaddr_t*)&addr, (pj_sockaddr_t*)&info.local_addr); 
    1279         if (tp_addr->sin_addr.s_addr != addr.sin_addr.s_addr) { 
    1280             tp_addr->sin_addr.s_addr = addr.sin_addr.s_addr; 
    1281             tp_addr->sin_port = addr.sin_port; 
    1282             sockaddr_to_host_port(tls->base.pool, &tls->base.local_name, 
    1283                                   tp_addr); 
     1372    tp_addr = (pj_sockaddr_in*)&tls->base.local_addr; 
     1373    pj_sockaddr_cp((pj_sockaddr_t*)&addr,  
     1374                   (pj_sockaddr_t*)&ssl_info.local_addr); 
     1375    if (tp_addr->sin_addr.s_addr != addr.sin_addr.s_addr) { 
     1376        tp_addr->sin_addr.s_addr = addr.sin_addr.s_addr; 
     1377        tp_addr->sin_port = addr.sin_port; 
     1378        sockaddr_to_host_port(tls->base.pool, &tls->base.local_name, 
     1379                              tp_addr); 
     1380    } 
     1381 
     1382    /* Server identity verification based on server certificate. */ 
     1383    if (ssl_info.remote_cert_info->version) { 
     1384        pj_str_t *remote_name; 
     1385        pj_ssl_cert_info *serv_cert = ssl_info.remote_cert_info; 
     1386        pj_bool_t matched = PJ_FALSE; 
     1387        unsigned i; 
     1388 
     1389        /* Remote name may be hostname or IP address */ 
     1390        if (tls->remote_name.slen) 
     1391            remote_name = &tls->remote_name; 
     1392        else 
     1393            remote_name = &tls->base.remote_name.host; 
     1394 
     1395        /* Start matching remote name with SubjectAltName fields of  
     1396         * server certificate. 
     1397         */ 
     1398        for (i = 0; i < serv_cert->subj_alt_name.cnt && !matched; ++i) { 
     1399            pj_str_t *cert_name = &serv_cert->subj_alt_name.entry[i].name; 
     1400 
     1401            switch (serv_cert->subj_alt_name.entry[i].type) { 
     1402            case PJ_SSL_CERT_NAME_DNS: 
     1403            case PJ_SSL_CERT_NAME_IP: 
     1404                matched = !pj_stricmp(remote_name, cert_name); 
     1405                break; 
     1406            case PJ_SSL_CERT_NAME_URI: 
     1407                if (pj_strnicmp2(cert_name, "sip:", 4) == 0 || 
     1408                    pj_strnicmp2(cert_name, "sips:", 5) == 0) 
     1409                { 
     1410                    pj_str_t host_part; 
     1411                    char *p; 
     1412 
     1413                    p = pj_strchr(cert_name, ':') + 1; 
     1414                    pj_strset(&host_part, p, cert_name->slen -  
     1415                                             (p - cert_name->ptr)); 
     1416                    matched = !pj_stricmp(remote_name, &host_part); 
     1417                } 
     1418                break; 
     1419            default: 
     1420                break; 
     1421            } 
    12841422        } 
    1285     } 
     1423         
     1424        /* When still not matched or no SubjectAltName fields in server 
     1425         * certificate, try with Common Name of Subject field. 
     1426         */ 
     1427        if (!matched) { 
     1428            matched = !pj_stricmp(remote_name, &serv_cert->subject.cn); 
     1429        } 
     1430 
     1431        if (!matched) 
     1432            ssl_info.verify_status |= PJ_SSL_CERT_EIDENTITY_NOT_MATCH; 
     1433    } 
     1434 
     1435    tls_verif_ignored = !tls->verify_server; 
     1436 
     1437    /* Notify transport state to application */ 
     1438    state_cb = pjsip_tpmgr_get_status_cb(tls->base.tpmgr); 
     1439    if (state_cb) { 
     1440        pjsip_transport_state_info state_info; 
     1441        pjsip_tls_state_info tls_info; 
     1442        pj_uint32_t tp_state = 0; 
     1443 
     1444        /* Init transport state notification callback */ 
     1445        pj_bzero(&state_info, sizeof(state_info)); 
     1446        pj_bzero(&tls_info, sizeof(tls_info)); 
     1447 
     1448        /* Set transport state info */ 
     1449        state_info.ext_info = &tls_info; 
     1450        tls_info.ssl_sock_info = &ssl_info; 
     1451 
     1452        /* Set transport state based on verification status */ 
     1453        if (ssl_info.verify_status) { 
     1454            state_info.status = PJSIP_TLS_ECONNECT; 
     1455            tp_state |= PJSIP_TP_STATE_TLS_VERIF_ERROR; 
     1456            if (tls->verify_server) 
     1457                tp_state |= PJSIP_TP_STATE_DISCONNECTED; 
     1458            else 
     1459                tp_state |= PJSIP_TP_STATE_CONNECTED; 
     1460        } else { 
     1461            tp_state |= PJSIP_TP_STATE_CONNECTED; 
     1462        } 
     1463 
     1464        tls_verif_ignored = (*state_cb)(&tls->base, tp_state, &state_info); 
     1465    } 
     1466 
     1467    /* Transport should be shutdown when there is TLS verification error 
     1468     * and application doesn't want to ignore it. 
     1469     */ 
     1470    if (ssl_info.verify_status &&  
     1471        (tls->verify_server || !tls_verif_ignored)) 
     1472    { 
     1473        if (tls->close_reason == PJ_SUCCESS)  
     1474            tls->close_reason = PJSIP_TLS_ECONNECT; 
     1475        pjsip_transport_shutdown(&tls->base); 
     1476        return PJ_FALSE; 
     1477    } 
     1478 
     1479    /* Mark that pending connect() operation has completed. */ 
     1480    tls->has_pending_connect = PJ_FALSE; 
    12861481 
    12871482    PJ_LOG(4,(tls->base.obj_name,  
     
    12941489              tls->base.remote_name.port)); 
    12951490 
    1296     /* Mark that pending connect() operation has completed. */ 
    1297     tls->has_pending_connect = PJ_FALSE; 
    1298  
    12991491    /* Start pending read */ 
    13001492    status = tls_start_read(tls); 
    1301     if (status != PJ_SUCCESS) { 
    1302         /* We can not destroy the transport since high level objects may 
    1303          * still keep reference to this transport. So we can only  
    1304          * instruct transport manager to gracefully start the shutdown 
    1305          * procedure for this transport. 
    1306          */ 
    1307         if (tls->close_reason==PJ_SUCCESS) tls->close_reason = status; 
    1308         pjsip_transport_shutdown(&tls->base); 
    1309         return PJ_FALSE; 
    1310     } 
     1493    if (status != PJ_SUCCESS) 
     1494        goto on_error; 
    13111495 
    13121496    /* Flush all pending send operations */ 
     
    13231507 
    13241508    return PJ_TRUE; 
     1509 
     1510on_error: 
     1511    tls_init_shutdown(tls, status); 
     1512 
     1513    return PJ_FALSE; 
    13251514} 
    13261515 
     
    13661555        tls_perror(tls->base.obj_name,  
    13671556                   "Error sending keep-alive packet", status); 
    1368         pjsip_transport_shutdown(&tls->base); 
     1557 
     1558        tls_init_shutdown(tls, status); 
    13691559        return; 
    13701560    } 
Note: See TracChangeset for help on using the changeset viewer.