pub struct UnjoinedSigningClient { /* private fields */ }Expand description
A client for the remote signing protocol that has not yet joined a session.
Clients can perform both the initiator and signer roles.
Implementations§
source§impl UnjoinedSigningClient
impl UnjoinedSigningClient
sourcepub fn new_initiator(
req: impl IntoClientRequest,
initiator: Box<dyn SessionInitiatePeer>,
session_info_cb: Option<SessionInfoCallback>
) -> Result<InitiatorClient, RemoteSignError>
pub fn new_initiator(
req: impl IntoClientRequest,
initiator: Box<dyn SessionInitiatePeer>,
session_info_cb: Option<SessionInfoCallback>
) -> Result<InitiatorClient, RemoteSignError>
Create a new client in the initiator role.
Examples found in repository?
src/cli.rs (lines 645-649)
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668
fn collect_certificates_from_args(
args: &ArgMatches,
scan_smartcard: bool,
) -> Result<(Vec<Box<dyn PrivateKey>>, Vec<CapturedX509Certificate>), AppleCodesignError> {
let mut keys: Vec<Box<dyn PrivateKey>> = vec![];
let mut certs = vec![];
if let Some(p12_path) = args.get_one::<String>("p12_path") {
let p12_data = std::fs::read(p12_path)?;
let p12_password = if let Some(password) = args.get_one::<String>("p12_password") {
password.to_string()
} else if let Some(path) = args.get_one::<String>("p12_password_file") {
std::fs::read_to_string(path)?
.lines()
.next()
.expect("should get a single line")
.to_string()
} else {
dialoguer::Password::new()
.with_prompt("Please enter password for p12 file")
.interact()?
};
let (cert, key) = parse_pfx_data(&p12_data, &p12_password)?;
keys.push(Box::new(key));
certs.push(cert);
}
if let Some(values) = args.get_many::<String>("pem_source") {
for pem_source in values {
warn!("reading PEM data from {}", pem_source);
let pem_data = std::fs::read(pem_source)?;
for pem in pem::parse_many(pem_data).map_err(AppleCodesignError::CertificatePem)? {
match pem.tag.as_str() {
"CERTIFICATE" => {
certs.push(CapturedX509Certificate::from_der(pem.contents)?);
}
"PRIVATE KEY" => {
keys.push(Box::new(InMemoryPrivateKey::from_pkcs8_der(&pem.contents)?));
}
"RSA PRIVATE KEY" => {
keys.push(Box::new(InMemoryPrivateKey::from_pkcs1_der(&pem.contents)?));
}
tag => warn!("(unhandled PEM tag {}; ignoring)", tag),
}
}
}
}
if let Some(values) = args.get_many::<String>("der_source") {
for der_source in values {
warn!("reading DER file {}", der_source);
let der_data = std::fs::read(der_source)?;
certs.push(CapturedX509Certificate::from_der(der_data)?);
}
}
find_certificates_in_keychain(args, &mut keys, &mut certs)?;
if scan_smartcard {
if let Some(slot) = args.get_one::<String>("smartcard_slot") {
let pin_env_var = args.get_one::<String>("smartcard_pin_env");
handle_smartcard_sign_slot(slot, pin_env_var.map(|x| &**x), &mut keys, &mut certs)?;
}
}
let remote_signing_url = if args.get_flag("remote_signer") {
args.get_one::<String>("remote_signing_url")
} else {
None
};
if let Some(remote_signing_url) = remote_signing_url {
let initiator = get_remote_signing_initiator(args)?;
let client = UnjoinedSigningClient::new_initiator(
remote_signing_url,
initiator,
Some(print_session_join),
)?;
// As part of the handshake we obtained the public certificates from the signer.
// So make them the canonical set.
if !certs.is_empty() {
warn!(
"ignoring {} local certificates and using remote signer's certificate(s)",
certs.len()
);
}
certs = vec![client.signing_certificate().clone()];
certs.extend(client.certificate_chain().iter().cloned());
// The client implements Sign, so we just use it as the private key.
keys = vec![Box::new(client)];
}
Ok((keys, certs))
}sourcepub fn new_signer(
joiner: Box<dyn SessionJoinPeerPreJoin>,
signing_key: &dyn KeyInfoSigner,
signing_cert: CapturedX509Certificate,
certificates: Vec<CapturedX509Certificate>,
default_server_url: String
) -> Result<SigningClient<'_>, RemoteSignError>
pub fn new_signer(
joiner: Box<dyn SessionJoinPeerPreJoin>,
signing_key: &dyn KeyInfoSigner,
signing_cert: CapturedX509Certificate,
certificates: Vec<CapturedX509Certificate>,
default_server_url: String
) -> Result<SigningClient<'_>, RemoteSignError>
Create a new client in the signer role.
Examples found in repository?
src/cli.rs (lines 2085-2091)
2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095
fn command_remote_sign(args: &ArgMatches) -> Result<(), AppleCodesignError> {
let remote_url = args
.get_one::<String>("remote_signing_url")
.expect("remote signing URL should always be present");
let session_join_string = if args.get_flag("session_join_string_editor") {
let mut value = None;
for _ in 0..3 {
if let Some(content) = dialoguer::Editor::new()
.require_save(true)
.edit("# Please enter the -----BEGIN SESSION JOIN STRING---- content below.\n# Remember to save the file!")?
{
value = Some(content);
break;
}
}
value.ok_or_else(|| {
AppleCodesignError::CliGeneralError("session join string not entered in editor".into())
})?
} else if let Some(path) = args.get_one::<String>("session_join_string_path") {
std::fs::read_to_string(path)?
} else if let Some(value) = args.get_one::<String>("session_join_string") {
value.to_string()
} else {
return Err(AppleCodesignError::CliGeneralError(
"session join string argument parsing failure".into(),
));
};
let mut joiner = create_session_joiner(session_join_string)?;
if let Some(env) = args.get_one::<String>("remote_shared_secret_env") {
let secret = std::env::var(env).map_err(|_| AppleCodesignError::CliBadArgument)?;
joiner.register_state(SessionJoinState::SharedSecret(secret.as_bytes().to_vec()))?;
} else if let Some(secret) = args.get_one::<String>("remote_shared_secret") {
joiner.register_state(SessionJoinState::SharedSecret(secret.as_bytes().to_vec()))?;
}
let (private_keys, mut public_certificates) = collect_certificates_from_args(args, true)?;
let private = private_keys
.into_iter()
.next()
.ok_or(AppleCodesignError::NoSigningCertificate)?;
let cert = public_certificates.remove(0);
let certificates = if let Some(chain) = cert.apple_root_certificate_chain() {
// The chain starts with self.
chain.into_iter().skip(1).collect::<Vec<_>>()
} else {
public_certificates
};
joiner.register_state(SessionJoinState::PublicKeyDecrypt(
private.to_public_key_peer_decrypt()?,
))?;
let client = UnjoinedSigningClient::new_signer(
joiner,
private.as_key_info_signer(),
cert,
certificates,
remote_url.to_string(),
)?;
client.run()?;
Ok(())
}sourcepub fn join_session(
self,
join_context: SessionJoinContext,
signing_key: &dyn KeyInfoSigner,
signing_cert: CapturedX509Certificate,
certificates: Vec<CapturedX509Certificate>
) -> Result<SigningClient<'_>, RemoteSignError>
pub fn join_session(
self,
join_context: SessionJoinContext,
signing_key: &dyn KeyInfoSigner,
signing_cert: CapturedX509Certificate,
certificates: Vec<CapturedX509Certificate>
) -> Result<SigningClient<'_>, RemoteSignError>
Join a signing session.
This should be called by signers once they have the session ID to join.
Examples found in repository?
src/remote_signing/mod.rs (line 493)
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
pub fn new_signer(
joiner: Box<dyn SessionJoinPeerPreJoin>,
signing_key: &dyn KeyInfoSigner,
signing_cert: CapturedX509Certificate,
certificates: Vec<CapturedX509Certificate>,
default_server_url: String,
) -> Result<SigningClient, RemoteSignError> {
// An error here could result in the peer hanging indefinitely because the session
// is unjoined. Ideally we'd recover from this by attempting to join with an error.
// However, we may not even be able to obtain the session ID since sometimes it is
// encrypted and the error could be from a decryption failure! So for now, just let
// the peer idle.
let join_context = joiner.join_context()?;
let server_url = join_context
.server_url
.as_ref()
.unwrap_or(&default_server_url);
let slf = Self::new(server_url)?;
slf.join_session(join_context, signing_key, signing_cert, certificates)
}Auto Trait Implementations§
impl !RefUnwindSafe for UnjoinedSigningClient
impl Send for UnjoinedSigningClient
impl Sync for UnjoinedSigningClient
impl Unpin for UnjoinedSigningClient
impl !UnwindSafe for UnjoinedSigningClient
Blanket Implementations§
§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
Causes
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
Causes
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
Causes
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
Causes
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
Causes
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
Causes
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
Causes
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
Causes
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
Formats each item in a sequence. Read more
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Pipes by value. This is generally the method you want to use. Read more
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
Borrows
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
Mutably borrows
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> Rwhere
Self: Borrow<B>,
B: 'a + ?Sized,
R: 'a,
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> Rwhere
Self: Borrow<B>,
B: 'a + ?Sized,
R: 'a,
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R
) -> Rwhere
Self: BorrowMut<B>,
B: 'a + ?Sized,
R: 'a,
fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R
) -> Rwhere
Self: BorrowMut<B>,
B: 'a + ?Sized,
R: 'a,
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> Rwhere
Self: AsRef<U>,
U: 'a + ?Sized,
R: 'a,
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> Rwhere
Self: AsRef<U>,
U: 'a + ?Sized,
R: 'a,
Borrows
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> Rwhere
Self: AsMut<U>,
U: 'a + ?Sized,
R: 'a,
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> Rwhere
Self: AsMut<U>,
U: 'a + ?Sized,
R: 'a,
Mutably borrows
self, then passes self.as_mut() into the pipe
function.§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
Immutable access to the
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
Mutable access to the
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
Immutable access to the
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
Mutable access to the
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Selfwhere
Self: Deref<Target = T>,
T: ?Sized,
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Selfwhere
Self: Deref<Target = T>,
T: ?Sized,
Immutable access to the
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Selfwhere
Self: DerefMut<Target = T> + Deref,
T: ?Sized,
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Selfwhere
Self: DerefMut<Target = T> + Deref,
T: ?Sized,
Mutable access to the
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
Calls
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
Calls
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
Calls
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
Calls
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
Calls
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
Calls
.tap_ref_mut() only in debug builds, and is erased in release
builds.