]>
Commit | Line | Data |
---|---|---|
e6d0212c DM |
1 | |
2 | Unfortunately the java certificate store does not correctly access | |
3 | the browser certificate store (firefox, chrome). We also tunnel VNC | |
4 | traffic from other cluster nodes. | |
5 | ||
6 | So we implement our own trust manager, and allow to pass the server | |
7 | certificate (or CA who signed the server certificate) as applet | |
8 | parameter "PVECert" (newline encoded as '|'). | |
9 | ||
10 | Index: new/java/src/com/tigervnc/vncviewer/X509Tunnel.java | |
11 | =================================================================== | |
12 | --- new.orig/java/src/com/tigervnc/vncviewer/X509Tunnel.java 2011-01-28 13:22:50.000000000 +0100 | |
13 | +++ new/java/src/com/tigervnc/vncviewer/X509Tunnel.java 2011-01-28 13:26:51.000000000 +0100 | |
14 | @@ -26,13 +26,23 @@ | |
15 | import javax.net.ssl.*; | |
16 | import java.security.*; | |
17 | import java.security.cert.*; | |
18 | +import java.security.cert.Certificate; | |
19 | +import java.security.cert.CertificateFactory; | |
20 | +import java.io.*; | |
21 | ||
22 | public class X509Tunnel extends TLSTunnelBase | |
23 | { | |
24 | ||
25 | - public X509Tunnel (Socket sock_) | |
26 | + Certificate pvecert; | |
27 | + | |
28 | + public X509Tunnel (Socket sock_, String certstr) throws CertificateException | |
29 | { | |
30 | super (sock_); | |
31 | + | |
32 | + if (certstr != null) { | |
33 | + CertificateFactory cf = CertificateFactory.getInstance("X.509"); | |
34 | + pvecert = cf.generateCertificate(new StringBufferInputStream(certstr)); | |
35 | + } | |
36 | } | |
37 | ||
38 | protected void setParam (SSLSocket sock) | |
39 | @@ -52,9 +62,51 @@ | |
40 | protected void initContext (SSLContext sc) throws java.security. | |
41 | GeneralSecurityException | |
42 | { | |
43 | - TrustManager[] myTM = new TrustManager[] | |
44 | - { | |
45 | - new MyX509TrustManager ()}; | |
46 | + TrustManager[] myTM; | |
47 | + | |
48 | + if (pvecert != null) { | |
49 | + myTM = new TrustManager[] { | |
50 | + new X509TrustManager() { | |
51 | + public java.security.cert.X509Certificate[] | |
52 | + getAcceptedIssuers() { | |
53 | + return null; | |
54 | + } | |
55 | + public void checkClientTrusted( | |
56 | + java.security.cert.X509Certificate[] certs, | |
57 | + String authType) throws CertificateException { | |
58 | + throw new CertificateException("no clients"); | |
59 | + } | |
60 | + public void checkServerTrusted( | |
61 | + java.security.cert.X509Certificate[] certs, | |
62 | + String authType) throws CertificateException { | |
63 | + | |
64 | + if (certs == null || certs.length < 1) { | |
65 | + throw new CertificateException("no certs"); | |
66 | + } | |
67 | + if (certs == null || certs.length > 1) { | |
68 | + throw new CertificateException("cert path too long"); | |
69 | + } | |
70 | + PublicKey cakey = pvecert.getPublicKey(); | |
71 | + | |
72 | + boolean ca_match; | |
73 | + try { | |
74 | + certs[0].verify(cakey); | |
75 | + ca_match = true; | |
76 | + } catch (Exception e) { | |
77 | + ca_match = false; | |
78 | + } | |
79 | + | |
80 | + if (!ca_match && !pvecert.equals(certs[0])) { | |
81 | + throw new CertificateException("certificate does not match"); | |
82 | + } | |
83 | + } | |
84 | + } | |
85 | + }; | |
86 | + } else { | |
87 | + myTM = new TrustManager[] { | |
88 | + new MyX509TrustManager () | |
89 | + }; | |
90 | + } | |
91 | sc.init (null, myTM, null); | |
92 | } | |
93 | ||
94 | @@ -100,4 +152,5 @@ | |
95 | return tm.getAcceptedIssuers (); | |
96 | } | |
97 | } | |
98 | + | |
99 | } | |
100 | Index: new/java/src/com/tigervnc/vncviewer/RfbProto.java | |
101 | =================================================================== | |
102 | --- new.orig/java/src/com/tigervnc/vncviewer/RfbProto.java 2011-01-28 13:22:50.000000000 +0100 | |
103 | +++ new/java/src/com/tigervnc/vncviewer/RfbProto.java 2011-01-28 13:26:51.000000000 +0100 | |
104 | @@ -411,7 +411,8 @@ | |
105 | } | |
106 | ||
107 | void authenticateX509() throws Exception { | |
108 | - X509Tunnel tunnel = new X509Tunnel(sock); | |
109 | + | |
110 | + X509Tunnel tunnel = new X509Tunnel(sock, viewer.PVECert); | |
111 | tunnel.setup (this); | |
112 | } | |
113 | ||
114 | Index: new/java/src/com/tigervnc/vncviewer/VncViewer.java | |
115 | =================================================================== | |
116 | --- new.orig/java/src/com/tigervnc/vncviewer/VncViewer.java 2011-01-28 13:26:16.000000000 +0100 | |
117 | +++ new/java/src/com/tigervnc/vncviewer/VncViewer.java 2011-01-28 13:26:51.000000000 +0100 | |
118 | @@ -95,6 +95,8 @@ | |
119 | int debugStatsExcludeUpdates; | |
120 | int debugStatsMeasureUpdates; | |
121 | ||
122 | + String PVECert; | |
123 | + | |
124 | JSObject jswin; | |
125 | String myid; | |
126 | ||
127 | @@ -278,7 +280,7 @@ | |
128 | fatalError(e.toString(), e); | |
129 | } | |
130 | } | |
131 | - | |
132 | + | |
133 | } | |
134 | ||
135 | // | |
136 | @@ -314,7 +316,7 @@ | |
137 | // If the rfbThread is being stopped, ignore any exceptions, | |
138 | // otherwise rethrow the exception so it can be handled. | |
139 | // | |
140 | - | |
141 | + | |
142 | void processNormalProtocol() throws Exception { | |
143 | try { | |
144 | vc.processNormalProtocol(); | |
145 | @@ -857,6 +859,11 @@ | |
146 | ||
147 | // SocketFactory. | |
148 | socketFactory = readParameter("SocketFactory", false); | |
149 | + | |
150 | + String tmpcert = readParameter("PVECert", false); | |
151 | + if (tmpcert != null) { | |
152 | + PVECert = tmpcert.replace('|', '\n'); | |
153 | + } | |
154 | } | |
155 | ||
156 | // | |
157 | @@ -1010,7 +1017,7 @@ | |
158 | } | |
159 | ||
160 | synchronized public void fatalError(String str, Exception e) { | |
161 | - | |
162 | + | |
163 | if (rfb != null && rfb.closed()) { | |
164 | // Not necessary to show error message if the error was caused | |
165 | // by I/O problems after the rfb.close() method call. | |
166 | @@ -1108,11 +1115,11 @@ | |
167 | public void enableInput(boolean enable) { | |
168 | vc.enableInput(enable); | |
169 | } | |
170 | - | |
171 | + | |
172 | // | |
173 | // Resize framebuffer if autoScale is enabled. | |
174 | // | |
175 | - | |
176 | + | |
177 | public void componentResized(ComponentEvent e) { | |
178 | if (e.getComponent() == vncFrame) { | |
179 | if (options.autoScale) { | |
180 | @@ -1124,11 +1131,11 @@ | |
181 | } | |
182 | } | |
183 | } | |
184 | - | |
185 | + | |
186 | // | |
187 | // Ignore component events we're not interested in. | |
188 | // | |
189 | - | |
190 | + | |
191 | public void componentShown(ComponentEvent e) { } | |
192 | public void componentMoved(ComponentEvent e) { } | |
193 | public void componentHidden(ComponentEvent e) { } |