X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=debug_tools%2Fnetconf_TCP_SSH_hijackingproxy.pl;h=a7125b35a0c74804cdce30388736010566d2db98;hb=c323834583ccbd7fc2b0eac4c3e149f3bb9b2ddc;hp=e4799d66c30f68a916e739f67dbe1e9aa94ecf0a;hpb=89651f6dc27d3d29625e89209181f20d1391ef11;p=transportpce.git diff --git a/debug_tools/netconf_TCP_SSH_hijackingproxy.pl b/debug_tools/netconf_TCP_SSH_hijackingproxy.pl index e4799d66c..a7125b35a 100755 --- a/debug_tools/netconf_TCP_SSH_hijackingproxy.pl +++ b/debug_tools/netconf_TCP_SSH_hijackingproxy.pl @@ -12,6 +12,7 @@ use strict; use warnings; + #use diagnostics; #uncomment this line for more details when encountering warnings use Net::OpenSSH; use FileHandle; @@ -20,15 +21,19 @@ use Getopt::Long qw(:config no_ignore_case bundling); use IO::Socket; use Net::hostent; -my ($host, $help, $usage, $proxy_port, $login, $password, $kidpid, $ssh_subsocket, $simpleproxy, - $pid, $ssh_handle, $client, $server, $capabilities, $hello_message, $verbose); +my ( + $host, $help, $usage, $proxy_port, + $login, $password, $kidpid, $ssh_subsocket, + $simpleproxy, $pid, $ssh_handle, $client, + $server, $capabilities, $hello_message, $verbose +); -GetOptions ( - "h|help" =>\$help, - "p|port=i"=>\$proxy_port, - "s|simpleproxy" =>\$simpleproxy, - "v|verbose" =>\$verbose, - "C|capabilities=s"=>\$capabilities +GetOptions( + "h|help" => \$help, + "p|port=i" => \$proxy_port, + "s|simpleproxy" => \$simpleproxy, + "v|verbose" => \$verbose, + "C|capabilities=s" => \$capabilities ); $usage = " USAGE: netconf_TCP_SSH_hijackproxy.pl [-h|--help] [-p|--port ] [-s|--simpleproxy] [-v|--verbose] [-C|--capabilities ] <[login[:password]@]host[:port]> [login] [password] @@ -59,39 +64,42 @@ if ($help) { exit(0); } -unless (@ARGV >= 1) { +unless ( @ARGV >= 1 ) { print $usage; exit(0); } -($host, $login, $password) = @ARGV; +( $host, $login, $password ) = @ARGV; #netconf default port is no 22 but 830 -if ($host !~ /:[0-9]+$/) { $host.=':830'; } +if ( $host !~ /:[0-9]+$/ ) { $host .= ':830'; } -if (!defined($proxy_port)) { $proxy_port = 9000; } +if ( !defined($proxy_port) ) { $proxy_port = 9000; } -my $connection_string=$host; +my $connection_string = $host; if ($password) { - $connection_string=$login.":".$password."@".$connection_string; -} elsif ($login) { - $connection_string=$login."@".$connection_string; + $connection_string = $login . ":" . $password . "@" . $connection_string; +} +elsif ($login) { + $connection_string = $login . "@" . $connection_string; } #retrieving hello custom file if any -if ((!defined ($simpleproxy))&&(defined ($capabilities))) { - open(CAPABILITIES,'<',$capabilities) or die ("can not open $capabilities") ; +if ( ( !defined($simpleproxy) ) && ( defined($capabilities) ) ) { + open( CAPABILITIES, '<', $capabilities ) + or die("can not open $capabilities"); while () { $hello_message .= $_; } - chop $hello_message; # removing EOF - $hello_message.="]]>]]>"; + chop $hello_message; # removing EOF + $hello_message .= "]]>]]>"; close(CAPABILITIES); } # the following regex are used to modify some part of the server messages relayed to the client # you can adapt it to your needs, some examples have been commented. -my %regex_hash=( +my %regex_hash = ( + # replace oo-device v1.2 by v1.2.1 # 'module=org-openroadm-device&revision=2016-10-14.*<\/capability>'=>'s/&revision=2016-10-14/&revision=2017-02-06/', # 'org-openroadm-device<\/identifier>2016-10-14'=>'s@org-openroadm-device2016-10-14@org-openroadm-device2017-02-06@', @@ -100,105 +108,119 @@ my %regex_hash=( # add the ietf-netconf capability to the hello handshake - without it, ODL netconf mountpoints can not work # '<\/capabilities>'=>'s@@\nurn:ietf:params:xml:ns:yang:ietf-netconf?module=ietf-netconf&revision=2011-06-01\n@', # add the right notifications capabilities to the hello handshake + provide another solution for the ietf-netconf capability - '<\/capabilities>'=>'s@@\nurn:ietf:params:xml:ns:netmod:notification?module=nc-notifications&revision=2008-07-14\nurn:ietf:params:xml:ns:netconf:notification:1.0?module=notifications&revision=2008-07-14\nurn:ietf:params:xml:ns:netconf:base:1.0?module=ietf-netconf&revision=2011-06-01\n@' + '<\/capabilities>' => +'s@@\nurn:ietf:params:xml:ns:netmod:notification?module=nc-notifications&revision=2008-07-14\nurn:ietf:params:xml:ns:netconf:notification:1.0?module=notifications&revision=2008-07-14\nurn:ietf:params:xml:ns:netconf:base:1.0?module=ietf-netconf&revision=2011-06-01\n@' ); -if (defined ($simpleproxy)) { %regex_hash=(); } +if ( defined($simpleproxy) ) { %regex_hash = (); } my %compiled_regex_hash; -foreach my $keyword (keys %regex_hash){ - eval ('$compiled_regex_hash{$keyword}= qr/'.$keyword.'/;'); +foreach my $keyword ( keys %regex_hash ) { + eval( '$compiled_regex_hash{$keyword}= qr/' . $keyword . '/;' ); } -$server = IO::Socket::INET->new( Proto => 'tcp', - LocalPort => $proxy_port, - Listen => SOMAXCONN, - Reuse => 1); +$server = IO::Socket::INET->new( + Proto => 'tcp', + LocalPort => $proxy_port, + Listen => SOMAXCONN, + Reuse => 1 +); die "can't setup server" unless $server; print STDERR "[Proxy server $0 accepting clients: Ctrl-C to stop]\n"; +while ( $client = $server->accept() ) { + $client->autoflush(1); + my $hostinfo = gethostbyaddr( $client->peeraddr ); + printf STDERR "[Incoming connection from %s]\n", + $hostinfo->name || $client->peerhost; -while ($client = $server->accept()) { - $client->autoflush(1); - my $hostinfo = gethostbyaddr($client->peeraddr); - printf STDERR "[Incoming connection from %s]\n", $hostinfo->name || $client->peerhost; + print STDERR "[relaying to " . $connection_string . "]\n"; + $ssh_handle = Net::OpenSSH->new( + $connection_string, + master_opts => [ -o => 'StrictHostKeyChecking=no' ], + timeout => 500, + kill_ssh_on_timeout => 500 + ); -print STDERR "[relaying to ".$connection_string."]\n"; + #netconf requires a specific socket + ( $ssh_subsocket, $pid ) = + $ssh_handle->open2socket( { ssh_opts => '-s' }, 'netconf' ); + die "can't establish connection: exiting\n" unless defined($ssh_subsocket); -$ssh_handle = Net::OpenSSH->new($connection_string, - master_opts => [-o => 'StrictHostKeyChecking=no'], - timeout => 500, kill_ssh_on_timeout => 500); + print STDERR "[Connected]\n"; -#netconf requires a specific socket -($ssh_subsocket, $pid) = $ssh_handle->open2socket({ssh_opts => '-s'}, 'netconf'); -die "can't establish connection: exiting\n" unless defined($ssh_subsocket); + # split the program into two processes, identical twins + die "can't fork: $!" unless defined( $kidpid = fork() ); -print STDERR "[Connected]\n"; + $| = 1; -# split the program into two processes, identical twins -die "can't fork: $!" unless defined($kidpid = fork()); +# the if{} block runs only in the parent process (server output relayed to the client) + if ( !$kidpid ) { -$|=1; + # copy the socket to standard output + my $buf; -# the if{} block runs only in the parent process (server output relayed to the client) -if (!$kidpid) { + if ( defined($hello_message) ) { - # copy the socket to standard output - my $buf; + #retrieve the server hello but do not relay it + while ( my $nread = sysread( $ssh_subsocket, $buf, 400 ) ) { + $ssh_subsocket->flush(); + if ( $buf =~ /]]>]]>/ ) { last } + } + + #send a custom hello message instead + print $client $hello_message; + if ( defined($verbose) ) { print STDOUT $hello_message; } + } - if (defined ($hello_message)) { - #retrieve the server hello but do not relay it - while (my $nread = sysread($ssh_subsocket,$buf,400)) { +#while (<$ssh_subsocket>) { +#buffer seems not totally flushed when using the usual syntax above (nor when using autoflush) + while ( my $nread = sysread( $ssh_subsocket, $buf, 400 ) ) { + foreach my $keyword ( keys %regex_hash ) { + if ( $buf =~ $compiled_regex_hash{$keyword} ) { + print STDERR 'found regex ' + . $keyword + . ": replacing '\n" + . $buf + . "\n' by '\n"; + eval( '$buf =~ ' . $regex_hash{$keyword} . ';' ); + print STDERR $buf . "\n'\n"; + } + } + print $client $buf; $ssh_subsocket->flush(); - if ($buf =~ /]]>]]>/) { last }; - }; - #send a custom hello message instead - print $client $hello_message; - if (defined($verbose)) { print STDOUT $hello_message; } - } + if ( defined($verbose) ) { print STDOUT $buf; } - #while (<$ssh_subsocket>) { - #buffer seems not totally flushed when using the usual syntax above (nor when using autoflush) - while (my $nread = sysread($ssh_subsocket,$buf,400)) { - foreach my $keyword (keys %regex_hash){ - if($buf =~ $compiled_regex_hash{$keyword}){ - print STDERR 'found regex '.$keyword.": replacing '\n".$buf."\n' by '\n"; - eval ('$buf =~ '.$regex_hash{$keyword}.';'); - print STDERR $buf."\n'\n"; - } } - print $client $buf; - $ssh_subsocket->flush(); - if (defined($verbose)) { print STDOUT $buf; } - }; + kill( "TERM", $kidpid ); # send SIGTERM to child + } - kill("TERM", $kidpid); # send SIGTERM to child -} # the else{} block runs only in the child process (client input relayed to the server) -else { - - $ssh_subsocket->autoflush(1); - sleep 1; # wait needed for ensuring STDOUT buffer is not melt - my $buf; - - #while (defined (my $buf = <$client>)) { - #usual syntax above used in verbose mode results into flush problems - while (my $nread = sysread($client,$buf,400)) { - print $ssh_subsocket $buf; - $client->flush(); - if (defined($verbose)) { print STDOUT $buf; } - }continue {} + else { + + $ssh_subsocket->autoflush(1); + sleep 1; # wait needed for ensuring STDOUT buffer is not melt + my $buf; + + #while (defined (my $buf = <$client>)) { + #usual syntax above used in verbose mode results into flush problems + while ( my $nread = sysread( $client, $buf, 400 ) ) { + print $ssh_subsocket $buf; + $client->flush(); + if ( defined($verbose) ) { print STDOUT $buf; } + } + continue { } - close $client; + close $client; -} + } -$|=0; + $| = 0; -sleep 2; -kill("TERM", $kidpid); # send SIGTERM to child + sleep 2; + kill( "TERM", $kidpid ); # send SIGTERM to child }