Merge branch 'pjsip:master' into master

This commit is contained in:
Benny Prijono 2022-07-18 09:59:48 +08:00 committed by GitHub
commit 70ecdb584e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 141 additions and 35 deletions

View File

@ -181,7 +181,7 @@ int platform_strerror( pj_os_err_type os_errcode,
os_errcode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
wbuf,
sizeof(wbuf),
PJ_ARRAY_SIZE(wbuf),
NULL);
if (len) {
pj_unicode_to_ansi(wbuf, len, buf, bufsize);

View File

@ -57,6 +57,10 @@
#include <openssl/opensslconf.h>
#include <openssl/opensslv.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
# include <openssl/decoder.h>
#endif
/* Specify whether server supports session reuse using session ID. */
#define SERVER_SUPPORT_SESSION_REUSE 1
@ -255,6 +259,18 @@ static char *SSLErrorString (int err)
}
}
# if OPENSSL_VERSION_NUMBER >= 0x30000000L
#define ERROR_LOG(msg, err, ssock) \
{ \
char err_str[PJ_ERR_MSG_SIZE]; \
char buf[PJ_INET6_ADDRSTRLEN + 10]; \
ERR_error_string_n(err, err_str, sizeof(err_str)); \
PJ_LOG(2,("SSL", "%s (%s): Level: %d err: <%lu> <%s> len: %d peer: %s", \
msg, action, level, err, err_str, len, \
(ssock && pj_sockaddr_has_addr(&ssock->rem_addr)? \
pj_sockaddr_print(&ssock->rem_addr, buf, sizeof(buf), 3):"???")));\
}
# else
#define ERROR_LOG(msg, err, ssock) \
{ \
char buf[PJ_INET6_ADDRSTRLEN+10]; \
@ -268,6 +284,7 @@ static char *SSLErrorString (int err)
(ssock && pj_sockaddr_has_addr(&ssock->rem_addr)? \
pj_sockaddr_print(&ssock->rem_addr, buf, sizeof(buf), 3):"???")));\
}
# endif
static void SSLLogErrors(char * action, int ret, int ssl_err, int len,
pj_ssl_sock_t *ssock)
@ -656,6 +673,7 @@ static pj_status_t init_openssl(void)
openssl_init_count = 1;
PJ_LOG(4, (THIS_FILE, "OpenSSL version : %x", OPENSSL_VERSION_NUMBER));
/* Register error subsystem */
status = pj_register_strerror(PJ_SSL_ERRNO_START,
PJ_SSL_ERRNO_SPACE_SIZE,
@ -1030,16 +1048,63 @@ static int xname_cmp(const X509_NAME **a, const X509_NAME **b) {
#endif
#if !defined(OPENSSL_NO_DH)
static void set_option(const pj_ssl_sock_t* ssock, SSL_CTX* ctx) {
unsigned long options = SSL_OP_CIPHER_SERVER_PREFERENCE |
#if !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER >= 0x10000000L
SSL_OP_SINGLE_ECDH_USE |
#endif
SSL_OP_SINGLE_DH_USE;
options = SSL_CTX_set_options(ctx, options);
PJ_LOG(4, (ssock->pool->obj_name, "SSL DH "
"initialized, PFS cipher-suites enabled"));
}
static void set_dh_use_option(BIO *bio, const pj_ssl_sock_t* ssock,
const pj_str_t *pass, SSL_CTX* ctx)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
DH* dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
if (dh != NULL) {
if (SSL_CTX_set_tmp_dh(ctx, dh)) {
set_option(ssock, ctx);
}
DH_free(dh);
}
#else
OSSL_DECODER_CTX* dctx;
EVP_PKEY* dh_pkey = NULL;
const char* format = "PEM";
const char* structure = NULL;
const char* keytype = NULL;
dctx = OSSL_DECODER_CTX_new_for_pkey(&dh_pkey, format, structure, keytype,
0, NULL, NULL);
if (dctx != NULL) {
if (pass->slen) {
OSSL_DECODER_CTX_set_passphrase(dctx,
(const unsigned char*)pass->ptr,
pass->slen);
}
if (OSSL_DECODER_from_bio(dctx, bio)) {
if (SSL_CTX_set0_tmp_dh_pkey(ctx, dh_pkey)) {
set_option(ssock, ctx);
}
}
OSSL_DECODER_CTX_free(dctx);
}
#endif
}
#endif
/* Initialize OpenSSL context for the ssock */
static pj_status_t init_ossl_ctx(pj_ssl_sock_t *ssock)
{
ossl_sock_t *ossock = (ossl_sock_t *)ssock;
SSL_CTX *ctx = NULL;
#if !defined(OPENSSL_NO_DH)
BIO *bio;
DH *dh;
long options;
#endif
SSL_METHOD *ssl_method = NULL;
pj_uint32_t ssl_opt = 0;
pj_ssl_cert_t *cert = ssock->cert;
@ -1121,6 +1186,14 @@ static pj_status_t init_ossl_ctx(pj_ssl_sock_t *ssock)
return GET_SSL_STATUS(ssock);
}
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
if (ssock->param.proto <= PJ_SSL_SOCK_PROTO_TLS1_1) {
/* TLS 1.0, TLS 1.1 no longer working at the default security
* level of 1 and instead requires security level 0. */
SSL_CTX_set_security_level(ossock->ossl_ctx, 0);
}
#endif
if (ssock->is_server) {
unsigned int sid_ctx = SERVER_SESSION_ID_CONTEXT;
@ -1237,22 +1310,9 @@ static pj_status_t init_ossl_ctx(pj_ssl_sock_t *ssock)
#if !defined(OPENSSL_NO_DH)
if (ssock->is_server) {
bio = BIO_new_file(cert->privkey_file.ptr, "r");
BIO *bio = BIO_new_file(cert->privkey_file.ptr, "r");
if (bio != NULL) {
dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
if (dh != NULL) {
if (SSL_CTX_set_tmp_dh(ctx, dh)) {
options = SSL_OP_CIPHER_SERVER_PREFERENCE |
#if !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER >= 0x10000000L
SSL_OP_SINGLE_ECDH_USE |
#endif
SSL_OP_SINGLE_DH_USE;
options = SSL_CTX_set_options(ctx, options);
PJ_LOG(4,(ssock->pool->obj_name, "SSL DH "
"initialized, PFS cipher-suites enabled"));
}
DH_free(dh);
}
set_dh_use_option(bio, ssock, &cert->privkey_pass, ctx);
BIO_free(bio);
}
}
@ -1359,20 +1419,7 @@ static pj_status_t init_ossl_ctx(pj_ssl_sock_t *ssock)
}
if (ssock->is_server) {
dh = PEM_read_bio_DHparams(kbio, NULL, NULL, NULL);
if (dh != NULL) {
if (SSL_CTX_set_tmp_dh(ctx, dh)) {
options = SSL_OP_CIPHER_SERVER_PREFERENCE |
#if !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER >= 0x10000000L
SSL_OP_SINGLE_ECDH_USE |
#endif
SSL_OP_SINGLE_DH_USE;
options = SSL_CTX_set_options(ctx, options);
PJ_LOG(4,(ssock->pool->obj_name, "SSL DH "
"initialized, PFS cipher-suites enabled"));
}
DH_free(dh);
}
set_dh_use_option(kbio, ssock, &cert->privkey_pass, ctx);
}
BIO_free(kbio);
}

View File

@ -45,6 +45,9 @@
#if PJSIP_AUTH_HAS_DIGEST_SHA256
# include <openssl/sha.h>
# if OPENSSL_VERSION_NUMBER >= 0x30000000L
# include <openssl/evp.h>
# endif
# ifdef _MSC_VER
# include <openssl/opensslv.h>
# if OPENSSL_VERSION_NUMBER >= 0x10100000L
@ -276,10 +279,24 @@ PJ_DEF(pj_status_t) pjsip_auth_create_digestSHA256(pj_str_t *result,
char ha1[PJSIP_SHA256STRLEN];
char ha2[PJSIP_SHA256STRLEN];
unsigned char digest[32];
#if OPENSSL_VERSION_NUMBER < 0x30000000L
SHA256_CTX pms;
#else
EVP_MD_CTX* mdctx;
const EVP_MD* md;
unsigned dig_len;
#endif
pj_assert(result->slen >= PJSIP_SHA256STRLEN);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
md = EVP_get_digestbyname("SHA256");
if (md == NULL) {
return PJ_ENOTSUP;
}
#endif
AUTH_TRACE_((THIS_FILE, "Begin creating digest"));
if ((cred_info->data_type & PASSWD_MASK) == PJSIP_CRED_DATA_PLAIN_PASSWD)
@ -287,6 +304,7 @@ PJ_DEF(pj_status_t) pjsip_auth_create_digestSHA256(pj_str_t *result,
/***
*** ha1 = SHA256(username ":" realm ":" password)
***/
#if OPENSSL_VERSION_NUMBER < 0x30000000L
SHA256_Init(&pms);
SHA256_Update( &pms, cred_info->username.ptr,
cred_info->username.slen);
@ -295,7 +313,18 @@ PJ_DEF(pj_status_t) pjsip_auth_create_digestSHA256(pj_str_t *result,
SHA256_Update( &pms, ":", 1);
SHA256_Update( &pms, cred_info->data.ptr, cred_info->data.slen);
SHA256_Final(digest, &pms);
#else
mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, cred_info->username.ptr, cred_info->username.slen);
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, realm->ptr, realm->slen);
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, cred_info->data.ptr, cred_info->data.slen);
EVP_DigestFinal_ex(mdctx, digest, &dig_len);
EVP_MD_CTX_free(mdctx);
#endif
digestNtoStr(digest, 32, ha1);
} else if ((cred_info->data_type & PASSWD_MASK) == PJSIP_CRED_DATA_DIGEST)
@ -319,11 +348,21 @@ PJ_DEF(pj_status_t) pjsip_auth_create_digestSHA256(pj_str_t *result,
/***
*** ha2 = SHA256(method ":" req_uri)
***/
#if OPENSSL_VERSION_NUMBER < 0x30000000L
SHA256_Init(&pms);
SHA256_Update( &pms, method->ptr, method->slen);
SHA256_Update( &pms, ":", 1);
SHA256_Update( &pms, uri->ptr, uri->slen);
SHA256_Final( digest, &pms);
#else
mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, method->ptr, method->slen);
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, uri->ptr, uri->slen);
EVP_DigestFinal_ex(mdctx, digest, &dig_len);
EVP_MD_CTX_free(mdctx);
#endif
digestNtoStr(digest, 32, ha2);
AUTH_TRACE_((THIS_FILE, " ha2=%.64s", ha2));
@ -335,6 +374,7 @@ PJ_DEF(pj_status_t) pjsip_auth_create_digestSHA256(pj_str_t *result,
*** When qop=auth is used:
*** response = SHA256(ha1 ":" nonce ":" nc ":" cnonce ":" qop ":" ha2)
***/
#if OPENSSL_VERSION_NUMBER < 0x30000000L
SHA256_Init(&pms);
SHA256_Update( &pms, ha1, PJSIP_SHA256STRLEN);
SHA256_Update( &pms, ":", 1);
@ -352,7 +392,26 @@ PJ_DEF(pj_status_t) pjsip_auth_create_digestSHA256(pj_str_t *result,
/* This is the final response digest. */
SHA256_Final(digest, &pms);
#else
mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, ha1, PJSIP_SHA256STRLEN);
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, nonce->ptr, nonce->slen);
if (qop && qop->slen != 0) {
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, nc->ptr, nc->slen);
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, cnonce->ptr, cnonce->slen);
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, qop->ptr, qop->slen);
}
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, ha2, PJSIP_SHA256STRLEN);
EVP_DigestFinal_ex(mdctx, digest, &dig_len);
EVP_MD_CTX_free(mdctx);
#endif
/* Convert digest to string and store in chal->response. */
result->slen = PJSIP_SHA256STRLEN;
digestNtoStr(digest, 32, result->ptr);