Skip to content

Commit d08d80c

Browse files
committed
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: Fix GH-21336: undefined behavior in snmp setSecurity.
2 parents 7e78b0f + 41458c6 commit d08d80c

File tree

3 files changed

+76
-8
lines changed

3 files changed

+76
-8
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ PHP NEWS
1313
. Fixed re-entrancy issue on php_pcre_match_impl, php_pcre_replace_impl,
1414
php_pcre_split_impl, and php_pcre_grep_impl. (David Carlier)
1515

16+
- SNMP:
17+
. Fixed bug GH-21336 (SNMP::setSecurity() undefined behavior with
18+
NULL arguments). (David Carlier)
19+
1620
- Standard:
1721
. Fixed bug GH-20906 (Assertion failure when messing up output buffers).
1822
(ndossche)

ext/snmp/snmp.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,7 @@ static bool snmp_session_set_sec_level(struct snmp_session *s, zend_string *leve
10061006
/* }}} */
10071007

10081008
/* {{{ Set the authentication protocol in the snmpv3 session */
1009-
static bool snmp_session_set_auth_protocol(struct snmp_session *s, zend_string *prot)
1009+
static ZEND_ATTRIBUTE_NONNULL bool snmp_session_set_auth_protocol(struct snmp_session *s, zend_string *prot)
10101010
{
10111011
#ifndef DISABLE_MD5
10121012
if (zend_string_equals_literal_ci(prot, "MD5")) {
@@ -1055,7 +1055,7 @@ static bool snmp_session_set_auth_protocol(struct snmp_session *s, zend_string *
10551055
/* }}} */
10561056

10571057
/* {{{ Set the security protocol in the snmpv3 session */
1058-
static bool snmp_session_set_sec_protocol(struct snmp_session *s, zend_string *prot)
1058+
static ZEND_ATTRIBUTE_NONNULL bool snmp_session_set_sec_protocol(struct snmp_session *s, zend_string *prot)
10591059
{
10601060
#ifndef NETSNMP_DISABLE_DES
10611061
if (zend_string_equals_literal_ci(prot, "DES")) {
@@ -1092,9 +1092,10 @@ static bool snmp_session_set_sec_protocol(struct snmp_session *s, zend_string *p
10921092
/* }}} */
10931093

10941094
/* {{{ Make key from pass phrase in the snmpv3 session */
1095-
static bool snmp_session_gen_auth_key(struct snmp_session *s, zend_string *pass)
1095+
static ZEND_ATTRIBUTE_NONNULL bool snmp_session_gen_auth_key(struct snmp_session *s, zend_string *pass)
10961096
{
10971097
int snmp_errno;
1098+
10981099
s->securityAuthKeyLen = USM_AUTH_KU_LEN;
10991100
if ((snmp_errno = generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
11001101
(uint8_t *) ZSTR_VAL(pass), ZSTR_LEN(pass),
@@ -1107,7 +1108,7 @@ static bool snmp_session_gen_auth_key(struct snmp_session *s, zend_string *pass)
11071108
/* }}} */
11081109

11091110
/* {{{ Make key from pass phrase in the snmpv3 session */
1110-
static bool snmp_session_gen_sec_key(struct snmp_session *s, zend_string *pass)
1111+
static ZEND_ATTRIBUTE_NONNULL bool snmp_session_gen_sec_key(struct snmp_session *s, zend_string *pass)
11111112
{
11121113
int snmp_errno;
11131114

@@ -1146,9 +1147,10 @@ static bool snmp_session_set_contextEngineID(struct snmp_session *s, zend_string
11461147
/* }}} */
11471148

11481149
/* {{{ Set all snmpv3-related security options */
1149-
static bool snmp_session_set_security(struct snmp_session *session, zend_string *sec_level,
1150+
static ZEND_ATTRIBUTE_NONNULL_ARGS(2) bool snmp_session_set_security(struct snmp_session *session, zend_string *sec_level,
11501151
zend_string *auth_protocol, zend_string *auth_passphrase, zend_string *priv_protocol,
1151-
zend_string *priv_passphrase, zend_string *contextName, zend_string *contextEngineID)
1152+
zend_string *priv_passphrase, zend_string *contextName, zend_string *contextEngineID,
1153+
uint32_t auth_protocol_argnum)
11521154
{
11531155

11541156
/* Setting the security level. */
@@ -1159,25 +1161,46 @@ static bool snmp_session_set_security(struct snmp_session *session, zend_string
11591161

11601162
if (session->securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
11611163

1164+
if (!auth_protocol) {
1165+
zend_argument_value_error(auth_protocol_argnum, "cannot be null when security level is \"authNoPriv\" or \"authPriv\"");
1166+
return false;
1167+
}
1168+
11621169
/* Setting the authentication protocol. */
11631170
if (!snmp_session_set_auth_protocol(session, auth_protocol)) {
11641171
/* ValueError already generated, just bail out */
11651172
return false;
11661173
}
11671174

1175+
if (!auth_passphrase) {
1176+
zend_argument_value_error(auth_protocol_argnum + 1, "cannot be null when security level is \"authNoPriv\" or \"authPriv\"");
1177+
return false;
1178+
}
1179+
11681180
/* Setting the authentication passphrase. */
11691181
if (!snmp_session_gen_auth_key(session, auth_passphrase)) {
11701182
/* Warning message sent already, just bail out */
11711183
return false;
11721184
}
11731185

11741186
if (session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
1187+
1188+
if (!priv_protocol) {
1189+
zend_argument_value_error(auth_protocol_argnum + 2, "cannot be null when security level is \"authPriv\"");
1190+
return false;
1191+
}
1192+
11751193
/* Setting the security protocol. */
11761194
if (!snmp_session_set_sec_protocol(session, priv_protocol)) {
11771195
/* ValueError already generated, just bail out */
11781196
return false;
11791197
}
11801198

1199+
if (!priv_passphrase) {
1200+
zend_argument_value_error(auth_protocol_argnum + 3, "cannot be null when security level is \"authPriv\"");
1201+
return false;
1202+
}
1203+
11811204
/* Setting the security protocol passphrase. */
11821205
if (!snmp_session_gen_sec_key(session, priv_passphrase)) {
11831206
/* Warning message sent already, just bail out */
@@ -1347,7 +1370,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
13471370
snmp_session_free(&session);
13481371
RETURN_FALSE;
13491372
}
1350-
if (version == SNMP_VERSION_3 && !snmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL)) {
1373+
if (version == SNMP_VERSION_3 && !snmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL, 4)) {
13511374
php_free_objid_query(&objid_query, oid_ht, value_ht, st);
13521375
snmp_session_free(&session);
13531376
/* Warning message sent already, just bail out */
@@ -1722,7 +1745,7 @@ PHP_METHOD(SNMP, setSecurity)
17221745
RETURN_THROWS();
17231746
}
17241747

1725-
if (!snmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7)) {
1748+
if (!snmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7, 2)) {
17261749
/* Warning message sent already, just bail out */
17271750
RETURN_FALSE;
17281751
}

ext/snmp/tests/gh21336.phpt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
GH-21336 (undefined behavior in snmp - NULL pointer dereference in setSecurity)
3+
--EXTENSIONS--
4+
snmp
5+
--FILE--
6+
<?php
7+
$session = new SNMP(SNMP::VERSION_3, 'localhost', 'user');
8+
9+
// auth protocol NULL
10+
try {
11+
$session->setSecurity('authPriv');
12+
} catch (ValueError $e) {
13+
echo $e->getMessage() . PHP_EOL;
14+
}
15+
16+
// auth passphrase NULL
17+
try {
18+
$session->setSecurity('authNoPriv', 'MD5');
19+
} catch (ValueError $e) {
20+
echo $e->getMessage() . PHP_EOL;
21+
}
22+
23+
// priv protocol NULL
24+
try {
25+
$session->setSecurity('authPriv', 'MD5', 'test12345');
26+
} catch (ValueError $e) {
27+
echo $e->getMessage() . PHP_EOL;
28+
}
29+
30+
// priv passphrase NULL
31+
try {
32+
$session->setSecurity('authPriv', 'MD5', 'test12345', 'AES');
33+
} catch (ValueError $e) {
34+
echo $e->getMessage() . PHP_EOL;
35+
}
36+
?>
37+
--EXPECT--
38+
SNMP::setSecurity(): Argument #2 ($authProtocol) cannot be null when security level is "authNoPriv" or "authPriv"
39+
SNMP::setSecurity(): Argument #3 ($authPassphrase) cannot be null when security level is "authNoPriv" or "authPriv"
40+
SNMP::setSecurity(): Argument #4 ($privacyProtocol) cannot be null when security level is "authPriv"
41+
SNMP::setSecurity(): Argument #5 ($privacyPassphrase) cannot be null when security level is "authPriv"

0 commit comments

Comments
 (0)