Exemple #1
0
/*******************************************************************-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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}