netdoc builder: Implement object() and add one test case

This commit is contained in:
Ian Jackson 2023-01-24 16:01:37 +00:00
parent 4f0d17d96d
commit eb3b261595
2 changed files with 50 additions and 2 deletions

View File

@ -24,10 +24,13 @@ use std::marker::PhantomData;
use std::ops::Deref;
use std::time::SystemTime;
use base64ct::{Base64, Encoding};
use humantime::format_rfc3339;
use tor_bytes::EncodeError;
use tor_error::{internal, into_internal, Bug};
use crate::parse::keyword::Keyword;
use crate::parse::tokenize::tag_keywords_ok;
/// Network document text according to dir-spec.txt s1.2 and maybe s1.3
///
@ -318,7 +321,33 @@ impl<'n> ItemEncoder<'n> {
// Writeable isn't dyn-compatible
data: impl tor_bytes::WriteableOnce,
) {
todo!()
use crate::parse::tokenize::object::*;
self.doc.write_with(|out| {
if keywords.is_empty() || !tag_keywords_ok(keywords) {
return Err(internal!("bad object keywords string {:?}", keywords));
}
let data = {
let mut bytes = vec![];
data.write_into(&mut bytes)
.map_err(EncodeError::always_bug)?;
Base64::encode_string(&bytes)
};
let mut data = &data[..];
writeln!(out, "\n{BEGIN_STR}{keywords}{TAG_END}").expect("write!");
while !data.is_empty() {
let (l, r) = if data.len() > BASE64_PEM_MAX_LINE {
data.split_at(BASE64_PEM_MAX_LINE)
} else {
(data, "")
};
writeln!(out, "{l}").expect("write!");
data = r;
}
// final newline will be written by Drop impl
write!(out, "{END_STR}{keywords}{TAG_END}").expect("write!");
Ok(())
});
}
}
@ -341,6 +370,7 @@ mod test {
//! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
use super::*;
use base64ct::{Base64Unpadded, Encoding};
use humantime::parse_rfc3339;
fn time(s: &str) -> SystemTime {
@ -351,6 +381,15 @@ mod test {
fn authcert() {
use crate::doc::authcert::AuthCertKwd as ACK;
// c&p from crates/tor-llcrypto/tests/testvec.rs
let pk_rsa = {
let pem = "
MIGJAoGBANUntsY9boHTnDKKlM4VfczcBE6xrYwhDJyeIkh7TPrebUBBvRBGmmV+
PYK8AM9irDtqmSR+VztUwQxH9dyEmwrM2gMeym9uXchWd/dt7En/JNL8srWIf7El
qiBHRBGbtkF/Re5pb438HC/CGyuujp43oZ3CUYosJOfY/X+sD0aVAgMBAAE";
Base64Unpadded::decode_vec(&pem.replace('\n', "")).unwrap()
};
let mut encode = NetdocEncoder::new();
encode.item(ACK::DIR_KEY_CERTIFICATE_VERSION).arg(&3);
encode
@ -362,6 +401,10 @@ mod test {
encode
.item(ACK::DIR_KEY_EXPIRES)
.arg(&time("2021-04-18T08:36:57Z"));
encode
.item(ACK::DIR_IDENTITY_KEY)
.object("RSA PUBLIC KEY", &*pk_rsa);
let doc = encode.finish().unwrap();
eprintln!("{}", &*doc);
assert_eq!(
@ -370,6 +413,12 @@ mod test {
fingerprint ED03BB616EB2F60BEC80151114BB25CEF515B226
dir-key-published 2020-04-18 08:36:57
dir-key-expires 2021-04-18 08:36:57
dir-identity-key
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBANUntsY9boHTnDKKlM4VfczcBE6xrYwhDJyeIkh7TPrebUBBvRBGmmV+
PYK8AM9irDtqmSR+VztUwQxH9dyEmwrM2gMeym9uXchWd/dt7En/JNL8srWIf7El
qiBHRBGbtkF/Re5pb438HC/CGyuujp43oZ3CUYosJOfY/X+sD0aVAgMBAAE=
-----END RSA PUBLIC KEY-----
"
);
}

View File

@ -22,7 +22,6 @@ pub(crate) mod object {
/// indicates the end of a begin or end tag.
pub(crate) const TAG_END: &str = "-----";
/// Maximum PEM base64 line length (not enforced during parsing)
#[allow(dead_code)] // TOOD HS
pub(crate) const BASE64_PEM_MAX_LINE: usize = 64;
}