Author: syrinx
Date: Thu Oct 17 11:49:46 2013
New Revision: 256678
URL: http://svnweb.freebsd.org/changeset/base/256678

Log:
  Fix SNMP Error response PDUs and properly encode them when using v3 
auth/encryption.
  
  Reported by:  harti@

Modified:
  head/contrib/bsnmp/lib/snmp.c
  head/contrib/bsnmp/lib/snmp.h
  head/contrib/bsnmp/lib/snmpagent.c

Modified: head/contrib/bsnmp/lib/snmp.c
==============================================================================
--- head/contrib/bsnmp/lib/snmp.c       Thu Oct 17 11:45:31 2013        
(r256677)
+++ head/contrib/bsnmp/lib/snmp.c       Thu Oct 17 11:49:46 2013        
(r256678)
@@ -288,11 +288,13 @@ parse_secparams(struct asn_buf *b, struc
        memset(buf, 0, 256);
        tb.asn_ptr = buf;
        tb.asn_len = 256;
+       u_int len;
 
-       if (asn_get_octetstring(b, buf, &tb.asn_len) != ASN_ERR_OK) {
+       if (asn_get_octetstring(b, buf, &len) != ASN_ERR_OK) {
                snmp_error("cannot parse usm header");
                return (ASN_ERR_FAILED);
        }
+       tb.asn_len = len;
 
        if (asn_get_sequence(&tb, &octs_len) != ASN_ERR_OK) {
                snmp_error("cannot decode usm header");
@@ -864,7 +866,7 @@ snmp_fix_encoding(struct asn_buf *b, str
                        return (SNMP_CODE_FAILED);
 
                pdu->scoped_len = b->asn_ptr - pdu->scoped_ptr;
-               if ((code = snmp_pdu_fix_padd(b, pdu))!= ASN_ERR_OK)
+               if (snmp_pdu_fix_padd(b, pdu) != ASN_ERR_OK)
                        return (SNMP_CODE_FAILED);
 
                if (pdu->security_model != SNMP_SECMODEL_USM)
@@ -997,7 +999,7 @@ snmp_pdu_encode(struct snmp_pdu *pdu, st
        if ((err = snmp_pdu_encode_header(resp_b, pdu)) != SNMP_CODE_OK)
                return (err);
        for (idx = 0; idx < pdu->nbindings; idx++)
-               if ((err = snmp_binding_encode(resp_b, &pdu->bindings[idx]))
+               if (snmp_binding_encode(resp_b, &pdu->bindings[idx])
                    != ASN_ERR_OK)
                        return (SNMP_CODE_FAILED);
 

Modified: head/contrib/bsnmp/lib/snmp.h
==============================================================================
--- head/contrib/bsnmp/lib/snmp.h       Thu Oct 17 11:45:31 2013        
(r256677)
+++ head/contrib/bsnmp/lib/snmp.h       Thu Oct 17 11:49:46 2013        
(r256678)
@@ -182,7 +182,7 @@ struct snmp_pdu {
 
        /* fixes for encoding */
        size_t                  outer_len;
-       size_t                  scoped_len;
+       asn_len_t               scoped_len;
        u_char                  *outer_ptr;
        u_char                  *digest_ptr;
        u_char                  *encrypted_ptr;

Modified: head/contrib/bsnmp/lib/snmpagent.c
==============================================================================
--- head/contrib/bsnmp/lib/snmpagent.c  Thu Oct 17 11:45:31 2013        
(r256677)
+++ head/contrib/bsnmp/lib/snmpagent.c  Thu Oct 17 11:49:46 2013        
(r256678)
@@ -166,7 +166,7 @@ find_subnode(const struct snmp_value *va
 }
 
 static void
-snmp_pdu_create_response(struct snmp_pdu *pdu, struct snmp_pdu *resp)
+snmp_pdu_create_response(const struct snmp_pdu *pdu, struct snmp_pdu *resp)
 {
        memset(resp, 0, sizeof(*resp));
        strcpy(resp->community, pdu->community);
@@ -952,18 +952,57 @@ enum snmp_ret
 snmp_make_errresp(const struct snmp_pdu *pdu, struct asn_buf *pdu_b,
     struct asn_buf *resp_b)
 {
+       u_char type;
        asn_len_t len;
        struct snmp_pdu resp;
        enum asn_err err;
        enum snmp_code code;
 
-       memset(&resp, 0, sizeof(resp));
+       snmp_pdu_create_response(pdu, &resp);
+
        if ((code = snmp_pdu_decode_header(pdu_b, &resp)) != SNMP_CODE_OK)
                return (SNMP_RET_IGN);
 
-       if (pdu_b->asn_len < len)
+       if (pdu->version == SNMP_V3) {
+               if (resp.user.priv_proto != SNMP_PRIV_NOPRIV &&
+                  (asn_get_header(pdu_b, &type, &resp.scoped_len) != ASN_ERR_OK
+                  || type != ASN_TYPE_OCTETSTRING)) {
+                       snmp_error("cannot decode encrypted pdu");
+                       return (SNMP_RET_IGN);
+               }
+
+               if (asn_get_sequence(pdu_b, &len) != ASN_ERR_OK) {
+                       snmp_error("cannot decode scoped pdu header");
+                       return (SNMP_RET_IGN);
+               }
+
+               len = SNMP_ENGINE_ID_SIZ;
+               if (asn_get_octetstring(pdu_b, (u_char *)resp.context_engine,
+                   &len) != ASN_ERR_OK) {
+                       snmp_error("cannot decode msg context engine");
+                       return (SNMP_RET_IGN);
+               }
+               resp.context_engine_len = len;
+               len = SNMP_CONTEXT_NAME_SIZ;
+               if (asn_get_octetstring(pdu_b, (u_char *)resp.context_name,
+                   &len) != ASN_ERR_OK) {
+                       snmp_error("cannot decode msg context name");
+                       return (SNMP_RET_IGN);
+               }
+               resp.context_name[len] = '\0';
+       }
+
+
+       if (asn_get_header(pdu_b, &type, &len) != ASN_ERR_OK) {
+               snmp_error("cannot get pdu header");
                return (SNMP_RET_IGN);
-       pdu_b->asn_len = len;
+       }
+
+       if ((type & ~ASN_TYPE_MASK) !=
+           (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT)) {
+               snmp_error("bad pdu header tag");
+               return (SNMP_RET_IGN);
+       }
 
        err = snmp_parse_pdus_hdr(pdu_b, &resp, &len);
        if (ASN_ERR_STOPPED(err))
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to