/*******************************************************************-o-****** * snmp_comstr_parse * * Parameters: * *data (I) Message. * *length (I/O) Bytes left in message. * *psid (O) Community string. * *slen (O) Length of community string. * *version (O) Message version. * * Returns: * Pointer to the remainder of data. * * * Parse the header of a community string-based message such as that found * in SNMPv1 and SNMPv2c. */ u_char * snmp_comstr_parse(u_char * data, size_t * length, u_char * psid, size_t * slen, long *version) { u_char type; long ver; size_t origlen = *slen; /* * Message is an ASN.1 SEQUENCE. */ data = asn_parse_sequence(data, length, &type, (ASN_SEQUENCE | ASN_CONSTRUCTOR), "auth message"); if (data == NULL) { return NULL; } /* * First field is the version. */ DEBUGDUMPHEADER("recv", "SNMP version"); data = asn_parse_int(data, length, &type, &ver, sizeof(ver)); DEBUGINDENTLESS(); *version = ver; if (data == NULL) { ERROR_MSG("bad parse of version"); return NULL; } /* * second field is the community string for SNMPv1 & SNMPv2c */ DEBUGDUMPHEADER("recv", "community string"); data = asn_parse_string(data, length, &type, psid, slen); DEBUGINDENTLESS(); if (data == NULL) { ERROR_MSG("bad parse of community"); return NULL; } psid[SNMP_MIN(*slen, origlen - 1)] = '\0'; return (u_char *) data; } /* end snmp_comstr_parse() */
int localsm_rgenerate_out_msg(struct snmp_secmod_outgoing_params *parms) { u_char **wholeMsg = parms->wholeMsg; size_t *offset = parms->wholeMsgOffset; int rc; size_t *wholeMsgLen = parms->wholeMsgLen; DEBUGMSGTL(("localsm", "Starting LOCALSM processing\n")); /* * We define here what the security message section will look like: * 04 00 -- null string * XXX: need to actually negotiate a context engine ID? * XXX: leave room for future expansion just in case? */ DEBUGDUMPHEADER("send", "localsm security parameters"); rc = asn_realloc_rbuild_header(wholeMsg, wholeMsgLen, offset, 1, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), 0); DEBUGINDENTLESS(); if (rc == 0) { DEBUGMSGTL(("localsm", "building msgSecurityParameters failed.\n")); return SNMPERR_TOO_LONG; } /* * Copy in the msgGlobalData and msgVersion. */ while ((*wholeMsgLen - *offset) < parms->globalDataLen) { if (!asn_realloc(wholeMsg, wholeMsgLen)) { DEBUGMSGTL(("localsm", "building global data failed.\n")); return SNMPERR_TOO_LONG; } } *offset += parms->globalDataLen; memcpy(*wholeMsg + *wholeMsgLen - *offset, parms->globalData, parms->globalDataLen); /* * Total packet sequence. */ rc = asn_realloc_rbuild_sequence(wholeMsg, wholeMsgLen, offset, 1, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), *offset); if (rc == 0) { DEBUGMSGTL(("localsm", "building master packet sequence failed.\n")); return SNMPERR_TOO_LONG; } DEBUGMSGTL(("localsm", "LOCALSM processing completed.\n")); return SNMPERR_SUCCESS; }
u_char * _docsis_snmp_build_var_op(u_char * data, oid * var_name, size_t * var_name_len, u_char var_val_type, size_t var_val_len, u_char * var_val, size_t * listlength) { size_t dummyLen, headerLen; u_char *dataPtr; dummyLen = *listlength; dataPtr = data; #if 0 data = asn_build_sequence(data, &dummyLen, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); if (data == NULL) { return NULL; } #endif if (dummyLen < 2) return NULL; data += 2; dummyLen -= 2; headerLen = data - dataPtr; *listlength -= headerLen; DEBUGDUMPHEADER("send", "Name"); data = asn_build_objid(data, listlength, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), var_name, *var_name_len); DEBUGINDENTLESS(); if (data == NULL) { ERROR_MSG("Can't build OID for variable"); return NULL; } DEBUGDUMPHEADER("send", "Value"); switch (var_val_type) { case ASN_INTEGER: data = asn_build_int(data, listlength, var_val_type, (long *) var_val, var_val_len); break; case ASN_GAUGE: case ASN_COUNTER: case ASN_TIMETICKS: case ASN_UINTEGER: data = asn_build_unsigned_int(data, listlength, var_val_type, (u_long *) var_val, var_val_len); break; #ifdef OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_COUNTER64: case ASN_OPAQUE_U64: #endif case ASN_COUNTER64: data = asn_build_unsigned_int64(data, listlength, var_val_type, (struct counter64 *) var_val, var_val_len); break; case ASN_OCTET_STR: case ASN_IPADDRESS: case ASN_OPAQUE: case ASN_NSAP: data = asn_build_string(data, listlength, var_val_type, var_val, var_val_len); break; case ASN_OBJECT_ID: data = asn_build_objid(data, listlength, var_val_type, (oid *) var_val, var_val_len / sizeof(oid)); break; case ASN_NULL: data = asn_build_null(data, listlength, var_val_type); break; case ASN_BIT_STR: data = asn_build_bitstring(data, listlength, var_val_type, var_val, var_val_len); break; case SNMP_NOSUCHOBJECT: case SNMP_NOSUCHINSTANCE: case SNMP_ENDOFMIBVIEW: data = asn_build_null(data, listlength, var_val_type); break; #ifdef OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_FLOAT: data = asn_build_float(data, listlength, var_val_type, (float *) var_val, var_val_len); break; case ASN_OPAQUE_DOUBLE: data = asn_build_double(data, listlength, var_val_type, (double *) var_val, var_val_len); break; case ASN_OPAQUE_I64: data = asn_build_signed_int64(data, listlength, var_val_type, (struct counter64 *) var_val, var_val_len); break; #endif /* OPAQUE_SPECIAL_TYPES */ default: ERROR_MSG("wrong type"); return NULL; } DEBUGINDENTLESS(); if (data == NULL) { ERROR_MSG("Can't build value"); return NULL; } dummyLen = (data - dataPtr) - headerLen; _docsis_asn_build_sequence(dataPtr, &dummyLen, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), dummyLen); return data; }
int tsm_rgenerate_out_msg(struct snmp_secmod_outgoing_params *parms) { u_char **wholeMsg = parms->wholeMsg; size_t *offset = parms->wholeMsgOffset; int rc; size_t *wholeMsgLen = parms->wholeMsgLen; netsnmp_tsmSecurityReference *tsmSecRef; netsnmp_tmStateReference *tmStateRef; DEBUGMSGTL(("tsm", "Starting TSM processing\n")); /* if we have this, this message is in response to something that came in earlier */ tsmSecRef = parms->secStateRef; if (tsmSecRef) { /* section 4.2, step 1 */ if (tsmSecRef->tmStateRef) tmStateRef = tsmSecRef->tmStateRef; else tmStateRef = SNMP_MALLOC_TYPEDEF(netsnmp_tmStateReference); if (NULL == tmStateRef) { snmp_log(LOG_ERR, "failed to allocate a tmStateReference\n"); return SNMPERR_GENERR; } tmStateRef->sameSecurity = NETSNMP_TM_USE_SAME_SECURITY; tmStateRef->requestedSecurityLevel = tsmSecRef->securityLevel; /* XXX: this may be freed automatically later by the library? */ SNMP_FREE(parms->secStateRef); } else { /* section 4.2, step 2 */ tmStateRef = SNMP_MALLOC_TYPEDEF(netsnmp_tmStateReference); if (tmStateRef == NULL) { return SNMPERR_GENERR; } tmStateRef->requestedSecurityLevel = parms->secLevel; tmStateRef->sameSecurity = NETSNMP_TM_SAME_SECURITY_NOT_REQUIRED; if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_LIB_TSM_USE_PREFIX)) { /* XXX: probably shouldn't be a hard-coded list of supported transports */ const char *prefix; if (strncmp("ssh:",parms->session->peername,4) == 0) prefix = "ssh:"; else if (strncmp("dtls:",parms->session->peername,4) == 0) prefix = "dtls:"; else return SNMPERR_GENERR; /* a: - lookup the prefix */ /* - if DNE, snmpTsmUnknownPrefixes++ and bail */ if (!prefix) { /* snmpTsmUnknownPrefixes++ */ return SNMPERR_GENERR; } /* - If secName doesn't have the prefix (or any): snmpTsmInvalidPrefixes++ and bail */ if (strchr(parms->secName, ':') == 0 || strlen(prefix)+1 >= parms->secNameLen || strncmp(parms->secName, prefix, strlen(prefix)) != 0 || parms->secName[strlen(prefix)] != ':') { /* snmpTsmInvalidPrefixes++ */ return SNMPERR_GENERR; } /* - Strip the prefix and trailing : */ /* set tmSecurityName to securityName minus stripped part */ memcpy(tmStateRef->securityName, parms->secName + strlen(prefix) + 1, parms->secNameLen - strlen(prefix) - 1); tmStateRef->securityNameLen = parms->secNameLen - strlen(prefix) -1; } else { /* set tmSecurityName to securityName */ memcpy(tmStateRef->securityName, parms->secName, parms->secNameLen); tmStateRef->securityNameLen = parms->secNameLen; } } tmStateRef->securityName[tmStateRef->securityNameLen] = '\0'; /* Section 4.2, Step 3: * - Set securityParameters to a zero-length OCTET STRING ('0400') * * We define here what the security message section will look like: * 04 00 -- null string */ DEBUGDUMPHEADER("send", "tsm security parameters"); rc = asn_realloc_rbuild_header(wholeMsg, wholeMsgLen, offset, 1, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), 0); DEBUGINDENTLESS(); if (rc == 0) { DEBUGMSGTL(("tsm", "building msgSecurityParameters failed.\n")); return SNMPERR_TOO_LONG; } /* Section 4.2, Step 4: * Combine the message parts into a wholeMsg and calculate wholeMsgLen */ /* * Copy in the msgGlobalData and msgVersion. */ while ((*wholeMsgLen - *offset) < parms->globalDataLen) { if (!asn_realloc(wholeMsg, wholeMsgLen)) { DEBUGMSGTL(("tsm", "building global data failed.\n")); return SNMPERR_TOO_LONG; } } *offset += parms->globalDataLen; memcpy(*wholeMsg + *wholeMsgLen - *offset, parms->globalData, parms->globalDataLen); /* * Total packet sequence. */ rc = asn_realloc_rbuild_sequence(wholeMsg, wholeMsgLen, offset, 1, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), *offset); if (rc == 0) { DEBUGMSGTL(("tsm", "building master packet sequence failed.\n")); return SNMPERR_TOO_LONG; } /* Section 4.2 Step 5: return everything */ if (parms->pdu->transport_data && parms->pdu->transport_data != tmStateRef) { snmp_log(LOG_ERR, "tsm: needed to free transport data\n"); SNMP_FREE(parms->pdu->transport_data); } /* put the transport state reference into the PDU for the transport */ if (SNMPERR_SUCCESS != memdup(&parms->pdu->transport_data, tmStateRef, sizeof(*tmStateRef))) { snmp_log(LOG_ERR, "tsm: malloc failure\n"); } parms->pdu->transport_data_length = sizeof(*tmStateRef); DEBUGMSGTL(("tsm", "TSM processing completed.\n")); return SNMPERR_SUCCESS; }
int tsm_rgenerate_out_msg(struct snmp_secmod_outgoing_params *parms) { u_char **wholeMsg = parms->wholeMsg; size_t *offset = parms->wholeMsgOffset; int rc; size_t *wholeMsgLen = parms->wholeMsgLen; netsnmp_tsmSecurityReference *tsmSecRef; netsnmp_tmStateReference *tmStateRef; int tmStateRefLocal = 0; DEBUGMSGTL(("tsm", "Starting TSM processing\n")); /* if we have this, then this message to be sent is in response to something that came in earlier and the tsmSecRef was created by the tsm_process_in_msg. */ tsmSecRef = parms->secStateRef; if (tsmSecRef) { /* 4.2, step 1: If there is a securityStateReference (Response or Report message), then this Security Model uses the cached information rather than the information provided by the ASI. */ /* 4.2, step 1: Extract the tmStateReference from the securityStateReference cache. */ netsnmp_assert_or_return(NULL != tsmSecRef->tmStateRef, SNMPERR_GENERR); tmStateRef = tsmSecRef->tmStateRef; /* 4.2 step 1: Set the tmRequestedSecurityLevel to the value of the extracted tmTransportSecurityLevel. */ tmStateRef->requestedSecurityLevel = tmStateRef->transportSecurityLevel; /* 4.2 step 1: Set the tmSameSecurity parameter in the tmStateReference cache to true. */ tmStateRef->sameSecurity = NETSNMP_TM_USE_SAME_SECURITY; /* 4.2 step 1: The cachedSecurityData for this message can now be discarded. */ SNMP_FREE(parms->secStateRef); } else { /* 4.2, step 2: If there is no securityStateReference (e.g., a Request-type or Notification message), then create a tmStateReference cache. */ tmStateRef = SNMP_MALLOC_TYPEDEF(netsnmp_tmStateReference); netsnmp_assert_or_return(NULL != tmStateRef, SNMPERR_GENERR); tmStateRefLocal = 1; /* XXX: we don't actually use this really in our implementation */ /* 4.2, step 2: Set tmTransportDomain to the value of transportDomain, tmTransportAddress to the value of transportAddress */ /* 4.2, step 2: and tmRequestedSecurityLevel to the value of securityLevel. */ tmStateRef->requestedSecurityLevel = parms->secLevel; /* 4.2, step 2: Set the transaction-specific tmSameSecurity parameter to false. */ tmStateRef->sameSecurity = NETSNMP_TM_SAME_SECURITY_NOT_REQUIRED; if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_TSM_USE_PREFIX)) { /* XXX: probably shouldn't be a hard-coded list of supported transports */ /* 4.2, step 2: If the snmpTsmConfigurationUsePrefix object is set to true, then use the transportDomain to look up the corresponding prefix. */ const char *prefix; if (strncmp("ssh:",parms->session->peername,4) == 0) prefix = "ssh:"; else if (strncmp("dtls:",parms->session->peername,5) == 0) prefix = "dtls:"; else if (strncmp("tls:",parms->session->peername,4) == 0) prefix = "tls:"; else { /* 4.2, step 2: If the prefix lookup fails for any reason, then the snmpTsmUnknownPrefixes counter is incremented, an error indication is returned to the calling module, and message processing stops. */ snmp_increment_statistic(STAT_TSM_SNMPTSMUNKNOWNPREFIXES); SNMP_FREE(tmStateRef); return SNMPERR_GENERR; } /* 4.2, step 2: If the lookup succeeds, but there is no prefix in the securityName, or the prefix returned does not match the prefix in the securityName, or the length of the prefix is less than 1 or greater than 4 US-ASCII alpha-numeric characters, then the snmpTsmInvalidPrefixes counter is incremented, an error indication is returned to the calling module, and message processing stops. */ if (strchr(parms->secName, ':') == 0 || strlen(prefix)+1 >= parms->secNameLen || strncmp(parms->secName, prefix, strlen(prefix)) != 0 || parms->secName[strlen(prefix)] != ':') { /* Note: since we're assiging the prefixes above the prefix lengths always meet the 1-4 criteria */ snmp_increment_statistic(STAT_TSM_SNMPTSMINVALIDPREFIXES); SNMP_FREE(tmStateRef); return SNMPERR_GENERR; } /* 4.2, step 2: Strip the transport-specific prefix and trailing ':' character (US-ASCII 0x3a) from the securityName. Set tmSecurityName to the value of securityName. */ memcpy(tmStateRef->securityName, parms->secName + strlen(prefix) + 1, parms->secNameLen - strlen(prefix) - 1); tmStateRef->securityNameLen = parms->secNameLen - strlen(prefix) -1; } else { /* 4.2, step 2: If the snmpTsmConfigurationUsePrefix object is set to false, then set tmSecurityName to the value of securityName. */ memcpy(tmStateRef->securityName, parms->secName, parms->secNameLen); tmStateRef->securityNameLen = parms->secNameLen; } } /* truncate the security name with a '\0' for safety */ tmStateRef->securityName[tmStateRef->securityNameLen] = '\0'; /* 4.2, step 3: Set securityParameters to a zero-length OCTET * STRING ('0400'). */ DEBUGDUMPHEADER("send", "tsm security parameters"); rc = asn_realloc_rbuild_header(wholeMsg, wholeMsgLen, offset, 1, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), 0); DEBUGINDENTLESS(); if (rc == 0) { DEBUGMSGTL(("tsm", "building msgSecurityParameters failed.\n")); if (tmStateRefLocal) SNMP_FREE(tmStateRef); return SNMPERR_TOO_LONG; } /* 4.2, step 4: Combine the message parts into a wholeMsg and calculate wholeMsgLength. */ while ((*wholeMsgLen - *offset) < parms->globalDataLen) { if (!asn_realloc(wholeMsg, wholeMsgLen)) { DEBUGMSGTL(("tsm", "building global data failed.\n")); if (tmStateRefLocal) SNMP_FREE(tmStateRef); return SNMPERR_TOO_LONG; } } *offset += parms->globalDataLen; memcpy(*wholeMsg + *wholeMsgLen - *offset, parms->globalData, parms->globalDataLen); /* 4.2, step 5: The wholeMsg, wholeMsgLength, securityParameters, and tmStateReference are returned to the calling Message Processing Model with the statusInformation set to success. */ /* For the Net-SNMP implemantion that actually means we start encoding the full packet sequence from here before returning it */ /* * Total packet sequence. */ rc = asn_realloc_rbuild_sequence(wholeMsg, wholeMsgLen, offset, 1, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), *offset); if (rc == 0) { DEBUGMSGTL(("tsm", "building master packet sequence failed.\n")); if (tmStateRefLocal) SNMP_FREE(tmStateRef); return SNMPERR_TOO_LONG; } if (parms->pdu->transport_data && parms->pdu->transport_data != tmStateRef) { snmp_log(LOG_ERR, "tsm: needed to free transport data\n"); SNMP_FREE(parms->pdu->transport_data); } /* put the transport state reference into the PDU for the transport */ parms->pdu->transport_data = netsnmp_memdup(tmStateRef, sizeof(*tmStateRef)); if (!parms->pdu->transport_data) snmp_log(LOG_ERR, "tsm: malloc failure\n"); parms->pdu->transport_data_length = sizeof(*tmStateRef); if (tmStateRefLocal) SNMP_FREE(tmStateRef); DEBUGMSGTL(("tsm", "TSM processing completed.\n")); return SNMPERR_SUCCESS; }