1#!/usr/bin/wish 2 3proc check_callback {} { 4 global debug 5 if {$debug} { 6 puts stderr "." 7 } 8 check_closed 9 after 1000 check_callback 10} 11 12proc getout {} { 13 global client_fh server_fh 14 15 set delay 50 16 catch {flush $client_fh} 17 after $delay 18 catch {close $client_fh} 19 set client_fh "" 20 after $delay 21 catch {flush $server_fh} 22 after $delay 23 catch {close $server_fh} 24 set server_fh "" 25 after $delay 26 27 global bmesg_cnt 28 if [info exists bmesg_cnt] { 29 catch {tkwait window .bmesg$bmesg_cnt} 30 } 31 destroy . 32 exit 33} 34 35proc check_closed {} { 36 global got_connection debug 37 global client_fh server_fh 38 39 if {! $got_connection} { 40 return 41 } 42 if {$client_fh != ""} { 43 set ef "" 44 catch {set ef [eof $client_fh]} 45 if {$ef == 1} { 46 if {$debug} { 47 puts stderr "client_fh EOF" 48 } 49 getout 50 } 51 } 52 if {$server_fh != ""} { 53 set ef "" 54 catch {set ef [eof $server_fh]} 55 if {$ef == 1} { 56 if {$debug} { 57 puts stderr "server_fh EOF" 58 } 59 getout 60 } 61 } 62} 63 64proc xfer_in_to_out {} { 65 global client_fh server_fh debug do_bridge 66 if {$client_fh != "" && ![eof $client_fh]} { 67 set ef "" 68 catch {set ef [eof $client_fh]} 69 if {$ef == 0} { 70 set str "" 71 catch {set str [read $client_fh 4096]} 72 if {$debug} { 73 #puts stderr "xfer_in_to_out: $str" 74 puts stderr "xfer_in_to_out: [string length $str]" 75 } 76 if {$server_fh != "" && $str != ""} { 77 catch {puts -nonewline $server_fh $str} 78 catch {flush $server_fh} 79 } 80 } 81 } 82 check_closed 83} 84 85proc xfer_out_to_in {} { 86 global client_fh server_fh debug do_bridge 87 if {$server_fh != ""} { 88 set ef "" 89 catch {set ef [eof $server_fh]} 90 if {$ef == 0} { 91 set str "" 92 catch {set str [read $server_fh 4096]} 93 if {$debug} { 94 #puts stderr "xfer_out_to_in: $str" 95 puts stderr "xfer_out_to_in: [string length $str]" 96 } 97 if {$client_fh != "" && $str != ""} { 98 catch {puts -nonewline $client_fh $str} 99 catch {flush $client_fh} 100 } 101 } 102 } 103 check_closed 104} 105 106proc bmesg {msg} { 107 global env 108 if {! [info exists env(BMESG)]} { 109 return 110 } 111 if {$env(BMESG) == 0} { 112 return 113 } 114 115 global bmesg_cnt 116 if {! [info exists bmesg_cnt]} { 117 set bmesg_cnt 0 118 } 119 incr bmesg_cnt 120 set w .bmesg$bmesg_cnt 121 catch {destroy $w} 122 toplevel $w 123 label $w.l -width 70 -text "$msg" 124 pack $w.l 125 update 126 if {$env(BMESG) > 1} { 127 for {set i 0} {$i < $env(BMESG)} {incr i} { 128 after 1000 129 update 130 } 131 } 132} 133 134proc do_connect_http {sock hostport which} { 135 global debug cur_proxy 136 set con "" 137 append con "CONNECT $hostport HTTP/1.1\r\n" 138 append con "Host: $hostport\r\n" 139 append con "Connection: close\r\n\r\n" 140 141 puts stderr "pxy=$which CONNECT $hostport HTTP/1.1 via $cur_proxy" 142 bmesg "H: $which CONNECT $hostport HTTP/1.1 $cur_proxy"; 143 144 puts -nonewline $sock $con 145 flush $sock 146 147 set r "" 148 set cnt 0 149 while {1} { 150 incr cnt 151 set c [read $sock 1] 152 if {$c == ""} { 153 check_closed 154 after 20 155 } 156 append r $c 157 if {[regexp "\r\n\r\n" $r] || [regexp "a--no--\n\n" $r]} { 158 break 159 } 160 if {$cnt > 30000} { 161 break 162 } 163 } 164 if {! [regexp {HTTP/.* 200} $r]} { 165 puts stderr "did not find HTTP 200 #1" 166 destroy . 167 exit 1 168 } 169} 170 171proc do_connect_socks4 {sock hostport which} { 172 global debug cur_proxy 173 174 set host "" 175 set port "" 176 if [regexp {^(.*):([0-9][0-9]*)$} $hostport mvar host port] { 177 ; 178 } else { 179 puts stderr "could not parse host:port $hostport" 180 destroy . 181 exit 1 182 } 183 184 set i1 "" 185 set i2 "" 186 set i3 "" 187 set i4 "" 188 189 set socks4a 0 190 191 if {$host == "localhost" || $host == "127.0.0.1"} { 192 set i1 127 193 set i2 0 194 set i3 0 195 set i4 1 196 197 } elseif [regexp {^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$} $host] { 198 set n [split $host "."] 199 set i1 [lindex $n 0] 200 set i2 [lindex $n 1] 201 set i3 [lindex $n 2] 202 set i4 [lindex $n 3] 203 } else { 204 set i1 0 205 set i2 0 206 set i3 0 207 set i4 3 208 209 set socks4a 1 210 } 211 212 if {$socks4a} { 213 puts stderr "pxy=$which socks4a connection to $host:$port via $cur_proxy" 214 } else { 215 puts stderr "pxy=$which socks4 connection to $host:$port via $cur_proxy" 216 } 217 218 set p1 [binary format ccScccc 4 1 $port $i1 $i2 $i3 $i4] 219 set p2 "nobody" 220 set p3 [binary format c 0] 221 222 puts -nonewline $sock $p1 223 puts -nonewline $sock $p2 224 puts -nonewline $sock $p3 225 if {$socks4a} { 226 puts -nonewline $sock $host 227 puts -nonewline $sock $p3 228 } 229 flush $sock 230 231 set r ""; set s ""; set i 0; set cnt 0 232 set ok 1 233 while {$cnt < 30000 && $i < 8} { 234 incr cnt 235 set c [read $sock 1] 236 if {$c == ""} { 237 check_closed 238 after 20 239 continue 240 } 241 242 binary scan $c c s 243 if {$i == 0 && $s != 0} { 244 puts stderr "socks4: $i - $s" 245 set ok 0 246 } 247 if {$i == 1 && $s != 90} { 248 puts stderr "socks4: $i - $s" 249 set ok 0 250 } 251 set r "$r,$s" 252 incr i 253 } 254 if {! $ok} { 255 puts stderr "socks4 failure: $r" 256 destroy . 257 exit 1 258 } 259} 260 261proc do_connect_socks5 {sock hostport which} { 262 global debug cur_proxy 263 264 set host "" 265 set port "" 266 if [regexp {^(.*):([0-9][0-9]*)$} $hostport mvar host port] { 267 ; 268 } else { 269 puts stderr "could not parse host:port $hostport" 270 destroy . 271 exit 1 272 } 273 274 set p1 [binary format ccc 5 1 0] 275 puts -nonewline $sock $p1 276 flush $sock 277 278 set r ""; set s ""; set i 0; set cnt 0 279 set ok 1 280 while {$cnt < 30000 && $i < 2} { 281 incr cnt 282 set c [read $sock 1] 283 if {$c == ""} { 284 check_closed 285 after 20 286 continue 287 } 288 289 binary scan $c c s 290 if {$i == 0 && $s != 5} { 291 puts stderr "$i - $s" 292 set ok 0 293 } 294 if {$i == 1 && $s != 0} { 295 puts stderr "$i - $s" 296 set ok 0 297 } 298 set r "$r,$s" 299 incr i 300 } 301 if {! $ok} { 302 puts stderr "socks5 failure: $r" 303 destroy . 304 exit 1 305 } 306 307 set len [string length $host] 308 set p1 [binary format ccccc 5 1 0 3 $len] 309 set p2 $host 310 311 set n1 [expr int($port/256)] 312 set n2 [expr "$port - $n1 * 256"] 313 set p3 [binary format cc $n1 $n2] 314 315 puts stderr "pxy=$which socks5 connection to $host:$port via $cur_proxy" 316 317 puts -nonewline $sock $p1 318 puts -nonewline $sock $p2 319 puts -nonewline $sock $p3 320 flush $sock 321 322 set i1 ""; set i2 ""; set i3 ""; set i4 "" 323 set r ""; set s ""; set i 0; set cnt 0 324 set ok 1 325 while {$cnt < 30000 && $i < 4} { 326 incr cnt 327 set c [read $sock 1] 328 if {$c == ""} { 329 check_closed 330 after 20 331 continue 332 } 333 334 binary scan $c c s 335 if {$i == 0} { 336 set i1 $s 337 } elseif {$i == 1} { 338 set i2 $s 339 } elseif {$i == 2} { 340 set i3 $s 341 } elseif {$i == 3} { 342 set i4 $s 343 } 344 incr i 345 } 346 set r "i1=$i1,i2=$i2,i3=$i3,i4=$i4" 347 348 if {$i4 == 1} { 349 set n 6 350 } elseif {$i4 == 3} { 351 set c "" 352 for {set i 0} {$i < 1000} {incr i} { 353 set c [read $sock 1] 354 if {$c == ""} { 355 check_closed 356 after 20 357 continue 358 } 359 break; 360 } 361 if {$c == ""} { 362 puts stderr "socks5 failure c: $r" 363 destroy . 364 exit 1 365 } 366 binary scan $c c s 367 set n [expr $s + 2] 368 } elseif {$i4 == 4} { 369 set n 18 370 } else { 371 puts stderr "socks5 failure x: $r" 372 destroy . 373 exit 1 374 } 375 #puts "n=$n --- $r" 376 377 set i 0; set cnt 0 378 while {$cnt < 30000 && $i < $n} { 379 incr cnt 380 set c [read $sock 1] 381 if {$c == ""} { 382 check_closed 383 after 20 384 continue 385 } 386 incr i 387 } 388 if {$i1 != 5 || $i2 != 0 || $i3 != 0} { 389 puts stderr "socks failure $r" 390 destroy . 391 exit 1 392 } 393} 394 395proc do_connect_repeater {sock hostport which repeater} { 396 global debug cur_proxy 397 398 # 250 is UltraVNC buffer size. 399 set con [binary format a250 $repeater] 400 401 puts stderr "pxy=$which REPEATER $repeater via $cur_proxy" 402 bmesg "R: $which CONNECT $hostport | $repeater $cur_proxy"; 403 404 puts -nonewline $sock $con 405 flush $sock 406 407 set r "" 408 set cnt 0 409 while {1} { 410 incr cnt 411 set c [read $sock 1] 412 if {$c == ""} { 413 check_closed 414 after 20 415 } 416 append r $c 417 if {[string length $r] >= 12} { 418 puts stderr "do_connect_repeater: $r" 419 break 420 } 421 if {$cnt > 30000} { 422 break 423 } 424 } 425} 426 427proc vread {n sock} { 428 set str "" 429 set max 3000 430 set dt 10 431 set i 0 432 set cnt 0 433 while {$cnt < $max && $i < $n} { 434 incr cnt 435 set c [read $sock 1] 436 if {$c == ""} { 437 check_closed 438 after $dt 439 continue 440 } 441 incr i 442 append str $c 443 } 444 if {$i != $n} { 445 puts stderr "vread failure $n $i" 446 destroy .; exit 1 447 } 448 return $str 449} 450 451proc append_handshake {str} { 452 global env 453 if [info exists env(SSVNC_PREDIGESTED_HANDSHAKE)] { 454 set file $env(SSVNC_PREDIGESTED_HANDSHAKE) 455 set fh "" 456 catch {set fh [open $file a]} 457 if {$fh != ""} { 458 puts $fh $str 459 catch {close $fh} 460 } 461 } 462} 463 464proc vencrypt_bridge_connection {fh host port} { 465 puts stderr "vencrypt_bridge_connection: got connection $fh $host $port" 466 bmesg "vencrypt_bridge_connection: got connection $fh $host $port" 467 global viewer_sock 468 set viewer_sock $fh 469} 470 471proc center_win {w} { 472 update 473 set W [winfo screenwidth $w] 474 set W [expr $W + 1] 475 wm geometry $w +$W+0 476 update 477 set x [expr [winfo screenwidth $w]/2 - [winfo width $w]/2] 478 set y [expr [winfo screenheight $w]/2 - [winfo height $w]/2] 479 480 wm geometry $w +$x+$y 481 wm deiconify $w 482 update 483} 484 485 486proc get_user_pass {} { 487 global env 488 set up "" 489 if [info exists env(SSVNC_UNIXPW)] { 490 set rm 0 491 set up $env(SSVNC_UNIXPW) 492 if [regexp {^rm:} $up] { 493 set rm 1 494 regsub {^rm:} $up "" up 495 } 496 if [file exists $up] { 497 set fh "" 498 set f $up 499 catch {set fh [open $up r]} 500 if {$fh != ""} { 501 gets $fh u 502 gets $fh p 503 catch {close $fh} 504 set up "$u@$p" 505 } 506 if {$rm} { 507 catch {file delete $f} 508 } 509 } 510 } elseif [info exists env(SSVNC_VENCRYPT_USERPASS)] { 511 set up $env(SSVNC_VENCRYPT_USERPASS) 512 } 513 if {$up != ""} { 514 return $up 515 } 516 517 toplevel .t 518 wm title .t {VeNCrypt Viewer Bridge User/Pass} 519 520 global user pass 521 set user "" 522 set pass "" 523 label .t.l -text {SSVNC VeNCrypt Viewer Bridge} 524 525 frame .t.f0 526 frame .t.f0.fL 527 label .t.f0.fL.la -text {Username: } 528 label .t.f0.fL.lb -text {Password: } 529 530 pack .t.f0.fL.la .t.f0.fL.lb -side top 531 532 frame .t.f0.fR 533 entry .t.f0.fR.ea -width 24 -textvariable user 534 entry .t.f0.fR.eb -width 24 -textvariable pass -show * 535 536 pack .t.f0.fR.ea .t.f0.fR.eb -side top -fill x 537 538 pack .t.f0.fL -side left 539 pack .t.f0.fR -side right -expand 1 -fill x 540 541 button .t.no -text Cancel -command {set user ""; set pass ""; destroy .t} 542 button .t.ok -text Done -command {destroy .t} 543 544 center_win .t 545 pack .t.l .t.f0 .t.no .t.ok -side top -fill x 546 update 547 wm deiconify .t 548 549 bind .t.f0.fR.ea <Return> {focus .t.f0.fR.eb} 550 bind .t.f0.fR.eb <Return> {destroy .t} 551 focus .t.f0.fR.ea 552 553 wm resizable .t 1 0 554 wm minsize .t [winfo reqwidth .t] [winfo reqheight .t] 555 556 tkwait window .t 557 if {$user == "" || $pass == ""} { 558 return "" 559 } else { 560 return "$user@$pass" 561 } 562} 563 564proc do_vencrypt_viewer_bridge {listen connect} { 565 global env 566 567 #set env(BMESG) 1 568 569 vencrypt_constants 570 571 set backwards 0 572 573 if {! [info exists env(SSVNC_PREDIGESTED_HANDSHAKE)]} { 574 puts stderr "no SSVNC_PREDIGESTED_HANDSHAKE filename in environment." 575 destroy .; exit 1 576 } 577 set handshake $env(SSVNC_PREDIGESTED_HANDSHAKE) 578 bmesg $handshake 579 580 if {$listen < 0} { 581 set backwards 1 582 set listen [expr -$listen] 583 } 584 585 # listen on $listen 586 global viewer_sock 587 set viewer_sock "" 588 set lsock "" 589 set rc [catch {set lsock [socket -myaddr 127.0.0.1 -server vencrypt_bridge_connection $listen]}] 590 if {$rc != 0} { 591 puts stderr "error listening on 127.0.0.1:$listen" 592 destroy .; exit 1 593 } 594 bmesg "listen on $listen OK" 595 596 # accept 597 vwait viewer_sock 598 catch {close $lsock} 599 fconfigure $viewer_sock -translation binary -blocking 0 600 601 global got_connection 602 set got_connection 1 603 604 # connect to $connect 605 set server_sock "" 606 set rc [catch {set server_sock [socket 127.0.0.1 $connect]}] 607 if {$rc != 0} { 608 puts stderr "error connecting to 127.0.0.1:$connect" 609 destroy .; exit 1 610 } 611 bmesg "made connection to $connect" 612 fconfigure $server_sock -translation binary -blocking 0 613 614 if {$backwards} { 615 puts stderr "reversing roles of viewer and server" 616 set t $viewer_sock 617 set viewer_sock $server_sock 618 set server_sock $t 619 } 620 621 # wait for SSVNC_PREDIGESTED_HANDSHAKE "done", put in hash. 622 set dt 200 623 set slept 0 624 set maxwait 20000 625 set hs(mode) init 626 while {$slept < $maxwait} { 627 after $dt 628 set slept [expr $slept + $dt] 629 set done 0 630 set fh "" 631 catch {set fh [open $handshake r]} 632 set str "" 633 if {$fh != ""} { 634 array unset hs 635 while {[gets $fh line] > -1} { 636 set line [string trim $line] 637 set str "$str$line\n"; 638 if {$line == "done"} { 639 set done 1 640 } elseif [regexp {=} $line] { 641 set s [split $line "="] 642 set key [lindex $s 0] 643 set val [lindex $s 1] 644 set hs($key) $val 645 } 646 } 647 catch {close $fh} 648 } 649 if {$done} { 650 puts stderr $str 651 bmesg "$str" 652 break 653 } 654 } 655 656 catch [file delete $handshake] 657 658 if {! [info exists hs(sectype)]} { 659 puts stderr "no hs(sectype) found" 660 destroy .; exit 1 661 } 662 663 # read viewer RFB 664 if {! [info exists hs(server)]} { 665 set hs(server) "RFB 003.008" 666 } 667 puts -nonewline $viewer_sock "$hs(server)\n" 668 flush $viewer_sock 669 puts stderr "sent $hs(server) to viewer sock." 670 671 set viewer_rfb [vread 12 $viewer_sock] 672 puts stderr "read viewer_rfb $viewer_rfb" 673 674 set viewer_major 3 675 set viewer_minor 8 676 if [regexp {^RFB 003\.0*([0-9][0-9]*)} $viewer_rfb m v] { 677 set viewer_minor $v 678 } 679 680 if {$hs(sectype) == $rfbSecTypeAnonTls} { 681 puts stderr "handling rfbSecTypeAnonTls" 682 if {$viewer_major > 3 || $viewer_minor >= 7} { 683 puts stderr "viewer >= 3.7, nothing to set up." 684 } else { 685 puts stderr "viewer <= 3.3, faking things up." 686 set t [vread 1 $server_sock] 687 binary scan $t c nsectypes 688 puts stderr "nsectypes=$nsectypes" 689 for {set i 0} {$i < $nsectypes} {incr i} { 690 set t [vread 1 $server_sock] 691 binary scan $t c st 692 puts stderr " $i: $st" 693 set types($st) $i 694 } 695 set use 1 696 if [info exists types(1)] { 697 set use 1 698 } elseif [info exists types(2)] { 699 set use 2 700 } else { 701 puts stderr "no valid sectypes" 702 destroy .; exit 1 703 } 704 # this should be MSB: 705 vsend_uchar $viewer_sock 0 706 vsend_uchar $viewer_sock 0 707 vsend_uchar $viewer_sock 0 708 vsend_uchar $viewer_sock $use 709 710 vsend_uchar $server_sock $use 711 if {$use == 1} { 712 set t [vread 4 $server_sock] 713 } 714 } 715 } elseif {$hs(sectype) == $rfbSecTypeVencrypt} { 716 puts stderr "handling rfbSecTypeVencrypt" 717 if {! [info exists hs(subtype)]} { 718 puts stderr "no subtype" 719 destroy .; exit 1 720 } 721 set fake_type "None" 722 set plain 0 723 724 set sub_type $hs(subtype) 725 726 727 if {$sub_type == $rfbVencryptTlsNone} { 728 set fake_type "None" 729 } elseif {$sub_type == $rfbVencryptTlsVnc} { 730 set fake_type "VncAuth" 731 } elseif {$sub_type == $rfbVencryptTlsPlain} { 732 set fake_type "None" 733 set plain 1 734 } elseif {$sub_type == $rfbVencryptX509None} { 735 set fake_type "None" 736 } elseif {$sub_type == $rfbVencryptX509Vnc} { 737 set fake_type "VncAuth" 738 } elseif {$sub_type == $rfbVencryptX509Plain} { 739 set fake_type "None" 740 set plain 1 741 } 742 743 if {$plain} { 744 set up [get_user_pass] 745 if [regexp {@} $up] { 746 set user $up 747 set pass $up 748 regsub {@.*$} $user "" user 749 regsub {^[^@]*@} $pass "" pass 750 vsend_uchar $server_sock 0 751 vsend_uchar $server_sock 0 752 vsend_uchar $server_sock 0 753 vsend_uchar $server_sock [string length $user] 754 vsend_uchar $server_sock 0 755 vsend_uchar $server_sock 0 756 vsend_uchar $server_sock 0 757 vsend_uchar $server_sock [string length $pass] 758 puts stderr "sending VencryptPlain user and pass." 759 puts -nonewline $server_sock $user 760 puts -nonewline $server_sock $pass 761 flush $server_sock 762 } 763 } 764 set ft 0 765 if {$fake_type == "None"} { 766 set ft 1 767 } elseif {$fake_type == "VncAuth"} { 768 set ft 2 769 } else { 770 puts stderr "no valid fake_type" 771 destroy .; exit 1 772 } 773 774 if {$viewer_major > 3 || $viewer_minor >= 7} { 775 vsend_uchar $viewer_sock 1 776 vsend_uchar $viewer_sock $ft 777 set t [vread 1 $viewer_sock] 778 binary scan $t c cr 779 if {$cr != $ft} { 780 puts stderr "client selected wront type $cr $ft" 781 destroy .; exit 1 782 } 783 } else { 784 puts stderr "viewer <= 3.3, faking things up." 785 # this should be MSB: 786 vsend_uchar $viewer_sock 0 787 vsend_uchar $viewer_sock 0 788 vsend_uchar $viewer_sock 0 789 vsend_uchar $viewer_sock $ft 790 791 if {$ft == 1} { 792 set t [vread 4 $server_sock] 793 } 794 } 795 } 796 797 global client_fh server_fh 798 set client_fh $viewer_sock 799 set server_fh $server_sock 800 801 fileevent $client_fh readable xfer_in_to_out 802 fileevent $server_fh readable xfer_out_to_in 803} 804 805proc vsend_uchar {sock n} { 806 set s [binary format c $n] 807 puts -nonewline $sock $s 808 flush $sock 809} 810 811proc vencrypt_constants {} { 812 uplevel { 813 set rfbSecTypeAnonTls 18 814 set rfbSecTypeVencrypt 19 815 816 set rfbVencryptPlain 256 817 set rfbVencryptTlsNone 257 818 set rfbVencryptTlsVnc 258 819 set rfbVencryptTlsPlain 259 820 set rfbVencryptX509None 260 821 set rfbVencryptX509Vnc 261 822 set rfbVencryptX509Plain 262 823 } 824} 825 826proc do_vencrypt {sock which} { 827 828 vencrypt_constants 829 830 set t [vread 1 $sock] 831 binary scan $t c vs_major 832 set t [vread 1 $sock] 833 binary scan $t c vs_minor 834 835 if {$vs_minor == "" || $vs_major == "" || $vs_major != 0 || $vs_minor < 2} { 836 puts stderr "vencrypt failure bad vs version major=$major minor=$minor" 837 destroy .; exit 1 838 } 839 puts stderr "server vencrypt version $vs_major.$vs_minor" 840 bmesg "server vencrypt version $vs_major.$vs_minor" 841 842 append_handshake "subversion=0.2" 843 vsend_uchar $sock 0 844 vsend_uchar $sock 2 845 846 set t [vread 1 $sock] 847 binary scan $t c result 848 if {$result != 0} { 849 puts stderr "vencrypt failed result: $result" 850 bmesg "vencrypt failed result: $result" 851 destroy .; exit 1 852 } 853 854 set t [vread 1 $sock] 855 binary scan $t c nsubtypes 856 puts stderr "nsubtypes: $nsubtypes" 857 bmesg "nsubtypes: $nsubtypes" 858 859 for {set i 0} {$i < $nsubtypes} {incr i} { 860 set t [vread 4 $sock] 861 binary scan $t I stype 862 puts stderr "subtypes: $i: $stype" 863 append_handshake "sst$i=$stype" 864 set subtypes($stype) $i 865 } 866 867 set subtype 0 868 if [info exists subtypes($rfbVencryptX509None)] { 869 set subtype $rfbVencryptX509None 870 puts stderr "selected rfbVencryptX509None" 871 } elseif [info exists subtypes($rfbVencryptX509Vnc)] { 872 set subtype $rfbVencryptX509Vnc 873 puts stderr "selected rfbVencryptX509Vnc" 874 } elseif [info exists subtypes($rfbVencryptX509Plain)] { 875 set subtype $rfbVencryptX509Plain 876 puts stderr "selected rfbVencryptX509Plain" 877 } elseif [info exists subtypes($rfbVencryptTlsNone)] { 878 set subtype $rfbVencryptTlsNone 879 puts stderr "selected rfbVencryptTlsNone" 880 } elseif [info exists subtypes($rfbVencryptTlsVnc)] { 881 set subtype $rfbVencryptTlsVnc 882 puts stderr "selected rfbVencryptTlsVnc" 883 } elseif [info exists subtypes($rfbVencryptTlsPlain)] { 884 set subtype $rfbVencryptTlsPlain 885 puts stderr "selected rfbVencryptTlsPlain" 886 } 887 append_handshake "subtype=$subtype" 888 set st [binary format I $subtype] 889 puts -nonewline $sock $st 890 flush $sock 891 892 if {$subtype == 0} { 893 puts stderr "vencrypt could not find an acceptable subtype: $subtype" 894 destroy .; exit 1 895 } 896 897 set t [vread 1 $sock] 898 binary scan $t c result 899 puts stderr "result=$result" 900 901 append_handshake "done" 902 903 if {$result == 0} { 904 puts stderr "vencrypt failure result: $result" 905 destroy .; exit 1 906 } 907 908} 909 910proc do_connect_vencrypt {sock hostport which} { 911 global debug cur_proxy 912 913 vencrypt_constants 914 915 puts stderr "pxy=$which vencrypt $hostport via $cur_proxy" 916 bmesg "V: $which vencrypt $hostport via $cur_proxy" 917 918 append_handshake "mode=connect" 919 920 set srfb [vread 12 $sock] 921 puts stderr "srfb: $srfb" 922 bmesg "srfb: $srfb" 923 set srfb [string trim $srfb] 924 append_handshake "server=$srfb" 925 926 set minor "" 927 if [regexp {^RFB 00[456]\.} $srfb] { 928 set minor 8 929 } elseif [regexp {^RFB 003\.0*([0-9][0-9]*)} $srfb mvar minor] { 930 ; 931 } 932 if {$minor == "" || $minor < 7} { 933 puts stderr "vencrypt failure bad minor=$minor" 934 destroy .; exit 1 935 } 936 937 set vrfb "RFB 003.008\n" 938 if {$minor == 7} { 939 set vrfb "RFB 003.007\n" 940 } 941 puts -nonewline $sock $vrfb 942 flush $sock 943 944 set vrfb [string trim $vrfb] 945 append_handshake "viewer=$vrfb" 946 append_handshake "latency=0.10" 947 948 set str [vread 1 $sock] 949 binary scan $str c nsec 950 puts stderr "nsec: $nsec" 951 bmesg "nsec: $nsec" 952 for {set i 0} {$i < $nsec} {incr i} { 953 set str [vread 1 $sock] 954 binary scan $str c sec 955 puts stderr "sec: $sec" 956 bmesg "sec: $sec" 957 set sectypes($i) $sec 958 } 959 for {set i 0} {$i < $nsec} {incr i} { 960 if {$sectypes($i) == $rfbSecTypeVencrypt} { 961 append_handshake "sectype=$rfbSecTypeVencrypt" 962 vsend_uchar $sock $rfbSecTypeVencrypt 963 after 500 964 bmesg "do_vencrypt $sock $which" 965 do_vencrypt $sock $which 966 return 967 } 968 } 969 for {set i 0} {$i < $nsec} {incr i} { 970 if {$sectypes($i) == $rfbSecTypeAnonTls} { 971 append_handshake "sectype=$rfbSecTypeAnonTls" 972 vsend_uchar $sock $rfbSecTypeAnonTls 973 bmesg "rfbSecTypeAnonTls" 974 after 500 975 append_handshake "done" 976 return 977 } 978 } 979} 980 981proc do_connect {sock type hostport which} { 982 if {$type == "http"} { 983 do_connect_http $sock $hostport $which 984 } elseif {$type == "socks"} { 985 do_connect_socks4 $sock $hostport $which 986 } elseif {$type == "socks5"} { 987 do_connect_socks5 $sock $hostport $which 988 } elseif [regexp -nocase {^repeater:} $type] { 989 regsub -nocase {^repeater:} $type "" repeater 990 do_connect_repeater $sock $hostport $which $repeater 991 } elseif {$type == "vencrypt"} { 992 do_connect_vencrypt $sock $hostport $which 993 } 994} 995 996proc handle_connection {fh host port} { 997 global proxy1_host proxy1_port proxy1_type 998 global proxy2_host proxy2_port proxy2_type 999 global proxy3_host proxy3_port proxy3_type 1000 global proxy1 proxy2 proxy3 dest 1001 global debug cur_proxy 1002 global got_connection 1003 1004 if {$got_connection} { 1005 catch {close $fh} 1006 return 1007 } 1008 set got_connection 1 1009 1010 if {$debug} { 1011 puts stderr "connection from: $host $port" 1012 puts stderr "socket $proxy1_host $proxy1_port" 1013 } 1014 1015 set rc [catch {set sock [socket $proxy1_host $proxy1_port]}] 1016 if {$rc != 0} { 1017 puts stderr "error connecting" 1018 catch {close $sock} 1019 destroy . 1020 exit 1021 } 1022 1023 if {$debug} { 1024 puts stderr "got sock: $sock" 1025 } 1026 1027 global client_fh server_fh 1028 set client_fh $fh 1029 set server_fh $sock 1030 1031 fconfigure $fh -translation binary -blocking 0 1032 fconfigure $sock -translation binary -blocking 0 1033 1034 set cur_proxy $proxy1 1035 if {$proxy2 != ""} { 1036 do_connect $sock $proxy1_type "$proxy2_host:$proxy2_port" 1 1037 1038 set cur_proxy $proxy2 1039 if {$proxy3 != ""} { 1040 do_connect $sock $proxy2_type "$proxy3_host:$proxy3_port" 2 1041 1042 set cur_proxy $proxy3 1043 do_connect $sock $proxy3_type $dest 3 1044 1045 } else { 1046 do_connect $sock $proxy2_type $dest 2 1047 } 1048 } else { 1049 do_connect $sock $proxy1_type $dest 1 1050 } 1051 1052 fileevent $fh readable xfer_in_to_out 1053 fileevent $sock readable xfer_out_to_in 1054} 1055 1056proc proxy_type {proxy} { 1057 if [regexp -nocase {^socks://} $proxy] { 1058 return "socks" 1059 } elseif [regexp -nocase {^socks4://} $proxy] { 1060 return "socks" 1061 } elseif [regexp -nocase {^socks4a://} $proxy] { 1062 return "socks" 1063 } elseif [regexp -nocase {^socks5://} $proxy] { 1064 return "socks5" 1065 } elseif [regexp -nocase {^http://} $proxy] { 1066 return "http" 1067 } elseif [regexp -nocase {^https://} $proxy] { 1068 return "http" 1069 } elseif [regexp -nocase {^repeater://.*\+(.*)$} $proxy mat idstr] { 1070 return "repeater:$idstr" 1071 } elseif [regexp -nocase {^vencrypt://} $proxy] { 1072 return "vencrypt" 1073 } else { 1074 return "http" 1075 } 1076} 1077 1078proc proxy_hostport {proxy} { 1079 regsub -nocase {^[a-z][a-z0-9]*://} $proxy "" hp 1080 regsub {\+.*$} $hp "" hp 1081 if {! [regexp {:[0-9]} $hp] && [regexp {^repeater:} $proxy]} { 1082 set hp "$hp:5900" 1083 } 1084 return $hp 1085} 1086 1087proc setb {} { 1088 wm withdraw . 1089 catch {destroy .b} 1090 button .b -text "CONNECT_BR" -command {destroy .} 1091 pack .b 1092 after 1000 check_callback 1093} 1094 1095proc connect_br_sleep {} { 1096 global env 1097 if [info exists env(CONNECT_BR_SLEEP)] { 1098 if [regexp {^[0-9][0-9]*$} $env(CONNECT_BR_SLEEP)] { 1099 setb 1100 for {set i 0} {$i < $env(CONNECT_BR_SLEEP)} {incr i} { 1101 bmesg "$i sleep" 1102 after 1000 1103 } 1104 } 1105 } 1106} 1107 1108global env 1109 1110set got_connection 0 1111set proxy1 "" 1112set proxy2 "" 1113set proxy3 "" 1114set client_fh "" 1115set server_fh "" 1116set do_bridge 0 1117set debug 0 1118 1119if [info exists env(CONNECT_BR_DEBUG)] { 1120 set debug 1 1121} 1122 1123if [info exists env(SSVNC_VENCRYPT_VIEWER_BRIDGE)] { 1124 set s [split $env(SSVNC_VENCRYPT_VIEWER_BRIDGE) ","] 1125 set listen [lindex $s 0] 1126 set connect [lindex $s 1] 1127 1128 setb 1129 1130 do_vencrypt_viewer_bridge $listen $connect 1131 set do_bridge 1 1132} 1133 1134if {$do_bridge} { 1135 ; 1136} else { 1137 if {$debug && 0} { 1138 if {! [info exists env(SSVNC_DEST)]} { 1139 set env(SSVNC_DEST) "haystack:2037" 1140 } 1141 if {! [info exists env(SSVNC_PROXY)]} { 1142 set env(SSVNC_PROXY) "haystack:2037" 1143 } 1144 if {! [info exists env(SSVNC_LISTEN)]} { 1145 set env(SSVNC_LISTEN) "6789" 1146 } 1147 } else { 1148 if {! [info exists env(SSVNC_DEST)]} { 1149 destroy .; exit; 1150 } 1151 if {! [info exists env(SSVNC_PROXY)]} { 1152 destroy .; exit; 1153 } 1154 if {! [info exists env(SSVNC_LISTEN)] && ! [info exists env(SSVNC_REVERSE)]} { 1155 destroy .; exit; 1156 } 1157 } 1158 1159 #set env(BMESG) 1 1160 1161 set dest $env(SSVNC_DEST) 1162 1163 if [regexp {,} $env(SSVNC_PROXY)] { 1164 set s [split $env(SSVNC_PROXY) ","] 1165 set proxy1 [lindex $s 0] 1166 set proxy2 [lindex $s 1] 1167 set proxy3 [lindex $s 2] 1168 } else { 1169 set proxy1 $env(SSVNC_PROXY) 1170 } 1171 1172 set proxy1_type [proxy_type $proxy1] 1173 set proxy1_hp [proxy_hostport $proxy1] 1174 1175 set proxy1_host "" 1176 set proxy1_port "" 1177 if [regexp {^(.*):([0-9][0-9]*)$} $proxy1_hp mvar proxy1_host proxy1_port] { 1178 ; 1179 } else { 1180 puts stderr "could not parse hp1 host:port $proxy1_hp" 1181 destroy . 1182 exit 1 1183 } 1184 1185 set proxy2_type "" 1186 set proxy2_host "" 1187 set proxy2_port "" 1188 1189 if {$proxy2 != ""} { 1190 set proxy2_type [proxy_type $proxy2] 1191 set proxy2_hp [proxy_hostport $proxy2] 1192 1193 set proxy2_host "" 1194 set proxy2_port "" 1195 if [regexp {^(.*):([0-9][0-9]*)$} $proxy2_hp mvar proxy2_host proxy2_port] { 1196 ; 1197 } else { 1198 puts stderr "could not parse hp2 host:port $proxy2_hp" 1199 destroy . 1200 exit 1 1201 } 1202 } 1203 1204 set proxy3_type "" 1205 set proxy3_host "" 1206 set proxy3_port "" 1207 1208 if {$proxy3 != ""} { 1209 set proxy3_type [proxy_type $proxy3] 1210 set proxy3_hp [proxy_hostport $proxy3] 1211 1212 set proxy3_host "" 1213 set proxy3_port "" 1214 if [regexp {^(.*):([0-9][0-9]*)$} $proxy3_hp mvar proxy3_host proxy3_port] { 1215 ; 1216 } else { 1217 puts stderr "could not parse hp3 host:port $proxy3_hp" 1218 destroy . 1219 exit 1 1220 } 1221 } 1222 1223 bmesg "1: '$proxy1_host' '$proxy1_port' '$proxy1_type'"; 1224 bmesg "2: '$proxy2_host' '$proxy2_port' '$proxy2_type'"; 1225 bmesg "3: '$proxy3_host' '$proxy3_port' '$proxy3_type'"; 1226 1227 if [info exists env(SSVNC_REVERSE)] { 1228 set rhost "" 1229 set rport "" 1230 if [regexp {^(.*):([0-9][0-9]*)$} $env(SSVNC_REVERSE) mvar rhost rport] { 1231 ; 1232 } else { 1233 puts stderr "could not parse SSVNC_REVERSE host:port $env(SSVNC_REVERSE)" 1234 destroy . 1235 exit 1 1236 } 1237 setb 1238 set rc [catch {set lsock [socket $rhost $rport]}] 1239 if {$rc != 0} { 1240 puts stderr "error reversing" 1241 bmesg "1 error reversing" 1242 after 2000 1243 set rc [catch {set lsock [socket $rhost $rport]}] 1244 } 1245 if {$rc != 0} { 1246 puts stderr "error reversing" 1247 bmesg "2 error reversing" 1248 after 2000 1249 set rc [catch {set lsock [socket $rhost $rport]}] 1250 } 1251 if {$rc != 0} { 1252 puts stderr "error reversing" 1253 bmesg "3 error reversing" 1254 destroy .; exit 1 1255 } 1256 puts stderr "SSVNC_REVERSE to $rhost $rport OK"; 1257 bmesg "SSVNC_REVERSE to $rhost $rport OK"; 1258 connect_br_sleep 1259 handle_connection $lsock $rhost $rport 1260 } else { 1261 set lport $env(SSVNC_LISTEN) 1262 connect_br_sleep 1263 set rc [catch {set lsock [socket -myaddr 127.0.0.1 -server handle_connection $lport]}] 1264 if {$rc != 0} { 1265 puts stderr "error listening" 1266 destroy .; exit 1 1267 } 1268 puts stderr "SSVNC_LISTEN on $lport OK"; 1269 setb 1270 } 1271} 1272