def handle_session(self): Logger.debug(7, 'Session loop running') self.incoming_message('<?xml version="1.0" encoding="UTF-8"?><hello xmlns="parrot"/>') while True: try: Logger.debug(5,'NETCONF server ready, waiting for next message') msg = self.read_msg() except EOFError: Logger.debug(5,'EOF -- end of session') return except Exception as e: verdict = self.handle_read_exception(e) if verdict == "kill-session": return if verdict == "kill-server": Logger.info('Server terminating') sys.exit(1) # Else keep going try: if("" == msg): Logger.debug(5,'EOF ++ end of session') return if self.incoming_message(msg) == True: return except Exception as e: Logger.error('Exception in server processing: ' + str(e))
def process_instructions(self, reply_msg): def split_processing_instructions(reply_msg): instructions = [] pi_start_marker = '<?parrot ' pi_end_marker = '?>' while True: pi_start = reply_msg.find(pi_start_marker) if pi_start < 0: break pi_end = reply_msg[pi_start:].find(pi_end_marker) if pi_end < 0: return ('bad-processing-instruction', reply_msg[pi_start:pi_start+20]) pi = reply_msg[pi_start+len(pi_start_marker):pi_end] if pi_start: instructions += [('send', reply_msg[:pi_start])] reply_msg = reply_msg[pi_end+len(pi_end_marker):] cmd = pi.split(" ")[0] data = pi[len(cmd)+1:] instructions += [(cmd, data)] if reply_msg: instructions += [('send', reply_msg)] if not instructions: instructions = [('empty-response', None)] return instructions instructions = split_processing_instructions(reply_msg) end_session = False for (cmd, data) in instructions: if cmd == "send": Logger.debug(6, f'Sending {len(data)} bytes', payload=data) self.send_message(data) elif cmd == "ignore": Logger.debug(5, f'Not sending any response') elif cmd == "netconf11": Logger.debug(5, f'Switching to NETCONF 1.1') self.choose_netconf_ver([11]) elif cmd == "netconf10": Logger.debug(5, f'Switching to NETCONF 1.0') self.choose_netconf_ver([10]) elif cmd == "empty-response": Logger.warning(f'Template did not provide any response. Ending the session.') end_session = True elif cmd == "end-session": Logger.info(f'Ending session') end_session = True else: Logger.error(f'Unknown processing instruction "{cmd}" in template. Ending the session.') end_session = True return end_session
def start_subsystem(self, name, transport, channel): Logger.debug( 8, f'NETCONFsubsys: start_subsystem name={name} transport={transport} channel={channel}' ) self.sock = channel Logger.debug(9, 'Started NETCONF server on channel {!r}'.format(channel)) try: self.handle_session() except Exception as e: Logger.error(f'NETCONFsubsys: callback exception {e}') ##raise Logger.debug(8, 'Stopped NETCONF server on channel {!r}'.format(channel))
def handle_connection(self, host_key): try: DoGSSAPIKeyExchange = False t = Transport(self.sock, gss_kex=DoGSSAPIKeyExchange) t.set_subsystem_handler('netconf', self.subsys) t.set_gss_host(socket.getfqdn("")) try: t.load_server_moduli() except: Logger.warning('Failed to load moduli -- gex will be unsupported.') t.add_server_key(host_key) server = Server() t.start_server(server=server) # wait for auth self.channel = t.accept(20) if self.channel is None: Logger.error('No SSH channel') return Logger.info('Waiting for message') server.event.wait(10) Logger.info('Closing') ##self.channel.close() Logger.info('Client connection closed') except ConnectionResetError as e: Logger.debug(5,'Connection reset by peer') except SSHException: Logger.error('SSH negotiation failed, client connection dropped') except Exception as e: Logger.error('Caught exception: ' + str(e.__class__) + ': ' + str(e)) traceback.print_exc() try: t.close() except: pass