boolean nego_read_request(rdpNego* nego, STREAM* s) { uint8 li; uint8 c; uint8 type; tpkt_read_header(s); li = tpdu_read_connection_request(s); if (li != stream_get_left(s) + 6) { printf("Incorrect TPDU length indicator.\n"); return false; } if (stream_get_left(s) > 8) { /* Optional routingToken or cookie, ending with CR+LF */ while (stream_get_left(s) > 0) { stream_read_uint8(s, c); if (c != '\x0D') continue; stream_peek_uint8(s, c); if (c != '\x0A') continue; stream_seek_uint8(s); break; } } if (stream_get_left(s) >= 8) { /* rdpNegData (optional) */ stream_read_uint8(s, type); /* Type */ if (type != TYPE_RDP_NEG_REQ) { printf("Incorrect negotiation request type %d\n", type); return false; } nego_process_negotiation_request(nego, s); } return true; }
uint16 tpkt_read_header(STREAM* s) { uint8 version; uint16 length; stream_peek_uint8(s, version); if (version == 3) { stream_seek(s, 2); stream_read_uint16_be(s, length); } else { /* not a TPKT header */ length = 0; } return length; }
void certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info) { STREAM* s; int length; uint8 padding; uint32 version; int modulus_length; int exponent_length; s = stream_new(0); s->p = s->data = cert->data; ber_read_sequence_tag(s, &length); /* Certificate (SEQUENCE) */ ber_read_sequence_tag(s, &length); /* TBSCertificate (SEQUENCE) */ /* Explicit Contextual Tag [0] */ ber_read_contextual_tag(s, 0, &length, true); ber_read_integer(s, &version); /* version (INTEGER) */ version++; /* serialNumber */ ber_read_integer(s, NULL); /* CertificateSerialNumber (INTEGER) */ /* signature */ ber_read_sequence_tag(s, &length); /* AlgorithmIdentifier (SEQUENCE) */ stream_seek(s, length); /* issuer */ ber_read_sequence_tag(s, &length); /* Name (SEQUENCE) */ stream_seek(s, length); /* validity */ ber_read_sequence_tag(s, &length); /* Validity (SEQUENCE) */ stream_seek(s, length); /* subject */ ber_read_sequence_tag(s, &length); /* Name (SEQUENCE) */ stream_seek(s, length); /* subjectPublicKeyInfo */ ber_read_sequence_tag(s, &length); /* SubjectPublicKeyInfo (SEQUENCE) */ /* subjectPublicKeyInfo::AlgorithmIdentifier */ ber_read_sequence_tag(s, &length); /* AlgorithmIdentifier (SEQUENCE) */ stream_seek(s, length); /* subjectPublicKeyInfo::subjectPublicKey */ ber_read_bit_string(s, &length, &padding); /* BIT_STRING */ /* RSAPublicKey (SEQUENCE) */ ber_read_sequence_tag(s, &length); /* SEQUENCE */ ber_read_integer_length(s, &modulus_length); /* modulus (INTEGER) */ /* skip zero padding, if any */ do { stream_peek_uint8(s, padding); if (padding == 0) { stream_seek(s, 1); modulus_length--; } } while (padding == 0); freerdp_blob_alloc(&info->modulus, modulus_length); stream_read(s, info->modulus.data, modulus_length); ber_read_integer_length(s, &exponent_length); /* publicExponent (INTEGER) */ stream_read(s, &info->exponent[4 - exponent_length], exponent_length); crypto_reverse(info->modulus.data, modulus_length); crypto_reverse(info->exponent, 4); }
static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, boolean user_loggedon) { STREAM* data_out; DEVICE* device; LIST_ITEM* item; uint32 count; uint8 c; int data_len; int i; int count_pos; int pos; data_out = stream_new(256); stream_write_uint16(data_out, RDPDR_CTYP_CORE); stream_write_uint16(data_out, PAKID_CORE_DEVICELIST_ANNOUNCE); count_pos = stream_get_pos(data_out); count = 0; stream_seek_uint32(data_out); /* deviceCount */ for (item = rdpdr->devman->devices->head; item; item = item->next) { device = (DEVICE*)item->data; /** * 1. versionMinor 0x0005 doesn't send PAKID_CORE_USER_LOGGEDON * so all devices should be sent regardless of user_loggedon * 2. smartcard devices should be always sent * 3. other devices are sent only after user_loggedon */ if (rdpdr->versionMinor == 0x0005 || device->type == RDPDR_DTYP_SMARTCARD || user_loggedon) { data_len = (device->data == NULL ? 0 : stream_get_length(device->data)); stream_check_size(data_out, 20 + data_len); stream_write_uint32(data_out, device->type); /* deviceType */ stream_write_uint32(data_out, device->id); /* deviceID */ strncpy((char*)stream_get_tail(data_out), device->name, 8); for (i = 0; i < 8; i++) { stream_peek_uint8(data_out, c); if (c > 0x7F) stream_write_uint8(data_out, '_'); else stream_seek_uint8(data_out); } stream_write_uint32(data_out, data_len); if (data_len > 0) stream_write(data_out, stream_get_data(device->data), data_len); count++; printf("registered device #%d: %s (type=%d id=%d)\n", count, device->name, device->type, device->id); } } pos = stream_get_pos(data_out); stream_set_pos(data_out, count_pos); stream_write_uint32(data_out, count); stream_set_pos(data_out, pos); stream_seal(data_out); svc_plugin_send((rdpSvcPlugin*)rdpdr, data_out); }
int transport_check_fds(rdpTransport* transport) { int pos; int status; uint8 header; uint16 length; STREAM* received; status = transport_read_nonblocking(transport); if (status <= 0) return status; while ((pos = stream_get_pos(transport->recv_buffer)) > 0) { /* Ensure the TPKT or Fast Path header is available. */ if (pos <= 4) return 0; stream_set_pos(transport->recv_buffer, 0); stream_peek_uint8(transport->recv_buffer, header); if (header == 0x03) /* TPKT */ length = tpkt_read_header(transport->recv_buffer); else /* Fast Path */ length = fastpath_read_header(transport->recv_buffer, NULL); if (length == 0) { printf("transport_check_fds: protocol error, not a TPKT header (%d).\n", header); return -1; } if (pos < length) { stream_set_pos(transport->recv_buffer, pos); return 0; /* Packet is not yet completely received. */ } /* * A complete packet has been received. In case there are trailing data * for the next packet, we copy it to the new receive buffer. */ received = transport->recv_buffer; transport->recv_buffer = stream_new(BUFFER_SIZE); if (pos > length) { stream_set_pos(received, length); stream_check_size(transport->recv_buffer, pos - length); stream_copy(transport->recv_buffer, received, pos - length); } stream_set_pos(received, length); stream_seal(received); stream_set_pos(received, 0); status = transport->recv_callback(transport, received, transport->recv_extra); stream_free(received); if (status < 0) return status; } return 0; }