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)
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
def test_encode_int(value, raw): encoder = BEREncoder() assert encoder.encode_int(value) == raw