📄 snmp_api.c
字号:
return 0;
}
static void
snmpv3_calc_msg_flags (int sec_level, int msg_command, u_char *flags)
{
*flags = 0;
if (sec_level == SNMP_SEC_LEVEL_AUTHNOPRIV)
*flags = SNMP_MSG_FLAG_AUTH_BIT;
else if (sec_level == SNMP_SEC_LEVEL_AUTHPRIV)
*flags = SNMP_MSG_FLAG_AUTH_BIT | SNMP_MSG_FLAG_PRIV_BIT;
if (SNMP_CMD_CONFIRMED(msg_command)) *flags |= SNMP_MSG_FLAG_RPRT_BIT;
return;
}
static int
snmpv3_verify_msg(struct request_list *rp, struct snmp_pdu *pdu)
{
struct snmp_pdu *rpdu;
if (!rp || !rp->pdu || !pdu) return 0;
/* Reports don't have to match anything according to the spec */
if (pdu->command == SNMP_MSG_REPORT) return 1;
rpdu = rp->pdu;
if (rp->request_id != pdu->reqid || rpdu->reqid != pdu->reqid) return 0;
if (rpdu->version != pdu->version) return 0;
if (rpdu->securityModel != pdu->securityModel) return 0;
if (rpdu->securityLevel != pdu->securityLevel) return 0;
if (rpdu->contextEngineIDLen != pdu->contextEngineIDLen ||
memcmp(rpdu->contextEngineID, pdu->contextEngineID,
pdu->contextEngineIDLen))
return 0;
if (rpdu->contextNameLen != pdu->contextNameLen ||
memcmp(rpdu->contextName, pdu->contextName, pdu->contextNameLen))
return 0;
if (rpdu->securityEngineIDLen != pdu->securityEngineIDLen ||
memcmp(rpdu->securityEngineID, pdu->securityEngineID,
pdu->securityEngineIDLen))
return 0;
if (rpdu->securityNameLen != pdu->securityNameLen ||
memcmp(rpdu->securityName, pdu->securityName, pdu->securityNameLen))
return 0;
return 1;
}
/* SNMPv3
* Takes a session and a pdu and serializes the ASN PDU into the area
* pointed to by packet. out_length is the size of the data area available.
* Returns the length of the completed packet in out_length. If any errors
* occur, -1 is returned. If all goes well, 0 is returned.
*/
static int
snmpv3_build(struct snmp_session *session,
struct snmp_pdu *pdu,
u_char *packet,
size_t *out_length)
{
int ret;
session->s_snmp_errno = 0;
session->s_errno = 0;
/* do validation for PDU types */
switch (pdu->command) {
case SNMP_MSG_RESPONSE:
case SNMP_MSG_TRAP2:
case SNMP_MSG_REPORT:
pdu->flags &= (~UCD_MSG_FLAG_EXPECT_RESPONSE);
/* Fallthrough */
case SNMP_MSG_GET:
case SNMP_MSG_GETNEXT:
case SNMP_MSG_SET:
case SNMP_MSG_INFORM:
if (pdu->errstat == SNMP_DEFAULT_ERRSTAT)
pdu->errstat = 0;
if (pdu->errindex == SNMP_DEFAULT_ERRINDEX)
pdu->errindex = 0;
break;
case SNMP_MSG_GETBULK:
if (pdu->max_repetitions < 0) {
session->s_snmp_errno = SNMPERR_BAD_REPETITIONS;
return -1;
}
if (pdu->non_repeaters < 0) {
session->s_snmp_errno = SNMPERR_BAD_REPEATERS;
return -1;
}
break;
case SNMP_MSG_TRAP:
session->s_snmp_errno = SNMPERR_V1_IN_V2;
return -1;
default:
session->s_snmp_errno = SNMPERR_UNKNOWN_PDU;
return -1;
}
if (pdu->securityEngineIDLen == 0) {
if (session->securityEngineIDLen) {
snmpv3_clone_engineID(&pdu->securityEngineID,
&pdu->securityEngineIDLen,
session->securityEngineID,
session->securityEngineIDLen);
}
}
if (pdu->contextEngineIDLen == 0) {
if (session->contextEngineIDLen) {
snmpv3_clone_engineID(&pdu->contextEngineID,
&pdu->contextEngineIDLen,
session->contextEngineID,
session->contextEngineIDLen);
} else if (pdu->securityEngineIDLen) {
snmpv3_clone_engineID(&pdu->contextEngineID,
&pdu->contextEngineIDLen,
pdu->securityEngineID,
pdu->securityEngineIDLen);
}
}
if (pdu->contextName == NULL) {
if (!session->contextName){
session->s_snmp_errno = SNMPERR_BAD_CONTEXT;
return -1;
}
pdu->contextName = strdup(session->contextName);
if (pdu->contextName == NULL) {
session->s_snmp_errno = SNMPERR_GENERR;
return -1;
}
pdu->contextNameLen = session->contextNameLen;
}
pdu->securityModel = SNMP_SEC_MODEL_USM;
if (pdu->securityNameLen == 0 && pdu->securityName == 0) {
if (session->securityNameLen == 0){
session->s_snmp_errno = SNMPERR_BAD_SEC_NAME;
return -1;
}
pdu->securityName = strdup(session->securityName);
if (pdu->securityName == NULL) {
session->s_snmp_errno = SNMPERR_GENERR;
return -1;
}
pdu->securityNameLen = session->securityNameLen;
}
if (pdu->securityLevel == 0) {
if (session->securityLevel == 0) {
session->s_snmp_errno = SNMPERR_BAD_SEC_LEVEL;
return -1;
}
pdu->securityLevel = session->securityLevel;
}
DEBUGMSGTL(("snmp_build",
"Building SNMPv3 message (secName:\"%s\", secLevel:%s)...\n",
((session->securityName) ? (char *)session->securityName :
((pdu->securityName) ? (char *)pdu->securityName :
"ERROR: undefined")),
usmSecLevelName[pdu->securityLevel]));
ret = snmpv3_packet_build(pdu, packet, out_length, NULL, 0);
if (-1 != ret) {
session->s_snmp_errno = ret;
}
return ret;
} /* end snmpv3_build() */
static u_char *
snmpv3_header_build(struct snmp_pdu *pdu, u_char *packet,
size_t *out_length, size_t length, u_char **msg_hdr_e)
{
u_char *global_hdr, *global_hdr_e;
u_char *cp;
u_char msg_flags;
long max_size;
long sec_model;
u_char *pb, *pb0e;
/* Save current location and build SEQUENCE tag and length placeholder
* for SNMP message sequence (actual length inserted later)
*/
cp = asn_build_sequence(packet, out_length,
(u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), length);
if (cp == NULL) return NULL;
if (msg_hdr_e != NULL)
*msg_hdr_e = cp;
pb0e = cp;
/* store the version field - msgVersion
*/
cp = asn_build_int(cp, out_length,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
(long *) &pdu->version, sizeof(pdu->version));
if (cp == NULL) return NULL;
global_hdr = cp;
/* msgGlobalData HeaderData */
cp = asn_build_sequence(cp, out_length,
(u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0);
if (cp == NULL) return NULL;
global_hdr_e = cp;
/* msgID */
cp = asn_build_int(cp, out_length,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
&pdu->msgid, sizeof(pdu->msgid));
if (cp == NULL) return NULL;
/* msgMaxSize */
max_size = SNMP_MAX_MSG_SIZE;
cp = asn_build_int(cp, out_length,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
&max_size, sizeof(max_size));
if (cp == NULL) return NULL;
/* msgFlags */
snmpv3_calc_msg_flags(pdu->securityLevel, pdu->command, &msg_flags);
cp = asn_build_string(cp, out_length,
(u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),
&msg_flags, sizeof(msg_flags));
if (cp == NULL) return NULL;
/* msgSecurityModel */
sec_model = SNMP_SEC_MODEL_USM;
cp = asn_build_int(cp, out_length,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
&sec_model, sizeof(sec_model));
if (cp == NULL) return NULL;
/* insert actual length of globalData
*/
pb = asn_build_sequence(global_hdr, out_length,
(u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
cp - global_hdr_e);
if (pb == NULL) return NULL;
/* insert the actual length of the entire packet
*/
pb = asn_build_sequence(packet, out_length,
(u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
length + (cp - pb0e));
if (pb == NULL) return NULL;
return cp;
} /* end snmpv3_header_build() */
static u_char *
snmpv3_scopedPDU_header_build(struct snmp_pdu *pdu,
u_char *packet, size_t *out_length,
u_char **spdu_e)
{
size_t init_length;
u_char *scopedPdu, *pb;
init_length = *out_length;
pb = scopedPdu = packet;
pb = asn_build_sequence(pb, out_length,
(u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0);
if (pb == NULL) return NULL;
if (spdu_e)
*spdu_e = pb;
pb = asn_build_string(pb, out_length,
(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),
pdu->contextEngineID, pdu->contextEngineIDLen);
if (pb == NULL) return NULL;
pb = asn_build_string(pb, out_length,
(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR),
(u_char *)pdu->contextName, pdu->contextNameLen);
if (pb == NULL) return NULL;
return pb;
} /* end snmpv3_scopedPDU_header_build() */
/* returns 0 if success, -1 if fail, not 0 if USM build failure */
int
snmpv3_packet_build(struct snmp_pdu *pdu, u_char *packet, size_t *out_length,
u_char *pdu_data, size_t pdu_data_len)
{
u_char *global_data, *sec_params, *spdu_hdr_e;
size_t global_data_len, sec_params_len;
u_char spdu_buf[SNMP_MAX_MSG_SIZE];
size_t spdu_buf_len, spdu_len;
u_char *cp;
int result;
global_data = packet;
/*
* build the headers for the packet, returned addr = start of secParams
*/
sec_params = snmpv3_header_build(pdu, global_data, out_length, 0, NULL);
if (sec_params == NULL) return -1;
global_data_len = sec_params - global_data;
sec_params_len = *out_length; /* length left in packet buf for sec_params */
/*
* build a scopedPDU structure into spdu_buf
*/
spdu_buf_len = SNMP_MAX_MSG_SIZE;
cp = snmpv3_scopedPDU_header_build(pdu,spdu_buf,&spdu_buf_len,&spdu_hdr_e);
if (cp == NULL) return -1;
/* build the PDU structure onto the end of spdu_buf
*/
if (pdu_data) {
memcpy(cp, pdu_data, pdu_data_len);
cp += pdu_data_len;
} else {
cp = snmp_pdu_build(pdu, cp, &spdu_buf_len);
if (cp == NULL) return -1;
}
/*
* re-encode the actual ASN.1 length of the scopedPdu
*/
spdu_len = cp - spdu_hdr_e; /* length of scopedPdu minus ASN.1 headers */
spdu_buf_len = SNMP_MAX_MSG_SIZE;
if (asn_build_sequence(spdu_buf, &spdu_buf_len,
(u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
spdu_len) == NULL)
return -1;
spdu_len = cp - spdu_buf; /* the length of the entire scopedPdu */
/*
* call the security module to possibly encrypt and authenticate the
* message - the entire message to transmitted on the wire is returned
*/
cp = NULL; *out_length = SNMP_MAX_MSG_SIZE;
result =
usm_generate_out_msg(
SNMP_VERSION_3,
global_data, global_data_len,
SNMP_MAX_MSG_SIZE,
SNMP_SEC_MODEL_USM,
pdu->securityEngineID, pdu->securityEngineIDLen,
pdu->securityName, pdu->securityNameLen,
pdu->securityLevel,
spdu_buf, spdu_len,
pdu->securityStateRef,
sec_params, &sec_params_len,
&cp, out_length);
return result;
} /* end snmpv3_packet_build() */
#endif /* CYGPKG_SNMPAGENT_V3_SUPPORT */
/*
* Takes a session and a pdu and serializes the ASN PDU into the area
* pointed to by packet. out_length is the size of the data area available.
* Returns the length of the completed packet in out_length. If any errors
* occur, -1 is returned. If all goes well, 0 is returned.
*/
static int
_snmp_build(struct snmp_session *session,
struct snmp_pdu *pdu,
u_char *packet,
size_t *out_length)
{
u_char *h0, *h0e = 0, *h1;
u_char *cp;
size_t length;
long version;
session->s_snmp_errno = 0;
session->s_errno = 0;
#ifdef CYGPKG_SNMPAGENT_V3_SUPPORT
if (pdu->version == SNMP_VERSION_3)
return snmpv3_build(session, pdu, packet, out_length);
#endif
switch
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -