ClientAuth is working

master
Niko 1 year ago
parent b984cd7532
commit 9a4446871a
  1. 19
      ng-app-js/src/lib.rs
  2. 8
      p2p-broker/src/server.rs
  3. 34
      p2p-client-ws/src/connection_ws.rs
  4. 37
      p2p-client-ws/src/remote_ws.rs
  5. 17
      p2p-client-ws/src/remote_ws_wasm.rs
  6. 2
      p2p-net/src/broker.rs
  7. 185
      p2p-net/src/connection.rs
  8. 7
      p2p-net/src/errors.rs
  9. 12
      p2p-net/src/types.rs

@ -4,6 +4,7 @@ use js_sys::Reflect;
#[cfg(target_arch = "wasm32")]
use p2p_client_ws::remote_ws_wasm::ConnectionWebSocket;
use p2p_net::broker::*;
use p2p_net::connection::{ClientConfig, StartConfig};
use p2p_net::types::{DirectPeerId, IP};
use p2p_net::utils::{spawn_and_log_error, ResultSend};
use p2p_net::{log, sleep};
@ -33,11 +34,14 @@ pub async fn greet(name: &str) {
241, 52, 155, 231, 83, 188, 189, 47, 135, 105, 213, 39, 91,
]);
log!("start connecting");
//let cnx = Arc::new();
let keys = p2p_net::utils::gen_keys();
let pub_key = PubKey::Ed25519PubKey(keys.1);
let (client_priv_key, client_pub_key) = generate_keypair();
let (user_priv_key, user_pub_key) = generate_keypair();
log!("start connecting");
let res = BROKER
.write()
.await
@ -48,6 +52,11 @@ pub async fn greet(name: &str) {
keys.0,
pub_key,
server_key,
StartConfig::Client(ClientConfig {
user: user_pub_key,
client: client_pub_key,
client_priv: client_priv_key,
}),
)
.await;
log!("broker.connect : {:?}", res);
@ -60,7 +69,7 @@ pub async fn greet(name: &str) {
async fn timer_close(remote_peer_id: DirectPeerId) -> ResultSend<()> {
async move {
sleep!(std::time::Duration::from_secs(10));
sleep!(std::time::Duration::from_secs(3));
log!("timeout");
BROKER
.write()
@ -71,11 +80,11 @@ pub async fn greet(name: &str) {
.await;
Ok(())
}
spawn_and_log_error(timer_close(pub_key));
spawn_and_log_error(timer_close(server_key));
//Broker::graceful_shutdown().await;
Broker::join_shutdown_with_timeout(std::time::Duration::from_secs(12)).await;
Broker::join_shutdown_with_timeout(std::time::Duration::from_secs(5)).await;
Ok(())
}

@ -588,7 +588,7 @@ impl BrokerServer {
let mut path = self.store.path();
path.push(REPO_STORES_SUBDIR);
path.push::<String>(repo_hash.clone().into());
std::fs::create_dir_all(path.clone()).map_err(|_e| ProtocolError::WriteError)?;
std::fs::create_dir_all(path.clone()).map_err(|_e| ProtocolError::IoError)?;
println!("path for repo store: {}", path.to_str().unwrap());
let repo = LmdbRepoStore::open(&path, *key.slice());
let mut writer = self.repo_stores.write().expect("write repo_store hashmap");
@ -846,7 +846,7 @@ impl BrokerServer {
if !include_children {
let block = store.get(&id)?;
s.send_blocking(block)
.map_err(|_e| ProtocolError::WriteError)?;
.map_err(|_e| ProtocolError::IoError)?;
Ok(r)
} else {
let obj = Object::load(id, None, store);
@ -863,7 +863,7 @@ impl BrokerServer {
let id = block.id();
if deduplicated.get(&id).is_none() {
s.send_blocking(block.clone())
.map_err(|_e| ProtocolError::WriteError)?;
.map_err(|_e| ProtocolError::IoError)?;
deduplicated.insert(id);
}
}
@ -902,7 +902,7 @@ impl BrokerServer {
let id = block.id();
if deduplicated.get(&id).is_none() {
s.send_blocking(block.clone())
.map_err(|_e| ProtocolError::WriteError)?;
.map_err(|_e| ProtocolError::IoError)?;
deduplicated.insert(id);
}
}

@ -2,7 +2,7 @@
* 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>
* <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
@ -13,27 +13,26 @@
use debug_print::*;
use p2p_repo::types::*;
use p2p_repo::utils::{generate_keypair, now_timestamp};
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_net::broker_connection::*;
use p2p_client::connection_remote::*;
use futures::{future, pin_mut, stream, SinkExt, StreamExt};
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>
{
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) {
@ -78,9 +77,7 @@ impl BrokerConnectionWebSocket{
.await;
match cnx_res {
Ok(mut cnx) => {
Ok(cnx)
}
Ok(mut cnx) => Ok(cnx),
Err(e) => {
debug_println!("cannot connect {:?}", e);
Err(e)
@ -93,5 +90,4 @@ impl BrokerConnectionWebSocket{
}
}
}
}
}

@ -47,6 +47,7 @@ impl IConnect for ConnectionWebSocket {
peer_privk: Sensitive<[u8; 32]>,
peer_pubk: PubKey,
remote_peer: DirectPeerId,
config: StartConfig,
) -> Result<ConnectionBase, NetError> {
let mut cnx = ConnectionBase::new(ConnectionDir::Client, TransportProtocol::WS);
@ -125,7 +126,7 @@ impl IConnect for ConnectionWebSocket {
debug_println!("END of WS loop");
});
cnx.start().await;
cnx.start(config).await;
//spawn_and_log_error(ws_loop(ws, cnx.take_sender(), cnx.take_receiver()));
@ -240,11 +241,11 @@ async fn ws_loop(
select! {
r = stream.next().fuse() => match r {
Some(Ok(msg)) => {
log!("GOT MESSAGE {:?}", msg);
//log!("GOT MESSAGE {:?}", msg);
if msg.is_close() {
if let Message::Close(Some(cf)) = msg {
log!("CLOSE from server with closeframe: {}",cf.reason);
log!("CLOSE from remote with closeframe: {}",cf.reason);
let last_command = match cf.code {
CloseCode::Normal =>
ConnectionCommand::Close,
@ -263,21 +264,20 @@ async fn ws_loop(
}
else {
let _ = futures::SinkExt::send(receiver, ConnectionCommand::Close).await;
log!("CLOSE from server");
log!("CLOSE from remote");
}
return Ok(ProtocolError::Closing);
} else {
futures::SinkExt::send(receiver,ConnectionCommand::Msg(serde_bare::from_slice::<ProtocolMessage>(&msg.into_data())?)).await
.map_err(|_e| NetError::IoError)?;
}
//return Ok(ProtocolError::Closing);
},
Some(Err(e)) => {log!("GOT ERROR {:?}",e);return Err(NetError::WsError);},
None => break
},
s = sender.next().fuse() => match s {
Some(msg) => {
log!("SENDING MESSAGE {:?}", msg);
//log!("SENDING MESSAGE {:?}", msg);
match msg {
ConnectionCommand::Msg(m) => {
futures::SinkExt::send(&mut stream,Message::binary(serde_bare::to_vec(&m)?)).await.map_err(|_e| NetError::IoError)?;
@ -302,7 +302,6 @@ async fn ws_loop(
match inner_loop(&mut ws, sender, &mut receiver).await {
Ok(proto_err) => {
if proto_err == ProtocolError::Closing {
//FIXME: remove this case
log!("ProtocolError::Closing");
let _ = ws.close(None).await;
} else if proto_err == ProtocolError::NoError {
@ -327,7 +326,7 @@ async fn ws_loop(
return Err(e);
}
}
log!("END OF LOOP");
//log!("END OF LOOP");
Ok(())
}
@ -347,8 +346,8 @@ mod test {
#[async_std::test]
pub async fn test_ws() -> Result<(), NetError> {
let mut random_buf = [0u8; 32];
getrandom::getrandom(&mut random_buf).unwrap();
// let mut random_buf = [0u8; 32];
// getrandom::getrandom(&mut random_buf).unwrap();
let server_key = PubKey::Ed25519PubKey([
22, 140, 190, 111, 82, 151, 27, 133, 83, 121, 71, 36, 209, 53, 53, 114, 52, 254, 218,
@ -356,11 +355,12 @@ mod test {
]);
let keys = p2p_net::utils::gen_keys();
let pub_key = PubKey::Ed25519PubKey(keys.1);
let (client_priv_key, client_pub_key) = generate_keypair();
let (user_priv_key, user_pub_key) = generate_keypair();
log!("start connecting");
//let (priv_key, pub_key) = generate_keypair();
{
let res = BROKER
.write()
@ -372,15 +372,22 @@ mod test {
keys.0,
pub_key.clone(),
server_key,
StartConfig::Client(ClientConfig {
user: user_pub_key,
client: client_pub_key,
client_priv: client_priv_key,
}),
)
.await;
log!("broker.connect : {:?}", res);
res.expect("assume the connection succeeds");
}
BROKER.read().await.print_status();
async fn timer_close(remote_peer_id: DirectPeerId) -> ResultSend<()> {
async move {
sleep!(std::time::Duration::from_secs(10));
sleep!(std::time::Duration::from_secs(3));
log!("timeout");
BROKER
.write()
@ -391,11 +398,11 @@ mod test {
.await;
Ok(())
}
spawn_and_log_error(timer_close(pub_key));
spawn_and_log_error(timer_close(server_key));
//Broker::graceful_shutdown().await;
Broker::join_shutdown_with_timeout(std::time::Duration::from_secs(12)).await;
Broker::join_shutdown_with_timeout(std::time::Duration::from_secs(5)).await;
Ok(())
}
}

@ -18,7 +18,7 @@ use p2p_net::errors::*;
use p2p_net::log;
use p2p_net::types::*;
use p2p_net::utils::*;
use p2p_net::{connection::*, WS_PORT};
use p2p_net::WS_PORT;
use p2p_repo::types::*;
use p2p_repo::utils::{generate_keypair, now_timestamp};
use std::sync::Arc;
@ -40,6 +40,7 @@ impl IConnect for ConnectionWebSocket {
peer_privk: Sensitive<[u8; 32]>,
peer_pubk: PubKey,
remote_peer: DirectPeerId,
config: StartConfig,
) -> Result<ConnectionBase, NetError> {
//pub async fn testt(url: &str) -> ResultSend<()> {
let mut cnx = ConnectionBase::new(ConnectionDir::Client, TransportProtocol::WS);
@ -65,12 +66,10 @@ impl IConnect for ConnectionWebSocket {
shutdown,
));
cnx.start().await;
cnx.start(config).await;
//spawn_and_log_error(read_loop(receiver_rx, sender_tx.clone()));
log!("sending...");
//cnx.close().await;
// spawn_and_log_error(async move {
// TimeoutFuture::new(10_000).await;
@ -113,11 +112,10 @@ async fn ws_loop(
) -> Result<ProtocolError, NetError> {
//let mut rx_sender = sender.fuse();
loop {
log!("BEFORE SELECT");
select! {
r = stream.next().fuse() => match r {
Some(msg) => {
log!("GOT MESSAGE {:?}", msg);
//log!("GOT MESSAGE {:?}", msg);
if let WsMessage::Binary(b) = msg {
receiver.send(ConnectionCommand::Msg(serde_bare::from_slice::<ProtocolMessage>(&b)?)).await
.map_err(|_e| NetError::IoError)?;
@ -130,7 +128,7 @@ async fn ws_loop(
},
s = sender.next().fuse() => match s {
Some(msg) => {
log!("SENDING MESSAGE {:?}", msg);
//log!("SENDING MESSAGE {:?}", msg);
match msg {
ConnectionCommand::Msg(m) => {
@ -152,16 +150,14 @@ async fn ws_loop(
},
}
}
log!("END SELECT");
Ok(ProtocolError::NoError)
}
log!("START of WS loop");
let mut events = ws
.observe(ObserveConfig::default())
//.observe(Filter::Pointer(WsEvent::is_closed).into())
.await
.expect_throw("observe");
log!("OBSERVED");
match inner_loop(&mut stream, sender, receiver.clone()).await {
Ok(proto_err) => {
if proto_err == ProtocolError::NoError {
@ -220,5 +216,6 @@ async fn ws_loop(
.await
.map_err(|_e| NetError::IoError)?;
log!("END of WS loop");
Ok(())
}

@ -218,6 +218,7 @@ impl Broker {
peer_privk: Sensitive<[u8; 32]>,
peer_pubk: PubKey,
remote_peer_id: DirectPeerId,
config: StartConfig,
) -> Result<(), NetError> {
if self.closing {
return Err(NetError::Closing);
@ -235,6 +236,7 @@ impl Broker {
Sensitive::<[u8; 32]>::from_slice(peer_privk.deref()),
peer_pubk,
remote_peer_id,
config,
)
.await?;

@ -20,6 +20,7 @@ use noise_protocol::{patterns::noise_xk, CipherState, HandshakeState};
use noise_rust_crypto::sensitive::Sensitive;
use noise_rust_crypto::*;
use p2p_repo::types::{PrivKey, PubKey};
use p2p_repo::utils::{sign, verify};
use serde_bare::from_slice;
use unique_id::sequence::SequenceGenerator;
use unique_id::Generator;
@ -42,6 +43,7 @@ pub trait IConnect: Send + Sync {
peer_privk: Sensitive<[u8; 32]>,
peer_pubk: PubKey,
remote_peer: DirectPeerId,
config: StartConfig,
) -> Result<ConnectionBase, NetError>;
}
@ -97,6 +99,9 @@ pub struct NoiseFSM {
from: Option<Sensitive<[u8; 32]>>,
to: Option<PubKey>,
nonce_for_hello: Vec<u8>,
config: Option<StartConfig>,
}
impl fmt::Debug for NoiseFSM {
@ -114,6 +119,25 @@ pub enum StepReply {
NONE,
}
pub struct ClientConfig {
pub user: PubKey,
pub client: PubKey,
pub client_priv: PrivKey,
}
pub struct ExtConfig {}
pub struct CoreConfig {}
pub struct AdminConfig {}
pub enum StartConfig {
Client(ClientConfig),
Ext(ExtConfig),
Core(CoreConfig),
Admin(AdminConfig),
}
impl NoiseFSM {
pub fn new(
tp: TransportProtocol,
@ -137,6 +161,8 @@ impl NoiseFSM {
noise_cipher_state_dec: None,
from: Some(from),
to,
nonce_for_hello: vec![],
config: None,
}
}
@ -168,14 +194,20 @@ impl NoiseFSM {
}
pub async fn send(&mut self, msg: ProtocolMessage) -> Result<(), ProtocolError> {
if self.state == FSMstate::AuthResult && self.noise_cipher_state_enc.is_some() {
log!("SENDING: {:?}", msg);
if self.noise_cipher_state_enc.is_some() {
let cipher = self.encrypt(msg)?;
self.sender
.send(ConnectionCommand::Msg(ProtocolMessage::Noise(cipher)))
.await;
.await
.map_err(|e| ProtocolError::IoError)?;
return Ok(());
} else {
return Err(ProtocolError::InvalidState);
self.sender
.send(ConnectionCommand::Msg(msg))
.await
.map_err(|e| ProtocolError::IoError)?;
return Ok(());
}
}
@ -207,6 +239,9 @@ impl NoiseFSM {
return Err(ProtocolError::MustBeEncrypted);
}
}
if msg_opt.is_some() {
log!("RECEIVED: {:?}", msg_opt.as_ref().unwrap());
}
match self.state {
// TODO verify that ID is zero
FSMstate::Local0 => {
@ -243,7 +278,7 @@ impl NoiseFSM {
.map_err(|e| ProtocolError::NoiseHandshakeFailed)?;
let noise = Noise::V0(NoiseV0 { data: payload });
self.sender.send(ConnectionCommand::Msg(noise.into())).await;
self.send(noise.into()).await?;
self.noise_handshake_state = Some(handshake);
@ -278,7 +313,7 @@ impl NoiseFSM {
})?;
let noise = Noise::V0(NoiseV0 { data: payload });
self.sender.send(ConnectionCommand::Msg(noise.into())).await;
self.send(noise.into()).await?;
self.noise_handshake_state = Some(handshake);
@ -309,19 +344,31 @@ impl NoiseFSM {
return Err(ProtocolError::NoiseHandshakeFailed);
}
let noise3 = ClientHello::Noise3(Noise::V0(NoiseV0 { data: payload }));
self.sender
.send(ConnectionCommand::Msg(noise3.into()))
.await;
let ciphers = handshake.get_ciphers();
match self.config.as_ref().unwrap() {
StartConfig::Client(client_config) => {
let noise3 =
ClientHello::Noise3(Noise::V0(NoiseV0 { data: payload }));
self.send(noise3.into()).await?;
self.state = FSMstate::ClientHello;
}
StartConfig::Ext(ext_config) => {
todo!();
}
StartConfig::Core(core_config) => {
todo!();
}
StartConfig::Admin(admin_config) => {
todo!();
}
}
self.noise_cipher_state_enc = Some(ciphers.0);
self.noise_cipher_state_dec = Some(ciphers.1);
self.noise_handshake_state = None;
self.state = FSMstate::ClientHello;
return Ok(StepReply::NONE);
}
}
@ -356,14 +403,14 @@ impl NoiseFSM {
let mut nonce_buf = [0u8; 32];
getrandom::getrandom(&mut nonce_buf).unwrap();
self.nonce_for_hello = nonce_buf.to_vec();
let server_hello = ServerHello::V0(ServerHelloV0 {
nonce: nonce_buf.to_vec(),
nonce: self.nonce_for_hello.clone(),
});
self.sender
.send(ConnectionCommand::Msg(server_hello.into()))
.await;
self.state = FSMstate::ServerHello;
self.send(server_hello.into()).await?;
return Ok(StepReply::NONE);
}
@ -373,9 +420,92 @@ impl NoiseFSM {
FSMstate::Noise3 => {}
FSMstate::ExtRequest => {}
FSMstate::ExtResponse => {}
FSMstate::ClientHello => {}
FSMstate::ServerHello => {}
FSMstate::ClientAuth => {}
FSMstate::ClientHello => {
if let Some(msg) = msg_opt.as_ref() {
if !self.dir.is_server() {
if let ProtocolMessage::ServerHello(hello) = msg {
if let StartConfig::Client(client_config) =
self.config.as_ref().unwrap()
{
let content = ClientAuthContentV0 {
user: client_config.user,
client: client_config.client,
/// Nonce from ServerHello
nonce: hello.nonce().clone(),
};
let ser = serde_bare::to_vec(&content)?;
let sig =
sign(client_config.client_priv, client_config.client, &ser)?;
let client_auth = ClientAuth::V0(ClientAuthV0 {
content,
/// Signature by client key
sig,
});
self.state = FSMstate::ClientAuth;
self.send(client_auth.into()).await?;
return Ok(StepReply::NONE);
}
}
}
}
}
FSMstate::ServerHello => {
if let Some(msg) = msg_opt.as_ref() {
if self.dir.is_server() {
if let ProtocolMessage::ClientAuth(client_auth) = msg {
if *client_auth.nonce() != self.nonce_for_hello {
return Err(ProtocolError::InvalidNonce);
}
let ser = serde_bare::to_vec(&client_auth.content_v0())?;
let mut result = ProtocolError::NoError;
let verif = verify(&ser, client_auth.sig(), client_auth.client());
if verif.is_err() {
result = verif.unwrap_err().into();
} else {
// TODO check that the device has been registered for this user. if not, set result = AccessDenied
}
let auth_result = AuthResult::V0(AuthResultV0 {
result: result.clone() as u16,
metadata: vec![],
});
self.send(auth_result.into()).await?;
if (result.is_err()) {
return Err(result);
}
log!("AUTHENTICATION SUCCESSFUL ! waiting for requests on the server side");
self.state = FSMstate::AuthResult;
return Ok(StepReply::NONE);
}
}
}
}
FSMstate::ClientAuth => {
if let Some(msg) = msg_opt.as_ref() {
if !self.dir.is_server() {
if let ProtocolMessage::AuthResult(auth_res) = msg {
if let StartConfig::Client(client_config) =
self.config.as_ref().unwrap()
{
if auth_res.result() != 0 {
return Err(ProtocolError::AccessDenied);
}
self.state = FSMstate::AuthResult;
log!("AUTHENTICATION SUCCESSFUL ! waiting for requests on the client side");
return Ok(StepReply::NONE);
}
}
}
}
}
FSMstate::AuthResult => {
if let Some(msg) = msg_opt {
let id = msg.id();
@ -467,12 +597,11 @@ impl ConnectionBase {
fsm: Arc<Mutex<NoiseFSM>>,
) -> ResultSend<()> {
while let Some(msg) = receiver.next().await {
log!("RECEIVED: {:?}", msg);
match msg {
ConnectionCommand::Close
| ConnectionCommand::Error(_)
| ConnectionCommand::ProtocolError(_) => {
log!("EXIT READ LOOP");
log!("EXIT READ LOOP because : {:?}", msg);
break;
}
ConnectionCommand::Msg(proto_msg) => {
@ -537,6 +666,7 @@ impl ConnectionBase {
}
}
}
log!("END OF READ LOOP");
Ok(())
}
@ -584,15 +714,20 @@ impl ConnectionBase {
self.send(ConnectionCommand::Close).await;
}
pub async fn start(&mut self) {
// BOOTSTRAP the protocol
pub async fn start(&mut self, config: StartConfig) {
// BOOTSTRAP the protocol from client-side
if !self.dir.is_server() {
let res;
let fsm = self.fsm.as_ref().unwrap();
res = fsm.lock().await.step(None).await;
{
let mut fsm = self.fsm.as_ref().unwrap().lock().await;
fsm.config = Some(config);
res = fsm.step(None).await;
}
if let Err(err) = res {
self.send(ConnectionCommand::ProtocolError(err)).await;
}
} else {
panic!("cannot call start on a server-side connection");
}
}

@ -47,7 +47,7 @@ pub enum ProtocolError {
PartialContent,
EndOfStream,
WriteError,
IoError,
WsError,
ActorError,
InvalidState,
@ -77,12 +77,17 @@ pub enum ProtocolError {
NoiseHandshakeFailed,
DecryptionError,
EncryptionError,
InvalidNonce,
} //MAX 949 ProtocolErrors
impl ProtocolError {
pub fn is_stream(&self) -> bool {
*self == ProtocolError::PartialContent || *self == ProtocolError::EndOfStream
}
pub fn is_err(&self) -> bool {
*self != ProtocolError::NoError
}
}
impl Error for ProtocolError {}

@ -1822,6 +1822,12 @@ impl ClientAuth {
}
}
impl From<ClientAuth> for ProtocolMessage {
fn from(msg: ClientAuth) -> ProtocolMessage {
ProtocolMessage::ClientAuth(msg)
}
}
/// Authentication result
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AuthResultV0 {
@ -1849,6 +1855,12 @@ impl AuthResult {
}
}
impl From<AuthResult> for ProtocolMessage {
fn from(msg: AuthResult) -> ProtocolMessage {
ProtocolMessage::AuthResult(msg)
}
}
//
// DIRECT / OUT-OF-BAND MESSAGES
//

Loading…
Cancel
Save