only accept signed snippets
Some checks reported errors
continuous-integration/drone/push Build encountered an error

This commit is contained in:
shimunn 2019-09-06 23:28:28 +02:00
parent 0202fe3162
commit 338f8f6729
Signed by: shimun
GPG Key ID: E81D8382DC2F971B
4 changed files with 995 additions and 11 deletions

931
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -16,3 +16,5 @@ rand = "0.4.2"
byteorder = "1.3.2" byteorder = "1.3.2"
chrono = "0.4.9" chrono = "0.4.9"
sequoia-openpgp = "0.9.0"
lazy_static = "1.4.0"

View File

@ -1,21 +1,30 @@
#[macro_use]
extern crate lazy_static;
extern crate chrono; extern crate chrono;
extern crate iron; extern crate iron;
extern crate rand; extern crate rand;
extern crate sequoia_openpgp as openpgp;
extern crate snap; extern crate snap;
mod pgp;
use crate::pgp::KnownKeys;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use chrono::*; use chrono::*;
use core::cell::RefCell;
use iron::method::Method; use iron::method::Method;
use iron::modifiers::Redirect; use iron::modifiers::Redirect;
use iron::prelude::*; use iron::prelude::*;
use iron::url::Url; use iron::url::Url;
use rand::Rng; use rand::Rng;
use std::borrow::BorrowMut;
use std::fs; use std::fs;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
use std::io::prelude::*; use std::io::prelude::*;
use std::iter::Iterator; use std::iter::Iterator;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::Mutex;
struct Snippet<'a> { struct Snippet<'a> {
id: String, id: String,
@ -137,6 +146,12 @@ const STORAGE_DIR: &str = "/snips";
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
const STORAGE_DIR: &str = "/tmp"; const STORAGE_DIR: &str = "/tmp";
lazy_static! {
static ref KNOWN_KEYS: Mutex<KnownKeys> = Mutex::new(
KnownKeys::load_dir([STORAGE_DIR, "keys"].join("/")).expect("Failed to load pubkeys")
);
}
const VERSION: &str = env!("CARGO_PKG_VERSION"); const VERSION: &str = env!("CARGO_PKG_VERSION");
fn handle(req: &mut Request) -> IronResult<Response> { fn handle(req: &mut Request) -> IronResult<Response> {
@ -148,7 +163,7 @@ fn handle(req: &mut Request) -> IronResult<Response> {
(Method::Post, Some(path)) => { (Method::Post, Some(path)) => {
if path == &"new" { if path == &"new" {
let snip = { let snip = {
let text: String = { let pgp_text: String = {
let bytes = ((&mut req.body).bytes().take(1024 * 512).collect::<Result< let bytes = ((&mut req.body).bytes().take(1024 * 512).collect::<Result<
Vec<u8>, Vec<u8>,
io::Error, io::Error,
@ -158,6 +173,11 @@ fn handle(req: &mut Request) -> IronResult<Response> {
String::from_utf8(bytes) String::from_utf8(bytes)
.map_err(|err| IronError::new(err, "Invalid utf8"))? .map_err(|err| IronError::new(err, "Invalid utf8"))?
}; };
let b_text = KNOWN_KEYS
.lock().unwrap()//.map_err(|_| IronError::new(std::error::Error::from("Mutex Err"), "PGP Context unavailable"))?
.verify(pgp_text.as_bytes())
.map_err(|err| IronError::new(err, "Untrusted signature"))?;
let text = String::from_utf8(b_text).unwrap();
Snippet::random(&storage).write(&*text).map_err(|err| { Snippet::random(&storage).write(&*text).map_err(|err| {
let msg = format!("Failed to save snippet: {:?}", &err); let msg = format!("Failed to save snippet: {:?}", &err);
IronError::new(err, msg) IronError::new(err, msg)

51
src/pgp.rs Normal file
View File

@ -0,0 +1,51 @@
use std::io;
use std::fs;
use std::fs::{File};
use std::path::Path;
use std::io::prelude::*;
use openpgp::parse::Parse;
use openpgp::*;
use openpgp::parse::stream::*;
pub struct KnownKeys {
keys: Vec<openpgp::TPK>
}
impl VerificationHelper for &KnownKeys {
fn get_public_keys(&mut self, _ids: &[KeyID]) -> Result<Vec<TPK>> {
Ok(self.keys.clone())
}
fn check(&mut self, structure: &MessageStructure) -> Result<()> {
Ok(()) // Implement your verification policy here.
}
}
impl KnownKeys {
pub fn load_dir(dir: impl AsRef<Path>) -> io::Result<KnownKeys> {
let mut keys: Vec<openpgp::TPK> = Vec::with_capacity(3);
for f in fs::read_dir(dir)? {
let f = f?;
if f.metadata()?.is_dir() {
continue;
}
let tpk = openpgp::TPK::from_file(f.path()).unwrap();
println!("Fingerprint: {}", tpk.fingerprint());
keys.push(tpk);
}
Ok(KnownKeys{
keys: keys
})
}
pub fn verify(&mut self, r: impl Read) -> io::Result<Vec<u8>> {
let mut content = Vec::with_capacity(2048);
let helper = &*self;
let mut v = Verifier::<&KnownKeys>::from_reader(r, helper, None).map_err(|e| dbg!(e)).unwrap();
if v.read_to_end(&mut content).is_err() {
return Err(io::Error::new(io::ErrorKind::InvalidData, "Signature Mismatch"));
}
Ok(content)
}
}