mirror of
https://gitlab.redox-os.org/CoffeeCode/redox-ssh.git
synced 2025-12-28 20:22:18 +01:00
Implement server host key file
This commit is contained in:
parent
0a3c2cb325
commit
5d81f21f3f
9 changed files with 102 additions and 50 deletions
|
|
@ -3,13 +3,14 @@ use std::fmt;
|
||||||
|
|
||||||
/// Slice of implemented key exchange algorithms, ordered by preference
|
/// Slice of implemented key exchange algorithms, ordered by preference
|
||||||
pub static KEY_EXCHANGE: &[KeyExchangeAlgorithm] = &[
|
pub static KEY_EXCHANGE: &[KeyExchangeAlgorithm] = &[
|
||||||
KeyExchangeAlgorithm::DH_GROUP_EXCHANGE_SHA1,
|
KeyExchangeAlgorithm::CURVE25519_SHA256,
|
||||||
// KeyExchangeAlgorithm::CURVE25519_SHA256,
|
// KeyExchangeAlgorithm::DH_GROUP_EXCHANGE_SHA1,
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Slice of implemented host key algorithms, ordered by preference
|
/// Slice of implemented host key algorithms, ordered by preference
|
||||||
pub static HOST_KEY: &[PublicKeyAlgorithm] = &[PublicKeyAlgorithm::SSH_RSA,
|
pub static HOST_KEY: &[PublicKeyAlgorithm] = &[
|
||||||
// PublicKeyAlgorithm::SSH_ED25519
|
PublicKeyAlgorithm::SSH_ED25519,
|
||||||
|
// PublicKeyAlgorithm::SSH_RSA,
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Slice of implemented encryption algorithms, ordered by preference
|
/// Slice of implemented encryption algorithms, ordered by preference
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,6 @@ use ssh::public_key;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let keypair = (public_key::ED25519.generate_key_pair)(None);
|
let keypair = (public_key::ED25519.generate_key_pair)(None);
|
||||||
let mut buffer = File::create("key.pub").unwrap();
|
let mut buffer = File::create("server.key").unwrap();
|
||||||
keypair.export(&mut buffer);
|
keypair.export(&mut buffer);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,45 @@
|
||||||
extern crate ssh;
|
extern crate ssh;
|
||||||
|
|
||||||
use std::io::{self, Write};
|
|
||||||
use std::str::FromStr;
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{self, Write};
|
||||||
use std::process;
|
use std::process;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use ssh::{Server, ServerConfig};
|
use ssh::{Server, ServerConfig};
|
||||||
|
use ssh::public_key::ED25519;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let mut quiet = false;
|
let mut quiet = false;
|
||||||
|
|
||||||
let mut config = ServerConfig::default();
|
let key_pair = File::open("server.key").and_then(
|
||||||
|
|mut f| (ED25519.import)(&mut f),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(ref err) = key_pair.as_ref().err() {
|
||||||
|
writeln!(io::stderr(), "sshd: failed to open server.key: {}", err)
|
||||||
|
.unwrap();
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut config = ServerConfig {
|
||||||
|
host: String::from("0.0.0.0"),
|
||||||
|
port: 22,
|
||||||
|
key: key_pair.unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
let mut args = env::args().skip(1);
|
let mut args = env::args().skip(1);
|
||||||
while let Some(arg) = args.next() {
|
while let Some(arg) = args.next() {
|
||||||
match arg.as_ref() {
|
match arg.as_ref()
|
||||||
|
{
|
||||||
"-q" => quiet = true,
|
"-q" => quiet = true,
|
||||||
"-p" => {
|
"-p" => {
|
||||||
config.port = u16::from_str(&args.next().expect("sshd: no argument to -p option"))
|
config.port =
|
||||||
.expect("sshd: invalid port number to -p option");
|
u16::from_str(
|
||||||
|
&args.next().expect("sshd: no argument to -p option"),
|
||||||
|
).expect("sshd: invalid port number to -p option");
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,49 @@
|
||||||
|
use crypto::curve25519::curve25519;
|
||||||
use key_exchange::{KeyExchange, KeyExchangeResult};
|
use key_exchange::{KeyExchange, KeyExchangeResult};
|
||||||
use packet::Packet;
|
use message::MessageType;
|
||||||
|
use packet::{Packet, ReadPacketExt, WritePacketExt};
|
||||||
|
use public_key::ED25519;
|
||||||
|
|
||||||
pub struct Curve25519 {
|
const ECDH_KEX_INIT: u8 = 30;
|
||||||
|
const ECDH_KEX_REPLY: u8 = 31;
|
||||||
|
|
||||||
}
|
pub struct Curve25519 {}
|
||||||
|
|
||||||
impl Curve25519 {
|
impl Curve25519 {
|
||||||
pub fn new() -> Curve25519 {
|
pub fn new() -> Curve25519 {
|
||||||
Curve25519 { }
|
Curve25519 {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KeyExchange for Curve25519 {
|
impl KeyExchange for Curve25519 {
|
||||||
fn process(&mut self, packet: &Packet) -> KeyExchangeResult {
|
fn process(&mut self, packet: &Packet) -> KeyExchangeResult {
|
||||||
KeyExchangeResult::Ok(None)
|
match packet.msg_type()
|
||||||
|
{
|
||||||
|
MessageType::KeyExchange(ECDH_KEX_INIT) => {
|
||||||
|
let mut reader = packet.reader();
|
||||||
|
let qc = reader.read_string().unwrap();
|
||||||
|
|
||||||
|
let keypair = (ED25519.generate_key_pair)(None);
|
||||||
|
let mut public_key = Vec::new();
|
||||||
|
keypair.write_public(&mut public_key);
|
||||||
|
|
||||||
|
println!("Received qc: {:?}", qc);
|
||||||
|
let mut packet =
|
||||||
|
Packet::new(MessageType::KeyExchange(ECDH_KEX_REPLY));
|
||||||
|
|
||||||
|
packet.with_writer(&|w| {
|
||||||
|
w.write_bytes(public_key.as_slice())?;
|
||||||
|
w.write_bytes(qc.as_slice())?;
|
||||||
|
w.write_bytes(&[0; 256])?;
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
KeyExchangeResult::Ok(Some(packet))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
debug!("Unhandled key exchange packet: {:?}", packet);
|
||||||
|
KeyExchangeResult::Error(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,9 @@ impl KeyExchange for DhGroupSha1 {
|
||||||
|
|
||||||
let mut packet = Packet::new(MessageType::KeyExchange(DH_GEX_GROUP));
|
let mut packet = Packet::new(MessageType::KeyExchange(DH_GEX_GROUP));
|
||||||
packet.with_writer(&|w| {
|
packet.with_writer(&|w| {
|
||||||
w.write_mpint(g.clone());
|
w.write_mpint(g.clone())?;
|
||||||
w.write_mpint(p.clone());
|
w.write_mpint(p.clone())?;
|
||||||
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
||||||
self.g = Some(g);
|
self.g = Some(g);
|
||||||
|
|
@ -71,9 +72,10 @@ impl KeyExchange for DhGroupSha1 {
|
||||||
|
|
||||||
let mut packet = Packet::new(MessageType::KeyExchange(DH_GEX_REPLY));
|
let mut packet = Packet::new(MessageType::KeyExchange(DH_GEX_REPLY));
|
||||||
packet.with_writer(&|w| {
|
packet.with_writer(&|w| {
|
||||||
w.write_string("HELLO WORLD");
|
w.write_string("HELLO WORLD")?;
|
||||||
w.write_mpint(e.clone());
|
w.write_mpint(e.clone())?;
|
||||||
w.write_string("HELLO WORLD");
|
w.write_string("HELLO WORLD")?;
|
||||||
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
||||||
self.e = Some(e);
|
self.e = Some(e);
|
||||||
|
|
|
||||||
|
|
@ -58,8 +58,8 @@ impl Packet {
|
||||||
&mut self.payload
|
&mut self.payload
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_writer(&mut self, f: &Fn(&mut Write) -> ()) {
|
pub fn with_writer(&mut self, f: &Fn(&mut Write) -> Result<()>) -> Result<()> {
|
||||||
f(&mut self.payload);
|
f(&mut self.payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reader<'a>(&'a self) -> BufReader<&'a [u8]> {
|
pub fn reader<'a>(&'a self) -> BufReader<&'a [u8]> {
|
||||||
|
|
@ -130,7 +130,7 @@ pub trait WritePacketExt: WriteBytesExt {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_bytes(&mut self, bytes: &[u8]) -> Result<()> {
|
fn write_bytes(&mut self, bytes: &[u8]) -> Result<()> {
|
||||||
self.write_u32::<BigEndian>(bytes.len() as u32)?;
|
self.write_uint32(bytes.len() as u32)?;
|
||||||
self.write_all(bytes)
|
self.write_all(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,6 +147,10 @@ pub trait WritePacketExt: WriteBytesExt {
|
||||||
self.write_bytes(bytes.as_slice())
|
self.write_bytes(bytes.as_slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_uint32(&mut self, value: u32) -> Result<()> {
|
||||||
|
self.write_u32::<BigEndian>(value as u32)
|
||||||
|
}
|
||||||
|
|
||||||
fn write_list<T: ToString>(&mut self, list: &[T]) -> Result<()> {
|
fn write_list<T: ToString>(&mut self, list: &[T]) -> Result<()> {
|
||||||
let mut string = String::new();
|
let mut string = String::new();
|
||||||
let mut iter = list.iter();
|
let mut iter = list.iter();
|
||||||
|
|
|
||||||
|
|
@ -3,20 +3,13 @@ use std::io::{self, Write};
|
||||||
|
|
||||||
use session::{Session, SessionType};
|
use session::{Session, SessionType};
|
||||||
use packet::Packet;
|
use packet::Packet;
|
||||||
|
use public_key::KeyPair;
|
||||||
use protocol;
|
use protocol;
|
||||||
|
|
||||||
pub struct ServerConfig {
|
pub struct ServerConfig {
|
||||||
pub host: String,
|
pub host: String,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
}
|
pub key: Box<KeyPair>
|
||||||
|
|
||||||
impl Default for ServerConfig {
|
|
||||||
fn default() -> ServerConfig {
|
|
||||||
ServerConfig {
|
|
||||||
host: "0.0.0.0".to_owned(),
|
|
||||||
port: 22,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
|
|
|
||||||
|
|
@ -91,23 +91,24 @@ impl<W: Write> Session<W> {
|
||||||
|
|
||||||
let mut packet = Packet::new(MessageType::KexInit);
|
let mut packet = Packet::new(MessageType::KexInit);
|
||||||
packet.with_writer(&|w| {
|
packet.with_writer(&|w| {
|
||||||
w.write_raw_bytes(cookie.as_slice());
|
w.write_raw_bytes(cookie.as_slice())?;
|
||||||
w.write_list(KEY_EXCHANGE);
|
w.write_list(KEY_EXCHANGE)?;
|
||||||
w.write_list(HOST_KEY);
|
w.write_list(HOST_KEY)?;
|
||||||
w.write_list(ENCRYPTION);
|
w.write_list(ENCRYPTION)?;
|
||||||
w.write_list(ENCRYPTION);
|
w.write_list(ENCRYPTION)?;
|
||||||
w.write_list(MAC);
|
w.write_list(MAC)?;
|
||||||
w.write_list(MAC);
|
w.write_list(MAC)?;
|
||||||
w.write_list(COMPRESSION);
|
w.write_list(COMPRESSION)?;
|
||||||
w.write_list(COMPRESSION);
|
w.write_list(COMPRESSION)?;
|
||||||
w.write_string("");
|
w.write_string("")?;
|
||||||
w.write_string("");
|
w.write_string("")?;
|
||||||
w.write_bool(false);
|
w.write_bool(false)?;
|
||||||
w.write_bytes(&[0, 0, 0, 0]);
|
w.write_uint32(0)?;
|
||||||
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
||||||
self.state = SessionState::KeyExchange;
|
self.state = SessionState::KeyExchange;
|
||||||
self.key_exchange = Some(Box::new(key_exchange::DhGroupSha1::new()));
|
self.key_exchange = Some(Box::new(key_exchange::Curve25519::new()));
|
||||||
packet.write_to(&mut self.stream);
|
packet.write_to(&mut self.stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ extern crate rand;
|
||||||
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use ssh::key::{self, CryptoSystem, KeyPair};
|
use ssh::public_key::{self, CryptoSystem, KeyPair};
|
||||||
|
|
||||||
fn test_export_import(keypair: &Box<KeyPair>) -> Box<KeyPair> {
|
fn test_export_import(keypair: &Box<KeyPair>) -> Box<KeyPair> {
|
||||||
// Export the keypair to a vector and import it again
|
// Export the keypair to a vector and import it again
|
||||||
|
|
@ -36,4 +36,4 @@ fn test_crypto_system(system: &CryptoSystem, key_size: Option<u32>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ed25519() { test_crypto_system(&key::ED25519, None); }
|
fn test_ed25519() { test_crypto_system(&public_key::ED25519, None); }
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue