Skip to content

Commit 8882676

Browse files
committed
Parse SocketAddress::OnionV2
1 parent edc5490 commit 8882676

File tree

2 files changed

+50
-55
lines changed

2 files changed

+50
-55
lines changed

lightning/src/ln/msgs.rs

+49-54
Original file line numberDiff line numberDiff line change
@@ -774,8 +774,12 @@ pub enum SocketAddress {
774774
/// An old-style Tor onion address/port on which the peer is listening.
775775
///
776776
/// This field is deprecated and the Tor network generally no longer supports V2 Onion
777-
/// addresses. Thus, the details are not parsed here.
778-
OnionV2([u8; 12]),
777+
/// addresses.
778+
OnionV2{
779+
/// The base32 of first 80 bits
780+
addr: [u8; 10],
781+
port: u16,
782+
},
779783
/// A new-style Tor onion address/port on which the peer is listening.
780784
///
781785
/// To create the human-readable "hostname", concatenate the ED25519 pubkey, checksum, and version,
@@ -805,7 +809,7 @@ impl SocketAddress {
805809
match self {
806810
&SocketAddress::TcpIpV4 {..} => { 1 },
807811
&SocketAddress::TcpIpV6 {..} => { 2 },
808-
&SocketAddress::OnionV2(_) => { 3 },
812+
&SocketAddress::OnionV2 {..} => { 3 },
809813
&SocketAddress::OnionV3 {..} => { 4 },
810814
&SocketAddress::Hostname {..} => { 5 },
811815
}
@@ -816,7 +820,7 @@ impl SocketAddress {
816820
match self {
817821
&SocketAddress::TcpIpV4 { .. } => { 6 },
818822
&SocketAddress::TcpIpV6 { .. } => { 18 },
819-
&SocketAddress::OnionV2(_) => { 12 },
823+
&SocketAddress::OnionV2 { .. } => { 12 },
820824
&SocketAddress::OnionV3 { .. } => { 37 },
821825
// Consists of 1-byte hostname length, hostname bytes, and 2-byte port.
822826
&SocketAddress::Hostname { ref hostname, .. } => { u16::from(hostname.len()) + 3 },
@@ -842,9 +846,10 @@ impl Writeable for SocketAddress {
842846
addr.write(writer)?;
843847
port.write(writer)?;
844848
},
845-
&SocketAddress::OnionV2(bytes) => {
849+
&SocketAddress::OnionV2{ ref addr, ref port } => {
846850
3u8.write(writer)?;
847-
bytes.write(writer)?;
851+
addr.write(writer)?;
852+
port.write(writer)?;
848853
},
849854
&SocketAddress::OnionV3 { ref ed25519_pubkey, ref checksum, ref version, ref port } => {
850855
4u8.write(writer)?;
@@ -879,7 +884,10 @@ impl Readable for Result<SocketAddress, u8> {
879884
port: Readable::read(reader)?,
880885
}))
881886
},
882-
3 => Ok(Ok(SocketAddress::OnionV2(Readable::read(reader)?))),
887+
3 => Ok(Ok(SocketAddress::OnionV2 {
888+
addr: Readable::read(reader)?,
889+
port: Readable::read(reader)?,
890+
})),
883891
4 => {
884892
Ok(Ok(SocketAddress::OnionV3 {
885893
ed25519_pubkey: Readable::read(reader)?,
@@ -961,40 +969,24 @@ impl From<std::net::SocketAddr> for SocketAddress {
961969
}
962970
}
963971

964-
/// Parses an OnionV2 host and port into a [`SocketAddress::OnionV2`].
965-
///
966-
/// The host part must end with ".onion".
967-
pub fn parse_onion_v2_address(host: &str) -> Result<SocketAddress, SocketAddressParseError> {
968-
if host.ends_with(".onion") {
969-
let domain = &host[..host.len() - ".onion".len()];
970-
if domain.len() != 16 {
971-
return Err(SocketAddressParseError::InvalidOnionV2);
972-
}
973-
let onion = base32::Alphabet::RFC4648 { padding: false }.decode(&domain).map_err(|_| SocketAddressParseError::InvalidOnionV2)?;
974-
if onion.len() != 12 {
975-
return Err(SocketAddressParseError::InvalidOnionV2);
976-
}
977-
let mut bytes = [0; 12];
978-
bytes.copy_from_slice(&onion);
979-
return Ok(SocketAddress::OnionV2(bytes));
980-
} else {
981-
return Err(SocketAddressParseError::InvalidInput);
982-
}
983-
}
984-
985-
/// Parses an OnionV3 host and port into a [`SocketAddress::OnionV3`].
972+
/// Parses an Onion host and port into a [`SocketAddress::OnionV3`].
986973
///
987974
/// The host part must end with ".onion".
988-
pub fn parse_onion_v3_address(host: &str, port: u16) -> Result<SocketAddress, SocketAddressParseError> {
975+
pub fn parse_onion_address(host: &str, port: u16) -> Result<SocketAddress, SocketAddressParseError> {
989976
if host.ends_with(".onion") {
990977
let domain = &host[..host.len() - ".onion".len()];
991-
if domain.len() != 56 {
978+
if domain.len() != 56 && domain.len() !=16 {
992979
return Err(SocketAddressParseError::InvalidOnionV3);
993980
}
994981
let onion = base32::Alphabet::RFC4648 { padding: false }.decode(&domain).map_err(|_| SocketAddressParseError::InvalidOnionV3)?;
995-
if onion.len() != 35 {
982+
if onion.len() != 35 && onion.len() != 10 {
996983
return Err(SocketAddressParseError::InvalidOnionV3);
997984
}
985+
if onion.len() == 10 {
986+
let mut addr = [0; 10];
987+
addr.copy_from_slice(&onion);
988+
return Ok(SocketAddress::OnionV2{ addr, port });
989+
}
998990
let version = onion[0];
999991
let first_checksum_flag = onion[1];
1000992
let second_checksum_flag = onion[2];
@@ -1009,9 +1001,9 @@ pub fn parse_onion_v3_address(host: &str, port: u16) -> Result<SocketAddress, So
10091001
}
10101002

10111003
/// [`SocketAddress::OnionV2`] to onion address string
1012-
pub fn to_onion_v2_string(bytes: &[u8; 12]) -> String {
1013-
let onion = base32::Alphabet::RFC4648 { padding: false }.encode(&bytes[..]);
1014-
format!("{onion}.onion")
1004+
pub fn to_onion_v2_string(addr: &[u8; 10], port: &u16) -> String {
1005+
let onion = base32::Alphabet::RFC4648 { padding: false }.encode(&addr[..]);
1006+
format!("{onion}.onion:{port}")
10151007
}
10161008

10171009
/// [`SocketAddress::OnionV3`] to onion address string
@@ -1029,7 +1021,7 @@ impl Display for SocketAddress {
10291021
match self {
10301022
SocketAddress::TcpIpV4{addr, port} => write!(f, "{}:{port}", std::net::Ipv4Addr::from(*addr))?,
10311023
SocketAddress::TcpIpV6{addr, port} => write!(f, "[{}]:{port}", std::net::Ipv6Addr::from(*addr))?,
1032-
SocketAddress::OnionV2(bytes) => write!(f, "{}", to_onion_v2_string(&bytes))?,
1024+
SocketAddress::OnionV2{addr, port} => write!(f, "{}", to_onion_v2_string(addr, port))?,
10331025
SocketAddress::OnionV3 {
10341026
ed25519_pubkey,
10351027
checksum,
@@ -1052,13 +1044,12 @@ impl FromStr for SocketAddress {
10521044
Err(_) => {
10531045
let trimmed_input = match s.rfind(":") {
10541046
Some(pos) => pos,
1055-
None if s.ends_with(".onion") => return parse_onion_v2_address(s),
1056-
_ => return Err(SocketAddressParseError::InvalidInput),
1047+
None => return Err(SocketAddressParseError::InvalidInput),
10571048
};
10581049
let host = &s[..trimmed_input];
10591050
let port: u16 = s[trimmed_input + 1..].parse().map_err(|_| SocketAddressParseError::InvalidPort)?;
10601051
if host.ends_with(".onion") {
1061-
return parse_onion_v3_address(host, port);
1052+
return parse_onion_address(host, port);
10621053
};
10631054
if let Ok(hostname) = Hostname::try_from(s[..trimmed_input].to_string()) {
10641055
return Ok(SocketAddress::Hostname { hostname, port });
@@ -2915,9 +2906,10 @@ mod tests {
29152906
});
29162907
}
29172908
if onionv2 {
2918-
addresses.push(msgs::SocketAddress::OnionV2(
2919-
[255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 38, 7]
2920-
));
2909+
addresses.push(msgs::SocketAddress::OnionV2 {
2910+
addr: [255, 254, 253, 252, 251, 250, 249, 248, 247, 246],
2911+
port: 9735,
2912+
});
29212913
}
29222914
if onionv3 {
29232915
addresses.push(msgs::SocketAddress::OnionV3 {
@@ -4125,19 +4117,19 @@ mod tests {
41254117
#[test]
41264118
#[cfg(feature = "std")]
41274119
fn test_socket_address_from_str() {
4128-
let v4 = SocketAddress::TcpIpV4 {
4120+
let tcpip_v4 = SocketAddress::TcpIpV4 {
41294121
addr: Ipv4Addr::new(127, 0, 0, 1).octets(),
41304122
port: 1234,
41314123
};
4132-
assert_eq!(v4, SocketAddress::from_str("127.0.0.1:1234").unwrap());
4133-
assert_eq!(v4, SocketAddress::from_str(&v4.to_string()).unwrap());
4124+
assert_eq!(tcpip_v4, SocketAddress::from_str("127.0.0.1:1234").unwrap());
4125+
assert_eq!(tcpip_v4, SocketAddress::from_str(&tcpip_v4.to_string()).unwrap());
41344126

4135-
let v6 = SocketAddress::TcpIpV6 {
4127+
let tcpip_v6 = SocketAddress::TcpIpV6 {
41364128
addr: Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).octets(),
41374129
port: 1234,
41384130
};
4139-
assert_eq!(v6, SocketAddress::from_str("[0:0:0:0:0:0:0:1]:1234").unwrap());
4140-
assert_eq!(v6, SocketAddress::from_str(&v6.to_string()).unwrap());
4131+
assert_eq!(tcpip_v6, SocketAddress::from_str("[0:0:0:0:0:0:0:1]:1234").unwrap());
4132+
assert_eq!(tcpip_v6, SocketAddress::from_str(&tcpip_v6.to_string()).unwrap());
41414133

41424134
let hostname = SocketAddress::Hostname {
41434135
hostname: Hostname::try_from("lightning-node.mydomain.com".to_string()).unwrap(),
@@ -4146,19 +4138,22 @@ mod tests {
41464138
assert_eq!(hostname, SocketAddress::from_str("lightning-node.mydomain.com:1234").unwrap());
41474139
assert_eq!(hostname, SocketAddress::from_str(&hostname.to_string()).unwrap());
41484140

4149-
let v2 = SocketAddress::OnionV2 ([37, 24, 75, 5, 25, 73, 117, 194, 139, 102, 182, 107]);
4150-
assert_eq!(v2, SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234").unwrap());
4151-
assert_eq!(v2, SocketAddress::from_str(&v2.to_string()).unwrap());
4141+
let onion_v2 = SocketAddress::OnionV2{
4142+
addr: [40, 4, 64, 185, 202, 19, 162, 75, 90, 200],
4143+
port: 80,
4144+
};
4145+
assert_eq!(onion_v2, SocketAddress::from_str("facebookcorewwwi.onion:80").unwrap());
4146+
assert_eq!(onion_v2, SocketAddress::from_str(&onion_v2.to_string()).unwrap());
41524147

4153-
let v3 = SocketAddress::OnionV3 {
4148+
let onion_v3 = SocketAddress::OnionV3 {
41544149
ed25519_pubkey: [37, 24, 75, 5, 25, 73, 117, 194, 139, 102, 182, 107, 4, 105, 247, 246, 85,
41554150
111, 177, 172, 49, 137, 167, 155, 64, 221, 163, 47, 31, 33, 71, 3],
41564151
checksum: 48326,
41574152
version: 121,
41584153
port: 1234
41594154
};
4160-
assert_eq!(v3, SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234").unwrap());
4161-
assert_eq!(v3, SocketAddress::from_str(&v3.to_string()).unwrap());
4155+
assert_eq!(onion_v3, SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234").unwrap());
4156+
assert_eq!(onion_v3, SocketAddress::from_str(&onion_v3.to_string()).unwrap());
41624157

41634158
assert_eq!(Err(SocketAddressParseError::InvalidOnionV3), SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6.onion:1234"));
41644159
assert_eq!(Err(SocketAddressParseError::InvalidInput), SocketAddress::from_str("127.0.0.1@1234"));

lightning/src/util/ser.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ macro_rules! impl_array {
587587

588588
impl_array!(3, u8); // for rgb, ISO 4712 code
589589
impl_array!(4, u8); // for IPv4
590-
impl_array!(12, u8); // for OnionV2
590+
impl_array!(10, u8); // for OnionV2
591591
impl_array!(16, u8); // for IPv6
592592
impl_array!(32, u8); // for channel id & hmac
593593
impl_array!(PUBLIC_KEY_SIZE, u8); // for PublicKey

0 commit comments

Comments
 (0)