Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for all pre-login tokens #192

Merged
merged 2 commits into from
Jan 7, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 76 additions & 5 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 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,69 @@ 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()?;

continue;
pimeys marked this conversation as resolved.
Show resolved Hide resolved
}

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 => {
let mut data = [0u8; 16];

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

// Microsoft UUID comes in a "wrong" order.
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()?;
pimeys marked this conversation as resolved.
Show resolved Hide resolved
}

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

Expand Down