mirror of
https://gitlab.redox-os.org/CoffeeCode/redox-ssh.git
synced 2025-12-28 19:02:19 +01:00
Rename Session to Connection
This commit is contained in:
parent
5d81f21f3f
commit
16c57380d7
5 changed files with 93 additions and 63 deletions
|
|
@ -1,55 +1,102 @@
|
||||||
|
use std::io::{self, BufRead, BufReader, Read, Write};
|
||||||
|
|
||||||
use key_exchange::{self, KeyExchange, KeyExchangeResult};
|
use key_exchange::{self, KeyExchange, KeyExchangeResult};
|
||||||
use message::MessageType;
|
use message::MessageType;
|
||||||
use packet::{Packet, ReadPacketExt, WritePacketExt};
|
use packet::{Packet, ReadPacketExt, WritePacketExt};
|
||||||
use std::io::Write;
|
use public_key::KeyPair;
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
enum SessionState {
|
enum ConnectionState {
|
||||||
Initial,
|
Initial,
|
||||||
KeyExchange,
|
KeyExchange,
|
||||||
Established,
|
Established,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum SessionType {
|
pub enum ConnectionType {
|
||||||
Server,
|
Server,
|
||||||
Client,
|
Client,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Session<W: Write> {
|
pub struct Connection<W: Write> {
|
||||||
stype: SessionType,
|
ctype: ConnectionType,
|
||||||
state: SessionState,
|
state: ConnectionState,
|
||||||
key_exchange: Option<Box<KeyExchange>>,
|
key_exchange: Option<Box<KeyExchange>>,
|
||||||
stream: W,
|
stream: W,
|
||||||
|
my_id: String,
|
||||||
|
peer_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Write> Session<W> {
|
impl<W: Write> Connection<W> {
|
||||||
pub fn new(stype: SessionType, stream: W) -> Session<W> {
|
pub fn new(ctype: ConnectionType, stream: W) -> Connection<W> {
|
||||||
Session {
|
Connection {
|
||||||
stype: stype,
|
ctype: ctype,
|
||||||
state: SessionState::Initial,
|
state: ConnectionState::Initial,
|
||||||
key_exchange: None,
|
key_exchange: None,
|
||||||
stream: stream,
|
stream: stream,
|
||||||
|
my_id: format!(
|
||||||
|
"SSH-2.0-RedoxSSH_{}\r\n",
|
||||||
|
env!("CARGO_PKG_VERSION")
|
||||||
|
),
|
||||||
|
peer_id: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn run(&mut self, mut stream: &mut Read) -> io::Result<()> {
|
||||||
|
self.stream.write(self.my_id.as_bytes())?;
|
||||||
|
self.peer_id = Some(self.read_id(stream)?);
|
||||||
|
|
||||||
|
if let Some(ref peer_id) = self.peer_id {
|
||||||
|
println!("Identifies as {:?}", peer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let packet = Packet::read_from(&mut stream).unwrap();
|
||||||
|
println!("packet: {:?}", packet);
|
||||||
|
self.process(&packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_id(&mut self, stream: &mut Read) -> io::Result<String> {
|
||||||
|
// The identification string has a maximum length of 255 bytes
|
||||||
|
// TODO: Make sure to stop reading if the client sends too much
|
||||||
|
|
||||||
|
let mut reader = BufReader::new(stream);
|
||||||
|
let mut id = String::new();
|
||||||
|
|
||||||
|
while !id.starts_with("SSH-") {
|
||||||
|
reader.read_line(&mut id)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(id.trim_right().to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn process(&mut self, packet: &Packet) {
|
pub fn process(&mut self, packet: &Packet) {
|
||||||
match packet.msg_type() {
|
match packet.msg_type()
|
||||||
|
{
|
||||||
MessageType::KexInit => {
|
MessageType::KexInit => {
|
||||||
println!("Starting Key Exchange!");
|
println!("Starting Key Exchange!");
|
||||||
self.kex_init(packet);
|
self.kex_init(packet);
|
||||||
}
|
}
|
||||||
MessageType::KeyExchange(_) => {
|
MessageType::KeyExchange(_) => {
|
||||||
if let Some(ref mut kex) = self.key_exchange {
|
if let Some(ref mut kex) = self.key_exchange {
|
||||||
match kex.process(packet) {
|
match kex.process(packet)
|
||||||
KeyExchangeResult::Ok(Some(packet)) => { packet.write_to(&mut self.stream); },
|
{
|
||||||
KeyExchangeResult::Error(Some(packet)) => { packet.write_to(&mut self.stream); },
|
KeyExchangeResult::Ok(Some(packet)) => {
|
||||||
KeyExchangeResult::Done(Some(packet)) => { packet.write_to(&mut self.stream); },
|
packet.write_to(&mut self.stream);
|
||||||
|
}
|
||||||
|
KeyExchangeResult::Error(Some(packet)) => {
|
||||||
|
packet.write_to(&mut self.stream);
|
||||||
|
}
|
||||||
|
KeyExchangeResult::Done(Some(packet)) => {
|
||||||
|
packet.write_to(&mut self.stream);
|
||||||
|
}
|
||||||
KeyExchangeResult::Ok(None) |
|
KeyExchangeResult::Ok(None) |
|
||||||
KeyExchangeResult::Error(None) |
|
KeyExchangeResult::Error(None) |
|
||||||
KeyExchangeResult::Done(None) => {}
|
KeyExchangeResult::Done(None) => {}
|
||||||
};
|
};
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
warn!("Received KeyExchange packet without KexInit");
|
warn!("Received KeyExchange packet without KexInit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -74,10 +121,12 @@ impl<W: Write> Session<W> {
|
||||||
let comp_algos_s2c = reader.read_enum_list::<CompressionAlgorithm>();
|
let comp_algos_s2c = reader.read_enum_list::<CompressionAlgorithm>();
|
||||||
|
|
||||||
let kex_algo = negotiate(KEY_EXCHANGE, kex_algos.unwrap().as_slice());
|
let kex_algo = negotiate(KEY_EXCHANGE, kex_algos.unwrap().as_slice());
|
||||||
let srv_host_key_algo = negotiate(HOST_KEY, srv_host_key_algos.unwrap().as_slice());
|
let srv_host_key_algo =
|
||||||
|
negotiate(HOST_KEY, srv_host_key_algos.unwrap().as_slice());
|
||||||
let enc_algo = negotiate(ENCRYPTION, enc_algos_s2c.unwrap().as_slice());
|
let enc_algo = negotiate(ENCRYPTION, enc_algos_s2c.unwrap().as_slice());
|
||||||
let mac_algo = negotiate(MAC, mac_algos_s2c.unwrap().as_slice());
|
let mac_algo = negotiate(MAC, mac_algos_s2c.unwrap().as_slice());
|
||||||
let comp_algo = negotiate(COMPRESSION, comp_algos_s2c.unwrap().as_slice());
|
let comp_algo =
|
||||||
|
negotiate(COMPRESSION, comp_algos_s2c.unwrap().as_slice());
|
||||||
|
|
||||||
println!("Negotiated Kex Algorithm: {:?}", kex_algo);
|
println!("Negotiated Kex Algorithm: {:?}", kex_algo);
|
||||||
println!("Negotiated Host Key Algorithm: {:?}", srv_host_key_algo);
|
println!("Negotiated Host Key Algorithm: {:?}", srv_host_key_algo);
|
||||||
|
|
@ -107,7 +156,7 @@ impl<W: Write> Session<W> {
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
||||||
self.state = SessionState::KeyExchange;
|
self.state = ConnectionState::KeyExchange;
|
||||||
self.key_exchange = Some(Box::new(key_exchange::Curve25519::new()));
|
self.key_exchange = Some(Box::new(key_exchange::Curve25519::new()));
|
||||||
packet.write_to(&mut self.stream);
|
packet.write_to(&mut self.stream);
|
||||||
}
|
}
|
||||||
|
|
@ -4,7 +4,6 @@ mod dh_group_sha1;
|
||||||
pub use self::curve25519::Curve25519;
|
pub use self::curve25519::Curve25519;
|
||||||
pub use self::dh_group_sha1::DhGroupSha1;
|
pub use self::dh_group_sha1::DhGroupSha1;
|
||||||
|
|
||||||
use session::Session;
|
|
||||||
use packet::Packet;
|
use packet::Packet;
|
||||||
|
|
||||||
pub enum KeyExchangeResult {
|
pub enum KeyExchangeResult {
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,9 @@ extern crate num_bigint;
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
mod algorithm;
|
mod algorithm;
|
||||||
mod protocol;
|
|
||||||
mod packet;
|
mod packet;
|
||||||
mod message;
|
mod message;
|
||||||
mod session;
|
mod connection;
|
||||||
mod key_exchange;
|
mod key_exchange;
|
||||||
|
|
||||||
pub mod public_key;
|
pub mod public_key;
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
use std::io::{Read, Write, BufReader, BufRead};
|
|
||||||
use std::io;
|
|
||||||
|
|
||||||
pub fn send_identification<W: Write>(stream: &mut W) -> io::Result<usize> {
|
|
||||||
let id = format!("SSH-2.0-RedoxSSH_{}\r\n", env!("CARGO_PKG_VERSION"));
|
|
||||||
stream.write(id.as_bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_identification<R: Read>(stream: &mut R) -> io::Result<String> {
|
|
||||||
// The identification string has a maximum length of 255 bytes
|
|
||||||
// TODO: Make sure that we stop reading when the client sends more than that
|
|
||||||
|
|
||||||
let mut reader = BufReader::new(stream);
|
|
||||||
let mut id = String::new();
|
|
||||||
|
|
||||||
while !id.starts_with("SSH-") {
|
|
||||||
reader.read_line(&mut id)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(id.trim_right().to_owned())
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
use std::net::TcpListener;
|
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
use std::net::TcpListener;
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
use session::{Session, SessionType};
|
use connection::{Connection, ConnectionType};
|
||||||
use packet::Packet;
|
use packet::Packet;
|
||||||
use public_key::KeyPair;
|
use public_key::KeyPair;
|
||||||
use protocol;
|
|
||||||
|
|
||||||
pub struct ServerConfig {
|
pub struct ServerConfig {
|
||||||
pub host: String,
|
pub host: String,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
pub key: Box<KeyPair>
|
pub key: Box<KeyPair>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
|
|
@ -22,28 +22,32 @@ impl Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&self) -> io::Result<()> {
|
pub fn run(&self) -> io::Result<()> {
|
||||||
let listener = TcpListener::bind((&*self.config.host, self.config.port)).expect(&*format!(
|
let listener = TcpListener::bind(
|
||||||
|
(&*self.config.host, self.config.port),
|
||||||
|
).expect(&*format!(
|
||||||
"sshd: failed to bind to {}:{}",
|
"sshd: failed to bind to {}:{}",
|
||||||
self.config.host,
|
self.config.host,
|
||||||
self.config.port
|
self.config.port
|
||||||
));
|
));
|
||||||
let (mut stream, addr) = listener.accept().expect(&*format!(
|
|
||||||
"sshd: failed to establish incoming connection"
|
|
||||||
));
|
|
||||||
|
|
||||||
println!("Incoming connection from {}", addr);
|
|
||||||
protocol::send_identification(&mut stream)?;
|
|
||||||
|
|
||||||
let id = protocol::read_identification(&mut stream)?;
|
|
||||||
println!("{} identifies as {}", addr, id);
|
|
||||||
|
|
||||||
let mut session = Session::new(SessionType::Server, stream.try_clone().unwrap());
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let packet = Packet::read_from(&mut stream).unwrap();
|
let (mut stream, addr) = listener.accept().expect(&*format!(
|
||||||
println!("packet: {:?}", packet);
|
"sshd: failed to establish incoming connection"
|
||||||
session.process(&packet);
|
));
|
||||||
|
|
||||||
|
println!("Incoming connection from {}", addr);
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
let mut connection = Connection::new(
|
||||||
|
ConnectionType::Server,
|
||||||
|
stream.try_clone().unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
connection.run(&mut stream);
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue