1#!/bin/sh
2# the next line restarts using wish \
3exec wish "$0" "$@"
4
5#
6# Copyright (c) 2006-2010 by Karl J. Runge <runge@karlrunge.com>
7#
8# ssvnc.tcl: gui wrapper to the programs in this
9# package. Also sets up service port forwarding.
10#
11set version 1.0.28
12
13set buck_zero $argv0
14
15proc center_win {w} {
16	global is_windows
17	update
18	set W [winfo screenwidth  $w]
19	set W [expr $W + 1]
20	wm geometry $w +$W+0
21	update
22	set x [expr [winfo screenwidth  $w]/2 - [winfo width  $w]/2]
23	set y [expr [winfo screenheight $w]/2 - [winfo height $w]/2]
24
25	if {$is_windows} {
26		set y [expr "$y - 30"]
27		if {$y <= 0} {
28			set y 1
29		}
30	}
31	wm geometry $w +$x+$y
32	wm deiconify $w
33	update
34}
35
36proc small_height {} {
37	set H [winfo screenheight .]
38	if {$H < 700} {
39		return 1
40	} else {
41		return 0
42	}
43}
44
45proc mac_raise {} {
46	global uname
47	if {$uname == "Darwin"} {
48		catch {exec /bin/sh -c {osascript -e 'tell application "Wish Shell" to activate' >/dev/null 2>&1 &}}
49		after 150
50		update
51		update idletasks
52	}
53}
54
55proc toplev {w} {
56	catch {destroy $w}
57	toplevel $w
58	catch {wm withdraw $w}
59}
60
61proc apply_bg {w} {
62	global is_windows system_button_face
63	if {$is_windows && $system_button_face != ""} {
64		catch {$w configure -bg "$system_button_face"}
65	}
66}
67
68proc line_count {{str ""} {pad 0}} {
69	set n $pad
70	foreach l [split $str "\n"] {
71		incr n
72	}
73	return $n
74}
75
76proc scroll_text {fr {w 80} {h 35}} {
77	global help_font is_windows scroll_text_focus
78
79	if {$h == 35 && [small_height]} {
80		set h 28
81	}
82	catch {destroy $fr}
83
84	frame $fr -bd 0
85
86	eval text $fr.t -width $w -height $h $help_font \
87		 -setgrid 1 -bd 2 -yscrollcommand {"$fr.y set"} -relief ridge
88
89	apply_bg $fr.t
90
91	scrollbar $fr.y -orient v -relief sunken -command "$fr.t yview"
92	pack $fr.y -side right -fill y
93	pack $fr.t -side top -fill both -expand 1
94
95	if {$scroll_text_focus} {
96		focus $fr.t
97	}
98}
99
100proc scroll_text_dismiss {fr {w 80} {h 35}} {
101	global help_font
102
103	if {$h == 35 && [small_height]} {
104		set h 28
105	}
106	scroll_text $fr $w $h
107
108	set up $fr
109	regsub {\.[^.]*$} $up "" up
110
111	button $up.d -text "Dismiss" -command "destroy $up"
112	bind $up <Escape> "destroy $up"
113	pack $up.d -side bottom -fill x
114	pack $fr -side top -fill both -expand 1
115}
116
117proc jiggle_text {w} {
118	global uname
119	if {$uname == "Darwin"} {
120		$w yview scroll 1 pages
121		update idletasks
122		$w yview scroll -1 pages
123		update idletasks
124	}
125}
126
127proc ts_help {} {
128	toplev .h
129
130	scroll_text_dismiss .h.f
131
132	center_win .h
133	wm title .h "Terminal Services VNC Viewer Help"
134
135	set msg {
136 Terminal Services:
137
138    The Terminal Services VNC Viewer uses SSH to establish an encrypted
139    and authenticated connection to the remote server.
140
141    Through the SSH channel, it automatically starts x11vnc in terminal
142    services mode on the remote server to find or create your desktop
143    session.  x11vnc is used for both the session management and the
144    VNC transport.
145
146    You MUST be able to log in via SSH to the remote terminal server.
147    Ask your administrator to set this up for you if it isn't already.
148    x11vnc must also be installed on the remote server machine.
149    See "Requirements" below.
150
151    This mode is started by the commands 'tsvnc' or 'ssvnc -ts' or
152    toggled by pressing Ctrl-t.  "SSVNC Mode" under Options -> Advanced
153    will also return to the full SSVNC.
154
155    Or in your ~/.ssvncrc (or ~/ssvnc_rc on Windows) put "mode=tsvnc"
156    to have the tool always start up in that mode.  To constrain the UI,
157    run with -tso or SSVNC_TS_ALWAYS set to prevent leaving the Terminal
158    Services mode.
159
160
161 Hosts and Displays:
162
163    Enter the remote VNC Terminal Services hostname in the
164    'VNC Terminal Server' entry.
165
166    Examples:
167
168           24.67.132.27
169           far-away.east
170           fred@someplace.no
171
172    Then click on "Connect".
173
174    Once the SSH is running (you may need to type a password or accept
175    a new ssh key in the terminal window that pops up), the VNC Viewer
176    will be automatically started directed to the local port of the SSH
177    tunnel which, in turn, encrypts and redirects the connection to the
178    remote VNC server.
179
180    x11vnc is run remotely to find or create your terminal services desktop
181    session.  It must be installed and accessible on the remote system.
182
183    Enter "user@hostname.com" in 'VNC Terminal Server' if the remote
184    username is different from the yours on this machine.  On Windows
185    you *MUST* supply the remote username due to a deficiency in Plink.
186    This entry is passed to SSH; it could also be an SSH alias you have
187    created (in ~/.ssh/config).
188
189    If the remote SSH server is run on a non-standard port, e.g. 2222, use
190    something like one of these:
191
192           far-away.east:2222
193           fred@someplace.no:2222
194
195    (unlike SSVNC mode, the number is the SSH port, not the VNC display)
196
197    If you find yourself in the unfortunate circumstance that your ssh
198    username has a space in it, use %SPACE (or %TAB) like this:
199
200           fred%SPACEflintstone@xyzzy.net
201
202
203 Zeroconf/Bonjour:
204
205    On Unix or Mac OS X, if the 'avahi-browse' or 'dns-sd' command is
206    available on the system and in your PATH, a 'Find' button is placed by
207    'VNC Host:Display'.  Clicking on Find will try to find VNC Servers
208    on your Local Network that advertize via the Zeroconf protocol.
209    A menu of found hosts is presented for you to select from.
210
211
212 Profiles:
213
214    Use "Save" to save a profile (i.e. a host:display and its specific
215    settings) with a name.  The "TS-" prefix will be suggested to help
216    you distinguish between Terminal Services and regular profiles.
217
218    To load in a saved Options profile, click on the "Load" button,
219    and choose which one you want.
220
221    To list your profiles from the command line use:
222
223         tsvnc -profiles    (or -list)
224
225    To launch profile1 directly from the command-line, or to a server
226    use things like:
227
228         tsvnc profile1
229         tsvnc /path/to/profile1.vnc
230         tsvnc hostname
231         tsvnc user@hostname
232
233    Note that the 'Verify All Certs' setting is NOT saved in profiles.
234
235
236 Proxies/Gateways:
237
238    Proxy/Gateway is usually a gateway machine to log into via SSH that is
239    not the machine running the VNC terminal services.  However, Web and
240    SOCKS proxies can also be used (see below).
241
242    For example if a company had a central login server: "ssh.company.com"
243    (accessible from the internet) and the internal server name was
244    "ts-server", one could put in
245
246           VNC Terminal Server:   ts-server
247           Proxy/Gateway:         ssh.company.com
248
249    It is OK if the hostname "ts-server" only resolves inside the firewall.
250
251    The 2nd host, ts-server in this example, MUST also be running an SSH
252    server and you must be able to log into it.  You may need to supply
253    a 2nd password to it to login.
254
255    Use username@host (e.g. joe@ts-server or jsmith@ssh.company.com)
256    if the user name differs between machines.
257
258    NOTE: On Windows you MUST always supply the username@ because putty's
259    plink requires it.
260
261
262    NON-STANDARD SSH PORT: To use a non-standard ssh port (i.e. a port other
263    than 22) you need to use the Proxy/Gateways as well.  E.g. something
264    like this for port 2222:
265
266           VNC Terminal Server:  ts-server
267           Proxy/Gateway:        jsmith@ssh.company.com:2222
268
269    On Unix/MacOSX the username@ is not needed if it is the same as on this
270    machine.
271
272
273    A Web or SOCKS proxy can also be used.  Use this if you are inside a
274    firewall that prohibits direct connections to remote SSH servers.
275    In Terminal Services SSH mode, the "http://" prefix is required for
276    web proxies.
277
278           VNC Terminal Server:  fred@someplace.no
279           Proxy/Gateway:        http://myproxy.west:8080
280
281    or for SOCKS:
282
283           VNC Terminal Server:  fred@someplace.no
284           Proxy/Gateway:        socks://mysocks.west:1080
285
286    use socks5://... to force the SOCKS5 version.  For a non-standard
287    port the above would be, e.g., fred@someplace.no:2222
288
289    As with a username that contains a space, use %SPACE (or %TAB) to
290    indicate it in the SSH proxies, e.g. john%SPACEsmith@ssh.company.com
291
292    One can also chain proxies and other things.  See the section
293    "SSH Proxies/Gateways" in the Main SSVNC Help for full details.
294
295
296 Options:
297
298    Click on Options to get to dialog boxes to:
299
300           - Desktop Type        (kde, gnome, failsafe, twm...)
301           - Desktop Size        (Geometry WxH and pixel depth)
302           - X Server Type       (Xvfb, Xdummy, Xvnc)
303           - Enable Printing     (CUPS and/or SMB/Windows)
304           - Enable Sound        (TBD, ESD partially working)
305           - File Transfer       (Ultra or TightVNC filexfer)
306           - View Only           (View only client)
307           - Change VNC Viewer   (Realvnc, ultra, etc...)
308           - X11 viewer MacOSX   (use bundled X11 vncviewer)
309           - Delete Profile...   (Delete a saved profile)
310
311           - Advanced Options:
312
313           - VNC Shared          (optional traditional VNC sharing)
314           - Multiple Sessions   (more than 1 session per server)
315           - X Login Greeter     (Connect to Login/Greeter Display)
316           - Other VNC Server    (redirect to 3rd party VNC Server)
317           - Use unixpw          (optional x11vnc login mode)
318           - Client 8bit Color   (VNC Viewer requests low color mode)
319           - Client-Side Caching (experimental x11vnc speedup)
320           - X11VNC Options      (set any extra x11vnc options)
321           - Extra Sleep         (delay a bit before starting viewer)
322           - Putty Args          (Windows: string for plink/putty cmd)
323           - Putty Agent         (Windows: launch pageant)
324           - Putty Key-Gen       (Windows: launch puttygen)
325           - SSH Local Protections  (a bit of safety on local side)
326           - SSH KnownHosts file (to avoid SSH 'localhost' collisions)
327           - SSVNC Mode          (Return to full SSVNC mode)
328
329           - Unix ssvncviewer    (set options for supplied Unix viewer)
330
331
332 Requirements:
333
334    When running this application on Unix/MacOSX the ssh(1) program must
335    be installed locally.  On Windows a plink/putty binary is included.
336
337    On the remote VNC Terminal Services host, x11vnc must be installed
338    (0.9.3 or higher), and at least one virtual X server: Xvfb, Xdummy,
339    or Xvnc must be available.  Xvfb is the most often used one.  All of
340    these programs must be available in $PATH on the remote server when
341    logged in via SSH.
342
343    The VNC terminal services administrator can make "x11vnc" be a wrapper
344    script that sets everything up correctly and then runs the real x11vnc.
345
346
347 Real X servers:
348
349    As a *BONUS*, if on the remote host, say a workstation, you have a
350    regular X session running on the physical hardware that you are
351    ALREADY logged into you can access to that display as well (x11vnc
352    will find it).
353
354    So this tool can be used as a simple way to launch x11vnc to find
355    your real X display on your workstation and connect to it.
356
357    The Printing and Sound redirection won't work for this mode however.
358    You will need to use the full SSVNC application to attempt that.
359
360    If you (mistakenly) have not logged into an X session on the real
361    X server on the workstation, a VIRTUAL (Xvfb, etc.) server will be
362    created for you (that may or may not be what you want).
363
364    The X Login Advanced setting can be used to connect to a X Display
365    Manger Greeter login panel (no one is logged in yet).  This requires
366    sudo(1) privileges on the remote machine.
367
368 More Info:
369
370    See these links for more information:
371
372        http://www.karlrunge.com/x11vnc/#tunnelling
373}
374
375	global version
376	set msg "                             SSVNC version: $version\n$msg"
377
378	.h.f.t insert end $msg
379	jiggle_text .h.f.t
380}
381
382proc help {} {
383	global ts_only
384	if {$ts_only} {
385		ts_help
386		return
387	}
388	toplev .h
389
390	set h 37
391	if [small_height] {
392		set h 26
393	}
394	scroll_text_dismiss .h.f 82 $h
395
396	center_win .h
397	wm title .h "SSL/SSH VNC Viewer Help"
398
399	global help_main help_prox help_misc help_tips
400
401	set help_main {
402 Hosts and Displays:
403
404    Enter the VNC host and display in the  'VNC Host:Display'  entry box.
405
406    It is of the form "host:number", where "host" is the hostname of the
407    machine running the VNC Server and "number" is the VNC display number;
408    it is often "0".  Some Examples:
409
410           snoopy:0
411
412           far-away.east:0
413
414           sunray-srv1.west:17
415
416           24.67.132.27:0
417
418    Then click on "Connect".  When you do the STUNNEL program will be started
419    locally to provide you with an outgoing SSL tunnel.
420
421    Once the STUNNEL is running, the TightVNC Viewer (Or perhaps Chicken of
422    the VNC on Mac OS X, or one you set under Options) will be automatically
423    started and directed to the local port of the SSL tunnel which, in turn,
424    encrypts and redirects the connection to the remote VNC server.
425
426    The remote VNC server **MUST** support an initial SSL/TLS handshake before
427    using the VNC protocol (i.e. VNC is tunnelled through the SSL channel
428    after it is established).  "x11vnc -ssl ..."  does this, and any VNC server
429    can be made to do this by using, e.g., STUNNEL or socat on the remote side.
430    SSVNC also supports VeNCrypt and ANONTLS SSL/TLS VNC servers (see below.)
431
432    * Automatic SSH Tunnels are described below.
433
434    * The 'No Encryption' / 'None' option provides a direct connection without
435      encryption (disable the button with the -enc option, or Options menu.)
436      More info in Tip 5.
437
438 Port numbers:
439
440    If you are using a port less than the default VNC port 5900 (usually
441    the VNC display = port - 5900), use the full port number itself, e.g.:
442
443         24.67.132.27:443
444
445    Note, however, if the number n after the colon is < 200, then a
446    port number 5900 + n is assumed; i.e. n is the VNC display number.
447    If you must use a TCP port less than 200, specify a negative value,
448    e.g.:  24.67.132.27:-80
449
450    For Reverse VNC connections (listening viewer, See Tip 2 and
451    Options -> Help), the port mapping is similar, except "listening
452    display :0" corresponds to port 5500, :1 to 5501, etc.
453    Specify a specific interface, e.g. 192.168.1.1:0 to have stunnel
454    listen on that interface only.  Listening on IPv6 can also be done, use
455    e.g. :::0 or ::1:0  This listening on IPv6 (:::0) works for UN-encrypted
456    reverse connections as well (mode 'None').
457
458
459 Zeroconf/Bonjour:
460
461    On Unix or Mac OS X, if the 'avahi-browse' or 'dns-sd' command is
462    available on the system and in your PATH, a 'Find' button is placed by
463    'VNC Host:Display'.  Clicking on Find will try to find VNC Servers on
464    your Local Network that advertize via the Zeroconf protocol.  A menu of
465    found hosts is presented for you to select from.
466
467
468 VNC Password:
469
470    On Unix or MacOSX IF there is a VNC password for the server you can
471    enter it in the "VNC Password:" entry box.
472
473    This is *REQUIRED* on MacOSX when Chicken of the VNC is used, because
474    that viewer does not put up a user password prompt when it learns
475    that a password is needed.
476
477    On Unix (including MacOSX using the X11 viewer) if you choose not to
478    enter the password you will simply be prompted for it in the terminal
479    window running TightVNC viewer if one is required.
480
481    On Windows TightVNC viewer will prompt you if a password is required.
482
483    NOTE: when you Save a VNC profile, the password is NOT saved (you need
484    to enter it each time).  Nor is the 'Verify All Certs' setting.
485
486
487 Profiles:
488
489    Use "Save" to save a profile (i.e. a host:display and its specific
490    settings) with a name.
491
492    To load in a saved Options profile, click on the "Load" button.
493
494    To list your profiles from the command line use:
495
496        ssvnc -profiles    (or -list)
497
498    You can launch ssvnc and have it immediately connect to the server
499    by invoking it something like this:
500
501        ssvnc profile1              (launches profile named "profile1")
502        ssvnc /path/to/profile.vnc  (loads the profile file, no launching)
503        ssvnc hostname:0            (connect to hostname VNC disp 0 via SSL)
504        ssvnc vnc+ssl://hostname:0  (same)
505        ssvnc vnc+ssh://hostname:0  (connect to hostname VNC disp 0 via SSH)
506
507    see the Tips 5 and 7 for more about the URL-like syntax.
508
509    If you don't want "ssvnc profile1" to immediately launch the connection
510    to the VNC server set the SSVNC_PROFILE_LOADONLY env. var. to 1.
511    (or specify the full path to the profile.vnc as shown above.)
512
513
514 SSL Certificate Verification:
515
516    *** IMPORTANT ***: If you do not take the steps to VERIFY the VNC Server's
517    SSL Certificate, you are in principle vulnerable to a Man-In-The-Middle
518    attack.  Without SSL Certificate verification, only passive network
519    sniffing attacks will be guaranteed to be prevented.  There are hacker
520    tools like dsniff/webmitm and cain that implement SSL Man-In-The-Middle
521    attacks.  They rely on the client user not bothering to check the cert.
522
523    Some people may be confused by the above because they are familiar with
524    their Web Browser using SSL (i.e. https://... websites) and those sites
525    are authenticated securely without the user's need to verify anything
526    manually.  The reason why this happens automatically is because 1) their
527    web browser comes with a bundle of Certificate Authority certificates
528    and 2) the https sites have paid money to the Certificate Authorities to
529    have their website certificate signed by them.  When using SSL in VNC we
530    normally do not do something this sophisticated, and so we have to verify
531    the certificates manually.  However, it is possible to use Certificate
532    Authorities with SSVNC; that method is described below.
533
534    You can use the "Fetch Cert" button to retrieve the Cert and then
535    after you check it is OK (say, via comparing the MD5 or other info)
536    you can "Save" it and use it to verify future connections to servers.
537    (However, see the note at the end of this section about CA certificates.)
538
539    When "Verify All Certs" is checked, this check is always enforced,
540    and so the first time you connect to a new server you may need to
541    follow a few dialogs to inspect and save the server certificate.
542    See the "Certs... -> Help" for information on how to manage certificates.
543
544    "Verify All Certs" is on by default.
545
546    Note, however, "Fetch Cert" and "Verify All Certs" are currently disabled
547    in the very rare "SSH + SSL" usage mode to avoid SSHing in twice.
548    You can manually set a ServerCert or CertsDir in this case if you like.
549
550
551    Advanced Method: Certificate Authority (CA):
552
553    If you, or your site administrator, goes though the steps of setting up
554    a Certificate Authority (CA) to sign the VNC server and/or VNC client
555    Certs, that can be used instead and avoids the need to manually verify
556    every cert while still authenticating every connection.  More info:
557    http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-ca
558
559    See the cmdline option -cacert file below in 'SSL Certificates'
560    for setting a default ServerCert/CA Cert.
561
562    You may also Import the CA Cert and save it to the 'Accepted Certs'
563    directory so the "Verify All Certs" automatic checking will find it.
564
565    Note that if a Server is using a CA signed certificate instead of
566    its own Self-Signed one, then the default "Verify All Certs/Fetch Cert"
567    saving mechanism will NOT succeed.  You must obtain the CA certificate
568    and explicitly set it as the ServerCert or Import it to Accepted Certs.
569
570
571 SSL/TLS Variants; VeNCrypt and ANONTLS:
572
573    SSVNC can also connect to VNC SSL/TLS variants; namely the VeNCrypt and
574    "TLS" VNC Security types.  Vino uses the latter (we call it "ANONTLS");
575    and a growing number use VeNCrypt (QEMU, ggi, virt-manager, VeNCrypt, Xen.)
576
577    Via the VeNCrypt bridge that SSVNC provides, the VeNCrypt/ANONTLS
578    support ALSO works with ANY 3rd party VNC Viewers you specify via
579    'Change VNC Viewer' (e.g. RealVNC, TightVNC, UltraVNC, etc.) that do
580    not directly support VeNCrypt or ANONTLS.  This works on all platforms:
581    Unix, MacOSX, and Windows.
582
583
584    Notes on VeNCrypt/ANONTLS Auto-detection:
585
586    IMPORTANT: VeNCrypt Server Auto-detection *ONLY* occurs in SSL mode
587    and when an initial fetch-cert action takes place.
588
589    While the initial certificate fetch is taking place SSVNC applies
590    heuristics to try to automatically detect the VeNCrypt or ANONTLS
591    protocol use by the VNC server.  This way it learns that the server
592    is using it and then knows to switch to VeNCrypt encrypted SSL/TLS at
593    the right point.  Then SSVNC makes a second (the real) connection to
594    VNC server and connects the VNC viewer to it.
595
596    In the default "Verify All Certs" mode, a fetch cert action always
597    takes place, and so VeNCrypt/ANONTLS will be autodected.
598
599    However, if you have specified an explicit ServerCert or disabled
600    "Verify All Certs" then even though the initial fetch cert action is no
601    longer needed, it is performed anyway because it allows VeNCrypt/ANONTLS
602    auto-detection.
603
604    To disabled this initial fetch (e.g. you know the VNC server is normal
605    SSL and not VeNCrypt/ANONTLS and want to connect more quickly) then
606    select "Do not Probe for VeNCrypt" in the Advanced Options menu.
607
608    On the other hand, if you know the VNC server ONLY supports VeNCrypt or
609    ANONTLS, to improve the accuracy and speed with which the connection
610    takes place, you can specify the one or both of the 'Server uses
611    VeNCrypt SSL encryption' and 'Server uses Anonymous Diffie-Hellman'
612    in the 'Advanced' options panel.  That way guessing via an initial
613    probe is not needed or performed.  See each options's Advanced Options
614    Help for more info.
615
616    Note that if you are using VeNCrypt or ANONTLS for REVERSE connections
617    (Listen) then you *MUST* set the 'Server uses VeNCrypt SSL encryption'
618    (and the ANON-DH if it applies) option in Advanced.  Note also that
619    REVERSE VeNCrypt and ANONTLS connections currently do not work on
620    Windows.
621
622    Also, if you are using the "Use SSH+SSL" double tunnel, you MUST set
623    'Server uses VeNCrypt SSL encryption' (and the ANON-DH if it applies)
624    because the initial fetch cert is disabled in SSH+SSL mode.
625
626
627 Deciphering SSL Negotiation Success or Failure:
628
629    Since SSVNC is a "glue program", in this case gluing VNCViewer and stunnel
630    together (with possibly a proxy helper) reporting is clumsy at best.
631    (In SSH encryption mode, it glues to ssh instead of stunnel.)  In most
632    cases the programs being "glued" are run in a terminal window where you
633    can see the program's output.  On Windows you will need to double click
634    on the stunnel tray icon to view its log.
635
636    Although the output is quite cryptic, you are encouraged to learn to
637    recognize some of the errors reported in it.
638
639    Here is stunnel output for a case of successfully verifying the VNC
640    Server's Certificate:
641
642      2008.11.20 08:09:39 LOG5[1472]: VERIFY OK: depth=0, /C=AU/L=...
643      2008.11.20 08:09:39 LOG6[1472]: SSL connected: new session negotiated
644      2008.11.20 08:09:39 LOG6[1472]: Negotiated ciphers: AES256-SHA SSLv3 ...
645
646    Here is a case where the Server's Cert did not match the ServerCert
647    we set:
648
649      2008.11.20 08:12:31 LOG4[1662]: VERIFY ERROR: depth=0, error=self ...
650      2008.11.20 08:12:31 LOG3[1662]: SSL_connect: 14090086: error:14090086:SSL
651           routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
652
653    Here is a case where the Server's Cert has expired:
654
655      2009.12.27 12:20:25 LOG4[25500]: VERIFY ERROR: depth=0, error=certificate
656           has expired: /C=AU/L=...
657      2009.12.27 12:20:25 LOG3[25500]: SSL_connect: 14090086: error:14090086:SSL
658           routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
659
660
661    If you disable "Verify All Certs" and do not supply a ServerCert,
662    then there will be no 'VERIFY ...' in the output because the SSVNC
663    stunnel accepts the server's cert without question (this is insecure.)
664
665    Also in the output will be messages about whether the SSL VNC server
666    rejected your connection because it requires you to authenticate
667    yourself with a certificate (MyCert).  Here is the case when you
668    supplied no MyCert:
669
670      2008.11.20 08:16:29 LOG3[1746]: SSL_connect: 14094410: error:14094410:
671          SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
672
673    or you used a certificate the server did not recognize:
674
675      2008.11.20 08:18:46 LOG3[1782]: SSL_connect: 14094412: error:14094412:
676          SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate
677
678    or your certificate has been revoked:
679
680     2008.11.20 08:20:08 LOG3[1913]: SSL_connect: 14094414: error:14094414:
681         SSL routines:SSL3_READ_BYTES:sslv3 alert certificate revoked
682
683
684 SSH:
685
686    Click on "Use SSH" if you want to use an *SSH* tunnel instead of SSL
687    (then the VNC Server does not need to speak SSL or use STUNNEL or socat).
688
689    You will need to be able to login to your account on the remote host
690    via SSH (e.g. via password, ssh keys, or ssh-agent).
691
692    Specify the SSH hostname and VNC display in the VNC Host:Display entry.
693    Use something like:
694
695           username@far-away.east:0
696
697    if your remote username is different from the one on the local viewer
698    machine.
699
700    On Windows you *MUST* supply the "username@" part because Putty/Plink
701    needs it to work correctly.
702
703    "SSH + SSL" is similar but its use is more rare because it requires 2
704    encrypted tunnels to reach the VNC server. See the Help under Options
705    for more info.
706
707    To connect to a non-standard SSH port, see SSH Proxies/Gateways section.
708
709    See Tip 8) for how to make this application be SSH-only with the -ssh
710    command line option or "sshvnc".
711
712    If you find yourself in the unfortunate circumstance that your ssh
713    username has a space in it, use %SPACE (or %TAB) like this:
714
715           fred%SPACEflintstone@xyzzy.net:0
716
717 Remote SSH Command:
718
719    In SSH or SSH + SSL mode you can also specify a remote command to run
720    on the remote ssh host in the "Remote SSH Command" entry.  The default
721    is just to sleep a bit (e.g. sleep 15) to make sure the tunnel ports
722    are established.  Alternatively you could have the remote command start
723    the VNC server, e.g.
724
725         x11vnc -display :0 -rfbport 5900 -localhost -nopw
726
727    When starting the VNC server this way, note that sometimes you will need
728    to correlate the VNC Display number with the "-rfbport" (or similar)
729    option of the server.  E.g. for VNC display :2
730
731         VNC Host:Display       username@somehost.com:2
732         Remote SSH Command:    x11vnc -find -rfbport 5902 -nopw
733
734    See the Tip 18) for using x11vnc PORT=NNNN feature (or vncserver(1)
735    output) to not need to specify the VNC display number or the x11vnc
736    -rfbport option.
737
738    Windows SSH SERVER: if you are ssh'ing INTO Windows (e.g. CYGWIN SSHD
739    server) there may be no "sleep" command so put in something like
740    "ping localhost" or "ping -n 10 -w 1000 localhost" to set a short
741    delay to let the tunnel ports get established.
742
743
744 SSL Certificates:
745
746    If you want to use a SSL Certificate (PEM) file to authenticate YOURSELF to
747    the VNC server ("MyCert") and/or to verify the identity of the VNC Server
748    ("ServerCert" or "CertsDir") select the certificate file by clicking the
749    "Certs ..." button before connecting.
750
751    Certificate verification is needed to prevent Man-In-The-Middle attacks;
752    if it is not done then only passive network sniffing attacks are prevented.
753    There are hacker tools like dsniff/webmitm and cain that implement SSL
754    Man-In-The-Middle attacks.  They rely on the client user not bothering to
755    check the cert.
756
757
758    See the x11vnc documentation:
759
760           http://www.karlrunge.com/x11vnc/ssl.html
761
762    for how to create and use PEM SSL certificate files.  An easy way is:
763
764           x11vnc -ssl SAVE ...
765
766    where it will print out its automatically generated certificate to the
767    screen and that can be copied safely to the viewer side.
768
769    You can also use the "Create Certificate" feature of this program under
770    "Certs ...".  Just click on it and follow the instructions in the dialog.
771    Then copy the cert file to the VNC Server and specify the other one in
772    the "Certs ..." dialog.
773
774    Alternatively you can use the "Import Certificate" action to paste in a
775    certificate or read one in from a file.  Or you can use the "Fetch Cert"
776    button on the main panel.  If "Verify All Certs" is checked, you will
777    be forced to check Certs of any new servers the first time you connect.
778
779    Note that "Verify All Certs" is on by default so that users who do not
780    understand the SSL Man-In-The-Middle problem will not be left completely
781    vulnerable to it (everyone still must make the effort to verify new
782    certificates by an external method to be completely safe).
783
784    To have "Verify All Certs" toggled off at startup, use "ssvnc -nv" or
785    set SSVNC_NO_VERIFY_ALL=1 before starting.  If you do not even want to
786    see the button, use "ssvnc -nvb" or SSVNC_NO_VERIFY_ALL_BUTTON=1.
787
788    Use the "-mycert file" option (same as "-cert file") to set a default
789    MyCert.  This is the same as "mycert=file" (also "cert=file") in the
790    ~/.ssvncrc file.  See Certs -> Help for more info.
791
792    Use the "-cacert file" option (same as "-ca file") to set a default
793    ServerCert (or CA).  This is the same as "cacert=file" (also "ca=file")
794    in the ~/.ssvncrc file.  See Certs -> Help for more info.
795
796    Use the "-crl file" option to set a default CRL File.  This is the same
797    as "crl=file" in the ~/.ssvncrc file.  See Certs -> Help for more info.
798
799    Prefix any of these files with "FORCE:" to make them immutable.
800
801
802
803 More Options:
804
805    To set other Options, e.g. for View-Only usage or to limit the number
806    of colors used, click on the "Options ..." button and read the Help there.
807
808 More Info:
809
810    Press the 'Proxies', 'Misc', and 'Tips' buttons below.
811
812    See also these links for more information:
813
814        http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-ext
815        http://stunnel.mirt.net
816        http://www.tightvnc.com
817}
818
819	set help_misc {
820 Windows STUNNEL problems:
821
822    Note that on Windows when the Viewer connection is finished by default
823    SSVNC will try to kill the STUNNEL process for you.
824
825    If Options -> Kill Stunnel Automatically is not set you will be
826    prompted if you want SSVNC to try to kill the STUNNEL process for you.
827    Usually you will say Yes, however if there are problems connecting
828    you may want to look at the STUNNEL Log first.
829
830    Before it is killed, double clicking the STUNNEL tray icon (dark green)
831    will show you its Log file (useful for debugging connection problems).
832
833    Even though SSVNC will kill the STUNNEL process for you, you will
834    still need to move the mouse over the icon to make the little picture
835    go away!!!  This is unfortunate but there does not seem to be a way
836    to avoid it.
837
838    In some cases you may need to terminate STUNNEL manually from the System
839    Tray (right click on dark green icon) and selecting "Exit".
840
841    Use -nokillstunnel or killstunnel=0 in ~/.ssvncrc to have SSVNC
842    start up with stunnel killing disabled.
843
844 Untrusted Local Users:
845
846    *IMPORTANT WARNING*:  If you run SSVNC on a workstation or computer
847    that other users can log into and you DO NOT TRUST these users
848    (it is a shame but sometimes one has to work in an environment like
849    this), then please note the following warning.
850
851    By 'do not trust' we mean they might try to gain access to remote
852    machines you connect to via SSVNC.  Note that an untrusted local
853    user can often obtain root access in a short amount of time; if a
854    user has achieved that, then all bets are off for ANYTHING that you
855    do on the workstation.  It is best to get rid of Untrusted Local
856    Users as soon as possible.
857
858    Both the SSL and SSH tunnels set up by SSVNC listen on certain ports
859    on the 'localhost' address and redirect TCP connections to the remote
860    machine; usually the VNC server running there (but it could also be
861    another service, e.g. CUPS printing).  These are the stunnel(8) SSL
862    redirection and the ssh(1) '-L' port redirection.  Because 'localhost'
863    is used only users or programs on the same workstation that is
864    running SSVNC can connect to these ports, however this includes any
865    local users (not just the user running SSVNC.)
866
867    If the untrusted local user tries to connect to these ports, he may
868    succeed by varying degrees to gain access to the remote machine.
869    We now list some safeguards one can put in place to try to make this
870    more difficult to achieve.
871
872    It probably pays to have the VNC server require a password, even
873    though there has already been SSL or SSH authentication (via
874    certificates or passwords).  In general if the VNC Server requires
875    SSL authentication of the viewer that helps, unless the untrusted
876    local user has gained access to your SSVNC certificate keys.
877
878    If the VNC server is configured to only allow one viewer connection
879    at a time, then the window of opportunity that the untrusted local
880    user can use is greatly reduced: he might only have a second or two
881    between the tunnel being set up and the SSVNC vncviewer connecting
882    to it (i.e. if the VNC server only allows a single connection, the
883    untrusted local user cannot connect once your session is established).
884    Similarly, when you disconnect the tunnel is torn down quickly and
885    there is little or no window of opportunity to connect (e.g. x11vnc
886    in its default mode exits after the first client disconnects).
887
888    Also for SSL tunnelling with stunnel(8) on Unix using one of the SSVNC
889    prebuilt 'bundles', a patched stunnel is provided that denies all
890    connections after the first one, and exits when the first one closes.
891    This is not true if the system installed stunnel(8) is used and is
892    not true when using SSVNC on Windows.
893
894    The following are experimental features that are added to SSVNC to
895    improve the situation for the SSL/stunnel and SSH cases.  Set them
896    via Options -> Advanced -> "STUNNEL Local Port Protections" or
897    "SSH Local Port Protections".
898
899    STUNNEL:
900
901    1) For SSL tunnelling with stunnel(8) on Unix there is a setting
902       'Use stunnel EXEC mode' that will try to exec(2) stunnel
903       instead of using a listening socket.  This will require using
904       the specially modified vncviewer unix viewer provided by SSVNC.
905       The mode works well and is currently set as the default.
906       Disable it if it causes problems or conflicts.
907
908    2) For SSL tunnelling with stunnel(8) on Unix there is a setting
909       'Use stunnel IDENT check' (experimental) to limit socket
910       connections to be from you (this assumes the untrusted local
911       user has not become root on your workstation and has modified
912       your local IDENT check service; if he has you have much bigger
913       problems to worry about...)
914
915       Neither of the above methods are available on Windows.
916
917    SSH:
918
919    1) There is also a simple LD_PRELOAD trick for SSH to limit the
920       number of accepted port redirection connections.  This makes the
921       window of time the untrusted local user can connect to the tunnel
922       much smaller.  Enable it via Options -> Advanced -> "SSH Local
923       Port Protections".  You will need to have the lim_accept.so file
924       in your SSVNC package.  The mode works well and is currently set
925       as the default.  Disable it if it causes problems or conflicts.
926
927       The above method is not available on Windows.
928
929    The main message is to 'Watch your Back' when you connect via the
930    SSVNC tunnels and there are users you don't trust on your workstation.
931    The same applies to ANY use of SSH '-L' port redirections or outgoing
932    stunnel SSL redirection services.
933}
934
935	set help_prox {
936 Here are a number of long sections on all sorts of proxies, Web, SOCKS,
937 SSH tunnels/gateways, UltraVNC, Single Click, etc., etc.
938
939
940 Proxies/Gateways:
941
942    If an intermediate proxy is needed to make the SSL connection
943    (e.g. a web gateway out of a firewall) enter it in the "Proxy/Gateway"
944    entry box:
945
946           VNC Host-Display:   host:number
947           Proxy/Gateway:      proxy-host:port
948    e.g.:
949           VNC Host-Display:   far-away.east:0
950           Proxy/Gateway:      myproxy.west:8080
951
952
953    If the "double proxy" case is required (e.g. coming out of a web
954    proxied firewall environment and then INTO a 2nd proxy to ultimately
955    reach the VNC server), separate them via a comma, e.g.:
956
957           VNC Host-Display:   far-away:0
958           Proxy/Gateway:      myproxy.west:8080,myhome.net:443
959
960    So it goes: viewer -> myproxy.west -> myhome.net -> far-away (VNC)
961
962    The proxies are assumed to be Web proxies.  To use SOCKS proxies:
963
964           VNC Host-Display:   far-away.east:0
965           Proxy/Gateway:      socks://mysocks.west:1080
966
967    Use socks5:// to force the SOCKS5 proxy protocol (e.g. for ssh -D).
968
969    You can prefix web proxies with http:// in SSL mode but it doesn't matter
970    since that is the default for a proxy.  (NOTE that in SSH or SSH+SSL
971    mode you MUST supply the http:// prefix for web proxies because in those
972    modes an SSH tunnel is the default proxy type: see the next section.)
973
974    Note that Web proxies are often configured to ONLY allow outgoing
975    connections to ports 443 (HTTPS) and 563 (SNEWS), so you might
976    have run the VNC server (or router port redirector) on those ports.
977    SOCKS proxies usually have no restrictions on port number.
978
979    You can chain up to 3 proxies (any combination of web (http://) and
980    socks://) by separating them with commas (i.e. first,second,third).
981
982    Proxies also work for un-encrypted connections ("None" or vnc://, Tip 5)
983
984    See the ss_vncviewer description and x11vnc FAQ for info on proxies:
985
986        http://www.karlrunge.com/x11vnc/faq.html#ss_vncviewer
987        http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-java-viewer-proxy
988
989
990 SSH Proxies/Gateways:
991
992    Proxy/Gateway also applies to SSH mode, it is a usually a gateway SSH
993    machine to log into via ssh that is not the workstation running the
994    VNC server.  However, Web and SOCKS proxies can also be used (see below).
995
996    For example if a company had a central login server: "ssh.company.com"
997    (accessible from the internet) and the internal workstation with VNC was
998    named "joes-pc", then to create an SSH tunnel one could put this in:
999
1000           VNC Host:Display:   joes-pc:0
1001           Proxy/Gateway:      ssh.company.com
1002
1003    It is OK if the hostname "joes-pc" only resolves inside the firewall.
1004
1005    The 2nd leg, from ssh.company.com -> joes-pc is done by a ssh -L
1006    redir and is not encrypted (but the viewer -> ssh.company.com 1st leg is
1007    an encrypted tunnel).
1008
1009    To SSH encrypt BOTH legs, try the "double SSH gateway" method using
1010    the "comma" notation:
1011
1012           VNC Host:Display:   localhost:0
1013           Proxy/Gateway:      ssh.company.com,joes-pc
1014
1015    this requires an SSH server also running on joes-pc.  So an initial SSH
1016    login is done to ssh.company.com, then a 2nd SSH is performed (through
1017    port a redirection of the first) to login straight to joes-pc where
1018    the VNC server is running.
1019
1020    Use username@host (e.g. joe@joes-pc  jsmith@ssh.company.com) if the
1021    user names differ between the various machines.
1022
1023    NOTE: On Windows you MUST always supply the username@ because putty's
1024    plink requires it.
1025
1026
1027    NON-STANDARD SSH PORT: To use a non-standard ssh port (i.e. a port other
1028    than 22) you need to use the Proxy/Gateways as well.  E.g. something
1029    like this for port 2222:
1030
1031           VNC Host:Display:   localhost:0
1032           Proxy/Gateway:      joe@far-away.east:2222
1033
1034    On Unix/MacOSX the username@ is not needed if it is the same as on
1035    the client.  This will also work going to a different internal machine,
1036    e.g. "joes-pc:0" instead of "localhost:0", as in the first example.
1037
1038
1039    A Web or SOCKS proxy can also be used with SSH.  Use this if you are
1040    inside a firewall that prohibits direct connections to remote SSH servers.
1041
1042           VNC Host:Display:   joe@far-away.east:0
1043           Proxy/Gateway:      http://myproxy.west:8080
1044
1045    or for SOCKS:
1046
1047           VNC Host:Display:   joe@far-away.east:0
1048           Proxy/Gateway:      socks://mysocks.west:1080
1049
1050    Use socks5://... to force the SOCKS5 version.  Note that the http://
1051    prefix is REQUIRED for web proxies in SSH or SSH+SSL modes (but it is
1052    the default proxy type in SSL mode.)
1053
1054    You can chain up to 3 proxies (any combination of http://, socks://
1055    and ssh) by separating them with commas (i.e. first,second,third).
1056
1057    Note: the Web and/or SOCKS proxies must come before any SSH gateways.
1058
1059    For a non-standard SSH port and a Web or SOCKS proxy try:
1060
1061           VNC Host:Display:   localhost:0
1062           Proxy/Gateway:      http://myproxy.west:8080,joe@far-away.east:2222
1063
1064    Even the "double SSH gateway" method (2 SSH encrypted legs) described
1065    above works with an initial Web or SOCKS proxy, e.g.:
1066
1067           VNC Host:Display:   localhost:0
1068           Proxy/Gateway:      socks://mysocks.west:1080,ssh.company.com,joes-pc
1069
1070
1071
1072    Some Notes on SSH localhost tunnelling with SSH options
1073      NoHostAuthenticationForLocalhost=yes and UserKnownHostsFile=file:
1074
1075    Warning:  Note that for proxy use with ssh(1), tunnels going through
1076    'localhost' are used.  This means ssh(1) thinks the remote hostname is
1077    'localhost', which may cause collisions and confusion when storing
1078    and checking SSH keys.
1079
1080    By default on Unix when a 'localhost' ssh host is involved the
1081    ssh option -o NoHostAuthenticationForLocalhost=yes is applied (see
1082    ssh_config(1) for details.)  This avoids the warnings and ssh refusing
1083    to connect, but it reduces security.  A man in the middle attack may
1084    be possible.  SSVNC prints out a warning in the terminal every time
1085    the NoHostAuthenticationForLocalhost option is used.
1086
1087    On Unix to disable the use of NoHostAuthenticationForLocalhost set the env.
1088    variable SSVNC_SSH_LOCALHOST_AUTH=1. This may induce extra ssh(1) dialogs.
1089
1090    On Unix a MUCH SAFER and more convenient way to proceed is to set the
1091    known hosts option in Options -> Advanced -> 'Private SSH KnownHosts file'
1092    Then, only for the host in the current profile, a private known_hosts
1093    file will be used and so there will be no 'localhost' collisions.
1094    This method is secure (assuming you verify the SSH key fingerprint)
1095    and avoids the man in the middle attack.
1096
1097    On Windows, Putty/Plink is used and does not have the UserKnownHosts
1098    or NoHostAuthenticationForLocalhost features.  Keys are stored in
1099    the registry as localhost:port pairs and so it is possible to use the
1100    'Port Slot' option to keep the keys separate to avoid the dialogs and
1101    also maintain good security.
1102
1103    Note that for the "double SSH gateway" method the risk from using
1104    NoHostAuthenticationForLocalhost is significantly less because the first
1105    ssh connection does not use the option (it connects directly to the remote
1106    host) and the second one is only exposed for the leg inside the first
1107    gateway (but is still vulnerable there when NoHostAuthenticationForLocalhost
1108    is used.)
1109
1110    As with a username that contains a space, use %SPACE (or %TAB) to
1111    indicate it in the SSH proxies, e.g. john%SPACEsmith@ssh.company.com
1112
1113 UltraVNC Proxies/Gateways:
1114
1115    UltraVNC has a "repeater" tool (http://www.uvnc.com/addons/repeater.html
1116    and http://koti.mbnet.fi/jtko/) that acts as a VNC proxy.  SSVNC can
1117    work with both mode I and mode II schemes of this repeater.
1118
1119    For Unix and MacOS X there is another re-implementation of the
1120    UltraVNC repeater:
1121
1122        http://www.karlrunge.com/x11vnc/ultravnc_repeater.pl
1123
1124    So one does not need to run the repeater on a Windows machine.
1125
1126    Note that even though the UltraVNC repeater tool is NOT SSL enabled,
1127    it can nevertheless act as a proxy for SSVNC SSL connections.
1128    This is because, just as with a Web proxy, the proxy negotiations
1129    occur before the SSL traffic starts.  (There is a separate UltraVNC
1130    tool, repeater_SSL.exe, that is SSL enabled and is discussed below.)
1131
1132    Note: it seems only SSL SSVNC connections make sense with the
1133    UltraVNC repeater.  SSH connections (previous section) do not seem to
1134    and so are not enabled to (let us know if you find a way to use it.)
1135
1136    Unencrypted (aka Direct) SSVNC VNC connections (Vnc:// prefix in
1137    'VNC Host:Display'; see Tip 5) also work with the UltraVNC repeater.
1138
1139    MODE I REPEATER:
1140
1141    For the mode I UltraVNC repeater the Viewer initiates the connection
1142    and passes a string that is the VNC server's IP address (or hostname)
1143    and port or display to the repeater (the repeater then makes the
1144    connection to the server host and then exchanges data back and forth.)
1145    To do this in SSVNC:
1146
1147           VNC Host:Display:   :0
1148           Proxy/Gateway:      repeater://myuvncrep.west:5900+joes-pc:1
1149
1150    Where "myuvncrep.west" is running the UltraVNC repeater and
1151    "joes-pc:1" is the VNC server the repeater will connect us to.
1152
1153    Note here that the VNC Host:Display can be anything because it is
1154    not used; we choose :0.  You cannot leave VNC Host:Display empty.
1155
1156    The Proxy/Gateway format is repeater://proxy:port+vncserver:display.
1157    The string after the "+" sign is passed to the repeater server for
1158    it to interpret (and so does not have to be the UltraVNC repeater;
1159    you could create your own if you wanted to.)  For this example,
1160    instead of joes-pc:1 it could be joes-pc:5901 or 192.168.1.4:1,
1161    192.168.1.4:5901, etc.
1162
1163    If you do not supply a proxy port, then the default 5900 is assumed,
1164    e.g. use repeater://myuvncrep.west+joes-pc:1 for port 5900 on
1165    myuvncrep.west then connecting to port 5901 on joes-pc.
1166
1167    X11VNC: For mode I operation the VNC server x11vnc simply runs as
1168    a normal SSL/VNC server:
1169
1170       x11vnc -ssl SAVE
1171
1172    because the repeater will connect to it as a VNC client would.
1173    For mode II operation additional options are needed (see below.)
1174
1175
1176    MODE II REPEATER:
1177
1178    For the mode II repeater both the VNC viewer and VNC server initiate
1179    TCP connections to the repeater proxy.  In this case they pass a string
1180    that identifies their mutual connection via "ID:NNNN", for example:
1181
1182           VNC Host:Display:   :0
1183           Proxy/Gateway:      repeater://myuvncrep.west:5900+ID:2345
1184
1185    again, the default proxy port is 5900 if not supplied.  And we need
1186    to supply a placeholder display ":0".
1187
1188    The fact that BOTH the VNC viewer and VNC server initiate outgoing
1189    TCP connections to the repeater makes some things tricky, especially
1190    for the SSL aspect.  In SSL one side takes the 'client' role and
1191    the other side must take the 'server' role.  These roles must be
1192    coordinated correctly or otherwise the SSL handshake will fail.
1193
1194    We now describe two scenarios: 1) SSVNC in Listening mode with STUNNEL
1195    in 'SSL server' role; and 2) SSVNC in Forward mode with STUNNEL in
1196    'SSL client' role.  For both cases we show how the corresponding
1197    VNC server x11vnc would be run.
1198
1199    SSVNC Listening mode / STUNNEL 'SSL server' role:
1200
1201      By default, when using SSL over a reverse connection the x11vnc VNC
1202      server will take the 'SSL client' role.  This way it can connect to a
1203      standard STUNNEL (SSL server) redirecting connections to a VNC viewer
1204      in Listen mode.  This is how SSVNC with SSL is normally intended to
1205      be used for reverse connections (i.e. without the UltraVNC Repeater.)
1206
1207      To do it this way with the mode II UltraVNC Repeater; you set
1208      Options -> Reverse VNC Connection, i.e. a "Listening Connection".
1209      You should disable 'Verify All Certs' unless you have already
1210      saved the VNC Server's certificate to Accepted Certs.  Or you can
1211      set ServerCert to the saved certificate.  Then click 'Listen'.
1212      In this case an outgoing connection is made to the UltraVNC
1213      repeater, but everything else is as for a Reverse connection.
1214
1215      Note that in Listening SSL mode you must supply a MyCert or use the
1216      "listen.pem" one you are prompted by SSVNC to create.
1217
1218      X11VNC command:
1219
1220        x11vnc -ssl -connect_or_exit repeater://myuvncrep.west+ID:2345
1221
1222
1223    SSVNC Forward mode / STUNNEL 'SSL client' role:
1224
1225      x11vnc 0.9.10 and later can act in the 'SSL server' role for Reverse
1226      connections (i.e. as it does for forward connections.)  Set these
1227      x11vnc options: '-env X11VNC_DISABLE_SSL_CLIENT_MODE=1 -sslonly'
1228
1229      The -sslonly option is to prevent x11vnc from thinking the delay in
1230      connection implies VeNCrypt instead of VNC over SSL.  With x11vnc
1231      in X11VNC_DISABLE_SSL_CLIENT_MODE mode, you can then have SSVNC make
1232      a regular forward connection to the UltraVNC repeater.
1233
1234      Note that SSVNC may attempt to do a 'Fetch Cert' action in forward
1235      connection mode to either retrieve the certificate or probe for
1236      VeNCrypt and/or ANONDH.  After that 'Fetch Cert' is done the
1237      connection to the UltraVNC repeater will be dropped.  This is a
1238      problem for the subsequent real VNC connection.  You can disable
1239      'Verify All Certs' AND also set 'Do not Probe for VeNCrypt'
1240      to avoid the 'Fetch Cert' action.  Or, perhaps better, add to
1241      x11vnc command line '-connect_or_exit repeater://... -loop300,2'
1242      (in addition to the options in the previous paragraphs.)  That way
1243      x11vnc will reconnect once to the Repeater after the 'Fetch Cert'
1244      action.  Then things should act pretty much as a normal forward
1245      SSL connection.
1246
1247      X11VNC 0.9.10 command (split into two lines):
1248
1249        x11vnc -ssl -connect_or_exit repeater://myuvncrep.west+ID:2345 \
1250             -env X11VNC_DISABLE_SSL_CLIENT_MODE=1 -loop300,2 -sslonly
1251
1252    We recommend using "SSVNC Forward mode / STUNNEL 'SSL client' role"
1253    if you are connecting to x11vnc 0.9.10 or later.  Since this does
1254    not use Listen mode it should be less error prone and less confusing
1255    and more compatible with other features.  Be sure to use all of
1256    the x11vnc options in the above command line.  To enable VeNCrypt,
1257    replace '-sslonly' with '-vencrypt force'.  If you do not indicate
1258    them explicitly to SSVNC, SSVNC may have to probe multiple times for
1259    VeNCrypt and/or ANONDH.  So you may need '-loop300,4' on the x11vnc
1260    cmdline so it will reconnect to the UltraVNC repeater 3 times.
1261
1262
1263    Note that for UNENCRYPTED (i.e. direct) SSVNC connections (see vnc://
1264    in Tip 5) using the UltraVNC Repeater mode II there is no need to
1265    use a reverse "Listening connection" and so you might as well use
1266    a forward connection.
1267
1268    For Listening connections, on Windows after the VNC connection you
1269    MUST manually terminate the listening VNC Viewer (and connect again
1270    if desired.)  Do this by going to the System Tray and terminating
1271    the Listening VNC Viewer.  Subsequent connection attempts using the
1272    repeater will fail unless you do this and restart the Listen.
1273
1274    On Unix and MacOS X after the VNC connection the UltraVNC repeater
1275    proxy script will automatically restart and reconnect to the repeater
1276    for another connection.  So you do not need to manually restart it.
1277    To stop the listening, kill the listening VNC Viewer with Ctrl-C.
1278
1279    In the previous sections it was mentioned one can chain up to 3
1280    proxies together by separating them with commas: proxy1,proxy2,proxy3.
1281    Except where explicitly noted below this should work for "repeater://..."
1282    as the final proxy.  E.g. you could use a web proxy to get out of a
1283    firewall, and then connect to a remote repeater.
1284
1285    The UltraVNC SSL enabled repeater_SSL.exe is discussed below.
1286
1287
1288 UltraVNC Single Click:
1289
1290    UltraVNC has Single Click (SC) Windows VNC servers that allow naive
1291    users to get them running very easily (a EXE download and a few
1292    mouse clicks).  See http://sc.uvnc.com/ for details on how to create
1293    these binaries.  Also there is a how-to here:
1294    http://www.simply-postcode-lookup.com/SingleClickUltraVNC/SingleClickVNC.htm
1295
1296    The SC EXE is a VNC *server* that starts up a Reverse VNC connection
1297    to a Listening Viewer (e.g. the viewer address/port/ID is hardwired
1298    into the SC EXE).  So SC is not really a proxy, but it can be used
1299    with UltraVNC repeater proxies and so we describe it here.
1300
1301    One important point for SC III binary creation: do NOT include
1302    "-id N" in the helpdesk.txt config file.  This is because the with
1303    SSVNC the Ultra VNC repeater IS NOT USED (see below for how to
1304    use it).  Use something like for helpdesk.txt:
1305
1306       [TITLE]
1307       My UltraVNC SC III
1308
1309       [HOST]
1310       Internet Support XYZ
1311       -sslproxy -connect xx.xx.xx.xx:5500 -noregistry
1312
1313    (replace xx.xx.xx.xx with IP address or hostname of the SSVNC machine.)
1314
1315    The Unix SSVNC vncviewer supports the both the unencrypted "SC I"
1316    mode and the SSL encrypted "SC III" mode.  For both cases SSVNC
1317    must be run in Listening mode (Options -> Reverse VNC Connection)
1318
1319    For SC I, enable Reverse VNC Connection and put Vnc://0 (see Tip 5
1320    below) in the VNC Host:Display to disable encryption (use a different
1321    number if you are not using the default listening port 5500).
1322    Then click on the "Listen" button and finally have the user run your
1323    Single Click I EXE.
1324
1325    BTW, we used this for a SC I helpdesk.txt:
1326
1327       [TITLE]
1328       My UltraVNC SC I
1329
1330       [HOST]
1331       Internet Support XYZ
1332       -connect xx.xx.xx.xx:5500 -noregistry
1333
1334    For SC III (SSL), enable Reverse VNC Connection and then UNSET "Verify
1335    All Certs" (this is required).  Let the VNC Host:Display be ":0"
1336    (use a different number if you are not using the default listening
1337    port 5500).  Then click on the "Listen" button and finally have the
1338    user run your Single Click III EXE.
1339
1340    Note that in Listening SSL mode you MUST supply a MyCert or use the
1341    "listen.pem" one you are prompted by SSVNC to create.
1342
1343
1344 UltraVNC repeater_SSL.exe proxy:
1345
1346    For repeater_SSL.exe SSL usage, with Single Click III or otherwise
1347    (available at http://www.uvnc.com/pchelpware/SCIII/index.html)
1348    it helps to realize that the ENTIRE connection is SSL encrypted,
1349    even the proxy host:port/ID:NNNN negotiation, and so a different
1350    approach needs to be taken from that described above in 'UltraVNC
1351    Proxies/Gateways'.  In this case do something like this:
1352
1353           VNC Host:Display:   :0
1354           Proxy/Gateway:      sslrepeater://myuvncrep.west:443+ID:2345
1355
1356    The sslrepeater:// part indicates the entire ID:XYZ negotiation must
1357    occur inside the SSL tunnel.  Listening mode is not required in this
1358    case: a forward VNC connection works fine (and is recommended).
1359    As before, the ":0" is simply a placeholder and is not used.
1360    Note that the UltraVNC repeater_SSL.exe listens on port 443 (HTTPS),
1361    (it is not clear that it can be modified to use another port.)
1362
1363    Non-ID connections sslrepeater://myuvncrep.west:443+host:disp also
1364    work, but the 2nd leg repeater <-> host:disp must be unencrypted.
1365    The first leg SSVNC <-> repeater is, however, SSL encrypted.
1366
1367    sslrepeater:// only works on Unix or MacOSX using the provided
1368    SSVNC vncviewer.  The modified viewer is needed; stock VNC viewers
1369    will not work.  Also, proxy chaining (bouncing off of more than one
1370    proxy) currently does not work for repeater_SSL.exe.
1371
1372
1373 VeNCrypt is treated as a proxy:
1374
1375    SSVNC supports the VeNCrypt VNC security type.  You will find out more
1376    about this security type in the other parts of the Help documentation.
1377    In short, it does a bit of plain-text VNC protocol negotiation before
1378    switching to SSL/TLS encryption and authentication.
1379
1380    SSVNC implements its VeNCrypt support as final proxy in a chain
1381    of proxies.  You don't need to know this or specify anything, but
1382    it is good to know since it uses up one of the 3 proxies you are
1383    allowed to chain together.  If you watch the command output you will
1384    see the vencrypt:// proxy item.
1385
1386    You can specify that a VNC server uses VeNCrypt (Options -> Advanced)
1387    or you can let SSVNC try to autodetect VeNCrypt.
1388
1389
1390 IPv6 can be treated as a proxy for UN-ENCRYPTED connections:
1391
1392    Read Tip 20 about SSVNC's IPv6 (128 bit IP addresses) support.
1393    In short, because stunnel and ssh support IPv6 hostnames and
1394    addresses, SSVNC does too without you needing to do anything.
1395
1396    However, in some rare usage modes you will need to specify the IPv6
1397    server destination in the Proxy/Gateway entry box.  The only case
1398    this appears to be needed is when making an un-encrypted connection
1399    to an IPv6 VNC server.  In this case neither stunnel nor ssh are
1400    used and you need to specify something like this:
1401
1402              VNC Host:Display:       localhost:0
1403              Proxy/Gateway:          ipv6://2001:4860:b009::68:5900
1404
1405    and then select 'None' as the encryption type.  Note that the above
1406    'localhost:0' setting can be anything; it is basically ignored.
1407
1408    Note that on Unix, MacOSX, and Windows un-encrypted ipv6 connections
1409    are AUTODETECTED and so you likely NEVER need to supply ipv6://
1410    Only try it if you encounter problems.  Also note that the ipv6://
1411    proxy type does not work on Windows, so only the autodetection is
1412    available there.
1413
1414    Note that if there is some other proxy, e.g. SOCKS or HTTP and that
1415    proxy server is an IPv6 host (or will connect you to one) then any
1416    sort of connection through that proxy will work OK: un-encrypted as
1417    well as SSL or SSH connections, etc.
1418
1419    Unencrypted connection is the only special case where you may need
1420    to specify an ipv6:// proxy.  If you find another use let us know.
1421
1422    See Tip 20 for more info.
1423}
1424
1425	set help_tips {
1426 Tips and Tricks:
1427
1428     Table of Contents:
1429
1430      1) Connect to Non-Standard SSH port.
1431      2) Reverse VNC connections (Listening)
1432      3) Global options in ~/.ssvncrc
1433      4) Fonts
1434      5) vnc://host for un-encrypted connection
1435      6) Home directory for memory stick usage, etc.
1436      7) vncs:// vncssl:// vnc+ssl:// vnc+ssh:// URL-like prefixes
1437      8) sshvnc / -ssh SSH only GUI
1438      9) tsvnc / -ts Terminal services only GUI (SSH+x11vnc)
1439     10) 2nd GUI window on Unix/MacOSX
1440     11) Ctrl-L or Button3 to Load profile
1441     12) SHELL command or Ctrl-S for SSH terminal w/o VNC
1442     13) KNOCK command for port-knock sequence
1443     14) Unix/MacOSX general SSL redirector (not just VNC)
1444     15) Environment variables
1445     16) Bigger "Open File" dialog window
1446     17) Unix/MacOSX extra debugging output
1447     18) Dynamic VNC Server Port determination with SSH
1448     19) No -t ssh cmdline option for older sshd
1449     20) IPv6 support.
1450
1451     1) To connect in SSH-Mode to a server running SSH on a non-standard
1452        port (22 is the standard port) you need to use the Proxy/Gateway
1453        setting.  The following is from the Proxies Help panel:
1454
1455        NON-STANDARD SSH PORT: To use a non-standard ssh port (i.e. a port other
1456        than 22) you need to use the Proxy/Gateways as well.  E.g. something
1457        like this for port 2222:
1458
1459               VNC Host:Display:   localhost:0
1460               Proxy/Gateway:      joe@far-away.east:2222
1461
1462        The username@ is not needed if it is the same as on the client.  This
1463        will also work going to a different internal machine, e.g. "joes-pc:0"
1464        instead of "localhost:0", as in the first example.
1465
1466     2) Reverse VNC connections (Listening) are possible as well.
1467        In this case the VNC Server initiates the connection to your
1468        waiting (i.e. listening) SSVNC viewer.
1469
1470        Go to Options and select "Reverse VNC connection".  In the 'VNC
1471        Host:Display' entry box put in the number (e.g. "0" or ":0", or
1472        ":1", etc) that corresponds to the Listening display (0 -> port
1473        5500, 1 -> port 5501, etc.) you want to use.  Then clicking on
1474        'Listen' puts your SSVNC viewer in a "listening" state on that
1475        port number, waiting for a connection from the VNC Server.
1476
1477        On Windows or using a 3rd party VNC Viewer multiple, simultaneous
1478        reverse connections are always enabled.  On Unix/MacOSX with the
1479        provided ssvncviewer they are disabled by default.  To enable them:
1480        Options -> Advanced -> Unix ssvncviewer -> Multiple LISTEN Connections
1481
1482        Specify a specific interface, e.g. 192.168.1.1:0 to have stunnel
1483        only listen on that interface.  IPv6 works too, e.g. :::0 or ::1:0
1484        This also works for UN-encrypted reverse connections as well ('None').
1485
1486        See the Options Help for more info.
1487
1488     3) You can put global options in your ~/.ssvncrc file (ssvnc_rc on
1489        Windows). Currently they are:
1490
1491	Put "mode=tsvnc" or "mode=sshvnc" in the ~/.ssvncrc file to have
1492	the application start up in the given mode.
1493
1494        desktop_type=wmaker    (e.g.) to switch the default Desktop Type.
1495
1496        desktop_size=1280x1024 (e.g.) to switch the default Desktop Size.
1497
1498        desktop_depth=24       (e.g.) to switch the default Desktop Color Depth
1499
1500        xserver_type=Xdummy    (e.g.) to switch the default X Server Type.
1501
1502        (The above 4 settings apply only to the Terminal Services Mode.)
1503
1504        noenc=1  (same as the -noenc option for a 'No Encryption' option)
1505        noenc=0  (do not show the 'No Encryption' option)
1506
1507        killstunnel=1 (same as -killstunnel), on Windows automatically kills
1508        the STUNNEL process when the viewer exits.  Disable via killstunnel=0
1509        and -nokillstunnel.
1510
1511        ipv6=0   act as though IPv6 was not detected.
1512        ipv6=1   act as though IPv6 was detected.
1513
1514        cotvnc=1 have the default vncviewer on Mac OS X be the Chicken of
1515        the VNC.  By default the included ssvnc X11 vncviewer is used
1516        (requires Mac OS X X11 server to be running.)
1517
1518        mycert=file (same as -mycert file option).  Set your default MyCert
1519        to "file".  If file does not exist ~/.vnc/certs/file is used.
1520
1521        cacert=file (same as -cacert file option).  Set your default ServerCert
1522        to "file".  If file does not exist ~/.vnc/certs/file is used.  If
1523        file is "CA" then ~/.vnc/certs/CA/cacert.pem is used.
1524
1525        crl=file (same as -crl file option).  Set your default CRL File
1526        to "file".  If file does not exist ~/.vnc/certs/file is used.
1527
1528        Prefix any of these cert/key files with "FORCE:" to make them
1529        immutable, e.g.  "cacert=FORCE:CA".
1530
1531        You can set any environment variable in ~/.ssvncrc by using a line
1532        like env=VAR=value, for example:  env=SSVNC_FINISH_SLEEP=2
1533
1534        To change the fonts (see Tip 4 below for examples):
1535
1536        font_default=tk-font-name     (sets the font for menus and buttons)
1537        font_fixed=tk-font-name       (sets the font for help text)
1538
1539     4) Fonts: To change the tk fonts, set these environment variables
1540        before starting up ssvnc: SSVNC_FONT_DEFAULT and SSVNC_FONT_FIXED.
1541        For example:
1542
1543            % env SSVNC_FONT_DEFAULT='helvetica -20 bold' ssvnc
1544            % env SSVNC_FONT_FIXED='courier -14' ssvnc
1545
1546        or set both of them at once.  You can also set 'font_default' and
1547        'font_fixed' in your ~/.ssvncrc.  E.g.:
1548
1549        font_default=helvetica -16 bold
1550        font_fixed=courier -12
1551
1552     5) If you want to make a Direct VNC connection, WITH *NO* SSL OR
1553        SSH ENCRYPTION or authentication, use the "vnc://" prefix in the
1554        VNC Host:Display entry box, e.g. "vnc://far-away.east:0"  This
1555        also works for reverse connections, e.g. vnc://0
1556
1557        Use Vnc:// (i.e. capital 'V') to avoid being prompted if you are
1558        sure you want no encryption.  For example, "Vnc://far-away.east:0"
1559        Shift+Ctrl-E in the entry box is a short-cut to add or remove
1560        the prefix "Vnc://" from the host:disp string.
1561
1562        You can also run ssvnc with the '-noenc' cmdline option (now
1563        the default) to have a check option 'None' that lets you turn off
1564        Encryption (and profiles will store this setting).  Pressing Ctrl-E
1565        on the main panel is a short-cut to toggle between the -noenc 'No
1566        Encryption' mode and normal mode.  The option "Show 'No Encryption'
1567        Option" under Options also toggles it.
1568
1569        The '-enc' option disables the button (and so makes it less obvious
1570        to naive users how to disable encryption.)
1571
1572        Note as of SSVNC 1.0.25 the '-noenc' mode is now the default. I.e.
1573        the 'No Encryption' option ('None') is shown by default.  When
1574        you select 'None' you do not need to supply the "vnc://" prefix.
1575        To disable the button supply the '-enc' cmdline option.
1576
1577        Setting SSVNC_DISABLE_ENCRYPTION_BUTTON=1 in your environment is
1578        the same as -noenc.  You can also put noenc=1 in your ~/.ssvncrc file.
1579
1580        Setting SSVNC_DISABLE_ENCRYPTION_BUTTON=0 in your environment is
1581        the same as -enc.  You can also put noenc=0 in your ~/.ssvncrc file.
1582
1583        Please be cautious/thoughtful when you make a VNC connection with
1584        encryption disabled.  You may send sensitive information (e.g. a
1585        password) over the network that can be sniffed.
1586
1587        It is also possible (although difficult) for someone to hijack an
1588        existing unencrypted VNC session.
1589
1590        Often SSVNC is used to connect to x11vnc where the Unix username and
1591        password is sent over the channel.  It would be a very bad idea to
1592        let that data be sent over an unencrypted connection!  In general,
1593        it is not wise to have a plaintext VNC connection.
1594
1595        Note that even the VNC Password challenge-response method (the password
1596        is not sent in plaintext) leaves your VNC password susceptible to a
1597        dictionary attack unless encryption is used to hide it.
1598
1599        So (well, before we made the button visible by default!) we forced
1600        you to learn about and supply the "vnc://" or "Vnc://" prefix to
1601        the host:port or use -noenc or the "Show 'No Encryption' Option"
1602        to disable encryption.  This is a small hurdle, but maybe someone
1603        will think twice.  It is a shame that VNC has been around for
1604        over 10 years and still does not have built-in strong encryption.
1605
1606        Note the Vnc:// or vnc:// prefix will be stored in any profile that
1607        you save so you do not have to enter it every time.
1608
1609        Set the env var SSVNC_NO_ENC_WARN=1 to skip the warning prompts the
1610        same as the capitalized Vnc:// does.
1611
1612     6) Mobile USB memory stick / flash drive usage:  You can unpack
1613        ssvnc to a flash drive for impromptu usage (e.g. from a friends
1614        computer).
1615
1616        If you create a directory "Home" in the toplevel ssvnc directory,
1617        then that will be the default location for your VNC profiles
1618        and certs.  So they follow the drive this way.  If you run like
1619        this: "ssvnc ." or "ssvnc.exe ." the "Home" directory will be
1620        created for you.
1621
1622        WARNING: if you use ssvnc from an "Internet Cafe", i.e. an
1623        untrusted computer, an unscrupulous person may be capturing
1624        keystrokes, etc.!
1625
1626	You can also set the SSVNC_HOME env. var. to point to any
1627	directory you want. It can be set after starting ssvnc by putting
1628	HOME=/path/to/dir in the Host:Display box and clicking "Connect".
1629
1630        For a Windows BAT file to get the "Home" directory correct
1631        something like this might be needed:
1632
1633         cd \ssvnc\Windows
1634         start \ssvnc\Windows\ssvnc.exe
1635
1636     7) In the VNC Host:Display entry you can also use these "URL-like"
1637        prefixes:
1638
1639           vncs://host:0, vncssl://host:0, vnc+ssl://host:0  for SSL
1640
1641        and
1642
1643           vncssh://host:0, vnc+ssh://host:0                 for SSH
1644
1645        There is no need to toggle the SSL/SSH setting.  These also work
1646        from the command line, e.g.:  ssvnc vnc+ssh://mymachine:10
1647
1648     8) If you want this application to be SSH only, then supply the
1649        command line option "-ssh" or set the env. var SSVNC_SSH_ONLY=1.
1650
1651        Then no GUI elements specific to SSL will appear (the
1652        documentation wills still refer to the SSL mode, however).
1653        To convert a running app to ssh-only select "Mode: SSH-Only"
1654        in Options.
1655
1656        The wrapper scripts "sshvnc" and "sshvnc.bat" will start it up
1657        automatically this way.
1658
1659        Or in your ~/.ssvncrc (or ~/ssvnc_rc on Windows) put "mode=sshvnc"
1660        to have the tool always start up in that mode.
1661
1662     9) For an even simpler "Terminal Services" mode use "tsvnc" or
1663        "tsvnc.bat" (or "-ts" option).  This mode automatically launches
1664        x11vnc on the remote side to find or create your Desktop session
1665        (usually the Xvfb X server).  So x11vnc must be available on the
1666        remote server machines under "Terminal Services" mode.
1667
1668        From a full ssvnc you can press Ctrl-h to go into ssh-only mode
1669        and Ctrl-t to toggle between "tsvnc" and "ssvnc" modes.  The
1670        Options Mode menu also let you switch.
1671
1672        Or in your ~/.ssvncrc (or ~/ssvnc_rc on Windows) put "mode=tsvnc"
1673        to have the tool always start up in that mode.
1674
1675    10) On Unix to get a 2nd GUI (e.g. for a 2nd connection) press Ctrl-N
1676        on the GUI.  If only the xterm window is visible you can press
1677        Ctrl-N or try Ctrl-LeftButton -> New SSVNC_GUI.  On Windows you
1678        will have to manually Start a new one: Start -> Run ..., etc.
1679
1680    11) Pressing the "Load" button or pressing Ctrl-L or Clicking the Right
1681        mouse button on the main GUI will invoke the Load dialog.
1682
1683        Pressing Ctrl-O on the main GUI will bring up the Options Panel.
1684        Pressing Ctrl-A on the main GUI will bring up the Advanced Options.
1685
1686    12) If you use "SHELL" for the "Remote SSH Command" (or in the display
1687        line: "user@hostname cmd=SHELL") then you get an SSH shell only:
1688        no VNC viewer will be launched.  On Windows "PUTTY" will try
1689        to use putty.exe (better terminal emulation than plink.exe).
1690
1691        A ShortCut for this is Ctrl-S with user@hostname in the entry box.
1692
1693    13) If you use "KNOCK" for the "Remote SSH Command" (or in the display
1694        line "user@hostname cmd=KNOCK") then only the port-knocking is done.
1695
1696        A ShortCut for this is Ctrl-P with hostname the entry box.
1697
1698        If it is KNOCKF, i.e. an extra "F", then the port-knocking
1699        "FINISH" sequence is sent, if any.  A ShortCut for this
1700        Shift-Ctrl-P as long as hostname is present.
1701
1702    14) On Unix to have SSVNC act as a general STUNNEL redirector (i.e. no
1703        VNC), put the desired host:port in VNC Host:Display (use a
1704        negative port value if it is to be less than 200), then go to
1705        Options -> Advanced -> Change VNC Viewer.  Change the "viewer"
1706        command to be "xmessage OK" or "xmessage <port>" (or sleep) where
1707        port is the desired local listening port.  Then click Connect.
1708        If you didn't set the local port look for it in the terminal output.
1709
1710        On Windows set 'viewer' to "NOTEPAD" or similar; you can't
1711        control the port though.  It is usually 5930, 5931, ... Watch
1712        the messages or look at the stunnel log.
1713
1714    15) Tricks with environment variables:
1715
1716        You can change the X DISPLAY variable by typing DISPLAY=... into
1717        VNC Host:Display and hitting Return or clicking Connect. Same
1718        for HOME=.  On Mac, you can set DYLD_LIBRARY_PATH=... too.
1719        It should propagate down the viewer.
1720
1721        Setting SLEEP=n increases the amount of time waited before
1722        starting the viewer.  The env. var. SSVNC_EXTRA_SLEEP also does
1723        this (and also Sleep: Option setting) Setting FINISH=n sets the
1724        amount of time slept before the Terminal window exits on Unix
1725        and MacOS X.  (same as SSVNC_FINISH_SLEEP env. var.)
1726
1727        Full list of parameters HOME/SSVNC_HOME, DISPLAY/SSVNC_DISPLAY
1728        DYLD_LIBRARY_PATH/SSVNC_DYLD_LIBRARY_PATH, SLEEP/SSVNC_EXTRA_SLEEP
1729        FINISH/SSVNC_FINISH_SLEEP, DEBUG_NETSTAT, REPEATER_FORCE,
1730        SSH_ONLY, TS_ONLY, NO_DELETE, BAT_SLEEP, IPV6/SSVNC_IPV6=0 or 1.
1731        See below for more info.  (the ones joined by "/" are equivalent
1732        names, and the latter can be set as an env. var. as well.)
1733
1734        After you set the parameter, clear out the 'VNC Host:Display'
1735        entry and replace it with the actual host and display number.
1736
1737        To replace the xterm terminal where most of the external commands
1738        are run set SSVNC_XTERM_REPLACEMENT to a command that will run
1739        a command in a terminal.  I.e.:  "$SSVNC_XTERM_REPLACEMENT cmd"
1740        will run cmd.  If present, %GEOMETRY is expanded to a desired
1741        +X+Y geometry.  If present, %TITLE is expanded to a desired title.
1742        Examples: SSVNC_XTERM_REPLACEMENT='gnome-terminal -e'
1743                  SSVNC_XTERM_REPLACEMENT='gnome-terminal -t "%TITLE" -e'
1744                  SSVNC_XTERM_REPLACEMENT='konsole -e'
1745
1746        More info: EXTRA_SLEEP: seconds of extra sleep in scripts;
1747        FINISH_SLEEP: final extra sleep at end; DEBUG_NETSTAT put up a
1748        window showing what netstat reports; NO_DELETE: do not delete tmp
1749        bat files on Windows (for debugging); BAT_SLEEP: sleep this many
1750        seconds at the end of each Windows bat file (for debugging.)
1751
1752        You can also set any environment variable by entering in something
1753        like ENV=VAR=VAL  e.g. ENV=SSH_AUTH_SOCK=/tmp/ssh-BF2297/agent.2297
1754        Use an empty VAL to unset the variable.
1755
1756        There are also a HUGE number of env. vars. that apply to the Unix
1757        and MacOS X wrapper script 'ss_vncviewer' and/or the ssvncviewer
1758        binary.  See Options -> Advanced -> Unix ssvncviewer -> Help for
1759        all of them.
1760
1761    16) On Unix you can make the "Open File" and "Save File" dialogs
1762        bigger by setting the env. var. SSVNC_BIGGER_DIALOG=1 or
1763        supplying the -bigger option.  If you set it to a Width x Height,
1764        e.g. SSVNC_BIGGER_DIALOG=500x200, that size will be used.
1765
1766    17) On Unix / MacOSX to enable debug output you can set these env.
1767        vars to 1: SSVNC_STUNNEL_DEBUG, SSVNC_VENCRYPT_DEBUG, and
1768        SS_DEBUG (very verbose)
1769
1770    18) Dynamic VNC Server Port determination and redirection:  If you
1771        are running SSVNC on Unix and are using SSH to start the remote
1772        VNC server and the VNC server prints out the line "PORT=NNNN"
1773        to indicate which dynamic port it is using (x11vnc does this),
1774        then if you prefix the SSH command with "PORT=" SSVNC will watch
1775        for the PORT=NNNN line and uses ssh's built in SOCKS proxy
1776        (ssh -D ...) to connect to the dynamic VNC server port through
1777        the SSH tunnel.  For example:
1778
1779                VNC Host:Display     user@somehost.com
1780                Remote SSH Command:  PORT= x11vnc -find -nopw
1781
1782        or "PORT= x11vnc -display :0 -localhost", etc.  Or use "P= ..."
1783
1784        There is also code to detect the display of the regular Unix
1785        vncserver(1).  It extracts the display (and hence port) from
1786        the lines "New 'X' desktop is hostname:4" and also
1787        "VNC server is already running as :4".  So you can use
1788        something like:
1789
1790                PORT= vncserver; sleep 15
1791        or:     PORT= vncserver :4; sleep 15
1792
1793        the latter is preferred because when you reconnect with it will
1794        find the already running one.  The former one will keep creating
1795        new X sessions if called repeatedly.
1796
1797        On Windows if PORT= is supplied SOCKS proxying is not used, but
1798        rather a high, random value of the VNC port is chosen (e.g. 8453)
1799        and assumed to be free, and is passed to x11vnc's -rfbport option.
1800        This only works with x11vnc (not vncserver).
1801
1802    19) On Unix if you are going to an older SSH server (e.g. Solaris 10),
1803        you will probably need to set the env. var. SS_VNCVIEWER_NO_T=1
1804        to disable the ssh "-t" option being used (that can prevent the
1805        command from being run).
1806
1807    20) SSVNC is basically a wrapper for the stunnel and ssh programs,
1808        and because those two programs have good IPv6 support SSVNC will
1809        for most usage modes support it as well.  IPv6 is 128 bit internet
1810        addresses (as opposed to IPv4 with its 32 bit xxx.yyy.zzz.nnn IPs.
1811
1812        So for basic SSL and SSH connections if you type in an IPv6 IP
1813        address, e.g. '2001:4860:b009::68', or a hostname with only an
1814        IPv6 lookup, e.g. ipv6.l.google.com, the connection will work
1815        because stunnel and ssh handle these properly.
1816
1817        Note that you often need to supply a display number or port after
1818        the address so put it, e.g. ':0' at the end: 2001:4860:b009::68:0
1819        You can also use the standard notation [2001:4860:b009::68]:0
1820        that is more clear.  You MUST specify the display if you use
1821        the IPv6 address notation (but :0 is still the default for a
1822        non-numeric hostname string.)
1823
1824        IPv4 addresses encoded in IPv6 notation also work, e.g.
1825        ::ffff:192.168.1.100 should work for the most part.
1826
1827        SSVNC on Unix and MacOSX also has its own Proxy helper tool
1828        (pproxy)  This script has been modified to handle IPv6 hostnames
1829        and addresses as long as the IO::Socket::INET6 Perl module
1830        is available.  On Windows the relay6.exe tool is used.
1831
1832        So for the most part IPv6 should work without you having to do
1833        anything special.  However, for rare usage, the proxy helper tool
1834        can also treat and IPv6 address as a special sort of 'proxy'.
1835        So in the entry Proxy/Gateway you can include ipv6://host:port
1836        and the IPv6 host will simply be connected to and the data
1837        transferred.  In this usage mode, set the VNC Host:Display
1838        to anything, e.g. 'localhost:0'; it is ignored if the ipv6://
1839        endpoint is specified as a proxy.  Need for ipv6:// usage proxy
1840        should be rare.
1841
1842        Note that for link local (not global) IPv6 addresses you may
1843        need to include the network interface at the end of the address,
1844        e.g. fe80::a00:20ff:fefd:53d4%eth0
1845
1846        Note that one can use a 3rd party VNC Viewer with SSVNC (see
1847        Options -> Advanced -> Change VNC Viewer.)  IPv6 will work for
1848        them as well even if they do not support IPv6.
1849
1850        IPv6 support on Unix, MacOSX, and Windows is essentially complete
1851        for all types of connections (including proxied, unencrypted and
1852        reverse connections.)  Let us know if you find a scenario that
1853        does not work (see the known exception for putty/plink below.)
1854
1855        You can set ipv6=0 in your ssvncrc, then no special relaying for
1856        IPv6 will be done (do this if there are problems or slowness in
1857        trying to relay ipv6 and you know you will not connect to any
1858        such hosts.)  Set ipv6=1 to force the special processing even if
1859        IPv6 was not autodetected.  To change this dynamically, you also
1860        enter IPV6=... in the VNC Host:Display entry box and press Enter.
1861        Also on Unix or MacOSX you can set the env. var. SSVNC_IPV6=0
1862        to disable the wrapper script from checking if hosts have ipv6
1863        addresses (this is the same as setting ipv6=0 in ssvncrc or by
1864        the setting ipv6 in the Entry box.)
1865
1866        On Windows plink.exe (SSH client) currently doesn't work for
1867        IPv6 address strings (e.g. 2001:4860:b009::68) but it does work
1868        for hostname strings that resolve to IPv6 addresses.
1869
1870        Note that one can make a home-brew SOCKS5 ipv4-to-ipv6 gateway
1871        proxy using ssh like this:
1872
1873          ssh -D '*:1080' localhost "printf 'Press Enter to Exit: '; read x"
1874
1875        then specify a proxy like socks5://hostname:1080 where hostname
1876        is the machine running the above ssh command.  Add '-v' to the
1877        ssh cmdline for verbose output.  See also the x11vnc inet6to4 tool
1878        (a direct ipv4/6 relay, not socks.)
1879}
1880
1881	global version
1882	set help_main "                             SSVNC version: $version\n$help_main"
1883	set help_misc "                             SSVNC version: $version\n$help_misc"
1884	set help_prox "                             SSVNC version: $version\n$help_prox"
1885	set help_tips "                             SSVNC version: $version\n$help_tips"
1886
1887	frame .h.w
1888	button .h.w.b1 -text "Main"    -command {help_text main}
1889	button .h.w.b2 -text "Proxies" -command {help_text prox}
1890	button .h.w.b3 -text "Misc"    -command {help_text misc}
1891	button .h.w.b4 -text "Tips"    -command {help_text tips}
1892
1893	pack .h.w.b1 .h.w.b2 .h.w.b3 .h.w.b4 -side left -fill x -expand 1
1894
1895	pack .h.w -side bottom -after .h.d -fill x
1896
1897	.h.f.t insert end $help_main
1898	jiggle_text .h.f.t
1899}
1900
1901proc help_text {which} {
1902	global help_main help_misc help_prox help_tips
1903	set txt ""
1904	if {$which == "main"} {
1905		set txt $help_main
1906	}
1907	if {$which == "misc"} {
1908		set txt $help_misc
1909	}
1910	if {$which == "prox"} {
1911		set txt $help_prox
1912	}
1913	if {$which == "tips"} {
1914		set txt $help_tips
1915	}
1916	catch {.h.f.t delete 0.0 end; .h.f.t insert end $txt; jiggle_text .h.f.t}
1917}
1918
1919proc ssvnc_escape_help {} {
1920	toplev .ekh
1921
1922	scroll_text_dismiss .ekh.f
1923
1924	center_win .ekh
1925	wm title .ekh "SSVNC Escape Keys Help"
1926
1927	set msg {
1928 SSVNC Escape Keys:
1929
1930   The Unix SSVNC VNC Viewer, ssvncviewer(1), has an 'Escape Keys'
1931   mechanism that enables using keystrokes that are bound as 'Hot Keys'
1932   to specific actions.
1933
1934   So, when you have all of the modifier keys ('escape keys') pressed down,
1935   then subsequent keystrokes are interpreted as local special actions
1936   instead of being sent to the remote VNC server.
1937
1938   This enables quick parameter changing and also panning of the viewport.
1939   E.g. the keystroke 'r' is mapped to refresh the screen.
1940
1941   Enter 'default' in the entry box to enable this feature and to use the
1942   default modifier list (Alt_L,Super_L on unix and Control_L,Meta_L on
1943   macosx) or set it to a list of modifier keys, e.g. Alt_L,Control_L.
1944   Note that _L means left side of keyboard and _R means right side.
1945
1946   Alt_L is the 'Alt' key on the left side of the keyboard, and Super_L
1947   is usually the 'WindowsFlaggie(TM)' on the left side of the keyboard,
1948   so when both of those are pressed, the escape keys mapping take effect.
1949
1950
1951   Here is info from the ssvncviewer(1) manual page:
1952
1953     -escape str    This sets the 'Escape Keys' modifier sequence and enables
1954                    escape keys mode.  When the modifier keys escape sequence
1955                    is held down, the next keystroke is interpreted locally
1956                    to perform a special action instead of being sent to the
1957                    remote VNC server.
1958
1959                    Use '-escape default' for the default modifier sequence.
1960                    (Unix: Alt_L,Super_L and MacOSX: Control_L,Meta_L)
1961
1962    Here are the 'Escape Keys: Help+Set' instructions from the Popup Menu:
1963
1964    Escape Keys:  Enter a comma separated list of modifier keys to be the
1965    'escape sequence'.  When these keys are held down, the next keystroke is
1966    interpreted locally to invoke a special action instead of being sent to
1967    the remote VNC server.  In other words, a set of 'Hot Keys'.
1968
1969    To enable or disable this, click on 'Escape Keys: Toggle' in the Popup.
1970
1971    Here is the list of hot-key mappings to special actions:
1972
1973       r: refresh desktop  b: toggle bell   c: toggle full-color
1974       f: file transfer    x: x11cursor     z: toggle Tight/ZRLE
1975       l: full screen      g: graball       e: escape keys dialog
1976       s: scale dialog     +: scale up (=)  -: scale down (_)
1977       t: text chat                         a: alphablend cursor
1978       V: toggle viewonly  Q: quit viewer   1 2 3 4 5 6: UltraVNC scale 1/n
1979
1980       Arrow keys:         pan the viewport about 10% for each keypress.
1981       PageUp / PageDown:  pan the viewport by a screenful vertically.
1982       Home   / End:       pan the viewport by a screenful horizontally.
1983       KeyPad Arrow keys:  pan the viewport by 1 pixel for each keypress.
1984       Dragging the Mouse with Button1 pressed also pans the viewport.
1985       Clicking Mouse Button3 brings up the Popup Menu.
1986
1987    The above mappings are *always* active in ViewOnly mode, unless you set the
1988    Escape Keys value to 'never'.
1989
1990    If the Escape Keys value below is set to 'default' then a default list of
1991    of modifier keys is used.  For Unix it is: Alt_L,Super_L and for MacOSX it
1992    is Control_L,Meta_L.  Note: the Super_L key usually has a Windows(TM) Flag
1993    on it.  Also note the _L and _R mean the key is on the LEFT or RIGHT side
1994    of the keyboard.
1995
1996    On Unix   the default is Alt and Windows keys on Left side of keyboard.
1997    On MacOSX the default is Control and Command keys on Left side of keyboard.
1998
1999    Example: Press and hold the Alt and Windows keys on the LEFT side of the
2000    keyboard and then press 'c' to toggle the full-color state.  Or press 't'
2001    to toggle the ultravnc Text Chat window, etc.
2002
2003    To use something besides the default, supply a comma separated list (or a
2004    single one) from: Shift_L Shift_R Control_L Control_R Alt_L Alt_R Meta_L
2005    Meta_R Super_L Super_R Hyper_L Hyper_R or Mode_switch.
2006}
2007
2008	.ekh.f.t insert end $msg
2009	jiggle_text .ekh.f.t
2010}
2011
2012#    Or Alternatively one can supply both hosts separated by
2013#    spaces (with the proxy second) in the VNC Host:Display box:
2014#
2015#           VNC Host-Display:   far-away.east:0    theproxy.net:8080
2016#
2017#    This looks a little strange, but it actually how SSVNC stores the
2018#    host info internally.
2019
2020#    You can also specify the remote SSH command by putting a string like
2021#
2022#         cmd=x11vnc -nopw -display :0 -rfbport 5900 -localhost
2023#
2024#    (use any command you wish to run) at the END of the VNC Host:Display
2025#    entry.  In general, you can cram it all in the VNC Host:Display if
2026#    you like:   host:disp  proxy:port  cmd=...  (this is the way it is
2027#    stored internally).
2028
2029proc help_certs {} {
2030	toplev .ch
2031
2032	set h 33
2033	if [small_height] {
2034		set h 28
2035	}
2036	scroll_text_dismiss .ch.f 87 $h
2037
2038	center_win .ch
2039	wm resizable .ch 1 0
2040
2041	wm title .ch "SSL Certificates Help"
2042
2043	set msg {
2044 Description:
2045
2046    *** IMPORTANT ***: Only with SSL Certificate verification (either manually
2047    or via a Certificate Authority certificate) can Man-In-The-Middle attacks be
2048    prevented.  Otherwise, only passive network sniffing attacks are prevented.
2049    There are hacker tools like dsniff/webmitm and cain that implement SSL
2050    Man-In-The-Middle attacks.  They rely on the client user not bothering to
2051    check the cert.
2052
2053    Some people may be confused by the above because they are familiar with
2054    their Web Browser using SSL (i.e. https://... websites) and those sites
2055    are authenticated securely without the user's need to verify anything
2056    manually.  The reason why this happens automatically is because 1) their
2057    web browser comes with a bundle of Certificate Authority certificates
2058    and 2) the https sites have paid money to the Certificate Authorities to
2059    have their website certificate signed by them.  When using SSL in VNC we
2060    normally do not do something this sophisticated, and so we have to verify
2061    the certificates manually.  However, it is possible to use Certificate
2062    Authorities with SSVNC; that method is described below.
2063
2064    The SSL Certificate files described below may have been created externally
2065    (e.g. by x11vnc or openssl): you can import them via "Import Certificate".
2066    OR you can click on "Create Certificate ..." to use THIS program to generate
2067    a Certificate + Private Key pair for you (in this case you will need to
2068    distribute one of the generated files to the VNC Server).
2069
2070    Then you associate the Saved cert with the VNC server, see the panel entry
2071    box description below.  Then click Connect.  You will usually want to Save
2072    this association in a VNC Server profile for the next time you connect.
2073
2074 Expiration:
2075
2076    SSL Certificates will Expire after a certain period (usually 1-2 years;
2077    if you create a cert with this tool you can set it to any length you want).
2078    So if for a particular Cert you find you can no longer connect, check the
2079    STUNNEL log output to see if the cert has expired.  Then create and distribute
2080    a new one.
2081
2082 Fetch Cert:
2083
2084    You can also retrieve and view the VNC Server's Cert via the "Fetch Cert"
2085    button on the main panel.  After you check that it is the correct Cert (e.g. by
2086    comparing MD5 hash or other info), you can save it.  The file it was saved
2087    as will be set as the "ServerCert" to verify against for the next connection.
2088    To make this verification check permanent, you will need to save the profile
2089    via 'Save'.
2090
2091    NOTE: See the CA section below for how "Fetch Cert/Verify All Certs" WILL NOT
2092    WORK when a Certificate Authority (CA) is used (i.e. you need to save the CA's
2093    cert instead.)  It will work if the certificate is Self-Signed.
2094
2095 Verify All Certs:
2096
2097    If "Verify All Certs" is checked on the main panel, you are always forced
2098    to check unrecognized server certs, and so the first time you connect to
2099    a new server you may need to follow a few dialogs to inspect and save the
2100    server certificate.
2101
2102    Under "Verify All Certs", new certificates are saved in the 'Accepted Certs'
2103    directory.  When the checkbox is set all host profiles with "CertsDir" set to
2104    "ACCEPTED_CERTS" (and an empty "ServerCert" setting) will be checked against
2105    the pool of accepted certificates in the 'Accepted Certs' directory.
2106
2107    Note that we have "Verify All Certs" on by default so that users who do not
2108    understand the SSL Man-In-The-Middle problem will not be left completely
2109    vulnerable to it.  Everyone still must make the effort to verify new
2110    certificates by an external method to be completely safe.
2111
2112    To have "Verify All Certs" toggled off at startup, use "ssvnc -nv" or set
2113    SSVNC_NO_VERIFY_ALL=1 before starting.  If you do not even want to see the
2114    button, use "ssvnc -nvb" or SSVNC_NO_VERIFY_ALL_BUTTON=1.
2115
2116    Note: "Fetch Cert" and "Verify All Certs" are currently not implemented in
2117    "SSH + SSL" mode.  In this case to have server authentication "ServerCert"
2118    must be set explicitly to a file (or "CertsDir" to a directory).
2119
2120    Also note that "Fetch Cert" only works in a limited fashion in "Listen"
2121    mode (it is the VNC Server that initiates the connection), and so you
2122    may need to be set via "ServerCert" as well.
2123
2124    NOTE: See the CA section below for how "Fetch Cert/Verify All Certs"
2125    WILL NOT WORK when a Certificate Authority (CA) is used (i.e. you need
2126    to save the CA's cert instead.)  The "Fetch Cert" saving method will
2127    work if the certificate is Self-Signed.
2128
2129 CA:
2130
2131    One can make SSL VNC server authentication more "automatic" as it is in
2132    Web Browsers going to HTTPS sites, by using a Certificate Authority (CA)
2133    cert (e.g. a professional one like Verisign or Thawte, or one your company
2134    or organization creates) for the "ServerCert".  This is described in detail
2135    here: http://www.karlrunge.com/x11vnc/ssl.html
2136
2137    CA's are not often used, but if the number of VNC Servers scales up it can
2138    be very convenient because the viewers (i.e. SSVNC) only need the CA cert,
2139    not all of the Server certs.
2140
2141    IMPORTANT NOTE: if a VNC Server is using a CA signed certificate instead
2142    of its own Self-Signed one, then "Fetch Cert", etc. saving mechanism
2143    WILL NOT WORK.  You must obtain the CA certificate and explicitly set
2144    it as the ServerCert or import it to 'Accepted Certs'.
2145
2146
2147 Now what goes into the panel's entry boxes is described.
2148
2149
2150 Your Certificate + Key (MyCert):
2151
2152    You can specify YOUR own SSL certificate (PEM) file in "MyCert" in which
2153    case it is used to authenticate YOU (the viewer) to the remote VNC Server.
2154    If this fails the remote VNC Server will drop the connection.
2155
2156    So the Server could use this method to authenticate Viewers instead of the
2157    more common practice of using a VNC password or x11vnc's -unixpw mode.
2158
2159
2160 Server Certificates (ServerCert/CertsDir):
2161
2162    Server certs can be specified in one of two ways:
2163
2164        - A single certificate (PEM) file for a single server
2165          or a single Certificate Authority (CA)
2166
2167        - A directory of certificate (PEM) files stored in
2168          the special OpenSSL hash fashion.
2169
2170    The former is set via "ServerCert" in this gui.
2171    The latter is set via "CertsDir" in this gui.
2172
2173    The former corresponds to the "CAfile" STUNNEL parameter.
2174    The latter corresponds to the "CApath" STUNNEL parameter.
2175
2176    See stunnel(8) or stunnel.mirt.net for more information.
2177
2178    If the remote VNC Server fails to authenticate itself with respect to the
2179    specified certificate(s), then the VNC Viewer (your side) will drop the
2180    connection.
2181
2182    Select which file or directory by clicking on the appropriate "Browse..."
2183    button.  Once selected, if you click Info or the Right Mouse button on
2184    "Browse..."  then information about the certificate will be displayed.
2185
2186    If, as is the default, "CertsDir" is set to the token "ACCEPTED_CERTS"
2187    (and "ServerCert" is unset) then the certificates accumulated in the special
2188    'Accepted Certs' directory will be used.  "ACCEPTED_CERTS" is the default for
2189    every server ("Verify All Certs").  Note that if you ever need to clean this
2190    directory, each cert is saved in two files, for example:
2191
2192          hostname-0=bf-d0-d6-9c-68-5a-fe-24-c6-60-ba-b4-14-e6-66-14.crt
2193    and
2194          9eb7c8be.0
2195
2196    This is because of the way OpenSSL must use hash-based filenames in Cert dirs.
2197    The file will have a "full filename:" line indicating the fingerprint and
2198    hostname associated with it.  Be sure to remove both files.  The Delete Certs
2199    dialog should automatically find the matching one for you and prompt you to
2200    remove it as well.
2201
2202 Certificate Revocation List (CRL File):
2203
2204    For large scale deployments, usually involving a CA Cert, it is worthwhile
2205    to be able to revoke individual certs (so that a new CA cert does not need to
2206    be created and new keys distributed).  Set CRL File to the path to the
2207    file containing the revoked certificates (or a directory containing
2208    OpenSSL style hash-based filenames.)  See the x11vnc -sslCRL documentation
2209    for how to create CRL's.  In short, the commands 'openssl ca -revoke ...'
2210    and 'openssl ca -gencrl ...' are the ones to look for; See the ca(1) manpage.
2211
2212 Create Certificate:
2213
2214    A simple dialog to create a Self-Signed Certificate.  See the x11vnc
2215    -sslGenCA, -sslGenCert options for creating a CA Cert and signing with it.
2216
2217 Import Certificate:
2218
2219    You can paste in a Certificate or read one in from a file to add to your
2220    list of Server Certificates.  If (also) saved in the 'Accepted Certs'
2221    directory, it will be automatically used to verify any Server when in
2222    'Verify All Certs' Mode.
2223
2224 Deleting Certificates:
2225
2226    To delete a Certificate+private_key pair click on "Delete Certificate"
2227    and select one in the menu.  You will be prompted to remove it,
2228    and also any corresponding .pem or .crt file.  For "ACCEPTED_CERTS"
2229    it will find the matching "HASH" file and prompt you to remove that too.
2230
2231
2232 Default Certs and Keys:
2233
2234    Use the "-mycert file" option (same as "-cert file") to set a default
2235    MyCert.  The user will then have to manually clear the field to not
2236    use a certificate.  This is the same as "mycert=file" (also "cert=file")
2237    in the ~/.ssvncrc file.  If "file" does not exist, then ~/.vnc/certs is
2238    prepended to it.
2239
2240    Use the "-cacert file" option (same as "-ca file") to set a default
2241    ServerCert.  The user will then have to manually clear the field to not
2242    set a server cert.  This is the same as "cacert=file" (also "ca=file")
2243    in the ~/.ssvncrc file.  If "file" does not exist, then ~/.vnc/certs is
2244    prepended to it.  Use "-cacert CA" to set it to ~/.vnc/certs/CA/cacert.pem
2245
2246    Use the "-crl file" option to set a default CRL File.  The user will
2247    then have to manually clear the field to not use a CRL.  This is the
2248    same as "crl=file" in the ~/.ssvncrc file.  If "file" does not exist,
2249    then ~/.vnc/certs is prepended to it.
2250
2251    A sys-admin might set up an SSVNC deployment for user's workstations or
2252    laptops using one or more of -cacert (authenticate VNC server to the
2253    user) or -mycert (authenticate user to VNC server) or -crl (supply a
2254    list of revoked certificates).  Prefix either one with "FORCE:" to make
2255    the setting unchangable.
2256
2257
2258 Notes:
2259
2260    If "Use SSH" has been selected then SSL certs are disabled.
2261
2262    See the x11vnc and STUNNEL documentation for how to create and use PEM
2263    certificate files:
2264
2265        http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-ext
2266        http://www.karlrunge.com/x11vnc/ssl.html
2267        http://stunnel.mirt.net
2268
2269    A common way to create and use a VNC Server certificate is:
2270
2271        x11vnc -ssl SAVE ...
2272
2273    and then copy the Server certificate to the local (viewer-side) machine.
2274    x11vnc prints out to the screen the Server certificate it generates
2275    (stored in ~/.vnc/certs/server.crt).  You can set "ServerCert" to it
2276    directly or use the "Import Certificate" action to save it to a file.
2277    Or use the "Fetch Cert" method to retrieve it (be sure to verify the
2278    MD5 fingerprint, etc).
2279
2280    x11vnc also has command line utilities to create server, client, and CA
2281    (Certificate Authority) certificates and sign with it. See the above URLs.
2282}
2283
2284	.ch.f.t insert end $msg
2285	jiggle_text .ch.f.t
2286}
2287
2288proc help_ts_opts {} {
2289	toplev .oh
2290
2291	scroll_text_dismiss .oh.f
2292
2293	center_win .oh
2294
2295	wm title .oh "Terminal Services VNC Options Help"
2296
2297set msg {
2298 Options:  Click on a checkbox to enable a feature and bring up its Dialog.
2299 Deselecting a checkbox will disable the feature (but settings from the
2300 Dialog are remembered).  Click on it again to re-enable.
2301
2302
2303 Desktop Type:
2304
2305    The default type of remote Desktop type is the "kde" (The K Desktop
2306    Environment) You can choose a different type: gnome, failsafe,
2307    twm, etc.
2308
2309    This setting will ONLY be used if the desktop needs to be created.
2310    If an existing session of yours is found it will be used instead
2311    (log out of that session if you want to create a new Desktop type
2312    or see the Multiple Sessions option under Advanced).
2313
2314 Desktop Size:
2315
2316    The default size of remote Desktop type is the "1280x1024" with a
2317    Color depth of 16 bits per pixel (BPP).  Choose one of the standard
2318    WxH values or enter a custom one (TBD).
2319
2320    This setting will ONLY be used if the desktop needs to be created.
2321    If an existing session of yours is found it will be used instead
2322    (log out of that session if you want to create a new Desktop size
2323    or see the Multiple Sessions option under Advanced).
2324
2325    Some X servers, Xdummy or a real X server, will allow dynamic screen
2326    size changing after the session has started via a GUI configuration
2327    tool (or xrandr(1) from the command line).
2328
2329 X Server Type:
2330
2331    The default type of remote X session is the "Xvfb" (X virtual frame
2332    buffer) X server.  It is available on most systems.  To choose a
2333    different type, select "Xdummy", "Xvnc", "Xvnc.redirect".
2334
2335    Xdummy is part of the x11vnc project and is a virtual X server with
2336    some nice features, but it Linux only and requires root permission
2337    to run.  One user put 'ALL ALL = NOPASSWD: /usr/local/bin/Xdummy*'
2338    in his sudo(1) configuration (via visudo).
2339
2340    For Xvnc that server is started up, and x11vnc polls it in its
2341    normal way.  Use Xvnc.redirect if you want x11vnc to find and/or
2342    create the Xvnc session, but after that merely transfer packets back
2343    and forth between VNC viewer and Xvnc (I.e. x11vnc does no polling
2344    or VNC protocol).
2345
2346
2347 Enable Printing:
2348
2349    This sets up a SSH port redirection for you from your remote session
2350    to your local print server.  The CUPS mechanism is used.  The local
2351    print server can also be SMB/Windows.
2352
2353 Enable Sound:
2354
2355    Not completely implemented yet.  A partially working ESD method
2356    is provided.  It may change over to http://nas.sourceforge.net in
2357    the future.  As with printing, it uses a SSH port redirection to a
2358    server running locally.
2359
2360 File Transfer:
2361
2362    x11vnc supports both the UltraVNC and TightVNC file transfer
2363    extensions.  On Windows both viewers support their file transfer
2364    protocol.  On Unix only the SSVNC VNC Viewer has filexfer support;
2365    it supports the UltraVNC flavor via a Java helper program.
2366
2367    Choose the one you want based on VNC viewer you will use.
2368    The defaults for the SSVNC viewer package are TightVNC on Windows
2369    and UltraVNC on Unix.
2370
2371 View Only:
2372
2373    Start the VNC Viewer in View-Only mode (it may be switched to full
2374    access later in the session).
2375
2376 Change VNC Viewer:
2377
2378    If you do not like the VNC Viewer bundled in the package, you can
2379    indicate another one here.
2380
2381 X11 viewer MacOSX:
2382
2383    On MacOSX try to use the bundled X11 vncviewer instead of the
2384    Chicken of the VNC viewer; the Xquartz X server must be installed
2385    (it is by default on 10.5.x) and the DISPLAY variable must be set
2386    (see Tip 15 of SSVNC Help to do this manually.)
2387
2388
2389 Advanced Options:
2390
2391 VNC Shared:
2392
2393    Normal use of this program, 'tsvnc', *ALREADY* allows simultaneous
2394    shared access of the remote desktop:   You simply log in as many
2395    times from as many different locations with 'tsvnc' as you like.
2396
2397    Select this option for the traditional VNC server shared mode of
2398    operation using a single x11vnc server.  SSH access is still required.
2399
2400 Multiple Sessions:
2401
2402    To enable one user to have more than one Terminal Services Desktop
2403    X session on a single machine, this option lets you create Tags for
2404    multiple ones (e.g. KDE_BIG, TWM_800x600)
2405
2406 X Login Greeter:
2407
2408    If you have root (sudo(1)) permission on the remote machine,
2409    you can have x11vnc try to connect to X displays that have nobody
2410    logged in yet.  This is most likely the login greeter running on
2411    the Physical console.  sudo(1) is used to run x11vnc with FD_XDM=1.
2412
2413    An initial ssh running 'sudo id' is performed to try to 'prime'
2414    sudo so the 2nd one that starts x11vnc does not need a password.
2415
2416    Note that if someone is already logged into the console of the XDM
2417    display you will see their X session.
2418
2419 Other VNC Server:
2420
2421    The x11vnc program running on the remote machine can be instructed to
2422    immediately redirect to some other (3rd party, e.g. Xvnc or vnc.so)
2423    VNC server.
2424
2425 Use unixpw:
2426
2427    This enables the x11vnc unixpw mode.  A Login: and Password: dialog
2428    will be presented in the VNC Viewer for the user to provide any Unix
2429    username and password whose session he wants to connect to.
2430
2431    This mode is useful if a shared terminal services user (e.g. 'tsuser')
2432    is used for the SSH login part (say via the SSH authorized_keys
2433    mechanism and all users share the same private SSH key for 'tsuser').
2434
2435    In normal usage the per-user SSH login should be the simplest and
2436    sufficient, in which case the unixpw option should NOT be selected.
2437
2438 Client 8bit Color:
2439
2440    Have the VNC Viewer request low color mode (8 bits per pixel) for
2441    slow links.  This may be disabled or further tuned (e.g. 64 color
2442    mode) in the viewer during the session.
2443
2444 Client-Side Caching:
2445
2446    x11vnc has an experiment Client-Side caching scheme "-ncache n"
2447    that can give nice speedups.  But there are some drawbacks
2448    because the cache-region is visible and uses much RAM.
2449    http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching
2450
2451 X11VNC Options:
2452
2453    If you are familiar with x11vnc, you can specify any of its features
2454    that you would like enabled.
2455
2456 SSVNC Mode:
2457
2458    Clicking on this button will return you to the full SSVNC Mode.
2459
2460 Unix ssvncviewer:
2461
2462    Clicking on this button will popup a menu for setting options
2463    of the Unix (and Mac OS X) provided SSVNC vncviewer.
2464
2465
2466 ~/.ssvncrc file:
2467
2468    You can put global options in your ~/.ssvncrc file (ssvnc_rc on
2469    Windows). Currently they are:
2470
2471    Put "mode=tsvnc" or "mode=sshvnc" in the ~/.ssvncrc file to have
2472    the application start up in the given mode.
2473
2474    desktop_type=wmaker  (e.g.) to switch the default Desktop Type.
2475
2476    desktop_size=1280x1024  (e.g.) to switch the default Desktop Size.
2477
2478    desktop_depth=24  (e.g.) to switch the default Desktop Color Depth.
2479
2480    xserver_type=Xdummy  (e.g.) to switch the default X Server Type.
2481
2482    (The above 4 settings apply only to the Terminal Services Mode.)
2483
2484    noenc=1  (same as the -noenc option for a 'No Encryption' option)
2485    noenc=0  (do not show the 'No Encryption' option)
2486
2487    font_default=tk-font-name     (sets the font for menus and buttons)
2488    font_fixed=tk-font-name       (sets the font for help text)
2489}
2490	.oh.f.t insert end $msg
2491	jiggle_text .oh.f.t
2492}
2493
2494proc help_opts {} {
2495	toplev .oh
2496
2497	scroll_text_dismiss .oh.f
2498
2499	center_win .oh
2500
2501	wm title .oh "SSL/SSH Viewer Options Help"
2502
2503set msg {
2504  Use SSL:  The default, use SSL via STUNNEL (this requires SSL aware VNC
2505            server, e.g. x11vnc -ssl SAVE ...)  See the description in the
2506            main Help panel.
2507
2508  Use SSH:  Instead of using STUNNEL SSL, use ssh(1) for the encrypted
2509            tunnel.  You must be able to log in via ssh to the remote host.
2510
2511            On Unix the cmdline ssh(1) program (it must already be installed)
2512            will be run in an xterm for passphrase authentication, prompts
2513            about RSA keys, etc.  On Windows the cmdline plink.exe program
2514            will be launched in a Windows Console window. (Apologies for
2515            the klunkiness..)
2516
2517            You can set the "VNC Host:Display" to "user@host:disp" to
2518            indicate ssh should log in as "user" on "host".  NOTE: On
2519            Windows you *MUST* always supply the "user@" part (due to a
2520            plink deficiency). E.g.:
2521
2522                VNC Host:Display:    fred@far-away.east:0
2523
2524
2525            Gateway:  If an intermediate gateway machine must be used
2526            (e.g. to enter a firewall; the VNC Server is not running on it),
2527            put it in the Proxy/Gateway entry, e.g.:
2528
2529                VNC Host:Display:    workstation:0
2530                Proxy/Gateway:       user@gateway-host:port
2531
2532            ssh is used to login to user@gateway-host and then a -L port
2533            redirection is set up to go to workstation:0 from gateway-host.
2534            ":port" is optional, use it if the gateway-host SSH port is
2535            not the default value 22.
2536
2537            Chaining 2 ssh's:  One can also do a "double ssh", i.e. a
2538            first SSH to the gateway login machine then a 2nd ssh to the
2539            destination machine (presumably it is running the vnc server).
2540
2541            Unlike the above example, the "last leg" (gateway-host ->
2542            workstation) is also encrypted by SSH this way.  Do this by
2543            splitting the gateway in two with a comma, the part before it
2544            is the first SSH:
2545
2546                VNC Host:Display: localhost:0
2547                Proxy/Gateway:    user@gateway-host:port,user@workstation:port
2548
2549            Web and SOCKS proxies can also be used with SSH:
2550
2551                VNC Host:Display: user@workstation:0
2552                Proxy/Gateway:    socks://socks.server:1080
2553
2554            See the "SSH Proxies/Gateways" in the Main Help document for full
2555            details.
2556
2557
2558            Remote Command:  In the "Remote SSH Command" entry you can to
2559            indicate that a remote command to be run.  The default is
2560            "sleep 15" to make sure port redirections get established. But you
2561            can run anything else, for example, to run x11vnc on your X :0
2562            workstation display:
2563
2564                x11vnc -display :0 -nopw
2565
2566
2567            Windows SSH SERVER: if you are ssh'ing INTO Windows (e.g. CYGWIN
2568            SSHD server) there may be no "sleep" command so put in something
2569            like "ping localhost" or "ping -n 10 -w 1000 localhost" to
2570            set a short delay to let the port redir get established.
2571
2572
2573            Trick:  If you use "SHELL" asl the "Remote SSH Command" then
2574            you get an SSH shell only: no VNC viewer will be launched.
2575            On Windows "PUTTY" will try to use putty.exe (better terminal
2576            emulation than plink.exe)  A shortcut for this is Ctrl-S as
2577            long as user@hostname is present in the "VNC Host:Display" box.
2578
2579
2580  Use SSH + SSL:
2581
2582            Tunnel the SSL connection through a SSH tunnel.  Use this
2583            if you want end-to-end SSL and must use a SSH gateway (e.g. to
2584            enter a firewall) or if additional SSH port redirs are required
2585            (CUPS, Sound, SMB tunnelling: See Advanced Options).
2586
2587            This is a RARELY used mode, but included in case the need arises.
2588
2589
2590  No Encryption:
2591
2592            In '-noenc' mode, which is now the default, (Ctrl-E also toggles
2593            this mode), use this to make a Direct connection to the VNC Server
2594            with no encryption whatsoever.  (Be careful about passwords, etc.)
2595
2596            The -noenc mode is now the default since SSVNC 1.0.25, use
2597            the '-enc' cmdline option to disable the button.
2598
2599
2600  Automatically Find X Session:
2601
2602            When using SSH mode to connect, you can select this option.  It
2603            simply sets the Remote SSH Command to:
2604
2605                 PORT= x11vnc -find -localhost
2606
2607            This requires that x11vnc is installed on the remote computer
2608            and is available in $PATH for the ssh login.  The command
2609            "x11vnc -find -localhost" command is run on the remote
2610            machine.
2611
2612            The -find option causes x11vnc to try to find an existing X
2613            session owned by the user (i.e. who you ssh in as).  If it
2614            does it attaches to it; otherwise the x11vnc VNC server exits
2615            immediately followed by your VNC Viewer.
2616
2617            The PORT= option just means to let x11vnc pick its own
2618            VNC port and then connect to whatever it picked.  Use P=
2619            for more debugging output.
2620
2621            The idea for this mode is you simply type 'username@workstation'
2622            in the VNC Host:Display box, Select 'Options -> Automatically
2623            Find X Session', and then click Connect.  The tsvnc mode is
2624            similar (it runs x11vnc on the remote side with the intent
2625            of automatically finding, or creating, your desktop).
2626
2627
2628  Unix Username & Password:
2629
2630            This is only available on Unix and MacOSX and when using
2631            the SSVNC enhanced TightVNC viewer (it has been modified to
2632            do Unix logins).  It supports a login dialog with servers
2633            doing something like x11vnc's "-unixpw" mode.  After any
2634            regular VNC authentication takes place (VNC Password), then
2635            it sends the Unix Username, a Return, the Unix Password and
2636            a final Return.  This saves you from typing them into the
2637            "login:" and "Password:" prompts in the viewer window.
2638
2639            Note that the x11vnc -unixpw login mode is external to the
2640            VNC protocol, so you need to be sure the VNC server is in
2641            this mode and will be waiting for the dialog.  Otherwise the
2642            username and password will be typed directly into the desktop
2643            application that happens to have the focus!
2644
2645            When you select this option "Unix Username:" and "Unix
2646            Password:" entry boxes appear on the main panel where you can
2647            type them in.  x11vnc has settings that can be specified after
2648            a ":" in the Unix username; they may be used here as well.
2649            (For example: username:3/4,nc for a smaller screen and -nocache)
2650
2651            If the Unix Username is not set when you click Connect, then
2652            any SSH username@host is used.  Otherwise the environment
2653            variable $USER or $LOGNAME and finally whoami(1) is used.
2654
2655            Also Note that the Unix Password is never saved in a VNC
2656            profile (so you have to type it each time).  Also, the remote
2657            x11vnc server is instructed to not echo the Username string
2658            by sending an initial Escape.  Set the SSVNC_UNIXPW_NOESC=1
2659            environment variable to override this.
2660
2661  Reverse VNC Connection:
2662
2663            Reverse (listening) VNC connections are possible as well.
2664            Enable with this button "Reverse VNC Connection (-LISTEN)"
2665
2666            In this case the VNC Server initiates the connection to your
2667            waiting (i.e. listening) SSVNC viewer.
2668
2669            For SSL connections in the 'VNC Host:Display' entry box put in
2670            the number (e.g. "0" or ":0" or ":1", etc.) that corresponds to
2671            the Listening display (0 -> port 5500, 1 -> port 5501, etc.) you
2672            want to use.  For example x11vnc can then be used via:
2673            "x11vnc ... -ssl SAVE -connect hostname:port" using the "port"
2674            with the one you chose.
2675
2676            Clicking on the 'Listen' button puts your SSVNC viewer
2677            in a "listening" state on that port number, waiting for a
2678            connection from the VNC Server.
2679
2680            Then a VNC server should establish a reverse connection to
2681            that port on this machine (e.g. -connect this-machine:5500
2682            or -connect this-machine:5503, etc.)
2683
2684            Server SSL certificates will be verified, however you WILL
2685            NOT be prompted about unrecognized ones; rather, you MUST
2686            set up the correct Server certificate (e.g. by importing).
2687            prior to any connections.
2688
2689            If the connection is failing in Reverse VNC (listening) mode,
2690            check the STUNNEL log output to see if STUNNEL is unable to
2691            authenticate the VNC Server.  If you want to allow in a
2692            reverse connection with NO Server authentication, unset the
2693            'Verify All Certs' option.
2694
2695            When listening in SSL, you will ALSO need to specify YOUR
2696            OWN SSL cert, "MyCert", or otherwise let the GUI prompt you
2697            to create a "listen.pem" and use that.
2698
2699            The "listen.pem" will be reused in later SSL Listening
2700            connections unless you specify a different one with MyCert.
2701
2702            On Windows or using a 3rd party VNC Viewer multiple,
2703            simultaneous reverse connections are always enabled.
2704            On Unix/MacOSX with the provided ssvncviewer they are disabled
2705            by default.  To enable them:
2706            Options -> Advanced -> Unix ssvncviewer -> Multiple LISTEN Conns.
2707
2708            For reverse connections in SSH or SSH + SSL modes it is a
2709            little trickier.  The SSH tunnel (with -R tunnel) must be
2710            established and remain up waiting for reverse connections.
2711            The default time is "sleep 1800", i.e. 30 mins.  You can put
2712            a longer or shorter sleep in "Remote SSH Command" (perhaps
2713            after your command runs:  cmd; sleep 3600).
2714
2715            For SSH reverse connections put "hostname:n" in
2716            'VNC Host:Display' or "user@hostname:n".  The "n" will be the
2717            listening display on the *REMOTE* side.  So to have the remote
2718            x11vnc connect use: "x11vnc ... -connect localhost:n" or
2719            "x11vnc -R connect:localhost:n" (-ssl will be needed for SSH+SSL
2720            mode).  If the -R port cannot be opened because it is in use
2721            by another program you will have to kill everything and start
2722            over using a different port.
2723
2724            In reverse connections mode be careful to protect the listening
2725            VNC Viewer from direct connections (neither SSL nor SSH)
2726            connecting directly to its listening port thereby bypassing
2727            the tunnel.  This can be done by a host-level firewall that
2728            only lets in, say, port 5500 (the default one ":0" for stunnel
2729            to listen on).  Or for SSH reverse connections allow NO 5500+n
2730            ports in.  For reverse connections, the Unix enhanced tightvnc
2731            viewers supplied in the SSVNC package will only listen on
2732            localhost so these precautions are not needed.
2733
2734            Specify a specific interface, e.g. 192.168.1.1:0 to have stunnel
2735            only listen on that interface.  IPv6 works too, e.g. :::0 or ::1:0
2736            Also works for UN-encrypted reverse connections as well ('None').
2737
2738            Note that for SSL connections use of "Proxy/Gateway" does not
2739            make sense: the remote side cannot initiate its reverse connection
2740            via the Proxy.
2741
2742            Note that for SSH or SSH+SSL connections use of "Proxy/Gateway"
2743            does not make sense (the ssh cannot do a -R on a remote host:port),
2744            unless it is a double proxy where the 2nd host is the machine with
2745            the VNC server.
2746
2747
2748  View Only:               Have VNC Viewer ignore mouse and keyboard input.
2749
2750  Fullscreen:              Start the VNC Viewer in fullscreen mode.
2751
2752  Raise On Beep:           Deiconify viewer when bell rings.
2753
2754  Use 8bit color:          Request a very low-color pixel format.
2755
2756  Do not use JPEG:         Do not use the jpeg aspect of the tight encoding.
2757
2758  Use X11 vncviewer on MacOSX:
2759                           On MacOSX try to use the bundled X11 vncviewer
2760                           instead of the Chicken of the VNC viewer;
2761                           The Xquartz X server must be installed (it is by
2762                           default on 10.5.x) and the DISPLAY variable must
2763                           be set (see Tip 15 of Help to do this manually.)
2764                           Put cotvnc=1 in ~/.ssvncrc to switch the default.
2765
2766  Kill Stunnel Automatically:
2767                           On Windows, automatically try to kill the STUNNEL
2768                           process when the VNC Viewer exits.  This is a
2769                           global setting (not per-profile); it can be also
2770                           set via either the -killstunnel cmdline option,
2771                           or killstunnel=1 in ssvnc_rc.  To disable it supply
2772                           -nokillstunnel or put killstunnel=0 in ssvnc_rc.
2773                           As of 1/2009 this option is on by default.
2774
2775                           The main drawback to having STUNNEL automatically
2776                           killed is that you will not be able to view its
2777                           logfile.  If you are having trouble connecting via
2778                           SSL, disable this option and double click on the
2779                           dark green STUNNEL icon in the tray to view the log.
2780
2781
2782  Compress Level/Quality:  Set TightVNC encoding parameters.
2783
2784
2785  Putty PW:  On Windows only: use the supplied password for plink SSH
2786             logins.  Unlike the other options the value is not saved
2787             when 'Save' is performed.  This feature is useful when
2788             options under "Advanced" are set that require TWO SSH's:
2789             you just have to type the password once in this entry box.
2790             The bundled pageant.exe and puttygen.exe programs can also
2791             be used to avoid repeatedly entering passwords (note this
2792             requires setting up and distributing SSH keys).  Start up
2793             pageant.exe or puttygen.exe and read the instructions there.
2794
2795             Note, that there is a small exposure to someone seeing the
2796             putty password on the plink command line.
2797
2798             Note that the Putty PW is not cleared if you load in a
2799             new VNC profile.
2800
2801
2802  Port Slot: On Windows ports cannot be selected or checked as easily as
2803             on Unix.  So listening ports for ssh redirs, proxy tunnelling,
2804             and etc. things are picked via finding a free "slot".
2805             The slots run from 30 to 99 and are locked based on the
2806             existence of a file with the slot number in it.  When the
2807             connection is about to be made, a free slot is found and used
2808             to work out some ports (e.g. 5930 for the local VNC port,
2809             etc.)  This way simultaneous SSVNC connections can take place.
2810
2811             One drawback of this is that Putty/Plink stores SSH keys based
2812             on hostname:port, and with a proxy tunnel the hostname is
2813             "localhost".  So the Putty key store may have key collisions
2814             for the localhost tunnels, and plink will prompt you to
2815             resolve the conflict WRT a different SSH key being discovered.
2816
2817             To work around this to some degree you can select a unique
2818             Port Slot (in the range 50-99) for a specific host.  Then the
2819             ssh redir port to this host will never change and so the
2820             Putty localhost:fixed-port key should remain valid.
2821
2822
2823  Mode:      To change the GUI Mode, select between the full SSVNC
2824             (i.e. SSL and SSH), SSHVNC (i.e. SSH-Only), and Terminal
2825             Services mode (TSVNC; uses x11vnc)
2826
2827             Note: You can put "mode=tsvnc" or "mode=sshvnc" in your
2828             ~/.ssvncrc file (ssvnc_rc on Windows) to have the application
2829             start up in the given mode.
2830
2831
2832  Show 'No Encryption' Option:
2833
2834             Note: since SSVNC 1.0.25 the 'No Encryption' Option is
2835             enabled by default.
2836
2837             Select this to display a button that disables both SSL and
2838             SSH encryption.  This is the same as Ctrl+E.  This puts
2839             a check item "None" on the main panel and also a "No
2840             Encryption" check item in the "Options" panel.  If you
2841             select this item, there will be NO encryption for the VNC
2842             connection (use cautiously) See Tip 5) under Help for more
2843             information about disabling encryption.
2844
2845
2846  Buttons:
2847
2848  Use Defaults:    Set all options to their defaults (i.e. unset).
2849
2850  Delete Profile:  Delete a saved profile.
2851
2852  Advanced:        Bring up the Advanced Options dialog.
2853
2854  Save and Load:
2855
2856             You can Save the current settings by clicking on Save
2857             (.vnc file) and you can also read in a saved one with Load
2858             Profile.  Use the Browse... button to select the filename
2859             via the GUI.
2860
2861             Pressing Ctrl-L or Clicking the Right mouse button on the
2862             main GUI will invoke the Load dialog.
2863
2864             Note: On Windows since the TightVNC Viewer will save its own
2865             settings in the Registry, some unexpected behavior is possible
2866             because the viewer is nearly always directed to the VNC host
2867             "localhost:30".  E.g. if you specify "View Only" in this gui
2868             once but not next time the Windows VNC Viewer may remember
2869             the setting.  Unfortunately there is not a /noreg option for
2870             the Viewer.
2871}
2872	.oh.f.t insert end $msg
2873	jiggle_text .oh.f.t
2874}
2875
2876proc help_fetch_cert {{selfsigned 1}} {
2877	toplev .fh
2878
2879	set h 35
2880	if [small_height] {
2881		set h 28
2882	}
2883	scroll_text_dismiss .fh.f 85 $h
2884
2885	center_win .fh
2886	wm resizable .fh 1 0
2887
2888	wm title .fh "Fetch Certificates Help"
2889
2890	set msg {
2891  The displayed SSL Certificate has been retrieved from the VNC Server via the
2892  "Fetch Cert" action.
2893
2894  It has merely been downloaded via the SSL Protocol:
2895
2896         *** IT HAS NOT BEEN VERIFIED OR AUTHENTICATED IN ANY WAY ***
2897
2898  So, in principle, it could be a fake certificate being inserted by a bad
2899  person attempting to perform a Man-In-The-Middle attack on your SSL connection.
2900
2901  If, however, by some external means you can verify the authenticity of this SSL
2902  Certificate you can use it for your VNC SSL connection to the VNC server you
2903  wish to connect to.  It will provide an authenticated and encrypted connection.
2904
2905  You can verify the SSL Certificate by comparing the MD5 or SHA1 hash value
2906  via a method/channel you know is safe (i.e. not also under control of a
2907  Man-In-The-Middle attacker).  You could also check the text between the
2908  -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- tags, etc.
2909
2910  Once you are sure it is correct, you can press the Save button to save the
2911  certificate to a file on the local machine for use when you connect via VNC
2912  tunneled through SSL.  If you save it, then that file will be set as the
2913  Certificate to verify the VNC server against.  You can see this in the dialog
2914  started via the "Certs..." button on the main panel.
2915
2916  NOTE: If you want to make Permanent the association of the saved SSL certificate
2917  file with the VNC server host, you MUST save the setting as a profile for
2918  loading later. To Save a Profile, click on Options -> Save Profile ...,
2919  and choose a name for the profile and then click on Save.
2920
2921  If "Verify All Certs" is checked, then you are forced to check all new certs.
2922  In this case the certs are saved in the 'Accepted Certs' directory against
2923  which all servers will be checked unless "ServerCert" or "CertsDir" has been
2924  set to something else.
2925
2926  To reload the profile at a later time, click on the "Load" button on the
2927  main panel and then select the name and click "Open".  If you want to be
2928  sure the certificate is still associated with the loaded in host, click on
2929  "Certs..." button and make sure the "ServerCert" points to the desired SSL
2930  filename.
2931
2932  See the Certs... Help for more information.  A sophisticated method can be set
2933  up using a Certificate Authority key to verify never before seen certificates
2934  (i.e. like your web browser does).
2935}
2936
2937	set msg2 {
2938  --------------------------------------------------------------------------
2939  NOTE: The certificate that was just downloaded IS NOT a Self-Signed
2940  certificate.  It was signed by a Certificate Authority (CA) instead.
2941  So saving it does not make sense because it cannot be used to authenticate
2942  anything.
2943
2944  You need to Obtain and Save the CA's certificate instead.
2945
2946  The remainder of this Help description applies ONLY to Self-Signed
2947  certificates (i.e. NOT the most recently downloaded one.)
2948  --------------------------------------------------------------------------
2949
2950
2951}
2952
2953	if {!$selfsigned} {
2954		regsub {  If, however,} $msg "$msg2  If, however," msg
2955	}
2956
2957	.fh.f.t insert end $msg
2958	jiggle_text .fh.f.t
2959}
2960
2961proc win_nokill_msg {} {
2962	global help_font is_windows system_button_face
2963	toplev .w
2964
2965	eval text .w.t -width 60 -height 11 $help_font
2966	button .w.d -text "Dismiss" -command {destroy .w}
2967	pack .w.t .w.d -side top -fill x
2968
2969	apply_bg .w.t
2970
2971	center_win .w
2972	wm resizable .w 1 0
2973
2974	wm title .w "SSL/SSH Viewer: Warning"
2975
2976	set msg {
2977    The VNC Viewer has exited.
2978
2979    You will need to terminate STUNNEL manually.
2980
2981    To do this go to the System Tray and right-click on the STUNNEL
2982    icon (dark green).  Then click "Exit".
2983
2984    You can also double click on the STUNNEL icon to view the log
2985    for error messages and other information.
2986}
2987	.w.t insert end $msg
2988}
2989
2990proc win_kill_msg {pids} {
2991	global terminate_pids
2992	global help_font
2993
2994	toplev .w
2995
2996	eval text .w.t -width 72 -height 21 $help_font
2997	button .w.d -text "Dismiss" -command {destroy .w; set terminate_pids no}
2998	button .w.k -text "Terminate STUNNEL" -command {destroy .w; set terminate_pids yes}
2999	pack .w.t .w.k .w.d -side top -fill x
3000
3001	apply_bg .w.t
3002
3003	center_win .w
3004	wm resizable .w 1 0
3005
3006	wm title .w "SSL/SSH Viewer: Warning"
3007
3008	set msg {
3009    The VNC Viewer has exited.
3010
3011    We can terminate the following still running STUNNEL process(es):
3012
3013}
3014	append msg "         $pids\n"
3015
3016	append msg {
3017    Click on the "Terminate STUNNEL" button below to do so.
3018
3019    Before terminating STUNNEL you can double click on the STUNNEL
3020    Tray icon to view its log for error messages and other information.
3021
3022    Note: You may STILL need to terminate STUNNEL manually if we are
3023    unable to kill it.  To do this go to the System Tray and right-click
3024    on the STUNNEL icon (dark green).  Then click "Exit".  You will
3025    probably also need to hover the mouse over the STUNNEL Tray Icon to
3026    make the Tray notice STUNNEL is gone...
3027
3028    To have STUNNEL automatically killed when the Viewer exits use the
3029    -killstunnel cmdline option, or set it under Options or in ssvnc_rc.
3030}
3031	.w.t insert end $msg
3032}
3033
3034proc win9x_plink_msg {file} {
3035	global help_font win9x_plink_msg_done
3036	toplev .pl
3037
3038	eval text .pl.t -width 90 -height 26 $help_font
3039	button .pl.d -text "OK" -command {destroy .pl; set win9x_plink_msg_done 1}
3040	wm protocol .pl WM_DELETE_WINDOW {catch {destroy .pl}; set win9x_plink_msg_done 1}
3041	pack .pl.t .pl.d -side top -fill x
3042
3043	apply_bg .pl.t
3044
3045	center_win .pl
3046	wm resizable .pl 1 0
3047
3048	wm title .pl "SSL/SSH Viewer: Win9x Warning"
3049
3050	set msg {
3051    Due to limitations on Window 9x you will have to manually start up
3052    a COMMAND.COM terminal and paste in the following command:
3053
3054}
3055	set pwd [pwd]
3056	regsub -all {/} $pwd "\\" pwd
3057	append msg "        $pwd\\$file\n"
3058
3059	append msg {
3060    The reason for this is a poor Console application implementation that
3061    affects many text based applications.
3062
3063    To start up a COMMAND.COM terminal, click on the Start -> Run, and then
3064    type COMMAND in the entry box and hit Return or click OK.
3065
3066    To select the above command, highlight it with the mouse and then press
3067    Ctrl-C.  Then go over to the COMMAND.COM window and click on the
3068    Clipboard paste button.  Once pasted in, press Return to run the script.
3069
3070    This will start up a PLINK.EXE ssh login to the remote computer,
3071    and after you log in successfully and indicate (QUICKLY!!) that the
3072    connection is OK by clicking OK in this dialog. If the SSH connection
3073    cannot be autodetected you will ALSO need to click "Success" in the
3074    "plink ssh status?" dialog, the VNC Viewer will be started going
3075    through the SSH tunnel.
3076}
3077	.pl.t insert end $msg
3078	wm deiconify .pl
3079}
3080
3081proc mesg {str} {
3082	set maxx 60
3083	if [regexp {^INFO: without Certificate} $str] {
3084		set maxx 72
3085	}
3086	if {[string length $str] > $maxx} {
3087		set lend [expr $maxx - 1]
3088		set str [string range $str 0 $lend]
3089		append str " ..."
3090	}
3091	.l configure -text $str
3092	update
3093	global env
3094	if [info exists env(SSVNC_MESG_DELAY)] {
3095		after $env(SSVNC_MESG_DELAY)
3096	}
3097}
3098
3099proc get_ssh_hp {str} {
3100	regsub {cmd=.*$} $str "" str
3101	set str [string trim $str]
3102	regsub {[ 	].*$} $str "" str
3103	return $str
3104}
3105
3106proc get_ssh_cmd {str} {
3107	set str [string trim $str]
3108	global ts_only
3109	if {$ts_only} {
3110		return [ts_x11vnc_cmd]
3111	}
3112	if [regexp {cmd=(.*$)} $str m cmd] {
3113		set cmd [string trim $cmd]
3114		regsub -nocase {^%x11vncr$} $cmd "x11vnc -nopw -display none -rawfb rand" cmd
3115		regsub -nocase {^%x11vnc$}  $cmd "x11vnc -nopw -display none -rawfb null" cmd
3116		return $cmd
3117	} else {
3118		return ""
3119	}
3120}
3121
3122proc get_ssh_proxy {str} {
3123	set str [string trim $str]
3124	regsub {cmd=.*$} $str "" str
3125	set str [string trim $str]
3126	if { ![regexp {[ 	]} $str]} {
3127		return ""
3128	}
3129	regsub {^.*[ 	][ 	]*} $str "" str
3130	return $str
3131}
3132
3133proc ts_x11vnc_cmd {} {
3134	global is_windows
3135	global ts_xserver_type choose_xserver ts_desktop_type choose_desktop ts_unixpw ts_vncshared
3136	global ts_desktop_size ts_desktop_depth choose_desktop_geom
3137	global choose_filexfer ts_filexfer
3138	global ts_x11vnc_opts  ts_x11vnc_path ts_x11vnc_autoport choose_x11vnc_opts
3139	global ts_othervnc choose_othervnc ts_xlogin
3140	global choose_sleep extra_sleep
3141
3142	set cmd ""
3143	if {$choose_x11vnc_opts && $ts_x11vnc_path != ""} {
3144		set cmd $ts_x11vnc_path
3145	} else {
3146		set cmd "x11vnc"
3147	}
3148	if {! $is_windows} {
3149		set cmd "PORT= $cmd"
3150	} else {
3151		set cmd "PORT= $cmd"
3152	}
3153
3154	set type $ts_xserver_type;
3155	if {! $choose_xserver} {
3156		set type ""
3157	}
3158	if {$choose_othervnc && $ts_othervnc == "find"} {
3159		set type "Xvnc.redirect"
3160	}
3161
3162	if [info exists choose_sleep] {
3163		if {! $choose_sleep} {
3164			set extra_sleep ""
3165		}
3166	}
3167
3168	if {$choose_othervnc && $ts_othervnc != "find"} {
3169		set cmd "$cmd -redirect $ts_othervnc"
3170	} elseif {$type == ""} {
3171		global ts_xserver_type_def
3172		if {$ts_xserver_type_def != ""} {
3173			set cmd "$cmd -display WAIT:cmd=FINDCREATEDISPLAY-$ts_xserver_type_def";
3174		} else {
3175			set cmd "$cmd -display WAIT:cmd=FINDCREATEDISPLAY-Xvfb";
3176		}
3177	} elseif {$type == "Xvfb"} {
3178		set cmd "$cmd -display WAIT:cmd=FINDCREATEDISPLAY-Xvfb";
3179	} elseif {$type == "Xdummy"} {
3180		set cmd "$cmd -display WAIT:cmd=FINDCREATEDISPLAY-Xdummy";
3181	} elseif {$type == "Xvnc"} {
3182		set cmd "$cmd -display WAIT:cmd=FINDCREATEDISPLAY-Xvnc";
3183	} elseif {$type == "Xvnc.redirect"} {
3184		set cmd "$cmd -display WAIT:cmd=FINDCREATEDISPLAY-Xvnc.redirect";
3185	}
3186
3187	# TBD: Cups + sound
3188
3189	set cmd "$cmd -localhost";
3190	set cmd "$cmd -nopw";
3191	global ts_ncache choose_ncache
3192	if {$choose_ncache && [regexp {^[0-9][0-9]*$} $ts_ncache]} {
3193		set cmd "$cmd -ncache $ts_ncache";
3194	} else {
3195		#set cmd "$cmd -nonc";
3196	}
3197	set cmd "$cmd -timeout 120";
3198	global ts_multisession choose_multisession
3199	regsub -all {[^A-z0-9_-]} $ts_multisession "" ts_multisession
3200	if {$choose_multisession && $ts_multisession != ""} {
3201		set cmd "$cmd -env FD_TAG='$ts_multisession'";
3202	}
3203	if {$choose_filexfer && $ts_filexfer != ""} {
3204		if {$ts_filexfer == "tight"} {
3205			set cmd "$cmd -tightfilexfer";
3206		} else {
3207			set cmd "$cmd -ultrafilexfer";
3208		}
3209	}
3210	if {$ts_unixpw} {
3211		set cmd "$cmd -unixpw";
3212	}
3213	if {$ts_vncshared} {
3214		set cmd "$cmd -shared";
3215	}
3216	set u "unknown"
3217	global env
3218	if {[info exists env(USER)]} {
3219		regsub -all {[^A-z]} $env(USER) "_" u
3220	}
3221	set cmd "$cmd -o \$HOME/.tsvnc.log.$u";	# XXX perms
3222
3223	set sess "kde"
3224	global ts_desktop_type_def
3225	if {$ts_desktop_type_def != ""} {
3226		set sess $ts_desktop_type_def
3227	}
3228	if {$choose_desktop && $ts_desktop_type != ""} {
3229		set sess $ts_desktop_type
3230	}
3231	set cmd "$cmd -env FD_SESS=$sess";
3232
3233	if {$choose_desktop_geom} {
3234		set geom "1280x1024"
3235		set dep 16
3236		global ts_desktop_size_def ts_desktop_depth_def
3237		if {$ts_desktop_size_def != ""} {
3238			set geom $ts_desktop_size_def
3239		}
3240		if {$ts_desktop_depth_def != ""} {
3241			set dep $ts_desktop_depth_def
3242		}
3243		if {$ts_desktop_size != ""} {
3244			if [regexp {^[0-9][0-9]*x[0-9][0-9]*$} $ts_desktop_size] {
3245				set geom $ts_desktop_size
3246			}
3247			if {$ts_desktop_depth != ""} {
3248				set geom "${geom}x$ts_desktop_depth"
3249			} else {
3250				set geom "${geom}x$dep"
3251			}
3252		} else {
3253			set geom "${geom}x$dep"
3254		}
3255		set cmd "$cmd -env FD_GEOM=$geom";
3256	}
3257	if {$is_windows} {
3258		;
3259	} elseif {$choose_x11vnc_opts && $ts_x11vnc_autoport != "" && [regexp {^[0-9][0-9]*$} $ts_x11vnc_autoport]} {
3260		set cmd "$cmd -autoport $ts_x11vnc_autoport";
3261	} else {
3262		set cmd "$cmd -env AUTO_PORT=5950";
3263	}
3264	if {$choose_x11vnc_opts && $ts_x11vnc_opts != ""} {
3265		set cmd "$cmd $ts_x11vnc_opts";
3266	}
3267	if {$ts_xlogin} {
3268		regsub {PORT= } $cmd "PORT= sudo " cmd
3269		regsub {P= } $cmd "P= sudo " cmd
3270		regsub { -o [^ ][^ ]*} $cmd "" cmd
3271
3272		set cmd "$cmd -env FD_XDM=1";
3273	}
3274
3275	return $cmd
3276}
3277
3278proc set_defaults {} {
3279	global defs env
3280
3281	global mycert svcert crtdir crlfil
3282	global use_alpha use_turbovnc disable_pipeline use_grab use_ssl use_ssh use_sshssl use_viewonly use_fullscreen use_bgr233
3283	global use_send_clipboard use_send_always
3284	global disable_all_encryption
3285	global use_nojpeg use_raise_on_beep use_compresslevel use_quality use_x11_macosx
3286	global compresslevel_text quality_text
3287	global use_cups use_sound use_smbmnt
3288	global cups_local_server cups_remote_port cups_manage_rcfile ts_cups_manage_rcfile cups_x11vnc
3289	global cups_local_smb_server cups_remote_smb_port
3290	global change_vncviewer change_vncviewer_path vncviewer_realvnc4
3291	global choose_xserver ts_xserver_type choose_desktop ts_desktop_type ts_unixpw ts_vncshared
3292	global choose_filexfer ts_filexfer
3293	global ts_x11vnc_opts choose_x11vnc_opts ts_x11vnc_path ts_x11vnc_autoport ts_xlogin
3294	global ts_othervnc choose_othervnc choose_sleep
3295	global choose_ncache ts_ncache choose_multisession ts_multisession
3296	global ts_mode ts_desktop_size ts_desktop_depth choose_desktop_geom
3297	global additional_port_redirs additional_port_redirs_list
3298	global stunnel_local_protection stunnel_local_protection_type ssh_local_protection multiple_listen listen_once listen_accept_popup listen_accept_popup_sc
3299	global ssh_known_hosts ssh_known_hosts_filename
3300	global ultra_dsm ultra_dsm_type ultra_dsm_file ultra_dsm_noultra ultra_dsm_salt
3301	global sound_daemon_remote_cmd sound_daemon_remote_port sound_daemon_kill sound_daemon_restart
3302	global sound_daemon_local_cmd sound_daemon_local_port sound_daemon_local_kill sound_daemon_x11vnc sound_daemon_local_start
3303	global smb_su_mode smb_mount_list
3304	global use_port_knocking port_knocking_list port_slot putty_args
3305	global ycrop_string ssvnc_scale ssvnc_escape sbwid_string rfbversion ssvnc_encodings ssvnc_extra_opts use_x11cursor use_nobell use_rawlocal use_notty use_popupfix extra_sleep use_listen use_unixpw use_x11vnc_find unixpw_username
3306	global disable_ssl_workarounds disable_ssl_workarounds_type
3307	global no_probe_vencrypt server_vencrypt server_anondh
3308	global include_list
3309	global svcert_default mycert_default crlfil_default
3310
3311
3312	set defs(use_viewonly) 0
3313	set defs(use_listen) 0
3314	set defs(disable_ssl_workarounds) 0
3315	set defs(disable_ssl_workarounds_type) "none"
3316	set defs(use_unixpw) 0
3317	set defs(unixpw_username) ""
3318	set defs(use_x11vnc_find) 0
3319	set defs(use_fullscreen) 0
3320	set defs(use_raise_on_beep) 0
3321	set defs(use_bgr233) 0
3322	set defs(use_alpha) 0
3323	set defs(use_send_clipboard) 0
3324	set defs(use_send_always) 0
3325	set defs(use_turbovnc) 0
3326	set defs(disable_pipeline) 0
3327	set defs(no_probe_vencrypt) 0
3328	set defs(server_vencrypt) 0
3329	set defs(server_anondh) 0
3330	set defs(use_grab) 0
3331	set defs(use_nojpeg) 0
3332	set defs(use_x11_macosx) 1
3333	if [info exists env(SSVNC_COTVNC)] {
3334		if {$env(SSVNC_COTVNC) != 0} {
3335			set defs(use_x11_macosx) 0
3336		}
3337	} elseif {![info exists env(DISPLAY)]} {
3338		set defs(use_x11_macosx) 0
3339	}
3340	set defs(use_compresslevel) "default"
3341	set defs(use_quality) "default"
3342	set defs(compresslevel_text) "Compress Level: default"
3343	set defs(quality_text) "Quality: default"
3344
3345	set defs(mycert) $mycert_default
3346	set defs(svcert) $svcert_default
3347	set defs(crtdir) "ACCEPTED_CERTS"
3348	set defs(crlfil) $crlfil_default
3349
3350	set defs(use_cups) 0
3351	set defs(use_sound) 0
3352	set defs(use_smbmnt) 0
3353
3354	set defs(choose_xserver) 0
3355	set defs(ts_xserver_type) ""
3356	set defs(choose_desktop) 0
3357	set defs(ts_desktop_type) ""
3358	set defs(ts_desktop_size) ""
3359	set defs(ts_desktop_depth) ""
3360	set defs(choose_desktop_geom) 0
3361	set defs(ts_unixpw) 0
3362	set defs(ts_vncshared) 0
3363	set defs(ts_ncache) 8
3364	set defs(choose_ncache) 0
3365	set defs(ts_multisession) ""
3366	set defs(choose_multisession) 0
3367	set defs(ts_filexfer) ""
3368	set defs(choose_filexfer) 0
3369	set defs(choose_x11vnc_opts) 0
3370	set defs(ts_x11vnc_opts) ""
3371	set defs(ts_x11vnc_path) ""
3372	set defs(ts_x11vnc_autoport) ""
3373	set defs(ts_othervnc) ""
3374	set defs(choose_othervnc) 0
3375	set defs(ts_xlogin) 0
3376	set defs(ts_mode) 0
3377
3378	set defs(change_vncviewer) 0
3379	set defs(change_vncviewer_path) ""
3380	set defs(cups_manage_rcfile) 1
3381	set defs(ts_cups_manage_rcfile) 0
3382	set defs(cups_x11vnc) 0
3383	set defs(vncviewer_realvnc4) 0
3384
3385	set defs(additional_port_redirs) 0
3386	set defs(additional_port_redirs_list) ""
3387
3388	set defs(stunnel_local_protection) 1
3389	set defs(stunnel_local_protection_type) "exec"
3390	set defs(ssh_local_protection) 1
3391	set defs(ssh_known_hosts) 0
3392	set defs(ssh_known_hosts_filename) ""
3393	set defs(multiple_listen) 0
3394	set defs(listen_once) 0
3395	set defs(listen_accept_popup) 0
3396	set defs(listen_accept_popup_sc) 0
3397
3398	set defs(ultra_dsm) 0
3399	set defs(ultra_dsm_file) ""
3400	set defs(ultra_dsm_type) "guess"
3401	set defs(ultra_dsm_noultra) 0
3402	set defs(ultra_dsm_salt) ""
3403
3404	set defs(port_slot) ""
3405	set defs(putty_args) ""
3406
3407	set defs(cups_local_server) ""
3408	set defs(cups_remote_port) ""
3409	set defs(cups_local_smb_server) ""
3410	set defs(cups_remote_smb_port) ""
3411
3412	set defs(smb_su_mode) "sudo"
3413	set defs(smb_mount_list) ""
3414
3415	set defs(sound_daemon_remote_cmd) ""
3416	set defs(sound_daemon_remote_port) ""
3417	set defs(sound_daemon_kill) 0
3418	set defs(sound_daemon_restart) 0
3419
3420	set defs(sound_daemon_local_cmd) ""
3421	set defs(sound_daemon_local_port) ""
3422	set defs(sound_daemon_local_start) 0
3423	set defs(sound_daemon_local_kill) 0
3424	set defs(sound_daemon_x11vnc) 0
3425
3426	set defs(ycrop_string) ""
3427	set defs(ssvnc_scale) ""
3428	set defs(ssvnc_escape) ""
3429	set defs(sbwid_string) ""
3430	set defs(rfbversion) ""
3431	set defs(ssvnc_encodings) ""
3432	set defs(ssvnc_extra_opts) ""
3433	set defs(use_x11cursor) 0
3434	set defs(use_nobell) 0
3435	set defs(use_rawlocal) 0
3436	set defs(use_notty) 0
3437	set defs(use_popupfix) 0
3438	set defs(extra_sleep) ""
3439	set defs(use_port_knocking) 0
3440	set defs(port_knocking_list) ""
3441
3442	set defs(include_list) ""
3443
3444	set dir [get_profiles_dir]
3445	set deffile ""
3446	if [file exists "$dir/defaults"] {
3447		set deffile "$dir/defaults"
3448	} elseif [file exists "$dir/defaults.vnc"] {
3449		set deffile "$dir/defaults.vnc"
3450	}
3451	if {$deffile != ""} {
3452		set fh ""
3453		catch {set fh [open $deffile "r"]}
3454		if {$fh != ""} {
3455			while {[gets $fh line] > -1} {
3456				set line [string trim $line]
3457				if [regexp {^#} $line] {
3458					continue
3459				}
3460				if [regexp {^([^=]*)=(.*)$} $line m var val] {
3461					if {$var == "disp"} {
3462						continue
3463					}
3464					if [info exists defs($var)] {
3465						set pct 0
3466						if {$var == "smb_mount_list"} {
3467							set pct 1
3468						}
3469						if {$var == "port_knocking_list"} {
3470							set pct 1
3471						}
3472						if {$pct} {
3473							regsub -all {%%%} $val "\n" val
3474						}
3475						set defs($var) $val
3476					}
3477				}
3478			}
3479			close $fh
3480		}
3481	}
3482
3483	global ssh_only ts_only
3484	if {$ssh_only || $ts_only} {
3485		set defs(use_ssl) 0
3486		set defs(use_ssh) 1
3487		set defs(use_sshssl) 0
3488	} else {
3489		set defs(use_ssl) 1
3490		set defs(use_ssh) 0
3491		set defs(use_sshssl) 0
3492	}
3493	set defs(disable_all_encryption) 0
3494
3495	foreach var [array names defs] {
3496		set $var $defs($var)
3497	}
3498
3499	global vncauth_passwd unixpw_passwd
3500	set vncauth_passwd ""
3501	set unixpw_passwd ""
3502
3503	if {$ssh_only || $ts_only} {
3504		ssl_ssh_adjust ssh
3505	} else {
3506		ssl_ssh_adjust ssl
3507	}
3508	listen_adjust
3509	unixpw_adjust
3510
3511	global last_load
3512	set last_load ""
3513}
3514
3515proc windows_listening_message {n} {
3516	global did_listening_message
3517
3518	global extra_cmd
3519	set extra_cmd ""
3520	set cmd [get_cmd $n]
3521
3522	if {$did_listening_message < 2} {
3523		incr did_listening_message
3524		global listening_name
3525
3526		set ln $listening_name
3527		if {$ln == ""} {
3528			set ln "this-computer:$n"
3529		}
3530
3531		set msg "
3532   About to start the Listening VNC Viewer (Reverse Connection).
3533
3534   The VNC Viewer command to be run is:
3535
3536       $cmd
3537
3538   After the Viewer starts listening, the VNC server should
3539   then Reverse connect to:
3540
3541       $ln
3542
3543   When the VNC Connection has ended **YOU MUST MANUALLY STOP**
3544   the Listening VNC Viewer.
3545
3546   To stop the Listening Viewer: right click on the VNC Icon in
3547   the tray and select 'Close listening daemon' (or similar).
3548
3549   ONLY AFTER THAT will you return to the SSVNC GUI.
3550
3551   Click OK now to start the Listening VNC Viewer.$extra_cmd
3552"
3553		global use_ssh use_sshssl
3554		if {$use_ssh || $use_sshssl} {
3555			set msg "${msg}   NOTE: You will probably also need to kill the SSH in the\n   terminal via Ctrl-C"
3556		}
3557
3558		global help_font is_windows system_button_face
3559		toplev .wll
3560		global wll_done
3561
3562		set wll_done 0
3563
3564		eval text .wll.t -width 64 -height 22 $help_font
3565		button .wll.d -text "OK" -command {destroy .wll; set wll_done 1}
3566		pack .wll.t .wll.d -side top -fill x
3567
3568		apply_bg .wll.t
3569
3570		center_win .wll
3571		wm resizable .wll 1 0
3572
3573		wm title .wll "SSL/SSH Viewer: Listening VNC Info"
3574
3575		.wll.t insert end $msg
3576
3577		vwait wll_done
3578	}
3579}
3580
3581proc get_cmd {n} {
3582	global use_alpha use_grab use_x11cursor use_nobell use_ssh
3583	global use_sshssl use_viewonly use_fullscreen use_bgr233
3584	global use_nojpeg use_raise_on_beep use_compresslevel use_quality
3585	global use_send_clipboard use_send_always change_vncviewer
3586	global change_vncviewer_path vncviewer_realvnc4 use_listen
3587	global disable_ssl_workarounds disable_ssl_workarounds_type env
3588
3589	set cmd "vncviewer"
3590	if {$change_vncviewer && $change_vncviewer_path != ""} {
3591		set cmd [string trim $change_vncviewer_path]
3592		regsub -all {\\} $cmd {/} cmd
3593		if {[regexp {[ \t]} $cmd]} {
3594			if {[regexp -nocase {\.exe$} $cmd]} {
3595				if {! [regexp {["']} $cmd]} { #"
3596					# hmmm, not following instructions, are they?
3597					set cmd "\"$cmd\""
3598				}
3599			}
3600		}
3601	}
3602	if {$use_viewonly} {
3603		if {$vncviewer_realvnc4} {
3604			append cmd " viewonly=1"
3605		} else {
3606			append cmd " /viewonly"
3607		}
3608	}
3609	if {$use_fullscreen} {
3610		if {$vncviewer_realvnc4} {
3611			append cmd " fullscreen=1"
3612		} else {
3613			append cmd " /fullscreen"
3614		}
3615	}
3616	if {$use_bgr233} {
3617		if {$vncviewer_realvnc4} {
3618			append cmd " lowcolourlevel=1"
3619		} else {
3620			append cmd " /8bit"
3621		}
3622	}
3623	if {$use_nojpeg} {
3624		if {! $vncviewer_realvnc4} {
3625			append cmd " /nojpeg"
3626		}
3627	}
3628	if {$use_raise_on_beep} {
3629		if {! $vncviewer_realvnc4} {
3630			append cmd " /belldeiconify"
3631		}
3632	}
3633	if {$use_compresslevel != "" && $use_compresslevel != "default"} {
3634		if {$vncviewer_realvnc4} {
3635			append cmd " zliblevel=$use_compresslevel"
3636		} else {
3637			append cmd " /compresslevel $use_compresslevel"
3638		}
3639	}
3640	if {$use_quality != "" && $use_quality != "default"} {
3641		if {! $vncviewer_realvnc4} {
3642			append cmd " /quality $use_quality"
3643		}
3644	}
3645
3646	global extra_cmd
3647	set extra_cmd ""
3648	if {$use_listen} {
3649		if {$vncviewer_realvnc4} {
3650			append cmd " listen=1"
3651		} else {
3652			append cmd " /listen"
3653		}
3654		set nn $n
3655		if {$nn < 100} {
3656			set nn [expr "$nn + 5500"]
3657		}
3658		global direct_connect_reverse_host_orig is_win9x
3659		if {![info exists direct_connect_reverse_host_orig]} {
3660			set direct_connect_reverse_host_orig ""
3661		}
3662		if {$direct_connect_reverse_host_orig != "" && !$is_win9x} {
3663			set nn2 [expr $nn + 15]
3664			set h0 $direct_connect_reverse_host_orig
3665			global win_localhost
3666			set extra_cmd "\n\nrelay6.exe $nn $win_localhost $nn2 /b:$h0"
3667			set nn $nn2
3668		}
3669
3670		append cmd " $nn"
3671
3672	} else {
3673		if [regexp {^[0-9][0-9]*$} $n] {
3674			global win_localhost
3675			append cmd " $win_localhost:$n"
3676		} else {
3677			append cmd " $n"
3678		}
3679	}
3680	return $cmd
3681}
3682
3683proc do_viewer_windows {n} {
3684	global use_listen env
3685
3686	set cmd [get_cmd $n]
3687
3688	set ipv6_pid2 ""
3689	if {$use_listen} {
3690		set nn $n
3691		if {$nn < 100} {
3692			set nn [expr "$nn + 5500"]
3693		}
3694		global direct_connect_reverse_host_orig is_win9x
3695		if {![info exists direct_connect_reverse_host_orig]} {
3696			set direct_connect_reverse_host_orig ""
3697		}
3698		if {$direct_connect_reverse_host_orig != "" && !$is_win9x} {
3699			set nn2 [expr $nn + 15]
3700			set h0 $direct_connect_reverse_host_orig
3701			global win_localhost
3702			set ipv6_pid2 [exec relay6.exe $nn $win_localhost $nn2 /b:$h0 &]
3703			set nn $nn2
3704		}
3705	}
3706
3707	if [info exists env(SSVNC_EXTRA_SLEEP)] {
3708		set t $env(SSVNC_EXTRA_SLEEP)
3709		mesg "sleeping an extra $t seconds..."
3710		set t [expr "$t * 1000"]
3711		after $t
3712	}
3713	global extra_sleep
3714	if {$extra_sleep != ""} {
3715		set t $extra_sleep
3716		mesg "sleeping an extra $t seconds..."
3717		set t [expr "$t * 1000"]
3718		after $t
3719	}
3720
3721	mesg $cmd
3722	set emess ""
3723	set rc [catch {eval exec $cmd} emess]
3724
3725	if {$ipv6_pid2 != ""} {
3726		winkill $ipv6_pid2
3727	}
3728
3729	if {$rc != 0} {
3730		raise .
3731		tk_messageBox -type ok -icon error -message $emess -title "Error: $cmd"
3732	}
3733}
3734
3735proc get_netstat {} {
3736	set ns ""
3737	catch {set ns [exec netstat -an]}
3738	return $ns
3739}
3740
3741proc get_ipconfig {} {
3742	global is_win9x
3743	set ip ""
3744	if {! $is_win9x} {
3745		catch {set ip [exec ipconfig]}
3746		return $ip
3747	}
3748
3749	set file "ip"
3750	append file [pid]
3751	append file ".txt"
3752
3753	# VF
3754	catch {[exec winipcfg /Batch $file]}
3755
3756	if [file exists $file] {
3757		set fh [open $file "r"]
3758		while {[gets $fh line] > -1} {
3759			append ip "$line\n"
3760		}
3761		close $fh
3762		catch {file delete $file}
3763	}
3764	return $ip
3765}
3766
3767proc read_file {file} {
3768	set str ""
3769	if [file exists $file] {
3770		set fh ""
3771		catch {set fh [open $file "r"]}
3772		if {$fh != ""} {
3773			while {[gets $fh line] > -1} {
3774				append str "$line\n"
3775			}
3776			close $fh
3777		}
3778	}
3779	return $str
3780}
3781
3782proc guess_nat_ip {} {
3783	global save_nat last_save_nat
3784	set s ""
3785
3786	if {! [info exists save_nat]} {
3787		set save_nat ""
3788		set last_save_nat 0
3789	}
3790	if {$save_nat != ""} {
3791		set now [clock seconds]
3792		if {$now < $last_save_nat + 45} {
3793			return $save_nat
3794		}
3795	}
3796	set s ""
3797	catch {set s [socket "www.whatismyip.com" 80]}
3798	set ip "unknown"
3799	if {$s != ""} {
3800		fconfigure $s -buffering none
3801		#puts $s "GET / HTTP/1.1"
3802		puts $s "GET /automation/n09230945.asp HTTP/1.1"
3803		puts $s "Host: www.whatismyip.com"
3804		puts $s "Connection: close"
3805		puts $s ""
3806		flush $s
3807		set on 0
3808		while { [gets $s line] > -1 } {
3809			if {! $on && [regexp {<HEAD>}  $line]} {set on 1}
3810			if {! $on && [regexp {<HTML>}  $line]} {set on 1}
3811			if {! $on && [regexp {<TITLE>} $line]} {set on 1}
3812			if {! $on && [regexp {^[0-9][0-9]*\.[0-9]} $line]} {set on 1}
3813			if {! $on} {
3814				continue;
3815			}
3816			if [regexp {([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*)} $line ip] {
3817				break
3818			}
3819		}
3820		close $s
3821	}
3822	if {$ip != "unknown"} {
3823		set save_nat $ip
3824		set last_save_nat [clock seconds]
3825	}
3826	return $ip
3827}
3828
3829proc check_for_ipv6 {} {
3830	global is_windows have_ipv6
3831	if {$have_ipv6 != ""} {
3832		return
3833	}
3834	if {! $is_windows} {
3835		set out ""
3836		catch {set out [exec netstat -an]}
3837		if [regexp {tcp6} $out] {
3838			set have_ipv6 1
3839		} elseif [regexp {udp6} $out] {
3840			set have_ipv6 1
3841		} elseif [regexp {:::} $out] {
3842			set have_ipv6 1
3843		} elseif [regexp {::1} $out] {
3844			set have_ipv6 1
3845		} elseif [regexp {TCP: IPv6.*LISTEN} $out] {
3846			set have_ipv6 1
3847		} else {
3848			set have_ipv6 0
3849		}
3850	} else {
3851		set out [get_ipconfig]
3852		set out [string trim $out]
3853		if {$out == ""} {
3854			catch {set out [exec ping6 -n 1 -w 2000 ::1]}
3855			if [regexp {Reply from.*bytes} $out] {
3856				if [regexp {Received = 1} $out] {
3857					set have_ipv6 1
3858					return
3859				}
3860			}
3861			set have_ipv6 0
3862			return
3863		}
3864		foreach line [split $out "\n\r"] {
3865			if {[regexp -nocase {IP Address.*:[ \t]*[a-f0-9]*:[a-f0-9]*:} $line]} {
3866				set have_ipv6 1
3867				return
3868			}
3869		}
3870		set have_ipv6 0
3871	}
3872}
3873proc guess_ip {} {
3874	global is_windows
3875	if {! $is_windows} {
3876		set out ""
3877		set out [get_hostname]
3878		if {$out != ""} {
3879			set hout ""
3880			catch {set hout [exec host $out]}
3881			if {$hout != ""} {
3882				if [regexp {has address ([.0-9][.0-9]*)} $hout mvar ip] {
3883					set ip [string trim $ip]
3884					return $ip
3885				}
3886			}
3887		}
3888		return ""
3889	} else {
3890		set out [get_ipconfig]
3891		set out [string trim $out]
3892		if {$out == ""} {
3893			return ""
3894		}
3895		foreach line [split $out "\n\r"] {
3896			if {[regexp -nocase {IP Address.*:[ \t]*([.0-9][.0-9]*)} $line mvar ip]} {
3897				set ip [string trim $ip]
3898				if [regexp {^[.0]*$} $ip] {
3899					continue
3900				}
3901				if [regexp {127\.0\.0\.1} $ip] {
3902					continue
3903				}
3904				if {$ip != ""} {
3905					return $ip
3906				}
3907			}
3908		}
3909		foreach line [split $out "\n\r"] {
3910			if {[regexp -nocase {IP Address.*:[ \t]*([:a-f0-9][%:a-f0-9]*)} $line mvar ip]} {
3911				set ip [string trim $ip]
3912				if [regexp {^[.0]*$} $ip] {
3913					continue
3914				}
3915				if [regexp {127\.0\.0\.1} $ip] {
3916					continue
3917				}
3918				if {$ip != ""} {
3919					return $ip
3920				}
3921			}
3922		}
3923	}
3924}
3925
3926proc bat_sleep {fh} {
3927	global env
3928	if [info exists env(SSVNC_BAT_SLEEP)] {
3929		puts $fh "@echo ."
3930		puts $fh "@echo -----"
3931		puts $fh "@echo Debug: BAT SLEEP for $env(SSVNC_BAT_SLEEP) seconds ..."
3932		puts $fh "@ping -n $env(SSVNC_BAT_SLEEP) -w 1000 0.0.0.1 > NUL"
3933		puts $fh "@echo BAT SLEEP done."
3934	}
3935}
3936
3937proc windows_start_sound_daemon {file} {
3938	global env
3939	global use_sound sound_daemon_local_cmd sound_daemon_local_start
3940
3941	# VF
3942	regsub {\.bat} $file "snd.bat" file2
3943	set fh2 [open $file2 "w"]
3944
3945	puts $fh2 $sound_daemon_local_cmd
3946	bat_sleep $fh2
3947	puts $fh2 "del $file2"
3948	close $fh2
3949
3950	mesg "Starting SOUND daemon..."
3951	if [info exists env(COMSPEC)] {
3952		if [info exists env(SSVNC_BAT_SLEEP)] {
3953			exec $env(COMSPEC) /c start $env(COMSPEC) /c $file2 &
3954		} else {
3955			exec $env(COMSPEC) /c $file2 &
3956		}
3957	} else {
3958		if [info exists env(SSVNC_BAT_SLEEP)] {
3959			exec cmd.exe /c start cmd.exe /c $file2 &
3960		} else {
3961			exec cmd.exe /c $file2 &
3962		}
3963	}
3964	after 1500
3965}
3966
3967proc winkill {pid} {
3968	global is_win9x
3969
3970	if {$pid == ""} {
3971		return
3972	}
3973	if {! $is_win9x} {
3974		catch {exec tskill.exe $pid}
3975		after 100
3976		catch {exec taskkill.exe /PID $pid}
3977		after 100
3978	}
3979	catch {exec w98/kill.exe /f $pid}
3980}
3981
3982proc windows_stop_sound_daemon {} {
3983	global use_sound sound_daemon_local_cmd sound_daemon_local_start
3984
3985	set cmd [string trim $sound_daemon_local_cmd]
3986
3987	regsub {[ \t].*$} $cmd "" cmd
3988	regsub {^.*\\} $cmd "" cmd
3989	regsub {^.*/} $cmd "" cmd
3990
3991	if {$cmd == ""} {
3992		return
3993	}
3994
3995	set output [get_task_list]
3996
3997	foreach line [split $output "\n\r"] {
3998		if [regexp "$cmd" $line] {
3999			if [regexp {(-?[0-9][0-9]*)} $line m p] {
4000				set pids($p) $line
4001			}
4002		}
4003	}
4004
4005	set count 0
4006	foreach pid [array names pids] {
4007		mesg "Stopping SOUND pid: $pid"
4008		winkill $pid
4009		if {$count == 0} {
4010			after 1200
4011		} else {
4012			after 500
4013		}
4014		incr count
4015	}
4016}
4017
4018proc contag {} {
4019	global concount
4020	if {! [info exists concount]} {
4021		set concount 0
4022	}
4023	incr concount
4024	set str [pid]
4025	set str "-$str-$concount"
4026}
4027
4028proc make_plink {} {
4029	toplev .plink
4030	#wm geometry .plink +700+500
4031	wm geometry .plink -40-40
4032	wm title .plink "plink SSH status?"
4033	set wd 37
4034	label .plink.l1 -anchor w -text "Login via plink/ssh to the remote server" -width $wd
4035	label .plink.l2 -anchor w -text "(supply username and password as needed)." -width $wd
4036	label .plink.l3 -anchor w -text "" -width $wd
4037	label .plink.l4 -anchor w -text "After ssh is set up, AND if the connection" -width $wd
4038	label .plink.l5 -anchor w -text "success is not autodetected, please click" -width $wd
4039	label .plink.l6 -anchor w -text "one of these buttons:" -width $wd
4040	global plink_status
4041	button .plink.fail -text "Failed" -command {destroy .plink; set plink_status no}
4042	button .plink.ok   -text "Success" -command {destroy .plink; set plink_status yes}
4043	pack .plink.l1 .plink.l2 .plink.l3 .plink.l4 .plink.l5 .plink.l6 .plink.fail .plink.ok -side top -fill x
4044
4045	update
4046}
4047
4048proc ssh_split {str} {
4049	regsub { .*$} $str "" str
4050	if {! [regexp {:[0-9][0-9]*$} $str]} {
4051		append str ":22"
4052	}
4053	regsub {:[0-9][0-9]*$} $str "" ssh_host
4054	regsub {^.*:} $str "" ssh_port
4055	if {$ssh_port == ""} {
4056		set ssh_port 22
4057	}
4058	if [regexp {@} $ssh_host] {
4059		regsub {@.*$} $ssh_host "" ssh_user
4060		regsub {^.*@} $ssh_host "" ssh_host
4061	} else {
4062		set ssh_user ""
4063	}
4064	return [list $ssh_user $ssh_host $ssh_port]
4065}
4066
4067proc check_debug_netstat {port str wn} {
4068	global debug_netstat
4069	if {! [info exists debug_netstat]} {
4070		return
4071	}
4072	if {$debug_netstat == "0" || $debug_netstat == ""} {
4073		return
4074	}
4075	mesg "DBG: $wn"
4076
4077	toplev .dbns
4078
4079	set h 35
4080	if [small_height] {
4081		set h 28
4082	}
4083	scroll_text_dismiss .dbns.f 82 $h
4084	center_win .dbns
4085	.dbns.f.t insert end "LOOKING FOR PORT: $port\n\n$str"
4086	jiggle_text .dbns.f.t
4087	update
4088	after 1000
4089}
4090
4091proc launch_windows_ssh {hp file n} {
4092	global is_win9x env
4093	global use_sshssl use_ssh putty_pw putty_args
4094	global port_knocking_list
4095	global use_listen listening_name
4096	global disable_ssl_workarounds disable_ssl_workarounds_type
4097	global ts_only
4098	global debug_netstat
4099
4100	set hpnew  [get_ssh_hp $hp]
4101	set proxy  [get_ssh_proxy $hp]
4102	set sshcmd [get_ssh_cmd $hp]
4103
4104	global win_localhost
4105
4106	set vnc_host $win_localhost
4107	set vnc_disp $hpnew
4108	regsub {^.*:} $vnc_disp "" vnc_disp
4109
4110	regsub {\.bat} $file ".flg" flag
4111
4112	if {$ts_only} {
4113		regsub {:0$} $hpnew "" hpnew
4114		if {$proxy == ""} {
4115			if {[regexp {^(.*):([0-9][0-9]*)$} $hpnew mv sshhst sshpt]} {
4116				set proxy "$sshhst:$sshpt"
4117				set hpnew $win_localhost
4118			}
4119		} else {
4120			if {![regexp {,} $proxy]} {
4121				if {$hpnew != $win_localhost} {
4122					set proxy "$proxy,$hpnew"
4123					set hpnew $win_localhost
4124				}
4125			}
4126		}
4127	} elseif {![regexp {^-?[0-9][0-9]*$} $vnc_disp]} {
4128		if {[regexp {cmd=SHELL} $hp]} {
4129			;
4130		} elseif {[regexp {cmd=PUTTY} $hp]} {
4131			;
4132		} else {
4133			# XXX add :0 instead?
4134			if {1} {
4135				set vnc_disp "vnc_disp:0"
4136				mesg "Added :0 to $vnc_disp"
4137			} else {
4138				mesg "Bad vncdisp, missing :0 ?, $vnc_disp"
4139				bell
4140				return 0
4141			}
4142		}
4143	}
4144
4145	if {$use_listen} {
4146		set vnc_port 5500
4147	} else {
4148		set vnc_port 5900
4149	}
4150
4151	if {$ts_only || [regexp {PORT= .*x11vnc} $sshcmd] || [regexp {P= .*x11vnc} $sshcmd]} {
4152		regsub {PORT= [ 	]*} $sshcmd "" sshcmd
4153		regsub {P= [ 	]*} $sshcmd "" sshcmd
4154		set vnc_port [expr "8100 + int(4000 * rand())"]
4155		set sshcmd "$sshcmd -rfbport $vnc_port"
4156	} elseif {[regexp {^-[0-9][0-9]*$} $vnc_disp]} {
4157		set vnc_port [expr "- $vnc_disp"]
4158	} elseif {![regexp {^[0-9][0-9]*$} $vnc_disp]} {
4159		;
4160	} elseif {$vnc_disp < 200} {
4161		if {$use_listen} {
4162			set vnc_port [expr $vnc_disp + 5500]
4163		} else {
4164			set vnc_port [expr $vnc_disp + 5900]
4165		}
4166	} else {
4167		set vnc_port $vnc_disp
4168	}
4169
4170	global ssh_ipv6_pid
4171	set ssh_ipv6_pid ""
4172
4173	set ssh_port 22
4174	set ssh_host [host_part $hpnew]
4175
4176	set double_ssh ""
4177	set p_port ""
4178	if {$proxy != ""} {
4179		if [regexp -nocase {(http|https|socks|socks4|socks5|repeater)://} $proxy] {
4180			set pproxy ""
4181			set sproxy1 ""
4182			set sproxy_rest ""
4183			set sproxy1_host ""
4184			set sproxy1_user ""
4185			set sproxy1_port ""
4186			foreach part [split $proxy ","] {
4187				if {[regexp {^[ 	]*$} $part]} {
4188					continue
4189				}
4190				if [regexp -nocase {^(http|https|socks|socks4|socks5|repeater)://} $part] {
4191					if {$pproxy == ""} {
4192						set pproxy $part
4193					} else {
4194						set pproxy "$pproxy,$part"
4195					}
4196				} else {
4197					if {$sproxy1 == ""} {
4198						set sproxy1 $part
4199					} else {
4200						if {$sproxy_rest == ""} {
4201							set sproxy_rest $part
4202						} else {
4203							set sproxy_rest "$sproxy_rest,$part"
4204						}
4205					}
4206				}
4207			}
4208
4209#mesg "pproxy: $pproxy"; after 2000
4210#mesg "sproxy1: $sproxy1"; after 2000
4211#mesg "sproxy_rest: $sproxy_rest"; after 2000
4212#mesg "ssh_host: $ssh_host"; after 2000
4213#mesg "ssh_port: $ssh_port"; after 2000
4214
4215			if {$sproxy1 != ""} {
4216				regsub {:[0-9][0-9]*$} $sproxy1 "" sproxy1_host
4217				regsub {^.*@} $sproxy1_host "" sproxy1_host
4218				regsub {@.*$} $sproxy1 "" sproxy1_user
4219				regsub {^.*:} $sproxy1 "" sproxy1_port
4220			} else {
4221				regsub {:[0-9][0-9]*$} $ssh_host "" sproxy1_host
4222				regsub {^.*@} $sproxy1_host "" sproxy1_host
4223				regsub {@.*$} $ssh_host "" sproxy1_user
4224				regsub {^.*:} $ssh_host "" sproxy1_port
4225			}
4226			if {![regexp {^[0-9][0-9]*$} $sproxy1_port]} {
4227				set sproxy1_port 22
4228			}
4229			if {$sproxy1_user != ""} {
4230				set sproxy1_user "$sproxy1_user@"
4231			}
4232
4233#mesg "sproxy1_host: $sproxy1_host"; after 2000
4234#mesg "sproxy1_user: $sproxy1_user"; after 2000
4235#mesg "sproxy1_port: $sproxy1_port"; after 2000
4236
4237			set port2 ""
4238			if [regexp -- {-([0-9][0-9]*)} [file tail $file] mv dport] {
4239				set port2 [expr 21000 + $dport]
4240			} else {
4241				set port2 [rand_port]
4242			}
4243
4244			global have_ipv6
4245			if {$have_ipv6} {
4246				set res [ipv6_proxy $pproxy "" ""]
4247				set pproxy    [lindex $res 0]
4248				set ssh_ipv6_pid [lindex $res 3]
4249			}
4250
4251			set env(SSVNC_PROXY) $pproxy
4252			set env(SSVNC_LISTEN) $port2
4253			set env(SSVNC_DEST) "$sproxy1_host:$sproxy1_port"
4254
4255			mesg "Starting Proxy TCP helper on port $port2 ..."
4256			after 300
4257			# ssh br case:
4258			set proxy_pid [exec "connect_br.exe" &]
4259
4260			catch { unset env(SSVNC_PROXY)  }
4261			catch { unset env(SSVNC_LISTEN) }
4262			catch { unset env(SSVNC_DEST)   }
4263
4264			if {$sproxy1 == ""} {
4265				set proxy "$win_localhost:$port2"
4266				if [regexp {^(.*)@} $ssh_host mv u] {
4267					set proxy "$u@$proxy"
4268				}
4269			} else {
4270				set proxy "${sproxy1_user}$win_localhost:$port2"
4271			}
4272			if {$sproxy_rest != ""} {
4273				set proxy "$proxy,$sproxy_rest"
4274			}
4275			mesg "Set proxy to: $proxy"
4276			after 300
4277		}
4278		if [regexp {,} $proxy] {
4279			if {$is_win9x} {
4280				mesg "Double proxy does not work on Win9x"
4281				bell
4282				winkill $ssh_ipv6_pid
4283				set ssh_ipv6_pid ""
4284				return 0
4285			}
4286			# user1@gateway:port1,user2@workstation:port2
4287			set proxy1 ""
4288			set proxy2 ""
4289			set s [split $proxy ","]
4290			set proxy1 [lindex $s 0]
4291			set proxy2 [lindex $s 1]
4292
4293			set p_port ""
4294			if [regexp -- {-([0-9][0-9]*)} [file tail $file] mv dport] {
4295				set p_port [expr 4000 + $dport]
4296			} else {
4297				set p_port [expr 3000 + 1000 * rand()]
4298				set p_port [expr round($p_port)]
4299			}
4300
4301			set s [ssh_split $proxy1]
4302			set ssh_user1 [lindex $s 0]
4303			set ssh_host1 [lindex $s 1]
4304			set ssh_port1 [lindex $s 2]
4305
4306			set s [ssh_split $proxy2]
4307			set ssh_user2 [lindex $s 0]
4308			set ssh_host2 [lindex $s 1]
4309			set ssh_port2 [lindex $s 2]
4310
4311			if {! [regexp {^[0-9][0-9]*$} $ssh_port1]} {
4312				set ssh_port1 22
4313			}
4314			if {! [regexp {^[0-9][0-9]*$} $ssh_port2]} {
4315				set ssh_port2 22
4316			}
4317
4318			set u1 ""
4319			if {$ssh_user1 != ""} {
4320				set u1 "${ssh_user1}@"
4321			}
4322			set u2 ""
4323			if {$ssh_user2 != ""} {
4324				set u2 "${ssh_user2}@"
4325			}
4326
4327			set double_ssh "-L $p_port:$ssh_host2:$ssh_port2 -P $ssh_port1 $u1$ssh_host1"
4328			set proxy_use "${u2}$win_localhost:$p_port"
4329
4330		} else {
4331			# user1@gateway:port1
4332			set proxy_use $proxy
4333		}
4334
4335		set ssh_host [host_part $proxy_use]
4336
4337		set ssh_port [port_part $proxy_use]
4338		if {! [regexp {^[0-9][0-9]*$} $ssh_port]} {
4339			set ssh_port 22
4340		}
4341
4342		set vnc_host [host_part $hpnew]
4343		if {$vnc_host == ""} {
4344			set vnc_host $win_localhost
4345		}
4346	}
4347
4348	if {![regexp {^[^ 	][^ 	]*@} $ssh_host]} {
4349		mesg "You must supply a username: user@host..."
4350		bell
4351		winkill $ssh_ipv6_pid
4352		set ssh_ipv6_pid ""
4353		return 0
4354	}
4355
4356	set verb "-v"
4357
4358	set pwd ""
4359	if {$is_win9x} {
4360		set pwd [pwd]
4361		regsub -all {/} $pwd "\\" pwd
4362	}
4363	if {! [regexp {^[0-9][0-9]*$} $n]} {
4364		set n 0
4365	}
4366
4367	if {$use_listen} {
4368		set use [expr $n + 5500]
4369	} else {
4370		set use [expr $n + 5900]
4371	}
4372
4373	set_smb_mounts
4374
4375	global use_smbmnt use_sound sound_daemon_kill
4376	set do_pre 0
4377	if {$use_smbmnt}  {
4378		set do_pre 1
4379	} elseif {$use_sound && $sound_daemon_kill} {
4380		set do_pre 1
4381	}
4382
4383	global skip_pre
4384	if {$skip_pre} {
4385		set do_pre 0
4386		set skip_pre 0
4387	}
4388
4389	set pw ""
4390	if {$putty_pw != ""} {
4391		if {! [regexp {"} $putty_pw]} {  #"
4392			set pw "                                                      -pw                                                   \"$putty_pw\""
4393		}
4394	}
4395
4396	set tag [contag]
4397
4398	set file_double ""
4399
4400	set file_pre ""
4401	set file_pre_cmd ""
4402	if {$do_pre} {
4403		set setup_cmds [ugly_setup_scripts pre $tag]
4404
4405		if {$setup_cmds != ""} {
4406			# VF
4407			regsub {\.bat} $file "pre.cmd" file_pre_cmd
4408			set fh [open $file_pre_cmd "w"]
4409			puts $fh "$setup_cmds sleep 10; "
4410			bat_sleep $fh
4411			close $fh
4412
4413			# VF
4414			regsub {\.bat} $file "pre.bat" file_pre
4415			set fh [open $file_pre "w"]
4416			set plink_str "plink.exe -ssh -C -P $ssh_port -m $file_pre_cmd $verb -t"
4417			if {$putty_args != ""} {
4418				append plink_str " $putty_args"
4419			}
4420
4421			global smb_redir_0
4422			if {$smb_redir_0 != ""} {
4423				append plink_str " $smb_redir_0"
4424			}
4425
4426			if [regexp {%} $ssh_host] {
4427				set uath ""
4428				regsub -all {%SPACE} $ssh_host " " uath
4429				regsub -all {%TAB} $uath "	" uath
4430				append plink_str "$pw \"$uath\""
4431			} else {
4432				append plink_str "$pw $ssh_host"
4433			}
4434
4435			if {$pw != ""} {
4436				puts $fh "echo off"
4437			}
4438			puts $fh $plink_str
4439
4440			bat_sleep $fh
4441			if {![info exists env(SSVNC_NO_DELETE)]} {
4442				if {$file_pre_cmd != ""} {
4443					puts $fh "del $file_pre_cmd"
4444				}
4445				puts $fh "del $file_pre"
4446			}
4447			close $fh
4448		}
4449	}
4450
4451	if {$is_win9x} {
4452		set sleep 35
4453	} else {
4454		set sleep 20
4455	}
4456	if {$use_listen} {
4457		set sleep 1800
4458	}
4459
4460	set setup_cmds [ugly_setup_scripts post $tag]
4461
4462	set do_shell 0
4463	if {$sshcmd == "SHELL"} {
4464		set setup_cmds ""
4465		set sshcmd {$SHELL}
4466		set do_shell 1
4467	} elseif {$sshcmd == "PUTTY"} {
4468		set setup_cmds ""
4469		set do_shell 1
4470	}
4471
4472	if {$sshcmd != "SHELL" && [regexp -nocase {x11vnc} $sshcmd]} {
4473		global use_cups cups_x11vnc cups_remote_port
4474		global cups_remote_smb_port
4475		global use_sound sound_daemon_x11vnc sound_daemon_remote_port
4476		global ts_only
4477		if {$ts_only} {
4478			set cups_x11vnc 1
4479			set sound_daemon_x11vnc 1
4480		}
4481		if {$use_cups && $cups_x11vnc && $cups_remote_port != ""} {
4482			set crp $cups_remote_port
4483			if {$ts_only} {
4484				set cups_remote_port [rand_port]
4485				set crp "DAEMON-$cups_remote_port"
4486			}
4487			set sshcmd "$sshcmd -env FD_CUPS=$crp"
4488		}
4489		if {$use_cups && $cups_x11vnc && $cups_remote_smb_port != ""} {
4490			set csp $cups_remote_smb_port
4491			if {$ts_only} {
4492				set cups_remote_smb_port [rand_port]
4493				set csp "DAEMON-$cups_remote_smb_port"
4494			}
4495			set sshcmd "$sshcmd -env FD_SMB=$csp"
4496		}
4497		if {$use_sound && $sound_daemon_x11vnc && $sound_daemon_remote_port != ""} {
4498			set srp $sound_daemon_remote_port
4499			if {$ts_only} {
4500				set sound_daemon_remote_port [rand_port]
4501				set srp "DAEMON-$sound_daemon_remote_port"
4502			}
4503			set sshcmd "$sshcmd -env FD_ESD=$srp"
4504		}
4505	}
4506
4507	set file_cmd ""
4508	if {$setup_cmds != ""} {
4509		# VF
4510		regsub {\.bat} $file ".cmd" file_cmd
4511		set fh_cmd [open $file_cmd "w"]
4512
4513		set str $setup_cmds
4514		if {$sshcmd != ""} {
4515			append str " $sshcmd; "
4516		} else {
4517			append str " sleep $sleep; "
4518		}
4519		puts $fh_cmd $str
4520		bat_sleep $fh_cmd
4521		close $fh_cmd
4522
4523		set sshcmd $setup_cmds
4524	}
4525
4526	if {$sshcmd == ""} {
4527		set pcmd "echo; echo SSH connected OK.; echo If this state is not autodetected,; echo Go Click the Success button."
4528		set sshcmd "$pcmd; sleep $sleep"
4529	}
4530
4531	global use_sound sound_daemon_local_cmd sound_daemon_local_start
4532	if {! $do_shell && ! $is_win9x && $use_sound && $sound_daemon_local_start && $sound_daemon_local_cmd != ""} {
4533		windows_start_sound_daemon $file
4534	}
4535
4536	# VF
4537	set fh [open $file "w"]
4538	if {$is_win9x} {
4539		puts $fh "cd $pwd"
4540		if {$file_pre != ""} {
4541			puts $fh "echo Press Ctrl-C --HERE-- when done with the Pre-Command shell work."
4542			puts $fh "start /w command.com /c $file_pre"
4543		}
4544	}
4545
4546	global use_cups use_smbmnt
4547	set extra_redirs ""
4548	if {$use_cups} {
4549		append extra_redirs [get_cups_redir]
4550	}
4551	if {$use_sound} {
4552		append extra_redirs [get_sound_redir]
4553	}
4554	global additional_port_redirs
4555	if {$additional_port_redirs} {
4556		append extra_redirs [get_additional_redir]
4557	}
4558
4559	if {$vnc_host == ""} {
4560		set vnc_host $win_localhost
4561	}
4562	regsub {^.*@} $vnc_host "" vnc_host
4563
4564	set redir "-L $use:$vnc_host:$vnc_port"
4565	if {$use_listen} {
4566		set redir "-R $vnc_port:$vnc_host:$use"
4567		set listening_name "localhost:$vnc_port  (on remote SSH side)"
4568	}
4569
4570	set plink_str "plink.exe -ssh -P $ssh_port $verb $redir $extra_redirs -t"
4571	if {$putty_args != ""} {
4572		append plink_str " $putty_args"
4573	}
4574	if {$extra_redirs != ""} {
4575		regsub {exe} $plink_str "exe -C" plink_str
4576	} else {
4577		# hmm we used to have it off... why?
4578		# ssh typing response?
4579		regsub {exe} $plink_str "exe -C" plink_str
4580	}
4581	set uath $ssh_host
4582	if [regexp {%} $uath] {
4583		regsub -all {%SPACE} $uath " " uath
4584		regsub -all {%TAB} $uath "	" uath
4585		set uath "\"$uath\""
4586	}
4587	if {$do_shell} {
4588		if {$sshcmd == "PUTTY"} {
4589		    if [regexp {^".*@} $uath] { #"
4590			    regsub {@} $uath {" "} uath
4591			    set uath "-l $uath"
4592		    }
4593		    if {$is_win9x} {
4594			set plink_str "putty.exe -ssh -C -P $ssh_port $extra_redirs $putty_args -t $pw $uath"
4595		    } else {
4596			set plink_str "start \"putty $ssh_host\" putty.exe -ssh -C -P $ssh_port $extra_redirs $putty_args -t $pw $uath"
4597			if [regexp {FINISH} $port_knocking_list] {
4598				regsub {start} $plink_str "start /wait" plink_str
4599			}
4600		    }
4601		} else {
4602			set plink_str "plink.exe -ssh -C -P $ssh_port $extra_redirs $putty_args -t $pw $uath"
4603			append plink_str { "$SHELL"}
4604		}
4605	} elseif {$file_cmd != ""} {
4606		append plink_str " -m $file_cmd$pw $uath"
4607	} else {
4608		append plink_str "$pw $uath \"$sshcmd\""
4609	}
4610
4611	if {$pw != ""} {
4612		puts $fh "echo off"
4613	}
4614	if {$ts_only && [regexp {sudo } $sshcmd]} {
4615		puts $fh "echo \" \""
4616		puts $fh "echo \"Doing Initial SSH with sudo id to prime sudo...\""
4617		puts $fh "echo \" \""
4618		puts $fh "plink.exe -ssh $putty_args -t $uath \"sudo id; tty\""
4619		puts $fh "echo \" \""
4620	}
4621	puts $fh $plink_str
4622	bat_sleep $fh
4623	puts $fh "del $flag"
4624	if {![info exists env(SSVNC_NO_DELETE)]} {
4625		if {$file_cmd != ""} {
4626			puts $fh "del $file_cmd"
4627		}
4628		puts $fh "del $file"
4629	}
4630	close $fh
4631
4632	catch {destroy .o}
4633	catch {destroy .oa}
4634	catch {destroy .os}
4635
4636	if { ![do_port_knock $ssh_host start]} {
4637		if {![info exists env(SSVNC_NO_DELETE)]} {
4638			catch {file delete $file}
4639			if {$file_cmd != ""} {
4640				catch {file delete $file_cmd}
4641			}
4642			if {$file_pre != ""} {
4643				catch {file delete $file_pre}
4644			}
4645		}
4646		winkill $ssh_ipv6_pid
4647		set ssh_ipv6_pid ""
4648		return 0
4649	}
4650
4651	if {$double_ssh != ""} {
4652		set plink_str_double_ssh "plink.exe -ssh $putty_args -t $pw $double_ssh \"echo sleep 60 ...; sleep 60; echo done.\""
4653
4654		# VF
4655		regsub {\.bat} $file "dob.bat" file_double
4656		set fhdouble [open $file_double "w"]
4657		puts $fhdouble $plink_str_double_ssh
4658		bat_sleep $fhdouble
4659		puts $fhdouble "del $flag"
4660		if {![info exists env(SSVNC_NO_DELETE)]} {
4661			puts $fhdouble "del $file_double"
4662		}
4663		close $fhdouble
4664
4665		set com "cmd.exe"
4666		if [info exists env(COMSPEC)] {
4667			set com $env(COMSPEC)
4668		}
4669
4670		set ff [open $flag "w"]
4671		puts $ff "flag"
4672		close $ff
4673
4674		global env
4675		if [info exists env(SSVNC_BAT_SLEEP)] {
4676			exec $com /c start $com /c $file_double &
4677		} else {
4678			exec $com /c $file_double &
4679		}
4680
4681		set waited 0
4682		set gotit 0
4683		while {$waited < 30000} {
4684			after 500
4685			update
4686			if {$use_listen} {
4687				set gotit 1
4688				break;
4689			}
4690			set ns [get_netstat]
4691			set re ":$p_port"
4692			check_debug_netstat $p_port $ns $waited
4693			append re {[ 	][ 	]*[0:.][0:.]*[ 	][ 	]*LISTEN}
4694			if [regexp $re $ns] {
4695				set gotit 1
4696				break
4697			}
4698			set waited [expr "$waited + 500"]
4699			if {![file exists $flag]} {
4700				break
4701			}
4702		}
4703		catch {file delete $flag}
4704		if {! $gotit} {
4705			after 5000
4706		}
4707	}
4708
4709	vencrypt_tutorial_mesg
4710
4711	set wdraw 1
4712	#set wdraw 0
4713	if [info exists debug_netstat] {
4714		if {$debug_netstat != "" && $debug_netstat != "0"} {
4715			set wdraw 0
4716		}
4717	}
4718
4719	set ff [open $flag "w"]
4720	puts $ff "flag"
4721	close $ff
4722
4723	if {$is_win9x} {
4724		if {$wdraw} {
4725			wm withdraw .
4726		}
4727		update
4728		win9x_plink_msg $file
4729		global win9x_plink_msg_done
4730		set win9x_plink_msg_done 0
4731		vwait win9x_plink_msg_done
4732	} else {
4733		set com "cmd.exe"
4734		if [info exists env(COMSPEC)] {
4735			set com $env(COMSPEC)
4736		}
4737
4738		if {$file_pre != ""} {
4739			set sl 0
4740			if {$use_smbmnt}  {
4741				global smb_su_mode
4742				if {$smb_su_mode == "su"} {
4743					set sl [expr $sl + 15]
4744				} elseif {$smb_su_mode == "sudo"} {
4745					set sl [expr $sl + 15]
4746				} else {
4747					set sl [expr $sl + 3]
4748				}
4749			}
4750			if {$pw == ""} {
4751				set sl [expr $sl + 5]
4752			}
4753
4754			set sl [expr $sl + 5]
4755			set st [clock seconds]
4756			set dt 0
4757			global entered_gui_top button_gui_top
4758			set entered_gui_top 0
4759			set button_gui_top 0
4760
4761			catch {wm geometry . "-40-40"}
4762			catch {wm withdraw .; update; wm deiconify .; raise .; update}
4763			mesg "Click on *This* Label when done with 1st SSH 0/$sl"
4764			after 600
4765
4766			global env
4767			if [info exists env(SSVNC_BAT_SLEEP)] {
4768				exec $com /c start $com /c $file_pre &
4769			} else {
4770				exec $com /c $file_pre &
4771			}
4772
4773			catch {lower .; update; raise .; update}
4774
4775			while {$dt < $sl} {
4776				after 100
4777				set dt [clock seconds]
4778				set dt [expr $dt - $st]
4779				mesg "Click on *This* Label when done with 1st SSH $dt/$sl"
4780				update
4781				update idletasks
4782				if {$dt <= 1} {
4783					set button_gui_top 0
4784				}
4785				if {$button_gui_top != 0 && $dt >= 3} {
4786					mesg "Running 2nd SSH now ..."
4787					after 1000
4788					break
4789				}
4790			}
4791			mesg "Running 2nd SSH ..."
4792		}
4793
4794		if {! $do_shell} {
4795			make_plink
4796		}
4797		if {$wdraw} {
4798			wm withdraw .
4799		}
4800
4801		update
4802		if {$do_shell && [regexp {FINISH} $port_knocking_list]} {
4803			catch {exec $com /c $file}
4804		} else {
4805			global env
4806			if [info exists env(SSVNC_BAT_SLEEP)] {
4807				exec $com /c start $com /c $file &
4808			} else {
4809				exec $com /c $file &
4810			}
4811		}
4812		after 1000
4813	}
4814
4815	if {$do_shell} {
4816		wm deiconify .
4817		update
4818		if {[regexp {FINISH} $port_knocking_list]} {
4819			do_port_knock $ssh_host finish
4820		}
4821		return 1
4822	}
4823	set made_plink 0
4824	if {$is_win9x} {
4825		make_plink
4826		set made_plink 1
4827	}
4828	global plink_status
4829	set plink_status ""
4830	set waited 0
4831	set cnt 0
4832	while {$waited < 30000} {
4833		after 500
4834		update
4835		if {$use_listen} {
4836			set plink_status yes
4837			break;
4838		}
4839		set ns [get_netstat]
4840		set re ":$use"
4841		check_debug_netstat $use $ns $waited
4842		append re {[ 	][ 	]*[0:.][0:.]*[ 	][ 	]*LISTEN}
4843		if [regexp $re $ns] {
4844			set plink_status yes
4845		}
4846		if {$plink_status != ""} {
4847			catch {destroy .plink}
4848			break
4849		}
4850
4851		if {$waited == 0} {
4852			#wm deiconify .plink
4853		}
4854		set waited [expr "$waited + 500"]
4855
4856		incr cnt
4857		if {$cnt >= 12} {
4858			set cnt 0
4859		}
4860		if {![file exists $flag]} {
4861			set plink_status flag_gone
4862			break
4863		}
4864	}
4865	catch {file delete $flag}
4866	if {$plink_status == ""} {
4867		if {! $made_plink} {
4868			make_plink
4869			set made_plink 1
4870		}
4871		vwait plink_status
4872	}
4873
4874	if {$use_sshssl} {
4875		global launch_windows_ssh_files
4876		if {$file != ""} {
4877			append launch_windows_ssh_files "$file "
4878		}
4879		if {$file_pre != ""} {
4880			append launch_windows_ssh_files "$file_pre "
4881		}
4882		if {$file_pre_cmd != ""} {
4883			append launch_windows_ssh_files "$file_pre_cmd "
4884		}
4885		regsub { *$} $launch_windows_ssh_files "" launch_windows_ssh_files
4886		return 1
4887	}
4888
4889	if {$plink_status != "yes"} {
4890		set m "unknown"
4891		if {$plink_status == "flag_gone"} {
4892			set m "plink script failed"
4893		} elseif {$plink_status == ""} {
4894			set m "timeout"
4895		}
4896		mesg "Error ($m) to $hp"
4897		wm deiconify .
4898	} else {
4899		after 1000
4900		do_viewer_windows $n
4901		wm deiconify .
4902		mesg "Disconnected from $hp"
4903	}
4904	update
4905	if [regexp {FINISH} $port_knocking_list] {
4906		do_port_knock $ssh_host finish
4907	}
4908
4909	if {![info exists env(SSVNC_NO_DELETE)]} {
4910		if {$file != ""} {
4911			catch {file delete $file}
4912		}
4913		if {$file_pre != ""} {
4914			catch {file delete $file_pre}
4915		}
4916		if {$file_pre_cmd != ""} {
4917			catch {file delete $file_pre_cmd}
4918		}
4919		if {$file_double != ""} {
4920			catch {file delete $file_double}
4921		}
4922	}
4923
4924	winkill $ssh_ipv6_pid
4925	set ssh_ipv6_pid ""
4926
4927	global sound_daemon_local_kill
4928	if {! $is_win9x && $use_sound && $sound_daemon_local_kill && $sound_daemon_local_cmd != ""} {
4929		windows_stop_sound_daemon
4930	}
4931	return 1
4932}
4933
4934proc check_ssh_needed {} {
4935	globalize
4936
4937	if {$use_ssh || $use_sshssl} {
4938		return
4939	}
4940	set must_cups 0
4941	set must_snd 0
4942	set must_smb 0
4943	set must_addl 0
4944	if {$use_cups} {
4945		if {$cups_local_server != ""} {set must_cups 1}
4946		if {$cups_remote_port != ""} {set must_cups 1}
4947		if {$cups_local_smb_server != ""} {set must_cups 1}
4948		if {$cups_remote_smb_port != ""} {set must_cups 1}
4949		if {$cups_manage_rcfile != ""} {set must_cups 1}
4950	}
4951	if {$use_sound} {
4952		if {$sound_daemon_remote_cmd != ""} {set must_snd 1}
4953		if {$sound_daemon_remote_port != ""} {set must_snd 1}
4954		if {$sound_daemon_kill} {set must_snd 1}
4955		if {$sound_daemon_restart} {set must_snd 1}
4956		if {$sound_daemon_local_cmd != ""} {set must_snd 1}
4957		if {$sound_daemon_local_port != ""} {set must_snd 1}
4958		if {$sound_daemon_local_kill} {set must_snd 1}
4959		if {$sound_daemon_local_start} {set must_snd 1}
4960	}
4961	if {$use_smbmnt} {
4962		if {[regexp {//} $smb_mount_list]} {set must_smb 1}
4963	}
4964	if {$additional_port_redirs} {
4965		set must_addl 1
4966	}
4967	if {$must_cups || $must_snd || $must_smb || $must_addl} {
4968		mesg "Cannot do Port redirs in non-SSH mode (SSL)"
4969		set msg ""
4970		if {$must_smb} {
4971			append msg "  - SMB Mount Port Redirection\n"
4972		}
4973		if {$must_snd} {
4974			append msg "  - ESD Sound Port Redirection\n"
4975		}
4976		if {$must_cups} {
4977			append msg "  - CUPS Port Redirection\n"
4978		}
4979		if {$must_addl} {
4980			append msg "  - Additional Port Redirections\n"
4981		}
4982                set msg "\"Use SSL\" mode selected (no SSH)\nThe following options will be disabled:\n\n$msg"
4983		bell
4984		update
4985		raise .
4986                tk_messageBox -type ok -icon info -message $msg
4987	}
4988}
4989
4990proc set_smb_mounts {} {
4991	global smb_redir_0 smb_mounts use_smbmnt
4992
4993	set smb_redir_0 ""
4994	set smb_mounts ""
4995	if {$use_smbmnt} {
4996		set l2 [get_smb_redir]
4997		set smb_redir_0 [lindex $l2 0]
4998		set smb_redir_0 [string trim $smb_redir_0]
4999		set smb_mounts  [lindex $l2 1]
5000	}
5001}
5002
5003proc mytmp {tmp} {
5004	global is_windows mktemp env
5005
5006	if {$is_windows} {
5007		return $tmp
5008	}
5009
5010	if {! [info exists mktemp]} {
5011		set mktemp ""
5012		foreach dir {/bin /usr/bin /usr/local/bin} {
5013			if [file exists "$dir/mktemp"] {
5014				set mktemp "$dir/mktemp"
5015				break
5016			}
5017		}
5018	}
5019	if {$mktemp != ""} {
5020		set tmp2 ""
5021		catch {set tmp2 [exec $mktemp "$tmp.XXXXXX"]}
5022		if [file exists $tmp2] {
5023			if [info exists env(DEBUG_MKTEMP)] {
5024				puts stderr "mytmp: $tmp2"
5025			}
5026			return $tmp2
5027		}
5028	}
5029	catch {exec rm -f $tmp}
5030	catch {file delete $tmp}
5031	if [file exists $tmp] {
5032		puts stderr "tmp file still exists: $tmp"
5033		exit 1
5034	}
5035	catch {exec touch $tmp}
5036	catch {exec chmod 600 $tmp}
5037	if [info exists env(DEBUG_MKTEMP)] {
5038		puts stderr "mytmp: $tmp"
5039	}
5040	return $tmp
5041}
5042
5043proc darwin_terminal_cmd {{title ""} {cmd ""} {bg 0}} {
5044	global darwin_terminal
5045
5046	set tries ""
5047	lappend tries "/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal"
5048
5049	if {! [info exists darwin_terminal]} {
5050		foreach try $tries {
5051			if [file exists $try] {
5052				if [file executable $try] {
5053					set darwin_terminal $try
5054					break
5055				}
5056			}
5057		}
5058		if {! [info exists darwin_terminal]} {
5059			set fh ""
5060			catch {set fh [open "| find /Applications -type f -name Terminal" "r"]}
5061			if {$fh != ""} {
5062				while {[gets $fh line] > -1} {
5063					if {! [file exists $line]} {
5064						continue
5065					}
5066					if {[file isdirectory $line]} {
5067						continue
5068					}
5069					if {! [regexp {/Terminal$} $line]} {
5070						continue
5071					}
5072					if {! [file executable $line]} {
5073						continue
5074					}
5075					set darwin_terminal $line
5076					break
5077				}
5078				close $fh
5079			}
5080		}
5081	}
5082	if {! [info exists darwin_terminal]} {
5083		raise .
5084		tk_messageBox -type ok -icon error -message "Cannot find Darwin Terminal program." -title "Cannot find Terminal program"
5085		mac_raise
5086		return
5087	}
5088
5089	global darwin_terminal_cnt
5090	set tmp /tmp/darwin_terminal_cmd.[tpid]
5091	if {! [info exists darwin_terminal_cnt]} {
5092		set darwin_terminal_cnt 0
5093	}
5094	incr darwin_terminal_cnt
5095	append tmp ".$darwin_terminal_cnt"
5096	set tmp [mytmp $tmp]
5097
5098	set fh ""
5099	catch {set fh [open $tmp w 0755]}
5100	catch {[exec chmod 755 $tmp]}
5101	if {$fh == ""} {
5102		raise .
5103		tk_messageBox -type ok -icon error -message "Cannot open temporary file: $tmp" -title "Cannot open file"
5104		mac_raise
5105		return
5106	}
5107	global env
5108	puts $fh "#!/bin/sh"
5109	puts $fh "PATH=$env(PATH)"
5110	puts $fh "export PATH"
5111	puts $fh "tmp=$tmp"
5112	puts $fh "sleep 1"
5113	puts $fh {if [ "X$DDDBG" != "X" ]; then ps www; fi}
5114	puts $fh {termpid=`ps www | grep -w Terminal | grep $tmp | grep -v grep | awk '{print $1}' | sort -n | tail -1`}
5115	puts $fh {echo try-1: termpid=$termpid mypid=$$}
5116	puts $fh {if [ "X$termpid" = "X" ]; then}
5117	puts $fh {	termpid=`ps www | grep -w Terminal | grep -v grep | awk '{print $1}' | sort -n | tail -1`}
5118	puts $fh {	echo try-2: termpid=$termpid mypid=$$}
5119	puts $fh {fi}
5120	puts $fh {if [ "X$termpid" = "X" ]; then}
5121	puts $fh {	termpid=`ps wwwwaux | grep -w Terminal | grep $tmp | grep -v grep | awk '{print $2}' | sort -n | tail -1`}
5122	puts $fh {	echo try-3: termpid=$termpid mypid=$$}
5123	puts $fh {fi}
5124	puts $fh {if [ "X$termpid" = "X" ]; then}
5125	puts $fh {	termpid=$$}
5126	puts $fh {	echo termpid-find-fail: termpid=$termpid mypid=$$}
5127	puts $fh {fi}
5128	puts $fh {trap "rm -f $tmp; kill -TERM $termpid; kill -TERM $mypid; kill -KILL $mypid; exit 0" 0 2 15}
5129	puts $fh {osascript -e 'tell application "Terminal" to activate' >/dev/null 2>&1 &}
5130	puts $fh "$cmd"
5131	puts $fh "sleep 1"
5132	puts $fh {rm -f $tmp}
5133	puts $fh {kill -TERM $termpid}
5134	puts $fh {kill -TERM $mypid}
5135	puts $fh {kill -KILL $mypid}
5136	puts $fh "exit 0"
5137	close $fh
5138	if {$bg} {
5139		catch {exec $darwin_terminal $tmp &}
5140	} else {
5141		catch {exec $darwin_terminal $tmp}
5142	}
5143}
5144
5145proc unix_terminal_cmd {{geometry "+100+100"} {title "xterm-command"} {cmd "echo test"} {bg 0} {xrm1 ""} {xrm2 ""} {xrm3 ""}} {
5146	global uname env
5147	if {$uname == "Darwin"} {
5148		global env
5149		set doX  0;
5150		if {! $doX} {
5151			darwin_terminal_cmd $title $cmd $bg
5152			return
5153		}
5154	}
5155
5156	global checked_for_xterm
5157	if {![info exists checked_for_xterm]} {
5158		set p ""
5159		set r [catch {set p [exec /bin/sh -c {type xterm}]}]
5160		set checked_for_xterm 1
5161		if {$r != 0} {
5162			set p [exec /bin/sh -c {type xterm 2>&1; exit 0}]
5163			set txt "Problem finding the 'xterm' command:\n\n$p\n\n"
5164			append txt "Perhaps you need to install a package containing 'xterm'  (Sigh...)\n\n"
5165			fetch_dialog $txt "xterm" "xterm" 0 [line_count $txt]
5166			update
5167			after 1000
5168			catch {tkwait window .fetch}
5169			update
5170		}
5171	}
5172
5173	if [info exists env(SSVNC_XTERM_REPLACEMENT)] {
5174		set tcmd $env(SSVNC_XTERM_REPLACEMENT)
5175		if {$tcmd != ""} {
5176			regsub -all {%GEOMETRY} $tcmd $geometry tcmd
5177			regsub -all {%TITLE} $tcmd $title tcmd
5178
5179			set tmp1 /tmp/xterm_replacement1.[tpid]
5180			set tmp1 [mytmp $tmp1]
5181			set fh1 ""
5182			catch {set fh1 [open $tmp1 "w"]}
5183
5184			set tmp2 /tmp/xterm_replacement2.[tpid]
5185			set tmp2 [mytmp $tmp2]
5186			set fh2 ""
5187			catch {set fh2 [open $tmp2 "w"]}
5188			if {$fh1 != "" && $fh2 != ""} {
5189				puts $fh1 "#!/bin/sh";
5190				puts $fh1 "$cmd"
5191				puts $fh1 "rm -f $tmp1"
5192				close $fh1
5193				catch {exec chmod 755 $tmp1}
5194				puts $fh2 "#!/bin/sh"
5195				puts $fh2 "$tcmd $tmp1"
5196				puts $fh2 "rm -f $tmp2"
5197				close $fh2
5198				catch {exec chmod 755 $tmp2}
5199				if {$bg} {
5200					exec $tmp2 2>@stdout &
5201				} else {
5202					exec $tmp2 2>@stdout
5203				}
5204				return
5205			}
5206			catch {close $fh1}
5207			catch {close $fh2}
5208		}
5209	}
5210
5211	if {$bg} {
5212		if {$xrm1 == ""} {
5213			exec xterm -sb -sl 2000 -geometry "$geometry" -title "$title" -e sh -c "$cmd" 2>@stdout &
5214		} else {
5215			exec xterm -sb -sl 2000 -geometry "$geometry" -title "$title" -xrm "$xrm1" -xrm "$xrm2" -xrm "$xrm3" -e sh -c "$cmd" 2>@stdout &
5216		}
5217	} else {
5218		if {$xrm1 == ""} {
5219			exec xterm -sb -sl 2000 -geometry "$geometry" -title "$title" -e sh -c "$cmd" 2>@stdout
5220		} else {
5221			exec xterm -sb -sl 2000 -geometry "$geometry" -title "$title" -xrm "$xrm1" -xrm "$xrm2" -xrm "$xrm3" -e sh -c "$cmd" 2>@stdout
5222		}
5223	}
5224}
5225
5226proc xterm_center_geometry {} {
5227	set sh [winfo screenheight .]
5228	set sw [winfo screenwidth .]
5229	set gw 500
5230	set gh 300
5231	set x [expr $sw/2 - $gw/2]
5232	set y [expr $sh/2 - $gh/2]
5233	if {$x < 0} {
5234		set x 10
5235	}
5236	if {$y < 0} {
5237		set y 10
5238	}
5239
5240	return "+$x+$y"
5241}
5242
5243proc smbmnt_wait {tee} {
5244	if {$tee != ""} {
5245		set start [clock seconds]
5246		set cut 30
5247		while {1} {
5248			set now [clock seconds]
5249			if {$now > $start + $cut} {
5250				break;
5251			}
5252			if [file exists $tee] {
5253				set sz 0
5254				catch {set sz [file size $tee]}
5255				if {$sz > 50} {
5256					set cut 50
5257				}
5258			}
5259			set g ""
5260			catch {set g [exec grep main-vnc-helper-finished $tee]}
5261			if [regexp {main-vnc-helper-finished} $g] {
5262				break
5263			}
5264			after 1000
5265		}
5266		catch {file delete $tee}
5267	} else {
5268		global smb_su_mode
5269		if {$smb_su_mode == "su"} {
5270			after 15000
5271		} elseif {$smb_su_mode == "sudo"} {
5272			after 10000
5273		}
5274	}
5275}
5276
5277proc do_unix_pre {tag proxy hp pk_hp}  {
5278	global env smb_redir_0 use_smbmnt
5279	global did_port_knock
5280
5281	set setup_cmds [ugly_setup_scripts pre $tag]
5282	set c "ss_vncviewer -ssh"
5283
5284	if {$proxy == ""} {
5285		set pxy $hp
5286		regsub {:[0-9][0-9]*$} $pxy "" pxy
5287		set c "$c -proxy '$pxy'"
5288	} else {
5289		set c "$c -proxy '$proxy'"
5290	}
5291
5292	if {$setup_cmds != ""} {
5293		set env(SS_VNCVIEWER_SSH_CMD) "$setup_cmds sleep 10"
5294		set env(SS_VNCVIEWER_SSH_ONLY) 1
5295		if {$smb_redir_0 != ""} {
5296			set c "$c -sshargs '$smb_redir_0'"
5297		}
5298
5299		if {! [do_port_knock $pk_hp start]} {
5300			return
5301		}
5302		set did_port_knock 1
5303
5304		if {$use_smbmnt} {
5305			set title "SSL/SSH VNC Viewer $hp -- SMB MOUNTS"
5306		} else {
5307			set title "SSL/SSH VNC Viewer $hp -- Pre Commands"
5308		}
5309
5310		set tee ""
5311		if {$use_smbmnt} {
5312			set tee $env(SSVNC_HOME)
5313			append tee "/.tee-etv$tag"
5314			set fh ""
5315			catch {set fh [open $tee "w"]}
5316			if {$fh == ""} {
5317				set tee ""
5318			} else {
5319				close $fh
5320				set c "$c | tee $tee"
5321			}
5322		}
5323
5324		unix_terminal_cmd "80x25+100+100" "$title" "set -xv; $c" 1
5325
5326		set env(SS_VNCVIEWER_SSH_CMD) ""
5327		set env(SS_VNCVIEWER_SSH_ONLY) ""
5328
5329		if {$use_smbmnt} {
5330			smbmnt_wait $tee
5331		} else {
5332			after 2000
5333		}
5334	}
5335}
5336proc init_vncdisplay {} {
5337	global vncdisplay vncproxy remote_ssh_cmd
5338	set vncdisplay [string trim $vncdisplay]
5339
5340	if {$vncdisplay == ""} {
5341		set vncproxy ""
5342		set remote_ssh_cmd ""
5343		return
5344	}
5345
5346	set hpnew  [get_ssh_hp $vncdisplay]
5347	set proxy  [get_ssh_proxy $vncdisplay]
5348	set sshcmd [get_ssh_cmd $vncdisplay]
5349
5350	set vncdisplay $hpnew
5351	set vncproxy $proxy
5352	set remote_ssh_cmd $sshcmd
5353
5354	global ssh_only ts_only
5355	if {$sshcmd != "" || $ssh_only || $ts_only} {
5356		global use_ssl use_ssh use_sshssl
5357		set use_ssl 0
5358		if {! $use_ssh && ! $use_sshssl} {
5359			set use_ssh 1
5360		}
5361	}
5362	# ssl_ssh_adjust will be called.
5363}
5364
5365proc get_vncdisplay {} {
5366	global vncdisplay vncproxy remote_ssh_cmd
5367	set vncdisplay [string trim $vncdisplay]
5368
5369	set t $vncdisplay
5370	regsub {[ \t]*cmd=.*$} $t "" t
5371	set t [string trim $t]
5372
5373	set str ""
5374	if [regexp {[ \t]} $t] {
5375		set str $t
5376	} else {
5377		if {$vncproxy != "" && $t == ""} {
5378			set str "--nohost-- $vncproxy"
5379		} else {
5380			set str "$t $vncproxy"
5381		}
5382	}
5383	if [regexp {cmd=.*$} $vncdisplay match] {
5384		if {$str == ""} {
5385			set str "--nohost--"
5386		}
5387		set str "$str $match"
5388	} else {
5389		if {$remote_ssh_cmd != ""} {
5390			if {$str == ""} {
5391				set str "--nohost--"
5392			}
5393			set str "$str cmd=$remote_ssh_cmd"
5394		}
5395	}
5396	set str [string trim $str]
5397	return $str
5398}
5399
5400proc port_knock_only {hp {mode KNOCK}} {
5401	if {$hp == ""} {
5402		set hp [get_vncdisplay]
5403		if {$hp == ""} {
5404			mesg "No host port found"
5405			bell
5406			return
5407		}
5408	}
5409	set hpnew  [get_ssh_hp $hp]
5410	set proxy  [get_ssh_proxy $hp]
5411	set sshcmd [get_ssh_cmd $hp]
5412	set hp $hpnew
5413
5414	set pk_hp ""
5415	if {$proxy != ""} {
5416		set pk_hp $proxy
5417	}
5418	if {$pk_hp == ""} {
5419		set pk_hp $hp
5420	}
5421	if {$mode == "KNOCK"} {
5422		do_port_knock $pk_hp start
5423	} elseif {$mode == "FINISH"} {
5424		do_port_knock $pk_hp finish
5425	}
5426}
5427
5428proc direct_connect_msg {} {
5429	set msg ""
5430	global env
5431	globalize
5432	if {$use_sshssl} {
5433		append msg "  - SSH + SSL tunnelling\n"
5434	} elseif {$use_ssh} {
5435		append msg "  - SSH tunnelling\n"
5436	} else {
5437		append msg "  - SSL tunnelling\n"
5438	}
5439	if [info exists env(SSVNC_NO_ENC_WARN)] {
5440		set msg ""
5441	}
5442	if {$use_smbmnt} {
5443		append msg "  - SMB Mount Port Redirection\n"
5444	}
5445	if {$use_sound} {
5446		append msg "  - ESD Sound Port Redirection\n"
5447	}
5448	if {$use_cups} {
5449		append msg "  - CUPS Port Redirection\n"
5450	}
5451	if {$additional_port_redirs} {
5452		append msg "  - Additional Port Redirections\n"
5453	}
5454	if {$mycert != "" || $svcert != "" || $crtdir != ""} {
5455		append msg "  - SSL certificate authentication\n"
5456	}
5457	if {$msg != ""} {
5458		set msg "Direct connect via vnc://hostname\nThe following options will be disabled:\n\n$msg"
5459		raise .
5460		tk_messageBox -type ok -icon info -message $msg
5461	}
5462}
5463
5464proc fetch_cert {save} {
5465	global env vncdisplay is_windows
5466	set hp [get_vncdisplay]
5467
5468	global vencrypt_detected
5469	set vencrypt_detected ""
5470
5471	global use_listen
5472	if {$use_listen} {
5473		if {$is_windows} {
5474			mesg "Fetch Cert not enabled for Reverse Connections"
5475			bell
5476			catch {raise .}
5477			mac_raise
5478			return
5479		}
5480		toplev .fcr
5481		global help_font
5482		wm title .fcr "Fetch Cert for Reverse Connections"
5483		global fcr_result
5484		set fcr_result 0
5485		eval text .fcr.t -width 55 -height 17 $help_font
5486		.fcr.t insert end {
5487   In Reverse VNC Connections (-LISTEN) mode, the
5488   Fetch Cert operation requires that the Remote
5489   VNC Server makes an initial connection NOW so
5490   we can collect its SSL Certificate.  Note that
5491   this method does not work for VeNCrypt servers.
5492   (If there are problems Fetching, one can always
5493   copy and import the Cert file manually.)
5494
5495   Do you want to Continue with this operation?
5496   If so, press "Continue" and Then instruct the
5497   remote VNC Server to make a Reverse Connection
5498   to us.
5499
5500   Otherwise, press "Cancel" to cancel the Fetch
5501   Cert operation.
5502}
5503
5504		button .fcr.cancel   -text Cancel   -command {set fcr_result 0; destroy .fcr}
5505		button .fcr.continue -text Continue -command {set fcr_result 1; destroy .fcr}
5506		button .fcr.continu2 -text Continue -command {set fcr_result 1; destroy .fcr}
5507		global uname
5508		if {$uname == "Darwin"} {
5509			pack .fcr.t .fcr.continu2 .fcr.continue .fcr.cancel -side top -fill x
5510
5511		} else {
5512			pack .fcr.t .fcr.continue .fcr.cancel -side top -fill x
5513		}
5514		center_win .fcr
5515
5516		tkwait window .fcr
5517		update
5518		after 50
5519
5520		if {$fcr_result != 1}  {
5521			return
5522		}
5523		update idletasks
5524		after 50
5525	}
5526
5527	regsub {[ 	]*cmd=.*$} $hp "" tt
5528	if {[regexp {^[ 	]*$} $tt]} {
5529		mesg "No host:disp supplied."
5530		bell
5531		catch {raise .}
5532		mac_raise
5533		return
5534	}
5535	if {[regexp -- {--nohost--} $tt]} {
5536		mesg "No host:disp supplied."
5537		bell
5538		catch {raise .}
5539		mac_raise
5540		return
5541	}
5542	if {! [regexp ":" $hp]} {
5543		if {! [regexp {cmd=} $hp]} {
5544			append hp ":0"
5545		}
5546	}
5547	set hpnew  [get_ssh_hp $hp]
5548	set proxy  [get_ssh_proxy $hp]
5549
5550
5551	set pstr 1
5552	mesg "Fetching $hpnew Cert..."
5553	global cert_text
5554	set cert_text ""
5555	.f4.getcert configure -state disabled
5556	update
5557	if {! $is_windows} {
5558		catch {set cert_text [fetch_cert_unix $hp]}
5559	} else {
5560		set cert_text [fetch_cert_windows $hp]
5561	}
5562
5563	if [info exists env(CERTDBG)] {puts "\nFetch-0-\n$cert_text"}
5564
5565	set vencrypt 0
5566	set anondh 0
5567	if {![regexp {BEGIN CERTIFICATE} $cert_text]} {
5568		if [regexp {CONNECTED} $cert_text] {
5569			set m 0
5570			if {![regexp -nocase {GET_SERVER_HELLO} $cert_text]} {
5571				set m 1
5572			}
5573			if [regexp -nocase -line {GET_SERVER_HELLO.*unknown protocol} $cert_text] {
5574				set m 1
5575			}
5576			if {![regexp -nocase {show_cert: SSL_connect failed} $cert_text]} {
5577				set m 1
5578			}
5579			if {!$m && $is_windows} {
5580				if [regexp -nocase {write:errno} $cert_text] {
5581					if [regexp -nocase {no peer certificate} $cert_text] {
5582						set m 1
5583					}
5584				}
5585			}
5586			if {$m} {
5587				# suspect VeNCrypt or ANONTLS plaintext RFB
5588				set cert_text ""
5589				set vencrypt 1
5590				incr pstr
5591				mesg "#${pstr} Fetching $hpnew Cert... $vencrypt/$anondh"
5592				if {! $is_windows} {
5593					catch {set cert_text [fetch_cert_unix    $hp $vencrypt $anondh]}
5594				} else {
5595					after 600
5596					catch {set cert_text [fetch_cert_windows $hp $vencrypt $anondh]}
5597				}
5598	if [info exists env(CERTDBG)] {puts "\nFetch-1-\n$cert_text"}
5599			}
5600		}
5601	}
5602	if {![regexp {BEGIN CERTIFICATE} $cert_text]} {
5603		if [regexp {CONNECTED} $cert_text] {
5604			set m 0
5605			if [regexp -nocase -line {error.*handshake failure} $cert_text] {
5606				set m 1
5607			}
5608			if [regexp -nocase -line {error.*unknown protocol} $cert_text] {
5609				set m 1
5610			}
5611			if {![regexp -nocase {show_cert: SSL_connect failed} $cert_text]} {
5612				set m 1
5613			}
5614			if {!$m && $is_windows} {
5615				if [regexp -nocase {no peer certificate} $cert_text] {
5616					set m 1
5617				}
5618			}
5619			if {$m} {
5620				# suspect Anonymous Diffie Hellman
5621				set cert_text ""
5622				set anondh 1
5623				incr pstr
5624				mesg "#${pstr} Fetching $hpnew Cert... $vencrypt/$anondh"
5625				if {! $is_windows} {
5626					catch {set cert_text [fetch_cert_unix    $hp $vencrypt $anondh]}
5627				} else {
5628					after 600
5629					catch {set cert_text [fetch_cert_windows $hp $vencrypt $anondh]}
5630				}
5631	if [info exists env(CERTDBG)] {puts "\nFetch-2-\n$cert_text"}
5632			}
5633		}
5634	}
5635	if {![regexp {BEGIN CERTIFICATE} $cert_text]} {
5636		if [regexp {CONNECTED} $cert_text] {
5637			if {[regexp -nocase -line {cipher.*ADH} $cert_text]} {
5638				# it is Anonymous Diffie Hellman
5639				mesg "WARNING: Anonymous Diffie Hellman Server detected (NO CERT)"
5640				after 300
5641				.f4.getcert configure -state normal
5642				return $cert_text
5643			} else {
5644				global vencrypt_detected
5645				set vencrypt_detected ""
5646			}
5647		}
5648	}
5649
5650	global vencrypt_detected server_vencrypt
5651	if {$vencrypt_detected != "" && !$server_vencrypt} {
5652		mesg "VeNCrypt or ANONTLS server detected."
5653		after 600
5654	}
5655
5656	.f4.getcert configure -state normal
5657	mesg "Fetched $hpnew Cert"
5658
5659	set n 47
5660	set ok 1
5661	if {$cert_text == ""} {
5662		set cert_text "An Error occurred in fetching SSL Certificate from $hp"
5663		set ok 0
5664		set n 4
5665	} elseif {! [regexp {BEGIN CERTIFICATE} $cert_text]} {
5666		set cert_text "An Error occurred in fetching $hp\n\n$cert_text"
5667		set n [line_count $cert_text 1]
5668		set ok 0
5669	} else {
5670		if [regexp -- {-----BEGIN SSL SESSION PARAMETERS-----} $cert_text] {
5671			set new ""
5672			set off 0
5673			foreach line [split $cert_text "\n"] {
5674				if [regexp -- {RFB 00} $line] {
5675					continue
5676				}
5677				if [regexp -- {Using default temp} $line] {
5678					continue
5679				}
5680				if [regexp -- {-----BEGIN SSL SESSION PARAMETERS-----} $line] {
5681					set off 1
5682				}
5683				if [regexp -- {-----END SSL SESSION PARAMETERS-----} $line] {
5684					set off 0
5685					continue
5686				}
5687				if {$off} {
5688					continue;
5689				}
5690				append new "$line\n"
5691			}
5692			if [regexp -- {-----BEGIN CERTIFICATE-----} $new] {
5693				set cert_text $new
5694			}
5695		}
5696		set text ""
5697		set on 0
5698		set subject ""
5699		set curr_subject ""
5700		set chain_n -1
5701		set chain(__empty__) ""
5702		foreach line [split $cert_text "\n"] {
5703			if [regexp -- {-----BEGIN CERTIFICATE-----} $line] {
5704				incr on
5705			}
5706			if {$chain_n < -1} {
5707				;
5708			} elseif [regexp {^ *([0-9]) *s:(.*/[A-Z][A-Z]*=.*$)} $line m cn sb] {
5709				set cn [string trim $cn]
5710				set sb [string trim $sb]
5711				#puts cn=$cn
5712				#puts sb=$sb
5713				if {$subject == ""} {
5714					set subject $sb
5715				}
5716				if {$cn > $chain_n} {
5717					set chain_n $cn
5718					set curr_subject $sb
5719				} else {
5720					set chain_n -2
5721				}
5722			} elseif [regexp {^ *i:(.*/[A-Z][A-Z]*=.*$)} $line m is] {
5723				set is [string trim $is]
5724				#puts is=$is
5725				if {$curr_subject != ""} {
5726					set chain($curr_subject) $is
5727				}
5728			}
5729			if {$on != 1} {
5730				continue;
5731			}
5732			append text "$line\n"
5733			if [regexp -- {-----END CERTIFICATE-----} $line] {
5734				set on 2
5735			}
5736		}
5737		set chain_str "subject: not-known\n"
5738		set curr_subject $subject
5739		set self_signed 0
5740		set top_issuer ""
5741		for {set i 0} {$i < 10} {incr i} {
5742			if {$curr_subject != ""} {
5743				if {$i == 0} {
5744					set chain_str "- subject: $curr_subject\n\n"
5745				} else {
5746					set chain_str "${chain_str}- issuer$i: $curr_subject\n\n"
5747					set top_issuer $curr_subject;
5748				}
5749				if {![info exists chain($curr_subject)]} {
5750					break
5751				} elseif {$chain($curr_subject) == ""} {
5752					break
5753				} elseif {$curr_subject == $chain($curr_subject)} {
5754					set j [expr $i + 1]
5755					set chain_str "${chain_str}- issuer$j: $curr_subject\n\n"
5756					set top_issuer $curr_subject;
5757					if {$i == 0} {
5758						set self_signed 1
5759					}
5760					break;
5761				}
5762				set curr_subject $chain($curr_subject)
5763			}
5764		}
5765		set chain_str "${chain_str}INFO: SELF_SIGNED=$self_signed\n\n"
5766		if {$self_signed} {
5767			set chain_str "${chain_str}INFO: Certificate is Self-Signed.\n"
5768			set chain_str "${chain_str}INFO: It will successfully authenticate when used as a ServerCert or Accepted-Cert.\n"
5769			set chain_str "${chain_str}INFO: Be sure to check carefully that you trust this certificate before saving it.\n"
5770		} else {
5771			set chain_str "${chain_str}INFO: Certificate is signed by a Certificate Authority (CA).\n"
5772			set chain_str "${chain_str}INFO: It *WILL NOT* successfully authenticate when used as a ServerCert or Accepted-Cert.\n"
5773			set chain_str "${chain_str}INFO: You need to Obtain and Save the CA's Certificate (issuer) instead"
5774			if {$top_issuer != ""} {
5775				set chain_str "${chain_str}:\nINFO: CA: $top_issuer\n"
5776			} else {
5777				set chain_str "${chain_str}.\n"
5778			}
5779		}
5780		#puts "\n$chain_str\n"
5781
5782		global is_windows
5783		set tmp "/tmp/cert.hsh.[tpid]"
5784		set tmp [mytmp $tmp]
5785		if {$is_windows} {
5786			# VF
5787			set tmp cert.hsh
5788		}
5789		set fh ""
5790		catch {set fh [open $tmp "w"]}
5791		if {$fh != ""} {
5792			puts $fh $text
5793			close $fh
5794			set info ""
5795			catch {set info [get_x509_info $tmp]}
5796			catch {file delete $tmp}
5797			if [regexp -nocase {MD5 Finger[^\n]*} $info mvar] {
5798				set cert_text "$mvar\n\n$cert_text"
5799			}
5800			if [regexp -nocase {SHA. Finger[^\n]*} $info mvar] {
5801				set cert_text "$mvar\n\n$cert_text"
5802			}
5803			set cert_text "$cert_text\n\n----------------------------------\nOutput of  openssl x509 -text -fingerprint:\n\n$info"
5804		}
5805		set cert_text "==== SSL Certificate from $hp ====\n\n$chain_str\n$cert_text"
5806	}
5807
5808	if {! $save} {
5809		return $cert_text
5810	}
5811
5812	fetch_dialog $cert_text $hp $hpnew $ok $n
5813}
5814
5815proc skip_non_self_signed {w hp} {
5816	set msg "Certificate from $hp is not Self-Signed, it was signed by a Certificate Authority (CA).  Saving it does not make sense because it cannot be used to authenticate anything.  You need to Obtain and Save the CA Certificate instead.  Save it anyway?"
5817	set reply [tk_messageBox -type okcancel -default cancel -parent $w -icon warning -message $msg -title "CA Signed Certificate"]
5818	if {$reply == "cancel"} {
5819		return 1
5820	} else {
5821		return 0
5822	}
5823}
5824
5825proc fetch_dialog {cert_text hp hpnew ok n} {
5826	toplev .fetch
5827
5828	if [small_height] {
5829		set n 28
5830	}
5831
5832	scroll_text_dismiss .fetch.f 90 $n
5833
5834	if {$ok} {
5835		set ss 0
5836		if [regexp {INFO: SELF_SIGNED=1} $cert_text] {
5837			button .fetch.save -text Save -command "destroy .fetch; save_cert {$hpnew}"
5838			set ss 1
5839		} else {
5840			button .fetch.save -text Save -command "if \[skip_non_self_signed .fetch {$hpnew}\] {return} else {destroy .fetch; save_cert {$hpnew}}"
5841			set ss 0
5842		}
5843		button .fetch.help -text Help -command "help_fetch_cert $ss"
5844		pack .fetch.help .fetch.save -side bottom -fill x
5845		.fetch.d configure -text "Cancel"
5846	}
5847
5848	center_win .fetch
5849	wm title .fetch "$hp Certificate"
5850
5851	.fetch.f.t insert end $cert_text
5852	jiggle_text .fetch.f.t
5853}
5854
5855
5856proc host_part {hp} {
5857	regsub {^ *}  $hp "" hp
5858	regsub { .*$} $hp "" hp
5859	if [regexp {^[0-9][0-9]*$} $hp] {
5860		return ""
5861	}
5862	set h $hp
5863	regsub {:[0-9][0-9]*$} $hp "" h
5864	return $h
5865}
5866
5867proc port_part {hp} {
5868	regsub { .*$} $hp "" hp
5869	set p ""
5870	if [regexp {:([0-9][0-9]*)$} $hp m val] {
5871		set p $val
5872	}
5873	return $p
5874}
5875
5876proc get_vencrypt_proxy {hpnew} {
5877	if [regexp -nocase {^vnc://} $hpnew] {
5878		return ""
5879	}
5880	set hpnew  [get_ssh_hp $hpnew]
5881	regsub -nocase {^[a-z0-9+]*://} $hpnew "" hpnew
5882	set h [host_part $hpnew]
5883	set p [port_part $hpnew]
5884
5885	if {$p == ""} {
5886		# might not matter, i.e. SSH+SSL only...
5887		set p 5900
5888	}
5889	set hp2 $h
5890	if {$p < 0} {
5891		set hp2 "$hp2:[expr - $p]"
5892	} elseif {$p < 200} {
5893		set hp2 "$hp2:[expr $p + 5900]"
5894	} else {
5895		set hp2 "$hp2:$p"
5896	}
5897	return "vencrypt://$hp2"
5898}
5899
5900proc fetch_cert_unix {hp {vencrypt 0} {anondh 0}} {
5901	global use_listen
5902
5903	set hpnew  [get_ssh_hp $hp]
5904	set proxy  [get_ssh_proxy $hp]
5905
5906	if {$vencrypt} {
5907		global vencrypt_detected
5908		set vencrypt_detected [get_vencrypt_proxy $hpnew]
5909		if {$proxy != ""} {
5910			set proxy "$proxy,$vencrypt_detected"
5911		} else {
5912			set proxy $vencrypt_detected
5913		}
5914	}
5915
5916	set cmd [list ss_vncviewer]
5917	if {$anondh} {
5918		lappend cmd "-anondh"
5919	}
5920	if {$proxy != ""} {
5921		lappend cmd "-proxy"
5922		lappend cmd $proxy
5923	}
5924	if {$use_listen} {
5925		lappend cmd "-listen"
5926	}
5927	lappend cmd "-showcert"
5928	lappend cmd $hpnew
5929
5930	if {$proxy != ""} {
5931		lappend cmd "2>/dev/null"
5932	}
5933	global env
5934	if [info exists env(CERTDBG)] {puts "\nFetch-cmd: $cmd"}
5935	set env(SSVNC_SHOWCERT_EXIT_0) 1
5936
5937	return [eval exec $cmd]
5938}
5939
5940proc win_nslookup {host} {
5941	global win_nslookup_cache
5942	if [info exists win_nslookup_cache($host)] {
5943		return $win_nslookup_cache($host)
5944	}
5945	if [regexp -nocase {[^a-z0-9:._-]} $host]  {
5946		set win_nslookup_cache($host) "invalid"
5947		return $win_nslookup_cache($host)
5948	}
5949	if [regexp {^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$} $host] {
5950		set win_nslookup_cache($host) $host
5951		return $win_nslookup_cache($host)
5952	}
5953	if [regexp -nocase {^[a-f0-9]*:[a-f0-9:]*:[a-f0-9:]*$} $host] {
5954		set win_nslookup_cache($host) $host
5955		return $win_nslookup_cache($host)
5956	}
5957	set nsout ""
5958	catch {set nsout [exec nslookup $host]}
5959	if {$nsout == "" || [regexp -nocase {server failed} $nsout]} {
5960		after 250
5961		set nsout ""
5962		catch {set nsout [exec nslookup $host]}
5963	}
5964	if {$nsout == "" || [regexp -nocase {server failed} $nsout]} {
5965		set win_nslookup_cache($host) "unknown"
5966		return $win_nslookup_cache($host)
5967	}
5968	regsub -all {Server:[^\n]*\nAddress:[^\n]*} $nsout "" nsout
5969	regsub {^.*Name:} $nsout "" nsout
5970	if [regexp {Address:[ \t]*([^\n]+)} $nsout mv addr] {
5971		set addr [string trim $addr]
5972		if {$addr != ""} {
5973			set win_nslookup_cache($host) $addr
5974			return $win_nslookup_cache($host)
5975		}
5976	}
5977	set win_nslookup_cache($host) "unknown"
5978	return $win_nslookup_cache($host)
5979}
5980
5981proc win_ipv4 {host} {
5982	global win_localhost
5983	set ip [win_nslookup $host];
5984	if [regexp {^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$} $ip] {
5985		return 1
5986	}
5987	return 0
5988}
5989
5990proc ipv6_proxy {proxy host port} {
5991	global is_windows win_localhost have_ipv6
5992
5993	if {!$have_ipv6} {
5994		return [list $proxy $host $port ""]
5995	} elseif {!$is_windows} {
5996		return [list $proxy $host $port ""]
5997	} else {
5998		set h0 ""
5999		set p0 ""
6000		set port3 ""
6001		set ipv6_pid ""
6002		set proxy0 $proxy
6003		if {$proxy == ""} {
6004			if [win_ipv4 $host] {
6005				return [list $proxy $host $port ""]
6006			}
6007			set port3 [rand_port]
6008			set h0 $host
6009			set p0 $port
6010			set host $win_localhost
6011			set port $port3
6012		} else {
6013			set parts [split $proxy ","]
6014			set n [llength $parts]
6015			for {set i 0} {$i < $n} {incr i} {
6016				set part [lindex $parts $i]
6017				set prefix ""
6018				set repeater 0
6019				regexp -nocase {^[a-z0-9+]*://} $part prefix
6020				regsub -nocase {^[a-z0-9+]*://}	$part "" part
6021				if [regexp {^repeater://} $prefix] {
6022					regsub {\+.*$} $part "" part
6023					if {![regexp {:([0-9][0-9]*)$} $part]} {
6024						set part "$part:5900"
6025					}
6026				}
6027				set modit 0
6028				set h1 ""
6029				set p1 ""
6030				if [regexp {^(.*):([0-9][0-9]*)$} $part mvar h1 p1] {
6031					if {$h1 == "localhost" || $h1 == $win_localhost} {
6032						continue
6033					} elseif [win_ipv4 $h1] {
6034						break
6035					}
6036					set modit 1
6037				} else {
6038					break
6039				}
6040				if {$modit} {
6041					set port3 [rand_port]
6042					set h0 $h1
6043					set p0 $p1
6044					lset parts $i "$prefix$win_localhost:$port3"
6045					break
6046				}
6047			}
6048			if {$h0 != "" && $p0 != "" && $port3 != ""} {
6049				set proxy [join $parts ","]
6050				#mesg "Reset proxy: $proxy"; after 3000
6051			}
6052		}
6053		if {$h0 != "" && $p0 != "" && $port3 != ""} {
6054			mesg "Starting IPV6 helper on port $port3 ..."
6055			set ipv6_pid [exec relay6.exe $port3 "$h0" "$p0" /b:$win_localhost &]
6056			after 400
6057			#mesg "r6 $port3 $h0 $p0"; after 3000
6058		}
6059		return [list $proxy $host $port $ipv6_pid]
6060	}
6061}
6062
6063proc fetch_cert_windows {hp {vencrypt 0} {anondh 0}} {
6064	global have_ipv6
6065
6066	regsub {^vnc.*://} $hp "" hp
6067
6068	set hpnew  [get_ssh_hp $hp]
6069	set proxy  [get_ssh_proxy $hp]
6070
6071	if {$vencrypt} {
6072		global vencrypt_detected
6073		set vencrypt_detected [get_vencrypt_proxy $hpnew]
6074		if {$proxy != ""} {
6075			set proxy "$proxy,$vencrypt_detected"
6076		} else {
6077			set proxy $vencrypt_detected
6078		}
6079	}
6080
6081	set host [host_part $hpnew]
6082
6083	global win_localhost
6084
6085	if {$host == ""} {
6086		set host $win_localhost
6087	}
6088
6089	if [regexp {^.*@} $host match] {
6090		mesg "Trimming \"$match\" from hostname"
6091		regsub {^.*@} $host "" host
6092	}
6093
6094	set disp [port_part $hpnew]
6095
6096	if {[regexp {^-[0-9][0-9]*$} $disp]} {
6097		;
6098	} elseif {$disp == "" || ! [regexp {^[0-9][0-9]*$} $disp]} {
6099		set disp 0
6100	}
6101	if {$disp < 0} {
6102		set port [expr "- $disp"]
6103	} elseif {$disp < 200} {
6104		set port [expr "$disp + 5900"]
6105	} else {
6106		set port $disp
6107	}
6108
6109	set ipv6_pid ""
6110	if {$have_ipv6} {
6111		set res [ipv6_proxy $proxy $host $port]
6112		set proxy    [lindex $res 0]
6113		set host     [lindex $res 1]
6114		set port     [lindex $res 2]
6115		set ipv6_pid [lindex $res 3]
6116	}
6117
6118	if {$proxy != ""} {
6119		global env
6120
6121		set port2 [rand_port]
6122
6123		set sp ""
6124		if [info exists env(SSVNC_PROXY)] {
6125			set sp $env(SSVNC_PROXY)
6126		}
6127		set sl ""
6128		if [info exists env(SSVNC_LISTEN)] {
6129			set sl $env(SSVNC_LISTEN)
6130		}
6131		set sd ""
6132		if [info exists env(SSVNC_DEST)] {
6133			set sd $env(SSVNC_DEST)
6134		}
6135
6136		set env(SSVNC_PROXY) $proxy
6137		set env(SSVNC_LISTEN) $port2
6138		set env(SSVNC_DEST) "$host:$port"
6139
6140		set host $win_localhost
6141		set port $port2
6142
6143		mesg "Starting Proxy TCP helper on port $port2 ..."
6144		after 300
6145		# fetch cert br case:
6146		set proxy_pid [exec "connect_br.exe" &]
6147
6148		if {$sp == ""} {
6149			catch { unset env(SSVNC_PROXY) }
6150		} else {
6151			set env(SSVNC_PROXY) $sp
6152		}
6153		if {$sl == ""} {
6154			catch { unset env(SSVNC_LISTEN) }
6155		} else {
6156			set env(SSVNC_LISTEN) $sl
6157		}
6158		if {$sd == ""} {
6159			catch { unset env(SSVNC_DEST) }
6160		} else {
6161			set env(SSVNC_DEST) $sd
6162		}
6163	}
6164
6165	set ossl [get_openssl]
6166	update
6167	# VF
6168	set tin tmpin.txt
6169	set tou tmpout.txt
6170	set fh ""
6171	catch {set fh [open $tin "w"]}
6172	if {$fh != ""} {
6173		puts $fh "Q"
6174		puts $fh "GET /WOMBAT HTTP/1.1\r\nHost: wombat.com\r\n\r\n\r\n"
6175		close $fh
6176	}
6177
6178	if {1} {
6179		set ph ""
6180		if {$anondh} {
6181			set ph [open "| $ossl s_client -prexit -connect $host:$port -cipher ALL:RC4+RSA:+SSLv2:@STRENGTH < $tin 2>NUL" "r"]
6182		} else {
6183			set ph [open "| $ossl s_client -prexit -connect $host:$port < $tin 2>NUL" "r"]
6184		}
6185
6186		set text ""
6187		if {$ph != ""} {
6188			set pids [pid $ph]
6189			set got 0
6190			while {[gets $ph line] > -1} {
6191				append text "$line\n"
6192				if [regexp {END CERT} $line] {
6193					set got 1
6194				}
6195				if {$anondh && [regexp -nocase {cipher.*ADH} $line]} {
6196					set got 1
6197				}
6198				if {$got && [regexp {^ *Verify return code} $line]} {
6199					break
6200				}
6201				if [regexp {^RFB } $line] {
6202					break
6203				}
6204				if [regexp {^DONE} $line] {
6205					break
6206				}
6207			}
6208			foreach pid $pids {
6209				winkill $pid
6210			}
6211			if {$ipv6_pid != ""} {
6212				winkill $ipv6_pid
6213			}
6214
6215			catch {close $ph}
6216			catch {file delete $tin $tou}
6217			return $text
6218		}
6219	} else {
6220		set pids ""
6221
6222		if {1} {
6223			if {$anondh} {
6224				set ph2 [open "| $ossl s_client -prexit -connect $host:$port -cipher ALL:RC4+RSA:+SSLv2:@STRENGTH > $tou 2>NUL" "w"]
6225			} else {
6226				set ph2 [open "| $ossl s_client -prexit -connect $host:$port > $tou 2>NUL" "w"]
6227			}
6228			set pids [pid $ph2]
6229			after 500
6230			for {set i 0} {$i < 128} {incr i} {
6231				puts $ph2 "Q"
6232			}
6233			catch {close $ph2}
6234		} else {
6235			if {$anondh} {
6236				set pids [exec $ossl s_client -prexit -connect $host:$port -cipher ALL:RC4+RSA:+SSLv2:@STRENGTH < $tin >& $tou &]
6237			} else {
6238				set pids [exec $ossl s_client -prexit -connect $host:$port < $tin >& $tou &]
6239			}
6240		}
6241
6242		for {set i 0} {$i < 10} {incr i} {
6243			after 500
6244			set got 0
6245			set ph ""
6246			catch {set ph [open $tou "r"]}
6247			if {$ph != ""} {
6248				while {[gets $ph line] > -1} {
6249					if [regexp {END CERT} $line] {
6250						set got 1
6251						break
6252					}
6253				}
6254				close $ph
6255			}
6256			if {$got} {
6257				break
6258			}
6259		}
6260		foreach pid $pids {
6261			winkill $pid
6262		}
6263		after 500
6264		set ph ""
6265		catch {set ph [open $tou "r"]}
6266	}
6267	set text ""
6268	if {$ph != ""} {
6269		while {[gets $ph line] > -1} {
6270			append text "$line\n"
6271		}
6272		close $ph
6273	}
6274	catch {file delete $tin $tou}
6275	if {$ipv6_pid != ""} {
6276		winkill $ipv6_pid
6277	}
6278	return $text
6279}
6280
6281proc check_accepted_certs {{probe_only 0}} {
6282	global cert_text always_verify_ssl
6283	global skip_verify_accepted_certs use_listen
6284	global ultra_dsm env
6285	global server_vencrypt server_anondh no_probe_vencrypt
6286
6287	if {! $always_verify_ssl} {
6288		set skip_verify_accepted_certs 1
6289		if {$server_vencrypt} {
6290			return 1
6291		}
6292		if {$no_probe_vencrypt} {
6293			return 1
6294		}
6295	}
6296	if {$server_anondh} {
6297		mesg "WARNING: Anonymous Diffie Hellman (SKIPPING CERT CHECK)"
6298		after 1000
6299		set skip_verify_accepted_certs 1
6300		return 1
6301	}
6302	if {$ultra_dsm} {
6303		return 1;
6304	}
6305	if {$use_listen} {
6306		return 1;
6307	}
6308
6309	global anon_dh_detected
6310	set anon_dh_detected 0
6311
6312	set cert_text [fetch_cert 0]
6313
6314	set mvar ""
6315	if {[regexp -nocase -line {cipher.*ADH} $cert_text mvar]} {
6316
6317		if [info exists env(CERTDBG)] {puts "\nFetch-MSG-\n$cert_text"}
6318		if [info exists env(CERTDBG)] {puts "\nBEGIN_MVAR: $mvar\nEND_MVAR\n"}
6319
6320		set msg "Anonymous Diffie-Hellman server detected.  There will be encryption, but no SSL/TLS authentication. Continue?"
6321		set reply [tk_messageBox -type okcancel -default ok -icon warning -message $msg -title "Anonymous Diffie-Hellman Detected"]
6322		set anon_dh_detected 1
6323		if {$reply == "cancel"} {
6324			return 0
6325		} else {
6326			global skip_verify_accepted_certs
6327			set skip_verify_accepted_certs 1
6328			return 1
6329		}
6330	}
6331
6332	if {$probe_only} {
6333		return 1
6334	}
6335	if {! $always_verify_ssl} {
6336		return 1
6337	}
6338
6339	set from ""
6340	set fingerprint ""
6341	set fingerline ""
6342	set self_signed 1
6343	set subject_issuer ""
6344	set subject ""
6345	set issuer ""
6346
6347	set i 0
6348	foreach line [split $cert_text "\n"] {
6349		incr i
6350		if {$i > 50} {
6351			break
6352		}
6353		if [regexp {^- subject: *(.*)$} $line m val] {
6354			set val [string trim $val]
6355			set subject_issuer "${subject_issuer}subject:$val\n"
6356			set subject $val
6357		}
6358		if [regexp {^- (issuer[0-9][0-9]*): *(.*)$} $line m is val] {
6359			set val [string trim $val]
6360			set subject_issuer "${subject_issuer}$is:$val\n"
6361			set issuer $val
6362		}
6363		if [regexp {^INFO: SELF_SIGNED=(.*)$} $line m val] {
6364			set subject_issuer "${subject_issuer}SELF_SIGNED:$val\n"
6365		}
6366		if [regexp {^depth=} $line] {
6367			break
6368		}
6369		if [regexp {^verify } $line] {
6370			break
6371		}
6372		if [regexp {^CONNECTED} $line] {
6373			break
6374		}
6375		if [regexp {^Certificate chain} $line] {
6376			break
6377		}
6378		if [regexp {^==== SSL Certificate from (.*) ====} $line mv str] {
6379			set from [string trim $str]
6380		}
6381		if [regexp -nocase {Fingerprint=(.*)} $line mv str] {
6382			set fingerline $line
6383			set fingerprint [string trim $str]
6384		}
6385		if [regexp -nocase {^INFO: SELF_SIGNED=([01])} $line mv str] {
6386			set self_signed $str
6387		}
6388	}
6389
6390	set fingerprint [string tolower $fingerprint]
6391	regsub -all {:} $fingerprint "-" fingerprint
6392	regsub -all {[\\/=]} $fingerprint "_" fingerprint
6393
6394	set from [string tolower $from]
6395	regsub -all {[\[\]]} $from "" from
6396	regsub -all {^[+a-z]*://} $from "" from
6397	regsub -all {:} $from "-" from
6398	regsub -all {[\\/=]} $from "_" from
6399	regsub -all {[ 	]} $from "_" from
6400
6401	if {$from == "" || $fingerprint == ""} {
6402		bell
6403		catch {raise .; update}
6404		mesg "WARNING: Error fetching Server Cert"
6405		after 500
6406		set hp [get_vncdisplay]
6407		set n [line_count $cert_text 1]
6408		fetch_dialog $cert_text $hp $hp 0 $n
6409		update
6410		after 2000
6411		return 0
6412	}
6413
6414	set hp [get_vncdisplay]
6415
6416	set adir [get_idir_certs ""]
6417	catch {file mkdir $adir}
6418	set adir "$adir/accepted"
6419	catch {file mkdir $adir}
6420
6421	set crt "$adir/$from=$fingerprint.crt"
6422
6423	if [file exists $crt] {
6424		if {$self_signed} {
6425			mesg "OK: Certificate found in ACCEPTED_CERTS"
6426			after 750
6427			return 1
6428		}
6429	}
6430
6431	set cnt 0
6432	foreach f [glob -nocomplain -directory $adir "*$fingerprint*.crt"] {
6433		mesg "CERT: $f"
6434		after 150
6435		if {$self_signed} {
6436			incr cnt
6437		}
6438	}
6439
6440	set oth 0
6441	set others [list]
6442	foreach f [glob -nocomplain -directory $adir "*$from*.crt"] {
6443		if {$f == $crt}  {
6444			continue
6445		}
6446		set fb [file tail $f]
6447		mesg "OTHER CERT: $fb"
6448		if {$cnt > 0} {
6449			after 400
6450		} else {
6451			bell
6452			after 800
6453		}
6454		lappend others $f
6455		incr oth
6456	}
6457
6458	foreach f [glob -nocomplain -directory $adir "*.crt"] {
6459		if {$f == $crt}  {
6460			continue
6461		}
6462		set saw 0
6463		foreach o $others {
6464			if {$f == $o} 	{
6465				set saw 1
6466				break
6467			}
6468		}
6469		if {$saw} {
6470			continue
6471		}
6472		set fh [open $f "r"]
6473		if {$fh == ""} {
6474			continue
6475		}
6476		set same 0
6477		set sub ""
6478		set iss ""
6479		set isn -1;
6480		while {[gets $fh line] > -1} {
6481			if [regexp {^Host-Display: (.*)$} $line mv hd] {
6482				if {$hd == $hp || $hd == $from} {
6483					set same 1
6484				}
6485			}
6486			if [regexp {^subject:(.*)$} $line mv val] {
6487				set sub $val
6488			}
6489			if [regexp {^issue([0-9][0-9]*):(.*)$} $line mv in val] {
6490				if {$in > $isn} {
6491					set isn $in
6492					set iss $val
6493				}
6494			}
6495		}
6496		close $fh;
6497
6498		if {!$self_signed} {
6499			if {$sub == ""} {
6500				set ossl [get_openssl]
6501				set si_txt [exec $ossl x509 -subject -issuer -noout -in $f]
6502				foreach line [split $si_txt "\n"] {
6503					if [regexp -nocase {^subject= *(.*)$} $line mv str] {
6504						set str [string trim $str]
6505						if {$str != ""} {
6506							set sub $str
6507						}
6508					} elseif [regexp -nocase {^issuer= *(.*)$} $line mv str] {
6509						set str [string trim $str]
6510						if {$iss != ""} {
6511							set iss $str
6512						}
6513					}
6514				}
6515			}
6516			if {$issuer != "" && $sub != ""} {
6517				global env
6518				if [info exists env(CERTDBG)] {
6519					puts "f: $f"
6520					puts "s: $sub"
6521					puts "i: $issuer"
6522					puts "==================="
6523				}
6524				if {$issuer == $sub} {
6525					set fb [file tail $f]
6526					mesg "Certificate Authority (CA) CERT: $fb"
6527					incr cnt
6528					after 500
6529				}
6530			}
6531			continue
6532		}
6533
6534		if {! $same} {
6535			continue
6536		}
6537
6538		set fb [file tail $f]
6539		mesg "OTHER CERT: $fb"
6540		if {$cnt > 0} {
6541			after 400
6542		} else {
6543			bell
6544			after 800
6545		}
6546		lappend others $f
6547		incr oth
6548	}
6549
6550	if {$cnt > 0} {
6551		if {$self_signed} {
6552			mesg "OK: Server Certificate found in ACCEPTED_CERTS"
6553			after 400
6554		} else {
6555			mesg "OK: CA Certificate found in ACCEPTED_CERTS"
6556			after 800
6557		}
6558		return 1
6559	}
6560
6561	set hp2 [get_vncdisplay]
6562	set msg "
6563    The Self-Signed SSL Certificate from host:
6564
6565        $hp2
6566
6567    Fingerprint: $fingerprint
6568
6569    Subject: $subject
6570
6571    is not present in the 'Accepted Certs' directory:
6572
6573        $adir
6574%WARN
6575    You will need to verify on your own that this is a certificate from a
6576    VNC server that you trust (e.g. by checking the fingerprint with that
6577    sent to you by the server administrator).
6578
6579
6580    THE QUESTION: Do you want this certificate to be saved in the Accepted Certs
6581    directory and then used to SSL authenticate VNC servers?
6582
6583
6584    By clicking 'Inspect and maybe Save Cert' you will be given the opportunity
6585    to inspect the certificate before deciding to save it or not.
6586"
6587
6588	set msg_bottom "
6589    Choose 'Ignore Cert for One Connection' to connect a single time to the
6590    server with *NO* certificate authentication.  You will see this dialog again
6591    the next time you connect to the same server.
6592
6593    Choose 'Continue as though I saved it' to launch stunnel and the VNC viewer.
6594    Do this if you know the correct Certificate is in the 'Accepted Certs'
6595    directory.  If it is not, stunnel will fail and report 'VERIFY ERROR:...'
6596
6597    Choose 'Cancel' to not connect to the VNC Server at all.
6598"
6599
6600	set msg_ca "
6601    The CA-signed SSL Certificate from host:
6602
6603        $hp2
6604
6605    Fingerprint: $fingerprint
6606
6607    Subject: $subject
6608
6609    Issuer:  $issuer
6610
6611    is signed by a Certificate Authority (CA) (the 'Issuer' above.)
6612
6613    However, the certificate of the CA 'Issuer' is not present in the
6614    'Accepted Certs' directory:
6615
6616        $adir
6617
6618    You will need to obtain the certificate of the CA 'Issuer' via some means
6619    (perhaps ask the VNC server administrator for it.)  Then, after you have
6620    verified that the CA certificate is one that you trust, import the
6621    certificate via Certs -> Import Certificate.  Be sure to select to also
6622    save it to the Accepted Certs directory so it will automatically be used.
6623"
6624	set msg "$msg$msg_bottom"
6625	set msg_ca "$msg_ca$msg_bottom"
6626
6627	if {!$self_signed} {
6628		set msg $msg_ca
6629	}
6630
6631	if {$oth == 0} {
6632		regsub {%WARN} $msg "" msg
6633	} else {
6634		set warn ""
6635		set wfp ""
6636		if {$oth == 1} {
6637			set warn "
6638**WARNING** The Following Cert was previously saved FOR THE SAME HOST-DISPLAY:
6639
6640"
6641			set wfp "BUT WITH A DIFFERENT FINGERPRINT."
6642
6643		} else {
6644			set warn "
6645**WARNING** The Following Certs were previously saved FOR THE SAME HOST-DISPLAY:
6646
6647"
6648			set wfp "BUT WITH DIFFERENT FINGERPRINTS."
6649		}
6650
6651		foreach o $others {
6652			set fb [file tail $o]
6653			set warn "$warn        $fb\n"
6654		}
6655		set warn "$warn\n    $wfp\n"
6656		set warn "$warn\n    This could be a Man-In-The-Middle attack, or simply that the Server changed"
6657		set warn "$warn\n    its Certificate.  *PLEASE CHECK* before proceeding!\n"
6658		regsub {%WARN} $msg $warn msg
6659		bell
6660	}
6661
6662	set n 0
6663	foreach l [split $msg "\n"] {
6664		incr n
6665	}
6666	if {!$self_signed} {
6667		set n [expr $n + 2]
6668	} else {
6669		set n [expr $n + 1]
6670	}
6671	if [small_height] {
6672		if {$n > 26} {
6673			set n 26
6674		}
6675	}
6676	toplev .acert
6677	scroll_text .acert.f 83 $n
6678
6679	button .acert.inspect -text "Inspect and maybe Save Cert ..." -command "destroy .acert; set accept_cert_dialog 1"
6680	button .acert.accept  -text "Ignore Cert for One Connection  " -command "destroy .acert; set accept_cert_dialog 2"
6681	button .acert.continue -text "Continue as though I saved it     " -command "destroy .acert; set accept_cert_dialog 3"
6682	button .acert.cancel -text "Cancel"   -command "destroy .acert; set accept_cert_dialog 0"
6683
6684	wm title .acert "Unrecognized SSL Cert!"
6685
6686	.acert.f.t insert end $msg
6687
6688	pack .acert.cancel .acert.continue .acert.accept .acert.inspect -side bottom -fill x
6689	pack .acert.f -side top -fill both -expand 1
6690
6691	if {! $self_signed} {
6692		catch {.acert.inspect configure -state disabled}
6693	}
6694
6695	center_win .acert
6696
6697	global accept_cert_dialog
6698	set accept_cert_dialog ""
6699
6700	jiggle_text .acert.f.t
6701
6702	tkwait window .acert
6703
6704	if {$accept_cert_dialog == 2} {
6705		set skip_verify_accepted_certs 1
6706		return 1
6707	}
6708	if {$accept_cert_dialog == 3} {
6709		return 1
6710	}
6711	if {$accept_cert_dialog != 1} {
6712		return 0
6713	}
6714
6715	global accepted_cert_dialog_in_progress
6716	set accepted_cert_dialog_in_progress 1
6717
6718	global fetch_cert_filename
6719	set fetch_cert_filename $crt
6720
6721	global do_save_saved_it
6722	set do_save_saved_it 0
6723	global do_save_saved_hash_it
6724	set do_save_saved_hash_it 0
6725
6726	fetch_dialog $cert_text $hp $hp 1 47
6727	update; after 150
6728
6729	catch {tkwait window .fetch}
6730	update; after 250
6731	catch {tkwait window .scrt}
6732	update; after 250
6733	if [winfo exists .scrt] {
6734		catch {tkwait window .scrt}
6735	}
6736
6737	set fetch_cert_filename ""
6738	set accepted_cert_dialog_in_progress 0
6739
6740	if {!$do_save_saved_hash_it} {
6741		save_hash $crt $adir $hp $fingerline $from $fingerprint $subject_issuer
6742	}
6743
6744	if {$do_save_saved_it} {
6745		return 1
6746	} else {
6747		return 0
6748	}
6749}
6750
6751proc save_hash {crt adir hp fingerline from fingerprint {subject_issuer ""}} {
6752	if ![file exists $crt] {
6753		return
6754	}
6755	set ossl [get_openssl]
6756	set hash [exec $ossl x509 -hash -noout -in $crt]
6757	set hash [string trim $hash]
6758	if [regexp {^([0-9a-f][0-9a-f]*)} $hash mv h] {
6759		set hashfile "$adir/$h.0"
6760		set hn "$h.0"
6761		if [file exists $hashfile] {
6762			set hashfile "$adir/$h.1"
6763			set hn "$h.1"
6764			if [file exists $hashfile] {
6765				set hashfile "$adir/$h.2"
6766				set hn "$h.2"
6767			}
6768		}
6769		set fh [open $crt "a"]
6770		if {$fh != ""} {
6771			puts $fh ""
6772			puts $fh "SSVNC-info:"
6773			puts $fh "Host-Display: $hp"
6774			puts $fh "$fingerline"
6775			puts $fh "hash-filename: $hn"
6776			puts $fh "full-filename: $from=$fingerprint.crt"
6777			puts -nonewline $fh $subject_issuer
6778			close $fh
6779		}
6780		catch {file copy -force $crt $hashfile}
6781		if [file exists $hashfile] {
6782			return 1
6783		}
6784	}
6785}
6786
6787proc tpid {} {
6788	global is_windows
6789	set p ""
6790
6791	if {!$is_windows} {
6792		catch {set p [exec sh -c {echo $$}]}
6793	}
6794	if {$p == ""} {
6795		set p [pid];
6796	}
6797	append p [clock clicks]
6798	return $p
6799}
6800
6801proc repeater_proxy_check {proxy} {
6802	if [regexp {^repeater://.*\+ID:[0-9]} $proxy] {
6803		global env rpc_m1 rpc_m2
6804		if {![info exists rpc_m1]} {
6805			set rpc_m1 0
6806			set rpc_m2 0
6807		}
6808		set force 0
6809		if [info exists env(REPEATER_FORCE)] {
6810			if {$env(REPEATER_FORCE) != "" && $env(REPEATER_FORCE) != "0"} {
6811				# no longer makes a difference.
6812				set force 1
6813			}
6814		}
6815		global use_listen ultra_dsm
6816		if {! $use_listen} {
6817			if {$ultra_dsm} {
6818				return 1;
6819			} else {
6820				if {0} {
6821					mesg "WARNING: repeater:// ID:nnn proxy might need Listen Mode"
6822					incr rpc_m1
6823					if {$rpc_m1 <= 2} {
6824						after 1000
6825					} else {
6826						after 200
6827					}
6828				}
6829				if {0} {
6830					# no longer required by x11vnc (X11VNC_DISABLE_SSL_CLIENT_MODE)
6831					bell
6832					mesg "ERROR: repeater:// ID:nnn proxy must use Listen Mode"
6833					after 1000
6834					return 0
6835				}
6836			}
6837		}
6838		global always_verify_ssl
6839		if [info exists always_verify_ssl] {
6840			if {$always_verify_ssl} {
6841				mesg "WARNING: repeater:// ID:nnn Verify All Certs may fail"
6842				incr rpc_m2
6843				if {$rpc_m2 == 1} {
6844					after 1500
6845				} elseif {$rpc_m2 == 2} {
6846					after 500
6847				} else {
6848					after 200
6849				}
6850			}
6851		}
6852	}
6853	return 1
6854}
6855
6856proc fini_unixpw {} {
6857	global named_pipe_fh unixpw_tmp
6858
6859	if {$named_pipe_fh != ""} {
6860		catch {close $named_pipe_fh}
6861	}
6862	if {$unixpw_tmp  != ""} {
6863		catch {file delete $unixpw_tmp}
6864	}
6865}
6866
6867proc init_unixpw {hp} {
6868	global use_unixpw unixpw_username unixpw_passwd
6869	global named_pipe_fh unixpw_tmp env
6870
6871	set named_pipe_fh ""
6872	set unixpw_tmp ""
6873
6874	if {$use_unixpw} {
6875		set name $unixpw_username
6876		set env(SSVNC_UNIXPW) ""
6877		if {$name == ""} {
6878			regsub {^.*://} $hp "" hp
6879			set hptmp [get_ssh_hp $hp]
6880			if [regexp {^(.*)@} $hptmp mv m1] {
6881				set name $m1
6882			}
6883		}
6884		if {$name == ""} {
6885			if [info exists env(USER)] {
6886				set name $env(USER)
6887			}
6888		}
6889		if {$name == ""} {
6890			if [info exists env(LOGNAME)] {
6891				set name $env(LOGNAME)
6892			}
6893		}
6894		if {$name == ""} {
6895			set name [exec whoami]
6896		}
6897		if {$name == ""} {
6898			set name "unknown"
6899		}
6900
6901		set tmp "/tmp/unixpipe.[tpid]"
6902		set tmp [mytmp $tmp]
6903		# need to make it a pipe
6904		catch {file delete $tmp}
6905		if {[file exists $tmp]} {
6906			mesg "file still exists: $tmp"
6907			bell
6908			return
6909		}
6910
6911		catch {exec mknod $tmp p}
6912		set fh ""
6913		if {! [file exists $tmp]} {
6914			catch {set fh [open $tmp "w"]}
6915		} else {
6916			catch {set fh [open $tmp "r+"]}
6917			set named_pipe_fh $fh
6918		}
6919		catch {exec chmod 600 $tmp}
6920		if {! [file exists $tmp]} {
6921			mesg "cannot create: $tmp"
6922			if {$named_pipe_fh != ""} {catch close $named_pipe_fh}
6923			bell
6924			return
6925		}
6926		#puts [exec ls -l $tmp]
6927		set unixpw_tmp $tmp
6928		puts $fh $name
6929		puts $fh $unixpw_passwd
6930		if {$named_pipe_fh != ""} {
6931			flush $fh
6932		} else {
6933			close $fh
6934		}
6935		exec sh -c "sleep 60; /bin/rm -f $tmp" &
6936		if {$unixpw_passwd == ""} {
6937			set env(SSVNC_UNIXPW) "."
6938		} else {
6939			set env(SSVNC_UNIXPW) "rm:$tmp"
6940		}
6941	} else {
6942		if [info exists env(SSVNC_UNIXPW)] {
6943			set env(SSVNC_UNIXPW) ""
6944		}
6945	}
6946}
6947
6948proc check_for_listen_ssl_cert {} {
6949	global mycert use_listen use_ssh ultra_dsm
6950	if {! $use_listen} {
6951		return 1
6952	}
6953	if {$use_ssh} {
6954		return 1
6955	}
6956	if {$ultra_dsm} {
6957		return 1
6958	}
6959	if {$mycert != ""} {
6960		return 1
6961	}
6962
6963	set name [get_idir_certs ""]
6964	set name "$name/listen.pem"
6965	if {[file exists $name]} {
6966		set mycert $name
6967		mesg "Using Listen Cert: $name"
6968		after 700
6969		return 1
6970	}
6971
6972	set title "SSL Listen requires MyCert";
6973	set msg "In SSL Listen mode a cert+key is required, but you have not specified  'MyCert'.\n\nCreate a cert+key 'listen' now?"
6974	set reply [tk_messageBox -type okcancel -default ok -icon warning -message $msg -title $msg]
6975	if {$reply == "cancel"} {
6976		return 0
6977	}
6978	create_cert $name
6979	tkwait window .ccrt
6980	if {[file exists $name]} {
6981		set mycert $name
6982		mesg "Using Listen Cert: $name"
6983		after 700
6984		return 1
6985	}
6986	return 0
6987}
6988
6989proc listen_verify_all_dialog {hp} {
6990	global use_listen always_verify_ssl
6991	global did_listen_verify_all_dialog
6992	global svcert
6993	global sshssl_sw ultra_dsm
6994
6995	if {!$use_listen} {
6996		return 1
6997	}
6998	if {!$always_verify_ssl} {
6999		return 1
7000	}
7001	if {$svcert != ""} {
7002		return 1
7003	}
7004	if {$ultra_dsm} {
7005		return 1
7006	}
7007	if [regexp -nocase {^vnc://} $hp] {
7008		return 1
7009	}
7010	if [info exists sshssl_sw] {
7011		if {$sshssl_sw == "none"} {
7012			return 1
7013		}
7014		if {$sshssl_sw == "ssh"} {
7015			return 1
7016		}
7017	}
7018	if [info exists did_listen_verify_all_dialog] {
7019		return 1
7020	}
7021
7022	toplev .lvd
7023	global help_font
7024	wm title .lvd "Verify All Certs for Reverse Connections"
7025	eval text .lvd.t -width 55 -height 22 $help_font
7026	.lvd.t insert end {
7027  Information:
7028
7029    You have the 'Verify All Certs' option enabled
7030    in Reverse VNC Connections (-LISTEN) mode.
7031
7032    For this to work, you must have ALREADY saved
7033    the remote VNC Server's Certificate to the
7034    'Accepted Certs' directory.  Otherwise the
7035    incoming Reverse connection will be rejected.
7036
7037    You can save the Server's Certificate by using
7038    the 'Import Certificate' dialog or on Unix
7039    and MacOSX by pressing 'Fetch Cert' and then
7040    have the Server make an initial connection.
7041
7042    If you do not want to save the certificate of
7043    the VNC Server making the Reverse connection,
7044    you must disable 'Verify All Certs' (note that
7045    this means the server authenticity will not be
7046    checked.)
7047}
7048
7049	button .lvd.ok   -text OK   -command {destroy .lvd}
7050	button .lvd.ok2  -text OK   -command {destroy .lvd}
7051	button .lvd.disable   -text "Disable 'Verify All Certs'"  -command {set always_verify_ssl 0; destroy .lvd}
7052	global uname
7053	if {$uname == "Darwin"} {
7054		pack .lvd.t .lvd.ok2 .lvd.disable .lvd.ok -side top -fill x
7055	} else {
7056		pack .lvd.t .lvd.disable .lvd.ok -side top -fill x
7057	}
7058	center_win .lvd
7059	update
7060
7061	tkwait window .lvd
7062	update
7063	after 50
7064	update
7065
7066	set did_listen_verify_all_dialog 1
7067	return 1
7068}
7069
7070proc reset_stunnel_extra_opts {} {
7071	global stunnel_extra_opts0 stunnel_extra_svc_opts0 env
7072	global ssvnc_multiple_listen0
7073	if {$stunnel_extra_opts0 != "none"} {
7074		set env(STUNNEL_EXTRA_OPTS) $stunnel_extra_opts0
7075	}
7076	if {$stunnel_extra_svc_opts0 != "none"} {
7077		set env(STUNNEL_EXTRA_SVC_OPTS) $stunnel_extra_svc_opts0
7078	}
7079	set env(SSVNC_LIM_ACCEPT_PRELOAD) ""
7080	if {$ssvnc_multiple_listen0 != "none"} {
7081		set env(SSVNC_MULTIPLE_LISTEN) $ssvnc_multiple_listen0
7082	}
7083	set env(SSVNC_ULTRA_DSM) ""
7084	set env(SSVNC_TURBOVNC) ""
7085	catch { unset env(VNCVIEWER_NO_PIPELINE_UPDATES) }
7086	catch { unset env(VNCVIEWER_NOTTY) }
7087	catch { unset env(SSVNC_ACCEPT_POPUP)    }
7088	catch { unset env(SSVNC_ACCEPT_POPUP_SC) }
7089	catch { unset env(SSVNC_KNOWN_HOSTS_FILE)    }
7090}
7091
7092proc maybe_add_vencrypt {proxy hp} {
7093	global vencrypt_detected server_vencrypt
7094	set vpd ""
7095	if {$vencrypt_detected != ""} {
7096		set vpd $vencrypt_detected
7097		set vencrypt_detected ""
7098	} elseif {$server_vencrypt} {
7099		set vpd [get_vencrypt_proxy $hp]
7100	}
7101	if {$vpd != ""} {
7102		mesg "vencrypt proxy: $vpd"
7103		if {$proxy != ""} {
7104			set proxy "$proxy,$vpd"
7105		} else {
7106			set proxy "$vpd"
7107		}
7108	}
7109	return $proxy
7110}
7111
7112proc no_certs_tutorial_mesg {} {
7113	global svcert crtdir
7114	global server_anondh
7115	global always_verify_ssl
7116
7117	set doit 0
7118	if {!$always_verify_ssl} {
7119		if {$svcert == ""} {
7120			if {$crtdir == "" || $crtdir == "ACCEPTED_CERTS"} {
7121				set doit 1
7122			}
7123		}
7124	} elseif {$server_anondh} {
7125		set doit 1
7126	}
7127	if {$doit} {
7128		mesg "INFO: without Certificate checking man-in-the-middle attack is possible."
7129	} else {
7130		set str ""
7131		catch {set str [.l cget -text]}
7132		if {$str != "" && [regexp {^INFO: without Certificate} $str]} {
7133			mesg ""
7134		}
7135	}
7136}
7137
7138proc vencrypt_tutorial_mesg {} {
7139	global use_ssh use_sshssl use_listen
7140	global server_vencrypt no_probe_vencrypt
7141	global ultra_dsm
7142
7143	set m ""
7144	if {$use_ssh} {
7145		;
7146	} elseif {$server_vencrypt} {
7147		;
7148	} elseif {$ultra_dsm} {
7149		;
7150	} elseif {$use_listen} {
7151		set m "No VeNCrypt Auto-Detection:  Listen mode."
7152	} elseif {$use_sshssl} {
7153		set m "No VeNCrypt Auto-Detection:  SSH+SSL mode."
7154	} elseif {$no_probe_vencrypt} {
7155		set m "No VeNCrypt Auto-Detection:  Disabled."
7156	}
7157	if {$m != ""} {
7158		mesg $m
7159		after 1000
7160	}
7161	return $m
7162
7163	#global svcert always_verify_ssl
7164	#$svcert != "" || !$always_verify_ssl
7165	#	set m "No VeNCrypt Auto-Detection: 'Verify All Certs' disabled"
7166}
7167
7168proc launch_unix {hp} {
7169	global smb_redir_0 smb_mounts env
7170	global vncauth_passwd use_unixpw unixpw_username unixpw_passwd
7171	global ssh_only ts_only use_x11cursor use_nobell use_rawlocal use_notty use_popupfix ssvnc_scale ssvnc_escape
7172	global ssvnc_encodings ssvnc_extra_opts
7173
7174	globalize
7175
7176	set cmd ""
7177
7178	if {[regexp {^vncssh://} $hp] || [regexp {^vnc\+ssh://} $hp]} {
7179		set use_ssl 0
7180		set use_ssh 1
7181		sync_use_ssl_ssh
7182	} elseif {[regexp {^vncs://} $hp] || [regexp {^vncssl://} $hp] || [regexp {^vnc\+ssl://} $hp]} {
7183		set use_ssl 1
7184		set use_ssh 0
7185		sync_use_ssl_ssh
7186	}
7187	if {[regexp {^rsh:/?/?} $hp]} {
7188		set use_ssl 0
7189		set use_ssh 1
7190		sync_use_ssl_ssh
7191	}
7192
7193	check_ssh_needed
7194
7195	set_smb_mounts
7196
7197	global did_port_knock
7198	set did_port_knock 0
7199	set pk_hp ""
7200
7201	set skip_ssh 0
7202	set do_direct 0
7203
7204	if [regexp {vnc://} $hp] {
7205		set skip_ssh 1
7206		set do_direct 1
7207		if {! [info exists env(SSVNC_NO_ENC_WARN)]} {
7208			direct_connect_msg
7209		}
7210	}
7211
7212	listen_verify_all_dialog $hp
7213
7214	if {! $do_direct} {
7215		if {! [check_for_listen_ssl_cert]} {
7216			return
7217		}
7218	}
7219
7220	global stunnel_extra_opts0 stunnel_extra_svc_opts0
7221	set stunnel_extra_opts0 ""
7222	set stunnel_extra_svc_opts0 ""
7223	global ssvnc_multiple_listen0
7224	set ssvnc_multiple_listen0 ""
7225
7226	if {[regexp -nocase {sslrepeater://} $hp]} {
7227		if {$disable_ssl_workarounds} {
7228			set disable_ssl_workarounds 0
7229			mesg "Disabling SSL workarounds for 'UVNC Single Click III Bug'"
7230			after 400
7231		}
7232	}
7233
7234	if [info exists env(STUNNEL_EXTRA_OPTS)] {
7235		set stunnel_extra_opts0 $env(STUNNEL_EXTRA_OPTS)
7236		if {$disable_ssl_workarounds} {
7237			if {$disable_ssl_workarounds_type == "none"} {
7238				;
7239			} elseif {$disable_ssl_workarounds_type == "noempty"} {
7240				set env(STUNNEL_EXTRA_OPTS) "$env(STUNNEL_EXTRA_OPTS)\noptions = DONT_INSERT_EMPTY_FRAGMENTS"
7241			}
7242		} else {
7243			set env(STUNNEL_EXTRA_OPTS) "$env(STUNNEL_EXTRA_OPTS)\noptions = ALL"
7244		}
7245	} else {
7246		if {$disable_ssl_workarounds} {
7247			if {$disable_ssl_workarounds_type == "none"} {
7248				;
7249			} elseif {$disable_ssl_workarounds_type == "noempty"} {
7250				set env(STUNNEL_EXTRA_OPTS) "options = DONT_INSERT_EMPTY_FRAGMENTS"
7251			}
7252		} else {
7253			set env(STUNNEL_EXTRA_OPTS) "options = ALL"
7254		}
7255	}
7256	if {$stunnel_local_protection && ! $use_listen} {
7257		if {$stunnel_local_protection_type == "ident"} {
7258			set user ""
7259			if {[info exists env(USER)]} {
7260				set user $env(USER)
7261			} elseif {[info exists env(LOGNAME)]} {
7262				set user $env(USER)
7263			}
7264			if {$user != ""} {
7265				if [info exists env(STUNNEL_EXTRA_SVC_OPTS)] {
7266					set stunnel_extra_svc_opts0 $env(STUNNEL_EXTRA_SVC_OPTS)
7267					set env(STUNNEL_EXTRA_SVC_OPTS) "$env(STUNNEL_EXTRA_SVC_OPTS)\nident = $user"
7268				} else {
7269					set env(STUNNEL_EXTRA_SVC_OPTS) "ident = $user"
7270				}
7271			}
7272		} elseif {$stunnel_local_protection_type == "exec"} {
7273			if [info exists env(STUNNEL_EXTRA_SVC_OPTS)] {
7274				set stunnel_extra_svc_opts0 $env(STUNNEL_EXTRA_SVC_OPTS)
7275				set env(STUNNEL_EXTRA_SVC_OPTS) "$env(STUNNEL_EXTRA_SVC_OPTS)\n#stunnel-exec"
7276			} else {
7277				set env(STUNNEL_EXTRA_SVC_OPTS) "#stunnel-exec"
7278			}
7279		}
7280	}
7281	if {$ultra_dsm} {
7282		if {$ultra_dsm_type == "securevnc"} {
7283			;
7284		} elseif {![file exists $ultra_dsm_file] && ![regexp {pw=} $ultra_dsm_file]} {
7285			mesg "DSM key file does exist: $ultra_dsm_file"
7286			bell
7287			after 1000
7288			return
7289		}
7290		global vncauth_passwd
7291		if {$ultra_dsm_file == "pw=VNCPASSWORD" || $ultra_dsm_file == "pw=VNCPASSWD"} {
7292			if {![info exists vncauth_passwd] || $vncauth_passwd == ""} {
7293				mesg "For DSM pw=VNCPASSWD you must supply the VNC Password"
7294				bell
7295				after 1000
7296				return
7297			}
7298			if [regexp {'} $vncauth_passwd] {
7299				mesg "For DSM pw=VNCPASSWD password must not contain single quotes."
7300				bell
7301				after 1000
7302				return
7303			}
7304		}
7305		set dsm "ultravnc_dsm_helper "
7306		if {$ultra_dsm_noultra} {
7307			append dsm "noultra:"
7308		}
7309		if {$use_listen} {
7310			append dsm "rev:"
7311		}
7312		if {$ultra_dsm_type == "guess"} {
7313			append dsm "."
7314		} else {
7315			append dsm $ultra_dsm_type
7316		}
7317		if {$ultra_dsm_noultra} {
7318			if {$ultra_dsm_salt != ""} {
7319				append dsm "@$ultra_dsm_salt"
7320			}
7321		}
7322		if {$ultra_dsm_file == "pw=VNCPASSWORD" || $ultra_dsm_file == "pw=VNCPASSWD"} {
7323			append dsm " pw='$vncauth_passwd'"
7324		} else {
7325			if {$ultra_dsm_file == "" && $ultra_dsm_type == "securevnc"} {
7326				append dsm " none"
7327			} else {
7328				append dsm " $ultra_dsm_file"
7329			}
7330		}
7331		set env(SSVNC_ULTRA_DSM) $dsm
7332	}
7333	if {$multiple_listen && $use_listen} {
7334		if [info exists env(SSVNC_MULTIPLE_LISTEN)] {
7335			set ssvnc_multiple_listen0 $env(SSVNC_MULTIPLE_LISTEN)
7336		}
7337		set env(SSVNC_MULTIPLE_LISTEN) "1"
7338	}
7339
7340	if {$use_ssh} {
7341		;
7342	} elseif {$use_sshssl} {
7343		;
7344	} elseif {$use_ssl} {
7345		set prox  [get_ssh_proxy $hp]
7346		if {$prox != "" && [regexp {@} $prox]} {
7347			mesg "Error: proxy contains '@'  Did you mean to use SSH mode?"
7348			bell
7349			return
7350		}
7351		if [regexp {@} $hp] {
7352			mesg "Error: host contains '@'  Did you mean to use SSH mode?"
7353			bell
7354			return
7355		}
7356	}
7357
7358	if {$use_ssh || $use_sshssl} {
7359		if {$ssh_local_protection} {
7360			if {![info exists env(LIM_ACCEPT)]} {
7361				set env(LIM_ACCEPT) 1
7362			}
7363			if {![info exists env(LIM_ACCEPT_TIME)]} {
7364				set env(LIM_ACCEPT_TIME) 35
7365			}
7366			set env(SSVNC_LIM_ACCEPT_PRELOAD) "lim_accept.so"
7367			mesg "SSH LIM_ACCEPT($env(LIM_ACCEPT),$env(LIM_ACCEPT_TIME)): lim_accept.so"
7368			after 700
7369		}
7370		if {$skip_ssh || $ultra_dsm} {
7371			set cmd "ss_vncviewer"
7372		} elseif {$use_ssh} {
7373			set cmd "ss_vncviewer -ssh"
7374		} else {
7375			set cmd "ss_vncviewer -sshssl"
7376			if {$mycert != ""} {
7377				set cmd "$cmd -mycert '$mycert'"
7378			}
7379			if {$crlfil != ""} {
7380				set cmd "$cmd -crl '$crlfil'"
7381			}
7382			if {$svcert != ""} {
7383				set cmd "$cmd -verify '$svcert'"
7384			} elseif {$crtdir != "" && $crtdir != "ACCEPTED_CERTS"} {
7385				set cmd "$cmd -verify '$crtdir'"
7386			}
7387		}
7388		if {$use_listen} {
7389			set cmd "$cmd -listen"
7390		}
7391		if {$ssh_local_protection} {
7392			regsub {ss_vncviewer} $cmd "ssvnc_cmd" cmd
7393		}
7394		set hpnew  [get_ssh_hp $hp]
7395		set proxy  [get_ssh_proxy $hp]
7396		set sshcmd [get_ssh_cmd $hp]
7397
7398		if {$use_sshssl} {
7399			if {!$do_direct} {
7400				set proxy [maybe_add_vencrypt $proxy $hp]
7401			}
7402		}
7403
7404		if {$ts_only} {
7405			regsub {:0$} $hpnew "" hpnew
7406			if {$proxy == ""} {
7407				# XXX host_part
7408				if {[regexp {^([^:]*):([0-9][0-9]*)$} $hpnew mv sshhst sshpt]} {
7409					set proxy "$sshhst:$sshpt"
7410					set hpnew "localhost"
7411				}
7412			} else {
7413				if {![regexp {,} $proxy]} {
7414					if {$hpnew != "localhost"} {
7415						set proxy "$proxy,$hpnew"
7416						set hpnew "localhost"
7417					}
7418				}
7419			}
7420		}
7421
7422#puts hp=$hp
7423#puts hpn=$hpnew
7424#puts pxy=$proxy
7425#puts cmd=$sshcmd
7426
7427		set hp $hpnew
7428
7429		if {$proxy != ""} {
7430			set cmd "$cmd -proxy '$proxy'"
7431			set pk_hp $proxy
7432		}
7433		if {$pk_hp == ""} {
7434			set pk_hp $hp
7435		}
7436
7437		set do_pre 0
7438		if {$use_smbmnt}  {
7439			set do_pre 1
7440		} elseif {$use_sound && $sound_daemon_kill} {
7441			set do_pre 1
7442		}
7443		global skip_pre
7444		if {$skip_pre || $skip_ssh} {
7445			set do_pre 0
7446			set skip_pre 0
7447		}
7448
7449		set tag [contag]
7450
7451		if {$do_pre} {
7452			do_unix_pre $tag $proxy $hp $pk_hp
7453		}
7454
7455
7456		set setup_cmds [ugly_setup_scripts post $tag]
7457
7458		if {$skip_ssh} {
7459			set setup_cmds ""
7460		}
7461		if {$sshcmd != "SHELL" && [regexp -nocase {x11vnc} $sshcmd]} {
7462			global use_cups cups_x11vnc cups_remote_port
7463			global cups_remote_smb_port
7464			global use_sound sound_daemon_x11vnc sound_daemon_remote_port
7465			global ts_only
7466			if {$ts_only} {
7467				set cups_x11vnc 1
7468				set sound_daemon_x11vnc 1
7469			}
7470			if {$use_cups && $cups_x11vnc && $cups_remote_port != ""} {
7471				set crp $cups_remote_port
7472				if {$ts_only} {
7473					set cups_remote_port [rand_port]
7474					set crp "DAEMON-$cups_remote_port"
7475				}
7476				set sshcmd "$sshcmd -env FD_CUPS=$crp"
7477			}
7478			if {$use_cups && $cups_x11vnc && $cups_remote_smb_port != ""} {
7479				set csp $cups_remote_smb_port
7480				if {$ts_only} {
7481					set cups_remote_smb_port [rand_port]
7482					set csp "DAEMON-$cups_remote_smb_port"
7483				}
7484				set sshcmd "$sshcmd -env FD_SMB=$csp"
7485			}
7486			if {$use_sound && $sound_daemon_x11vnc && $sound_daemon_remote_port != ""} {
7487				set srp $sound_daemon_remote_port
7488				if {$ts_only} {
7489					set sound_daemon_remote_port [rand_port]
7490					set srp "DAEMON-$sound_daemon_remote_port"
7491				}
7492				set sshcmd "$sshcmd -env FD_ESD=$srp"
7493			}
7494		}
7495
7496		if {$sshcmd == "SHELL"} {
7497			set env(SS_VNCVIEWER_SSH_CMD) {$SHELL}
7498			set env(SS_VNCVIEWER_SSH_ONLY) 1
7499		} elseif {$setup_cmds != ""} {
7500			if {$sshcmd == ""} {
7501				set sshcmd "sleep 15"
7502			}
7503			set env(SS_VNCVIEWER_SSH_CMD) "$setup_cmds$sshcmd"
7504		} else {
7505			if {$sshcmd != ""} {
7506				set cmd "$cmd -sshcmd '$sshcmd'"
7507			}
7508		}
7509
7510		set sshargs ""
7511		if {$use_cups} {
7512			append sshargs [get_cups_redir]
7513		}
7514		if {$use_sound} {
7515			append sshargs [get_sound_redir]
7516		}
7517		if {$additional_port_redirs} {
7518			append sshargs [get_additional_redir]
7519		}
7520
7521		set sshargs [string trim $sshargs]
7522		if {$skip_ssh} {
7523			set sshargs ""
7524		}
7525		if {$sshargs != ""} {
7526			set cmd "$cmd -sshargs '$sshargs'"
7527			set env(SS_VNCVIEWER_USE_C) 1
7528		} else {
7529			# hmm we used to have it off... why?
7530			# ssh typing response?
7531			set env(SS_VNCVIEWER_USE_C) 1
7532		}
7533		if {$sshcmd == "SHELL"} {
7534			set env(SS_VNCVIEWER_SSH_ONLY) 1
7535			if {$proxy == ""} {
7536				set hpt $hpnew
7537				# XXX host_part
7538				regsub {:[0-9][0-9]*$} $hpt "" hpt
7539				set cmd "$cmd -proxy '$hpt'"
7540			}
7541			set geometry [xterm_center_geometry]
7542			if {$pk_hp == ""} {
7543				set pk_hp $hp
7544			}
7545			if {! $did_port_knock} {
7546				if {! [do_port_knock $pk_hp start]} {
7547					reset_stunnel_extra_opts
7548					return
7549				}
7550				set did_port_knock 1
7551			}
7552
7553			if {[regexp {FINISH} $port_knocking_list]} {
7554				wm withdraw .
7555				update
7556				unix_terminal_cmd $geometry "SHELL to $hp" "$cmd"
7557				wm deiconify .
7558				update
7559				do_port_knock $pk_hp finish
7560			} else {
7561				unix_terminal_cmd $geometry "SHELL to $hp" "$cmd" 1
7562			}
7563			set env(SS_VNCVIEWER_SSH_CMD) ""
7564			set env(SS_VNCVIEWER_SSH_ONLY) ""
7565			set env(SS_VNCVIEWER_USE_C) ""
7566			reset_stunnel_extra_opts
7567			return
7568		}
7569	} else {
7570		set cmd "ssvnc_cmd"
7571		set hpnew  [get_ssh_hp $hp]
7572		set proxy  [get_ssh_proxy $hp]
7573
7574		if {!$do_direct && ![repeater_proxy_check $proxy]} {
7575			reset_stunnel_extra_opts
7576			return
7577		}
7578
7579		if {! $do_direct && ! $ultra_dsm && ![regexp -nocase {ssh://} $hpnew]} {
7580			set did_check 0
7581			if {$mycert != ""} {
7582				set cmd "$cmd -mycert '$mycert'"
7583			}
7584			if {$crlfil != ""} {
7585				set cmd "$cmd -crl '$crlfil'"
7586			}
7587			if {$svcert != ""} {
7588				set cmd "$cmd -verify '$svcert'"
7589			} elseif {$crtdir != ""} {
7590				if {$crtdir == "ACCEPTED_CERTS"} {
7591					global skip_verify_accepted_certs
7592					set skip_verify_accepted_certs 0
7593
7594					set did_check 1
7595					if {! [check_accepted_certs 0]} {
7596						reset_stunnel_extra_opts
7597						return
7598					}
7599					if {! $skip_verify_accepted_certs} {
7600						set adir [get_idir_certs ""]
7601						set adir "$adir/accepted"
7602						catch {file mkdir $adir}
7603						set cmd "$cmd -verify '$adir'"
7604					}
7605
7606				} else {
7607					set cmd "$cmd -verify '$crtdir'"
7608				}
7609			}
7610			if {! $did_check} {
7611				check_accepted_certs 1
7612			}
7613		}
7614
7615		if {!$do_direct} {
7616			set proxy [maybe_add_vencrypt $proxy $hp]
7617		}
7618
7619		if {$proxy != ""} {
7620			set cmd "$cmd -proxy '$proxy'"
7621		}
7622		set hp $hpnew
7623		if [regexp {^.*@} $hp match] {
7624			catch {raise .; update}
7625			mesg "Trimming \"$match\" from hostname"
7626			after 700
7627			regsub {^.*@} $hp "" hp
7628		}
7629		if [regexp {@} $proxy] {
7630			bell
7631			catch {raise .; update}
7632			mesg "WARNING: SSL proxy contains \"@\" sign"
7633			after 1500
7634		}
7635	}
7636
7637	global anon_dh_detected
7638	if {$anon_dh_detected || $server_anondh} {
7639		if {!$do_direct} {
7640			set cmd "$cmd -anondh"
7641		}
7642		set anon_dh_detected 0
7643	}
7644	if {$use_alpha} {
7645		set cmd "$cmd -alpha"
7646	}
7647	if {$use_send_clipboard} {
7648		set cmd "$cmd -sendclipboard"
7649	}
7650	if {$use_send_always} {
7651		set cmd "$cmd -sendalways"
7652	}
7653	if {$use_turbovnc} {
7654		set env(SSVNC_TURBOVNC) 1
7655	}
7656	if {$disable_pipeline} {
7657		set env(VNCVIEWER_NO_PIPELINE_UPDATES) 1
7658	}
7659	if {$ssh_known_hosts_filename != ""} {
7660		set env(SSVNC_KNOWN_HOSTS_FILE) $ssh_known_hosts_filename
7661	}
7662	if {$use_grab} {
7663		set cmd "$cmd -grab"
7664	}
7665	if {$use_x11cursor} {
7666		set cmd "$cmd -x11cursor"
7667	}
7668	if {$use_nobell} {
7669		set cmd "$cmd -nobell"
7670	}
7671	if {$use_rawlocal} {
7672		set cmd "$cmd -rawlocal"
7673	}
7674	if {$use_notty} {
7675		set env(VNCVIEWER_NOTTY) 1
7676	}
7677	if {$use_popupfix} {
7678		set cmd "$cmd -popupfix"
7679	}
7680	if {$ssvnc_scale != ""} {
7681		set cmd "$cmd -scale '$ssvnc_scale'"
7682	}
7683	if {$ssvnc_escape != ""} {
7684		set cmd "$cmd -escape '$ssvnc_escape'"
7685	}
7686	if {$ssvnc_encodings != ""} {
7687		set cmd "$cmd -ssvnc_encodings '$ssvnc_encodings'"
7688	}
7689	if {$ssvnc_extra_opts != ""} {
7690		set cmd "$cmd -ssvnc_extra_opts '$ssvnc_extra_opts'"
7691	}
7692	if {$rfbversion != ""} {
7693		set cmd "$cmd -rfbversion '$rfbversion'"
7694	}
7695	if {$vncviewer_realvnc4} {
7696		set cmd "$cmd -realvnc4"
7697	}
7698	if {$use_listen} {
7699		set cmd "$cmd -listen"
7700		if {$listen_once} {
7701			set cmd "$cmd -onelisten"
7702		}
7703		if {$listen_accept_popup} {
7704			if {$listen_accept_popup_sc} {
7705				set env(SSVNC_ACCEPT_POPUP_SC) 1
7706			} else {
7707				set env(SSVNC_ACCEPT_POPUP) 1
7708			}
7709		}
7710	}
7711
7712	global darwin_cotvnc
7713	if {$darwin_cotvnc} {
7714		set env(DARWIN_COTVNC) 1
7715	} else {
7716		if [info exists env(DISPLAY)] {
7717			if {$env(DISPLAY) != ""} {
7718				set env(DARWIN_COTVNC) 0
7719			} else {
7720				set env(DARWIN_COTVNC) 1
7721			}
7722		} else {
7723			set env(DARWIN_COTVNC) 1
7724		}
7725	}
7726
7727	set do_vncspacewrapper 0
7728	if {$change_vncviewer && $change_vncviewer_path != ""} {
7729		set path [string trim $change_vncviewer_path]
7730		if [regexp {^["'].} $path]  {	# "
7731			set tmp "/tmp/vncspacewrapper.[tpid]"
7732			set tmp [mytmp $tmp]
7733			set do_vncspacewrapper 1
7734			if {0} {
7735				catch {file delete $tmp}
7736				if {[file exists $tmp]} {
7737					catch {destroy .c}
7738					mesg "file still exists: $tmp"
7739					bell
7740					reset_stunnel_extra_opts
7741					return
7742				}
7743			}
7744			catch {set fh [open $tmp "w"]}
7745			catch {exec chmod 700 $tmp}
7746			if {! [file exists $tmp]} {
7747				catch {destroy .c}
7748				mesg "cannot create: $tmp"
7749				bell
7750				reset_stunnel_extra_opts
7751				return
7752			}
7753			puts $fh "#!/bin/sh"
7754			puts $fh "echo $tmp; set -xv"
7755			puts $fh "$path \"\$@\""
7756			puts $fh "sleep 1; rm -f $tmp"
7757			close $fh
7758			set path $tmp
7759		}
7760		set env(VNCVIEWERCMD) $path
7761	} else {
7762		if [info exists env(VNCVIEWERCMD_OVERRIDE)] {
7763			set env(VNCVIEWERCMD) $env(VNCVIEWERCMD_OVERRIDE)
7764		} else {
7765			set env(VNCVIEWERCMD) ""
7766		}
7767	}
7768
7769	set realvnc4 $vncviewer_realvnc4
7770	set realvnc3 0
7771	set flavor ""
7772	if {! $darwin_cotvnc} {
7773		set done 0
7774		if {$do_vncspacewrapper} {
7775			if [regexp -nocase {ultra} $change_vncviewer_path] {
7776				set done 1
7777				set flavor "ultravnc"
7778			} elseif [regexp -nocase {chicken.of} $change_vncviewer_path] {
7779				set done 1
7780				set flavor "cotvnc"
7781			}
7782		}
7783		if {! $done} {
7784			catch {set flavor [exec ss_vncviewer -viewerflavor 2>/dev/null]}
7785		}
7786	}
7787	if [regexp {realvnc4} $flavor] {
7788		set realvnc4 1
7789	}
7790	if [regexp {tightvnc} $flavor] {
7791		set realvnc4 0
7792	}
7793	if [regexp {realvnc3} $flavor] {
7794		set realvnc4 0
7795		set realvnc3 1
7796	}
7797	if {$realvnc4} {
7798		set cmd "$cmd -realvnc4"
7799	}
7800
7801	set cmd "$cmd $hp"
7802
7803	set passwdfile ""
7804	if {$vncauth_passwd != ""} {
7805		global use_listen
7806		set footest [mytmp /tmp/.check.[tpid]]
7807		catch {file delete $footest}
7808		global mktemp
7809		set passwdfile "/tmp/.vncauth_tmp.[tpid]"
7810		if {$mktemp == ""} {
7811			set passwdfile "$env(SSVNC_HOME)/.vncauth_tmp.[tpid]"
7812		}
7813
7814		set passwdfile [mytmp $passwdfile]
7815		catch {exec vncstorepw $vncauth_passwd $passwdfile}
7816		catch {exec chmod 600 $passwdfile}
7817		if {$use_listen} {
7818			global env
7819			set env(SS_VNCVIEWER_RM) $passwdfile
7820		} else {
7821			if {$darwin_cotvnc} {
7822				catch {exec sh -c "sleep 60; rm $passwdfile 2>/dev/null" &}
7823			} else {
7824				catch {exec sh -c "sleep 20; rm $passwdfile 2>/dev/null" &}
7825			}
7826		}
7827		if {$darwin_cotvnc} {
7828			set cmd "$cmd --PasswordFile $passwdfile"
7829		} elseif {$flavor == "unknown"} {
7830			;
7831		} else {
7832			set cmd "$cmd -passwd $passwdfile"
7833		}
7834	}
7835
7836	if {$use_viewonly} {
7837		if {$darwin_cotvnc} {
7838			set cmd "$cmd --ViewOnly"
7839		} elseif {$flavor == "unknown"} {
7840			;
7841		} elseif {$flavor == "ultravnc"} {
7842			set cmd "$cmd /viewonly"
7843		} else {
7844			set cmd "$cmd -viewonly"
7845		}
7846	}
7847	if {$use_fullscreen} {
7848		if {$darwin_cotvnc} {
7849			set cmd "$cmd --FullScreen"
7850		} elseif {$flavor == "ultravnc"} {
7851			set cmd "$cmd /fullscreen"
7852		} elseif {$flavor == "unknown"} {
7853			if [regexp {vinagre} $change_vncviewer_path] {
7854				set cmd "$cmd -f"
7855			}
7856		} else {
7857			set cmd "$cmd -fullscreen"
7858		}
7859	}
7860	if {$use_bgr233} {
7861		if {$realvnc4} {
7862			set cmd "$cmd -lowcolourlevel 1"
7863		} elseif {$flavor == "ultravnc"} {
7864			set cmd "$cmd /8bit"
7865		} elseif {$flavor == "ultravnc"} {
7866			;
7867		} elseif {$flavor == "unknown"} {
7868			;
7869		} else {
7870			set cmd "$cmd -bgr233"
7871		}
7872	}
7873	if {$use_nojpeg} {
7874		if {$darwin_cotvnc} {
7875			;
7876		} elseif {$flavor == "ultravnc"} {
7877			;
7878		} elseif {$flavor == "unknown"} {
7879			;
7880		} elseif {! $realvnc4 && ! $realvnc3} {
7881			set cmd "$cmd -nojpeg"
7882		}
7883	}
7884	if {! $use_raise_on_beep} {
7885		if {$darwin_cotvnc} {
7886			;
7887		} elseif {$flavor == "ultravnc"} {
7888			;
7889		} elseif {$flavor == "unknown"} {
7890			;
7891		} elseif {! $realvnc4 && ! $realvnc3} {
7892			set cmd "$cmd -noraiseonbeep"
7893		}
7894	}
7895	if {$use_compresslevel != "" && $use_compresslevel != "default"} {
7896		if {$realvnc3} {
7897			;
7898		} elseif {$flavor == "ultravnc"} {
7899			;
7900		} elseif {$flavor == "unknown"} {
7901			;
7902		} elseif {$realvnc4} {
7903			set cmd "$cmd -zliblevel '$use_compresslevel'"
7904		} else {
7905			set cmd "$cmd -compresslevel '$use_compresslevel'"
7906		}
7907	}
7908	if {$use_quality != "" && $use_quality != "default"} {
7909		if {$darwin_cotvnc} {
7910			;
7911		} elseif {$flavor == "ultravnc"} {
7912			;
7913		} elseif {$flavor == "unknown"} {
7914			;
7915		} elseif {! $realvnc4 && ! $realvnc3} {
7916			set cmd "$cmd -quality '$use_quality'"
7917		}
7918	}
7919	if {$use_ssh || $use_sshssl} {
7920		# realvnc4 -preferredencoding zrle
7921		if {$darwin_cotvnc} {
7922			;
7923		} elseif {$flavor == "ultravnc"} {
7924			;
7925		} elseif {$flavor == "unknown"} {
7926			;
7927		} elseif {$realvnc4} {
7928			set cmd "$cmd -preferredencoding zrle"
7929		} else {
7930			set cmd "$cmd -encodings 'copyrect tight zrle zlib hextile'"
7931		}
7932	}
7933
7934	global ycrop_string
7935	global sbwid_string
7936	catch {unset env(VNCVIEWER_SBWIDTH)}
7937	catch {unset env(VNCVIEWER_YCROP)}
7938	if {[info exists ycrop_string] && $ycrop_string != ""}  {
7939		set t $ycrop_string
7940		if [regexp {,sb=([0-9][0-9]*)} $t m mv1]  {
7941			set env(VNCVIEWER_SBWIDTH) $mv1
7942		}
7943		regsub {,sb=([0-9][0-9]*)} $t "" t
7944		if {$t != ""} {
7945			set env(VNCVIEWER_YCROP) $t
7946		}
7947	}
7948	if {[info exists sbwid_string] && $sbwid_string != ""}  {
7949		set t $sbwid_string
7950		set env(VNCVIEWER_SBWIDTH) $sbwid_string
7951		if {$t != ""} {
7952			set env(VNCVIEWER_SBWIDTH) $t
7953		}
7954	}
7955
7956	catch {destroy .o}
7957	catch {destroy .oa}
7958	catch {destroy .os}
7959	update
7960
7961	if {$use_sound && $sound_daemon_local_start && $sound_daemon_local_cmd != ""} {
7962		mesg "running: $sound_daemon_local_cmd"
7963		global sound_daemon_local_pid
7964		set sound_daemon_local_pid ""
7965		#exec sh -c "$sound_daemon_local_cmd " >& /dev/null </dev/null &
7966		set sound_daemon_local_pid [exec sh -c "echo \$\$; exec $sound_daemon_local_cmd </dev/null 1>/dev/null 2>/dev/null &"]
7967		update
7968		after 500
7969	}
7970
7971	if {$pk_hp == ""} {
7972		set pk_hp $hp
7973	}
7974	if {! $did_port_knock} {
7975		if {! [do_port_knock $pk_hp start]} {
7976			wm deiconify .
7977			update
7978			reset_stunnel_extra_opts
7979			return
7980		}
7981		set did_port_knock 1
7982	}
7983
7984	init_unixpw $hp
7985
7986	if {! $do_direct} {
7987		vencrypt_tutorial_mesg
7988	}
7989
7990	wm withdraw .
7991	update
7992
7993	set geometry [xterm_center_geometry]
7994	set xrm1 "*.srinterCommand:true"
7995	set xrm2 $xrm1
7996	set xrm3 $xrm1
7997	if {[info exists env(SSVNC_GUI_CMD)]} {
7998		set xrm1 "*.printerCommand:env XTERM_PRINT=1 $env(SSVNC_GUI_CMD)"
7999		set xrm2 "XTerm*VT100*translations:#override Shift<Btn3Down>:print()\\nCtrl<Key>N:print()"
8000		set xrm3 "*mainMenu*print*Label:  New SSVNC_GUI"
8001	}
8002	set m "Done. You Can X-out or Ctrl-C this Terminal if you like.  Use Ctrl-\\\\ to pause."
8003	global uname
8004	if {$uname == "Darwin"} {
8005		regsub {X-out or } $m "" m
8006	}
8007	set te "set -xv; "
8008	if {$ts_only} {
8009		set te ""
8010	}
8011
8012	global extra_sleep
8013	set ssvnc_extra_sleep_save ""
8014	if {$extra_sleep != ""} {
8015		if [info exists env(SSVNC_EXTRA_SLEEP)] {
8016			set ssvnc_extra_sleep_save $env(SSVNC_EXTRA_SLEEP)
8017		}
8018		set env(SSVNC_EXTRA_SLEEP) $extra_sleep
8019	}
8020
8021	set sstx "SSL/SSH VNC Viewer"
8022	set hptx $hp
8023	global use_listen
8024	if {$use_listen} {
8025		set sstx "SSVNC"
8026		set hptx "$hp (Press Ctrl-C to Stop Listening)"
8027	}
8028
8029
8030	set s1 5
8031	set s2 4
8032	if [info exists env(SSVNC_FINISH_SLEEP)] {
8033		set s1 $env(SSVNC_FINISH_SLEEP);
8034		set s2 $s1
8035	}
8036
8037	unix_terminal_cmd $geometry "$sstx $hptx" \
8038	"$te$cmd; set +xv; ulimit -c 0; trap 'printf \"Paused. Press Enter to exit:\"; read x' QUIT; echo; echo $m; echo; echo sleep $s1; echo; sleep $s2" 0 $xrm1 $xrm2 $xrm3
8039
8040	set env(SS_VNCVIEWER_SSH_CMD) ""
8041	set env(SS_VNCVIEWER_USE_C) ""
8042
8043	if {$extra_sleep != ""} {
8044		if {$ssvnc_extra_sleep_save != ""} {
8045			set env(SSVNC_EXTRA_SLEEP) $ssvnc_extra_sleep_save
8046		} else {
8047			catch {unset env(SSVNC_EXTRA_SLEEP)}
8048		}
8049	}
8050
8051	if {$use_sound && $sound_daemon_local_kill && $sound_daemon_local_cmd != ""} {
8052		# XXX need to kill just one...
8053		set daemon [string trim $sound_daemon_local_cmd]
8054		regsub {^gw[ \t]*} $daemon "" daemon
8055		regsub {[ \t].*$} $daemon "" daemon
8056		regsub {^.*/} $daemon "" daemon
8057		mesg "killing sound daemon: $daemon"
8058		global sound_daemon_local_pid
8059		if {$sound_daemon_local_pid != ""} {
8060#puts pid=$sound_daemon_local_pid
8061			catch {exec sh -c "kill $sound_daemon_local_pid"  >/dev/null 2>/dev/null </dev/null &}
8062			incr sound_daemon_local_pid
8063			catch {exec sh -c "kill $sound_daemon_local_pid"  >/dev/null 2>/dev/null </dev/null &}
8064			set sound_daemon_local_pid ""
8065		} elseif {$daemon != ""} {
8066			catch {exec sh -c "killall $daemon"  >/dev/null 2>/dev/null </dev/null &}
8067			catch {exec sh -c "pkill -x $daemon" >/dev/null 2>/dev/null </dev/null &}
8068		}
8069	}
8070	if {$passwdfile != ""} {
8071		catch {file delete $passwdfile}
8072	}
8073	wm deiconify .
8074	mac_raise
8075	mesg "Disconnected from $hp"
8076	if {[regexp {FINISH} $port_knocking_list]} {
8077		do_port_knock $pk_hp finish
8078	}
8079
8080	reset_stunnel_extra_opts
8081
8082	fini_unixpw
8083}
8084
8085proc kill_stunnel {pids} {
8086	set count 0
8087	foreach pid $pids {
8088		mesg "killing STUNNEL pid: $pid"
8089		winkill $pid
8090		if {$count == 0} {
8091			after 600
8092		} else {
8093			after 300
8094		}
8095		incr count
8096	}
8097}
8098
8099proc get_task_list {} {
8100	global is_win9x
8101
8102	set output1 ""
8103	set output2 ""
8104	if {! $is_win9x} {
8105		# try for tasklist on XP pro
8106		catch {set output1 [exec tasklist.exe]}
8107	}
8108	catch {set output2 [exec w98/tlist.exe]}
8109
8110	set output $output1
8111	append output "\n"
8112	append output $output2
8113
8114	return $output
8115}
8116
8117proc note_stunnel_pids {when} {
8118	global is_win9x pids_before pids_after pids_new
8119
8120	if {$when == "before"} {
8121		array unset pids_before
8122		array unset pids_after
8123		set pids_new {}
8124		set pids_before(none) "none"
8125		set pids_after(none)  "none"
8126	}
8127
8128	set output [get_task_list]
8129
8130	foreach line [split $output "\n\r"] {
8131		set m 0
8132		if [regexp -nocase {stunnel} $line] {
8133			set m 1
8134		} elseif [regexp -nocase {connect_br} $line] {
8135			set m 1
8136		}
8137		if {$m} {
8138			if [regexp {(-?[0-9][0-9]*)} $line m p] {
8139				if {$when == "before"} {
8140					set pids_before($p) $line
8141				} else {
8142					set pids_after($p) $line
8143				}
8144			}
8145		}
8146	}
8147	if {$when == "after"} {
8148		foreach new [array names pids_after] {
8149			if {! [info exists pids_before($new)]} {
8150				lappend pids_new $new
8151			}
8152		}
8153	}
8154}
8155
8156proc del_launch_windows_ssh_files {} {
8157	global launch_windows_ssh_files
8158	global env
8159
8160	if {[info exists env(SSVNC_NO_DELETE)]} {
8161		return
8162	}
8163
8164	if {$launch_windows_ssh_files != ""} {
8165		foreach tf [split $launch_windows_ssh_files] {
8166			if {$tf == ""} {
8167				continue
8168			}
8169			catch {file delete $tf}
8170		}
8171	}
8172}
8173
8174proc launch_shell_only {} {
8175	global is_windows
8176	global skip_pre
8177	global use_ssl use_ssh use_sshssl
8178
8179	set hp [get_vncdisplay]
8180	regsub {cmd=.*$} $hp "" hp
8181	set hp [string trim $hp]
8182	if {$is_windows} {
8183		append hp " cmd=PUTTY"
8184	} else {
8185		append hp " cmd=SHELL"
8186	}
8187	set use_ssl_save $use_ssl
8188	set use_ssh_save $use_ssh
8189	set use_sshssl_save $use_sshssl
8190	set skip_pre 1
8191	if {! $use_ssh && ! $use_sshssl} {
8192		set use_ssh 1
8193		set use_ssl 1
8194	}
8195	launch $hp
8196
8197	set use_ssl $use_ssl_save
8198	set use_ssh $use_ssh_save
8199	set use_sshssl $use_sshssl_save
8200}
8201
8202proc to_sshonly {} {
8203	global ssh_only ts_only env
8204	global showing_no_encryption
8205	#if {$showing_no_encryption} {
8206	#	toggle_no_encryption
8207	#}
8208	if {$ssh_only && !$ts_only} {
8209		return
8210	}
8211	if {[info exists env(SSVNC_TS_ALWAYS)]} {
8212		return
8213	}
8214	set ssh_only 1
8215	set ts_only 0
8216
8217	set t "SSH VNC Viewer"
8218	wm title . $t
8219	catch {pack forget .f4}
8220	catch {pack forget .b.certs}
8221	catch {.l configure -text $t}
8222
8223	global vncdisplay vncauth_passwd unixpw_username vncproxy remote_ssh_cmd
8224	set vncdisplay ""
8225	set vncauth_passwd ""
8226	set unixpw_username ""
8227	set vncproxy ""
8228	set remote_ssh_cmd ""
8229
8230	set_defaults
8231}
8232
8233proc toggle_tsonly {} {
8234	global ts_only env
8235	if {$ts_only} {
8236		if {![info exists env(SSVNC_TS_ALWAYS)]} {
8237			to_ssvnc
8238		}
8239	} else {
8240		to_tsonly
8241	}
8242}
8243
8244proc toggle_sshonly {} {
8245	global ssh_only env
8246	if {$ssh_only} {
8247		to_ssvnc
8248	} else {
8249		to_sshonly
8250	}
8251}
8252
8253proc to_tsonly {} {
8254	global ts_only
8255	global showing_no_encryption
8256	#if {$showing_no_encryption} {
8257	#	toggle_no_encryption
8258	#}
8259	if {$ts_only} {
8260		return
8261	}
8262	set ts_only 1
8263	set ssh_only 1
8264
8265	set t "Terminal Services VNC Viewer"
8266	wm title . $t
8267	catch {pack forget .f4}
8268	catch {pack forget .f3}
8269	catch {pack forget .f1}
8270	catch {pack forget .b.certs}
8271	catch {.l configure -text $t}
8272	catch {.f0.l configure -text "VNC Terminal Server:"}
8273
8274	global vncdisplay vncauth_passwd unixpw_username vncproxy remote_ssh_cmd
8275	set vncdisplay ""
8276	set vncauth_passwd ""
8277	set unixpw_username ""
8278	set vncproxy ""
8279	set remote_ssh_cmd ""
8280
8281	set_defaults
8282}
8283
8284proc to_ssvnc {} {
8285	global ts_only ssh_only env
8286
8287	if {!$ts_only && !$ssh_only} {
8288		return;
8289	}
8290	if {[info exists env(SSVNC_TS_ALWAYS)]} {
8291		return
8292	}
8293	set ts_only 0
8294	set ssh_only 0
8295
8296	set t "SSL/SSH VNC Viewer"
8297	wm title . $t
8298	catch {pack configure .f1 -after .f0 -side top -fill x}
8299	catch {pack configure .f3 -after .f2 -side top -fill x}
8300	catch {pack configure .f4 -after .f3 -side top -fill x}
8301	catch {pack configure .b.certs -before .b.opts -side left -expand 1 -fill x}
8302	catch {.l configure -text $t}
8303	catch {.f0.l configure -text "VNC Host:Display"}
8304
8305	#global started_with_noenc
8306	#if {$started_with_noenc} {
8307	#	toggle_no_encryption
8308	#}
8309
8310	global vncdisplay vncauth_passwd unixpw_username vncproxy remote_ssh_cmd
8311	set vncdisplay ""
8312	set vncauth_passwd ""
8313	set unixpw_username ""
8314	set vncproxy ""
8315	set remote_ssh_cmd ""
8316
8317	set_defaults
8318}
8319
8320proc launch {{hp ""}} {
8321	global tcl_platform is_windows
8322	global mycert svcert crtdir crlfil
8323	global pids_before pids_after pids_new
8324	global env
8325	global use_ssl use_ssh use_sshssl sshssl_sw use_listen disable_ssl_workarounds
8326	global vncdisplay
8327
8328	set debug 0
8329	if {$hp == ""} {
8330		set hp [get_vncdisplay]
8331	}
8332
8333	set hpt [string trim $hp]
8334	regsub {[ 	].*$} $hpt "" hpt
8335
8336
8337	if {[regexp {^HOME=} $hpt] || [regexp {^SSVNC_HOME=} $hpt]} {
8338		set t $hpt
8339		regsub {^.*HOME=} $t "" t
8340		set t [string trim $t]
8341		set env(SSVNC_HOME) $t
8342		mesg "Set SSVNC_HOME to $t"
8343		set vncdisplay ""
8344		return 0
8345	}
8346	if {[regexp {^DISPLAY=} $hpt] || [regexp {^SSVNC_DISPLAY=} $hpt]} {
8347		set t $hpt
8348		regsub {^.*DISPLAY=} $t "" t
8349		set t [string trim $t]
8350		set env(DISPLAY) $t
8351		mesg "Set DISPLAY to $t"
8352		set vncdisplay ""
8353		global uname darwin_cotvnc
8354		if {$uname == "Darwin"} {
8355			if {$t != ""} {
8356				set darwin_cotvnc 0
8357			} else {
8358				set darwin_cotvnc 1
8359			}
8360		}
8361		return 0
8362	}
8363	if {[regexp {^DYLD_LIBRARY_PATH=} $hpt] || [regexp {^SSVNC_DYLD_LIBRARY_PATH=} $hpt]} {
8364		set t $hpt
8365		regsub {^.*DYLD_LIBRARY_PATH=} $t "" t
8366		set t [string trim $t]
8367		set env(DYLD_LIBRARY_PATH) $t
8368		set env(SSVNC_DYLD_LIBRARY_PATH) $t
8369		mesg "Set DYLD_LIBRARY_PATH to $t"
8370		set vncdisplay ""
8371		return 0
8372	}
8373	if {[regexp {^SLEEP=} $hpt] || [regexp {^SSVNC_EXTRA_SLEEP=} $hpt]} {
8374		set t $hpt
8375		regsub {^.*SLEEP=} $t "" t
8376		set t [string trim $t]
8377		set env(SSVNC_EXTRA_SLEEP) $t
8378		mesg "Set SSVNC_EXTRA_SLEEP to $t"
8379		set vncdisplay ""
8380		return 0
8381	}
8382	if {[regexp {^SSH=} $hpt]} {
8383		set t $hpt
8384		regsub {^.*SSH=} $t "" t
8385		set t [string trim $t]
8386		set env(SSH) $t
8387		mesg "Set SSH to $t"
8388		set vncdisplay ""
8389		return 0
8390	}
8391	if {[regexp {^FINISH=} $hpt] || [regexp {^SSVNC_FINISH_SLEEP=} $hpt]} {
8392		set t $hpt
8393		regsub {^.*=} $t "" t
8394		set t [string trim $t]
8395		set env(SSVNC_FINISH_SLEEP) $t
8396		mesg "Set SSVNC_FINISH_SLEEP to $t"
8397		set vncdisplay ""
8398		return 0
8399	}
8400	if {[regexp {^NO_DELETE=} $hpt] || [regexp {^SSVNC_NO_DELETE=} $hpt]} {
8401		set t $hpt
8402		regsub {^.*=} $t "" t
8403		set t [string trim $t]
8404		set env(SSVNC_NO_DELETE) $t
8405		mesg "Set SSVNC_NO_DELETE to $t"
8406		set vncdisplay ""
8407		return 0
8408	}
8409	if {[regexp {^BAT_SLEEP=} $hpt] || [regexp {^SSVNC_BAT_SLEEP=} $hpt]} {
8410		set t $hpt
8411		regsub {^.*=} $t "" t
8412		set t [string trim $t]
8413		set env(SSVNC_BAT_SLEEP) $t
8414		mesg "Set SSVNC_BAT_SLEEP to $t"
8415		set vncdisplay ""
8416		return 0
8417	}
8418	if {[regexp {^DEBUG_NETSTAT=} $hpt]} {
8419		set t $hpt
8420		regsub {^.*DEBUG_NETSTAT=} $t "" t
8421		global debug_netstat
8422		set debug_netstat $t
8423		mesg "Set DEBUG_NETSTAT to $t"
8424		set vncdisplay ""
8425		return 0
8426	}
8427	if {[regexp {^REPEATER_FORCE=} $hpt]} {
8428		set t $hpt
8429		regsub {^.*REPEATER_FORCE=} $t "" t
8430		set env(REPEATER_FORCE) $t
8431		mesg "Set REPEATER_FORCE to $t"
8432		set vncdisplay ""
8433		return 0
8434	}
8435	if {[regexp -nocase {^SSH.?ONLY} $hpt]} {
8436		global ssh_only
8437		if {$ssh_only} {
8438			return 0;
8439		}
8440		to_sshonly
8441
8442		return 0
8443	}
8444	if {[regexp -nocase {^TS.?ONLY} $hpt]} {
8445		global ts_only
8446		if {$ts_only} {
8447			return 0;
8448		}
8449		to_tsonly
8450
8451		return 0
8452	}
8453	if {[regexp -nocase {^IPV6=([01])} $hpt mv val]} {
8454		global env have_ipv6
8455		set have_ipv6 $val
8456		set env(SSVNC_IPV6) $val
8457		mesg "Set have_ipv6 to $val"
8458		set vncdisplay ""
8459		return 0
8460	}
8461	if {[regexp {^ENV=([A-z0-9][A-z0-9]*)=(.*)$} $hpt mv var val]} {
8462		global env
8463		if {$val == ""} {
8464			catch {unset env($var)}
8465			mesg "Unset $var"
8466		} else {
8467			set env($var) "$val"
8468			mesg "Set $var to $val"
8469		}
8470		set vncdisplay ""
8471		return 0
8472	}
8473
8474	regsub {[ 	]*cmd=.*$} $hp "" tt
8475
8476	if {[regexp {^[ 	]*$} $tt]} {
8477		mesg "No host:disp supplied."
8478		bell
8479		catch {raise .}
8480		mac_raise
8481		return
8482	}
8483	if {[regexp -- {--nohost--} $tt]} {
8484		mesg "No host:disp supplied."
8485		bell
8486		catch {raise .}
8487		mac_raise
8488		return
8489	}
8490	# XXX host_part
8491	if {! [regexp ":" $hp]} {
8492		if {! [regexp {cmd=} $hp]} {
8493			set s [string trim $hp]
8494			if {! [regexp { } $s]} {
8495				append hp ":0"
8496			} else {
8497				regsub { } $hp ":0 " hp
8498			}
8499		}
8500	}
8501
8502	if {!$use_ssl && !$use_ssh && !$use_sshssl && $sshssl_sw == "none"} {
8503		regsub -nocase {^[a-z0-9+]*://}	$hp "" hp
8504		set hp "Vnc://$hp"
8505	}
8506
8507	mesg "Using: $hp"
8508	after 600
8509
8510	set sc [get_ssh_cmd $hp]
8511	if {[regexp {^KNOCK} $sc]} {
8512		if [regexp {^KNOCKF} $sc] {
8513			port_knock_only $hp "FINISH"
8514		} else {
8515			port_knock_only $hp "KNOCK"
8516		}
8517		return
8518	}
8519
8520	if {$debug} {
8521		mesg "\"$tcl_platform(os)\" | \"$tcl_platform(osVersion)\""
8522		after 1000
8523	}
8524
8525	if [regexp {V[Nn][Cc]://} $hp] {
8526		set env(SSVNC_NO_ENC_WARN) 1
8527		regsub {V[Nn][Cc]://} $hp "vnc://" hp
8528	}
8529	regsub -nocase {^vnc://}	$hp "vnc://" hp
8530	regsub -nocase {^vncs://}	$hp "vncs://" hp
8531	regsub -nocase {^vncssl://}	$hp "vncssl://" hp
8532	regsub -nocase {^vnc\+ssl://}	$hp "vnc+ssl://" hp
8533	regsub -nocase {^vncssh://}	$hp "vncssh://" hp
8534	regsub -nocase {^vnc\+ssh://}	$hp "vnc+ssh://" hp
8535
8536	if {! $is_windows} {
8537		launch_unix $hp
8538		return
8539	}
8540
8541	##############################################################
8542	# WINDOWS BELOW:
8543
8544	if [regexp {^vnc://} $hp] {
8545		if {! [info exists env(SSVNC_NO_ENC_WARN)]} {
8546			direct_connect_msg
8547		}
8548		regsub {^vnc://} $hp "" hp
8549		direct_connect_windows $hp
8550		return
8551	} elseif [regexp {^vncs://} $hp] {
8552		set use_ssl 1
8553		set use_ssh 0
8554		regsub {^vncs://} $hp "" hp
8555		sync_use_ssl_ssh
8556	} elseif [regexp {^vncssl://} $hp] {
8557		set use_ssl 1
8558		set use_ssh 0
8559		regsub {^vncssl://} $hp "" hp
8560		sync_use_ssl_ssh
8561	} elseif [regexp {^vnc\+ssl://} $hp] {
8562		set use_ssl 1
8563		set use_ssh 0
8564		regsub {^vnc\+ssl://} $hp "" hp
8565		sync_use_ssl_ssh
8566	} elseif [regexp {^vncssh://} $hp] {
8567		set use_ssh 1
8568		set use_ssl 0
8569		regsub {vncssh://} $hp "" hp
8570		sync_use_ssl_ssh
8571	} elseif [regexp {^vnc\+ssh://} $hp] {
8572		set use_ssh 1
8573		set use_ssl 0
8574		regsub {^vnc\+ssh://} $hp "" hp
8575		sync_use_ssl_ssh
8576	}
8577
8578	check_ssh_needed
8579
8580	if {! $use_ssh} {
8581		if {$mycert != ""} {
8582			if {! [file exists $mycert]} {
8583				mesg "MyCert does not exist: $mycert"
8584				bell
8585				return
8586			}
8587		}
8588		if {$svcert != ""} {
8589			if {! [file exists $svcert]} {
8590				mesg "ServerCert does not exist: $svcert"
8591				bell
8592				return
8593			}
8594		} elseif {$crtdir != ""} {
8595			if {! [file exists $crtdir] && $crtdir != "ACCEPTED_CERTS"} {
8596				mesg "CertsDir does not exist: $crtdir"
8597				bell
8598				return
8599			}
8600		}
8601		if {$crlfil != ""} {
8602			if {! [file exists $crlfil]} {
8603				mesg "CRL File does not exist: $crlfil"
8604				bell
8605				return
8606			}
8607		}
8608	}
8609
8610	# VF
8611	set prefix "stunnel-vnc"
8612	set suffix "conf"
8613	if {$use_ssh || $use_sshssl} {
8614		set prefix "plink_vnc"
8615		set suffix "bat"
8616	}
8617
8618	set file1 ""
8619	set n1 ""
8620	set file2 ""
8621	set n2 ""
8622	set n3 ""
8623	set n4 ""
8624	set now [clock seconds]
8625
8626	set proxy [get_ssh_proxy $hp]
8627	if {$use_sshssl} {
8628		set proxy ""
8629	}
8630	if {! [repeater_proxy_check $proxy]} {
8631		return
8632	}
8633
8634	global port_slot
8635	if {$port_slot != ""} {
8636		set file1 "$prefix-$port_slot.$suffix"
8637		set n1 $port_slot
8638		set ps [expr $port_slot + 200]
8639		set file2 "$prefix-$ps.$suffix"
8640		set n2 $ps
8641		mesg "Using Port Slot: $port_slot"
8642		after 700
8643	}
8644
8645	for {set i 30} {$i <= 99} {incr i}  {
8646		set try "$prefix-$i.$suffix"
8647		if {$i == $port_slot} {
8648			continue
8649		}
8650		if {[file exists $try]}  {
8651			set mt [file mtime $try]
8652			set age [expr "$now - $mt"]
8653			set week [expr "7 * 3600 * 24"]
8654			if {$age > $week} {
8655				catch {file delete $try}
8656			}
8657		}
8658		if {! [file exists $try]}  {
8659			if {$file1 == ""} {
8660				set file1 $try
8661				set n1 $i
8662			} elseif {$file2 == ""} {
8663				set file2 $try
8664				set n2 $i
8665			} else {
8666				break
8667			}
8668		}
8669	}
8670
8671	if {$file1 == ""} {
8672		mesg "could not find free stunnel file"
8673		bell
8674		return
8675	}
8676
8677	if {$n1 == ""} {
8678		set n1 10
8679	}
8680	if {$n2 == ""} {
8681		set n2 11
8682	}
8683	set n3 [expr $n1 + 100]
8684	set n4 [expr $n2 + 100]
8685
8686	global launch_windows_ssh_files
8687	set launch_windows_ssh_files ""
8688
8689	set did_port_knock 0
8690
8691	global listening_name
8692	set listening_name ""
8693
8694	if {$use_ssh} {
8695		;
8696	} elseif {$use_sshssl} {
8697		;
8698	} elseif {$use_ssl} {
8699		if {$proxy != "" && [regexp {@} $proxy]} {
8700			mesg "Error: proxy contains '@'  Did you mean to use SSH mode?"
8701			bell
8702			return
8703		}
8704		if [regexp {@} $hp] {
8705			mesg "Error: host contains '@'  Did you mean to use SSH mode?"
8706			bell
8707			return
8708		}
8709	}
8710
8711	global ssh_ipv6_pid
8712	set ssh_ipv6_pid ""
8713
8714	if {$use_sshssl} {
8715		set rc [launch_windows_ssh $hp $file2 $n2]
8716		if {$rc == 0} {
8717			if {![info exists env(SSVNC_NO_DELETE)]} {
8718				catch {file delete $file1}
8719				catch {file delete $file2}
8720			}
8721			del_launch_windows_ssh_files
8722			return
8723		}
8724		set did_port_knock 1
8725	} elseif {$use_ssh} {
8726		launch_windows_ssh $hp $file1 $n1
8727		# WE ARE DONE.
8728		return
8729	}
8730
8731	set host [host_part $hp];
8732	set host_orig $host
8733
8734	global win_localhost
8735
8736	if {$host == ""} {
8737		set host $win_localhost
8738	}
8739
8740	if [regexp {^.*@} $host match] {
8741		catch {raise .; update}
8742		mesg "Trimming \"$match\" from hostname"
8743		after 700
8744		regsub {^.*@} $host "" host
8745	}
8746
8747	set disp [port_part $hp]
8748	if {[regexp {^-[0-9][0-9]*$} $disp]} {
8749		;
8750	} elseif {$disp == "" || ! [regexp {^[0-9][0-9]*$} $disp]} {
8751		set disp 0
8752	}
8753
8754	if {$disp < 0} {
8755		set port [expr "- $disp"]
8756	} elseif {$disp < 200} {
8757		if {$use_listen} {
8758			set port [expr "$disp + 5500"]
8759		} else {
8760			set port [expr "$disp + 5900"]
8761		}
8762	} else {
8763		set port $disp
8764	}
8765
8766	if {$debug} {
8767		mesg "file: $file1"
8768		after 1000
8769	}
8770
8771	listen_verify_all_dialog $hp
8772
8773	if {$use_listen && $mycert == ""} {
8774		if {! [check_for_listen_ssl_cert]} {
8775			return;
8776		}
8777	}
8778
8779	set fail 0
8780
8781	set fh [open $file1 "w"]
8782
8783	if {$use_listen} {
8784		puts $fh "client = no"
8785	} else {
8786		puts $fh "client = yes"
8787	}
8788	global disable_ssl_workarounds disable_ssl_workarounds_type
8789	if {$disable_ssl_workarounds} {
8790		if {$disable_ssl_workarounds_type == "noempty"} {
8791			puts $fh "options = DONT_INSERT_EMPTY_FRAGMENTS"
8792		}
8793	} else {
8794		puts $fh "options = ALL"
8795	}
8796
8797	puts $fh "taskbar = yes"
8798	puts $fh "RNDbytes = 2048"
8799	puts $fh "RNDfile = bananarand.bin"
8800	puts $fh "RNDoverwrite = yes"
8801	puts $fh "debug = 6"
8802
8803	if {$mycert != ""} {
8804		if {! [file exists $mycert]} {
8805			mesg "MyCert does not exist: $mycert"
8806			bell
8807			set fail 1
8808		}
8809		puts $fh "cert = $mycert"
8810	} elseif {$use_listen} {
8811		# see above, this should not happen.
8812		puts $fh "cert = _nocert_"
8813	}
8814	if {$crlfil != ""} {
8815		if [file isdirectory $crlfil] {
8816			puts $fh "CRLpath = $crlfil"
8817		} else {
8818			puts $fh "CRLfile = $crlfil"
8819		}
8820	}
8821
8822	set did_check 0
8823
8824	if {$svcert != ""} {
8825		if {! [file exists $svcert]} {
8826			mesg "ServerCert does not exist: $svcert"
8827			bell
8828			set fail 1
8829		}
8830		puts $fh "CAfile = $svcert"
8831		puts $fh "verify = 2"
8832	} elseif {$crtdir != ""} {
8833		if {$crtdir == "ACCEPTED_CERTS"} {
8834			global skip_verify_accepted_certs
8835			set skip_verify_accepted_certs 0
8836			set did_check 1
8837			if {$use_sshssl} {
8838				set skip_verify_accepted_certs 1
8839				set did_check 0
8840			} elseif {! [check_accepted_certs 0]} {
8841				set fail 1
8842			}
8843			if {! $skip_verify_accepted_certs} {
8844				set adir [get_idir_certs ""]
8845				set adir "$adir/accepted"
8846				catch {file mkdir $adir}
8847				puts $fh "CApath = $adir"
8848				puts $fh "verify = 2"
8849			}
8850		} else {
8851			if {! [file exists $crtdir]} {
8852				mesg "CertsDir does not exist: $crtdir"
8853				bell
8854				set fail 1
8855			}
8856			puts $fh "CApath = $crtdir"
8857			puts $fh "verify = 2"
8858		}
8859	}
8860
8861	if {!$did_check} {
8862		check_accepted_certs 1
8863	}
8864
8865	if {$use_sshssl} {
8866		set p [expr "$n2 + 5900"]
8867		set proxy [maybe_add_vencrypt $proxy "$win_localhost:$p"]
8868	} else {
8869		set proxy [maybe_add_vencrypt $proxy $hp]
8870	}
8871
8872	set ipv6_pid ""
8873	global have_ipv6
8874	if {$have_ipv6} {
8875		if {$proxy == "" && $use_ssl} {
8876			# stunnel can handle ipv6
8877		} else {
8878			set res [ipv6_proxy $proxy $host $port]
8879			set proxy    [lindex $res 0]
8880			set host     [lindex $res 1]
8881			set port     [lindex $res 2]
8882			set ipv6_pid [lindex $res 3]
8883		}
8884	}
8885
8886	set p_reverse 0
8887
8888	if {$proxy != ""} {
8889		if {$use_sshssl} {
8890			;
8891		} elseif [regexp {@} $proxy] {
8892			bell
8893			catch {raise .; update}
8894			mesg "WARNING: SSL proxy contains \"@\" sign"
8895			after 1500
8896		}
8897		set env(SSVNC_PROXY) $proxy
8898		set env(SSVNC_DEST) "$host:$port"
8899		if {$use_listen} {
8900			set env(SSVNC_REVERSE) "$win_localhost:$port"
8901			set env(CONNECT_BR_SLEEP) 3
8902			set p_reverse 1
8903		} else {
8904			if {$use_sshssl && [regexp {vencrypt:} $proxy]} {
8905				set env(SSVNC_LISTEN) [expr "$n4 + 5900"]
8906			} else {
8907				set env(SSVNC_LISTEN) [expr "$n2 + 5900"]
8908			}
8909		}
8910		if {[info exists env(PROXY_DEBUG)]} {
8911			foreach var [list SSVNC_PROXY SSVNC_DEST SSVNC_REVERSE CONNECT_BR_SLEEP SSVNC_LISTEN] {
8912				if [info exists env($var)] {
8913					mesg "$var $env($var)"; after 2500;
8914				}
8915			}
8916		}
8917	}
8918
8919	global anon_dh_detected server_anondh
8920	if {$anon_dh_detected || $server_anondh} {
8921		puts $fh "ciphers = ALL:RC4+RSA:+SSLv2:@STRENGTH"
8922		set anon_dh_detected 0
8923	}
8924
8925
8926	puts $fh "\[vnc$n1\]"
8927	set port2 ""
8928	set port3 ""
8929	if {! $use_listen} {
8930		set port2 [expr "$n1 + 5900"]
8931		if [regexp {vencrypt:} $proxy] {
8932			set port3 [expr "$n3 + 5900"]
8933			set port2 $port3
8934			puts $fh "accept = $win_localhost:$port3"
8935		} else {
8936			puts $fh "accept = $win_localhost:$port2"
8937		}
8938
8939		if {$use_sshssl && [regexp {vencrypt:} $proxy]} {
8940			set port [expr "$n4 + 5900"]
8941			puts $fh "connect = $win_localhost:$port"
8942		} elseif {$use_sshssl || $proxy != ""} {
8943			set port [expr "$n2 + 5900"]
8944			puts $fh "connect = $win_localhost:$port"
8945		} else {
8946			puts $fh "connect = $host:$port"
8947		}
8948	} else {
8949		set port2 [expr "$n1 + 5500"]
8950		set hloc ""
8951		if {$use_ssh} {
8952			# not reached?
8953			set hloc "$win_localhost:"
8954			set listening_name "$win_localhost:$port  (on remote SSH side)"
8955		} else {
8956			set hn [get_hostname]
8957			if {$hn == ""} {
8958				set hn "this-computer"
8959			}
8960			set listening_name "$hn:$port  (or nn.nn.nn.nn:$port, etc.)"
8961		}
8962		if {$host_orig != "" && $hloc == ""} {
8963			set hloc "$host_orig:"
8964		}
8965		puts $fh "accept = $hloc$port"
8966		puts $fh "connect = $win_localhost:$port2"
8967	}
8968
8969	puts $fh "delay = no"
8970	puts $fh ""
8971	close $fh
8972
8973	if {! $did_port_knock} {
8974		if {! [do_port_knock $host start]} {
8975			set fail 1
8976		}
8977		set did_port_knock 1
8978	}
8979
8980	if {$fail} {
8981		if {![info exists env(SSVNC_NO_DELETE)]} {
8982			catch {file delete $file1}
8983		}
8984		catch { unset env(SSVNC_PROXY) }
8985		catch { unset env(SSVNC_LISTEN) }
8986		catch { unset env(SSVNC_REVERSE) }
8987		catch { unset env(SSVNC_DEST) }
8988		catch { unset env(SSVNC_PREDIGESTED_HANDSHAKE) }
8989		catch { unset env(CONNECT_BR_SLEEP) }
8990		winkill $ipv6_pid
8991		winkill $ssh_ipv6_pid
8992		set ssh_ipv6_pid ""
8993		return
8994	}
8995
8996	note_stunnel_pids "before"
8997
8998	set proxy_pid ""
8999	set proxy_pid2 ""
9000
9001	if {$use_listen} {
9002		windows_listening_message $n1
9003	}
9004
9005	if {$proxy != ""} {
9006		if [regexp {vencrypt:} $proxy] {
9007			set vport [expr "$n1 + 5900"]
9008			mesg "Starting VeNCrypt helper on port $vport,$port3 ..."
9009			after 500
9010			if {![info exists env(SSVNC_NO_DELETE)]} {
9011				catch {file delete "$file1.pre"}
9012			}
9013			set env(SSVNC_PREDIGESTED_HANDSHAKE) "$file1.pre"
9014			set env(SSVNC_VENCRYPT_VIEWER_BRIDGE) "$vport,$port3"
9015			set proxy_pid2 [exec "connect_br.exe" &]
9016			catch { unset env(SSVNC_VENCRYPT_VIEWER_BRIDGE) }
9017		}
9018		mesg "Starting TCP helper on port $port ..."
9019		after 400
9020		# ssl br case:
9021		set proxy_pid [exec "connect_br.exe" &]
9022		catch { unset env(SSVNC_PROXY) }
9023		catch { unset env(SSVNC_LISTEN) }
9024		catch { unset env(SSVNC_REVERSE) }
9025		catch { unset env(SSVNC_DEST) }
9026		catch { unset env(SSVNC_PREDIGESTED_HANDSHAKE) }
9027		catch { unset env(CONNECT_BR_SLEEP) }
9028	}
9029
9030	mesg "Starting STUNNEL on port $port2 ..."
9031	after 500
9032
9033	set pids [exec stunnel $file1 &]
9034
9035	if {! $p_reverse} {
9036		after 300
9037		set vtm [vencrypt_tutorial_mesg]
9038		if {$vtm == ""} {
9039			after 300
9040		}
9041	}
9042
9043	note_stunnel_pids "after"
9044
9045	if {$debug} {
9046		after 1000
9047		mesg "pids $pids"
9048		after 1000
9049	} else {
9050		catch {destroy .o}
9051		catch {destroy .oa}
9052		catch {destroy .os}
9053		wm withdraw .
9054	}
9055
9056	do_viewer_windows $n1
9057
9058	del_launch_windows_ssh_files
9059
9060	if {![info exists env(SSVNC_NO_DELETE)]} {
9061		catch {file delete $file1}
9062	}
9063
9064	if {$debug} {
9065		;
9066	} else {
9067		wm deiconify .
9068	}
9069	mesg "Disconnected from $hp."
9070
9071	global port_knocking_list
9072	if [regexp {FINISH} $port_knocking_list] {
9073		do_port_knock $host finish
9074	}
9075
9076	if {[llength $pids_new] > 0} {
9077		set plist [join $pids_new ", "]
9078		global terminate_pids
9079		set terminate_pids ""
9080		global kill_stunnel
9081		if {$kill_stunnel} {
9082			set terminate_pids yes
9083		} else {
9084			win_kill_msg $plist
9085			update
9086			vwait terminate_pids
9087		}
9088		if {$terminate_pids == "yes"} {
9089			kill_stunnel $pids_new
9090		}
9091	} else {
9092		win_nokill_msg
9093	}
9094	mesg "Disconnected from $hp."
9095	winkill $ipv6_pid
9096	winkill $ssh_ipv6_pid
9097	set ssh_ipv6_pid ""
9098
9099	global is_win9x use_sound sound_daemon_local_kill sound_daemon_local_cmd
9100	if {! $is_win9x && $use_sound && $sound_daemon_local_kill && $sound_daemon_local_cmd != ""} {
9101		windows_stop_sound_daemon
9102	}
9103}
9104
9105proc direct_connect_windows {{hp ""}} {
9106	global tcl_platform is_windows
9107	global env use_listen
9108
9109	set proxy [get_ssh_proxy $hp]
9110
9111	set did_port_knock 0
9112
9113	global listening_name
9114	set listening_name ""
9115
9116	set host [host_part $hp]
9117
9118	set host_orig $host
9119
9120	global win_localhost
9121	if {$host == ""} {
9122		set host $win_localhost
9123	}
9124
9125	if [regexp {^.*@} $host match] {
9126		catch {raise .; update}
9127		mesg "Trimming \"$match\" from hostname"
9128		after 700
9129		regsub {^.*@} $host "" host
9130	}
9131
9132	set disp [port_part $hp]
9133	if {[regexp {^-[0-9][0-9]*$} $disp]} {
9134		;
9135	} elseif {$disp == "" || ! [regexp {^[0-9][0-9]*$} $disp]} {
9136		set disp 0
9137	}
9138
9139	if {$disp < 0} {
9140		set port [expr "- $disp"]
9141	} elseif {$disp < 200} {
9142		if {$use_listen} {
9143			set port [expr "$disp + 5500"]
9144		} else {
9145			set port [expr "$disp + 5900"]
9146		}
9147	} else {
9148		set port $disp
9149	}
9150
9151	global have_ipv6
9152	set ipv6_pid ""
9153	if {$have_ipv6 && !$use_listen} {
9154		set res [ipv6_proxy $proxy $host $port]
9155		set proxy    [lindex $res 0]
9156		set host     [lindex $res 1]
9157		set port     [lindex $res 2]
9158		set ipv6_pid [lindex $res 3]
9159	}
9160
9161	if {$proxy != ""} {
9162		if [regexp {@} $proxy] {
9163			bell
9164			catch {raise .; update}
9165			mesg "WARNING: SSL proxy contains \"@\" sign"
9166			after 1500
9167		}
9168		set n2 45
9169
9170		set env(SSVNC_PROXY) $proxy
9171		set env(SSVNC_LISTEN) [expr "$n2 + 5900"]
9172		set env(SSVNC_DEST) "$host:$port"
9173
9174		set port [expr $n2 + 5900]
9175		set host $win_localhost
9176	}
9177
9178	set fail 0
9179	if {! $did_port_knock} {
9180		if {! [do_port_knock $host start]} {
9181			set fail 1
9182		}
9183		set did_port_knock 1
9184	}
9185
9186	if {$fail} {
9187		catch { unset env(SSVNC_PROXY) }
9188		catch { unset env(SSVNC_LISTEN) }
9189		catch { unset env(SSVNC_DEST) }
9190		winkill $ipv6_pid
9191		return
9192	}
9193
9194	set proxy_pid ""
9195	if {$proxy != ""} {
9196		mesg "Starting Proxy TCP helper on port $port ..."
9197		after 400
9198		# unencrypted br case:
9199		set proxy_pid [exec "connect_br.exe" &]
9200		catch { unset env(SSVNC_PROXY) }
9201		catch { unset env(SSVNC_LISTEN) }
9202		catch { unset env(SSVNC_DEST) }
9203	}
9204
9205	vencrypt_tutorial_mesg
9206
9207	catch {destroy .o}
9208	catch {destroy .oa}
9209	catch {destroy .os}
9210	wm withdraw .
9211
9212	if {$use_listen} {
9213		set n $port
9214		if {$n >= 5500} {
9215			set n [expr $n - 5500]
9216		}
9217		global direct_connect_reverse_host_orig
9218		set direct_connect_reverse_host_orig $host_orig
9219
9220		do_viewer_windows "$n"
9221
9222		set direct_connect_reverse_host_orig ""
9223	} else {
9224		if {$port >= 5900 && $port < 6100} {
9225			set port [expr $port - 5900]
9226		}
9227		do_viewer_windows "$host:$port"
9228	}
9229
9230	wm deiconify .
9231
9232	mesg "Disconnected from $hp."
9233
9234	winkill $ipv6_pid
9235
9236	global port_knocking_list
9237	if [regexp {FINISH} $port_knocking_list] {
9238		do_port_knock $host finish
9239	}
9240
9241	mesg "Disconnected from $hp."
9242}
9243
9244proc get_idir_certs {str} {
9245	global is_windows env
9246	set idir ""
9247	if {$str != ""} {
9248		if [file isdirectory $str] {
9249			set idir $str
9250		} else {
9251			set idir [file dirname $str]
9252		}
9253		if {$is_windows} {
9254			regsub -all {\\} $idir "/" idir
9255			regsub -all {//*} $idir "/" idir
9256		}
9257	}
9258	if {$idir == ""} {
9259		if {$is_windows} {
9260			if [info exists env(SSVNC_HOME)] {
9261				set t "$env(SSVNC_HOME)/ss_vnc"
9262				regsub -all {\\} $t "/" t
9263				regsub -all {//*} $t "/" t
9264				if {! [file isdirectory $t]} {
9265					catch {file mkdir $t}
9266				}
9267				set t "$env(SSVNC_HOME)/ss_vnc/certs"
9268				regsub -all {\\} $t "/" t
9269				regsub -all {//*} $t "/" t
9270				if {! [file isdirectory $t]} {
9271					catch {file mkdir $t}
9272				}
9273				if [file isdirectory $t] {
9274					set idir $t
9275				}
9276			}
9277			if {$idir == ""} {
9278				set t [file dirname [pwd]]
9279				set t "$t/certs"
9280				if [file isdirectory $t] {
9281					set idir $t
9282				}
9283			}
9284		}
9285		if {$idir == ""} {
9286			if [info exists env(SSVNC_HOME)] {
9287				set t "$env(SSVNC_HOME)/.vnc"
9288				if {! [file isdirectory $t]} {
9289					catch {file mkdir $t}
9290				}
9291				set t "$env(SSVNC_HOME)/.vnc/certs"
9292				if {! [file isdirectory $t]} {
9293					catch {file mkdir $t}
9294				}
9295				if [file isdirectory $t] {
9296					set idir $t
9297				}
9298			}
9299		}
9300	}
9301	if {$idir == ""} {
9302		if {$is_windows} {
9303			set idir [get_profiles_dir]
9304		}
9305		if {$idir == ""} {
9306			set idir [pwd]
9307		}
9308	}
9309	return $idir
9310}
9311
9312proc delete_cert {{parent "."}} {
9313	set idir [get_idir_certs ""]
9314	set f ""
9315	unix_dialog_resize $parent
9316	if {$idir != ""} {
9317		set f [tk_getOpenFile -parent $parent -initialdir $idir]
9318	} else {
9319		set f [tk_getOpenFile -parent $parent]
9320	}
9321	if {$f != "" && [file exists $f]} {
9322		set reply [tk_messageBox -parent $parent -type yesno -icon question -title "Delete Cert" -message "Delete $f"]
9323		if {$reply == "yes"} {
9324			global mycert svcert crlfil
9325			set f_text [read_file $f]
9326			set f2 ""
9327			catch {file delete $f}
9328			if {$f == $mycert} { set mycert "" }
9329			if {$f == $svcert} { set svcert "" }
9330			if {$f == $crlfil} { set crlfil "" }
9331			if [regexp {\.crt$} $f] {
9332				regsub {\.crt$} $f ".pem" f2
9333			} elseif [regexp {\.pem$} $f] {
9334				regsub {\.pem$} $f ".crt" f2
9335			}
9336			if {$f2 != "" && [file exists $f2]} {
9337				set reply [tk_messageBox -parent $parent -type yesno -icon question -title "Delete Cert" -message "Delete $f2"]
9338				if {$reply == "yes"} {
9339					catch {file delete $f2}
9340					if {$f2 == $mycert} { set mycert "" }
9341					if {$f2 == $svcert} { set svcert "" }
9342					if {$f2 == $crlfil} { set crlfil "" }
9343				}
9344			}
9345			set dir [file dirname $f]
9346			if {$f_text != "" && [regexp {accepted$} $dir]} {
9347				foreach crt [glob -nocomplain -directory $dir {*.crt} {*.pem} {*.[0-9]}] {
9348					#puts "try $crt"
9349					set c_text [read_file $crt]
9350					if {$c_text == ""} {
9351						continue
9352					}
9353					if {$c_text != $f_text} {
9354						continue
9355					}
9356					set reply [tk_messageBox -parent $parent -type yesno -icon question -title "Delete Identical Cert" -message "Delete Identical $crt"]
9357					if {$reply == "yes"} {
9358						catch {file delete $crt}
9359					}
9360				}
9361			}
9362		}
9363	}
9364	catch {wm deiconify .c}
9365	update
9366}
9367
9368proc set_mycert {{parent "."}} {
9369	global mycert
9370	set idir [get_idir_certs $mycert]
9371	set t ""
9372	unix_dialog_resize $parent
9373	if {$idir != ""} {
9374		set t [tk_getOpenFile -parent $parent -initialdir $idir]
9375	} else {
9376		set t [tk_getOpenFile -parent $parent]
9377	}
9378	if {$t != ""} {
9379		set mycert $t
9380	}
9381	catch {wm deiconify .c}
9382	v_mycert
9383	update
9384}
9385
9386proc set_crlfil {{parent "."}} {
9387	global crlfil
9388	set idir [get_idir_certs $crlfil]
9389	set t ""
9390	unix_dialog_resize $parent
9391	if {$idir != ""} {
9392		set t [tk_getOpenFile -parent $parent -initialdir $idir]
9393	} else {
9394		set t [tk_getOpenFile -parent $parent]
9395	}
9396	if {$t != ""} {
9397		set crlfil $t
9398	}
9399	catch {wm deiconify .c}
9400	v_crlfil
9401	update
9402}
9403
9404proc set_ultra_dsm_file {{parent "."}} {
9405	global ultra_dsm_file
9406	set idir [get_idir_certs $ultra_dsm_file]
9407	set t ""
9408	unix_dialog_resize $parent
9409	if {$idir != ""} {
9410		set t [tk_getOpenFile -parent $parent -initialdir $idir]
9411	} else {
9412		set t [tk_getOpenFile -parent $parent]
9413	}
9414	if {$t != ""} {
9415		set ultra_dsm_file $t
9416	}
9417	update
9418}
9419
9420proc set_ssh_known_hosts_file {{parent "."}} {
9421	global ssh_known_hosts_filename is_windows uname
9422
9423	if {$ssh_known_hosts_filename == ""} {
9424		set pdir [get_profiles_dir]
9425		set pdir "$pdir/ssh_known_hosts"
9426		catch {file mkdir $pdir}
9427
9428		global last_load
9429		if {![info exists last_load]} {
9430			set last_load ""
9431		}
9432		if {$last_load != ""} {
9433			set dispf [string trim $last_load]
9434			set dispf [file tail $dispf]
9435
9436			regsub {\.vnc$} $dispf "" dispf
9437			if {![regexp {\.known$} $dispf]} {
9438				set dispf "$dispf.known"
9439			}
9440			set guess $dispf
9441		} else {
9442			set vncdisp [get_vncdisplay]
9443			set dispf [string trim $vncdisp]
9444			if {$dispf != ""} {
9445				regsub {[ 	].*$} $dispf "" dispf
9446				regsub -all {/} $dispf "" dispf
9447			} else {
9448				set dispf "unique-name-here"
9449			}
9450			if {$is_windows || $uname == "Darwin"} {
9451				regsub -all {:} $dispf "-" dispf
9452			} else {
9453				regsub -all {:} $dispf "-" dispf
9454			}
9455			if {![regexp {\.known$} $dispf]} {
9456				set dispf "$dispf.known"
9457			}
9458			set guess $dispf
9459		}
9460	} else {
9461		set pdir [file dirname $ssh_known_hosts_filename]
9462		set guess [file tail $ssh_known_hosts_filename]
9463	}
9464
9465	set t ""
9466	unix_dialog_resize $parent
9467	if {$pdir != ""} {
9468		set t [tk_getSaveFile -parent $parent -initialdir $pdir -initialfile $guess]
9469	} else {
9470		set t [tk_getSaveFile -parent $parent -initialfile $guess]
9471	}
9472	if {$t != ""} {
9473		set ssh_known_hosts_filename $t
9474	}
9475	update
9476}
9477
9478proc show_cert {crt} {
9479	if {$crt == ""} {
9480		bell
9481		return
9482	}
9483	if {! [file exists $crt]} {
9484		bell
9485		return
9486	}
9487	set info ""
9488	catch {set info [get_x509_info $crt]}
9489	if {$info == ""} {
9490		bell
9491		return
9492	}
9493
9494	set w .show_certificate
9495	toplev $w
9496	scroll_text $w.f
9497	button $w.b -text Dismiss -command "destroy $w"
9498	bind $w <Escape> "destroy $w"
9499	$w.f.t insert end $info
9500
9501	pack $w.b -side bottom -fill x
9502	pack $w.f -side top -fill both -expand 1
9503	center_win $w
9504	catch {raise $w}
9505}
9506
9507proc show_crl {crl} {
9508	if {$crl == ""} {
9509		bell
9510		return
9511	}
9512	if {! [file exists $crl]} {
9513		bell
9514		return
9515	}
9516
9517	set flist [list]
9518
9519	if [file isdirectory $crl] {
9520		foreach cfile [glob -nocomplain -directory $crl "*"] {
9521			if [file isfile $cfile] {
9522				lappend flist $cfile
9523			}
9524		}
9525	} else {
9526		lappend flist $crl
9527	}
9528
9529	set ossl [get_openssl]
9530	set info ""
9531
9532	foreach cfile $flist {
9533		catch {
9534			set ph [open "| $ossl crl -fingerprint -text -noout -in \"$cfile\"" "r"]
9535			while {[gets $ph line] > -1} {
9536				append info "$line\n"
9537			}
9538			close $ph
9539			append info "\n"
9540		}
9541	}
9542
9543	set w .show_crl
9544	toplev $w
9545	scroll_text $w.f
9546	button $w.b -text Dismiss -command "destroy $w"
9547	bind $w <Escape> "destroy $w"
9548	$w.f.t insert end $info
9549
9550	pack $w.b -side bottom -fill x
9551	pack $w.f -side top -fill both -expand 1
9552	center_win $w
9553	catch {raise $w}
9554}
9555
9556proc v_svcert {} {
9557	global svcert
9558	if {$svcert == "" || ! [file exists $svcert]} {
9559		catch {.c.svcert.i configure -state disabled}
9560	} else {
9561		catch {.c.svcert.i configure -state normal}
9562	}
9563	no_certs_tutorial_mesg
9564	return 1
9565}
9566
9567proc v_mycert {} {
9568	global mycert
9569	if {$mycert == "" || ! [file exists $mycert]} {
9570		catch {.c.mycert.i configure -state disabled}
9571	} else {
9572		catch {.c.mycert.i configure -state normal}
9573	}
9574	return 1
9575}
9576
9577proc v_crlfil {} {
9578	global crlfil
9579	if {$crlfil == "" || ! [file exists $crlfil]} {
9580		catch {.c.crlfil.i configure -state disabled}
9581	} else {
9582		catch {.c.crlfil.i configure -state normal}
9583	}
9584	return 1
9585}
9586
9587proc show_mycert {} {
9588	global mycert
9589	show_cert $mycert
9590}
9591
9592proc show_svcert {} {
9593	global svcert
9594	show_cert $svcert
9595}
9596
9597proc show_crlfil {} {
9598	global crlfil
9599	show_crl $crlfil
9600}
9601
9602proc set_svcert {{parent "."}} {
9603	global svcert crtdir
9604	set idir [get_idir_certs $svcert]
9605	set t ""
9606	unix_dialog_resize $parent
9607	if {$idir != ""} {
9608		set t [tk_getOpenFile -parent $parent -initialdir $idir]
9609	} else {
9610		set t [tk_getOpenFile -parent $parent]
9611	}
9612	if {$t != ""} {
9613		set crtdir ""
9614		set svcert $t
9615	}
9616	catch {wm deiconify .c}
9617	v_svcert
9618	update
9619}
9620
9621proc set_crtdir {{parent "."}} {
9622	global svcert crtdir
9623	set idir ""
9624	if {$crtdir == "ACCEPTED_CERTS"} {
9625		set idir [get_idir_certs ""]
9626	} else {
9627		set idir [get_idir_certs $crtdir]
9628	}
9629	set t ""
9630	unix_dialog_resize $parent
9631	if {$idir != ""} {
9632		set t [tk_chooseDirectory -parent $parent -initialdir $idir]
9633	} else {
9634		set t [tk_chooseDirectory -parent $parent]
9635	}
9636	if {$t != ""} {
9637		set svcert ""
9638		set crtdir $t
9639	}
9640	catch {wm deiconify .c}
9641	update
9642}
9643
9644proc set_createcert_file {} {
9645	global ccert
9646	if {[info exists ccert(FILE)]} {
9647		set idir [get_idir_certs $ccert(FILE)]
9648	}
9649	unix_dialog_resize .ccrt
9650	if {$idir != ""} {
9651		set t [tk_getSaveFile -parent .ccrt -defaultextension ".pem" -initialdir $idir]
9652	} else {
9653		set t [tk_getSaveFile -parent .ccrt -defaultextension ".pem"]
9654	}
9655	if {$t != ""} {
9656		set ccert(FILE) $t
9657	}
9658	catch {raise .ccrt}
9659	update
9660}
9661
9662proc check_pp {} {
9663	global ccert
9664	if {$ccert(ENC)} {
9665		catch {.ccrt.pf.e configure -state normal}
9666		catch {focus .ccrt.pf.e}
9667		catch {.ccrt.pf.e icursor end}
9668	} else {
9669		catch {.ccrt.pf.e configure -state disabled}
9670	}
9671}
9672
9673proc get_openssl {} {
9674	global is_windows
9675	if {$is_windows} {
9676		set ossl "openssl.exe"
9677	} else {
9678		set ossl "openssl"
9679	}
9680}
9681
9682proc get_x509_info {crt} {
9683	set ossl [get_openssl]
9684	set info ""
9685	update
9686	set ph [open "| $ossl x509 -text -fingerprint -in \"$crt\"" "r"]
9687	while {[gets $ph line] > -1} {
9688		append info "$line\n"
9689	}
9690	close $ph
9691	return $info
9692}
9693
9694proc do_oss_create {} {
9695	global is_windows is_win9x
9696
9697	set cfg {
9698[ req ]
9699default_bits            = 2048
9700encrypt_key             = yes
9701distinguished_name      = req_distinguished_name
9702
9703[ req_distinguished_name ]
9704countryName                     = Country Name (2 letter code)
9705countryName_default             = %CO
9706countryName_min                 = 2
9707countryName_max                 = 2
9708
9709stateOrProvinceName             = State or Province Name (full name)
9710stateOrProvinceName_default     = %ST
9711
9712localityName                    = Locality Name (eg, city)
9713localityName_default            = %LOC
9714
97150.organizationName              = Organization Name (eg, company)
97160.organizationName_default      = %ON
9717
9718organizationalUnitName          = Organizational Unit Name (eg, section)
9719organizationalUnitName_default  = %OUN
9720
9721commonName                      = Common Name (eg, YOUR name)
9722commonName_default              = %CN
9723commonName_max                  = 64
9724
9725emailAddress                    = Email Address
9726emailAddress_default            = %EM
9727emailAddress_max                = 64
9728}
9729
9730	global ccert
9731
9732	if {$ccert(FILE) == ""} {
9733		catch {destroy .c}
9734		mesg "No output cert file supplied"
9735		bell
9736		return
9737	}
9738	if {! [regexp {\.pem$} $ccert(FILE)]} {
9739		append ccert(FILE) ".pem"
9740	}
9741	set pem $ccert(FILE)
9742	regsub {\.pem$} $ccert(FILE) ".crt" crt
9743
9744	if {$ccert(ENC)} {
9745		if {[string length $ccert(PASS)] < 4} {
9746			catch {destroy .c}
9747			mesg "Passphrase must be at least 4 characters long."
9748			bell
9749			return
9750		}
9751	}
9752	if {[string length $ccert(CO)] != 2} {
9753		catch {destroy .c}
9754		mesg "Country Name must be at exactly 2 characters long."
9755		bell
9756		return
9757	}
9758	if {[string length $ccert(CN)] > 64} {
9759		catch {destroy .c}
9760		mesg "Common Name must be less than 65 characters long."
9761		bell
9762		return
9763	}
9764	if {[string length $ccert(EM)] > 64} {
9765		catch {destroy .c}
9766		mesg "Email Address must be less than 65 characters long."
9767		bell
9768		return
9769	}
9770
9771	foreach t {EM CN OUN ON LOC ST CO} {
9772
9773		set val $ccert($t)
9774		if {$val == ""} {
9775			set val "none"
9776		}
9777		regsub "%$t" $cfg "$val" cfg
9778	}
9779
9780	global is_windows
9781
9782	if {$is_windows} {
9783		# VF
9784		set tmp "cert.cfg"
9785	} else {
9786		set tmp "/tmp/cert.cfg.[tpid]"
9787		set tmp [mytmp $tmp]
9788		catch {set fh [open $tmp "w"]}
9789		catch {exec chmod 600 $tmp}
9790		if {! [file exists $tmp]} {
9791			catch {destroy .c}
9792			mesg "cannot create: $tmp"
9793			bell
9794			return
9795		}
9796	}
9797	set fh ""
9798	catch {set fh [open $tmp "w"]}
9799	if {$fh == ""} {
9800		catch {destroy .c}
9801		mesg "cannot create: $tmp"
9802		bell
9803		catch {file delete $tmp}
9804		return
9805	}
9806
9807	puts $fh $cfg
9808	close $fh
9809
9810	set ossl [get_openssl]
9811
9812	set cmd "$ossl req -config $tmp -nodes -new -newkey rsa:2048 -x509 -batch"
9813	if {$ccert(DAYS) != ""} {
9814		set cmd "$cmd -days $ccert(DAYS)"
9815	}
9816	if {$is_windows} {
9817		set cmd "$cmd -keyout {$pem} -out {$crt}"
9818	} else {
9819		set cmd "$cmd -keyout \"$pem\" -out \"$crt\""
9820	}
9821
9822	if {$is_windows} {
9823		set emess ""
9824		if {$is_win9x} {
9825			catch {file delete $pem}
9826			catch {file delete $crt}
9827			update
9828			eval exec $cmd &
9829			catch {raise .}
9830			set sl 0
9831			set max 100
9832			#if {$ccert(ENC)} {
9833			#	set max 100
9834			#}
9835			set maxms [expr $max * 1000]
9836			while {$sl < $maxms} {
9837				set s2 [expr $sl / 1000]
9838				mesg "running openssl ... $s2/$max"
9839				if {[file exists $pem] && [file exists $crt]} {
9840					after 2000
9841					break
9842				}
9843				after 500
9844				set sl [expr $sl + 500]
9845			}
9846			mesg ""
9847		} else {
9848			update
9849			set rc [catch {eval exec $cmd} emess]
9850			if {$rc != 0 && [regexp -nocase {error:} $emess]} {
9851				raise .
9852				tk_messageBox -type ok -icon error -message $emess -title "OpenSSL req command failed"
9853				return
9854			}
9855		}
9856	} else {
9857		set geometry [xterm_center_geometry]
9858		update
9859		unix_terminal_cmd $geometry "Running OpenSSL" "$cmd"
9860		catch {file attributes $pem -permissions go-rw}
9861		catch {file attributes $crt -permissions go-w}
9862	}
9863	catch {file delete $tmp}
9864
9865	set bad ""
9866	if {! [file exists $pem]} {
9867		set bad "$pem "
9868	}
9869	if {! [file exists $crt]} {
9870		set bad "$crt"
9871	}
9872	if {$bad != ""} {
9873		raise .
9874		tk_messageBox -type ok -icon error -message "Not created: $bad" -title "OpenSSL could not create cert"
9875		catch {raise .c}
9876		return
9877	}
9878
9879	if {$ccert(ENC) && $ccert(PASS) != ""} {
9880		set cmd "$ossl rsa -in \"$pem\" -des3 -out \"$pem\" -passout stdin"
9881		set ph ""
9882		set emess ""
9883		update
9884		set rc [catch {set ph [open "| $cmd" "w"]} emess]
9885		if {$rc != 0 || $ph == ""} {
9886			raise .
9887			tk_messageBox -type ok -icon error -message $emess -title "Could not encrypt private key"
9888			catch {file delete $pem}
9889			catch {file delete $crt}
9890			return
9891		}
9892		puts $ph $ccert(PASS)
9893		set emess ""
9894		set rc [catch {close $ph} emess]
9895		#puts $emess
9896		#puts $rc
9897	}
9898
9899	set in  [open $crt "r"]
9900	set out [open $pem "a"]
9901	while {[gets $in line] > -1} {
9902		puts $out $line
9903	}
9904	close $in
9905	close $out
9906
9907	catch {raise .c}
9908	set p .
9909	if [winfo exists .c] {
9910		set p .c
9911	}
9912
9913	set reply [tk_messageBox -parent $p -type yesno -title "View Cert" -message "View Certificate and Info?"]
9914	catch {raise .c}
9915	if {$reply == "yes"} {
9916		set w .view_cert
9917		toplev $w
9918		scroll_text $w.f
9919		set cert ""
9920		set fh ""
9921		catch {set fh [open $crt "r"]}
9922		if {$fh != ""} {
9923			while {[gets $fh line] > -1} {
9924				append cert "$line\n"
9925			}
9926			catch {close $fh}
9927		}
9928
9929		global yegg
9930		set yegg ""
9931		button $w.b -text Dismiss -command "destroy $w; set yegg 1"
9932		pack $w.b -side bottom -fill x
9933		bind $w <Escape> "destroy $w; set yegg 1"
9934
9935		$w.f.t insert end "\n"
9936		$w.f.t insert end "$crt:\n"
9937		$w.f.t insert end "\n"
9938		$w.f.t insert end $cert
9939		$w.f.t insert end "\n"
9940
9941		set info [get_x509_info $crt]
9942		$w.f.t insert end $info
9943
9944		pack $w.f -side top -fill both -expand 1
9945		center_win $w
9946		catch {raise $w}
9947		vwait yegg
9948		catch {raise .c}
9949	}
9950
9951	set p .
9952	if [winfo exists .c] {
9953		set p .c
9954	}
9955	set reply [tk_messageBox -parent $p -type yesno -title "View Private Key" -message "View Private Key?"]
9956	catch {raise .c}
9957	if {$reply == "yes"} {
9958		set w .view_key
9959		toplev $w
9960		scroll_text $w.f
9961		set key ""
9962		set fh [open $pem "r"]
9963		while {[gets $fh line] > -1} {
9964			append key "$line\n"
9965		}
9966		close $fh
9967
9968		global yegg
9969		set yegg ""
9970		button $w.b -text Dismiss -command "destroy $w; set yegg 1"
9971		pack $w.b -side bottom -fill x
9972		bind $w <Escape> "destroy $w; set yegg 1"
9973
9974		$w.f.t insert end "\n"
9975		$w.f.t insert end "$pem:\n"
9976		$w.f.t insert end "\n"
9977		$w.f.t insert end $key
9978		$w.f.t insert end "\n"
9979
9980		pack $w.f -side top -fill both -expand 1
9981		center_win $w
9982		catch {raise $w}
9983		vwait yegg
9984		catch {raise .c}
9985	}
9986}
9987
9988proc create_cert {{name ""}} {
9989
9990	toplev .ccrt
9991	wm title .ccrt "Create SSL Certificate"
9992
9993	global uname
9994	set h 27
9995	if [small_height] {
9996		set h 14
9997	} elseif {$uname == "Darwin"} {
9998		set h 20
9999	}
10000	scroll_text .ccrt.f 80 $h
10001
10002	set msg {
10003    This dialog helps you to create a simple Self-Signed SSL certificate.
10004
10005    On Unix the openssl(1) program must be installed and in $PATH.
10006    On Windows, a copy of the openssl program is provided for convenience.
10007
10008    The resulting certificate files can be used for either:
10009
10010       1) authenticating yourself (VNC Viewer) to a VNC Server
10011    or 2) your verifying the identity of a remote VNC Server.
10012
10013    In either case you will need to safely copy one of the generated key or
10014    certificate files to the remote VNC Server and have the VNC Server use
10015    it.  Or you could send it to the system administrator of the VNC Server.
10016
10017    For the purpose of description, assume that the filename selected in the
10018    "Save to file" entry is "vnccert.pem".  That file will be generated
10019    by this process and so will the "vnccert.crt" file.  "vnccert.pem"
10020    contains both the Private Key and the Public Certificate.  "vnccert.crt"
10021    only contains the Public Certificate.
10022
10023    For case 1) you would copy "vnccert.crt" to the VNC Server side and
10024    instruct the server to use it.  For x11vnc it would be for example:
10025
10026        x11vnc -sslverify /path/to/vnccert.crt -ssl SAVE ...
10027
10028    (it is also possible to handle many client certs at once in a directory,
10029    see the -sslverify documentation).  Then you would use "vnccert.pem"
10030    as the MyCert entry in the SSL Certificates dialog.
10031
10032    For case 2) you would copy "vnccert.pem" to the VNC Server side and
10033    instruct the server to use it.  For x11vnc it would be for example:
10034
10035        x11vnc -ssl /path/to/vnccert.pem
10036
10037    Then you would use "vnccert.crt" as the as the ServerCert entry in the
10038    "SSL Certificates" dialog.
10039
10040
10041    Creating the Certificate:
10042
10043    Choose a output filename (ending in .pem) in the "Save to file" entry.
10044
10045    Then fill in the identification information (Country, State or Province,
10046    etc).
10047
10048    The click on "Create" to generate the certificate files.
10049
10050    Encrypting the Private Key:  It is a very good idea to encrypt the
10051    Private Key that goes in the "vnccert.pem".  The downside is that
10052    whenever that key is used (e.g. starting up x11vnc using it) then
10053    the passphrase will need to be created.  If you do not encrypt it and
10054    somebody steals a copy of the "vnccert.pem" file then they can pretend
10055    to be you.
10056
10057    After you have created the certificate files, you must copy and import
10058    either "vnccert.pem" or "vnccert.pem" to the remote VNC Server and
10059    also select the other file in the "SSL Certificates" dialog.
10060    See the description above.
10061
10062    For more information see:
10063
10064           http://www.karlrunge.com/x11vnc/ssl.html
10065           http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-int
10066
10067    The first one describes how to use x11vnc to create Certificate
10068    Authority (CA) certificates in addition to Self-Signed ones.
10069
10070
10071    Tip: if you choose the "Common Name" to be the internet hostname
10072    (e.g. gateway.mydomain.com) that connections will be made to or
10073    from that will avoid many dialogs when connecting mentioning that
10074    the hostname does not match the Common Name.
10075}
10076	.ccrt.f.t insert end $msg
10077
10078	global ccert ccert_init tcert
10079
10080
10081	if {! [info exists ccert_init]} {
10082		set ccert_init 1
10083		set ccert(CO) "US"
10084		set ccert(ST) "Massachusetts"
10085		set ccert(LOC) "Boston"
10086		set ccert(ON) "My Company"
10087		set ccert(OUN) "Product Development"
10088		set ccert(CN) "www.nowhere.none"
10089		set ccert(EM) "admin@nowhere.none"
10090		set ccert(DAYS) "730"
10091		set ccert(FILE) ""
10092	}
10093
10094	set ccert(ENC) 0
10095	set ccert(PASS) ""
10096
10097	set tcert(CO) "Country Name (2 letter code):"
10098	set tcert(ST) "State or Province Name (full name):"
10099	set tcert(LOC) "Locality Name (eg, city):"
10100	set tcert(ON) "Organization Name (eg, company):"
10101	set tcert(OUN) "Organizational Unit Name (eg, section):"
10102	set tcert(CN) "Common Name (eg, YOUR name):"
10103	set tcert(EM) "Email Address:"
10104	set tcert(DAYS) "Days until expiration:"
10105
10106	set idir [get_idir_certs ""]
10107	if {$name != ""} {
10108		if {[regexp {/} $name] || [regexp {\.pem$} $name] || [regexp {\.crt$} $name]} {
10109			set ccert(FILE) $name
10110		} else {
10111			set ccert(FILE) "$idir/$name.pem"
10112		}
10113	} elseif {$ccert(FILE) == ""} {
10114		set ccert(FILE) "$idir/vnccert.pem"
10115	}
10116
10117	button .ccrt.cancel -text "Cancel" -command {destroy .ccrt; catch {raise .c}}
10118	bind .ccrt <Escape> {destroy .ccrt; catch {raise .c}}
10119	wm protocol .ccrt WM_DELETE_WINDOW {destroy .ccrt; catch {raise .c}}
10120
10121	button .ccrt.create -text "Generate Cert" -command {destroy .ccrt; catch {raise .c}; do_oss_create}
10122
10123	pack .ccrt.create .ccrt.cancel -side bottom -fill x
10124
10125	set ew 40
10126
10127	set w .ccrt.pf
10128	frame $w
10129	checkbutton $w.check -anchor w -variable ccert(ENC) -text \
10130		"Encrypt Key with Passphrase" -command {check_pp}
10131
10132	entry $w.e -width $ew -textvariable ccert(PASS) -state disabled \
10133		-show *
10134
10135	pack $w.e -side right
10136	pack $w.check -side left -expand 1 -fill x
10137	pack $w -side bottom -fill x
10138
10139	set w .ccrt.fl
10140	frame $w
10141	label $w.l -anchor w -text "Save to file:"
10142
10143	entry $w.e -width $ew -textvariable ccert(FILE)
10144	button $w.b -text "Browse..." -command {set_createcert_file; catch {raise .ccrt}}
10145	if {$name != ""} {
10146		$w.b configure -state disabled
10147	}
10148
10149	pack $w.e -side right
10150	pack $w.b -side right
10151	pack $w.l -side left -expand 1 -fill x
10152	pack $w -side bottom -fill x
10153
10154	set i 0
10155	foreach t {DAYS EM CN OUN ON LOC ST CO} {
10156		set w .ccrt.f$i
10157		frame $w
10158		label $w.l -anchor w -text "$tcert($t)"
10159		entry $w.e -width $ew -textvariable ccert($t)
10160		pack $w.e  -side right
10161		pack $w.l  -side left -expand 1 -fill x
10162		pack $w -side bottom -fill x
10163		incr i
10164	}
10165
10166	pack .ccrt.f -side top -fill both -expand 1
10167
10168	center_win .ccrt
10169}
10170
10171proc import_check_mode {w} {
10172	global import_mode
10173	if {$import_mode == "paste"} {
10174		$w.mf.b configure -state disabled
10175		$w.mf.e configure -state disabled
10176		$w.plab configure -state normal
10177		$w.paste.t configure -state normal
10178	} else {
10179		$w.mf.b configure -state normal
10180		$w.mf.e configure -state normal
10181		$w.plab configure -state disabled
10182		$w.paste.t configure -state disabled
10183	}
10184}
10185
10186proc import_browse {par} {
10187	global import_file
10188
10189	set idir ""
10190	if {$import_file != ""} {
10191		set idir [get_idir_certs $import_file]
10192	}
10193	unix_dialog_resize $par
10194	if {$idir != ""} {
10195		set t [tk_getOpenFile -parent $par -initialdir $idir]
10196	} else {
10197		set t [tk_getOpenFile -parent $par]
10198	}
10199	if {$t != ""} {
10200		set import_file $t
10201	}
10202	catch {raise $par}
10203	update
10204}
10205
10206proc import_save_browse {{par ".icrt"}} {
10207	global import_save_file
10208
10209	set idir ""
10210	if {$import_save_file != ""} {
10211		set idir [get_idir_certs $import_save_file]
10212	}
10213	if {$idir == ""} {
10214		set idir [get_idir_certs ""]
10215	}
10216	unix_dialog_resize $par
10217	if {$idir != ""} {
10218		set t [tk_getSaveFile -parent $par -defaultextension ".crt" -initialdir $idir]
10219	} else {
10220		set t [tk_getSaveFile -parent $par -defaultextension ".crt"]
10221	}
10222	if {$t != ""} {
10223		set import_save_file $t
10224	}
10225	catch {raise $par}
10226	update
10227}
10228
10229proc do_save {par} {
10230	global import_mode import_file import_save_file
10231	global also_save_to_accepted_certs
10232
10233	if {![info exists also_save_to_accepted_certs]} {
10234		set also_save_to_accepted_certs 0
10235	}
10236
10237	if {$import_save_file == "" && ! $also_save_to_accepted_certs} {
10238		tk_messageBox -parent $par -type ok -icon error \
10239			-message "No Save File supplied" -title "Save File"
10240		return
10241	}
10242
10243	set str ""
10244	set subject_issuer ""
10245	if {$import_mode == "save_cert_text"} {
10246		global save_cert_text
10247		set str $save_cert_text
10248		set i 0
10249		foreach line [split $str "\n"] {
10250			incr i
10251			if {$i > 50} {
10252				break
10253			}
10254			if [regexp {^- subject: *(.*)$} $line m val] {
10255				set subject_issuer "${subject_issuer}subject:$val\n"
10256			}
10257			if [regexp {^- (issuer[0-9][0-9]*): *(.*)$} $line m is val] {
10258				set subject_issuer "${subject_issuer}$is:$val\n"
10259			}
10260			if [regexp {^INFO: SELF_SIGNED=(.*)$} $line m val] {
10261				set subject_issuer "${subject_issuer}SELF_SIGNED:$val\n"
10262			}
10263		}
10264	} elseif {$import_mode == "paste"} {
10265		set str [$par.paste.t get 1.0 end]
10266	} else {
10267		if {! [file exists $import_file]} {
10268			tk_messageBox -parent $par -type ok -icon error \
10269				-message "Input file \"$import_file\" does not exist." -title "Import File"
10270			return
10271		}
10272		set fh ""
10273		set emess ""
10274		set rc [catch {set fh [open $import_file "r"]} emess]
10275		if {$rc != 0 || $fh == ""} {
10276			tk_messageBox -parent $par -type ok -icon error \
10277				-message $emess -title "Import File: $import_file"
10278			return
10279		}
10280		while {[gets $fh line] > -1} {
10281			append str "$line\n"
10282		}
10283		close $fh
10284	}
10285
10286	if {! [regexp {BEGIN CERTIFICATE} $str]} {
10287		tk_messageBox -parent $par -type ok -icon error \
10288			-message "Import Text does not contain \"BEGIN CERTIFICATE\"" -title "Imported Text"
10289		return
10290	}
10291	if {! [regexp {END CERTIFICATE} $str]} {
10292		tk_messageBox -parent $par -type ok -icon error \
10293			-message "Import Text does not contain \"END CERTIFICATE\"" -title "Imported Text"
10294		return
10295	}
10296
10297	global is_windows
10298	set fh ""
10299	set emess ""
10300	set deltmp ""
10301	if {$import_save_file == ""} {
10302		if {! $is_windows} {
10303			set deltmp /tmp/import.[tpid]
10304		} else {
10305			set deltmp import.[tpid]
10306		}
10307		set deltmp [mytmp $deltmp]
10308		set import_save_file $deltmp
10309	}
10310	set rc [catch {set fh [open $import_save_file "w"]} emess]
10311	if {$rc != 0 || $fh == ""} {
10312		tk_messageBox -parent $par -type ok -icon error \
10313			-message $emess -title "Save File: $import_save_file"
10314		return
10315	}
10316	if {! $is_windows} {
10317		catch {file attributes $import_save_file -permissions go-w}
10318		if {[regexp {PRIVATE} $str] || [regexp {\.pem$} $import_save_file]} {
10319			catch {file attributes $import_save_file -permissions go-rw}
10320		}
10321	}
10322
10323	puts -nonewline $fh $str
10324	close $fh
10325
10326	global do_save_saved_it
10327	set do_save_saved_it 1
10328
10329	if {$also_save_to_accepted_certs} {
10330		set ossl [get_openssl]
10331		set fp_txt ""
10332		set fp_txt [exec $ossl x509 -fingerprint -noout -in $import_save_file]
10333
10334		set adir [get_idir_certs ""]
10335		set adir "$adir/accepted"
10336		catch {file mkdir $adir}
10337
10338		set fingerprint ""
10339		set fingerline ""
10340
10341		set i 0
10342		foreach line [split $fp_txt "\n"] {
10343			incr i
10344			if {$i > 5} {
10345				break
10346			}
10347			if [regexp -nocase {Fingerprint=(.*)} $line mv str] {
10348				set fingerline $line
10349				set fingerprint [string trim $str]
10350			}
10351		}
10352
10353		set fingerprint [string tolower $fingerprint]
10354		regsub -all {:} $fingerprint "-" fingerprint
10355		regsub -all {[\\/=]} $fingerprint "_" fingerprint
10356
10357		if {$subject_issuer == ""} {
10358			set si_txt ""
10359			set si_txt [exec $ossl x509 -subject -issuer -noout -in $import_save_file]
10360			set sub ""
10361			set iss ""
10362			foreach line [split $si_txt "\n"] {
10363				if [regexp -nocase {^subject= *(.*)$} $line mv str] {
10364					set str [string trim $str]
10365					set sub $str
10366				} elseif [regexp -nocase {^issuer= *(.*)$} $line mv str] {
10367					set str [string trim $str]
10368					set iss $str
10369				}
10370			}
10371			if {$sub != "" && $iss != ""} {
10372				set subject_issuer "subject:$sub\nissuer1:$iss\n"
10373				if {$sub == $iss} {
10374					set subject_issuer "${subject_issuer}SELF_SIGNED:1\n"
10375				} else {
10376					set subject_issuer "${subject_issuer}SELF_SIGNED:0\n"
10377				}
10378			}
10379		}
10380
10381		global vncdisplay
10382		set from [get_ssh_hp $vncdisplay]
10383		if {$from == ""} {
10384			set from [file tail $import_save_file]
10385			regsub {\..*$} $from "" from
10386		}
10387		if {$from == ""} {
10388			set from "import"
10389		}
10390		if [regexp -- {^:[0-9][0-9]*$} $from] {
10391			set from "listen$from"
10392		}
10393		set hp $from
10394
10395		set from [string tolower $from]
10396		regsub -all {^[+a-z]*://} $from "" from
10397		regsub -all {:} $from "-" from
10398		regsub -all {[\\/=]} $from "_" from
10399		regsub -all {[ 	]} $from "_" from
10400
10401		set crt "$adir/$from=$fingerprint.crt"
10402		catch {file copy -force $import_save_file $crt}
10403
10404		global do_save_saved_hash_it
10405		set do_save_saved_hash_it 1
10406		save_hash $crt $adir $hp $fingerline $from $fingerprint $subject_issuer
10407	}
10408
10409	catch {destroy $par}
10410	set p .c
10411	if {![winfo exists .c]} {
10412		global accepted_cert_dialog_in_progress
10413		if {! $accepted_cert_dialog_in_progress} {
10414			if {$deltmp == ""} {
10415				getcerts
10416				update
10417			}
10418		}
10419	}
10420	if {![winfo exists .c]} {
10421		set p .
10422	}
10423	catch {raise .c}
10424	catch {destroy .scrt}
10425	if {$deltmp != ""} {
10426		catch {file delete $deltmp}
10427		set import_save_file ""
10428		return;
10429	}
10430	tk_messageBox -parent $p -type ok -icon info \
10431		-message "Saved to file: $import_save_file" -title "Save File: $import_save_file"
10432}
10433
10434proc import_cert {} {
10435
10436	toplev .icrt
10437	wm title .icrt "Import SSL Certificate"
10438
10439	global scroll_text_focus
10440	set scroll_text_focus 0
10441	global uname
10442	set h 19
10443	if [small_height] {
10444		set h 12
10445	} elseif {$uname == "Darwin"} {
10446		set h 16
10447	}
10448	scroll_text .icrt.f 90 $h
10449	set scroll_text_focus 1
10450
10451	set msg {
10452    This dialog lets you import a SSL Certificate by either pasting one in or by
10453    loading from another file.  Choose which input mode you want to use by the toggle
10454    "Paste / Read from File".
10455
10456    There are two types of files we use 1) Certificate only, and 2) Private Key
10457    and Certificate.
10458
10459    Type 1) would be used to verify the identity of a remote VNC Server, whereas
10460    type 2) would be used to authenticate ourselves to the remote VNC Server.
10461
10462    A type 1) by convention ends with file suffix ".crt" and looks like:
10463
10464-----BEGIN CERTIFICATE-----
10465MIID2jCCAsKgAwIBAgIJALKypfV8BItCMA0GCSqGSIb3DQEBBAUAMIGgMQswCQYD
10466(more lines) ...
10467TCQ+tbQ/DOiTXGKx1nlcKoPdkG+QVQVJthlQcpam
10468-----END CERTIFICATE-----
10469
10470    A type 2) by convention ends with file suffix ".pem" and looks like:
10471
10472-----BEGIN RSA PRIVATE KEY-----
10473MIIEpAIBAAKCAQEA4sApd7WaPKQRWnFe9T04D4pglQB0Ti0/dCVHxg8WEVQ8OdcW
10474(more lines) ...
104759kBmNotUiTpvRM+e7E/zRemhvY9qraFooqMWzi9JrgYfeLfSvvFfGw==
10476-----END RSA PRIVATE KEY-----
10477-----BEGIN CERTIFICATE-----
10478MIID2jCCAsKgAwIBAgIJALKypfV8BItCMA0GCSqGSIb3DQEBBAUAMIGgMQswCQYD
10479(more lines) ...
10480TCQ+tbQ/DOiTXGKx1nlcKoPdkG+QVQVJthlQcpam
10481-----END CERTIFICATE-----
10482
10483    You do not need to use the ".crt" or ".pem" convention if you do not want to.
10484
10485    First, either paste in the text or set the "Read from File" filename.
10486
10487    Next, set the "Save to File" name to the file where the imported certificate
10488    will be saved.
10489
10490    Then, click on "Save" to save the imported Certificate.
10491
10492    After you have imported the Certificate (or Key + Certificate), select it to
10493    use for a connection via the "MyCert" or "ServerCert" dialog.
10494}
10495	.icrt.f.t insert end $msg
10496
10497	global icert import_mode
10498
10499	set import_mode "paste"
10500
10501	set w .icrt.mf
10502	frame $w
10503
10504	radiobutton $w.p -pady 1 -anchor w -variable import_mode -value paste \
10505		-text "Paste" -command "import_check_mode .icrt"
10506
10507	radiobutton $w.f -pady 1 -anchor w -variable import_mode -value file \
10508		-text "Read from File:" -command "import_check_mode .icrt"
10509
10510	global import_file
10511	set import_file ""
10512	entry $w.e -width 40 -textvariable import_file
10513
10514	button $w.b -pady 1 -anchor w -text "Browse..." -command {import_browse .icrt}
10515	pack $w.b -side right
10516	pack $w.p $w.f -side left
10517	pack $w.e -side left -expand 1 -fill x
10518
10519	$w.b configure -state disabled
10520	$w.e configure -state disabled
10521
10522	label .icrt.plab -anchor w -text "Paste Certificate here:     (extra blank lines above or below are OK)"
10523	set h 22
10524	if [small_height] {
10525		set h 11
10526	} elseif {$uname == "Darwin"} {
10527		set h 11
10528	}
10529	scroll_text .icrt.paste 90 $h
10530
10531	button .icrt.cancel -text "Cancel" -command {destroy .icrt; catch {raise .c}}
10532	bind .icrt <Escape> {destroy .icrt; catch {raise .c}}
10533	wm protocol .icrt WM_DELETE_WINDOW {destroy .icrt; catch {raise .c}}
10534
10535	button .icrt.save -text "Save" -command {do_save .icrt}
10536
10537	set w .icrt.sf
10538	frame $w
10539
10540	label $w.l -text "Save to File:" -anchor w
10541	global import_save_file
10542	set import_save_file ""
10543	entry $w.e -width 40 -textvariable import_save_file
10544	button $w.b -pady 1 -anchor w -text "Browse..." -command import_save_browse
10545
10546	global also_save_to_accepted_certs
10547	set also_save_to_accepted_certs 0
10548	checkbutton .icrt.ac -anchor w -variable also_save_to_accepted_certs -text \
10549	    "Also Save to the 'Accepted Certs' directory" -relief raised
10550
10551	pack $w.b -side right
10552	pack $w.l -side left
10553	pack $w.e -side left -expand 1 -fill x
10554
10555	pack .icrt.save .icrt.cancel .icrt.ac .icrt.sf .icrt.mf -side bottom -fill x
10556	pack .icrt.paste .icrt.plab -side bottom -fill x
10557
10558	pack .icrt.f -side top -fill both -expand 1
10559
10560	.icrt.paste.t insert end ""
10561
10562	focus .icrt.paste.t
10563
10564	center_win .icrt
10565}
10566
10567proc save_cert {hp} {
10568
10569	global cert_text
10570
10571	toplev .scrt
10572	wm title .scrt "Import/Save SSL Certificate"
10573
10574	global scroll_text_focus
10575	set scroll_text_focus 0
10576	global uname
10577
10578	global accepted_cert_dialog_in_progress
10579	set h 20
10580	if {$accepted_cert_dialog_in_progress} {
10581		set mode "accepted"
10582		set h 15
10583		if [small_height] {
10584			set h 11
10585		}
10586	} else {
10587		set mode "normal"
10588		set h 20
10589		if [small_height] {
10590			set h 16
10591		}
10592	}
10593	scroll_text .scrt.f 90 $h
10594
10595	set scroll_text_focus 1
10596
10597	set msg1 {
10598    This dialog lets you import a SSL Certificate retrieved from a VNC server.
10599
10600    Be sure to have verified its authenticity via an external means (checking
10601    the MD5 hash value sent to you by the administrator, etc)
10602
10603    Set "Save to File" to the filename where the imported cert will be saved.
10604
10605    If you also want the Certificate to be saved to the pool of certs in the
10606    'Accepted Certs' directory, select the checkbox.  By default all Servers are
10607    verified against the certificates in this pool.
10608
10609    Then, click on "Save" to save the imported Certificate.
10610
10611    After you have imported the Certificate it will be automatically selected as
10612    the "ServerCert" for the next connection to this host: %HOST
10613
10614    To make the ServerCert setting to the imported cert file PERMANENT, select
10615    'Save' to save it in the profile for this host.
10616}
10617
10618	set msg2 {
10619    This dialog lets you import a SSL Certificate retrieved from a VNC server.
10620
10621    Be sure to have verified its authenticity via an external means (checking
10622    the MD5 hash value sent to you by the administrator, etc)
10623
10624    It will be added to the 'Accepted Certs' directory.  The "Save to File"
10625    below is already set to the correct directory and file name.
10626
10627    Click on "Save" to add it to the Accepted Certs.
10628
10629    It, and the other certs in that directory, will be used to authenticate
10630    any VNC Server that has "ACCEPTED_CERTS" as the "CertsDir" value in the
10631    "Certs..." dialog.  This is the default checking policy.
10632}
10633
10634	set msg ""
10635	if {$mode == "normal"} {
10636		set msg $msg1
10637	} else {
10638		set msg $msg2
10639	}
10640
10641	regsub {%HOST} $msg "$hp" msg
10642	.scrt.f.t insert end $msg
10643
10644	set w .scrt.mf
10645	frame $w
10646
10647	global import_file
10648	set import_file ""
10649	entry $w.e -width 40 -textvariable import_file
10650
10651	set h 22
10652	if [small_height] {
10653		set h 10
10654	}
10655	scroll_text .scrt.paste 90 $h
10656
10657	button .scrt.cancel -text "Cancel" -command {destroy .scrt; catch {raise .c}}
10658	bind .scrt <Escape> {destroy .scrt; catch {raise .c}}
10659	wm protocol .scrt WM_DELETE_WINDOW {destroy .scrt; catch {raise .c}}
10660
10661	global import_save_file
10662	if {$mode == "normal"} {
10663		button .scrt.save -text "Save" -command {do_save .scrt; set svcert $import_save_file}
10664	} else {
10665		button .scrt.save -text "Save" -command {do_save .scrt}
10666	}
10667
10668	if [regexp -nocase -- {ACCEPT} $cert_text] {
10669		if [regexp -nocase -- {Client certificate} $cert_text] {
10670			if [regexp -- {^:[0-9][0-9]*$} $hp] {
10671				if [regexp -nocase {subject=.*CN=([^/][^/]*)/} $cert_text mv0 mv1] {
10672					regsub -all {[ 	]} $mv1 "" mv1
10673					set hp "$mv1$hp"
10674				} else {
10675					set hp "listen$hp"
10676				}
10677			}
10678		}
10679	}
10680
10681	set w .scrt.sf
10682	frame $w
10683
10684	label $w.l -text "Save to File:" -anchor w
10685	set import_save_file "server:$hp.crt"
10686	global is_windows
10687	regsub -all {:} $import_save_file "-" import_save_file
10688
10689	set import_save_file [get_idir_certs ""]/$import_save_file
10690
10691	global fetch_cert_filename
10692	if {$fetch_cert_filename != ""} {
10693		set import_save_file $fetch_cert_filename
10694	}
10695
10696	entry $w.e -width 40 -textvariable import_save_file
10697	button $w.b -pady 1 -anchor w -text "Browse..." -command {import_save_browse .scrt}
10698
10699	pack $w.b -side right
10700	pack $w.l -side left
10701	pack $w.e -side left -expand 1 -fill x
10702
10703	global also_save_to_accepted_certs
10704	set also_save_to_accepted_certs 0
10705	if [regexp -nocase -- {ACCEPT} $cert_text] {
10706		if [regexp -nocase -- {Client certificate} $cert_text] {
10707			set also_save_to_accepted_certs 1
10708		}
10709	}
10710	checkbutton .scrt.ac -anchor w -variable also_save_to_accepted_certs -text \
10711	    "Also Save to the 'Accepted Certs' directory" -relief raised
10712
10713	if {$mode == "normal"} {
10714		pack .scrt.cancel .scrt.save .scrt.sf .scrt.ac .scrt.mf -side bottom -fill x
10715	} else {
10716		pack .scrt.cancel .scrt.save .scrt.sf          .scrt.mf -side bottom -fill x
10717	}
10718	pack .scrt.paste -side bottom -fill x
10719
10720	pack .scrt.f -side top -fill both -expand 1
10721
10722	set text ""
10723	set on 0
10724	foreach line [split $cert_text "\n"] {
10725		if [regexp -- {-----BEGIN CERTIFICATE-----} $line] {
10726			incr on
10727		}
10728		if {$on != 1} {
10729			continue;
10730		}
10731		append text "$line\n"
10732		if [regexp -- {-----END CERTIFICATE-----} $line] {
10733			set on 2
10734		}
10735	}
10736	global save_cert_text
10737	set save_cert_text $text
10738	.scrt.paste.t insert end "$text"
10739	global import_mode
10740	set import_mode "save_cert_text"
10741
10742	focus .scrt.paste.t
10743
10744	center_win .scrt
10745}
10746
10747
10748proc getcerts {} {
10749	global mycert svcert crtdir crlfil
10750	global use_ssh use_sshssl
10751	toplev .c
10752	wm title .c "SSL Certificates"
10753	frame .c.mycert
10754	frame .c.svcert
10755	frame .c.crtdir
10756	frame .c.crlfil
10757	label .c.mycert.l -anchor w -width 12 -text "MyCert:"
10758	label .c.svcert.l -anchor w -width 12 -text "ServerCert:"
10759	label .c.crtdir.l -anchor w -width 12 -text "CertsDir:"
10760	label .c.crlfil.l -anchor w -width 12 -text "CRL File:"
10761
10762	entry .c.mycert.e -width 32 -textvariable mycert -vcmd v_mycert
10763	entry .c.svcert.e -width 32 -textvariable svcert -vcmd v_svcert
10764	entry .c.crtdir.e -width 32 -textvariable crtdir
10765	entry .c.crlfil.e -width 32 -textvariable crlfil -vcmd v_crlfil
10766
10767	bind .c.mycert.e <Enter> {.c.mycert.e validate}
10768	bind .c.mycert.e <Leave> {.c.mycert.e validate}
10769	bind .c.svcert.e <Enter> {.c.svcert.e validate}
10770	bind .c.svcert.e <Leave> {.c.svcert.e validate}
10771
10772	button .c.mycert.b -text "Browse..." -command {set_mycert .c; catch {raise .c}}
10773	button .c.svcert.b -text "Browse..." -command {set_svcert .c; catch {raise .c}}
10774	button .c.crtdir.b -text "Browse..." -command {set_crtdir .c; catch {raise .c}}
10775	button .c.crlfil.b -text "Browse..." -command {set_crlfil .c; catch {raise .c}}
10776
10777	button .c.mycert.i -text "Info" -command {show_mycert}
10778	button .c.svcert.i -text "Info" -command {show_svcert}
10779	button .c.crtdir.i -text "Info" -command {}
10780	button .c.crlfil.i -text "Info" -command {show_crlfil}
10781
10782	bind .c.mycert.b <Enter> "v_mycert"
10783	bind .c.svcert.b <Enter> "v_svcert"
10784	bind .c.crlfil.b <Enter> "v_crlfil"
10785
10786	.c.mycert.i configure -state disabled
10787	.c.svcert.i configure -state disabled
10788	.c.crtdir.i configure -state disabled
10789	.c.crlfil.i configure -state disabled
10790
10791	bind .c.mycert.b <B3-ButtonRelease>   "show_mycert"
10792	bind .c.svcert.b <B3-ButtonRelease>   "show_svcert"
10793	bind .c.crlfil.b <B3-ButtonRelease>   "show_crlfil"
10794
10795	set do_crl 1
10796	set do_row 1
10797
10798	set c .c
10799	if {$do_row} {
10800		frame .c.b0
10801		set c .c.b0
10802	}
10803
10804	button $c.create -text "Create Certificate ..." -command {create_cert}
10805	button $c.import -text "Import Certificate ..." -command {import_cert}
10806	button $c.delete -text "Delete Certificate ..." -command {delete_cert .c}
10807
10808	if {$c != ".c"} {
10809		pack $c.create $c.import $c.delete  -fill x -expand 1 -side left
10810	}
10811
10812	frame .c.b
10813	button .c.b.done -text "Done" -command {catch {destroy .c}}
10814	bind .c <Escape> {destroy .c}
10815	button .c.b.help -text "Help" -command help_certs
10816	pack .c.b.help .c.b.done -fill x -expand 1 -side left
10817
10818	set wlist [list mycert svcert crtdir]
10819	lappend wlist crlfil
10820
10821	foreach w $wlist {
10822		pack .c.$w.l -side left
10823		pack .c.$w.e -side left -expand 1 -fill x
10824		pack .c.$w.b -side left
10825		pack .c.$w.i -side left
10826		bind .c.$w.e <Return> ".c.$w.b invoke"
10827		if {$use_ssh} {
10828			.c.$w.l configure -state disabled
10829			.c.$w.e configure -state disabled
10830			.c.$w.b configure -state disabled
10831		}
10832	}
10833
10834	global svcert_default_force mycert_default_force crlfil_default_force
10835	if {$mycert_default_force} {
10836		.c.mycert.e configure -state readonly
10837		.c.mycert.b configure -state disabled
10838	}
10839	if {$svcert_default_force} {
10840		.c.svcert.e configure -state readonly
10841		.c.svcert.b configure -state disabled
10842		.c.crtdir.e configure -state readonly
10843		.c.crtdir.b configure -state disabled
10844	}
10845	if {$crlfil_default_force} {
10846		.c.crlfil.e configure -state readonly
10847		.c.crlfil.b configure -state disabled
10848	}
10849
10850	if {$mycert != ""} {
10851		v_mycert
10852	}
10853	if {$svcert != ""} {
10854		v_svcert
10855	}
10856	if {$crlfil != ""} {
10857		v_crlfil
10858	}
10859
10860	set wlist [list .c.mycert .c.svcert .c.crtdir]
10861	if {$do_crl} {
10862		lappend wlist .c.crlfil
10863	}
10864	if {$c != ".c"} {
10865		lappend wlist $c
10866	} else {
10867		lappend wlist .c.create .c.import .c.delete
10868	}
10869	lappend wlist .c.b
10870
10871	eval pack $wlist -side top -fill x
10872
10873	center_win .c
10874	wm resizable .c 1 0
10875
10876	focus .c
10877}
10878
10879proc get_profiles_dir {} {
10880	global env is_windows
10881
10882	set dir ""
10883	if {$is_windows} {
10884		if [info exists env(SSVNC_HOME)] {
10885			set t "$env(SSVNC_HOME)/ss_vnc"
10886			regsub -all {\\} $t "/" t
10887			regsub -all {//*} $t "/" t
10888			if {! [file isdirectory $t]} {
10889				catch {file mkdir $t}
10890			}
10891			if [file isdirectory $t] {
10892				set dir $t
10893				set s "$t/profiles"
10894				if {! [file exists $s]} {
10895					catch {file mkdir $s}
10896				}
10897			}
10898		}
10899		if {$dir == ""} {
10900			set t [file dirname [pwd]]
10901			set t "$t/profiles"
10902			if [file isdirectory $t] {
10903				set dir $t
10904			}
10905		}
10906	} elseif [info exists env(SSVNC_HOME)] {
10907		set t "$env(SSVNC_HOME)/.vnc"
10908		catch {file mkdir $t}
10909		if [file isdirectory $t] {
10910			set dir $t
10911			set s "$t/profiles"
10912			if {! [file exists $s]} {
10913				catch {file mkdir $s}
10914			}
10915		}
10916	}
10917
10918	if {$dir != ""} {
10919
10920	} elseif [info exists env(SSVNC_BASEDIR)] {
10921		set dir $env(SSVNC_BASEDIR)
10922	} else {
10923		set dir [pwd]
10924	}
10925	if [file isdirectory "$dir/profiles"] {
10926		set dir "$dir/profiles"
10927	}
10928	return $dir
10929}
10930
10931proc globalize {} {
10932	global defs
10933	foreach var [array names defs] {
10934		uplevel global $var
10935	}
10936}
10937
10938proc load_include {include dir} {
10939	global include_vars defs
10940
10941	if [info exists include_vars] {
10942		unset include_vars
10943	}
10944
10945	foreach inc [split $include ", "] {
10946		set f [string trim $inc]
10947#puts "f=$f";
10948		if {$f == ""} {
10949			continue
10950		}
10951		set try ""
10952		if {[regexp {/} $f] || [regexp {\\} $f]} {
10953			set try $f;
10954		} else {
10955			set try "$dir/$f"
10956		}
10957		if {! [file exists $try]} {
10958			set try "$dir/$f.vnc"
10959		}
10960#puts "try: $try"
10961		if [file exists $try] {
10962			set fh ""
10963			catch {set fh [open $try "r"]}
10964			if {$fh == ""} {
10965				continue
10966			}
10967			mesg "Applying template: $inc"
10968			after 100
10969			while {[gets $fh line] > -1} {
10970				append inc_str "$line\n"
10971				if [regexp {^([^=]*)=(.*)$} $line m var val] {
10972					if {! [info exists defs($var)]} {
10973						continue
10974					}
10975					if {$var == "include_list"} {
10976						continue
10977					}
10978					set pct 0
10979					if {$var == "smb_mount_list"} {
10980						set pct 1
10981					}
10982					if {$var == "port_knocking_list"} {
10983						set pct 1
10984					}
10985					if {$pct} {
10986						regsub -all {%%%} $val "\n" val
10987					}
10988					if {$val != $defs($var)} {
10989#puts "include_vars $var $val"
10990						set include_vars($var) $val
10991					}
10992				}
10993			}
10994			catch {close $fh}
10995		}
10996	}
10997}
10998
10999proc unix_dialog_resize {{w .}} {
11000	global env is_windows uname unix_dialog_size
11001	set ok 0
11002	set width 600
11003	set height 300
11004	if {[info exists env(SSVNC_BIGGER_DIALOG)]} {
11005		set ok 1
11006		if {[regexp {([0-9][0-9]*)x([0-9][0-9]*)} $env(SSVNC_BIGGER_DIALOG) m wi he]} {
11007			set width $wi;
11008			set height $he;
11009		}
11010	} elseif {[info exists env(USER)] && $env(USER) == "runge"} {
11011		set ok 1
11012	}
11013	if {$ok} {
11014		# this is a personal hack because tk_getOpenFile size is not configurable.
11015		if {!$is_windows && $uname != "Darwin"} {
11016			if {$w == "."} {
11017				set w2 .__tk_filedialog
11018			} else {
11019				set w2 $w.__tk_filedialog
11020			}
11021			set w3 $w2.icons.canvas
11022			global udr_w4
11023			set udr_w4 $w2.f2.cancel
11024			if {! [info exists unix_dialog_size($w)]} {
11025				after 50 {global udr_w4; catch {$udr_w4 invoke}}
11026				tk_getOpenFile -parent $w -initialdir /
11027				set unix_dialog_size($w) 1
11028			}
11029			if [winfo exists $w3] {
11030				catch {$w3 configure -width $width}
11031				catch {$w3 configure -height $height}
11032			}
11033		}
11034	}
11035}
11036
11037proc delete_profile {{parent "."}} {
11038
11039	globalize
11040
11041	set dir [get_profiles_dir]
11042
11043	unix_dialog_resize $parent
11044	set file [tk_getOpenFile -parent $parent -initialdir $dir -title "DELETE VNC Profile"]
11045
11046	if {$file == ""} {
11047		return
11048	}
11049
11050	set tail [file tail $file]
11051
11052	set ans [tk_messageBox -type okcancel -title "Delete $tail" -message "Really Delete $file?" -icon warning]
11053
11054	if {$ans == "ok"} {
11055		catch {file delete $file}
11056		mesg "Deleted $tail"
11057	} else {
11058		mesg "Delete Skipped."
11059	}
11060}
11061
11062proc load_profile {{parent "."} {infile ""}} {
11063	global profdone
11064	global vncdisplay
11065
11066	globalize
11067
11068	set dir [get_profiles_dir]
11069
11070	if {$infile != ""} {
11071		set file $infile
11072	} else {
11073		unix_dialog_resize
11074		set file [tk_getOpenFile -parent $parent -defaultextension \
11075			".vnc" -initialdir $dir -title "Load VNC Profile"]
11076	}
11077
11078	if {$file == ""} {
11079		set profdone 1
11080		return
11081	}
11082	set fh [open $file "r"]
11083	if {! [info exists fh]} {
11084		set profdone 1
11085		return
11086	}
11087
11088	set goto_mode "";
11089	set str ""
11090	set include ""
11091	set sw 1
11092	while {[gets $fh line] > -1} {
11093		append str "$line\n"
11094		if [regexp {^include_list=(.*)$} $line m val] {
11095			set include $val
11096		}
11097		global ssh_only ts_only
11098		if {$ssh_only || $ts_only} {
11099			if [regexp {use_ssh=0} $line] {
11100				if {$sw} {
11101					mesg "Switching to SSVNC mode."
11102					set goto_mode "ssvnc"
11103					update
11104					after 300
11105				} else {
11106					bell
11107					mesg "Cannot Load an SSL profile in SSH-ONLY mode."
11108					set profdone 1
11109					close $fh
11110					return
11111				}
11112			}
11113		}
11114		if {! $ts_only} {
11115			if [regexp {ts_mode=1} $line] {
11116				if {$sw} {
11117					mesg "Switching to Terminal Services mode."
11118					set goto_mode "tsonly"
11119					update
11120					after 300
11121				} else {
11122					bell
11123					mesg "Cannot Load a Terminal Svcs profile SSVNC mode."
11124					set profdone 1
11125					close $fh
11126					return
11127				}
11128			}
11129		} else {
11130			if [regexp {ts_mode=0} $line] {
11131				if {$sw} {
11132					mesg "Switching to SSVNC mode."
11133					set goto_mode "ssvnc"
11134					update
11135					after 300
11136				} else {
11137					bell
11138					mesg "Cannot Load a Terminal Svcs profile SSVNC mode."
11139					set profdone 1
11140					close $fh
11141					return
11142				}
11143			}
11144		}
11145	}
11146	close $fh
11147
11148	if {$include != ""} {
11149		load_include $include $dir
11150	}
11151
11152	if {$goto_mode == "tsonly"} {
11153		to_tsonly
11154	} elseif {$goto_mode == "ssvnc"} {
11155		to_ssvnc
11156	} elseif {$goto_mode == "sshvnc"} {
11157		to_sshvnc
11158	}
11159	set_defaults
11160
11161	global include_vars
11162	if [info exists include_vars] {
11163		foreach var [array names include_vars] {
11164			set $var $include_vars($var)
11165		}
11166	}
11167
11168
11169	global use_ssl use_ssh use_sshssl
11170	set use_ssl 0
11171	set use_ssh 0
11172	set use_sshssl 0
11173
11174	global defs
11175	foreach line [split $str "\n"] {
11176		set line [string trim $line]
11177		if [regexp {^#} $line] {
11178			continue
11179		}
11180		if [regexp {^([^=]*)=(.*)$} $line m var val] {
11181			if {$var == "disp"} {
11182				set vncdisplay $val
11183				continue
11184			}
11185			if [info exists defs($var)] {
11186				set pct 0
11187				if {$var == "smb_mount_list"} {
11188					set pct 1
11189				}
11190				if {$var == "port_knocking_list"} {
11191					set pct 1
11192				}
11193				if {$pct} {
11194					regsub -all {%%%} $val "\n" val
11195				}
11196				set $var $val
11197			}
11198		}
11199	}
11200
11201	init_vncdisplay
11202	if {! $use_ssl && ! $use_ssh && ! $use_sshssl} {
11203		if {! $disable_all_encryption} {
11204			set use_ssl 1
11205		}
11206	}
11207	if {$use_ssl} {
11208		set use_ssh 0
11209		set use_sshssl 0
11210	} elseif {$use_ssh && $use_sshssl} {
11211		set use_ssh 0
11212	}
11213	sync_use_ssl_ssh
11214
11215	set compresslevel_text "Compress Level: $use_compresslevel"
11216	set quality_text "Quality: $use_quality"
11217
11218	set profdone 1
11219	putty_pw_entry check
11220	listen_adjust
11221	unixpw_adjust
11222
11223	global last_load
11224	set last_load [file tail $file]
11225
11226	global uname darwin_cotvnc
11227	if {$uname == "Darwin"} {
11228		if {$use_x11_macosx} {
11229			set darwin_cotvnc 0;
11230		} else {
11231			set darwin_cotvnc 1;
11232		}
11233	}
11234
11235	mesg "Loaded [file tail $file]"
11236}
11237
11238proc sync_use_ssl_ssh {} {
11239	global use_ssl use_ssh use_sshssl
11240	global disable_all_encryption
11241	if {$use_ssl} {
11242		ssl_ssh_adjust ssl
11243	} elseif {$use_ssh} {
11244		ssl_ssh_adjust ssh
11245	} elseif {$use_sshssl} {
11246		ssl_ssh_adjust sshssl
11247	} elseif {$disable_all_encryption} {
11248		ssl_ssh_adjust none
11249	} else {
11250		ssl_ssh_adjust ssl
11251	}
11252}
11253
11254proc save_profile {{parent "."}} {
11255	global is_windows uname
11256	global profdone
11257	global include_vars defs
11258	global ts_only
11259	global last_load
11260
11261	globalize
11262
11263	set dir [get_profiles_dir]
11264
11265	set vncdisp [get_vncdisplay]
11266
11267	set dispf [string trim $vncdisp]
11268	if {$dispf != ""} {
11269		regsub {[ 	].*$} $dispf "" dispf
11270		regsub -all {/} $dispf "" dispf
11271	} else {
11272		global ts_only
11273		if {$ts_only} {
11274			mesg "No VNC Terminal Server supplied."
11275		} else {
11276			mesg "No VNC Host:Disp supplied."
11277		}
11278		bell
11279		return
11280	}
11281	if {$is_windows || $uname == "Darwin"} {
11282		regsub -all {:} $dispf "-" dispf
11283	} else {
11284		regsub -all {:} $dispf "-" dispf
11285	}
11286	regsub -all {[\[\]]} $dispf "" dispf
11287	if {$ts_only && ![regexp {^TS-} $dispf]} {
11288		set dispf "TS-$dispf"
11289	}
11290	if {![regexp {\.vnc$} $dispf]} {
11291		set dispf "$dispf.vnc"
11292	}
11293
11294	set guess $dispf
11295	if {$last_load != ""} {
11296		set guess $last_load
11297	}
11298
11299	unix_dialog_resize
11300	set file [tk_getSaveFile -parent $parent -defaultextension ".vnc" \
11301		-initialdir $dir -initialfile "$guess" -title "Save VNC Profile"]
11302	if {$file == ""} {
11303		set profdone 1
11304		return
11305	}
11306	set fh [open $file "w"]
11307	if {! [info exists fh]} {
11308		set profdone 1
11309		return
11310	}
11311	set h [string trim $vncdisp]
11312	set p $h
11313	# XXX host_part
11314	regsub {:[0-9][0-9]*$} $h "" h
11315	set host $h
11316	regsub {[ 	].*$} $p "" p
11317	regsub {^.*:} $p "" p
11318	regsub { .*$} $p "" p
11319	if {$p == ""} {
11320		set p 0
11321	} elseif {![regexp {^[-0-9][0-9]*$} $p]} {
11322		set p 0
11323	}
11324	if {$p < 0} {
11325		set port $p
11326	} elseif {$p < 200} {
11327		set port [expr $p + 5900]
11328	} else {
11329		set port $p
11330	}
11331
11332	set h [string trim $vncdisp]
11333	regsub {cmd=.*$} $h "" h
11334	set h [string trim $h]
11335	if {! [regexp {[ 	]} $h]} {
11336		set h ""
11337	} else {
11338		regsub {^.*[ 	]} $h "" h
11339	}
11340	if {$h == ""} {
11341		set proxy ""
11342		set proxyport ""
11343	} else {
11344		set p $h
11345		regsub {:[0-9][0-9]*$} $h "" h
11346		set proxy $h
11347		regsub {[ 	].*$} $p "" p
11348		regsub {^.*:} $p "" p
11349		if {$p == ""} {
11350			set proxyport 0
11351		} else {
11352			set proxyport $p
11353		}
11354	}
11355
11356	puts $fh "\[connection\]"
11357	puts $fh "host=$host"
11358	puts $fh "port=$port"
11359	puts $fh "proxyhost=$proxy"
11360	puts $fh "proxyport=$proxyport"
11361	puts $fh "disp=$vncdisp"
11362	puts $fh "\n\[options\]"
11363	puts $fh "# parameters commented out with '#' indicate the default setting."
11364
11365	if {$include_list != ""} {
11366		load_include $include_list [get_profiles_dir]
11367	}
11368	global sshssl_sw
11369	if {! $use_ssl && ! $use_ssh && ! $use_sshssl} {
11370		if {$sshssl_sw == "none"} {
11371			set disable_all_encryption 1
11372		}
11373	}
11374
11375	global ts_only ssh_only
11376	if {$ts_only} {
11377		set ts_mode 1
11378	} else {
11379		set ts_mode 0
11380	}
11381	foreach var [lsort [array names defs]] {
11382		eval set val \$$var
11383		set pre ""
11384		if {$val == $defs($var)} {
11385			set pre "#"
11386		}
11387		if {$ssh_only && $var == "use_ssh"} {
11388			set pre ""
11389		}
11390		set pct 0
11391		if {$var == "smb_mount_list"} {
11392			set pct 1
11393		}
11394		if {$var == "port_knocking_list"} {
11395			set pct 1
11396		}
11397		if {$include_list != "" && [info exists include_vars($var)]} {
11398			if {$val == $include_vars($var)} {
11399				if {$pct} {
11400					regsub -all "\n" $val "%%%" val
11401				}
11402				puts $fh "#from include: $var=$val"
11403				continue
11404			}
11405		}
11406		if {$pct} {
11407			regsub -all "\n" $val "%%%" val
11408		}
11409		puts $fh "$pre$var=$val"
11410	}
11411
11412	close $fh
11413
11414	mesg "Saved Profile: [file tail $file]"
11415
11416	set last_load [file tail $file]
11417
11418	set profdone 1
11419}
11420
11421proc set_ssh {} {
11422	global use_ssl
11423	if {$use_ssl} {
11424		ssl_ssh_adjust ssh
11425	}
11426}
11427
11428proc expand_IP {redir} {
11429	if {! [regexp {:IP:} $redir]} {
11430		return $redir
11431	}
11432	if {! [regexp {(-R).*:IP:} $redir]} {
11433		return $redir
11434	}
11435
11436	set ip [guess_ip]
11437	set ip [string trim $ip]
11438	if {$ip == ""} {
11439		return $redir
11440	}
11441
11442	regsub -all {:IP:} $redir ":$ip:" redir
11443	return $redir
11444}
11445
11446proc rand_port {} {
11447	global rand_port_list
11448
11449	set p ""
11450	for {set i 0} {$i < 30} {incr i} {
11451		set p [expr 25000 + 35000 * rand()]
11452		set p [expr round($p)]
11453		if {![info exists rand_port_list($p)]} {
11454			break
11455		}
11456	}
11457	if {$p == ""} {
11458		unset rand_port_list
11459		set p [expr 25000 + 35000 * rand()]
11460		set p [expr round($p)]
11461	}
11462	set rand_port_list($p) 1
11463	return $p
11464}
11465
11466proc get_cups_redir {} {
11467	global cups_local_server cups_remote_port
11468	global cups_local_smb_server cups_remote_smb_port
11469
11470	regsub -all {[ 	]} $cups_local_server "" cups_local_server
11471	regsub -all {[ 	]} $cups_remote_port "" cups_remote_port
11472	regsub -all {[ 	]} $cups_local_smb_server "" cups_local_smb_server
11473	regsub -all {[ 	]} $cups_remote_smb_port "" cups_remote_smb_port
11474
11475	set redir ""
11476
11477	if {$cups_local_server != "" && $cups_remote_port != ""} {
11478		set redir "$cups_remote_port:$cups_local_server"
11479		regsub -all {['" 	]} $redir {} redir; #"
11480		set redir " -R $redir"
11481	}
11482	if {$cups_local_smb_server != "" && $cups_remote_smb_port != ""} {
11483		set redir2 "$cups_remote_smb_port:$cups_local_smb_server"
11484		regsub -all {['" 	]} $redir2 {} redir2; #"
11485		set redir "$redir -R $redir2"
11486	}
11487	set redir [expand_IP $redir]
11488	return $redir
11489}
11490
11491proc get_additional_redir {} {
11492	global additional_port_redirs additional_port_redirs_list
11493	global ts_only choose_x11vnc_opts
11494	if {! $additional_port_redirs || $additional_port_redirs_list == ""} {
11495		return ""
11496	}
11497	if {$ts_only && !$choose_x11vnc_opts} {
11498		return ""
11499	}
11500	set redir [string trim $additional_port_redirs_list]
11501	regsub -all {['"]} $redir {} redir; #"
11502	set redir " $redir"
11503	set redir [expand_IP $redir]
11504	return $redir
11505}
11506
11507proc get_sound_redir {} {
11508	global sound_daemon_remote_port sound_daemon_local_port
11509	global sound_daemon_x11vnc
11510
11511	regsub -all {[ 	]} $sound_daemon_remote_port "" sound_daemon_remote_port
11512	regsub -all {[ 	]} $sound_daemon_local_port "" sound_daemon_local_port
11513
11514	set redir ""
11515	if {$sound_daemon_local_port == "" || $sound_daemon_remote_port == ""} {
11516		return $redir
11517	}
11518
11519	set loc $sound_daemon_local_port
11520	if {! [regexp {:} $loc]} {
11521		global uname
11522		if {$uname == "Darwin"} {
11523			set loc "127.0.0.1:$loc"
11524		} else {
11525			global is_windows
11526			if {$is_windows} {
11527				global win_localhost
11528				set loc "$win_localhost:$loc"
11529			} else {
11530				set loc "localhost:$loc"
11531			}
11532		}
11533	}
11534	set redir "$sound_daemon_remote_port:$loc"
11535	regsub -all {['" 	]} $redir {} redir; #"
11536	set redir " -R $redir"
11537	set redir [expand_IP $redir]
11538	return $redir
11539}
11540
11541proc get_smb_redir {} {
11542	global smb_mount_list
11543
11544	set s [string trim $smb_mount_list]
11545	if {$s == ""} {
11546		return ""
11547	}
11548
11549	set did(0) 1
11550	set redir ""
11551	set mntlist ""
11552
11553	foreach line [split $s "\r\n"] {
11554		set str [string trim $line]
11555		if {$str == ""} {
11556			continue
11557		}
11558		if {[regexp {^#} $str]} {
11559			continue
11560		}
11561
11562		set port ""
11563		if [regexp {^([0-9][0-9]*)[ \t][ \t]*(.*)} $str mvar port rest] {
11564			# leading port
11565			set str [string trim $rest]
11566		}
11567
11568		# grab:  //share /dest [host[:port]]
11569		set share ""
11570		set dest ""
11571		set hostport ""
11572		foreach item [split $str] {
11573			if {$item == ""} {
11574				continue
11575			}
11576			if {$share == ""} {
11577				set share [string trim $item]
11578			} elseif {$dest == ""} {
11579				set dest [string trim $item]
11580			} elseif {$hostport == ""} {
11581				set hostport [string trim $item]
11582			}
11583		}
11584
11585		regsub {^~/} $dest {$HOME/} dest
11586
11587		# work out the local host:port
11588		set lhost ""
11589		set lport ""
11590		if {$hostport != ""} {
11591			if [regexp {(.*):([0-9][0-9]*)} $hostport mvar lhost lport] {
11592				;
11593			} else {
11594				set lhost $hostport
11595				set lport 139
11596			}
11597		} else {
11598			if [regexp {//([^/][^/]*)/} $share mvar h] {
11599				if [regexp {(.*):([0-9][0-9]*)} $h mvar lhost lport] {
11600					;
11601				} else {
11602					set lhost $h
11603					set lport 139
11604				}
11605			} else {
11606				global is_windows win_localhost
11607				set lhost "localhost"
11608				if {$is_windows} {
11609					set lhost $win_localhost
11610				}
11611				set lport 139
11612			}
11613		}
11614
11615		if {$port == ""} {
11616			if [info exists did("$lhost:$lport")] {
11617				# reuse previous one:
11618				set port $did("$lhost:$lport")
11619			} else {
11620				# choose one at random:
11621				for {set i 0} {$i < 3} {incr i} {
11622					set port [expr 20100 + 9000 * rand()]
11623					set port [expr round($port)]
11624					if { ! [info exists did($port)] } {
11625						break
11626					}
11627				}
11628			}
11629			set did($port) 1
11630		}
11631
11632		if {$mntlist != ""} {
11633			append mntlist " "
11634		}
11635		append mntlist "$share,$dest,$port"
11636
11637		if { ! [info exists did("$lhost:$lport")] } {
11638			append redir " -R $port:$lhost:$lport"
11639			set did("$lhost:$lport") $port
11640		}
11641	}
11642
11643	regsub -all {['"]} $redir {} redir; #"
11644	set redir [expand_IP $redir]
11645
11646	regsub -all {['"]} $mntlist {} mntlist; #"
11647
11648	set l [list]
11649	lappend l $redir
11650	lappend l $mntlist
11651	return $l
11652}
11653
11654proc ugly_setup_scripts {mode tag} {
11655
11656set cmd(1) {
11657	SSHD_PID=""
11658	FLAG=$HOME/.vnc-helper-flag__PID__
11659
11660	if [ "X$USER" = "X" ]; then
11661		USER=$LOGNAME
11662	fi
11663
11664	DO_CUPS=0
11665	cups_dir=$HOME/.cups
11666	cups_cfg=$cups_dir/client.conf
11667	cups_host=localhost
11668	cups_port=NNNN
11669
11670	DO_SMB=0
11671	DO_SMB_SU=0
11672	DO_SMB_WAIT=0
11673	smb_mounts=
11674	DONE_PORT_CHECK=NNNN
11675	smb_script=$HOME/.smb-mounts__PID__.sh
11676
11677	DO_SOUND=0
11678	DO_SOUND_KILL=0
11679	DO_SOUND_RESTART=0
11680	sound_daemon_remote_prog=
11681	sound_daemon_remote_args=
11682
11683	findpid() {
11684		db=0
11685		back=30
11686		touch $FLAG
11687		tty=`tty | sed -e "s,/dev/,,"`
11688
11689		if [ "X$TOPPID" = "X" ]; then
11690			TOPPID=$$
11691			if [ $db = 1 ]; then echo "set TOPPID to $TOPPID"; fi
11692			back=70
11693		fi
11694		#back=5
11695		if [ $db = 1 ]; then echo "TOPPID=$TOPPID THISPID=$$ back=$back"; fi
11696
11697		i=1
11698		while [ $i -lt $back ]
11699		do
11700			try=`expr $TOPPID - $i`
11701			if [ $try -lt 1 ]; then
11702				try=`expr 32768 + $try`
11703			fi
11704			if [ $db = 1 ]; then echo try-1=$try; ps $try; fi
11705			if ps $try 2>/dev/null | grep "sshd.*$USER" | grep "$tty" >/dev/null; then
11706				if [ $db = 1 ]; then echo Found=$try; fi
11707				SSHD_PID="$try"
11708				echo
11709				ps $try
11710				echo
11711				break
11712			fi
11713			i=`expr $i + 1`
11714		done
11715
11716		if [ "X$SSHD_PID" = "X" ]; then
11717			back=`expr $back + 20`
11718			#back=5
11719
11720			for fallback in 2 3
11721			do
11722				i=1
11723				while [ $i -lt $back ]
11724				do
11725					try=`expr $TOPPID - $i`
11726					if [ $try -lt 1 ]; then
11727						try=`expr 32768 + $try`
11728					fi
11729					match="sshd.*$USER"
11730					if [ $fallback = 3 ]; then
11731						match="sshd"
11732					fi
11733					if [ $db = 1 ]; then echo "try-$fallback=$try match=$match"; ps $try; fi
11734					if ps $try 2>/dev/null | grep "$match" >/dev/null; then
11735						if [ $db = 1 ]; then echo Found=$try; fi
11736						SSHD_PID="$try"
11737						echo
11738						ps $try
11739						echo
11740						break
11741					fi
11742					i=`expr $i + 1`
11743				done
11744				if [ "X$SSHD_PID" != "X" ]; then
11745					break
11746				fi
11747			done
11748		fi
11749		#curlie}
11750};
11751
11752set cmd(2) {
11753		#curlie{
11754		if [ "X$SSHD_PID" = "X" ]; then
11755			if [ $db = 1 ]; then
11756				echo
11757				pstr=`ps -elf | grep "$USER" | grep "$tty" | grep -v grep | grep -v PID | grep -v "ps -elf"`
11758				echo "$pstr"
11759			fi
11760			plist=`ps -elf | grep "$USER" | grep "$tty" | grep -v grep | grep -v PID | grep -v "ps -elf" | awk "{print \\\$4}" | sort -n`
11761			if [ $db = 1 ]; then
11762				echo
11763				echo "$plist"
11764			fi
11765			for try in $plist
11766			do
11767				if [ $db = 1 ]; then echo try-final=$try; ps $try; fi
11768				if echo "$try" | grep "^[0-9][0-9]*\\\$" > /dev/null; then
11769					:
11770				else
11771					continue
11772				fi
11773				if ps $try | egrep vnc-helper > /dev/null; then
11774					:
11775				else
11776					if [ $db = 1 ]; then echo Found=$try; fi
11777					SSHD_PID=$try
11778					echo
11779					ps $try
11780					echo
11781					break
11782				fi
11783			done
11784		fi
11785		if [ "X$SSHD_PID" = "X" ]; then
11786			#ugh
11787			SSHD_PID=$$
11788		fi
11789
11790		echo "vnc-helper: [for cups/smb/esd]      SSHD_PID=$SSHD_PID MY_PID=$$ TTY=$tty"
11791		echo "vnc-helper: To force me to finish:  rm $FLAG"
11792	}
11793
11794	wait_til_ssh_gone() {
11795		try_perl=""
11796		if type perl >/dev/null 2>&1; then
11797			if [ -d /proc -a -e /proc/$$ ]; then
11798				try_perl="1"
11799			fi
11800		fi
11801		if [ "X$try_perl" = "X1" ]; then
11802			# try to avoid wasting pids:
11803			perl -e "while (1) {if(-d \"/proc\" && ! -e \"/proc/$SSHD_PID\"){exit} if(! -f \"$FLAG\"){exit} sleep 1;}"
11804		else
11805			while [ 1 ]
11806			do
11807				ps $SSHD_PID > /dev/null 2>&1
11808				if [ $? != 0 ]; then
11809					break
11810				fi
11811				if [ ! -f $FLAG ]; then
11812					break
11813				fi
11814				sleep 1
11815			done
11816		fi
11817		rm -f $FLAG
11818		if [ "X$DO_SMB_WAIT" = "X1" ]; then
11819			rm -f $smb_script
11820		fi
11821	}
11822};
11823
11824set cmd(3) {
11825	update_client_conf() {
11826		mkdir -p $cups_dir
11827
11828		if [ ! -f $cups_cfg.back ]; then
11829			touch $cups_cfg.back
11830		fi
11831		if [ ! -f $cups_cfg ]; then
11832			touch $cups_cfg
11833		fi
11834
11835		if grep ssvnc-auto $cups_cfg > /dev/null; then
11836			:
11837		else
11838			cp -p $cups_cfg $cups_cfg.back
11839		fi
11840
11841		echo "#-ssvnc-auto:" > $cups_cfg
11842		sed -e "s/^ServerName/#-ssvnc-auto-#ServerName/" $cups_cfg.back >> $cups_cfg
11843		echo "ServerName $cups_host:$cups_port" >> $cups_cfg
11844
11845		echo
11846		echo "-----------------------------------------------------------------"
11847		echo "On `hostname`:"
11848		echo
11849		echo "The CUPS $cups_cfg config file has been set to:"
11850		echo
11851		cat $cups_cfg | grep -v "^#-ssvnc-auto:" | sed -e "s/^/  /"
11852		echo
11853		echo "If there are problems automatically restoring it, edit or remove"
11854		echo "the file to go back to the local CUPS settings."
11855		echo
11856		echo "A backup has been placed in: $cups_cfg.back"
11857		echo
11858		echo "See the SSVNC CUPS dialog for more details on printing."
11859		if type lpstat >/dev/null 2>&1; then
11860			echo
11861			echo "lpstat -a output:"
11862			echo
11863			(lpstat -a 2>&1 | sed -e "s/^/  /") &
11864			sleep 0.5 >/dev/null 2>&1
11865		fi
11866		echo "-----------------------------------------------------------------"
11867		echo
11868	}
11869
11870	reset_client_conf() {
11871		cp $cups_cfg $cups_cfg.tmp
11872		grep -v "^ServerName" $cups_cfg.tmp | grep -v "^#-ssvnc-auto:" | sed -e "s/^#-ssvnc-auto-#ServerName/ServerName/" > $cups_cfg
11873		rm -f $cups_cfg.tmp
11874	}
11875
11876	cupswait() {
11877		trap "" INT QUIT HUP
11878		trap "reset_client_conf; rm -f $FLAG; exit" TERM
11879		wait_til_ssh_gone
11880		reset_client_conf
11881	}
11882};
11883
11884#		if [ "X$DONE_PORT_CHECK" != "X" ]; then
11885#			if type perl >/dev/null 2>&1; then
11886#				perl -e "use IO::Socket::INET; \$SIG{INT} = \"IGNORE\"; \$SIG{QUIT} = \"IGNORE\"; \$SIG{HUP} = \"INGORE\"; my \$client = IO::Socket::INET->new(Listen => 5, LocalAddr => \"localhost\", LocalPort => $DONE_PORT_CHECK, Proto => \"tcp\")->accept(); \$line = <\$client>; close \$client; unlink \"$smb_script\";" </dev/null >/dev/null 2>/dev/null &
11887#				if [ $? = 0 ]; then
11888#					have_perl_done="1"
11889#				fi
11890#			fi
11891#		fi
11892
11893set cmd(4) {
11894	smbwait() {
11895		trap "" INT QUIT HUP
11896		wait_til_ssh_gone
11897	}
11898	do_smb_mounts() {
11899		if [ "X$smb_mounts" = "X" ]; then
11900			return
11901		fi
11902		echo > $smb_script
11903		have_perl_done=""
11904		echo "echo" >> $smb_script
11905		dests=""
11906		for mnt in $smb_mounts
11907		do
11908			smfs=`echo "$mnt" | awk -F, "{print \\\$1}"`
11909			dest=`echo "$mnt" | awk -F, "{print \\\$2}"`
11910			port=`echo "$mnt" | awk -F, "{print \\\$3}"`
11911			dest=`echo "$dest" | sed -e "s,__USER__,$USER,g" -e "s,__HOME__,$HOME,g"`
11912			if [ ! -d $dest ]; then
11913				mkdir -p $dest
11914			fi
11915			echo "echo SMBMOUNT:" >> $smb_script
11916			echo "echo smbmount $smfs $dest -o uid=$USER,ip=127.0.0.1,port=$port" >> $smb_script
11917			echo "smbmount \"$smfs\" \"$dest\" -o uid=$USER,ip=127.0.0.1,port=$port" >> $smb_script
11918			echo "echo; df \"$dest\"; echo" >> $smb_script
11919			dests="$dests $dest"
11920		done
11921		#curlie}
11922};
11923
11924set cmd(5) {
11925		echo "(" >> $smb_script
11926		echo "un_mnt() {" >> $smb_script
11927		for dest in $dests
11928		do
11929			echo "  echo smbumount $dest" >> $smb_script
11930			echo "  smbumount \"$dest\"" >> $smb_script
11931		done
11932		echo "}" >> $smb_script
11933		echo "trap \"\" INT QUIT HUP" >> $smb_script
11934		echo "trap \"un_mnt; exit\" TERM" >> $smb_script
11935
11936		try_perl=""
11937		if type perl >/dev/null 2>&1; then
11938			try_perl=1
11939		fi
11940		uname=`uname`
11941		if [ "X$uname" != "XLinux" -a "X$uname" != "XSunOS" -a "X$uname" != "XDarwin" ]; then
11942			try_perl=""
11943		fi
11944
11945		if [ "X$try_perl" = "X" ]; then
11946			echo "while [ -f $smb_script ]" >> $smb_script
11947			echo "do" >> $smb_script
11948			echo "     sleep 1" >> $smb_script
11949			echo "done" >> $smb_script
11950		else
11951			echo "perl -e \"while (-f \\\"$smb_script\\\") {sleep 1;} exit 0;\"" >> $smb_script
11952		fi
11953		echo "un_mnt" >> $smb_script
11954		echo ") &" >> $smb_script
11955		echo "-----------------------------------------------------------------"
11956		echo "On `hostname`:"
11957		echo
11958		if [ "$DO_SMB_SU" = "0" ]; then
11959			echo "We now run the smbmount script as user $USER"
11960			echo
11961			echo sh $smb_script
11962			sh $smb_script
11963			rc=0
11964		elif [ "$DO_SMB_SU" = "1" ]; then
11965			echo "We now run the smbmount script via su(1)"
11966			echo
11967			echo "The first \"Password:\" will be for that of root to run the smbmount script."
11968			echo
11969			echo "Subsequent \"Password:\" will be for the SMB share(s) (hit Return if no passwd)"
11970			echo
11971			echo SU:
11972			echo "su root -c \"sh $smb_script\""
11973			su root -c "sh $smb_script"
11974			rc=$?
11975		elif [ "$DO_SMB_SU" = "2" ]; then
11976			echo "We now run the smbmount script via sudo(8)"
11977			echo
11978			echo "The first \"Password:\" will be for that of the sudo(8) password."
11979			echo
11980			echo "Subsequent \"Password:\" will be for the SMB shares (hit enter if no passwd)"
11981			echo
11982			echo SUDO:
11983			sd="sudo"
11984			echo "$sd sh $smb_script"
11985			$sd sh $smb_script
11986			rc=$?
11987		fi
11988};
11989
11990set cmd(6) {
11991		#curlie{
11992		echo
11993		if [ "$rc" = 0 ]; then
11994			if [ "X$have_perl_done" = "X1" -o 1 = 1 ] ; then
11995				echo
11996				echo "Your SMB shares will be unmounted when the VNC connection closes,"
11997				echo "*AS LONG AS* No Applications have any of the share files opened or are"
11998				echo "cd-ed into any of the share directories."
11999				echo
12000				echo "Try to make sure nothing is accessing the SMB shares before disconnecting"
12001				echo "the VNC session.  If you fail to do that follow these instructions:"
12002			fi
12003			echo
12004			echo "To unmount your SMB shares make sure no applications are still using any of"
12005			echo "the files and no shells are still cd-ed into the share area, then type:"
12006			echo
12007			echo "   rm -f $smb_script"
12008			echo
12009			echo "In the worst case run: smbumount /path/to/mount/point for each mount as root"
12010			echo
12011			echo "Even with the remote redirection gone the kernel should umount after a timeout."
12012		else
12013			echo
12014			if [ "$DO_SMB_SU" = "1" ]; then
12015				echo "su(1) to run smbmount(8) failed."
12016			elif [ "$DO_SMB_SU" = "2" ]; then
12017				echo "sudo(8) to run smbmount(8) failed."
12018			fi
12019			rm -f $smb_script
12020		fi
12021		echo "-----------------------------------------------------------------"
12022		echo
12023	}
12024};
12025
12026set cmd(7) {
12027
12028	setup_sound() {
12029		dpid=""
12030		d=$sound_daemon_remote_prog
12031		if type pgrep >/dev/null 2>/dev/null; then
12032			dpid=`pgrep -U $USER -x $d | head -1`
12033		else
12034			dpid=`env PATH=/usr/ucb:$PATH ps wwwwaux | grep -w $USER | grep -w $d | grep -v grep | head -1`
12035		fi
12036		echo "-----------------------------------------------------------------"
12037		echo "On `hostname`:"
12038		echo
12039		echo "Setting up Sound: pid=$dpid"
12040		if [ "X$dpid" != "X" ]; then
12041			dcmd=`env PATH=/usr/ucb:$PATH ps wwwwaux | grep -w $USER | grep -w $d | grep -w $dpid | grep -v grep | head -1 | sed -e "s/^.*$d/$d/"`
12042			if [ "X$DO_SOUND_KILL" = "X1" ]; then
12043				echo "Stopping sound daemon: $sound_daemon_remote_prog $dpid"
12044				echo "sound cmd: $dcmd"
12045				kill -TERM $dpid
12046			fi
12047		fi
12048		echo "-----------------------------------------------------------------"
12049		echo
12050	}
12051
12052	reset_sound() {
12053		if [ "X$DO_SOUND_RESTART" = "X1" ]; then
12054			d=$sound_daemon_remote_prog
12055			a=$sound_daemon_remote_args
12056			echo "Restaring sound daemon: $d $a"
12057			$d $a </dev/null >/dev/null 2>&1 &
12058		fi
12059	}
12060
12061	soundwait() {
12062		trap "" INT QUIT HUP
12063		trap "reset_sound; rm -f $FLAG; exit" TERM
12064		wait_til_ssh_gone
12065		reset_sound
12066	}
12067
12068
12069	findpid
12070
12071	if [ $DO_SMB = 1 ]; then
12072		do_smb_mounts
12073	fi
12074
12075	waiter=0
12076
12077	if [ $DO_CUPS = 1 ]; then
12078		update_client_conf
12079		cupswait </dev/null >/dev/null 2>/dev/null &
12080		waiter=1
12081	fi
12082
12083	if [ $DO_SOUND = 1 ]; then
12084		setup_sound
12085		soundwait </dev/null >/dev/null 2>/dev/null &
12086		waiter=1
12087	fi
12088	if [ $DO_SMB_WAIT = 1 ]; then
12089		if [ $waiter != 1 ]; then
12090			smbwait </dev/null >/dev/null 2>/dev/null &
12091			waiter=1
12092		fi
12093	fi
12094
12095
12096	#FINMSG
12097	echo "--main-vnc-helper-finished--"
12098	#cat $0
12099	rm -f $0
12100	exit 0
12101};
12102
12103	set cmdall ""
12104
12105	for {set i 1} {$i <= 7} {incr i} {
12106		set v $cmd($i);
12107		regsub -all "\n" $v "%" v
12108		regsub -all {.curlie.} $v "" v
12109		set cmd($i) $v
12110		append cmdall "echo "
12111		if {$i == 1} {
12112			append cmdall {TOPPID=$$ %}
12113		}
12114		append cmdall {'}
12115		append cmdall $cmd($i)
12116		append cmdall {' | tr '%' '\n'}
12117		if {$i == 1} {
12118			append cmdall {>}
12119		} else {
12120			append cmdall {>>}
12121		}
12122		append cmdall {$HOME/.vnc-helper-cmd__PID__; }
12123	}
12124	append cmdall {sh $HOME/.vnc-helper-cmd__PID__; }
12125
12126	regsub -all {vnc-helper-cmd} $cmdall "vnc-helper-cmd-$mode" cmdall
12127	if {$tag == ""} {
12128		set tag [pid]
12129	}
12130	regsub -all {__PID__} $cmdall "$tag" cmdall
12131
12132	set orig $cmdall
12133
12134	global use_cups cups_local_server cups_remote_port cups_manage_rcfile ts_only ts_cups_manage_rcfile cups_x11vnc
12135	regsub -all {[ 	]} $cups_local_server "" cups_local_server
12136	regsub -all {[ 	]} $cups_remote_port "" cups_remote_port
12137	if {$use_cups} {
12138		set dorc 0
12139		if {$ts_only} {
12140			if {$ts_cups_manage_rcfile} {
12141				set dorc 1
12142			}
12143		} else {
12144			if {$cups_manage_rcfile} {
12145				set dorc 1
12146			}
12147		}
12148		if {$dorc && $mode == "post"} {
12149			if {$cups_local_server != "" && $cups_remote_port != ""} {
12150				regsub {DO_CUPS=0} $cmdall {DO_CUPS=1} cmdall
12151				regsub {cups_port=NNNN} $cmdall "cups_port=$cups_remote_port" cmdall
12152			}
12153		}
12154	}
12155
12156	global use_smbmnt smb_su_mode smb_mounts
12157	if {$use_smbmnt} {
12158		if {$smb_mounts != ""} {
12159			set smbm $smb_mounts
12160			regsub -all {%USER} $smbm "__USER__" smbm
12161			regsub -all {%HOME} $smbm "__HOME__" smbm
12162			if {$mode == "pre"} {
12163				regsub {DO_SMB=0} $cmdall {DO_SMB=1} cmdall
12164				if {$smb_su_mode == "su"} {
12165					regsub {DO_SMB_SU=0} $cmdall {DO_SMB_SU=1} cmdall
12166				} elseif {$smb_su_mode == "sudo"} {
12167					regsub {DO_SMB_SU=0} $cmdall {DO_SMB_SU=2} cmdall
12168				} elseif {$smb_su_mode == "none"} {
12169					regsub {DO_SMB_SU=0} $cmdall {DO_SMB_SU=0} cmdall
12170				} else {
12171					regsub {DO_SMB_SU=0} $cmdall {DO_SMB_SU=1} cmdall
12172				}
12173				regsub {smb_mounts=} $cmdall "smb_mounts=\"$smbm\"" cmdall
12174			} elseif {$mode == "post"} {
12175				regsub {DO_SMB_WAIT=0} $cmdall {DO_SMB_WAIT=1} cmdall
12176			}
12177		}
12178	}
12179
12180	global use_sound
12181	if {$use_sound} {
12182		if {$mode == "pre"} {
12183			global sound_daemon_remote_cmd sound_daemon_kill sound_daemon_restart
12184			if {$sound_daemon_kill} {
12185				regsub {DO_SOUND_KILL=0} $cmdall {DO_SOUND_KILL=1} cmdall
12186				regsub {DO_SOUND=0} $cmdall {DO_SOUND=1} cmdall
12187			}
12188			if {$sound_daemon_restart} {
12189				regsub {DO_SOUND_RESTART=0} $cmdall {DO_SOUND_RESTART=1} cmdall
12190				regsub {DO_SOUND=0} $cmdall {DO_SOUND=1} cmdall
12191			}
12192			set sp [string trim $sound_daemon_remote_cmd]
12193			regsub {[ \t].*$} $sp "" sp
12194			set sa [string trim $sound_daemon_remote_cmd]
12195			regsub {^[^ \t][^ \t]*[ \t][ \t]*} $sa "" sa
12196			regsub {sound_daemon_remote_prog=} $cmdall "sound_daemon_remote_prog=\"$sp\"" cmdall
12197			regsub {sound_daemon_remote_args=} $cmdall "sound_daemon_remote_args=\"$sa\"" cmdall
12198		}
12199	}
12200
12201	if {$mode == "pre"} {
12202		set dopre 0
12203		if {$use_smbmnt && $smb_mounts != ""} {
12204			set dopre 1
12205		}
12206		if {$use_sound && $sound_daemon_kill} {
12207			set dopre 1
12208		}
12209		if {$dopre} {
12210			global is_windows
12211			if {$is_windows} {
12212				regsub {#FINMSG} $cmdall {echo "Now Go Click on the Label to Start the 2nd SSH"} cmdall
12213			} else {
12214				regsub {#FINMSG} $cmdall {echo "Finished with the 1st SSH tasks, the 2nd SSH should start shortly..."} cmdall
12215			}
12216		}
12217	}
12218
12219	set cmdstr $cmdall
12220
12221	if {"$orig" == "$cmdall"} {
12222		set cmdstr ""
12223	}
12224	global env
12225	if [info exists env(SSVNC_DEBUG_CUPS)] {
12226		regsub -all {db=0} $cmdstr "db=1" cmdstr
12227		set pout ""
12228		regsub -all {%} $cmdstr "\n" pout
12229		puts stderr "\nSERVICE REDIR COMMAND:\n\n$pout\n"
12230	}
12231	return $cmdstr
12232}
12233
12234proc ts_unixpw_dialog {} {
12235
12236	toplev .uxpw
12237	wm title .uxpw "Use unixpw"
12238
12239	scroll_text .uxpw.f 80 14
12240
12241	global ts_unixpw
12242
12243	set msg {
12244    This enables the x11vnc unixpw mode.  A Login: and Password: dialog
12245    will be presented in the VNC Viewer for the user to provide any Unix
12246    username and password whose session he wants to connect to.  So this
12247    may require typing in the password a 2nd time after the one for SSH.
12248
12249    This mode is useful if a shared terminal services user (e.g. 'tsuser')
12250    is used for the SSH login part (say via the SSH authorized_keys
12251    mechanism and all users share the same private SSH key for 'tsuser').
12252
12253    Note, However that the default usage of a per-user SSH login should
12254    be the simplest and also sufficient for most situations, in which
12255    case this "Use unixpw" option should NOT be selected.
12256}
12257	.uxpw.f.t insert end $msg
12258
12259	button .uxpw.cancel -text "Cancel" -command {destroy .uxpw; set ts_unixpw 0}
12260	bind .uxpw <Escape> {destroy .uxpw; set ts_unixpw 0}
12261	wm protocol .uxpw WM_DELETE_WINDOW {destroy .uxpw; set ts_unixpw 0}
12262
12263	button .uxpw.done -text "Done" -command {destroy .uxpw; set ts_unixpw 1}
12264
12265	pack .uxpw.done .uxpw.cancel -side bottom -fill x
12266	pack .uxpw.f -side top -fill both -expand 1
12267
12268	center_win .uxpw
12269}
12270
12271proc ts_vncshared_dialog {} {
12272
12273	toplev .vncs
12274	wm title .vncs "VNC Shared"
12275
12276	scroll_text .vncs.f 80 23
12277
12278	global ts_vncshared
12279
12280	set msg {
12281    Normal use of this program, 'tsvnc', *ALREADY* allows simultaneous
12282    shared access of the remote desktop:   You simply log in as many
12283    times from as many different locations with 'tsvnc' as you like.
12284
12285    However, doing it that way starts up a new x11vnc for each connection.
12286    In some circumstances you may want a single x11vnc running but allow
12287    multiple VNC viewers to access it simultaneously.
12288
12289    This option (VNC Shared) enables that rarer usage case by passing
12290    '-shared' to the remote x11vnc command.
12291
12292    With this option enabled, the new shared connections must
12293    still connect to the Terminal Server via SSH for encryption and
12294    authentication.  They must also do the normal SSH port redirection
12295    to access the x11vnc port (usually 5900, but look for the PORT=
12296    output for the actual value).
12297
12298    They could use SSVNC for that, or do it manually in terminal
12299    windows, more information:
12300
12301       http://www.karlrunge.com/x11vnc/#tunnelling
12302}
12303	.vncs.f.t insert end $msg
12304
12305	button .vncs.cancel -text "Cancel" -command {destroy .vncs; set ts_vncshared 0}
12306	bind .vncs <Escape> {destroy .vncs; set ts_vncshared 0}
12307	wm protocol .vncs WM_DELETE_WINDOW {destroy .vncs; set ts_vncshared 0}
12308	button .vncs.done -text "Done" -command {destroy .vncs; set ts_vncshared 1}
12309
12310	pack .vncs.done .vncs.cancel -side bottom -fill x
12311	pack .vncs.f -side top -fill both -expand 1
12312
12313	center_win .vncs
12314}
12315
12316proc ts_multi_dialog {} {
12317
12318	toplev .mult
12319	wm title .mult "Multiple Sessions"
12320
12321	scroll_text .mult.f 80 21
12322
12323	global ts_multisession choose_multisession
12324
12325	set msg {
12326    Normally in Terminal Services mode (tsvnc) your user account (the
12327    one you SSH in as) can only have a single Terminal Services X session
12328    running at a time on one server machine.
12329
12330    This is simply because x11vnc chooses the first Desktop (X session)
12331    of yours that it can find.  It will never create a 2nd X session
12332    because it keeps finding the 1st one.
12333
12334    To have Multiple Sessions for one username on a single machine,
12335    choose a unique Session "Tag", that will be associated with the X
12336    session and x11vnc will only choose the one that has this Tag.
12337
12338    For this to work ALL of your sessions on the server machine must
12339    have a different tag (that is, if you have an existing session with
12340    no tag, x11vnc might find a tagged one first instead of it).
12341
12342    The tag must be made of only letters, numbers, dash, or underscore.
12343
12344    Examples:  KDE_SMALL,  gnome-2,  test1
12345}
12346	.mult.f.t insert end $msg
12347
12348	frame .mult.c
12349	label .mult.c.l -anchor w -text "Tag:"
12350	entry .mult.c.e -width 20 -textvariable ts_multisession
12351	pack .mult.c.l -side left
12352	pack .mult.c.e -side left -expand 1 -fill x
12353
12354	button .mult.cancel -text "Cancel" -command {destroy .mult; set choose_multisession 0}
12355	bind .mult <Escape> {destroy .mult; set choose_multisession 0}
12356	wm protocol .mult WM_DELETE_WINDOW {destroy .mult; set choose_multisession 0}
12357
12358	bind .mult.c.e <Return> {destroy .mult; set choose_multisession 1}
12359	button .mult.done -text "Done" -command {destroy .mult; set choose_multisession 1}
12360
12361	pack .mult.done .mult.cancel .mult.c -side bottom -fill x
12362	pack .mult.f -side top -fill both -expand 1
12363
12364	center_win .mult
12365	focus .mult.c.e
12366}
12367
12368proc ts_xlogin_dialog {} {
12369
12370	toplev .xlog
12371	wm title .xlog "X Login Greeter"
12372
12373	set h 33
12374	if [small_height] {
12375		set h 28
12376	}
12377	scroll_text .xlog.f 80 $h
12378
12379	global ts_xlogin
12380
12381	set msg {
12382    If you have root (sudo(1)) permission on the remote machine, you
12383    can have x11vnc try to connect to a X display(s) that has No One
12384    Logged In Yet.  This is most likely the login greeter running on
12385    the Physical console.  sudo(1) is used to run x11vnc with FD_XDM=1.
12386
12387    This is different from tsvnc's regular Terminal Services mode where
12388    usually a virtual (RAM only, e.g. Xvfb) X server used.  With this option
12389    it is the physical graphics hardware that will be connected to.
12390
12391    Note that if your user is ALREADY logged into the physical display,
12392    you don't need to use this X Login option because x11vnc should find
12393    it in its normal find-display procedure and not need sudo(1).
12394
12395    An initial ssh running 'sudo id' is performed to try to 'prime'
12396    sudo so the 2nd one that runs x11vnc does not need a password.
12397    This may not always succeed...
12398
12399    Note that if someone is already logged into the display console
12400    via XDM (GDM, KDM etc.) you will see and control their X session.
12401
12402    Otherwise, you will get the Greeter X login screen where you can
12403    log in via username and password.  Your SSVNC 'Terminal Services'
12404    Desktop Type, Size, Printing etc. settings will be ignored in this
12405    case of course because XDM, GDM, or KDM is creating your X session,
12406    not x11vnc.
12407
12408    Note that the GDM display manager has a setting KillInitClients in
12409    gdm.conf that will kill x11vnc right after you log in, and so you would
12410    have to repeat the whole process ('Connect' button) to attach to your
12411    session. See http://www.karlrunge.com/x11vnc/faq.html#faq-display-manager
12412    for more info.
12413}
12414	.xlog.f.t insert end $msg
12415
12416	button .xlog.cancel -text "Cancel" -command {destroy .xlog; set ts_xlogin 0}
12417	bind .xlog <Escape> {destroy .xlog; set ts_xlogin 0}
12418	wm protocol .xlog WM_DELETE_WINDOW {destroy .xlog; set ts_xlogin 0}
12419
12420	button .xlog.done -text "Done" -command {destroy .xlog; set ts_xlogin 1}
12421
12422	pack .xlog.done .xlog.cancel -side bottom -fill x
12423	pack .xlog.f -side top -fill both -expand 1
12424
12425	center_win .xlog
12426}
12427
12428
12429proc ts_othervnc_dialog {} {
12430
12431	toplev .ovnc
12432	wm title .ovnc "Other VNC Server"
12433
12434	scroll_text .ovnc.f 80 21
12435
12436	global ts_othervnc choose_othervnc
12437
12438	set msg {
12439    The x11vnc program running on the remote machine can be instructed to
12440    immediately redirect to some other (3rd party, e.g. Xvnc or vnc.so)
12441    VNC server.
12442
12443    It should be a little faster to have x11vnc forward the VNC protocol
12444    rather than having it poll the corresponding X server for changes
12445    in the way it normally does and translate to VNC.
12446
12447    This mode also enables a simple way to add SSL or find X display
12448    support to a 3rd party VNC Server lacking these features.
12449
12450    In the entry box put the other vnc display, e.g. "localhost:0" or
12451    "somehost:5".
12452
12453    The string "find" in the entry will have x11vnc try to find an X
12454    display in its normal way, and then redirect to the corresponding VNC
12455    server port.  This assumes if the X display is, say, :2 (i.e. port
12456    6002) then the VNC display is also :2 (i.e. port 5902).  This mode is
12457    the same as an "X Server Type" of "Xvnc.redirect" (and overrides it).
12458}
12459	.ovnc.f.t insert end $msg
12460
12461	frame .ovnc.c
12462	label .ovnc.c.l -anchor w -text "Other VNC Server:"
12463	entry .ovnc.c.e -width 20 -textvariable ts_othervnc
12464	pack .ovnc.c.l -side left
12465	pack .ovnc.c.e -side left -expand 1 -fill x
12466
12467	button .ovnc.cancel -text "Cancel" -command {destroy .ovnc; set choose_othervnc 0}
12468	bind .ovnc <Escape> {destroy .ovnc; set choose_othervnc 0}
12469	wm protocol .ovnc WM_DELETE_WINDOW {destroy .ovnc; set choose_othervnc 0}
12470	button .ovnc.done -text "Done" -command {destroy .ovnc; set choose_othervnc 1}
12471	bind .ovnc.c.e <Return> {destroy .ovnc; set choose_othervnc 1}
12472
12473	if {$ts_othervnc == ""} {
12474		set ts_othervnc "find"
12475	}
12476
12477	pack .ovnc.done .ovnc.cancel .ovnc.c -side bottom -fill x
12478	pack .ovnc.f -side top -fill both -expand 1
12479
12480	center_win .ovnc
12481	focus .ovnc.c.e
12482}
12483
12484proc ts_sleep_dialog {} {
12485
12486	toplev .eslp
12487	wm title .eslp "Extra Sleep"
12488
12489	scroll_text .eslp.f 80 5
12490
12491	global extra_sleep
12492
12493	set msg {
12494    Sleep: Enter a number to indicate how many extra seconds to sleep
12495    while waiting for the VNC viewer to start up.  On Windows this
12496    can give extra time to enter the Putty/Plink password, etc.
12497}
12498	.eslp.f.t insert end $msg
12499
12500	frame .eslp.c
12501	label .eslp.c.l -anchor w -text "Extra Sleep:"
12502	entry .eslp.c.e -width 20 -textvariable extra_sleep
12503	pack .eslp.c.l -side left
12504	pack .eslp.c.e -side left -expand 1 -fill x
12505
12506	button .eslp.cancel -text "Cancel" -command {destroy .eslp; set choose_sleep 0}
12507	bind .eslp <Escape> {destroy .eslp; set choose_sleep 0}
12508	wm protocol .eslp WM_DELETE_WINDOW {destroy .eslp; set choose_sleep 0}
12509	button .eslp.done -text "Done" -command {destroy .eslp; set choose_sleep 1}
12510	bind .eslp.c.e <Return> {destroy .eslp; set choose_sleep 1}
12511
12512	global choose_sleep
12513	if {! $choose_sleep} {
12514		set extra_sleep ""
12515	}
12516
12517	pack .eslp.done .eslp.cancel .eslp.c -side bottom -fill x
12518	pack .eslp.f -side top -fill both -expand 1
12519
12520	center_win .eslp
12521	focus .eslp.c.e
12522}
12523
12524proc ts_putty_args_dialog {} {
12525
12526	toplev .parg
12527	wm title .parg "Putty Args"
12528
12529	scroll_text .parg.f 80 5
12530
12531	global putty_args
12532
12533	set msg {
12534    Putty Args: Enter a string to be added to every plink.exe and putty.exe
12535    command line.  For example: -i C:\mykey.ppk
12536}
12537	.parg.f.t insert end $msg
12538
12539	frame .parg.c
12540	label .parg.c.l -anchor w -text "Putty Args:"
12541	entry .parg.c.e -width 20 -textvariable putty_args
12542	pack .parg.c.l -side left
12543	pack .parg.c.e -side left -expand 1 -fill x
12544
12545	button .parg.cancel -text "Cancel" -command {destroy .parg; set choose_parg 0}
12546	bind .parg <Escape> {destroy .parg; set choose_parg 0}
12547	wm protocol .parg WM_DELETE_WINDOW {destroy .parg; set choose_parg 0}
12548	button .parg.done -text "Done" -command {destroy .parg; set choose_parg 1}
12549	bind .parg.c.e <Return> {destroy .parg; set choose_parg 1}
12550
12551	global choose_parg
12552	if {! $choose_parg} {
12553		set putty_args ""
12554	}
12555
12556	pack .parg.done .parg.cancel .parg.c -side bottom -fill x
12557	pack .parg.f -side top -fill both -expand 1
12558
12559	center_win .parg
12560	focus .parg.c.e
12561}
12562
12563proc ts_ncache_dialog {} {
12564
12565	toplev .nche
12566	wm title .nche "Client-Side Caching"
12567
12568	scroll_text .nche.f 80 22
12569
12570	global ts_ncache choose_ncache
12571
12572	set msg {
12573    This enables the *experimental* x11vnc client-side caching mode.
12574    It often gives nice speedups, but can sometimes lead to painting
12575    errors or window "flashing". (you can repaint the screen by tapping
12576    the Left Alt key 3 times in a row)
12577
12578    It is a very simple but hoggy method: uncompressed image pixmaps are
12579    stored in the viewer in a large (20-100MB) display region beneath
12580    the actual display screen.  You may need also to adjust your VNC Viewer
12581    to not show this region (the SSVNC Unix viewer does it automatically).
12582
12583    The scheme uses a lot of RAM, but at least it has the advantage that
12584    it works with every VNC Viewer.  Otherwise the VNC protocol would
12585    need to be modified, changing both the server and the viewer.
12586
12587    Set the x11vnc "-ncache" parameter to an even integer between 2
12588    and 20.  This is the increase in area factor over the normal screen
12589    for the caching region.  So 10 means use 10 times the RAM to store
12590    pixmaps.  The default is 8.
12591
12592    More info: http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching
12593}
12594	.nche.f.t insert end $msg
12595
12596	frame .nche.c
12597	label .nche.c.l -anchor w -text "ncache:"
12598	radiobutton .nche.c.r2  -text "2"  -variable ts_ncache -value "2"
12599	radiobutton .nche.c.r4  -text "4"  -variable ts_ncache -value "4"
12600	radiobutton .nche.c.r6  -text "6"  -variable ts_ncache -value "6"
12601	radiobutton .nche.c.r8  -text "8"  -variable ts_ncache -value "8"
12602	radiobutton .nche.c.r10 -text "10" -variable ts_ncache -value "10"
12603	radiobutton .nche.c.r12 -text "12" -variable ts_ncache -value "12"
12604	radiobutton .nche.c.r14 -text "14" -variable ts_ncache -value "14"
12605	radiobutton .nche.c.r16 -text "16" -variable ts_ncache -value "16"
12606	radiobutton .nche.c.r18 -text "18" -variable ts_ncache -value "18"
12607	radiobutton .nche.c.r20 -text "20" -variable ts_ncache -value "20"
12608	pack .nche.c.l -side left
12609	pack .nche.c.r2 .nche.c.r4 .nche.c.r6 .nche.c.r8 .nche.c.r10 \
12610		.nche.c.r12 .nche.c.r14 .nche.c.r16 .nche.c.r18  .nche.c.r20 -side left
12611	button .nche.cancel -text "Cancel" -command {destroy .nche; set choose_ncache 0}
12612	bind .nche <Escape> {destroy .nche; set choose_ncache 0}
12613	wm protocol .nche WM_DELETE_WINDOW {destroy .nche; set choose_ncache 0}
12614	button .nche.done -text "Done" -command {destroy .nche; set choose_ncache 1}
12615
12616	pack .nche.done .nche.cancel .nche.c -side bottom -fill x
12617	pack .nche.f -side top -fill both -expand 1
12618
12619	center_win .nche
12620}
12621
12622proc ts_x11vnc_opts_dialog {} {
12623
12624	toplev .x11v
12625	wm title .x11v "x11vnc Options"
12626
12627	set h 23
12628	if [small_height] {
12629		set h 21
12630	}
12631	scroll_text .x11v.f 80 $h
12632
12633	global ts_x11vnc_opts ts_x11vnc_path ts_x11vnc_autoport choose_x11vnc_opts
12634	global additional_port_redirs_list
12635
12636	set msg {
12637    If you are an expert with x11vnc's endless options and tweaking
12638    parameters feel free to specify any you want here in "Options".
12639
12640    Also, if you need to specify the path to the x11vnc program on the
12641    remote side because it will not be in $PATH, put it in the "Full
12642    Path" entry.
12643
12644    Port Redirs are additional SSH "-L port:host:port" or "-R port:host:port"
12645    (forward or reverse, resp.) port redirections you want.  In SSVNC mode,
12646    see the detailed description under: Options -> Advanced -> Port Redirs.
12647
12648    Some potentially useful options:
12649
12650	-solid		-scale		-scale_cursor
12651	-passwd		-rfbauth	-http
12652	-xrandr		-rotate		-noxdamage
12653	-xkb		-skip_lockkeys	-nomodtweak
12654	-repeat		-cursor		-wmdt
12655	-nowireframe	-ncache_cr	-speeds
12656
12657    More info: http://www.karlrunge.com/x11vnc/faq.html#faq-cmdline-opts
12658}
12659#    In Auto Port put a starting port for x11vnc to try autoprobing
12660#    instead of the default 5900.  It starts at the value you supply and
12661#    works upward until a free one is found. (x11vnc 0.9.3 or later).
12662
12663	.x11v.f.t insert end $msg
12664
12665	frame .x11v.c
12666	label .x11v.c.l -width 10 -anchor w -text "Options:"
12667	entry .x11v.c.e -textvariable ts_x11vnc_opts
12668	pack .x11v.c.l -side left
12669	pack .x11v.c.e -side left -expand 1 -fill x
12670
12671	frame .x11v.c2
12672	label .x11v.c2.l -width 10 -anchor w -text "Full Path:"
12673	entry .x11v.c2.e -textvariable ts_x11vnc_path
12674	pack .x11v.c2.l -side left
12675	pack .x11v.c2.e -side left -expand 1 -fill x
12676
12677#	frame .x11v.c3
12678#	label .x11v.c3.l -width 10 -anchor w -text "Auto Port:"
12679#	entry .x11v.c3.e -textvariable ts_x11vnc_autoport
12680#	pack .x11v.c3.l -side left
12681#	pack .x11v.c3.e -side left -expand 1 -fill x
12682
12683	frame .x11v.c4
12684	label .x11v.c4.l -width 10 -anchor w -text "Port Redirs:"
12685	entry .x11v.c4.e -textvariable additional_port_redirs_list
12686	pack .x11v.c4.l -side left
12687	pack .x11v.c4.e -side left -expand 1 -fill x
12688
12689	button .x11v.cancel -text "Cancel" -command {destroy .x11v; set choose_x11vnc_opts 0}
12690	bind .x11v <Escape> {destroy .x11v; set choose_x11vnc_opts 0}
12691	wm protocol .x11v WM_DELETE_WINDOW {destroy .x11v; set choose_x11vnc_opts 0}
12692	button .x11v.done -text "Done" -command {destroy .x11v; set choose_x11vnc_opts 1;
12693			if {$additional_port_redirs_list != ""} {set additional_port_redirs 1} else {set additional_port_redirs 0}}
12694
12695#	pack .x11v.done .x11v.cancel .x11v.c4 .x11v.c3 .x11v.c2 .x11v.c -side bottom -fill x
12696	pack .x11v.done .x11v.cancel .x11v.c4 .x11v.c2 .x11v.c -side bottom -fill x
12697	pack .x11v.f -side top -fill both -expand 1
12698
12699	center_win .x11v
12700	focus .x11v.c.e
12701}
12702
12703
12704proc ts_filexfer_dialog {} {
12705
12706	toplev .xfer
12707	wm title .xfer "File Transfer"
12708	global choose_filexfer ts_filexfer
12709
12710	scroll_text .xfer.f 70 13
12711
12712	set msg {
12713    x11vnc supports both the UltraVNC and TightVNC file transfer
12714    extensions.  On Windows both viewers support their file transfer
12715    protocol.  On Unix only the SSVNC VNC Viewer can do filexfer; it
12716    supports the UltraVNC flavor via a Java helper program (and so
12717    java(1) is required on the viewer-side).
12718
12719    Choose the one you want based on VNC viewer you will use.
12720    The defaults for the SSVNC viewer package are TightVNC on
12721    Windows and UltraVNC on Unix.
12722
12723    For more info see: http://www.karlrunge.com/x11vnc/faq.html#faq-filexfer
12724}
12725	.xfer.f.t insert end $msg
12726
12727	global is_windows
12728	if {$ts_filexfer == ""} {
12729		if {$is_windows} {
12730			set ts_filexfer "tight"
12731		} else {
12732			set ts_filexfer "ultra"
12733		}
12734	}
12735
12736	frame .xfer.c
12737	radiobutton .xfer.c.tight  -text "TightVNC"  -variable ts_filexfer -value "tight" -relief ridge
12738	radiobutton .xfer.c.ultra  -text "UltraVNC"  -variable ts_filexfer -value "ultra" -relief ridge
12739
12740	pack .xfer.c.ultra .xfer.c.tight -side left -fill x -expand 1
12741
12742	button .xfer.cancel -text "Cancel" -command {destroy .xfer; set choose_filexfer 0}
12743	bind .xfer <Escape> {destroy .xfer; set choose_filexfer 0}
12744	wm protocol .xfer WM_DELETE_WINDOW {destroy .xfer; set choose_filexfer 0}
12745	button .xfer.done -text "Done" -command {destroy .xfer; set choose_filexfer 1}
12746
12747	pack .xfer.done .xfer.cancel -side bottom -fill x
12748	pack .xfer.c -side bottom -fill x -expand 1
12749	pack .xfer.f -side top -fill both -expand 1
12750
12751	center_win .xfer
12752}
12753
12754proc ts_cups_dialog {} {
12755
12756	toplev .cups
12757	wm title .cups "CUPS and SMB Printing"
12758	global cups_local_server cups_remote_port cups_manage_rcfile ts_cups_manage_rcfile cups_x11vnc
12759	global cups_local_smb_server cups_remote_smb_port
12760
12761	set h 30
12762	if [small_height] {
12763		set h 24
12764	}
12765	scroll_text .cups.f 80 $h
12766
12767
12768	set msg {
12769    This method requires a working CUPS Desktop setup on the remote side
12770    of the connection and working CUPS (or possibly Windows SMB or IPP)
12771    printing on the local viewer-side of the connection.
12772
12773    For CUPS printing redirection to work properly, you MUST enable it for
12774    the connection that *creates* your terminal services X session (i.e. the
12775    first connection.)  You cannot retroactively enable CUPS redirection
12776    on an already existing terminal services X session.  (See CUPS printing
12777    for normal SSVNC mode for how you might do that.)
12778
12779    Enter the VNC Viewer side (i.e. where you are sitting) CUPS server
12780    under "Local CUPS Server".  Use "localhost:631" if there is one
12781    on your viewer machine (normally the case if you set up a printer
12782    on your unix or macosx system), or, e.g., "my-print-srv:631" for a
12783    nearby CUPS print server.  Note that 631 is the default CUPS port.
12784
12785    (On MacOSX it seems better to use "127.0.0.1" instead of "localhost".)
12786
12787    The SSVNC Terminal Services created remote Desktop session will have
12788    the variables CUPS_SERVER and IPP_PORT set so all printing applications
12789    will be redirected to your local CUPS server.  So your locally available
12790    printers should appear in the remote print dialogs.
12791
12792
12793    Windows/SMB Printers:  Under "Local SMB Print Server" you can set a
12794    port redirection for a Windows (non-CUPS) SMB printer.  If localhost:139
12795    does not work, try the literal string "IP:139", or use the known value
12796    of the IP address manually.  139 is the default SMB port; nowadays 445
12797    might be a better possibility.
12798
12799    For Windows/SMB Printers if there is no local CUPS print server, it is
12800    usually a very good idea to make the CUPS Server setting EMPTY (to avoid
12801    desktop apps trying incessantly to reach the nonexistent CUPS server.)
12802
12803    On the remote side, in the Desktop session the variables $SMB_SERVER,
12804    $SMB_HOST, and $SMB_PORT will be set for you to use.
12805
12806    Unfortunately, printing to Windows may only ve partially functional due
12807    to the general lack PostScript support on Windows.
12808
12809    If you have print admin permission on the remote machine you can
12810    configure CUPS to know about your Windows printer via lpadmin(8) or
12811    a GUI tool.  You give it the URI:
12812
12813        smb://localhost:port/printername
12814
12815    or possibly:
12816
12817        smb://localhost:port/computer/printername
12818
12819    "port" will be found in the $SMB_PORT.  You also need to identify
12820    the printer type.  NOTE: You will leave "Local CUPS Server" blank in
12821    this case.  The smbspool(1) command should also work as well, at least
12822    for PostScript printers.
12823
12824    A similar thing can be done with CUPS printers if you are having problems
12825    with the above default mechanism.  Use
12826
12827        http://localhost:port/printers/printername
12828
12829    For more info see: http://www.karlrunge.com/x11vnc/faq.html#faq-cups
12830}
12831
12832#    The "Manage 'ServerName' in .cups/client.conf for me" setting is usually
12833#    NOT needed unless you are using Terminal Services to connect to an
12834#    existing Session that did NOT have CUPS print redirection set at session
12835#    start time (i.e. IPP_PORT and CUPS_SERVER were not set up).  In that
12836#    case, select this option as a workaround: NOTE that the client.conf
12837#    setting will REDIRECT ALL PRINTING for apps with the same $HOME/.cups
12838#    directory (which you probably do not want), however it will be reset
12839#    when the SSVNC viewer disconnects.
12840
12841	.cups.f.t insert end $msg
12842
12843	global uname
12844	if {$cups_local_server == ""} {
12845		if {$uname == "Darwin"} {
12846			set cups_local_server "127.0.0.1:631"
12847		} else {
12848			set cups_local_server "localhost:631"
12849		}
12850	}
12851	if {$cups_remote_port == ""} {
12852		set cups_remote_port [expr "6731 + int(1000 * rand())"]
12853	}
12854	if {$cups_local_smb_server == ""} {
12855		global is_windows
12856		if {$is_windows} {
12857			set cups_local_smb_server "IP:139"
12858		} elseif {$uname == "Darwin"} {
12859			set cups_local_smb_server "127.0.0.1:139"
12860		} else {
12861			set cups_local_smb_server "localhost:139"
12862		}
12863	}
12864	if {$cups_remote_smb_port == ""} {
12865		set cups_remote_smb_port [expr "7731 + int(1000 * rand())"]
12866	}
12867
12868	frame .cups.serv
12869	label .cups.serv.l -anchor w -text "Local CUPS Server:      "
12870	entry .cups.serv.e -width 40 -textvariable cups_local_server
12871	pack .cups.serv.e -side right
12872	pack .cups.serv.l -side left -expand 1 -fill x
12873
12874	frame .cups.smbs
12875	label .cups.smbs.l -anchor w -text "Local SMB Print Server:      "
12876	entry .cups.smbs.e -width 40 -textvariable cups_local_smb_server
12877	pack .cups.smbs.e -side right
12878	pack .cups.smbs.l -side left -expand 1 -fill x
12879
12880	# not working with x11vnc:
12881	checkbutton .cups.cupsrc -anchor w -variable ts_cups_manage_rcfile -text \
12882		"Manage 'ServerName' in the remote \$HOME/.cups/client.conf file for me"
12883
12884	button .cups.cancel -text "Cancel" -command {destroy .cups; set use_cups 0}
12885	bind .cups <Escape> {destroy .cups; set use_cups 0}
12886	wm protocol .cups WM_DELETE_WINDOW {destroy .cups; set use_cups 0}
12887	button .cups.done -text "Done" -command {destroy .cups; if {$use_cups} {set_ssh}}
12888
12889	pack .cups.done .cups.cancel .cups.smbs .cups.serv -side bottom -fill x
12890	pack .cups.f -side top -fill both -expand 1
12891
12892	center_win .cups
12893	focus .cups.serv.e
12894}
12895
12896
12897proc cups_dialog {} {
12898
12899	toplev .cups
12900	wm title .cups "CUPS Tunnelling"
12901	global cups_local_server cups_remote_port cups_manage_rcfile cups_x11vnc
12902	global cups_local_smb_server cups_remote_smb_port
12903	global ts_only
12904	if {$ts_only} {
12905		ts_cups_dialog
12906		return
12907	}
12908
12909	global uname
12910	set h 33
12911	if [small_height] {
12912		set h 17
12913	} elseif {$uname == "Darwin"} {
12914		set h 24
12915	}
12916	scroll_text .cups.f 80 $h
12917
12918
12919	set msg {
12920    CUPS Printing requires SSH be used to set up the CUPS Print service TCP
12921    port redirection.  This will be either of the "Use SSH" or "SSH+SSL" modes.
12922    NOTE:  For pure SSL tunnelling it currently will not work.
12923
12924    This method requires working CUPS software setups on BOTH the remote
12925    and local sides of the connection.
12926
12927    If the remote VNC server is Windows you probably cannot SSH into it
12928    anyway...  If you can, you will still need to set up a special printer
12929    TCP port redirection on your own.  Perhaps adding and configuring a
12930    "Unix Printer" under Windows (like Method #2 below) will work.
12931
12932    If the local machine (SSVNC side) is Windows, see the bottom of this
12933    help for redirecting to SMB printers.
12934
12935    If the remote VNC server is Mac OS X this method may or may not work.
12936    Sometimes applications need to be restarted to get them to notice the
12937    new printers.  Adding and configuring a special "Unix Printer",
12938    (Method #2) below, might yield more reliable results at the cost of
12939    additional setup and permissions.
12940
12941    For Unix/Linux remote VNC servers, applications may also need to be
12942    restarted to notice the new printers.  The only case known to work
12943    well is the one where the remote side has no CUPS printers configured.
12944    As mentioned above, see Method #2 for another method.
12945
12946    *************************************************************************
12947    *** Directions:
12948
12949    You choose your own remote CUPS redir port below under "Use Remote
12950    CUPS Port".  6631 is our default and is used in the examples below.
12951    Use it or some random value greater than 1024.  Note that the standard
12952    CUPS server port is 631.
12953
12954    The port you choose must be unused on the VNC server machine (it is NOT
12955    checked for you).  Print requests connecting to it are redirected to
12956    your local VNC viewer-side CUPS server through the SSH tunnel.
12957
12958    (Note: root SSH login permission is needed for ports less than 1024,
12959    e.g. 631; this is not recommended, use something around 6631 instead).
12960
12961    Then enter the VNC Viewer side (i.e. where you are sitting) CUPS server
12962    into "Local CUPS Server".  A good choice is the default "localhost:631"
12963    if there is a cups server on your viewer machine (this is usually the case
12964    if you have set up a printer).  Otherwise enter, e.g., "my-print-srv:631"
12965    for your nearby (viewer-side) CUPS print server.
12966
12967
12968    The "Manage 'ServerName' in the $HOME/.cups/client.conf file for me"
12969    setting below is enabled by default.  It should handle most situations.
12970
12971    What it does is modify the .cups/client.conf file on the VNC server-side
12972    to redirect the print requests while the SSVNC viewer is connected.  When
12973    SSVNC disconnects .cups/client.conf is restored to its previous setting.
12974
12975    If, for some reason, the SSVNC CUPS script fails to restore this file
12976    after SSVNC disconnects, run this command on the remote machine:
12977
12978        cp $HOME/.cups/client.conf.back $HOME/.cups/client.conf
12979
12980    to regain your initial printing configuration.
12981
12982
12983    You can also use CUPS on the VNC server-side to redirect to Windows
12984    (SMB) printers.  See the additional info for Windows Printing at the
12985    bottom of this help.
12986
12987
12988    In case the default method (automatic .cups/client.conf modification)
12989    fails, we describe below all of the possible methods that can be tried.
12990
12991    As noted above, you may need to restart applications for them to notice
12992    the new printers or for them to revert to the original printers.  If this
12993    is not acceptable, consider Method #2 below if you have the permission
12994    and ability to alter the print queues for this.
12995
12996
12997    *************************************************************************
12998    *** Method #1:  Manually create or edit the file $HOME/.cups/client.conf
12999    on the VNC server side by putting in something like this in it:
13000
13001    	ServerName localhost:6631
13002
13003    based on the port you set in this dialog's entry box.
13004
13005    After the remote VNC Connection is finished, to go back to the non-SSH
13006    tunnelled CUPS server and either remove the client.conf file or comment
13007    out the ServerName line.  This restores the normal CUPS server for
13008    you on the remote VNC server machine.
13009
13010    Select "Manage 'ServerName' in the $HOME/.cups/client.conf file for me"
13011    to do this editing of the VNC server-side CUPS config file for you
13012    automatically.  NOTE: It is now on by default (deselect it if you want
13013    to manage the file manually; e.g. you print through the tunnel only very
13014    rarely, or often print locally when the tunnel is up, etc.)
13015
13016    Select "Pass -env FD_CUPS=<Port> to x11vnc command line" if you are
13017    starting x11vnc as the Remote SSH Command, and x11vnc is running in
13018    -create mode (i.e. FINDCREATEDISPLAY).  That way, when your X session
13019    is created IPP_PORT will be set correctly for the entire session.
13020    This is the mode used for 'Terminal Services' printing.
13021
13022    NOTE: You probably would never select both of the above two options
13023    at the same time, since they conflict with each other to some degree.
13024
13025
13026    *************************************************************************
13027    *** Method #2:  If you have admin permission on the VNC Server machine
13028    you can likely "Add a Printer" via a GUI dialog, a Wizard, CUPS Web
13029    interface (i.e. http://localhost:631/), lpadmin(8), etc.
13030
13031    You will need to tell the dialog that the network printer located
13032    is at, e.g., localhost:6631, and anything else needed to identify
13033    the printer (type, model, etc).  NOTE: sometimes it is best to set
13034    the model/type as "Generic / Postscript Printer" to avoid problems
13035    with garbage being printed out.
13036
13037    For the URI to use, we have successfully used ones like this with CUPS:
13038
13039       http://localhost:6631/printers/Deskjet-3840
13040        ipp://localhost:6631/printers/Deskjet-3840
13041
13042    for an HP Deskjet-3840 printer.  See the CUPS documentation for more
13043    about the URI syntax and pathname.
13044
13045    This mode makes the client.conf ServerName parameter unnecessary
13046    (BE SURE TO DISABLE the "Manage 'ServerName' ... for me"  option.)
13047
13048
13049    *************************************************************************
13050    *** Method #3:  Restarting individual applications with the IPP_PORT
13051    set will enable redirected printing for them, e.g.:
13052
13053       env IPP_PORT=6631 firefox
13054
13055    If you can only get this method to work, an extreme application would
13056    be to run the whole desktop, e.g. "env IPP_PORT=6631 gnome-session", but
13057    then you would need some sort of TCP redirector (ssh -L comes to mind),
13058    to direct it to 631 when not connected remotely.
13059
13060
13061    *************************************************************************
13062    *** Windows/SMB Printers:  Under "Local SMB Print Server" you can set
13063    a port redirection for a Windows (non-CUPS) SMB printer.  E.g. port
13064    6632 -> localhost:139.
13065
13066    If localhost:139 does not work, try the literal string "IP:139", or
13067    insert the actual IP address manually.  NOTE: Nowadays on Windows port
13068    445 might be a better choice.
13069
13070    For Windows printers, if there is no local CUPS print server, set the
13071    'Local CUPS Server' and 'Use Remote CUPS Port' to be EMPTY (to avoid
13072    desktop apps trying incessantly to reach the nonexistent CUPS server.)
13073
13074    You must enable Sharing for your local Windows Printer.  Use Windows
13075    Printer configuration dialogs to do this.
13076
13077    Next, you need to have sudo or print admin permission so that you can
13078    configure the *remote* CUPS to know about this Windows printer via
13079    lpadmin(8) or GUI Printer Configuration dialog, etc (Method #2 above).
13080    You basically give it the URI:
13081
13082        smb://localhost:6632/printername
13083
13084    For example, we have had success with GNOME CUPS printing configuration
13085    using:
13086
13087	smb://localhost:6632/HPOffice
13088	smb://localhost:6632/COMPUTERNAME/HPOffice
13089
13090    where "HPOffice" was the name Windows shares the printer as.
13091
13092    Also with this SMB port redir mode, as a last resort you can often print
13093    using the smbspool(8) program like this:
13094
13095       smbspool smb://localhost:6632/printer job user title 1 "" myfile.ps
13096
13097    You could put this in a script.  For this URI, it appears only the number
13098    of copies ("1" above) and the file itself are important.
13099
13100    If on the local (SSVNC viewer) side there is some nearby CUPS print server
13101    that knows about your Windows printer, you might have better luck with
13102    that instead of using SMB.  Set 'Local CUPS Server' to it.
13103
13104    For more info see: http://www.karlrunge.com/x11vnc/faq.html#faq-cups
13105}
13106	.cups.f.t insert end $msg
13107
13108	global uname
13109	set something_set 0
13110
13111	if {$cups_local_server != ""} {
13112		set something_set 1
13113	}
13114	if {$cups_local_smb_server != ""} {
13115		set something_set 1
13116	}
13117
13118	if {$cups_local_server == "" && ! $something_set} {
13119		if {$uname == "Darwin"} {
13120			set cups_local_server "127.0.0.1:631"
13121		} else {
13122			set cups_local_server "localhost:631"
13123		}
13124	}
13125	if {$cups_remote_port == "" && ! $something_set} {
13126		set cups_remote_port "6631"
13127	}
13128	if {$cups_local_smb_server == "" && ! $something_set} {
13129		global is_windows
13130		if {$is_windows} {
13131			set cups_local_smb_server "IP:139"
13132		} elseif {$uname == "Darwin"} {
13133			set cups_local_smb_server "127.0.0.1:139"
13134		} else {
13135			set cups_local_smb_server "localhost:139"
13136		}
13137	}
13138	if {$cups_remote_smb_port == "" && ! $something_set} {
13139		set cups_remote_smb_port "6632"
13140	}
13141
13142	frame .cups.serv
13143	label .cups.serv.l -anchor w -text "Local CUPS Server:      "
13144	entry .cups.serv.e -width 40 -textvariable cups_local_server
13145	pack .cups.serv.e -side right
13146	pack .cups.serv.l -side left -expand 1 -fill x
13147
13148	frame .cups.port
13149	label .cups.port.l -anchor w -text "Use Remote CUPS Port:"
13150	entry .cups.port.e -width 40 -textvariable cups_remote_port
13151	pack .cups.port.e -side right
13152	pack .cups.port.l -side left -expand 1 -fill x
13153
13154	frame .cups.smbs
13155	label .cups.smbs.l -anchor w -text "Local SMB Print Server:      "
13156	entry .cups.smbs.e -width 40 -textvariable cups_local_smb_server
13157	pack .cups.smbs.e -side right
13158	pack .cups.smbs.l -side left -expand 1 -fill x
13159
13160	frame .cups.smbp
13161	label .cups.smbp.l -anchor w -text "Use Remote SMB Print Port:"
13162	entry .cups.smbp.e -width 40 -textvariable cups_remote_smb_port
13163	pack .cups.smbp.e -side right
13164	pack .cups.smbp.l -side left -expand 1 -fill x
13165
13166	checkbutton .cups.cupsrc -anchor w -variable cups_manage_rcfile -text \
13167		"Manage 'ServerName' in the remote \$HOME/.cups/client.conf file for me"
13168
13169	checkbutton .cups.x11vnc -anchor w -variable cups_x11vnc -text \
13170		"Pass -env FD_CUPS=<Port> to x11vnc command line."
13171
13172	button .cups.cancel -text "Cancel" -command {destroy .cups; set use_cups 0}
13173	bind .cups <Escape> {destroy .cups; set use_cups 0}
13174	wm protocol .cups WM_DELETE_WINDOW {destroy .cups; set use_cups 0}
13175	button .cups.done -text "Done" -command {destroy .cups; if {$use_cups} {set_ssh}}
13176
13177	button .cups.guess -text "Help me decide ..." -command {}
13178	.cups.guess configure -state disabled
13179
13180	pack .cups.done .cups.cancel .cups.guess .cups.x11vnc .cups.cupsrc .cups.smbp .cups.smbs .cups.port .cups.serv -side bottom -fill x
13181	pack .cups.f -side top -fill both -expand 1
13182
13183	center_win .cups
13184	focus .cups.serv.e
13185}
13186
13187proc ts_sound_dialog {} {
13188
13189	global is_windows
13190	global ts_only
13191
13192	toplev .snd
13193	wm title .snd "Sound Tunnelling"
13194
13195	scroll_text .snd.f 80 21
13196
13197	set msg {
13198    Your remote Desktop will be started in an Enlightenment Sound Daemon
13199    (ESD) environment (esddsp(1), which must be installed on the remote
13200    machine), and a local ESD sound daemon (esd(1)) will be started to
13201    play the sounds for you to hear.
13202
13203    In the entry box below you can choose the port that the local esd
13204    will use to listen on.  The default ESD port is 16001.  You will
13205    need to choose different values if you will have more than one esd
13206    running locally.
13207
13208    The command run (with port replaced by your choice) will be:
13209
13210      %RCMD
13211
13212    Note: Unfortunately not all applications work with ESD.
13213          And esd's LD_PRELOAD is broken on 64+32bit Linux (x86_64).
13214          And so this mode is not working well currently...
13215
13216    For more info see: http://www.karlrunge.com/x11vnc/faq.html#faq-sound
13217}
13218
13219
13220	global sound_daemon_remote_port sound_daemon_local_port sound_daemon_local_cmd
13221	global sound_daemon_local_start sound_daemon_local_kill
13222
13223	set sound_daemon_local_start 1
13224	set sound_daemon_local_kill 1
13225
13226	if {$sound_daemon_remote_port == ""} {
13227		set sound_daemon_remote_port 16010
13228	}
13229	if {$sound_daemon_local_port == ""} {
13230		set sound_daemon_local_port 16010
13231	}
13232
13233	if {$sound_daemon_local_cmd == ""} {
13234		global is_windows
13235		if {$is_windows} {
13236			set sound_daemon_local_cmd {esound\esd -promiscuous -as 5 -port %PORT -tcp -bind 127.0.0.1}
13237		} else {
13238			set sound_daemon_local_cmd {esd -promiscuous -as 5 -port %PORT -tcp -bind 127.0.0.1}
13239		}
13240	}
13241	regsub {%PORT} $sound_daemon_local_cmd $sound_daemon_local_port sound_daemon_local_cmd
13242
13243	regsub {%RCMD} $msg $sound_daemon_local_cmd msg
13244	.snd.f.t insert end $msg
13245
13246	frame .snd.lport
13247	label .snd.lport.l -anchor w -text "Local Sound Port:     "
13248	entry .snd.lport.e -width 45 -textvariable sound_daemon_local_port
13249	pack .snd.lport.e -side right
13250	pack .snd.lport.l -side left -expand 1 -fill x
13251
13252	button .snd.cancel -text "Cancel" -command {destroy .snd; set use_sound 0}
13253	bind .snd <Escape> {destroy .snd; set use_sound 0}
13254	wm protocol .snd WM_DELETE_WINDOW {destroy .snd; set use_sound 0}
13255	button .snd.done -text "Done" -command {destroy .snd; if {$use_sound} {set_ssh}}
13256	bind .snd.lport.e <Return> {destroy .snd; if {$use_sound} {set_ssh}}
13257
13258	pack .snd.done .snd.cancel .snd.lport -side bottom -fill x
13259	pack .snd.f -side bottom -fill both -expand 1
13260
13261	center_win .snd
13262	focus .snd.lport.e
13263}
13264
13265proc sound_dialog {} {
13266
13267	global is_windows
13268	global ts_only
13269	if {$ts_only} {
13270		ts_sound_dialog;
13271		return
13272	}
13273
13274	toplev .snd
13275	wm title .snd "ESD/ARTSD Sound Tunnelling"
13276
13277	global uname
13278	set h 28
13279	if [small_height] {
13280		set h 14
13281	} elseif {$uname == "Darwin"} {
13282		set h 20
13283	}
13284	scroll_text .snd.f 80 $h
13285
13286	set msg {
13287    Sound tunnelling to a sound daemon requires SSH be used to set up the
13288    service port redirection.  This will be either of the "Use SSH" or
13289    "SSH+SSL" modes. NOTE: For pure SSL tunnelling it currently will not work.
13290
13291    This method requires working Sound daemon (e.g. ESD or ARTSD) software
13292    setups on BOTH the remote and local sides of the connection.
13293
13294    Often this means you want to run your ENTIRE remote desktop with ALL
13295    applications instructed to use the sound daemon's network port.  E.g.
13296
13297        esddsp -s localhost:16001  startkde
13298        esddsp -s localhost:16001  gnome-session
13299
13300    and similarly for artsdsp, etc.  You put this in your ~/.xession,
13301    or other startup file.  This is non standard.  If you do not want to
13302    do this you still can direct *individual* sound applications through
13303    the tunnel, for example "esddsp -s localhost:16001 soundapp", where
13304    "soundapp" is some application that makes noise (say xmms or mpg123).
13305
13306    Select "Pass -env FD_ESD=<Port> to x11vnc command line."  if you are
13307    starting x11vnc as the Remote SSH Command, and x11vnc is running in
13308    -create mode (i.e. FINDCREATEDISPLAY).  That way, your X session is
13309    started via "esddsp -s ... <session>"  and the ESD variables will be
13310    set correctly for the entire session.  (This mode make most sense for
13311    a virtual, e.g. Xvfb or Xdummy session, not one a physical display).
13312
13313    Also, usually the remote Sound daemon must be killed BEFORE the SSH port
13314    redir is established (because it is listening on the port we want to use
13315    for the SSH redir), and, presumably, restarted when the VNC connection
13316    finished.
13317
13318    One may also want to start and kill a local sound daemon that will
13319    play the sound received over the network on the local machine.
13320
13321    You can indicate the remote and local Sound daemon commands below and
13322    how they should be killed and/or restart.  Some examples:
13323
13324        esd -promiscuous -as 5 -port 16001 -tcp -bind 127.0.0.1
13325        artsd -n -p 7265 -F 10 -S 4096 -n -s 5 -m artsmessage -l 3 -f
13326
13327    or you can leave some or all blank and kill/start them manually.
13328
13329    For convenience, a Windows port of ESD is provided in the util/esound
13330    directory, and so this might work for a Local command:
13331
13332        esound\esd -promiscuous -as 5 -port 16001 -tcp -bind 127.0.0.1
13333
13334    NOTE: If you indicate "Remote Sound daemon: Kill at start." below,
13335    then THERE WILL BE TWO SSH'S: THE FIRST ONE TO KILL THE DAEMON.
13336    So you may need to supply TWO SSH PASSWORDS, unless you are using
13337    something like ssh-agent(1), the Putty PW setting, etc.
13338
13339    You will also need to supply the remote and local sound ports for
13340    the SSH redirs.  For esd the default port is 16001, but you can choose
13341    another one if you prefer.
13342
13343    For "Local Sound Port" you can also supply "host:port" instead of just
13344    a numerical port to specify non-localhost connections, e.g. to another
13345    nearby machine.
13346
13347    For more info see: http://www.karlrunge.com/x11vnc/faq.html#faq-sound
13348}
13349	.snd.f.t insert end $msg
13350
13351	global sound_daemon_remote_port sound_daemon_local_port sound_daemon_local_cmd
13352	if {$sound_daemon_remote_port == ""} {
13353		set sound_daemon_remote_port 16001
13354	}
13355	if {$sound_daemon_local_port == ""} {
13356		set sound_daemon_local_port 16001
13357	}
13358
13359	if {$sound_daemon_local_cmd == ""} {
13360		global is_windows
13361		if {$is_windows} {
13362			set sound_daemon_local_cmd {esound\esd -promiscuous -as 5 -port %PORT -tcp -bind 127.0.0.1}
13363		} else {
13364			set sound_daemon_local_cmd {esd -promiscuous -as 5 -port %PORT -tcp -bind 127.0.0.1}
13365		}
13366		regsub {%PORT} $sound_daemon_local_cmd $sound_daemon_local_port sound_daemon_local_cmd
13367	}
13368
13369
13370	frame .snd.remote
13371	label .snd.remote.l -anchor w -text "Remote Sound daemon cmd: "
13372	entry .snd.remote.e -width 45 -textvariable sound_daemon_remote_cmd
13373	pack .snd.remote.e -side right
13374	pack .snd.remote.l -side left -expand 1 -fill x
13375
13376	frame .snd.local
13377	label .snd.local.l -anchor w -text "Local Sound daemon cmd:     "
13378	entry .snd.local.e -width 45 -textvariable sound_daemon_local_cmd
13379	pack .snd.local.e -side right
13380	pack .snd.local.l -side left -expand 1 -fill x
13381
13382	frame .snd.rport
13383	label .snd.rport.l -anchor w -text "Remote Sound Port: "
13384	entry .snd.rport.e -width 45 -textvariable sound_daemon_remote_port
13385	pack .snd.rport.e -side right
13386	pack .snd.rport.l -side left -expand 1 -fill x
13387
13388	frame .snd.lport
13389	label .snd.lport.l -anchor w -text "Local Sound Port:     "
13390	entry .snd.lport.e -width 45 -textvariable sound_daemon_local_port
13391	pack .snd.lport.e -side right
13392	pack .snd.lport.l -side left -expand 1 -fill x
13393
13394
13395	checkbutton .snd.sdk -anchor w -variable sound_daemon_kill -text \
13396		"Remote Sound daemon: Kill at start."
13397
13398	checkbutton .snd.sdr -anchor w -variable sound_daemon_restart -text \
13399		"Remote Sound daemon: Restart at end."
13400
13401	checkbutton .snd.sdsl -anchor w -variable sound_daemon_local_start -text \
13402		"Local Sound daemon: Run at start."
13403
13404	checkbutton .snd.sdkl -anchor w -variable sound_daemon_local_kill -text \
13405		"Local Sound daemon: Kill at end."
13406
13407	checkbutton .snd.x11vnc -anchor w -variable sound_daemon_x11vnc -text \
13408		"Pass -env FD_ESD=<Port> to x11vnc command line."
13409
13410	button .snd.guess -text "Help me decide ..." -command {}
13411	.snd.guess configure -state disabled
13412
13413	global is_win9x
13414	if {$is_win9x} {
13415		.snd.local.e configure -state disabled
13416		.snd.local.l configure -state disabled
13417		.snd.sdsl configure -state disabled
13418		.snd.sdkl configure -state disabled
13419	}
13420
13421	button .snd.cancel -text "Cancel" -command {destroy .snd; set use_sound 0}
13422	bind .snd <Escape> {destroy .snd; set use_sound 0}
13423	wm protocol .snd WM_DELETE_WINDOW {destroy .snd; set use_sound 0}
13424	button .snd.done -text "Done" -command {destroy .snd; if {$use_sound} {set_ssh}}
13425
13426	pack .snd.done .snd.cancel .snd.guess .snd.x11vnc .snd.sdkl .snd.sdsl .snd.sdr .snd.sdk .snd.lport .snd.rport \
13427		.snd.local .snd.remote -side bottom -fill x
13428	pack .snd.f -side bottom -fill both -expand 1
13429
13430	center_win .snd
13431	focus .snd.remote.e
13432}
13433
13434# Share ideas.
13435#
13436# Unix:
13437#
13438# if type smbclient
13439# first parse smbclient -L localhost -N
13440# and/or      smbclient -L `hostname` -N
13441# Get Sharenames and Servers and Domain.
13442#
13443# loop over servers, doing smbclient -L server -N
13444# pile this into a huge list, sep by disk and printers.
13445#
13446# WinXP:
13447#
13448# parse "NET VIEW" output similarly.
13449#
13450# Have checkbox for each disk.  Set default root to /var/tmp/${USER}-mnts
13451# Let them change that at once and have it populate.
13452#
13453# use   //hostname/share  /var/tmp/runge-mnts/hostname/share
13454#
13455#
13456# Printers, hmmm.  Can't add to remote cups list...  I guess have the list
13457# ready for CUPS dialog to suggest which SMB servers they want to redirect
13458# to...
13459
13460proc get_hostname {} {
13461	global is_windows is_win9x
13462	set str ""
13463	if {$is_windows} {
13464		if {1} {
13465			catch {set str [exec hostname]}
13466			regsub -all {[\r]} $str "" str
13467		} else {
13468			catch {set str [exec net config]}
13469			if [regexp -nocase {Computer name[ \t]+\\\\([^ \t]+)} $str mv str] {
13470				;
13471			} else {
13472				set str ""
13473			}
13474		}
13475	} else {
13476		catch {set str [exec hostname]}
13477	}
13478	set str [string trim $str]
13479	return $str
13480}
13481
13482proc smb_list_windows {smbhost} {
13483	global smb_local smb_local_hosts smb_this_host
13484	global is_win9x
13485	set dbg 0
13486
13487	set domain ""
13488
13489	if {$is_win9x} {
13490		# exec net view ... doesn't work.
13491		set smb_this_host "unknown"
13492		return
13493	}
13494
13495	set this_host [get_hostname]
13496	set This_host [string toupper $this_host]
13497	set smb_this_host $This_host
13498
13499	if {$smbhost == $smb_this_host} {
13500		catch {set out0 [exec net view]}
13501		regsub -all {[\r]} $out0 "" out0
13502		foreach line [split $out0 "\n"] {
13503			if [regexp -nocase {in workgroup ([^ \t]+)} $line mv wg] {
13504				regsub -all {[.]} $wg "" wg
13505				set domain $wg
13506			} elseif [regexp {^\\\\([^ \t]+)[ \t]*(.*)} $line mv host comment] {
13507				set smb_local($smbhost:server:$host) $comment
13508			}
13509		}
13510	}
13511
13512	set out1 ""
13513	set h "\\\\$smbhost"
13514	catch {set out1 [exec net view $h]}
13515	regsub -all {[\r]} $out1 "" out1
13516
13517	if {$dbg} {puts "SMBHOST: $smbhost"}
13518
13519	set mode ""
13520	foreach line [split $out1 "\n"] {
13521		if [regexp {^[ \t]*---} $line] {
13522			continue
13523		}
13524		if [regexp -nocase {The command} $line] {
13525			continue
13526		}
13527		if [regexp -nocase {Shared resources} $line] {
13528			continue
13529		}
13530		if [regexp -nocase {^[ \t]*Share[ \t]*name} $line] {
13531			set mode "shares"
13532			continue
13533		}
13534		set line [string trim $line]
13535		if {$line == ""} {
13536			continue
13537		}
13538		if {$mode == "shares"} {
13539			if [regexp {^([^ \t]+)[ \t]+([^ \t]+)[ \t]*(.*)$} $line mv name type comment] {
13540				if {$dbg} {
13541					puts "SHR: $name"
13542					puts "---: $type"
13543					puts "---: $comment"
13544				}
13545				if [regexp -nocase {^Disk$} $type] {
13546					set smb_local($smbhost:disk:$name) $comment
13547				} elseif [regexp -nocase {^Print} $type] {
13548					set smb_local($smbhost:printer:$name) $comment
13549				}
13550			}
13551		}
13552	}
13553
13554	set smb_local($smbhost:domain) $domain
13555}
13556
13557proc smb_list_unix {smbhost} {
13558	global smb_local smb_local_hosts smb_this_host
13559	set smbclient [in_path smbclient]
13560	if {[in_path smbclient] == ""} {
13561		return ""
13562	}
13563	set dbg 0
13564
13565	set this_host [get_hostname]
13566	set This_host [string toupper $this_host]
13567	set smb_this_host $This_host
13568
13569	set out1 ""
13570	catch {set out1 [exec smbclient -N -L $smbhost 2>@ stdout]}
13571
13572	if {$dbg} {puts "SMBHOST: $smbhost"}
13573	if {$smbhost == $this_host || $smbhost == $This_host} {
13574		if {$out1 == ""} {
13575			catch {set out1 [exec smbclient -N -L localhost 2>@ stdout]}
13576		}
13577	}
13578
13579	set domain ""
13580	set mode ""
13581	foreach line [split $out1 "\n"] {
13582		if [regexp {^[ \t]*---} $line] {
13583			continue
13584		}
13585		if [regexp {Anonymous login} $line] {
13586			continue
13587		}
13588		if {$domain == "" && [regexp {Domain=\[([^\]]+)\]} $line mv domain]} {
13589			if {$dbg} {puts "DOM: $domain"}
13590			continue
13591		}
13592		if [regexp {^[ \t]*Sharename} $line] {
13593			set mode "shares"
13594			continue
13595		}
13596		if [regexp {^[ \t]*Server} $line] {
13597			set mode "server"
13598			continue
13599		}
13600		if [regexp {^[ \t]*Workgroup} $line] {
13601			set mode "workgroup"
13602			continue
13603		}
13604		set line [string trim $line]
13605		if {$mode == "shares"} {
13606			if [regexp {^([^ \t]+)[ \t]+([^ \t]+)[ \t]*(.*)$} $line mv name type comment] {
13607				if {$dbg} {
13608					puts "SHR: $name"
13609					puts "---: $type"
13610					puts "---: $comment"
13611				}
13612				if [regexp -nocase {^Disk$} $type] {
13613					set smb_local($smbhost:disk:$name) $comment
13614				} elseif [regexp -nocase {^Printer$} $type] {
13615					set smb_local($smbhost:printer:$name) $comment
13616				}
13617			}
13618		} elseif {$mode == "server"} {
13619			if [regexp {^([^ \t]+)[ \t]*(.*)$} $line mv host comment] {
13620				if {$dbg} {
13621					puts "SVR: $host"
13622					puts "---: $comment"
13623				}
13624				set smb_local($smbhost:server:$host) $comment
13625			}
13626		} elseif {$mode == "workgroup"} {
13627			if [regexp {^([^ \t]+)[ \t]+(.*)$} $line mv work host] {
13628				if {$dbg} {
13629					puts "WRK: $work"
13630					puts "---: $host"
13631				}
13632				if {$host != ""} {
13633					set smb_local($smbhost:master:$work) $host
13634				}
13635			}
13636		}
13637	}
13638
13639	set smb_local($smbhost:domain) $domain
13640}
13641
13642proc smb_list {} {
13643	global is_windows smb_local smb_local_hosts
13644	global smb_host_list
13645
13646	set smb_local(null) ""
13647
13648	if {! [info exists smb_host_list]} {
13649		set smb_host_list ""
13650	}
13651	if [info exists smb_local] {
13652		unset smb_local
13653	}
13654	if [info exists smb_local_hosts] {
13655		unset smb_local_hosts
13656	}
13657
13658	set this_host [get_hostname]
13659	set this_host [string toupper $this_host]
13660	if {$is_windows} {
13661		smb_list_windows $this_host
13662	} else {
13663		smb_list_unix $this_host
13664	}
13665	set did($this_host) 1
13666	set keys [array names smb_local]
13667	foreach item [split $smb_host_list] {
13668		if {$item != ""} {
13669			set item [string toupper $item]
13670			lappend keys "$this_host:server:$item"
13671		}
13672	}
13673	foreach key $keys {
13674		if [regexp "^$this_host:server:(.*)\$" $key mv host]  {
13675			if {$host == ""} {
13676				continue
13677			}
13678			set smb_local_hosts($host) 1
13679			if {! [info exists did($host)]} {
13680				if {$is_windows} {
13681					smb_list_windows $host
13682				} else {
13683					smb_list_unix $host
13684				}
13685				set did($host) 1
13686			}
13687		}
13688	}
13689}
13690
13691proc smb_check_selected {} {
13692	global smbmount_exists smbmount_sumode
13693	global smb_selected smb_selected_mnt smb_selected_cb smb_selected_en
13694
13695	set ok 0
13696	if {$smbmount_exists && $smbmount_sumode != "dontknow"} {
13697		set ok 1
13698	}
13699	set state disabled
13700	if {$ok} {
13701		set state normal
13702	}
13703
13704	foreach cb [array names smb_selected_cb] {
13705		catch {$cb configure -state $state}
13706	}
13707	foreach en [array names smb_selected_en] {
13708		catch {$en configure -state $state}
13709	}
13710}
13711
13712proc make_share_widgets {w} {
13713
13714	set share_label $w.f.hl
13715	catch {$share_label configure -text "Share Name: PROBING ..."}
13716	update
13717
13718	smb_list
13719
13720	set saw_f 0
13721	foreach child [winfo children $w] {
13722		if {$child == "$w.f"} {
13723			set saw_f 1
13724			continue
13725		}
13726		catch {destroy $child}
13727	}
13728
13729	set w1 47
13730	set w2 44
13731
13732	if {! $saw_f} {
13733		set wf $w.f
13734		frame $wf
13735		label $wf.hl -width $w1 -text "Share Name:" -anchor w
13736		label $wf.hr -width $w2 -text "  Mount Point:" -anchor w
13737
13738		pack $wf.hl $wf.hr -side left -expand 1
13739		pack $wf -side top -fill x
13740
13741		.smbwiz.f.t window create end -window $w
13742	}
13743
13744	global smb_local smb_local_hosts smb_this_host smb_selected smb_selected_mnt
13745	global smb_selected_host smb_selected_name
13746	global smb_selected_cb smb_selected_en
13747	global smb_host_list
13748	if [info exists smb_selected]      {array unset smb_selected }
13749	if [info exists smb_selected_mnt]  {array unset smb_selected_mnt}
13750	if [info exists smb_selected_cb]   {array unset smb_selected_cb}
13751	if [info exists smb_selected_en]   {array unset smb_selected_en}
13752	if [info exists smb_selected_host] {array unset smb_selected_host}
13753	if [info exists smb_selected_name] {array unset smb_selected_name}
13754
13755	set hosts [list $smb_this_host]
13756	lappend hosts [lsort [array names smb_local_hosts]]
13757
13758	set smb_host_list ""
13759	set i 0
13760
13761	global smb_mount_prefix
13762	set smb_mount_prefix "/var/tmp/%USER-mnts"
13763
13764	foreach host [lsort [array names smb_local_hosts]] {
13765
13766		if [info exists did($host)] {
13767			continue
13768		}
13769		set did($host) 1
13770
13771		append smb_host_list "$host "
13772
13773		foreach key [lsort [array names smb_local]] {
13774			if [regexp {^([^:]+):([^:]+):(.*)$} $key mv host2 type name] {
13775				if {$host2 != $host}  {
13776					continue
13777				}
13778				if {$type != "disk"} {
13779					continue
13780				}
13781				set wf $w.f$i
13782				frame $wf
13783				checkbutton $wf.c -anchor w -width $w1 -variable smb_selected($i) \
13784					-text "//$host/$name" -relief ridge
13785				if {! [info exists smb_selected($i)]} {
13786					set smb_selected($i) 0
13787				}
13788
13789				entry $wf.e -width $w2 -textvariable smb_selected_mnt($i)
13790				set smb_selected_mnt($i) "$smb_mount_prefix/$host/$name"
13791
13792				set smb_selected_host($i) $host
13793				set smb_selected_name($i) $name
13794
13795				set smb_selected_cb($wf.c) $i
13796				set smb_selected_en($wf.e) $i
13797				set comment $smb_local($key)
13798
13799				bind $wf.c <Enter> "$share_label configure -text {Share Name: $comment}"
13800				bind $wf.c <Leave> "$share_label configure -text {Share Name:}"
13801
13802				$wf.c configure -state disabled
13803				$wf.e configure -state disabled
13804
13805				pack $wf.c $wf.e -side left -expand 1
13806				pack $wf -side top -fill x
13807				incr i
13808			}
13809		}
13810	}
13811	if {$i == 0} {
13812		global is_win9x
13813		$share_label configure -text {Share Name: No SMB Share Hosts were found!}
13814		if {$is_win9x} {
13815			.smbwiz.f.t insert end "\n(this feature does not work on Win9x you have have to enter them manually: //HOST/share /var/tmp/mymnt)\n"
13816		}
13817	} else {
13818		$share_label configure -text "Share Name: Found $i SMB Shares"
13819	}
13820	smb_check_selected
13821}
13822
13823proc smb_help_me_decide {} {
13824	global is_windows
13825	global smb_local smb_local_hosts smb_this_host smb_selected smb_selected_mnt
13826	global smb_selected_host smb_selected_name
13827	global smb_selected_cb smb_selected_en
13828	global smb_host_list
13829
13830	toplev .smbwiz
13831	set title "SMB Filesystem Tunnelling -- Help Me Decide"
13832	wm title .smbwiz $title
13833	set id "  "
13834
13835	set h 40
13836	if [small_height] {
13837		set h 30
13838	}
13839	scroll_text .smbwiz.f 100 $h
13840
13841	set msg {
13842For now you will have to verify the following information manually.
13843
13844You can do this by either logging into the remote machine to find the info or asking the sysadmin for it.
13845
13846}
13847
13848	if {! $is_windows} {
13849		.smbwiz.f.t configure -font {Helvetica -12 bold}
13850	}
13851	.smbwiz.f.t insert end $msg
13852
13853	set w .smbwiz.f.t.f1
13854	frame $w -bd 1 -relief ridge -cursor {top_left_arrow}
13855
13856	.smbwiz.f.t insert end "\n"
13857
13858	.smbwiz.f.t insert end "1) Indicate the existence of the 'smbmount' command on the remote system:\n"
13859	.smbwiz.f.t insert end "\n$id"
13860	global smbmount_exists
13861	set smbmount_exists 0
13862
13863	checkbutton $w.smbmount_exists -pady 1 -anchor w -variable smbmount_exists \
13864		-text "Yes, the 'smbmount' command exists on the remote system." \
13865		-command smb_check_selected
13866
13867	pack $w.smbmount_exists
13868	.smbwiz.f.t window create end -window $w
13869
13870	.smbwiz.f.t insert end "\n\n\n"
13871
13872	set w .smbwiz.f.t.f2
13873	frame $w -bd 1 -relief ridge -cursor {top_left_arrow}
13874
13875	.smbwiz.f.t insert end "2) Indicate your authorization to run 'smbmount' on the remote system:\n"
13876	.smbwiz.f.t insert end "\n$id"
13877	global smbmount_sumode
13878	set smbmount_sumode "dontknow"
13879
13880	radiobutton $w.dk -pady 1 -anchor w -variable smbmount_sumode -value dontknow \
13881		-text "I do not know if I can mount SMB shares on the remote system via 'smbmount'" \
13882		-command smb_check_selected
13883	pack $w.dk -side top -fill x
13884
13885	radiobutton $w.su -pady 1 -anchor w -variable smbmount_sumode -value su \
13886		-text "I know the Password to run commands as root on the remote system via 'su'" \
13887		-command smb_check_selected
13888	pack $w.su -side top -fill x
13889
13890	radiobutton $w.sudo -pady 1 -anchor w -variable smbmount_sumode -value sudo \
13891		-text "I know the Password to run commands as root on the remote system via 'sudo'" \
13892		-command smb_check_selected
13893	pack $w.sudo -side top -fill x
13894
13895	radiobutton $w.ru -pady 1 -anchor w -variable smbmount_sumode -value none \
13896		-text "I do not need to be root on the remote system to mount SMB shares via 'smbmount'" \
13897		-command smb_check_selected
13898	pack $w.ru -side top -fill x
13899
13900	.smbwiz.f.t window create end -window $w
13901
13902	global smb_wiz_done
13903	set smb_wiz_done 0
13904
13905	button .smbwiz.cancel -text "Cancel" -command {set smb_wiz_done 1}
13906	button .smbwiz.done -text "Done" -command {set smb_wiz_done 1}
13907	pack .smbwiz.done -side bottom -fill x
13908	pack .smbwiz.f -side top -fill both -expand 1
13909
13910	wm protocol .smbwiz WM_DELETE_WINDOW {set smb_wiz_done 1}
13911	center_win .smbwiz
13912
13913	wm title .smbwiz "Searching for Local SMB shares..."
13914	update
13915	wm title .smbwiz $title
13916
13917	global smb_local smb_this_host
13918	.smbwiz.f.t insert end "\n\n\n"
13919
13920	set w .smbwiz.f.t.f3
13921	catch {destroy $w}
13922	frame $w -bd 1 -relief ridge -cursor {top_left_arrow}
13923
13924	.smbwiz.f.t insert end "3) Select SMB shares to mount and their mount point on the remote system:\n"
13925	.smbwiz.f.t insert end "\n${id}"
13926
13927	make_share_widgets $w
13928
13929	.smbwiz.f.t insert end "\n(%USER will be expanded to the username on the remote system and %HOME the home directory)\n"
13930
13931	.smbwiz.f.t insert end "\n\n\n"
13932
13933	.smbwiz.f.t insert end "You can change the list of Local SMB hosts to probe and the mount point prefix here:\n"
13934	.smbwiz.f.t insert end "\n$id"
13935	set w .smbwiz.f.t.f4
13936	frame $w -bd 1 -relief ridge -cursor {top_left_arrow}
13937	set wf .smbwiz.f.t.f4.f
13938	frame $wf
13939	label $wf.l -text "SMB Hosts:  "  -anchor w
13940	entry $wf.e -textvariable smb_host_list -width 60
13941	button $wf.b -text "Apply" -command {make_share_widgets .smbwiz.f.t.f3}
13942	bind $wf.e <Return> "$wf.b invoke"
13943	pack $wf.l $wf.e $wf.b -side left
13944	pack $wf
13945	pack $w
13946
13947	.smbwiz.f.t window create end -window $w
13948
13949	.smbwiz.f.t insert end "\n$id"
13950
13951	set w .smbwiz.f.t.f5
13952	frame $w -bd 1 -relief ridge -cursor {top_left_arrow}
13953	set wf .smbwiz.f.t.f5.f
13954	frame $wf
13955	label $wf.l -text "Mount Prefix:"  -anchor w
13956	entry $wf.e -textvariable smb_mount_prefix -width 60
13957	button $wf.b -text "Apply" -command {apply_mount_point_prefix .smbwiz.f.t.f5.f.e}
13958	bind $wf.e <Return> "$wf.b invoke"
13959	pack $wf.l $wf.e $wf.b -side left
13960	pack $wf
13961	pack $w
13962
13963	.smbwiz.f.t window create end -window $w
13964
13965	.smbwiz.f.t insert end "\n\n\n"
13966
13967	.smbwiz.f.t see 1.0
13968	.smbwiz.f.t configure -state disabled
13969	update
13970
13971	vwait smb_wiz_done
13972	catch {destroy .smbwiz}
13973
13974	if {! $smbmount_exists || $smbmount_sumode == "dontknow"} {
13975		tk_messageBox -type ok -parent .oa -icon warning -message "Sorry we couldn't help out!\n'smbmount' info on the remote system is required for SMB mounting" -title "SMB mounting -- aborting"
13976		global use_smbmnt
13977		set use_smbmnt 0
13978		catch {raise .oa}
13979		return
13980	}
13981	global smb_su_mode
13982	set smb_su_mode $smbmount_sumode
13983
13984	set max 0
13985	foreach en [array names smb_selected_en] {
13986		set i $smb_selected_en($en)
13987		set host $smb_selected_host($i)
13988		set name $smb_selected_name($i)
13989
13990		set len [string length "//$host/$name"]
13991		if {$len > $max} {
13992			set max $len
13993		}
13994	}
13995
13996	set max [expr $max + 8]
13997
13998	set strs ""
13999	foreach en [array names smb_selected_en] {
14000		set i $smb_selected_en($en)
14001		if {! $smb_selected($i)} {
14002			continue
14003		}
14004		set host $smb_selected_host($i)
14005		set name $smb_selected_name($i)
14006		set mnt $smb_selected_mnt($i)
14007
14008		set share "//$host/$name"
14009		set share [format "%-${max}s" $share]
14010
14011		lappend strs "$share $mnt"
14012	}
14013	set text ""
14014	foreach str [lsort $strs] {
14015		append text "$str\n"
14016	}
14017
14018	global smb_mount_list
14019	set smb_mount_list $text
14020
14021	smb_dialog
14022}
14023
14024proc apply_mount_point_prefix {w} {
14025	global smb_selected_host smb_selected_name
14026	global smb_selected_en smb_selected_mnt
14027
14028	set prefix ""
14029	catch {set prefix [$w get]}
14030	if {$prefix == ""} {
14031		mesg "No mount prefix."
14032		bell
14033		return
14034	}
14035
14036	foreach en [array names smb_selected_en] {
14037		set i $smb_selected_en($en)
14038		set host $smb_selected_host($i)
14039		set name $smb_selected_name($i)
14040		set smb_selected_mnt($i) "$prefix/$host/$name"
14041	}
14042}
14043
14044proc smb_dialog {} {
14045	toplev .smb
14046	wm title .smb "SMB Filesystem Tunnelling"
14047	global smb_su_mode smb_mount_list
14048	global use_smbmnt
14049
14050	global help_font
14051
14052	global uname
14053	set h 33
14054	if [small_height] {
14055		set h 17
14056	} elseif {$uname == "Darwin"} {
14057		set h 24
14058	}
14059	scroll_text .smb.f 80 $h
14060
14061	set msg {
14062    Windows/Samba Filesystem mounting requires SSH be used to set up the SMB
14063    service port redirection.  This will be either of the "Use SSH" or
14064    "SSH+SSL" modes. NOTE: For pure SSL tunnelling it currently will not work.
14065
14066    This method requires a working Samba software setup on the remote
14067    side of the connection (VNC server) and existing Samba or Windows file
14068    server(s) on the local side (VNC viewer).
14069
14070    The smbmount(8) program MUST be installed on the remote side. This
14071    evidently limits the mounting to Linux systems.  Let us know of similar
14072    utilities on other Unixes.  Mounting onto remote Windows machines is
14073    currently not supported (our SSH mode with services setup only works
14074    to Unix).  On Debian and Ubuntu the smbmount program is currently in
14075    the package named 'smbfs'.
14076
14077    Depending on how smbmount is configured you may be able to run it
14078    as a regular user, or it may require running under su(1) or sudo(8)
14079    (root password or user password required, respectively).  You select
14080    which one you want via the checkbuttons below.
14081
14082    In addition to a possible su(1) or sudo(8) password, you may ALSO
14083    need to supply passwords to mount each SMB share. This is an SMB passwd.
14084    If it has no password just hit enter after the "Password:" prompt.
14085
14086    The passwords are supplied when the 1st SSH connection starts up;
14087    be prepared to respond to them.
14088
14089    NOTE: USE OF SMB TUNNELLING MODE WILL REQUIRE TWO SSH'S, AND SO YOU
14090    MAY NEED TO SUPPLY TWO LOGIN PASSWORDS UNLESS YOU ARE USING SOMETHING
14091    LIKE ssh-agent(1) or the Putty PW setting.
14092    %WIN
14093
14094    To indicate the Windows/Samba shares to mount enter them one per line
14095    in one of the forms:
14096
14097      //machine1/share   ~/Desktop/my-mount1
14098      //machine2/fubar   /var/tmp/my-foobar2  192.168.100.53:3456
14099      1139  //machine3/baz  /var/tmp/baz      [...]
14100
14101    The first part is the standard SMB host and share name //hostname/dir
14102    (note this share is on the local viewer-side not on the remote end).
14103    A leading '#' will cause the entire line to be skipped.
14104
14105    The second part, e.g. /var/tmp/my-foobar2, is the directory to mount
14106    the share on the remote (VNC Server) side.  You must be able to
14107    write to this directory.  It will be created if it does not exist.
14108    A leading character ~ will be expanded to $HOME.  So will the string
14109    %HOME.  The string %USER will get expanded to the remote username.
14110
14111    An optional part like 192.168.100.53:3456 is used to specify the real
14112    hostname or IP address, and possible non-standard port, on the local
14113    side if for some reason the //hostname is not sufficient.
14114
14115    An optional leading numerical value, 1139 in the above example, indicates
14116    which port to use on the Remote side to SSH redirect to the local side.
14117    Otherwise a random one is tried (a unique one is needed for each SMB
14118    server:port combination).  A fixed one is preferred: choose a free
14119    remote port.
14120
14121    The standard SMB service ports (local side) are 445 and 139.  139 is
14122    used by this application.
14123
14124    Sometimes "localhost" will not work on Windows machines for a share
14125    hostname, and you will have to specify a different network interface
14126    (e.g. the machine's IP address).  If you use the literal string "IP"
14127    it will be attempted to replace it with the numerical IP address, e.g.:
14128
14129      //machine1/share   ~/Desktop/my-mount1   IP
14130
14131    VERY IMPORTANT: Before terminating the VNC Connection, make sure no
14132    applications are using any of the SMB shares (or shells are cd-ed
14133    into the share).  This way the shares will be automatically unmounted.
14134    Otherwise you will need to log in again, stop processes from using
14135    the share, become root and umount the shares manually ("smbumount
14136    /path/to/share", etc.)
14137
14138    For more info see: http://www.karlrunge.com/x11vnc/faq.html#faq-smb-shares
14139}
14140
14141	set msg2 {
14142    To speed up moving to the next step, iconify the first SSH console
14143    when you are done entering passwords, etc. and then click on the
14144    main panel 'VNC Host:Display' label.
14145}
14146
14147	global is_windows
14148	if {! $is_windows} {
14149		regsub { *%WIN} $msg "" msg
14150	} else {
14151		set msg2 [string trim $msg2]
14152		regsub { *%WIN} $msg "    $msg2" msg
14153	}
14154	.smb.f.t insert end $msg
14155
14156	frame .smb.r
14157	label .smb.r.l -text "smbmount(8) auth mode:" -relief ridge
14158	radiobutton .smb.r.none -text "None" -variable smb_su_mode -value "none"
14159	radiobutton .smb.r.su   -text "su(1)" -variable smb_su_mode -value "su"
14160	radiobutton .smb.r.sudo -text "sudo(8)" -variable smb_su_mode -value "sudo"
14161
14162	pack .smb.r.l .smb.r.none .smb.r.sudo .smb.r.su -side left -fill x
14163
14164	label .smb.info -text "Supply the mounts (one per line) below:" -anchor w -relief ridge
14165
14166	eval text .smb.mnts -width 80 -height 5 $help_font
14167	.smb.mnts insert end $smb_mount_list
14168
14169	button .smb.guess -text "Help me decide ..." -command {destroy .smb; smb_help_me_decide}
14170
14171	button .smb.cancel -text "Cancel" -command {set use_smbmnt 0; destroy .smb}
14172	bind .smb <Escape> {set use_smbmnt 0; destroy .smb}
14173	wm protocol .smb WM_DELETE_WINDOW {set use_smbmnt 0; destroy .smb}
14174	button .smb.done -text "Done" -command {if {$use_smbmnt} {set_ssh; set smb_mount_list [.smb.mnts get 1.0 end]}; destroy .smb}
14175
14176	pack .smb.done .smb.cancel .smb.guess .smb.mnts .smb.info .smb.r -side bottom -fill x
14177	pack .smb.f -side top -fill both -expand 1
14178
14179	center_win .smb
14180}
14181
14182proc help_advanced_opts {} {
14183	toplev .ah
14184
14185	scroll_text_dismiss .ah.f
14186
14187	center_win .ah
14188
14189	wm title .ah "Advanced Options Help"
14190
14191	set msg {
14192    These Advanced Options that may require extra software installed on
14193    the VNC server-side (the remote server machine) and/or on the VNC
14194    client-side (where this gui is running).
14195
14196    The Service redirection options, CUPS, ESD/ARTSD, and SMB will
14197    require that you use SSH for tunneling so that they can use the -R
14198    port redirection will be enabled for each service.  I.e. "Use SSH"
14199    or "SSH + SSL" mode.
14200
14201    These options may also require additional configuration to get them
14202    to work properly.  Please submit bug reports if it appears it should
14203    be working for your setup but is not.
14204
14205    Brief (and some not so brief) descriptions:
14206
14207      CUPS Print tunnelling:
14208
14209         Redirect localhost:6631 (say) on the VNC server to your local
14210         CUPS server.  SSH mode is required.
14211
14212      ESD/ARTSD Audio tunnelling:
14213
14214         Redirect localhost:16001 (say) on the VNC server to your local
14215         ESD, etc. sound server.  SSH mode is required.
14216
14217      SMB mount tunnelling:
14218
14219         Redirect localhost:1139 (say) on the VNC server and through that
14220         mount SMB file shares from your local server.  The remote machine
14221         must be Linux with smbmount installed. SSH mode is required.
14222
14223      Additional Port Redirs (via SSH):
14224
14225         Specify additional -L port:host:port and -R port:host:port
14226         cmdline options for SSH to enable additional services.
14227         SSH mode is required.
14228
14229      Automatically Find X Login/Greeter:
14230
14231         This mode is similar to "Automatically Find X Session" except
14232         that it will attach to a X Login/Greeter screen that no one
14233         has logged into yet.  It requires root privileges via sudo(1)
14234         on the remote machine.  SSH mode is required.
14235
14236         As with "Automatically Find X Session" it works only with SSH
14237         mode and requires x11vnc be installed on the remote computer.
14238
14239         It simply sets the Remote SSH Command to:
14240
14241              PORT= sudo x11vnc -find -localhost -env FD_XDM=1
14242
14243         An initial ssh running 'sudo id' is performed to try to
14244         'prime' sudo so the 2nd one that runs x11vnc does not need
14245         a password.  This may not always succeed... please mail us
14246         the details if it doesn't.
14247
14248         See the 'X Login' description in 'Terminal Services' Mode
14249         Help for more info.
14250
14251      Private SSH KnownHosts file:
14252
14253         On Unix in SSH mode, let the user specify a non-default
14254         ssh known_hosts file to be used only by the current profile.
14255         This is the UserKnownHostsFile ssh option and is described in the
14256         ssh_config(1) man page.  This is useful to avoid proxy 'localhost'
14257         SSH key collisions.
14258
14259         Normally one should simply let ssh use its default file
14260         ~/.ssh/known_hosts for tracking SSH keys.  The only problem that
14261         happens is when multiple SSVNC connections use localhost tunnel
14262         port redirections.  These make ssh connect to 'localhost' on some
14263         port (where the proxy is listening.)  Then the different keys
14264         from the multiple ssh servers collide when ssh saves them under
14265         'localhost' in ~/.ssh/known_hosts.
14266
14267         So if you are using a proxy with SSVNC or doing a "double SSH
14268         gateway" your ssh will connect to a proxy port on localhost, and you
14269         should set a private KnownHosts file for that connection profile.
14270         This is secure and avoids man-in-the-middle attack (as long as
14271         you actually verify the initial save of the SSH key!)
14272
14273         The default file location will be:
14274
14275                  ~/.vnc/ssh_known_hosts/profile-name.known
14276
14277         but you can choose any place you like.  It must of course be
14278         unique and not shared with another ssh connection otherwise they
14279         both may complain about the key for 'localhost' changing, etc.
14280
14281      SSH Local Port Protections:
14282
14283         An LD_PRELOAD hack to limit the number of SSH port redirections
14284         to 1 and within the first 35 seconds.  So there is a smaller
14285         window when the user can try to use your tunnel compared to
14286         the duration of your session.  SSH mode is required.
14287
14288      STUNNEL Local Port Protections:
14289
14290         Try to prevent Untrusted Local Users (see the main Help panel)
14291         from using your STUNNEL tunnel to connect to the remote VNC
14292         Server.
14293
14294      Change VNC Viewer:
14295
14296         Specify a non-bundled VNC Viewer (e.g.  UltraVNC or RealVNC)
14297         to run instead of the bundled TightVNC Viewer.
14298
14299      Port Knocking:
14300
14301         For "closed port" services, first "knock" on the firewall ports
14302         in a certain way to open the door for SSH or SSL.  The port
14303         can also be closed when the encrypted VNC connection finishes.
14304
14305      UltraVNC DSM Encryption Plugin:
14306
14307         On Unix only, by using the supplied tool, ultravnc_dsm_helper,
14308         encrypted connections to UltraVNC servers using their plugins
14309         is enabled.  Support for secret key encryption to Non-UltraVNC
14310         DSM servers is also supported, e.g. x11vnc -enc blowfish:my.key
14311
14312      Do not Probe for VeNCrypt:
14313
14314         Disable VeNCrypt auto-detection probe when not needed.
14315
14316         By default in SSL mode an initial probe for the use of the
14317         VeNCrypt or ANONTLS protocol is performed.  This is done
14318         during the initial fetch-cert action.  Once auto-detected in
14319         the initial probe, the real connection to the VNC Server will
14320         use this information to switch to SSL/TLS at the right point in
14321         the VeNCrypt/ANONTLS handshake.
14322
14323         In "Verify All Certs" mode initial the fetch-cert action is
14324         required so the automatic probing for VeNCrypt is always done.
14325         The fetch-cert is not needed if you specified a ServerCert or if
14326         you disabled "Verify All Certs".  But by default the fetch-cert
14327         is done anyway to try to auto-detect VeNCrypt/ANONTLS.
14328
14329         Set 'Do not Probe for VeNCrypt' to skip this unneeded fetch-cert
14330         action (and hence speed up connecting.)  Use this if you
14331         know the VNC Server uses normal SSL and not VeNCrypt/ANONTLS.
14332
14333         See also the next option, 'Server uses VeNCrypt SSL encryption'
14334         to if you know it uses VeNCrypt/ANONTLS (the probing will also
14335         be skipped if that option is set.)
14336
14337      Server uses VeNCrypt SSL encryption:
14338
14339         Indicate that the VNC server uses the VeNCrypt extension to VNC;
14340         it switches to an SSL/TLS tunnel at a certain point in the
14341         VNC Handshake.  This is in constrast to the default ssvnc/x11vnc
14342         SSL tunnel behavior where the *entire* VNC traffic goes through
14343         SSL (i.e. it is vncs:// in the way https:// uses SSL)
14344
14345         Enable this option if you know the server supports VeNCrypt.
14346         Also use this option for the older ANONTLS extension (vino).
14347         Doing so will give the quickest and most reliable connection
14348         to VeNCrypt/ANONTLS servers.  If set, any probing to try to
14349         auto-detect VeNCrypt/ANONTLS will be skipped.
14350
14351         Some VNC servers supporting VeNCrypt: VeNCrypt, QEMU, ggi,
14352         virt-manager, and Xen.  Vino supports ANONTLS.
14353
14354         The SSVNC VeNCrypt/ANONTLS support even works with 3rd party
14355         VNC Viewers you specify via 'Change VNC Viewer' (e.g. RealVNC,
14356         TightVNC, UltraVNC etc.) that do not directly support it.
14357
14358         Note: many VeNCrypt servers only support Anonymous Diffie Hellman
14359         TLS which has NO built in authentication and you will also need
14360         to set the option described in the next section.
14361
14362         If you are using VeNCrypt or ANONTLS for REVERSE connections
14363         (Listen) then you *MUST* set this 'Server uses VeNCrypt SSL
14364         encryption' option.   Note also that REVERSE connections using
14365         VeNCrypt/ANONTLS currently do not work on Windows.
14366
14367         Also, if you are using the "Use SSH+SSL" double tunnel to a
14368         VeNCrypt/ANONTLS server, you MUST set 'Server uses VeNCrypt
14369         SSL encryption' because "Verify All Certs" is disabled in
14370         SSH+SSL mode.
14371
14372      Server uses Anonymous Diffie-Hellman
14373
14374         Anonymous Diffie-Hellman can be used for SSL/TLS connections but
14375         there are no Certificates for authentication.  Therefore only
14376         passive eavesdropping attacks are prevented, not Man-In-The-Middle
14377         attacks.  Not recommended; try to use verified X509 certs instead.
14378
14379         Enable this option if you know the server only supports Anon DH.
14380         When you do so, remember that ALL Certificate checking will be
14381         skipped (even if you have 'Verify All Certs' selected or set
14382         a ServerCert.)
14383
14384         SSVNC may be able to autodetect Anon DH even if you haven't
14385         selected 'Server uses Anonymous Diffie-Hellman'. Once detected, it
14386         will prompt you whether it should continue.  Set the 'Server uses
14387         Anonymous Diffie-Hellman' option to avoid trying autodetection
14388         (i.e. forcing the issue.)
14389
14390         Note that most Anonymous Diffie-Hellman VNC Servers do so
14391         via the VeNCrypt or ANONTLS VNC extensions (see the previous
14392         section.)  For these servers if you select 'Server uses Anonymous
14393         Diffie-Hellman' you *MUST* ALSO select 'Server uses VeNCrypt SSL
14394         encryption', otherwise SSVNC may have no chance to auto-detect
14395         the VeNCrypt/ANONTLS protocol.
14396
14397         Also note, if you are using the "Use SSH+SSL" double tunnel to
14398         a VeNCrypt/ANONTLS server using Anon DH you MUST set 'Server
14399         uses Anonymous Diffie-Hellman' because "Verify All Certs"
14400         is disabled in SSH+SSL mode.
14401
14402      Include:
14403
14404       Default settings and Include Templates:
14405
14406         Before explaining how Include works, first note that if you
14407         do not prefer some of SSVNC's default settings you can start
14408         up SSVNC and then change the settings for the options that you
14409         want to have a different default value.  Then type "defaults"
14410         in VNC Host:Display entry box and press "Save" to save them in
14411         the "defaults.vnc" profile.  After this, SSVNC will initialize
14412         all of the default values and then apply your override values
14413         in "defaults".
14414
14415         For example, suppose you always want to use a different, 3rd
14416         party VNC Viewer.  Set Options -> Advanced -> Change VNC Viewer
14417         to what you want, and then save it as the "defaults" profile.
14418         Now that default setting will apply to all profiles, and SSVNC
14419         in its startup state.
14420
14421         To edit the defaults Load it, make changes, and then Save it.
14422         Delete the "defaults" profile to go back to no modifications.
14423         Note that defaults created and saved while defaults.vnc existed
14424         will NOT be automatically adjusted.
14425
14426       Include Templates:
14427
14428         Now suppose you have a certain class of settings that you do
14429         not want to always be applied, but you want them to apply to a
14430         group of profiles.
14431
14432         For example, suppose you have some settings for very low
14433         bandwidth connections (e.g. low color modes and/or aggressive
14434         compression and quality settings.)  Set these values in SSVNC
14435         and then in the VNC Host:Display entry box type in, say,
14436         "slowlink" and then press Save.  This will save those settings
14437         in the template profile named "slowlink.vnc".
14438
14439         Now to create a real profile that uses this template type the
14440         host:disp in "VNC Host:Display" and in Options -> Advanced
14441         -> Includes type in "slowlink".  Then press Save to save the
14442         host profile.  Then re-Load it.  The "slowlink" settings will
14443         be applied after the defaults.  Make any other changes to the
14444         setting for this profile and Save it again.  Next time you load
14445         it in, the Include template settings will override the defaults
14446         and then the profile itself is read in.
14447
14448         You may supply a comma or space separated list of templates
14449         to include.  They are applied in the order listed.  They can be
14450         full path names or basenames relative to the profiles directory.
14451         You do not need to supply the .vnc suffix.  The non-default
14452         settings in them will be applied first, and then any values in
14453         the loaded Profile will override them.
14454
14455      Sleep:
14456
14457         Enter a number to indicate how many extra seconds to sleep
14458         while waiting for the VNC viewer to start up.  On Windows this
14459         can give extra time to enter the Putty/Plink password, etc.
14460
14461      Putty Args:
14462
14463         Windows only, supply a string to be added to all plink.exe
14464         and putty.exe commands.  Example: -i C:\mykey.ppk
14465
14466      Launch Putty Pagent:
14467
14468         Windows only, launch the Putty key agent tool (pageant) to hold
14469         your SSH private keys for automatic logging in by putty/plink.
14470
14471      Launch Putty Key-Gen:
14472
14473         Windows only, launch the Putty key generation tool (puttygen)
14474         to create new SSH private keys.
14475
14476      Unix ssvncviewer:
14477
14478         Display a popup menu with options that apply to the special
14479         Unix SSVNC VNC Viewer (perhaps called 'ssvncviewer') provided by
14480         this SSVNC package.  This only applies to Unix or Mac OS X.
14481
14482      Use ssh-agent:
14483
14484         On Unix only: restart the GUI in the presence of ssh-agent(1)
14485         (e.g. in case you forgot to start your agent before starting
14486         this GUI).  An xterm will be used to enter passphrases, etc.
14487         This can avoid repeatedly entering passphrases for the SSH logins
14488         (note this requires setting up and distributing SSH keys).
14489
14490
14491    About the CheckButtons:
14492
14493         Ahem, Well...., yes quite a klunky UI: you have to toggle the
14494         CheckButton to pull up the Dialog box a 2nd, etc. time... don't
14495         worry your settings will still be there!
14496}
14497
14498	.ah.f.t insert end $msg
14499	jiggle_text .ah.f.t
14500}
14501
14502proc help_ssvncviewer_opts {} {
14503	toplev .av
14504
14505	scroll_text_dismiss .av.f
14506
14507	center_win .av
14508
14509	wm title .av "Unix SSVNC viewer Options Help"
14510
14511	set msg {
14512    These Unix SSVNC VNC Viewer Options apply only on Unix or Mac OS X
14513    when using the viewer (ssvncviewer) supplied by this SSVNC package.
14514
14515    Brief descriptions:
14516
14517      Multiple LISTEN Connections:
14518
14519         Allow multiple VNC servers to reverse connect at the same time
14520         and so display each of their desktops on your screen at the
14521         same time.
14522
14523      Listen Once:
14524
14525         Try to have the VNC Viewer exit after the first listening
14526         connection. (It may not always be detected; use Ctrl-C to exit)
14527
14528      Listen Accept Popup Dialog:
14529
14530         In -listen (reverse connection listening) mode when a reverse
14531         VNC connection comes in show a popup asking whether to Accept
14532         or Reject the connection. (-acceptpopup vncviewer option.)
14533
14534      Accept Popup UltraVNC Single Click:
14535
14536         As in 'Listen Accept Popup Dialog', except assume the remote
14537         VNC server is UltraVNC Single Click and force the execution of
14538         the protocol to retrieve the extra remote-side info (Windows
14539         User, ComputerName, etc) which is then also displayed in the
14540         Popup window. (-acceptpopupsc vncviewer option.)
14541
14542      Use X11 Cursor:
14543
14544         When drawing the mouse cursor shape locally, use an X11 cursor
14545         instead of drawing it directly into the framebuffer.  This
14546         can sometimes give better response, and avoid problems under
14547         'Scaling'.
14548
14549      Disable Bell:
14550
14551         Disable beeps coming from remote side.
14552
14553      Use Raw Local:
14554
14555         Use the VNC Raw encoding for 'localhost' connections (instead
14556         of assuming there is a local tunnel, SSL or SSH, going to the
14557         remote machine.
14558
14559      Avoid Using Terminal:
14560
14561         By default the Unix ssvncviewer will prompt for usernames,
14562         passwords, etc. in the terminal it is running inside of.
14563         Set this option to use windows for messages and prompting as
14564         much as possible.  Messages will also go to the terminal, but
14565         all prompts will be done via popup window.
14566
14567         Note that stunnel(1) may prompt for a passphrase to unlock a
14568         private SSL key.  This is fairly rare because it is usually
14569         for Client-side SSL authentication.  stunnel will prompt from
14570         the terminal; there seems to be no way around this.
14571
14572         Also, note that ssh(1) may prompt for an ssh key passphrase
14573         or Unix password.  This can be avoided in a number of ways,
14574         the simplest one is to use ssh-agent(1) and ssh-add(1).
14575         However ssh(1) may also prompt you to accept a new public key
14576         for a host or warn you if the key has changed, etc.
14577
14578      Use Popup Fix:
14579
14580         Enable a fix that warps the popup (F8) to the mouse pointer.
14581
14582      Use XGrabServer (for fullscreen):
14583
14584         On Unix only, use the XGrabServer workaround for older window
14585         managers.  Sometimes also needed on recent (2008) GNOME.  This
14586         workaround can make going into/out-of Fullscreen work better.
14587
14588      Cursor Alphablending:
14589
14590         Use the x11vnc alpha hack for translucent cursors (requires Unix,
14591         32bpp and same endianness)
14592
14593      TurboVNC:
14594
14595         If available on your platform, use a ssvncviewer compiled with
14596         TurboVNC support.  This is based on the VirtualGL project:
14597         http://www.sourceforge.net/projects/virtualgl	You will need
14598         to install the VirtualGL's TurboJPEG library too.
14599
14600         Currently (May/2009) only Linux.i686, Linux.x86_64, and
14601         Darwin.i386 have vncviewer.turbovnc binaries shipped in the
14602         ssvnc bundles.  See the build instructions for how you might
14603         compile your own.
14604
14605      Disable Pipelined Updates:
14606
14607         Disable the TurboVNC-like pipelined updates mode.  Pipelined
14608         updates is the default even when not TurboVNC enabled.  They
14609         ask for the next screen update before the current one has
14610         finished downloading, and so this might reduce the slowdown
14611         due to high latency or low bandwidth by 2X or so.  Disable
14612         them if they cause problems with the remote VNC Server or
14613         use too much bandwidth.
14614
14615      Send CLIPBOARD not PRIMARY:
14616
14617         When sending locally selected text to the VNC server side,
14618         send the CLIPBOARD selection instead of the PRIMARY selection.
14619
14620      Send Selection Every time:
14621
14622         Send selected text to the VNC server side every time the mouse
14623         focus enters the main VNC Viewer window instead only when it
14624         appears to have changed since the last send.
14625
14626      Scaling:
14627
14628         Use viewer-side (i.e. local) scaling of the VNC screen.  Supply
14629         a fraction, e.g. 0.75 or 3/4, or a WxH geometry, e.g. 1280x1024,
14630         or the string 'fit' to fill the current screen.  Use 'auto'
14631         to scale the desktop to match the viewer window size.
14632
14633         If you observe mouse trail painting errors try using X11 Cursor.
14634
14635         Note that since the local scaling is done in software it can
14636         be slow.  Since ZRLE is better than Tight in this regard, when
14637         scaling is detected, the encoding will be switched to ZRLE.
14638         Use the Popup to go back to Tight if you want to, or set the
14639         env. var. SSVNC_PRESERVE_ENCODING=1 to disable the switch.
14640
14641         For additional speedups under local scaling: try having a solid
14642         desktop background on the remote side (either manually or using
14643         'x11vnc -solid ...'); and also consider using client side caching
14644         'x11vnc -ncache 10 ...' if the remote server is x11vnc.
14645
14646      Escape Keys:
14647
14648         Enable 'Escape Keys', a set of modifier keys that, if all are
14649         pressed down, enable local Hot Key actions.  Set to 'default'
14650         to use the default (Alt_L,Super_L on unix, Control_L,Meta_L
14651         on macosx) or set to a list of modifier keys.
14652
14653      Y Crop:
14654
14655         This is for x11vnc's -ncache client side caching scheme with our
14656         Unix TightVNC viewer.  Sets the Y value to "crop" the viewer
14657         size at (below the cut is the pixel cache region you do not
14658         want to see).  If the screen is tall (H > 2*W) ycropping will
14659         be autodetected, or you can set to -1 to force autodection.
14660         Otherwise, set it to the desired Y value.  You can also set
14661         the scrollbar width (very thin by default) by appending ",sb=N"
14662         (or use ",sb=N" by itself to just set the scrollbar width).
14663
14664      ScrollBar Width:
14665
14666         This is for x11vnc's -ncache client side caching scheme with our
14667         Unix TightVNC viewer.  For Y-Crop mode, set the size of the
14668         scrollbars (often one want it to be very narrow, e.g. 2 pixels
14669         to be less distracting.
14670
14671      RFB Version:
14672
14673         Set the numerical version of RFB (VNC) protocol to pretend to
14674         be, 3.x.  Usually only needed with UltraVNC servers.
14675
14676      Encodings:
14677
14678         List encodings in preferred order, for example
14679         'copyrect zrle tight'   The list of encodings is:
14680         copyrect tight zrle zywrle hextile zlib corre rre raw
14681
14682      Extra Options:
14683
14684         String of extra Unix ssvncviewer command line options.  I.e. for
14685         ones like -16bpp that cannot be set inside this SSVNC GUI.  For a
14686         list click Help then 'SSVNC vncviewer -help Output'.
14687
14688
14689    These are environment variables one may set to affect the options
14690    of the SSVNC vncviewer and also the ss_vncviewer wrapper script
14691    (and hence may apply to 3rd party vncviewers too)
14692
14693         VNCVIEWER_ALPHABLEND     (-alpha, see Cursor Alphablending above)
14694         VNCVIEWER_POPUP_FIX      (-popupfix, warp popup to mouse location)
14695         VNCVIEWER_GRAB_SERVER    (-graball, see Use XGrabServer above)
14696         VNCVIEWER_YCROP          (-ycrop, see Y Crop above)
14697         VNCVIEWER_SBWIDTH        (-sbwidth, see ScrollBar Width above)
14698         VNCVIEWER_RFBVERSION     (-rfbversion, e.g. 3.6)
14699         VNCVIEWER_ENCODINGS      (-encodings, e.g. "copyrect zrle hextile")
14700         VNCVIEWER_NOBELL         (-nobell)
14701         VNCVIEWER_X11CURSOR      (-x11cursor, see Use X11 Cursor above)
14702         VNCVIEWER_RAWLOCAL       (-rawlocal, see Use Raw Local above)
14703         VNCVIEWER_NOTTY          (-notty, see Avoid Using Terminal above)
14704         VNCVIEWER_ESCAPE         (-escape, see Escape Keys above)
14705         VNCVIEWER_ULTRADSM       (-ultradsm)
14706         VNCVIEWER_PIPELINE_UPDATES (-pipeline, see above)
14707         VNCVIEWER_SEND_CLIPBOARD (-sendclipboard)
14708         VNCVIEWER_SEND_ALWAYS    (-sendalways)
14709         VNCVIEWER_RECV_TEXT      (-recvtext clipboard/primary/both)
14710         VNCVIEWER_NO_CUTBUFFER   (do not send CUTBUFFER0 as fallback)
14711         VNCVIEWER_NO_PIPELINE_UPDATES (-nopipeline)
14712         VNCVIEWER_ALWAYS_RECENTER (set to avoid(?) recentering on resize)
14713         VNCVIEWER_IS_REALVNC4    (indicate vncviewer is realvnc4 flavor.)
14714         VNCVIEWER_NO_IPV4        (-noipv4)
14715         VNCVIEWER_NO_IPV6        (-noipv6)
14716         VNCVIEWER_FORCE_UP       (force raise on fullscreen graball)
14717         VNCVIEWER_PASSWORD       (danger: set vnc passwd via env. var.)
14718         VNCVIEWER_MIN_TITLE      (minimum window title (appshare))
14719
14720         VNCVIEWERCMD             (unix viewer command, default vncviewer)
14721         VNCVIEWERCMD_OVERRIDE    (force override of VNCVIEWERCMD)
14722         VNCVIEWERCMD_EXTRA_OPTS  (extra options to pass to VNCVIEWERCMD)
14723         VNCVIEWER_LISTEN_LOCALHOST (force ssvncviewer to -listen on localhost)
14724         VNCVIEWER_NO_SEC_TYPE_TIGHT(force ssvncviewer to skip rfbSecTypeTight)
14725         HEXTILE_YCROP_TOO        (testing: nosync_ycrop for hextile updates.)
14726
14727         SS_DEBUG                 (very verbose debug printout by script.)
14728         SS_VNCVIEWER_LISTEN_PORT (force listen port.)
14729         SS_VNCVIEWER_NO_F        (no -f for SSH.)
14730         SS_VNCVIEWER_NO_T        (no -t for SSH.)
14731         SS_VNCVIEWER_USE_C       (force -C compression for SSH.)
14732         SS_VNCVIEWER_SSH_CMD     (override SSH command to run.)
14733         SS_VNCVIEWER_NO_MAXCONN  (no maxconn for stunnel (obsolete))
14734         SS_VNCVIEWER_RM          (file containing vnc passwd to remove.)
14735         SS_VNCVIEWER_SSH_ONLY    (run the SSH command, then exit.)
14736
14737         SSVNC_MULTIPLE_LISTEN    (-multilisten, see Multiple LISTEN above)
14738         SSVNC_ACCEPT_POPUP       (-acceptpopup, see Accept Popup Dialog)
14739         SSVNC_ACCEPT_POPUP_SC    (-acceptpopupsc, see Accept Popup Dialog)
14740         SSVNC_TURBOVNC           (see TurboVNC above)
14741         SSVNC_UNIXPW             (-unixpw)
14742         SSVNC_UNIXPW_NOESC       (do not send escape in -unixpw mode)
14743         SSVNC_SCALE              (-scale, see Scaling above)
14744         SSVNC_NOSOLID            (do not do solid region speedup in
14745                                   scaling mode.)
14746         SSVNC_PRESERVE_ENCODING  (do not switch to ZRLE when scaling)
14747         SSVNC_FINISH_SLEEP       (on unix/macosx sleep this many seconds
14748                                   before exiting the terminal, default 5)
14749
14750         Misc (special usage or debugging or ss_vncviewer settings):
14751
14752         SSVNC_MESG_DELAY         (sleep this many millisec between messages)
14753         SSVNC_NO_ENC_WARN        (do not print out a NO ENCRYPTION warning)
14754         SSVNC_EXTRA_SLEEP        (same as Sleep: window)
14755         SSVNC_NO_ULTRA_DSM       (disable ultravnc dsm encryption)
14756         SSVNC_ULTRA_DSM          (the ultravnc_dsm_helper command)
14757         SSVNC_ULTRA_FTP_JAR      (file location of ultraftp.jar jar file)
14758         SSVNC_KNOWN_HOSTS_FILE   (file for per-connection ssh known hosts)
14759         SSVNC_SCALE_STATS        (print scaling stats)
14760         SSVNC_NOSOLID            (disable solid special case while scaling)
14761         SSVNC_DEBUG_RELEASE      (debug printout for keyboard modifiers.)
14762         SSVNC_DEBUG_ESCAPE_KEYS  (debug printout for escape keys)
14763         SSVNC_NO_MAYBE_SYNC      (skip XSync() calls in certain painting)
14764         SSVNC_MAX_LISTEN         (number of time to listen for reverse conn.)
14765         SSVNC_LISTEN_ONCE        (listen for reverse conn. only once)
14766         STUNNEL_LISTEN           (stunnel interface for reverse conn.
14767         SSVNC_NO_MESSAGE_POPUP   (do not place info messages in popup.)
14768         SSVNC_SET_SECURITY_TYPE  (force VeNCrypt security type)
14769         SSVNC_PREDIGESTED_HANDSHAKE (string used for VeNCrypt, etc. connect)
14770         SSVNC_SKIP_RFB_PROTOCOL_VERSION (force viewer to be RFB 3.8)
14771         SSVNC_DEBUG_SEC_TYPES    (debug security types for VeNCrypt)
14772         SSVNC_DEBUG_MSLOGON      (extra printout for ultravnc mslogon proto)
14773         SSVNC_DEBUG_RECTS        (printout debug for RFB rectangles.)
14774         SSVNC_DEBUG_CHAT         (printout debug info for chat mode.)
14775         SSVNC_DELAY_SYNC         (faster local drawing delaying XSync)
14776         SSVNC_DEBUG_SELECTION    (printout debug for selection/clipboard)
14777         SSVNC_REPEATER           (URL-ish sslrepeater:// thing for UltraVNC)
14778         SSVNC_VENCRYPT_DEBUG     (debug printout for VeNCrypt mode.)
14779         SSVNC_VENCRYPT_USERPASS  (force VeNCrypt user:pass)
14780         SSVNC_STUNNEL_DEBUG      (increase stunnel debugging printout)
14781         SSVNC_STUNNEL_VERIFY3    (increase stunnel verify from 2 to 3)
14782         SSVNC_LIM_ACCEPT_PRELOAD (preload library to limit accept(2))
14783         SSVNC_SOCKS5             (socks5 for x11vnc PORT= mode, default)
14784         SSVNC_SOCKS4		  (socks4 for x11vnc PORT= mode)
14785         SSVNC_NO_IPV6_PROXY      (do not setup a ipv6:// proxy)
14786         SSVNC_NO_IPV6_PROXY_DIRECT (do not setup a ipv6:// proxy unencrypted)
14787         SSVNC_PORT_IPV6          (x11vnc PORT= mode is to ipv6-only)
14788         SSVNC_IPV6               (0 to disable ss_vncviewer ipv6 check)
14789         SSVNC_FETCH_TIMEOUT      (ss_vncviewer cert fetch timeout)
14790         SSVNC_USE_S_CLIENT       (force cert fetch to be 'openssl s_client')
14791         SSVNC_SHOWCERT_EXIT_0    (force showcert to exit with success)
14792         SSVNC_SSH_LOCALHOST_AUTH (force SSH localhost auth check.)
14793         SSVNC_TEST_SEC_TYPE      (force PPROXY VeNCrypt type; testing)
14794         SSVNC_TEST_SEC_SUBTYPE   (force PPROXY VeNCrypt subtype; testing)
14795         SSVNC_EXIT_DEBUG         (testing: prompt to exit at end.)
14796         SSVNC_UP_DEBUG           (gui user/passwd debug mode.)
14797         SSVNC_UP_FILE            (gui user/passwd file.)
14798
14799         STUNNEL_EXTRA_OPTS       (extra options for stunnel.)
14800
14801         X11VNC_APPSHARE_DEBUG    (for debugging -appshare mode.)
14802         NO_X11VNC_APPSHARE       (shift down for escape keys.)
14803         DEBUG_HandleFileXfer     (ultravnc filexfer)
14804         DEBUG_RFB_SMSG           (RFB server message debug.)
14805}
14806
14807	.av.f.t insert end $msg
14808	button .av.htext -text "SSVNC vncviewer -help Output" -command show_viewer_help
14809	pack .av.htext -side bottom -fill x
14810	jiggle_text .av.f.t
14811}
14812
14813proc show_viewer_help {} {
14814	toplev .vhlp
14815
14816	set h 35
14817	if [small_height] {
14818		set h 30
14819	}
14820	scroll_text_dismiss .vhlp.f 83 $h
14821
14822	center_win .vhlp
14823	wm resizable .vhlp 1 0
14824
14825	wm title .vhlp "SSVNC vncviewer -help Output"
14826
14827	set msg "-- No Help Output --"
14828	catch {set msg [exec ss_vncviewer -viewerhelp 2>/dev/null]}
14829
14830	.vhlp.f.t insert end $msg
14831	jiggle_text .vhlp.f.t
14832}
14833
14834proc set_viewer_path {} {
14835	global change_vncviewer_path
14836	unix_dialog_resize .chviewer
14837	set change_vncviewer_path [tk_getOpenFile -parent .chviewer]
14838	catch {raise .chviewer}
14839	update
14840}
14841
14842proc change_vncviewer_dialog {} {
14843	global change_vncviewer change_vncviewer_path vncviewer_realvnc4
14844	global ts_only
14845
14846	toplev .chviewer
14847	wm title .chviewer "Change VNC Viewer"
14848
14849	global help_font
14850	if {$ts_only} {
14851		eval text .chviewer.t -width 90 -height 16 $help_font
14852	} else {
14853		eval text .chviewer.t -width 90 -height 27 $help_font
14854	}
14855	apply_bg .chviewer.t
14856
14857	set msg {
14858    To use your own VNC Viewer (i.e. one installed by you, not included in this
14859    package), e.g. UltraVNC or RealVNC, type in the program name, or browse for
14860    the full path to it.  You can put command line arguments after the program.
14861
14862    Note that due to incompatibilities with respect to command line options
14863    there may be issues, especially if many command line options are supplied.
14864    You can specify your own command line options below if you like (and try to
14865    avoid setting any others in this GUI under "Options").
14866
14867    If the path to the program name has spaces it in, surround it with double quotes:
14868
14869        "C:\Program Files\My Vnc Viewer\VNCVIEWER.EXE"
14870
14871    Make sure the very first character is a quote.  You should quote the command
14872    even if it is only the command line arguments that need extra protection:
14873
14874        "wine" -- "/home/fred/Program Flies/UltraVNC-1.0.2.exe" /64colors
14875
14876    Since the command line options differ between them greatly, if you know it
14877    is of the RealVNC 4.x flavor, indicate on the check box. Otherwise we guess.
14878
14879    To have SSVNC act as a general STUNNEL redirector (no VNC) set the viewer to be
14880    "xmessage OK" or "xmessage <port>" or "sleep n" or "sleep n <port>" (or "NOTEPAD"
14881    on Windows).  The default listen port is 5930.  The destination is set in "VNC
14882    Host:Display" (for a remote port less than 200 use the negative of the port value).
14883}
14884
14885	if {$ts_only} {
14886		regsub {Note that due(.|\n)*If the} $msg "If the" msg
14887		regsub {To have SSVNC act(.|\n)*} $msg "" msg
14888	}
14889	.chviewer.t insert end $msg
14890
14891	frame .chviewer.path
14892	label .chviewer.path.l -text "VNC Viewer:"
14893	entry .chviewer.path.e -width 40 -textvariable change_vncviewer_path
14894	button .chviewer.path.b -text "Browse..." -command set_viewer_path
14895	checkbutton .chviewer.path.r -anchor w -variable vncviewer_realvnc4 -text \
14896		"RealVNC 4.x"
14897
14898	pack .chviewer.path.l -side left
14899	pack .chviewer.path.e -side left -expand 1 -fill x
14900	pack .chviewer.path.b -side left
14901	pack .chviewer.path.r -side left
14902
14903	button .chviewer.cancel -text "Cancel" -command {destroy .chviewer; set change_vncviewer 0}
14904	bind .chviewer <Escape> {destroy .chviewer; set change_vncviewer 0}
14905	wm protocol .chviewer WM_DELETE_WINDOW {destroy .chviewer; set change_vncviewer 0}
14906	button .chviewer.done -text "Done" -command {destroy .chviewer; catch {raise .oa}}
14907	bind .chviewer.path.e <Return> {destroy .chviewer; catch {raise .oa}}
14908
14909	pack .chviewer.t .chviewer.path .chviewer.cancel .chviewer.done -side top -fill x
14910
14911	center_win .chviewer
14912	wm resizable .chviewer 1 0
14913
14914	focus .chviewer.path.e
14915}
14916
14917proc port_redir_dialog {} {
14918	global additional_port_redirs additional_port_redirs_list
14919
14920	toplev .redirs
14921	wm title .redirs "Additional Port Redirections (via SSH)"
14922
14923	global help_font uname
14924	set h 35
14925	if [small_height] {
14926		set h 27
14927	}
14928	eval text .redirs.t -width 80 -height $h $help_font
14929	apply_bg .redirs.t
14930
14931	set msg {
14932    Specify any additional SSH port redirections you desire for the
14933    connection.  Put as many as you want separated by spaces.  These only
14934    apply to SSH and SSH+SSL connections, they do not apply to Pure SSL
14935    connections.
14936
14937    -L port1:host:port2  will listen on port1 on the local machine (where
14938                         you are sitting) and redirect them to port2 on
14939                         "host".  "host" is relative to the remote side
14940                         (VNC Server).  Use "localhost" for the remote
14941                         machine itself.
14942
14943    -R port1:host:port2  will listen on port1 on the remote machine
14944                         (where the VNC server is running) and redirect
14945                         them to port2 on "host".  "host" is relative
14946                         to the local side (where you are sitting).
14947                         Use "localhost" for this machine.
14948
14949    Perhaps you want a redir to a web server inside an intranet:
14950
14951        -L 8001:web-int:80
14952
14953    Or to redir a remote port to your local SSH daemon:
14954
14955        -R 5022:localhost:22
14956
14957    etc.  There are many interesting possibilities.
14958
14959    Sometimes, especially for Windows Shares, you cannot do a -R redir to
14960    localhost, but need to supply the IP address of the network interface
14961    (e.g. by default the Shares do not listen on localhost:139).  As a
14962    convenience you can do something like -R 1139:IP:139 (for any port
14963    numbers) and the IP will be attempted to be expanded.  If this fails
14964    for some reason you will have to use the actual numerical IP address.
14965}
14966	.redirs.t insert end $msg
14967
14968	frame .redirs.path
14969	label .redirs.path.l -text "Port Redirs:"
14970	entry .redirs.path.e -width 40 -textvariable additional_port_redirs_list
14971
14972	pack .redirs.path.l -side left
14973	pack .redirs.path.e -side left -expand 1 -fill x
14974
14975	button .redirs.cancel -text "Cancel" -command {set additional_port_redirs 0; destroy .redirs}
14976	bind .redirs <Escape> {set additional_port_redirs 0; destroy .redirs}
14977	wm protocol .redirs WM_DELETE_WINDOW {set additional_port_redirs 0; destroy .redirs}
14978	button .redirs.done -text "Done" -command {destroy .redirs}
14979
14980	pack .redirs.t .redirs.path .redirs.cancel .redirs.done -side top -fill x
14981
14982	center_win .redirs
14983	wm resizable .redirs 1 0
14984
14985	focus .redirs.path.e
14986}
14987
14988proc stunnel_sec_dialog {} {
14989	global stunnel_local_protection
14990
14991	toplev .stlsec
14992	wm title .stlsec "STUNNEL Local Port Protections"
14993
14994	global help_font uname
14995
14996	set h 37
14997	if [small_height] {
14998		set h 26
14999	}
15000	scroll_text .stlsec.f 82 $h
15001
15002	apply_bg .stlsec.f
15003
15004	set msg {
15005    See the discussion of "Untrusted Local Users" in the main 'Help'
15006    panel for info about users who are able to log into the workstation
15007    you run SSVNC on and might try to use your encrypted tunnel to gain
15008    access to the remote VNC machine.
15009
15010    On Unix, for STUNNEL SSL tunnels we provide two options as extra
15011    safeguards against untrusted local users.  Both only apply to Unix/MacOSX.
15012    Note that Both options are *IGNORED* in reverse connection (Listen) mode.
15013
15014    1) The first one 'Use stunnel EXEC mode' (it is mutually exclusive with
15015       option 2).  For this case the modified SSVNC Unix viewer must be
15016       used: it execs the stunnel program instead of connecting to it via
15017       TCP/IP.  Thus there is no localhost listening port involved at all.
15018
15019       This is the best solution for SSL stunnel tunnels, it works well and
15020       is currently enabled by default.  Disable it if there are problems.
15021
15022    2) The second one 'Use stunnel IDENT check', uses the stunnel(8)
15023       'ident = username' to use the local identd daemon (IDENT RFC 1413
15024       http://www.ietf.org/rfc/rfc1413.txt) to check that the locally
15025       connecting program (the SSVNC vncviewer) is being run by your userid.
15026       See the stunnel(8) man page for details.
15027
15028       Normally the IDENT check service cannot be trusted much when used
15029       *remotely* (the remote host may be have installed a modified daemon).
15030       However when using the IDENT check service *locally* it should be
15031       reliable.  If not, it means the local machine (where you run SSVNC)
15032       has already been root compromised and you have a serious problem.
15033
15034       Enabling 'Use stunnel IDENT check' requires a working identd on the
15035       local machine.  Often it is not installed or enabled (because it is not
15036       deemed to be useful, etc).  identd is usually run out of the inetd(8)
15037       super-server.  Even when installed and running it is often configured
15038       incorrectly.  On a Debian/lenny system we actually found that the
15039       kernel module 'tcp_diag' needed to be loaded! ('modprobe tcp_diag')
15040}
15041	.stlsec.f.t insert end $msg
15042
15043	radiobutton .stlsec.ident -relief ridge -anchor w -variable stunnel_local_protection_type -value "ident" -text "Use stunnel IDENT check"
15044	radiobutton .stlsec.exec  -relief ridge -anchor w -variable stunnel_local_protection_type -value "exec"  -text "Use stunnel EXEC mode"
15045
15046	button .stlsec.cancel -text "Cancel" -command {set stunnel_local_protection 0; destroy .stlsec}
15047	bind .stlsec <Escape> {set stunnel_local_protection 0; destroy .stlsec}
15048	wm protocol .stlsec WM_DELETE_WINDOW {set stunnel_local_protection 0; destroy .stlsec}
15049	button .stlsec.done -text "Done" -command {if {$stunnel_local_protection_type == "none"} {set stunnel_local_protection 0}; destroy .stlsec}
15050
15051	pack .stlsec.f .stlsec.exec .stlsec.ident .stlsec.cancel .stlsec.done -side top -fill x
15052
15053	center_win .stlsec
15054	wm resizable .stlsec 1 0
15055}
15056
15057proc disable_ssl_workarounds_dialog {} {
15058	global disable_ssl_workarounds disable_ssl_workarounds_type
15059
15060	toplev .sslwrk
15061	wm title .sslwrk "Disable SSL Workarounds"
15062
15063	global help_font uname
15064	set h 36
15065	if [small_height] {
15066		set h 24
15067	}
15068	scroll_text .sslwrk.f 86 $h
15069
15070	apply_bg .sslwrk.f
15071
15072	set msg {
15073    Some SSL implementations are incomplete or buggy or do not work properly
15074    with other implementations.  SSVNC uses STUNNEL for its SSL encryption,
15075    and STUNNEL uses the OpenSSL SSL implementation.
15076
15077    This causes some problems with non-OpenSSL implementations on the VNC server
15078    side.  The most noticable one is the UltraVNC Single Click III (SSL) server:
15079
15080       http://www.uvnc.com/pchelpware/SCIII/index.html
15081
15082    It can make a reverse connection to SSVNC via an encrypted SSL tunnel.
15083
15084    Unfortunately, in the default operation with STUNNEL the connection will be
15085    dropped after 2-15 minutes due to an unexpected packet.
15086
15087    Because of this, by default SSVNC will enable some SSL workarounds to make
15088    connections like these work.  This is the STUNNEL 'options = ALL' setting:
15089    it enables a basic set of SSL workarounds.
15090
15091    You can read all about these workarounds in the stunnel(8) manpage and the
15092    OpenSSL SSL_CTX_set_options(3) manpage.
15093
15094    Why are we mentioning this?  STUNNELS's 'options = ALL' lowers the SSL
15095    security a little bit.  If you know you do not have an incompatible SSL
15096    implementation on the server side (e.g. any one using OpenSSL is compatible,
15097    x11vnc in particular), then you can regain that little bit of security by
15098    selecting the "Disable SSL Workarounds" option.
15099
15100    "Disable All SSL Workarounds" selected below will do that.  On the other hand,
15101    choose "Keep the DONT_INSERT_EMPTY_FRAGMENTS Workaround" to retain that one,
15102    commonly needed workaround.
15103
15104    BTW, you can set the environment variable STUNNEL_EXTRA_OPTS_USER to add
15105    any lines to the STUNNEL global config that you want to.  See the stunnel(8)
15106    man page for more details.
15107}
15108	.sslwrk.f.t insert end $msg
15109
15110	radiobutton .sslwrk.none    -relief ridge -anchor w -variable disable_ssl_workarounds_type -value "none" -text "Disable All Workarounds"
15111	radiobutton .sslwrk.noempty  -relief ridge -anchor w -variable disable_ssl_workarounds_type -value "noempty"  -text "Keep the DONT_INSERT_EMPTY_FRAGMENTS Workaround"
15112
15113	button .sslwrk.cancel -text "Cancel" -command {set disable_ssl_workarounds 0; destroy .sslwrk}
15114	bind .sslwrk <Escape> {set disable_ssl_workarounds 0; destroy .sslwrk}
15115	wm protocol .sslwrk WM_DELETE_WINDOW {set disable_ssl_workarounds 0; destroy .sslwrk}
15116	button .sslwrk.done -text "Done" -command {destroy .sslwrk}
15117
15118	pack .sslwrk.f .sslwrk.none .sslwrk.noempty .sslwrk.cancel .sslwrk.done -side top -fill x
15119
15120	center_win .sslwrk
15121	wm resizable .sslwrk 1 0
15122}
15123
15124proc update_no_ultra_dsm {} {
15125	global ultra_dsm_noultra
15126	global ultra_dsm_type
15127
15128	foreach b {bf des3 aes aes256 l e} {
15129		if {! $ultra_dsm_noultra} {
15130			.ultradsm.nou.$b configure -state disabled
15131		} else {
15132			.ultradsm.nou.$b configure -state normal
15133		}
15134	}
15135	if {! $ultra_dsm_noultra} {
15136		if {$ultra_dsm_type == "arc4"} {
15137			;
15138		} elseif {$ultra_dsm_type == "aesv2"} {
15139			;
15140		} elseif {$ultra_dsm_type == "msrc4"} {
15141			;
15142		} elseif {$ultra_dsm_type == "msrc4_sc"} {
15143			;
15144		} elseif {$ultra_dsm_type == "securevnc"} {
15145			;
15146		} else {
15147			set ultra_dsm_type guess
15148		}
15149		catch {.ultradsm.key.securevnc configure -state normal}
15150		catch {.ultradsm.key.msrc4_sc  configure -state normal}
15151	} else {
15152		catch {.ultradsm.key.securevnc configure -state disabled}
15153		catch {.ultradsm.key.msrc4_sc  configure -state disabled}
15154	}
15155}
15156
15157proc ultra_dsm_dialog {} {
15158	global ultra_dsm ultra_dsm_file ultra_dsm_type
15159
15160	toplev .ultradsm
15161	wm title .ultradsm "UltraVNC DSM Encryption Plugin"
15162
15163	global help_font
15164	set h 40
15165	if [small_height] {
15166		set h 22
15167	}
15168	scroll_text .ultradsm.f 85 $h
15169
15170	set msg {
15171    On Unix and MacOSX with the provided SSVNC vncviewer, you can connect to an
15172    UltraVNC server that is using one of its DSM encryption plugins: MSRC4, ARC4,
15173    AESV2, and SecureVNC. More info at: http://www.uvnc.com/features/encryption.html
15174
15175    IMPORTANT: The UltraVNC DSM MSRC4, ARC4, and AESV2 implementations contain
15176    unfixed errors that could allow an eavesdropper to recover the session
15177    key or traffic easily.  They often do not provide strong encryption, but
15178    only provide basic obscurity instead.  Do not use them with critical data.
15179    The newer SecureVNC Plugin does not suffer from these problems.
15180
15181    See the bottom of this help text for how to use symmetric encryption with
15182    Non-UltraVNC servers (for example, x11vnc 0.9.5 or later).  This mode does not
15183    suffer the shortcomings of the UltraVNC MSRC4, ARC4, and AESV2 implementations.
15184
15185    You will need to specify the corresponding UltraVNC encryption key (created
15186    by you using an UltraVNC server or viewer).  It is usually called 'rc4.key'
15187    (for MSRC4), 'arc4.key' (for ARC4), and 'aesv2.key' (for AESV2).  Specify the
15188    path to it or Browse for it.  Also, specify which type of plugin it is (or use
15189    'guess' to have it guess via the before mentioned filenames).
15190
15191    The choice "UVNC SC" enables a special workaround for use with UltraVNC Single
15192    Click and the MSRC4 plugin.  It may not be needed on recent SC (e.g. from
15193    ~2009 and later; select "MSRC4" for these newer ones.)
15194
15195    You can also specify pw=my-password instead of a keyfile.  Use single quotes
15196    pw='....' if the password contains shell meta-characters `!$&*(){}[]|;<>?
15197
15198    Use the literal string 'pw=VNCPASSWD' to have the VNC password that you
15199    entered into the 'VNC Password:' be used for the pw=...
15200
15201    SSL and SSH tunnels do not apply in this mode (any settings are ignored.)
15202
15203    Proxying works in this mode, as well as Reverse Connections (Listen)
15204
15205    The choice "SecureVNC" refers to the SecureVNC Plugin using 128 bit AES or
15206    ARC4 with 2048 bit RSA key exchange described here:
15207
15208          http://adamwalling.com/SecureVNC
15209
15210    Note in its default mode SecureVNC is *Vulnerable* to Man-In-The-Middle attacks
15211    (encryption but no server authentication) so do not use it with critical data.
15212    In SecureVNC mode you do not need to supply a 'Ultra DSM Keyfile'.  However,
15213    if you DO supply a keyfile filename (recommended) if that file does not exist
15214    you will be prompted if you want to save the UltraVNC server's RSA key in it.
15215    The key's MD5 checksum is displayed so that you can verify that the key is
15216    trusted.  One way to print out the SecureVNC public key MD5 checksum is:
15217
15218    openssl rsa -inform DER -outform DER -pubout -in ./Server_SecureVNC.pkey | dd bs=1 skip=24 | md5sum
15219
15220    Then on subsequent connections, if you continue to specify this filename, the
15221    SecureVNCPlugin server's RSA key will be checked against the file's contents
15222    and if they differ the connection will be dropped.
15223
15224    NOTE, However, if the SecureVNC keyfile ends in the string 'ClientAuth.pkey'
15225    then its contents are used for SecureVNC's normal Client Authentication dialog
15226    (you need to use Windows SecureVNCPlugin to generate this file on the server
15227    side, it is usually called "Viewer_ClientAuth.pkey", and then safely copy it
15228    to the viewer side.)  If you want to do BOTH Client Auth and server RSA key
15229    storing (recommended), have the keyfile end in 'ClientAuth.pkey.rsa'; that way
15230    the file will be used for storing the server RSA key and then the '.rsa' is
15231    trimmed off and the remainder used for the SecureVNC Client Auth data filename.
15232
15233    Note that despite its intentions, Client Authentication in the FIRST release of
15234    SecureVNC is still susceptible to Man-In-The-Middle attacks.  Even when that
15235    is fixed, SecureVNC Client Authentication is still susceptible to "spoofing"
15236    attacks where the viewer user may be tricked into revealing his VNC or MS-Logon
15237    password if his connection is intercepted.  It is recommended you verify and
15238    save the Server key (see above) in addition to using Client Authentication.
15239
15240    UltraVNC DSM encryption modes are currently experimental because unfortunately
15241    the UltraVNC DSM plugin also modifies the RFB protocol(!), and so the SSVNC
15242    vncviewer had to be modified to support it.  The tight, zlib, and some minor
15243    encodings currently do not work in this mode and are disabled.
15244
15245    Note that this mode also requires the utility tool named 'ultravnc_dsm_helper'
15246    that should be included in your SSVNC kit.
15247
15248    Select 'Non-Ultra DSM' to use symmetric encryption to a Non-UltraVNC server via
15249    a supported symmetric key cipher.  x11vnc supports symmetric encryption via,
15250    e.g., "x11vnc -enc aesv2:./my.key".  Extra ciphers are enabled for this mode
15251    (e.g. blowfish and 3des).  'UVNC SC' and SecureVNC do not apply in this mode.
15252
15253    Note for the Non-Ultra DSM case it will also work with any VNC Viewer
15254    (i.e. selected by Options -> Advanced -> Change VNC Viewer) not only the
15255    supplied SSVNC vncviewer.
15256
15257    For experts: You can also set the random salt size and initialization vector
15258    size in Salt,IV for example "8,16".  See the x11vnc and 'ultravnc_dsm_helper
15259    -help' documentation for more info on this.
15260}
15261
15262	.ultradsm.f.t insert end $msg
15263
15264	frame .ultradsm.path
15265	label .ultradsm.path.l -text "Ultra DSM Keyfile:"
15266	entry .ultradsm.path.e -width 40 -textvariable ultra_dsm_file
15267	button .ultradsm.path.b -text "Browse..." -command {set_ultra_dsm_file .ultradsm}
15268
15269	pack .ultradsm.path.l -side left
15270	pack .ultradsm.path.e -side left -expand 1 -fill x
15271	pack .ultradsm.path.b -side left
15272
15273	frame .ultradsm.key
15274	label .ultradsm.key.l -text "Type of Key:        "
15275	radiobutton .ultradsm.key.guess -pady 1 -anchor w -variable ultra_dsm_type -value guess \
15276		-text "Guess"
15277	radiobutton .ultradsm.key.arc4 -pady 1 -anchor w -variable ultra_dsm_type -value arc4 \
15278		-text "ARC4"
15279
15280	radiobutton .ultradsm.key.aesv2 -pady 1 -anchor w -variable ultra_dsm_type -value aesv2 \
15281		-text "AESV2"
15282
15283	radiobutton .ultradsm.key.msrc4 -pady 1 -anchor w -variable ultra_dsm_type -value msrc4 \
15284		-text "MSRC4"
15285
15286	radiobutton .ultradsm.key.msrc4_sc -pady 1 -anchor w -variable ultra_dsm_type -value msrc4_sc \
15287		-text "UVNC SC"
15288
15289	radiobutton .ultradsm.key.securevnc -pady 1 -anchor w -variable ultra_dsm_type -value securevnc \
15290		-text "SecureVNC"
15291
15292	pack .ultradsm.key.l -side left
15293	pack .ultradsm.key.guess -side left
15294	pack .ultradsm.key.arc4 -side left
15295	pack .ultradsm.key.aesv2 -side left
15296	pack .ultradsm.key.msrc4 -side left
15297	pack .ultradsm.key.msrc4_sc -side left
15298	pack .ultradsm.key.securevnc -side left
15299
15300	frame .ultradsm.nou
15301	checkbutton .ultradsm.nou.cb -text "Non-Ultra DSM" -variable ultra_dsm_noultra -command update_no_ultra_dsm
15302	radiobutton .ultradsm.nou.bf -pady 1 -anchor w -variable ultra_dsm_type -value blowfish \
15303		-text "Blowfish"
15304
15305	radiobutton .ultradsm.nou.des3 -pady 1 -anchor w -variable ultra_dsm_type -value 3des \
15306		-text "3DES"
15307
15308	radiobutton .ultradsm.nou.aes -pady 1 -anchor w -variable ultra_dsm_type -value "aes-cfb" \
15309		-text "AES-CFB"
15310
15311	radiobutton .ultradsm.nou.aes256 -pady 1 -anchor w -variable ultra_dsm_type -value "aes256" \
15312		-text "AES-256"
15313
15314	label .ultradsm.nou.l -text " Salt,IV"
15315	entry .ultradsm.nou.e -width 6 -textvariable ultra_dsm_salt
15316
15317	pack .ultradsm.nou.cb -side left
15318	pack .ultradsm.nou.bf -side left
15319	pack .ultradsm.nou.des3 -side left
15320	pack .ultradsm.nou.aes -side left
15321	pack .ultradsm.nou.aes256 -side left
15322	pack .ultradsm.nou.l -side left
15323	pack .ultradsm.nou.e -side left -expand 0
15324
15325	update_no_ultra_dsm
15326
15327	button .ultradsm.cancel -text "Cancel" -command {destroy .ultradsm; set ultra_dsm 0}
15328	bind .ultradsm <Escape> {destroy .ultradsm; set ultra_dsm 0}
15329	wm protocol .ultradsm WM_DELETE_WINDOW {destroy .ultradsm; set ultra_dsm 0}
15330	button .ultradsm.done -text "Done" -command {destroy .ultradsm; catch {raise .oa}}
15331	bind .ultradsm.path.e <Return> {destroy .ultradsm; catch {raise .oa}}
15332
15333	pack .ultradsm.f .ultradsm.path .ultradsm.key .ultradsm.nou .ultradsm.cancel .ultradsm.done -side top -fill x
15334
15335	center_win .ultradsm
15336	wm resizable .ultradsm 1 0
15337
15338	focus .ultradsm.path.e
15339}
15340
15341proc ssh_known_hosts_dialog {} {
15342	global ssh_known_hosts ssh_known_hosts_filename
15343
15344	toplev .sshknownhosts
15345	wm title .sshknownhosts "Private SSH KnownHosts file"
15346
15347	global help_font
15348	set h 31
15349	if [small_height] {
15350		set h 23
15351	}
15352	scroll_text .sshknownhosts.f 80 $h
15353
15354	set msg {
15355      Private SSH KnownHosts file:
15356
15357         On Unix in SSH mode, let the user specify a non-default
15358         ssh known_hosts file to be used only by the current profile.
15359         This is the UserKnownHostsFile ssh option and is described in the
15360         ssh_config(1) man page.  This is useful to avoid proxy 'localhost'
15361         SSH key collisions.
15362
15363         Normally one should simply let ssh use its default file
15364         ~/.ssh/known_hosts for tracking SSH keys.  The only problem with
15365         that happens when multiple SSVNC connections use localhost tunnel
15366         port redirections.  These make ssh connect to 'localhost' on some
15367         port (where the proxy is listening.)  Then the different keys
15368         from the multiple ssh servers collide when ssh saves them under
15369         'localhost' in ~/.ssh/known_hosts.
15370
15371         So if you are using a proxy with SSVNC or doing a "double SSH
15372         gateway" your ssh will connect to a proxy port on localhost, and you
15373         should set a private KnownHosts file for that connection profile.
15374         This is secure and avoids man-in-the-middle attack (as long as
15375         you actually verify the initial save of the SSH key!)
15376
15377         The default file location will be:
15378
15379                  ~/.vnc/ssh_known_hosts/profile-name.known
15380
15381         but you can choose any place you like.  It must of course be
15382         unique and not shared with another ssh connection otherwise they
15383         both may complain about the key for 'localhost' changing, etc.
15384}
15385
15386	.sshknownhosts.f.t insert end $msg
15387
15388	frame .sshknownhosts.path
15389	label .sshknownhosts.path.l -text "SSH KnownHosts file:"
15390	entry .sshknownhosts.path.e -width 40 -textvariable ssh_known_hosts_filename
15391	button .sshknownhosts.path.b -text "Browse..." -command {set_ssh_known_hosts_file .sshknownhosts}
15392
15393	pack .sshknownhosts.path.l -side left
15394	pack .sshknownhosts.path.e -side left -expand 1 -fill x
15395	pack .sshknownhosts.path.b -side left
15396
15397	button .sshknownhosts.cancel -text "Cancel" -command {destroy .sshknownhosts; set ssh_known_hosts 0}
15398	bind .sshknownhosts <Escape> {destroy .sshknownhosts; set ssh_known_hosts 0}
15399	wm protocol .sshknownhosts WM_DELETE_WINDOW {destroy .sshknownhosts; set ssh_known_hosts 0}
15400	button .sshknownhosts.done -text "Done" -command {destroy .sshknownhosts; catch {raise .oa}}
15401	bind .sshknownhosts.path.e <Return> {destroy .sshknownhosts; catch {raise .oa}}
15402
15403	pack .sshknownhosts.f .sshknownhosts.path .sshknownhosts.cancel .sshknownhosts.done -side top -fill x
15404
15405	center_win .sshknownhosts
15406	wm resizable .sshknownhosts 1 0
15407
15408	focus .sshknownhosts.path.e
15409}
15410
15411proc ssh_sec_dialog {} {
15412	global ssh_local_protection
15413
15414	toplev .sshsec
15415	wm title .sshsec "SSH Local Port Protections"
15416
15417	global help_font
15418	eval text .sshsec.t -width 80 -height 28 $help_font
15419
15420	apply_bg .sshsec.t
15421
15422	set msg {
15423    See the discussion of "Untrusted Local Users" in the main 'Help'
15424    panel for info about users who are able to log into the workstation
15425    you run SSVNC on and might try to use your encrypted tunnel to gain
15426    access to the remote VNC machine.
15427
15428    On Unix, for SSH tunnels we have an LD_PRELOAD hack (lim_accept.so)
15429    that will limit ssh from accepting any local redirection connections
15430    after the first one or after 35 seconds, whichever comes first.
15431    The first SSH port redirection connection is intended to be the one
15432    that tunnels your VNC Viewer to reach the remote server.
15433
15434    You can adjust these defaults LIM_ACCEPT=1 LIM_ACCEPT_TIME=35 by
15435    setting those env. vars. to different values.
15436
15437    Note that there is still a window of a few seconds the Untrusted
15438    Local User can try to connect before your VNC Viewer does.  So this
15439    method is far from perfect.  But once your VNC session is established,
15440    he should be blocked out.  Test to make sure blocking is taking place.
15441
15442    Do not use this option if you are doing SSH Service redirections
15443    'Additional Port Redirections (via SSH)' that redirect a local port
15444    to the remote server via ssh -L.
15445
15446    Note that if the shared object "lim_accept.so" cannot be found,
15447    this option has no effect.  Watch the output in the terminal for
15448    the "SSVNC_LIM_ACCEPT_PRELOAD" setting.
15449}
15450	.sshsec.t insert end $msg
15451
15452	button .sshsec.cancel -text "Cancel" -command {set ssh_local_protection 0; destroy .sshsec}
15453	bind .sshsec <Escape> {set ssh_local_protection 0; destroy .sshsec}
15454	wm protocol .sshsec WM_DELETE_WINDOW {set ssh_local_protection 0; destroy .sshsec}
15455	button .sshsec.done -text "Done" -command {destroy .sshsec}
15456
15457	pack .sshsec.t .sshsec.cancel .sshsec.done -side top -fill x
15458
15459	center_win .sshsec
15460	wm resizable .sshsec 1 0
15461}
15462
15463proc multilisten_dialog {} {
15464	global multiple_listen
15465
15466	toplev .multil
15467	wm title .multil "Multiple LISTEN Connections"
15468
15469	global help_font
15470	set h 36
15471	if [small_height] {
15472		set h 30
15473	}
15474	eval text .multil.t -width 84 -height $h $help_font
15475
15476	apply_bg .multil.t
15477
15478	set msg {
15479    Set this option to allow SSVNC (when in LISTEN / Reverse connections
15480    mode) to allow multiple VNC servers to connect at the same time and
15481    so display each of their desktops on your screen at the same time.
15482
15483    This option only applies on Unix or MaOSX when using the supplied
15484    SSVNC vncviewer.  If you specify your own VNC Viewer it has no effect.
15485
15486    On Windows (only the stock TightVNC viewer is provided) it has no effect
15487    because the Windows SSVNC can ONLY do "Multiple LISTEN Connections".
15488    Similarly on MacOSX if the COTVNC viewer is used there is no effect.
15489
15490    Rationale:  To play it safe, the Unix vncviewer provided by SSVNC
15491    (ssvncviewer) only allows one LISTEN reverse connection at a time.
15492    This is to prohibit malicious people on the network from depositing
15493    as many desktops on your screen as he likes, even if you are already
15494    connected to VNC server you desire.
15495
15496    For example, perhaps the malicious user could trick you into typing
15497    a password into the desktop he displays on your screen.
15498
15499    This protection is not perfect, because the malicious user could
15500    try to reverse connect to you before the correct VNC server reverse
15501    connects to you.  This is even more of a problem if you keep your
15502    SSVNC viewer in LISTEN mode but unconnected for long periods of time.
15503    Pay careful attention in this case if you are to supplying sensitive
15504    information to the remote desktop.
15505
15506    Enable 'Multiple LISTEN Connections' if you want to disable the default
15507    protection in the Unix SSVNC vncviewer; i.e. allow multiple reverse
15508    connections simultaneously (all vnc viewers we know of do this by default)
15509
15510    For more control, do not select 'Multiple LISTEN Connections', but
15511    rather set the env. var SSVNC_MULTIPLE_LISTEN=MAX:n to limit the number
15512    of simultaneous reverse connections to "n"
15513}
15514	.multil.t insert end $msg
15515
15516	button .multil.cancel -text "Cancel" -command {set multiple_listen 0; destroy .multil}
15517	bind .multil <Escape> {set multiple_listen 0; destroy .multil}
15518	wm protocol .multil WM_DELETE_WINDOW {set multiple_listen 0; destroy .multil}
15519	button .multil.done -text "Done" -command {destroy .multil}
15520
15521	pack .multil.t .multil.cancel .multil.done -side top -fill x
15522
15523	center_win .multil
15524	wm resizable .multil 1 0
15525}
15526
15527proc use_grab_dialog {} {
15528	global usg_grab
15529
15530	toplev .usegrb
15531	wm title .usegrb "Use XGrabServer (for fullscreen)"
15532
15533	global help_font
15534	eval text .usegrb.t -width 85 -height 29 $help_font
15535
15536	apply_bg .usegrb.t
15537
15538	set msg {
15539    On Unix, some Window managers and some Desktops make it difficult for the
15540    SSVNC Unix VNC viewer to go into full screen mode (F9) and/or return.
15541
15542    Sometimes one can go into full screen mode, but then your keystrokes or
15543    Mouse actions do not get through.  This can leave you trapped because you
15544    cannot inject input (F9 again) to get out of full screen mode.  (Tip:
15545    press Ctrl-Alt-F2 for a console login shell; then kill your vncviewer
15546    process, e.g. pkill vncviewer; then Alt-F7 to get back to your desktop)
15547
15548    We have seen this in some very old Window managers (e.g. fvwm2 circa
15549    1998) and some very new Desktops (e.g. GNOME circa 2008).  We try
15550    to work around the problem on recent desktops by using the NEW_WM
15551    interface, but if you use Fullscreen, you may need to use this option.
15552
15553    The default for the SSVNC Unix VNC viewer is '-grabkbd' mode where it will
15554    try to exclusively grab the keyboard.  This often works correctly.
15555
15556    However if Fullscreen is not working properly, try setting this
15557    'Use XGrabServer' option to enable '-graball' mode where it tries to grab
15558    the entire X server.  This usually works, but can be a bit flakey.
15559
15560    Sometimes toggling F9 a few times gets lets the vncviewer fill the whole
15561    screen.  Sometimes tapping F9 very quickly gets it to snap in.  If GNOME
15562    (or whatever desktop) is still showing its taskbars, it is recommended
15563    you toggle F9 until it isn't. Otherwise, it is not clear who gets the input.
15564
15565    Best of luck.
15566}
15567	.usegrb.t insert end $msg
15568
15569	button .usegrb.cancel -text "Cancel" -command {set use_grab 0; destroy .usegrb}
15570	bind .usegrb <Escape> {set use_grab 0; destroy .usegrb}
15571	wm protocol .usegrb WM_DELETE_WINDOW {set use_grab 0; destroy .usegrb}
15572	button .usegrb.done -text "Done" -command {destroy .usegrb}
15573
15574	pack .usegrb.t .usegrb.cancel .usegrb.done -side top -fill x
15575
15576	center_win .usegrb
15577	wm resizable .usegrb 1 0
15578}
15579
15580
15581proc find_netcat {} {
15582	global is_windows
15583
15584	set nc ""
15585
15586	if {! $is_windows} {
15587		set nc [in_path "netcat"]
15588		if {$nc == ""} {
15589			set nc [in_path "nc"]
15590		}
15591	} else {
15592		set try "netcat.exe"
15593		if [file exists $try] {
15594			set nc $try
15595		}
15596	}
15597	return $nc
15598}
15599
15600proc pk_expand {cmd host} {
15601	global tcl_platform
15602	set secs [clock seconds]
15603	set msecs [clock clicks -milliseconds]
15604	set user $tcl_platform(user)
15605	if [regexp {%IP} $cmd] {
15606		set ip [guess_ip]
15607		if {$ip == ""} {
15608			set ip "unknown"
15609		}
15610		regsub -all {%IP} $cmd $ip cmd
15611	}
15612	if [regexp {%NAT} $cmd] {
15613		set ip [guess_nat_ip]
15614		regsub -all {%NAT} $cmd $ip cmd
15615	}
15616	regsub -all {%HOST} $cmd $host cmd
15617	regsub -all {%USER} $cmd $user cmd
15618	regsub -all {%SECS} $cmd $secs cmd
15619	regsub -all {%MSECS} $cmd $msecs cmd
15620
15621	return $cmd
15622}
15623
15624proc backtick_expand {str} {
15625	set str0 $str
15626	set collect ""
15627	set count 0
15628	while {[regexp {^(.*)`([^`]+)`(.*)$} $str mv p1 cmd p2]} {
15629		set out [eval exec $cmd]
15630		set str "$p1$out$p2"
15631		incr count
15632		if {$count > 10}  {
15633			break
15634		}
15635	}
15636	return $str
15637}
15638
15639proc read_from_pad {file} {
15640	set fh ""
15641	if {[catch {set fh [open $file "r"]}] != 0} {
15642		return "FAIL"
15643	}
15644
15645	set accum ""
15646	set match ""
15647	while {[gets $fh line] > -1} {
15648		if [regexp {^[ \t]*#} $line] {
15649			append accum "$line\n"
15650		} elseif [regexp {^[ \t]*$} $line] {
15651			append accum "$line\n"
15652		} elseif {$match == ""} {
15653			set match $line
15654			append accum "# $line\n"
15655		} else {
15656			append accum "$line\n"
15657		}
15658	}
15659
15660	close $fh
15661
15662	if {$match == ""} {
15663		return "FAIL"
15664	}
15665
15666	if {[catch {set fh [open $file "w"]}] != 0} {
15667		return "FAIL"
15668	}
15669
15670	puts -nonewline $fh $accum
15671
15672	return $match
15673}
15674
15675proc do_port_knock {hp mode} {
15676	global use_port_knocking port_knocking_list
15677	global is_windows
15678
15679	if {! $use_port_knocking} {
15680		return 1
15681	}
15682	if {$port_knocking_list == ""} {
15683		return 1
15684	}
15685	set list $port_knocking_list
15686
15687	if {$mode == "finish"} {
15688		if {! [regexp {FINISH} $list]} {
15689			mesg "PortKnock(finish): done"
15690			return 1
15691		} else {
15692			regsub {^.*FINISH} $list "" list
15693		}
15694	} elseif {$mode == "start"} {
15695		if {[regexp {FINISH} $list]} {
15696			regsub {FINISH.*$} $list "" list
15697		}
15698	}
15699
15700	set default_delay 150
15701
15702	set host [string trim $hp]
15703	# XXX host_part
15704	regsub {^vnc://} $host "" host
15705	regsub {^.*@} $host "" host
15706	regsub {:[0-9][0-9]*$} $host "" host
15707	set host0 [string trim $host]
15708
15709	if {$host0 == ""} {
15710		bell
15711		mesg "PortKnock: No host: $hp"
15712		return 0
15713	}
15714
15715	set m ""
15716
15717	if [regexp {PAD=([^\n]+)} $list mv padfile] {
15718		set tlist [read_from_pad $padfile]
15719		set tlist [string trim $tlist]
15720		if {$tlist == "" || $tlist == "FAIL"} {
15721			raise .
15722			tk_messageBox -type ok -icon error \
15723				-message "Failed to read entry from $padfile" \
15724				-title "Error: Padfile $padfile"
15725			return 0
15726		}
15727		regsub -all {PAD=([^\n]+)} $list $tlist list
15728	}
15729
15730	set spl ",\n\r"
15731	if [regexp {CMD=}   $list] {set spl "\n\r"}
15732	if [regexp {CMDX=}  $list] {set spl "\n\r"}
15733	if [regexp {SEND=}  $list] {set spl "\n\r"}
15734	if [regexp {SENDX=} $list] {set spl "\n\r"}
15735
15736	set i 0
15737	set pi 0
15738
15739	foreach line [split $list $spl] {
15740		set line [string trim $line]
15741		set line0 $line
15742
15743		if {$line == ""} {
15744			continue
15745		}
15746		if [regexp {^#} $line] {
15747			continue
15748		}
15749
15750		if [regexp {^sleep[ \t][ \t]*([0-9][0-9]*)} $line mv sl] {
15751			set m "PortKnock: sleep $sl"
15752			mesg $m
15753			after $sl
15754			continue
15755		}
15756		if [regexp {^delay[ \t][ \t]*([0-9][0-9]*)} $line mv sl] {
15757			set m "PortKnock: delay=$sl"
15758			mesg $m
15759			set default_delay $sl
15760			continue
15761		}
15762
15763		if [regexp {^CMD=(.*)} $line mv cmd] {
15764			set m "PortKnock: CMD: $cmd"
15765			mesg $m
15766			eval exec $cmd
15767			continue
15768		}
15769		if [regexp {^CMDX=(.*)} $line mv cmd] {
15770			set cmd [pk_expand $cmd $host0]
15771			set m "PortKnock: CMDX: $cmd"
15772			mesg $m
15773			eval exec $cmd
15774			continue
15775		}
15776
15777		if [regexp {`} $line] {
15778			#set line [backtick_expand $line]
15779		}
15780
15781		set snd ""
15782		if [regexp {^(.*)SEND=(.*)$} $line mv line snd]  {
15783			set line [string trim $line]
15784			set snd [string trim $snd]
15785			regsub -all {%NEWLINE} $snd "\n" snd
15786		} elseif [regexp {^(.*)SENDX=(.*)$} $line mv line snd]  {
15787			set line [string trim $line]
15788			set snd [string trim $snd]
15789			set snd [pk_expand $snd $host0]
15790			regsub -all {%NEWLINE} $snd "\n" snd
15791		}
15792
15793		set udp 0
15794		if [regexp -nocase {[/:]udp} $line] {
15795			set udp 1
15796			regsub -all -nocase {[/:]udp} $line " " line
15797			set line [string trim $line]
15798		}
15799		regsub -all -nocase {[/:]tcp} $line " " line
15800		set line [string trim $line]
15801
15802		set delay 0
15803		if [regexp {^(.*)[ \t][ \t]*([0-9][0-9]*)$} $line mv first delay] {
15804			set line [string trim $first]
15805		}
15806
15807		if {[regexp {^(.*):([0-9][0-9]*)$} $line mv host port]} {
15808			;
15809		} else {
15810			set host $host0
15811			set port $line
15812		}
15813		set host [string trim $host]
15814		set port [string trim $port]
15815
15816		if {$host == ""} {
15817			set host $host0
15818		}
15819
15820		if {$port == ""} {
15821			bell
15822			set m "PortKnock: No port found: \"$line0\""
15823			mesg $m
15824			return 0
15825		}
15826		if {! [regexp {^[0-9][0-9]*$} $port]} {
15827			bell
15828			set m "PortKnock: Invalid port: \"$port\""
15829			mesg $m
15830			return 0
15831		}
15832		regsub {,.*$} $host "" host
15833		if {[regexp {[ \t]} $host]} {
15834			bell
15835			set m "PortKnock: Invalid host: \"$host\""
15836			mesg $m
15837			return 0
15838		}
15839		if {! [regexp {^[-A-z0-9_.][-A-z0-9_.]*$} $host]} {
15840			bell
15841			set m "PortKnock: Invalid host: \"$host\""
15842			mesg $m
15843			return 0
15844		}
15845
15846		set nc ""
15847		if {$udp || $snd != ""} {
15848			set nc [find_netcat]
15849			if {$nc == ""} {
15850				bell
15851				set m "PortKnock: UDP: netcat(1) not found"
15852				mesg $m
15853				after 1000
15854				continue
15855			}
15856		}
15857
15858		if {$snd != ""} {
15859			global env
15860			set pfile "payload$pi.txt"
15861			if {! $is_windows} {
15862				set pfile "$env(SSVNC_HOME)/.$pfile"
15863			}
15864			set pfiles($pi) $pfile
15865			incr pi
15866			set fh [open $pfile "w"]
15867			puts -nonewline $fh "$snd"
15868			close $fh
15869
15870			set m "PortKnock: SEND: $host $port"
15871			mesg $m
15872			if {$is_windows} {
15873				if {$udp} {
15874					catch {exec $nc -d -u -w 1 "$host" "$port" < $pfile &}
15875				} else {
15876					catch {exec $nc -d    -w 1 "$host" "$port" < $pfile &}
15877				}
15878			} else {
15879				if {$udp} {
15880					catch {exec $nc    -u -w 1 "$host" "$port" < $pfile &}
15881				} else {
15882					catch {exec $nc       -w 1 "$host" "$port" < $pfile &}
15883				}
15884			}
15885			catch {after 50; file delete $pfile}
15886
15887		} elseif {$udp} {
15888			set m "PortKnock: UDP: $host $port"
15889			mesg $m
15890			if {! $is_windows} {
15891				catch {exec echo a | $nc -u -w 1 "$host" "$port" &}
15892			} else {
15893				set fh [open "nc_in.txt" "w"]
15894				puts $fh "a"
15895				close $fh
15896				catch {exec $nc -d -u -w 1 "$host" "$port" < "nc_in.txt" &}
15897			}
15898		} else {
15899			set m "PortKnock: TCP: $host $port"
15900			mesg $m
15901			set s ""
15902			set emess ""
15903			set rc [catch {set s [socket -async $host $port]} emess]
15904			if {$rc != 0} {
15905				raise .
15906				tk_messageBox -type ok -icon error -message $emess -title "Error: socket -async $host $port"
15907			}
15908			set sockets($i) $s
15909			# seems we have to close it immediately to avoid multiple SYN's.
15910			# does not help on Win9x.
15911			catch {after 30; close $s};
15912			incr i
15913		}
15914
15915		if {$delay == 0} {
15916			if {$default_delay > 0} {
15917				after $default_delay
15918			}
15919		} elseif {$delay > 0} {
15920			after $delay
15921		}
15922	}
15923
15924	if {0} {
15925		for {set j 0} {$j < $i} {incr j} {
15926			set $s $sockets($j)
15927			if {$s != ""} {
15928				catch {close $s}
15929			}
15930		}
15931	}
15932	for {set j 0} {$j < $pi} {incr j} {
15933		set f $pfiles($j)
15934		if {$f != ""} {
15935			if [file exists $f] {
15936				after 100
15937			}
15938			catch {file delete $f}
15939		}
15940	}
15941	if {$is_windows} {
15942		catch {file delete "nc_in.txt"}
15943	}
15944	if {$m != ""} {
15945		set m "$m,"
15946	}
15947	if {$mode == "finish"} {
15948		mesg "PortKnock(finish): done"
15949	} else {
15950		mesg "PortKnock: done"
15951	}
15952	return 1
15953}
15954
15955proc port_knocking_dialog {} {
15956	toplev .pk
15957	wm title .pk "Port Knocking"
15958	global use_port_knocking port_knocking_list
15959
15960	global help_font
15961
15962	global uname
15963
15964	set h 35
15965	if [small_height] {
15966		set h 22
15967	} elseif {$uname == "Darwin"} {
15968		set h 25
15969	}
15970	scroll_text .pk.f 85 $h
15971
15972	set msg {
15973 Description:
15974
15975    Port Knocking is where a network connection to a service is not provided
15976    to just any client, but rather only to those that immediately prior to
15977    connecting send a more or less secret pattern of connections to other
15978    ports on the firewall.
15979
15980    Somewhat like "knocking" on the door with the correct sequence before it
15981    being opened (but not necessarily letting you in yet).  It is also possible
15982    to have a single encrypted packet (e.g. UDP) payload communicate with the
15983    firewall instead of knocking on a sequence of ports.
15984
15985    Only after the correct sequence of ports is observed by the firewall does
15986    it allow the IP address of the client to attempt to connect to the service.
15987
15988    So, for example, instead of allowing any host on the internet to connect
15989    to your SSH service and then try to login with a username and password, the
15990    client first must "tickle" your firewall with the correct sequence of ports.
15991    Only then will it be allowed to connect to your SSH service at all.
15992
15993    This does not replace the authentication and security of SSH, it merely
15994    puts another layer of protection around it. E.g., suppose an exploit for
15995    SSH was discovered, you would most likely have more time to fix/patch
15996    the problem than if any client could directly connect to your SSH server.
15997
15998    For more information http://www.portknocking.org/ and
15999    http://www.linuxjournal.com/article/6811
16000
16001
16002 Tip:
16003
16004    If you just want to use the Port Knocking for an SSH shell and not
16005    for a VNC tunnel, then specify something like "user@hostname cmd=SHELL"
16006    (or "user@hostname cmd=PUTTY" on Windows) in the VNC Host:Display entry box
16007    on the main panel.  This will do everything short of starting the viewer.
16008    A shortcut for this is Ctrl-S as long as user@hostname is present.
16009
16010
16011 Specifying the Knocks:
16012
16013    In the text area below "Supply port knocking pattern" you put in the pattern
16014    of "knocks" needed for this connection.  You can separate the knocks by
16015    commas or put them one per line.
16016
16017    Each "knock" is of this form:
16018
16019           [host:]port[/udp] [delay]
16020
16021    In the simplest form just a numerical port, e.g. 5433, is supplied.
16022    Items inside [...] are optional and described below.
16023
16024    The packet is sent to the same host that the VNC (or SSH) connection will
16025    be made to.  If you want it to go to a different host or IP use the [host:]
16026    prefix.  It can be either a hostname or numerical IP.
16027
16028    A TCP packet is sent by default.
16029
16030    If you need to send a UDP packet, the netcat (aka "nc") program must be
16031    installed on Unix (tcl/tk does not support udp connections).  Indicate this
16032    with "/udp" following the port number (you can also use "/tcp", but since
16033    it is the default it is not necessary).  (You can also use ":udp" to match
16034    the knockd syntax).  See the example below.  For convenience a Windows netcat
16035    binary is supplied.
16036
16037    The last field, [delay], is an optional number of milliseconds to delay
16038    before continuing on to the next knock.
16039
16040
16041 Examples:
16042
16043           5433, 12321, 1661
16044
16045           fw.example.com:5433, 12321/udp 3000, 1661 2000
16046
16047           fw.example.com:5433
16048           12321/udp 3000
16049           1661 2000
16050
16051    Note how the first two examples separate their knocks via commas ",".
16052    The 3rd example is equivalent to the 2nd and splits them up by new lines.
16053
16054    Note for each knock any second number (e.g. the "2000" in "1661 2000") is
16055    a DELAY in milliseconds, not a port number.  If you had a comma separating
16056    them: "1661, 2000" that would mean two separate knocks: one to port 1661
16057    followed by one to 2000 (with basically no delay between them).
16058
16059    In examples 2 and 3, "fw.example.com" represents some machine other than
16060    the VNC/SSH host.  By default, the VNC/SSH host is the one the packet is
16061    sent to.
16062
16063    If one of the items is the string "FINISH", then the part before it is
16064    used prior to connecting and the part after is used once the connection
16065    is finished.  This can be used, say, to close the firewall port.  Example:
16066
16067           5433, 12321, FINISH, 7659, 2314
16068
16069    (or one can split them up via lines as above.)
16070
16071
16072 Advanced port knock actions:
16073
16074    If the string in the text field contains anywhere the strings "CMD=", "CMDX=",
16075    or "SEND=", then splitting on commas is not done: it is only split on lines.
16076
16077    Then, if a line begins CMD=... the string after the = is run as an
16078    external command.  The command could be anything you want, e.g. it could
16079    be a port-knocking client that does the knocking, perhaps encrypting the
16080    "knocks" pattern somehow or using a Single Packet Authorization method such
16081    as http://www.cipherdyne.com/fwknop/
16082
16083    Extra quotes (sometimes "'foo bar'") may be needed to preserve spaces in
16084    command line arguments because the tcl/tk eval(n) command is used.  You
16085    can also use {...} for quoting strings with spaces.
16086
16087    If a line begins CMDX=... then before the command is run the following
16088    tokens are expanded to strings:
16089
16090      %IP       Current machine's IP address (NAT may make this not useful).
16091      %NAT      Try to get effective IP by contacting http://www.whatismyip.com
16092      %HOST     The remote host of the connection.
16093      %USER     The current user.
16094      %SECS     The current time in seconds (platform dependent).
16095      %MSECS    Platform dependent time having at least millisecond granularity.
16096
16097   Lines not matching CMD= or CMDX= are treated as normal port knocks but with
16098   one exception.  If a line ends in SEND=... (i.e. after the [host:]port,
16099   etc., part) then the string after the = is sent as a payload for the tcp
16100   or udp connection to [host:]port.  netcat is used for these SEND cases
16101   (and must be available on Unix).  If newlines (\n) are needed in the
16102   SEND string, use %NEWLINE.  Sending binary data is not yet supported;
16103   use CMD= with your own program.
16104
16105
16106 Advanced Examples:
16107
16108      CMD=port_knock_client -password wombat33
16109      CMDX=port_knock_client -password wombat33 -host %HOST -src %NAT
16110
16111      fw.example.com:5433/udp SEND=ASDLFKSJDF
16112
16113
16114 More tricks:
16115
16116      To temporarily "comment out" a knock, insert a leading "#" character.
16117
16118      Use "sleep N" to insert a raw sleep for N milliseconds (e.g. between
16119      CMD=... items or at the very end of the knocks to wait).
16120
16121      If a knock entry matches "delay N" the default delay is set to
16122      N milliseconds (it is 150 initially).
16123
16124
16125 One Time Pads:
16126
16127      If the text contains a (presumably single) line of the form:
16128
16129           PAD=/path/to/a/one/time/pad/file
16130
16131      then that file is opened and the first non-blank line not beginning
16132      with "#" is used as the knock pattern.  The pad file is rewritten
16133      with that line starting with a "#" (so it will be skipped next time).
16134
16135      The PAD=... string is replaced with the read-in knock pattern line.
16136      So, if needed, one can preface the PAD=... with "delay N" to set the
16137      default delay, and one can also put a "sleep N" after the PAD=...
16138      line to indicate a final sleep.  One can also surround the PAD=
16139      line with other knock and CMD= CMDX= lines, but that usage sounds
16140      a bit rare.  Example:
16141
16142           delay 1000
16143           PAD=C:\My Pads\work-pad1.txt
16144           sleep 4000
16145
16146
16147 Port knock only:
16148
16149      If, in the 'VNC Host:Display' entry, you use "user@hostname cmd=KNOCK"
16150      then only the port-knocking is performed.  A shortcut for this is
16151      Ctrl-P as long as hostname is present in the entry box.  If it
16152      matches cmd=KNOCKF, i.e. an extra "F", then the port-knocking
16153      "FINISH" sequence is sent, if any.  A shortcut for this Shift-Ctrl-P
16154      as long as hostname is present.
16155}
16156	.pk.f.t insert end $msg
16157
16158	label .pk.info -text "Supply port knocking pattern:" -anchor w -relief ridge
16159
16160	eval text .pk.rule -width 80 -height 5 $help_font
16161	.pk.rule insert end $port_knocking_list
16162
16163	button .pk.cancel -text "Cancel" -command {set use_port_knocking 0; destroy .pk}
16164	bind .pk <Escape> {set use_port_knocking 0; destroy .pk}
16165	wm protocol .pk WM_DELETE_WINDOW {set use_port_knocking 0; destroy .pk}
16166	button .pk.done -text "Done" -command {if {$use_port_knocking} {set port_knocking_list [.pk.rule get 1.0 end]}; destroy .pk}
16167
16168	pack .pk.done .pk.cancel .pk.rule .pk.info -side bottom -fill x
16169	pack .pk.f -side top -fill both -expand 1
16170
16171	center_win .pk
16172}
16173
16174proc choose_desktop_dialog {} {
16175	toplev .sd
16176	wm title .sd "Desktop Type"
16177	global ts_desktop_type choose_desktop
16178
16179	global ts_desktop_type_def
16180	set def "kde"
16181	if {$ts_desktop_type_def != ""} {
16182		set def $ts_desktop_type_def
16183	}
16184
16185	if {$ts_desktop_type == ""} {
16186		set ts_desktop_type $def
16187	}
16188
16189	label .sd.l1 -anchor w -text "Select the type of remote Desktop"
16190	label .sd.l2 -anchor w -text "for your session (default: $def)"
16191
16192	radiobutton .sd.b1 -anchor w -variable ts_desktop_type -value kde      -text kde
16193	radiobutton .sd.b2 -anchor w -variable ts_desktop_type -value gnome    -text gnome
16194	radiobutton .sd.b3 -anchor w -variable ts_desktop_type -value Xsession -text cde
16195	radiobutton .sd.b4 -anchor w -variable ts_desktop_type -value mwm      -text mwm
16196	radiobutton .sd.b5 -anchor w -variable ts_desktop_type -value wmaker   -text wmaker
16197	radiobutton .sd.b6 -anchor w -variable ts_desktop_type -value xfce     -text xfce
16198	radiobutton .sd.b7 -anchor w -variable ts_desktop_type -value enlightenment   -text enlightenment
16199	radiobutton .sd.b8 -anchor w -variable ts_desktop_type -value twm      -text twm
16200	radiobutton .sd.b9 -anchor w -variable ts_desktop_type -value failsafe -text failsafe
16201
16202	button .sd.cancel -text "Cancel" -command {destroy .sd; set choose_desktop 0; set ts_desktop_type ""}
16203	bind .sd <Escape> {destroy .sd; set choose_desktop 0; set ts_desktop_type ""}
16204	wm protocol .sd WM_DELETE_WINDOW {destroy .sd; set choose_desktop 0; set ts_desktop_type ""}
16205	button .sd.done -text "Done" -command {destroy .sd}
16206
16207	pack .sd.l1 .sd.l2 .sd.b1 .sd.b2 .sd.b3 .sd.b4 .sd.b5 .sd.b6 .sd.b7 .sd.b8 .sd.b9 .sd.cancel .sd.done -side top -fill x
16208
16209	center_win .sd
16210}
16211
16212proc choose_size_dialog {} {
16213	toplev .sz
16214	wm title .sz "Desktop Size"
16215	global ts_desktop_size ts_desktop_depth choose_desktop_geom
16216
16217	set def1 "1280x1024"
16218	set def2 "16"
16219
16220	global ts_desktop_size_def ts_desktop_depth_def
16221	if {$ts_desktop_size_def != ""} {
16222		set def1 $ts_desktop_size_def
16223	}
16224	if {$ts_desktop_depth_def != ""} {
16225		set def2 $ts_desktop_depth_def
16226	}
16227
16228	if {$ts_desktop_size == ""} {
16229		set ts_desktop_size $def1
16230	}
16231	if {$ts_desktop_depth == ""} {
16232		set ts_desktop_depth $def2
16233	}
16234
16235	label .sz.l1 -anchor w -text "Select the Size and Color depth"
16236	label .sz.l2 -anchor w -text "for your Desktop session."
16237	label .sz.l3 -anchor w -text "Default: $def1 and $def2 bits/pixel."
16238
16239	label .sz.g0 -anchor w -text "Width x Height:" -relief groove
16240
16241	radiobutton .sz.g1 -anchor w -variable ts_desktop_size -value "640x480"   -text "    640x480"
16242	radiobutton .sz.g2 -anchor w -variable ts_desktop_size -value "800x600"   -text "    800x600"
16243	radiobutton .sz.g3 -anchor w -variable ts_desktop_size -value "1024x768"  -text "  1024x768"
16244	radiobutton .sz.g4 -anchor w -variable ts_desktop_size -value "1280x1024" -text "1280x1024"
16245	radiobutton .sz.g5 -anchor w -variable ts_desktop_size -value "1400x1050" -text "1400x1050"
16246	radiobutton .sz.g6 -anchor w -variable ts_desktop_size -value "1600x1200" -text "1600x1200"
16247	radiobutton .sz.g7 -anchor w -variable ts_desktop_size -value "1920x1200" -text "1920x1200"
16248
16249	frame .sz.c
16250	label .sz.c.l -anchor w -text "Custom:"
16251	entry .sz.c.e -width 10 -textvariable ts_desktop_size
16252	pack .sz.c.l -side left
16253	pack .sz.c.e -side left -expand 1 -fill x
16254	bind .sz.c.e <Return> {destroy .sz}
16255
16256	label .sz.d0 -anchor w -text "Color Depth:" -relief groove
16257
16258	radiobutton .sz.d1 -anchor w -variable ts_desktop_depth -value "8" -text  "  8 bits/pixel"
16259	radiobutton .sz.d2 -anchor w -variable ts_desktop_depth -value "16" -text "16 bits/pixel"
16260	radiobutton .sz.d3 -anchor w -variable ts_desktop_depth -value "24" -text "24 bits/pixel"
16261
16262	button .sz.cancel -text "Cancel" -command {destroy .sz; set choose_desktop_geom 0; set ts_desktop_size ""; set ts_desktop_depth ""}
16263	bind .sz <Escape> {destroy .sz; set choose_desktop_geom 0; set ts_desktop_size ""; set ts_desktop_depth ""}
16264	wm protocol .sz WM_DELETE_WINDOW {destroy .sz; set choose_desktop_geom 0; set ts_desktop_size ""; set ts_desktop_depth ""}
16265	button .sz.done -text "Done" -command {destroy .sz}
16266
16267	pack .sz.l1 .sz.l2 .sz.l3 \
16268		.sz.g0 .sz.g1 .sz.g2 .sz.g3 .sz.g4 .sz.g5 .sz.g6 .sz.g7 \
16269		.sz.c \
16270		.sz.d0 .sz.d1 .sz.d2 .sz.d3 \
16271		.sz.cancel .sz.done -side top -fill x
16272
16273	center_win .sz
16274	focus .sz.c.e
16275}
16276
16277proc choose_xserver_dialog {} {
16278	toplev .st
16279	wm title .st "X Server Type"
16280	global ts_xserver_type choose_xserver
16281
16282	set def "Xvfb"
16283	global ts_xserver_type_def
16284	if {$ts_xserver_type_def != ""} {
16285		set def $ts_xserver_type_def
16286	}
16287
16288	if {$ts_xserver_type == ""} {
16289		set ts_xserver_type $def
16290	}
16291
16292	label .st.l1 -anchor w -text "Select the type of remote X server"
16293	label .st.l2 -anchor w -text "for your session (default: $def)"
16294
16295	radiobutton .st.b1 -anchor w -variable ts_xserver_type -value Xvfb -text "Xvfb"
16296
16297	radiobutton .st.b2 -anchor w -variable ts_xserver_type -value Xdummy -text "Xdummy"
16298
16299	radiobutton .st.b3 -anchor w -variable ts_xserver_type -value Xvnc -text "Xvnc"
16300
16301	radiobutton .st.b4 -anchor w -variable ts_xserver_type -value Xvnc.redirect -text "Xvnc.redirect"
16302
16303	button .st.cancel -text "Cancel" -command {destroy .st; set choose_xserver 0; set ts_xserver_type ""}
16304	bind .st <Escape> {destroy .st; set choose_xserver 0; set ts_xserver_type ""}
16305	wm protocol .st WM_DELETE_WINDOW {destroy .st; set choose_xserver 0; set ts_xserver_type ""}
16306	button .st.done -text "Done" -command {destroy .st}
16307
16308	pack .st.l1 .st.l2 .st.b1 .st.b2 .st.b3 .st.b4 .st.cancel .st.done -side top -fill x
16309
16310	center_win .st
16311}
16312
16313proc set_ts_options {} {
16314	global use_cups use_sound use_smbmnt
16315	global change_vncviewer choose_xserver
16316	global ts_only is_windows
16317	global darwin_cotvnc use_x11_macosx uname
16318	if {! $ts_only} {
16319		return
16320	}
16321	catch {destroy .o}
16322	toplev .ot
16323	wm title .ot "Options"
16324
16325	set i 1
16326
16327	checkbutton .ot.b$i -anchor w -variable choose_desktop -text \
16328		"Desktop Type" \
16329		-command {if {$choose_desktop} {choose_desktop_dialog}}
16330	incr i
16331
16332	checkbutton .ot.b$i -anchor w -variable choose_desktop_geom -text \
16333		"Desktop Size" \
16334		-command {if {$choose_desktop_geom} {choose_size_dialog}}
16335	incr i
16336
16337	checkbutton .ot.b$i -anchor w -variable choose_xserver -text \
16338		"X Server Type" \
16339		-command {if {$choose_xserver} {choose_xserver_dialog}}
16340	incr i
16341
16342	checkbutton .ot.b$i -anchor w -variable use_cups -text \
16343		"Enable Printing" \
16344		-command {if {$use_cups} {cups_dialog}}
16345	incr i
16346
16347	checkbutton .ot.b$i -anchor w -variable use_sound -text \
16348		"Enable Sound" \
16349		-command {if {$use_sound} {sound_dialog}}
16350	incr i
16351
16352#	checkbutton .ot.b$i -anchor w -variable use_smbmnt -text \
16353#		"Enable SMB mount tunnelling" \
16354#		-command {if {$use_smbmnt} {smb_dialog}}
16355#	incr i
16356
16357	checkbutton .ot.b$i -anchor w -variable choose_filexfer -text \
16358		"File Transfer" \
16359		-command {if {$choose_filexfer} {ts_filexfer_dialog}}
16360	incr i
16361
16362	checkbutton .ot.b$i -anchor w -variable use_viewonly -text \
16363		"View Only"
16364	incr i
16365
16366	checkbutton .ot.b$i -anchor w -variable change_vncviewer -text \
16367		"Change VNC Viewer" \
16368		-command change_vncviewer_dialog_wrap
16369	incr i
16370
16371	if {!$is_windows && $uname == "Darwin"} {
16372		checkbutton .ot.b$i -anchor w -variable use_x11_macosx -text \
16373			"X11 viewer MacOSX" \
16374			-command {if {$use_x11_macosx} {set darwin_cotvnc 0} else {set darwin_cotvnc 1}; set_darwin_cotvnc_buttons}
16375		incr i
16376	}
16377
16378	button .ot.b$i -anchor w -text "   Delete Profile..." \
16379		-command {destroy .ot; delete_profile}
16380	incr i
16381
16382	button .ot.b$i -anchor w -text "   Advanced ..." -command {set_ts_adv_options}
16383	incr i
16384
16385	for {set j 1} {$j < $i} {incr j} {
16386		pack .ot.b$j -side top -fill x
16387	}
16388
16389	frame .ot.b
16390	button .ot.b.done -text "Done" -command {destroy .ot}
16391	button .ot.b.help -text "Help" -command help_ts_opts
16392	pack .ot.b.help .ot.b.done -fill x -expand 1 -side left
16393
16394	bind .ot <Escape> {destroy .ot}
16395	wm protocol .ot WM_DELETE_WINDOW {destroy .ot}
16396
16397	pack .ot.b -side top -fill x
16398
16399	center_win .ot
16400	wm resizable .ot 1 0
16401	focus .ot
16402}
16403
16404proc set_ts_adv_options {} {
16405	global ts_only ts_unixpw ts_vncshared
16406	global ts_ncache ts_multisession
16407	global choose_othervnc darwin_cotvnc choose_sleep
16408	global is_windows
16409
16410	if {! $ts_only} {
16411		return
16412	}
16413	catch {destroy .ot}
16414	toplev .ot2
16415	wm title .ot2 "Advanced"
16416
16417	set i 1
16418
16419	checkbutton .ot2.b$i -anchor w -variable ts_vncshared -text \
16420		"VNC Shared" \
16421		-command {if {$ts_vncshared} {ts_vncshared_dialog}}
16422	incr i
16423
16424	checkbutton .ot2.b$i -anchor w -variable choose_multisession -text \
16425		"Multiple Sessions" \
16426		-command {if {$choose_multisession} {ts_multi_dialog}}
16427	incr i
16428
16429	checkbutton .ot2.b$i -anchor w -variable ts_xlogin -text \
16430		"X Login Greeter" \
16431		-command {if {$ts_xlogin} {ts_xlogin_dialog}}
16432	incr i
16433
16434	checkbutton .ot2.b$i -anchor w -variable choose_othervnc -text \
16435		"Other VNC Server" \
16436		-command {if {$choose_othervnc} {ts_othervnc_dialog}}
16437	incr i
16438
16439	checkbutton .ot2.b$i -anchor w -variable ts_unixpw -text \
16440		"Use unixpw" \
16441		-command {if {$ts_unixpw} {ts_unixpw_dialog}}
16442	incr i
16443
16444	checkbutton .ot2.b$i -anchor w -variable use_bgr233 -text \
16445		"Client 8bit Color"
16446	if {$darwin_cotvnc} {.ot2.b$i configure -state disabled}
16447	global darwin_cotvnc_blist
16448	set darwin_cotvnc_blist(.ot2.b$i) 1
16449	incr i
16450
16451	checkbutton .ot2.b$i -anchor w -variable choose_ncache -text \
16452		"Client-Side Caching" \
16453		-command {if {$choose_ncache} {ts_ncache_dialog}}
16454	incr i
16455
16456	checkbutton .ot2.b$i -anchor w -variable choose_x11vnc_opts -text \
16457		"X11VNC Options" \
16458		-command {if {$choose_x11vnc_opts} {ts_x11vnc_opts_dialog}}
16459	incr i
16460
16461	checkbutton .ot2.b$i -anchor w -variable choose_sleep -text \
16462		"Extra Sleep" \
16463		-command {if {$choose_sleep} {ts_sleep_dialog}}
16464	incr i
16465
16466        if {$is_windows} {
16467		checkbutton .ot2.b$i -anchor w -variable choose_parg -text \
16468			"Putty Args" \
16469			-command {if {$choose_parg} {ts_putty_args_dialog}}
16470		incr i
16471        }
16472
16473	if {!$is_windows} {
16474		checkbutton .ot2.b$i -anchor w -variable ssh_local_protection -text \
16475			"SSH Local Protections" \
16476			-command {if {$ssh_local_protection} {ssh_sec_dialog}}
16477		if {$is_windows} {.ot2.b$i configure -state disabled}
16478		incr i
16479
16480		checkbutton .ot2.b$i -anchor w -variable ssh_known_hosts -text \
16481			"SSH KnownHosts file" \
16482			-command {if {$ssh_known_hosts} {ssh_known_hosts_dialog}}
16483		if {$is_windows} {.ot2.b$i configure -state disabled}
16484		incr i
16485	}
16486
16487	if {$is_windows} {
16488		button .ot2.b$i -anchor w -text "   Putty Agent" \
16489			-command {catch {exec pageant.exe &}}
16490		incr i
16491
16492		button .ot2.b$i -anchor w -text "   Putty Key-Gen" \
16493			-command {catch {exec puttygen.exe &}}
16494		incr i
16495	}
16496
16497	global env
16498	if {![info exists env(SSVNC_TS_ALWAYS)]} {
16499		button .ot2.b$i -anchor w -text "   SSVNC Mode" \
16500			-command {destroy .ot2; to_ssvnc}
16501		incr i
16502	}
16503
16504	if {!$is_windows} {
16505		button .ot2.b$i -anchor w -text "   Unix ssvncviewer ..." \
16506			-command {set_ssvncviewer_options}
16507		if {$is_windows} {
16508			.ot2.b$i configure -state disabled
16509		}
16510		global change_vncviewer
16511		if {$change_vncviewer} {
16512			.ot2.b$i configure -state disabled
16513		}
16514		global ts_uss_button
16515		set ts_uss_button .ot2.b$i
16516		incr i
16517	}
16518
16519	for {set j 1} {$j < $i} {incr j} {
16520		pack .ot2.b$j -side top -fill x
16521	}
16522
16523	frame .ot2.b
16524	button .ot2.b.done -text "Done" -command {destroy .ot2}
16525	button .ot2.b.help -text "Help" -command help_ts_opts
16526	pack .ot2.b.help .ot2.b.done -fill x -expand 1 -side left
16527
16528	bind .ot2 <Escape> {destroy .ot2}
16529	wm protocol .ot2 WM_DELETE_WINDOW {destroy .ot2}
16530
16531	pack .ot2.b -side top -fill x
16532
16533	center_win .ot2
16534	wm resizable .ot2 1 0
16535	focus .ot2
16536}
16537
16538proc change_vncviewer_dialog_wrap {} {
16539	global change_vncviewer ts_uss_button is_windows
16540	if {$change_vncviewer} {
16541		change_vncviewer_dialog
16542		catch {tkwait window .chviewer}
16543	}
16544	if {$change_vncviewer || $is_windows} {
16545		catch {.oa.ss configure -state disabled}
16546	} else {
16547		catch {.oa.ss configure -state normal}
16548	}
16549	if [info exists ts_uss_button] {
16550		if {$change_vncviewer || $is_windows} {
16551			catch {$ts_uss_button configure -state disabled}
16552		} else {
16553			catch {$ts_uss_button configure -state normal}
16554		}
16555	}
16556}
16557
16558proc set_advanced_options {} {
16559	global use_cups use_sound use_smbmnt
16560	global change_vncviewer
16561	global use_port_knocking port_knocking_list
16562	global is_windows darwin_cotvnc
16563	global use_ssh use_sshssl
16564	global use_x11_macosx
16565	global adv_ssh
16566	global showing_no_encryption
16567	global x11vnc_xlogin_widget
16568
16569	catch {destroy .o}
16570	toplev .oa
16571	wm title .oa "Advanced Options"
16572
16573	set i 1
16574
16575	checkbutton .oa.b$i -anchor w -variable use_cups -text \
16576		"Enable CUPS Print tunnelling" \
16577		-command {if {$use_cups} {cups_dialog}}
16578	if {!$use_ssh && !$use_sshssl} {.oa.b$i configure -state disabled}
16579	set adv_ssh(cups) .oa.b$i
16580	incr i
16581
16582	checkbutton .oa.b$i -anchor w -variable use_sound -text \
16583		"Enable ESD/ARTSD Audio tunnelling" \
16584		-command {if {$use_sound} {sound_dialog}}
16585	if {!$use_ssh && !$use_sshssl} {.oa.b$i configure -state disabled}
16586	set adv_ssh(snd) .oa.b$i
16587	incr i
16588
16589	checkbutton .oa.b$i -anchor w -variable use_smbmnt -text \
16590		"Enable SMB mount tunnelling" \
16591		-command {if {$use_smbmnt} {smb_dialog}}
16592	if {!$use_ssh && !$use_sshssl} {.oa.b$i configure -state disabled}
16593	set adv_ssh(smb) .oa.b$i
16594	incr i
16595
16596	checkbutton .oa.b$i -anchor w -variable use_x11vnc_xlogin -text \
16597		"Automatically Find X Login/Greeter" -command {x11vnc_find_adjust "xlogin"}
16598	if {!$use_ssh && !$use_sshssl} {.oa.b$i configure -state disabled}
16599	set x11vnc_xlogin_widget ".oa.b$i"
16600	incr i
16601
16602	checkbutton .oa.b$i -anchor w -variable additional_port_redirs -text \
16603		"Additional Port Redirs (via SSH)" \
16604		-command {if {$additional_port_redirs} {port_redir_dialog}}
16605	if {!$use_ssh && !$use_sshssl} {.oa.b$i configure -state disabled}
16606	set adv_ssh(redirs) .oa.b$i
16607	incr i
16608
16609	global use_ssl use_ssh use_sshssl
16610
16611	if {!$is_windows} {
16612		checkbutton .oa.b$i -anchor w -variable ssh_known_hosts -text \
16613			"Private SSH KnownHosts file" \
16614			-command {if {$ssh_known_hosts} {ssh_known_hosts_dialog}}
16615		set adv_ssh(knownhosts) .oa.b$i
16616		if {$use_ssl}    {.oa.b$i configure -state disabled}
16617		if {$is_windows} {.oa.b$i configure -state disabled}
16618		incr i
16619
16620		checkbutton .oa.b$i -anchor w -variable ssh_local_protection -text \
16621			"SSH Local Port Protections" \
16622			-command {if {$ssh_local_protection} {ssh_sec_dialog}}
16623		global ssh_local_protection_button
16624		set ssh_local_protection_button .oa.b$i
16625		if {$use_ssl}    {.oa.b$i configure -state disabled}
16626		if {$is_windows} {.oa.b$i configure -state disabled}
16627		incr i
16628	}
16629
16630   global ssh_only
16631   if {!$ssh_only} {
16632	if {!$is_windows} {
16633		checkbutton .oa.b$i -anchor w -variable stunnel_local_protection -text \
16634			"STUNNEL Local Port Protections" \
16635			-command {if {$stunnel_local_protection} {stunnel_sec_dialog}}
16636		global stunnel_local_protection_button
16637		set stunnel_local_protection_button .oa.b$i
16638		if {$use_ssh}    {.oa.b$i configure -state disabled}
16639		if {$is_windows} {.oa.b$i configure -state disabled}
16640		incr i
16641	}
16642
16643	checkbutton .oa.b$i -anchor w -variable disable_ssl_workarounds -text \
16644		"Disable SSL Workarounds" \
16645		-command {if {$disable_ssl_workarounds} {disable_ssl_workarounds_dialog}}
16646	global disable_ssl_workarounds_button
16647	set disable_ssl_workarounds_button .oa.b$i
16648	if {$use_ssh}    {.oa.b$i configure -state disabled}
16649	incr i
16650
16651	if {!$is_windows} {
16652		checkbutton .oa.b$i -anchor w -variable ultra_dsm -text \
16653			"UltraVNC DSM Encryption Plugin" \
16654			-command {if {$ultra_dsm} {ultra_dsm_dialog}}
16655		global ultra_dsm_button
16656		set ultra_dsm_button .oa.b$i
16657		if {$is_windows} {.oa.b$i configure -state disabled}
16658		if {$use_ssh}    {.oa.b$i configure -state disabled}
16659		incr i
16660	}
16661
16662	checkbutton .oa.b$i -anchor w -variable no_probe_vencrypt -text \
16663		"Do not Probe for VeNCrypt"
16664	global no_probe_vencrypt_button
16665	set no_probe_vencrypt_button .oa.b$i
16666	if {$use_ssh}    {.oa.b$i configure -state disabled}
16667	incr i
16668
16669	checkbutton .oa.b$i -anchor w -variable server_vencrypt -text \
16670		"Server uses VeNCrypt SSL encryption"
16671	global vencrypt_button
16672	set vencrypt_button .oa.b$i
16673	if {$use_ssh}    {.oa.b$i configure -state disabled}
16674	incr i
16675
16676	checkbutton .oa.b$i -anchor w -variable server_anondh -text \
16677		"Server uses Anonymous Diffie-Hellman" -command no_certs_tutorial_mesg
16678	global anondh_button
16679	set anondh_button .oa.b$i
16680	if {$use_ssh}    {.oa.b$i configure -state disabled}
16681	incr i
16682   }
16683
16684	checkbutton .oa.b$i -anchor w -variable change_vncviewer -text \
16685		"Change VNC Viewer" \
16686		-command change_vncviewer_dialog_wrap
16687	incr i
16688
16689	checkbutton .oa.b$i -anchor w -variable use_port_knocking -text \
16690		"Port Knocking" \
16691		-command {if {$use_port_knocking} {port_knocking_dialog}}
16692	incr i
16693
16694	for {set j 1} {$j < $i} {incr j} {
16695		pack .oa.b$j -side top -fill x
16696	}
16697
16698	global include_list extra_sleep
16699	frame .oa.fis
16700	frame .oa.fis.fL
16701	frame .oa.fis.fR
16702	label .oa.fis.fL.la -anchor w -text "Include:"
16703	label .oa.fis.fL.lb -anchor w -text "Sleep:"
16704	if {$is_windows} {
16705		label .oa.fis.fL.lc -anchor w -text "Putty Args:"
16706		pack .oa.fis.fL.la .oa.fis.fL.lb .oa.fis.fL.lc -side top -fill x
16707	} else {
16708		pack .oa.fis.fL.la .oa.fis.fL.lb -side top -fill x
16709	}
16710
16711	entry .oa.fis.fR.ea -width 10 -textvariable include_list
16712	entry .oa.fis.fR.eb -width 10 -textvariable extra_sleep
16713	if {$is_windows} {
16714		entry .oa.fis.fR.ec -width 10 -textvariable putty_args
16715		pack .oa.fis.fR.ea .oa.fis.fR.eb .oa.fis.fR.ec -side top -fill x
16716	} else {
16717		pack .oa.fis.fR.ea .oa.fis.fR.eb -side top -fill x
16718	}
16719
16720	pack .oa.fis.fL -side left
16721	pack .oa.fis.fR -side right -expand 1 -fill x
16722
16723	pack .oa.fis -side top -fill x
16724
16725
16726	if {!$is_windows} {
16727		global uname
16728		set t1 "         Unix ssvncviewer ..."
16729		if {$uname == "Darwin" } { regsub {^ *} $t1 "" t1 }
16730		button .oa.ss -anchor w -text $t1 -command set_ssvncviewer_options
16731		pack   .oa.ss -side top -fill x
16732		if {$is_windows} {
16733			.oa.ss configure -state disabled
16734		}
16735		global change_vncviewer
16736		if {$change_vncviewer} {
16737			.oa.ss configure -state disabled
16738		}
16739
16740		set t2 "         Use ssh-agent"
16741		if {$uname == "Darwin" } { regsub {^ *} $t2 "" t2 }
16742
16743		button .oa.sa -anchor w -text $t2 -command ssh_agent_restart
16744		pack .oa.sa -side top -fill x
16745		if {$is_windows} {
16746			.oa.sa configure -state disabled
16747		}
16748	} else {
16749		set t1 "         Launch Putty Agent"
16750		button .oa.pa -anchor w -text $t1 -command {catch {exec pageant.exe &}}
16751		pack   .oa.pa -side top -fill x
16752
16753		set t2 "         Launch Putty Key-Gen"
16754		button .oa.pg -anchor w -text $t2 -command {catch {exec puttygen.exe &}}
16755		pack   .oa.pg -side top -fill x
16756	}
16757
16758	frame .oa.b
16759	button .oa.b.done -text "Done" -command {destroy .oa}
16760	bind .oa <Escape> {destroy .oa}
16761	wm protocol .oa WM_DELETE_WINDOW {destroy .oa}
16762	button .oa.b.help -text "Help" -command help_advanced_opts
16763
16764	global use_listen
16765	if {$use_listen} {
16766		button .oa.b.connect -text "Listen" -command launch
16767	} else {
16768		button .oa.b.connect -text "Connect" -command launch
16769	}
16770
16771	pack .oa.b.help .oa.b.connect .oa.b.done -fill x -expand 1 -side left
16772
16773	pack .oa.b -side top -fill x
16774
16775	center_win .oa
16776	wm resizable .oa 1 0
16777	focus .oa
16778}
16779
16780proc set_ssvncviewer_options {} {
16781	global is_windows darwin_cotvnc
16782	global use_ssh use_sshssl use_x11cursor use_rawlocal use_notty use_popupfix use_alpha use_turbovnc disable_pipeline use_grab use_nobell
16783	global use_send_clipboard use_send_always
16784	global ssvnc_scale ssvnc_escape
16785	global server_vencrypt server_anondh
16786
16787	if {$is_windows} {
16788		return
16789	}
16790
16791	catch {destroy .oa}
16792	toplev .os
16793	wm title .os "Unix ssvncviewer Options"
16794
16795	set darwinlist [list]
16796
16797	set f0 .os.f
16798	frame $f0
16799	set fl $f0.fl
16800	frame $fl
16801	set fr $f0.fr
16802	frame $fr
16803
16804	set i 1
16805	set j 1
16806
16807	checkbutton $fl.b$i -anchor w -variable multiple_listen -text \
16808		"Multiple LISTEN Connections" \
16809		-command {if {$multiple_listen} {multilisten_dialog}}
16810	global multiple_listen_button use_listen
16811	set multiple_listen_button $fl.b$i
16812	if {$is_windows}  {$fl.b$i configure -state disabled}
16813	if {!$use_listen} {$fl.b$i configure -state disabled}
16814	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16815	incr i
16816
16817	checkbutton $fl.b$i -anchor w -variable listen_once -text \
16818		"Listen Once"
16819	global listen_once_button
16820	set listen_once_button $fl.b$i
16821	if {!$use_listen} {$fl.b$i configure -state disabled}
16822	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16823	incr i
16824
16825	checkbutton $fl.b$i -anchor w -variable listen_accept_popup -text \
16826		"Listen Accept Popup Dialog" \
16827		-command { if {$listen_accept_popup} { catch {$listen_accept_popup_button_sc configure -state normal} } else { catch {$listen_accept_popup_button_sc  configure -state disabled} } }
16828	global listen_accept_popup_button
16829	set listen_accept_popup_button $fl.b$i
16830	if {!$use_listen} {$fl.b$i configure -state disabled}
16831	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16832	incr i
16833
16834	global listen_accept_popup
16835	checkbutton $fl.b$i -anchor w -variable listen_accept_popup_sc -text \
16836		"   Accept Popup UltraVNC Single Click"
16837	global listen_accept_popup_button_sc
16838	set listen_accept_popup_button_sc $fl.b$i
16839	if {!$use_listen} {$fl.b$i configure -state disabled}
16840	if {!$listen_accept_popup} {$fl.b$i configure -state disabled}
16841	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16842	incr i
16843
16844	checkbutton $fl.b$i -anchor w -variable use_x11cursor -text \
16845		"Use X11 Cursor"
16846	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16847	incr i
16848
16849	checkbutton $fl.b$i -anchor w -variable use_nobell -text \
16850		"Disable Bell"
16851	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16852	incr i
16853
16854	checkbutton $fl.b$i -anchor w -variable use_rawlocal -text \
16855		"Use Raw Local"
16856	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16857	incr i
16858
16859	checkbutton $fl.b$i -anchor w -variable use_notty -text \
16860		"Avoid Using Terminal"
16861	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16862	incr i
16863
16864	checkbutton $fl.b$i -anchor w -variable use_popupfix -text \
16865		"Use Popup Fix"
16866	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16867	incr i
16868
16869	checkbutton $fl.b$i -anchor w -variable use_grab -text \
16870		"Use XGrabServer (for fullscreen)" \
16871		-command {if {$use_grab} {use_grab_dialog}}
16872	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16873	incr i
16874
16875	checkbutton $fl.b$i -anchor w -variable use_alpha -text \
16876		"Cursor Alphablending (32bpp required)     "
16877	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16878	incr i
16879
16880	checkbutton $fl.b$i -anchor w -variable use_turbovnc -text \
16881		"TurboVNC (if available on platform)"
16882	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16883	incr i
16884
16885	checkbutton $fl.b$i -anchor w -variable disable_pipeline -text \
16886		"Disable Pipelined Updates"
16887	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16888	incr i
16889
16890	checkbutton $fl.b$i -anchor w -variable use_send_clipboard -text \
16891		"Send CLIPBOARD not PRIMARY"
16892	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16893	incr i
16894
16895	checkbutton $fl.b$i -anchor w -variable use_send_always -text \
16896		"Send Selection Every time"
16897	lappend darwinlist $fl.b$i; if {$darwin_cotvnc} {$fl.b$i configure -state disabled}
16898	incr i
16899
16900	set relief ridge
16901
16902	frame $fr.b$j -height 2; incr j
16903
16904	frame $fr.b$j -relief $relief -borderwidth 2
16905
16906	global ffont
16907	label $fr.b$j.l -font $ffont -anchor w -text "Examples: '0.75', '1024x768', 'fit' (fill screen), or 'auto' ";
16908
16909	global ssvnc_scale
16910	frame $fr.b$j.f
16911	label $fr.b$j.f.l -text "Scaling: "
16912	lappend darwinlist $fr.b$j.f.l; if {$darwin_cotvnc} {$fr.b$j.f.l configure -state disabled}
16913	entry $fr.b$j.f.e -width 10 -textvariable ssvnc_scale
16914	lappend darwinlist $fr.b$j.f.e; if {$darwin_cotvnc} {$fr.b$j.f.e configure -state disabled}
16915	pack $fr.b$j.f.l -side left
16916	pack $fr.b$j.f.e -side right -expand 1 -fill x
16917
16918	pack $fr.b$j.f $fr.b$j.l -side top -fill x
16919
16920	incr j
16921
16922	frame $fr.b$j -height 2; incr j
16923
16924	frame $fr.b$j -relief $relief -borderwidth 2
16925
16926	label $fr.b$j.l -font $ffont -anchor w -text "Examples: 'default', 'Control_L,Alt_L', 'never'";
16927
16928	global ssvnc_escape
16929	frame $fr.b$j.f
16930	label $fr.b$j.f.l -text "Escape Keys: "
16931	lappend darwinlist $fr.b$j.f.l; if {$darwin_cotvnc} {$fr.b$j.f.l configure -state disabled}
16932	entry $fr.b$j.f.e -width 10 -textvariable ssvnc_escape
16933	lappend darwinlist $fr.b$j.f.e; if {$darwin_cotvnc} {$fr.b$j.f.e configure -state disabled}
16934	button $fr.b$j.f.b -relief ridge -text Help -command ssvnc_escape_help
16935	lappend darwinlist $fr.b$j.f.b; if {$darwin_cotvnc} {$fr.b$j.f.b configure -state disabled}
16936	pack $fr.b$j.f.l -side left
16937	pack $fr.b$j.f.b -side right
16938	pack $fr.b$j.f.e -side right -expand 1 -fill x
16939
16940	pack $fr.b$j.f $fr.b$j.l -side top -fill x
16941
16942	incr j
16943
16944	frame $fr.b$j -height 2; incr j
16945
16946	frame $fr.b$j -relief $relief -borderwidth 2
16947
16948	label $fr.b$j.l -font $ffont -anchor w -text "Enter the max height in pixels, e.g. '900'";
16949
16950	global ycrop_string
16951	frame $fr.b$j.f
16952	label $fr.b$j.f.l -text "Y Crop: "
16953	lappend darwinlist $fr.b$j.f.l; if {$darwin_cotvnc} {$fr.b$j.f.l configure -state disabled}
16954	entry $fr.b$j.f.e -width 10 -textvariable ycrop_string
16955	lappend darwinlist $fr.b$j.f.e; if {$darwin_cotvnc} {$fr.b$j.f.e configure -state disabled}
16956	pack $fr.b$j.f.l -side left
16957	pack $fr.b$j.f.e -side right -expand 1 -fill x
16958
16959	pack $fr.b$j.f $fr.b$j.l -side top -fill x
16960
16961	incr j
16962
16963	frame $fr.b$j -height 2; incr j
16964
16965	frame $fr.b$j -relief $relief -borderwidth 2
16966
16967	label $fr.b$j.l -font $ffont -anchor w -text "Enter the scrollbar width in pixels, e.g. '4'";
16968
16969	global sbwid_string
16970	frame $fr.b$j.f
16971	label $fr.b$j.f.l -text "ScrollBar Width: "
16972	lappend darwinlist $fr.b$j.f.l; if {$darwin_cotvnc} {$fr.b$j.f.l configure -state disabled}
16973	entry $fr.b$j.f.e -width 10 -textvariable sbwid_string
16974	lappend darwinlist $fr.b$j.f.e; if {$darwin_cotvnc} {$fr.b$j.f.e configure -state disabled}
16975	pack $fr.b$j.f.l -side left
16976	pack $fr.b$j.f.e -side right -expand 1 -fill x
16977
16978	pack $fr.b$j.f $fr.b$j.l -side top -fill x
16979
16980	incr j
16981
16982	frame $fr.b$j -height 2; incr j
16983
16984	frame $fr.b$j -relief $relief -borderwidth 2
16985
16986	label $fr.b$j.l  -font $ffont -anchor w -text "Enter the RFB version to pretend to be using, e.g. '3.4'";
16987	label $fr.b$j.l2 -font $ffont -anchor w -text "Sometimes needed for UltraVNC: 3.4, 3.6, 3.14, 3.16";
16988
16989	global rfbversion
16990	frame $fr.b$j.f
16991	label $fr.b$j.f.l -text "RFB Version: "
16992	lappend darwinlist $fr.b$j.f.l; if {$darwin_cotvnc} {$fr.b$j.f.l configure -state disabled}
16993	entry $fr.b$j.f.e -width 10 -textvariable rfbversion
16994	lappend darwinlist $fr.b$j.f.e; if {$darwin_cotvnc} {$fr.b$j.f.e configure -state disabled}
16995	pack $fr.b$j.f.l -side left
16996	pack $fr.b$j.f.e -side right -expand 1 -fill x
16997
16998	pack $fr.b$j.f $fr.b$j.l $fr.b$j.l2  -side top -fill x
16999
17000	incr j
17001
17002	frame $fr.b$j -height 2; incr j
17003
17004	frame $fr.b$j -relief $relief -borderwidth 2
17005
17006	label $fr.b$j.l1 -font $ffont -anchor w -text "List encodings in preferred order, for example";
17007	label $fr.b$j.l2 -font $ffont -anchor w -text "'copyrect zrle tight'   The full list of encodings is:";
17008	label $fr.b$j.l3 -font $ffont -anchor w -text "copyrect tight zrle zywrle hextile zlib corre rre raw";
17009
17010	global ssvnc_encodings
17011	frame $fr.b$j.f
17012	label $fr.b$j.f.l -text "Encodings: "
17013	lappend darwinlist $fr.b$j.f.l; if {$darwin_cotvnc} {$fr.b$j.f.l configure -state disabled}
17014	entry $fr.b$j.f.e -width 10 -textvariable ssvnc_encodings
17015	lappend darwinlist $fr.b$j.f.e; if {$darwin_cotvnc} {$fr.b$j.f.e configure -state disabled}
17016	pack $fr.b$j.f.l -side left
17017	pack $fr.b$j.f.e -side right -expand 1 -fill x
17018
17019	pack $fr.b$j.f $fr.b$j.l1 $fr.b$j.l2 $fr.b$j.l3 -side top -fill x
17020
17021	incr j
17022
17023	frame $fr.b$j -height 2; incr j
17024
17025	frame $fr.b$j -relief $relief -borderwidth 2
17026
17027	label $fr.b$j.l1 -font $ffont -anchor w -text "Add any extra options for ssvncviewer that you want.";
17028	label $fr.b$j.l2 -font $ffont -anchor w -text "For example: -16bpp -appshare -noshm etc. See Help for a list.";
17029
17030	global ssvnc_extra_opts
17031	frame $fr.b$j.f
17032	label $fr.b$j.f.l -text "Extra Options: "
17033	lappend darwinlist $fr.b$j.f.l; if {$darwin_cotvnc} {$fr.b$j.f.l configure -state disabled}
17034	entry $fr.b$j.f.e -width 10 -textvariable ssvnc_extra_opts
17035	lappend darwinlist $fr.b$j.f.e; if {$darwin_cotvnc} {$fr.b$j.f.e configure -state disabled}
17036	pack $fr.b$j.f.l -side left
17037	pack $fr.b$j.f.e -side right -expand 1 -fill x
17038
17039	pack $fr.b$j.f $fr.b$j.l1 $fr.b$j.l2 -side top -fill x
17040
17041	incr j
17042
17043	frame $fr.b$j -height 2; incr j
17044
17045	for {set k 1} {$k < $i} {incr k} {
17046		pack $fl.b$k -side top -fill x
17047	}
17048	for {set k 1} {$k < $j} {incr k} {
17049		pack $fr.b$k -side top -fill x
17050	}
17051
17052	pack $fl -side left -fill both
17053	pack $fr -side left -fill both -expand 1
17054
17055	pack $f0 -side top -fill both
17056
17057	frame .os.b
17058	button .os.b.done -text "Done" -command {destroy .os}
17059	bind .os <Escape> {destroy .os}
17060	wm protocol .os WM_DELETE_WINDOW {destroy .os}
17061	button .os.b.help -text "Help" -command help_ssvncviewer_opts
17062
17063	global use_listen
17064	if {$use_listen} {
17065		button .os.b.connect -text "Listen" -command launch
17066	} else {
17067		button .os.b.connect -text "Connect" -command launch
17068	}
17069
17070	pack .os.b.help .os.b.connect .os.b.done -fill x -expand 1 -side left
17071
17072	pack .os.b -side top -fill x
17073
17074	global darwin_cotvnc_blist
17075	foreach b $darwinlist {
17076		set darwin_cotvnc_blist($b) 1
17077	}
17078
17079	center_win .os
17080	wm resizable .os 1 0
17081	wm minsize .os [winfo reqwidth .os] [winfo reqheight .os]
17082	focus .os
17083}
17084
17085
17086proc in_path {cmd} {
17087	global env
17088	set p $env(PATH)
17089	foreach dir [split $p ":"] {
17090		set try "$dir/$cmd"
17091		if [file exists $try] {
17092			return "$try"
17093		}
17094	}
17095	return ""
17096}
17097
17098proc ssh_agent_restart {} {
17099	global env
17100
17101	set got_ssh_agent 0
17102	set got_ssh_add 0
17103	set got_ssh_agent2 0
17104	set got_ssh_add2 0
17105
17106	if {[in_path "ssh-agent"]  != ""} {set got_ssh_agent 1}
17107	if {[in_path "ssh-agent2"] != ""} {set got_ssh_agent2 1}
17108	if {[in_path "ssh-add"]    != ""} {set got_ssh_add 1}
17109	if {[in_path "ssh-add2"]   != ""} {set got_ssh_add2 1}
17110
17111	set ssh_agent ""
17112	set ssh_add ""
17113	if {[info exists env(USER)] && $env(USER) == "runge"} {
17114		if {$got_ssh_agent2} {
17115			set ssh_agent "ssh-agent2"
17116		}
17117		if {$got_ssh_add2} {
17118			set ssh_add "ssh-add2"
17119		}
17120	}
17121	if {$ssh_agent == "" && $got_ssh_agent} {
17122		set ssh_agent "ssh-agent"
17123	}
17124	if {$ssh_add == "" && $got_ssh_add} {
17125		set ssh_add "ssh-add"
17126	}
17127	if {$ssh_agent == ""} {
17128		bell
17129		mesg "could not find ssh-agent in PATH"
17130		return
17131	}
17132	if {$ssh_add == ""} {
17133		bell
17134		mesg "could not find ssh-add in PATH"
17135		return
17136	}
17137	set tmp $env(SSVNC_HOME)/.vnc-sa[tpid]
17138	set tmp [mytmp $tmp]
17139	set fh ""
17140	catch {set fh [open $tmp "w"]}
17141	if {$fh == ""} {
17142		bell
17143		mesg "could not open tmp file $tmp"
17144		return
17145	}
17146
17147	puts $fh "#!/bin/sh"
17148	puts $fh "eval `$ssh_agent -s`"
17149	puts $fh "$ssh_add"
17150	puts $fh "SSVNC_GUI_CHILD=\"\""
17151	puts $fh "export SSVNC_GUI_CHILD"
17152
17153	global buck_zero
17154	set cmd $buck_zero
17155
17156	if [info exists env(SSVNC_GUI_CMD)] {
17157		set cmd $env(SSVNC_GUI_CMD)
17158	}
17159	#puts $fh "$cmd </dev/null 1>/dev/null 2>/dev/null &"
17160	puts $fh "nohup $cmd &"
17161	puts $fh "sleep 1"
17162	puts $fh "rm -f $tmp"
17163	close $fh
17164
17165	wm withdraw .
17166	catch {wm withdraw .o}
17167	catch {wm withdraw .oa}
17168
17169	unix_terminal_cmd "+200+200" "Restarting with ssh-agent/ssh-add" "sh $tmp" 1
17170	after 10000
17171	destroy .
17172	exit
17173}
17174
17175proc putty_pw_entry {mode} {
17176	if {$mode == "check"} {
17177		global use_sshssl use_ssh
17178		if {$use_sshssl || $use_ssh} {
17179			putty_pw_entry enable
17180		} else {
17181			putty_pw_entry disable
17182		}
17183		return
17184	}
17185	if {$mode == "disable"} {
17186		catch {.o.pw.l configure -state disabled}
17187		catch {.o.pw.e configure -state disabled}
17188	} else {
17189		catch {.o.pw.l configure -state normal}
17190		catch {.o.pw.e configure -state normal}
17191	}
17192}
17193proc adv_ssh_tog {on} {
17194	global adv_ssh
17195	foreach b {cups snd smb redirs knownhosts} {
17196		if [info exists adv_ssh($b)] {
17197			if {$on} {
17198				catch {$adv_ssh($b) configure -state normal}
17199			} else {
17200				catch {$adv_ssh($b) configure -state disabled}
17201			}
17202		}
17203	}
17204}
17205
17206proc adv_listen_ssl_tog {on} {
17207	global stunnel_local_protection_button is_windows
17208	global disable_ssl_workarounds_button
17209	global vencrypt_button no_probe_vencrypt_button anondh_button ultra_dsm_button
17210
17211	set blist [list]
17212	if [info exists stunnel_local_protection_button] {
17213		lappend blist $stunnel_local_protection_button
17214	}
17215	if [info exists disable_ssl_workarounds_button] {
17216		lappend blist $disable_ssl_workarounds_button
17217	}
17218	if [info exists ultra_dsm_button] {
17219		lappend blist $ultra_dsm_button
17220	}
17221	if [info exists no_probe_vencrypt_button] {
17222		lappend blist $no_probe_vencrypt_button
17223	}
17224	if [info exists vencrypt_button] {
17225		lappend blist $vencrypt_button
17226	}
17227	if [info exists anondh_button] {
17228		lappend blist $anondh_button
17229	}
17230	foreach b $blist {
17231		if {$on} {
17232			catch {$b configure -state normal}
17233		} else {
17234			catch {$b configure -state disabled}
17235		}
17236	}
17237
17238	if {$is_windows} {
17239		catch {$stunnel_local_protection_button configure -state disabled}
17240		catch {$ultra_dsm_button                configure -state disabled}
17241	}
17242}
17243
17244proc adv_listen_ssh_tog {on} {
17245	global ssh_local_protection_button is_windows
17246	if [info exists ssh_local_protection_button] {
17247		if {$on} {
17248			catch {$ssh_local_protection_button configure -state normal}
17249		} else {
17250			catch {$ssh_local_protection_button configure -state disabled}
17251		}
17252	}
17253	if {$is_windows} {
17254		catch {$ssh_local_protection_button configure -state disabled}
17255	}
17256}
17257
17258proc ssl_ssh_adjust {which} {
17259	global use_ssl use_ssh use_sshssl sshssl_sw
17260	global remote_ssh_cmd_list
17261	global x11vnc_find_widget x11vnc_xlogin_widget uvnc_bug_widget
17262
17263	if {$which == "ssl"} {
17264		set use_ssl 1
17265		set use_ssh 0
17266		set use_sshssl 0
17267		set sshssl_sw "ssl"
17268		catch {.f4.getcert configure -state normal}
17269		catch {.f4.always  configure -state normal}
17270		if [info exists x11vnc_find_widget] {
17271			catch {$x11vnc_find_widget configure -state disabled}
17272		}
17273		if [info exists x11vnc_xlogin_widget] {
17274			catch {$x11vnc_xlogin_widget configure -state disabled}
17275		}
17276		if [info exists uvnc_bug_widget] {
17277			catch {$uvnc_bug_widget configure -state normal}
17278		}
17279		adv_ssh_tog 0
17280		adv_listen_ssl_tog 1
17281		adv_listen_ssh_tog 0
17282	} elseif {$which == "none"} {
17283		set use_ssl 0
17284		set use_ssh 0
17285		set use_sshssl 0
17286		set sshssl_sw "none"
17287		catch {.f4.getcert configure -state disabled}
17288		catch {.f4.always  configure -state disabled}
17289		if [info exists x11vnc_find_widget] {
17290			catch {$x11vnc_find_widget configure -state disabled}
17291		}
17292		if [info exists x11vnc_xlogin_widget] {
17293			catch {$x11vnc_xlogin_widget configure -state disabled}
17294		}
17295		if [info exists uvnc_bug_widget] {
17296			catch {$uvnc_bug_widget configure -state normal}
17297		}
17298		adv_ssh_tog 0
17299		adv_listen_ssl_tog 0
17300		adv_listen_ssh_tog 0
17301	} elseif {$which == "ssh"} {
17302		set use_ssl 0
17303		set use_ssh 1
17304		set use_sshssl 0
17305		set sshssl_sw "ssh"
17306		catch {.f4.getcert configure -state disabled}
17307		catch {.f4.always  configure -state disabled}
17308		if [info exists x11vnc_find_widget] {
17309			catch {$x11vnc_find_widget configure -state normal}
17310		}
17311		if [info exists x11vnc_xlogin_widget] {
17312			catch {$x11vnc_xlogin_widget configure -state normal}
17313		}
17314		if [info exists uvnc_bug_widget] {
17315			catch {$uvnc_bug_widget configure -state disabled}
17316		}
17317		adv_ssh_tog 1
17318		adv_listen_ssl_tog 0
17319		adv_listen_ssh_tog 1
17320	} elseif {$which == "sshssl"} {
17321		set use_ssl 0
17322		set use_ssh 0
17323		set use_sshssl 1
17324		set sshssl_sw "sshssl"
17325		catch {.f4.getcert configure -state disabled}
17326		catch {.f4.always  configure -state disabled}
17327		if [info exists x11vnc_find_widget] {
17328			catch {$x11vnc_find_widget configure -state normal}
17329		}
17330		if [info exists x11vnc_xlogin_widget] {
17331			catch {$x11vnc_xlogin_widget configure -state normal}
17332		}
17333		if [info exists uvnc_bug_widget] {
17334			catch {$uvnc_bug_widget configure -state normal}
17335		}
17336		adv_ssh_tog 1
17337		adv_listen_ssl_tog 1
17338		adv_listen_ssh_tog 1
17339	}
17340
17341	if [info exists remote_ssh_cmd_list] {
17342		if {$use_ssh || $use_sshssl} {
17343			foreach w $remote_ssh_cmd_list {
17344				$w configure -state normal
17345			}
17346		}
17347		if {$use_ssl || $sshssl_sw == "none"} {
17348			foreach w $remote_ssh_cmd_list {
17349				$w configure -state disabled
17350			}
17351		}
17352	}
17353
17354	if {! $use_ssl && ! $use_ssh && ! $use_sshssl} {
17355		if {$sshssl_sw != "none"} {
17356			set use_ssl 1
17357			set sshssl_sw "ssl"
17358		}
17359	}
17360	global ssh_only ts_only
17361	if {$ssh_only || $ts_only} {
17362		set use_ssl 0
17363		set use_sshssl 0
17364		set use_ssh 1
17365		set sshssl_sw "ssh"
17366	}
17367
17368	putty_pw_entry check
17369}
17370
17371proc listen_adjust {} {
17372	global use_listen revs_button multiple_listen_button is_windows
17373	global listen_once_button listen_accept_popup_button listen_accept_popup_button_sc
17374	if {![info exists multiple_listen_button]} {
17375		set multiple_listen_button "none"
17376	}
17377	if {$use_listen} {
17378		catch {.b.conn configure -text "Listen"}
17379		catch {.o.b.connect configure -text "Listen"}
17380		catch {$multiple_listen_button configure -state normal}
17381		catch {$listen_once_button configure -state normal}
17382		catch {$listen_accept_popup_button configure -state normal}
17383		catch {$listen_accept_popup_button_sc configure -state normal}
17384		catch {mesg "Listen :N -> Port 5500+N, i.e. :0 -> 5500, :1 -> 5501, :2 -> 5502 ..."}
17385	} else {
17386		catch {.b.conn configure -text "Connect"}
17387		catch {.o.b.connect configure -text "Connect"}
17388		catch {$multiple_listen_button configure -state disabled}
17389		catch {$listen_once_button configure -state disabled}
17390		catch {$listen_accept_popup_button configure -state disabled}
17391		catch {$listen_accept_popup_button_sc configure -state disabled}
17392		catch {mesg "Switched to Forward Connection mode."}
17393	}
17394	if {$is_windows} {
17395		catch {$multiple_listen_button configure -state disabled}
17396		catch {$listen_once_button configure -state disabled}
17397		catch {$listen_accept_popup_button configure -state disabled}
17398		catch {$listen_accept_popup_button_sc configure -state disabled}
17399	}
17400}
17401
17402proc unixpw_adjust {} {
17403	global is_windows use_unixpw darwin_cotvnc
17404	if {$is_windows || $darwin_cotvnc} {
17405		return;
17406	}
17407	if {$use_unixpw} {
17408		pack configure .fu -after .f1 -fill x
17409		catch {focus .fu.e}
17410	} else {
17411		pack forget .fu
17412	}
17413}
17414
17415proc x11vnc_find_adjust {which} {
17416	global remote_ssh_cmd
17417	global use_x11vnc_find x11vnc_find_widget
17418	global use_x11vnc_xlogin x11vnc_xlogin_widget
17419
17420	if {$which == "find"} {
17421		if {$use_x11vnc_find} {
17422			set use_x11vnc_xlogin 0
17423		}
17424	} elseif {$which == "xlogin"} {
17425		if {$use_x11vnc_xlogin} {
17426			set use_x11vnc_find 0
17427		}
17428	}
17429	if {! $use_x11vnc_find && ! $use_x11vnc_xlogin} {
17430		set remote_ssh_cmd "";
17431		return
17432	}
17433	if {![regexp {x11vnc} $remote_ssh_cmd]} {
17434		set remote_ssh_cmd "";
17435	}
17436	regsub {^[ 	]*PORT= [ 	]*} $remote_ssh_cmd "" remote_ssh_cmd
17437	regsub {^[ 	]*P= [ 	]*} $remote_ssh_cmd "" remote_ssh_cmd
17438	regsub {^[ 	]*sudo x11vnc[ 	]*} $remote_ssh_cmd "" remote_ssh_cmd
17439	regsub {^[ 	]*x11vnc[ 	]*} $remote_ssh_cmd "" remote_ssh_cmd
17440	regsub -all {[ 	]*-find[ 	]*} $remote_ssh_cmd " " remote_ssh_cmd
17441	regsub -all {[ 	]*-localhost[ 	]*} $remote_ssh_cmd " " remote_ssh_cmd
17442	regsub -all {[ 	]*-env FD_XDM=1[ 	]*} $remote_ssh_cmd " " remote_ssh_cmd
17443	if {$use_x11vnc_find} {
17444		set remote_ssh_cmd "PORT= x11vnc -find -localhost -nopw $remote_ssh_cmd"
17445	} else {
17446		set remote_ssh_cmd "PORT= sudo x11vnc -find -localhost -env FD_XDM=1 -nopw $remote_ssh_cmd"
17447	}
17448	regsub {[ 	]*$} $remote_ssh_cmd "" remote_ssh_cmd
17449	regsub {^[ 	]*} $remote_ssh_cmd "" remote_ssh_cmd
17450	regsub -all {[ 	][ 	]*} $remote_ssh_cmd " " remote_ssh_cmd
17451}
17452
17453proc set_darwin_cotvnc_buttons {} {
17454	global darwin_cotvnc uname darwin_cotvnc_blist
17455
17456	if {$uname == "Darwin" && [info exists darwin_cotvnc_blist]} {
17457		foreach b [array names darwin_cotvnc_blist] {
17458			if {$darwin_cotvnc} {
17459				catch {$b configure -state disabled}
17460			} else {
17461				catch {$b configure -state normal}
17462			}
17463		}
17464	}
17465}
17466
17467proc disable_encryption {} {
17468	global env
17469	if {[info exists env(SSVNC_DISABLE_ENCRYPTION_BUTTON)]} {
17470		set s $env(SSVNC_DISABLE_ENCRYPTION_BUTTON)
17471		if {$s != "" && $s != "0"} {
17472			return 1;
17473		}
17474	}
17475	return 0;
17476}
17477proc set_options {} {
17478	global use_alpha use_grab use_ssh use_sshssl use_viewonly use_fullscreen use_bgr233
17479	global use_nojpeg use_raise_on_beep use_compresslevel use_quality use_x11_macosx
17480	global use_send_clipboard use_send_always
17481	global compresslevel_text quality_text
17482	global env is_windows darwin_cotvnc uname
17483	global use_listen
17484	global use_x11vnc_find x11vnc_find_widget
17485	global use_x11vnc_xlogin x11vnc_xlogin_widget uvnc_bug_widget
17486	global ts_only
17487	global darwin_cotvnc_blist
17488	global showing_no_encryption no_enc_button no_enc_prev
17489
17490	if {$ts_only} {
17491		set_ts_options
17492		return
17493	}
17494
17495	toplev .o
17496	wm title .o "SSL/SSH VNC Options"
17497
17498	set i 1
17499
17500	radiobutton .o.b$i -anchor w -variable sshssl_sw -value ssl -text \
17501		"Use SSL" -command {ssl_ssh_adjust ssl}
17502	incr i
17503
17504	radiobutton .o.b$i -anchor w -variable sshssl_sw -value ssh -text \
17505		"Use SSH" -command {ssl_ssh_adjust ssh}
17506	incr i
17507
17508	radiobutton .o.b$i -anchor w -variable sshssl_sw -value sshssl -text \
17509		"Use SSH+SSL" -command {ssl_ssh_adjust sshssl}
17510	set iss $i
17511	set no_enc_prev .o.b$i
17512	incr i
17513
17514	radiobutton .o.b$i -anchor w -variable sshssl_sw -value none -text \
17515		"No Encryption" -command {ssl_ssh_adjust none}
17516	set no_enc_button .o.b$i
17517	set ine $i
17518	incr i
17519
17520	checkbutton .o.b$i -anchor w -variable use_x11vnc_find -text \
17521		"Automatically Find X Session" -command {x11vnc_find_adjust "find"}
17522	if {!$use_ssh && !$use_sshssl} {.o.b$i configure -state disabled}
17523	set x11vnc_find_widget ".o.b$i"
17524	incr i
17525
17526	if {! $is_windows} {
17527		checkbutton .o.b$i -anchor w -variable use_unixpw -text \
17528			"Unix Username & Password" -command {unixpw_adjust}
17529		if {$darwin_cotvnc} {.o.b$i configure -state disabled}
17530		set darwin_cotvnc_blist(.o.b$i) 1
17531		incr i
17532	}
17533
17534	checkbutton .o.b$i -anchor w -variable use_listen -text \
17535		"Reverse VNC Connection (-LISTEN)" -command {listen_adjust; if {$vncdisplay == ""} {set vncdisplay ":0"} else {set vncdisplay ""}; if {0 && $use_listen} {destroy .o}}
17536	#if {$is_windows} {.o.b$i configure -state disabled}
17537	#if {$darwin_cotvnc} {.o.b$i configure -state disabled}
17538	#set darwin_cotvnc_blist(.o.b$i) 1
17539	incr i
17540
17541	checkbutton .o.b$i -anchor w -variable use_viewonly -text \
17542		"View Only"
17543	incr i
17544
17545	checkbutton .o.b$i -anchor w -variable use_fullscreen -text \
17546		"Fullscreen"
17547	incr i
17548
17549	checkbutton .o.b$i -anchor w -variable use_raise_on_beep -text \
17550		"Raise On Beep"
17551	if {$darwin_cotvnc} {.o.b$i configure -state disabled}
17552	set darwin_cotvnc_blist(.o.b$i) 1
17553	incr i
17554
17555	checkbutton .o.b$i -anchor w -variable use_bgr233 -text \
17556		"Use 8bit color (-bgr233)"
17557	if {$darwin_cotvnc} {.o.b$i configure -state disabled}
17558	set darwin_cotvnc_blist(.o.b$i) 1
17559	incr i
17560
17561	checkbutton .o.b$i -anchor w -variable use_nojpeg -text \
17562		"Do not use JPEG (-nojpeg)"
17563	if {$darwin_cotvnc} {.o.b$i configure -state disabled}
17564	set darwin_cotvnc_blist(.o.b$i) 1
17565	incr i
17566
17567	if {$uname == "Darwin"} {
17568		checkbutton .o.b$i -anchor w -variable use_x11_macosx -text \
17569			"Use X11 vncviewer on MacOSX" \
17570			-command {if {$use_x11_macosx} {set darwin_cotvnc 0} else {set darwin_cotvnc 1}; set_darwin_cotvnc_buttons}
17571		if {$uname != "Darwin"} {.o.b$i configure -state disabled}
17572		incr i
17573	}
17574
17575	if {$is_windows} {
17576		global kill_stunnel
17577		checkbutton .o.b$i -anchor w -variable kill_stunnel -text \
17578			"Kill Stunnel Automatically"
17579		incr i
17580	}
17581
17582
17583	menubutton .o.b$i -anchor w -menu .o.b$i.m -textvariable compresslevel_text -relief groove
17584	set compresslevel_text "Compress Level: $use_compresslevel"
17585	if {$darwin_cotvnc} {.o.b$i configure -state disabled}
17586	set darwin_cotvnc_blist(.o.b$i) 1
17587
17588	menu .o.b$i.m -tearoff 0
17589	for {set j -1} {$j < 10} {incr j} {
17590		set v $j
17591		set l $j
17592		if {$j == -1} {
17593			set v "default"
17594			set l "default"
17595		}
17596		.o.b$i.m add radiobutton -variable use_compresslevel \
17597			-value $v -label $l -command \
17598			{set compresslevel_text "Compress Level: $use_compresslevel"}
17599	}
17600	incr i
17601
17602	menubutton .o.b$i -anchor w -menu .o.b$i.m -textvariable quality_text -relief groove
17603	set quality_text "Quality: $use_quality"
17604	if {$darwin_cotvnc} {.o.b$i configure -state disabled}
17605	set darwin_cotvnc_blist(.o.b$i) 1
17606
17607	menu .o.b$i.m -tearoff 0
17608	for {set j -1} {$j < 10} {incr j} {
17609		set v $j
17610		set l $j
17611		if {$j == -1} {
17612			set v "default"
17613			set l "default"
17614		}
17615		.o.b$i.m add radiobutton -variable use_quality \
17616			-value $v -label $l -command \
17617			{set quality_text "Quality: $use_quality"}
17618	}
17619	incr i
17620
17621	global use_mode ts_only ssh_only
17622	if {$ts_only} {
17623		set use_mode "Terminal Services (tsvnc)"
17624	} elseif {$ssh_only} {
17625		set use_mode "SSH-Only (sshvnc)"
17626	} else {
17627		set use_mode "SSVNC"
17628	}
17629	global mode_text
17630	set mode_text "Mode: $use_mode"
17631
17632	menubutton .o.b$i -anchor w -menu .o.b$i.m -textvariable mode_text -relief groove
17633
17634	menu .o.b$i.m -tearoff 0
17635	.o.b$i.m add radiobutton -variable use_mode -value "SSVNC"  \
17636		-label "SSVNC" -command { if {$ts_only || $ssh_only} {to_ssvnc; set mode_text "Mode: SSVNC"; destroy .o}}
17637	.o.b$i.m add radiobutton -variable use_mode -value "SSH-Only (sshvnc)" \
17638		-label "SSH-Only (sshvnc)" -command { if {$ts_only || ! $ssh_only} {to_sshonly; set mode_text "Mode: SSH-Only (sshvnc)"; destroy .o}}
17639	.o.b$i.m add radiobutton -variable use_mode -value "Terminal Services (tsvnc)" \
17640		-label "Terminal Services (tsvnc)" -command {to_tsonly; set mode_text "Mode: Terminal Services (tsvnc)"; destroy .o}
17641	incr i
17642
17643	global started_with_noenc
17644
17645	if {0 && $started_with_noenc && $showing_no_encryption} {
17646		;
17647	} elseif {$ssh_only} {
17648		;
17649	} else {
17650		checkbutton .o.b$i -anchor w -variable showing_no_encryption -text \
17651			"Show 'No Encryption' Option" -pady 5 \
17652			-command {toggle_no_encryption 1}
17653		# -relief raised
17654		incr i
17655	}
17656
17657	for {set j 1} {$j < $i} {incr j} {
17658		global ssh_only ts_only
17659		if {$ssh_only && $j <= 3} {
17660			continue;
17661		}
17662		if {$ts_only && $j <= 3} {
17663			continue;
17664		}
17665		if {!$showing_no_encryption && $j == $ine} {
17666			continue;
17667		}
17668
17669		pack .o.b$j -side top -fill x
17670	}
17671
17672	if {$is_windows} {
17673		global port_slot putty_pw
17674
17675		frame .o.pp
17676		frame .o.pp.fL
17677		frame .o.pp.fR
17678		label .o.pp.fL.la -anchor w -text "Putty PW:"
17679		label .o.pp.fL.lb -anchor w -text "Port Slot:"
17680		pack .o.pp.fL.la .o.pp.fL.lb -side top -fill x
17681
17682		entry .o.pp.fR.ea -width 10 -show * -textvariable putty_pw
17683		entry .o.pp.fR.eb -width 10 -textvariable port_slot
17684		pack .o.pp.fR.ea .o.pp.fR.eb  -side top -fill x
17685
17686		pack .o.pp.fL -side left
17687		pack .o.pp.fR -side right -expand 1 -fill x
17688
17689		pack .o.pp -side top -fill x
17690
17691		putty_pw_entry check
17692	}
17693
17694	global uname
17695	set t1 "             Advanced ..."
17696	set t2 "             Use Defaults"
17697	set t3 "             Delete Profile ..."
17698	if {$uname == "Darwin"} {
17699		regsub {^ *} $t1 "" t1
17700		regsub {^ *} $t2 "" t2
17701		regsub {^ *} $t3 "" t3
17702	}
17703
17704	button .o.advanced -anchor w -text $t1 -command set_advanced_options
17705	button .o.clear    -anchor w -text $t2 -command {set_defaults; init_vncdisplay}
17706	button .o.delete   -anchor w -text $t3 -command {destroy .o; delete_profile}
17707
17708	pack .o.clear -side top -fill x
17709	pack .o.delete -side top -fill x
17710	pack .o.advanced -side top -fill x
17711
17712#	pack .o.s_prof -side top -fill x
17713#	pack .o.l_prof -side top -fill x
17714
17715	frame .o.b
17716	button .o.b.done -text "Done" -command {destroy .o}
17717	bind .o <Escape> {destroy .o}
17718	wm protocol .o WM_DELETE_WINDOW {destroy .o}
17719	button .o.b.help -text "Help" -command help_opts
17720	global use_listen
17721	if {$use_listen} {
17722		button .o.b.connect -text "Listen" -command launch
17723	} else {
17724		button .o.b.connect -text "Connect" -command launch
17725	}
17726
17727	pack .o.b.help .o.b.connect .o.b.done -fill x -expand 1 -side left
17728
17729	pack .o.b -side top -fill x
17730
17731	center_win .o
17732	wm resizable .o 1 0
17733	focus .o
17734}
17735
17736proc check_writable {} {
17737	set test test[pid].txt
17738	catch {set f [open $test "w"]; puts $f "test"; close $f}
17739
17740	###catch {file delete -force $test}	# testing.
17741
17742	if ![file exists $test] {
17743		global env
17744		if [info exists env(SSVNC_HOME)] {
17745			set dir "$env(SSVNC_HOME)/ss_vnc/cache"
17746			catch {file mkdir $dir}
17747			if ![file exists $dir] {
17748				return
17749			}
17750			foreach f [glob -type f * */* */*/*] {
17751				set dest "$dir/$f"
17752				set dirn [file dirname $dest]
17753				catch {file mkdir $dirn}
17754				catch {file copy -force -- $f $dest}
17755			}
17756			cd $dir
17757			###catch {set f [open $test "w"]; puts $f "test"; close $f}
17758		}
17759	} else {
17760		catch {file delete -force $test}
17761	}
17762}
17763
17764proc print_help {} {
17765
17766	global help_main help_prox help_misc help_tips
17767	set b "\n============================================================================\n"
17768	help
17769	#set str [.h.f.t get 1.0 end]
17770	#puts "${b}Help:\n$str"
17771	puts "${b}Help Main:\n$help_main"
17772	puts "${b}Help Proxies:\n$help_prox"
17773	puts "${b}Help Misc:\n$help_misc"
17774	puts "${b}Help Tips:\n$help_tips"
17775	destroy .h
17776
17777	help_opts
17778	set str [.oh.f.t get 1.0 end]
17779	puts "${b}SSL/SSH Viewer Options Help:\n$str"
17780	destroy .oh
17781
17782	help_advanced_opts
17783	set str [.ah.f.t get 1.0 end]
17784	puts "${b}Advanced Options Help:\n$str"
17785	destroy .ah
17786
17787	help_ssvncviewer_opts
17788	set str [.av.f.t get 1.0 end]
17789	puts "${b}ssvncviewer Options Help:\n$str"
17790	destroy .av
17791
17792	help_certs
17793	set str [.ch.f.t get 1.0 end]
17794	puts "${b}SSL Certificates Help:\n$str"
17795	destroy .ch
17796
17797	help_fetch_cert
17798	set str [.fh.f.t get 1.0 end]
17799	puts "${b}Fetch Certificates Help:\n$str"
17800	destroy .fh
17801
17802	create_cert
17803	set str [.ccrt.f.t get 1.0 end]
17804	puts "${b}Create SSL Certificate Dialog:\n$str"
17805	destroy .ccrt
17806
17807	import_cert
17808	set str [.icrt.f.t get 1.0 end]
17809	puts "${b}Import SSL Certificate Dialog:\n$str"
17810	destroy .icrt
17811
17812	global cert_text
17813	set cert_text "empty"
17814	save_cert "help:0"
17815	set str [.scrt.f.t get 1.0 end]
17816	puts "${b}Save SSL Certificate Dialog:\n$str"
17817	destroy .scrt
17818
17819	ts_help
17820	set str [.h.f.t get 1.0 end]
17821	puts "${b}Terminal Services Help:\n$str"
17822	destroy .h
17823
17824	help_ts_opts
17825	set str [.oh.f.t get 1.0 end]
17826	puts "${b}Terminal Services VNC Options Help:\n$str"
17827	destroy .oh
17828
17829	ts_unixpw_dialog
17830	set str [.uxpw.f.t get 1.0 end]
17831	puts "${b}Terminal Services Use unixpw Dialog:\n$str"
17832	destroy .uxpw
17833
17834	ts_vncshared_dialog
17835	set str [.vncs.f.t get 1.0 end]
17836	puts "${b}Terminal Services VNC Shared Dialog:\n$str"
17837	destroy .vncs
17838
17839	ts_multi_dialog
17840	set str [.mult.f.t get 1.0 end]
17841	puts "${b}Terminal Services Multiple Sessions Dialog:\n$str"
17842	destroy .mult
17843
17844	ts_xlogin_dialog
17845	set str [.xlog.f.t get 1.0 end]
17846	puts "${b}Terminal Services X Login Dialog:\n$str"
17847	destroy .xlog
17848
17849	ts_othervnc_dialog
17850	set str [.ovnc.f.t get 1.0 end]
17851	puts "${b}Terminal Services Other VNC Server Dialog:\n$str"
17852	destroy .ovnc
17853
17854	ts_ncache_dialog
17855	set str [.nche.f.t get 1.0 end]
17856	puts "${b}Terminal Services Client-Side Caching Dialog:\n$str"
17857	destroy .nche
17858
17859	ts_x11vnc_opts_dialog
17860	set str [.x11v.f.t get 1.0 end]
17861	puts "${b}Terminal Services x11vnc Options Dialog:\n$str"
17862	destroy .x11v
17863
17864	ts_filexfer_dialog
17865	set str [.xfer.f.t get 1.0 end]
17866	puts "${b}Terminal Services File Transfer Dialog:\n$str"
17867	destroy .xfer
17868
17869	ts_sound_dialog
17870	set str [.snd.f.t get 1.0 end]
17871	puts "${b}Terminal Services Sound Tunnelling Dialog:\n$str"
17872	destroy .snd
17873
17874	ts_cups_dialog
17875	set str [.cups.f.t get 1.0 end]
17876	puts "${b}Terminal Services CUPS Dialog:\n$str"
17877	destroy .cups
17878
17879	help_ssvncviewer_opts
17880	set str [.av.f.t get 1.0 end]
17881	puts "${b}Unix SSVNC viewer Options Help:\n$str"
17882	destroy .av
17883
17884	change_vncviewer_dialog
17885	set str [.chviewer.t get 1.0 end]
17886	puts "${b}Unix Change VNC Viewer Dialog:\n$str"
17887	destroy .chviewer
17888
17889	cups_dialog
17890	set str [.cups.f.t get 1.0 end]
17891	puts "${b}CUPS Dialog:\n$str"
17892	destroy .cups
17893
17894	sound_dialog
17895	set str [.snd.f.t get 1.0 end]
17896	puts "${b}ESD Audio Tunnelling Dialog:\n$str"
17897	destroy .snd
17898
17899	smb_dialog
17900	set str [.smb.f.t get 1.0 end]
17901	puts "${b}SMB Mounting Dialog:\n$str"
17902	destroy .smb
17903
17904	port_redir_dialog
17905	set str [.redirs.t get 1.0 end]
17906	puts "${b}Additional Port Redirections Dialog:\n$str"
17907	destroy .redirs
17908
17909	port_knocking_dialog
17910	set str [.pk.f.t get 1.0 end]
17911	puts "${b}Port Knocking Dialog:\n$str"
17912	destroy .pk
17913
17914	ssvnc_escape_help
17915	set str [.ekh.f.t get 1.0 end]
17916	puts "${b}SSVNC Escape Keys Help:\n$str"
17917	destroy .ekh
17918
17919	stunnel_sec_dialog
17920	set str [.stlsec.f.t get 1.0 end]
17921	puts "${b}STUNNEL Local Port Protections Dialog:\n$str"
17922	destroy .stlsec
17923
17924	disable_ssl_workarounds_dialog
17925	set str [.sslwrk.f.t get 1.0 end]
17926	puts "${b}Disable SSL Workarounds Dialog:\n$str"
17927	destroy .sslwrk
17928
17929	ultra_dsm_dialog
17930	set str [.ultradsm.f.t get 1.0 end]
17931	puts "${b}UltraVNC DSM Encryption Plugin Dialog:\n$str"
17932	destroy .ultradsm
17933
17934	ssh_known_hosts_dialog
17935	set str [.sshknownhosts.f.t get 1.0 end]
17936	puts "${b}Private SSH KnownHosts file Dialog:\n$str"
17937	destroy .sshknownhosts
17938
17939	ssh_sec_dialog
17940	set str [.sshsec.t get 1.0 end]
17941	puts "${b}SSH Local Port Protections Dialog:\n$str"
17942	destroy .sshsec
17943
17944	multilisten_dialog
17945	set str [.multil.t get 1.0 end]
17946	puts "${b}Multiple LISTEN Connections Dialog:\n$str"
17947	destroy .multil
17948
17949	use_grab_dialog
17950	set str [.usegrb.t get 1.0 end]
17951	puts "${b}Use XGrabServer (for fullscreen) Dialog:\n$str"
17952	destroy .usegrb
17953}
17954
17955proc zeroconf_fill {b m} {
17956	global is_windows zeroconf_command last_post
17957
17958	if {$is_windows} {
17959		return;
17960	}
17961
17962	if {![info exists last_post]} {
17963		set last_post 0
17964	}
17965	set now [clock seconds]
17966	if {$now < [expr $last_post + 10]} {
17967		# cache menu for 10 secs.
17968		return
17969	}
17970
17971	.  config -cursor {watch}
17972	$b config -cursor {watch}
17973	$b configure -state disabled
17974
17975	$m delete 0 end
17976	update
17977
17978	set emsg ""
17979	set output ""
17980	set none "No VNC servers detected"
17981
17982	set rc 1
17983	set rd 0
17984	if {$zeroconf_command == "avahi-browse"} {
17985		set rc [catch {set output [exec avahi-browse -r -t -p -k _rfb._tcp 2>/dev/null]} emsg]
17986	} elseif {$zeroconf_command == "dns-sd"} {
17987		set rc [catch {set output [exec /bin/sh -c {pid=$$; export pid; (sleep 1; kill $pid) & exec dns-sd -B _rfb._tcp} 2>/dev/null]} emsg]
17988		set rd 1
17989	} elseif {$zeroconf_command == "mDNS"} {
17990		set rc [catch {set output [exec /bin/sh -c {pid=$$; export pid; (sleep 1; kill $pid) & exec mDNS   -B _rfb._tcp} 2>/dev/null]} emsg]
17991		set rd 1
17992	}
17993
17994	#puts "rc=$rc output=$output"
17995	if {$rd == 1 && $rc != 0} {
17996		if [regexp {_rfb} $emsg] {
17997			set rc 0
17998			set output $emsg
17999		}
18000	}
18001
18002	set count 0
18003
18004	if {$rc != 0} {
18005		$m add command -label $none
18006		incr count
18007
18008	} elseif {$output == "" || [regexp {^[ \t\n]*$} $output]} {
18009		$m add command -label $none
18010		incr count
18011
18012	} elseif {$zeroconf_command == "avahi-browse"} {
18013		set lines [split $output "\n"]
18014		set saw("__none__") 1
18015		foreach line $lines {
18016			set items [split $line ";"]
18017			if {[llength $items] != 10} {
18018				continue
18019			}
18020			if {[lindex $items 0] != "="} {
18021				continue
18022			}
18023
18024			# =;eth0;IPv4;tmp2\0582;_rfb._tcp;local;tmp2.local;10.0.2.252;5902;
18025			set eth  [lindex $items 1]
18026			set ipv  [lindex $items 2]
18027			set name [lindex $items 3]
18028			set type [lindex $items 4]
18029			set loc  [lindex $items 5]
18030			set host [lindex $items 6]
18031			set ip   [lindex $items 7]
18032			set port [lindex $items 8]
18033
18034			if {![regexp -nocase {ipv4} $ipv]} {
18035				continue
18036			}
18037
18038			set name0 $name
18039			regsub -all {\\\\} $name "__bockslosh__" name
18040			regsub -all {\\\.} $name "." name
18041
18042			set n 0
18043			while {1} {
18044				incr n
18045				if {$n > 100} {
18046					break
18047				}
18048				if {[regexp {\\[0-9][0-9][0-9]} $name match]} {
18049					#puts "match1=$match"
18050					regsub {\\} $match "" match
18051					set d $match
18052					regsub {^0*} $d "" d
18053					set c [format "%c" $d]
18054					if {"$c" == "&"}  {
18055						set c "\\$c"
18056					}
18057					regsub "\\\\$match" $name $c name
18058					#puts "match: $match  c='$c'\nname=$name"
18059				} else {
18060					break
18061				}
18062			}
18063
18064			regsub -all {__bockslosh__} $name "\\" name
18065
18066			set hp $host
18067			if {$port >= 5900 && $port <= 6100} {
18068				set d [expr $port - 5900]
18069				set hp "$host:$d"
18070			} else {
18071				set hp "$host:$port"
18072			}
18073			if {![info exists saw($name)]} {
18074				regsub -all {[^[:alnum:],./:@%_=+-]} $hp "" hp
18075				$m add command -label "$name - $hp" -command "set vncdisplay \"$hp\""
18076				incr count
18077				set p $port
18078				if {$p <= 200} {
18079					set p "-$port"
18080				}
18081				regsub -all {[^[:alnum:],./:@%_=+-]} "$ip:$p" "" ipp
18082				$m add command -label "$name - $ipp" -command "set vncdisplay \"$ipp\""
18083				incr count
18084				set saw($name) 1
18085			}
18086		}
18087	} else {
18088		set lines [split $output "\n"]
18089		set saw("__none__") 1
18090		global dns_sd_cache last_dns_sd
18091		if {![info exists last_dns_sd]} {
18092			set last_dns_sd 0
18093		}
18094		if {[clock seconds] > [expr $last_dns_sd + 1800]} {
18095			catch { unset dns_sd_cache }
18096			set last_dns_sd [clock seconds]
18097		}
18098		foreach line $lines {
18099			if [regexp -nocase {^Browsing} $line] {
18100				continue;
18101			}
18102			if [regexp -nocase {^Timestamp} $line] {
18103				continue;
18104			}
18105			if [regexp -nocase {killed:} $line] {
18106				continue;
18107			}
18108			if {![regexp {_rfb\._tcp} $line]} {
18109				continue;
18110			}
18111			regsub {[ \t\n]*$} $line "" line
18112			regsub {^.*_rfb\._tcp[^ ]*  *} $line "" name
18113
18114			if {[info exists saw($name)]} {
18115				continue
18116			}
18117			set saw($name) 1
18118
18119			set hp "$name"
18120			if {[info exists dns_sd_cache($name)]} {
18121				set hp $dns_sd_cache($name)
18122			} else {
18123				global env
18124				regsub -all {"} $name "" name2
18125				set env(DNS_SD_LU) $name2
18126				set emsg ""
18127				if {$zeroconf_command == "dns-sd"} {
18128					set rc [catch {set output [exec /bin/sh -c {pid=$$; export pid; (sleep 1; kill $pid) & exec dns-sd -L "$DNS_SD_LU" _rfb._tcp .} 2>/dev/null]} emsg]
18129				} elseif {$zeroconf_command == "mDNS"} {
18130					set rc [catch {set output [exec /bin/sh -c {pid=$$; export pid; (sleep 1; kill $pid) & exec mDNS   -L "$DNS_SD_LU" _rfb._tcp .} 2>/dev/null]} emsg]
18131					regsub -all {[ \t][ \t]*:} $emsg ":" emsg
18132				}
18133				regsub -all {  *} $emsg " " emsg
18134				if [regexp -nocase {be reached at  *([^ \t\n][^ \t\n]*)} $emsg match hpm] {
18135					if [regexp {^(.*):([0-9][0-9]*)$} $hpm mv hm pm] {
18136						if {$pm >= 5900 && $pm <= 6100} {
18137							set pm [expr $pm - 5900]
18138						}
18139						set hp "$hm:$pm"
18140					} else {
18141						set hp $hpm
18142					}
18143					set dns_sd_cache($name) $hp
18144				} else {
18145					set hp "$name"
18146					if {![regexp {:[0-9][0-9]*$} $hp]} {
18147						set hp "$name:0"
18148					}
18149				}
18150			}
18151			regsub -all {[^[:alnum:],./:@%_=+-]} $hp "" hp
18152			$m add command -label "$name - $hp" -command "set vncdisplay \"$hp\""
18153			incr count
18154		}
18155	}
18156	$b configure -state normal
18157	.  config -cursor {}
18158	$b config -cursor {}
18159	if {$count == 0}  {
18160		$m add command -label $none
18161	}
18162	set last_post [clock seconds]
18163}
18164
18165proc check_zeroconf_browse {} {
18166	global is_windows zeroconf_command
18167
18168	set zeroconf_command ""
18169	if {$is_windows} {
18170		return 0;
18171	}
18172	set p ""
18173	set r [catch {set p [exec /bin/sh -c {type avahi-browse}]}]
18174	if {$r == 0} {
18175		regsub {^.* is  *} $p "" p
18176		regsub -all {[ \t\n\r]} $p "" p
18177		if [file exists $p] {
18178			set zeroconf_command "avahi-browse"
18179			return 1
18180		}
18181	}
18182	set p ""
18183	set r [catch {set p [exec /bin/sh -c {type dns-sd}]}]
18184	if {$r == 0} {
18185		regsub {^.* is  *} $p "" p
18186		regsub -all {[ \t\n\r]} $p "" p
18187		if [file exists $p] {
18188			set zeroconf_command "dns-sd"
18189			global env
18190			if [info exists env(USE_MDNS)] {
18191				# testing
18192				set zeroconf_command "mDNS"
18193			}
18194			return 1
18195		}
18196	}
18197	set p ""
18198	set r [catch {set p [exec /bin/sh -c {type mDNS}]}]
18199	if {$r == 0} {
18200		regsub {^.* is  *} $p "" p
18201		regsub -all {[ \t\n\r]} $p "" p
18202		if [file exists $p] {
18203			set zeroconf_command "mDNS"
18204			return 1
18205		}
18206	}
18207	return 0
18208}
18209
18210proc toggle_no_encryption {{rev 0}} {
18211	global showing_no_encryption
18212	global no_enc_button no_enc_prev
18213	global ts_only ssh_only
18214	global use_ssl use_ssh use_sshssl
18215
18216	if {$rev} {
18217		# reverse it first
18218		if {$showing_no_encryption} {
18219			set showing_no_encryption 0
18220		} else {
18221			set showing_no_encryption 1
18222		}
18223	}
18224
18225	if {$showing_no_encryption} {
18226		catch {pack forget .f4.none}
18227		catch {pack forget $no_enc_button}
18228		if {!$use_ssl && !$use_ssh && !$use_sshssl} {
18229			set use_ssl 1
18230			sync_use_ssl_ssh
18231		}
18232		set showing_no_encryption 0
18233	} else {
18234		if {$ts_only || $ssh_only} {
18235			return
18236		}
18237		catch {pack .f4.none -side left}
18238		if {![info exists no_enc_button]} {
18239			catch {destroy .o}
18240		} elseif {![winfo exists $no_enc_button]} {
18241			catch {destroy .o}
18242		} else {
18243			catch {pack $no_enc_button -after $no_enc_prev -fill x}
18244		}
18245		set showing_no_encryption 1
18246	}
18247}
18248
18249proc toggle_vnc_prefix {} {
18250	global vncdisplay
18251	if [regexp -nocase {^vnc://} $vncdisplay] {
18252		regsub -nocase {^vnc://} $vncdisplay "" vncdisplay
18253	} else {
18254		regsub -nocase {^[a-z0-9+]*://} $vncdisplay "" vncdisplay
18255		set vncdisplay "Vnc://$vncdisplay"
18256	}
18257	catch {.f0.e icursor end}
18258}
18259
18260############################################
18261
18262global env
18263
18264if {[regexp -nocase {Windows.9} $tcl_platform(os)]} {
18265	set is_win9x 1
18266} else {
18267	set is_win9x 0
18268}
18269
18270set is_windows 0
18271if { [regexp -nocase {Windows} $tcl_platform(os)]} {
18272	set is_windows 1
18273}
18274
18275set uname ""
18276if {! $is_windows} {
18277	catch {set uname [exec uname]}
18278}
18279
18280set ffont "fixed"
18281
18282global have_ipv6
18283set have_ipv6 ""
18284check_for_ipv6
18285
18286# need to check if "fixed" font under XFT on tk8.5 is actually fixed width!!
18287if {$tcl_platform(platform) == "unix"} {
18288	set ls ""
18289	catch {set ls [font metrics $ffont -linespace]}
18290	set fs ""
18291	catch {set fs [font metrics $ffont -fixed]}
18292	set redo 0
18293	if {$fs != "" && $fs != "1"} {
18294		set redo 1
18295	}
18296	if {$ls != "" && $ls > 14} {
18297		set redo 1
18298	}
18299	if {$redo} {
18300		foreach fn [font names] {
18301			if {$fn == "TkFixedFont"} {
18302				set ffont $fn
18303				break
18304			}
18305		}
18306	}
18307	catch {option add *Dialog.msg.font {helvetica -14 bold}}
18308	catch {option add *Dialog.msg.wrapLength 4i}
18309}
18310
18311if {$uname == "Darwin"} {
18312	set ffont "Monaco 10"
18313
18314	#option add *Button.font Helvetica widgetDefault
18315	catch {option add *Button.font {System 10} widgetDefault}
18316}
18317
18318# set SSVNC_HOME to HOME in case we modify it for mobile use:
18319if [info exists env(HOME)] {
18320	if {! [info exists env(SSVNC_HOME)]} {
18321		set env(SSVNC_HOME) $env(HOME)
18322	}
18323}
18324
18325# For mobile use, e.g. from a USB flash drive, we look for a "home" or "Home"
18326# directory relative to this script where the profiles and certs will be kept
18327# by default.
18328if [file exists $buck_zero] {
18329	#puts "$buck_zero"
18330	set up [file dirname $buck_zero]
18331
18332	if {$up == "."} {
18333		# this is actually bad news on windows because we cd'd to util.
18334		set up ".."
18335	} else {
18336		set up [file dirname $up]
18337	}
18338	set dirs [list $up]
18339
18340	if {! $is_windows && $up != ".."} {
18341		# get rid of bin
18342		set up [file dirname $up]
18343		lappend dirs $up
18344	}
18345
18346	for {set i 0} {$i < $argc} {incr i} {
18347		set it0 [lindex $argv $i]
18348		if {$it0 == "."} {
18349			if {![file isdirectory "$up/home"] && ![file isdirectory "$up/Home"]} {
18350				catch {file mkdir "$up/Home"}
18351			}
18352			break
18353		}
18354	}
18355
18356	set gotone 0
18357
18358	foreach d $dirs {
18359		set try "$d/home"
18360		#puts "$try"
18361		if [file isdirectory $try] {
18362			set env(SSVNC_HOME) $try
18363			set gotone 1
18364			break
18365		}
18366		set try "$d/Home"
18367		#puts "$try"
18368		if [file isdirectory $try] {
18369			set env(SSVNC_HOME) $try
18370			set gotone 1
18371			break
18372		}
18373	}
18374	if {$gotone} {
18375		set b ""
18376		if {$is_windows} {
18377			set b "$env(SSVNC_HOME)/ss_vnc"
18378		} else {
18379			set b "$env(SSVNC_HOME)/.vnc"
18380		}
18381		catch {file mkdir $b}
18382		catch {file mkdir "$b/certs"}
18383		catch {file mkdir "$b/profiles"}
18384	}
18385	#puts "HOME: $env(SSVNC_HOME)"
18386}
18387
18388global svcert_default mycert_default crlfil_default
18389global svcert_default_force mycert_default_force crlfil_default_force
18390set svcert_default ""
18391set mycert_default ""
18392set crlfil_default ""
18393set svcert_default_force 0
18394set mycert_default_force 0
18395set crlfil_default_force 0
18396
18397set saw_ts_only 0
18398set saw_ssh_only 0
18399
18400set ssvncrc $env(SSVNC_HOME)/.ssvncrc
18401if {$is_windows} {
18402	set ssvncrc $env(SSVNC_HOME)/ssvnc_rc
18403}
18404
18405global ts_desktop_size_def ts_desktop_depth_def ts_desktop_type_def ts_xserver_type_def
18406set ts_desktop_size_def ""
18407set ts_desktop_depth_def ""
18408set ts_desktop_type_def ""
18409set ts_xserver_type_def ""
18410
18411global win_localhost
18412set win_localhost "127.0.0.1"
18413
18414global kill_stunnel
18415set kill_stunnel 1
18416
18417global started_with_noenc
18418
18419if {! [info exists env(SSVNC_DISABLE_ENCRYPTION_BUTTON)]} {
18420	set env(SSVNC_DISABLE_ENCRYPTION_BUTTON) 1
18421	set started_with_noenc 1
18422} else {
18423	if {$env(SSVNC_DISABLE_ENCRYPTION_BUTTON) == "0"} {
18424		set started_with_noenc 0
18425	} elseif {$env(SSVNC_DISABLE_ENCRYPTION_BUTTON) == "1"} {
18426		set started_with_noenc 1
18427	} else {
18428		set env(SSVNC_DISABLE_ENCRYPTION_BUTTON) 1
18429		set started_with_noenc 1
18430	}
18431}
18432
18433if [file exists $ssvncrc] {
18434	set fh ""
18435	catch {set fh [open $ssvncrc "r"]}
18436	if {$fh != ""} {
18437		while {[gets $fh line] > -1} {
18438			set str [string trim $line]
18439			if [regexp {^#} $str] {
18440				continue
18441			}
18442			if [regexp {^mode=tsvnc} $str] {
18443				set saw_ts_only 1
18444				set saw_ssh_only 0
18445			} elseif [regexp {^mode=sshvnc} $str] {
18446				set saw_ts_only 0
18447				set saw_ssh_only 1
18448			} elseif [regexp {^mode=ssvnc} $str] {
18449				set saw_ts_only 0
18450				set saw_ssh_only 0
18451			}
18452			if [regexp {^desktop_type=(.*)$} $str m val] {
18453				set val [string trim $val]
18454				set ts_desktop_type_def $val
18455			}
18456			if [regexp {^desktop_size=(.*)$} $str m val] {
18457				set val [string trim $val]
18458				set ts_desktop_size_def $val
18459			}
18460			if [regexp {^desktop_depth=(.*)$} $str m val] {
18461				set val [string trim $val]
18462				set ts_desktop_depth_def $val
18463			}
18464			if [regexp {^xserver_type=(.*)$} $str m val] {
18465				set val [string trim $val]
18466				set ts_xserver_type_def $val
18467			}
18468			if [regexp {^font_default=(.*)$} $str m val] {
18469				set val [string trim $val]
18470				catch {option add *font $val}
18471				catch {option add *Dialog.msg.font $val}
18472			}
18473			if [regexp {^font_fixed=(.*)$} $str m val] {
18474				set val [string trim $val]
18475				set ffont $val
18476			}
18477			if [regexp {^noenc=1} $str] {
18478				global env
18479				set env(SSVNC_DISABLE_ENCRYPTION_BUTTON) 1
18480				set started_with_noenc 1
18481			}
18482			if [regexp {^noenc=0} $str] {
18483				global env
18484				set env(SSVNC_DISABLE_ENCRYPTION_BUTTON) 0
18485				set started_with_noenc 0
18486			}
18487			if [regexp {^cotvnc=1} $str] {
18488				global env
18489				set env(SSVNC_COTVNC) 1
18490			}
18491			if [regexp {^cotvnc=0} $str] {
18492				global env
18493				set env(SSVNC_COTVNC) 0
18494			}
18495			if [regexp {^killstunnel=1} $str] {
18496				set kill_stunnel 1
18497			}
18498			if [regexp {^killstunnel=0} $str] {
18499				set kill_stunnel 0
18500			}
18501			global have_ipv6
18502			if [regexp {^ipv6=1} $str] {
18503				set have_ipv6 1
18504				set env(SSVNC_IPV6) 1
18505			}
18506			if [regexp {^ipv6=0} $str] {
18507				set have_ipv6 0
18508				set env(SSVNC_IPV6) 0
18509			}
18510			if [regexp {^mycert=(.*)$} $str m val] {
18511				set val [string trim $val]
18512				set mycert_default $val
18513			}
18514			if [regexp {^cert=(.*)$} $str m val] {
18515				set val [string trim $val]
18516				set mycert_default $val
18517			}
18518			if [regexp {^cacert=(.*)$} $str m val] {
18519				set val [string trim $val]
18520				set svcert_default $val
18521			}
18522			if [regexp {^ca=(.*)$} $str m val] {
18523				set val [string trim $val]
18524				set svcert_default $val
18525			}
18526			if [regexp {^crl=(.*)$} $str m val] {
18527				set val [string trim $val]
18528				set crlfil_default $val
18529			}
18530			if [regexp {^env=([^=]*)=(.*)$} $str m var val] {
18531				global env
18532				set env($var) $val
18533			}
18534		}
18535		close $fh
18536	}
18537}
18538
18539for {set i 0} {$i < $argc} {incr i} {
18540	set item [lindex $argv $i]
18541	regsub {^--} $item "-" item
18542	if {$item == "-profiles" || $item == "-list"} {
18543		set dir [get_profiles_dir]
18544		#puts stderr "VNC Profiles:"
18545		#puts stderr " "
18546		if {[info exists env(SSVNC_TS_ONLY)]} {
18547			set saw_ts_only 1
18548		} elseif {[info exists env(SSVNC_SSH_ONLY)]} {
18549			set saw_ssh_only 1
18550		}
18551		set profs [list]
18552		foreach prof [glob -nocomplain -directory $dir "*.vnc"] {
18553			set s [file tail $prof]
18554			regsub {\.vnc$} $s "" s
18555			if {$saw_ts_only || $saw_ssh_only} {
18556				set ok 0;
18557				set tsok 0;
18558				set fh ""
18559				catch {set fh [open $prof "r"]}
18560				if {$fh != ""} {
18561					while {[gets $fh line] > -1} {
18562						if {[regexp {use_ssh=1} $line]} {
18563							set ok 1
18564						}
18565						if {[regexp {ts_mode=1} $line]} {
18566							set tsok 1
18567						}
18568					}
18569					close $fh
18570				}
18571				if {$saw_ts_only && !$tsok} {
18572					continue;
18573				} elseif {! $ok} {
18574					continue
18575				}
18576			}
18577			lappend profs $s
18578		}
18579		foreach prof [lsort $profs] {
18580			puts "$prof"
18581		}
18582		exit
18583	} elseif {$item == "-nvb"} {
18584		global env
18585		set env(SSVNC_NO_VERIFY_ALL_BUTTON) 1
18586	} elseif {$item == "-noenc"} {
18587		global env
18588		set env(SSVNC_DISABLE_ENCRYPTION_BUTTON) 1
18589		set started_with_noenc 1
18590	} elseif {$item == "-enc"} {
18591		global env
18592		set env(SSVNC_DISABLE_ENCRYPTION_BUTTON) 0
18593	} elseif {$item == "-bigger"} {
18594		global env
18595		if {![info exists env(SSVNC_BIGGER_DIALOG)]} {
18596			set env(SSVNC_BIGGER_DIALOG) 1
18597		}
18598	} elseif {$item == "-ssh"} {
18599		set saw_ssh_only 1
18600		set saw_ts_only 0
18601	} elseif {$item == "-ts"} {
18602		set saw_ts_only 1
18603		set saw_ssh_only 0
18604	} elseif {$item == "-ssl" || $item == "-ss"} {
18605		set saw_ts_only 0
18606		set saw_ssh_only 0
18607	} elseif {$item == "-tso"} {
18608		global env
18609		set env(SSVNC_TS_ALWAYS) 1
18610		set saw_ts_only 1
18611	} elseif {$item == "-killstunnel"} {
18612		set kill_stunnel 1
18613	} elseif {$item == "-nokillstunnel"} {
18614		set kill_stunnel 0
18615	} elseif {$item == "-mycert" || $item == "-cert"} {
18616		incr i
18617		set mycert_default [lindex $argv $i]
18618	} elseif {$item == "-cacert" || $item == "-ca"} {
18619		incr i
18620		set svcert_default [lindex $argv $i]
18621	} elseif {$item == "-crl"} {
18622		incr i
18623		set crlfil_default [lindex $argv $i]
18624	}
18625}
18626
18627if [info exists env(SSVNC_FONT_FIXED)] {
18628	set ffont $env(SSVNC_FONT_FIXED)
18629}
18630
18631if [info exists env(SSVNC_FONT_DEFAULT)] {
18632	catch {option add *font $env(SSVNC_FONT_DEFAULT)}
18633	catch {option add *Dialog.msg.font $env(SSVNC_FONT_DEFAULT)}
18634}
18635
18636if [regexp {[ 	]} $ffont] {
18637	set help_font "-font \"$ffont\""
18638} else {
18639	set help_font "-font $ffont"
18640}
18641
18642if { [regexp -nocase {Windows} $tcl_platform(os)]} {
18643	cd util
18644	if {$help_font == "-font fixed"} {
18645		set help_font ""
18646	}
18647}
18648
18649if {$saw_ts_only && $saw_ssh_only} {
18650	set saw_ssh_only 0
18651}
18652
18653global ssh_only
18654set ssh_only 0
18655if {[info exists env(SSVNC_SSH_ONLY)] || $saw_ssh_only} {
18656	set ssh_only 1
18657}
18658
18659global ts_only
18660set ts_only 0
18661if {[info exists env(SSVNC_TS_ONLY)] || $saw_ts_only} {
18662	set ts_only 1
18663}
18664
18665if {$mycert_default != ""} {
18666	if [regexp -nocase {^FORCE:} $mycert_default] {
18667		set mycert_default_force 1
18668		regsub -nocase {^FORCE:} $mycert_default "" mycert_default
18669	}
18670	if {![file exists $mycert_default]} {
18671		set idir [get_idir_certs ""]
18672		set mycert_default "$idir/$mycert_default"
18673	}
18674}
18675
18676if {$svcert_default != ""} {
18677	if [regexp -nocase {^FORCE:} $svcert_default] {
18678		set svcert_default_force 1
18679		regsub -nocase {^FORCE:} $svcert_default "" svcert_default
18680	}
18681	if {![file exists $svcert_default]} {
18682		set idir [get_idir_certs ""]
18683		if {$svcert_default == "CA"} {
18684			set svcert_default "$idir/CA/cacert.pem"
18685		} else {
18686			set svcert_default "$idir/$svcert_default"
18687		}
18688	}
18689}
18690
18691if {$crlfil_default != ""} {
18692	if [regexp -nocase {^FORCE:} $crlfil_default] {
18693		set crlfil_default_force 1
18694		regsub -nocase {^FORCE:} $crlfil_default "" crlfil_default
18695	}
18696	if {![file exists $crlfil_default]} {
18697		set idir [get_idir_certs ""]
18698		set crlfil_default "$idir/$crlfil_default"
18699	}
18700}
18701
18702if {$is_windows} {
18703	check_writable
18704}
18705
18706
18707set darwin_cotvnc 0
18708if {$uname == "Darwin"} {
18709	if {! [info exists env(DISPLAY)]} {
18710		set darwin_cotvnc 1
18711	} elseif {[regexp {/tmp/} $env(DISPLAY)]} {
18712		set darwin_cotvnc 1
18713	}
18714	if [info exists env(SSVNC_HOME)] {
18715		set t "$env(SSVNC_HOME)/.vnc"
18716		if {! [file exists $t]} {
18717			catch {file mkdir $t}
18718		}
18719	}
18720}
18721
18722##for testing macosx
18723if [info exists env(FORCE_DARWIN)] {
18724	set uname Darwin
18725	set darwin_cotvnc 1
18726}
18727
18728set putty_pw ""
18729
18730global scroll_text_focus
18731set scroll_text_focus 1
18732
18733set multientry 1
18734
18735wm withdraw .
18736if {$ssh_only} {
18737	wm title . "SSH VNC Viewer"
18738} elseif {$ts_only} {
18739	wm title . "Terminal Services VNC Viewer"
18740} else {
18741	wm title . "SSL/SSH VNC Viewer"
18742}
18743
18744wm resizable . 1 0
18745
18746set_defaults
18747if {$uname == "Darwin"} {
18748	if [info exists use_x11_macosx] {
18749		if {$use_x11_macosx} {
18750			set darwin_cotvnc 0
18751		}
18752	}
18753}
18754set skip_pre 0
18755
18756set vncdisplay ""
18757set last_load ""
18758set vncproxy ""
18759set remote_ssh_cmd ""
18760set vncauth_passwd ""
18761
18762global did_listening_message
18763set did_listening_message 0
18764
18765global accepted_cert_dialog_in_progress
18766set accepted_cert_dialog_in_progress 0
18767
18768global fetch_cert_filename
18769set fetch_cert_filename ""
18770
18771set vhd "VNC Host:Display"
18772if {$ssh_only} {
18773	label .l -text "SSH VNC Viewer" -relief ridge
18774} elseif {$ts_only} {
18775	label .l -text "Terminal Services VNC Viewer" -relief ridge
18776	set vhd "VNC Terminal Server:"
18777} else {
18778	label .l -text "SSL/SSH VNC Viewer" -relief ridge
18779}
18780
18781set wl 21
18782set we 40
18783frame .f0
18784if {$multientry} {
18785	label .f0.l -width $wl -anchor w -text "$vhd" -relief ridge
18786} else {
18787	label .f0.l -anchor w -text "$vhd" -relief ridge
18788}
18789entry .f0.e -width $we -textvariable vncdisplay
18790pack  .f0.l -side left
18791bind  .f0.e <Return> launch
18792bind  .f0.e <Control-E> {toggle_vnc_prefix}
18793pack  .f0.e -side left -expand 1 -fill x
18794
18795if {[check_zeroconf_browse]} {
18796	menubutton .f0.mb -relief ridge -menu .f0.mb.m -text "Find"
18797	menu .f0.mb.m -tearoff 0 -postcommand {zeroconf_fill .f0.mb .f0.mb.m}
18798	pack  .f0.mb -side left
18799}
18800
18801frame .f1
18802label .f1.l -width $wl -anchor w -text "VNC Password:" -relief ridge
18803entry .f1.e -width $we -textvariable vncauth_passwd -show *
18804pack  .f1.l -side left
18805pack  .f1.e -side left -expand 1 -fill x
18806bind  .f1.e <Return> launch
18807
18808frame .fu
18809label .fu.l -width $wl -anchor w -text "Unix Username:" -relief ridge
18810entry .fu.e -width 14 -textvariable unixpw_username
18811label .fu.m -anchor w -text "Unix Password:" -relief ridge
18812entry .fu.f -textvariable unixpw_passwd -show *
18813pack  .fu.l -side left
18814pack  .fu.e .fu.m -side left
18815pack  .fu.f -side left -expand 1 -fill x
18816bind  .fu.f <Return> launch
18817
18818frame .f2
18819label .f2.l -width $wl -anchor w -text "Proxy/Gateway:" -relief ridge
18820entry .f2.e -width $we -textvariable vncproxy
18821pack  .f2.l -side left
18822pack  .f2.e -side left -expand 1 -fill x
18823bind  .f2.e <Return> launch
18824
18825frame .f3
18826label .f3.l -width $wl -anchor w -text "Remote SSH Command:" -relief ridge
18827entry .f3.e -width $we -textvariable remote_ssh_cmd
18828pack  .f3.l -side left
18829pack  .f3.e -side left -expand 1 -fill x
18830.f3.l configure -state disabled
18831.f3.e configure -state disabled
18832bind  .f3.e <Return> launch
18833
18834set remote_ssh_cmd_list {.f3.e .f3.l}
18835
18836frame .f4
18837radiobutton .f4.ssl -anchor w    -variable sshssl_sw -value ssl    -command {ssl_ssh_adjust ssl}    -text "Use SSL"
18838radiobutton .f4.ssh -anchor w    -variable sshssl_sw -value ssh    -command {ssl_ssh_adjust ssh}    -text "Use SSH"
18839radiobutton .f4.sshssl -anchor w -variable sshssl_sw -value sshssl -command {ssl_ssh_adjust sshssl} -text "SSH+SSL"
18840pack .f4.ssl .f4.ssh .f4.sshssl -side left -fill x
18841
18842set showing_no_encryption 0
18843radiobutton .f4.none   -anchor w -variable sshssl_sw -value none   -command {ssl_ssh_adjust none}   -text "None   "
18844if [disable_encryption] {
18845	pack .f4.none -side left
18846	set showing_no_encryption 1
18847}
18848
18849global skip_verify_accepted_certs
18850set skip_verify_accepted_certs 0
18851global anon_dh_detected
18852set anon_dh_detected 0
18853global vencrypt_detected
18854set vencrypt_detected ""
18855
18856global always_verify_ssl
18857set always_verify_ssl 1;
18858if {[info exists env(SSVNC_NO_VERIFY_ALL)]} {
18859	set always_verify_ssl 0;
18860}
18861
18862if {$uname == "Darwin"} {
18863	button .f4.getcert -command {fetch_cert 1} -text "Fetch Cert"
18864} else {
18865	button .f4.getcert -command {fetch_cert 1} -text "Fetch Cert" -padx 3
18866}
18867checkbutton .f4.always -variable always_verify_ssl -text "Verify All Certs" -command no_certs_tutorial_mesg
18868pack .f4.getcert -side right -fill x
18869if {[info exists env(SSVNC_NO_VERIFY_ALL_BUTTON)]} {
18870	set always_verify_ssl 0;
18871} else {
18872	pack .f4.always -side right -fill x
18873}
18874
18875if {$ssh_only || $ts_only} {
18876	ssl_ssh_adjust ssh
18877} else {
18878	ssl_ssh_adjust ssl
18879}
18880
18881frame .b
18882button .b.help  -text "Help" -command help
18883button .b.certs -text "Certs ..." -command getcerts
18884button .b.opts  -text "Options ..." -command set_options
18885button .b.load  -text "Load" -command {load_profile}
18886button .b.save  -text "Save" -command {save_profile}
18887button .b.conn  -text "Connect" -command launch
18888button .b.exit  -text "Exit" -command {destroy .; exit}
18889
18890
18891if {$ssh_only || $ts_only} {
18892	pack          .b.opts .b.save .b.load .b.conn .b.help .b.exit -side left -expand 1 -fill x
18893} else {
18894	pack .b.certs .b.opts .b.save .b.load .b.conn .b.help .b.exit -side left -expand 1 -fill x
18895}
18896
18897if {$multientry} {
18898	if {! $is_windows} {
18899		if {$ssh_only} {
18900			pack .l .f0 .f1 .f2 .f3     .b -side top -fill x
18901		} elseif {$ts_only} {
18902			pack .l .f0     .f2         .b -side top -fill x
18903		} else {
18904			pack .l .f0 .f1 .f2 .f3 .f4 .b -side top -fill x
18905		}
18906	} else {
18907		if {$ssh_only} {
18908			pack .l .f0     .f2 .f3     .b -side top -fill x
18909		} elseif {$ts_only} {
18910			pack .l .f0     .f2         .b -side top -fill x
18911		} else {
18912			pack .l .f0     .f2 .f3 .f4 .b -side top -fill x
18913		}
18914	}
18915} else {
18916	pack .l .f0 .b -side top -fill x
18917}
18918if {![info exists env(SSVNC_GUI_CHILD)] || $env(SSVNC_GUI_CHILD) == ""} {
18919	center_win .
18920}
18921focus .f0.e
18922
18923wm deiconify .
18924
18925global system_button_face
18926set system_button_face ""
18927foreach item [.b.help configure -bg] {
18928	set system_button_face $item
18929}
18930
18931if {[info exists env(SSVNC_GUI_CMD)]} {
18932	set env(SSVNC_GUI_CHILD) 1
18933	bind . <Control-n> "exec $env(SSVNC_GUI_CMD) &"
18934}
18935bind . <Control-q> "destroy .; exit"
18936bind . <Shift-Escape> "destroy .; exit"
18937bind . <Control-s> "launch_shell_only"
18938bind . <Control-p> {port_knock_only "" "KNOCK"}
18939bind . <Control-P> {port_knock_only "" "FINISH"}
18940bind . <Control-l> {load_profile}
18941bind . <B3-ButtonRelease> {load_profile}
18942
18943bind . <Control-t> {toggle_tsonly}
18944bind . <Control-d> {delete_profile}
18945bind . <Shift-B3-ButtonRelease> {toggle_tsonly}
18946bind . <Shift-B2-ButtonRelease> {toggle_tsonly}
18947bind .l <Shift-ButtonRelease> {toggle_tsonly}
18948bind . <Control-h> {toggle_sshonly}
18949bind . <Control-T> {to_ssvnc}
18950bind . <Control-a> {set_advanced_options}
18951bind . <Control-o> {set_options}
18952bind . <Control-u> {set_ssvncviewer_options}
18953bind . <Control-e> {toggle_no_encryption}
18954
18955global entered_gui_top button_gui_top
18956set entered_gui_top 0
18957set button_gui_top 0
18958bind . <Enter> {set entered_gui_top 1}
18959bind .l <ButtonPress> {set button_gui_top 1}
18960bind .f0.l <ButtonPress> {set button_gui_top 1}
18961
18962update
18963
18964mac_raise
18965
18966set didload 0
18967
18968for {set i 0} {$i < $argc} {incr i} {
18969	set item [lindex $argv $i]
18970	regsub {^--} $item "-" item
18971	if {$item == "."} {
18972		;
18973	} elseif {$item == "-nv"} {
18974		set always_verify_ssl 0
18975	} elseif {$item == "-help"} {
18976		help
18977	} elseif {$item == "-ssh"} {
18978		;
18979	} elseif {$item == "-bigger"} {
18980		;
18981	} elseif {$item == "-ts"} {
18982		;
18983	} elseif {$item == "-ss"} {
18984		;
18985	} elseif {$item == "-ssl"} {
18986		;
18987	} elseif {$item == "-tso"} {
18988		;
18989	} elseif {$item == "-mycert" || $item == "-cert"} {
18990		incr i
18991	} elseif {$item == "-cacert" || $item == "-ca"} {
18992		incr i
18993	} elseif {$item == "-crl"} {
18994		incr i
18995	} elseif {$item == "-printhelp"} {
18996		print_help
18997		exit;
18998	} elseif {$item != ""} {
18999		if {[file exists $item] && [file isfile $item]}  {
19000			set didload 1
19001			load_profile . $item
19002		} else {
19003			set ok 0
19004			set dir [get_profiles_dir]
19005			set try "$dir/$item"
19006			foreach try [list $dir/$item $dir/$item.vnc] {
19007				if {[file exists $try] && [file isfile $try]} {
19008					load_profile . $try
19009					set ok 1
19010					break;
19011				}
19012			}
19013			if {! $ok && [regexp {:[0-9][0-9]*$} $item]} {
19014				global vncdisplay
19015				set vncdisplay $item
19016				set ok 1
19017			}
19018
19019			if {! $ok} {
19020			    if {$ts_only || $ssh_only} {
19021				global vncdisplay
19022				set vncdisplay $item
19023				set ok 1
19024			    }
19025			}
19026			if {$ok} {
19027				update
19028				set didload 1
19029				if [info exists env(SSVNC_PROFILE_LOADONLY)] {
19030					if {$env(SSVNC_PROFILE_LOADONLY) == "1"} {
19031						set ok 0
19032					}
19033				}
19034				if {$ok} {
19035					after 750
19036					launch
19037				}
19038			}
19039		}
19040	}
19041}
19042