Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 36 additions & 24 deletions ext/snmp/snmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,8 @@ static void php_free_objid_query(struct objid_query *objid_query, HashTable* oid
*/
static bool php_snmp_parse_oid(
zval *object, int st, struct objid_query *objid_query, zend_string *oid_str, HashTable *oid_ht,
zend_string *type_str, HashTable *type_ht, zend_string *value_str, HashTable *value_ht
zend_string *type_str, HashTable *type_ht, zend_string *value_str, HashTable *value_ht,
uint32_t oid_argument_offset, uint32_t type_argument_offset, uint32_t value_argument_offset
) {
char *pptr;
uint32_t idx_type = 0, idx_value = 0;
Expand All @@ -682,7 +683,7 @@ static bool php_snmp_parse_oid(
ZEND_ASSERT(type_str && value_str);

if (ZSTR_LEN(type_str) != 1) {
zend_value_error("Type must be a single character");
zend_argument_value_error(type_argument_offset, "must be a single character");
efree(objid_query->vars);
return false;
}
Expand All @@ -693,7 +694,7 @@ static bool php_snmp_parse_oid(
objid_query->count++;
} else if (oid_ht) { /* we got objid array */
if (zend_hash_num_elements(oid_ht) == 0) {
zend_value_error("Array of object IDs must not be empty");
zend_argument_value_error(oid_argument_offset, "must not be empty when passed as an array");
return false;
}
objid_query->vars = (snmpobjarg *)safe_emalloc(sizeof(snmpobjarg), zend_hash_num_elements(oid_ht), 0);
Expand Down Expand Up @@ -738,14 +739,14 @@ static bool php_snmp_parse_oid(
char ptype = *ZSTR_VAL(type);
zend_string_release(type);
if (len != 1) {
zend_value_error("Type must be a single character");
zend_argument_value_error(type_argument_offset, "must be a single character");
php_free_objid_query(objid_query, oid_ht, value_ht, st);
return false;
}
objid_query->vars[objid_query->count].type = ptype;
idx_type++;
} else {
php_error_docref(NULL, E_WARNING, "'%s': no type set", ZSTR_VAL(tmp));
zend_argument_value_error(type_argument_offset, "must contain a type for object ID '%s'", ZSTR_VAL(tmp));
php_free_objid_query(objid_query, oid_ht, value_ht, st);
return false;
}
Expand Down Expand Up @@ -780,7 +781,7 @@ static bool php_snmp_parse_oid(
objid_query->vars[objid_query->count].value = ZSTR_VAL(tmp);
idx_value++;
} else {
php_error_docref(NULL, E_WARNING, "'%s': no value set", ZSTR_VAL(tmp));
zend_argument_value_error(value_argument_offset, "must contain a value for object ID '%s'", ZSTR_VAL(tmp));
php_free_objid_query(objid_query, oid_ht, value_ht, st);
return false;
}
Expand Down Expand Up @@ -827,7 +828,7 @@ static bool php_snmp_parse_oid(
/* {{{ snmp_session_init
allocates memory for session and session->peername, caller should free it manually using snmp_session_free() and efree()
*/
static bool snmp_session_init(php_snmp_session **session_p, int version, zend_string *hostname, zend_string *community, zend_long timeout, zend_long retries, int timeout_argument_offset)
static bool snmp_session_init(php_snmp_session **session_p, int version, zend_string *hostname, zend_string *community, zend_long timeout, zend_long retries, int hostname_argument_offset, int timeout_argument_offset)
{
php_snmp_session *session;
char *pptr, *host_ptr;
Expand All @@ -842,22 +843,22 @@ static bool snmp_session_init(php_snmp_session **session_p, int version, zend_st
ZEND_ASSERT(community != NULL);

if (zend_str_has_nul_byte(hostname)) {
zend_argument_value_error(2, "must not contain any null bytes");
zend_argument_value_error(hostname_argument_offset, "must not contain any null bytes");
return false;
}
Comment thread
prateekbhujel marked this conversation as resolved.
Outdated

if (ZSTR_LEN(hostname) >= MAX_NAME_LEN) {
zend_argument_value_error(2, "length must be lower than %d", MAX_NAME_LEN);
zend_argument_value_error(hostname_argument_offset, "length must be lower than %d", MAX_NAME_LEN);
return false;
}

if (zend_str_has_nul_byte(community)) {
zend_argument_value_error(3, "must not contain any null bytes");
zend_argument_value_error(hostname_argument_offset + 1, "must not contain any null bytes");
return false;
}
Comment thread
prateekbhujel marked this conversation as resolved.
Outdated

if (ZSTR_LEN(community) == 0) {
zend_argument_must_not_be_empty_error(3);
zend_argument_must_not_be_empty_error(hostname_argument_offset + 1);
return false;
}

Expand Down Expand Up @@ -899,22 +900,22 @@ static bool snmp_session_init(php_snmp_session **session_p, int version, zend_st
char *pport = pptr + 2;
tmp_port = atoi(pport);
if (tmp_port < 0 || tmp_port > USHRT_MAX) {
zend_argument_value_error(2, "remote port must be between 0 and %u", USHRT_MAX);
zend_argument_value_error(hostname_argument_offset, "remote port must be between 0 and %u", USHRT_MAX);
return false;
}
remote_port = (unsigned short)tmp_port;
}
*pptr = '\0';
} else {
php_error_docref(NULL, E_WARNING, "Malformed IPv6 address, closing square bracket missing");
zend_argument_value_error(hostname_argument_offset, "has a malformed IPv6 address, closing square bracket missing");
return false;
}
} else { /* IPv4 address */
if ((pptr = strchr(host_ptr, ':'))) {
char *pport = pptr + 1;
tmp_port = atoi(pport);
if (tmp_port < 0 || tmp_port > USHRT_MAX) {
zend_argument_value_error(2, "remote port must be between 0 and %u", USHRT_MAX);
zend_argument_value_error(hostname_argument_offset, "remote port must be between 0 and %u", USHRT_MAX);
return false;
}
remote_port = (unsigned short)tmp_port;
Expand Down Expand Up @@ -1123,14 +1124,13 @@ static ZEND_ATTRIBUTE_NONNULL bool snmp_session_gen_sec_key(struct snmp_session
/* }}} */

/* {{{ Set context Engine Id in the snmpv3 session */
static bool snmp_session_set_contextEngineID(struct snmp_session *s, zend_string * contextEngineID)
static bool snmp_session_set_contextEngineID(struct snmp_session *s, zend_string * contextEngineID, uint32_t contextEngineID_argument_offset)
{
size_t ebuf_len = 32, eout_len = 0;
uint8_t *ebuf = (uint8_t *) emalloc(ebuf_len);

if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, ZSTR_VAL(contextEngineID))) {
// TODO Promote to Error?
php_error_docref(NULL, E_WARNING, "Bad engine ID value '%s'", ZSTR_VAL(contextEngineID));
zend_argument_value_error(contextEngineID_argument_offset, "must be a valid context engine ID");
efree(ebuf);
return false;
}
Expand All @@ -1149,7 +1149,7 @@ static bool snmp_session_set_contextEngineID(struct snmp_session *s, zend_string
static ZEND_ATTRIBUTE_NONNULL_ARGS(2) bool snmp_session_set_security(struct snmp_session *session, zend_string *sec_level,
zend_string *auth_protocol, zend_string *auth_passphrase, zend_string *priv_protocol,
zend_string *priv_passphrase, zend_string *contextName, zend_string *contextEngineID,
uint32_t auth_protocol_argnum)
uint32_t auth_protocol_argnum, uint32_t contextEngineID_argument_offset)
{

/* Setting the security level. */
Expand Down Expand Up @@ -1215,7 +1215,7 @@ static ZEND_ATTRIBUTE_NONNULL_ARGS(2) bool snmp_session_set_security(struct snmp
}

/* Setting contextEngineIS if specified */
if (contextEngineID && ZSTR_LEN(contextEngineID) && !snmp_session_set_contextEngineID(session, contextEngineID)) {
if (contextEngineID && ZSTR_LEN(contextEngineID) && !snmp_session_set_contextEngineID(session, contextEngineID, contextEngineID_argument_offset)) {
/* Warning message sent already, just bail out */
return false;
}
Expand Down Expand Up @@ -1243,6 +1243,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
php_snmp_session *session;
int session_less_mode = (getThis() == NULL);
int timeout_argument_offset = -1;
uint32_t oid_argument_offset = 1, type_argument_offset = 0, value_argument_offset = 0;
php_snmp_object *snmp_object;
php_snmp_object glob_snmp_object;

Expand Down Expand Up @@ -1271,6 +1272,9 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
ZEND_PARSE_PARAMETERS_END();

timeout_argument_offset = 10;
oid_argument_offset = 8;
type_argument_offset = 9;
value_argument_offset = 10;
} else {
/* SNMP_CMD_GET
* SNMP_CMD_GETNEXT
Expand All @@ -1291,6 +1295,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
ZEND_PARSE_PARAMETERS_END();

timeout_argument_offset = 9;
oid_argument_offset = 8;
}
} else {
if (st & SNMP_CMD_SET) {
Expand All @@ -1306,6 +1311,9 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
ZEND_PARSE_PARAMETERS_END();

timeout_argument_offset = 6;
oid_argument_offset = 3;
type_argument_offset = 4;
value_argument_offset = 5;
} else {
/* SNMP_CMD_GET
* SNMP_CMD_GETNEXT
Expand All @@ -1321,6 +1329,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
ZEND_PARSE_PARAMETERS_END();

timeout_argument_offset = 4;
oid_argument_offset = 3;
}
}
} else {
Expand All @@ -1330,6 +1339,8 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
Z_PARAM_ARRAY_HT_OR_STR(type_ht, type_str)
Z_PARAM_ARRAY_HT_OR_STR(value_ht, value_str)
ZEND_PARSE_PARAMETERS_END();
type_argument_offset = 2;
value_argument_offset = 3;
} else if (st & SNMP_CMD_WALK) {
ZEND_PARSE_PARAMETERS_START(1, 4)
Z_PARAM_ARRAY_HT_OR_STR(oid_ht, oid_str)
Expand Down Expand Up @@ -1359,17 +1370,18 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
}
}

if (!php_snmp_parse_oid(getThis(), st, &objid_query, oid_str, oid_ht, type_str, type_ht, value_str, value_ht)) {
if (!php_snmp_parse_oid(getThis(), st, &objid_query, oid_str, oid_ht, type_str, type_ht, value_str, value_ht,
oid_argument_offset, type_argument_offset, value_argument_offset)) {
RETURN_FALSE;
}

if (session_less_mode) {
if (!snmp_session_init(&session, version, a1, a2, timeout, retries, timeout_argument_offset)) {
if (!snmp_session_init(&session, version, a1, a2, timeout, retries, 1, timeout_argument_offset)) {
php_free_objid_query(&objid_query, oid_ht, value_ht, st);
snmp_session_free(&session);
RETURN_FALSE;
}
if (version == SNMP_VERSION_3 && !snmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL, 4)) {
if (version == SNMP_VERSION_3 && !snmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL, 4, 0)) {
php_free_objid_query(&objid_query, oid_ht, value_ht, st);
snmp_session_free(&session);
/* Warning message sent already, just bail out */
Expand Down Expand Up @@ -1664,7 +1676,7 @@ PHP_METHOD(SNMP, __construct)
snmp_session_free(&(snmp_object->session));
}

if (!snmp_session_init(&(snmp_object->session), version, a1, a2, timeout, retries, 4)) {
if (!snmp_session_init(&(snmp_object->session), version, a1, a2, timeout, retries, 2, 4)) {
return;
}
snmp_object->max_oids = 0;
Expand Down Expand Up @@ -1738,7 +1750,7 @@ PHP_METHOD(SNMP, setSecurity)
RETURN_THROWS();
}

if (!snmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7, 2)) {
if (!snmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7, 2, 7)) {
Comment thread
prateekbhujel marked this conversation as resolved.
/* Warning message sent already, just bail out */
Comment thread
prateekbhujel marked this conversation as resolved.
Outdated
RETURN_FALSE;
}
Expand Down
4 changes: 2 additions & 2 deletions ext/snmp/tests/gh16959.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,5 @@ array(4) {
}
Object of class stdClass could not be converted to string
Object of class stdClass could not be converted to string
Type must be a single character
Type must be a single character
snmp2_set(): Argument #4 ($type) must be a single character
snmp2_set(): Argument #4 ($type) must be a single character
10 changes: 6 additions & 4 deletions ext/snmp/tests/ipv6.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ snmp_set_quick_print(false);
snmp_set_valueretrieval(SNMP_VALUE_PLAIN);

var_dump(snmpget($hostname6_port, $community, '.1.3.6.1.2.1.1.1.0'));
var_dump(snmpget('[dead:beef::', $community, '.1.3.6.1.2.1.1.1.0'));
try {
var_dump(snmpget('[dead:beef::', $community, '.1.3.6.1.2.1.1.1.0'));
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
?>
--EXPECTF--
string(%d) "%s"

Warning: snmpget(): Malformed IPv6 address, closing square bracket missing in %s on line %d
bool(false)
snmpget(): Argument #1 ($hostname) has a malformed IPv6 address, closing square bracket missing
10 changes: 6 additions & 4 deletions ext/snmp/tests/snmp-object-setSecurity_error.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ try {

var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', ''));
var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', 'ty'));
var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', 'test12345', 'context', 'dsa'));
try {
var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', 'test12345', 'context', 'dsa'));
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}

var_dump($session->close());

Expand All @@ -76,7 +80,5 @@ bool(false)

Warning: SNMP::setSecurity(): Error generating a key for privacy pass phrase 'ty': Generic error (The supplied password length is too short.) in %s on line %d
bool(false)

Warning: SNMP::setSecurity(): Bad engine ID value 'dsa' in %s on line %d
bool(false)
SNMP::setSecurity(): Argument #7 ($contextEngineId) must be a valid context engine ID
bool(true)
2 changes: 1 addition & 1 deletion ext/snmp/tests/snmp2_get.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ var_dump(snmp2_get($hostname, $community, array('.1.3.6.1.2.1.1.1.0', '.1.3.6.1.
--EXPECTF--
Checking error handling
Empty OID array
Array of object IDs must not be empty
snmp2_get(): Argument #3 ($object_id) must not be empty when passed as an array
Checking working
Single OID
string(%d) "%s"
Expand Down
30 changes: 17 additions & 13 deletions ext/snmp/tests/snmp2_set.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,22 @@ var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $ol
var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));

echo "Multiple OID, single type in array, multiple value\n";
$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s'), array($newvalue1, $newvalue2), $timeout, $retries);
var_dump($z);
try {
$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s'), array($newvalue1, $newvalue2), $timeout, $retries);
var_dump($z);
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));

echo "Multiple OID & type, single value in array\n";
$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s', 's'), array($newvalue1), $timeout, $retries);
var_dump($z);
try {
$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s', 's'), array($newvalue1), $timeout, $retries);
var_dump($z);
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));

Expand Down Expand Up @@ -167,7 +175,7 @@ var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $ol
--EXPECTF--
Check error handing
No type & no value (timeout & retries instead)
Type must be a single character
snmp2_set(): Argument #4 ($type) must be a single character
No value (timeout instead), retries instead of timeout

Warning: snmp2_set(): Could not add variable: OID='%s' type='q' value='%i': Bad variable type ("q") in %s on line %d
Expand Down Expand Up @@ -216,23 +224,19 @@ Value must be of type string when object ID is a string
bool(true)
bool(true)
Multiple OID, 1st wrong type
Type must be a single character
snmp2_set(): Argument #4 ($type) must be a single character
bool(true)
bool(true)
Multiple OID, 2nd wrong type
Type must be a single character
snmp2_set(): Argument #4 ($type) must be a single character
bool(true)
bool(true)
Multiple OID, single type in array, multiple value

Warning: snmp2_set(): '%s': no type set in %s on line %d
bool(false)
snmp2_set(): Argument #4 ($type) must contain a type for object ID 'SNMPv2-MIB::sysLocation.0'
bool(true)
bool(true)
Multiple OID & type, single value in array

Warning: snmp2_set(): '%s': no value set in %s on line %d
bool(false)
snmp2_set(): Argument #5 ($value) must contain a value for object ID 'SNMPv2-MIB::sysLocation.0'
bool(true)
bool(true)
Multiple OID, 1st bogus, single type, multiple value
Expand Down
Loading
Loading