mail: use base_uri from RequestOrigin

This will cause outgoing emails to contain onion addresses for backlinks
to the server, if the request comes via onion service.
This commit is contained in:
Vincent Breitmoser 2019-06-23 01:39:36 +02:00
parent 36a016c15b
commit 65df904cd0
No known key found for this signature in database
GPG Key ID: 7BD18320DEADFA11
6 changed files with 60 additions and 14 deletions

View File

@ -31,7 +31,6 @@ mod context {
pub struct Service {
from: Mailbox,
base_uri: String,
domain: String,
templates: Handlebars,
transport: Transport,
@ -65,21 +64,20 @@ impl Service {
?.to_string();
Ok(Self {
from: from.parse().unwrap(),
base_uri: base_uri,
domain: domain,
templates: templates,
transport: transport,
})
}
pub fn send_verification(&self, tpk_name: String, userid: &Email,
pub fn send_verification(&self, base_uri: &str, tpk_name: String, userid: &Email,
token: &str)
-> Result<()> {
let ctx = context::Verification {
primary_fp: tpk_name,
uri: format!("{}/verify/{}", self.base_uri, token),
uri: format!("{}/verify/{}", base_uri, token),
userid: userid.to_string(),
base_uri: self.base_uri.clone(),
base_uri: base_uri.to_owned(),
domain: self.domain.clone(),
};
@ -91,12 +89,12 @@ impl Service {
)
}
pub fn send_manage_token(&self, tpk_name: String, recipient: &Email,
pub fn send_manage_token(&self, base_uri: &str, tpk_name: String, recipient: &Email,
link_path: &str) -> Result<()> {
let ctx = context::Manage {
primary_fp: tpk_name,
uri: format!("{}{}", self.base_uri, link_path),
base_uri: self.base_uri.clone(),
uri: format!("{}{}", base_uri, link_path),
base_uri: base_uri.to_owned(),
domain: self.domain.clone(),
};

View File

@ -112,6 +112,7 @@ pub fn vks_manage_key(
#[post("/manage", data="<request>")]
pub fn vks_manage_post(
db: State<KeyDatabase>,
request_origin: RequestOrigin,
mail_service: rocket::State<mail::Service>,
rate_limiter: rocket::State<RateLimiter>,
request: Form<forms::ManageRequest>,
@ -153,7 +154,8 @@ pub fn vks_manage_post(
let token = token_service.create(&StatelessVerifyToken { fpr });
let link_path = uri!(vks_manage_key: token).to_string();
if let Err(e) = mail_service.send_manage_token(fpr_text, &email, &link_path) {
let base_uri = request_origin.get_base_uri();
if let Err(e) = mail_service.send_manage_token(base_uri, fpr_text, &email, &link_path) {
return MyResponse::ise(e);
}

View File

@ -796,6 +796,44 @@ pub mod tests {
assert_eq!(response.status(), Status::BadRequest);
}
#[test]
fn upload_verify_onion() {
let (tmpdir, client) = client().unwrap();
let filemail_into = tmpdir.path().join("filemail");
// Generate a key and upload it.
let (tpk, _) = TPKBuilder::autocrypt(
None, Some("foo@invalid.example.com"))
.generate().unwrap();
let mut tpk_serialized = Vec::new();
tpk.serialize(&mut tpk_serialized).unwrap();
let token = vks_publish_submit_get_token(&client, &tpk_serialized);
// Check the verification link
let encoded = ::url::form_urlencoded::Serializer::new(String::new())
.append_pair("token", &token)
.append_pair("address", "foo@invalid.example.com")
.finish();
let response = client.post("/upload/request-verify")
.header(ContentType::Form)
.header(Header::new("X-Is-Onion", "true"))
.body(encoded.as_bytes())
.dispatch();
assert_eq!(response.status(), Status::Ok);
// Now check for the verification mail.
let pattern = format!("{}(/verify/[^ \t\n]*)", BASE_URI_ONION);
let confirm_uri = pop_mail_capture_pattern(&filemail_into, &pattern);
let response = client.get(&confirm_uri).dispatch();
assert_eq!(response.status(), Status::Ok);
assert_consistency(client.rocket());
}
#[test]
fn upload_curl_shortcut() {
let (_tmpdir, client) = client().unwrap();

View File

@ -5,6 +5,7 @@ use database::types::{Fingerprint,Email};
use mail;
use tokens::{self, StatelessSerializable};
use rate_limiter::RateLimiter;
use web::RequestOrigin;
use sequoia_openpgp::TPK;
@ -167,6 +168,7 @@ fn process_key_single(
pub fn request_verify(
db: rocket::State<KeyDatabase>,
request_origin: RequestOrigin,
token_stateful: rocket::State<StatefulTokens>,
token_stateless: rocket::State<tokens::Service>,
mail_service: rocket::State<mail::Service>,
@ -197,7 +199,7 @@ pub fn request_verify(
for email in emails_requested {
let rate_limit_ok = rate_limiter.action_perform(format!("verify-{}", &email));
if rate_limit_ok {
if send_verify_email(&mail_service, &token_stateful, &verify_state.fpr, &email).is_err() {
if send_verify_email(&request_origin, &mail_service, &token_stateful, &verify_state.fpr, &email).is_err() {
return UploadResponse::err(&format!("error sending email to {}", &email));
}
}
@ -217,6 +219,7 @@ fn check_tpk_state(
}
fn send_verify_email(
request_origin: &RequestOrigin,
mail_service: &mail::Service,
token_stateful: &StatefulTokens,
fpr: &Fingerprint,
@ -227,6 +230,7 @@ fn send_verify_email(
let token_verify = token_stateful.new_token("verify", token_str.as_bytes())?;
mail_service.send_verification(
request_origin.get_base_uri(),
fpr.to_string(),
&email,
&token_verify,

View File

@ -96,6 +96,7 @@ pub fn upload_fallback(
#[post("/vks/v1/request-verify", format = "json", data="<data>")]
pub fn request_verify_json(
db: rocket::State<KeyDatabase>,
request_origin: RequestOrigin,
token_stateful: rocket::State<StatefulTokens>,
token_stateless: rocket::State<tokens::Service>,
mail_service: rocket::State<mail::Service>,
@ -105,7 +106,7 @@ pub fn request_verify_json(
let data = json_or_error(data)?;
let json::VerifyRequest { token, addresses } = data.into_inner();
let result = vks::request_verify(
db, token_stateful, token_stateless, mail_service,
db, request_origin, token_stateful, token_stateless, mail_service,
rate_limiter, token, addresses);
upload_ok_json(result)
}

View File

@ -290,6 +290,7 @@ pub fn quick_upload(
#[get("/upload/<token>", rank = 2)]
pub fn quick_upload_proceed(
db: rocket::State<KeyDatabase>,
request_origin: RequestOrigin,
token_stateful: rocket::State<StatefulTokens>,
token_stateless: rocket::State<tokens::Service>,
mail_service: rocket::State<mail::Service>,
@ -297,7 +298,7 @@ pub fn quick_upload_proceed(
token: String,
) -> MyResponse {
let result = vks::request_verify(
db, token_stateful, token_stateless, mail_service,
db, request_origin, token_stateful, token_stateless, mail_service,
rate_limiter, token, vec!());
MyResponse::upload_response(result)
}
@ -388,6 +389,7 @@ fn process_multipart(
#[post("/upload/request-verify", format = "application/x-www-form-urlencoded", data="<request>")]
pub fn request_verify_form(
db: rocket::State<KeyDatabase>,
request_origin: RequestOrigin,
token_stateful: rocket::State<StatefulTokens>,
token_stateless: rocket::State<tokens::Service>,
mail_service: rocket::State<mail::Service>,
@ -396,7 +398,7 @@ pub fn request_verify_form(
) -> MyResponse {
let forms::VerifyRequest { token, address } = request.into_inner();
let result = vks::request_verify(
db, token_stateful, token_stateless, mail_service,
db, request_origin, token_stateful, token_stateless, mail_service,
rate_limiter, token, vec!(address));
MyResponse::upload_response(result)
}
@ -404,6 +406,7 @@ pub fn request_verify_form(
#[post("/upload/request-verify", format = "multipart/form-data", data="<request>")]
pub fn request_verify_form_data(
db: rocket::State<KeyDatabase>,
request_origin: RequestOrigin,
token_stateful: rocket::State<StatefulTokens>,
token_stateless: rocket::State<tokens::Service>,
mail_service: rocket::State<mail::Service>,
@ -412,7 +415,7 @@ pub fn request_verify_form_data(
) -> MyResponse {
let forms::VerifyRequest { token, address } = request.into_inner();
let result = vks::request_verify(
db, token_stateful, token_stateless, mail_service,
db, request_origin, token_stateful, token_stateless, mail_service,
rate_limiter, token, vec!(address));
MyResponse::upload_response(result)
}