Compare commits

...

6 Commits

Author SHA1 Message Date
Asterisk Development Team
a5c572f6d3 Update for 18.5.1 2021-07-22 17:10:20 -05:00
Kevin Harwell
6c1aec36cb AST-2021-009 - pjproject-bundled: Avoid crash during handshake for TLS
If an SSL socket parent/listener was destroyed during the handshake,
depending on timing, it was possible for the handling callback to
attempt access of it after the fact thus causing a crash.

ASTERISK-29415 #close

Change-Id: I105dacdcd130ea7fdd4cf2010ccf35b5eaf1432d
2021-07-22 16:20:11 -05:00
Kevin Harwell
98e0b536d7 AST-2021-008 - chan_iax2: remote crash on unsupported media format
If chan_iax2 received a packet with an unsupported media format, for
example vp9, then it would set the frame's format to NULL. This could
then result in a crash later when an attempt was made to access the
format.

This patch makes it so chan_iax2 now ignores/drops frames received
with unsupported media format types.

ASTERISK-29392 #close

Change-Id: Ifa869a90dafe33eed8fd9463574fe6f1c0ad3eb1
2021-07-22 15:13:37 -05:00
Joshua C. Colp
4a525a8971 AST-2021-007 - res_pjsip_session: Don't offer if no channel exists.
If a re-INVITE is received after we have sent a BYE request then it
is possible for no channel to be present on the session. If this
occurs we allow PJSIP to produce the offer instead. Since the call
is being hung up if it produces an incorrect offer it doesn't
actually matter. This also ensures that code which produces SDP
does not need to handle if a channel is not present.

ASTERISK-29381

Change-Id: I673cb88c432f38f69b2e0851d55cc57a62236042
2021-07-22 13:39:42 -05:00
Asterisk Development Team
69f8f98b87 Update for 18.5.0 2021-06-24 07:50:57 -05:00
Asterisk Development Team
e74910bc8f Update for 18.5.0-rc1 2021-06-17 09:45:00 -05:00
15 changed files with 98812 additions and 9 deletions

1
.lastclean Normal file
View File

@@ -0,0 +1 @@
40

1
.version Normal file
View File

@@ -0,0 +1 @@
18.5.1

95431
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><title>Release Summary - asterisk-18.5.1</title><h1 align="center"><a name="top">Release Summary</a></h1><h3 align="center">asterisk-18.5.1</h3><h3 align="center">Date: 2021-07-22</h3><h3 align="center">&lt;asteriskteam@digium.com&gt;</h3><hr><h2 align="center">Table of Contents</h2><ol>
<li><a href="#summary">Summary</a></li>
<li><a href="#contributors">Contributors</a></li>
<li><a href="#closed_issues">Closed Issues</a></li>
<li><a href="#diffstat">Diffstat</a></li>
</ol><hr><a name="summary"><h2 align="center">Summary</h2></a><center><a href="#top">[Back to Top]</a></center><p>This release has been made to address one or more security vulnerabilities that have been identified. A security advisory document has been published for each vulnerability that includes additional information. Users of versions of Asterisk that are affected are strongly encouraged to review the advisories and determine what action they should take to protect their systems from these issues.</p><p>Security Advisories:</p><ul>
<li><a href="http://downloads.asterisk.org/pub/security/AST-2021-007,AST-2021-008,AST-2021-009.html">AST-2021-007,AST-2021-008,AST-2021-009</a></li>
</ul><p>The data in this summary reflects changes that have been made since the previous release, asterisk-18.5.0.</p><hr><a name="contributors"><h2 align="center">Contributors</h2></a><center><a href="#top">[Back to Top]</a></center><p>This table lists the people who have submitted code, those that have tested patches, as well as those that reported issues on the issue tracker that were resolved in this release. For coders, the number is how many of their patches (of any size) were committed into this release. For testers, the number is the number of times their name was listed as assisting with testing a patch. Finally, for reporters, the number is the number of issues that they reported that were affected by commits that went into this release.</p><table width="100%" border="0">
<tr><th width="33%">Coders</th><th width="33%">Testers</th><th width="33%">Reporters</th></tr>
<tr valign="top"><td width="33%">2 Kevin Harwell <kharwell@sangoma.com><br/>1 Joshua C. Colp <jcolp@sangoma.com><br/></td><td width="33%"><td width="33%">1 Michael Welk <dl5ocd@darc.de><br/>1 Ivan Poddubny <ivan.poddubny@gmail.com><br/>1 Andrew Yager <andrew@rwts.com.au><br/></td></tr>
</table><hr><a name="closed_issues"><h2 align="center">Closed Issues</h2></a><center><a href="#top">[Back to Top]</a></center><p>This is a list of all issues from the issue tracker that were closed by changes that went into this release.</p><h3>Security</h3><h4>Category: Channels/chan_pjsip</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-29415">ASTERISK-29415</a>: Crash in PJSIP TLS transport <br/>Reported by: Andrew Yager<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=6c1aec36cb55ca1f85452dbe54e6ed4a3421a6b2">[6c1aec36cb]</a> Kevin Harwell -- AST-2021-009 - pjproject-bundled: Avoid crash during handshake for TLS</li>
</ul><br><h4>Category: Resources/res_pjsip_session</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-29381">ASTERISK-29381</a>: chan_pjsip: Remote denial of service by an authenticated user<br/>Reported by: Ivan Poddubny<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=4a525a89719ede3f8719d2cf2aeca410467e8df8">[4a525a8971]</a> Joshua C. Colp -- AST-2021-007 - res_pjsip_session: Don't offer if no channel exists.</li>
</ul><br><h3>Bug</h3><h4>Category: Channels/chan_iax2</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-29392">ASTERISK-29392</a>: chan_iax2: Asterisk crashes when queueing video with format<br/>Reported by: Michael Welk<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=98e0b536d73959f8868a8e7435bec1b425e515ac">[98e0b536d7]</a> Kevin Harwell -- AST-2021-008 - chan_iax2: remote crash on unsupported media format</li>
</ul><br><hr><a name="diffstat"><h2 align="center">Diffstat Results</h2></a><center><a href="#top">[Back to Top]</a></center><p>This is a summary of the changes to the source code that went into this release that was generated using the diffstat utility.</p><pre>channels/chan_iax2.c | 40 +-
res/res_pjsip_session.c | 10
third-party/pjproject/patches/0110-tls-parent-listener-destroyed.patch | 166 ++++++++++
third-party/pjproject/patches/0111-ssl-premature-destroy.patch | 136 ++++++++
4 files changed, 343 insertions(+), 9 deletions(-)</pre><br></html>

107
asterisk-18.5.1-summary.txt Normal file
View File

@@ -0,0 +1,107 @@
Release Summary
asterisk-18.5.1
Date: 2021-07-22
<asteriskteam@digium.com>
----------------------------------------------------------------------
Table of Contents
1. Summary
2. Contributors
3. Closed Issues
4. Diffstat
----------------------------------------------------------------------
Summary
[Back to Top]
This release has been made to address one or more security vulnerabilities
that have been identified. A security advisory document has been published
for each vulnerability that includes additional information. Users of
versions of Asterisk that are affected are strongly encouraged to review
the advisories and determine what action they should take to protect their
systems from these issues.
Security Advisories:
* AST-2021-007,AST-2021-008,AST-2021-009
The data in this summary reflects changes that have been made since the
previous release, asterisk-18.5.0.
----------------------------------------------------------------------
Contributors
[Back to Top]
This table lists the people who have submitted code, those that have
tested patches, as well as those that reported issues on the issue tracker
that were resolved in this release. For coders, the number is how many of
their patches (of any size) were committed into this release. For testers,
the number is the number of times their name was listed as assisting with
testing a patch. Finally, for reporters, the number is the number of
issues that they reported that were affected by commits that went into
this release.
Coders Testers Reporters
2 Kevin Harwell 1 Michael Welk
1 Joshua C. Colp 1 Ivan Poddubny
1 Andrew Yager
----------------------------------------------------------------------
Closed Issues
[Back to Top]
This is a list of all issues from the issue tracker that were closed by
changes that went into this release.
Security
Category: Channels/chan_pjsip
ASTERISK-29415: Crash in PJSIP TLS transport
Reported by: Andrew Yager
* [6c1aec36cb] Kevin Harwell -- AST-2021-009 - pjproject-bundled: Avoid
crash during handshake for TLS
Category: Resources/res_pjsip_session
ASTERISK-29381: chan_pjsip: Remote denial of service by an authenticated
user
Reported by: Ivan Poddubny
* [4a525a8971] Joshua C. Colp -- AST-2021-007 - res_pjsip_session: Don't
offer if no channel exists.
Bug
Category: Channels/chan_iax2
ASTERISK-29392: chan_iax2: Asterisk crashes when queueing video with
format
Reported by: Michael Welk
* [98e0b536d7] Kevin Harwell -- AST-2021-008 - chan_iax2: remote crash
on unsupported media format
----------------------------------------------------------------------
Diffstat Results
[Back to Top]
This is a summary of the changes to the source code that went into this
release that was generated using the diffstat utility.
channels/chan_iax2.c | 40 +-
res/res_pjsip_session.c | 10
third-party/pjproject/patches/0110-tls-parent-listener-destroyed.patch | 166 ++++++++++
third-party/pjproject/patches/0111-ssl-premature-destroy.patch | 136 ++++++++
4 files changed, 343 insertions(+), 9 deletions(-)

View File

@@ -4132,6 +4132,7 @@ static void __get_from_jb(const void *p)
long ms;
long next;
struct timeval now = ast_tvnow();
struct ast_format *voicefmt;
/* Make sure we have a valid private structure before going on */
ast_mutex_lock(&iaxsl[callno]);
@@ -4151,10 +4152,9 @@ static void __get_from_jb(const void *p)
ms = ast_tvdiff_ms(now, pvt->rxcore);
if(ms >= (next = jb_next(pvt->jb))) {
struct ast_format *voicefmt;
voicefmt = ast_format_compatibility_bitfield2format(pvt->voiceformat);
ret = jb_get(pvt->jb, &frame, ms, voicefmt ? ast_format_get_default_ms(voicefmt) : 20);
voicefmt = ast_format_compatibility_bitfield2format(pvt->voiceformat);
if (voicefmt && ms >= (next = jb_next(pvt->jb))) {
ret = jb_get(pvt->jb, &frame, ms, ast_format_get_default_ms(voicefmt));
switch(ret) {
case JB_OK:
fr = frame.data;
@@ -4182,7 +4182,7 @@ static void __get_from_jb(const void *p)
pvt = iaxs[callno];
}
}
break;
break;
case JB_DROP:
iax2_frame_free(frame.data);
break;
@@ -6451,8 +6451,14 @@ static int decode_frame(ast_aes_decrypt_key *dcx, struct ast_iax2_full_hdr *fh,
f->frametype = fh->type;
if (f->frametype == AST_FRAME_VIDEO) {
f->subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1));
if (!f->subclass.format) {
f->subclass.format = ast_format_none;
}
} else if (f->frametype == AST_FRAME_VOICE) {
f->subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub));
if (!f->subclass.format) {
f->subclass.format = ast_format_none;
}
} else {
f->subclass.integer = uncompress_subclass(fh->csub);
}
@@ -9929,8 +9935,8 @@ static int socket_process_meta(int packet_len, struct ast_iax2_meta_hdr *meta, s
} else if (iaxs[fr->callno]->voiceformat == 0) {
ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n");
iax2_vnak(fr->callno);
} else {
f.subclass.format = ast_format_compatibility_bitfield2format(iaxs[fr->callno]->voiceformat);
} else if ((f.subclass.format = ast_format_compatibility_bitfield2format(
iaxs[fr->callno]->voiceformat))) {
f.datalen = len;
if (f.datalen >= 0) {
if (f.datalen)
@@ -10173,11 +10179,17 @@ static int socket_process_helper(struct iax2_thread *thread)
f.frametype = fh->type;
if (f.frametype == AST_FRAME_VIDEO) {
f.subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub & ~0x40));
if (!f.subclass.format) {
return 1;
}
if ((fh->csub >> 6) & 0x1) {
f.subclass.frame_ending = 1;
}
} else if (f.frametype == AST_FRAME_VOICE) {
f.subclass.format = ast_format_compatibility_bitfield2format(uncompress_subclass(fh->csub));
if (!f.subclass.format) {
return 1;
}
} else {
f.subclass.integer = uncompress_subclass(fh->csub);
}
@@ -11795,6 +11807,11 @@ immediatedial:
f.subclass.frame_ending = 1;
}
f.subclass.format = ast_format_compatibility_bitfield2format(iaxs[fr->callno]->videoformat);
if (!f.subclass.format) {
ast_variables_destroy(ies.vars);
ast_mutex_unlock(&iaxsl[fr->callno]);
return 1;
}
} else {
ast_log(LOG_WARNING, "Received mini frame before first full video frame\n");
iax2_vnak(fr->callno);
@@ -11816,9 +11833,14 @@ immediatedial:
} else {
/* A mini frame */
f.frametype = AST_FRAME_VOICE;
if (iaxs[fr->callno]->voiceformat > 0)
if (iaxs[fr->callno]->voiceformat > 0) {
f.subclass.format = ast_format_compatibility_bitfield2format(iaxs[fr->callno]->voiceformat);
else {
if (!f.subclass.format) {
ast_variables_destroy(ies.vars);
ast_mutex_unlock(&iaxsl[fr->callno]);
return 1;
}
} else {
ast_debug(1, "Received mini frame before first full voice frame\n");
iax2_vnak(fr->callno);
ast_variables_destroy(ies.vars);

View File

@@ -0,0 +1,41 @@
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL,
CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
);
-- Running upgrade -> 210693f3123d
CREATE TABLE cdr (
accountcode VARCHAR(20),
src VARCHAR(80),
dst VARCHAR(80),
dcontext VARCHAR(80),
clid VARCHAR(80),
channel VARCHAR(80),
dstchannel VARCHAR(80),
lastapp VARCHAR(80),
lastdata VARCHAR(80),
start DATETIME,
answer DATETIME,
end DATETIME,
duration INTEGER,
billsec INTEGER,
disposition VARCHAR(45),
amaflags VARCHAR(45),
userfield VARCHAR(256),
uniqueid VARCHAR(150),
linkedid VARCHAR(150),
peeraccount VARCHAR(20),
sequence INTEGER
);
INSERT INTO alembic_version (version_num) VALUES ('210693f3123d');
-- Running upgrade 210693f3123d -> 54cde9847798
ALTER TABLE cdr MODIFY accountcode VARCHAR(80) NULL;
ALTER TABLE cdr MODIFY peeraccount VARCHAR(80) NULL;
UPDATE alembic_version SET version_num='54cde9847798' WHERE alembic_version.version_num = '210693f3123d';

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL,
CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
);
-- Running upgrade -> a2e9769475e
CREATE TABLE voicemail_messages (
dir VARCHAR(255) NOT NULL,
msgnum INTEGER NOT NULL,
context VARCHAR(80),
macrocontext VARCHAR(80),
callerid VARCHAR(80),
origtime INTEGER,
duration INTEGER,
recording BLOB,
flag VARCHAR(30),
category VARCHAR(30),
mailboxuser VARCHAR(30),
mailboxcontext VARCHAR(30),
msg_id VARCHAR(40)
);
ALTER TABLE voicemail_messages ADD CONSTRAINT voicemail_messages_dir_msgnum PRIMARY KEY (dir, msgnum);
CREATE INDEX voicemail_messages_dir ON voicemail_messages (dir);
INSERT INTO alembic_version (version_num) VALUES ('a2e9769475e');
-- Running upgrade a2e9769475e -> 39428242f7f5
ALTER TABLE voicemail_messages MODIFY recording BLOB(4294967295) NULL;
UPDATE alembic_version SET version_num='39428242f7f5' WHERE alembic_version.version_num = 'a2e9769475e';

View File

@@ -0,0 +1,45 @@
BEGIN;
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL,
CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
);
-- Running upgrade -> 210693f3123d
CREATE TABLE cdr (
accountcode VARCHAR(20),
src VARCHAR(80),
dst VARCHAR(80),
dcontext VARCHAR(80),
clid VARCHAR(80),
channel VARCHAR(80),
dstchannel VARCHAR(80),
lastapp VARCHAR(80),
lastdata VARCHAR(80),
start TIMESTAMP WITHOUT TIME ZONE,
answer TIMESTAMP WITHOUT TIME ZONE,
"end" TIMESTAMP WITHOUT TIME ZONE,
duration INTEGER,
billsec INTEGER,
disposition VARCHAR(45),
amaflags VARCHAR(45),
userfield VARCHAR(256),
uniqueid VARCHAR(150),
linkedid VARCHAR(150),
peeraccount VARCHAR(20),
sequence INTEGER
);
INSERT INTO alembic_version (version_num) VALUES ('210693f3123d');
-- Running upgrade 210693f3123d -> 54cde9847798
ALTER TABLE cdr ALTER COLUMN accountcode TYPE VARCHAR(80);
ALTER TABLE cdr ALTER COLUMN peeraccount TYPE VARCHAR(80);
UPDATE alembic_version SET version_num='54cde9847798' WHERE alembic_version.version_num = '210693f3123d';
COMMIT;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
BEGIN;
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL,
CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
);
-- Running upgrade -> a2e9769475e
CREATE TABLE voicemail_messages (
dir VARCHAR(255) NOT NULL,
msgnum INTEGER NOT NULL,
context VARCHAR(80),
macrocontext VARCHAR(80),
callerid VARCHAR(80),
origtime INTEGER,
duration INTEGER,
recording BYTEA,
flag VARCHAR(30),
category VARCHAR(30),
mailboxuser VARCHAR(30),
mailboxcontext VARCHAR(30),
msg_id VARCHAR(40)
);
ALTER TABLE voicemail_messages ADD CONSTRAINT voicemail_messages_dir_msgnum PRIMARY KEY (dir, msgnum);
CREATE INDEX voicemail_messages_dir ON voicemail_messages (dir);
INSERT INTO alembic_version (version_num) VALUES ('a2e9769475e');
-- Running upgrade a2e9769475e -> 39428242f7f5
ALTER TABLE voicemail_messages ALTER COLUMN recording TYPE BYTEA;
UPDATE alembic_version SET version_num='39428242f7f5' WHERE alembic_version.version_num = 'a2e9769475e';
COMMIT;

View File

@@ -5263,6 +5263,16 @@ static void session_inv_on_create_offer(pjsip_inv_session *inv, pjmedia_sdp_sess
pjmedia_sdp_session *offer;
int i;
/* We allow PJSIP to produce an SDP if no channel is present. This may result
* in an incorrect SDP occurring, but if no channel is present then we are in
* the midst of a BYE and are hanging up. This ensures that all the code to
* produce an SDP doesn't need to worry about a channel being present or not,
* just in case.
*/
if (!session->channel) {
return;
}
if (inv->neg) {
if (pjmedia_sdp_neg_was_answer_remote(inv->neg)) {
pjmedia_sdp_neg_get_active_remote(inv->neg, &previous_sdp);

View File

@@ -0,0 +1,166 @@
From bb92c97ea512aa0ef316c9b2335c7d57b84dfc9a Mon Sep 17 00:00:00 2001
From: Nanang Izzuddin <nanang@teluu.com>
Date: Wed, 16 Jun 2021 12:12:35 +0700
Subject: [PATCH 1/2] - Avoid SSL socket parent/listener getting destroyed
during handshake by increasing parent's reference count. - Add missing SSL
socket close when the newly accepted SSL socket is discarded in SIP TLS
transport.
---
pjlib/src/pj/ssl_sock_imp_common.c | 44 +++++++++++++++++++++--------
pjsip/src/pjsip/sip_transport_tls.c | 23 ++++++++++++++-
2 files changed, 55 insertions(+), 12 deletions(-)
diff --git a/pjlib/src/pj/ssl_sock_imp_common.c b/pjlib/src/pj/ssl_sock_imp_common.c
index bc468bcb3..abec31805 100644
--- a/pjlib/src/pj/ssl_sock_imp_common.c
+++ b/pjlib/src/pj/ssl_sock_imp_common.c
@@ -224,6 +224,8 @@ static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock,
/* Accepting */
if (ssock->is_server) {
+ pj_bool_t ret = PJ_TRUE;
+
if (status != PJ_SUCCESS) {
/* Handshake failed in accepting, destroy our self silently. */
@@ -241,6 +243,12 @@ static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock,
status);
}
+ /* Decrement ref count of parent */
+ if (ssock->parent->param.grp_lock) {
+ pj_grp_lock_dec_ref(ssock->parent->param.grp_lock);
+ ssock->parent = NULL;
+ }
+
/* Originally, this is a workaround for ticket #985. However,
* a race condition may occur in multiple worker threads
* environment when we are destroying SSL objects while other
@@ -284,23 +292,29 @@ static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock,
return PJ_FALSE;
}
+
/* Notify application the newly accepted SSL socket */
if (ssock->param.cb.on_accept_complete2) {
- pj_bool_t ret;
ret = (*ssock->param.cb.on_accept_complete2)
(ssock->parent, ssock, (pj_sockaddr_t*)&ssock->rem_addr,
pj_sockaddr_get_len((pj_sockaddr_t*)&ssock->rem_addr),
status);
- if (ret == PJ_FALSE)
- return PJ_FALSE;
} else if (ssock->param.cb.on_accept_complete) {
- pj_bool_t ret;
ret = (*ssock->param.cb.on_accept_complete)
(ssock->parent, ssock, (pj_sockaddr_t*)&ssock->rem_addr,
pj_sockaddr_get_len((pj_sockaddr_t*)&ssock->rem_addr));
- if (ret == PJ_FALSE)
- return PJ_FALSE;
}
+
+ /* Decrement ref count of parent and reset parent (we don't need it
+ * anymore, right?).
+ */
+ if (ssock->parent->param.grp_lock) {
+ pj_grp_lock_dec_ref(ssock->parent->param.grp_lock);
+ ssock->parent = NULL;
+ }
+
+ if (ret == PJ_FALSE)
+ return PJ_FALSE;
}
/* Connecting */
@@ -864,9 +878,13 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
if (status != PJ_SUCCESS)
goto on_return;
+ /* Set parent and add ref count (avoid parent destroy during handshake) */
+ ssock->parent = ssock_parent;
+ if (ssock->parent->param.grp_lock)
+ pj_grp_lock_add_ref(ssock->parent->param.grp_lock);
+
/* Update new SSL socket attributes */
ssock->sock = newsock;
- ssock->parent = ssock_parent;
ssock->is_server = PJ_TRUE;
if (ssock_parent->cert) {
status = pj_ssl_sock_set_certificate(ssock, ssock->pool,
@@ -913,16 +931,20 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
ssock->asock_rbuf = (void**)pj_pool_calloc(ssock->pool,
ssock->param.async_cnt,
sizeof(void*));
- if (!ssock->asock_rbuf)
- return PJ_ENOMEM;
+ if (!ssock->asock_rbuf) {
+ status = PJ_ENOMEM;
+ goto on_return;
+ }
for (i = 0; i<ssock->param.async_cnt; ++i) {
- ssock->asock_rbuf[i] = (void*) pj_pool_alloc(
+ ssock->asock_rbuf[i] = (void*) pj_pool_alloc(
ssock->pool,
ssock->param.read_buffer_size +
sizeof(read_data_t*));
- if (!ssock->asock_rbuf[i])
- return PJ_ENOMEM;
+ if (!ssock->asock_rbuf[i]) {
+ status = PJ_ENOMEM;
+ goto on_return;
+ }
}
/* Create active socket */
diff --git a/pjsip/src/pjsip/sip_transport_tls.c b/pjsip/src/pjsip/sip_transport_tls.c
index 17b7ae3de..ce524d53f 100644
--- a/pjsip/src/pjsip/sip_transport_tls.c
+++ b/pjsip/src/pjsip/sip_transport_tls.c
@@ -1325,9 +1325,26 @@ static pj_bool_t on_accept_complete2(pj_ssl_sock_t *ssock,
PJ_UNUSED_ARG(src_addr_len);
listener = (struct tls_listener*) pj_ssl_sock_get_user_data(ssock);
+ if (!listener) {
+ /* Listener already destroyed, e.g: after TCP accept but before SSL
+ * handshake is completed.
+ */
+ if (new_ssock && accept_status == PJ_SUCCESS) {
+ /* Close the SSL socket if the accept op is successful */
+ PJ_LOG(4,(THIS_FILE,
+ "Incoming TLS connection from %s (sock=%d) is discarded "
+ "because listener is already destroyed",
+ pj_sockaddr_print(src_addr, addr, sizeof(addr), 3),
+ new_ssock));
+
+ pj_ssl_sock_close(new_ssock);
+ }
+
+ return PJ_FALSE;
+ }
if (accept_status != PJ_SUCCESS) {
- if (listener && listener->tls_setting.on_accept_fail_cb) {
+ if (listener->tls_setting.on_accept_fail_cb) {
pjsip_tls_on_accept_fail_param param;
pj_ssl_sock_info ssi;
@@ -1350,6 +1367,8 @@ static pj_bool_t on_accept_complete2(pj_ssl_sock_t *ssock,
PJ_ASSERT_RETURN(new_ssock, PJ_TRUE);
if (!listener->is_registered) {
+ pj_ssl_sock_close(new_ssock);
+
if (listener->tls_setting.on_accept_fail_cb) {
pjsip_tls_on_accept_fail_param param;
pj_bzero(&param, sizeof(param));
@@ -1401,6 +1420,8 @@ static pj_bool_t on_accept_complete2(pj_ssl_sock_t *ssock,
ssl_info.grp_lock, &tls);
if (status != PJ_SUCCESS) {
+ pj_ssl_sock_close(new_ssock);
+
if (listener->tls_setting.on_accept_fail_cb) {
pjsip_tls_on_accept_fail_param param;
pj_bzero(&param, sizeof(param));

View File

@@ -0,0 +1,136 @@
From 68c69f516f95df1faa42e5647e9ce7cfdc41ac38 Mon Sep 17 00:00:00 2001
From: Nanang Izzuddin <nanang@teluu.com>
Date: Wed, 16 Jun 2021 12:15:29 +0700
Subject: [PATCH 2/2] - Fix silly mistake: accepted active socket created
without group lock in SSL socket. - Replace assertion with normal validation
check of SSL socket instance in OpenSSL verification callback (verify_cb())
to avoid crash, e.g: if somehow race condition with SSL socket destroy
happens or OpenSSL application data index somehow gets corrupted.
---
pjlib/src/pj/ssl_sock_imp_common.c | 3 +-
pjlib/src/pj/ssl_sock_ossl.c | 45 +++++++++++++++++++++++++-----
2 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/pjlib/src/pj/ssl_sock_imp_common.c b/pjlib/src/pj/ssl_sock_imp_common.c
index bc468bcb3..c2b8a846b 100644
--- a/pjlib/src/pj/ssl_sock_imp_common.c
+++ b/pjlib/src/pj/ssl_sock_imp_common.c
@@ -927,6 +927,7 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
/* Create active socket */
pj_activesock_cfg_default(&asock_cfg);
+ asock_cfg.grp_lock = ssock->param.grp_lock;
asock_cfg.async_cnt = ssock->param.async_cnt;
asock_cfg.concurrency = ssock->param.concurrency;
asock_cfg.whole_data = PJ_TRUE;
@@ -942,7 +943,7 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
goto on_return;
pj_grp_lock_add_ref(glock);
- asock_cfg.grp_lock = ssock->param.grp_lock = glock;
+ ssock->param.grp_lock = glock;
pj_grp_lock_add_handler(ssock->param.grp_lock, ssock->pool, ssock,
ssl_on_destroy);
}
diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c
index a95b339a5..56841f80a 100644
--- a/pjlib/src/pj/ssl_sock_ossl.c
+++ b/pjlib/src/pj/ssl_sock_ossl.c
@@ -327,7 +327,8 @@ static pj_status_t STATUS_FROM_SSL_ERR(char *action, pj_ssl_sock_t *ssock,
ERROR_LOG("STATUS_FROM_SSL_ERR", err, ssock);
}
- ssock->last_err = err;
+ if (ssock)
+ ssock->last_err = err;
return GET_STATUS_FROM_SSL_ERR(err);
}
@@ -344,7 +345,8 @@ static pj_status_t STATUS_FROM_SSL_ERR2(char *action, pj_ssl_sock_t *ssock,
/* Dig for more from OpenSSL error queue */
SSLLogErrors(action, ret, err, len, ssock);
- ssock->last_err = ssl_err;
+ if (ssock)
+ ssock->last_err = ssl_err;
return GET_STATUS_FROM_SSL_ERR(ssl_err);
}
@@ -587,6 +589,13 @@ static pj_status_t init_openssl(void)
/* Create OpenSSL application data index for SSL socket */
sslsock_idx = SSL_get_ex_new_index(0, "SSL socket", NULL, NULL, NULL);
+ if (sslsock_idx == -1) {
+ status = STATUS_FROM_SSL_ERR2("Init", NULL, -1, ERR_get_error(), 0);
+ PJ_LOG(1,(THIS_FILE,
+ "Fatal error: failed to get application data index for "
+ "SSL socket"));
+ return status;
+ }
return status;
}
@@ -614,21 +623,36 @@ static int password_cb(char *buf, int num, int rwflag, void *user_data)
}
-/* SSL password callback. */
+/* SSL certificate verification result callback.
+ * Note that this callback seems to be always called from library worker
+ * thread, e.g: active socket on_read_complete callback, which should have
+ * already been equipped with race condition avoidance mechanism (should not
+ * be destroyed while callback is being invoked).
+ */
static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
{
- pj_ssl_sock_t *ssock;
- SSL *ossl_ssl;
+ pj_ssl_sock_t *ssock = NULL;
+ SSL *ossl_ssl = NULL;
int err;
/* Get SSL instance */
ossl_ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
SSL_get_ex_data_X509_STORE_CTX_idx());
- pj_assert(ossl_ssl);
+ if (!ossl_ssl) {
+ PJ_LOG(1,(THIS_FILE,
+ "SSL verification callback failed to get SSL instance"));
+ goto on_return;
+ }
/* Get SSL socket instance */
ssock = SSL_get_ex_data(ossl_ssl, sslsock_idx);
- pj_assert(ssock);
+ if (!ssock) {
+ /* SSL socket may have been destroyed */
+ PJ_LOG(1,(THIS_FILE,
+ "SSL verification callback failed to get SSL socket "
+ "instance (sslsock_idx=%d).", sslsock_idx));
+ goto on_return;
+ }
/* Store verification status */
err = X509_STORE_CTX_get_error(x509_ctx);
@@ -706,6 +730,7 @@ static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
if (PJ_FALSE == ssock->param.verify_peer)
preverify_ok = 1;
+on_return:
return preverify_ok;
}
@@ -1213,6 +1238,12 @@ static void ssl_destroy(pj_ssl_sock_t *ssock)
static void ssl_reset_sock_state(pj_ssl_sock_t *ssock)
{
ossl_sock_t *ossock = (ossl_sock_t *)ssock;
+
+ /* Detach from SSL instance */
+ if (ossock->ossl_ssl) {
+ SSL_set_ex_data(ossock->ossl_ssl, sslsock_idx, NULL);
+ }
+
/**
* Avoid calling SSL_shutdown() if handshake wasn't completed.
* OpenSSL 1.0.2f complains if SSL_shutdown() is called during an