1
//! Implement a concrete type to build channels over a transport.
2

            
3
use async_trait::async_trait;
4
use futures::{AsyncRead, AsyncWrite};
5
use std::io;
6
use std::sync::{Arc, Mutex};
7
use std::time::Duration;
8
use tracing::instrument;
9

            
10
use crate::factory::{BootstrapReporter, ChannelFactory, IncomingChannelFactory};
11
use crate::transport::TransportImplHelper;
12
use crate::{Error, event::ChanMgrEventSender};
13

            
14
use safelog::MaybeSensitive;
15
use tor_basic_utils::rand_hostname;
16
use tor_error::internal;
17
use tor_linkspec::{ChanTarget, HasChanMethod, IntoOwnedChanTarget, OwnedChanTarget};
18
use tor_proto::channel::ChannelType;
19
use tor_proto::channel::kist::KistParams;
20
use tor_proto::channel::params::ChannelPaddingInstructionsUpdates;
21
use tor_proto::memquota::ChannelAccount;
22
use tor_proto::peer::PeerAddr;
23
use tor_rtcompat::SpawnExt;
24
use tor_rtcompat::{CertifiedConn, Runtime, StreamOps, TlsProvider, tls::TlsConnector};
25

            
26
#[cfg(feature = "relay")]
27
use {
28
    safelog::Sensitive, std::net::SocketAddr, tor_error::bad_api_usage,
29
    tor_proto::RelayChannelAuthMaterial, tor_proto::relay::CreateRequestHandler,
30
};
31

            
32
/// TLS-based channel builder.
33
///
34
/// This is a separate type so that we can keep our channel management code
35
/// network-agnostic.
36
///
37
/// It uses a provided `TransportHelper` type to make a connection (possibly
38
/// directly over TCP, and possibly over some other protocol).  It then
39
/// negotiates TLS over that connection, and negotiates a Tor channel over that
40
/// TLS session.
41
///
42
/// This channel builder does not retry on failure, but it _does_ implement a
43
/// time-out.
44
pub struct ChanBuilder<R: Runtime, H: TransportImplHelper>
45
where
46
    R: tor_rtcompat::TlsProvider<H::Stream>,
47
{
48
    /// Asynchronous runtime for TLS, TCP, spawning, and timeouts.
49
    runtime: R,
50
    /// The transport object that we use to construct streams.
51
    transport: H,
52
    /// Object to build TLS connections.
53
    tls_connector: <R as TlsProvider<H::Stream>>::Connector,
54
    /// Object to accept TLS connections.
55
    #[cfg(feature = "relay")]
56
    tls_acceptor: Option<<R as TlsProvider<H::Stream>>::Acceptor>,
57
    /// Relay authentication key material needed for relay channels.
58
    #[cfg(feature = "relay")]
59
    auth_material: Option<Arc<RelayChannelAuthMaterial>>,
60
    /// Our address(es) to use in the NETINFO cell.
61
    // TODO: We might want one day to support updating the addresses here in the same way we
62
    // support updating the auth_material. One use case for this is the relay config reload.
63
    #[cfg(feature = "relay")]
64
    my_addrs: Vec<SocketAddr>,
65
    /// Provided to each new channel so that they can handle CREATE* requests.
66
    #[cfg(feature = "relay")]
67
    create_request_handler: Option<Arc<CreateRequestHandler>>,
68
}
69

            
70
impl<R: Runtime, H: TransportImplHelper> ChanBuilder<R, H>
71
where
72
    R: TlsProvider<H::Stream>,
73
{
74
    /// Construct a new client specific ChanBuilder.
75
19
    pub fn new_client(runtime: R, transport: H) -> Self {
76
19
        let tls_connector = <R as TlsProvider<H::Stream>>::tls_connector(&runtime);
77
19
        ChanBuilder {
78
19
            runtime,
79
19
            transport,
80
19
            tls_connector,
81
19
            #[cfg(feature = "relay")]
82
19
            tls_acceptor: None,
83
19
            #[cfg(feature = "relay")]
84
19
            auth_material: None,
85
19
            #[cfg(feature = "relay")]
86
19
            my_addrs: Vec::new(),
87
19
            #[cfg(feature = "relay")]
88
19
            create_request_handler: None,
89
19
        }
90
19
    }
91

            
92
    /// Construct a new relay specific ChanBuilder.
93
    #[cfg(feature = "relay")]
94
    pub fn new_relay(
95
        runtime: R,
96
        transport: H,
97
        auth_material: Arc<RelayChannelAuthMaterial>,
98
        my_addrs: Vec<SocketAddr>,
99
        create_request_handler: Option<Arc<CreateRequestHandler>>,
100
    ) -> crate::Result<Self> {
101
        use tor_error::into_internal;
102
        use tor_rtcompat::tls::TlsAcceptorSettings;
103

            
104
        // Build the TLS acceptor.
105
        let tls_settings = TlsAcceptorSettings::new(auth_material.tls_key_and_cert().clone())
106
            .map_err(into_internal!("Unable to build TLS acceptor setting"))?;
107
        let tls_acceptor = <R as TlsProvider<H::Stream>>::tls_acceptor(&runtime, tls_settings)
108
            .map_err(into_internal!("Unable to build TLS acceptor"))?;
109

            
110
        // Same builder as a client but with auth material and acceptor.
111
        let mut builder = Self::new_client(runtime, transport);
112
        builder.auth_material = Some(auth_material);
113
        builder.tls_acceptor = Some(tls_acceptor);
114
        builder.my_addrs = my_addrs;
115
        builder.create_request_handler = create_request_handler;
116

            
117
        Ok(builder)
118
    }
119

            
120
    /// Build a new `ChanBuilder` with the given `auth_material`,
121
    /// cloning everything else.
122
    ///
123
    /// This is needed because some relay keys rotate over time.
124
    #[cfg(feature = "relay")]
125
    pub fn rebuild_with_auth_material(
126
        &self,
127
        auth_material: Arc<RelayChannelAuthMaterial>,
128
    ) -> crate::Result<Self>
129
    where
130
        H: Clone,
131
    {
132
        Self::new_relay(
133
            self.runtime.clone(),
134
            self.transport.clone(),
135
            auth_material,
136
            self.my_addrs.clone(),
137
            self.create_request_handler.as_ref().map(Arc::clone),
138
        )
139
    }
140

            
141
    /// Build a new `ChanBuilder` with the given CREATE* request `handler`,
142
    /// cloning everything else.
143
    ///
144
    /// This is needed so that we can set the handler,
145
    /// which isn't known when the builder is initially created.
146
    #[cfg(feature = "relay")]
147
    pub fn rebuild_with_create_request_handler(
148
        &self,
149
        handler: Arc<CreateRequestHandler>,
150
    ) -> crate::Result<Self>
151
    where
152
        H: Clone,
153
    {
154
        let auth_material = self.auth_material.clone().ok_or_else(|| {
155
            internal!("Trying to set a CREATE* request handler for a non-relay channel builder")
156
        })?;
157

            
158
        Self::new_relay(
159
            self.runtime.clone(),
160
            self.transport.clone(),
161
            auth_material,
162
            self.my_addrs.clone(),
163
            Some(handler),
164
        )
165
    }
166

            
167
    /// Return the outbound channel type of this config.
168
    ///
169
    /// The channel type is used when creating outbound channels. Relays always initiate channels
170
    /// as "relay initiator" while client and bridges behave like a "client initiator".
171
    ///
172
    /// Important: The wrong channel type is returned if this is called before `with_identities()`
173
    /// is called.
174
3
    fn outbound_chan_type(&self) -> ChannelType {
175
        #[cfg(feature = "relay")]
176
3
        if self.auth_material.is_some() {
177
            return ChannelType::RelayInitiator;
178
3
        }
179
3
        ChannelType::ClientInitiator
180
3
    }
181
}
182

            
183
#[async_trait]
184
impl<R: Runtime, H: TransportImplHelper> ChannelFactory for ChanBuilder<R, H>
185
where
186
    R: tor_rtcompat::TlsProvider<H::Stream> + Send + Sync,
187
    H: Send + Sync,
188
{
189
    #[instrument(skip_all, level = "trace")]
190
    async fn connect_via_transport(
191
        &self,
192
        target: &OwnedChanTarget,
193
        reporter: BootstrapReporter,
194
        memquota: ChannelAccount,
195
    ) -> crate::Result<Arc<tor_proto::channel::Channel>> {
196
        use tor_rtcompat::SleepProviderExt;
197

            
198
        // TODO: make this an option.  And make a better value.
199
        let delay = if target.chan_method().is_direct() {
200
            std::time::Duration::new(5, 0)
201
        } else {
202
            std::time::Duration::new(10, 0)
203
        };
204

            
205
        self.runtime
206
            .timeout(delay, self.connect_no_timeout(target, reporter.0, memquota))
207
            .await
208
            .map_err(|_| Error::ChanTimeout {
209
                peer: target.to_logged(),
210
            })?
211
    }
212
}
213

            
214
#[async_trait]
215
impl<R: Runtime, H: TransportImplHelper> IncomingChannelFactory for ChanBuilder<R, H>
216
where
217
    R: tor_rtcompat::TlsProvider<H::Stream> + Send + Sync,
218
    H: Send + Sync,
219
{
220
    type Stream = H::Stream;
221

            
222
    #[cfg(feature = "relay")]
223
    async fn accept_from_transport(
224
        &self,
225
        peer: Sensitive<std::net::SocketAddr>,
226
        stream: Self::Stream,
227
        memquota: ChannelAccount,
228
    ) -> crate::Result<Arc<tor_proto::channel::Channel>> {
229
        use tor_linkspec::OwnedChanTargetBuilder;
230
        use tor_proto::relay::MaybeVerifiableRelayResponderChannel;
231

            
232
        // Note that as we accept a connection, we don't expect any specific identities and so we
233
        // can only build a target from the peer address. This means that the verification process
234
        // will not match the identities seen (if a relay <-> relay channel) to this target which
235
        // is fine as we are a responder.
236
        let target_no_ids = OwnedChanTargetBuilder::default()
237
            .addrs(vec![peer.into_inner()])
238
            .build()
239
            .map_err(|e| internal!("Unable to build chan target from peer sockaddr: {e}"))?;
240
        // Convert into a PeerAddr but keep it sensitive, this can be a client/bridge.
241
        let peer_addr: MaybeSensitive<PeerAddr> =
242
            MaybeSensitive::sensitive(peer.into_inner().into());
243

            
244
        // Helpers: For error mapping.
245
        let map_ioe = |ioe, action| Error::Io {
246
            action,
247
            peer: peer_addr.clone(),
248
            source: ioe,
249
        };
250
        let map_proto = |source, target: &OwnedChanTarget, clock_skew| Error::Proto {
251
            source,
252
            peer: target.to_logged(),
253
            clock_skew,
254
        };
255

            
256
        let tls = self
257
            .tls_acceptor
258
            .as_ref()
259
            .ok_or_else(|| internal!("Accepting connection without TLS acceptor"))?
260
            .negotiate_unvalidated(stream, "ignored")
261
            .await
262
            .map_err(|e| map_ioe(e.into(), "TLS negotiation"))?;
263
        let auth_material = self
264
            .auth_material
265
            .as_ref()
266
            .ok_or_else(|| internal!("Unable to build relay channel without auth material"))?
267
            .clone();
268

            
269
        let our_cert = tls
270
            .own_certificate()
271
            .map_err(|e| map_ioe(e.into(), "TLS Certs"))?
272
            .ok_or_else(|| Error::Internal(internal!("TLS connection without our certificate")))?
273
            .into_owned();
274

            
275
        let create_request_handler = self.create_request_handler.as_ref().ok_or_else(|| {
276
            bad_api_usage!("Can't create a relay channel without a CREATE* request handler")
277
        })?;
278

            
279
        let builder = tor_proto::RelayChannelBuilder::new();
280

            
281
        let unverified = builder
282
            .accept(
283
                Sensitive::new(peer_addr.inner()),
284
                self.my_addrs.clone(),
285
                tls,
286
                self.runtime.clone(),
287
                auth_material,
288
                memquota,
289
                Arc::clone(create_request_handler),
290
            )
291
            .handshake(|| self.runtime.wallclock())
292
            .await
293
            .map_err(|e| map_proto(e, &target_no_ids, None))?;
294

            
295
        let (chan, reactor) = match unverified {
296
            MaybeVerifiableRelayResponderChannel::Verifiable(c) => {
297
                let clock_skew = c.clock_skew();
298
                let now = self.runtime.wallclock();
299
                c.verify(&target_no_ids, &our_cert, Some(now))
300
                    .map_err(|e| map_proto(e, &target_no_ids, Some(clock_skew)))?
301
                    .finish()
302
                    .await
303
                    .map_err(|e| map_proto(e, &target_no_ids, Some(clock_skew)))?
304
            }
305
            MaybeVerifiableRelayResponderChannel::NonVerifiable(c) => {
306
                c.finish().map_err(|e| map_proto(e, &target_no_ids, None))?
307
            }
308
        };
309

            
310
        // Launch a task to run the channel reactor.
311
        self.runtime
312
            .spawn(async {
313
                let _ = reactor.run().await;
314
            })
315
            .map_err(|e| Error::from_spawn("responder channel reactor", e))?;
316

            
317
        Ok(chan)
318
    }
319
}
320

            
321
impl<R: Runtime, H: TransportImplHelper> ChanBuilder<R, H>
322
where
323
    R: tor_rtcompat::TlsProvider<H::Stream> + Send + Sync,
324
    H: Send + Sync,
325
{
326
    /// Perform the work of `connect_via_transport`, but without enforcing a timeout.
327
    ///
328
    /// Return a [`Channel`](tor_proto::channel::Channel) on success.
329
    #[instrument(skip_all, level = "trace")]
330
1
    async fn connect_no_timeout(
331
1
        &self,
332
1
        target: &OwnedChanTarget,
333
1
        event_sender: Arc<Mutex<ChanMgrEventSender>>,
334
1
        memquota: ChannelAccount,
335
1
    ) -> crate::Result<Arc<tor_proto::channel::Channel>> {
336
        use tor_rtcompat::tls::CertifiedConn;
337

            
338
        {
339
            event_sender.lock().expect("Lock poisoned").record_attempt();
340
        }
341

            
342
        // Before actually doing the connect, we need to validate the channel target based on this
343
        // build outbound channel type. There are restrictions we need to apply.
344
        self.validate_target(target)?;
345

            
346
        // 1a. Negotiate the TCP connection or other stream.
347

            
348
        // The returned PeerAddr is the actual address we are connected to.
349
        let (peer_addr, stream) = self.transport.connect(target).await?;
350
        // The peer could be a bridge/guard or a relay. We have to shield it right away to avoid
351
        // leaking the info in the logs but we also want the info for a relay<-> relay.
352
        let peer_addr = match self.outbound_chan_type() {
353
            ChannelType::ClientInitiator => MaybeSensitive::sensitive(peer_addr),
354
            ChannelType::RelayInitiator => MaybeSensitive::not_sensitive(peer_addr),
355
            _ => return Err(Error::Internal(internal!("Unknown outbound channel type"))),
356
        };
357

            
358
2
        let map_ioe = |action: &'static str| {
359
2
            let peer = peer_addr.clone();
360
            move |ioe: io::Error| Error::Io {
361
                action,
362
                peer,
363
                source: ioe.into(),
364
            }
365
2
        };
366

            
367
        {
368
            // TODO(nickm): At some point, it would be helpful to the
369
            // bootstrapping logic if we could distinguish which
370
            // transport just succeeded.
371
            event_sender
372
                .lock()
373
                .expect("Lock poisoned")
374
                .record_tcp_success();
375
        }
376

            
377
        // 1b. Negotiate TLS.
378

            
379
        let hostname = rand_hostname::random_hostname(&mut rand::rng());
380

            
381
        let tls = self
382
            .tls_connector
383
            .negotiate_unvalidated(stream, hostname.as_str())
384
            .await
385
            .map_err(map_ioe("TLS negotiation"))?;
386

            
387
        let peer_tls_cert = tls
388
            .peer_certificate()
389
            .map_err(map_ioe("TLS certs"))?
390
            .ok_or_else(|| Error::Internal(internal!("TLS connection with no peer certificate")))?
391
            // Note: we could skip this "into_owned" if we computed any necessary digest on the
392
            // certificate earlier.  That would require changing out channel negotiation APIs,
393
            // though, and might not be worth it.
394
            .into_owned();
395

            
396
        {
397
            event_sender
398
                .lock()
399
                .expect("Lock poisoned")
400
                .record_tls_finished();
401
        }
402

            
403
        // Store this so we can log it in case we don't recognize it.
404
        let outbound_chan_type = self.outbound_chan_type();
405
        let chan = match outbound_chan_type {
406
            ChannelType::ClientInitiator => {
407
                self.build_client_channel(
408
                    tls,
409
                    peer_addr,
410
                    target,
411
                    &peer_tls_cert,
412
                    memquota,
413
                    event_sender.clone(),
414
                )
415
                .await?
416
            }
417
            #[cfg(feature = "relay")]
418
            ChannelType::RelayInitiator => {
419
                self.build_relay_channel(
420
                    tls,
421
                    peer_addr,
422
                    target,
423
                    &peer_tls_cert,
424
                    memquota,
425
                    event_sender.clone(),
426
                )
427
                .await?
428
            }
429
            _ => {
430
                return Err(Error::Internal(internal!(
431
                    "Unusable channel type for outbound: {outbound_chan_type}",
432
                )));
433
            }
434
        };
435

            
436
        event_sender
437
            .lock()
438
            .expect("Lock poisoned")
439
            .record_handshake_done();
440

            
441
        Ok(chan)
442
1
    }
443

            
444
    /// Validate the given `target` as we (a relay) are attempting to connect to another relay.
445
    #[cfg(feature = "relay")]
446
    fn validate_target_as_relay<CT>(&self, target: &CT) -> crate::Result<()>
447
    where
448
        CT: ChanTarget,
449
    {
450
        use tor_linkspec::HasRelayIds;
451

            
452
        // Make sure we don't attempt to use a PT method for this relay channel.
453
        if !target.chan_method().is_direct() {
454
            // Return an internal error because the circuit reactor asking us to use a PT is a code
455
            // flow issue, not a protocol violation.
456
            return Err(Error::UnusableTarget(tor_error::bad_api_usage!(
457
                "Relays don't support outbound PT channels"
458
            )));
459
        }
460

            
461
        // Make sure that all addresses are allowed for an EXTEND. For instance, connecting to a
462
        // local/private network for security reasons as a it could lead to network
463
        // scanning by measuring latency between successful connect() and failures.
464
        //
465
        // If no addresses, it returns true and thus no error.
466
        if !target.all_addrs_allowed_for_outgoing_channels() {
467
            return Err(Error::Proto {
468
                source: tor_proto::Error::ChanProto(
469
                    "Target address is not allowed for outgoing channels".into(),
470
                ),
471
                peer: target.to_owned().into(),
472
                clock_skew: None,
473
            });
474
        }
475

            
476
        // Connecting to a relay as a relay without key material will fail. This should never
477
        // happen hence the internal error.
478
        let Some(auth_material) = &self.auth_material else {
479
            return Err(Error::Internal(tor_error::bad_api_usage!(
480
                "Relay initiating a channel without key auth material"
481
            )));
482
        };
483

            
484
        // Any of our identities match the given target, we are connecting to ourselves, refuse.
485
        if auth_material.has_any_relay_id_from(target) {
486
            Err(Error::Proto {
487
                source: tor_proto::Error::ChanProto("Refusing to build channel to ourself".into()),
488
                peer: target.to_owned().into(),
489
                clock_skew: None,
490
            })
491
        } else {
492
            Ok(())
493
        }
494
    }
495

            
496
    /// Validate the given target as in if it is fine to connect to it.
497
    ///
498
    ///There are several rules to follow based on the channel outbound type.
499
1
    fn validate_target<CT>(&self, target: &CT) -> crate::Result<()>
500
1
    where
501
1
        CT: ChanTarget,
502
    {
503
        // Make sure that each address has a valid port.
504
1
        if !target.has_all_nonzero_port() {
505
            return Err(Error::Proto {
506
                source: tor_proto::Error::ChanProto("Target address port is invalid".into()),
507
                peer: target.to_owned().into(),
508
                clock_skew: None,
509
            });
510
1
        }
511

            
512
        // Make sure no target address is ourself including the port. A relay is allowed to connect
513
        // to its IP address but on a different port. We also want to avoid a client bridge to
514
        // connect back to itself.
515
        #[cfg(feature = "relay")]
516
1
        for addr in target.addrs() {
517
1
            if self.my_addrs.contains(&addr) {
518
                return Err(Error::Proto {
519
                    source: tor_proto::Error::ChanProto("Target address is ours".into()),
520
                    peer: target.to_owned().into(),
521
                    clock_skew: None,
522
                });
523
1
            }
524
        }
525

            
526
1
        let chan_type = self.outbound_chan_type();
527
1
        match chan_type {
528
            // This is a client connecting to a relay.
529
1
            ChannelType::ClientInitiator => Ok(()),
530
            // This is a relay connecting to a relay.
531
            #[cfg(feature = "relay")]
532
            ChannelType::RelayInitiator => self.validate_target_as_relay(target),
533
            // ChannelType is non_exhaustive but also we only cover outbound channels.
534
            _ => Err(Error::UnusableTarget(tor_error::bad_api_usage!(
535
                "Channel type can't be used as a target: {chan_type}"
536
            ))),
537
        }
538
1
    }
539

            
540
    /// Build a client channel (always initiator).
541
    ///
542
    /// This spawns the Reactor and return the [`tor_proto::channel::Channel`].
543
1
    async fn build_client_channel<T>(
544
1
        &self,
545
1
        tls: T,
546
1
        peer_addr: MaybeSensitive<PeerAddr>,
547
1
        target: &OwnedChanTarget,
548
1
        peer_tls_cert: &[u8],
549
1
        memquota: ChannelAccount,
550
1
        event_sender: Arc<Mutex<ChanMgrEventSender>>,
551
1
    ) -> crate::Result<Arc<tor_proto::channel::Channel>>
552
1
    where
553
1
        T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
554
1
    {
555
        // Helper to map protocol level error.
556
        //
557
        // We are logging the `target` here as these protocol error happens during the handshake
558
        // and we need to log the identities that are being tried but it will honor safe logging
559
        // for the relay <-> relay case which is not ideal but a tradeoff in complexity.
560
1
        let map_proto = |source, target: &OwnedChanTarget, clock_skew| Error::Proto {
561
            source,
562
            peer: target.to_logged(),
563
            clock_skew,
564
        };
565

            
566
1
        let now = self.runtime.wallclock();
567

            
568
        // Get the client specific channel builder.
569
1
        let mut builder = tor_proto::ClientChannelBuilder::new();
570
1
        builder.set_declared_method(target.chan_method());
571

            
572
1
        let unverified = builder
573
1
            .launch(
574
1
                tls,
575
1
                self.runtime.clone(), /* TODO provide ZST SleepProvider instead */
576
1
                memquota,
577
            )
578
1
            .connect(|| self.runtime.wallclock())
579
1
            .await
580
1
            .map_err(|e| Error::from_proto_no_skew(e, target))?;
581

            
582
1
        let clock_skew = unverified.clock_skew();
583
1
        let (chan, reactor) = unverified
584
1
            .verify(target, peer_tls_cert, Some(now))
585
1
            .map_err(|source| match &source {
586
                tor_proto::Error::HandshakeCertsExpired { .. } => {
587
                    event_sender
588
                        .lock()
589
                        .expect("Lock poisoned")
590
                        .record_handshake_done_with_skewed_clock();
591
                    map_proto(source, target, Some(clock_skew))
592
                }
593
                _ => Error::from_proto_no_skew(source, target),
594
            })?
595
1
            .finish(peer_addr)
596
1
            .await
597
1
            .map_err(|e| map_proto(e, target, Some(clock_skew)))?;
598

            
599
        // Launch a task to run the channel reactor.
600
1
        self.runtime
601
1
            .spawn(async {
602
1
                let _ = reactor.run().await;
603
1
            })
604
1
            .map_err(|e| Error::from_spawn("client channel reactor", e))?;
605
1
        Ok(chan)
606
1
    }
607

            
608
    /// Build a relay initiator channel.
609
    ///
610
    /// This spawns the Reactor and return the [`tor_proto::channel::Channel`].
611
    #[cfg(feature = "relay")]
612
    async fn build_relay_channel<T>(
613
        &self,
614
        tls: T,
615
        peer_addr: MaybeSensitive<PeerAddr>,
616
        target: &OwnedChanTarget,
617
        peer_tls_cert: &[u8],
618
        memquota: ChannelAccount,
619
        event_sender: Arc<Mutex<ChanMgrEventSender>>,
620
    ) -> crate::Result<Arc<tor_proto::channel::Channel>>
621
    where
622
        T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
623
    {
624
        let builder = tor_proto::RelayChannelBuilder::new();
625
        let auth_material = self
626
            .auth_material
627
            .as_ref()
628
            .ok_or_else(|| internal!("Unable to build relay channel without auth material"))?
629
            .clone();
630

            
631
        let create_request_handler = self.create_request_handler.as_ref().ok_or_else(|| {
632
            bad_api_usage!("Can't create a relay channel without a CREATE* request handler")
633
        })?;
634

            
635
        let unverified = builder
636
            .launch(
637
                tls,
638
                self.runtime.clone(), /* TODO provide ZST SleepProvider instead */
639
                auth_material,
640
                self.my_addrs.clone(),
641
                target,
642
                memquota,
643
                Arc::clone(create_request_handler),
644
            )
645
            .connect(|| self.runtime.wallclock())
646
            .await
647
            .map_err(|e| Error::from_proto_no_skew(e, target))?;
648

            
649
        let now = self.runtime.wallclock();
650
        let clock_skew = unverified.clock_skew();
651
        let (chan, reactor) = unverified
652
            .verify(target, peer_tls_cert, Some(now))
653
            .map_err(|source| match &source {
654
                tor_proto::Error::HandshakeCertsExpired { .. } => {
655
                    event_sender
656
                        .lock()
657
                        .expect("Lock poisoned")
658
                        .record_handshake_done_with_skewed_clock();
659
                    Error::Proto {
660
                        source,
661
                        peer: target.to_logged(),
662
                        clock_skew: Some(clock_skew),
663
                    }
664
                }
665
                _ => Error::from_proto_no_skew(source, target),
666
            })?
667
            // Peer address is not sensitive as this is a relay<->relay connection.
668
            .finish(peer_addr.inner())
669
            .await
670
            .map_err(|source| Error::Proto {
671
                source,
672
                peer: target.to_logged(),
673
                clock_skew: Some(clock_skew),
674
            })?;
675

            
676
        // Launch a task to run the channel reactor.
677
        self.runtime
678
            .spawn(async {
679
                let _ = reactor.run().await;
680
            })
681
            .map_err(|e| Error::from_spawn("relay channel reactor", e))?;
682

            
683
        Ok(chan)
684
    }
685
}
686

            
687
impl crate::mgr::AbstractChannel for tor_proto::channel::Channel {
688
    fn is_canonical(&self) -> bool {
689
        self.is_canonical()
690
    }
691
    fn is_canonical_to_peer(&self) -> bool {
692
        self.is_canonical_to_peer()
693
    }
694
1
    fn is_usable(&self) -> bool {
695
1
        !self.is_closing()
696
1
    }
697
1
    fn duration_unused(&self) -> Option<Duration> {
698
1
        self.duration_unused()
699
1
    }
700
54
    fn reparameterize(
701
54
        &self,
702
54
        updates: Arc<ChannelPaddingInstructionsUpdates>,
703
54
    ) -> tor_proto::Result<()> {
704
54
        tor_proto::channel::Channel::reparameterize(self, updates)
705
54
    }
706
    fn reparameterize_kist(&self, kist_params: KistParams) -> tor_proto::Result<()> {
707
        tor_proto::channel::Channel::reparameterize_kist(self, kist_params)
708
    }
709
18
    fn engage_padding_activities(&self) {
710
18
        tor_proto::channel::Channel::engage_padding_activities(self);
711
18
    }
712
}
713

            
714
#[cfg(test)]
715
mod test {
716
    // @@ begin test lint list maintained by maint/add_warning @@
717
    #![allow(clippy::bool_assert_comparison)]
718
    #![allow(clippy::clone_on_copy)]
719
    #![allow(clippy::dbg_macro)]
720
    #![allow(clippy::mixed_attributes_style)]
721
    #![allow(clippy::print_stderr)]
722
    #![allow(clippy::print_stdout)]
723
    #![allow(clippy::single_char_pattern)]
724
    #![allow(clippy::unwrap_used)]
725
    #![allow(clippy::unchecked_time_subtraction)]
726
    #![allow(clippy::useless_vec)]
727
    #![allow(clippy::needless_pass_by_value)]
728
    #![allow(clippy::string_slice)] // See arti#2571
729
    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
730
    use super::*;
731
    use crate::{
732
        Result,
733
        mgr::{AbstractChannel, AbstractChannelFactory},
734
    };
735
    use futures::StreamExt as _;
736
    use std::net::SocketAddr;
737
    use std::time::{Duration, SystemTime};
738
    use tor_linkspec::{ChannelMethod, HasRelayIds, RelayIdType};
739
    use tor_llcrypto::pk::ed25519::Ed25519Identity;
740
    use tor_llcrypto::pk::rsa::RsaIdentity;
741
    use tor_proto::channel::Channel;
742
    use tor_proto::memquota::{ChannelAccount, SpecificAccount as _};
743
    use tor_rtcompat::{NetStreamListener, test_with_one_runtime};
744
    use tor_rtmock::{io::LocalStream, net::MockNetwork};
745

            
746
    #[allow(deprecated)] // TODO #1885
747
    use tor_rtmock::MockSleepRuntime;
748

            
749
    // Make sure that the builder can build a real channel.  To test
750
    // this out, we set up a listener that pretends to have the right
751
    // IP, fake the current time, and use a canned response from
752
    // [`testing::msgs`] crate.
753
    #[test]
754
    fn build_ok() -> Result<()> {
755
        use crate::testing::msgs;
756
        let orport: SocketAddr = msgs::ADDR.parse().unwrap();
757
        let ed: Ed25519Identity = msgs::ED_ID.into();
758
        let rsa: RsaIdentity = msgs::RSA_ID.into();
759
        let client_addr = "192.0.2.17".parse().unwrap();
760
        let tls_cert = msgs::X509_CERT.into();
761
        let target = OwnedChanTarget::builder()
762
            .addrs(vec![orport])
763
            .method(ChannelMethod::Direct(vec![orport]))
764
            .ed_identity(ed)
765
            .rsa_identity(rsa)
766
            .build()
767
            .unwrap();
768
        let now = SystemTime::UNIX_EPOCH + Duration::new(msgs::NOW, 0);
769

            
770
        test_with_one_runtime!(|rt| async move {
771
            // Stub out the internet so that this connection can work.
772
            let network = MockNetwork::new();
773

            
774
            // Set up a client runtime with a given IP
775
            let client_rt = network
776
                .builder()
777
                .add_address(client_addr)
778
                .runtime(rt.clone());
779
            // Mock the current time too
780
            #[allow(deprecated)] // TODO #1885
781
            let client_rt = MockSleepRuntime::new(client_rt);
782

            
783
            // Set up a relay runtime with a different IP
784
            let relay_rt = network
785
                .builder()
786
                .add_address(orport.ip())
787
                .runtime(rt.clone());
788

            
789
            // open a fake TLS listener and be ready to handle a request.
790
            let lis = relay_rt.mock_net().listen_tls(&orport, tls_cert).unwrap();
791

            
792
            // Tell the client to believe in a different timestamp.
793
            client_rt.jump_to(now);
794

            
795
            // Create the channel builder that we want to test.
796
            let transport = crate::transport::DefaultTransport::new(client_rt.clone(), None);
797
            let builder = ChanBuilder::new_client(client_rt, transport);
798

            
799
            let (r1, r2): (Result<Arc<Channel>>, Result<LocalStream>) = futures::join!(
800
                async {
801
                    // client-side: build a channel!
802
                    builder
803
                        .build_channel(
804
                            &target,
805
                            BootstrapReporter::fake(),
806
                            ChannelAccount::new_noop(),
807
                        )
808
                        .await
809
                },
810
                async {
811
                    // relay-side: accept the channel
812
                    // (and pretend to know what we're doing).
813
                    let (mut con, addr) = lis
814
                        .incoming()
815
                        .next()
816
                        .await
817
                        .expect("Closed?")
818
                        .expect("accept failed");
819
                    assert_eq!(client_addr, addr.ip());
820
                    crate::testing::answer_channel_req(&mut con)
821
                        .await
822
                        .expect("answer failed");
823
                    Ok(con)
824
                }
825
            );
826

            
827
            let chan = r1.unwrap();
828
            assert_eq!(chan.identity(RelayIdType::Ed25519), Some((&ed).into()));
829
            assert!(chan.is_usable());
830
            // In theory, time could pass here, so we can't just use
831
            // "assert_eq!(dur_unused, dur_unused2)".
832
            let dur_unused = Channel::duration_unused(&chan);
833
            let dur_unused_2 = AbstractChannel::duration_unused(chan.as_ref());
834
            let dur_unused_3 = Channel::duration_unused(&chan);
835
            assert!(dur_unused.unwrap() <= dur_unused_2.unwrap());
836
            assert!(dur_unused_2.unwrap() <= dur_unused_3.unwrap());
837

            
838
            r2.unwrap();
839
            Ok(())
840
        })
841
    }
842

            
843
    // TODO: Write tests for timeout logic, once there is smarter logic.
844
}