#!/usr/bin/perl # Universal script to launch rdp client with ssh tunnel to CSO # supported systems # Mac OSX: MS remote desktop v2 or v8 # linux: rdesktop # $version = " Version: 0.0 2014-08-26"; $version = " Version: 0.1 2014-09-26"; # S. Radford # Portions adapted from tunnelopen.pl # Copyright (c) 2008 Thomas A. Fine # Redistribution is permitted, in whole or in part, for commercial and # non-commercial purposes, provided only that this copyright notice # remains. use Socket; $timeout=30; $startport=12345; $maxtries=50; $options=""; $user=""; $localhost="localhost"; $command="sleep $timeout"; $service = "rdp"; $ssh_host = "kilauea.caltech.edu"; $host="localhost"; $rdpport=3389; $width = $templatewidth = 1024; $height = $templateheight = 768; $geometry = $width."x".$height; # determine os type, available remote desktop clients $ostype=$^O; if ($debug) { print STDERR $ostype, "\n"; } # $debug not defined yet if ($ostype eq "darwin") { # application versions and paths $rdpver=2; $rdpapp2 = "/Applications/Remote Desktop Connection.app"; $rdpapp8 = "/Applications/Microsoft Remote Desktop.app"; # template files $rdpconn="$ENV{HOME}/Documents/RDC Connections/"; $rdptemplate = "template$$.rdp"; $rdptmp="tmp$$.rdp"; $templatehost="rdphost"; $templateport="98765"; $templateuser="rdpuser"; } elsif ($ostype eq "linux") { if (length (`which rdesktop 2>/dev/null`) > 0) { $rdpapp = "rdesktop"; } else { print STDERR "No supported remote desktop client available \n"; exit(-1); } if ($debug) { print STDERR $rdpapp, "\n"; } } else { print STDERR "Unsupported system ", $ostype, "\n"; exit(-1); } # parse options while (substr($ARGV[0],0,1) eq "-") { $opt=shift(@ARGV); if ($opt eq "-l" || $opt eq "--login") { $user = shift(@ARGV) . "@"; } elsif ($opt eq "-ll" ) { $user= getpwuid($<) . "@"; } elsif ($opt eq "-b" || $opt eq "--debug") { $debug=1; } elsif ($opt eq "-t" || $opt eq "--timeout") { if (length($command) == 0) { &usage; exit(-1); } $timeout=shift(@ARGV); if ($timeout !~ /^[0-9]+[hmd]?$/) { &usage; exit(-1); } if ($timeout =~ /[hmd]$/) { $u=substr($timeout,length($timeout)-1,1); $timeout=substr($timeout,0,length($timeout)-1); if ($u eq "m") { $timeout *= 60; } if ($u eq "h") { $timeout *= 3600; } if ($u eq "d") { $timeout *= 86400; } } $command="sleep $timeout"; ++$customtimeout; } elsif ($opt eq "-v") { $rdpver=shift(@ARGV); } elsif ($opt eq "-g" || $opt eq "--geometry") { $geometry=shift(@ARGV); if (index(lc($geometry),"x") > 0) { ($width, $height) = split('x', lc($geometry), 2) ; } else { $width = $geometry ; } $geometry = $width."x".$height; if ($width !~ /^[0-9]/ || $height !~ /^[0-9]/) { &usage; exit(-1); } } elsif ($opt eq "-C" || $opt eq "--comp") { $options .= "-C "; } elsif ($opt eq "-h" || $opt eq "--help") { &usage; exit(0); } } if ($ostype eq "darwin") { die ( "Unknown (to this script) RDC version\n" ) unless ($rdpver eq 2 || $rdpver eq 8) ; if ($rdpver == 2) { unless (-e $rdpapp2) { $rdpver=8; } } if ($rdpver == 2) { die "Application not found: $rdpapp2\n" unless (-e $rdpapp2) ; $rdpapp = $rdpapp2 ; } elsif ($rdpver == 8) { die "Application not found: $rdpapp8\n" unless (-e $rdpapp8) ; $rdpapp = $rdpapp8 ; } } if ($debug) { print STDERR "app: $rdpapp \n"; } if ($#ARGV == -1 || $#ARGV > 0) { &usage; exit(0); } if ($user eq "") { $user= getpwuid($<) . "@"; } $target=shift(@ARGV); if ($debug) { print STDERR "target: ", $target, "\n"; } # parse target to extract username, ip address ($host,$port)=split(':',$target); if (index($host,'@') > 0) { ($servuser,$host)=split('@',$host); # $servuser .= '@'; } if ($port>0) { $remoteport=$port; } else { $remoteport=$rdpport; } if ($debug) { print STDERR "host: ", $host, "\n"; } if ($debug) { print STDERR "port: ", $port, "\n"; } if ($debug) { print STDERR "servuser: ", $servuser, "\n"; } # if (length($ssh_host) == 0) { $ssh_host=$host; } $proto = getprotobyname('tcp'); if (!socket(S,PF_INET,SOCK_STREAM,$proto)) { print STDERR "Can't create socket: $!\n"; exit(-1); } for ($i=$startport; $i<$startport+$maxtries; ++$i) { $here=sockaddr_in($i,inet_aton($localhost)); if (bind(S, $here)) { if ($debug) { print STDERR "using local port $i\n"; } $localport=$i; #this shouldn't cause TIME_WAIT, because it isn't connected or listening close(S); last; } } if ($localport == 0) { print STDERR "Can't find an available intermediate port!\n"; exit(-1); } if ($ostype eq "darwin") { # Prepare temporary RDC parameter file from template # create directory and templates if necessary if ($debug) { print STDERR "template: $rdpconn$rdptemplate\n", "tmp: $rdpconn$rdptmp\n"; } unless (-d "$rdpconn") { if ($debug) { print STDERR "Creating RDP template $rdpconn\n"; } mkdir "$rdpconn" or die "Cannot create $rdpconn\n"; } unless (-e "$rdpconn$rdptemplate") { if ($debug) { print STDERR "Creating RDP template $rdpconn$rdptemplate\n"; } &template; } open(INF, "<", "$rdpconn$rdptemplate") or die "Cannot open $rdpconn$rdptemplate\n $!"; open(OUF, ">", "$rdpconn$rdptmp") or die "Cannot open $rdpconn$rdptmp\n $!"; # copy template to configuration file # substitute $localhost, $localport, $servuser, and geometry for placeholders while () { s/$templatehost/$localhost/g; s/$templateport/$localport/g; s/$templateuser/$servuser/g; s/$templatewidth/$width/g; s/$templateheight/$height/g; print OUF; } close(OUF); close(IUF); # remove template unlink "$rdpconn$rdptemplate" or warn "Could not unlink $rdpconn$rdptemplate:\n $!"; } # open ssh tunnel if ($debug) { print STDERR "ssh -L $localport:$host:$remoteport -f $options $user$ssh_host $command\n"; } print "ssh $user$ssh_host\n"; system("ssh -L $localport:$host:$remoteport -f $options $user$ssh_host $command"); if ($ostype eq "darwin") { # open configuration file, system opens rdp app $rdpapp =~ s/ /\\ /g ; # escape embedded spaces $rdpconn =~ s/ /\\ /g ; # escape embedded spaces if ($debug) { print STDERR "open -a $rdpapp $rdpconn$rdptmp \n"; } system("open -a $rdpapp $rdpconn$rdptmp "); sleep 5; # wait for app to start # should test process id, etc. # remove configuration file $rdpconn =~ s/\\ / /g ; # un-escape embedded spaces unlink "$rdpconn$rdptmp" or warn "Could not unlink $rdpconn$rdptmp:\n $!"; } elsif ($ostype eq "linux") { if ($servuser ne "") { if ($debug) { print STDERR "$rdpapp -g $geometry -u $servuser $localhost:$localport & \n"; } system("$rdpapp -g $geometry -u $servuser $localhost:$localport &"); } else { if ($debug) { print STDERR "$rdpapp -g $geometry $localhost:$localport & \n"; } system("$rdpapp -g $geometry $localhost:$localport &"); } } else { print STDERR "Unsupported system ", $ostype, "\n"; &usage; exit(-1); } # # END OF MAIN # sub usage { print <$rdpconn$rdptemplate") or die "Cannot open $rdpconn$rdptemplate\n $!"; if ($rdpver == 2) { # RDC v2 print OUF < AddToKeychain ApplicationPath AudioRedirectionMode 0 AuthenticateLevel 0 AutoReconnect BitmapCaching ColorDepth 2 ConnectionString rdphost:98765 DesktopSize DesktopHeight 768 DesktopWidth 1024 Display 0 Domain remotehost DontWarnOnChange DontWarnOnDriveMount DontWarnOnQuit DriveRedirectionMode 0 FontSmoothing FullWindowDrag HideMacDock KeyMappingTable UI_ALPHANUMERIC_KEY MacKeyCode 102 MacModifier 0 On UI_ALT_KEY MacKeyCode 4294967295 MacModifier 2048 On UI_CONTEXT_MENU_KEY MacKeyCode 120 MacModifier 2048 On UI_CONVERSION_KEY MacKeyCode 4294967295 MacModifier 0 On UI_HALF_FULL_WIDTH_KEY MacKeyCode 49 MacModifier 256 On UI_HIRAGANA_KEY MacKeyCode 104 MacModifier 0 On UI_NON_CONVERSION_KEY MacKeyCode 4294967295 MacModifier 0 On UI_NUM_LOCK_KEY MacKeyCode 71 MacModifier 0 On UI_PAUSE_BREAK_KEY MacKeyCode 99 MacModifier 2048 On UI_PRINT_SCREEN_KEY MacKeyCode 118 MacModifier 2048 On UI_SCROLL_LOCK_KEY MacKeyCode 107 MacModifier 0 On UI_SECONDARY_MOUSE_BUTTON MacKeyCode 256 MacModifier 4608 On UI_WINDOWS_START_KEY MacKeyCode 122 MacModifier 2048 On MenuAnimations PrinterRedirection RedirectFolder RedirectPrinter RemoteApplication Themes UserName rdpuser Wallpaper WorkingDirectory EEE } else { # MS RD v8 print OUF <