Changeset 3106 for pjproject


Ignore:
Timestamp:
Feb 24, 2010 5:43:34 AM (15 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).
Location:
pjproject/trunk
Files:
1 added
27 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/build.symbian/pjlib.mmp

    r3046 r3106  
    5050SOURCE          rand.c 
    5151SOURCE          rbtree.c 
     52SOURCE          ssl_sock_common.c 
     53SOURCE          ssl_sock_dump.c 
    5254SOURCE          sock_common.c 
    5355SOURCE          sock_qos_common.c 
     
    7375SOURCE          os_timestamp_posix.c 
    7476SOURCE          pool_policy_new.cpp 
    75 SOURCE          ssl_sock_common.c 
    7677SOURCE          ssl_sock_symbian.cpp 
    7778SOURCE          sock_symbian.cpp 
  • pjproject/trunk/build.symbian/pjlib_test.mmp

    r3046 r3106  
    7070SYSTEMINCLUDE   \epoc32\include\libc 
    7171 
    72 LIBRARY         esock.lib insock.lib charconv.lib euser.lib estlib.lib securesocket.lib  
     72LIBRARY         esock.lib insock.lib charconv.lib euser.lib estlib.lib  
     73LIBRARY         securesocket.lib x509.lib crypto.lib x500.lib  
     74  
    7375#ifdef WINSCW 
    7476STATICLIBRARY   eexe.lib ecrt0.lib 
  • pjproject/trunk/build.symbian/symbian_ua.mmp

    r3046 r3106  
    7272#endif 
    7373 
    74 LIBRARY                 esock.lib insock.lib charconv.lib euser.lib estlib.lib commdb.lib apengine.lib securesocket.lib  
     74LIBRARY                 esock.lib insock.lib charconv.lib euser.lib estlib.lib commdb.lib apengine.lib  
     75LIBRARY                 securesocket.lib x509.lib crypto.lib x500.lib  
    7576 
    7677// The default 8KB seems to be insufficient with all bells and 
  • pjproject/trunk/pjlib/build/Makefile

    r2970 r3106  
    2727        pool.o pool_buf.o pool_caching.o pool_dbg.o rand.o \ 
    2828        rbtree.o sock_common.o sock_qos_common.o sock_qos_bsd.o \ 
    29         ssl_sock_common.o ssl_sock_ossl.o string.o timer.o types.o 
     29        ssl_sock_common.o ssl_sock_ossl.o ssl_sock_dump.o \ 
     30        string.o timer.o types.o 
    3031export PJLIB_CFLAGS += $(_CFLAGS) 
    3132 
  • pjproject/trunk/pjlib/build/cacert.pem

    r2971 r3106  
    11-----BEGIN CERTIFICATE----- 
    2 MIIDXzCCAkegAwIBAgIJAPqAwYU5OQLXMA0GCSqGSIb3DQEBBQUAMEYxCzAJBgNV 
    3 BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMQ4wDAYDVQQKDAVwanNpcDESMBAG 
    4 A1UEAwwJcGpzaXAubGFiMB4XDTA5MTAyMjE3MTczN1oXDTE5MTAyMDE3MTczN1ow 
    5 RjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxDjAMBgNVBAoMBXBq 
    6 c2lwMRIwEAYDVQQDDAlwanNpcC5sYWIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 
    7 ggEKAoIBAQDWWvnL+oSC0Q6OwGLt2YuhXTEzIVv3B+SGQ7tajB6H3WXVeq+1NmU9 
    8 Yzca33g4FRrU7n4smYmKLzm1aniBhNmJjA+t+gbyizKnLMaCLoG52tUoULcANGKU 
    9 aGwlmvZFugDn2eVg6UfUfRzEGbV3q3a/PzSsOEPwsMeF3YMQJPhkoyPQLtWgUXgP 
    10 89Nyq3XjGGtw/qmUgQjE8a6/P0yXc+myI0hmApmZ9nB3YmlB5W3q6WoU2gGhLXf4 
    11 12rH/LgdnPhM4ijS554Kv9EcUDdQTTrm6bYg66tj+qTet7DolUOlTZ3vKpuCK3tt 
    12 eK9CbNPVzsMsB3yCALSLzQ347pIwfLaJAgMBAAGjUDBOMB0GA1UdDgQWBBRE/VNp 
    13 kNQmLEXKQ+NM4bOVj95zYTAfBgNVHSMEGDAWgBRE/VNpkNQmLEXKQ+NM4bOVj95z 
    14 YTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCj/gzJKTOZDEBD+zr7 
    15 lvbVctiYE9o8ObxZQsnl/6zI2V9H/2yc1sqQyjBupzw6c37ehvk30yIyUfD3ts87 
    16 2xaJ5VgtgUI3FI5DQ+ASyQXmDawUEmXIGqHb2gDrXBQLd6uMpvNDNW+7TouuniyA 
    17 F12JUCNITeXaVJ0c8d4A9J9DlszBfYUzI45yIQu1gbpnpH74Sp/hG77EMxrRau+x 
    18 EFFmV7gAmkCgOBnXm8jTKqNre/GfLfO7w2xoLsubSLnK46U3iLGBIJJRVGu3UQuN 
    19 k1o7CiIKf0SSWj1bQI99ipTj8obBKRqj1nSbgKF/U6FIfd8DGcVvbJCSAG2czzyA 
    20 5tdA 
     2MIICNDCCAZ2gAwIBAgIJAIa9mZggMk2WMA0GCSqGSIb3DQEBBAUAMDMxEjAQBgNV 
     3BAMTCXBqc2lwLmxhYjEdMBsGCSqGSIb3DQEJARYOdGVzdEBwanNpcC5sYWIwHhcN 
     4MTAwMjEwMDkwNTQ0WhcNMjAwMjA4MDkwNTQ0WjAzMRIwEAYDVQQDEwlwanNpcC5s 
     5YWIxHTAbBgkqhkiG9w0BCQEWDnRlc3RAcGpzaXAubGFiMIGfMA0GCSqGSIb3DQEB 
     6AQUAA4GNADCBiQKBgQDI9T0Pf+1gKOTOAGEpZ481Q6xfm5vz6n1+6udxzQtfPKlQ 
     7rPD5x5im2u3tmy6ABxZeY5tCdeikBPiGlc5bRIRng6KM8kidkg3gEhwhRUxHCMWb 
     8mBpkz7rFERf/pWAOCqYCiy1RT8QrK+XOFoFdJhdF85UPDEUw+pHEsYetTDs9RQID 
     9AQABo1AwTjBMBgNVHREERTBDgglwanNpcC5sYWKCDXNpcC5wanNpcC5sYWKBDnRl 
     10c3RAcGpzaXAubGFihhFzaXA6c2lwLnBqc2lwLmxhYocEfwAAATANBgkqhkiG9w0B 
     11AQQFAAOBgQCLPl/WF1QvjT36kVLH0nxfHwDOJuAzlh6nv9rYBviOLw9FTEMgW6hA 
     12oG55YSdVjTnMynTMOH/kVp4Vxlk46A8neE+/LI8RPh6lJh52vb+iPAtBpsQoq06T 
     13+u4DfJcN8Y/jy+QAn78jryKjwKuZWfuWny9gxsLWMUbH5Bc6v6wfQQ== 
    2114-----END CERTIFICATE----- 
  • pjproject/trunk/pjlib/build/pjlib.dsp

    r3052 r3106  
    341341# Begin Source File 
    342342 
     343SOURCE=..\src\pj\ssl_sock_dump.c 
     344# End Source File 
     345# Begin Source File 
     346 
    343347SOURCE=..\src\pj\ssl_sock_ossl.c 
    344348# End Source File 
  • pjproject/trunk/pjlib/build/pjlib.vcproj

    r3052 r3106  
    56475647                        <File 
    56485648                                RelativePath="..\src\pj\ssl_sock_common.c" 
     5649                                > 
     5650                        </File> 
     5651                        <File 
     5652                                RelativePath="..\src\pj\ssl_sock_dump.c" 
    56495653                                > 
    56505654                        </File> 
  • pjproject/trunk/pjlib/build/privkey.pem

    r2971 r3106  
    11-----BEGIN RSA PRIVATE KEY----- 
    2 MIIEpQIBAAKCAQEA1lr5y/qEgtEOjsBi7dmLoV0xMyFb9wfkhkO7Woweh91l1Xqv 
    3 tTZlPWM3Gt94OBUa1O5+LJmJii85tWp4gYTZiYwPrfoG8osypyzGgi6BudrVKFC3 
    4 ADRilGhsJZr2RboA59nlYOlH1H0cxBm1d6t2vz80rDhD8LDHhd2DECT4ZKMj0C7V 
    5 oFF4D/PTcqt14xhrcP6plIEIxPGuvz9Ml3PpsiNIZgKZmfZwd2JpQeVt6ulqFNoB 
    6 oS13+Ndqx/y4HZz4TOIo0ueeCr/RHFA3UE065um2IOurY/qk3rew6JVDpU2d7yqb 
    7 git7bXivQmzT1c7DLAd8ggC0i80N+O6SMHy2iQIDAQABAoIBAQCAke7Ujz2d7WDq 
    8 9LAh8+NRdUFGZtLvd9d1RPkCVZsWaRBknIL5kVfmGzV5M+K62MXQRACAJdOeg7b8 
    9 fpErNpD4dH8PHjG+lwlZxnyGpvh+jqhd1xP81m7ujzeW0ry2k9tpNYPkveespyJy 
    10 6Oy0i67dBT9FsTXnD1GNlJDBRTuLuEkTTBqbn/2s3+gUfChJ4HPmYMeO9HU4PcfM 
    11 yUsHatBiIkXiCKdDZVMDr5AUVD0Wo3uHPGJ8ZreURAjH+ldG09+/EsVoPberbrDZ 
    12 ZxJ70VKG+ZZTY8HZr9OsZhDZDrHiw9PdG7Hvg7bCvv+gDzZ/z8F+7YHjRjmD5Tp5 
    13 Ex5hDco1AoGBAPfdfzwmqb79AXwYH0HZkkl2EXpzbR9LRgvWlOMSN3GlZhusvGQR 
    14 up6iGk9QnmoEtQS2IAuK4JT3r+yoM/20Nadq5ZUpkZ49SHuZ6+eZpotv3Fh8Oay8 
    15 TAi2vBGM7EQPUOjPOWMRaYGBz3FT/GvUGPTeQ8jYt1gy8F18+A8xD8pTAoGBAN1j 
    16 7+yTly+M47U6mIUXcwoelaS4f/kMcwKHO0O182S4ktfjzc3TpQbHm68ws1rB3iFZ 
    17 SFOP/d04tVxZqPBhN2SpXRHGqTJxXthdTbu3scLMedlf4jY11SRiHX4PDnoBQ1GJ 
    18 NpdkMoex25Fw3AqSVpP61zo8sJkqpqjFfeQDbfgzAoGBAKyGx1ZmDwc6cjsfSzp5 
    19 p+JsRVQ3XcBHk9UPooi/mEoJd55RyLvav0xFxwxoMCvZZOqHnpyKKTJniVOv7Khu 
    20 NF55AJ6n1Y0QWRB3ngWSJKOv0+7fYQHD+yShlRyeO6JQCuBRxT8Y0phrc6oNbIjd 
    21 lBV1VDdL6aqBol9gagWg/72zAoGBAK1rAx1F3z+YFSZ459AZNjvPCVkmTNhBMDXi 
    22 yEGZ3TYgfqYuA6AfET3mTcVFWLjW87EbxtPuDuWi7i2Q7gydmk53fDfYbeDdfXXu 
    23 YF2S3uPAWBI2UXQ1ZuhBEukT0jsvkhPkb6bXDd3NLDkZNsPxLXBtJPqxX4QbLME3 
    24 Mg3RweqRAoGAJ4iXP2b4XWhg17qpDtpn8nhFxLNdhxdaDSKRL8oKQLteds3wS0fi 
    25 ZlaU1P9a3ygTpNquKlmdLJTQEDAVjV5DDlrQAPxtSSytHulNzXRMQFaeydar3Ssv 
    26 J07BPdQs6JEgV071rGGzBcL8ulo7qCdnGxU6GmhLkS4MBbTuqR6jmgU= 
     2MIICXgIBAAKBgQDI9T0Pf+1gKOTOAGEpZ481Q6xfm5vz6n1+6udxzQtfPKlQrPD5 
     3x5im2u3tmy6ABxZeY5tCdeikBPiGlc5bRIRng6KM8kidkg3gEhwhRUxHCMWbmBpk 
     4z7rFERf/pWAOCqYCiy1RT8QrK+XOFoFdJhdF85UPDEUw+pHEsYetTDs9RQIDAQAB 
     5AoGAGV+1xQY/H7wqH8S2f/begzg3RJ8uUt8R13urm5frTqwnKNOdXbyRDshn8G9+ 
     6sJW0gliLWxnuNP+Xrc6ujqGZIguK/yAxJ3LprAN2Ay1lW2ONyZNMquBeIY5Txhyy 
     7SnU7U+NQYgA3+w9T7O7YQ575TTDm2gri558jIx8t55Wo9sUCQQDtjfGZ3sYXwpxR 
     8MvtdtfwDxSKhf6glT6dn7/37KITBZXFy6Eb/tHrEEUuwR46g30vTd2JElCB+QExu 
     94sZDt813AkEA2I/WXdGVRXtHzVivf3AnqWyXfrfAAXlBmEkgPyIPwE1+mxeNxkU7 
     10TRn0MOqAfbQW4+GRIYCKSBLodRnRq2iKIwJBAJLYa8DyNQH7CyYmnbwQAvlRo1ax 
     110v89ff6CHD5ljar/SmH9s+XdawZIqsENet13KyhNZDGAX5WrqZPiGy1BMYECQQC1 
     12FREawfUfdEZF3rJgzVdcxACpZNyYXtwKipr8L28cTbBf3wIdmCZOAjW98VgfxEaf 
     13pi3E5ca7HZRi1oQL4A4hAkEA5koHCQYl+5PDjbLtxl0VyVCpmT9BrcZ99MS+ZEaW 
     142+HpKIhXrEFxePQaWbCaW7gjKmKUwC0qqu0moedqJC3mzg== 
    2715-----END RSA PRIVATE KEY----- 
  • pjproject/trunk/pjlib/include/pj/ssl_sock.h

    r2998 r3106  
    6161 
    6262 
     63typedef enum pj_ssl_cert_verify_flag_t 
     64{ 
     65    /** 
     66     * No error in verification. 
     67     */ 
     68    PJ_SSL_CERT_ESUCCESS                                = 0, 
     69 
     70    /** 
     71     * The issuer certificate cannot be found. 
     72     */ 
     73    PJ_SSL_CERT_EISSUER_NOT_FOUND                       = (1 << 0), 
     74 
     75    /** 
     76     * The certificate is untrusted. 
     77     */ 
     78    PJ_SSL_CERT_EUNTRUSTED                              = (1 << 1), 
     79 
     80    /** 
     81     * The certificate has expired or not yet valid. 
     82     */ 
     83    PJ_SSL_CERT_EVALIDITY_PERIOD                        = (1 << 2), 
     84 
     85    /** 
     86     * One or more fields of the certificate cannot be decoded due to 
     87     * invalid format. 
     88     */ 
     89    PJ_SSL_CERT_EINVALID_FORMAT                         = (1 << 3), 
     90 
     91    /** 
     92     * The certificate cannot be used for the specified purpose. 
     93     */ 
     94    PJ_SSL_CERT_EINVALID_PURPOSE                        = (1 << 4), 
     95 
     96    /** 
     97     * The issuer info in the certificate does not match to the (candidate)  
     98     * issuer certificate, e.g: issuer name not match to subject name 
     99     * of (candidate) issuer certificate. 
     100     */ 
     101    PJ_SSL_CERT_EISSUER_MISMATCH                        = (1 << 5), 
     102 
     103    /** 
     104     * The CRL certificate cannot be found or cannot be read properly. 
     105     */ 
     106    PJ_SSL_CERT_ECRL_FAILURE                            = (1 << 6), 
     107 
     108    /** 
     109     * The certificate has been revoked. 
     110     */ 
     111    PJ_SSL_CERT_EREVOKED                                = (1 << 7), 
     112 
     113    /** 
     114     * The certificate chain length is too long. 
     115     */ 
     116    PJ_SSL_CERT_ECHAIN_TOO_LONG                         = (1 << 8), 
     117 
     118    /** 
     119     * The server identity does not match to any identities specified in  
     120     * the certificate, e.g: subjectAltName extension, subject common name. 
     121     * This flag will only be set by application as SSL socket does not  
     122     * perform server identity verification. 
     123     */ 
     124    PJ_SSL_CERT_EIDENTITY_NOT_MATCH                     = (1 << 30), 
     125 
     126    /** 
     127     * Unknown verification error. 
     128     */ 
     129    PJ_SSL_CERT_EUNKNOWN                                = (1 << 31) 
     130 
     131} pj_ssl_cert_verify_flag_t; 
     132 
     133 
     134typedef enum pj_ssl_cert_name_type 
     135{ 
     136    PJ_SSL_CERT_NAME_UNKNOWN = 0, 
     137    PJ_SSL_CERT_NAME_RFC822, 
     138    PJ_SSL_CERT_NAME_DNS, 
     139    PJ_SSL_CERT_NAME_URI, 
     140    PJ_SSL_CERT_NAME_IP 
     141} pj_ssl_cert_name_type; 
     142 
    63143/** 
    64144 * Describe structure of certificate info. 
    65145 */ 
    66146typedef struct pj_ssl_cert_info { 
    67     pj_str_t    subject;            /**< Subject.               */ 
    68     pj_str_t    issuer;             /**< Issuer.                */ 
    69     unsigned    version;            /**< Certificate version.   */ 
    70     pj_time_val validity_start;     /**< Validity start.        */ 
    71     pj_time_val validity_end;       /**< Validity end.          */ 
    72     pj_bool_t   validity_use_gmt;   /**< Flag if validity date/time  
    73                                          use GMT.               */ 
     147 
     148    unsigned    version;            /**< Certificate version    */ 
     149 
     150    pj_uint8_t  serial_no[20];      /**< Serial number, array of 
     151                                         octets, first index is 
     152                                         MSB                    */ 
     153 
     154    struct { 
     155        pj_str_t        cn;         /**< Common name            */ 
     156        pj_str_t        info;       /**< One line subject, fields 
     157                                         are separated by slash */ 
     158    } subject;                      /**< Subject                */ 
     159 
     160    struct { 
     161        pj_str_t        cn;         /**< Common name            */ 
     162        pj_str_t        info;       /**< One line subject, fields 
     163                                         are separated by slash.*/ 
     164    } issuer;                       /**< Issuer                 */ 
     165 
     166    struct { 
     167        pj_time_val     start;      /**< Validity start         */ 
     168        pj_time_val     end;        /**< Validity end           */ 
     169        pj_bool_t       gmt;        /**< Flag if validity date/time  
     170                                         use GMT                */ 
     171    } validity;                     /**< Validity               */ 
     172 
     173    struct { 
     174        unsigned        cnt;        /**< # of entry             */ 
     175        struct { 
     176            pj_ssl_cert_name_type type; 
     177                                    /**< Name type              */ 
     178            pj_str_t    name;       /**< The name               */ 
     179        } *entry;                   /**< Subject alt name entry */ 
     180    } subj_alt_name;                /**< Subject alternative 
     181                                         name extension         */ 
     182 
    74183} pj_ssl_cert_info; 
    75184 
     
    92201                                                 const pj_str_t *privkey_pass, 
    93202                                                 pj_ssl_cert_t **p_cert); 
     203 
     204 
     205/** 
     206 * Dump SSL certificate info. 
     207 * 
     208 * @param ci            The certificate info. 
     209 * @param prefix        Prefix string for each line. 
     210 * @param buf           The buffer where certificate info will be printed on. 
     211 * @param buf_size      The buffer size. 
     212 * 
     213 * @return              PJ_SUCCESS when successful. 
     214 */ 
     215PJ_DECL(pj_status_t) pj_ssl_cert_info_dump(const pj_ssl_cert_info *ci, 
     216                                           const char *prefix, 
     217                                           char *buf, 
     218                                           pj_size_t buf_size); 
     219 
     220 
     221/** 
     222 * Get SSL certificate verification error messages from verification status. 
     223 * 
     224 * @param verify_status The SSL certificate verification status. 
     225 * @param error_strings Array of strings to receive the verification error  
     226 *                      messages. 
     227 * @param count         On input it specifies maximum error messages should be 
     228 *                      retrieved. On output it specifies the number of error 
     229 *                      messages retrieved. 
     230 * 
     231 * @return              PJ_SUCCESS when successful. 
     232 */ 
     233PJ_DECL(pj_status_t) pj_ssl_cert_verify_error_st(pj_uint32_t verify_status,  
     234                                                 const char *error_strings[], 
     235                                                 unsigned *count); 
    94236 
    95237 
     
    364506     * Describes active local certificate info. 
    365507     */ 
    366     pj_ssl_cert_info local_cert_info; 
     508    pj_ssl_cert_info *local_cert_info; 
    367509    
    368510    /** 
    369511     * Describes active remote certificate info. 
    370512     */ 
    371     pj_ssl_cert_info remote_cert_info; 
    372     
     513    pj_ssl_cert_info *remote_cert_info; 
     514 
     515    /** 
     516     * Status of peer certificate verification. 
     517     */ 
     518    pj_uint32_t         verify_status; 
     519 
    373520} pj_ssl_sock_info; 
    374521 
     
    524671 
    525672    /** 
    526      * When secure socket is acting as client (perform outgoing connection) 
    527      * and it needs to verify server name (e.g: host or domain name) by 
    528      * matching it to the name specified in the server certificate. This  
    529      * setting is useful when the server is hosting multiple domains for 
    530      * the same listening socket. 
     673     * Server name indication. When secure socket is acting as client  
     674     * (perform outgoing connection) and the server may host multiple 
     675     * 'virtual' servers at a single underlying network address, setting 
     676     * this will allow client to tell the server a name of the server 
     677     * it is contacting. 
    531678     * 
    532679     * Default value is zero/not-set. 
  • pjproject/trunk/pjlib/src/pj/ssl_sock_common.c

    r2998 r3106  
    1818 */ 
    1919#include <pj/ssl_sock.h> 
     20#include <pj/assert.h> 
    2021#include <pj/errno.h> 
    2122#include <pj/string.h> 
     
    129130 
    130131 
     132/* Get cipher name string */ 
    131133PJ_DEF(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher) 
    132134{ 
     
    141143    return NULL; 
    142144} 
     145 
     146 
     147 
     148 
     149PJ_DEF(pj_status_t) pj_ssl_cert_verify_error_st(pj_uint32_t verify_status,  
     150                                                const char *error_strings[], 
     151                                                unsigned *count) 
     152{ 
     153    unsigned i = 0, shift_idx = 0; 
     154    unsigned unknown = 0; 
     155    pj_uint32_t errs; 
     156 
     157    PJ_ASSERT_RETURN(error_strings && count, PJ_EINVAL); 
     158 
     159    if (verify_status == PJ_SSL_CERT_ESUCCESS && *count) { 
     160        error_strings[0] = "OK"; 
     161        *count = 1; 
     162        return PJ_SUCCESS; 
     163    } 
     164 
     165    errs = verify_status; 
     166 
     167    while (errs && i < *count) { 
     168        pj_uint32_t err; 
     169        const char *p = NULL; 
     170 
     171        if ((errs & 1) == 0) { 
     172            shift_idx++; 
     173            errs >>= 1; 
     174            continue; 
     175        } 
     176 
     177        err = (1 << shift_idx); 
     178 
     179        switch (err) { 
     180        case PJ_SSL_CERT_EISSUER_NOT_FOUND: 
     181            p = "The issuer certificate cannot be found"; 
     182            break; 
     183        case PJ_SSL_CERT_EUNTRUSTED: 
     184            p = "The certificate is untrusted"; 
     185            break; 
     186        case PJ_SSL_CERT_EVALIDITY_PERIOD: 
     187            p = "The certificate has expired or not yet valid"; 
     188            break; 
     189        case PJ_SSL_CERT_EINVALID_FORMAT: 
     190            p = "One or more fields of the certificate cannot be decoded " 
     191                "due to invalid format"; 
     192            break; 
     193        case PJ_SSL_CERT_EISSUER_MISMATCH: 
     194            p = "The issuer info in the certificate does not match to the " 
     195                "(candidate) issuer certificate"; 
     196            break; 
     197        case PJ_SSL_CERT_ECRL_FAILURE: 
     198            p = "The CRL certificate cannot be found or cannot be read " 
     199                "properly"; 
     200            break; 
     201        case PJ_SSL_CERT_EREVOKED: 
     202            p = "The certificate has been revoked"; 
     203            break; 
     204        case PJ_SSL_CERT_EINVALID_PURPOSE: 
     205            p = "The certificate or CA certificate cannot be used for the " 
     206                "specified purpose"; 
     207            break; 
     208        case PJ_SSL_CERT_ECHAIN_TOO_LONG: 
     209            p = "The certificate chain length is too long"; 
     210            break; 
     211        case PJ_SSL_CERT_EIDENTITY_NOT_MATCH: 
     212            p = "The server identity does not match to any identities " 
     213                "specified in the certificate"; 
     214            break; 
     215        case PJ_SSL_CERT_EUNKNOWN: 
     216        default: 
     217            unknown++; 
     218            break; 
     219        } 
     220         
     221        /* Set error string */ 
     222        if (p) 
     223            error_strings[i++] = p; 
     224 
     225        /* Next */ 
     226        shift_idx++; 
     227        errs >>= 1; 
     228    } 
     229 
     230    /* Unknown error */ 
     231    if (unknown && i < *count) 
     232        error_strings[i++] = "Unknown verification error"; 
     233 
     234    *count = i; 
     235 
     236    return PJ_SUCCESS; 
     237} 
  • pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c

    r3020 r3106  
    4646#include <openssl/ssl.h> 
    4747#include <openssl/err.h> 
     48#include <openssl/x509v3.h> 
    4849 
    4950 
     
    153154    pj_ioqueue_op_key_t   handshake_op_key; 
    154155    pj_timer_entry        timer; 
     156    pj_status_t           verify_status; 
    155157 
    156158    pj_sock_t             sock; 
     
    208210#define PJ_SSL_ERRNO_SPACE_SIZE         PJ_ERRNO_SPACE_SIZE 
    209211 
     212#define STATUS_FROM_SSL_ERR(err, status) { \ 
     213    status = ERR_GET_LIB(err)*300 + ERR_GET_REASON(err);\ 
     214    pj_assert(status < PJ_SSL_ERRNO_SPACE_SIZE);\ 
     215    if (status) status += PJ_SSL_ERRNO_START;\ 
     216} 
     217 
    210218#define GET_SSL_STATUS(status) { \ 
    211219    unsigned long e = ERR_get_error();\ 
    212     status = ERR_GET_LIB(e)*300 + ERR_GET_REASON(e);\ 
    213     pj_assert(status < PJ_SSL_ERRNO_SPACE_SIZE);\ 
    214     if (status) status += PJ_SSL_ERRNO_START;\ 
     220    STATUS_FROM_SSL_ERR(e, status);\ 
    215221} 
    216222 
     
    236242    { 
    237243        const char *tmp = NULL; 
    238         tmp = ERR_reason_error_string(ssl_err); 
     244 
     245        if (ssl_err >= 300) 
     246            tmp = ERR_reason_error_string(ssl_err); 
     247        else 
     248            tmp = X509_verify_cert_error_string(ssl_err); 
    239249 
    240250        if (tmp) { 
     
    263273static pj_ssl_cipher openssl_ciphers[100]; 
    264274static unsigned openssl_cipher_num; 
     275 
     276/* OpenSSL application data index */ 
     277static int sslsock_idx; 
    265278 
    266279 
     
    330343    } 
    331344 
     345    /* Create OpenSSL application data index for SSL socket */ 
     346    sslsock_idx = SSL_get_ex_new_index(0, "SSL socket", NULL, NULL, NULL); 
     347 
    332348    return PJ_SUCCESS; 
    333349} 
     
    356372 
    357373 
    358 /* Create and initialize new SSL context */ 
    359 static pj_status_t create_ssl_ctx(pj_ssl_sock_t *ssock, SSL_CTX **p_ctx) 
     374/* SSL password callback. */ 
     375static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) 
     376{ 
     377    pj_ssl_sock_t *ssock; 
     378    SSL *ossl_ssl; 
     379    int err; 
     380 
     381    /* Get SSL instance */ 
     382    ossl_ssl = X509_STORE_CTX_get_ex_data(x509_ctx,  
     383                                    SSL_get_ex_data_X509_STORE_CTX_idx()); 
     384    pj_assert(ossl_ssl); 
     385 
     386    /* Get SSL socket instance */ 
     387    ssock = SSL_get_ex_data(ossl_ssl, sslsock_idx); 
     388    pj_assert(ssock); 
     389 
     390    /* Store verification status */ 
     391    err = X509_STORE_CTX_get_error(x509_ctx); 
     392    switch (err) { 
     393    case X509_V_OK: 
     394        break; 
     395 
     396    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: 
     397        ssock->verify_status |= PJ_SSL_CERT_EISSUER_NOT_FOUND; 
     398        break; 
     399 
     400    case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: 
     401    case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: 
     402    case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: 
     403    case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: 
     404        ssock->verify_status |= PJ_SSL_CERT_EINVALID_FORMAT; 
     405        break; 
     406 
     407    case X509_V_ERR_CERT_NOT_YET_VALID: 
     408    case X509_V_ERR_CERT_HAS_EXPIRED: 
     409        ssock->verify_status |= PJ_SSL_CERT_EVALIDITY_PERIOD; 
     410        break; 
     411 
     412    case X509_V_ERR_UNABLE_TO_GET_CRL: 
     413    case X509_V_ERR_CRL_NOT_YET_VALID: 
     414    case X509_V_ERR_CRL_HAS_EXPIRED: 
     415    case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: 
     416    case X509_V_ERR_CRL_SIGNATURE_FAILURE: 
     417    case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: 
     418    case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: 
     419        ssock->verify_status |= PJ_SSL_CERT_ECRL_FAILURE; 
     420        break;   
     421 
     422    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 
     423    case X509_V_ERR_CERT_UNTRUSTED: 
     424    case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: 
     425    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: 
     426        ssock->verify_status |= PJ_SSL_CERT_EUNTRUSTED; 
     427        break;   
     428 
     429    case X509_V_ERR_CERT_SIGNATURE_FAILURE: 
     430    case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: 
     431    case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: 
     432    case X509_V_ERR_AKID_SKID_MISMATCH: 
     433    case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: 
     434    case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: 
     435        ssock->verify_status |= PJ_SSL_CERT_EISSUER_MISMATCH; 
     436        break; 
     437 
     438    case X509_V_ERR_CERT_REVOKED: 
     439        ssock->verify_status |= PJ_SSL_CERT_EREVOKED; 
     440        break;   
     441 
     442    case X509_V_ERR_INVALID_PURPOSE: 
     443    case X509_V_ERR_CERT_REJECTED: 
     444    case X509_V_ERR_INVALID_CA: 
     445        ssock->verify_status |= PJ_SSL_CERT_EINVALID_PURPOSE; 
     446        break; 
     447 
     448    case X509_V_ERR_CERT_CHAIN_TOO_LONG: /* not really used */ 
     449    case X509_V_ERR_PATH_LENGTH_EXCEEDED: 
     450        ssock->verify_status |= PJ_SSL_CERT_ECHAIN_TOO_LONG; 
     451        break; 
     452 
     453    /* Unknown errors */ 
     454    case X509_V_ERR_OUT_OF_MEM: 
     455    default: 
     456        ssock->verify_status |= PJ_SSL_CERT_EUNKNOWN; 
     457        break; 
     458    } 
     459 
     460    /* When verification is not requested just return ok here, however 
     461     * application can still get the verification status. 
     462     */ 
     463    if (PJ_FALSE == ssock->param.verify_peer) 
     464        preverify_ok = 1; 
     465 
     466    return preverify_ok; 
     467} 
     468 
     469/* Setting SSL sock cipher list */ 
     470static pj_status_t set_cipher_list(pj_ssl_sock_t *ssock); 
     471 
     472 
     473/* Create and initialize new SSL context and instance */ 
     474static pj_status_t create_ssl(pj_ssl_sock_t *ssock) 
    360475{ 
    361476    SSL_METHOD *ssl_method; 
     
    365480    pj_status_t status; 
    366481         
    367     pj_assert(ssock && p_ctx); 
     482    pj_assert(ssock); 
    368483 
    369484    cert = ssock->cert; 
     
    394509    } 
    395510 
    396     /* Create SSL context for the listener */ 
     511    /* Create SSL context */ 
    397512    ctx = SSL_CTX_new(ssl_method); 
    398513    if (ctx == NULL) { 
     
    456571    } 
    457572 
     573    /* Create SSL instance */ 
     574    ssock->ossl_ctx = ctx; 
     575    ssock->ossl_ssl = SSL_new(ssock->ossl_ctx); 
     576    if (ssock->ossl_ssl == NULL) { 
     577        GET_SSL_STATUS(status); 
     578        return status; 
     579    } 
     580 
     581    /* Set SSL sock as application data of SSL instance */ 
     582    SSL_set_ex_data(ssock->ossl_ssl, sslsock_idx, ssock); 
    458583 
    459584    /* SSL verification options */ 
    460     if (ssock->param.verify_peer) { 
    461         mode = SSL_VERIFY_PEER; 
    462     } else { 
    463         mode = SSL_VERIFY_NONE; 
    464     } 
    465  
     585    mode = SSL_VERIFY_PEER; 
    466586    if (ssock->is_server && ssock->param.require_client_cert) 
    467         mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_PEER; 
    468  
    469     SSL_CTX_set_verify(ctx, mode, NULL); 
    470  
    471     *p_ctx = ctx; 
     587        mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; 
     588 
     589    SSL_set_verify(ssock->ossl_ssl, mode, &verify_cb); 
     590 
     591    /* Set cipher list */ 
     592    status = set_cipher_list(ssock); 
     593    if (status != PJ_SUCCESS) 
     594        return status; 
     595 
     596    /* Setup SSL BIOs */ 
     597    ssock->ossl_rbio = BIO_new(BIO_s_mem()); 
     598    ssock->ossl_wbio = BIO_new(BIO_s_mem()); 
     599    BIO_set_close(ssock->ossl_rbio, BIO_CLOSE); 
     600    BIO_set_close(ssock->ossl_wbio, BIO_CLOSE); 
     601    SSL_set_bio(ssock->ossl_ssl, ssock->ossl_rbio, ssock->ossl_wbio); 
    472602 
    473603    return PJ_SUCCESS; 
     
    475605 
    476606 
    477 /* Destroy SSL context */ 
    478 static void destroy_ssl_ctx(SSL_CTX *ctx) 
    479 { 
    480     SSL_CTX_free(ctx); 
     607/* Destroy SSL context and instance */ 
     608static void destroy_ssl(pj_ssl_sock_t *ssock) 
     609{ 
     610    /* Destroy SSL instance */ 
     611    if (ssock->ossl_ssl) { 
     612        SSL_shutdown(ssock->ossl_ssl); 
     613        SSL_free(ssock->ossl_ssl); /* this will also close BIOs */ 
     614        ssock->ossl_ssl = NULL; 
     615    } 
     616 
     617    /* Destroy SSL context */ 
     618    if (ssock->ossl_ctx) { 
     619        SSL_CTX_free(ssock->ossl_ctx); 
     620        ssock->ossl_ctx = NULL; 
     621    } 
    481622 
    482623    /* Potentially shutdown OpenSSL library if this is the last 
     
    492633    ssock->ssl_state = SSL_STATE_NULL; 
    493634 
    494     if (ssock->ossl_ssl) { 
    495         SSL_shutdown(ssock->ossl_ssl); 
    496         SSL_free(ssock->ossl_ssl); /* this will also close BIOs */ 
    497         ssock->ossl_ssl = NULL; 
    498     } 
    499     if (ssock->ossl_ctx) { 
    500         destroy_ssl_ctx(ssock->ossl_ctx); 
    501         ssock->ossl_ctx = NULL; 
    502     } 
     635    destroy_ssl(ssock); 
     636 
    503637    if (ssock->asock) { 
    504638        pj_activesock_close(ssock->asock); 
     
    640774 
    641775 
    642 /* Get certificate info from OpenSSL X509 */ 
     776/* Get Common Name field string from a general name string */ 
     777static void get_cn_from_gen_name(const pj_str_t *gen_name, pj_str_t *cn) 
     778{ 
     779    pj_str_t CN_sign = {"/CN=", 4}; 
     780    char *p, *q; 
     781 
     782    pj_bzero(cn, sizeof(cn)); 
     783 
     784    p = pj_strstr(gen_name, &CN_sign); 
     785    if (!p) 
     786        return; 
     787 
     788    p += 4; /* shift pointer to value part */ 
     789    pj_strset(cn, p, gen_name->slen - (p - gen_name->ptr)); 
     790    q = pj_strchr(cn, '/'); 
     791    if (q) 
     792        cn->slen = q - p; 
     793} 
     794 
     795 
     796/* Get certificate info from OpenSSL X509, in case the certificate info 
     797 * hal already populated, this function will check if the contents need  
     798 * to be updated by inspecting the issuer and the serial number. 
     799 */ 
    643800static void get_cert_info(pj_pool_t *pool, pj_ssl_cert_info *ci, X509 *x) 
    644801{ 
    645     pj_ssl_cert_info info; 
    646     char buf1[256]; 
    647     char buf2[256]; 
    648  
    649     pj_assert(pool && ci); 
    650  
    651     if (!x) { 
    652         pj_bzero(ci, sizeof(pj_ssl_cert_info)); 
     802    pj_bool_t update_needed; 
     803    char buf[512]; 
     804    pj_uint8_t serial_no[64] = {0}; /* should be >= sizeof(ci->serial_no) */ 
     805    pj_uint8_t *p; 
     806    unsigned len; 
     807    GENERAL_NAMES *names = NULL; 
     808 
     809    pj_assert(pool && ci && x); 
     810 
     811    /* Get issuer */ 
     812    X509_NAME_oneline(X509_get_issuer_name(x), buf, sizeof(buf)); 
     813 
     814    /* Get serial no */ 
     815    p = (pj_uint8_t*) M_ASN1_STRING_data(X509_get_serialNumber(x)); 
     816    len = M_ASN1_STRING_length(X509_get_serialNumber(x)); 
     817    if (len > sizeof(ci->serial_no))  
     818        len = sizeof(ci->serial_no); 
     819    pj_memcpy(serial_no + sizeof(ci->serial_no) - len, p, len); 
     820 
     821    /* Check if the contents need to be updated. */ 
     822    update_needed = pj_strcmp2(&ci->issuer.info, buf) ||  
     823                    pj_memcmp(ci->serial_no, serial_no, sizeof(ci->serial_no)); 
     824    if (!update_needed) 
    653825        return; 
    654     } 
    655  
    656     pj_bzero(&info, sizeof(info)); 
    657  
    658     /* Populate cert info */ 
    659     info.subject = pj_str(X509_NAME_oneline(X509_get_subject_name(x),buf1, 
    660                                             sizeof(buf1))); 
    661     info.issuer = pj_str(X509_NAME_oneline(X509_get_issuer_name(x), buf2, 
    662                                            sizeof(buf2))); 
    663     info.version = X509_get_version(x) + 1; 
    664     parse_ossl_asn1_time(&info.validity_start, &info.validity_use_gmt, 
     826 
     827    /* Update cert info */ 
     828 
     829    pj_bzero(ci, sizeof(pj_ssl_cert_info)); 
     830 
     831    /* Version */ 
     832    ci->version = X509_get_version(x) + 1; 
     833 
     834    /* Issuer */ 
     835    pj_strdup2(pool, &ci->issuer.info, buf); 
     836    get_cn_from_gen_name(&ci->issuer.info, &ci->issuer.cn); 
     837 
     838    /* Serial number */ 
     839    pj_memcpy(ci->serial_no, serial_no, sizeof(ci->serial_no)); 
     840 
     841    /* Subject */ 
     842    pj_strdup2(pool, &ci->subject.info,  
     843               X509_NAME_oneline(X509_get_subject_name(x), 
     844                                 buf, sizeof(buf))); 
     845    get_cn_from_gen_name(&ci->subject.info, &ci->subject.cn); 
     846 
     847    /* Validity */ 
     848    parse_ossl_asn1_time(&ci->validity.start, &ci->validity.gmt, 
    665849                         X509_get_notBefore(x)); 
    666     parse_ossl_asn1_time(&info.validity_end, &info.validity_use_gmt, 
     850    parse_ossl_asn1_time(&ci->validity.end, &ci->validity.gmt, 
    667851                         X509_get_notAfter(x)); 
    668852 
    669     /* Update certificate info */ 
    670     if (pj_strcmp(&ci->subject, &info.subject)) 
    671         pj_strdup(pool, &ci->subject, &info.subject); 
    672     if (pj_strcmp(&ci->issuer, &info.issuer)) 
    673         pj_strdup(pool, &ci->issuer, &info.issuer); 
    674     ci->version = info.version; 
    675     ci->validity_start = info.validity_start; 
    676     ci->validity_end = info.validity_end; 
    677     ci->validity_use_gmt = info.validity_use_gmt; 
     853    /* Subject Alternative Name extension */ 
     854    if (ci->version >= 3) { 
     855        names = (GENERAL_NAMES*) X509_get_ext_d2i(x, NID_subject_alt_name, 
     856                                                  NULL, NULL); 
     857    } 
     858    if (names) { 
     859        unsigned i, cnt; 
     860 
     861        cnt = sk_GENERAL_NAME_num(names); 
     862        ci->subj_alt_name.entry = pj_pool_calloc(pool, cnt,  
     863                                            sizeof(*ci->subj_alt_name.entry)); 
     864 
     865        for (i = 0; i < cnt; ++i) { 
     866            unsigned char *p = 0; 
     867            pj_ssl_cert_name_type type = PJ_SSL_CERT_NAME_UNKNOWN; 
     868            const GENERAL_NAME *name; 
     869             
     870            name = sk_GENERAL_NAME_value(names, i); 
     871 
     872            switch (name->type) { 
     873                case GEN_EMAIL: 
     874                    len = ASN1_STRING_to_UTF8(&p, name->d.ia5); 
     875                    type = PJ_SSL_CERT_NAME_RFC822; 
     876                    break; 
     877                case GEN_DNS: 
     878                    len = ASN1_STRING_to_UTF8(&p, name->d.ia5); 
     879                    type = PJ_SSL_CERT_NAME_DNS; 
     880                    break; 
     881                case GEN_URI: 
     882                    len = ASN1_STRING_to_UTF8(&p, name->d.ia5); 
     883                    type = PJ_SSL_CERT_NAME_URI; 
     884                    break; 
     885                case GEN_IPADD: 
     886                    p = ASN1_STRING_data(name->d.ip); 
     887                    len = ASN1_STRING_length(name->d.ip); 
     888                    type = PJ_SSL_CERT_NAME_IP; 
     889                    break; 
     890                default: 
     891                    break; 
     892            } 
     893 
     894            if (p && len && type != PJ_SSL_CERT_NAME_UNKNOWN) { 
     895                ci->subj_alt_name.entry[ci->subj_alt_name.cnt].type = type; 
     896                if (type == PJ_SSL_CERT_NAME_IP) { 
     897                    int af = pj_AF_INET(); 
     898                    if (len == sizeof(pj_in6_addr)) af = pj_AF_INET6(); 
     899                    pj_inet_ntop2(af, p, buf, sizeof(buf)); 
     900                    pj_strdup2(pool,  
     901                          &ci->subj_alt_name.entry[ci->subj_alt_name.cnt].name, 
     902                          buf); 
     903                } else { 
     904                    pj_strdup2(pool,  
     905                          &ci->subj_alt_name.entry[ci->subj_alt_name.cnt].name,  
     906                          (char*)p); 
     907                    OPENSSL_free(p); 
     908                } 
     909                ci->subj_alt_name.cnt++; 
     910            } 
     911        } 
     912    } 
    678913} 
    679914 
     
    690925    /* Active local certificate */ 
    691926    x = SSL_get_certificate(ssock->ossl_ssl); 
    692     get_cert_info(ssock->pool, &ssock->local_cert_info, x); 
    693     /* Don't free local's X509! */ 
     927    if (x) { 
     928        get_cert_info(ssock->pool, &ssock->local_cert_info, x); 
     929        /* Don't free local's X509! */ 
     930    } else { 
     931        pj_bzero(&ssock->local_cert_info, sizeof(pj_ssl_cert_info)); 
     932    } 
    694933 
    695934    /* Active remote certificate */ 
    696935    x = SSL_get_peer_certificate(ssock->ossl_ssl); 
    697     get_cert_info(ssock->pool, &ssock->remote_cert_info, x); 
    698     /* Free peer's X509 */ 
    699     X509_free(x); 
     936    if (x) { 
     937        get_cert_info(ssock->pool, &ssock->remote_cert_info, x); 
     938        /* Free peer's X509 */ 
     939        X509_free(x); 
     940    } else { 
     941        pj_bzero(&ssock->remote_cert_info, sizeof(pj_ssl_cert_info)); 
     942    } 
    700943} 
    701944 
     
    12321475 
    12331476    /* Create SSL context */ 
    1234     status = create_ssl_ctx(ssock, &ssock->ossl_ctx); 
     1477    status = create_ssl(ssock); 
    12351478    if (status != PJ_SUCCESS) 
    12361479        goto on_return; 
    1237  
    1238     /* Create SSL instance */ 
    1239     ssock->ossl_ssl = SSL_new(ssock->ossl_ctx); 
    1240     if (ssock->ossl_ssl == NULL) { 
    1241         GET_SSL_STATUS(status); 
    1242         goto on_return; 
    1243     } 
    1244  
    1245     /* Set cipher list */ 
    1246     status = set_cipher_list(ssock); 
    1247     if (status != PJ_SUCCESS) 
    1248         goto on_return; 
    1249  
    1250     /* Setup SSL BIOs */ 
    1251     ssock->ossl_rbio = BIO_new(BIO_s_mem()); 
    1252     ssock->ossl_wbio = BIO_new(BIO_s_mem()); 
    1253     BIO_set_close(ssock->ossl_rbio, BIO_CLOSE); 
    1254     BIO_set_close(ssock->ossl_wbio, BIO_CLOSE); 
    1255     SSL_set_bio(ssock->ossl_ssl, ssock->ossl_rbio, ssock->ossl_wbio); 
    12561480 
    12571481    /* Prepare read buffer */ 
     
    13521576 
    13531577    /* Create SSL context */ 
    1354     status = create_ssl_ctx(ssock, &ssock->ossl_ctx); 
     1578    status = create_ssl(ssock); 
    13551579    if (status != PJ_SUCCESS) 
    13561580        goto on_return; 
    1357  
    1358     /* Create SSL instance */ 
    1359     ssock->ossl_ssl = SSL_new(ssock->ossl_ctx); 
    1360     if (ssock->ossl_ssl == NULL) { 
    1361         GET_SSL_STATUS(status); 
    1362         goto on_return; 
    1363     } 
    1364  
    1365     /* Set cipher list */ 
    1366     status = set_cipher_list(ssock); 
    1367     if (status != PJ_SUCCESS) 
    1368         goto on_return; 
    1369  
    1370     /* Setup SSL BIOs */ 
    1371     ssock->ossl_rbio = BIO_new(BIO_s_mem()); 
    1372     ssock->ossl_wbio = BIO_new(BIO_s_mem()); 
    1373     BIO_set_close(ssock->ossl_rbio, BIO_CLOSE); 
    1374     BIO_set_close(ssock->ossl_wbio, BIO_CLOSE); 
    1375     SSL_set_bio(ssock->ossl_ssl, ssock->ossl_rbio, ssock->ossl_wbio); 
    13761581 
    13771582    /* Prepare read buffer */ 
     
    16521857     
    16531858    if (info->established) { 
     1859        const SSL_CIPHER *cipher; 
     1860 
    16541861        /* Current cipher */ 
    1655         const SSL_CIPHER *cipher; 
    1656  
    16571862        cipher = SSL_get_current_cipher(ssock->ossl_ssl); 
    16581863        info->cipher = (cipher->id & 0x00FFFFFF); 
     
    16621867 
    16631868        /* Certificates info */ 
    1664         info->local_cert_info = ssock->local_cert_info; 
    1665         info->remote_cert_info = ssock->remote_cert_info; 
     1869        info->local_cert_info = &ssock->local_cert_info; 
     1870        info->remote_cert_info = &ssock->remote_cert_info; 
     1871 
     1872        /* Verification status */ 
     1873        info->verify_status = ssock->verify_status; 
    16661874    } 
    16671875 
  • pjproject/trunk/pjlib/src/pj/ssl_sock_symbian.cpp

    r2998 r3106  
    128128        return KErrNotFound; 
    129129    } 
     130    const CX509Certificate *GetPeerCert() { 
     131        if (securesock_) 
     132            return securesock_->ServerCert(); 
     133        return NULL; 
     134    } 
    130135 
    131136private: 
     
    410415struct pj_ssl_sock_t 
    411416{ 
     417    pj_pool_t           *pool; 
    412418    pj_ssl_sock_cb       cb; 
    413419    void                *user_data; 
     
    435441    pj_ssl_cipher       *ciphers; 
    436442    pj_str_t             servername; 
     443    pj_ssl_cert_info     remote_cert_info; 
    437444}; 
     445 
     446 
     447static pj_str_t get_cert_name(pj_pool_t *pool, 
     448                              const CX500DistinguishedName &name) 
     449{ 
     450    TInt i; 
     451    char buf[1024]; 
     452    TUint8 *p; 
     453    TInt l = sizeof(buf); 
     454     
     455    p = (TUint8*)buf; 
     456    for(i = 0; i < name.Count(); ++i) { 
     457        const CX520AttributeTypeAndValue &attr = name.Element(i); 
     458 
     459        /* Print element separator */ 
     460        *p++ = '/'; 
     461        if (0 == --l) break; 
     462 
     463        /* Print the type. */ 
     464        TPtr8 type(p, l); 
     465        type.Copy(attr.Type()); 
     466        p += type.Length(); 
     467        l -= type.Length(); 
     468        if (0 >= --l) break; 
     469 
     470        /* Print equal sign */ 
     471        *p++ = '='; 
     472        if (0 == --l) break; 
     473         
     474        /* Print the value. Let's just get the raw data here */ 
     475        TPtr8 value(p, l); 
     476        value.Copy(attr.EncodedValue().Mid(2)); 
     477        p += value.Length(); 
     478        l -= value.Length(); 
     479        if (0 >= --l) break; 
     480    } 
     481     
     482    pj_str_t src, res; 
     483    pj_strset(&src, buf, sizeof(buf) - l); 
     484    pj_strdup(pool, &res, &src); 
     485     
     486    return res; 
     487} 
     488                             
     489/* Get certificate info from CX509Certificate. 
     490 */ 
     491static void get_cert_info(pj_pool_t *pool, pj_ssl_cert_info *ci, 
     492                          const CX509Certificate *x) 
     493{ 
     494    unsigned len; 
     495     
     496    pj_assert(pool && ci && x); 
     497     
     498    pj_bzero(ci, sizeof(*ci)); 
     499     
     500    /* Version */ 
     501    ci->version = x->Version(); 
     502     
     503    /* Serial number */ 
     504    len = x->SerialNumber().Length(); 
     505    if (len > sizeof(ci->serial_no))  
     506        len = sizeof(ci->serial_no); 
     507    pj_memcpy(ci->serial_no + sizeof(ci->serial_no) - len,  
     508              x->SerialNumber().Ptr(), len); 
     509     
     510    /* Subject */ 
     511    { 
     512        HBufC *subject = NULL; 
     513        TRAPD(err, subject = x->SubjectL()); 
     514        if (err == KErrNone) { 
     515            TPtr16 ptr16(subject->Des()); 
     516            len = ptr16.Length(); 
     517            TPtr8 ptr8((TUint8*)pj_pool_alloc(pool, len), len); 
     518            ptr8.Copy(ptr16); 
     519            pj_strset(&ci->subject.cn, (char*)ptr8.Ptr(), ptr8.Length()); 
     520        } 
     521        ci->subject.info = get_cert_name(pool, x->SubjectName()); 
     522    } 
     523 
     524    /* Issuer */ 
     525    { 
     526        HBufC *issuer = NULL; 
     527        TRAPD(err, issuer = x->IssuerL()); 
     528        if (err == KErrNone) { 
     529            TPtr16 ptr16(issuer->Des()); 
     530            len = ptr16.Length(); 
     531            TPtr8 ptr8((TUint8*)pj_pool_alloc(pool, len), len); 
     532            ptr8.Copy(ptr16); 
     533            pj_strset(&ci->issuer.cn, (char*)ptr8.Ptr(), ptr8.Length()); 
     534        } 
     535        ci->issuer.info = get_cert_name(pool, x->IssuerName()); 
     536    } 
     537     
     538    /* Validity */ 
     539    const CValidityPeriod &valid_period = x->ValidityPeriod(); 
     540    TTime base_time(TDateTime(1970, EJanuary, 0, 0, 0, 0, 0)); 
     541    TTimeIntervalSeconds tmp_sec; 
     542    valid_period.Start().SecondsFrom(base_time, tmp_sec); 
     543    ci->validity.start.sec = tmp_sec.Int();  
     544    valid_period.Finish().SecondsFrom(base_time, tmp_sec); 
     545    ci->validity.end.sec = tmp_sec.Int(); 
     546} 
     547 
     548 
     549/* Update certificates info. This function should be called after handshake 
     550 * or renegotiation successfully completed. 
     551 */ 
     552static void update_certs_info(pj_ssl_sock_t *ssock) 
     553{ 
     554    const CX509Certificate *x; 
     555 
     556    pj_assert(ssock && ssock->sock && 
     557              ssock->sock->GetState() == CPjSSLSocket::SSL_STATE_ESTABLISHED); 
     558         
     559    /* Active remote certificate */ 
     560    x = ssock->sock->GetPeerCert(); 
     561    if (x) { 
     562        get_cert_info(ssock->pool, &ssock->remote_cert_info, x); 
     563    } else { 
     564        pj_bzero(&ssock->remote_cert_info, sizeof(pj_ssl_cert_info)); 
     565    } 
     566} 
    438567 
    439568 
     
    505634     
    506635    /* Init secure socket */ 
     636    ssock->pool = pool; 
    507637    ssock->sock_af = param->sock_af; 
    508638    ssock->sock_type = param->sock_type; 
     
    644774        /* Remote address */ 
    645775        pj_sockaddr_cp((pj_sockaddr_t*)&info->remote_addr,  
    646                    (pj_sockaddr_t*)&ssock->rem_addr); 
     776                       (pj_sockaddr_t*)&ssock->rem_addr); 
     777         
     778        /* Certificates info */ 
     779        info->remote_cert_info = &ssock->remote_cert_info; 
    647780    } 
    648781 
     
    729862        status = reader->Read(&read_cb, ssock, *ssock->read_state.read_buf,  
    730863                              ssock->read_state.flags); 
    731         if (status != PJ_EPENDING) { 
    732             /* Notify error */ 
    733             (*ssock->cb.on_data_read)(ssock, NULL, 0, status, NULL); 
    734         } 
    735     } 
    736      
     864    } 
     865     
     866    /* Connection closed or something goes wrong */ 
    737867    if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
    738         /* Connection closed or something goes wrong */ 
     868        /* Notify error */ 
     869        if (ssock->cb.on_data_read) { 
     870            pj_bool_t ret = (*ssock->cb.on_data_read)(ssock, NULL, 0,  
     871                                                      status, NULL); 
     872            if (!ret) { 
     873                /* We've been destroyed */ 
     874                return; 
     875            } 
     876        } 
     877         
    739878        delete ssock->read_state.read_buf; 
    740879        delete ssock->read_state.orig_buf; 
     
    10021141    if (status == PJ_SUCCESS) { 
    10031142        ssock->established = PJ_TRUE; 
     1143        update_certs_info(ssock); 
    10041144    } else { 
    10051145        delete ssock->sock; 
  • pjproject/trunk/pjlib/src/pjlib-test/ssl_sock.c

    r3018 r3106  
    2323 
    2424#define CERT_DIR                    "../build/" 
    25 #define CERT_CA_FILE                NULL 
     25#define CERT_CA_FILE                CERT_DIR "cacert.pem" 
    2626#define CERT_FILE                   CERT_DIR "cacert.pem" 
    2727#define CERT_PRIVKEY_FILE           CERT_DIR "privkey.pem" 
     
    8484}; 
    8585 
    86 static void dump_cert_info(const char *prefix, const pj_ssl_cert_info *ci) 
     86static void dump_ssl_info(const pj_ssl_sock_info *si) 
    8787{ 
    88     const char *wdays[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; 
    89     pj_parsed_time pt1; 
    90     pj_parsed_time pt2; 
    91  
    92     pj_time_decode(&ci->validity_start, &pt1); 
    93     pj_time_decode(&ci->validity_end, &pt2); 
    94  
    95     PJ_LOG(3, ("", "%sSubject    : %.*s", prefix, ci->subject.slen, ci->subject.ptr)); 
    96     PJ_LOG(3, ("", "%sIssuer     : %.*s", prefix, ci->issuer.slen, ci->issuer.ptr)); 
    97     PJ_LOG(3, ("", "%sVersion    : v%d", prefix, ci->version)); 
    98     PJ_LOG(3, ("", "%sValid from : %s %4d-%02d-%02d %02d:%02d:%02d.%03d %s",  
    99                    prefix, wdays[pt1.wday], pt1.year, pt1.mon+1, pt1.day, 
    100                    pt1.hour, pt1.min, pt1.sec, pt1.msec, 
    101                    (ci->validity_use_gmt? "GMT":""))); 
    102     PJ_LOG(3, ("", "%sValid to   : %s %4d-%02d-%02d %02d:%02d:%02d.%03d %s",  
    103                    prefix, wdays[pt2.wday], pt2.year, pt2.mon+1, pt2.day, 
    104                    pt2.hour, pt2.min, pt2.sec, pt2.msec, 
    105                    (ci->validity_use_gmt? "GMT":""))); 
     88    const char *tmp_st; 
     89 
     90    /* Print cipher name */ 
     91    tmp_st = pj_ssl_cipher_name(si->cipher); 
     92    if (tmp_st == NULL) 
     93        tmp_st = "[Unknown]"; 
     94    PJ_LOG(3, ("", ".....Cipher: %s", tmp_st)); 
     95 
     96    /* Print remote certificate info and verification result */ 
     97    if (si->remote_cert_info && si->remote_cert_info->subject.info.slen)  
     98    { 
     99        char buf[2048]; 
     100        const char *verif_msgs[32]; 
     101        unsigned verif_msg_cnt; 
     102 
     103        /* Dump remote TLS certificate info */ 
     104        PJ_LOG(3, ("", ".....Remote certificate info:")); 
     105        pj_ssl_cert_info_dump(si->remote_cert_info, "  ", buf, sizeof(buf)); 
     106        PJ_LOG(3,("", "\n%s", buf)); 
     107 
     108        /* Dump remote TLS certificate verification result */ 
     109        verif_msg_cnt = PJ_ARRAY_SIZE(verif_msgs); 
     110        pj_ssl_cert_verify_error_st(si->verify_status, 
     111                                    verif_msgs, &verif_msg_cnt); 
     112        PJ_LOG(3,("", ".....Remote certificate verification result: %s", 
     113                  (verif_msg_cnt == 1? verif_msgs[0]:""))); 
     114        if (verif_msg_cnt > 1) { 
     115            unsigned i; 
     116            for (i = 0; i < verif_msg_cnt; ++i) 
     117                PJ_LOG(3,("", "..... - %s", verif_msgs[i])); 
     118        } 
     119    } 
    106120} 
    107121 
     
    131145    PJ_LOG(3, ("", "...Connected %s -> %s!", buf1, buf2)); 
    132146 
    133     if (st->is_verbose) { 
    134         const char *tmp_st; 
    135  
    136         /* Print cipher name */ 
    137         tmp_st = pj_ssl_cipher_name(info.cipher); 
    138         if (tmp_st == NULL) 
    139             tmp_st = "[Unknown]"; 
    140         PJ_LOG(3, ("", ".....Cipher: %s", tmp_st)); 
    141  
    142         /* Print certificates info */ 
    143         if (info.local_cert_info.subject.slen) { 
    144             PJ_LOG(3, ("", ".....Local certificate info:")); 
    145             dump_cert_info(".......", &info.local_cert_info); 
    146         } 
    147         if (info.remote_cert_info.subject.slen) { 
    148             PJ_LOG(3, ("", ".....Remote certificate info:")); 
    149             dump_cert_info(".......", &info.remote_cert_info); 
    150         } 
    151     } 
     147    if (st->is_verbose) 
     148        dump_ssl_info(&info); 
    152149 
    153150    /* Start reading data */ 
     
    199196    struct test_state *st; 
    200197    void *read_buf[1]; 
     198    pj_ssl_sock_info info; 
     199    char buf[64]; 
    201200    pj_status_t status; 
    202201 
     
    208207    pj_ssl_sock_set_user_data(newsock, st); 
    209208 
    210     if (st->is_verbose) { 
    211         pj_ssl_sock_info info; 
    212         char buf[64]; 
    213         const char *tmp_st; 
    214  
    215         status = pj_ssl_sock_get_info(newsock, &info); 
    216         if (status != PJ_SUCCESS) { 
    217             app_perror("...ERROR pj_ssl_sock_get_info()", status); 
    218             goto on_return; 
    219         } 
    220  
    221         pj_sockaddr_print(src_addr, buf, sizeof(buf), 1); 
    222         PJ_LOG(3, ("", "...Accepted connection from %s", buf)); 
    223  
    224         /* Print cipher name */ 
    225         tmp_st = pj_ssl_cipher_name(info.cipher); 
    226         if (tmp_st == NULL) 
    227             tmp_st = "[Unknown]"; 
    228         PJ_LOG(3, ("", ".....Cipher: %s", tmp_st)); 
    229  
    230         /* Print certificates info */ 
    231         if (info.local_cert_info.subject.slen) { 
    232             PJ_LOG(3, ("", ".....Local certificate info:")); 
    233             dump_cert_info(".......", &info.local_cert_info); 
    234         } 
    235         if (info.remote_cert_info.subject.slen) { 
    236             PJ_LOG(3, ("", ".....Remote certificate info:")); 
    237             dump_cert_info(".......", &info.remote_cert_info); 
    238         } 
    239     } 
     209    status = pj_ssl_sock_get_info(newsock, &info); 
     210    if (status != PJ_SUCCESS) { 
     211        app_perror("...ERROR pj_ssl_sock_get_info()", status); 
     212        goto on_return; 
     213    } 
     214 
     215    pj_sockaddr_print(src_addr, buf, sizeof(buf), 1); 
     216    PJ_LOG(3, ("", "...Accepted connection from %s", buf)); 
     217 
     218    if (st->is_verbose) 
     219        dump_ssl_info(&info); 
    240220 
    241221    /* Start reading data */ 
     
    461441    param.timeout.sec = 0; 
    462442    param.timeout.msec = ms_timeout; 
     443    param.proto = PJ_SSL_SOCK_PROTO_SSL23; 
    463444    pj_time_val_normalize(&param.timeout); 
    464445 
     
    513494 
    514495static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto, 
    515                      pj_ssl_cipher srv_cipher, pj_ssl_cipher cli_cipher) 
     496                     pj_ssl_cipher srv_cipher, pj_ssl_cipher cli_cipher, 
     497                     pj_bool_t req_client_cert, pj_bool_t client_provide_cert) 
    516498{ 
    517499    pj_pool_t *pool = NULL; 
     
    534516    } 
    535517 
    536     /* Set cert */ 
     518    pj_ssl_sock_param_default(&param); 
     519    param.cb.on_accept_complete = &ssl_on_accept_complete; 
     520    param.cb.on_connect_complete = &ssl_on_connect_complete; 
     521    param.cb.on_data_read = &ssl_on_data_read; 
     522    param.cb.on_data_sent = &ssl_on_data_sent; 
     523    param.ioqueue = ioqueue; 
     524    param.ciphers = ciphers; 
     525 
     526    /* Init default bind address */ 
     527    { 
     528        pj_str_t tmp_st; 
     529        pj_sockaddr_init(PJ_AF_INET, &addr, pj_strset2(&tmp_st, "127.0.0.1"), 0); 
     530    } 
     531 
     532    /* === SERVER === */ 
     533    param.proto = srv_proto; 
     534    param.user_data = &state_serv; 
     535    param.ciphers_num = (srv_cipher == -1)? 0 : 1; 
     536    param.require_client_cert = req_client_cert; 
     537    ciphers[0] = srv_cipher; 
     538 
     539    state_serv.pool = pool; 
     540    state_serv.echo = PJ_TRUE; 
     541    state_serv.is_server = PJ_TRUE; 
     542    state_serv.is_verbose = PJ_TRUE; 
     543 
     544    status = pj_ssl_sock_create(pool, &param, &ssock_serv); 
     545    if (status != PJ_SUCCESS) { 
     546        goto on_return; 
     547    } 
     548 
     549    /* Set server cert */ 
    537550    { 
    538551        pj_str_t tmp1, tmp2, tmp3, tmp4; 
     
    547560            goto on_return; 
    548561        } 
    549     } 
    550  
    551     pj_ssl_sock_param_default(&param); 
    552     param.cb.on_accept_complete = &ssl_on_accept_complete; 
    553     param.cb.on_connect_complete = &ssl_on_connect_complete; 
    554     param.cb.on_data_read = &ssl_on_data_read; 
    555     param.cb.on_data_sent = &ssl_on_data_sent; 
    556     param.ioqueue = ioqueue; 
    557     param.ciphers = ciphers; 
    558  
    559     /* Init default bind address */ 
    560     { 
    561         pj_str_t tmp_st; 
    562         pj_sockaddr_init(PJ_AF_INET, &addr, pj_strset2(&tmp_st, "127.0.0.1"), 0); 
    563     } 
    564  
    565     /* SERVER */ 
    566     param.proto = srv_proto; 
    567     param.user_data = &state_serv; 
    568     param.ciphers_num = (srv_cipher == -1)? 0 : 1; 
    569     ciphers[0] = srv_cipher; 
    570  
    571     state_serv.pool = pool; 
    572     state_serv.echo = PJ_TRUE; 
    573     state_serv.is_server = PJ_TRUE; 
    574     state_serv.is_verbose = PJ_TRUE; 
    575  
    576     status = pj_ssl_sock_create(pool, &param, &ssock_serv); 
    577     if (status != PJ_SUCCESS) { 
    578         goto on_return; 
    579     } 
    580  
    581     status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert); 
    582     if (status != PJ_SUCCESS) { 
    583         goto on_return; 
     562 
     563        status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert); 
     564        if (status != PJ_SUCCESS) { 
     565            goto on_return; 
     566        } 
    584567    } 
    585568 
     
    597580    } 
    598581 
    599     /* CLIENT */ 
     582    /* === CLIENT === */ 
    600583    param.proto = cli_proto; 
    601584    param.user_data = &state_cli; 
     
    624607    if (status != PJ_SUCCESS) { 
    625608        goto on_return; 
     609    } 
     610 
     611    /* Set cert for client */ 
     612    { 
     613 
     614        if (!client_provide_cert) { 
     615            pj_str_t tmp1, tmp2; 
     616 
     617            pj_strset2(&tmp1, (char*)CERT_CA_FILE); 
     618            pj_strset2(&tmp2, NULL); 
     619            status = pj_ssl_cert_load_from_files(pool,  
     620                                                 &tmp1, &tmp2, &tmp2, &tmp2, 
     621                                                 &cert); 
     622            if (status != PJ_SUCCESS) { 
     623                goto on_return; 
     624            } 
     625        } 
     626 
     627        status = pj_ssl_sock_set_certificate(ssock_cli, pool, cert); 
     628        if (status != PJ_SUCCESS) { 
     629            goto on_return; 
     630        } 
    626631    } 
    627632 
     
    10141019    state_cli = pj_pool_calloc(pool, clients, sizeof(struct test_state)); 
    10151020 
     1021    /* Get start timestamp */ 
     1022    pj_gettimeofday(&start); 
     1023 
    10161024    /* Setup clients */ 
    10171025    for (i = 0; i < clients; ++i) { 
     
    10651073    } 
    10661074 
    1067     /* Get start timestamp */ 
    1068     pj_gettimeofday(&start); 
    1069  
    10701075    /* Wait until everything has been sent/received or error */ 
    10711076    while (clients_num) 
     
    11511156    PJ_LOG(3,("", "..echo test w/ TLSv1 and TLS_RSA_WITH_DES_CBC_SHA cipher")); 
    11521157    ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1, PJ_SSL_SOCK_PROTO_TLS1,  
    1153                     TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA); 
     1158                    TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA,  
     1159                    PJ_FALSE, PJ_FALSE); 
    11541160    if (ret != 0) 
    11551161        return ret; 
     
    11571163    PJ_LOG(3,("", "..echo test w/ SSLv23 and TLS_RSA_WITH_AES_256_CBC_SHA cipher")); 
    11581164    ret = echo_test(PJ_SSL_SOCK_PROTO_SSL23, PJ_SSL_SOCK_PROTO_SSL23,  
    1159                     TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA); 
     1165                    TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, 
     1166                    PJ_FALSE, PJ_FALSE); 
    11601167    if (ret != 0) 
    11611168        return ret; 
     
    11631170    PJ_LOG(3,("", "..echo test w/ incompatible proto")); 
    11641171    ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1, PJ_SSL_SOCK_PROTO_SSL3,  
    1165                     TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA); 
     1172                    TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA, 
     1173                    PJ_FALSE, PJ_FALSE); 
    11661174    if (ret == 0) 
    11671175        return PJ_EBUG; 
     
    11691177    PJ_LOG(3,("", "..echo test w/ incompatible ciphers")); 
    11701178    ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT,  
    1171                     TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA); 
     1179                    TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, 
     1180                    PJ_FALSE, PJ_FALSE); 
    11721181    if (ret == 0) 
    11731182        return PJ_EBUG; 
     1183 
     1184    PJ_LOG(3,("", "..echo test w/ client cert required but not provided")); 
     1185    ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT,  
     1186                    TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, 
     1187                    PJ_TRUE, PJ_FALSE); 
     1188    if (ret == 0) 
     1189        return PJ_EBUG; 
     1190 
     1191    PJ_LOG(3,("", "..echo test w/ client cert required and provided")); 
     1192    ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT,  
     1193                    TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, 
     1194                    PJ_TRUE, PJ_TRUE); 
     1195    if (ret != 0) 
     1196        return ret; 
    11741197 
    11751198    PJ_LOG(3,("", "..client non-SSL (handshake timeout 5 secs)")); 
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c

    r3093 r3106  
    27892789 
    27902790/* 
     2791 * Transport status notification 
     2792 */ 
     2793static pj_bool_t on_transport_state(pjsip_transport *tp, pj_uint32_t state, 
     2794                                    const pjsip_transport_state_info *info) 
     2795{ 
     2796    char host_port[128]; 
     2797 
     2798    pj_ansi_snprintf(host_port, sizeof(host_port), "[%.*s:%d]", 
     2799                     (int)tp->remote_name.host.slen, 
     2800                     tp->remote_name.host.ptr, 
     2801                     tp->remote_name.port); 
     2802 
     2803    if (state & PJSIP_TP_STATE_CONNECTED) { 
     2804        PJ_LOG(3,(THIS_FILE, "SIP transport %s is connected to %s",  
     2805                 tp->type_name, host_port)); 
     2806    }  
     2807    else if (state & PJSIP_TP_STATE_ACCEPTED) { 
     2808        PJ_LOG(3,(THIS_FILE, "SIP transport %s accepted %s", 
     2809                 tp->type_name, host_port)); 
     2810    }  
     2811    else if (state & PJSIP_TP_STATE_DISCONNECTED) { 
     2812        char buf[100]; 
     2813 
     2814        snprintf(buf, sizeof(buf), "SIP transport %s is disconnected from %s", 
     2815                 tp->type_name, host_port); 
     2816        pjsua_perror(THIS_FILE, buf, info->status); 
     2817    } 
     2818    else if (state & PJSIP_TP_STATE_REJECTED) { 
     2819        char buf[100]; 
     2820 
     2821        snprintf(buf, sizeof(buf), "SIP transport %s rejected %s", 
     2822                 tp->type_name, host_port); 
     2823        pjsua_perror(THIS_FILE, buf, info->status); 
     2824    } 
     2825 
     2826#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0 
     2827 
     2828    if (!pj_ansi_stricmp(tp->type_name, "tls") && info->ext_info && 
     2829        (state == PJSIP_TP_STATE_CONNECTED ||  
     2830         (state & PJSIP_TP_STATE_TLS_VERIF_ERROR))) 
     2831    { 
     2832        pjsip_tls_state_info *tls_info = (pjsip_tls_state_info*)info->ext_info; 
     2833        pj_ssl_sock_info *ssl_sock_info = (pj_ssl_sock_info*) 
     2834                                          tls_info->ssl_sock_info; 
     2835        char buf[2048]; 
     2836        const char *verif_msgs[32]; 
     2837        unsigned verif_msg_cnt; 
     2838 
     2839        /* Dump server TLS certificate */ 
     2840        pj_ssl_cert_info_dump(ssl_sock_info->remote_cert_info, "  ", 
     2841                              buf, sizeof(buf)); 
     2842        PJ_LOG(4,(THIS_FILE, "TLS cert info of %s:\n%s", host_port, buf)); 
     2843 
     2844        /* Dump server TLS certificate verification result */ 
     2845        verif_msg_cnt = PJ_ARRAY_SIZE(verif_msgs); 
     2846        pj_ssl_cert_verify_error_st(ssl_sock_info->verify_status, 
     2847                                    verif_msgs, &verif_msg_cnt); 
     2848        PJ_LOG(3,(THIS_FILE, "TLS cert verification result of %s : %s", 
     2849                             host_port, 
     2850                             (verif_msg_cnt == 1? verif_msgs[0]:""))); 
     2851        if (verif_msg_cnt > 1) { 
     2852            unsigned i; 
     2853            for (i = 0; i < verif_msg_cnt; ++i) 
     2854                PJ_LOG(3,(THIS_FILE, "- %s", verif_msgs[i])); 
     2855        } 
     2856 
     2857        if (state & PJSIP_TP_STATE_TLS_VERIF_ERROR &&  
     2858            !app_config.udp_cfg.tls_setting.verify_server)  
     2859        { 
     2860            PJ_LOG(3,(THIS_FILE, "PJSUA is configured to ignore TLS cert " 
     2861                                 "verification errors")); 
     2862        } 
     2863    } 
     2864 
     2865#endif 
     2866    return PJ_TRUE; 
     2867} 
     2868 
     2869/* 
    27912870 * Print buddy list. 
    27922871 */ 
     
    43844463    app_config.cfg.cb.on_nat_detect = &on_nat_detect; 
    43854464    app_config.cfg.cb.on_mwi_info = &on_mwi_info; 
     4465    app_config.cfg.cb.on_transport_state = &on_transport_state; 
    43864466 
    43874467    /* Set sound device latency */ 
  • pjproject/trunk/pjsip-apps/src/symbian_ua/ua.cpp

    r2999 r3106  
    271271} 
    272272 
     273/* 
     274 * Transport status notification 
     275 */ 
     276static pj_bool_t on_transport_state(pjsip_transport *tp, pj_uint32_t state, 
     277                                    const pjsip_transport_state_info *info) 
     278{ 
     279    char host_port[128]; 
     280 
     281    pj_ansi_snprintf(host_port, sizeof(host_port), "[%.*s:%d]", 
     282                     (int)tp->remote_name.host.slen, 
     283                     tp->remote_name.host.ptr, 
     284                     tp->remote_name.port); 
     285 
     286    if (state & PJSIP_TP_STATE_CONNECTED) { 
     287        PJ_LOG(3,(THIS_FILE, "SIP transport %s is connected to %s",  
     288                 tp->type_name, host_port)); 
     289    }  
     290    else if (state & PJSIP_TP_STATE_ACCEPTED) { 
     291        PJ_LOG(3,(THIS_FILE, "SIP transport %s accepted %s", 
     292                 tp->type_name, host_port)); 
     293    }  
     294    else if (state & PJSIP_TP_STATE_DISCONNECTED) { 
     295        char buf[100]; 
     296 
     297        snprintf(buf, sizeof(buf), "SIP transport %s is disconnected from %s", 
     298                 tp->type_name, host_port); 
     299        pjsua_perror(THIS_FILE, buf, info->status); 
     300    } 
     301    else if (state & PJSIP_TP_STATE_REJECTED) { 
     302        char buf[100]; 
     303 
     304        snprintf(buf, sizeof(buf), "SIP transport %s rejected %s", 
     305                 tp->type_name, host_port); 
     306        pjsua_perror(THIS_FILE, buf, info->status); 
     307    } 
     308 
     309#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0 
     310 
     311    if (!pj_ansi_stricmp(tp->type_name, "tls") && info->ext_info && 
     312        (state == PJSIP_TP_STATE_CONNECTED ||  
     313         (state & PJSIP_TP_STATE_TLS_VERIF_ERROR))) 
     314    { 
     315        pjsip_tls_state_info *tls_info = (pjsip_tls_state_info*)info->ext_info; 
     316        pj_ssl_sock_info *ssl_sock_info = (pj_ssl_sock_info*) 
     317                                          tls_info->ssl_sock_info; 
     318        char buf[2048]; 
     319 
     320        /* Dump server TLS certificate */ 
     321        pj_ssl_cert_info_dump(ssl_sock_info->remote_cert_info, "  ", 
     322                              buf, sizeof(buf)); 
     323        PJ_LOG(4,(THIS_FILE, "TLS cert info of %s:\n%s", host_port, buf)); 
     324    } 
     325 
     326#endif 
     327    return PJ_TRUE; 
     328} 
     329 
    273330 
    274331//#include<e32debug.h> 
     
    331388    cfg.cb.on_call_replaced = &on_call_replaced; 
    332389    cfg.cb.on_nat_detect = &on_nat_detect; 
     390    cfg.cb.on_transport_state = &on_transport_state; 
    333391     
    334392    if (SIP_PROXY) { 
     
    10551113     
    10561114    // Initialize RSocketServ 
    1057     if ((err=aSocketServer.Connect()) != KErrNone) 
     1115    if ((err=aSocketServer.Connect(32)) != KErrNone) 
    10581116        return PJ_STATUS_FROM_OS(err); 
    10591117     
  • pjproject/trunk/pjsip-apps/src/symbian_ua_gui/group/symbian_ua_gui.mmp

    r2821 r3106  
    4242LIBRARY                 ecom.lib inetprotutil.lib http.lib esock.lib 
    4343LIBRARY                 charconv.lib estlib.lib  
     44LIBRARY                 securesocket.lib x509.lib crypto.lib x500.lib 
    4445 
    4546// Ordering static libs based on dependencies, most to least dependent, 
  • pjproject/trunk/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp

    r2394 r3106  
    264264     
    265265    // Initialize RSocketServ 
    266     if ((err=aSocketServer.Connect()) != KErrNone) 
     266    if ((err=aSocketServer.Connect(32)) != KErrNone) 
    267267        return PJ_STATUS_FROM_OS(err); 
    268268     
  • pjproject/trunk/pjsip/include/pjsip/sip_endpoint.h

    r2394 r3106  
    373373 
    374374 
     375/** 
     376 * Find a SIP transport suitable for sending SIP message to the specified 
     377 * address by also considering the outgoing SIP message data. If transport  
     378 * selector ("sel") is set, then the function will check if the transport  
     379 * selected is suitable to send requests to the specified address. 
     380 * 
     381 * @see pjsip_tpmgr_acquire_transport 
     382 * 
     383 * @param endpt     The SIP endpoint instance. 
     384 * @param type      The type of transport to be acquired. 
     385 * @param remote    The remote address to send message to. 
     386 * @param addr_len  Length of the remote address. 
     387 * @param sel       Optional pointer to transport selector instance which is 
     388 *                  used to find explicit transport, if required. 
     389 * @param tdata     Optional pointer to SIP message data to be sent. 
     390 * @param p_tp      Pointer to receive the transport instance, if one is found. 
     391 * 
     392 * @return          PJ_SUCCESS on success, or the appropriate error code. 
     393 */ 
     394PJ_DECL(pj_status_t)  
     395pjsip_endpt_acquire_transport2(pjsip_endpoint *endpt, 
     396                               pjsip_transport_type_e type, 
     397                               const pj_sockaddr_t *remote, 
     398                               int addr_len, 
     399                               const pjsip_tpselector *sel, 
     400                               pjsip_tx_data *tdata, 
     401                               pjsip_transport **p_tp); 
     402 
     403 
    375404/***************************************************************************** 
    376405 * 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport.h

    r3077 r3106  
    541541    struct 
    542542    { 
     543        /** Server name.  
     544         */ 
     545        pj_str_t                 name; 
     546 
    543547        /** Server addresses resolved.  
    544548         */ 
     
    688692     */ 
    689693    long                    type; 
     694 
     695    /** 
     696     * Hash of host name. 
     697     */ 
     698    pj_uint32_t             hname; 
    690699 
    691700    /** 
     
    919928 
    920929    /** 
    921      * Create new outbound connection. 
     930     * Create new outbound connection suitable for sending SIP message 
     931     * to specified remote address. 
    922932     * Note that the factory is responsible for both creating the 
    923933     * transport and registering it to the transport manager. 
     
    929939                                    int addr_len, 
    930940                                    pjsip_transport **transport); 
     941 
     942    /** 
     943     * Create new outbound connection suitable for sending SIP message 
     944     * to specified remote address by also considering outgoing SIP  
     945     * message data. 
     946     * Note that the factory is responsible for both creating the 
     947     * transport and registering it to the transport manager. 
     948     */ 
     949    pj_status_t (*create_transport2)(pjsip_tpfactory *factory, 
     950                                     pjsip_tpmgr *mgr, 
     951                                     pjsip_endpoint *endpt, 
     952                                     const pj_sockaddr *rem_addr, 
     953                                     int addr_len, 
     954                                     pjsip_tx_data *tdata, 
     955                                     pjsip_transport **transport); 
    931956 
    932957    /** 
     
    10991124                                                   const pjsip_tpselector *sel, 
    11001125                                                   pjsip_transport **tp); 
     1126 
     1127/** 
     1128 * Find suitable transport for sending SIP message to specified remote  
     1129 * destination by also considering the outgoing SIP message. If no suitable  
     1130 * transport is found, a new one will be created. 
     1131 * 
     1132 * This is an internal function since normally application doesn't have access 
     1133 * to transport manager. Application should use pjsip_endpt_acquire_transport() 
     1134 * instead. 
     1135 * 
     1136 * @param mgr       The transport manager instance. 
     1137 * @param type      The type of transport to be acquired. 
     1138 * @param remote    The remote address to send message to. 
     1139 * @param addr_len  Length of the remote address. 
     1140 * @param sel       Optional pointer to transport selector instance which is 
     1141 *                  used to find explicit transport, if required. 
     1142 * @param tdata     Optional pointer to data to be sent. 
     1143 * @param tp        Pointer to receive the transport instance, if one is found. 
     1144 * 
     1145 * @return          PJ_SUCCESS on success, or the appropriate error code. 
     1146 */ 
     1147PJ_DECL(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr, 
     1148                                                    pjsip_transport_type_e type, 
     1149                                                    const pj_sockaddr_t *remote, 
     1150                                                    int addr_len, 
     1151                                                    const pjsip_tpselector *sel, 
     1152                                                    pjsip_tx_data *tdata, 
     1153                                                    pjsip_transport **tp); 
    11011154 
    11021155/** 
     
    11881241                                          pjsip_tp_send_callback cb); 
    11891242 
     1243 
     1244/** 
     1245 * Enumeration of transport state types. 
     1246 */ 
     1247typedef enum pjsip_transport_state_type { 
     1248 
     1249    /** Transport connected.    */ 
     1250    PJSIP_TP_STATE_CONNECTED        = (1 << 0), 
     1251 
     1252    /** Transport accepted.     */ 
     1253    PJSIP_TP_STATE_ACCEPTED         = (1 << 1), 
     1254 
     1255    /** Transport disconnected. */ 
     1256    PJSIP_TP_STATE_DISCONNECTED     = (1 << 2), 
     1257 
     1258    /** Incoming connection rejected.   */ 
     1259    PJSIP_TP_STATE_REJECTED         = (1 << 3), 
     1260 
     1261    /** TLS verification error. */ 
     1262    PJSIP_TP_STATE_TLS_VERIF_ERROR  = (1 << 8) 
     1263 
     1264} pjsip_transport_state_type; 
     1265 
     1266 
     1267/** 
     1268 * Structure of transport state info. 
     1269 */ 
     1270typedef struct pjsip_transport_state_info { 
     1271    /** 
     1272     * The last error code related to the transport state. 
     1273     */ 
     1274    pj_status_t          status; 
     1275     
     1276    /** 
     1277     * Optional extended info, the content is specific for each transport type. 
     1278     */ 
     1279    void                *ext_info; 
     1280} pjsip_transport_state_info; 
     1281 
     1282 
     1283/** 
     1284 * Type of callback to receive transport state notifications, such as 
     1285 * transport connected, disconnected or TLS verification error. 
     1286 * 
     1287 * @param tp            The transport instance. 
     1288 * @param state         The transport state, this may contain single or  
     1289 *                      combination of transport state types defined in 
     1290 *                      #pjsip_transport_state_type. 
     1291 * @param info          The transport state info. 
     1292 * 
     1293 * @return              When TLS verification fails and peer verification in 
     1294 *                      #pjsip_tls_setting is not set, application may return 
     1295 *                      PJ_TRUE to ignore the verification result and continue 
     1296 *                      using the transport. On other cases, this return value 
     1297 *                      is currently not used and will be ignored. 
     1298 */ 
     1299typedef pj_bool_t (*pjsip_tp_state_callback)( 
     1300                                    pjsip_transport *tp, 
     1301                                    pj_uint32_t state, 
     1302                                    const pjsip_transport_state_info *info); 
     1303 
     1304 
     1305/** 
     1306 * Setting callback of transport state notification. The caller will be 
     1307 * notified whenever the state of transport is changed. The type of 
     1308 * events are defined in #pjsip_transport_state_type. 
     1309 *  
     1310 * @param mgr       Transport manager. 
     1311 * @param cb        Callback to be called to notify caller about transport  
     1312 *                  status changing. 
     1313 * 
     1314 * @return          PJ_SUCCESS on success, or the appropriate error code. 
     1315 */ 
     1316PJ_DECL(pj_status_t) pjsip_tpmgr_set_status_cb(pjsip_tpmgr *mgr, 
     1317                                               pjsip_tp_state_callback *cb); 
     1318 
     1319 
     1320/** 
     1321 * Getting the callback of transport state notification. 
     1322 *  
     1323 * @param mgr       Transport manager. 
     1324 * 
     1325 * @return          The transport state callback or NULL if it is not set. 
     1326 */ 
     1327PJ_DECL(pjsip_tp_state_callback*) pjsip_tpmgr_get_status_cb( 
     1328                                               const pjsip_tpmgr *mgr); 
     1329 
     1330 
    11901331/** 
    11911332 * @} 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport_tls.h

    r2998 r3106  
    2727 
    2828#include <pjsip/sip_transport.h> 
     29#include <pj/ssl_sock.h> 
    2930#include <pj/string.h> 
    3031#include <pj/sock_qos.h> 
     
    122123 
    123124    /** 
    124      * When PJSIP is acting as a client (outgoing TLS connections),  
    125      * it will always receive a certificate from the peer.  
    126      * If \a verify_server is disabled (set to zero), PJSIP will not  
    127      * verifiy the certificate and allows TLS connections to servers  
    128      * which do not present a valid certificate.  
    129      * If \a tls_verify_server is non-zero, PJSIP verifies the server  
    130      * certificate and will close the TLS connection if the server  
    131      * certificate is not valid. 
    132      * 
    133      * This setting corresponds to OpenSSL SSL_VERIFY_PEER flag. 
    134      * Default value is zero. 
     125     * Specifies the action when verification of server TLS certificate 
     126     * resulting errors: 
     127     * - If \a verify_server is disabled (set to PJ_FALSE), TLS transport  
     128     *   will just notify the application via #pjsip_tp_state_callback with 
     129     *   state (PJSIP_TP_STATE_CONNECTED | PJSIP_TP_STATE_TLS_VERIF_ERROR) 
     130     *   whenever there is any TLS verification error, the return value of  
     131     *   the callback will be used to decide whether transport should be  
     132     *   shutdown. 
     133     * - If \a verify_server is enabled (set to PJ_TRUE), TLS transport  
     134     *   will be shutdown and application will be notified with state 
     135     *   (PJSIP_TP_STATE_DISCONNECTED | PJSIP_TP_STATE_TLS_VERIF_ERROR) 
     136     *   whenever there is any TLS verification error. 
     137     * 
     138     * When the verification resulting success, application will be notified 
     139     * via #pjsip_tp_state_callback with state PJSIP_TP_STATE_CONNECTED. 
     140     * 
     141     * Default value is PJ_FALSE. 
    135142     */ 
    136143    pj_bool_t   verify_server; 
    137144 
    138145    /** 
    139      * When acting as server (incoming TLS connections), setting 
    140      * \a verify_client to non-zero will cause the transport to activate 
    141      * peer verification upon receiving incoming TLS connection. 
    142      * 
    143      * This setting corresponds to OpenSSL SSL_VERIFY_PEER flag. 
    144      * Default value is zero. 
     146     * Specifies the action when verification of server TLS certificate 
     147     * resulting errors: 
     148     * - If \a verify_client is disabled (set to PJ_FALSE), TLS transport  
     149     *   will just notify the application via #pjsip_tp_state_callback with 
     150     *   state (PJSIP_TP_STATE_ACCEPTED | PJSIP_TP_STATE_TLS_VERIF_ERROR) 
     151     *   whenever there is any TLS verification error, the return value of  
     152     *   the callback will be used to decide whether transport should be  
     153     *   shutdown. 
     154     * - If \a verify_client is enabled (set to PJ_TRUE), TLS transport  
     155     *   will be shutdown and application will be notified with state 
     156     *   (PJSIP_TP_STATE_REJECTED | PJSIP_TP_STATE_TLS_VERIF_ERROR) 
     157     *   whenever there is any TLS verification error. 
     158     * 
     159     * When the verification resulting success, application will be notified 
     160     * via #pjsip_tp_state_callback with state PJSIP_TP_STATE_ACCEPTED. 
     161     * 
     162     * Default value is PJ_FALSE. 
    145163     */ 
    146164    pj_bool_t   verify_client; 
     
    151169     * 
    152170     * This setting corresponds to SSL_VERIFY_FAIL_IF_NO_PEER_CERT flag. 
    153      * Default value is zero. 
     171     * Default value is PJ_FALSE. 
    154172     */ 
    155173    pj_bool_t   require_client_cert; 
     
    189207 
    190208} pjsip_tls_setting; 
     209 
     210 
     211/** 
     212 * This structure defines transport state extended info specifically for 
     213 * TLS transport. 
     214 */ 
     215typedef struct pjsip_tls_state_info 
     216{ 
     217    /** 
     218     * SSL socket info. 
     219     */ 
     220    pj_ssl_sock_info    *ssl_sock_info; 
     221 
     222} pjsip_tls_state_info; 
    191223 
    192224 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r3078 r3106  
    844844    void (*on_mwi_info)(pjsua_acc_id acc_id, pjsua_mwi_info *mwi_info); 
    845845 
     846    /** 
     847     * This callback is called when transport state is changed. See also 
     848     * #pjsip_tp_state_callback. 
     849     * 
     850     * @param tp        The transport instance. 
     851     * @param state     The transport state, this may contain single or  
     852     *                  combination of transport state types defined in 
     853     *                  #pjsip_transport_state_type. 
     854     * @param info      The transport state info. 
     855     * 
     856     * @return          When TLS verification fails and peer verification in 
     857     *                  #pjsip_tls_setting is not set, application may return 
     858     *                  PJ_TRUE to ignore the verification result and continue 
     859     *                  using the transport. On other cases, this return value 
     860     *                  is currently not used and will be ignored. 
     861     */ 
     862    pj_bool_t (*on_transport_state)(pjsip_transport *tp, pj_uint32_t state, 
     863                                    const pjsip_transport_state_info *info); 
     864 
    846865} pjsua_callback; 
    847866 
  • pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c

    r2394 r3106  
    10761076 
    10771077/* 
     1078 * Find/create transport. 
     1079 */ 
     1080PJ_DEF(pj_status_t) pjsip_endpt_acquire_transport2(pjsip_endpoint *endpt, 
     1081                                                   pjsip_transport_type_e type, 
     1082                                                   const pj_sockaddr_t *remote, 
     1083                                                   int addr_len, 
     1084                                                   const pjsip_tpselector *sel, 
     1085                                                   pjsip_tx_data *tdata, 
     1086                                                   pjsip_transport **transport) 
     1087{ 
     1088    return pjsip_tpmgr_acquire_transport2(endpt->transport_mgr, type, remote,  
     1089                                          addr_len, sel, tdata, transport); 
     1090} 
     1091 
     1092 
     1093/* 
    10781094 * Report error. 
    10791095 */ 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport.c

    r3077 r3106  
    9090    void           (*on_rx_msg)(pjsip_endpoint*, pj_status_t, pjsip_rx_data*); 
    9191    pj_status_t    (*on_tx_msg)(pjsip_endpoint*, pjsip_tx_data*); 
     92    pjsip_tp_state_callback *tp_state_cb; 
     93    void *tp_state_user_data; 
    9294}; 
    9395 
     
    865867     * Register to hash table (see Trac ticket #42). 
    866868     */ 
    867     key_len = sizeof(tp->key.type) + tp->addr_len; 
     869    key_len = sizeof(tp->key.type) + sizeof(tp->key.hname) + tp->addr_len; 
    868870    pj_lock_acquire(mgr->lock); 
    869871 
     
    915917     * Unregister from hash table (see Trac ticket #42). 
    916918     */ 
    917     key_len = sizeof(tp->key.type) + tp->addr_len; 
     919    key_len = sizeof(tp->key.type) + sizeof(tp->key.hname) + tp->addr_len; 
    918920    hval = 0; 
    919921    entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval); 
     
    15031505                                                  pjsip_transport **tp) 
    15041506{ 
     1507    return pjsip_tpmgr_acquire_transport2(mgr, type, remote, addr_len, sel, 
     1508                                          NULL, tp); 
     1509} 
     1510 
     1511/* 
     1512 * pjsip_tpmgr_acquire_transport2() 
     1513 * 
     1514 * Get transport suitable to communicate to remote. Create a new one 
     1515 * if necessary. 
     1516 */ 
     1517PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr, 
     1518                                                   pjsip_transport_type_e type, 
     1519                                                   const pj_sockaddr_t *remote, 
     1520                                                   int addr_len, 
     1521                                                   const pjsip_tpselector *sel, 
     1522                                                   pjsip_tx_data *tdata, 
     1523                                                   pjsip_transport **tp) 
     1524{ 
    15051525    pjsip_tpfactory *factory; 
    15061526    pj_status_t status; 
     
    15721592        pjsip_transport *transport; 
    15731593 
     1594        /* 
     1595         * Find factory that can create such transport. 
     1596         */ 
     1597        factory = mgr->factory_list.next; 
     1598        while (factory != &mgr->factory_list) { 
     1599            if (factory->type == type) 
     1600                break; 
     1601            factory = factory->next; 
     1602        } 
     1603        if (factory == &mgr->factory_list) 
     1604            factory = NULL; 
     1605 
    15741606        pj_bzero(&key, sizeof(key)); 
    1575         key_len = sizeof(key.type) + addr_len; 
     1607        key_len = sizeof(key.type) + sizeof(key.hname) + addr_len; 
    15761608 
    15771609        /* First try to get exact destination. */ 
    15781610        key.type = type; 
    15791611        pj_memcpy(&key.rem_addr, remote, addr_len); 
     1612        if (factory && factory->create_transport2 &&  
     1613            tdata && tdata->dest_info.name.slen) 
     1614        { 
     1615            /* Only include hostname hash in the key when the factory support 
     1616             * create_transport2() and tdata is supplied. 
     1617             */ 
     1618            key.hname = pj_hash_calc_tolower(0,  
     1619                                    (char*)tdata->dest_info.name.ptr, 
     1620                                    &tdata->dest_info.name); 
     1621        } 
    15801622 
    15811623        transport = (pjsip_transport*) 
    15821624                    pj_hash_get(mgr->table, &key, key_len, NULL); 
     1625 
    15831626        if (transport == NULL) { 
    15841627            unsigned flag = pjsip_transport_get_flag_from_type(type); 
    15851628            const pj_sockaddr *remote_addr = (const pj_sockaddr*)remote; 
     1629 
    15861630 
    15871631            /* Ignore address for loop transports. */ 
     
    15921636 
    15931637                pj_bzero(addr, addr_len); 
    1594                 key_len = sizeof(key.type) + addr_len; 
     1638                key_len = sizeof(key.type) + sizeof(key.hname) + addr_len; 
    15951639                transport = (pjsip_transport*)  
    15961640                            pj_hash_get(mgr->table, &key, key_len, NULL); 
     
    16051649                addr->addr.sa_family = remote_addr->addr.sa_family; 
    16061650 
    1607                 key_len = sizeof(key.type) + addr_len; 
     1651                key_len = sizeof(key.type) + sizeof(key.hname) + addr_len; 
    16081652                transport = (pjsip_transport*) 
    16091653                            pj_hash_get(mgr->table, &key, key_len, NULL); 
     
    16251669        /* 
    16261670         * Transport not found! 
    1627          * Find factory that can create such transport. 
    16281671         */ 
    1629         factory = mgr->factory_list.next; 
    1630         while (factory != &mgr->factory_list) { 
    1631             if (factory->type == type) 
    1632                 break; 
    1633             factory = factory->next; 
    1634         } 
    1635  
    1636         if (factory == &mgr->factory_list) { 
     1672        if (NULL == factory) { 
    16371673            /* No factory can create the transport! */ 
    16381674            pj_lock_release(mgr->lock); 
     
    16401676            return PJSIP_EUNSUPTRANSPORT; 
    16411677        } 
    1642  
    16431678    } 
    16441679 
     
    16471682 
    16481683    /* Request factory to create transport. */ 
    1649     status = factory->create_transport(factory, mgr, mgr->endpt, 
    1650                                        (const pj_sockaddr*) remote, addr_len, 
    1651                                        tp); 
     1684    if (factory->create_transport2) { 
     1685        status = factory->create_transport2(factory, mgr, mgr->endpt, 
     1686                                            (const pj_sockaddr*) remote,  
     1687                                            addr_len, tdata, tp); 
     1688    } else { 
     1689        status = factory->create_transport(factory, mgr, mgr->endpt, 
     1690                                           (const pj_sockaddr*) remote,  
     1691                                           addr_len, tp); 
     1692    } 
    16521693    if (status == PJ_SUCCESS) { 
    16531694        PJ_ASSERT_ON_FAIL(tp!=NULL,  
     
    17121753} 
    17131754 
     1755PJ_DEF(pj_status_t) pjsip_tpmgr_set_status_cb(pjsip_tpmgr *mgr, 
     1756                                              pjsip_tp_state_callback *cb) 
     1757{ 
     1758    PJ_ASSERT_RETURN(mgr, PJ_EINVAL); 
     1759 
     1760    mgr->tp_state_cb = cb; 
     1761 
     1762    return PJ_SUCCESS; 
     1763} 
     1764 
     1765PJ_DEF(pjsip_tp_state_callback*) pjsip_tpmgr_get_status_cb( 
     1766                                              const pjsip_tpmgr *mgr) 
     1767{ 
     1768    PJ_ASSERT_RETURN(mgr, NULL); 
     1769 
     1770    return mgr->tp_state_cb; 
     1771} 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c

    r3035 r3106  
    166166    host_port->port = pj_sockaddr_get_port(addr); 
    167167} 
     168 
     169 
     170static void tcp_init_shutdown(struct tcp_transport *tcp, pj_status_t status) 
     171{ 
     172    pjsip_tp_state_callback *state_cb; 
     173 
     174    if (tcp->close_reason == PJ_SUCCESS) 
     175        tcp->close_reason = status; 
     176 
     177    if (tcp->base.is_shutdown) 
     178        return; 
     179 
     180    /* Notify application of transport disconnected state */ 
     181    state_cb = pjsip_tpmgr_get_status_cb(tcp->base.tpmgr); 
     182    if (state_cb) { 
     183        pjsip_transport_state_info state_info; 
     184 
     185        pj_bzero(&state_info, sizeof(state_info)); 
     186        state_info.status = tcp->close_reason; 
     187        (*state_cb)(&tcp->base, PJSIP_TP_STATE_DISCONNECTED, &state_info); 
     188    } 
     189 
     190    /* We can not destroy the transport since high level objects may 
     191     * still keep reference to this transport. So we can only  
     192     * instruct transport manager to gracefully start the shutdown 
     193     * procedure for this transport. 
     194     */ 
     195    pjsip_transport_shutdown(&tcp->base); 
     196} 
     197 
    168198 
    169199/* 
     
    922952    struct tcp_transport *tcp; 
    923953    char addr[PJ_INET6_ADDRSTRLEN+10]; 
     954    pjsip_tp_state_callback *state_cb; 
    924955    pj_status_t status; 
    925956 
     
    967998                pj_gettimeofday(&tcp->last_activity); 
    968999            } 
     1000 
     1001            /* Notify application of transport state accepted */ 
     1002            state_cb = pjsip_tpmgr_get_status_cb(tcp->base.tpmgr); 
     1003            if (state_cb) { 
     1004                pjsip_transport_state_info state_info; 
     1005             
     1006                pj_bzero(&state_info, sizeof(state_info)); 
     1007                (*state_cb)(&tcp->base, PJSIP_TP_STATE_ACCEPTED, &state_info); 
     1008            } 
    9691009        } 
    9701010    } 
     
    10141054        status = (bytes_sent == 0) ? PJ_RETURN_OS_ERROR(OSERR_ENOTCONN) : 
    10151055                                     -bytes_sent; 
    1016         if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status; 
    1017         pjsip_transport_shutdown(&tcp->base); 
     1056 
     1057        tcp_init_shutdown(tcp, status); 
    10181058 
    10191059        return PJ_FALSE; 
     
    11101150                if (status == PJ_SUCCESS)  
    11111151                    status = PJ_RETURN_OS_ERROR(OSERR_ENOTCONN); 
    1112                 if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status; 
    1113                 pjsip_transport_shutdown(&tcp->base); 
     1152 
     1153                tcp_init_shutdown(tcp, status); 
    11141154            } 
    11151155        } 
     
    12001240        PJ_LOG(4,(tcp->base.obj_name, "TCP connection closed")); 
    12011241         
    1202         /* We can not destroy the transport since high level objects may 
    1203          * still keep reference to this transport. So we can only  
    1204          * instruct transport manager to gracefully start the shutdown 
    1205          * procedure for this transport. 
    1206          */ 
    1207         if (tcp->close_reason==PJ_SUCCESS)  
    1208             tcp->close_reason = status; 
    1209         pjsip_transport_shutdown(&tcp->base); 
     1242        tcp_init_shutdown(tcp, status); 
    12101243 
    12111244        return PJ_FALSE; 
     
    12291262    pj_sockaddr_in addr; 
    12301263    int addrlen; 
     1264 
     1265    pjsip_tp_state_callback *state_cb; 
    12311266 
    12321267    tcp = (struct tcp_transport*) pj_activesock_get_user_data(asock); 
     
    12531288        } 
    12541289 
    1255         /* We can not destroy the transport since high level objects may 
    1256          * still keep reference to this transport. So we can only  
    1257          * instruct transport manager to gracefully start the shutdown 
    1258          * procedure for this transport. 
    1259          */ 
    1260         if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status; 
    1261         pjsip_transport_shutdown(&tcp->base); 
    1262         return PJ_FALSE; 
     1290        tcp_init_shutdown(tcp, status); 
    12631291    } 
    12641292 
     
    12941322    status = tcp_start_read(tcp); 
    12951323    if (status != PJ_SUCCESS) { 
    1296         /* We can not destroy the transport since high level objects may 
    1297          * still keep reference to this transport. So we can only  
    1298          * instruct transport manager to gracefully start the shutdown 
    1299          * procedure for this transport. 
    1300          */ 
    1301         if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status; 
    1302         pjsip_transport_shutdown(&tcp->base); 
     1324        tcp_init_shutdown(tcp, status); 
    13031325        return PJ_FALSE; 
     1326    } 
     1327 
     1328    /* Notify application of transport state connected */ 
     1329    state_cb = pjsip_tpmgr_get_status_cb(tcp->base.tpmgr); 
     1330    if (state_cb) { 
     1331        pjsip_transport_state_info state_info; 
     1332     
     1333        pj_bzero(&state_info, sizeof(state_info)); 
     1334        (*state_cb)(&tcp->base, PJSIP_TP_STATE_CONNECTED, &state_info); 
    13041335    } 
    13051336 
     
    13591390        tcp_perror(tcp->base.obj_name,  
    13601391                   "Error sending keep-alive packet", status); 
    1361         pjsip_transport_shutdown(&tcp->base); 
     1392        tcp_init_shutdown(tcp, status); 
    13621393        return; 
    13631394    } 
  • 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    } 
  • pjproject/trunk/pjsip/src/pjsip/sip_util.c

    r3069 r3106  
    779779            pjsip_hdr_clone(cancel_tdata->pool, req_tdata->saved_strict_route); 
    780780    } 
     781 
     782    /* Copy the destination host name from the original request */ 
     783    pj_strdup(cancel_tdata->pool, &cancel_tdata->dest_info.name, 
     784              &req_tdata->dest_info.name); 
    781785 
    782786    /* Finally copy the destination info from the original request */ 
     
    11351139 
    11361140        /* Acquire transport. */ 
    1137         status = pjsip_endpt_acquire_transport( stateless_data->endpt, 
     1141        status = pjsip_endpt_acquire_transport2(stateless_data->endpt, 
    11381142                                                cur_addr_type, 
    11391143                                                cur_addr, 
    11401144                                                cur_addr_len, 
    11411145                                                &tdata->tp_sel, 
     1146                                                tdata, 
    11421147                                                &stateless_data->cur_transport); 
    11431148        if (status != PJ_SUCCESS) { 
     
    13201325     */ 
    13211326    if (tdata->dest_info.addr.count == 0) { 
     1327        /* Copy the destination host name to TX data */ 
     1328        pj_strdup(tdata->pool, &tdata->dest_info.name, &dest_info.addr.host); 
     1329 
    13221330        pjsip_endpt_resolve( endpt, tdata->pool, &dest_info, stateless_data, 
    13231331                             &stateless_send_resolver_callback); 
     
    14661474        pjsip_tpselector_add_ref(sraw_data->sel); 
    14671475    } 
     1476 
     1477    /* Copy the destination host name to TX data */ 
     1478    pj_strdup(tdata->pool, &tdata->dest_info.name, &dest_info.addr.host); 
    14681479 
    14691480    /* Resolve destination host. 
     
    16231634 
    16241635    /* Acquire transport. */ 
    1625     status = pjsip_endpt_acquire_transport( send_state->endpt,  
     1636    status = pjsip_endpt_acquire_transport2(send_state->endpt,  
    16261637                                            addr->entry[0].type, 
    16271638                                            &addr->entry[0].addr, 
    16281639                                            addr->entry[0].addr_len, 
    16291640                                            &send_state->tdata->tp_sel, 
     1641                                            send_state->tdata, 
    16301642                                            &send_state->cur_transport); 
    16311643    if (status != PJ_SUCCESS) { 
     
    17031715        } 
    17041716    } else { 
     1717        /* Copy the destination host name to TX data */ 
     1718        pj_strdup(tdata->pool, &tdata->dest_info.name,  
     1719                  &res_addr->dst_host.addr.host); 
     1720 
    17051721        pjsip_endpt_resolve(endpt, tdata->pool, &res_addr->dst_host,  
    17061722                            send_state, &send_response_resolver_cb); 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r3021 r3106  
    18111811         * Create TLS transport. 
    18121812         */ 
    1813         /* 
    1814          * Create TCP transport. 
    1815          */ 
    18161813        pjsua_transport_config config; 
    18171814        pjsip_host_port a_name; 
     
    18681865    } 
    18691866 
     1867    /* Set transport state callback */ 
     1868    if (pjsua_var.ua_cfg.cb.on_transport_state) { 
     1869        pjsip_tpmgr_set_status_cb(pjsip_endpt_get_tpmgr(pjsua_var.endpt), 
     1870                                  &pjsua_var.ua_cfg.cb.on_transport_state); 
     1871    } 
    18701872 
    18711873    /* Return the ID */ 
Note: See TracChangeset for help on using the changeset viewer.