|
|
|
@ -11,15 +11,17 @@ proc check_callback {} {
|
|
|
|
|
|
|
|
|
|
proc getout {} {
|
|
|
|
|
global client_fh server_fh
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set delay 50
|
|
|
|
|
catch {flush $client_fh}
|
|
|
|
|
after $delay
|
|
|
|
|
catch {close $client_fh}
|
|
|
|
|
set client_fh ""
|
|
|
|
|
after $delay
|
|
|
|
|
catch {flush $server_fh}
|
|
|
|
|
after $delay
|
|
|
|
|
catch {close $server_fh}
|
|
|
|
|
set server_fh ""
|
|
|
|
|
after $delay
|
|
|
|
|
|
|
|
|
|
global bmesg_cnt
|
|
|
|
@ -37,54 +39,78 @@ proc check_closed {} {
|
|
|
|
|
if {! $got_connection} {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if {$client_fh != "" && [eof $client_fh]} {
|
|
|
|
|
if {$debug} {
|
|
|
|
|
puts stderr "client_fh EOF"
|
|
|
|
|
if {$client_fh != ""} {
|
|
|
|
|
set ef ""
|
|
|
|
|
catch {set ef [eof $client_fh]}
|
|
|
|
|
if {$ef == 1} {
|
|
|
|
|
if {$debug} {
|
|
|
|
|
puts stderr "client_fh EOF"
|
|
|
|
|
}
|
|
|
|
|
getout
|
|
|
|
|
}
|
|
|
|
|
getout
|
|
|
|
|
}
|
|
|
|
|
if {$server_fh != "" && [eof $server_fh]} {
|
|
|
|
|
if {$debug} {
|
|
|
|
|
puts stderr "server_fh EOF"
|
|
|
|
|
if {$server_fh != ""} {
|
|
|
|
|
set ef ""
|
|
|
|
|
catch {set ef [eof $server_fh]}
|
|
|
|
|
if {$ef == 1} {
|
|
|
|
|
if {$debug} {
|
|
|
|
|
puts stderr "server_fh EOF"
|
|
|
|
|
}
|
|
|
|
|
getout
|
|
|
|
|
}
|
|
|
|
|
getout
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc xfer_in_to_out {} {
|
|
|
|
|
global client_fh server_fh debug
|
|
|
|
|
global client_fh server_fh debug do_bridge
|
|
|
|
|
if {$client_fh != "" && ![eof $client_fh]} {
|
|
|
|
|
set str ""
|
|
|
|
|
catch {set str [read $client_fh 4096]}
|
|
|
|
|
if {$debug} {
|
|
|
|
|
puts stderr "xfer_in_to_out: $str"
|
|
|
|
|
}
|
|
|
|
|
if {$server_fh != "" && $str != ""} {
|
|
|
|
|
puts -nonewline $server_fh $str
|
|
|
|
|
flush $server_fh
|
|
|
|
|
set ef ""
|
|
|
|
|
catch {set ef [eof $client_fh]}
|
|
|
|
|
if {$ef == 0} {
|
|
|
|
|
set str ""
|
|
|
|
|
catch {set str [read $client_fh 4096]}
|
|
|
|
|
if {$debug} {
|
|
|
|
|
#puts stderr "xfer_in_to_out: $str"
|
|
|
|
|
puts stderr "xfer_in_to_out: [string length $str]"
|
|
|
|
|
}
|
|
|
|
|
if {$server_fh != "" && $str != ""} {
|
|
|
|
|
catch {puts -nonewline $server_fh $str}
|
|
|
|
|
catch {flush $server_fh}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
check_closed
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc xfer_out_to_in {} {
|
|
|
|
|
global client_fh server_fh debug
|
|
|
|
|
if {$server_fh != "" && ![eof $server_fh]} {
|
|
|
|
|
set str ""
|
|
|
|
|
catch {set str [read $server_fh 4096]}
|
|
|
|
|
if {$debug} {
|
|
|
|
|
puts stderr "xfer_out_to_in: $str"
|
|
|
|
|
}
|
|
|
|
|
if {$client_fh != "" && $str != ""} {
|
|
|
|
|
puts -nonewline $client_fh $str
|
|
|
|
|
flush $client_fh
|
|
|
|
|
global client_fh server_fh debug do_bridge
|
|
|
|
|
if {$server_fh != ""} {
|
|
|
|
|
set ef ""
|
|
|
|
|
catch {set ef [eof $server_fh]}
|
|
|
|
|
if {$ef == 0} {
|
|
|
|
|
set str ""
|
|
|
|
|
catch {set str [read $server_fh 4096]}
|
|
|
|
|
if {$debug} {
|
|
|
|
|
#puts stderr "xfer_out_to_in: $str"
|
|
|
|
|
puts stderr "xfer_out_to_in: [string length $str]"
|
|
|
|
|
}
|
|
|
|
|
if {$client_fh != "" && $str != ""} {
|
|
|
|
|
catch {puts -nonewline $client_fh $str}
|
|
|
|
|
catch {flush $client_fh}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
check_closed
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc bmesg {msg} {
|
|
|
|
|
return
|
|
|
|
|
global env
|
|
|
|
|
if {! [info exists env(BMESG)]} {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if {$env(BMESG) == 0} {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
global bmesg_cnt
|
|
|
|
|
if {! [info exists bmesg_cnt]} {
|
|
|
|
@ -380,6 +406,560 @@ proc do_connect_repeater {sock hostport which repeater} {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc vread {n sock} {
|
|
|
|
|
set str ""
|
|
|
|
|
set max 3000
|
|
|
|
|
set dt 10
|
|
|
|
|
set i 0
|
|
|
|
|
set cnt 0
|
|
|
|
|
while {$cnt < $max && $i < $n} {
|
|
|
|
|
incr cnt
|
|
|
|
|
set c [read $sock 1]
|
|
|
|
|
if {$c == ""} {
|
|
|
|
|
check_closed
|
|
|
|
|
after $dt
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
incr i
|
|
|
|
|
append str $c
|
|
|
|
|
}
|
|
|
|
|
if {$i != $n} {
|
|
|
|
|
puts stderr "vread failure $n $i"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
return $str
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc append_handshake {str} {
|
|
|
|
|
global env
|
|
|
|
|
if [info exists env(SSVNC_PREDIGESTED_HANDSHAKE)] {
|
|
|
|
|
set file $env(SSVNC_PREDIGESTED_HANDSHAKE)
|
|
|
|
|
set fh ""
|
|
|
|
|
catch {set fh [open $file a]}
|
|
|
|
|
if {$fh != ""} {
|
|
|
|
|
puts $fh $str
|
|
|
|
|
catch {close $fh}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc vencrypt_bridge_connection {fh host port} {
|
|
|
|
|
puts stderr "vencrypt_bridge_connection: got connection $fh $host $port"
|
|
|
|
|
bmesg "vencrypt_bridge_connection: got connection $fh $host $port"
|
|
|
|
|
global viewer_sock
|
|
|
|
|
set viewer_sock $fh
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc center_win {w} {
|
|
|
|
|
update
|
|
|
|
|
set W [winfo screenwidth $w]
|
|
|
|
|
set W [expr $W + 1]
|
|
|
|
|
wm geometry $w +$W+0
|
|
|
|
|
update
|
|
|
|
|
set x [expr [winfo screenwidth $w]/2 - [winfo width $w]/2]
|
|
|
|
|
set y [expr [winfo screenheight $w]/2 - [winfo height $w]/2]
|
|
|
|
|
|
|
|
|
|
wm geometry $w +$x+$y
|
|
|
|
|
wm deiconify $w
|
|
|
|
|
update
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc get_user_pass {} {
|
|
|
|
|
global env
|
|
|
|
|
set up ""
|
|
|
|
|
if [info exists env(SSVNC_UNIXPW)] {
|
|
|
|
|
set rm 0
|
|
|
|
|
set up $env(SSVNC_UNIXPW)
|
|
|
|
|
if [regexp {^rm:} $up] {
|
|
|
|
|
set rm 1
|
|
|
|
|
regsub {^rm:} $up "" up
|
|
|
|
|
}
|
|
|
|
|
if [file exists $up] {
|
|
|
|
|
set fh ""
|
|
|
|
|
set f $up
|
|
|
|
|
catch {set fh [open $up r]}
|
|
|
|
|
if {$fh != ""} {
|
|
|
|
|
gets $fh u
|
|
|
|
|
gets $fh p
|
|
|
|
|
catch {close $fh}
|
|
|
|
|
set up "$u@$p"
|
|
|
|
|
}
|
|
|
|
|
if {$rm} {
|
|
|
|
|
catch {file delete $f}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} elseif [info exists env(SSVNC_VENCRYPT_USERPASS)] {
|
|
|
|
|
set up $env(SSVNC_VENCRYPT_USERPASS)
|
|
|
|
|
}
|
|
|
|
|
if {$up != ""} {
|
|
|
|
|
return $up
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
toplevel .t
|
|
|
|
|
wm title .t {VeNCrypt Viewer Bridge User/Pass}
|
|
|
|
|
|
|
|
|
|
global user pass
|
|
|
|
|
set user ""
|
|
|
|
|
set pass ""
|
|
|
|
|
label .t.l -text {SSVNC VeNCrypt Viewer Bridge}
|
|
|
|
|
|
|
|
|
|
frame .t.f0
|
|
|
|
|
frame .t.f0.fL
|
|
|
|
|
label .t.f0.fL.la -text {Username: }
|
|
|
|
|
label .t.f0.fL.lb -text {Password: }
|
|
|
|
|
|
|
|
|
|
pack .t.f0.fL.la .t.f0.fL.lb -side top
|
|
|
|
|
|
|
|
|
|
frame .t.f0.fR
|
|
|
|
|
entry .t.f0.fR.ea -width 24 -textvariable user
|
|
|
|
|
entry .t.f0.fR.eb -width 24 -textvariable pass -show *
|
|
|
|
|
|
|
|
|
|
pack .t.f0.fR.ea .t.f0.fR.eb -side top -fill x
|
|
|
|
|
|
|
|
|
|
pack .t.f0.fL -side left
|
|
|
|
|
pack .t.f0.fR -side right -expand 1 -fill x
|
|
|
|
|
|
|
|
|
|
button .t.no -text Cancel -command {set user ""; set pass ""; destroy .t}
|
|
|
|
|
button .t.ok -text Done -command {destroy .t}
|
|
|
|
|
|
|
|
|
|
center_win .t
|
|
|
|
|
pack .t.l .t.f0 .t.no .t.ok -side top -fill x
|
|
|
|
|
update
|
|
|
|
|
wm deiconify .t
|
|
|
|
|
|
|
|
|
|
bind .t.f0.fR.ea <Return> {focus .t.f0.fR.eb}
|
|
|
|
|
bind .t.f0.fR.eb <Return> {destroy .t}
|
|
|
|
|
focus .t.f0.fR.ea
|
|
|
|
|
|
|
|
|
|
wm resizable .t 1 0
|
|
|
|
|
wm minsize .t [winfo reqwidth .t] [winfo reqheight .t]
|
|
|
|
|
|
|
|
|
|
tkwait window .t
|
|
|
|
|
if {$user == "" || $pass == ""} {
|
|
|
|
|
return ""
|
|
|
|
|
} else {
|
|
|
|
|
return "$user@$pass"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc do_vencrypt_viewer_bridge {listen connect} {
|
|
|
|
|
global env
|
|
|
|
|
|
|
|
|
|
#set env(BMESG) 1
|
|
|
|
|
|
|
|
|
|
vencrypt_constants
|
|
|
|
|
|
|
|
|
|
set backwards 0
|
|
|
|
|
|
|
|
|
|
if {! [info exists env(SSVNC_PREDIGESTED_HANDSHAKE)]} {
|
|
|
|
|
puts stderr "no SSVNC_PREDIGESTED_HANDSHAKE filename in environment."
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
set handshake $env(SSVNC_PREDIGESTED_HANDSHAKE)
|
|
|
|
|
bmesg $handshake
|
|
|
|
|
|
|
|
|
|
if {$listen < 0} {
|
|
|
|
|
set backwards 1
|
|
|
|
|
set listen [expr -$listen]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# listen on $listen
|
|
|
|
|
global viewer_sock
|
|
|
|
|
set viewer_sock ""
|
|
|
|
|
set lsock ""
|
|
|
|
|
set rc [catch {set lsock [socket -myaddr 127.0.0.1 -server vencrypt_bridge_connection $listen]}]
|
|
|
|
|
if {$rc != 0} {
|
|
|
|
|
puts stderr "error listening on 127.0.0.1:$listen"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
bmesg "listen on $listen OK"
|
|
|
|
|
|
|
|
|
|
# accept
|
|
|
|
|
vwait viewer_sock
|
|
|
|
|
catch {close $lsock}
|
|
|
|
|
fconfigure $viewer_sock -translation binary -blocking 0
|
|
|
|
|
|
|
|
|
|
global got_connection
|
|
|
|
|
set got_connection 1
|
|
|
|
|
|
|
|
|
|
# connect to $connect
|
|
|
|
|
set server_sock ""
|
|
|
|
|
set rc [catch {set server_sock [socket 127.0.0.1 $connect]}]
|
|
|
|
|
if {$rc != 0} {
|
|
|
|
|
puts stderr "error connecting to 127.0.0.1:$connect"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
bmesg "made connection to $connect"
|
|
|
|
|
fconfigure $server_sock -translation binary -blocking 0
|
|
|
|
|
|
|
|
|
|
if {$backwards} {
|
|
|
|
|
puts stderr "reversing roles of viewer and server"
|
|
|
|
|
set t $viewer_sock
|
|
|
|
|
set viewer_sock $server_sock
|
|
|
|
|
set server_sock $t
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# wait for SSVNC_PREDIGESTED_HANDSHAKE "done", put in hash.
|
|
|
|
|
set dt 200
|
|
|
|
|
set slept 0
|
|
|
|
|
set maxwait 20000
|
|
|
|
|
set hs(mode) init
|
|
|
|
|
while {$slept < $maxwait} {
|
|
|
|
|
after $dt
|
|
|
|
|
set slept [expr $slept + $dt]
|
|
|
|
|
set done 0
|
|
|
|
|
set fh ""
|
|
|
|
|
catch {set fh [open $handshake r]}
|
|
|
|
|
set str ""
|
|
|
|
|
if {$fh != ""} {
|
|
|
|
|
array unset hs
|
|
|
|
|
while {[gets $fh line] > -1} {
|
|
|
|
|
set line [string trim $line]
|
|
|
|
|
set str "$str$line\n";
|
|
|
|
|
if {$line == "done"} {
|
|
|
|
|
set done 1
|
|
|
|
|
} elseif [regexp {=} $line] {
|
|
|
|
|
set s [split $line "="]
|
|
|
|
|
set key [lindex $s 0]
|
|
|
|
|
set val [lindex $s 1]
|
|
|
|
|
set hs($key) $val
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch {close $fh}
|
|
|
|
|
}
|
|
|
|
|
if {$done} {
|
|
|
|
|
puts stderr $str
|
|
|
|
|
bmesg "$str"
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
catch [file delete $handshake]
|
|
|
|
|
|
|
|
|
|
if {! [info exists hs(sectype)]} {
|
|
|
|
|
puts stderr "no hs(sectype) found"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# read viewer RFB
|
|
|
|
|
if {! [info exists hs(server)]} {
|
|
|
|
|
set hs(server) "RFB 003.008"
|
|
|
|
|
}
|
|
|
|
|
puts -nonewline $viewer_sock "$hs(server)\n"
|
|
|
|
|
flush $viewer_sock
|
|
|
|
|
puts stderr "sent $hs(server) to viewer sock."
|
|
|
|
|
|
|
|
|
|
set viewer_rfb [vread 12 $viewer_sock]
|
|
|
|
|
puts stderr "read viewer_rfb $viewer_rfb"
|
|
|
|
|
|
|
|
|
|
set viewer_major 3
|
|
|
|
|
set viewer_minor 8
|
|
|
|
|
if [regexp {^RFB 003\.0*([0-9][0-9]*)} $viewer_rfb m v] {
|
|
|
|
|
set viewer_minor $v
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if {$hs(sectype) == $rfbSecTypeAnonTls} {
|
|
|
|
|
puts stderr "handling rfbSecTypeAnonTls"
|
|
|
|
|
if {$viewer_major > 3 || $viewer_minor >= 7} {
|
|
|
|
|
puts stderr "viewer >= 3.7, nothing to set up."
|
|
|
|
|
} else {
|
|
|
|
|
puts stderr "viewer <= 3.3, faking things up."
|
|
|
|
|
set t [vread 1 $server_sock]
|
|
|
|
|
binary scan $t c nsectypes
|
|
|
|
|
puts stderr "nsectypes=$nsectypes"
|
|
|
|
|
for {set i 0} {$i < $nsectypes} {incr i} {
|
|
|
|
|
set t [vread 1 $server_sock]
|
|
|
|
|
binary scan $t c st
|
|
|
|
|
puts stderr " $i: $st"
|
|
|
|
|
set types($st) $i
|
|
|
|
|
}
|
|
|
|
|
set use 1
|
|
|
|
|
if [info exists types(1)] {
|
|
|
|
|
set use 1
|
|
|
|
|
} elseif [info exists types(2)] {
|
|
|
|
|
set use 2
|
|
|
|
|
} else {
|
|
|
|
|
puts stderr "no valid sectypes"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
# this should be MSB:
|
|
|
|
|
vsend_uchar $viewer_sock 0
|
|
|
|
|
vsend_uchar $viewer_sock 0
|
|
|
|
|
vsend_uchar $viewer_sock 0
|
|
|
|
|
vsend_uchar $viewer_sock $use
|
|
|
|
|
|
|
|
|
|
vsend_uchar $server_sock $use
|
|
|
|
|
if {$use == 1} {
|
|
|
|
|
set t [vread 4 $server_sock]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} elseif {$hs(sectype) == $rfbSecTypeVencrypt} {
|
|
|
|
|
puts stderr "handling rfbSecTypeVencrypt"
|
|
|
|
|
if {! [info exists hs(subtype)]} {
|
|
|
|
|
puts stderr "no subtype"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
set fake_type "None"
|
|
|
|
|
set plain 0
|
|
|
|
|
|
|
|
|
|
set sub_type $hs(subtype)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if {$sub_type == $rfbVencryptTlsNone} {
|
|
|
|
|
set fake_type "None"
|
|
|
|
|
} elseif {$sub_type == $rfbVencryptTlsVnc} {
|
|
|
|
|
set fake_type "VncAuth"
|
|
|
|
|
} elseif {$sub_type == $rfbVencryptTlsPlain} {
|
|
|
|
|
set fake_type "None"
|
|
|
|
|
set plain 1
|
|
|
|
|
} elseif {$sub_type == $rfbVencryptX509None} {
|
|
|
|
|
set fake_type "None"
|
|
|
|
|
} elseif {$sub_type == $rfbVencryptX509Vnc} {
|
|
|
|
|
set fake_type "VncAuth"
|
|
|
|
|
} elseif {$sub_type == $rfbVencryptX509Plain} {
|
|
|
|
|
set fake_type "None"
|
|
|
|
|
set plain 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if {$plain} {
|
|
|
|
|
set up [get_user_pass]
|
|
|
|
|
if [regexp {@} $up] {
|
|
|
|
|
set user $up
|
|
|
|
|
set pass $up
|
|
|
|
|
regsub {@.*$} $user "" user
|
|
|
|
|
regsub {^[^@]*@} $pass "" pass
|
|
|
|
|
vsend_uchar $server_sock 0
|
|
|
|
|
vsend_uchar $server_sock 0
|
|
|
|
|
vsend_uchar $server_sock 0
|
|
|
|
|
vsend_uchar $server_sock [string length $user]
|
|
|
|
|
vsend_uchar $server_sock 0
|
|
|
|
|
vsend_uchar $server_sock 0
|
|
|
|
|
vsend_uchar $server_sock 0
|
|
|
|
|
vsend_uchar $server_sock [string length $pass]
|
|
|
|
|
puts stderr "sending VencryptPlain user and pass."
|
|
|
|
|
puts -nonewline $server_sock $user
|
|
|
|
|
puts -nonewline $server_sock $pass
|
|
|
|
|
flush $server_sock
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
set ft 0
|
|
|
|
|
if {$fake_type == "None"} {
|
|
|
|
|
set ft 1
|
|
|
|
|
} elseif {$fake_type == "VncAuth"} {
|
|
|
|
|
set ft 2
|
|
|
|
|
} else {
|
|
|
|
|
puts stderr "no valid fake_type"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if {$viewer_major > 3 || $viewer_minor >= 7} {
|
|
|
|
|
vsend_uchar $viewer_sock 1
|
|
|
|
|
vsend_uchar $viewer_sock $ft
|
|
|
|
|
set t [vread 1 $viewer_sock]
|
|
|
|
|
binary scan $t c cr
|
|
|
|
|
if {$cr != $ft} {
|
|
|
|
|
puts stderr "client selected wront type $cr $ft"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
puts stderr "viewer <= 3.3, faking things up."
|
|
|
|
|
# this should be MSB:
|
|
|
|
|
vsend_uchar $viewer_sock 0
|
|
|
|
|
vsend_uchar $viewer_sock 0
|
|
|
|
|
vsend_uchar $viewer_sock 0
|
|
|
|
|
vsend_uchar $viewer_sock $ft
|
|
|
|
|
|
|
|
|
|
if {$ft == 1} {
|
|
|
|
|
set t [vread 4 $server_sock]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
global client_fh server_fh
|
|
|
|
|
set client_fh $viewer_sock
|
|
|
|
|
set server_fh $server_sock
|
|
|
|
|
|
|
|
|
|
fileevent $client_fh readable xfer_in_to_out
|
|
|
|
|
fileevent $server_fh readable xfer_out_to_in
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc vsend_uchar {sock n} {
|
|
|
|
|
set s [binary format c $n]
|
|
|
|
|
puts -nonewline $sock $s
|
|
|
|
|
flush $sock
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc vencrypt_constants {} {
|
|
|
|
|
uplevel {
|
|
|
|
|
set rfbSecTypeAnonTls 18
|
|
|
|
|
set rfbSecTypeVencrypt 19
|
|
|
|
|
|
|
|
|
|
set rfbVencryptPlain 256
|
|
|
|
|
set rfbVencryptTlsNone 257
|
|
|
|
|
set rfbVencryptTlsVnc 258
|
|
|
|
|
set rfbVencryptTlsPlain 259
|
|
|
|
|
set rfbVencryptX509None 260
|
|
|
|
|
set rfbVencryptX509Vnc 261
|
|
|
|
|
set rfbVencryptX509Plain 262
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc do_vencrypt {sock which} {
|
|
|
|
|
|
|
|
|
|
vencrypt_constants
|
|
|
|
|
|
|
|
|
|
set t [vread 1 $sock]
|
|
|
|
|
binary scan $t c vs_major
|
|
|
|
|
set t [vread 1 $sock]
|
|
|
|
|
binary scan $t c vs_minor
|
|
|
|
|
|
|
|
|
|
if {$vs_minor == "" || $vs_major == "" || $vs_major != 0 || $vs_minor < 2} {
|
|
|
|
|
puts stderr "vencrypt failure bad vs version major=$major minor=$minor"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
puts stderr "server vencrypt version $vs_major.$vs_minor"
|
|
|
|
|
bmesg "server vencrypt version $vs_major.$vs_minor"
|
|
|
|
|
|
|
|
|
|
append_handshake "subversion=0.2"
|
|
|
|
|
vsend_uchar $sock 0
|
|
|
|
|
vsend_uchar $sock 2
|
|
|
|
|
|
|
|
|
|
set t [vread 1 $sock]
|
|
|
|
|
binary scan $t c result
|
|
|
|
|
if {$result != 0} {
|
|
|
|
|
puts stderr "vencrypt failed result: $result"
|
|
|
|
|
bmesg "vencrypt failed result: $result"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set t [vread 1 $sock]
|
|
|
|
|
binary scan $t c nsubtypes
|
|
|
|
|
puts stderr "nsubtypes: $nsubtypes"
|
|
|
|
|
bmesg "nsubtypes: $nsubtypes"
|
|
|
|
|
|
|
|
|
|
for {set i 0} {$i < $nsubtypes} {incr i} {
|
|
|
|
|
set t [vread 4 $sock]
|
|
|
|
|
binary scan $t I stype
|
|
|
|
|
puts stderr "subtypes: $i: $stype"
|
|
|
|
|
append_handshake "sst$i=$stype"
|
|
|
|
|
set subtypes($stype) $i
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set subtype 0
|
|
|
|
|
if [info exists subtypes($rfbVencryptX509None)] {
|
|
|
|
|
set subtype $rfbVencryptX509None
|
|
|
|
|
puts stderr "selected rfbVencryptX509None"
|
|
|
|
|
} elseif [info exists subtypes($rfbVencryptX509Vnc)] {
|
|
|
|
|
set subtype $rfbVencryptX509Vnc
|
|
|
|
|
puts stderr "selected rfbVencryptX509Vnc"
|
|
|
|
|
} elseif [info exists subtypes($rfbVencryptX509Plain)] {
|
|
|
|
|
set subtype $rfbVencryptX509Plain
|
|
|
|
|
puts stderr "selected rfbVencryptX509Plain"
|
|
|
|
|
} elseif [info exists subtypes($rfbVencryptTlsNone)] {
|
|
|
|
|
set subtype $rfbVencryptTlsNone
|
|
|
|
|
puts stderr "selected rfbVencryptTlsNone"
|
|
|
|
|
} elseif [info exists subtypes($rfbVencryptTlsVnc)] {
|
|
|
|
|
set subtype $rfbVencryptTlsVnc
|
|
|
|
|
puts stderr "selected rfbVencryptTlsVnc"
|
|
|
|
|
} elseif [info exists subtypes($rfbVencryptTlsPlain)] {
|
|
|
|
|
set subtype $rfbVencryptTlsPlain
|
|
|
|
|
puts stderr "selected rfbVencryptTlsPlain"
|
|
|
|
|
}
|
|
|
|
|
append_handshake "subtype=$subtype"
|
|
|
|
|
set st [binary format I $subtype]
|
|
|
|
|
puts -nonewline $sock $st
|
|
|
|
|
flush $sock
|
|
|
|
|
|
|
|
|
|
if {$subtype == 0} {
|
|
|
|
|
puts stderr "vencrypt could not find an acceptable subtype: $subtype"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set t [vread 1 $sock]
|
|
|
|
|
binary scan $t c result
|
|
|
|
|
puts stderr "result=$result"
|
|
|
|
|
|
|
|
|
|
append_handshake "done"
|
|
|
|
|
|
|
|
|
|
if {$result == 0} {
|
|
|
|
|
puts stderr "vencrypt failure result: $result"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc do_connect_vencrypt {sock hostport which} {
|
|
|
|
|
global debug cur_proxy
|
|
|
|
|
|
|
|
|
|
vencrypt_constants
|
|
|
|
|
|
|
|
|
|
puts stderr "pxy=$which vencrypt $hostport via $cur_proxy"
|
|
|
|
|
bmesg "V: $which vencrypt $hostport via $cur_proxy"
|
|
|
|
|
|
|
|
|
|
append_handshake "mode=connect"
|
|
|
|
|
|
|
|
|
|
set srfb [vread 12 $sock]
|
|
|
|
|
puts stderr "srfb: $srfb"
|
|
|
|
|
bmesg "srfb: $srfb"
|
|
|
|
|
set srfb [string trim $srfb]
|
|
|
|
|
append_handshake "server=$srfb"
|
|
|
|
|
|
|
|
|
|
set minor ""
|
|
|
|
|
if [regexp {^RFB 00[456]\.} $srfb] {
|
|
|
|
|
set minor 8
|
|
|
|
|
} elseif [regexp {^RFB 003\.0*([0-9][0-9]*)} $srfb mvar minor] {
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
if {$minor == "" || $minor < 7} {
|
|
|
|
|
puts stderr "vencrypt failure bad minor=$minor"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set vrfb "RFB 003.008\n"
|
|
|
|
|
if {$minor == 7} {
|
|
|
|
|
set vrfb "RFB 003.007\n"
|
|
|
|
|
}
|
|
|
|
|
puts -nonewline $sock $vrfb
|
|
|
|
|
flush $sock
|
|
|
|
|
|
|
|
|
|
set vrfb [string trim $vrfb]
|
|
|
|
|
append_handshake "viewer=$vrfb"
|
|
|
|
|
append_handshake "latency=0.10"
|
|
|
|
|
|
|
|
|
|
set str [vread 1 $sock]
|
|
|
|
|
binary scan $str c nsec
|
|
|
|
|
puts stderr "nsec: $nsec"
|
|
|
|
|
bmesg "nsec: $nsec"
|
|
|
|
|
for {set i 0} {$i < $nsec} {incr i} {
|
|
|
|
|
set str [vread 1 $sock]
|
|
|
|
|
binary scan $str c sec
|
|
|
|
|
puts stderr "sec: $sec"
|
|
|
|
|
bmesg "sec: $sec"
|
|
|
|
|
set sectypes($i) $sec
|
|
|
|
|
}
|
|
|
|
|
for {set i 0} {$i < $nsec} {incr i} {
|
|
|
|
|
if {$sectypes($i) == $rfbSecTypeVencrypt} {
|
|
|
|
|
append_handshake "sectype=$rfbSecTypeVencrypt"
|
|
|
|
|
vsend_uchar $sock $rfbSecTypeVencrypt
|
|
|
|
|
after 500
|
|
|
|
|
bmesg "do_vencrypt $sock $which"
|
|
|
|
|
do_vencrypt $sock $which
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for {set i 0} {$i < $nsec} {incr i} {
|
|
|
|
|
if {$sectypes($i) == $rfbSecTypeAnonTls} {
|
|
|
|
|
append_handshake "sectype=$rfbSecTypeAnonTls"
|
|
|
|
|
vsend_uchar $sock $rfbSecTypeAnonTls
|
|
|
|
|
bmesg "rfbSecTypeAnonTls"
|
|
|
|
|
after 500
|
|
|
|
|
append_handshake "done"
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc do_connect {sock type hostport which} {
|
|
|
|
|
if {$type == "http"} {
|
|
|
|
|
do_connect_http $sock $hostport $which
|
|
|
|
@ -390,6 +970,8 @@ proc do_connect {sock type hostport which} {
|
|
|
|
|
} elseif [regexp -nocase {^repeater:} $type] {
|
|
|
|
|
regsub -nocase {^repeater:} $type "" repeater
|
|
|
|
|
do_connect_repeater $sock $hostport $which $repeater
|
|
|
|
|
} elseif {$type == "vencrypt"} {
|
|
|
|
|
do_connect_vencrypt $sock $hostport $which
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -431,9 +1013,6 @@ proc handle_connection {fh host port} {
|
|
|
|
|
fconfigure $fh -translation binary -blocking 0
|
|
|
|
|
fconfigure $sock -translation binary -blocking 0
|
|
|
|
|
|
|
|
|
|
fileevent $fh readable xfer_in_to_out
|
|
|
|
|
fileevent $sock readable xfer_out_to_in
|
|
|
|
|
|
|
|
|
|
set cur_proxy $proxy1
|
|
|
|
|
if {$proxy2 != ""} {
|
|
|
|
|
do_connect $sock $proxy1_type "$proxy2_host:$proxy2_port" 1
|
|
|
|
@ -451,6 +1030,9 @@ proc handle_connection {fh host port} {
|
|
|
|
|
} else {
|
|
|
|
|
do_connect $sock $proxy1_type $dest 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fileevent $fh readable xfer_in_to_out
|
|
|
|
|
fileevent $sock readable xfer_out_to_in
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc proxy_type {proxy} {
|
|
|
|
@ -468,6 +1050,8 @@ proc proxy_type {proxy} {
|
|
|
|
|
return "http"
|
|
|
|
|
} elseif [regexp -nocase {^repeater://.*\+(.*)$} $proxy mat idstr] {
|
|
|
|
|
return "repeater:$idstr"
|
|
|
|
|
} elseif [regexp -nocase {^vencrypt://} $proxy] {
|
|
|
|
|
return "vencrypt"
|
|
|
|
|
} else {
|
|
|
|
|
return "http"
|
|
|
|
|
}
|
|
|
|
@ -482,111 +1066,132 @@ proc proxy_hostport {proxy} {
|
|
|
|
|
return $hp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc setb {} {
|
|
|
|
|
wm withdraw .
|
|
|
|
|
button .b -text "CONNECT_BR" -command {destroy .}
|
|
|
|
|
pack .b
|
|
|
|
|
after 1000 check_callback
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
global env
|
|
|
|
|
|
|
|
|
|
set got_connection 0
|
|
|
|
|
set proxy1 ""
|
|
|
|
|
set proxy2 ""
|
|
|
|
|
set proxy3 ""
|
|
|
|
|
set client_fh ""
|
|
|
|
|
set server_fh ""
|
|
|
|
|
|
|
|
|
|
set do_bridge 0
|
|
|
|
|
set debug 0
|
|
|
|
|
if {$debug} {
|
|
|
|
|
if {! [info exists env(SSVNC_DEST)]} {
|
|
|
|
|
set env(SSVNC_DEST) "haystack:2037"
|
|
|
|
|
}
|
|
|
|
|
if {! [info exists env(SSVNC_PROXY)]} {
|
|
|
|
|
set env(SSVNC_PROXY) "haystack:2037"
|
|
|
|
|
}
|
|
|
|
|
if {! [info exists env(SSVNC_LISTEN)]} {
|
|
|
|
|
set env(SSVNC_LISTEN) "6789"
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if {! [info exists env(SSVNC_DEST)]} {
|
|
|
|
|
destroy .; exit;
|
|
|
|
|
}
|
|
|
|
|
if {! [info exists env(SSVNC_PROXY)]} {
|
|
|
|
|
destroy .; exit;
|
|
|
|
|
}
|
|
|
|
|
if {! [info exists env(SSVNC_LISTEN)] && ! [info exists env(SSVNC_REVERSE)]} {
|
|
|
|
|
destroy .; exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if [info exists env(CONNECT_BR_DEBUG)] {
|
|
|
|
|
set debug 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set dest $env(SSVNC_DEST)
|
|
|
|
|
if [info exists env(SSVNC_VENCRYPT_VIEWER_BRIDGE)] {
|
|
|
|
|
set s [split $env(SSVNC_VENCRYPT_VIEWER_BRIDGE) ","]
|
|
|
|
|
set listen [lindex $s 0]
|
|
|
|
|
set connect [lindex $s 1]
|
|
|
|
|
|
|
|
|
|
if [regexp {,} $env(SSVNC_PROXY)] {
|
|
|
|
|
set s [split $env(SSVNC_PROXY) ","]
|
|
|
|
|
set proxy1 [lindex $s 0]
|
|
|
|
|
set proxy2 [lindex $s 1]
|
|
|
|
|
set proxy3 [lindex $s 2]
|
|
|
|
|
} else {
|
|
|
|
|
set proxy1 $env(SSVNC_PROXY)
|
|
|
|
|
setb
|
|
|
|
|
|
|
|
|
|
do_vencrypt_viewer_bridge $listen $connect
|
|
|
|
|
set do_bridge 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set proxy1_type [proxy_type $proxy1]
|
|
|
|
|
set proxy1_hp [proxy_hostport $proxy1]
|
|
|
|
|
if {$do_bridge} {
|
|
|
|
|
;
|
|
|
|
|
} else {
|
|
|
|
|
if {$debug && 0} {
|
|
|
|
|
if {! [info exists env(SSVNC_DEST)]} {
|
|
|
|
|
set env(SSVNC_DEST) "haystack:2037"
|
|
|
|
|
}
|
|
|
|
|
if {! [info exists env(SSVNC_PROXY)]} {
|
|
|
|
|
set env(SSVNC_PROXY) "haystack:2037"
|
|
|
|
|
}
|
|
|
|
|
if {! [info exists env(SSVNC_LISTEN)]} {
|
|
|
|
|
set env(SSVNC_LISTEN) "6789"
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if {! [info exists env(SSVNC_DEST)]} {
|
|
|
|
|
destroy .; exit;
|
|
|
|
|
}
|
|
|
|
|
if {! [info exists env(SSVNC_PROXY)]} {
|
|
|
|
|
destroy .; exit;
|
|
|
|
|
}
|
|
|
|
|
if {! [info exists env(SSVNC_LISTEN)] && ! [info exists env(SSVNC_REVERSE)]} {
|
|
|
|
|
destroy .; exit;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set s [split $proxy1_hp ":"]
|
|
|
|
|
set proxy1_host [lindex $s 0]
|
|
|
|
|
set proxy1_port [lindex $s 1]
|
|
|
|
|
#set env(BMESG) 1
|
|
|
|
|
|
|
|
|
|
set proxy2_type ""
|
|
|
|
|
set proxy2_host ""
|
|
|
|
|
set proxy2_port ""
|
|
|
|
|
set dest $env(SSVNC_DEST)
|
|
|
|
|
|
|
|
|
|
if {$proxy2 != ""} {
|
|
|
|
|
set proxy2_type [proxy_type $proxy2]
|
|
|
|
|
set proxy2_hp [proxy_hostport $proxy2]
|
|
|
|
|
set s [split $proxy2_hp ":"]
|
|
|
|
|
set proxy2_host [lindex $s 0]
|
|
|
|
|
set proxy2_port [lindex $s 1]
|
|
|
|
|
}
|
|
|
|
|
if [regexp {,} $env(SSVNC_PROXY)] {
|
|
|
|
|
set s [split $env(SSVNC_PROXY) ","]
|
|
|
|
|
set proxy1 [lindex $s 0]
|
|
|
|
|
set proxy2 [lindex $s 1]
|
|
|
|
|
set proxy3 [lindex $s 2]
|
|
|
|
|
} else {
|
|
|
|
|
set proxy1 $env(SSVNC_PROXY)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set proxy3_type ""
|
|
|
|
|
set proxy3_host ""
|
|
|
|
|
set proxy3_port ""
|
|
|
|
|
set proxy1_type [proxy_type $proxy1]
|
|
|
|
|
set proxy1_hp [proxy_hostport $proxy1]
|
|
|
|
|
|
|
|
|
|
if {$proxy3 != ""} {
|
|
|
|
|
set proxy3_type [proxy_type $proxy3]
|
|
|
|
|
set proxy3_hp [proxy_hostport $proxy3]
|
|
|
|
|
set s [split $proxy3_hp ":"]
|
|
|
|
|
set proxy3_host [lindex $s 0]
|
|
|
|
|
set proxy3_port [lindex $s 1]
|
|
|
|
|
}
|
|
|
|
|
set s [split $proxy1_hp ":"]
|
|
|
|
|
set proxy1_host [lindex $s 0]
|
|
|
|
|
set proxy1_port [lindex $s 1]
|
|
|
|
|
|
|
|
|
|
bmesg "1: '$proxy1_host' '$proxy1_port' '$proxy1_type'";
|
|
|
|
|
bmesg "2: '$proxy2_host' '$proxy2_port' '$proxy2_type'";
|
|
|
|
|
bmesg "3: '$proxy3_host' '$proxy3_port' '$proxy3_type'";
|
|
|
|
|
set proxy2_type ""
|
|
|
|
|
set proxy2_host ""
|
|
|
|
|
set proxy2_port ""
|
|
|
|
|
|
|
|
|
|
set got_connection 0
|
|
|
|
|
if {$proxy2 != ""} {
|
|
|
|
|
set proxy2_type [proxy_type $proxy2]
|
|
|
|
|
set proxy2_hp [proxy_hostport $proxy2]
|
|
|
|
|
set s [split $proxy2_hp ":"]
|
|
|
|
|
set proxy2_host [lindex $s 0]
|
|
|
|
|
set proxy2_port [lindex $s 1]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc setb {} {
|
|
|
|
|
wm withdraw .
|
|
|
|
|
button .b -text "CONNECT_BR" -command {destroy .}
|
|
|
|
|
pack .b
|
|
|
|
|
after 1000 check_callback
|
|
|
|
|
}
|
|
|
|
|
set proxy3_type ""
|
|
|
|
|
set proxy3_host ""
|
|
|
|
|
set proxy3_port ""
|
|
|
|
|
|
|
|
|
|
if [info exists env(SSVNC_REVERSE)] {
|
|
|
|
|
set s [split $env(SSVNC_REVERSE) ":"]
|
|
|
|
|
set rhost [lindex $s 0]
|
|
|
|
|
set rport [lindex $s 1]
|
|
|
|
|
set rc [catch {set lsock [socket $rhost $rport]}]
|
|
|
|
|
if {$rc != 0} {
|
|
|
|
|
puts stderr "error reversing"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
if {$proxy3 != ""} {
|
|
|
|
|
set proxy3_type [proxy_type $proxy3]
|
|
|
|
|
set proxy3_hp [proxy_hostport $proxy3]
|
|
|
|
|
set s [split $proxy3_hp ":"]
|
|
|
|
|
set proxy3_host [lindex $s 0]
|
|
|
|
|
set proxy3_port [lindex $s 1]
|
|
|
|
|
}
|
|
|
|
|
puts stderr "SSVNC_REVERSE to $rhost $rport OK";
|
|
|
|
|
setb
|
|
|
|
|
handle_connection $lsock $rhost $rport
|
|
|
|
|
} else {
|
|
|
|
|
set lport $env(SSVNC_LISTEN)
|
|
|
|
|
set rc [catch {set lsock [socket -myaddr 127.0.0.1 -server handle_connection $lport]}]
|
|
|
|
|
if {$rc != 0} {
|
|
|
|
|
puts stderr "error listening"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
|
|
|
|
|
bmesg "1: '$proxy1_host' '$proxy1_port' '$proxy1_type'";
|
|
|
|
|
bmesg "2: '$proxy2_host' '$proxy2_port' '$proxy2_type'";
|
|
|
|
|
bmesg "3: '$proxy3_host' '$proxy3_port' '$proxy3_type'";
|
|
|
|
|
|
|
|
|
|
if [info exists env(SSVNC_REVERSE)] {
|
|
|
|
|
set s [split $env(SSVNC_REVERSE) ":"]
|
|
|
|
|
set rhost [lindex $s 0]
|
|
|
|
|
set rport [lindex $s 1]
|
|
|
|
|
set rc [catch {set lsock [socket $rhost $rport]}]
|
|
|
|
|
if {$rc != 0} {
|
|
|
|
|
puts stderr "error reversing"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
puts stderr "SSVNC_REVERSE to $rhost $rport OK";
|
|
|
|
|
setb
|
|
|
|
|
handle_connection $lsock $rhost $rport
|
|
|
|
|
} else {
|
|
|
|
|
set lport $env(SSVNC_LISTEN)
|
|
|
|
|
set rc [catch {set lsock [socket -myaddr 127.0.0.1 -server handle_connection $lport]}]
|
|
|
|
|
if {$rc != 0} {
|
|
|
|
|
puts stderr "error listening"
|
|
|
|
|
destroy .; exit 1
|
|
|
|
|
}
|
|
|
|
|
puts stderr "SSVNC_LISTEN on $lport OK";
|
|
|
|
|
setb
|
|
|
|
|
}
|
|
|
|
|
puts stderr "SSVNC_LISTEN on $lport OK";
|
|
|
|
|
setb
|
|
|
|
|
}
|
|
|
|
|