Skip to content

Commit

Permalink
Add support for all pre-login tokens (#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
Julius de Bruijn authored Jan 7, 2022
1 parent 951c6ee commit 6ec6963
Showing 1 changed file with 73 additions and 6 deletions.
79 changes: 73 additions & 6 deletions src/tds/codec/pre_login.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
use super::guid::reorder_bytes;
use super::{Decode, Encode};
use crate::{tds, Error, Result};
use byteorder::{BigEndian, ReadBytesExt};
use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
use bytes::{BufMut, BytesMut};
use std::convert::TryFrom;
use std::io::{self, Cursor};
use std::io::{self, Cursor, Read};
use tds::EncryptionLevel;
use uuid::Uuid;

/// Client application activity id token used for debugging purposes introduced
/// in TDS 7.4.
#[derive(Debug)]
pub struct ActivityId {
id: Uuid,
sequence: u32,
}

/// The prelogin packet used to initialize a connection
#[derive(Debug)]
Expand All @@ -15,10 +25,17 @@ pub struct PreloginMessage {
pub sub_build: u16,
/// token=0x01
pub encryption: EncryptionLevel,
/// token=0x02
pub instance_name: Option<String>,
/// [client] threadid for debugging purposes, token=0x03
pub thread_id: u32,
/// token=0x04
pub mars: bool,
/// token=0x05
pub activity_id: Option<ActivityId>,
/// token=0x06
pub fed_auth_required: bool,
pub nonce: Option<[u8; 32]>,
}

impl PreloginMessage {
Expand All @@ -28,8 +45,12 @@ impl PreloginMessage {
version: driver_version as u32,
sub_build: (driver_version >> 32) as u16,
encryption: EncryptionLevel::NotSupported,
instance_name: None,
thread_id: 0,
mars: false,
activity_id: None,
fed_auth_required: false,
nonce: None,
}
}

Expand Down Expand Up @@ -113,19 +134,65 @@ impl Decode<BytesMut> for PreloginMessage {
// TODO: support parsing more
match token {
// version
0 => {
0x00 => {
ret.version = cursor.read_u32::<BigEndian>()?;
ret.sub_build = cursor.read_u16::<BigEndian>()?;
}
// encryption
1 => {
0x01 => {
let encrypt = cursor.read_u8()?;
ret.encryption = tds::EncryptionLevel::try_from(encrypt).map_err(|_| {
Error::Protocol(format!("invalid encryption value: {}", encrypt).into())
})?;
}
3 => debug_assert_eq!(length, 0), // threadid
4 => debug_assert_eq!(length, 1), // mars
// instance name
0x02 => {
let mut bytes = Vec::new();
let mut next_byte = cursor.read_u8()?;

while next_byte != 0x00 {
bytes.push(next_byte);
next_byte = cursor.read_u8()?;
}

if !bytes.is_empty() {
ret.instance_name = Some(String::from_utf8_lossy(&bytes).into_owned());
}
}
// threadid (should be empty when sent from server to client)
0x03 => debug_assert_eq!(length, 0),
// mars
0x04 => {
ret.mars = cursor.read_u8()? != 0;
}
// activity id
0x05 => {
// Data is a Guid, 16 bytes and ordered the wrong way around
// than Uuid.
let mut data = [0u8; 16];

cursor.read_exact(&mut data)?;
reorder_bytes(&mut data);

ret.activity_id = Some(ActivityId {
id: Uuid::from_bytes(data),
sequence: cursor.read_u32::<LittleEndian>()?,
});
}
// fed auth
0x06 => {
ret.fed_auth_required = cursor.read_u8()? != 0;
}
// nonce
0x07 => {
let mut data = [0u8; 32];

for item in data.iter_mut() {
*item = cursor.read_u8()?;
}

ret.nonce = Some(data);
}
_ => panic!("unsupported prelogin token: {}", token),
}

Expand Down

0 comments on commit 6ec6963

Please sign in to comment.