refactor(adb_client): Extract common AUTH handshake logic to a reusable method in adb_message_device.rs

This commit is contained in:
Koji AGAWA
2025-10-25 11:09:35 +09:00
committed by cocool97
parent 88526aa943
commit c83df4309f
3 changed files with 68 additions and 105 deletions

View File

@@ -1,10 +1,10 @@
use super::{ADBRsaKey, ADBTransportMessage, MessageCommand, models::MessageSubcommand};
use crate::device::adb_transport_message::{AUTH_RSAPUBLICKEY, AUTH_SIGNATURE, AUTH_TOKEN};
use crate::{ADBMessageTransport, AdbStatResponse, Result, RustADBError, constants::BUFFER_SIZE};
use byteorder::{LittleEndian, ReadBytesExt};
use rand::Rng;
use std::io::{Cursor, Read, Seek};
use crate::{ADBMessageTransport, AdbStatResponse, Result, RustADBError, constants::BUFFER_SIZE};
use super::{ADBTransportMessage, MessageCommand, models::MessageSubcommand};
use std::time::Duration;
/// Generic structure representing an ADB device reachable over an [`ADBMessageTransport`].
/// Structure is totally agnostic over which transport is truly used.
@@ -33,6 +33,66 @@ impl<T: ADBMessageTransport> ADBMessageDevice<T> {
&mut self.transport
}
pub(crate) fn auth_handshake(
&mut self,
message: ADBTransportMessage,
private_key: &ADBRsaKey,
) -> Result<()> {
match message.header().command() {
MessageCommand::Auth => {
log::debug!("Authentication required");
}
_ => return Ok(()),
}
// At this point, we should have received an AUTH message with arg0 == 1
let auth_message = match message.header().arg0() {
AUTH_TOKEN => message,
v => {
return Err(RustADBError::ADBRequestFailed(format!(
"Received AUTH message with type != 1 ({v})"
)));
}
};
let sign = private_key.sign(auth_message.into_payload())?;
let message = ADBTransportMessage::new(MessageCommand::Auth, AUTH_SIGNATURE, 0, &sign);
self.get_transport_mut().write_message(message)?;
let received_response = self.get_transport_mut().read_message()?;
if received_response.header().command() == MessageCommand::Cnxn {
log::info!(
"Authentication OK, device info {}",
String::from_utf8(received_response.into_payload())?
);
return Ok(());
}
let mut pubkey = private_key.android_pubkey_encode()?.into_bytes();
pubkey.push(b'\0');
let message = ADBTransportMessage::new(MessageCommand::Auth, AUTH_RSAPUBLICKEY, 0, &pubkey);
self.get_transport_mut().write_message(message)?;
let response = self
.get_transport_mut()
.read_message_with_timeout(Duration::from_secs(10))
.and_then(|message| {
message.assert_command(MessageCommand::Cnxn)?;
Ok(message)
})?;
log::info!(
"Authentication OK, device info {}",
String::from_utf8(response.into_payload())?
);
Ok(())
}
/// Receive a message and acknowledge it by replying with an `OKAY` command
pub(crate) fn recv_and_reply_okay(&mut self) -> Result<ADBTransportMessage> {
let message = self.transport.read_message()?;

View File

@@ -1,14 +1,12 @@
use std::io::Write;
use std::path::{Path, PathBuf};
use std::time::Duration;
use std::{io::Read, net::SocketAddr};
use super::adb_message_device::ADBMessageDevice;
use super::models::MessageCommand;
use super::{ADBRsaKey, ADBTransportMessage, get_default_adb_key_path};
use crate::device::adb_transport_message::{AUTH_RSAPUBLICKEY, AUTH_SIGNATURE, AUTH_TOKEN};
use crate::device::adb_usb_device::read_adb_private_key;
use crate::{ADBDeviceExt, ADBMessageTransport, ADBTransport, Result, RustADBError, TcpTransport};
use crate::{ADBDeviceExt, ADBMessageTransport, ADBTransport, Result, TcpTransport};
/// Represent a device reached and available over USB.
#[derive(Debug)]
@@ -78,6 +76,7 @@ impl ADBTcpDevice {
}
MessageCommand::Auth => {
log::debug!("Authentication required");
return self.inner.auth_handshake(message, &self.private_key);
}
_ => {
return Err(crate::RustADBError::WrongResponseReceived(
@@ -86,54 +85,6 @@ impl ADBTcpDevice {
));
}
}
// At this point, we should have receive an AUTH message with arg0 == 1
let auth_message = match message.header().arg0() {
AUTH_TOKEN => message,
v => {
return Err(RustADBError::ADBRequestFailed(format!(
"Received AUTH message with type != 1 ({v})"
)));
}
};
let sign = self.private_key.sign(auth_message.into_payload())?;
let message = ADBTransportMessage::new(MessageCommand::Auth, AUTH_SIGNATURE, 0, &sign);
self.get_transport_mut().write_message(message)?;
let received_response = self.get_transport_mut().read_message()?;
if received_response.header().command() == MessageCommand::Cnxn {
log::info!(
"Authentication OK, device info {}",
String::from_utf8(received_response.into_payload())?
);
return Ok(());
}
let mut pubkey = self.private_key.android_pubkey_encode()?.into_bytes();
pubkey.push(b'\0');
let message = ADBTransportMessage::new(MessageCommand::Auth, AUTH_RSAPUBLICKEY, 0, &pubkey);
self.get_transport_mut().write_message(message)?;
let response = self
.get_transport_mut()
.read_message_with_timeout(Duration::from_secs(10))
.and_then(|message| {
message.assert_command(MessageCommand::Cnxn)?;
Ok(message)
})?;
log::info!(
"Authentication OK, device info {}",
String::from_utf8(response.into_payload())?
);
Ok(())
}
#[inline]

View File

@@ -7,7 +7,6 @@ use std::io::Read;
use std::io::Write;
use std::path::Path;
use std::path::PathBuf;
use std::time::Duration;
use super::adb_message_device::ADBMessageDevice;
use super::models::MessageCommand;
@@ -15,7 +14,6 @@ use super::{ADBRsaKey, ADBTransportMessage};
use crate::ADBDeviceExt;
use crate::ADBMessageTransport;
use crate::ADBTransport;
use crate::device::adb_transport_message::{AUTH_RSAPUBLICKEY, AUTH_SIGNATURE, AUTH_TOKEN};
use crate::{Result, RustADBError, USBTransport};
pub fn read_adb_private_key<P: AsRef<Path>>(private_key_path: P) -> Result<Option<ADBRsaKey>> {
@@ -195,55 +193,9 @@ impl ADBUSBDevice {
if message.header().command() == MessageCommand::Cnxn {
return Ok(());
}
message.assert_command(MessageCommand::Auth)?;
// At this point, we should have receive an AUTH message with arg0 == 1
let auth_message = match message.header().arg0() {
AUTH_TOKEN => message,
v => {
return Err(RustADBError::ADBRequestFailed(format!(
"Received AUTH message with type != 1 ({v})"
)));
}
};
let sign = self.private_key.sign(auth_message.into_payload())?;
let message = ADBTransportMessage::new(MessageCommand::Auth, AUTH_SIGNATURE, 0, &sign);
self.get_transport_mut().write_message(message)?;
let received_response = self.get_transport_mut().read_message()?;
if received_response.header().command() == MessageCommand::Cnxn {
log::info!(
"Authentication OK, device info {}",
String::from_utf8(received_response.into_payload())?
);
return Ok(());
}
let mut pubkey = self.private_key.android_pubkey_encode()?.into_bytes();
pubkey.push(b'\0');
let message = ADBTransportMessage::new(MessageCommand::Auth, AUTH_RSAPUBLICKEY, 0, &pubkey);
self.get_transport_mut().write_message(message)?;
let response = self
.get_transport_mut()
.read_message_with_timeout(Duration::from_secs(10))
.and_then(|message| {
message.assert_command(MessageCommand::Cnxn)?;
Ok(message)
})?;
log::info!(
"Authentication OK, device info {}",
String::from_utf8(response.into_payload())?
);
Ok(())
self.inner.auth_handshake(message, &self.private_key)
}
#[inline]