diff options
Diffstat (limited to 'pjlib/src/pj/ssl_sock_symbian.cpp')
-rw-r--r-- | pjlib/src/pj/ssl_sock_symbian.cpp | 198 |
1 files changed, 179 insertions, 19 deletions
diff --git a/pjlib/src/pj/ssl_sock_symbian.cpp b/pjlib/src/pj/ssl_sock_symbian.cpp index 95c10077..47288fae 100644 --- a/pjlib/src/pj/ssl_sock_symbian.cpp +++ b/pjlib/src/pj/ssl_sock_symbian.cpp @@ -32,6 +32,104 @@ #define THIS_FILE "ssl_sock_symbian.cpp" + +/* Cipher name structure */ +typedef struct cipher_name_t { + pj_ssl_cipher cipher; + const char *name; +} cipher_name_t; + +/* Cipher name constants */ +static cipher_name_t cipher_names[] = +{ + {PJ_TLS_NULL_WITH_NULL_NULL, "NULL"}, + + /* TLS/SSLv3 */ + {PJ_TLS_RSA_WITH_NULL_MD5, "TLS_RSA_WITH_NULL_MD5"}, + {PJ_TLS_RSA_WITH_NULL_SHA, "TLS_RSA_WITH_NULL_SHA"}, + {PJ_TLS_RSA_WITH_NULL_SHA256, "TLS_RSA_WITH_NULL_SHA256"}, + {PJ_TLS_RSA_WITH_RC4_128_MD5, "TLS_RSA_WITH_RC4_128_MD5"}, + {PJ_TLS_RSA_WITH_RC4_128_SHA, "TLS_RSA_WITH_RC4_128_SHA"}, + {PJ_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"}, + {PJ_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"}, + {PJ_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA"}, + {PJ_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256"}, + {PJ_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS_RSA_WITH_AES_256_CBC_SHA256"}, + {PJ_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"}, + {PJ_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"}, + {PJ_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"}, + {PJ_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"}, + {PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA, "TLS_DH_DSS_WITH_AES_128_CBC_SHA"}, + {PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA, "TLS_DH_RSA_WITH_AES_128_CBC_SHA"}, + {PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"}, + {PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"}, + {PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA, "TLS_DH_DSS_WITH_AES_256_CBC_SHA"}, + {PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA, "TLS_DH_RSA_WITH_AES_256_CBC_SHA"}, + {PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"}, + {PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"}, + {PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA256, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"}, + {PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA256, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"}, + {PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"}, + {PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"}, + {PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA256, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"}, + {PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA256, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"}, + {PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"}, + {PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"}, + {PJ_TLS_DH_anon_WITH_RC4_128_MD5, "TLS_DH_anon_WITH_RC4_128_MD5"}, + {PJ_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"}, + {PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA, "TLS_DH_anon_WITH_AES_128_CBC_SHA"}, + {PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA, "TLS_DH_anon_WITH_AES_256_CBC_SHA"}, + {PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA256, "TLS_DH_anon_WITH_AES_128_CBC_SHA256"}, + {PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA256, "TLS_DH_anon_WITH_AES_256_CBC_SHA256"}, + + /* TLS (deprecated) */ + {PJ_TLS_RSA_EXPORT_WITH_RC4_40_MD5, "TLS_RSA_EXPORT_WITH_RC4_40_MD5"}, + {PJ_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"}, + {PJ_TLS_RSA_WITH_IDEA_CBC_SHA, "TLS_RSA_WITH_IDEA_CBC_SHA"}, + {PJ_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"}, + {PJ_TLS_RSA_WITH_DES_CBC_SHA, "TLS_RSA_WITH_DES_CBC_SHA"}, + {PJ_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"}, + {PJ_TLS_DH_DSS_WITH_DES_CBC_SHA, "TLS_DH_DSS_WITH_DES_CBC_SHA"}, + {PJ_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"}, + {PJ_TLS_DH_RSA_WITH_DES_CBC_SHA, "TLS_DH_RSA_WITH_DES_CBC_SHA"}, + {PJ_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"}, + {PJ_TLS_DHE_DSS_WITH_DES_CBC_SHA, "TLS_DHE_DSS_WITH_DES_CBC_SHA"}, + {PJ_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"}, + {PJ_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS_DHE_RSA_WITH_DES_CBC_SHA"}, + {PJ_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"}, + {PJ_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"}, + {PJ_TLS_DH_anon_WITH_DES_CBC_SHA, "TLS_DH_anon_WITH_DES_CBC_SHA"}, + + /* SSLv3 */ + {PJ_SSL_FORTEZZA_KEA_WITH_NULL_SHA, "SSL_FORTEZZA_KEA_WITH_NULL_SHA"}, + {PJ_SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA,"SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA"}, + {PJ_SSL_FORTEZZA_KEA_WITH_RC4_128_SHA, "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA"}, + + /* SSLv2 */ + {PJ_SSL_CK_RC4_128_WITH_MD5, "SSL_CK_RC4_128_WITH_MD5"}, + {PJ_SSL_CK_RC4_128_EXPORT40_WITH_MD5, "SSL_CK_RC4_128_EXPORT40_WITH_MD5"}, + {PJ_SSL_CK_RC2_128_CBC_WITH_MD5, "SSL_CK_RC2_128_CBC_WITH_MD5"}, + {PJ_SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, "SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5"}, + {PJ_SSL_CK_IDEA_128_CBC_WITH_MD5, "SSL_CK_IDEA_128_CBC_WITH_MD5"}, + {PJ_SSL_CK_DES_64_CBC_WITH_MD5, "SSL_CK_DES_64_CBC_WITH_MD5"}, + {PJ_SSL_CK_DES_192_EDE3_CBC_WITH_MD5, "SSL_CK_DES_192_EDE3_CBC_WITH_MD5"} +}; + + +/* Get cipher name string */ +static const char* get_cipher_name(pj_ssl_cipher cipher) +{ + unsigned i, n; + + n = PJ_ARRAY_SIZE(cipher_names); + for (i = 0; i < n; ++i) { + if (cipher == cipher_names[i].cipher) + return cipher_names[i].name; + } + + return "CIPHER_UNKNOWN"; +} + typedef void (*CPjSSLSocket_cb)(int err, void *key); class CPjSSLSocketReader : public CActive @@ -115,7 +213,8 @@ public: int Connect(CPjSSLSocket_cb cb, void *key, const TInetAddr &local_addr, const TInetAddr &rem_addr, - const TDesC8 &servername = TPtrC8(NULL,0)); + const TDesC8 &servername = TPtrC8(NULL,0), + const TDesC8 &ciphers = TPtrC8(NULL,0)); int Send(CPjSSLSocket_cb cb, void *key, const TDesC8 &aDesc, TUint flags); int SendSync(const TDesC8 &aDesc, TUint flags); @@ -146,6 +245,7 @@ private: TBuf<32> ssl_proto_; TInetAddr rem_addr_; TPtrC8 servername_; + TPtrC8 ciphers_; TInetAddr local_addr_; TSockXfrLength sent_len_; @@ -186,7 +286,8 @@ private: int CPjSSLSocket::Connect(CPjSSLSocket_cb cb, void *key, const TInetAddr &local_addr, const TInetAddr &rem_addr, - const TDesC8 &servername) + const TDesC8 &servername, + const TDesC8 &ciphers) { pj_status_t status; @@ -213,7 +314,11 @@ int CPjSSLSocket::Connect(CPjSSLSocket_cb cb, void *key, cb_ = cb; key_ = key; rem_addr_ = rem_addr; + + /* Note: the following members only keep the pointer, not the data */ servername_.Set(servername); + ciphers_.Set(ciphers); + rSock.Connect(rem_addr_, iStatus); SetActive(); state_ = SSL_STATE_CONNECTING; @@ -318,6 +423,8 @@ void CPjSSLSocket::RunL() if (servername_.Length() > 0) securesock_->SetOpt(KSoSSLDomainName, KSolInetSSL, servername_); + if (ciphers_.Length() > 0) + securesock_->SetAvailableCipherSuites(ciphers_); // FlushSessionCache() seems to also fire signals to all // completed AOs (something like CActiveScheduler::RunIfReady()) @@ -441,9 +548,8 @@ struct pj_ssl_sock_t pj_ssl_sock_proto proto; pj_time_val timeout; - unsigned ciphers_num; - pj_ssl_cipher *ciphers; pj_str_t servername; + pj_str_t ciphers; pj_ssl_cert_info remote_cert_info; }; @@ -579,15 +685,20 @@ static void update_certs_info(pj_ssl_sock_t *ssock) } +/* Available ciphers */ +static unsigned ciphers_num_ = 0; +static struct ciphers_t +{ + pj_ssl_cipher id; + const char *name; +} ciphers_[64]; + /* * Get cipher list supported by SSL/TLS backend. */ PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables (pj_ssl_cipher ciphers[], unsigned *cipher_num) { - /* Available ciphers */ - static pj_ssl_cipher ciphers_[64]; - static unsigned ciphers_num_ = 0; unsigned i; PJ_ASSERT_RETURN(ciphers && cipher_num, PJ_EINVAL); @@ -605,25 +716,69 @@ PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables (pj_ssl_cipher ciphers[], ciphers_num_ = ciphers_buf.Length() / 2; if (ciphers_num_ > PJ_ARRAY_SIZE(ciphers_)) ciphers_num_ = PJ_ARRAY_SIZE(ciphers_); - for (i = 0; i < ciphers_num_; ++i) - ciphers_[i] = (pj_ssl_cipher)(ciphers_buf[i*2]*10 + - ciphers_buf[i*2+1]); + for (i = 0; i < ciphers_num_; ++i) { + ciphers_[i].id = (pj_ssl_cipher)(ciphers_buf[i*2]*10 + + ciphers_buf[i*2+1]); + ciphers_[i].name = get_cipher_name(ciphers_[i].id); + } } delete secure_sock; } if (ciphers_num_ == 0) { + *cipher_num = 0; return PJ_ENOTFOUND; } *cipher_num = PJ_MIN(*cipher_num, ciphers_num_); for (i = 0; i < *cipher_num; ++i) - ciphers[i] = ciphers_[i]; + ciphers[i] = ciphers_[i].id; return PJ_SUCCESS; } + +/* Get cipher name string */ +PJ_DEF(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher) +{ + unsigned i; + + if (ciphers_num_ == 0) { + pj_ssl_cipher c[1]; + i = 0; + pj_ssl_cipher_get_availables(c, &i); + } + + for (i = 0; i < ciphers_num_; ++i) { + if (cipher == ciphers_[i].id) + return ciphers_[i].name; + } + + return NULL; +} + + +/* Check if the specified cipher is supported by SSL/TLS backend. */ +PJ_DEF(pj_bool_t) pj_ssl_cipher_is_supported(pj_ssl_cipher cipher) +{ + unsigned i; + + if (ciphers_num_ == 0) { + pj_ssl_cipher c[1]; + i = 0; + pj_ssl_cipher_get_availables(c, &i); + } + + for (i = 0; i < ciphers_num_; ++i) { + if (cipher == ciphers_[i].id) + return PJ_TRUE; + } + + return PJ_FALSE; +} + + /* * Create SSL socket instance. */ @@ -652,14 +807,15 @@ PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool, ssock->cb = param->cb; ssock->user_data = param->user_data; ssock->timeout = param->timeout; - ssock->ciphers_num = param->ciphers_num; if (param->ciphers_num > 0) { - unsigned i; - ssock->ciphers = (pj_ssl_cipher*) - pj_pool_calloc(pool, param->ciphers_num, - sizeof(pj_ssl_cipher)); - for (i = 0; i < param->ciphers_num; ++i) - ssock->ciphers[i] = param->ciphers[i]; + /* Cipher list in Symbian is represented as array of two-octets. */ + ssock->ciphers.slen = param->ciphers_num*2; + ssock->ciphers.ptr = (char*)pj_pool_alloc(pool, ssock->ciphers.slen); + pj_uint8_t *c = (pj_uint8_t*)ssock->ciphers.ptr; + for (unsigned i = 0; i < param->ciphers_num; ++i) { + *c++ = (pj_uint8_t)(param->ciphers[i] & 0xFF00) >> 8; + *c++ = (pj_uint8_t)(param->ciphers[i] & 0xFF); + } } pj_strdup_with_null(pool, &ssock->servername, ¶m->server_name); @@ -1246,9 +1402,13 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_connect (pj_ssl_sock_t *ssock, TPtrC8 servername_((TUint8*)ssock->servername.ptr, ssock->servername.slen); + /* Convert cipher list to Symbian descriptor */ + TPtrC8 ciphers_((TUint8*)ssock->ciphers.ptr, + ssock->ciphers.slen); + /* Try to connect */ status = sock->Connect(&connect_cb, ssock, localaddr_, remaddr_, - servername_); + servername_, ciphers_); if (status != PJ_SUCCESS && status != PJ_EPENDING) { delete sock; return status; |