1 Index: invirt-vnc-client/InvirtTrustManager.java
2 ===================================================================
3 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4 +++ invirt-vnc-client/InvirtTrustManager.java 2008-10-31 06:09:10.000000000 -0400
7 + * Copyright 2006 Perry Nguyen <pfnguyen@hanhuy.com>
8 + * Licensed under the Apache License, Version 2.0 (the "License");
9 + * you may not use this file except in compliance with the License.
10 + * You may obtain a copy of the License at
12 + * http://www.apache.org/licenses/LICENSE-2.0
14 + * Unless required by applicable law or agreed to in writing, software
15 + * distributed under the License is distributed on an "AS IS" BASIS,
16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 + * See the License for the specific language governing permissions and
18 + * limitations under the License.
20 +import java.io.IOException;
21 +import java.io.InputStream;
22 +import java.security.KeyStore;
23 +import java.security.KeyStoreException;
24 +import java.security.NoSuchAlgorithmException;
25 +import java.security.cert.CertificateException;
26 +import java.security.cert.X509Certificate;
27 +import java.util.Enumeration;
28 +import java.util.logging.Level;
29 +import java.util.logging.Logger;
31 +import javax.net.ssl.TrustManager;
32 +import javax.net.ssl.TrustManagerFactory;
33 +import javax.net.ssl.X509TrustManager;
35 +public class InvirtTrustManager implements X509TrustManager {
36 + private X509TrustManager trustManager;
37 + private final static char[] KEY_STORE_PASSWORD =
38 + { 'f', 'o', 'o', 'b', 'a', 'r' };
39 + private final static String KEY_STORE_RESOURCE =
42 + private KeyStore loadKeyStore() throws Exception {
43 + InputStream in = getClass().getClassLoader().getResourceAsStream(
44 + KEY_STORE_RESOURCE);
48 + //log.severe("Unable to open KeyStore");
49 + throw new NullPointerException();
51 + ks = KeyStore.getInstance(KeyStore.getDefaultType());
52 + ks.load(in, KEY_STORE_PASSWORD);
53 + /*if (log.isLoggable(Level.FINEST)) {
54 + for (Enumeration<String> aliases = ks.aliases();
55 + aliases.hasMoreElements();) {
56 + String alias = aliases.nextElement();
57 + log.finest("ALIAS: " + alias);
60 + } catch (NoSuchAlgorithmException e) {
62 + } catch (CertificateException e) {
64 + } catch (IOException e) {
66 + } catch (KeyStoreException e) {
73 + catch (IOException e) { } // ignore
77 + private void createTrustManager() {
80 + KeyStore keystore = loadKeyStore();
81 + TrustManagerFactory factory = TrustManagerFactory.getInstance(
82 + TrustManagerFactory.getDefaultAlgorithm());
83 + factory.init(keystore);
84 + TrustManager[] trustManagers = factory.getTrustManagers();
85 + if (trustManagers.length == 0)
86 + throw new IllegalStateException("No trust manager found");
87 + setTrustManager((X509TrustManager) trustManagers[0]);
88 + } catch (NoSuchAlgorithmException e) {
90 + } catch (KeyStoreException e) {
93 + } catch (Exception e) {
94 + e.printStackTrace();
97 + private void throwError(Exception e) throws Exception {
98 + //HttpClientError error = new HttpClientError(e.getMessage());
99 + //error.initCause(e);
102 + public X509TrustManager getTrustManager() {
103 + if (trustManager == null)
104 + createTrustManager();
105 + return trustManager;
108 + public void setTrustManager(X509TrustManager trustManager) {
109 + this.trustManager = trustManager;
112 + public void checkClientTrusted(X509Certificate[] chain, String authType)
113 + throws CertificateException {
114 + getTrustManager().checkClientTrusted(chain, authType);
117 + public void checkServerTrusted(X509Certificate[] chain, String authType)
118 + throws CertificateException {
119 + getTrustManager().checkServerTrusted(chain, authType);
123 + public X509Certificate[] getAcceptedIssuers() {
124 + return getTrustManager().getAcceptedIssuers();
128 \ No newline at end of file
129 Index: invirt-vnc-client/Makefile
130 ===================================================================
131 --- invirt-vnc-client.orig/Makefile 2008-10-31 06:09:10.000000000 -0400
132 +++ invirt-vnc-client/Makefile 2008-10-31 06:09:10.000000000 -0400
134 DesCipher.class CapabilityInfo.class CapsContainer.class \
135 RecordingFrame.class SessionRecorder.class \
136 SocketFactory.class HTTPConnectSocketFactory.class \
137 + VNCProxyConnectSocketFactory.class VNCProxyConnectSocket.class \
138 HTTPConnectSocket.class ReloginPanel.class \
139 - InStream.class MemInStream.class ZlibInStream.class
140 + InStream.class MemInStream.class ZlibInStream.class \
141 + VNCProxyConnectSocketWrapper.class SocketWrapper.class SocketWrapper\$$WrappingSocketImpl.class InvirtTrustManager.class
143 SOURCES = VncViewer.java RfbProto.java AuthPanel.java VncCanvas.java \
146 DesCipher.java CapabilityInfo.java CapsContainer.java \
147 RecordingFrame.java SessionRecorder.java \
148 SocketFactory.java HTTPConnectSocketFactory.java \
149 + VNCProxyConnectSocketFactory.java VNCProxyConnectSocket.java \
150 HTTPConnectSocket.java ReloginPanel.java \
151 - InStream.java MemInStream.java ZlibInStream.java
152 + InStream.java MemInStream.java ZlibInStream.java \
153 + VNCProxyConnectSocketWrapper.java SocketWrapper.java InvirtTrustManager.java
155 all: $(CLASSES) $(ARCHIVE)
157 Index: invirt-vnc-client/RfbProto.java
158 ===================================================================
159 --- invirt-vnc-client.orig/RfbProto.java 2007-04-26 22:36:00.000000000 -0400
160 +++ invirt-vnc-client/RfbProto.java 2008-10-31 06:09:10.000000000 -0400
161 @@ -208,11 +208,13 @@
164 if (viewer.socketFactory == null) {
165 + System.out.println("Null socketFactory");
166 sock = new Socket(host, port);
169 Class factoryClass = Class.forName(viewer.socketFactory);
170 SocketFactory factory = (SocketFactory)factoryClass.newInstance();
171 + System.out.println("Using socketFactory " + factory);
172 if (viewer.inAnApplet)
173 sock = factory.createSocket(host, port, viewer);
179 - System.out.println("RFB socket closed");
180 + System.out.println("RFB socket closed " + sock);
184 Index: invirt-vnc-client/SocketWrapper.java
185 ===================================================================
186 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
187 +++ invirt-vnc-client/SocketWrapper.java 2008-10-31 06:09:10.000000000 -0400
190 + * Written by Dawid Kurzyniec and released to the public domain, as explained
191 + * at http://creativecommons.org/licenses/publicdomain
194 +//package edu.emory.mathcs.util.net;
198 +import java.nio.channels.*;
201 + * Wrapper for sockets which enables to add functionality in subclasses
202 + * on top of existing, connected sockets. It is useful when direct subclassing
203 + * of delegate socket class is not possible, e.g. if the delegate socket is
204 + * created by a library. Possible usage example is socket factory chaining.
205 + * This class delegates all socket-related requests to the wrapped delegate,
208 + * @author Dawid Kurzyniec
211 +public abstract class SocketWrapper extends Socket {
214 + * the wrapped delegate socket.
216 + protected final Socket delegate;
219 + * Creates new socket wrapper for a given socket. The delegate
220 + * must be connected and bound and it must not be closed.
221 + * @param delegate the delegate socket to wrap
222 + * @throws SocketException if the delegate socket is closed, not bound,
225 + protected SocketWrapper(Socket delegate) throws SocketException {
226 + super(new WrappingSocketImpl(delegate));
227 + this.delegate = delegate;
228 + System.out.println("Creating SocketWrapper $Rev$");
231 + public SocketChannel getChannel() {
232 + return delegate.getChannel();
236 + * Returns true, indicating that the socket is bound.
240 + public boolean isBound() {
244 + public boolean isClosed() {
245 + return super.isClosed() || delegate.isClosed();
249 + * Returns true, indicating that the socket is connected.
253 + public boolean isConnected() {
257 + public boolean isInputShutdown() {
258 + return super.isInputShutdown() || delegate.isInputShutdown();
261 + public boolean isOutputShutdown() {
262 + return super.isInputShutdown() || delegate.isOutputShutdown();
265 + private static class WrappingSocketImpl extends SocketImpl {
266 + private final Socket delegate;
267 + WrappingSocketImpl(Socket delegate) throws SocketException {
268 + if (delegate == null) {
269 + throw new NullPointerException();
271 + if (delegate.isClosed()) {
272 + throw new SocketException("Delegate server socket is closed");
274 + if (!(delegate.isBound())) {
275 + throw new SocketException("Delegate server socket is not bound");
277 + if (!(delegate.isConnected())) {
278 + throw new SocketException("Delegate server socket is not connected");
280 + this.delegate = delegate;
283 + protected void create(boolean stream) {}
285 + protected void connect(String host, int port) {
286 + // delegate is always connected, thus this method is never called
287 + throw new UnsupportedOperationException();
290 + protected void connect(InetAddress address, int port) {
291 + // delegate is always connected, thus this method is never called
292 + throw new UnsupportedOperationException();
295 + protected void connect(SocketAddress address, int timeout) {
296 + // delegate is always connected, thus this method is never called
297 + throw new UnsupportedOperationException();
300 + protected void bind(InetAddress host, int port) {
301 + // delegate is always bound, thus this method is never called
302 + throw new UnsupportedOperationException();
305 + protected void listen(int backlog) {
306 + // this wrapper is never used by a ServerSocket
307 + throw new UnsupportedOperationException();
310 + protected void accept(SocketImpl s) {
311 + // this wrapper is never used by a ServerSocket
312 + throw new UnsupportedOperationException();
315 + protected InputStream getInputStream() throws IOException {
316 + return delegate.getInputStream();
319 + protected OutputStream getOutputStream() throws IOException {
320 + return delegate.getOutputStream();
323 + protected int available() throws IOException {
324 + return getInputStream().available();
327 + protected void close() throws IOException {
328 + System.out.println("Calling delegate.close");
332 + protected void shutdownInput() throws IOException {
333 + delegate.shutdownInput();
336 + protected void shutdownOutput() throws IOException {
337 + delegate.shutdownOutput();
340 + protected FileDescriptor getFileDescriptor() {
341 + // this wrapper is never used by a ServerSocket
342 + throw new UnsupportedOperationException();
345 + protected InetAddress getInetAddress() {
346 + return delegate.getInetAddress();
349 + protected int getPort() {
350 + return delegate.getPort();
353 + protected boolean supportsUrgentData() {
354 + return false; // must be overridden in sub-class
357 + protected void sendUrgentData (int data) throws IOException {
358 + delegate.sendUrgentData(data);
361 + protected int getLocalPort() {
362 + return delegate.getLocalPort();
365 + public Object getOption(int optID) throws SocketException {
367 + case SocketOptions.IP_TOS:
368 + return new Integer(delegate.getTrafficClass());
369 + case SocketOptions.SO_BINDADDR:
370 + return delegate.getLocalAddress();
371 + case SocketOptions.SO_KEEPALIVE:
372 + return Boolean.valueOf(delegate.getKeepAlive());
373 + case SocketOptions.SO_LINGER:
374 + return new Integer(delegate.getSoLinger());
375 + case SocketOptions.SO_OOBINLINE:
376 + return Boolean.valueOf(delegate.getOOBInline());
377 + case SocketOptions.SO_RCVBUF:
378 + return new Integer(delegate.getReceiveBufferSize());
379 + case SocketOptions.SO_REUSEADDR:
380 + return Boolean.valueOf(delegate.getReuseAddress());
381 + case SocketOptions.SO_SNDBUF:
382 + return new Integer(delegate.getSendBufferSize());
383 + case SocketOptions.SO_TIMEOUT:
384 + return new Integer(delegate.getSoTimeout());
385 + case SocketOptions.TCP_NODELAY:
386 + return Boolean.valueOf(delegate.getTcpNoDelay());
387 + case SocketOptions.SO_BROADCAST:
389 + throw new IllegalArgumentException("Unsupported option type");
393 + public void setOption(int optID, Object value) throws SocketException {
395 + case SocketOptions.SO_BINDADDR:
396 + throw new IllegalArgumentException("Socket is bound");
397 + case SocketOptions.SO_KEEPALIVE:
398 + delegate.setKeepAlive(((Boolean)value).booleanValue());
400 + case SocketOptions.SO_LINGER:
401 + if (value instanceof Boolean) {
402 + delegate.setSoLinger(((Boolean)value).booleanValue(), 0);
405 + delegate.setSoLinger(true, ((Integer)value).intValue());
408 + case SocketOptions.SO_OOBINLINE:
409 + delegate.setOOBInline(((Boolean)value).booleanValue());
411 + case SocketOptions.SO_RCVBUF:
412 + delegate.setReceiveBufferSize(((Integer)value).intValue());
414 + case SocketOptions.SO_REUSEADDR:
415 + delegate.setReuseAddress(((Boolean)value).booleanValue());
417 + case SocketOptions.SO_SNDBUF:
418 + delegate.setSendBufferSize(((Integer)value).intValue());
420 + case SocketOptions.SO_TIMEOUT:
421 + delegate.setSoTimeout(((Integer)value).intValue());
423 + case SocketOptions.TCP_NODELAY:
424 + delegate.setTcpNoDelay(((Boolean)value).booleanValue());
426 + case SocketOptions.SO_BROADCAST:
428 + throw new IllegalArgumentException("Unsupported option type");
433 + public void close() throws IOException {
434 + System.out.println("Calling SocketWrapper.delegate.close");
438 + public boolean equals(Object obj) {
439 + if (!(obj instanceof SocketWrapper)) return false;
440 + SocketWrapper that = (SocketWrapper)obj;
441 + return this.delegate.equals(that.delegate);
444 + public int hashCode() {
445 + return delegate.hashCode() ^ 0x01010101;
447 + public String toString() {
448 + return "<SocketWrapper " + super.toString() + "(delegating to " + delegate.toString() + ")" + ">";
451 \ No newline at end of file
452 Index: invirt-vnc-client/VNCProxyConnectSocket.java
453 ===================================================================
454 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
455 +++ invirt-vnc-client/VNCProxyConnectSocket.java 2008-10-31 06:09:10.000000000 -0400
458 +// Copyright (C) 2002 Constantin Kaplinsky, Inc. All Rights Reserved.
459 +// Copyright 2007 MIT Student Information Processing Board
461 +// This is free software; you can redistribute it and/or modify
462 +// it under the terms of the GNU General Public License as published by
463 +// the Free Software Foundation; either version 2 of the License, or
464 +// (at your option) any later version.
466 +// This software is distributed in the hope that it will be useful,
467 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
468 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
469 +// GNU General Public License for more details.
471 +// You should have received a copy of the GNU General Public License
472 +// along with this software; if not, write to the Free Software
473 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
478 +// VNCProxySocket.java together with VNCProxySocketFactory.java
479 +// implement an alternate way to connect to VNC servers via one or two
480 +// VNCProxy proxies supporting the VNCProxy VNCCONNECT method.
486 +class VNCProxyConnectSocket extends Socket {
488 + public VNCProxyConnectSocket(String host, int port,
489 + String vmname, String authtoken)
490 + throws IOException {
492 + // Connect to the specified HTTP proxy
495 + // Send the CONNECT request
496 + getOutputStream().write(("CONNECTVNC " + vmname +
497 + " VNCProxy/1.0\r\nAuth-token: " + authtoken +
498 + "\r\n\r\n").getBytes());
500 + // Read the first line of the response
501 + DataInputStream is = new DataInputStream(getInputStream());
502 + String str = is.readLine();
504 + // Check the HTTP error code -- it should be "200" on success
505 + if (!str.startsWith("VNCProxy/1.0 200 ")) {
506 + if (str.startsWith("VNCProxy/1.0 "))
507 + str = str.substring(13);
508 + throw new IOException("Proxy reports \"" + str + "\"");
511 + // Success -- skip remaining HTTP headers
513 + str = is.readLine();
514 + } while (str.length() != 0);
518 Index: invirt-vnc-client/VNCProxyConnectSocketFactory.java
519 ===================================================================
520 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
521 +++ invirt-vnc-client/VNCProxyConnectSocketFactory.java 2008-10-31 06:09:10.000000000 -0400
524 +// Copyright (C) 2002 Constantin Kaplinsky, Inc. All Rights Reserved.
525 +// Copyright 2007 MIT Student Information Processing Board
527 +// This is free software; you can redistribute it and/or modify
528 +// it under the terms of the GNU General Public License as published by
529 +// the Free Software Foundation; either version 2 of the License, or
530 +// (at your option) any later version.
532 +// This software is distributed in the hope that it will be useful,
533 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
534 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
535 +// GNU General Public License for more details.
537 +// You should have received a copy of the GNU General Public License
538 +// along with this software; if not, write to the Free Software
539 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
544 +// VNCProxyConnectSocketFactory.java together with VNCProxyConnectSocket.java
545 +// implement an alternate way to connect to VNC servers via one or two
546 +// VNCProxy proxies supporting the VNCProxy CONNECT method.
549 +import java.applet.*;
551 +import javax.net.ssl.*;
554 +class VNCProxyConnectSocketFactory implements SocketFactory {
556 + SSLSocketFactory factory;
558 + public VNCProxyConnectSocketFactory() {
560 + SSLContext c = SSLContext.getInstance("SSL");
562 + new TrustManager[] { new InvirtTrustManager() },
565 + (SSLSocketFactory)c.getSocketFactory();
566 + } catch (Exception e) {
567 + e.printStackTrace();
571 + public Socket createSocket(String host, int port, Applet applet)
572 + throws IOException {
574 + return createSocket(host, port,
575 + applet.getParameter("VMNAME"),
576 + applet.getParameter("AUTHTOKEN"));
579 + public Socket createSocket(String host, int port, String[] args)
580 + throws IOException {
582 + return createSocket(host, port,
583 + readArg(args, "VMNAME"),
584 + readArg(args, "AUTHTOKEN"));
587 + public Socket createSocket(String host, int port,
588 + String vmname, String authtoken)
589 + throws IOException {
591 + if (vmname == null || authtoken == null) {
592 + System.out.println("Incomplete parameter list for VNCProxyConnectSocket");
593 + return new Socket(host, port);
596 + System.out.println("VNCProxy CONNECT via proxy " + host +
597 + " port " + port + " to vm " + vmname);
598 + SSLSocket ssls = (SSLSocket)factory.createSocket(host, port);
599 + ssls.startHandshake();
600 + VNCProxyConnectSocketWrapper s =
601 + new VNCProxyConnectSocketWrapper(ssls, vmname, authtoken);
606 + private String readArg(String[] args, String name) {
608 + for (int i = 0; i < args.length; i += 2) {
609 + if (args[i].equalsIgnoreCase(name)) {
612 + } catch (Exception e) {
621 Index: invirt-vnc-client/VNCProxyConnectSocketWrapper.java
622 ===================================================================
623 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
624 +++ invirt-vnc-client/VNCProxyConnectSocketWrapper.java 2008-10-31 06:09:10.000000000 -0400
627 +// Copyright (C) 2002 Constantin Kaplinsky, Inc. All Rights Reserved.
628 +// Copyright 2007 MIT Student Information Processing Board
630 +// This is free software; you can redistribute it and/or modify
631 +// it under the terms of the GNU General Public License as published by
632 +// the Free Software Foundation; either version 2 of the License, or
633 +// (at your option) any later version.
635 +// This software is distributed in the hope that it will be useful,
636 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
637 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
638 +// GNU General Public License for more details.
640 +// You should have received a copy of the GNU General Public License
641 +// along with this software; if not, write to the Free Software
642 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
647 +// VNCProxySocket.java together with VNCProxySocketFactory.java
648 +// implement an alternate way to connect to VNC servers via one or two
649 +// VNCProxy proxies supporting the VNCProxy VNCCONNECT method.
655 +class VNCProxyConnectSocketWrapper extends SocketWrapper {
657 + public VNCProxyConnectSocketWrapper(Socket sock,
658 + String vmname, String authtoken)
659 + throws IOException {
663 + // Send the CONNECT request
664 + getOutputStream().write(("CONNECTVNC " + vmname +
665 + " VNCProxy/1.0\r\nAuth-token: " + authtoken +
666 + "\r\n\r\n").getBytes());
668 + // Read the first line of the response
669 + DataInputStream is = new DataInputStream(getInputStream());
670 + String str = is.readLine();
672 + // Check the HTTP error code -- it should be "200" on success
673 + if (!str.startsWith("VNCProxy/1.0 200 ")) {
674 + if (str.startsWith("VNCProxy/1.0 "))
675 + str = str.substring(13);
676 + throw new IOException("Proxy reports \"" + str + "\"");
679 + // Success -- skip remaining HTTP headers
681 + str = is.readLine();
682 + } while (str.length() != 0);