def snmp_server(self): """ SNMP server coroutine :return: """ self.logger.info("Stating BEEF SNMP server") yield self.server_iostream.connect() decoder = BERDecoder() encoder = BEREncoder() while True: # Wait for SNMP request request = yield self.server_iostream.read_bytes( self.MAX_REQUEST_SIZE, partial=True) pdu = decoder.parse_sequence(request)[0] self.logger.info("SNMP REQUEST: %r", pdu) version = pdu[0] community = pdu[1] pdu_type = pdu[2][0] request_id = pdu[2][1] if pdu_type == PDU_GET_REQUEST: err_status, err_index, data = self.snmp_get_response(pdu) elif pdu_type == PDU_GETNEXT_REQUEST: err_status, err_index, data = self.snmp_getnext_response(pdu) elif pdu_type == PDU_GETBULK_REQUEST: err_status, err_index, data = self.snmp_getbulk_response(pdu) else: # @todo: Unsupported PDU type pass # Build response resp = encoder.encode_sequence([ encoder.encode_int(version), encoder.encode_octet_string(community), encoder.encode_choice( PDU_RESPONSE, [ encoder.encode_int(request_id), encoder.encode_int(err_status), encoder.encode_int(err_index), encoder.encode_sequence([ encoder.encode_sequence( [encoder.encode_oid(str(oid)), value]) for oid, value in data ]), ], ), ]) self.logger.info("RESPONSE = %r", data) yield self.server_iostream.write(resp)
def test_encode_sequence(data, result): encoder = BEREncoder() assert encoder.encode_sequence(data) == result
def test_encode_choice(tag, data, result): encoder = BEREncoder() assert encoder.encode_choice(tag, data) == result
def test_encode_null(value): encoder = BEREncoder() assert encoder.encode_null() == value
def test_encode_oid(oid, raw): encoder = BEREncoder() assert encoder.encode_oid(oid) == raw
def test_encode_real(raw, value): encoder = BEREncoder() assert encoder.encode_real(raw) == value
def test_encode_int(value, raw): encoder = BEREncoder() assert encoder.encode_int(value) == raw
def test_encode_octet_string(raw, value): encoder = BEREncoder() assert encoder.encode_octet_string(raw) == value
def test_encode_tlv(tag, primitive, data, value): encoder = BEREncoder() assert encoder.encode_tlv(tag, primitive, data) == value
async def send_and_receive( self, data: bytes, address: Tuple[str, int]) -> Tuple[bytes, Tuple[str, int]]: pdu = BERDecoder().parse_sequence(data)[0] self.logger.info("SNMP REQUEST: %r", pdu) version = pdu[0] community = pdu[1] pdu_type = pdu[2][0] request_id = pdu[2][1] if pdu_type == PDU_GET_REQUEST: err_status, err_index, data = self.snmp_get_response(pdu) elif pdu_type == PDU_GETNEXT_REQUEST: err_status, err_index, data = self.snmp_getnext_response(pdu) elif pdu_type == PDU_GETBULK_REQUEST: err_status, err_index, data = self.snmp_getbulk_response(pdu) else: raise ScriptError("Unknown PDU type") # Build response encoder = BEREncoder() response = encoder.encode_sequence([ encoder.encode_int(version), encoder.encode_octet_string(community), encoder.encode_choice( PDU_RESPONSE, [ encoder.encode_int(request_id), encoder.encode_int(err_status), encoder.encode_int(err_index), encoder.encode_sequence([ encoder.encode_sequence( [encoder.encode_oid(str(oid)), smart_bytes(value)]) for oid, value in data ]), ], ), ]) self.logger.info("RESPONSE = %r", data) return response, address