-
Notifications
You must be signed in to change notification settings - Fork 0
/
rdesktop
executable file
·244 lines (213 loc) · 8.36 KB
/
rdesktop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#!/bin/bash
help() { cat <</help
rdesktop-wrapper
This is a wrapper around rdesktop to handle ssh tunnels and a nickname index
* You can specify a tunneled host as if it were in your local network
* You can specify a host mapped in your ~/.rdesktop_table file
* You can specify user accounts as part of the hostname, like user@host
* Three new options: --list-maps, --map-help, --completion-help
* You can have entries in '~/.rdesktop_table' like:
#title [user@]server[:port] # default port=3389, user=$USER
hannibal localhost:13389
scipio adam@scipio
* If you use alternate remote desktop ports in your ssh tunnels, you can
put a comment that says "rdesktop" above it. Say "rdesktop next 4" to
indicate that the next four nonwhitespace lines are remote desktop tunnels.
Part of net-scripts: https://github.com/adamhotep/net-scripts
rdesktop-wrapper 0.6.20240714.0, Copyright 2006+ by Adam Katz, GPLv2+
/help
}
##########################################
# 0.1 Initial alpha-release; stable for ME, used more than daily.
# Rather messy code, known bug with spaced arguments, needs rehaul,
# and the inclusion of perl is silly (but more reliable than sed -E).
# 0.2 Better help
# 0.3 Fixed bug with more than one tunnel per host in ssh_config, zsh comp fix
# 0.4 Fixed nmap bug, there are likely more...
# 0.5 Now using bash for arrays so this works with quoted (spaced) parameters
# 0.6.20100513 Rewrote ssh_config parser, allow ssh_config comment hint
# 0.6.20240707 Using more portable `sed -E` in place of `sed -r`, rewrote help()
# At this point, this code is abandonware; I don't use it any more.
# You can debug this by setting $DEBUG to "true" before running this script
##########################################
# TODO
# * Rewrite the whole thing in perl (lots of work; it works fine as is...)
# * Reconsider blanket exclusion of wildcard hosts in sshd_config
# * Test to see if connected to a host before okaying its ssh tunnels
# * Get somebody to say they use and like this script
##########################################
completion_help() { echo \
'For hosts tab completion in zsh, add these lines to your .zshrc:
function _get_rdesktops() {
reply=(`
rdesktop --list-maps 2>/dev/null |sed -E "s/^port.*maps ([^:]+):.*ough/\1/"
_get_hosts
`)
}
compctl -K _get_rdesktops rdesktop'
}
lookup_table=~/.rdesktop_table
[ -n "$DEBUG" ] && debug() { echo "$*" >&2; } || debug() { true; }
# get list of maps from lookup table file
get_lookups() {
[ -s "$lookup_table" ] && \
perl -ne 's/\W*#.*//; s/^(\S+)\s+/$1 \t/s; print if /./;' <"$lookup_table"
}
# get list of ssh tunnels for port 3389 (and my alt, 33389) from ~/.ssh/config
get_tunnels() {
perl -e '
sub report_tunnel {
my ($forward, $target, $host) = @_;
while ( length($forward) < 8 ) { $forward .= " "; }
$target =~ s/:3389$//;
while ( length($target) < 30 ) { $target .= " "; }
print "port $forward maps $target through $host\n";
}
open (SSH_CONFIG, "< $ENV{HOME}/.ssh/config") or die $!;
while (<SSH_CONFIG>) {
chomp;
next unless /Host\s+([^*]+)$/;
my $host = $1;
do {
$_ = <SSH_CONFIG>;
last if ! defined;
if (/#.*\brdesktop\s*(?:(?:next\s*)?(\d+\b))?/) {
my $n = 1;
$n = $1 if ( defined($1) && $1 > 1 );
for (1; $n > 0; $n--) {
$_ = <SSH_CONFIG>;
last if ! defined;
s/#.*$//;
$_ = <SSH_CONFIG> if (/^\s*$/);
last if ! defined || ! /LocalForward\s+((?:\S*:)?\d+)\s+(\S+)/;
report_tunnel ($1, $2, $host);
}
}
if (/LocalForward(?:\s+|\s*=\s*)((?:\S*:)?\d+)\s+(\S+:3?3389\d*)\b/) {
report_tunnel ($1, $2, $host);
}
} while (! /Host\s/);
}
close (SSH_CONFIG);
'
}
# just show the list and exit
case x$*${args[*]} in
*-completion* ) completion_help; exit 0;;
*--map-help* ) help; exit 0;;
*--????-maps* ) get_lookups; get_tunnels; exit 0;;
*--tunneltest*) get_tunnels; exit 0;;
*-h* ) help=true ;;
esac
# list order in path, like 'which -a' w/out aliases
scanpath() {
for d in `echo $PATH |sed 's/:/ /g'`; do ls "$d/$1" 2>/dev/null; done
}
if [ -n "$help" ]; then
help
fi
debug "finding 'rdesktop' in path"
[ -n "`echo $0 |grep /`" ] && apath="$0" && aline=1 || aline=2
run=`scanpath rdesktop |grep -v "^$apath$" |sed "${aline}q;d"`
[ -z "$run" ] && echo "No rdesktop executable found in path" <&2 && exit 2
debug "we will use the second hit in the path, which is '$run'"
if [ -n "$help" ]; then
$run -h
exit 0
fi
# throw all but last argument into $args array
while [ -n "$2" ]; do
# can't have -g and -A, so nix the -g (it doesn't make any sense anyway)
echo "x$*"|grep ".-A" >/dev/null && [ "$1" != "${1#-g}" ] && shift && continue
args[${i:-1}]="$1"
i=$(($i+1))
shift
done
rd=`echo $1 |sed 's/^.*@//'`
user=`echo $1 |sed -e "/@/!d" -e "s/@$rd$//" -e "s/^/-u /"`
#user=`echo $1 |perl -ne 'if /\@/ { s/^([^@]+)\@.*$/-u $1/; print; }'`
local=`echo $1 |perl -ne 'print if /\b(127\.0\.[0-9.]+|localhost.*)/'`
[ -n "$local" ] && [ -z "`echo $local|grep :`" ] && local="$local:3389"
# try lookup table
if [ -s "$lookup_table" ]; then
table=`get_lookups |perl -ne "print if /^\S*$rd\b/"`
debug "lookup table has data, host '$rd' best match is '$table'"
fi
# try ssh config (but not if we are local!)
if [ -z "$table" ]; then
debug "no match on table lookup, trying to search for '$rd' in ssh conf"
if [ -n "$local" ]; then
port=`echo $local|sed 's/^.*://'` # we already set the default port above
else
port=`get_tunnels |perl -ne \
"if (/\b$rd\b/) "'{ s/^\S+\s(\d+).*$/$1/; print; }'`
fi
[ -n "$port" ] && title=`get_tunnels |perl -ne \
"if (/port $port\\b.*\\b$rd\\b/)
{ s/^.*maps\s//; s/[\t ]+/-/g; s/-$//; s/:3?3389//g; print; }"`
[ -n "$title" ] && table="$title localhost:$port" \
&& debug "found ssh-tunnel titled '$title' matching '$rd'" \
|| debug "no ssh tunnel matches query '$rd'"
fi
# try the host literally
if [ -z "$table" ]; then
debug "no match on ssh conf, testing if '$rd' is a literal host or host:port"
host=`echo $rd |sed "s/:.*$//"`
port=`echo $rd |sed "s/$host:*//"`
[ -z "$port" ] && port=3389
debug " testing $host:$port"
# nmap with timeouts (version 4+) is awesome! ... why doens't 2s work!?
my_nmap() {
$tsocks nmap -P0 -sT -T4 --host-timeout 1501 -p"$1" "$2" 2>&1 |grep "$3";
}
# fall back to telnet if nmap doesn't report on the requested port
if my_nmap 25 localhost '^25/' >/dev/null
then
p=`my_nmap $port $host "^$port.*open"`
if [ -z "$p" ]; then
tsocks=tsocks && p=`my_nmap $port $host "^$port.*open"`
[ -z "$p" ] && unset tsocks || echo "works with tsocks"
fi
[ -n "$p" ] && go=true
else echo X |telnet -e X "$1" $2 >/dev/null 2>&1 && go=true
fi
[ -n "$go" ] && table="$rd $host:$port" && debug "literal works, using '$rd'"
fi
if [ -z "$table" ]; then
debug "still nothing ... is '$rd' an argument?"
case $rd in
# no host, let real rdesktop give errors/help
-*) $run "${args[@]}" $rd; exit $? ;;
esac
debug "not an argument ... spit out error message"
echo "`basename $0`: could not connect to \`$rd'"
[ -s "$lookup_table" ] && match=" match in the" \
|| map_help="- see `basename $0` --map-help"
echo "
Found no$match lookup table at \`$lookup_table' $map_help
Found no match in your ssh config for a tunneled rdesktop port (3389)
Server \`$host' does not appear to accept TCP connections on port \`$port'
Trying ping..."
ping -n -c3 "$host" 2>/dev/null
exit 2
fi
if [[ -z "$tsocks" && "$table" =~ (10\.0\.101\.[0-9]+|\.bf)(:[0-9]+)?$ ]]; then
tsocks=tsocks
debug "tsocks enabled for table '$table'"
fi
[ -z "$user" ] && [ -n "`echo $table|grep '@'`" ] && \
user=`echo $table |perl -pne 's/^.*\b([^\@]+)\@.*$/-u $1/'` # extract username
[ -n "$user" ] && debug "a username will be specified with '$user'"
table=`echo $table |perl -pne 's/\s[^\@]+\@/ /'` # remove username form table
dbrun="$tsocks $run ${args[@]} $user -T $table"
#debug "running '$dbrun'..."
if debug is-on 2>&1 |grep is-on >/dev/null; then
debug "running: '$run \\"
for a in "${args[@]}"; do debug " \"$a\" \\"; done
debug " $user \\"
debug " -T $table"
fi
$tsocks $run "${args[@]}" $user -T $table
RETVAL=$?
[ $RETVAL != 0 ] && debug "command '$dbrun' failed with exit code '$RETVAL'" >&2
exit $RETVAL