add gpg/curl shortcut

This commit is contained in:
Vincent Breitmoser 2019-06-05 14:33:02 +02:00
parent 6b916f6556
commit f8b6fab897
No known key found for this signature in database
GPG Key ID: 7BD18320DEADFA11
5 changed files with 153 additions and 22 deletions

View File

@ -70,6 +70,7 @@ code.snippet {
}
blockquote {
font-family: monospace;
background: #f9f9f9;
border-left: 10px solid #ccc;
margin: 1.5em 10px;

1
dist/templates/500-plain.html.hbs vendored Normal file
View File

@ -0,0 +1 @@
Error: {{internal_error}}

View File

@ -31,26 +31,48 @@
</p>
<h2 style="margin-left: 3%;"><img src="/assets/img/gnupg.svg" style="display: inline; height: 2em; vertical-align: -30%; padding-right: 10px;" /> GnuPG</h2>
<p>
To configure GnuPG to use <span class="brand">keys.openpgp.org</span>
as keyserver, add this line to your <tt>gpg.conf</tt> file:
<blockquote>
keyserver hkps://keys.openpgp.org
</blockquote>
Alternatively, commands can be run with an extra parameter
<tt>--keyserver keys.openpgp.org</tt>.
<ul>
<li>
To locate the key of a user, by email address:
<blockquote>gpg --locate-keys user@example.net</blockquote>
</li>
<li>To refresh all your keys (e.g. new revocation certificates and subkeys):
<blockquote>gpg --refresh</blockquote>
</li>
</ul>
To configure GnuPG to use <span class="brand">keys.openpgp.org</span>
as keyserver, add this line to your <tt>gpg.conf</tt> file:
<blockquote>
keyserver hkps://keys.openpgp.org
</blockquote>
<h3>Retrieving keys</h3>
<ul>
<li>
To locate the key of a user, by email address:
<blockquote>gpg --locate-keys user@example.net</blockquote>
</li>
<li>To refresh all your keys (e.g. new revocation certificates and subkeys):
<blockquote>gpg --refresh</blockquote>
</li>
</ul>
<h3>Uploading your key</h3>
<p>
Keys can be uploaded with GnuPG's <tt>--send-keys</tt> command, but
identity information can't be verified that way to make the key
searchable by e-mail address (<a href="/about">what's that?</a>).
</p>
<ul>
<li>
You can try this shortcut for uploading your key, which outputs
a direct link to the verification page:
<blockquote>
gpg --export your_address@example.net | curl -T - {{base_uri}}
</blockquote>
</li>
<li>
Alternatively, you can export them to a file and enter that into the
<a href="/upload" target="_blank">upload</a> page:
<blockquote>
gpg --export your_address@example.net &gt; my_key.pub
</blockquote>
</li>
</ul>
<h2 style="margin-left: 3%;">Others</h2>
<p>

View File

@ -148,6 +148,23 @@ mod templates {
pub version: String,
}
#[derive(Serialize)]
pub struct About {
pub base_uri: String,
pub commit: String,
pub version: String,
}
impl About {
pub fn new(base_uri: impl Into<String>) -> Self {
Self {
base_uri: base_uri.into(),
version: env!("VERGEN_SEMVER").to_string(),
commit: env!("VERGEN_SHA_SHORT").to_string(),
}
}
}
impl General {
pub fn new(error: Option<String>) -> Self {
Self {
@ -280,8 +297,8 @@ fn faq() -> Template {
}
#[get("/about/usage")]
fn usage() -> Template {
Template::render("about/usage", templates::General::default())
fn usage(state: rocket::State<HagridState>) -> Template {
Template::render("about/usage", templates::About::new(state.base_uri.as_ref()))
}
#[get("/about/privacy")]
@ -323,6 +340,8 @@ fn rocket_factory(rocket: rocket::Rocket) -> Result<rocket::Rocket> {
vks_web::request_verify_form,
vks_web::request_verify_form_data,
vks_web::verify_confirm,
vks_web::quick_upload,
vks_web::quick_upload_proceed,
// HKP
hkp::pks_lookup,
hkp::pks_add_form,
@ -733,6 +752,23 @@ pub mod tests {
assert_eq!(response.status(), Status::BadRequest);
}
#[test]
fn upload_curl_shortcut() {
let (_tmpdir, client) = client().unwrap();
let (tpk, _) = TPKBuilder::autocrypt(
None, Some("foo@invalid.example.com".into()))
.generate().unwrap();
let mut tpk_serialized = Vec::new();
tpk.serialize(&mut tpk_serialized).unwrap();
let _token = vks_publish_shortcut_get_token(&client, &tpk_serialized);
check_mr_responses_by_fingerprint(&client, &tpk, 0);
check_null_responses_by_email(&client, "foo@invalid.example.com");
}
/// Asserts that the given URI 404s.
pub fn check_null_response(client: &Client, uri: &str) {
let response = client.get(uri).dispatch();
@ -891,7 +927,6 @@ pub mod tests {
assert!(response.body_string().unwrap().contains("pending"));
}
fn check_mails_and_verify_email(client: &Client, filemail_path: &Path) {
let pattern = format!("{}(/verify/[^ \t\n]*)", BASE_URI);
let confirm_uri = pop_mail_capture_pattern(filemail_path, &pattern);
@ -980,6 +1015,21 @@ pub mod tests {
.dispatch()
}
fn vks_publish_shortcut_get_token<'a>(client: &'a Client, data: &[u8]) -> String {
let mut response = client.put("/")
.body(data)
.dispatch();
let response_body = response.body_string().unwrap();
assert_eq!(response.status(), Status::Ok);
assert!(response_body.contains("Key successfully uploaded"));
let pattern = format!("{}/upload/([^ \t\n]*)", BASE_URI);
let capture_re = regex::bytes::Regex::new(&pattern).unwrap();
let capture_content = capture_re .captures(response_body.as_bytes()).unwrap()
.get(1).unwrap().as_bytes();
String::from_utf8_lossy(capture_content).to_string()
}
fn vks_publish_json_get_token<'a>(client: &'a Client, data: &[u8]) -> String {
let mut response = client.post("/vks/v1/upload")
.header(ContentType::JSON)

View File

@ -12,7 +12,7 @@ use rocket::Data;
use database::{KeyDatabase, StatefulTokens};
use mail;
use tokens;
use web::MyResponse;
use web::{HagridState,MyResponse};
use rate_limiter::RateLimiter;
use std::io::Read;
@ -87,11 +87,30 @@ mod template {
}
impl MyResponse {
fn upload_response_quick(response: UploadResponse, base_uri: &str) -> Self {
match response {
UploadResponse::Ok { token, key_fpr: _, is_revoked: _, status: _ } => {
let uri = uri!(quick_upload_proceed: token);
let text = format!(
"Key successfully uploaded. Proceed here:\n{}{}\n",
base_uri,
uri
);
MyResponse::plain(text)
},
UploadResponse::OkMulti { key_fprs } =>
MyResponse::plain(format!("Uploaded {} keys.\n", key_fprs.len())),
UploadResponse::Error(error) => MyResponse::bad_request(
"500-plain", failure::err_msg(error)),
}
}
fn upload_response(response: UploadResponse) -> Self {
match response {
UploadResponse::Ok { token, key_fpr, is_revoked, status } =>
Self::upload_ok(token, key_fpr, is_revoked, status),
UploadResponse::OkMulti { key_fprs } => Self::upload_ok_multi(key_fprs),
UploadResponse::OkMulti { key_fprs } =>
Self::upload_ok_multi(key_fprs),
UploadResponse::Error(error) => MyResponse::bad_request(
"upload/upload", failure::err_msg(error)),
}
@ -191,6 +210,44 @@ pub fn upload_post_form_data(
process_upload(&db, &tokens_stateless, &rate_limiter, data, boundary)
}
#[put("/", data = "<data>")]
pub fn quick_upload(
db: rocket::State<KeyDatabase>,
tokens_stateless: rocket::State<tokens::Service>,
rate_limiter: rocket::State<RateLimiter>,
state: rocket::State<HagridState>,
data: Data,
) -> MyResponse {
use std::io::Cursor;
let mut buf = Vec::default();
if let Err(error) = std::io::copy(&mut data.open().take(UPLOAD_LIMIT), &mut buf) {
return MyResponse::bad_request("500-plain", failure::err_msg(error));
}
MyResponse::upload_response_quick(vks::process_key(
&db,
&tokens_stateless,
&rate_limiter,
Cursor::new(buf)), &state.base_uri)
}
#[get("/upload/<token>", rank = 2)]
pub fn quick_upload_proceed(
db: rocket::State<KeyDatabase>,
token_stateful: rocket::State<StatefulTokens>,
token_stateless: rocket::State<tokens::Service>,
mail_service: rocket::State<mail::Service>,
rate_limiter: rocket::State<RateLimiter>,
token: String,
) -> MyResponse {
let result = vks::request_verify(
db, token_stateful, token_stateless, mail_service,
rate_limiter, token, vec!());
MyResponse::upload_response(result)
}
#[post("/upload/submit", format = "application/x-www-form-urlencoded", data = "<data>")]
pub fn upload_post_form(
db: rocket::State<KeyDatabase>,