// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers // All rights reserved. // Licensed under the Apache License, Version 2.0 // // or the MIT license , // at your option. All files in the project carrying such // notice may not be copied, modified, or distributed except // according to those terms. #[macro_use] extern crate slice_as_array; pub mod types; mod cli; use crate::cli::*; use clap::Parser; use p2p_broker::server_ws::run_server; use p2p_broker::utils::*; use p2p_net::utils::{gen_keys, keys_from_bytes, Dual25519Keys, Sensitive, U8Array}; use p2p_net::WS_PORT; use p2p_repo::log::*; use p2p_repo::{ types::{PrivKey, PubKey}, utils::{generate_keypair, keypair_from_ed, sign, verify}, }; use std::fs::{read_to_string, write}; use std::io::Read; use std::io::Write; use std::io::{BufReader, ErrorKind}; use std::path::{Path, PathBuf}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum InterfaceType { Loopback, Private, Public, Invalid, } pub fn print_ipv4(ip: &default_net::ip::Ipv4Net) -> String { format!("{}/{}", ip.addr, ip.prefix_len) } pub fn print_ipv6(ip: &default_net::ip::Ipv6Net) -> String { format!("{}/{}", ip.addr, ip.prefix_len) } pub struct Interface { pub if_type: InterfaceType, pub name: String, pub mac_addr: Option, /// List of Ipv4Net for the network interface pub ipv4: Vec, /// List of Ipv6Net for the network interface pub ipv6: Vec, } pub fn get_interface() -> Vec { let mut res: Vec = vec![]; let interfaces = default_net::get_interfaces(); for interface in interfaces { if interface.ipv4.len() > 0 { let first_v4 = interface.ipv4[0].addr; let if_type = if first_v4.is_loopback() { InterfaceType::Loopback } else if first_v4.is_private() || first_v4.is_link_local() { InterfaceType::Private } else if !first_v4.is_unspecified() && !first_v4.is_documentation() && !first_v4.is_broadcast() && !first_v4.is_multicast() { InterfaceType::Public } else { InterfaceType::Invalid }; if if_type == InterfaceType::Invalid { continue; } let interf = Interface { if_type, name: interface.name, mac_addr: interface.mac_addr, ipv4: interface.ipv4, ipv6: interface.ipv6, }; res.push(interf); } } res } pub fn print_interfaces() { let interfaces = get_interface(); for interface in interfaces { println!("{} \t{:?}", interface.name, interface.if_type); println!( "\tIPv4: {}", interface .ipv4 .iter() .map(|ip| print_ipv4(ip)) .collect::>() .join(" ") ); println!( "\tIPv6: {}", interface .ipv6 .iter() .map(|ip| print_ipv6(ip)) .collect::>() .join(" ") ); if let Some(mac_addr) = interface.mac_addr { println!("\tMAC: {}", mac_addr); } } } fn decode_key(key_string: String) -> Result<[u8; 32], ()> { let vec = base64_url::decode(&key_string).map_err(|_| log_err!("key has invalid content"))?; Ok(*slice_as_array!(&vec, [u8; 32]) .ok_or(()) .map_err(|_| log_err!("key has invalid content array"))?) } #[async_std::main] async fn main() -> std::io::Result<()> { let args = Cli::parse(); if args.list_interfaces { println!("list of network interfaces"); print_interfaces(); return Ok(()); } if std::env::var("RUST_LOG").is_err() { if args.verbose == 0 { std::env::set_var("RUST_LOG", "warn"); } else if args.verbose == 1 { std::env::set_var("RUST_LOG", "info"); } else if args.verbose == 2 { std::env::set_var("RUST_LOG", "debug"); } else if args.verbose >= 3 { std::env::set_var("RUST_LOG", "trace"); } } env_logger::init(); log_info!("Starting NextGraph daemon (ngd)"); log_debug!("base {:?}", args.base); let mut path = PathBuf::from(&args.base); path.push("server"); if !path.is_absolute() { path = std::env::current_dir().unwrap().join(path); } log_debug!("cur {}", std::env::current_dir().unwrap().display()); log_debug!("home {}", path.to_str().unwrap()); std::fs::create_dir_all(path.clone()).unwrap(); // reading key from file, if any let mut key_path = path.clone(); key_path.push("key"); let key_from_file: Option<[u8; 32]>; let res = |key_path| -> Result<[u8; 32], &str> { let file = read_to_string(key_path).map_err(|_| "")?; decode_key( file.lines() .nth(0) .ok_or("empty file")? .to_string() .trim() .to_string(), ) .map_err(|_| "invalid file") }(&key_path); if res.is_err() && res.unwrap_err().len() > 0 { log_err!( "provided key file is incorrect. {}. aborting start", res.unwrap_err() ); return Err(ErrorKind::InvalidInput.into()); } key_from_file = match res { Err(_) => None, Ok(k) => Some(k), }; let keys: [[u8; 32]; 4] = match args.key { Some(key_string) => { if key_from_file.is_some() { log_err!("provided key option will not be used as a key file is already present"); gen_broker_keys(Some(key_from_file.unwrap())) } else { let res = decode_key(key_string); if res.is_err() { log_err!("provided key is invalid. cannot start"); return Err(ErrorKind::InvalidInput.into()); } if args.save_key { let master_key = base64_url::encode(&res.unwrap()); if let Err(e) = write(key_path.clone(), master_key) { log_err!("cannot save key to file. aborting start"); return Err(e); } log_info!("The key has been saved to {}", key_path.to_str().unwrap()); } gen_broker_keys(Some(res.unwrap())) } } None => { if key_from_file.is_some() { gen_broker_keys(Some(key_from_file.unwrap())) } else { let res = gen_broker_keys(None); let master_key = base64_url::encode(&res[0]); if args.save_key { if let Err(e) = write(key_path.clone(), master_key) { log_err!("cannot save key to file. aborting start"); return Err(e); } log_info!("The key has been saved to {}", key_path.to_str().unwrap()); } else { // on purpose we don't log the key, just print it out stdout, as it should be saved in logger's files println!("YOUR GENERATED KEY IS: {}", master_key); log_err!("At your request, the key wasn't saved."); log_err!("provide it again to the next start of ngd with --key option or NG_SERVER_KEY env variable"); } res } } }; println!("{:?}", keys); // let keys = gen_keys(); // let pub_key = PubKey::Ed25519PubKey(keys.1); // let (ed_priv_key, ed_pub_key) = generate_keypair(); // let duals = Dual25519Keys::generate(); // let eds = keypair_from_ed(duals.ed25519_priv, duals.ed25519_pub); // let test_vector: Vec = vec![71, 51, 206, 126, 9, 84, 132]; // let sig = sign(eds.0, eds.1, &test_vector).unwrap(); // verify(&test_vector, sig, eds.1).unwrap(); // let privkey = duals.x25519_priv; // let pubkey = PubKey::Ed25519PubKey(duals.x25519_public); // log_debug!("Public key of node: {:?}", keys.1); // log_debug!("Private key of node: {:?}", keys.0.as_slice()); let (privkey, pubkey) = keys_from_bytes(keys[1]); // let pubkey = PubKey::Ed25519PubKey([ // 95, 155, 249, 202, 41, 105, 71, 51, 206, 126, 9, 84, 132, 92, 60, 7, 74, 179, 46, 21, 21, // 242, 171, 27, 249, 79, 76, 176, 168, 43, 83, 2, // ]); // let privkey = Sensitive::<[u8; 32]>::from_slice(&[ // 56, 86, 36, 0, 109, 59, 152, 66, 166, 71, 201, 20, 119, 64, 173, 99, 215, 52, 40, 189, 96, // 142, 3, 134, 167, 187, 235, 4, 39, 26, 31, 119, // ]); log_debug!("Public key of node: {:?}", pubkey); log_debug!("Private key of node: {:?}", privkey.as_slice()); run_server("127.0.0.1", WS_PORT, privkey, pubkey, path).await?; Ok(()) }