1use crate::{
2 auth::TorAuthentication,
3 error::TorError,
4 key::{TorEd25519SigningKey, TorServiceId},
5};
6use futures::{SinkExt, StreamExt};
7use lazy_static::lazy_static;
8use log::info;
9use regex::{Captures, Regex};
10use serde::{Deserialize, Serialize};
11use std::fmt::{Display, Error, Formatter};
12use std::net::{AddrParseError, SocketAddr as TcpSocketAddr};
13use std::os::unix::net::SocketAddr as UnixSocketAddr;
14use std::path::Path;
15use std::pin::Pin;
16use std::str::FromStr;
17use std::task::{Context, Poll};
18use tokio::{
19 io::{AsyncRead, AsyncWrite, ReadBuf, ReadHalf, WriteHalf},
20 net::{TcpListener, TcpStream, ToSocketAddrs, UnixListener, UnixStream},
21};
22use tokio_stream::wrappers::{TcpListenerStream, UnixListenerStream};
23use tokio_util::codec::{FramedRead, FramedWrite, LinesCodec, LinesCodecError};
24
25#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Deserialize, Serialize)]
29pub enum TorSocketAddr {
30 Tcp(TcpSocketAddr),
31 Unix(String),
32}
33
34impl TorSocketAddr {
35 fn from_tcp_string(address: &str) -> Result<Self, AddrParseError> {
37 Ok(Self::Tcp(TcpSocketAddr::from_str(address)?))
38 }
39
40 fn from_unix_string<P: AsRef<Path>>(path: P) -> Result<Self, std::io::Error> {
42 Ok(Self::Unix(
43 UnixSocketAddr::from_pathname(path)?
44 .as_pathname()
45 .unwrap()
46 .to_str()
47 .unwrap()
48 .to_string(),
49 ))
50 }
51}
52
53impl From<TcpSocketAddr> for TorSocketAddr {
55 fn from(socket_addr: TcpSocketAddr) -> Self {
56 Self::Tcp(socket_addr)
57 }
58}
59
60impl Display for TorSocketAddr {
61 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
62 match self {
63 Self::Tcp(sock_addr) => write!(f, "{}", sock_addr),
64 Self::Unix(sock_addr) => write!(f, "unix:{:?}", sock_addr),
65 }
66 }
67}
68
69#[derive(Debug)]
71pub enum ListenAddressParseError {
72 TcpParseError(AddrParseError),
73 UnixParseError(std::io::Error),
74}
75
76impl std::error::Error for ListenAddressParseError {}
77
78impl Display for ListenAddressParseError {
79 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
80 match self {
81 Self::TcpParseError(error) => write!(f, "Error parsing TCP address: {}", error),
82 Self::UnixParseError(error) => write!(f, "Error parsing Unix address:{}", error),
83 }
84 }
85}
86
87impl From<AddrParseError> for ListenAddressParseError {
88 fn from(err: AddrParseError) -> Self {
89 Self::TcpParseError(err)
90 }
91}
92
93impl From<std::io::Error> for ListenAddressParseError {
94 fn from(err: std::io::Error) -> Self {
95 Self::UnixParseError(err)
96 }
97}
98
99impl FromStr for TorSocketAddr {
100 type Err = ListenAddressParseError;
101
102 fn from_str(s: &str) -> Result<Self, Self::Err> {
103 if let Some(path) = s.strip_prefix("unix:") {
104 Ok(Self::from_unix_string(path)?)
105 } else {
106 Ok(Self::from_tcp_string(s)?)
107 }
108 }
109}
110
111#[derive(Debug)]
113pub enum OnionServiceListener {
114 Tcp(TcpListener),
115 Unix(UnixListener),
116}
117
118impl OnionServiceListener {
119 pub async fn bind(socket_addr: TorSocketAddr) -> Result<OnionServiceListener, std::io::Error> {
121 match socket_addr {
122 TorSocketAddr::Tcp(socket_addr) => Ok(OnionServiceListener::Tcp(
123 TcpListener::bind(socket_addr).await?,
124 )),
125 TorSocketAddr::Unix(path) => Ok(OnionServiceListener::Unix(UnixListener::bind(path)?)),
126 }
127 }
128
129 pub async fn accept(&self) -> Result<(OnionServiceStream, TorSocketAddr), std::io::Error> {
131 match self {
132 Self::Tcp(listener) => {
133 let (stream, socket) = listener.accept().await?;
134 Ok((OnionServiceStream::Tcp(stream), socket.into()))
135 }
136 Self::Unix(listener) => {
137 let (stream, socket) = listener.accept().await?;
138 Ok((
139 OnionServiceStream::Unix(stream),
140 TorSocketAddr::Unix(
141 socket.as_pathname().unwrap().to_string_lossy().to_string(),
142 ),
143 ))
144 }
145 }
146 }
147
148 pub fn as_stream(self) -> OnionServiceListenerStream {
149 match self {
150 OnionServiceListener::Tcp(listener) => {
151 OnionServiceListenerStream::Tcp(TcpListenerStream::new(listener))
152 }
153 OnionServiceListener::Unix(listener) => {
154 OnionServiceListenerStream::Unix(UnixListenerStream::new(listener))
155 }
156 }
157 }
158}
159
160pub enum OnionServiceListenerStream {
161 Tcp(TcpListenerStream),
162 Unix(UnixListenerStream),
163}
164
165pub enum OnionServiceStream {
167 Tcp(TcpStream),
168 Unix(UnixStream),
169}
170
171impl AsyncRead for OnionServiceStream {
172 fn poll_read(
173 self: Pin<&mut Self>,
174 cx: &mut Context<'_>,
175 buf: &mut ReadBuf<'_>,
176 ) -> Poll<Result<(), std::io::Error>> {
177 match Pin::into_inner(self) {
178 Self::Tcp(stream) => Pin::new(stream).poll_read(cx, buf),
179 Self::Unix(stream) => Pin::new(stream).poll_read(cx, buf),
180 }
181 }
182}
183
184impl AsyncWrite for OnionServiceStream {
185 fn poll_write(
186 self: Pin<&mut Self>,
187 cx: &mut Context<'_>,
188 buf: &[u8],
189 ) -> Poll<Result<usize, std::io::Error>> {
190 match Pin::into_inner(self) {
191 Self::Tcp(stream) => Pin::new(stream).poll_write(cx, buf),
192 Self::Unix(stream) => Pin::new(stream).poll_write(cx, buf),
193 }
194 }
195
196 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), std::io::Error>> {
197 match Pin::into_inner(self) {
198 Self::Tcp(stream) => Pin::new(stream).poll_flush(cx),
199 Self::Unix(stream) => Pin::new(stream).poll_flush(cx),
200 }
201 }
202
203 fn poll_shutdown(
204 self: Pin<&mut Self>,
205 cx: &mut Context<'_>,
206 ) -> Poll<Result<(), std::io::Error>> {
207 match Pin::into_inner(self) {
208 Self::Tcp(stream) => Pin::new(stream).poll_shutdown(cx),
209 Self::Unix(stream) => Pin::new(stream).poll_shutdown(cx),
210 }
211 }
212}
213
214#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Deserialize, Serialize)]
216pub struct OnionServiceMapping {
217 virt_port: u16,
218 listen_address: TorSocketAddr,
219}
220
221impl OnionServiceMapping {
222 pub fn new(virt_port: u16, listen_address: Option<TorSocketAddr>) -> Self {
223 Self {
224 virt_port,
225 listen_address: match listen_address {
226 None => {
227 TorSocketAddr::from_tcp_string(&format!("127.0.0.1:{}", virt_port)).unwrap()
228 }
229 Some(a) => a,
230 },
231 }
232 }
233
234 pub fn virt_port(&self) -> u16 {
235 self.virt_port
236 }
237
238 pub fn listen_address(&self) -> &TorSocketAddr {
239 &self.listen_address
240 }
241}
242
243#[derive(Clone, Debug, Eq, PartialEq)]
245pub struct OnionAddress {
246 service_id: TorServiceId,
247 service_port: u16,
248}
249
250impl OnionAddress {
251 pub fn new(service_id: TorServiceId, port: u16) -> Self {
252 Self {
253 service_id,
254 service_port: port,
255 }
256 }
257
258 pub fn service_id(&self) -> &TorServiceId {
259 &self.service_id
260 }
261
262 pub fn service_port(&self) -> u16 {
263 self.service_port
264 }
265}
266
267impl FromStr for OnionAddress {
268 type Err = TorError;
269
270 fn from_str(s: &str) -> Result<Self, Self::Err> {
271 let values = s.split(':').collect::<Vec<&str>>();
272 if values.len() != 2 {
273 return Err(TorError::protocol_error("Bad onion address"));
274 }
275 let host_values = values[0].split('.').collect::<Vec<&str>>();
276 if host_values.len() != 2 || host_values[1] != "onion" {
277 return Err(TorError::protocol_error("Bad onion address"));
278 }
279 let service_id = match TorServiceId::from_str(host_values[0]) {
280 Ok(id) => id,
281 Err(error) => {
282 return Err(TorError::protocol_error(&format!(
283 "Error parsing host field in onion address: {}",
284 error
285 )));
286 }
287 };
288 let service_port = match values[1].parse::<u16>() {
289 Ok(port) => port,
290 Err(error) => {
291 return Err(TorError::protocol_error(&format!(
292 "Error parsing port field in onion address: {}",
293 error
294 )));
295 }
296 };
297 Ok(Self {
298 service_id,
299 service_port,
300 })
301 }
302}
303
304impl Display for OnionAddress {
305 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
306 write!(f, "{}.onion:{}", self.service_id, self.service_port)
307 }
308}
309
310pub struct OnionService {
325 ports: Vec<OnionServiceMapping>,
326 service_id: TorServiceId,
327 signing_key: TorEd25519SigningKey,
328}
329
330impl OnionService {
331 pub fn new<K>(key: K, ports: &[OnionServiceMapping]) -> Self
333 where
334 TorEd25519SigningKey: From<K>,
335 {
336 let signing_key: TorEd25519SigningKey = key.into();
337 let service_id = signing_key.verifying_key().into();
338 Self {
339 ports: ports.to_vec(),
340 service_id,
341 signing_key,
342 }
343 }
344
345 pub fn listen_addresses_for_onion_address(&self, onion_address: &str) -> Vec<TorSocketAddr> {
349 self.ports
350 .iter()
351 .map(|p| (p, format!("{}.onion:{}", self.service_id, p.virt_port)))
352 .filter(|(_p, a)| a == onion_address)
353 .map(|(p, _a)| p.listen_address.clone())
354 .collect()
355 }
356
357 pub fn listen_addresses_for_port(&self, service_port: u16) -> Vec<TorSocketAddr> {
359 self.ports
360 .iter()
361 .filter(|p| p.virt_port == service_port)
362 .map(|p| p.listen_address.clone())
363 .collect()
364 }
365
366 pub fn onion_address(&self, service_port: u16) -> Result<OnionAddress, TorError> {
369 if self.ports.iter().any(|p| p.virt_port == service_port) {
370 Ok(OnionAddress {
371 service_id: self.service_id.clone(),
372 service_port,
373 })
374 } else {
375 Err(TorError::protocol_error(&format!(
376 "No Onion Service Port {} found for onion service {}",
377 service_port, self.service_id
378 )))
379 }
380 }
381
382 pub fn onion_addresses(&self) -> Vec<OnionAddress> {
384 self.ports
385 .iter()
386 .map(|p| OnionAddress::new(self.service_id.clone(), p.virt_port))
387 .collect()
388 }
389
390 pub fn service_id(&self) -> &TorServiceId {
392 &self.service_id
393 }
394
395 pub fn signing_key(&self) -> &TorEd25519SigningKey {
397 &self.signing_key
398 }
399
400 fn into_signing_key(self) -> TorEd25519SigningKey {
402 self.signing_key
403 }
404
405 pub fn ports(&self) -> Vec<OnionServiceMapping> {
407 self.ports.clone()
408 }
409}
410
411impl From<OnionService> for TorEd25519SigningKey {
413 fn from(onion_service: OnionService) -> Self {
414 onion_service.into_signing_key()
415 }
416}
417
418#[derive(Debug)]
420pub struct ControlResponse {
421 pub status_code: u16,
422 pub reply: String,
423}
424
425impl ControlResponse {
426 fn new() -> Self {
427 Self {
428 status_code: 0,
429 reply: String::new(),
430 }
431 }
432}
433
434fn parse_status_code(code_str: &str) -> Result<u16, TorError> {
435 match code_str.parse::<u16>() {
436 Ok(status_code) => Ok(status_code),
437 Err(error) => Err(TorError::protocol_error(&format!(
438 "Error parsing response status code: {}",
439 error
440 ))),
441 }
442}
443
444async fn read_control_response<S: StreamExt<Item = Result<String, LinesCodecError>> + Unpin>(
446 reader: &mut S,
447) -> Result<ControlResponse, TorError> {
448 lazy_static! {
449 static ref MID_REGEX: Regex = Regex::new(r"^(?P<code>\d{3})-(?P<reply_line>.*)$").unwrap();
451
452 static ref DATA_REGEX: Regex =
454 Regex::new(r"^(?P<code>\d{3})\+(?P<reply_line>.*)$").unwrap();
455
456 static ref END_REGEX: Regex = Regex::new(r"^(?P<code>\d{3}) (?P<reply_line>.*)$").unwrap();
458 }
459
460 let mut control_response = ControlResponse::new();
461 loop {
462 let mut line = read_line(reader).await?;
463 info!("<= {}", line);
464 match MID_REGEX.captures(&line) {
465 Some(captures) => {
467 control_response.status_code = parse_status_code(&captures["code"])?;
468 control_response
469 .reply
470 .push_str(&format!("{}\n", &captures["reply_line"]));
471 }
472 None => match DATA_REGEX.captures(&line.clone()) {
473 Some(captures) => {
475 control_response.status_code = parse_status_code(&captures["code"])?;
476 let mut reply_line = captures["reply_line"].to_string();
477 reply_line.push('\n');
478 loop {
479 line = read_line(reader).await?;
480 if line == "." {
481 break;
482 }
483 reply_line.push_str(&line);
484 reply_line.push('\n');
485 }
486 control_response.reply = reply_line;
487 read_line(reader).await?;
489 return Ok(control_response);
490 }
491 None => match END_REGEX.captures(&line) {
492 Some(captures) => {
493 control_response.status_code = parse_status_code(&captures["code"])?;
494 if control_response.reply.is_empty() {
496 control_response.reply.push_str(&captures["reply_line"]);
497 }
498 return Ok(control_response);
499 }
500 None => {
501 return Err(TorError::ProtocolError(format!(
502 "Unknown response: {}",
503 line
504 )))
505 }
506 },
507 },
508 }
509 }
510}
511
512async fn read_line<S: StreamExt<Item = Result<String, LinesCodecError>> + Unpin>(
514 reader: &mut S,
515) -> Result<String, TorError> {
516 match reader.next().await {
517 Some(Ok(line)) => Ok(line),
518 Some(Err(error)) => Err(error.into()),
519 None => Err(TorError::protocol_error("Unexpected EOF on stream")),
520 }
521}
522
523fn format_onion_service_request_string(
525 key_type: &str,
526 key_blob: &str,
527 ports: &[OnionServiceMapping],
528 transient: bool,
529) -> String {
530 let flags = if transient { "" } else { "Flags=Detach" };
531 let port_string = ports
532 .iter()
533 .map(|p| format!("Port={},{}", p.virt_port, p.listen_address))
534 .collect::<Vec<String>>()
535 .join(" ");
536 format!("{}:{} {} {}", key_type, key_blob, flags, port_string)
537}
538
539fn format_key_request_string(
540 ports: &[OnionServiceMapping],
541 transient: bool,
542 signing_key: Option<&TorEd25519SigningKey>,
543) -> String {
544 match signing_key {
545 Some(signing_key) => format_onion_service_request_string(
546 "ED25519-V3",
547 &signing_key.to_blob(),
548 ports,
549 transient,
550 ),
551 None => format_onion_service_request_string("NEW", "BEST", ports, transient),
552 }
553}
554
555fn parse_required_response_field<'a>(
557 captures: &Captures<'a>,
558 field_name: &str,
559 field_arg: &str,
560 response_type: &str,
561) -> Result<&'a str, TorError> {
562 match captures.name(field_name) {
563 Some(field) => Ok(field.as_str()),
564 None => Err(TorError::protocol_error(&format!(
565 "'{}' field not found in {} response",
566 field_arg, response_type,
567 ))),
568 }
569}
570
571fn parse_add_onion_response(
572 captures: &Captures<'_>,
573 ports: &[OnionServiceMapping],
574 signing_key: Option<TorEd25519SigningKey>,
575) -> Result<OnionService, TorError> {
576 let service_id =
577 parse_required_response_field(captures, "service_id", "ServiceID", "ADD_ONION")?;
578
579 let (returned_signing_key, verifying_key) = match signing_key {
582 Some(signing_key) => {
583 let verifying_key = signing_key.verifying_key();
584 (signing_key, verifying_key)
585 }
586 None => match captures.name("key_type") {
587 Some(_) => {
588 let signing_key =
589 TorEd25519SigningKey::from_blob(captures.name("key_blob").unwrap().as_str())
590 .unwrap();
591 let verifying_key = signing_key.verifying_key();
592 (signing_key, verifying_key)
593 }
594 None => {
595 return Err(TorError::protocol_error(
596 "Expected signing key to be returned by Tor",
597 ));
598 }
599 },
600 };
601
602 let expected_service_id: TorServiceId = verifying_key.into();
603
604 if expected_service_id.as_str() != service_id {
605 return Err(
606 TorError::protocol_error(&format!(
607 "Service ID for onion service returned by tor ({}) doesn't match the service ID generated from verifying key ({})",
608 service_id, expected_service_id.as_str())));
609 }
610
611 if let Err(error) = TorServiceId::from_str(service_id) {
612 return Err(TorError::protocol_error(&format!(
613 "Error parsing Tor Service ID: {}",
614 error
615 )));
616 }
617
618 Ok(OnionService::new(returned_signing_key, ports))
620}
621
622#[derive(Clone, Debug)]
625pub struct ProtocolInfo {
626 pub auth_methods: Vec<String>,
627 pub cookie_file: Option<String>,
628 pub tor_version: String,
629}
630
631#[derive(Debug)]
634pub struct TorControlConnection {
635 reader: FramedRead<ReadHalf<TcpStream>, LinesCodec>,
636 writer: FramedWrite<WriteHalf<TcpStream>, LinesCodec>,
637 protocol_info: Option<ProtocolInfo>,
638}
639
640impl TorControlConnection {
641 pub async fn connect<A: ToSocketAddrs>(addrs: A) -> Result<Self, TorError> {
643 let this = Self::with_stream(TcpStream::connect(addrs).await?)?;
644 Ok(this)
645 }
646
647 pub(crate) fn with_stream(stream: TcpStream) -> Result<Self, TorError> {
649 let (reader, writer) = tokio::io::split(stream);
650 Ok(Self {
651 reader: FramedRead::new(reader, LinesCodec::new()),
652 writer: FramedWrite::new(writer, LinesCodec::new()),
653 protocol_info: None,
654 })
655 }
656
657 async fn write(&mut self, data: &str) -> Result<(), TorError> {
659 self.writer.send(data).await?;
660 Ok(())
661 }
662
663 pub async fn get_protocol_info(&mut self) -> Result<ProtocolInfo, TorError> {
665 if self.protocol_info.is_some() {
666 Ok(self.protocol_info.clone().unwrap())
667 } else {
668 let control_response = self.send_command("PROTOCOLINFO", Some("1")).await?;
669
670 if control_response.status_code != 250 {
671 return Err(TorError::protocol_error(&format!(
672 "Expected status code 250, got {}",
673 control_response.status_code
674 )));
675 }
676
677 lazy_static! {
679 static ref RE: Regex =
680 Regex::new(r"^PROTOCOLINFO 1\nAUTH METHODS=(?P<auth_methods>[^ ]*)( COOKIEFILE=(?P<cookie_file>.*))*\nVERSION Tor=(?P<tor_version>.*)\n")
681 .unwrap();
682 }
683 let captures = match RE.captures(&control_response.reply) {
684 Some(captures) => captures,
685 None => {
686 return Err(TorError::protocol_error(
687 "Error parsing PROTOCOLINFO response",
688 ))
689 }
690 };
691 let auth_methods = parse_required_response_field(
692 &captures,
693 "auth_methods",
694 "AUTH METHODS",
695 "PROTOCOLINFO",
696 )?
697 .split(',')
698 .map(|s| s.to_string())
699 .collect();
700 let tor_version =
701 parse_required_response_field(&captures, "tor_version", "VERSION", "PROTOCOLINFO")?
702 .replace('"', "");
703 let protocol_info = ProtocolInfo {
704 auth_methods,
705 cookie_file: captures
706 .name("cookie_file")
707 .map(|c| c.as_str().replace('"', "").to_string()),
708 tor_version,
709 };
710 self.protocol_info = Some(protocol_info.clone());
711 Ok(protocol_info)
712 }
713 }
714
715 pub async fn get_info(&mut self, info: &str) -> Result<Vec<String>, TorError> {
717 let control_response = self.send_command("GETINFO", Some(info)).await?;
718 info!(
719 "Send GETINFO command, got control response {:?}",
720 control_response
721 );
722 if control_response.status_code != 250 {
723 return Err(TorError::protocol_error(&format!(
724 "Expected status code 250, got {}",
725 control_response.status_code
726 )));
727 }
728 let split_response = &control_response
729 .reply
730 .trim_end()
731 .split('=')
732 .collect::<Vec<&str>>();
733 if split_response.len() <= 1 {
734 return Err(TorError::protocol_error(&format!(
735 "Got unexpected reply '{}', expected key/value pair",
736 control_response.reply
737 )));
738 }
739
740 let response = split_response[1].split('\n').collect::<Vec<&str>>();
741
742 let mut ret = Vec::new();
743 for value in response.iter() {
744 if !value.is_empty() {
745 ret.push(value.to_string());
746 }
747 }
748
749 Ok(ret)
750 }
751
752 pub async fn authenticate(&mut self, method: &TorAuthentication) -> Result<(), TorError> {
754 method.authenticate(self).await?;
755 Ok(())
756 }
757
758 pub(crate) async fn send_command(
760 &mut self,
761 command: &str,
762 arguments: Option<&str>,
763 ) -> Result<ControlResponse, TorError> {
764 let command_string = match arguments {
765 None => command.to_string(),
766 Some(arguments) => format!("{} {}", command, arguments),
767 };
768 info!("=> {}", command_string);
769 self.write(&command_string).await?;
770 match read_control_response(&mut self.reader).await {
771 Ok(control_response) => match control_response.status_code {
772 250 | 251 => Ok(control_response),
773 _ => Err(TorError::ProtocolError(control_response.reply)),
774 },
775 Err(error) => Err(error),
776 }
777 }
778
779 pub async fn create_onion_service(
781 &mut self,
782 ports: &[OnionServiceMapping],
783 transient: bool,
784 signing_key: Option<TorEd25519SigningKey>,
785 ) -> Result<OnionService, TorError> {
786 let request_string = format_key_request_string(ports, transient, signing_key.as_ref());
788
789 let control_response = self
791 .send_command("ADD_ONION", Some(&request_string))
792 .await?;
793 info!(
794 "Sent ADD_ONION command, got control response {:?}",
795 control_response
796 );
797
798 if control_response.status_code != 250 {
799 return Err(TorError::protocol_error(&format!(
800 "Expected status code 250, got {}",
801 control_response.status_code
802 )));
803 }
804
805 lazy_static! {
807 static ref RE: Regex =
808 Regex::new(r"(?m)^ServiceID=(?P<service_id>.*)\n(PrivateKey=(?P<key_type>[^:]*):(?<key_blob>.*)$)?$")
809 .unwrap();
810 }
811 match RE.captures(&control_response.reply) {
812 Some(captures) => parse_add_onion_response(&captures, ports, signing_key),
813 None => Err(TorError::ProtocolError(format!(
814 "Unexpected response: {} {}",
815 control_response.status_code, control_response.reply,
816 ))),
817 }
818 }
819
820 pub async fn delete_onion_service(&mut self, service_id: &str) -> Result<(), TorError> {
821 let service_id_string = service_id.replace(".onion", "");
823
824 let control_response = self
826 .send_command("DEL_ONION", Some(&service_id_string))
827 .await?;
828 info!(
829 "Sent DEL_ONION command, got control response {:?}",
830 control_response
831 );
832
833 if control_response.status_code != 250 {
834 Err(TorError::protocol_error(&format!(
835 "Expected status code 250, got {}",
836 control_response.status_code
837 )))
838 } else {
839 Ok(())
840 }
841 }
842}
843
844#[cfg(test)]
845mod tests {
846 use super::*;
847 use futures::SinkExt;
848 use tokio;
849 use tokio::net::{TcpListener, TcpStream};
850 use tokio_util::codec::{Framed, LinesCodec};
851
852 async fn create_mock() -> Result<(TcpStream, TcpStream), Box<dyn std::error::Error>> {
853 let listener = TcpListener::bind("127.0.0.1:0").await?;
854 let addr = listener.local_addr()?;
855 let join_handle = tokio::spawn(async move { listener.accept().await.unwrap() });
856 let client = TcpStream::connect(addr).await?;
857 let (server_stream, _) = join_handle.await?;
858
859 Ok((client, server_stream))
860 }
861
862 async fn create_framed_mock() -> Result<
863 (Framed<TcpStream, LinesCodec>, Framed<TcpStream, LinesCodec>),
864 Box<dyn std::error::Error>,
865 > {
866 let (client, server) = create_mock().await?;
867 let reader = Framed::new(client, LinesCodec::new());
868 let server = Framed::new(server, LinesCodec::new());
869
870 Ok((reader, server))
871 }
872
873 #[tokio::test]
874 async fn test_read_good_control_response() -> Result<(), Box<dyn std::error::Error>> {
875 let (mut client, mut server) = create_framed_mock().await?;
877 server.send("250 OK").await?;
878 let result = read_control_response(&mut client).await;
879 assert!(result.is_ok());
880 let control_response = result.unwrap();
881 assert_eq!(250, control_response.status_code);
882 assert_eq!("OK", control_response.reply);
883
884 Ok(())
885 }
886
887 #[tokio::test]
888 async fn test_read_garbled_control_response() -> Result<(), Box<dyn std::error::Error>> {
889 let (mut client, mut server) = create_framed_mock().await?;
891 server.send("idon'tknowwhatthisis").await?;
892 let result = read_control_response(&mut client).await;
893 assert!(result.is_err());
894 match result.err() {
895 Some(TorError::ProtocolError(_)) => assert!(true),
896 _ => assert!(false),
897 }
898
899 let (mut client, mut server) = create_framed_mock().await?;
901 server
902 .send("250-ServiceID=647qjf6w3evdbdpy7oidf5vda6rsjzsl5a6ofsaou2v77hj7dmn2spqd")
903 .await?;
904 server.send("250-PrivateKey=ED25519-V3:yLSDc8b11PaIHTtNtvi9lNW99IME2mdrO4k381zDkHv//WRUGrkBALBQ9MbHy2SLA/NmfS7YxmcR/FY8ppRfIA==").await?;
905 server.send("250 OK").await?;
906 let result = read_control_response(&mut client).await;
907 assert!(result.is_ok());
908 let control_response = result.unwrap();
909 assert_eq!(250, control_response.status_code);
910 assert_eq!(
911 "ServiceID=647qjf6w3evdbdpy7oidf5vda6rsjzsl5a6ofsaou2v77hj7dmn2spqd\nPrivateKey=ED25519-V3:yLSDc8b11PaIHTtNtvi9lNW99IME2mdrO4k381zDkHv//WRUGrkBALBQ9MbHy2SLA/NmfS7YxmcR/FY8ppRfIA==\n",
912 control_response.reply);
913
914 Ok(())
915 }
916
917 #[tokio::test]
918 async fn test_read_data_control_response() -> Result<(), Box<dyn std::error::Error>> {
919 let (mut client, mut server) = create_framed_mock().await?;
921 server.send("250+onions/current=").await?;
922 server
923 .send("647qjf6w3evdbdpy7oidf5vda6rsjzsl5a6ofsaou2v77hj7dmn2spqd")
924 .await?;
925 server
926 .send("yxq7fa63tthq3nd2ul52jjcdpblyai6k3cfmdkyw23ljsoob66z3ywid")
927 .await?;
928 server.send(".").await?;
929 server.send("250 OK").await?;
930 let result = read_control_response(&mut client).await;
931 assert!(result.is_ok());
932 let control_response = result.unwrap();
933 assert_eq!(250, control_response.status_code);
934 assert_eq!("onions/current=\n647qjf6w3evdbdpy7oidf5vda6rsjzsl5a6ofsaou2v77hj7dmn2spqd\nyxq7fa63tthq3nd2ul52jjcdpblyai6k3cfmdkyw23ljsoob66z3ywid\n",
935 control_response.reply,
936 );
937
938 Ok(())
939 }
940
941 #[tokio::test]
942 async fn test_authenticate() -> Result<(), Box<dyn std::error::Error>> {
943 let (client, server) = create_mock().await?;
944 let mut server = Framed::new(server, LinesCodec::new());
945 server
946 .send("250-PROTOCOLINFO 1\n250-AUTH METHODS=NULL\n250-VERSION Tor=1\n250 OK")
947 .await?;
948 server.send("250 OK").await?;
949 let mut tor = TorControlConnection::with_stream(client)?;
950 let result = tor.authenticate(&TorAuthentication::Null).await;
951 assert!(result.is_ok());
952
953 let (client, server) = create_mock().await?;
954 let mut server = Framed::new(server, LinesCodec::new());
955 server.send("551 Oops").await?;
956 let mut tor = TorControlConnection::with_stream(client)?;
957 let result = tor.authenticate(&TorAuthentication::Null).await;
958 assert!(result.is_err());
959
960 Ok(())
961 }
962
963 #[tokio::test]
964 async fn test_create_onion_service() -> Result<(), Box<dyn std::error::Error>> {
965 let (client, server) = create_mock().await?;
966 let mut server = Framed::new(server, LinesCodec::new());
967 server
968 .send("250-ServiceID=vvqbbaknxi6w44t6rplzh7nmesfzw3rjujdijpqsu5xl3nhlkdscgqad")
969 .await?;
970 server
971 .send("250-PrivateKey=ED25519-V3:0H/jnBeWzMoU1MGNRQPnmd8JqlpTNS3UeTiDOMyPTGGXXpLd0KinCtQbcgz2fCYjbzfK3ElJ7x3zGCkB1fAtAA==")
972 .await?;
973 server.send("250 OK").await?;
974 let mut tor = TorControlConnection::with_stream(client)?;
975 let onion_service = tor
976 .create_onion_service(&[OnionServiceMapping::new(8080, None)], true, None)
977 .await?;
978 assert_eq!(8080, onion_service.ports[0].virt_port);
979 assert_eq!(
980 TorSocketAddr::from_tcp_string("127.0.0.1:8080"),
981 Ok(onion_service.ports[0].clone().listen_address)
982 );
983 assert_eq!(
984 "vvqbbaknxi6w44t6rplzh7nmesfzw3rjujdijpqsu5xl3nhlkdscgqad",
985 onion_service.service_id.as_str()
986 );
987 assert_eq!(
988 OnionAddress::from_str(
989 "vvqbbaknxi6w44t6rplzh7nmesfzw3rjujdijpqsu5xl3nhlkdscgqad.onion:8080"
990 )?,
991 onion_service.onion_address(8080).unwrap()
992 );
993 Ok(())
994 }
995
996 #[tokio::test]
997 async fn test_get_protocol_info() -> Result<(), Box<dyn std::error::Error>> {
998 let (client, server) = create_mock().await?;
999 let mut server = Framed::new(server, LinesCodec::new());
1000 server.send("250-PROTOCOLINFO 1").await?;
1001 server.send("250-AUTH METHODS=NULL,FOO").await?;
1002 server.send("250-VERSION Tor=\"0.4.7.13\"").await?;
1003 server.send("250 OK").await?;
1004 let mut tor = TorControlConnection::with_stream(client)?;
1005 tor.get_protocol_info().await?;
1006
1007 Ok(())
1008 }
1009
1010 #[test]
1011 fn test_parse_onion_address() -> Result<(), Box<dyn std::error::Error>> {
1012 let address = OnionAddress::from_str(
1013 "647qjf6w3evdbdpy7oidf5vda6rsjzsl5a6ofsaou2v77hj7dmn2spqd.onion:80",
1014 )?;
1015 assert_eq!(
1016 TorServiceId::from_str("647qjf6w3evdbdpy7oidf5vda6rsjzsl5a6ofsaou2v77hj7dmn2spqd")?,
1017 address.service_id
1018 );
1019 assert_eq!(80, address.service_port);
1020
1021 if let Ok(_) = OnionAddress::from_str("foobar:27") {
1022 assert!(false);
1023 }
1024
1025 if let Ok(_) = OnionAddress::from_str(
1026 "647qjf6w3evdbdpy7oidf5vda6rsjzsl5a6ofsaou2v77hj7dmn2spqd.onion:abcd",
1027 ) {
1028 assert!(false);
1029 }
1030
1031 Ok(())
1032 }
1033}