Skip to content

Commit 5f881d3

Browse files
committed
libsnmp, USM: Introduce a reference count in struct usmStateReference
This patch fixes https://sourceforge.net/p/net-snmp/bugs/2956/.
1 parent cae2cb0 commit 5f881d3

File tree

2 files changed

+53
-42
lines changed

2 files changed

+53
-42
lines changed

Diff for: snmplib/snmp_client.c

+5-17
Original file line numberDiff line numberDiff line change
@@ -405,28 +405,16 @@ _clone_pdu_header(netsnmp_pdu *pdu)
405405
return NULL;
406406
}
407407

408-
if (pdu->securityStateRef &&
409-
pdu->command == SNMP_MSG_TRAP2) {
410-
411-
netsnmp_assert(pdu->securityModel == SNMP_DEFAULT_SECMODEL);
412-
ret = usm_clone_usmStateReference((struct usmStateReference *) pdu->securityStateRef,
413-
(struct usmStateReference **) &newpdu->securityStateRef );
414-
415-
if (ret)
416-
{
408+
sptr = find_sec_mod(newpdu->securityModel);
409+
if (sptr && sptr->pdu_clone) {
410+
/* call security model if it needs to know about this */
411+
ret = sptr->pdu_clone(pdu, newpdu);
412+
if (ret) {
417413
snmp_free_pdu(newpdu);
418414
return NULL;
419415
}
420416
}
421417

422-
if ((sptr = find_sec_mod(newpdu->securityModel)) != NULL &&
423-
sptr->pdu_clone != NULL) {
424-
/*
425-
* call security model if it needs to know about this
426-
*/
427-
(*sptr->pdu_clone) (pdu, newpdu);
428-
}
429-
430418
return newpdu;
431419
}
432420

Diff for: snmplib/snmpusm.c

+48-25
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ netsnmp_feature_child_of(usm_support, usm_all)
8585
netsnmp_feature_require(usm_support)
8686

8787
struct usmStateReference {
88+
int refcnt;
8889
char *usr_name;
8990
size_t usr_name_length;
9091
u_char *usr_engine_id;
@@ -280,42 +281,63 @@ free_enginetime_on_shutdown(int majorid, int minorid, void *serverarg,
280281
static struct usmStateReference *
281282
usm_malloc_usmStateReference(void)
282283
{
283-
struct usmStateReference *retval = (struct usmStateReference *)
284-
calloc(1, sizeof(struct usmStateReference));
284+
struct usmStateReference *retval;
285+
286+
retval = calloc(1, sizeof(struct usmStateReference));
287+
if (retval)
288+
retval->refcnt = 1;
285289

286290
return retval;
287291
} /* end usm_malloc_usmStateReference() */
288292

293+
static int
294+
usm_clone(netsnmp_pdu *pdu, netsnmp_pdu *new_pdu)
295+
{
296+
struct usmStateReference *ref = pdu->securityStateRef;
297+
struct usmStateReference **new_ref =
298+
(struct usmStateReference **)&new_pdu->securityStateRef;
299+
int ret = 0;
300+
301+
if (!ref)
302+
return ret;
303+
304+
if (pdu->command == SNMP_MSG_TRAP2) {
305+
netsnmp_assert(pdu->securityModel == SNMP_DEFAULT_SECMODEL);
306+
ret = usm_clone_usmStateReference(ref, new_ref);
307+
} else {
308+
netsnmp_assert(ref == *new_ref);
309+
ref->refcnt++;
310+
}
311+
312+
return ret;
313+
}
314+
289315
static void
290316
usm_free_usmStateReference(void *old)
291317
{
292-
struct usmStateReference *old_ref = (struct usmStateReference *) old;
293-
294-
if (old_ref) {
295-
296-
if (old_ref->usr_name_length)
297-
SNMP_FREE(old_ref->usr_name);
298-
if (old_ref->usr_engine_id_length)
299-
SNMP_FREE(old_ref->usr_engine_id);
300-
if (old_ref->usr_auth_protocol_length)
301-
SNMP_FREE(old_ref->usr_auth_protocol);
302-
if (old_ref->usr_priv_protocol_length)
303-
SNMP_FREE(old_ref->usr_priv_protocol);
304-
305-
if (old_ref->usr_auth_key_length && old_ref->usr_auth_key) {
306-
SNMP_ZERO(old_ref->usr_auth_key, old_ref->usr_auth_key_length);
307-
SNMP_FREE(old_ref->usr_auth_key);
308-
}
309-
if (old_ref->usr_priv_key_length && old_ref->usr_priv_key) {
310-
SNMP_ZERO(old_ref->usr_priv_key, old_ref->usr_priv_key_length);
311-
SNMP_FREE(old_ref->usr_priv_key);
312-
}
318+
struct usmStateReference *ref = old;
319+
320+
if (!ref)
321+
return;
322+
323+
if (--ref->refcnt > 0)
324+
return;
313325

314-
SNMP_ZERO(old_ref, sizeof(*old_ref));
315-
SNMP_FREE(old_ref);
326+
SNMP_FREE(ref->usr_name);
327+
SNMP_FREE(ref->usr_engine_id);
328+
SNMP_FREE(ref->usr_auth_protocol);
329+
SNMP_FREE(ref->usr_priv_protocol);
316330

331+
if (ref->usr_auth_key_length && ref->usr_auth_key) {
332+
SNMP_ZERO(ref->usr_auth_key, ref->usr_auth_key_length);
333+
SNMP_FREE(ref->usr_auth_key);
334+
}
335+
if (ref->usr_priv_key_length && ref->usr_priv_key) {
336+
SNMP_ZERO(ref->usr_priv_key, ref->usr_priv_key_length);
337+
SNMP_FREE(ref->usr_priv_key);
317338
}
318339

340+
SNMP_FREE(ref);
319341
} /* end usm_free_usmStateReference() */
320342

321343
struct usmUser *
@@ -4916,6 +4938,7 @@ init_usm(void)
49164938
def->encode_reverse = usm_secmod_rgenerate_out_msg;
49174939
def->encode_forward = usm_secmod_generate_out_msg;
49184940
def->decode = usm_secmod_process_in_msg;
4941+
def->pdu_clone = usm_clone;
49194942
def->pdu_free_state_ref = usm_free_usmStateReference;
49204943
def->session_setup = usm_session_init;
49214944
def->handle_report = usm_handle_report;

0 commit comments

Comments
 (0)