parent
9a4446871a
commit
39764bfa0e
@ -1,3 +0,0 @@ |
||||
pub struct ClientConnection {} |
||||
|
||||
impl ClientConnection {} |
@ -1,180 +0,0 @@ |
||||
// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
|
||||
// All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
|
||||
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
|
||||
// at your option. All files in the project carrying such
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use std::pin::Pin; |
||||
|
||||
use debug_print::*; |
||||
use futures::future::BoxFuture; |
||||
use futures::future::OptionFuture; |
||||
use futures::FutureExt; |
||||
use p2p_net::actors::*; |
||||
use p2p_net::errors::*; |
||||
use p2p_net::types::*; |
||||
use p2p_repo::types::*; |
||||
use p2p_repo::utils::*; |
||||
use rust_fsm::*; |
||||
|
||||
// state_machine! {
|
||||
// derive(Debug)
|
||||
// AuthProtocolClient(Ready)
|
||||
|
||||
// Ready(ClientHelloSent) => ClientHelloSent,
|
||||
// ClientHelloSent(ServerHelloReceived) => ServerHelloReceived,
|
||||
// ServerHelloReceived(ClientAuthSent) => ClientAuthSent,
|
||||
// ClientAuthSent(AuthResultReceived) => AuthResult,
|
||||
// AuthResult => {
|
||||
// Ok => BrokerProtocol,
|
||||
// Error => Closed,
|
||||
// },
|
||||
// }
|
||||
|
||||
// state_machine! {
|
||||
// derive(Debug)
|
||||
// AuthProtocolServer(Ready)
|
||||
|
||||
// Ready(ClientHelloReceived) => ClientHelloReceived,
|
||||
// ClientHelloReceived(ServerHelloSent) => ServerHelloSent,
|
||||
// ServerHelloSent(ClientAuthReceived) => ClientAuthReceived,
|
||||
// ClientAuthReceived => {
|
||||
// Ok => AuthResultOk,
|
||||
// Error => AuthResultError,
|
||||
// },
|
||||
// AuthResultOk(AuthResultSent) => BrokerProtocol,
|
||||
// AuthResultError(AuthResultSent) => Closed,
|
||||
// }
|
||||
|
||||
#[derive(Debug)] |
||||
pub struct AuthProtocolHandler { |
||||
//machine: StateMachine<AuthProtocolServer>,
|
||||
nonce: Option<Vec<u8>>, |
||||
user: Option<PubKey>, |
||||
} |
||||
|
||||
impl AuthProtocolHandler { |
||||
pub fn new() -> AuthProtocolHandler { |
||||
AuthProtocolHandler { |
||||
//machine: StateMachine::new(),
|
||||
nonce: None, |
||||
user: None, |
||||
} |
||||
} |
||||
|
||||
pub fn get_user(&self) -> Option<PubKey> { |
||||
self.user |
||||
} |
||||
|
||||
pub fn handle_init(&mut self, client_hello: ClientHello) -> Result<Vec<u8>, ProtocolError> { |
||||
// let _ = self
|
||||
// .machine
|
||||
// .consume(&AuthProtocolServerInput::ClientHelloReceived)
|
||||
// .map_err(|_e| ProtocolError::InvalidState)?;
|
||||
|
||||
let mut random_buf = [0u8; 32]; |
||||
getrandom::getrandom(&mut random_buf).unwrap(); |
||||
let nonce = random_buf.to_vec(); |
||||
let reply = ServerHello::V0(ServerHelloV0 { |
||||
nonce: nonce.clone(), |
||||
}); |
||||
self.nonce = Some(nonce); |
||||
|
||||
// let _ = self
|
||||
// .machine
|
||||
// .consume(&AuthProtocolServerInput::ServerHelloSent)
|
||||
// .map_err(|_e| ProtocolError::InvalidState)?;
|
||||
|
||||
//debug_println!("sending nonce to client: {:?}", self.nonce);
|
||||
|
||||
Ok(serde_bare::to_vec(&reply).unwrap()) |
||||
} |
||||
|
||||
pub fn handle_incoming( |
||||
&mut self, |
||||
frame: Vec<u8>, |
||||
) -> ( |
||||
Result<Vec<u8>, ProtocolError>, |
||||
Pin<Box<OptionFuture<BoxFuture<'static, u16>>>>, |
||||
) { |
||||
fn prepare_reply(res: Result<Vec<u8>, ProtocolError>) -> AuthResult { |
||||
let (result, metadata) = match res { |
||||
Ok(m) => (0, m), |
||||
Err(e) => (e.into(), vec![]), |
||||
}; |
||||
AuthResult::V0(AuthResultV0 { result, metadata }) |
||||
} |
||||
|
||||
fn process_state( |
||||
handler: &mut AuthProtocolHandler, |
||||
frame: Vec<u8>, |
||||
) -> Result<Vec<u8>, ProtocolError> { |
||||
// match handler.machine.state() {
|
||||
// &AuthProtocolServerState::ServerHelloSent => {
|
||||
let message = serde_bare::from_slice::<ClientAuth>(&frame)?; |
||||
// let _ = handler
|
||||
// .machine
|
||||
// .consume(&AuthProtocolServerInput::ClientAuthReceived)
|
||||
// .map_err(|_e| ProtocolError::InvalidState)?;
|
||||
|
||||
// verifying client auth
|
||||
|
||||
debug_println!("verifying client auth"); |
||||
|
||||
let _ = verify( |
||||
&serde_bare::to_vec(&message.content_v0()).unwrap(), |
||||
message.sig(), |
||||
message.user(), |
||||
) |
||||
.map_err(|_e| ProtocolError::AccessDenied)?; |
||||
|
||||
// debug_println!(
|
||||
// "matching nonce : {:?} {:?}",
|
||||
// message.nonce(),
|
||||
// handler.nonce.as_ref().unwrap()
|
||||
// );
|
||||
|
||||
if message.nonce() != handler.nonce.as_ref().unwrap() { |
||||
// let _ = handler
|
||||
// .machine
|
||||
// .consume(&AuthProtocolServerInput::Error)
|
||||
// .map_err(|_e| ProtocolError::InvalidState);
|
||||
|
||||
return Err(ProtocolError::AccessDenied); |
||||
} |
||||
|
||||
// TODO check that the device has been registered for this user. if not, return AccessDenied
|
||||
|
||||
// all is good, we advance the FSM and send back response
|
||||
// let _ = handler
|
||||
// .machine
|
||||
// .consume(&AuthProtocolServerInput::Ok)
|
||||
// .map_err(|_e| ProtocolError::InvalidState)?;
|
||||
|
||||
handler.user = Some(message.user()); |
||||
|
||||
Ok(vec![]) // without any metadata
|
||||
//}
|
||||
//_ => Err(ProtocolError::InvalidState),
|
||||
//}
|
||||
} |
||||
|
||||
let res = process_state(self, frame); |
||||
let is_err = res.as_ref().err().cloned(); |
||||
let reply = prepare_reply(res); |
||||
let reply_ser: Result<Vec<u8>, ProtocolError> = Ok(serde_bare::to_vec(&reply).unwrap()); |
||||
if is_err.is_some() { |
||||
( |
||||
reply_ser, |
||||
Box::pin(OptionFuture::from(Some( |
||||
async move { reply.result() }.boxed(), |
||||
))), |
||||
) |
||||
} else { |
||||
(reply_ser, Box::pin(OptionFuture::from(None))) |
||||
} |
||||
} |
||||
} |
@ -1,147 +0,0 @@ |
||||
// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
|
||||
// All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
|
||||
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
|
||||
// at your option. All files in the project carrying such
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
//! Local Connection to a Broker
|
||||
|
||||
use futures::{ |
||||
ready, |
||||
stream::Stream, |
||||
task::{Context, Poll}, |
||||
Future, |
||||
select, FutureExt, |
||||
}; |
||||
use futures::channel::mpsc; |
||||
use std::pin::Pin; |
||||
use std::{collections::HashSet, fmt::Debug}; |
||||
|
||||
use crate::server::BrokerServer; |
||||
use debug_print::*; |
||||
use futures::{pin_mut, stream, Sink, SinkExt, StreamExt}; |
||||
use p2p_repo::object::*; |
||||
use p2p_repo::store::*; |
||||
use p2p_repo::types::*; |
||||
use p2p_repo::utils::*; |
||||
use p2p_net::errors::*; |
||||
use p2p_net::types::*; |
||||
use p2p_net::broker_connection::*; |
||||
use std::collections::HashMap; |
||||
|
||||
|
||||
pub struct BrokerConnectionLocal<'a> { |
||||
broker: &'a mut BrokerServer, |
||||
user: PubKey, |
||||
} |
||||
|
||||
#[async_trait::async_trait] |
||||
impl<'a> BrokerConnection for BrokerConnectionLocal<'a> { |
||||
type OC = BrokerConnectionLocal<'a>; |
||||
type BlockStream = async_channel::Receiver<Block>; |
||||
|
||||
async fn close(&mut self) {} |
||||
|
||||
async fn add_user( |
||||
&mut self, |
||||
user_id: PubKey, |
||||
admin_user_pk: PrivKey, |
||||
) -> Result<(), ProtocolError> { |
||||
let op_content = AddUserContentV0 { user: user_id }; |
||||
let sig = sign(admin_user_pk, self.user, &serde_bare::to_vec(&op_content)?)?; |
||||
|
||||
self.broker.add_user(self.user, user_id, sig) |
||||
} |
||||
|
||||
async fn process_overlay_request( |
||||
&mut self, |
||||
overlay: OverlayId, |
||||
request: BrokerOverlayRequestContentV0, |
||||
) -> Result<(), ProtocolError> { |
||||
match request { |
||||
BrokerOverlayRequestContentV0::OverlayConnect(_) => { |
||||
self.broker.connect_overlay(self.user, overlay) |
||||
} |
||||
BrokerOverlayRequestContentV0::OverlayJoin(j) => { |
||||
self.broker |
||||
.join_overlay(self.user, overlay, j.repo_pubkey(), j.secret(), j.peers()) |
||||
} |
||||
BrokerOverlayRequestContentV0::ObjectPin(op) => { |
||||
self.broker.pin_object(self.user, overlay, op.id()) |
||||
} |
||||
BrokerOverlayRequestContentV0::ObjectUnpin(op) => { |
||||
self.broker.unpin_object(self.user, overlay, op.id()) |
||||
} |
||||
BrokerOverlayRequestContentV0::ObjectDel(op) => { |
||||
self.broker.del_object(self.user, overlay, op.id()) |
||||
} |
||||
BrokerOverlayRequestContentV0::BlockPut(b) => { |
||||
self.broker.put_block(self.user, overlay, b.block()) |
||||
} |
||||
_ => Err(ProtocolError::InvalidState), |
||||
} |
||||
} |
||||
|
||||
async fn process_overlay_request_objectid_response( |
||||
&mut self, |
||||
overlay: OverlayId, |
||||
request: BrokerOverlayRequestContentV0, |
||||
) -> Result<ObjectId, ProtocolError> { |
||||
match request { |
||||
BrokerOverlayRequestContentV0::ObjectCopy(oc) => { |
||||
self.broker |
||||
.copy_object(self.user, overlay, oc.id(), oc.expiry()) |
||||
} |
||||
_ => Err(ProtocolError::InvalidState), |
||||
} |
||||
} |
||||
|
||||
async fn process_overlay_request_stream_response( |
||||
&mut self, |
||||
overlay: OverlayId, |
||||
request: BrokerOverlayRequestContentV0, |
||||
) -> Result<Pin<Box<Self::BlockStream>>, ProtocolError> { |
||||
match request { |
||||
|
||||
BrokerOverlayRequestContentV0::BlockGet(b) => self |
||||
.broker |
||||
.get_block(self.user, overlay, b.id(), b.include_children(), b.topic()) |
||||
.map(|r| Box::pin(r)), |
||||
BrokerOverlayRequestContentV0::BranchSyncReq(b) => self |
||||
.broker |
||||
.sync_branch( |
||||
self.user, |
||||
&overlay, |
||||
b.heads(), |
||||
b.known_heads(), |
||||
b.known_commits(), |
||||
) |
||||
.map(|r| Box::pin(r)), |
||||
_ => Err(ProtocolError::InvalidState), |
||||
} |
||||
} |
||||
|
||||
async fn del_user(&mut self, user_id: PubKey, admin_user_pk: PrivKey) {} |
||||
|
||||
async fn add_client(&mut self, user_id: PubKey, admin_user_pk: PrivKey) {} |
||||
|
||||
async fn del_client(&mut self, user_id: PubKey, admin_user_pk: PrivKey) {} |
||||
|
||||
async fn overlay_connect( |
||||
&mut self, |
||||
repo_link: &RepoLink, |
||||
public: bool, |
||||
) -> Result<OverlayConnectionClient<BrokerConnectionLocal<'a>>, ProtocolError> { |
||||
let overlay = self.process_overlay_connect(repo_link, public).await?; |
||||
Ok(OverlayConnectionClient::create(self, overlay, repo_link.clone())) |
||||
} |
||||
} |
||||
|
||||
impl<'a> BrokerConnectionLocal<'a> { |
||||
pub fn new(broker: &'a mut BrokerServer, user: PubKey) -> BrokerConnectionLocal<'a> { |
||||
BrokerConnectionLocal { broker, user } |
||||
} |
||||
} |
@ -1,3 +0,0 @@ |
||||
pub struct ServerConnection {} |
||||
|
||||
impl ServerConnection {} |
@ -1,93 +0,0 @@ |
||||
/* |
||||
* Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers |
||||
* All rights reserved. |
||||
* Licensed under the Apache License, Version 2.0 |
||||
* <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
|
||||
* or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
|
||||
* at your option. All files in the project carrying such |
||||
* notice may not be copied, modified, or distributed except |
||||
* according to those terms. |
||||
*/ |
||||
|
||||
//! WebSocket Remote Connection to a Broker
|
||||
|
||||
use debug_print::*; |
||||
|
||||
use futures::{future, pin_mut, stream, SinkExt, StreamExt}; |
||||
use p2p_client::connection_remote::*; |
||||
use p2p_net::broker_connection::*; |
||||
use p2p_net::errors::*; |
||||
use p2p_net::types::*; |
||||
use p2p_repo::types::*; |
||||
use p2p_repo::utils::{generate_keypair, now_timestamp}; |
||||
|
||||
use async_tungstenite::async_std::connect_async; |
||||
use async_tungstenite::client_async; |
||||
use async_tungstenite::tungstenite::{Error, Message}; |
||||
|
||||
pub struct BrokerConnectionWebSocket {} |
||||
|
||||
impl BrokerConnectionWebSocket { |
||||
pub async fn open( |
||||
url: &str, |
||||
priv_key: PrivKey, |
||||
pub_key: PubKey, |
||||
) -> Result<impl BrokerConnection, ProtocolError> { |
||||
let res = connect_async(url).await; |
||||
|
||||
match (res) { |
||||
Ok((ws, _)) => { |
||||
debug_println!("WebSocket handshake completed"); |
||||
|
||||
let (write, read) = ws.split(); |
||||
let mut frames_stream_read = read.map(|msg_res| match msg_res { |
||||
Err(e) => { |
||||
debug_println!("ERROR {:?}", e); |
||||
vec![] |
||||
} |
||||
Ok(message) => { |
||||
if message.is_close() { |
||||
debug_println!("CLOSE FROM SERVER"); |
||||
vec![] |
||||
} else { |
||||
message.into_data() |
||||
} |
||||
} |
||||
}); |
||||
async fn transform(message: Vec<u8>) -> Result<Message, Error> { |
||||
if message.len() == 0 { |
||||
debug_println!("sending CLOSE message to SERVER"); |
||||
Ok(Message::Close(None)) |
||||
} else { |
||||
Ok(Message::binary(message)) |
||||
} |
||||
} |
||||
let frames_stream_write = write |
||||
.with(|message| transform(message)) |
||||
.sink_map_err(|e| ProtocolError::WriteError); |
||||
|
||||
let master_key: [u8; 32] = [0; 32]; |
||||
let mut cnx_res = ConnectionRemote::open_broker_connection( |
||||
frames_stream_write, |
||||
frames_stream_read, |
||||
pub_key, |
||||
priv_key, |
||||
PubKey::Ed25519PubKey([1; 32]), |
||||
) |
||||
.await; |
||||
|
||||
match cnx_res { |
||||
Ok(mut cnx) => Ok(cnx), |
||||
Err(e) => { |
||||
debug_println!("cannot connect {:?}", e); |
||||
Err(e) |
||||
} |
||||
} |
||||
} |
||||
Err(e) => { |
||||
debug_println!("Cannot connect: {:?}", e); |
||||
Err(ProtocolError::ConnectionError) |
||||
} |
||||
} |
||||
} |
||||
} |