1 2 package ch.ethz.ssh2.channel; 3 4 import java.io.IOException ; 5 import java.io.InputStream ; 6 import java.io.OutputStream ; 7 import java.net.Socket ; 8 9 import ch.ethz.ssh2.log.Logger; 10 11 17 public class RemoteX11AcceptThread extends Thread 18 { 19 private static final Logger log = Logger.getLogger(RemoteX11AcceptThread.class); 20 21 Channel c; 22 23 String remoteOriginatorAddress; 24 int remoteOriginatorPort; 25 26 Socket s; 27 28 public RemoteX11AcceptThread(Channel c, String remoteOriginatorAddress, int remoteOriginatorPort) 29 { 30 this.c = c; 31 this.remoteOriginatorAddress = remoteOriginatorAddress; 32 this.remoteOriginatorPort = remoteOriginatorPort; 33 } 34 35 public void run() 36 { 37 try 38 { 39 40 41 c.cm.sendOpenConfirmation(c); 42 43 44 45 OutputStream remote_os = c.getStdinStream(); 46 InputStream remote_is = c.getStdoutStream(); 47 48 55 56 79 80 81 82 byte[] header = new byte[6]; 83 84 if (remote_is.read(header) != 6) 85 throw new IOException ("Unexpected EOF on X11 startup!"); 86 87 if ((header[0] != 0x42) && (header[0] != 0x6c)) throw new IOException ("Unknown endian format in X11 message!"); 89 90 91 92 int idxMSB = (header[0] == 0x42) ? 0 : 1; 93 94 95 96 byte[] auth_buff = new byte[6]; 97 98 if (remote_is.read(auth_buff) != 6) 99 throw new IOException ("Unexpected EOF on X11 startup!"); 100 101 int authProtocolNameLength = ((auth_buff[idxMSB] & 0xff) << 8) | (auth_buff[1 - idxMSB] & 0xff); 102 int authProtocolDataLength = ((auth_buff[2 + idxMSB] & 0xff) << 8) | (auth_buff[3 - idxMSB] & 0xff); 103 104 if ((authProtocolNameLength > 256) || (authProtocolDataLength > 256)) 105 throw new IOException ("Buggy X11 authorization data"); 106 107 int authProtocolNamePadding = ((4 - (authProtocolNameLength % 4)) % 4); 108 int authProtocolDataPadding = ((4 - (authProtocolDataLength % 4)) % 4); 109 110 byte[] authProtocolName = new byte[authProtocolNameLength]; 111 byte[] authProtocolData = new byte[authProtocolDataLength]; 112 113 byte[] paddingBuffer = new byte[4]; 114 115 if (remote_is.read(authProtocolName) != authProtocolNameLength) 116 throw new IOException ("Unexpected EOF on X11 startup! (authProtocolName)"); 117 118 if (remote_is.read(paddingBuffer, 0, authProtocolNamePadding) != authProtocolNamePadding) 119 throw new IOException ("Unexpected EOF on X11 startup! (authProtocolNamePadding)"); 120 121 if (remote_is.read(authProtocolData) != authProtocolDataLength) 122 throw new IOException ("Unexpected EOF on X11 startup! (authProtocolData)"); 123 124 if (remote_is.read(paddingBuffer, 0, authProtocolDataPadding) != authProtocolDataPadding) 125 throw new IOException ("Unexpected EOF on X11 startup! (authProtocolDataPadding)"); 126 127 if ("MIT-MAGIC-COOKIE-1".equals(new String (authProtocolName)) == false) 128 throw new IOException ("Unknown X11 authorization protocol!"); 129 130 if (authProtocolDataLength != 16) 131 throw new IOException ("Wrong data length for X11 authorization data!"); 132 133 StringBuffer tmp = new StringBuffer (32); 134 for (int i = 0; i < authProtocolData.length; i++) 135 { 136 String digit2 = Integer.toHexString(authProtocolData[i] & 0xff); 137 tmp.append((digit2.length() == 2) ? digit2 : "0" + digit2); 138 } 139 String hexEncodedFakeCookie = tmp.toString(); 140 141 144 145 synchronized (c) 146 { 147 148 c.hexX11FakeCookie = hexEncodedFakeCookie; 149 } 150 151 152 153 X11ServerData sd = c.cm.checkX11Cookie(hexEncodedFakeCookie); 154 155 if (sd == null) 156 throw new IOException ("Invalid X11 cookie received."); 157 158 162 163 s = new Socket (sd.hostname, sd.port); 164 165 OutputStream x11_os = s.getOutputStream(); 166 InputStream x11_is = s.getInputStream(); 167 168 169 170 x11_os.write(header); 171 172 if (sd.x11_magic_cookie == null) 173 { 174 byte[] emptyAuthData = new byte[6]; 175 176 x11_os.write(emptyAuthData); 177 } 178 else 179 { 180 if (sd.x11_magic_cookie.length != 16) 181 throw new IOException ("The real X11 cookie has an invalid length!"); 182 183 184 x11_os.write(auth_buff); 185 x11_os.write(authProtocolName); 186 x11_os.write(paddingBuffer, 0, authProtocolNamePadding); 187 x11_os.write(sd.x11_magic_cookie); 188 x11_os.write(paddingBuffer, 0, authProtocolDataPadding); 189 } 190 191 x11_os.flush(); 192 193 194 195 StreamForwarder r2l = new StreamForwarder(c, null, null, remote_is, x11_os, "RemoteToX11"); 196 StreamForwarder l2r = new StreamForwarder(c, null, null, x11_is, remote_os, "X11ToRemote"); 197 198 199 200 r2l.setDaemon(true); 201 r2l.start(); 202 l2r.run(); 203 204 while (r2l.isAlive()) 205 { 206 try 207 { 208 r2l.join(); 209 } 210 catch (InterruptedException e) 211 { 212 } 213 } 214 215 216 217 c.cm.closeChannel(c, "EOF on both X11 streams reached.", true); 218 s.close(); 219 } 220 catch (IOException e) 221 { 222 log.log(50, "IOException in X11 proxy code: " + e.getMessage()); 223 224 try 225 { 226 c.cm.closeChannel(c, "IOException in X11 proxy code (" + e.getMessage() + ")", true); 227 } 228 catch (IOException e1) 229 { 230 } 231 try 232 { 233 if (s != null) 234 s.close(); 235 } 236 catch (IOException e1) 237 { 238 } 239 } 240 } 241 } 242 | Popular Tags |