Skip to content

Commit 246c57c

Browse files
committed
Merge #1277: Overhaul core Tracker: move authentication to http-tracker-core and udp-tracker-core
fdc2543 refactor: extract UDP connect service (Jose Celano) 4618f70 refactor: exatract response builders for UDP handlers (Jose Celano) 91525af refactor: [#1275] move authentication in udp tracker to core (Jose Celano) 4fd79b7 refactor: [#1275] move conenction cookie to udp_tracker_core package (Jose Celano) 694621b refactor: [#1275] extract ConnectionCookieError enum (Jose Celano) ecc093f refactor: [#1275] move scrape authentication in http tracker to core (Jose Celano) f6bf070 refactor: [#1275] move announce authentication in http tracker to core (Jose Celano) Pull request description: Overhaul core Tracker: move authentication to `http-tracker-core` and `udp-tracker-core`. HTTP Tracker: - [x] Announce - [x] Scrape UDP Tracker: - [x] Announce - [x] Scrape ACKs for top commit: josecelano: ACK fdc2543 Tree-SHA512: aad933f02307f6abb0a0afc9629f4b7282b2e57d2842f637f92310e28e3a82a53ffecc50ad46ba1f63b1660279c69e2b6af1b664218ab93f3cd7dce0e40ca339
2 parents 467d50a + fdc2543 commit 246c57c

File tree

22 files changed

+513
-214
lines changed

22 files changed

+513
-214
lines changed

packages/http-protocol/src/v1/responses/error.rs

+8
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ impl From<bittorrent_tracker_core::error::WhitelistError> for Error {
7979
}
8080
}
8181

82+
impl From<bittorrent_tracker_core::authentication::Error> for Error {
83+
fn from(err: bittorrent_tracker_core::authentication::Error) -> Self {
84+
Error {
85+
failure_reason: format!("Tracker authentication error: {err}"),
86+
}
87+
}
88+
}
89+
8290
#[cfg(test)]
8391
mod tests {
8492

packages/tracker-core/src/authentication/key/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,10 @@ pub enum Error {
185185
/// Indicates that the key has expired.
186186
#[error("Key has expired, {location}")]
187187
KeyExpired { location: &'static Location<'static> },
188+
189+
/// Indicates that the required key for authentication was not provided.
190+
#[error("Missing authentication key, {location}")]
191+
MissingAuthKey { location: &'static Location<'static> },
188192
}
189193

190194
impl From<r2d2_sqlite::rusqlite::Error> for Error {

src/packages/http_tracker_core/services/announce.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88
//! It also sends an [`http_tracker_core::statistics::event::Event`]
99
//! because events are specific for the HTTP tracker.
1010
use std::net::IpAddr;
11+
use std::panic::Location;
1112
use std::sync::Arc;
1213

1314
use bittorrent_http_protocol::v1::requests::announce::{peer_from_request, Announce};
1415
use bittorrent_http_protocol::v1::responses;
1516
use bittorrent_http_protocol::v1::services::peer_ip_resolver::{self, ClientIpSources};
1617
use bittorrent_tracker_core::announce_handler::{AnnounceHandler, PeersWanted};
1718
use bittorrent_tracker_core::authentication::service::AuthenticationService;
19+
use bittorrent_tracker_core::authentication::{self, Key};
1820
use bittorrent_tracker_core::whitelist;
1921
use torrust_tracker_configuration::Core;
2022
use torrust_tracker_primitives::core::AnnounceData;
@@ -42,12 +44,28 @@ use crate::packages::http_tracker_core;
4244
pub async fn handle_announce(
4345
core_config: &Arc<Core>,
4446
announce_handler: &Arc<AnnounceHandler>,
45-
_authentication_service: &Arc<AuthenticationService>,
47+
authentication_service: &Arc<AuthenticationService>,
4648
whitelist_authorization: &Arc<whitelist::authorization::WhitelistAuthorization>,
4749
opt_http_stats_event_sender: &Arc<Option<Box<dyn http_tracker_core::statistics::event::sender::Sender>>>,
4850
announce_request: &Announce,
4951
client_ip_sources: &ClientIpSources,
52+
maybe_key: Option<Key>,
5053
) -> Result<AnnounceData, responses::error::Error> {
54+
// Authentication
55+
if core_config.private {
56+
match maybe_key {
57+
Some(key) => match authentication_service.authenticate(&key).await {
58+
Ok(()) => (),
59+
Err(error) => return Err(error.into()),
60+
},
61+
None => {
62+
return Err(responses::error::Error::from(authentication::key::Error::MissingAuthKey {
63+
location: Location::caller(),
64+
}))
65+
}
66+
}
67+
}
68+
5169
// Authorization
5270
match whitelist_authorization.authorize(&announce_request.info_hash).await {
5371
Ok(()) => (),
@@ -257,6 +275,7 @@ mod tests {
257275
&core_http_tracker_services.http_stats_event_sender,
258276
&announce_request,
259277
&client_ip_sources,
278+
None,
260279
)
261280
.await
262281
.unwrap();
@@ -300,6 +319,7 @@ mod tests {
300319
&core_http_tracker_services.http_stats_event_sender,
301320
&announce_request,
302321
&client_ip_sources,
322+
None,
303323
)
304324
.await
305325
.unwrap();
@@ -351,6 +371,7 @@ mod tests {
351371
&core_http_tracker_services.http_stats_event_sender,
352372
&announce_request,
353373
&client_ip_sources,
374+
None,
354375
)
355376
.await
356377
.unwrap();
@@ -383,6 +404,7 @@ mod tests {
383404
&core_http_tracker_services.http_stats_event_sender,
384405
&announce_request,
385406
&client_ip_sources,
407+
None,
386408
)
387409
.await
388410
.unwrap();

src/packages/http_tracker_core/services/scrape.rs

+57-31
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use bittorrent_http_protocol::v1::requests::scrape::Scrape;
1414
use bittorrent_http_protocol::v1::responses;
1515
use bittorrent_http_protocol::v1::services::peer_ip_resolver::{self, ClientIpSources};
1616
use bittorrent_primitives::info_hash::InfoHash;
17+
use bittorrent_tracker_core::authentication::service::AuthenticationService;
18+
use bittorrent_tracker_core::authentication::Key;
1719
use bittorrent_tracker_core::scrape_handler::ScrapeHandler;
1820
use torrust_tracker_configuration::Core;
1921
use torrust_tracker_primitives::core::ScrapeData;
@@ -40,12 +42,26 @@ use crate::packages::http_tracker_core;
4042
pub async fn handle_scrape(
4143
core_config: &Arc<Core>,
4244
scrape_handler: &Arc<ScrapeHandler>,
45+
authentication_service: &Arc<AuthenticationService>,
4346
opt_http_stats_event_sender: &Arc<Option<Box<dyn http_tracker_core::statistics::event::sender::Sender>>>,
4447
scrape_request: &Scrape,
4548
client_ip_sources: &ClientIpSources,
46-
return_fake_scrape_data: bool,
49+
maybe_key: Option<Key>,
4750
) -> Result<ScrapeData, responses::error::Error> {
48-
// Authorization for scrape requests is handled at the `bittorrent-_racker_core`
51+
// Authentication
52+
let return_fake_scrape_data = if core_config.private {
53+
match maybe_key {
54+
Some(key) => match authentication_service.authenticate(&key).await {
55+
Ok(()) => false,
56+
Err(_error) => true,
57+
},
58+
None => true,
59+
}
60+
} else {
61+
false
62+
};
63+
64+
// Authorization for scrape requests is handled at the `bittorrent_tracker_core`
4965
// level for each torrent.
5066

5167
let peer_ip = match peer_ip_resolver::invoke(core_config.net.on_reverse_proxy, client_ip_sources) {
@@ -111,6 +127,8 @@ mod tests {
111127
use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes, PeerId};
112128
use bittorrent_primitives::info_hash::InfoHash;
113129
use bittorrent_tracker_core::announce_handler::AnnounceHandler;
130+
use bittorrent_tracker_core::authentication::key::repository::in_memory::InMemoryKeyRepository;
131+
use bittorrent_tracker_core::authentication::service::AuthenticationService;
114132
use bittorrent_tracker_core::databases::setup::initialize_database;
115133
use bittorrent_tracker_core::scrape_handler::ScrapeHandler;
116134
use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository;
@@ -127,27 +145,39 @@ mod tests {
127145
use crate::packages::http_tracker_core;
128146
use crate::servers::http::test_helpers::tests::sample_info_hash;
129147

130-
fn initialize_announce_and_scrape_handlers_for_public_tracker() -> (Arc<AnnounceHandler>, Arc<ScrapeHandler>) {
131-
initialize_announce_and_scrape_handlers_with_configuration(&configuration::ephemeral_public())
148+
struct Container {
149+
announce_handler: Arc<AnnounceHandler>,
150+
scrape_handler: Arc<ScrapeHandler>,
151+
authentication_service: Arc<AuthenticationService>,
132152
}
133153

134-
fn initialize_announce_and_scrape_handlers_with_configuration(
135-
config: &Configuration,
136-
) -> (Arc<AnnounceHandler>, Arc<ScrapeHandler>) {
154+
fn initialize_services_for_public_tracker() -> Container {
155+
initialize_services_with_configuration(&configuration::ephemeral_public())
156+
}
157+
158+
fn initialize_services_with_configuration(config: &Configuration) -> Container {
137159
let database = initialize_database(&config.core);
138160
let in_memory_whitelist = Arc::new(InMemoryWhitelist::default());
139161
let whitelist_authorization = Arc::new(WhitelistAuthorization::new(&config.core, &in_memory_whitelist.clone()));
140162
let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default());
141163
let db_torrent_repository = Arc::new(DatabasePersistentTorrentRepository::new(&database));
164+
let in_memory_key_repository = Arc::new(InMemoryKeyRepository::default());
165+
let authentication_service = Arc::new(AuthenticationService::new(&config.core, &in_memory_key_repository));
166+
142167
let announce_handler = Arc::new(AnnounceHandler::new(
143168
&config.core,
144169
&whitelist_authorization,
145170
&in_memory_torrent_repository,
146171
&db_torrent_repository,
147172
));
173+
148174
let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository));
149175

150-
(announce_handler, scrape_handler)
176+
Container {
177+
announce_handler,
178+
scrape_handler,
179+
authentication_service,
180+
}
151181
}
152182

153183
fn sample_info_hashes() -> Vec<InfoHash> {
@@ -166,14 +196,6 @@ mod tests {
166196
}
167197
}
168198

169-
fn initialize_scrape_handler_with_config(config: &Configuration) -> Arc<ScrapeHandler> {
170-
let in_memory_whitelist = Arc::new(InMemoryWhitelist::default());
171-
let whitelist_authorization = Arc::new(WhitelistAuthorization::new(&config.core, &in_memory_whitelist.clone()));
172-
let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default());
173-
174-
Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository))
175-
}
176-
177199
mock! {
178200
HttpStatsEventSender {}
179201
impl http_tracker_core::statistics::event::sender::Sender for HttpStatsEventSender {
@@ -197,8 +219,7 @@ mod tests {
197219

198220
use crate::packages::http_tracker_core::services::scrape::handle_scrape;
199221
use crate::packages::http_tracker_core::services::scrape::tests::{
200-
initialize_announce_and_scrape_handlers_with_configuration, initialize_scrape_handler_with_config,
201-
sample_info_hashes, sample_peer, MockHttpStatsEventSender,
222+
initialize_services_with_configuration, sample_info_hashes, sample_peer, MockHttpStatsEventSender,
202223
};
203224
use crate::packages::{self, http_tracker_core};
204225
use crate::servers::http::test_helpers::tests::sample_info_hash;
@@ -212,15 +233,16 @@ mod tests {
212233
packages::http_tracker_core::statistics::setup::factory(false);
213234
let http_stats_event_sender = Arc::new(http_stats_event_sender);
214235

215-
let (announce_handler, scrape_handler) = initialize_announce_and_scrape_handlers_with_configuration(&configuration);
236+
let container = initialize_services_with_configuration(&configuration);
216237

217238
let info_hash = sample_info_hash();
218239
let info_hashes = vec![info_hash];
219240

220241
// Announce a new peer to force scrape data to contain non zeroed data
221242
let mut peer = sample_peer();
222243
let original_peer_ip = peer.ip();
223-
announce_handler
244+
container
245+
.announce_handler
224246
.announce(&info_hash, &mut peer, &original_peer_ip, &PeersWanted::AsManyAsPossible)
225247
.await
226248
.unwrap();
@@ -236,11 +258,12 @@ mod tests {
236258

237259
let scrape_data = handle_scrape(
238260
&core_config,
239-
&scrape_handler,
261+
&container.scrape_handler,
262+
&container.authentication_service,
240263
&http_stats_event_sender,
241264
&scrape_request,
242265
&client_ip_sources,
243-
false,
266+
None,
244267
)
245268
.await
246269
.unwrap();
@@ -271,7 +294,7 @@ mod tests {
271294
let http_stats_event_sender: Arc<Option<Box<dyn http_tracker_core::statistics::event::sender::Sender>>> =
272295
Arc::new(Some(Box::new(http_stats_event_sender_mock)));
273296

274-
let scrape_handler = initialize_scrape_handler_with_config(&config);
297+
let container = initialize_services_with_configuration(&config);
275298

276299
let peer_ip = IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1));
277300

@@ -286,11 +309,12 @@ mod tests {
286309

287310
handle_scrape(
288311
&Arc::new(config.core),
289-
&scrape_handler,
312+
&container.scrape_handler,
313+
&container.authentication_service,
290314
&http_stats_event_sender,
291315
&scrape_request,
292316
&client_ip_sources,
293-
false,
317+
None,
294318
)
295319
.await
296320
.unwrap();
@@ -309,7 +333,7 @@ mod tests {
309333
let http_stats_event_sender: Arc<Option<Box<dyn http_tracker_core::statistics::event::sender::Sender>>> =
310334
Arc::new(Some(Box::new(http_stats_event_sender_mock)));
311335

312-
let scrape_handler = initialize_scrape_handler_with_config(&config);
336+
let container = initialize_services_with_configuration(&config);
313337

314338
let peer_ip = IpAddr::V6(Ipv6Addr::new(0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969));
315339

@@ -324,11 +348,12 @@ mod tests {
324348

325349
handle_scrape(
326350
&Arc::new(config.core),
327-
&scrape_handler,
351+
&container.scrape_handler,
352+
&container.authentication_service,
328353
&http_stats_event_sender,
329354
&scrape_request,
330355
&client_ip_sources,
331-
false,
356+
None,
332357
)
333358
.await
334359
.unwrap();
@@ -347,7 +372,7 @@ mod tests {
347372

348373
use crate::packages::http_tracker_core::services::scrape::fake;
349374
use crate::packages::http_tracker_core::services::scrape::tests::{
350-
initialize_announce_and_scrape_handlers_for_public_tracker, sample_info_hashes, sample_peer, MockHttpStatsEventSender,
375+
initialize_services_for_public_tracker, sample_info_hashes, sample_peer, MockHttpStatsEventSender,
351376
};
352377
use crate::packages::{self, http_tracker_core};
353378
use crate::servers::http::test_helpers::tests::sample_info_hash;
@@ -358,15 +383,16 @@ mod tests {
358383
packages::http_tracker_core::statistics::setup::factory(false);
359384
let http_stats_event_sender = Arc::new(http_stats_event_sender);
360385

361-
let (announce_handler, _scrape_handler) = initialize_announce_and_scrape_handlers_for_public_tracker();
386+
let container = initialize_services_for_public_tracker();
362387

363388
let info_hash = sample_info_hash();
364389
let info_hashes = vec![info_hash];
365390

366391
// Announce a new peer to force scrape data to contain not zeroed data
367392
let mut peer = sample_peer();
368393
let original_peer_ip = peer.ip();
369-
announce_handler
394+
container
395+
.announce_handler
370396
.announce(&info_hash, &mut peer, &original_peer_ip, &PeersWanted::AsManyAsPossible)
371397
.await
372398
.unwrap();

0 commit comments

Comments
 (0)