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 message::MessageType;
|
||||
use packet::{Packet, ReadPacketExt, WritePacketExt};
|
||||
use std::io::Write;
|
||||
use public_key::KeyPair;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum SessionState {
|
||||
enum ConnectionState {
|
||||
Initial,
|
||||
KeyExchange,
|
||||
Established,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum SessionType {
|
||||
pub enum ConnectionType {
|
||||
Server,
|
||||
Client,
|
||||
}
|
||||
|
||||
pub struct Session<W: Write> {
|
||||
stype: SessionType,
|
||||
state: SessionState,
|
||||
pub struct Connection<W: Write> {
|
||||
ctype: ConnectionType,
|
||||
state: ConnectionState,
|
||||
key_exchange: Option<Box<KeyExchange>>,
|
||||
stream: W,
|
||||
my_id: String,
|
||||
peer_id: Option<String>,
|
||||
}
|
||||
|
||||
impl<W: Write> Session<W> {
|
||||
pub fn new(stype: SessionType, stream: W) -> Session<W> {
|
||||
Session {
|
||||
stype: stype,
|
||||
state: SessionState::Initial,
|
||||
impl<W: Write> Connection<W> {
|
||||
pub fn new(ctype: ConnectionType, stream: W) -> Connection<W> {
|
||||
Connection {
|
||||
ctype: ctype,
|
||||
state: ConnectionState::Initial,
|
||||
key_exchange: None,
|
||||
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) {
|
||||
match packet.msg_type() {
|
||||
match packet.msg_type()
|
||||
{
|
||||
MessageType::KexInit => {
|
||||
println!("Starting Key Exchange!");
|
||||
self.kex_init(packet);
|
||||
}
|
||||
MessageType::KeyExchange(_) => {
|
||||
if let Some(ref mut kex) = self.key_exchange {
|
||||
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::Done(Some(packet)) => { packet.write_to(&mut self.stream); },
|
||||
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::Done(Some(packet)) => {
|
||||
packet.write_to(&mut self.stream);
|
||||
}
|
||||
KeyExchangeResult::Ok(None) |
|
||||
KeyExchangeResult::Error(None) |
|
||||
KeyExchangeResult::Done(None) => {}
|
||||
};
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
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 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 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 Host Key Algorithm: {:?}", srv_host_key_algo);
|
||||
|
|
@ -107,7 +156,7 @@ impl<W: Write> Session<W> {
|
|||
Ok(())
|
||||
});
|
||||
|
||||
self.state = SessionState::KeyExchange;
|
||||
self.state = ConnectionState::KeyExchange;
|
||||
self.key_exchange = Some(Box::new(key_exchange::Curve25519::new()));
|
||||
packet.write_to(&mut self.stream);
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ mod dh_group_sha1;
|
|||
pub use self::curve25519::Curve25519;
|
||||
pub use self::dh_group_sha1::DhGroupSha1;
|
||||
|
||||
use session::Session;
|
||||
use packet::Packet;
|
||||
|
||||
pub enum KeyExchangeResult {
|
||||
|
|
|
|||
|
|
@ -6,10 +6,9 @@ extern crate num_bigint;
|
|||
extern crate log;
|
||||
|
||||
mod algorithm;
|
||||
mod protocol;
|
||||
mod packet;
|
||||
mod message;
|
||||
mod session;
|
||||
mod connection;
|
||||
mod key_exchange;
|
||||
|
||||
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::net::TcpListener;
|
||||
use std::thread;
|
||||
|
||||
use session::{Session, SessionType};
|
||||
use connection::{Connection, ConnectionType};
|
||||
use packet::Packet;
|
||||
use public_key::KeyPair;
|
||||
use protocol;
|
||||
|
||||
pub struct ServerConfig {
|
||||
pub host: String,
|
||||
pub port: u16,
|
||||
pub key: Box<KeyPair>
|
||||
pub key: Box<KeyPair>,
|
||||
}
|
||||
|
||||
pub struct Server {
|
||||
|
|
@ -22,28 +22,32 @@ impl Server {
|
|||
}
|
||||
|
||||
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 {}:{}",
|
||||
self.config.host,
|
||||
self.config.port
|
||||
));
|
||||
|
||||
loop {
|
||||
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);
|
||||
thread::spawn(move || {
|
||||
let mut connection = Connection::new(
|
||||
ConnectionType::Server,
|
||||
stream.try_clone().unwrap(),
|
||||
);
|
||||
|
||||
let mut session = Session::new(SessionType::Server, stream.try_clone().unwrap());
|
||||
connection.run(&mut stream);
|
||||
});
|
||||
|
||||
loop {
|
||||
let packet = Packet::read_from(&mut stream).unwrap();
|
||||
println!("packet: {:?}", packet);
|
||||
session.process(&packet);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue