--- sourceforge.net/branches/RDESKTOP/rdesktop/iso.c 2000/05/10 07:36:34 3 +++ sourceforge.net/trunk/rdesktop/iso.c 2003/08/11 11:08:19 439 @@ -1,7 +1,7 @@ -/* +/* -*- c-basic-offset: 8 -*- rdesktop: A Remote Desktop Protocol client. Protocol services - ISO layer - Copyright (C) Matthew Chapman 1999-2000 + Copyright (C) Matthew Chapman 1999-2002 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,157 +18,196 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "includes.h" +#include "rdesktop.h" -/* Establish a connection up to the ISO layer */ -HCONN iso_connect(char *server) +/* Send a self-contained ISO PDU */ +static void +iso_send_msg(uint8 code) { - HCONN conn; - uint8 code; + STREAM s; - if ((conn = tcp_connect(server)) == NULL) - return NULL; + s = tcp_init(11); - iso_send_msg(conn, ISO_PDU_CR); + out_uint8(s, 3); /* version */ + out_uint8(s, 0); /* reserved */ + out_uint16_be(s, 11); /* length */ - if (!iso_recv_msg(conn, &code) || (code != ISO_PDU_CC)) - { - fprintf(stderr, "ISO error, expected CC\n"); - tcp_disconnect(conn); - return NULL; - } + out_uint8(s, 6); /* hdrlen */ + out_uint8(s, code); + out_uint16(s, 0); /* dst_ref */ + out_uint16(s, 0); /* src_ref */ + out_uint8(s, 0); /* class */ - return conn; + s_mark_end(s); + tcp_send(s); } -/* Disconnect from the ISO layer */ -void iso_disconnect(HCONN conn) +static void +iso_send_connection_request(char *username) { - iso_send_msg(conn, ISO_PDU_DR); - tcp_disconnect(conn); -} + STREAM s; + int length = 30 + strlen(username); -/* Send self-contained ISO message identified by code */ -BOOL iso_send_msg(HCONN conn, uint8 code) -{ - TPKT tpkt; - TPDU tpdu; + s = tcp_init(length); + + out_uint8(s, 3); /* version */ + out_uint8(s, 0); /* reserved */ + out_uint16_be(s, length); /* length */ + + out_uint8(s, length - 5); /* hdrlen */ + out_uint8(s, ISO_PDU_CR); + out_uint16(s, 0); /* dst_ref */ + out_uint16(s, 0); /* src_ref */ + out_uint8(s, 0); /* class */ + + out_uint8p(s, "Cookie: mstshash=", strlen("Cookie: mstshash=")); + out_uint8p(s, username, strlen(username)); - iso_make_tpkt(&tpkt, 11); - iso_io_tpkt(&conn->out, &tpkt); - iso_make_tpdu(&tpdu, code); - iso_io_tpdu(&conn->out, &tpdu); - MARK_END(conn->out); - return tcp_send(conn); + out_uint8(s, 0x0d); /* Unknown */ + out_uint8(s, 0x0a); /* Unknown */ + + s_mark_end(s); + tcp_send(s); } /* Receive a message on the ISO layer, return code */ -BOOL iso_recv_msg(HCONN conn, uint8 *code) +static STREAM +iso_recv_msg(uint8 * code) { - TPDU tpdu; - TPKT tpkt; - BOOL res; - - res = tcp_recv(conn, 4); - res = res ? iso_io_tpkt(&conn->in, &tpkt) : False; - res = res ? tcp_recv(conn, tpkt.length - 4) : False; - res = res ? iso_io_tpdu(&conn->in, &tpdu) : False; + STREAM s; + uint16 length; + uint8 version; + + next_packet: + s = tcp_recv(NULL, 4); + if (s == NULL) + return NULL; - *code = tpdu.code; - return res; -} + in_uint8(s, version); + switch (version & 3) + { + case 0: + in_uint8(s, length); + if (length & 0x80) + { + length &= ~0x80; + next_be(s, length); + } + break; + + case 3: + in_uint8s(s, 1); /* pad */ + in_uint16_be(s, length); + break; + + default: + error("TPKT v%d\n", version); + return NULL; + } -/* Initialise ISO transport data packet */ -void iso_init(struct connection *conn) -{ - PUSH_LAYER(conn->out, iso_offset, 7); -} + s = tcp_recv(s, length - 4); + if (s == NULL) + return NULL; -/* Receive ISO transport data packet */ -BOOL iso_recv(HCONN conn) -{ - uint8 code; + if ((version & 3) == 0) + { + rdp5_process(s, version & 0x80); + goto next_packet; + } - if (!iso_recv_msg(conn, &code) || (code != ISO_PDU_DT)) + in_uint8s(s, 1); /* hdrlen */ + in_uint8(s, *code); + + if (*code == ISO_PDU_DT) { - fprintf(stderr, "ISO error, expected DT\n"); - return False; + in_uint8s(s, 1); /* eot */ + return s; } - return True; + in_uint8s(s, 5); /* dst_ref, src_ref, class */ + return s; } -/* Receive ISO transport data packet */ -BOOL iso_send(HCONN conn) +/* Initialise ISO transport data packet */ +STREAM +iso_init(int length) { - TPKT tpkt; - TPDU tpdu; + STREAM s; - POP_LAYER(conn->out, iso_offset); - iso_make_tpkt(&tpkt, conn->out.end); - iso_io_tpkt(&conn->out, &tpkt); - iso_make_tpdu(&tpdu, ISO_PDU_DT); - iso_io_tpdu(&conn->out, &tpdu); - return tcp_send(conn); -} + s = tcp_init(length + 7); + s_push_layer(s, iso_hdr, 7); -/* Initialise a TPKT structure */ -void iso_make_tpkt(TPKT *tpkt, int length) -{ - tpkt->version = 3; - tpkt->reserved = 0; - tpkt->length = length; + return s; } -/* Marshall/demarshall a TPKT structure */ -BOOL iso_io_tpkt(STREAM s, TPKT *tpkt) +/* Send an ISO data PDU */ +void +iso_send(STREAM s) { - if (!prs_io_uint8(s, &tpkt->version)) - return False; + uint16 length; - if (tpkt->version != 3) - { - fprintf(stderr, "Wrong TPKT version %d\n", tpkt->version); - return False; - } + s_pop_layer(s, iso_hdr); + length = s->end - s->p; - if (!prs_io_uint8 (s, &tpkt->reserved)) - return False; + out_uint8(s, 3); /* version */ + out_uint8(s, 0); /* reserved */ + out_uint16_be(s, length); - if (!msb_io_uint16(s, &tpkt->length)) - return False; + out_uint8(s, 2); /* hdrlen */ + out_uint8(s, ISO_PDU_DT); /* code */ + out_uint8(s, 0x80); /* eot */ - return True; + tcp_send(s); } -/* Initialise a TPDU structure */ -void iso_make_tpdu(TPDU *tpdu, uint8 code) +/* Receive ISO transport data packet */ +STREAM +iso_recv(void) { - tpdu->hlen = (code == ISO_PDU_DT) ? 2 : 6; - tpdu->code = code; - tpdu->dst_ref = tpdu->src_ref = 0; - tpdu->class = 0; - tpdu->eot = 0x80; + STREAM s; + uint8 code; + + s = iso_recv_msg(&code); + if (s == NULL) + return NULL; + + if (code != ISO_PDU_DT) + { + error("expected DT, got 0x%x\n", code); + return NULL; + } + + return s; } -/* Marshall/demarshall a TPDU structure */ -BOOL iso_io_tpdu(STREAM s, TPDU *tpdu) +/* Establish a connection up to the ISO layer */ +BOOL +iso_connect(char *server, char *username) { - BOOL res = True; + uint8 code; + + if (!tcp_connect(server)) + return False; - res = res ? prs_io_uint8 (s, &tpdu->hlen) : False; - res = res ? prs_io_uint8 (s, &tpdu->code) : False; + iso_send_connection_request(username); - if (tpdu->code == ISO_PDU_DT) - { - res = res ? prs_io_uint8(s, &tpdu->eot) : False; - } - else + if (iso_recv_msg(&code) == NULL) + return False; + + if (code != ISO_PDU_CC) { - res = res ? msb_io_uint16(s, &tpdu->dst_ref) : False; - res = res ? msb_io_uint16(s, &tpdu->src_ref) : False; - res = res ? prs_io_uint8 (s, &tpdu->class ) : False; + error("expected CC, got 0x%x\n", code); + tcp_disconnect(); + return False; } - return res; + return True; +} + +/* Disconnect from the ISO layer */ +void +iso_disconnect(void) +{ + iso_send_msg(ISO_PDU_DR); + tcp_disconnect(); }