1 /* Copyright (c) 2007 by Errata Security */
\r
3 #include "netframe.h"
\r
13 const unsigned char *community;
\r
14 unsigned community_length;
\r
15 unsigned request_id;
\r
16 unsigned error_index;
\r
17 unsigned error_status;
\r
20 const unsigned snmp_length(struct NetFrame *frame, const unsigned char *px, unsigned length, unsigned *r_offset)
\r
24 if ( (*r_offset >= length)
\r
25 || (px[*r_offset] & 0x80)
\r
26 && ((*r_offset) + (px[*r_offset]&0x7F) >= length)) {
\r
27 FRAMERR(frame, "snmp: truncated\n");
\r
31 result = px[(*r_offset)++];
\r
32 if (result & 0x80) {
\r
33 unsigned length_of_length = result & 0x7F;
\r
34 if (length_of_length == 0) {
\r
35 FRAMERR(frame, "snmp: unexpected value\n");
\r
40 while (length_of_length) {
\r
41 result = result * 256 + px[(*r_offset)++];
\r
42 if (result > 0x10000) {
\r
43 FRAMERR(frame, "snmp: unexpected value\n");
\r
51 const unsigned snmp_integer(struct NetFrame *frame, const unsigned char *px, unsigned length, unsigned *r_offset)
\r
53 unsigned int_length;
\r
56 if (px[(*r_offset)++] != 0x02) {
\r
57 FRAMERR(frame, "snmp: unexpected tag\n");
\r
62 int_length = snmp_length(frame, px, length, r_offset);
\r
63 if (int_length == 0xFFFFffff) {
\r
67 if (*r_offset + int_length > length) {
\r
68 FRAMERR(frame, "snmp: truncated\n");
\r
74 while (int_length--)
\r
75 result = result * 256 + px[(*r_offset)++];
\r
80 static unsigned snmp_tag(const unsigned char *px, unsigned length, unsigned *r_offset)
\r
82 if (*r_offset >= length)
\r
84 return px[(*r_offset)++];
\r
87 void process_snmp(struct Seaper *seap, struct NetFrame *frame, const unsigned char *px, unsigned length)
\r
90 unsigned outer_length;
\r
91 struct SNMP snmp[1];
\r
93 memset(&snmp, 0, sizeof(*snmp));
\r
96 if (snmp_tag(px, length, &offset) != 0x30)
\r
100 outer_length = snmp_length(frame, px, length, &offset);
\r
101 if (length > outer_length + offset)
\r
102 length = outer_length + offset;
\r
105 snmp->version = snmp_integer(frame, px, length, &offset);
\r
106 if (snmp->version != 0)
\r
110 if (snmp_tag(px, length, &offset) != 0x04)
\r
112 snmp->community_length = snmp_length(frame, px, length, &offset);
\r
113 snmp->community = px+offset;
\r
114 offset += snmp->community_length;
\r
117 snmp->pdu_tag = snmp_tag(px, length, &offset);
\r
118 if (snmp->pdu_tag < 0xA0 || 0xA5 < snmp->pdu_tag)
\r
120 outer_length = snmp_length(frame, px, length, &offset);
\r
121 if (length > outer_length + offset)
\r
122 length = outer_length + offset;
\r
125 snmp->request_id = snmp_integer(frame, px, length, &offset);
\r
126 snmp->error_status = snmp_integer(frame, px, length, &offset);
\r
127 snmp->error_index = snmp_integer(frame, px, length, &offset);
\r
130 if (snmp_tag(px, length, &offset) != 0x30)
\r
132 outer_length = snmp_length(frame, px, length, &offset);
\r
133 if (length > outer_length + offset)
\r
134 length = outer_length + offset;
\r
136 /* Var-bind list */
\r
137 while (offset < length) {
\r
138 unsigned varbind_length;
\r
139 unsigned varbind_end;
\r
140 if (px[offset++] != 0x30) {
\r
141 FRAMERR(frame, "snmp: unexpected value\n");
\r
144 varbind_length = snmp_length(frame, px, length, &offset);
\r
145 if (varbind_length == 0xFFFFffff)
\r
147 varbind_end = offset + varbind_length;
\r
148 if (varbind_end > length) {
\r
149 FRAMERR(frame, "snmp: unexpected value\n");
\r
154 if (snmp_tag(px,length,&offset) != 6)
\r
157 unsigned oid_length = snmp_length(frame, px, length, &offset);
\r
158 const unsigned char *oid = px+offset;
\r
159 unsigned value_tag;
\r
160 unsigned value_length;
\r
162 offset += oid_length;
\r
163 if (offset > length)
\r
166 value_tag = snmp_tag(px,length,&offset);
\r
167 value_length = snmp_length(frame, px, length, &offset);
\r
169 switch (snmp->pdu_tag) {
\r
171 process_record(seap,
\r
172 "proto",REC_SZ,"SNMP",-1,
\r
173 "GET", REC_FRAMESRC, frame, -1,
\r
174 "community",REC_PRINTABLE, snmp->community, snmp->community_length,
\r
176 process_record(seap,
\r
177 "proto",REC_SZ,"SNMP",-1,
\r
178 "GET", REC_FRAMESRC, frame, -1,
\r
179 "oid",REC_OID, oid, oid_length,
\r
183 FRAMERR(frame, "snmp: unknown msg type\n");
\r