Skip to content

Commit f6bf070

Browse files
committed
refactor: [torrust#1275] move announce authentication in http tracker to core
1 parent 467d50a commit f6bf070

File tree

7 files changed

+53
-37
lines changed

7 files changed

+53
-37
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/servers/http/v1/extractors/authentication_key.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,6 @@ fn custom_error(rejection: &PathRejection) -> responses::error::Error {
117117
location: Location::caller(),
118118
})
119119
}
120-
axum::extract::rejection::PathRejection::MissingPathParams(_) => {
121-
responses::error::Error::from(auth::Error::MissingAuthKey {
122-
location: Location::caller(),
123-
})
124-
}
125120
_ => responses::error::Error::from(auth::Error::CannotExtractKeyParam {
126121
location: Location::caller(),
127122
}),
@@ -148,6 +143,9 @@ mod tests {
148143

149144
let response = parse_key(invalid_key).unwrap_err();
150145

151-
assert_error_response(&response, "Authentication error: Invalid format for authentication key param");
146+
assert_error_response(
147+
&response,
148+
"Tracker authentication error: Invalid format for authentication key param",
149+
);
152150
}
153151
}

src/servers/http/v1/handlers/announce.rs

+6-25
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
//!
66
//! The handlers perform the authentication and authorization of the request,
77
//! and resolve the client IP address.
8-
use std::panic::Location;
98
use std::sync::Arc;
109

1110
use aquatic_udp_protocol::AnnounceEvent;
@@ -22,12 +21,10 @@ use hyper::StatusCode;
2221
use torrust_tracker_configuration::Core;
2322
use torrust_tracker_primitives::core::AnnounceData;
2423

25-
use super::common::auth::map_auth_error_to_error_response;
2624
use crate::packages::http_tracker_core;
2725
use crate::servers::http::v1::extractors::announce_request::ExtractRequest;
2826
use crate::servers::http::v1::extractors::authentication_key::Extract as ExtractKey;
2927
use crate::servers::http::v1::extractors::client_ip_sources::Extract as ExtractClientIpSources;
30-
use crate::servers::http::v1::handlers::common::auth;
3128

3229
/// It handles the `announce` request when the HTTP tracker does not require
3330
/// authentication (no PATH `key` parameter required).
@@ -134,23 +131,6 @@ async fn handle_announce(
134131
client_ip_sources: &ClientIpSources,
135132
maybe_key: Option<Key>,
136133
) -> Result<AnnounceData, responses::error::Error> {
137-
// todo: move authentication inside `http_tracker_core::services::announce::handle_announce`
138-
139-
// Authentication
140-
if core_config.private {
141-
match maybe_key {
142-
Some(key) => match authentication_service.authenticate(&key).await {
143-
Ok(()) => (),
144-
Err(error) => return Err(map_auth_error_to_error_response(&error)),
145-
},
146-
None => {
147-
return Err(responses::error::Error::from(auth::Error::MissingAuthKey {
148-
location: Location::caller(),
149-
}))
150-
}
151-
}
152-
}
153-
154134
http_tracker_core::services::announce::handle_announce(
155135
&core_config.clone(),
156136
&announce_handler.clone(),
@@ -159,6 +139,7 @@ async fn handle_announce(
159139
&opt_http_stats_event_sender.clone(),
160140
announce_request,
161141
client_ip_sources,
142+
maybe_key,
162143
)
163144
.await
164145
}
@@ -339,10 +320,7 @@ mod tests {
339320
.await
340321
.unwrap_err();
341322

342-
assert_error_response(
343-
&response,
344-
"Authentication error: Missing authentication key param for private tracker",
345-
);
323+
assert_error_response(&response, "Tracker authentication error: Missing authentication key");
346324
}
347325

348326
#[tokio::test]
@@ -366,7 +344,10 @@ mod tests {
366344
.await
367345
.unwrap_err();
368346

369-
assert_error_response(&response, "Authentication error: Failed to read key");
347+
assert_error_response(
348+
&response,
349+
"Tracker authentication error: Failed to read key: YZSl4lMZupRuOpSRC3krIKR5BPB14nrJ",
350+
);
370351
}
371352
}
372353

src/servers/http/v1/handlers/common/auth.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,17 @@ use thiserror::Error;
1414
/// from the URL path.
1515
#[derive(Debug, Error)]
1616
pub enum Error {
17-
#[error("Missing authentication key param for private tracker. Error in {location}")]
18-
MissingAuthKey { location: &'static Location<'static> },
1917
#[error("Invalid format for authentication key param. Error in {location}")]
2018
InvalidKeyFormat { location: &'static Location<'static> },
19+
2120
#[error("Cannot extract authentication key param from URL path. Error in {location}")]
2221
CannotExtractKeyParam { location: &'static Location<'static> },
2322
}
2423

2524
impl From<Error> for responses::error::Error {
2625
fn from(err: Error) -> Self {
2726
responses::error::Error {
28-
failure_reason: format!("Authentication error: {err}"),
27+
failure_reason: format!("Tracker authentication error: {err}"),
2928
}
3029
}
3130
}
@@ -36,6 +35,6 @@ pub fn map_auth_error_to_error_response(err: &authentication::Error) -> response
3635
// impl From<authentication::Error> for responses::error::Error
3736
// Consider moving the trait implementation to the http-protocol package.
3837
responses::error::Error {
39-
failure_reason: format!("Authentication error: {err}"),
38+
failure_reason: format!("Tracker authentication error: {err}"),
4039
}
4140
}

tests/servers/http/asserts.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -141,5 +141,9 @@ pub async fn assert_cannot_parse_query_params_error_response(response: Response,
141141
pub async fn assert_authentication_error_response(response: Response) {
142142
assert_eq!(response.status(), 200);
143143

144-
assert_bencoded_error(&response.text().await.unwrap(), "Authentication error", Location::caller());
144+
assert_bencoded_error(
145+
&response.text().await.unwrap(),
146+
"Tracker authentication error",
147+
Location::caller(),
148+
);
145149
}

0 commit comments

Comments
 (0)