summaryrefslogtreecommitdiff
path: root/pjlib
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2015-05-07 04:48:19 +0000
committerNanang Izzuddin <nanang@teluu.com>2015-05-07 04:48:19 +0000
commit3866e1c3e2173b477cfaceb1f13f8a9458dcfaa3 (patch)
treee403650ce7bf204d347826be7a3951228fed0162 /pjlib
parentd2e299bfe6ca3dd77727c3928b6898767d8e51d2 (diff)
Close #1849: Enabled multiple TLS certificate chains (RSA+ECC+DSA) for server socket.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5087 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjlib')
-rw-r--r--pjlib/include/pj/ssl_sock.h10
-rw-r--r--pjlib/src/pj/ssl_sock_ossl.c44
2 files changed, 52 insertions, 2 deletions
diff --git a/pjlib/include/pj/ssl_sock.h b/pjlib/include/pj/ssl_sock.h
index 172943da..c24e7bd9 100644
--- a/pjlib/include/pj/ssl_sock.h
+++ b/pjlib/include/pj/ssl_sock.h
@@ -185,7 +185,10 @@ typedef struct pj_ssl_cert_info {
/**
- * Create credential from files.
+ * Create credential from files. TLS server application can provide multiple
+ * certificates (RSA, ECC, and DSA) by supplying certificate name with "_rsa"
+ * suffix, e.g: "pjsip_rsa.pem", the library will automatically check for
+ * other certificates with "_ecc" and "_dsa" suffix.
*
* @param CA_file The file of trusted CA list.
* @param cert_file The file of certificate.
@@ -203,7 +206,10 @@ PJ_DECL(pj_status_t) pj_ssl_cert_load_from_files(pj_pool_t *pool,
pj_ssl_cert_t **p_cert);
/**
- * Create credential from files.
+ * Create credential from files. TLS server application can provide multiple
+ * certificates (RSA, ECC, and DSA) by supplying certificate name with "_rsa"
+ * suffix, e.g: "pjsip_rsa.pem", the library will automatically check for
+ * other certificates with "_ecc" and "_dsa" suffix.
*
* This is the same as pj_ssl_cert_load_from_files() but also
* accepts an additional param CA_path to load CA certificates from
diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c
index e2726f66..bffb5f1e 100644
--- a/pjlib/src/pj/ssl_sock_ossl.c
+++ b/pjlib/src/pj/ssl_sock_ossl.c
@@ -21,6 +21,7 @@
#include <pj/compat/socket.h>
#include <pj/assert.h>
#include <pj/errno.h>
+#include <pj/file_access.h>
#include <pj/list.h>
#include <pj/lock.h>
#include <pj/log.h>
@@ -671,6 +672,49 @@ static pj_status_t create_ssl(pj_ssl_sock_t *ssock)
}
if (ssock->is_server) {
+ char *p = NULL;
+
+ /* If certificate file name contains "_rsa.", let's check if there are
+ * ecc and dsa certificates too.
+ */
+ if (cert && cert->cert_file.slen) {
+ const pj_str_t RSA = {"_rsa.", 5};
+ p = pj_strstr(&cert->cert_file, &RSA);
+ if (p) p++; /* Skip underscore */
+ }
+ if (p) {
+ /* Certificate type string length must be exactly 3 */
+ enum { CERT_TYPE_LEN = 3 };
+ const char* cert_types[] = { "ecc", "dsa" };
+ char *cf = cert->cert_file.ptr;
+ int i;
+
+ /* Check and load ECC & DSA certificates & private keys */
+ for (i = 0; i < PJ_ARRAY_SIZE(cert_types); ++i) {
+ int err;
+
+ pj_memcpy(p, cert_types[i], CERT_TYPE_LEN);
+ if (!pj_file_exists(cf))
+ continue;
+
+ err = SSL_CTX_use_certificate_chain_file(ctx, cf);
+ if (err == 1)
+ err = SSL_CTX_use_PrivateKey_file(ctx, cf,
+ SSL_FILETYPE_PEM);
+ if (err == 1) {
+ PJ_LOG(4,(ssock->pool->obj_name,
+ "Additional certificate '%s' loaded.", cf));
+ } else {
+ pj_perror(1, ssock->pool->obj_name, GET_SSL_STATUS(ssock),
+ "Error loading certificate file '%s'", cf);
+ ERR_clear_error();
+ }
+ }
+
+ /* Put back original name */
+ pj_memcpy(p, "rsa", CERT_TYPE_LEN);
+ }
+
#ifndef SSL_CTRL_SET_ECDH_AUTO
#define SSL_CTRL_SET_ECDH_AUTO 94
#endif