Skip to content

Commit fc3c757

Browse files
committed
Perform character set and length validation only
1 parent d969b5b commit fc3c757

File tree

2 files changed

+35
-28
lines changed

2 files changed

+35
-28
lines changed

lightning/src/ln/msgs.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use io_extras::read_to_end;
4040

4141
use util::events::MessageSendEventsProvider;
4242
use util::logger;
43-
use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt, ShortAsciiString};
43+
use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt, Hostname};
4444

4545
use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
4646

@@ -445,7 +445,7 @@ pub enum NetAddress {
445445
/// A hostname/port on which the peer is listening.
446446
Hostname {
447447
/// The hostname on which the node is listening.
448-
hostname: ShortAsciiString,
448+
hostname: Hostname,
449449
/// The port on which the node is listening.
450450
port: u16,
451451
},
@@ -1852,7 +1852,7 @@ mod tests {
18521852
use ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
18531853
use ln::msgs;
18541854
use ln::msgs::{FinalOnionHopData, OptionalField, OnionErrorPacket, OnionHopDataFormat};
1855-
use util::ser::{Writeable, Readable, ShortAsciiString};
1855+
use util::ser::{Writeable, Readable, Hostname};
18561856

18571857
use bitcoin::hashes::hex::FromHex;
18581858
use bitcoin::util::address::Address;
@@ -2033,7 +2033,7 @@ mod tests {
20332033
}
20342034
if hostname {
20352035
addresses.push(msgs::NetAddress::Hostname {
2036-
hostname: ShortAsciiString::try_from(String::from("host")).unwrap(),
2036+
hostname: Hostname::try_from(String::from("host")).unwrap(),
20372037
port: 9735,
20382038
});
20392039
}

lightning/src/util/ser.rs

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -915,67 +915,72 @@ impl Readable for String {
915915
}
916916
}
917917

918-
/// Represents a printable ASCII string whose length can be represented by a single byte.
918+
/// Represents a hostname for serialization purposes.
919+
/// Only the character set and length will be validated.
920+
/// The character set consists of ASCII alphanumeric characters, hyphens, and periods.
921+
/// Its length is guaranteed to be representable by a single byte.
919922
/// This serialization is used by BOLT 7 hostnames.
920923
#[derive(Clone, Debug, PartialEq)]
921-
pub struct ShortAsciiString(String);
922-
impl ShortAsciiString {
923-
/// Returns the length of the short ASCII string.
924+
pub struct Hostname(String);
925+
impl Hostname {
926+
/// Returns the length of the hostname.
924927
pub fn len(&self) -> u8 {
925928
(&self.0).len() as u8
926929
}
927930
}
928-
impl Deref for ShortAsciiString {
931+
impl Deref for Hostname {
929932
type Target = String;
930933

931934
fn deref(&self) -> &Self::Target {
932935
&self.0
933936
}
934937
}
935-
impl From<ShortAsciiString> for String {
936-
fn from(short_s: ShortAsciiString) -> Self {
938+
impl From<Hostname> for String {
939+
fn from(short_s: Hostname) -> Self {
937940
short_s.0
938941
}
939942
}
940-
impl TryFrom<Vec<u8>> for ShortAsciiString {
943+
impl TryFrom<Vec<u8>> for Hostname {
941944
type Error = ();
942945

943946
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
944947
if let Ok(s) = String::from_utf8(bytes) {
945-
ShortAsciiString::try_from(s)
948+
Hostname::try_from(s)
946949
} else {
947950
Err(())
948951
}
949952
}
950953
}
951-
impl TryFrom<String> for ShortAsciiString {
954+
impl TryFrom<String> for Hostname {
952955
type Error = ();
953956

954957
fn try_from(s: String) -> Result<Self, Self::Error> {
955958
if s.len() <= 255 && s.chars().all(|c|
956-
c.is_ascii() && !c.is_ascii_control()
959+
c.is_ascii_alphanumeric() ||
960+
c == '.' ||
961+
c == '-'
957962
) {
958-
Ok(ShortAsciiString(s))
963+
Ok(Hostname(s))
959964
} else {
960965
Err(())
961966
}
962967
}
963968
}
964-
impl Writeable for ShortAsciiString {
969+
impl Writeable for Hostname {
965970
#[inline]
966971
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
967972
self.len().write(w)?;
968973
w.write_all(self.as_bytes())
969974
}
970975
}
971-
impl Readable for ShortAsciiString {
976+
impl Readable for Hostname {
972977
#[inline]
973-
fn read<R: Read>(r: &mut R) -> Result<ShortAsciiString, DecodeError> {
978+
fn read<R: Read>(r: &mut R) -> Result<Hostname, DecodeError> {
974979
let len: u8 = Readable::read(r)?;
975980
let mut vec = Vec::with_capacity(len.into());
976981
vec.resize(len.into(), 0);
977982
r.read_exact(&mut vec)?;
978-
ShortAsciiString::try_from(vec).map_err(|_| DecodeError::InvalidValue)
983+
Hostname::try_from(vec).map_err(|_| DecodeError::InvalidValue)
979984
}
980985
}
981986

@@ -998,23 +1003,25 @@ impl Readable for Duration {
9981003
#[cfg(test)]
9991004
mod tests {
10001005
use core::convert::TryFrom;
1001-
use util::ser::{Readable, ShortAsciiString, Writeable};
1006+
use util::ser::{Readable, Hostname, Writeable};
10021007

10031008
#[test]
1004-
fn short_ascii_string_conversion() {
1005-
assert_eq!(ShortAsciiString::try_from(String::from("test")).unwrap().as_str(), "test");
1009+
fn hostname_conversion() {
1010+
assert_eq!(Hostname::try_from(String::from("a-test.com")).unwrap().as_str(), "a-test.com");
10061011

1007-
assert!(ShortAsciiString::try_from(String::from("⚡")).is_err());
1012+
assert!(Hostname::try_from(String::from("\"")).is_err());
1013+
assert!(Hostname::try_from(String::from("$")).is_err());
1014+
assert!(Hostname::try_from(String::from("⚡")).is_err());
10081015
let mut large_vec = Vec::with_capacity(256);
10091016
large_vec.resize(256, b'A');
1010-
assert!(ShortAsciiString::try_from(String::from_utf8(large_vec).unwrap()).is_err());
1017+
assert!(Hostname::try_from(String::from_utf8(large_vec).unwrap()).is_err());
10111018
}
10121019

10131020
#[test]
1014-
fn short_ascii_string_serialization() {
1015-
let short_s = ShortAsciiString::try_from(String::from("test")).unwrap();
1021+
fn hostname_serialization() {
1022+
let short_s = Hostname::try_from(String::from("test")).unwrap();
10161023
let mut buf: Vec<u8> = Vec::new();
10171024
short_s.write(&mut buf).unwrap();
1018-
assert_eq!(ShortAsciiString::read(&mut buf.as_slice()).unwrap().as_str(), "test");
1025+
assert_eq!(Hostname::read(&mut buf.as_slice()).unwrap().as_str(), "test");
10191026
}
10201027
}

0 commit comments

Comments
 (0)