1 diff -Naur vnc_javasrc.orig/Makefile vnc_javasrc/Makefile 2 --- vnc_javasrc.orig/Makefile 2004-03-04 08:34:25.000000000 -0500 3 +++ vnc_javasrc/Makefile 2010-05-18 20:56:26.000000000 -0400 4 @@ -4,6 +4,7 @@ 5 6 CP = cp 7 JC = javac 8 +JC_ARGS = -target 1.4 -source 1.4 9 JAR = jar 10 ARCHIVE = VncViewer.jar 11 MANIFEST = MANIFEST.MF 12 @@ -15,25 +16,29 @@ 13 DesCipher.class CapabilityInfo.class CapsContainer.class \ 14 RecordingFrame.class SessionRecorder.class AuthUnixLoginPanel.class \ 15 SocketFactory.class HTTPConnectSocketFactory.class \ 16 - HTTPConnectSocket.class ReloginPanel.class 17 + HTTPConnectSocket.class ReloginPanel.class \ 18 + SSLSocketToMe.class 19 + 20 +SSL_CLASSES = SSLSocketToMe*.class TrustDialog.class 21 22 SOURCES = VncViewer.java RfbProto.java AuthPanel.java VncCanvas.java \ 23 OptionsFrame.java ClipboardFrame.java ButtonPanel.java \ 24 DesCipher.java CapabilityInfo.java CapsContainer.java \ 25 RecordingFrame.java SessionRecorder.java AuthUnixLoginPanel.java \ 26 SocketFactory.java HTTPConnectSocketFactory.java \ 27 - HTTPConnectSocket.java ReloginPanel.java 28 + HTTPConnectSocket.java ReloginPanel.java \ 29 + SSLSocketToMe.java 30 31 all: $(CLASSES) $(ARCHIVE) 32 33 $(CLASSES): $(SOURCES) 34 - $(JC) -target 1.1 -O $(SOURCES) 35 + $(JC) $(JC_ARGS) -O $(SOURCES) 36 37 $(ARCHIVE): $(CLASSES) $(MANIFEST) 38 - $(JAR) cfm $(ARCHIVE) $(MANIFEST) $(CLASSES) 39 + $(JAR) cfm $(ARCHIVE) $(MANIFEST) $(CLASSES) $(SSL_CLASSES) 40 41 install: $(CLASSES) $(ARCHIVE) 42 - $(CP) $(CLASSES) $(ARCHIVE) $(PAGES) $(INSTALL_DIR) 43 + $(CP) $(CLASSES) $(SSL_CLASSES) $(ARCHIVE) $(PAGES) $(INSTALL_DIR) 44 45 export:: $(CLASSES) $(ARCHIVE) $(PAGES) 46 @$(ExportJavaClasses) 47 diff -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto.java 48 --- vnc_javasrc.orig/RfbProto.java 2004-03-04 08:34:25.000000000 -0500 49 +++ vnc_javasrc/RfbProto.java 2010-11-30 22:05:12.000000000 -0500 50 @@ -199,7 +199,21 @@ 51 host = h; 52 port = p; 53 54 - if (viewer.socketFactory == null) { 55 + if (! viewer.disableSSL) { 56 + System.out.println("new SSLSocketToMe"); 57 + SSLSocketToMe ssl; 58 + try { 59 + ssl = new SSLSocketToMe(host, port, v); 60 + } catch (Exception e) { 61 + throw new IOException(e.getMessage()); 62 + } 63 + 64 + try { 65 + sock = ssl.connectSock(); 66 + } catch (Exception es) { 67 + throw new IOException(es.getMessage()); 68 + } 69 + } else if (viewer.socketFactory == null) { 70 sock = new Socket(host, port); 71 } else { 72 try { 73 @@ -255,7 +269,7 @@ 74 || (b[10] < '0') || (b[10] > '9') || (b[11] != '\n')) 75 { 76 throw new Exception("Host " + host + " port " + port + 77 - " is not an RFB server"); 78 + " is not an RFB server: " + b); 79 } 80 81 serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0'); 82 @@ -892,6 +906,38 @@ 83 final static int ALT_MASK = InputEvent.ALT_MASK; 84 85 86 + void writeWheelEvent(MouseWheelEvent evt) throws IOException { 87 + 88 + eventBufLen = 0; 89 + 90 + int x = evt.getX(); 91 + int y = evt.getY(); 92 + 93 + if (x < 0) x = 0; 94 + if (y < 0) y = 0; 95 + 96 + int ptrmask; 97 + 98 + int clicks = evt.getWheelRotation(); 99 + System.out.println("writeWheelEvent: clicks: " + clicks); 100 + if (clicks > 0) { 101 + ptrmask = 16; 102 + } else if (clicks < 0) { 103 + ptrmask = 8; 104 + } else { 105 + return; 106 + } 107 + 108 + eventBuf[eventBufLen++] = (byte) PointerEvent; 109 + eventBuf[eventBufLen++] = (byte) ptrmask; 110 + eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff); 111 + eventBuf[eventBufLen++] = (byte) (x & 0xff); 112 + eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff); 113 + eventBuf[eventBufLen++] = (byte) (y & 0xff); 114 + 115 + os.write(eventBuf, 0, eventBufLen); 116 + } 117 + 118 // 119 // Write a pointer event message. We may need to send modifier key events 120 // around it to set the correct modifier state. 121 @@ -992,6 +1038,19 @@ 122 boolean down = (evt.getID() == KeyEvent.KEY_PRESSED); 123 124 int key; 125 + if (viewer.debugKeyboard) { 126 + System.out.println("----------------------------------------"); 127 + System.out.println("evt.getKeyChar: " + evt.getKeyChar()); 128 + System.out.println("getKeyText: " + KeyEvent.getKeyText(evt.getKeyCode())); 129 + System.out.println("evt.getKeyCode: " + evt.getKeyCode()); 130 + System.out.println("evt.getID: " + evt.getID()); 131 + System.out.println("evt.getKeyLocation: " + evt.getKeyLocation()); 132 + System.out.println("evt.isActionKey: " + evt.isActionKey()); 133 + System.out.println("evt.isControlDown: " + evt.isControlDown()); 134 + System.out.println("evt.getModifiers: " + evt.getModifiers()); 135 + System.out.println("getKeyModifiersText: " + KeyEvent.getKeyModifiersText(evt.getModifiers())); 136 + System.out.println("evt.paramString: " + evt.paramString()); 137 + } 138 if (evt.isActionKey()) { 139 140 // 141 @@ -1025,6 +1084,13 @@ 142 return; 143 } 144 145 + if(key == 0xffc2 && viewer.mapF5_to_atsign) { 146 + if (viewer.debugKeyboard) { 147 + System.out.println("Mapping: F5 -> AT "); 148 + } 149 + key = 0x40; 150 + } 151 + 152 } else { 153 154 // 155 @@ -1036,6 +1102,7 @@ 156 157 key = keyChar; 158 159 + 160 if (key < 0x20) { 161 if (evt.isControlDown()) { 162 key += 0x60; 163 @@ -1121,6 +1188,16 @@ 164 int oldModifiers = 0; 165 166 void writeModifierKeyEvents(int newModifiers) { 167 + if(viewer.forbid_Ctrl_Alt) { 168 + if ((newModifiers & CTRL_MASK) != 0 && (newModifiers & ALT_MASK) != 0) { 169 + int orig = newModifiers; 170 + newModifiers &= ~ALT_MASK; 171 + newModifiers &= ~CTRL_MASK; 172 + if (viewer.debugKeyboard) { 173 + System.out.println("Ctrl+Alt modifiers: " + orig + " -> " + newModifiers); 174 + } 175 + } 176 + } 177 if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK)) 178 writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0); 179 180 diff -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSLSocketToMe.java 181 --- vnc_javasrc.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500 182 +++ vnc_javasrc/SSLSocketToMe.java 2010-07-10 19:18:06.000000000 -0400 183 @@ -0,0 +1,2067 @@ 184 +/* 185 + * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. 186 + * 187 + * Copyright (c) 2006 Karl J. Runge <runge (a] karlrunge.com> 188 + * All rights reserved. 189 + * 190 + * This is free software; you can redistribute it and/or modify 191 + * it under the terms of the GNU General Public License as published by 192 + * the Free Software Foundation; version 2 of the License, or 193 + * (at your option) any later version. 194 + * 195 + * This software is distributed in the hope that it will be useful, 196 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 197 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 198 + * GNU General Public License for more details. 199 + * 200 + * You should have received a copy of the GNU General Public License 201 + * along with this software; if not, write to the Free Software 202 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 203 + * USA. 204 + * 205 + */ 206 + 207 +import java.net.*; 208 +import java.io.*; 209 +import javax.net.ssl.*; 210 +import java.util.*; 211 + 212 +import java.security.*; 213 +import java.security.cert.*; 214 +import java.security.spec.*; 215 +import java.security.cert.Certificate; 216 +import java.security.cert.CertificateFactory; 217 + 218 +import java.awt.*; 219 +import java.awt.event.*; 220 + 221 +public class SSLSocketToMe { 222 + 223 + /* basic member data: */ 224 + String host; 225 + int port; 226 + VncViewer viewer; 227 + 228 + boolean debug = true; 229 + boolean debug_certs = false; 230 + 231 + /* sockets */ 232 + SSLSocket socket = null; 233 + SSLSocketFactory factory; 234 + 235 + /* fallback for Proxy connection */ 236 + boolean proxy_in_use = false; 237 + boolean proxy_failure = false; 238 + public DataInputStream is = null; 239 + public OutputStream os = null; 240 + 241 + /* strings from user WRT proxy: */ 242 + String proxy_auth_string = null; 243 + String proxy_dialog_host = null; 244 + int proxy_dialog_port = 0; 245 + 246 + Socket proxySock; 247 + DataInputStream proxy_is; 248 + OutputStream proxy_os; 249 + 250 + /* trust contexts */ 251 + SSLContext trustloc_ctx; 252 + SSLContext trustall_ctx; 253 + SSLContext trustsrv_ctx; 254 + SSLContext trusturl_ctx; 255 + SSLContext trustone_ctx; 256 + 257 + /* corresponding trust managers */ 258 + TrustManager[] trustAllCerts; 259 + TrustManager[] trustSrvCert; 260 + TrustManager[] trustUrlCert; 261 + TrustManager[] trustOneCert; 262 + 263 + /* client-side SSL auth key (oneTimeKey=...) */ 264 + KeyManager[] mykey = null; 265 + 266 + boolean user_wants_to_see_cert = true; 267 + String cert_fail = null; 268 + 269 + /* cert(s) we retrieve from Web server, VNC server, or serverCert param: */ 270 + java.security.cert.Certificate[] trustallCerts = null; 271 + java.security.cert.Certificate[] trustsrvCerts = null; 272 + java.security.cert.Certificate[] trusturlCerts = null; 273 + 274 + /* utility to decode hex oneTimeKey=... and serverCert=... */ 275 + byte[] hex2bytes(String s) { 276 + byte[] bytes = new byte[s.length()/2]; 277 + for (int i=0; i<s.length()/2; i++) { 278 + int j = 2*i; 279 + try { 280 + int val = Integer.parseInt(s.substring(j, j+2), 16); 281 + if (val > 127) { 282 + val -= 256; 283 + } 284 + Integer I = new Integer(val); 285 + bytes[i] = Byte.decode(I.toString()).byteValue(); 286 + 287 + } catch (Exception e) { 288 + ; 289 + } 290 + } 291 + return bytes; 292 + } 293 + 294 + SSLSocketToMe(String h, int p, VncViewer v) throws Exception { 295 + host = h; 296 + port = p; 297 + viewer = v; 298 + 299 + debug_certs = v.debugCerts; 300 + 301 + /* we will first try default factory for certification: */ 302 + 303 + factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); 304 + 305 + dbg("SSL startup: " + host + " " + port); 306 + 307 + 308 + /* create trust managers to be used if initial handshake fails: */ 309 + 310 + trustAllCerts = new TrustManager[] { 311 + /* 312 + * this one accepts everything. Only used if user 313 + * has disabled checking (trustAllVncCerts=yes) 314 + * or when we grab the cert to show it to them in 315 + * a dialog and ask them to manually verify/accept it. 316 + */ 317 + new X509TrustManager() { 318 + public java.security.cert.X509Certificate[] 319 + getAcceptedIssuers() { 320 + return null; 321 + } 322 + public void checkClientTrusted( 323 + java.security.cert.X509Certificate[] certs, 324 + String authType) { 325 + /* empty */ 326 + } 327 + public void checkServerTrusted( 328 + java.security.cert.X509Certificate[] certs, 329 + String authType) { 330 + /* empty */ 331 + dbg("ALL: an untrusted connect to grab cert."); 332 + } 333 + } 334 + }; 335 + 336 + trustUrlCert = new TrustManager[] { 337 + /* 338 + * this one accepts only the retrieved server 339 + * cert by SSLSocket by this applet and stored in 340 + * trusturlCerts. 341 + */ 342 + new X509TrustManager() { 343 + public java.security.cert.X509Certificate[] 344 + getAcceptedIssuers() { 345 + return null; 346 + } 347 + public void checkClientTrusted( 348 + java.security.cert.X509Certificate[] certs, 349 + String authType) throws CertificateException { 350 + throw new CertificateException("No Clients (URL)"); 351 + } 352 + public void checkServerTrusted( 353 + java.security.cert.X509Certificate[] certs, 354 + String authType) throws CertificateException { 355 + /* we want to check 'certs' against 'trusturlCerts' */ 356 + if (trusturlCerts == null) { 357 + throw new CertificateException( 358 + "No Trust url Certs array."); 359 + } 360 + if (trusturlCerts.length < 1) { 361 + throw new CertificateException( 362 + "No Trust url Certs."); 363 + } 364 + if (certs == null) { 365 + throw new CertificateException( 366 + "No this-certs array."); 367 + } 368 + if (certs.length < 1) { 369 + throw new CertificateException( 370 + "No this-certs Certs."); 371 + } 372 + if (certs.length != trusturlCerts.length) { 373 + throw new CertificateException( 374 + "certs.length != trusturlCerts.length " + certs.length + " " + trusturlCerts.length); 375 + } 376 + boolean ok = true; 377 + for (int i = 0; i < certs.length; i++) { 378 + if (! trusturlCerts[i].equals(certs[i])) { 379 + ok = false; 380 + dbg("URL: cert mismatch at i=" + i); 381 + dbg("URL: cert mismatch cert" + certs[i]); 382 + dbg("URL: cert mismatch url" + trusturlCerts[i]); 383 + if (cert_fail == null) { 384 + cert_fail = "cert-mismatch"; 385 + } 386 + } 387 + if (debug_certs) { 388 + dbg("\n***********************************************"); 389 + dbg("URL: cert info at i=" + i); 390 + dbg("URL: cert info cert" + certs[i]); 391 + dbg("==============================================="); 392 + dbg("URL: cert info url" + trusturlCerts[i]); 393 + dbg("***********************************************"); 394 + } 395 + } 396 + if (!ok) { 397 + throw new CertificateException( 398 + "Server Cert Chain != URL Cert Chain."); 399 + } 400 + dbg("URL: trusturlCerts[i] matches certs[i] i=0:" + (certs.length-1)); 401 + } 402 + } 403 + }; 404 + 405 + trustSrvCert = new TrustManager[] { 406 + /* 407 + * this one accepts cert given to us in the serverCert 408 + * Applet Parameter we were started with. It is 409 + * currently a fatal error if the VNC Server's cert 410 + * doesn't match it. 411 + */ 412 + new X509TrustManager() { 413 + public java.security.cert.X509Certificate[] 414 + getAcceptedIssuers() { 415 + return null; 416 + } 417 + public void checkClientTrusted( 418 + java.security.cert.X509Certificate[] certs, 419 + String authType) throws CertificateException { 420 + throw new CertificateException("No Clients (SRV)"); 421 + } 422 + public void checkServerTrusted( 423 + java.security.cert.X509Certificate[] certs, 424 + String authType) throws CertificateException { 425 + /* we want to check 'certs' against 'trustsrvCerts' */ 426 + if (trustsrvCerts == null) { 427 + throw new CertificateException( 428 + "No Trust srv Certs array."); 429 + } 430 + if (trustsrvCerts.length < 1) { 431 + throw new CertificateException( 432 + "No Trust srv Certs."); 433 + } 434 + if (certs == null) { 435 + throw new CertificateException( 436 + "No this-certs array."); 437 + } 438 + if (certs.length < 1) { 439 + throw new CertificateException( 440 + "No this-certs Certs."); 441 + } 442 + if (certs.length != trustsrvCerts.length) { 443 + throw new CertificateException( 444 + "certs.length != trustsrvCerts.length " + certs.length + " " + trustsrvCerts.length); 445 + } 446 + boolean ok = true; 447 + for (int i = 0; i < certs.length; i++) { 448 + if (! trustsrvCerts[i].equals(certs[i])) { 449 + ok = false; 450 + dbg("SRV: cert mismatch at i=" + i); 451 + dbg("SRV: cert mismatch cert" + certs[i]); 452 + dbg("SRV: cert mismatch srv" + trustsrvCerts[i]); 453 + if (cert_fail == null) { 454 + cert_fail = "server-cert-mismatch"; 455 + } 456 + } 457 + if (debug_certs) { 458 + dbg("\n***********************************************"); 459 + dbg("SRV: cert info at i=" + i); 460 + dbg("SRV: cert info cert" + certs[i]); 461 + dbg("==============================================="); 462 + dbg("SRV: cert info srv" + trustsrvCerts[i]); 463 + dbg("***********************************************"); 464 + } 465 + } 466 + if (!ok) { 467 + throw new CertificateException( 468 + "Server Cert Chain != serverCert Applet Parameter Cert Chain."); 469 + } 470 + dbg("SRV: trustsrvCerts[i] matches certs[i] i=0:" + (certs.length-1)); 471 + } 472 + } 473 + }; 474 + 475 + trustOneCert = new TrustManager[] { 476 + /* 477 + * this one accepts only the retrieved server 478 + * cert by SSLSocket by this applet we stored in 479 + * trustallCerts that user has accepted or applet 480 + * parameter trustAllVncCerts=yes is set. This is 481 + * for when we reconnect after the user has manually 482 + * accepted the trustall cert in the dialog (or set 483 + * trustAllVncCerts=yes applet param.) 484 + */ 485 + new X509TrustManager() { 486 + public java.security.cert.X509Certificate[] 487 + getAcceptedIssuers() { 488 + return null; 489 + } 490 + public void checkClientTrusted( 491 + java.security.cert.X509Certificate[] certs, 492 + String authType) throws CertificateException { 493 + throw new CertificateException("No Clients (ONE)"); 494 + } 495 + public void checkServerTrusted( 496 + java.security.cert.X509Certificate[] certs, 497 + String authType) throws CertificateException { 498 + /* we want to check 'certs' against 'trustallCerts' */ 499 + if (trustallCerts == null) { 500 + throw new CertificateException( 501 + "No Trust All Server Certs array."); 502 + } 503 + if (trustallCerts.length < 1) { 504 + throw new CertificateException( 505 + "No Trust All Server Certs."); 506 + } 507 + if (certs == null) { 508 + throw new CertificateException( 509 + "No this-certs array."); 510 + } 511 + if (certs.length < 1) { 512 + throw new CertificateException( 513 + "No this-certs Certs."); 514 + } 515 + if (certs.length != trustallCerts.length) { 516 + throw new CertificateException( 517 + "certs.length != trustallCerts.length " + certs.length + " " + trustallCerts.length); 518 + } 519 + boolean ok = true; 520 + for (int i = 0; i < certs.length; i++) { 521 + if (! trustallCerts[i].equals(certs[i])) { 522 + ok = false; 523 + dbg("ONE: cert mismatch at i=" + i); 524 + dbg("ONE: cert mismatch cert" + certs[i]); 525 + dbg("ONE: cert mismatch all" + trustallCerts[i]); 526 + } 527 + if (debug_certs) { 528 + dbg("\n***********************************************"); 529 + dbg("ONE: cert info at i=" + i); 530 + dbg("ONE: cert info cert" + certs[i]); 531 + dbg("==============================================="); 532 + dbg("ONE: cert info all" + trustallCerts[i]); 533 + dbg("***********************************************"); 534 + } 535 + } 536 + if (!ok) { 537 + throw new CertificateException( 538 + "Server Cert Chain != TRUSTALL Cert Chain."); 539 + } 540 + dbg("ONE: trustallCerts[i] matches certs[i] i=0:" + (certs.length-1)); 541 + } 542 + } 543 + }; 544 + 545 + /* 546 + * The above TrustManagers are used: 547 + * 548 + * 1) to retrieve the server cert in case of failure to 549 + * display it to the user in a dialog. 550 + * 2) to subsequently connect to the server if user agrees. 551 + */ 552 + 553 + /* 554 + * build oneTimeKey cert+key if supplied in applet parameter: 555 + */ 556 + if (viewer.oneTimeKey != null && viewer.oneTimeKey.equals("PROMPT")) { 557 + ClientCertDialog d = new ClientCertDialog(); 558 + viewer.oneTimeKey = d.queryUser(); 559 + } 560 + if (viewer.oneTimeKey != null && viewer.oneTimeKey.indexOf(",") > 0) { 561 + int idx = viewer.oneTimeKey.indexOf(","); 562 + 563 + String onetimekey = viewer.oneTimeKey.substring(0, idx); 564 + byte[] key = hex2bytes(onetimekey); 565 + String onetimecert = viewer.oneTimeKey.substring(idx+1); 566 + byte[] cert = hex2bytes(onetimecert); 567 + 568 + KeyFactory kf = KeyFactory.getInstance("RSA"); 569 + PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key ); 570 + PrivateKey ff = kf.generatePrivate (keysp); 571 + if (debug_certs) { 572 + dbg("one time key " + ff); 573 + } 574 + 575 + CertificateFactory cf = CertificateFactory.getInstance("X.509"); 576 + Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); 577 + Certificate[] certs = new Certificate[c.toArray().length]; 578 + if (c.size() == 1) { 579 + Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); 580 + if (debug_certs) { 581 + dbg("one time cert" + tmpcert); 582 + } 583 + certs[0] = tmpcert; 584 + } else { 585 + certs = (Certificate[]) c.toArray(); 586 + } 587 + 588 + KeyStore ks = KeyStore.getInstance("JKS"); 589 + ks.load(null, null); 590 + ks.setKeyEntry("onetimekey", ff, "".toCharArray(), certs); 591 + String da = KeyManagerFactory.getDefaultAlgorithm(); 592 + KeyManagerFactory kmf = KeyManagerFactory.getInstance(da); 593 + kmf.init(ks, "".toCharArray()); 594 + 595 + mykey = kmf.getKeyManagers(); 596 + } 597 + 598 + /* 599 + * build serverCert cert if supplied in applet parameter: 600 + */ 601 + if (viewer.serverCert != null) { 602 + CertificateFactory cf = CertificateFactory.getInstance("X.509"); 603 + byte[] cert = hex2bytes(viewer.serverCert); 604 + Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); 605 + trustsrvCerts = new Certificate[c.toArray().length]; 606 + if (c.size() == 1) { 607 + Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); 608 + trustsrvCerts[0] = tmpcert; 609 + } else { 610 + trustsrvCerts = (Certificate[]) c.toArray(); 611 + } 612 + } 613 + 614 + /* the trust loc certs context: */ 615 + try { 616 + trustloc_ctx = SSLContext.getInstance("SSL"); 617 + 618 + /* 619 + * below is a failed attempt to get jvm's default 620 + * trust manager using null (below) makes it so 621 + * for HttpsURLConnection the server cannot be 622 + * verified (no prompting.) 623 + */ 624 + if (false) { 625 + boolean didit = false; 626 + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 627 + tmf.init((KeyStore) null); 628 + TrustManager [] tml = tmf.getTrustManagers(); 629 + for (int i = 0; i < tml.length; i++) { 630 + TrustManager tm = tml[i]; 631 + if (tm instanceof X509TrustManager) { 632 + TrustManager tm1[] = new TrustManager[1]; 633 + tm1[0] = tm; 634 + trustloc_ctx.init(mykey, tm1, null); 635 + didit = true; 636 + break; 637 + } 638 + } 639 + if (!didit) { 640 + trustloc_ctx.init(mykey, null, null); 641 + } 642 + } else { 643 + /* we have to set trust manager to null */ 644 + trustloc_ctx.init(mykey, null, null); 645 + } 646 + 647 + } catch (Exception e) { 648 + String msg = "SSL trustloc_ctx FAILED."; 649 + dbg(msg); 650 + throw new Exception(msg); 651 + } 652 + 653 + /* the trust all certs context: */ 654 + try { 655 + trustall_ctx = SSLContext.getInstance("SSL"); 656 + trustall_ctx.init(mykey, trustAllCerts, new 657 + java.security.SecureRandom()); 658 + 659 + } catch (Exception e) { 660 + String msg = "SSL trustall_ctx FAILED."; 661 + dbg(msg); 662 + throw new Exception(msg); 663 + } 664 + 665 + /* the trust url certs context: */ 666 + try { 667 + trusturl_ctx = SSLContext.getInstance("SSL"); 668 + trusturl_ctx.init(mykey, trustUrlCert, new 669 + java.security.SecureRandom()); 670 + 671 + } catch (Exception e) { 672 + String msg = "SSL trusturl_ctx FAILED."; 673 + dbg(msg); 674 + throw new Exception(msg); 675 + } 676 + 677 + /* the trust srv certs context: */ 678 + try { 679 + trustsrv_ctx = SSLContext.getInstance("SSL"); 680 + trustsrv_ctx.init(mykey, trustSrvCert, new 681 + java.security.SecureRandom()); 682 + 683 + } catch (Exception e) { 684 + String msg = "SSL trustsrv_ctx FAILED."; 685 + dbg(msg); 686 + throw new Exception(msg); 687 + } 688 + 689 + /* the trust the one cert from server context: */ 690 + try { 691 + trustone_ctx = SSLContext.getInstance("SSL"); 692 + trustone_ctx.init(mykey, trustOneCert, new 693 + java.security.SecureRandom()); 694 + 695 + } catch (Exception e) { 696 + String msg = "SSL trustone_ctx FAILED."; 697 + dbg(msg); 698 + throw new Exception(msg); 699 + } 700 + } 701 + 702 + /* 703 + * we call this early on to 1) check for a proxy, 2) grab 704 + * Browser/JVM accepted HTTPS cert. 705 + */ 706 + public void check_for_proxy_and_grab_vnc_server_cert() { 707 + 708 + trusturlCerts = null; 709 + proxy_in_use = false; 710 + 711 + if (viewer.ignoreProxy) { 712 + /* applet param says skip it. */ 713 + /* the downside is we do not set trusturlCerts for comparison later... */ 714 + /* nor do we autodetect x11vnc for GET=1. */ 715 + return; 716 + } 717 + 718 + dbg("------------------------------------------------"); 719 + dbg("Into check_for_proxy_and_grab_vnc_server_cert():"); 720 + 721 + dbg("TRYING HTTPS:"); 722 + String ustr = "https://" + host + ":"; 723 + if (viewer.httpsPort != null) { 724 + ustr += viewer.httpsPort; 725 + } else { 726 + ustr += port; 727 + } 728 + ustr += viewer.urlPrefix + "/check.https.proxy.connection"; 729 + dbg("ustr is: " + ustr); 730 + 731 + try { 732 + /* prepare for an HTTPS URL connection to host:port */ 733 + URL url = new URL(ustr); 734 + HttpsURLConnection https = (HttpsURLConnection) url.openConnection(); 735 + 736 + if (mykey != null) { 737 + /* with oneTimeKey (mykey) we can't use the default SSL context */ 738 + if (trustsrvCerts != null) { 739 + dbg("passing trustsrv_ctx to HttpsURLConnection to provide client cert."); 740 + https.setSSLSocketFactory(trustsrv_ctx.getSocketFactory()); 741 + } else if (trustloc_ctx != null) { 742 + dbg("passing trustloc_ctx to HttpsURLConnection to provide client cert."); 743 + https.setSSLSocketFactory(trustloc_ctx.getSocketFactory()); 744 + } 745 + } 746 + 747 + https.setUseCaches(false); 748 + https.setRequestMethod("GET"); 749 + https.setRequestProperty("Pragma", "No-Cache"); 750 + https.setRequestProperty("Proxy-Connection", "Keep-Alive"); 751 + https.setDoInput(true); 752 + 753 + dbg("trying https.connect()"); 754 + https.connect(); 755 + 756 + dbg("trying https.getServerCertificates()"); 757 + trusturlCerts = https.getServerCertificates(); 758 + 759 + if (trusturlCerts == null) { 760 + dbg("set trusturlCerts to null!"); 761 + } else { 762 + dbg("set trusturlCerts to non-null"); 763 + } 764 + 765 + if (https.usingProxy()) { 766 + proxy_in_use = true; 767 + dbg("An HTTPS proxy is in use. There may be connection problems."); 768 + } 769 + 770 + dbg("trying https.getContent()"); 771 + Object output = https.getContent(); 772 + dbg("trying https.disconnect()"); 773 + https.disconnect(); 774 + if (! viewer.GET) { 775 + String header = https.getHeaderField("VNC-Server"); 776 + if (header != null && header.startsWith("x11vnc")) { 777 + dbg("detected x11vnc server (1), setting GET=1"); 778 + viewer.GET = true; 779 + } 780 + } 781 + 782 + } catch(Exception e) { 783 + dbg("HttpsURLConnection: " + e.getMessage()); 784 + } 785 + 786 + if (proxy_in_use) { 787 + dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); 788 + dbg("------------------------------------------------"); 789 + return; 790 + } else if (trusturlCerts != null && !viewer.forceProxy) { 791 + /* Allow user to require HTTP check? use forceProxy for now. */ 792 + dbg("SKIPPING HTTP PROXY CHECK: got trusturlCerts, assuming proxy info is correct."); 793 + dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); 794 + dbg("------------------------------------------------"); 795 + return; 796 + } 797 + 798 + /* 799 + * XXX need to remember scenario where this extra check 800 + * gives useful info. User's Browser proxy settings? 801 + */ 802 + dbg("TRYING HTTP:"); 803 + ustr = "http://" + host + ":" + port; 804 + ustr += viewer.urlPrefix + "/index.vnc"; 805 + dbg("ustr is: " + ustr); 806 + 807 + try { 808 + /* prepare for an HTTP URL connection to the same host:port (but not httpsPort) */ 809 + URL url = new URL(ustr); 810 + HttpURLConnection http = (HttpURLConnection) 811 + url.openConnection(); 812 + 813 + http.setUseCaches(false); 814 + http.setRequestMethod("GET"); 815 + http.setRequestProperty("Pragma", "No-Cache"); 816 + http.setRequestProperty("Proxy-Connection", "Keep-Alive"); 817 + http.setDoInput(true); 818 + 819 + dbg("trying http.connect()"); 820 + http.connect(); 821 + 822 + if (http.usingProxy()) { 823 + proxy_in_use = true; 824 + dbg("An HTTP proxy is in use. There may be connection problems."); 825 + } 826 + dbg("trying http.getContent()"); 827 + Object output = http.getContent(); 828 + dbg("trying http.disconnect()"); 829 + http.disconnect(); 830 + if (! viewer.GET) { 831 + String header = http.getHeaderField("VNC-Server"); 832 + if (header != null && header.startsWith("x11vnc")) { 833 + dbg("detected x11vnc server (2), setting GET=1"); 834 + viewer.GET = true; 835 + } 836 + } 837 + } catch(Exception e) { 838 + dbg("HttpURLConnection: " + e.getMessage()); 839 + } 840 + dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); 841 + dbg("------------------------------------------------"); 842 + } 843 + 844 + public Socket connectSock() throws IOException { 845 + /* 846 + * first try a https connection to detect a proxy, and 847 + * grab the VNC server cert at the same time: 848 + */ 849 + check_for_proxy_and_grab_vnc_server_cert(); 850 + 851 + boolean srv_cert = false; 852 + 853 + if (trustsrvCerts != null) { 854 + /* applet parameter suppled serverCert */ 855 + dbg("viewer.trustSrvCert-0 using trustsrv_ctx"); 856 + factory = trustsrv_ctx.getSocketFactory(); 857 + srv_cert = true; 858 + } else if (viewer.trustAllVncCerts) { 859 + /* trust all certs (no checking) */ 860 + dbg("viewer.trustAllVncCerts-0 using trustall_ctx"); 861 + factory = trustall_ctx.getSocketFactory(); 862 + } else if (trusturlCerts != null) { 863 + /* trust certs the Browser/JVM accepted in check_for_proxy... */ 864 + dbg("using trusturl_ctx"); 865 + factory = trusturl_ctx.getSocketFactory(); 866 + } else { 867 + /* trust the local defaults */ 868 + dbg("using trustloc_ctx"); 869 + factory = trustloc_ctx.getSocketFactory(); 870 + } 871 + 872 + socket = null; 873 + 874 + try { 875 + if (proxy_in_use && viewer.forceProxy) { 876 + throw new Exception("forcing proxy (forceProxy)"); 877 + } else if (viewer.CONNECT != null) { 878 + throw new Exception("forcing CONNECT"); 879 + } 880 + 881 + int timeout = 6; 882 + if (timeout > 0) { 883 + socket = (SSLSocket) factory.createSocket(); 884 + InetSocketAddress inetaddr = new InetSocketAddress(host, port); 885 + dbg("Using timeout of " + timeout + " secs to: " + host + ":" + port); 886 + socket.connect(inetaddr, timeout * 1000); 887 + } else { 888 + socket = (SSLSocket) factory.createSocket(host, port); 889 + } 890 + 891 + } catch (Exception esock) { 892 + dbg("socket error: " + esock.getMessage()); 893 + if (proxy_in_use || viewer.CONNECT != null) { 894 + proxy_failure = true; 895 + if (proxy_in_use) { 896 + dbg("HTTPS proxy in use. Trying to go with it."); 897 + } else { 898 + dbg("viewer.CONNECT reverse proxy in use. Trying to go with it."); 899 + } 900 + try { 901 + socket = proxy_socket(factory); 902 + } catch (Exception e) { 903 + dbg("proxy_socket error: " + e.getMessage()); 904 + } 905 + } else { 906 + /* n.b. socket is left in error state to cause ex. below. */ 907 + } 908 + } 909 + 910 + try { 911 + socket.startHandshake(); 912 + 913 + dbg("The Server Connection Verified OK on 1st try."); 914 + 915 + java.security.cert.Certificate[] currentTrustedCerts; 916 + BrowserCertsDialog bcd; 917 + 918 + SSLSession sess = socket.getSession(); 919 + currentTrustedCerts = sess.getPeerCertificates(); 920 + 921 + if (viewer.trustAllVncCerts) { 922 + dbg("viewer.trustAllVncCerts-1 keeping socket."); 923 + } else if (currentTrustedCerts == null || currentTrustedCerts.length < 1) { 924 + try { 925 + socket.close(); 926 + } catch (Exception e) { 927 + dbg("socket is grumpy."); 928 + } 929 + socket = null; 930 + throw new SSLHandshakeException("no current certs"); 931 + } 932 + 933 + String serv = ""; 934 + try { 935 + CertInfo ci = new CertInfo(currentTrustedCerts[0]); 936 + serv = ci.get_certinfo("CN"); 937 + } catch (Exception e) { 938 + ; 939 + } 940 + 941 + if (viewer.trustAllVncCerts) { 942 + dbg("viewer.trustAllVncCerts-2 skipping browser certs dialog"); 943 + user_wants_to_see_cert = false; 944 + } else if (viewer.serverCert != null && trustsrvCerts != null) { 945 + dbg("viewer.serverCert-1 skipping browser certs dialog"); 946 + user_wants_to_see_cert = false; 947 + } else if (viewer.trustUrlVncCert) { 948 + dbg("viewer.trustUrlVncCert-1 skipping browser certs dialog"); 949 + user_wants_to_see_cert = false; 950 + } else { 951 + /* have a dialog with the user: */ 952 + bcd = new BrowserCertsDialog(serv, host + ":" + port); 953 + dbg("browser certs dialog begin."); 954 + bcd.queryUser(); 955 + dbg("browser certs dialog finished."); 956 + 957 + if (bcd.showCertDialog) { 958 + String msg = "user wants to see cert"; 959 + dbg(msg); 960 + user_wants_to_see_cert = true; 961 + if (cert_fail == null) { 962 + cert_fail = "user-view"; 963 + } 964 + throw new SSLHandshakeException(msg); 965 + } else { 966 + user_wants_to_see_cert = false; 967 + dbg("browser certs dialog: user said yes, accept it"); 968 + } 969 + } 970 + 971 + } catch (SSLHandshakeException eh) { 972 + dbg("SSLHandshakeException: could not automatically verify Server."); 973 + dbg("msg: " + eh.getMessage()); 974 + 975 + 976 + /* send a cleanup string just in case: */ 977 + String getoutstr = "GET /index.vnc HTTP/1.0\r\nConnection: close\r\n\r\n"; 978 + 979 + try { 980 + OutputStream os = socket.getOutputStream(); 981 + os.write(getoutstr.getBytes()); 982 + socket.close(); 983 + } catch (Exception e) { 984 + dbg("socket is grumpy!"); 985 + } 986 + 987 + /* reload */ 988 + 989 + socket = null; 990 + 991 + String reason = null; 992 + 993 + if (srv_cert) { 994 + /* for serverCert usage we make this a fatal error. */ 995 + throw new IOException("Fatal: VNC Server's Cert does not match Applet Parameter 'serverCert=...'"); 996 + /* see below in TrustDialog were we describe this case to user anyway */ 997 + } 998 + 999 + /* 1000 + * Reconnect, trusting any cert, so we can grab 1001 + * the cert to show it to the user in a dialog 1002 + * for him to manually accept. This connection 1003 + * is not used for anything else. 1004 + */ 1005 + factory = trustall_ctx.getSocketFactory(); 1006 + if (proxy_failure) { 1007 + socket = proxy_socket(factory); 1008 + } else { 1009 + socket = (SSLSocket) factory.createSocket(host, port); 1010 + } 1011 + 1012 + if (debug_certs) { 1013 + dbg("trusturlCerts: " + trusturlCerts); 1014 + dbg("trustsrvCerts: " + trustsrvCerts); 1015 + } 1016 + if (trusturlCerts == null && cert_fail == null) { 1017 + cert_fail = "missing-certs"; 1018 + } 1019 + 1020 + try { 1021 + socket.startHandshake(); 1022 + 1023 + dbg("The TrustAll Server Cert-grab Connection (trivially) Verified OK."); 1024 + 1025 + /* grab the cert: */ 1026 + try { 1027 + SSLSession sess = socket.getSession(); 1028 + trustallCerts = sess.getPeerCertificates(); 1029 + } catch (Exception e) { 1030 + throw new Exception("Could not get " + 1031 + "Peer Certificate"); 1032 + } 1033 + if (debug_certs) { 1034 + dbg("trustallCerts: " + trustallCerts); 1035 + } 1036 + 1037 + if (viewer.trustAllVncCerts) { 1038 + dbg("viewer.trustAllVncCerts-3. skipping dialog, trusting everything."); 1039 + } else if (! browser_cert_match()) { 1040 + /* 1041 + * close socket now, we will reopen after 1042 + * dialog if user agrees to use the cert. 1043 + */ 1044 + try { 1045 + OutputStream os = socket.getOutputStream(); 1046 + os.write(getoutstr.getBytes()); 1047 + socket.close(); 1048 + } catch (Exception e) { 1049 + dbg("socket is grumpy!!"); 1050 + } 1051 + socket = null; 1052 + 1053 + /* dialog with user to accept cert or not: */ 1054 + 1055 + TrustDialog td= new TrustDialog(host, port, 1056 + trustallCerts); 1057 + 1058 + if (cert_fail == null) { 1059 + ; 1060 + } else if (cert_fail.equals("user-view")) { 1061 + reason = "Reason for this Dialog:\n\n" 1062 + + " You Asked to View the Certificate."; 1063 + } else if (cert_fail.equals("server-cert-mismatch")) { 1064 + /* this is now fatal error, see above. */ 1065 + reason = "Reason for this Dialog:\n\n" 1066 + + " The VNC Server's Certificate does not match the Certificate\n" 1067 + + " specified in the supplied 'serverCert' Applet Parameter."; 1068 + } else if (cert_fail.equals("cert-mismatch")) { 1069 + reason = "Reason for this Dialog:\n\n" 1070 + + " The VNC Server's Certificate does not match the Website's\n" 1071 + + " HTTPS Certificate (that you previously accepted; either\n" 1072 + + " manually or automatically via Certificate Authority.)"; 1073 + } else if (cert_fail.equals("missing-certs")) { 1074 + reason = "Reason for this Dialog:\n\n" 1075 + + " Not all Certificates could be obtained to check."; 1076 + } 1077 + 1078 + if (! td.queryUser(reason)) { 1079 + String msg = "User decided against it."; 1080 + dbg(msg); 1081 + throw new IOException(msg); 1082 + } 1083 + } 1084 + 1085 + } catch (Exception ehand2) { 1086 + dbg("** Could not TrustAll Verify Server!"); 1087 + 1088 + throw new IOException(ehand2.getMessage()); 1089 + } 1090 + 1091 + /* reload again: */ 1092 + 1093 + if (socket != null) { 1094 + try { 1095 + socket.close(); 1096 + } catch (Exception e) { 1097 + dbg("socket is grumpy!!!"); 1098 + } 1099 + socket = null; 1100 + } 1101 + 1102 + /* 1103 + * Now connect a 3rd time, using the cert 1104 + * retrieved during connection 2 (sadly, that 1105 + * the user likely blindly agreed to...) 1106 + */ 1107 + 1108 + factory = trustone_ctx.getSocketFactory(); 1109 + if (proxy_failure) { 1110 + socket = proxy_socket(factory); 1111 + } else { 1112 + socket = (SSLSocket) factory.createSocket(host, port); 1113 + } 1114 + 1115 + try { 1116 + socket.startHandshake(); 1117 + dbg("TrustAll/TrustOne Server Connection Verified #3."); 1118 + 1119 + } catch (Exception ehand3) { 1120 + dbg("** Could not TrustAll/TrustOne Verify Server #3."); 1121 + 1122 + throw new IOException(ehand3.getMessage()); 1123 + } 1124 + } 1125 + 1126 + /* we have socket (possibly null) at this point, so proceed: */ 1127 + 1128 + /* handle x11vnc GET=1, if applicable: */ 1129 + if (socket != null && viewer.GET) { 1130 + String str = "GET "; 1131 + str += viewer.urlPrefix; 1132 + str += "/request.https.vnc.connection"; 1133 + str += " HTTP/1.0\r\n"; 1134 + str += "Pragma: No-Cache\r\n"; 1135 + str += "\r\n"; 1136 + 1137 + System.out.println("sending: " + str); 1138 + OutputStream os = socket.getOutputStream(); 1139 + String type = "os"; 1140 + 1141 + if (type == "os") { 1142 + os.write(str.getBytes()); 1143 + os.flush(); 1144 + System.out.println("used OutputStream"); 1145 + } else if (type == "bs") { 1146 + BufferedOutputStream bs = new BufferedOutputStream(os); 1147 + bs.write(str.getBytes()); 1148 + bs.flush(); 1149 + System.out.println("used BufferedOutputStream"); 1150 + } else if (type == "ds") { 1151 + DataOutputStream ds = new DataOutputStream(os); 1152 + ds.write(str.getBytes()); 1153 + ds.flush(); 1154 + System.out.println("used DataOutputStream"); 1155 + } 1156 + if (false) { 1157 + String rep = ""; 1158 + DataInputStream is = new DataInputStream( 1159 + new BufferedInputStream(socket.getInputStream(), 16384)); 1160 + while (true) { 1161 + rep += readline(is); 1162 + if (rep.indexOf("\r\n\r\n") >= 0) { 1163 + break; 1164 + } 1165 + } 1166 + System.out.println("rep: " + rep); 1167 + } 1168 + } 1169 + 1170 + dbg("SSL returning socket to caller."); 1171 + dbg(""); 1172 + 1173 + /* could be null, let caller handle that. */ 1174 + return (Socket) socket; 1175 + } 1176 + 1177 + boolean browser_cert_match() { 1178 + String msg = "Browser URL accept previously accepted cert"; 1179 + 1180 + if (user_wants_to_see_cert) { 1181 + return false; 1182 + } 1183 + 1184 + if (viewer.serverCert != null || trustsrvCerts != null) { 1185 + if (cert_fail == null) { 1186 + cert_fail = "server-cert-mismatch"; 1187 + } 1188 + } 1189 + if (trustallCerts != null && trusturlCerts != null) { 1190 + if (trustallCerts.length == trusturlCerts.length) { 1191 + boolean ok = true; 1192 + /* check toath trustallCerts (socket) equals trusturlCerts (browser) */ 1193 + for (int i = 0; i < trusturlCerts.length; i++) { 1194 + if (! trustallCerts[i].equals(trusturlCerts[i])) { 1195 + dbg("BCM: cert mismatch at i=" + i); 1196 + dbg("BCM: cert mismatch url" + trusturlCerts[i]); 1197 + dbg("BCM: cert mismatch all" + trustallCerts[i]); 1198 + ok = false; 1199 + } 1200 + } 1201 + if (ok) { 1202 + System.out.println(msg); 1203 + if (cert_fail == null) { 1204 + cert_fail = "did-not-fail"; 1205 + } 1206 + return true; 1207 + } else { 1208 + if (cert_fail == null) { 1209 + cert_fail = "cert-mismatch"; 1210 + } 1211 + return false; 1212 + } 1213 + } 1214 + } 1215 + if (cert_fail == null) { 1216 + cert_fail = "missing-certs"; 1217 + } 1218 + return false; 1219 + } 1220 + 1221 + private void dbg(String s) { 1222 + if (debug) { 1223 + System.out.println(s); 1224 + } 1225 + } 1226 + 1227 + private int gint(String s) { 1228 + int n = -1; 1229 + try { 1230 + Integer I = new Integer(s); 1231 + n = I.intValue(); 1232 + } catch (Exception ex) { 1233 + return -1; 1234 + } 1235 + return n; 1236 + } 1237 + 1238 + /* this will do the proxy CONNECT negotiation and hook us up. */ 1239 + 1240 + private void proxy_helper(String proxyHost, int proxyPort) { 1241 + 1242 + boolean proxy_auth = false; 1243 + String proxy_auth_basic_realm = ""; 1244 + String hp = host + ":" + port; 1245 + dbg("proxy_helper: " + proxyHost + ":" + proxyPort + " hp: " + hp); 1246 + 1247 + /* we loop here a few times trying for the password case */ 1248 + for (int k=0; k < 2; k++) { 1249 + dbg("proxy_in_use psocket: " + k); 1250 + 1251 + if (proxySock != null) { 1252 + try { 1253 + proxySock.close(); 1254 + } catch (Exception e) { 1255 + dbg("proxy socket is grumpy."); 1256 + } 1257 + } 1258 + 1259 + proxySock = psocket(proxyHost, proxyPort); 1260 + if (proxySock == null) { 1261 + dbg("1-a sadly, returning a null socket"); 1262 + return; 1263 + } 1264 + 1265 + String req1 = "CONNECT " + hp + " HTTP/1.1\r\n" 1266 + + "Host: " + hp + "\r\n"; 1267 + 1268 + dbg("requesting via proxy: " + req1); 1269 + 1270 + if (proxy_auth) { 1271 + if (proxy_auth_string == null) { 1272 + ProxyPasswdDialog pp = new ProxyPasswdDialog(proxyHost, proxyPort, proxy_auth_basic_realm); 1273 + pp.queryUser(); 1274 + proxy_auth_string = pp.getAuth(); 1275 + } 1276 + //dbg("auth1: " + proxy_auth_string); 1277 + 1278 + String auth2 = Base64Coder.encodeString(proxy_auth_string); 1279 + //dbg("auth2: " + auth2); 1280 + 1281 + req1 += "Proxy-Authorization: Basic " + auth2 + "\r\n"; 1282 + //dbg("req1: " + req1); 1283 + 1284 + dbg("added Proxy-Authorization: Basic ... to request"); 1285 + } 1286 + req1 += "\r\n"; 1287 + 1288 + try { 1289 + proxy_os.write(req1.getBytes()); 1290 + String reply = readline(proxy_is); 1291 + 1292 + dbg("proxy replied: " + reply.trim()); 1293 + 1294 + if (reply.indexOf("HTTP/1.") == 0 && reply.indexOf(" 407 ") > 0) { 1295 + proxy_auth = true; 1296 + proxySock.close(); 1297 + } else if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { 1298 + proxySock.close(); 1299 + proxySock = psocket(proxyHost, proxyPort); 1300 + if (proxySock == null) { 1301 + dbg("2-a sadly, returning a null socket"); 1302 + return; 1303 + } 1304 + } 1305 + } catch(Exception e) { 1306 + dbg("some proxy socket problem: " + e.getMessage()); 1307 + } 1308 + 1309 + /* read the rest of the HTTP headers */ 1310 + while (true) { 1311 + String line = readline(proxy_is); 1312 + dbg("proxy line: " + line.trim()); 1313 + if (proxy_auth) { 1314 + String uc = line.toLowerCase(); 1315 + if (uc.indexOf("proxy-authenticate:") == 0) { 1316 + if (uc.indexOf(" basic ") >= 0) { 1317 + int idx = uc.indexOf(" realm"); 1318 + if (idx >= 0) { 1319 + proxy_auth_basic_realm = uc.substring(idx+1); 1320 + } 1321 + } 1322 + } 1323 + } 1324 + if (line.equals("\r\n") || line.equals("\n")) { 1325 + break; 1326 + } 1327 + } 1328 + if (!proxy_auth || proxy_auth_basic_realm.equals("")) { 1329 + /* we only try once for the non-password case: */ 1330 + break; 1331 + } 1332 + } 1333 + } 1334 + 1335 + public SSLSocket proxy_socket(SSLSocketFactory factory) { 1336 + Properties props = null; 1337 + String proxyHost = null; 1338 + int proxyPort = 0; 1339 + String proxyHost_nossl = null; 1340 + int proxyPort_nossl = 0; 1341 + String str; 1342 + 1343 + /* see if we can guess the proxy info from Properties: */ 1344 + try { 1345 + props = System.getProperties(); 1346 + } catch (Exception e) { 1347 + /* sandboxed applet might not be able to read it. */ 1348 + dbg("props failed: " + e.getMessage()); 1349 + } 1350 + if (viewer.proxyHost != null) { 1351 + dbg("Using supplied proxy " + viewer.proxyHost + " " + viewer.proxyPort + " applet parameters."); 1352 + proxyHost = viewer.proxyHost; 1353 + if (viewer.proxyPort != null) { 1354 + proxyPort = gint(viewer.proxyPort); 1355 + } else { 1356 + proxyPort = 8080; 1357 + } 1358 + 1359 + } else if (props != null) { 1360 + dbg("\n---------------\nAll props:"); 1361 + props.list(System.out); 1362 + dbg("\n---------------\n\n"); 1363 + 1364 + /* scrape throught properties looking for proxy info: */ 1365 + 1366 + for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { 1367 + String s = (String) e.nextElement(); 1368 + String v = System.getProperty(s); 1369 + String s2 = s.toLowerCase(); 1370 + String v2 = v.toLowerCase(); 1371 + 1372 + if (s2.indexOf("proxy.https.host") >= 0) { 1373 + proxyHost = v2; 1374 + continue; 1375 + } 1376 + if (s2.indexOf("proxy.https.port") >= 0) { 1377 + proxyPort = gint(v2); 1378 + continue; 1379 + } 1380 + if (s2.indexOf("proxy.http.host") >= 0) { 1381 + proxyHost_nossl = v2; 1382 + continue; 1383 + } 1384 + if (s2.indexOf("proxy.http.port") >= 0) { 1385 + proxyPort_nossl = gint(v2); 1386 + continue; 1387 + } 1388 + } 1389 + 1390 + for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { 1391 + String s = (String) e.nextElement(); 1392 + String v = System.getProperty(s); 1393 + String s2 = s.toLowerCase(); 1394 + String v2 = v.toLowerCase(); 1395 + 1396 + if (proxyHost != null && proxyPort > 0) { 1397 + break; 1398 + } 1399 + 1400 + // look for something like: javaplugin.proxy.config.list = http=10.0.2.1:8082 1401 + if (s2.indexOf("proxy") < 0 && v2.indexOf("proxy") < 0) { 1402 + continue; 1403 + } 1404 + if (v2.indexOf("http") < 0) { 1405 + continue; 1406 + } 1407 + 1408 + String[] pieces = v.split("[,;]"); 1409 + for (int i = 0; i < pieces.length; i++) { 1410 + String p = pieces[i]; 1411 + int j = p.indexOf("https"); 1412 + if (j < 0) { 1413 + j = p.indexOf("http"); 1414 + if (j < 0) { 1415 + continue; 1416 + } 1417 + } 1418 + j = p.indexOf("=", j); 1419 + if (j < 0) { 1420 + continue; 1421 + } 1422 + p = p.substring(j+1); 1423 + String [] hp = p.split(":"); 1424 + if (hp.length != 2) { 1425 + continue; 1426 + } 1427 + if (hp[0].length() > 1 && hp[1].length() > 1) { 1428 + 1429 + proxyPort = gint(hp[1]); 1430 + if (proxyPort < 0) { 1431 + continue; 1432 + } 1433 + proxyHost = new String(hp[0]); 1434 + break; 1435 + } 1436 + } 1437 + } 1438 + } 1439 + if (proxyHost != null) { 1440 + if (proxyHost_nossl != null && proxyPort_nossl > 0) { 1441 + dbg("Using http proxy info instead of https."); 1442 + proxyHost = proxyHost_nossl; 1443 + proxyPort = proxyPort_nossl; 1444 + } 1445 + } 1446 + 1447 + if (proxy_in_use) { 1448 + if (proxy_dialog_host != null && proxy_dialog_port > 0) { 1449 + proxyHost = proxy_dialog_host; 1450 + proxyPort = proxy_dialog_port; 1451 + } 1452 + if (proxyHost != null) { 1453 + dbg("Lucky us! we figured out the Proxy parameters: " + proxyHost + " " + proxyPort); 1454 + } else { 1455 + /* ask user to help us: */ 1456 + ProxyDialog pd = new ProxyDialog(proxyHost, proxyPort); 1457 + pd.queryUser(); 1458 + proxyHost = pd.getHost(); 1459 + proxyPort = pd.getPort(); 1460 + proxy_dialog_host = new String(proxyHost); 1461 + proxy_dialog_port = proxyPort; 1462 + dbg("User said host: " + pd.getHost() + " port: " + pd.getPort()); 1463 + } 1464 + 1465 + proxy_helper(proxyHost, proxyPort); 1466 + if (proxySock == null) { 1467 + return null; 1468 + } 1469 + } else if (viewer.CONNECT != null) { 1470 + dbg("viewer.CONNECT psocket:"); 1471 + proxySock = psocket(host, port); 1472 + if (proxySock == null) { 1473 + dbg("1-b sadly, returning a null socket"); 1474 + return null; 1475 + } 1476 + } 1477 + 1478 + if (viewer.CONNECT != null) { 1479 + String hp = viewer.CONNECT; 1480 + String req2 = "CONNECT " + hp + " HTTP/1.1\r\n" 1481 + + "Host: " + hp + "\r\n\r\n"; 1482 + 1483 + dbg("requesting2: " + req2); 1484 + 1485 + try { 1486 + proxy_os.write(req2.getBytes()); 1487 + String reply = readline(proxy_is); 1488 + 1489 + dbg("proxy replied2: " + reply.trim()); 1490 + 1491 + if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { 1492 + proxySock.close(); 1493 + proxySock = psocket(proxyHost, proxyPort); 1494 + if (proxySock == null) { 1495 + dbg("2-b sadly, returning a null socket"); 1496 + return null; 1497 + } 1498 + } 1499 + } catch(Exception e) { 1500 + dbg("proxy socket problem-2: " + e.getMessage()); 1501 + } 1502 + 1503 + while (true) { 1504 + String line = readline(proxy_is); 1505 + dbg("proxy line2: " + line.trim()); 1506 + if (line.equals("\r\n") || line.equals("\n")) { 1507 + break; 1508 + } 1509 + } 1510 + } 1511 + 1512 + Socket sslsock = null; 1513 + try { 1514 + sslsock = factory.createSocket(proxySock, host, port, true); 1515 + } catch(Exception e) { 1516 + dbg("sslsock prob: " + e.getMessage()); 1517 + dbg("3 sadly, returning a null socket"); 1518 + } 1519 + 1520 + return (SSLSocket) sslsock; 1521 + } 1522 + 1523 + Socket psocket(String h, int p) { 1524 + Socket psock = null; 1525 + try { 1526 + psock = new Socket(h, p); 1527 + proxy_is = new DataInputStream(new BufferedInputStream( 1528 + psock.getInputStream(), 16384)); 1529 + proxy_os = psock.getOutputStream(); 1530 + } catch(Exception e) { 1531 + dbg("psocket prob: " + e.getMessage()); 1532 + return null; 1533 + } 1534 + 1535 + return psock; 1536 + } 1537 + 1538 + String readline(DataInputStream i) { 1539 + byte[] ba = new byte[1]; 1540 + String s = new String(""); 1541 + ba[0] = 0; 1542 + try { 1543 + while (ba[0] != 0xa) { 1544 + ba[0] = (byte) i.readUnsignedByte(); 1545 + s += new String(ba); 1546 + } 1547 + } catch (Exception e) { 1548 + ; 1549 + } 1550 + return s; 1551 + } 1552 +} 1553 + 1554 +class TrustDialog implements ActionListener { 1555 + String msg, host, text; 1556 + int port; 1557 + java.security.cert.Certificate[] trustallCerts = null; 1558 + boolean viewing_cert = false; 1559 + boolean trust_this_session = false; 1560 + 1561 + /* 1562 + * this is the gui to show the user the cert and info and ask 1563 + * them if they want to continue using this cert. 1564 + */ 1565 + 1566 + Button ok, cancel, viewcert; 1567 + TextArea textarea; 1568 + Checkbox accept, deny; 1569 + Dialog dialog; 1570 + 1571 + String s1 = "Accept this certificate temporarily for this session"; 1572 + String s2 = "Do not accept this certificate and do not connect to" 1573 + + " this VNC server"; 1574 + String ln = "\n---------------------------------------------------\n\n"; 1575 + 1576 + TrustDialog (String h, int p, java.security.cert.Certificate[] s) { 1577 + host = h; 1578 + port = p; 1579 + trustallCerts = s; 1580 + 1581 + msg = "VNC Server " + host + ":" + port + " Not Verified"; 1582 + } 1583 + 1584 + public boolean queryUser(String reason) { 1585 + 1586 + /* create and display the dialog for unverified cert. */ 1587 + 1588 + Frame frame = new Frame(msg); 1589 + 1590 + dialog = new Dialog(frame, true); 1591 + 1592 + String infostr = ""; 1593 + if (trustallCerts.length == 1) { 1594 + CertInfo ci = new CertInfo(trustallCerts[0]); 1595 + infostr = ci.get_certinfo("all"); 1596 + } 1597 + if (reason != null) { 1598 + reason += "\n\n"; 1599 + } 1600 + 1601 + text = "\n" 1602 ++ "Unable to verify the identity of\n" 1603 ++ "\n" 1604 ++ " " + host + ":" + port + "\n" 1605 ++ "\n" 1606 ++ infostr 1607 ++ "\n" 1608 ++ "as a trusted VNC server.\n" 1609 ++ "\n" 1610 ++ reason 1611 ++ "In General not being able to verify the VNC Server and/or your seeing this Dialog\n" 1612 ++ "is due to one of the following:\n" 1613 ++ "\n" 1614 ++ " - Your requesting to View the Certificate before accepting.\n" 1615 ++ "\n" 1616 ++ " - The VNC server is using a Self-Signed Certificate or a Certificate\n" 1617 ++ " Authority not recognized by your Web Browser or Java Plugin runtime.\n" 1618 ++ "\n" 1619 ++ " - The use of an Apache SSL portal scheme employing CONNECT proxying AND\n" 1620 ++ " the Apache Web server has a certificate *different* from the VNC server's.\n" 1621 ++ "\n" 1622 ++ " - No previously accepted Certificate (via Web Broswer/Java Plugin) could be\n" 1623 ++ " obtained by this applet to compare the VNC Server Certificate against.\n" 1624 ++ "\n" 1625 ++ " - The VNC Server's Certificate does not match the one specified in the\n" 1626 ++ " supplied 'serverCert' Java Applet Parameter.\n" 1627 ++ "\n" 1628 ++ " - A Man-In-The-Middle attack impersonating as the VNC server that you wish\n" 1629 ++ " to connect to. (Wouldn't that be exciting!!)\n" 1630 ++ "\n" 1631 ++ "By safely copying the VNC server's Certificate (or using a common Certificate\n" 1632 ++ "Authority certificate) you can configure your Web Browser and Java Plugin to\n" 1633 ++ "automatically authenticate this VNC Server.\n" 1634 ++ "\n" 1635 ++ "If you do so, then you will only have to click \"Yes\" when this VNC Viewer\n" 1636 ++ "applet asks you whether to trust your Browser/Java Plugin's acceptance of the\n" 1637 ++ "certificate (except for the Apache portal case above where they don't match.)\n" 1638 ++ "\n" 1639 ++ "You can also set the applet parameter 'trustUrlVncCert=yes' to automatically\n" 1640 ++ "accept certificates already accepted/trusted by your Web Browser/Java Plugin,\n" 1641 ++ "and thereby see no dialog from this VNC Viewer applet.\n" 1642 +; 1643 + 1644 + /* the accept / do-not-accept radio buttons: */ 1645 + CheckboxGroup checkbox = new CheckboxGroup(); 1646 + accept = new Checkbox(s1, true, checkbox); 1647 + deny = new Checkbox(s2, false, checkbox); 1648 + 1649 + /* put the checkboxes in a panel: */ 1650 + Panel check = new Panel(); 1651 + check.setLayout(new GridLayout(2, 1)); 1652 + 1653 + check.add(accept); 1654 + check.add(deny); 1655 + 1656 + /* make the 3 buttons: */ 1657 + ok = new Button("OK"); 1658 + cancel = new Button("Cancel"); 1659 + viewcert = new Button("View Certificate"); 1660 + 1661 + ok.addActionListener(this); 1662 + cancel.addActionListener(this); 1663 + viewcert.addActionListener(this); 1664 + 1665 + /* put the buttons in their own panel: */ 1666 + Panel buttonrow = new Panel(); 1667 + buttonrow.setLayout(new FlowLayout(FlowLayout.LEFT)); 1668 + buttonrow.add(viewcert); 1669 + buttonrow.add(ok); 1670 + buttonrow.add(cancel); 1671 + 1672 + /* label at the top: */ 1673 + Label label = new Label(msg, Label.CENTER); 1674 + label.setFont(new Font("Helvetica", Font.BOLD, 16)); 1675 + 1676 + /* textarea in the middle */ 1677 + textarea = new TextArea(text, 38, 64, 1678 + TextArea.SCROLLBARS_VERTICAL_ONLY); 1679 + textarea.setEditable(false); 1680 + 1681 + /* put the two panels in their own panel at bottom: */ 1682 + Panel bot = new Panel(); 1683 + bot.setLayout(new GridLayout(2, 1)); 1684 + bot.add(check); 1685 + bot.add(buttonrow); 1686 + 1687 + /* now arrange things inside the dialog: */ 1688 + dialog.setLayout(new BorderLayout()); 1689 + 1690 + dialog.add("North", label); 1691 + dialog.add("South", bot); 1692 + dialog.add("Center", textarea); 1693 + 1694 + dialog.pack(); 1695 + dialog.resize(dialog.preferredSize()); 1696 + 1697 + dialog.show(); /* block here til OK or Cancel pressed. */ 1698 + 1699 + return trust_this_session; 1700 + } 1701 + 1702 + public synchronized void actionPerformed(ActionEvent evt) { 1703 + 1704 + if (evt.getSource() == viewcert) { 1705 + /* View Certificate button clicked */ 1706 + if (viewing_cert) { 1707 + /* show the original info text: */ 1708 + textarea.setText(text); 1709 + viewcert.setLabel("View Certificate"); 1710 + viewing_cert = false; 1711 + } else { 1712 + int i; 1713 + /* show all (likely just one) certs: */ 1714 + textarea.setText(""); 1715 + for (i=0; i < trustallCerts.length; i++) { 1716 + int j = i + 1; 1717 + textarea.append("Certificate[" + 1718 + j + "]\n\n"); 1719 + textarea.append( 1720 + trustallCerts[i].toString()); 1721 + textarea.append(ln); 1722 + } 1723 + viewcert.setLabel("View Info"); 1724 + viewing_cert = true; 1725 + 1726 + textarea.setCaretPosition(0); 1727 + } 1728 + 1729 + } else if (evt.getSource() == ok) { 1730 + /* OK button clicked */ 1731 + if (accept.getState()) { 1732 + trust_this_session = true; 1733 + } else { 1734 + trust_this_session = false; 1735 + } 1736 + //dialog.dispose(); 1737 + dialog.hide(); 1738 + 1739 + } else if (evt.getSource() == cancel) { 1740 + /* Cancel button clicked */ 1741 + trust_this_session = false; 1742 + 1743 + //dialog.dispose(); 1744 + dialog.hide(); 1745 + } 1746 + } 1747 + 1748 + String get_certinfo() { 1749 + String all = ""; 1750 + String fields[] = {"CN", "OU", "O", "L", "C"}; 1751 + int i; 1752 + if (trustallCerts.length < 1) { 1753 + all = ""; 1754 + return all; 1755 + } 1756 + String cert = trustallCerts[0].toString(); 1757 + 1758 + /* 1759 + * For now we simply scrape the cert string, there must 1760 + * be an API for this... perhaps optionValue? 1761 + */ 1762 + 1763 + for (i=0; i < fields.length; i++) { 1764 + int f, t, t1, t2; 1765 + String sub, mat = fields[i] + "="; 1766 + 1767 + f = cert.indexOf(mat, 0); 1768 + if (f > 0) { 1769 + t1 = cert.indexOf(", ", f); 1770 + t2 = cert.indexOf("\n", f); 1771 + if (t1 < 0 && t2 < 0) { 1772 + continue; 1773 + } else if (t1 < 0) { 1774 + t = t2; 1775 + } else if (t2 < 0) { 1776 + t = t1; 1777 + } else if (t1 < t2) { 1778 + t = t1; 1779 + } else { 1780 + t = t2; 1781 + } 1782 + if (t > f) { 1783 + sub = cert.substring(f, t); 1784 + all = all + " " + sub + "\n"; 1785 + } 1786 + } 1787 + } 1788 + return all; 1789 + } 1790 +} 1791 + 1792 +class ProxyDialog implements ActionListener { 1793 + String guessedHost = null; 1794 + String guessedPort = null; 1795 + /* 1796 + * this is the gui to show the user the cert and info and ask 1797 + * them if they want to continue using this cert. 1798 + */ 1799 + 1800 + Button ok; 1801 + Dialog dialog; 1802 + TextField entry; 1803 + String reply = ""; 1804 + 1805 + ProxyDialog (String h, int p) { 1806 + guessedHost = h; 1807 + try { 1808 + guessedPort = Integer.toString(p); 1809 + } catch (Exception e) { 1810 + guessedPort = "8080"; 1811 + } 1812 + } 1813 + 1814 + public void queryUser() { 1815 + 1816 + /* create and display the dialog for unverified cert. */ 1817 + 1818 + Frame frame = new Frame("Need Proxy host:port"); 1819 + 1820 + dialog = new Dialog(frame, true); 1821 + 1822 + 1823 + Label label = new Label("Please Enter your https Proxy info as host:port", Label.CENTER); 1824 + //label.setFont(new Font("Helvetica", Font.BOLD, 16)); 1825 + entry = new TextField(30); 1826 + ok = new Button("OK"); 1827 + ok.addActionListener(this); 1828 + 1829 + String guess = ""; 1830 + if (guessedHost != null) { 1831 + guess = guessedHost + ":" + guessedPort; 1832 + } 1833 + entry.setText(guess); 1834 + 1835 + dialog.setLayout(new BorderLayout()); 1836 + dialog.add("North", label); 1837 + dialog.add("Center", entry); 1838 + dialog.add("South", ok); 1839 + dialog.pack(); 1840 + dialog.resize(dialog.preferredSize()); 1841 + 1842 + dialog.show(); /* block here til OK or Cancel pressed. */ 1843 + return; 1844 + } 1845 + 1846 + public String getHost() { 1847 + int i = reply.indexOf(":"); 1848 + if (i < 0) { 1849 + return "unknown"; 1850 + } 1851 + String h = reply.substring(0, i); 1852 + return h; 1853 + } 1854 + 1855 + public int getPort() { 1856 + int i = reply.indexOf(":"); 1857 + int p = 8080; 1858 + if (i < 0) { 1859 + return p; 1860 + } 1861 + i++; 1862 + String ps = reply.substring(i); 1863 + try { 1864 + Integer I = new Integer(ps); 1865 + p = I.intValue(); 1866 + } catch (Exception e) { 1867 + ; 1868 + } 1869 + return p; 1870 + } 1871 + 1872 + public synchronized void actionPerformed(ActionEvent evt) { 1873 + System.out.println(evt.getActionCommand()); 1874 + if (evt.getSource() == ok) { 1875 + reply = entry.getText(); 1876 + //dialog.dispose(); 1877 + dialog.hide(); 1878 + } 1879 + } 1880 +} 1881 + 1882 +class ProxyPasswdDialog implements ActionListener { 1883 + String guessedHost = null; 1884 + String guessedPort = null; 1885 + String guessedUser = null; 1886 + String guessedPasswd = null; 1887 + String realm = null; 1888 + /* 1889 + * this is the gui to show the user the cert and info and ask 1890 + * them if they want to continue using this cert. 1891 + */ 1892 + 1893 + Button ok; 1894 + Dialog dialog; 1895 + TextField entry1; 1896 + TextField entry2; 1897 + String reply1 = ""; 1898 + String reply2 = ""; 1899 + 1900 + ProxyPasswdDialog (String h, int p, String realm) { 1901 + guessedHost = h; 1902 + try { 1903 + guessedPort = Integer.toString(p); 1904 + } catch (Exception e) { 1905 + guessedPort = "8080"; 1906 + } 1907 + this.realm = realm; 1908 + } 1909 + 1910 + public void queryUser() { 1911 + 1912 + /* create and display the dialog for unverified cert. */ 1913 + 1914 + Frame frame = new Frame("Proxy Requires Username and Password"); 1915 + 1916 + dialog = new Dialog(frame, true); 1917 + 1918 + //Label label = new Label("Please Enter your Web Proxy Username in the top Entry and Password in the bottom Entry", Label.CENTER); 1919 + TextArea label = new TextArea("Please Enter your Web Proxy\nUsername in the Top Entry and\nPassword in the Bottom Entry,\nand then press OK.", 4, 20, TextArea.SCROLLBARS_NONE); 1920 + entry1 = new TextField(30); 1921 + entry2 = new TextField(30); 1922 + entry2.setEchoChar('*'); 1923 + ok = new Button("OK"); 1924 + ok.addActionListener(this); 1925 + 1926 + dialog.setLayout(new BorderLayout()); 1927 + dialog.add("North", label); 1928 + dialog.add("Center", entry1); 1929 + dialog.add("South", entry2); 1930 + dialog.add("East", ok); 1931 + dialog.pack(); 1932 + dialog.resize(dialog.preferredSize()); 1933 + 1934 + dialog.show(); /* block here til OK or Cancel pressed. */ 1935 + return; 1936 + } 1937 + 1938 + public String getAuth() { 1939 + return reply1 + ":" + reply2; 1940 + } 1941 + 1942 + public synchronized void actionPerformed(ActionEvent evt) { 1943 + System.out.println(evt.getActionCommand()); 1944 + if (evt.getSource() == ok) { 1945 + reply1 = entry1.getText(); 1946 + reply2 = entry2.getText(); 1947 + //dialog.dispose(); 1948 + dialog.hide(); 1949 + } 1950 + } 1951 +} 1952 + 1953 +class ClientCertDialog implements ActionListener { 1954 + 1955 + Button ok; 1956 + Dialog dialog; 1957 + TextField entry; 1958 + String reply = ""; 1959 + 1960 + ClientCertDialog() { 1961 + ; 1962 + } 1963 + 1964 + public String queryUser() { 1965 + 1966 + /* create and display the dialog for unverified cert. */ 1967 + 1968 + Frame frame = new Frame("Enter SSL Client Cert+Key String"); 1969 + 1970 + dialog = new Dialog(frame, true); 1971 + 1972 + 1973 + Label label = new Label("Please Enter the SSL Client Cert+Key String 308204c0...,...522d2d0a", Label.CENTER); 1974 + entry = new TextField(30); 1975 + ok = new Button("OK"); 1976 + ok.addActionListener(this); 1977 + 1978 + dialog.setLayout(new BorderLayout()); 1979 + dialog.add("North", label); 1980 + dialog.add("Center", entry); 1981 + dialog.add("South", ok); 1982 + dialog.pack(); 1983 + dialog.resize(dialog.preferredSize()); 1984 + 1985 + dialog.show(); /* block here til OK or Cancel pressed. */ 1986 + return reply; 1987 + } 1988 + 1989 + public synchronized void actionPerformed(ActionEvent evt) { 1990 + System.out.println(evt.getActionCommand()); 1991 + if (evt.getSource() == ok) { 1992 + reply = entry.getText(); 1993 + //dialog.dispose(); 1994 + dialog.hide(); 1995 + } 1996 + } 1997 +} 1998 + 1999 +class BrowserCertsDialog implements ActionListener { 2000 + Button yes, no; 2001 + Dialog dialog; 2002 + String vncServer; 2003 + String hostport; 2004 + public boolean showCertDialog = true; 2005 + 2006 + BrowserCertsDialog(String serv, String hp) { 2007 + vncServer = serv; 2008 + hostport = hp; 2009 + } 2010 + 2011 + public void queryUser() { 2012 + 2013 + /* create and display the dialog for unverified cert. */ 2014 + 2015 + Frame frame = new Frame("Use Browser/JVM Certs?"); 2016 + 2017 + dialog = new Dialog(frame, true); 2018 + 2019 + String m = ""; 2020 +m += "\n"; 2021 +m += "This VNC Viewer applet does not have its own keystore to track\n"; 2022 +m += "SSL certificates, and so cannot authenticate the certificate\n"; 2023 +m += "of the VNC Server:\n"; 2024 +m += "\n"; 2025 +m += " " + hostport + "\n\n " + vncServer + "\n"; 2026 +m += "\n"; 2027 +m += "on its own.\n"; 2028 +m += "\n"; 2029 +m += "However, it has noticed that your Web Browser and/or Java VM Plugin\n"; 2030 +m += "has previously accepted the same certificate. You may have set\n"; 2031 +m += "this up permanently or just for this session, or the server\n"; 2032 +m += "certificate was signed by a CA cert that your Web Browser or\n"; 2033 +m += "Java VM Plugin has.\n"; 2034 +m += "\n"; 2035 +m += "If the VNC Server connection times out while you are reading this\n"; 2036 +m += "dialog, then restart the connection and try again.\n"; 2037 +m += "\n"; 2038 +m += "Should this VNC Viewer applet now connect to the above VNC server?\n"; 2039 +m += "\n"; 2040 + 2041 + TextArea textarea = new TextArea(m, 22, 64, 2042 + TextArea.SCROLLBARS_VERTICAL_ONLY); 2043 + textarea.setEditable(false); 2044 + yes = new Button("Yes"); 2045 + yes.addActionListener(this); 2046 + no = new Button("No, Let Me See the Certificate."); 2047 + no.addActionListener(this); 2048 + 2049 + dialog.setLayout(new BorderLayout()); 2050 + dialog.add("North", textarea); 2051 + dialog.add("Center", yes); 2052 + dialog.add("South", no); 2053 + dialog.pack(); 2054 + dialog.resize(dialog.preferredSize()); 2055 + 2056 + dialog.show(); /* block here til Yes or No pressed. */ 2057 + System.out.println("done show()"); 2058 + return; 2059 + } 2060 + 2061 + public synchronized void actionPerformed(ActionEvent evt) { 2062 + System.out.println(evt.getActionCommand()); 2063 + if (evt.getSource() == yes) { 2064 + showCertDialog = false; 2065 + //dialog.dispose(); 2066 + dialog.hide(); 2067 + } else if (evt.getSource() == no) { 2068 + showCertDialog = true; 2069 + //dialog.dispose(); 2070 + dialog.hide(); 2071 + } 2072 + System.out.println("done actionPerformed()"); 2073 + } 2074 +} 2075 + 2076 +class CertInfo { 2077 + String fields[] = {"CN", "OU", "O", "L", "C"}; 2078 + java.security.cert.Certificate cert; 2079 + String certString = ""; 2080 + 2081 + CertInfo(java.security.cert.Certificate c) { 2082 + cert = c; 2083 + certString = cert.toString(); 2084 + } 2085 + 2086 + String get_certinfo(String which) { 2087 + int i; 2088 + String cs = new String(certString); 2089 + String all = ""; 2090 + 2091 + /* 2092 + * For now we simply scrape the cert string, there must 2093 + * be an API for this... perhaps optionValue? 2094 + */ 2095 + for (i=0; i < fields.length; i++) { 2096 + int f, t, t1, t2; 2097 + String sub, mat = fields[i] + "="; 2098 + 2099 + f = cs.indexOf(mat, 0); 2100 + if (f > 0) { 2101 + t1 = cs.indexOf(", ", f); 2102 + t2 = cs.indexOf("\n", f); 2103 + if (t1 < 0 && t2 < 0) { 2104 + continue; 2105 + } else if (t1 < 0) { 2106 + t = t2; 2107 + } else if (t2 < 0) { 2108 + t = t1; 2109 + } else if (t1 < t2) { 2110 + t = t1; 2111 + } else { 2112 + t = t2; 2113 + } 2114 + if (t > f) { 2115 + sub = cs.substring(f, t); 2116 + all = all + " " + sub + "\n"; 2117 + if (which.equals(fields[i])) { 2118 + return sub; 2119 + } 2120 + } 2121 + } 2122 + } 2123 + if (which.equals("all")) { 2124 + return all; 2125 + } else { 2126 + return ""; 2127 + } 2128 + } 2129 +} 2130 + 2131 +class Base64Coder { 2132 + 2133 + // Mapping table from 6-bit nibbles to Base64 characters. 2134 + private static char[] map1 = new char[64]; 2135 + static { 2136 + int i=0; 2137 + for (char c='A'; c<='Z'; c++) map1[i++] = c; 2138 + for (char c='a'; c<='z'; c++) map1[i++] = c; 2139 + for (char c='0'; c<='9'; c++) map1[i++] = c; 2140 + map1[i++] = '+'; map1[i++] = '/'; } 2141 + 2142 + // Mapping table from Base64 characters to 6-bit nibbles. 2143 + private static byte[] map2 = new byte[128]; 2144 + static { 2145 + for (int i=0; i<map2.length; i++) map2[i] = -1; 2146 + for (int i=0; i<64; i++) map2[map1[i]] = (byte)i; } 2147 + 2148 + /** 2149 + * Encodes a string into Base64 format. 2150 + * No blanks or line breaks are inserted. 2151 + * @param s a String to be encoded. 2152 + * @return A String with the Base64 encoded data. 2153 + */ 2154 + public static String encodeString (String s) { 2155 + return new String(encode(s.getBytes())); } 2156 + 2157 + /** 2158 + * Encodes a byte array into Base64 format. 2159 + * No blanks or line breaks are inserted. 2160 + * @param in an array containing the data bytes to be encoded. 2161 + * @return A character array with the Base64 encoded data. 2162 + */ 2163 + public static char[] encode (byte[] in) { 2164 + return encode(in,in.length); } 2165 + 2166 + /** 2167 + * Encodes a byte array into Base64 format. 2168 + * No blanks or line breaks are inserted. 2169 + * @param in an array containing the data bytes to be encoded. 2170 + * @param iLen number of bytes to process in <code>in</code>. 2171 + * @return A character array with the Base64 encoded data. 2172 + */ 2173 + public static char[] encode (byte[] in, int iLen) { 2174 + int oDataLen = (iLen*4+2)/3; // output length without padding 2175 + int oLen = ((iLen+2)/3)*4; // output length including padding 2176 + char[] out = new char[oLen]; 2177 + int ip = 0; 2178 + int op = 0; 2179 + while (ip < iLen) { 2180 + int i0 = in[ip++] & 0xff; 2181 + int i1 = ip < iLen ? in[ip++] & 0xff : 0; 2182 + int i2 = ip < iLen ? in[ip++] & 0xff : 0; 2183 + int o0 = i0 >>> 2; 2184 + int o1 = ((i0 & 3) << 4) | (i1 >>> 4); 2185 + int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); 2186 + int o3 = i2 & 0x3F; 2187 + out[op++] = map1[o0]; 2188 + out[op++] = map1[o1]; 2189 + out[op] = op < oDataLen ? map1[o2] : '='; op++; 2190 + out[op] = op < oDataLen ? map1[o3] : '='; op++; } 2191 + return out; } 2192 + 2193 + /** 2194 + * Decodes a string from Base64 format. 2195 + * @param s a Base64 String to be decoded. 2196 + * @return A String containing the decoded data. 2197 + * @throws IllegalArgumentException if the input is not valid Base64 encoded data. 2198 + */ 2199 + public static String decodeString (String s) { 2200 + return new String(decode(s)); } 2201 + 2202 + /** 2203 + * Decodes a byte array from Base64 format. 2204 + * @param s a Base64 String to be decoded. 2205 + * @return An array containing the decoded data bytes. 2206 + * @throws IllegalArgumentException if the input is not valid Base64 encoded data. 2207 + */ 2208 + public static byte[] decode (String s) { 2209 + return decode(s.toCharArray()); } 2210 + 2211 + /** 2212 + * Decodes a byte array from Base64 format. 2213 + * No blanks or line breaks are allowed within the Base64 encoded data. 2214 + * @param in a character array containing the Base64 encoded data. 2215 + * @return An array containing the decoded data bytes. 2216 + * @throws IllegalArgumentException if the input is not valid Base64 encoded data. 2217 + */ 2218 + public static byte[] decode (char[] in) { 2219 + int iLen = in.length; 2220 + if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); 2221 + while (iLen > 0 && in[iLen-1] == '=') iLen--; 2222 + int oLen = (iLen*3) / 4; 2223 + byte[] out = new byte[oLen]; 2224 + int ip = 0; 2225 + int op = 0; 2226 + while (ip < iLen) { 2227 + int i0 = in[ip++]; 2228 + int i1 = in[ip++]; 2229 + int i2 = ip < iLen ? in[ip++] : 'A'; 2230 + int i3 = ip < iLen ? in[ip++] : 'A'; 2231 + if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) 2232 + throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); 2233 + int b0 = map2[i0]; 2234 + int b1 = map2[i1]; 2235 + int b2 = map2[i2]; 2236 + int b3 = map2[i3]; 2237 + if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) 2238 + throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); 2239 + int o0 = ( b0 <<2) | (b1>>>4); 2240 + int o1 = ((b1 & 0xf)<<4) | (b2>>>2); 2241 + int o2 = ((b2 & 3)<<6) | b3; 2242 + out[op++] = (byte)o0; 2243 + if (op<oLen) out[op++] = (byte)o1; 2244 + if (op<oLen) out[op++] = (byte)o2; } 2245 + return out; } 2246 + 2247 + // Dummy constructor. 2248 + private Base64Coder() {} 2249 + 2250 +} 2251 diff -Naur vnc_javasrc.orig/VncCanvas.java vnc_javasrc/VncCanvas.java 2252 --- vnc_javasrc.orig/VncCanvas.java 2004-10-10 02:15:54.000000000 -0400 2253 +++ vnc_javasrc/VncCanvas.java 2010-11-30 21:01:15.000000000 -0500 2254 @@ -28,13 +28,14 @@ 2255 import java.lang.*; 2256 import java.util.zip.*; 2257 2258 +import java.util.Collections; 2259 2260 // 2261 // VncCanvas is a subclass of Canvas which draws a VNC desktop on it. 2262 // 2263 2264 class VncCanvas extends Canvas 2265 - implements KeyListener, MouseListener, MouseMotionListener { 2266 + implements KeyListener, MouseListener, MouseMotionListener, MouseWheelListener { 2267 2268 VncViewer viewer; 2269 RfbProto rfb; 2270 @@ -81,6 +82,20 @@ 2271 cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6)); 2272 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF); 2273 2274 + // kludge to not show any Java cursor in the canvas since we are 2275 + // showing the soft cursor (should be a user setting...) 2276 + Cursor dot = Toolkit.getDefaultToolkit().createCustomCursor( 2277 + Toolkit.getDefaultToolkit().createImage(new byte[4]), new Point(0,0), 2278 + "dot"); 2279 + this.setCursor(dot); 2280 + 2281 + // while we are at it... get rid of the keyboard traversals that 2282 + // make it so we can't type a Tab character: 2283 + this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 2284 + Collections.EMPTY_SET); 2285 + this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 2286 + Collections.EMPTY_SET); 2287 + 2288 colors = new Color[256]; 2289 for (int i = 0; i < 256; i++) 2290 colors[i] = new Color(cm8.getRGB(i)); 2291 @@ -169,6 +184,7 @@ 2292 inputEnabled = true; 2293 addMouseListener(this); 2294 addMouseMotionListener(this); 2295 + addMouseWheelListener(this); 2296 if (viewer.showControls) { 2297 viewer.buttonPanel.enableRemoteAccessControls(true); 2298 } 2299 @@ -177,6 +193,7 @@ 2300 inputEnabled = false; 2301 removeMouseListener(this); 2302 removeMouseMotionListener(this); 2303 + removeMouseWheelListener(this); 2304 if (viewer.showControls) { 2305 viewer.buttonPanel.enableRemoteAccessControls(false); 2306 } 2307 @@ -1190,6 +1207,9 @@ 2308 public void mouseDragged(MouseEvent evt) { 2309 processLocalMouseEvent(evt, true); 2310 } 2311 + public void mouseWheelMoved(MouseWheelEvent evt) { 2312 + processLocalMouseWheelEvent(evt); 2313 + } 2314 2315 public void processLocalKeyEvent(KeyEvent evt) { 2316 if (viewer.rfb != null && rfb.inNormalProtocol) { 2317 @@ -1221,6 +1241,19 @@ 2318 evt.consume(); 2319 } 2320 2321 + public void processLocalMouseWheelEvent(MouseWheelEvent evt) { 2322 + if (viewer.rfb != null && rfb.inNormalProtocol) { 2323 + synchronized(rfb) { 2324 + try { 2325 + rfb.writeWheelEvent(evt); 2326 + } catch (Exception e) { 2327 + e.printStackTrace(); 2328 + } 2329 + rfb.notify(); 2330 + } 2331 + } 2332 + } 2333 + 2334 public void processLocalMouseEvent(MouseEvent evt, boolean moved) { 2335 if (viewer.rfb != null && rfb.inNormalProtocol) { 2336 if (moved) { 2337 @@ -1387,9 +1420,9 @@ 2338 result = cm8.getRGB(pixBuf[i]); 2339 } else { 2340 result = 0xFF000000 | 2341 - (pixBuf[i * 4 + 1] & 0xFF) << 16 | 2342 - (pixBuf[i * 4 + 2] & 0xFF) << 8 | 2343 - (pixBuf[i * 4 + 3] & 0xFF); 2344 + (pixBuf[i * 4 + 2] & 0xFF) << 16 | 2345 + (pixBuf[i * 4 + 1] & 0xFF) << 8 | 2346 + (pixBuf[i * 4 + 0] & 0xFF); 2347 } 2348 } else { 2349 result = 0; // Transparent pixel 2350 @@ -1403,9 +1436,9 @@ 2351 result = cm8.getRGB(pixBuf[i]); 2352 } else { 2353 result = 0xFF000000 | 2354 - (pixBuf[i * 4 + 1] & 0xFF) << 16 | 2355 - (pixBuf[i * 4 + 2] & 0xFF) << 8 | 2356 - (pixBuf[i * 4 + 3] & 0xFF); 2357 + (pixBuf[i * 4 + 2] & 0xFF) << 16 | 2358 + (pixBuf[i * 4 + 1] & 0xFF) << 8 | 2359 + (pixBuf[i * 4 + 0] & 0xFF); 2360 } 2361 } else { 2362 result = 0; // Transparent pixel 2363 diff -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncViewer.java 2364 --- vnc_javasrc.orig/VncViewer.java 2004-03-04 08:34:25.000000000 -0500 2365 +++ vnc_javasrc/VncViewer.java 2010-03-27 17:57:04.000000000 -0400 2366 @@ -29,6 +29,7 @@ 2367 import java.awt.event.*; 2368 import java.io.*; 2369 import java.net.*; 2370 +import java.util.*; 2371 2372 public class VncViewer extends java.applet.Applet 2373 implements java.lang.Runnable, WindowListener { 2374 @@ -80,7 +81,7 @@ 2375 // Variables read from parameter values. 2376 String socketFactory; 2377 String host; 2378 - int port; 2379 + int port, vncserverport; 2380 boolean showControls; 2381 boolean offerRelogin; 2382 boolean showOfflineDesktop; 2383 @@ -88,6 +89,24 @@ 2384 int deferCursorUpdates; 2385 int deferUpdateRequests; 2386 2387 + boolean disableSSL; 2388 + boolean GET; 2389 + String CONNECT; 2390 + String urlPrefix; 2391 + String httpsPort; 2392 + String oneTimeKey; 2393 + String serverCert; 2394 + String proxyHost; 2395 + String proxyPort; 2396 + boolean forceProxy; 2397 + boolean ignoreProxy; 2398 + boolean trustAllVncCerts; 2399 + boolean trustUrlVncCert; 2400 + boolean debugCerts; 2401 + boolean debugKeyboard; 2402 + boolean mapF5_to_atsign; 2403 + boolean forbid_Ctrl_Alt; 2404 + 2405 // Reference to this applet for inter-applet communication. 2406 public static java.applet.Applet refApplet; 2407 2408 @@ -282,10 +301,24 @@ 2409 validate(); 2410 } 2411 2412 - while (!tryAuthenticate()) { 2413 - authenticator.retry(); 2414 - authenticatorUnixLogin.retry(); 2415 - } 2416 + if (false) { 2417 + /* a bug on retries: 'Error: bad position: 8' sun.awt.X11.XTextFieldPeer.setCaretPosition(XTextFieldPeer.java:215) */ 2418 + while (!tryAuthenticate()) { 2419 + authenticator.retry(); 2420 + authenticatorUnixLogin.retry(); 2421 + } 2422 + } else { 2423 + /* just try once and not forever... */ 2424 + if (!tryAuthenticate()) { 2425 + showConnectionStatus("Authentication Failed."); 2426 + showMessage("Authentication Failed."); 2427 + if (!offerRelogin) { 2428 + fatalError("auth failed."); 2429 + } 2430 + } else { 2431 + //showConnectionStatus("Authentication OK."); 2432 + } 2433 + } 2434 } 2435 2436 2437 @@ -428,7 +461,10 @@ 2438 gbc.ipadx = 100; 2439 gbc.ipady = 50; 2440 gridbag.setConstraints(authPanel, gbc); 2441 + try { 2442 vncContainer.add(authPanel); 2443 + } catch (Exception e) { 2444 + } 2445 2446 if (inSeparateFrame) { 2447 vncFrame.pack(); 2448 @@ -590,9 +626,28 @@ 2449 fatalError("HOST parameter not specified"); 2450 } 2451 } 2452 + Date d = new Date(); 2453 + System.out.println("-\nSSL VNC Java Applet starting. " + d); 2454 2455 - String str = readParameter("PORT", true); 2456 - port = Integer.parseInt(str); 2457 + port = 0; 2458 + String str = readParameter("PORT", false); 2459 + if (str != null) { 2460 + port = Integer.parseInt(str); 2461 + } 2462 + // When there is a proxy VNCSERVERPORT may be inaccessible (inside firewall). 2463 + vncserverport = 0; 2464 + str = readParameter("VNCSERVERPORT", false); 2465 + if (str != null) { 2466 + vncserverport = Integer.parseInt(str); 2467 + } 2468 + if (port == 0 && vncserverport == 0) { 2469 + fatalError("Neither PORT nor VNCSERVERPORT parameters specified"); 2470 + } 2471 + if (port == 0) { 2472 + // Nevertheless, fall back to vncserverport if we have to. 2473 + System.out.println("using vncserverport: '" + vncserverport + "' for PORT."); 2474 + port = vncserverport; 2475 + } 2476 2477 if (inAnApplet) { 2478 str = readParameter("Open New Window", false); 2479 @@ -626,6 +681,121 @@ 2480 2481 // SocketFactory. 2482 socketFactory = readParameter("SocketFactory", false); 2483 + 2484 + // SSL 2485 + disableSSL = false; 2486 + str = readParameter("DisableSSL", false); 2487 + if (str != null && str.equalsIgnoreCase("Yes")) 2488 + disableSSL = true; 2489 + 2490 + httpsPort = readParameter("httpsPort", false); 2491 + 2492 + // Extra GET, CONNECT string: 2493 + CONNECT = readParameter("CONNECT", false); 2494 + if (CONNECT != null) { 2495 + CONNECT = CONNECT.replaceAll(" ", ":"); 2496 + } 2497 + 2498 + GET = false; 2499 + str = readParameter("GET", false); 2500 + if (str != null && str.equalsIgnoreCase("Yes")) { 2501 + GET = true; 2502 + } 2503 + if (str != null && str.equalsIgnoreCase("1")) { 2504 + GET = true; 2505 + } 2506 + 2507 + urlPrefix = readParameter("urlPrefix", false); 2508 + if (urlPrefix != null) { 2509 + urlPrefix = urlPrefix.replaceAll("%2F", "/"); 2510 + urlPrefix = urlPrefix.replaceAll("%2f", "/"); 2511 + urlPrefix = urlPrefix.replaceAll("_2F_", "/"); 2512 + if (urlPrefix.indexOf("/") != 0) { 2513 + urlPrefix = "/" + urlPrefix; 2514 + } 2515 + } else { 2516 + urlPrefix = ""; 2517 + } 2518 + System.out.println("urlPrefix: '" + urlPrefix + "'"); 2519 + 2520 + oneTimeKey = readParameter("oneTimeKey", false); 2521 + if (oneTimeKey != null) { 2522 + System.out.println("oneTimeKey is set."); 2523 + } 2524 + 2525 + serverCert = readParameter("serverCert", false); 2526 + if (serverCert != null) { 2527 + System.out.println("serverCert is set."); 2528 + } 2529 + 2530 + forceProxy = false; 2531 + proxyHost = null; 2532 + proxyPort = null; 2533 + str = readParameter("forceProxy", false); 2534 + if (str != null) { 2535 + if (str.equalsIgnoreCase("Yes")) { 2536 + forceProxy = true; 2537 + } else if (str.equalsIgnoreCase("No")) { 2538 + forceProxy = false; 2539 + } else { 2540 + forceProxy = true; 2541 + String[] pieces = str.split(" "); 2542 + proxyHost = new String(pieces[0]); 2543 + if (pieces.length >= 2) { 2544 + proxyPort = new String(pieces[1]); 2545 + } else { 2546 + proxyPort = new String("8080"); 2547 + } 2548 + } 2549 + } 2550 + str = readParameter("proxyHost", false); 2551 + if (str != null) { 2552 + proxyHost = new String(str); 2553 + } 2554 + str = readParameter("proxyPort", false); 2555 + if (str != null) { 2556 + proxyPort = new String(str); 2557 + } 2558 + if (proxyHost != null && proxyPort == null) { 2559 + proxyPort = new String("8080"); 2560 + } 2561 + 2562 + ignoreProxy = false; 2563 + str = readParameter("ignoreProxy", false); 2564 + if (str != null && str.equalsIgnoreCase("Yes")) { 2565 + ignoreProxy = true; 2566 + } 2567 + 2568 + trustAllVncCerts = false; 2569 + str = readParameter("trustAllVncCerts", false); 2570 + if (str != null && str.equalsIgnoreCase("Yes")) { 2571 + trustAllVncCerts = true; 2572 + } 2573 + trustUrlVncCert = false; 2574 + str = readParameter("trustUrlVncCert", false); 2575 + if (str != null && str.equalsIgnoreCase("Yes")) { 2576 + trustUrlVncCert = true; 2577 + } 2578 + debugCerts = false; 2579 + str = readParameter("debugCerts", false); 2580 + if (str != null && str.equalsIgnoreCase("Yes")) { 2581 + debugCerts = true; 2582 + } 2583 + debugKeyboard = false; 2584 + str = readParameter("debugKeyboard", false); 2585 + if (str != null && str.equalsIgnoreCase("Yes")) { 2586 + debugKeyboard = true; 2587 + } 2588 + mapF5_to_atsign = false; 2589 + str = readParameter("mapF5_to_atsign", false); 2590 + if (str != null && str.equalsIgnoreCase("Yes")) { 2591 + mapF5_to_atsign = true; 2592 + } 2593 + forbid_Ctrl_Alt = false; 2594 + str = readParameter("forbid_Ctrl_Alt", false); 2595 + if (str != null && str.equalsIgnoreCase("Yes")) { 2596 + forbid_Ctrl_Alt = true; 2597 + } 2598 } 2599 2600 public String readParameter(String name, boolean required) { 2601