// Copyright (c) 2018 Brandl, Valentin // Author: Brandl, Valentin // // Licensed unter the Apache License, Version 2.0 or the MIT license, at your // option. // // ******************************************************************************** // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of // the Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // ******************************************************************************** // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use actix_web::{ error::{Error, ErrorInternalServerError, ErrorUnauthorized, JsonPayloadError, ParseError}, FromRequest, HttpMessage, HttpRequest, Result, }; use futures::future::{err as FutErr, Future}; use std::{ops::Deref, sync::Arc}; #[derive(Debug, Fail)] pub enum ExecuteError { #[fail(display = "Stdin error")] Stdin, } pub struct Config { token: String, command: String, key_path: String, ok_marker: String, server: String, } impl Config { pub fn new( token: String, command: String, key_path: String, ok_marker: String, server: String, ) -> Self { Self { token, command, key_path, ok_marker, server, } } #[inline] pub fn token(&self) -> &str { &self.token } #[inline] pub fn command(&self) -> &str { &self.command } #[inline] pub fn key_path(&self) -> &str { &self.key_path } #[inline] pub fn ok_marker(&self) -> &str { &self.ok_marker } #[inline] pub fn server(&self) -> &str { &self.server } } pub struct Validated(T); impl FromRequest> for Validated { type Config = (); type Result = Box>; fn from_request(req: &HttpRequest>, _: &Self::Config) -> Self::Result { let state = req.state().clone(); let sig = extract_signature(&req); if sig.is_err() { return Box::new(FutErr(sig.unwrap_err())); } let sig = sig.unwrap(); Box::new(req.clone().body().from_err().and_then(move |body| { if ::crypto::verify_signature(state.token().as_bytes(), &body, &sig) { let delete: T = ::serde_json::from_slice(&body) .map_err(|e| ErrorInternalServerError(JsonPayloadError::Deserialize(e)))?; Ok(Validated(delete)) } else { Err(ErrorUnauthorized(ParseError::Header)) } })) } } impl Deref for Validated { type Target = T; fn deref(&self) -> &T { &self.0 } } fn extract_signature(req: &HttpRequest) -> Result> { Ok(req.headers() .get(::data::TOKEN_HEADER) .as_ref() .ok_or_else(|| ErrorUnauthorized(ParseError::Header))? .to_str() .map_err(ErrorUnauthorized) .and_then(|s| { ::crypto::hex_str_to_bytes(s).map_err(|_| ErrorUnauthorized(ParseError::Header)) }) .map_err(ErrorUnauthorized)?) }