001: ///////////////////////////////////////////////////////////////////////////////
002: //
003: // This program is free software; you can redistribute it and/or modify
004: // it under the terms of the GNU General Public License and GNU Library
005: // General Public License as published by the Free Software Foundation;
006: // either version 2, or (at your option) any later version.
007: //
008: // This program is distributed in the hope that it will be useful,
009: // but WITHOUT ANY WARRANTY; without even the implied warranty of
010: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: // GNU General Public License and GNU Library General Public License
012: // for more details.
013: //
014: // You should have received a copy of the GNU General Public License
015: // and GNU Library General Public License along with this program; if
016: // not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
017: // MA 02139, USA.
018: //
019: ///////////////////////////////////////////////////////////////////////////////
020:
021: package org.rdesktop.server.rdp;
022:
023: import java.io.*;
024: import java.net.*;
025:
026: import org.rdesktop.server.rdp.rdp5.Rdp5;
027: import org.rdesktop.server.rdp.crypto.CryptoException;
028:
029: public abstract class RdpAbstractISO {
030: private static final int CONNECTION_REQUEST = 0xE0;
031: private static final int CONNECTION_CONFIRM = 0xD0;
032: private static final int DISCONNECT_REQUEST = 0x80;
033: private static final int DATA_TRANSFER = 0xF0;
034: private static final int ERROR = 0x70;
035: private static final int PROTOCOL_VERSION = 0x03;
036: private static final int EOT = 0x80;
037:
038: private RdpProto m_rdpProto;
039: private DataInputStream m_in;
040: private DataOutputStream m_out;
041: protected Socket m_rdpsock;
042:
043: public RdpAbstractISO(RdpProto rdpProto) {
044: m_rdpProto = rdpProto;
045: m_rdpsock = null;
046: m_in = null;
047: m_out = null;
048: }
049:
050: private void sendMessage(int type) throws IOException {
051: byte[] packet = new byte[11];
052: RdpPacket buffer = new RdpPacket(11);
053:
054: buffer.set8(PROTOCOL_VERSION); // send Version Info
055: buffer.set8(0); // reserved byte
056: buffer.setBigEndian16(11); // Length
057: buffer.set8(6); // Length of Header
058:
059: buffer.set8(type); //where code = CR or DR
060: buffer.setBigEndian16(0); // Destination reference ( 0 at CC and DR)
061:
062: buffer.setBigEndian16(0); // source reference should be a reasonable address we use 0
063: buffer.set8(0); //service class
064: buffer.copyToByteArray(packet, 0, 0, packet.length);
065: m_out.write(packet);
066: m_out.flush();
067: }
068:
069: private RdpPacket tcp_recv(RdpPacket p, int length)
070: throws IOException {
071: RdpPacket buffer = null;
072:
073: byte[] packet = new byte[length];
074: m_in.readFully(packet, 0, length);
075:
076: if (p == null) {
077: buffer = new RdpPacket(length);
078: buffer.copyFromByteArray(packet, 0, 0, packet.length);
079: buffer.markEnd(length);
080: buffer.setStart(buffer.getPosition());
081: } else {
082: buffer = new RdpPacket((p.getEnd() - p.getStart()) + length);
083: buffer.copyFromPacket(p, p.getStart(), 0, p.getEnd());
084: buffer.copyFromByteArray(packet, 0, p.getEnd(),
085: packet.length);
086: buffer.markEnd(p.getSize() + packet.length);
087: buffer.setPosition(p.getPosition());
088: buffer.setStart(0);
089: }
090:
091: return buffer;
092: }
093:
094: protected Socket negotiateSSL(Socket sock) throws Exception {
095: // TODO
096: return sock;
097: }
098:
099: protected void doSocketConnect(String host, int port)
100: throws IOException {
101: m_rdpsock = new Socket(InetAddress.getByName(host), port);
102: }
103:
104: public RdpPacket init(int length) {
105: RdpPacket data = new RdpPacket(length + 7);
106: data.incrementPosition(7);
107: data.setStart(data.getPosition());
108: return data;
109: }
110:
111: public int available() throws java.io.IOException {
112: return m_in.available();
113: }
114:
115: public void connect() throws IOException, RdpDesktopException,
116: RdpOrderException, CryptoException {
117: int[] code = new int[1];
118: doSocketConnect(m_rdpProto.m_host, m_rdpProto.m_port);
119: m_rdpsock.setTcpNoDelay(RdpOptions.low_latency);
120: m_in = new DataInputStream(new BufferedInputStream(m_rdpsock
121: .getInputStream()));
122: m_out = new DataOutputStream(new BufferedOutputStream(m_rdpsock
123: .getOutputStream()));
124: send_connection_request();
125:
126: receiveMessage(code);
127: if (code[0] != CONNECTION_CONFIRM) {
128: throw new RdpDesktopException("Expected CC got:"
129: + Integer.toHexString(code[0]).toUpperCase());
130: }
131:
132: /*
133: if (RdpOptions.use_ssl == true)
134: {
135: try
136: {
137: m_rdpsock = this.negotiateSSL(m_rdpsock);
138: m_in = new DataInputStream(m_rdpsock.getInputStream());
139: m_out = new DataOutputStream(m_rdpsock.getOutputStream());
140: }
141: catch (Exception e)
142: {
143: e.printStackTrace();
144: throw new RdpDesktopException("SSL negotiation failed: " + e.getMessage());
145: }
146: }
147: */
148: }
149:
150: public void send(RdpPacket buffer) throws RdpDesktopException,
151: IOException {
152: if (m_rdpsock == null) {
153: return;
154: }
155:
156: if (buffer.getEnd() < 0) {
157: throw new RdpDesktopException("No End Mark!");
158: }
159:
160: int length = buffer.getEnd();
161: byte[] packet = new byte[length];
162: buffer.setPosition(0);
163: buffer.set8(PROTOCOL_VERSION); // Version
164: buffer.set8(0); // reserved
165: buffer.setBigEndian16(length); //length of packet
166:
167: buffer.set8(2); //length of header
168: buffer.set8(DATA_TRANSFER);
169: buffer.set8(EOT);
170: buffer.copyToByteArray(packet, 0, 0, buffer.getEnd());
171: m_out.write(packet);
172: m_out.flush();
173: }
174:
175: public RdpPacket receive() throws IOException, RdpDesktopException,
176: RdpOrderException, CryptoException {
177: int[] type = new int[1];
178: RdpPacket buffer = receiveMessage(type);
179:
180: if (buffer == null) {
181: return null;
182: }
183:
184: if (type[0] != DATA_TRANSFER) {
185: throw new RdpDesktopException("Expected DT got:" + type[0]);
186: }
187:
188: return buffer;
189: }
190:
191: private RdpPacket receiveMessage(int[] type) throws IOException,
192: RdpDesktopException, RdpOrderException, CryptoException {
193: RdpPacket s = null;
194: int length, version;
195:
196: next_packet:
197:
198: while (true) {
199: s = tcp_recv(null, 4);
200: if (s == null) {
201: return null;
202: }
203:
204: version = s.get8();
205:
206: if (version == 3) {
207: s.incrementPosition(1); // pad
208: length = s.getBigEndian16();
209: } else {
210: length = s.get8();
211: if ((length & 0x80) != 0) {
212: length &= ~0x80;
213: length = (length << 8) + s.get8();
214: }
215: }
216:
217: s = tcp_recv(s, length - 4);
218: if (s == null) {
219: return null;
220: }
221:
222: if ((version & 3) == 0) {
223: ((Rdp5) m_rdpProto).rdp5_process(s,
224: (version & 0x80) != 0);
225: continue next_packet;
226: } else {
227: break;
228: }
229: }
230:
231: s.get8();
232: type[0] = s.get8();
233:
234: if (type[0] == DATA_TRANSFER) {
235: s.incrementPosition(1); // eot
236: return s;
237: }
238:
239: s.incrementPosition(5); // dst_ref, src_ref, class
240: return s;
241: }
242:
243: public void disconnect() {
244: if (m_rdpsock == null) {
245: return;
246: }
247:
248: try {
249: sendMessage(DISCONNECT_REQUEST);
250:
251: if (m_rdpsock != null) {
252: m_rdpsock.close();
253: }
254: } catch (IOException e) {
255: }
256:
257: m_rdpsock = null;
258: m_in = null;
259: m_out = null;
260: }
261:
262: public void send_connection_request() throws IOException {
263: String uname = m_rdpProto.m_username;
264: if (uname.length() > 9) {
265: uname = uname.substring(0, 9);
266: }
267:
268: int length = 11 + (m_rdpProto.m_username.length() > 0 ? ("Cookie: mstshash="
269: .length()
270: + uname.length() + 2)
271: : 0) + 8;
272: RdpPacket buffer = new RdpPacket(length);
273: byte[] packet = new byte[length];
274:
275: buffer.set8(PROTOCOL_VERSION); // send Version Info
276: buffer.set8(0); // reserved byte
277: buffer.setBigEndian16(length); // Length
278: buffer.set8(length - 5); // Length of Header
279: buffer.set8(CONNECTION_REQUEST);
280: buffer.setBigEndian16(0); // Destination reference ( 0 at CC and DR)
281: buffer.setBigEndian16(0); // source reference should be a reasonable address we use 0
282: buffer.set8(0); //service class
283:
284: if (m_rdpProto.m_username.length() > 0) {
285: buffer.out_uint8p("Cookie: mstshash=", "Cookie: mstshash="
286: .length());
287: buffer.out_uint8p(uname, uname.length());
288:
289: buffer.set8(0x0d); // unknown
290: buffer.set8(0x0a); // unknown
291: }
292:
293: /*
294: // Authentication request?
295: buffer.setLittleEndian16(0x01);
296: buffer.setLittleEndian16(0x08);
297: // Do we try to use SSL?
298: buffer.set8(RdpOptions.use_ssl? 0x01 : 0x00);
299: buffer.incrementPosition(3);
300: */
301: buffer.copyToByteArray(packet, 0, 0, packet.length);
302: m_out.write(packet);
303: m_out.flush();
304: }
305: }
|