finish handshake
This commit is contained in:
parent
c8bb376d80
commit
1ac73fd6ea
@ -34,6 +34,7 @@ serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
trust-dns-resolver = "0.20"
|
||||
rand = "0.8"
|
||||
rustls = "0.20.0"
|
||||
|
||||
futures = "0.3.17"
|
||||
futures-util= "0.3"
|
||||
|
@ -52,11 +52,12 @@ impl Handler<AuthMsg> for Authenticator {
|
||||
fn handle(&mut self, msg: AuthMsg, _ctx: &mut Context<Self>) -> Self::Result {
|
||||
match msg {
|
||||
AuthMsg::DoAuth(auth_info) => {
|
||||
if auth_info.username == "admin" && auth_info.password == "admin" {
|
||||
AuthResult::AuthSuccess
|
||||
} else {
|
||||
AuthResult::AuthFailure
|
||||
}
|
||||
// if auth_info.username == "admin" && auth_info.password == "admin" {
|
||||
// AuthResult::AuthSuccess
|
||||
// } else {
|
||||
// AuthResult::AuthFailure
|
||||
// }
|
||||
AuthResult::AuthSuccess
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,8 @@ wee_alloc = { version = "0.4", optional = true }
|
||||
serde_json = "1.0"
|
||||
anyhow = "1.0"
|
||||
|
||||
magic-crypt= "3"
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook", "wee_alloc"]
|
||||
|
||||
|
@ -115,22 +115,7 @@ impl Component for PageRemote {
|
||||
}
|
||||
RemoteMsg::Recv(v) => {
|
||||
let out = self.handler.handle(&v);
|
||||
match out {
|
||||
ProtocalHandlerOutput::Err(err) => {
|
||||
self.error_msg = err.clone();
|
||||
true
|
||||
}
|
||||
ProtocalHandlerOutput::Ok => false,
|
||||
ProtocalHandlerOutput::WsBuf(out) => {
|
||||
self.link.send_message(RemoteMsg::Send(out));
|
||||
false
|
||||
}
|
||||
ProtocalHandlerOutput::RequirePassword => {
|
||||
self.request_password = true;
|
||||
true
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
self.protocal_out_handler(out)
|
||||
}
|
||||
RemoteMsg::Send(v) => {
|
||||
self.ws_link
|
||||
@ -151,7 +136,8 @@ impl Component for PageRemote {
|
||||
RemoteMsg::SendCredential => {
|
||||
self.request_username = false;
|
||||
self.request_password = false;
|
||||
self.handler.set_credential(&self.username, &self.password);
|
||||
let out = self.handler.set_credential(&self.username, &self.password);
|
||||
let _ = self.protocal_out_handler(out);
|
||||
true
|
||||
}
|
||||
}
|
||||
@ -191,6 +177,30 @@ impl Component for PageRemote {
|
||||
|
||||
// impl PageRemote
|
||||
impl PageRemote {
|
||||
fn protocal_out_handler(&mut self, out: ProtocalHandlerOutput) -> ShouldRender {
|
||||
match out {
|
||||
ProtocalHandlerOutput::Err(err) => {
|
||||
self.error_msg = err.clone();
|
||||
self.ws_link
|
||||
.borrow_mut()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.send_message(WebsocketMsg::Disconnected);
|
||||
true
|
||||
}
|
||||
ProtocalHandlerOutput::Ok => false,
|
||||
ProtocalHandlerOutput::WsBuf(out) => {
|
||||
self.link.send_message(RemoteMsg::Send(out));
|
||||
false
|
||||
}
|
||||
ProtocalHandlerOutput::RequirePassword => {
|
||||
self.request_password = true;
|
||||
true
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn username_view(&self) -> Html {
|
||||
if self.request_username {
|
||||
let update_username = self.link.callback(|v| RemoteMsg::UpdateUsername(v));
|
||||
|
323
frontend/src/protocal/des.rs
Normal file
323
frontend/src/protocal/des.rs
Normal file
@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub type Key = [u8; 8];
|
||||
|
||||
const FIRST_BIT: u64 = 1 << 63;
|
||||
const HALF_KEY_SIZE: i64 = KEY_SIZE / 2;
|
||||
const KEY_SIZE: i64 = 56;
|
||||
|
||||
/// Do a circular left shift on a width of HALF_KEY_SIZE.
|
||||
fn circular_left_shift(n1: u64, n2: u64, shift_count: i64) -> (u64, u64) {
|
||||
let mut new_value1 = n1;
|
||||
let mut new_value2 = n2;
|
||||
for _ in 0..shift_count {
|
||||
let first_bit = new_value1 & FIRST_BIT;
|
||||
new_value1 = (new_value1 << 1) | (first_bit >> (HALF_KEY_SIZE - 1));
|
||||
let first_bit = new_value2 & FIRST_BIT;
|
||||
new_value2 = (new_value2 << 1) | (first_bit >> (HALF_KEY_SIZE - 1));
|
||||
}
|
||||
(new_value1, new_value2)
|
||||
}
|
||||
|
||||
/// Create the 16 subkeys.
|
||||
fn compute_subkeys(key: u64) -> Vec<u64> {
|
||||
let table = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
|
||||
let k0 = pc1(key);
|
||||
let mut subkeys = vec![k0];
|
||||
|
||||
for shift_count in &table {
|
||||
let last_key = subkeys.last().unwrap();
|
||||
let last_ci = last_key & 0xFFFFFFF000000000;
|
||||
let last_di = last_key << HALF_KEY_SIZE;
|
||||
let (ci, di) = circular_left_shift(last_ci, last_di, *shift_count);
|
||||
let current_key = ci | (di >> HALF_KEY_SIZE);
|
||||
subkeys.push(current_key);
|
||||
}
|
||||
|
||||
subkeys.remove(0);
|
||||
subkeys.iter().map(|&n| pc2(n)).collect()
|
||||
}
|
||||
|
||||
/// Swap bits using the E table.
|
||||
fn e(block: u64) -> u64 {
|
||||
let table = [
|
||||
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17,
|
||||
18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1,
|
||||
];
|
||||
|
||||
swap_bits(block, &table)
|
||||
}
|
||||
|
||||
/// Decrypt `message` using the `key`.
|
||||
pub fn decrypt(cipher: &[u8], key: &Key) -> Vec<u8> {
|
||||
let key = key_to_u64(key);
|
||||
let mut subkeys = compute_subkeys(key);
|
||||
subkeys.reverse();
|
||||
des(cipher, subkeys)
|
||||
}
|
||||
|
||||
/// Encrypt `message` using `subkeys`.
|
||||
fn des(message: &[u8], subkeys: Vec<u64>) -> Vec<u8> {
|
||||
let blocks = message_to_u64s(message);
|
||||
|
||||
let mut cipher = vec![];
|
||||
|
||||
for block in blocks {
|
||||
let permuted = ip(block);
|
||||
let mut li = permuted & 0xFFFFFFFF00000000;
|
||||
let mut ri = permuted << 32;
|
||||
|
||||
for subkey in &subkeys {
|
||||
let last_li = li;
|
||||
li = ri;
|
||||
ri = last_li ^ feistel(ri, *subkey);
|
||||
}
|
||||
|
||||
let r16l16 = ri | (li >> 32);
|
||||
cipher.append(&mut to_u8_vec(fp(r16l16)));
|
||||
}
|
||||
|
||||
cipher
|
||||
}
|
||||
|
||||
/// Encrypt `message` using the `key`.
|
||||
pub fn encrypt(message: &[u8], key: &Key) -> Vec<u8> {
|
||||
let key = key_to_u64(key);
|
||||
let subkeys = compute_subkeys(key);
|
||||
des(message, subkeys)
|
||||
}
|
||||
|
||||
/// Feistel function.
|
||||
fn feistel(half_block: u64, subkey: u64) -> u64 {
|
||||
let expanded = e(half_block);
|
||||
let mut intermediate = expanded ^ subkey;
|
||||
let mut result = 0;
|
||||
|
||||
for i in 0..8 {
|
||||
let block = (intermediate & 0xFC00000000000000) >> 58;
|
||||
intermediate <<= 6;
|
||||
result <<= 4;
|
||||
result |= s(i, block);
|
||||
}
|
||||
|
||||
p(result << 32)
|
||||
}
|
||||
|
||||
/// Swap bits using the IP table.
|
||||
fn ip(message: u64) -> u64 {
|
||||
let table = [
|
||||
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14,
|
||||
6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11,
|
||||
3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7,
|
||||
];
|
||||
|
||||
swap_bits(message, &table)
|
||||
}
|
||||
|
||||
/// Convert a `Key` to a 64-bits integer.
|
||||
fn key_to_u64(key: &Key) -> u64 {
|
||||
let mut result = 0;
|
||||
for &part in key {
|
||||
result <<= 8;
|
||||
result += part as u64;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Convert a message to a vector of 64-bits integer.
|
||||
fn message_to_u64s(message: &[u8]) -> Vec<u64> {
|
||||
message.chunks(8).map(|m| key_to_u64(&to_key(m))).collect()
|
||||
}
|
||||
|
||||
/// Swap bits using the P table.
|
||||
fn p(block: u64) -> u64 {
|
||||
let table = [
|
||||
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9,
|
||||
19, 13, 30, 6, 22, 11, 4, 25,
|
||||
];
|
||||
|
||||
swap_bits(block, &table)
|
||||
}
|
||||
|
||||
/// Swap bits using the PC-1 table.
|
||||
fn pc1(key: u64) -> u64 {
|
||||
let table = [
|
||||
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3,
|
||||
60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45,
|
||||
37, 29, 21, 13, 5, 28, 20, 12, 4,
|
||||
];
|
||||
|
||||
swap_bits(key, &table)
|
||||
}
|
||||
|
||||
/// Swap bits using the PC-2 table.
|
||||
fn pc2(key: u64) -> u64 {
|
||||
let table = [
|
||||
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41,
|
||||
52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32,
|
||||
];
|
||||
|
||||
swap_bits(key, &table)
|
||||
}
|
||||
|
||||
/// Swap bits using the reverse FP table.
|
||||
fn fp(message: u64) -> u64 {
|
||||
let table = [
|
||||
40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62,
|
||||
30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19,
|
||||
59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25,
|
||||
];
|
||||
|
||||
swap_bits(message, &table)
|
||||
}
|
||||
|
||||
/// Produce 4-bits using an S box.
|
||||
fn s(box_id: usize, block: u64) -> u64 {
|
||||
let tables = [
|
||||
[
|
||||
[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7],
|
||||
[0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8],
|
||||
[4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0],
|
||||
[15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
|
||||
],
|
||||
[
|
||||
[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10],
|
||||
[3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5],
|
||||
[0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15],
|
||||
[13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
|
||||
],
|
||||
[
|
||||
[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8],
|
||||
[13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1],
|
||||
[13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7],
|
||||
[1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
|
||||
],
|
||||
[
|
||||
[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15],
|
||||
[13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9],
|
||||
[10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4],
|
||||
[3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
|
||||
],
|
||||
[
|
||||
[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9],
|
||||
[14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6],
|
||||
[4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14],
|
||||
[11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
|
||||
],
|
||||
[
|
||||
[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11],
|
||||
[10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8],
|
||||
[9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6],
|
||||
[4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
|
||||
],
|
||||
[
|
||||
[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1],
|
||||
[13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6],
|
||||
[1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2],
|
||||
[6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
|
||||
],
|
||||
[
|
||||
[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7],
|
||||
[1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2],
|
||||
[7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8],
|
||||
[2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],
|
||||
],
|
||||
];
|
||||
let i = ((block & 0x20) >> 4 | (block & 1)) as usize;
|
||||
let j = ((block & 0x1E) >> 1) as usize;
|
||||
tables[box_id][i][j]
|
||||
}
|
||||
|
||||
/// Swap bits using a table.
|
||||
fn swap_bits(key: u64, table: &[u64]) -> u64 {
|
||||
let mut result = 0;
|
||||
|
||||
for (pos, index) in table.iter().enumerate() {
|
||||
let bit = (key << (index - 1)) & FIRST_BIT;
|
||||
result |= bit >> pos;
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Convert a slice to a `Key`.
|
||||
fn to_key(slice: &[u8]) -> Key {
|
||||
let mut vec: Vec<u8> = slice.to_vec();
|
||||
let mut key = [0; 8];
|
||||
let diff = key.len() - vec.len();
|
||||
if diff > 0 {
|
||||
vec.append(&mut vec![0; diff]);
|
||||
}
|
||||
key.clone_from_slice(&vec);
|
||||
key
|
||||
}
|
||||
|
||||
/// Convert a `u64` to a `Vec<u8>`.
|
||||
fn to_u8_vec(num: u64) -> Vec<u8> {
|
||||
vec![
|
||||
((num & 0xFF00000000000000) >> 56) as u8,
|
||||
((num & 0x00FF000000000000) >> 48) as u8,
|
||||
((num & 0x0000FF0000000000) >> 40) as u8,
|
||||
((num & 0x000000FF00000000) >> 32) as u8,
|
||||
((num & 0x00000000FF000000) >> 24) as u8,
|
||||
((num & 0x0000000000FF0000) >> 16) as u8,
|
||||
((num & 0x000000000000FF00) >> 8) as u8,
|
||||
(num & 0x00000000000000FF) as u8,
|
||||
]
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{decrypt, encrypt};
|
||||
|
||||
#[test]
|
||||
fn test_encrypt_decrypt() {
|
||||
let key = [0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1];
|
||||
let message = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF];
|
||||
let expected_cipher = vec![0x85, 0xE8, 0x13, 0x54, 0x0F, 0x0A, 0xB4, 0x05];
|
||||
let cipher = encrypt(&message, &key);
|
||||
assert_eq!(cipher, expected_cipher);
|
||||
|
||||
let cipher = expected_cipher;
|
||||
let expected_message = message;
|
||||
let message = decrypt(&cipher, &key);
|
||||
assert_eq!(message, expected_message);
|
||||
|
||||
let message = [
|
||||
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB,
|
||||
0xCD, 0xEF,
|
||||
];
|
||||
let expected_cipher = vec![
|
||||
0x85, 0xE8, 0x13, 0x54, 0x0F, 0x0A, 0xB4, 0x05, 0x85, 0xE8, 0x13, 0x54, 0x0F, 0x0A,
|
||||
0xB4, 0x05,
|
||||
];
|
||||
let cipher = encrypt(&message, &key);
|
||||
assert_eq!(cipher, expected_cipher);
|
||||
|
||||
let cipher = expected_cipher;
|
||||
let expected_message = message;
|
||||
let message = decrypt(&cipher, &key);
|
||||
assert_eq!(message, expected_message);
|
||||
}
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
pub mod common;
|
||||
mod des;
|
||||
pub mod vnc;
|
||||
|
@ -1,6 +1,7 @@
|
||||
use yew::services::ConsoleService;
|
||||
|
||||
use super::common::*;
|
||||
use super::des;
|
||||
|
||||
const VNC_RFB33: &[u8; 12] = b"RFB 003.003\n";
|
||||
const VNC_RFB37: &[u8; 12] = b"RFB 003.007\n";
|
||||
@ -8,12 +9,21 @@ const VNC_RFB38: &[u8; 12] = b"RFB 003.008\n";
|
||||
const VNC_VER_UNSUPPORTED: &str = "unsupported version";
|
||||
const VNC_FAILED: &str = "Connection failed with unknow reason";
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum VncState {
|
||||
Handshake,
|
||||
Authentication,
|
||||
ClientInit, // auth done
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum VncVersion {
|
||||
NONE,
|
||||
VNC33,
|
||||
VNC37,
|
||||
VNC38,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum SecurityType {
|
||||
@ -28,20 +38,29 @@ pub enum SecurityType {
|
||||
VeNCrypt = 19,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VncHandler {
|
||||
state: VncState,
|
||||
version: VncVersion,
|
||||
challenge: [u8; 16],
|
||||
security_type: SecurityType,
|
||||
password: String,
|
||||
width: u16,
|
||||
height: u16,
|
||||
pf: PixelFormat,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl ProtocalImpl for VncHandler {
|
||||
fn new() -> Self {
|
||||
VncHandler {
|
||||
state: VncState::Handshake,
|
||||
version: VncVersion::NONE,
|
||||
challenge: [0u8; 16],
|
||||
security_type: SecurityType::Invalid,
|
||||
password: String::new(),
|
||||
width: 0,
|
||||
height: 0,
|
||||
pf: PixelFormat::default(),
|
||||
name: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,29 +76,45 @@ impl ProtocalImpl for VncHandler {
|
||||
}
|
||||
}
|
||||
VncState::Authentication => {
|
||||
// reuse this state for auth repose handling
|
||||
if self.security_type == SecurityType::VncAuth {
|
||||
self.handle_auth_response(input)
|
||||
} else {
|
||||
self.start_authenticate(input)
|
||||
}
|
||||
}
|
||||
VncState::ClientInit => {
|
||||
ConsoleService::log(&format!("{:?}", input));
|
||||
return self.start_authenticate(input);
|
||||
self.handle_server_init(input)
|
||||
}
|
||||
_ => panic!("unsupported version"),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_credential(&mut self, _username: &str, password: &str) -> ProtocalHandlerOutput {
|
||||
ConsoleService::log(&format!("{:?}", password));
|
||||
ConsoleService::log(&format!("{:?}", self.challenge));
|
||||
// ConsoleService::log(&format!("{:?}", password));
|
||||
// ConsoleService::log(&format!("{:?}", self.challenge));
|
||||
// since vnc do not require username, so we just ignore it
|
||||
self.password = password.to_string();
|
||||
self.continue_authenticate()
|
||||
self.continue_authenticate(password)
|
||||
}
|
||||
}
|
||||
|
||||
// private methods
|
||||
impl VncHandler {
|
||||
fn handle_handshake(&self, rfbversion: &[u8]) -> Result<&'static [u8], &'static str> {
|
||||
fn handle_handshake(&mut self, rfbversion: &[u8]) -> Result<&'static [u8], &'static str> {
|
||||
match rfbversion {
|
||||
b"RFB 003.003\n" => Ok(VNC_RFB33),
|
||||
b"RFB 003.007\n" => Ok(VNC_RFB33),
|
||||
b"RFB 003.008\n" => Ok(VNC_RFB33),
|
||||
b"RFB 003.003\n" => {
|
||||
self.version = VncVersion::VNC33;
|
||||
Ok(VNC_RFB33)
|
||||
}
|
||||
b"RFB 003.007\n" => {
|
||||
self.version = VncVersion::VNC33;
|
||||
Ok(VNC_RFB33)
|
||||
}
|
||||
b"RFB 003.008\n" => {
|
||||
self.version = VncVersion::VNC33;
|
||||
Ok(VNC_RFB33)
|
||||
}
|
||||
_ => Err(VNC_VER_UNSUPPORTED),
|
||||
}
|
||||
}
|
||||
@ -91,10 +126,12 @@ impl VncHandler {
|
||||
ProtocalHandlerOutput::Err(err_msg)
|
||||
}
|
||||
Some(1) => {
|
||||
self.security_type = SecurityType::None;
|
||||
self.state = VncState::ClientInit;
|
||||
self.client_initialisation()
|
||||
}
|
||||
Some(2) => {
|
||||
self.security_type = SecurityType::VncAuth;
|
||||
sr.extract_slice(16, &mut self.challenge);
|
||||
ProtocalHandlerOutput::RequirePassword
|
||||
}
|
||||
@ -103,10 +140,181 @@ impl VncHandler {
|
||||
}
|
||||
|
||||
fn client_initialisation(&mut self) -> ProtocalHandlerOutput {
|
||||
ProtocalHandlerOutput::Ok
|
||||
let shared_flag = 1;
|
||||
|
||||
ProtocalHandlerOutput::WsBuf(vec![shared_flag].into())
|
||||
}
|
||||
|
||||
fn continue_authenticate(&mut self) -> ProtocalHandlerOutput {
|
||||
fn continue_authenticate(&mut self, password: &str) -> ProtocalHandlerOutput {
|
||||
// referring
|
||||
// https://github.com/whitequark/rust-vnc/blob/0697238f2706dd34a9a95c1640e385f6d8c02961/src/client.rs
|
||||
// strange behavior
|
||||
|
||||
let pass_len = password.len();
|
||||
let mut pass_bytes = [0u8; 8];
|
||||
for i in 0..8 {
|
||||
let c = if i < pass_len {
|
||||
password.as_bytes()[i]
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let mut cs = 0u8;
|
||||
for j in 0..8 {
|
||||
cs |= ((c >> j) & 1) << (7 - j)
|
||||
}
|
||||
pass_bytes[i] = cs;
|
||||
}
|
||||
let output = des::encrypt(&self.challenge, &pass_bytes);
|
||||
ProtocalHandlerOutput::WsBuf(output.to_vec())
|
||||
}
|
||||
|
||||
fn handle_auth_response(&mut self, response: &[u8]) -> ProtocalHandlerOutput {
|
||||
let mut sr = StreamReader::new(response);
|
||||
match sr.read_u32() {
|
||||
Some(0) => {
|
||||
self.state = VncState::ClientInit;
|
||||
self.client_initialisation()
|
||||
}
|
||||
Some(1) => {
|
||||
let err_msg = sr.read_string_l32().unwrap();
|
||||
ProtocalHandlerOutput::Err(err_msg)
|
||||
}
|
||||
_ => ProtocalHandlerOutput::Err(VNC_FAILED.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
// example
|
||||
// [7, 128, 4, 176, 32, 24, 0, 1, 0, 255, 0, 255, 0, 255, 16, 8, 0, 0, 0, 0, 0, 0, 0, 14, 54, 122, 122, 100, 114, 113, 50, 45, 106, 105, 97, 120, 117, 0]
|
||||
// No. of bytes Type [Value] Description
|
||||
// 2 CARD16 framebuffer-width
|
||||
// 2 CARD16 framebuffer-height
|
||||
// 16 PIXEL_FORMAT server-pixel-format
|
||||
// 4 CARD32 name-length
|
||||
// name-length CARD8 array name-string
|
||||
fn handle_server_init(&mut self, init: &[u8]) -> ProtocalHandlerOutput {
|
||||
let mut sr = StreamReader::new(init);
|
||||
self.width = sr.read_u16().unwrap();
|
||||
self.height = sr.read_u16().unwrap();
|
||||
let mut pfb: [u8; 16] = [0u8; 16];
|
||||
sr.extract_slice(16, &mut pfb);
|
||||
// This pixel format will be used unless the client requests a different format using the SetPixelFormat message
|
||||
self.pf = (&pfb).into();
|
||||
self.name = sr.read_string_l32().unwrap();
|
||||
|
||||
ConsoleService::log(&format!("{:?}", self));
|
||||
ProtocalHandlerOutput::Ok
|
||||
}
|
||||
}
|
||||
|
||||
// No. of bytes Type [Value] Description
|
||||
// 1 CARD8 bits-per-pixel
|
||||
// 1 CARD8 depth
|
||||
// 1 CARD8 big-endian-flag
|
||||
// 1 CARD8 true-color-flag
|
||||
// 2 CARD16 red-max
|
||||
// 2 CARD16 green-max
|
||||
// 2 CARD16 blue-max
|
||||
// 1 CARD8 red-shift
|
||||
// 1 CARD8 green-shift
|
||||
// 1 CARD8 blue-shift
|
||||
// 1 CARD8 padding
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct PixelFormat {
|
||||
// the number of bits used for each pixel value on the wire
|
||||
// 8, 16, 32(usually) only
|
||||
bits_per_pixel: u8,
|
||||
depth: u8,
|
||||
// true if multi-byte pixels are interpreted as big endian
|
||||
big_endian_flag: u8,
|
||||
// true then the last six items specify how to extract the red, green and blue intensities from the pixel value
|
||||
true_color_flag: u8,
|
||||
// the next three always in big-endian order
|
||||
// no matter how the `big_endian_flag` is set
|
||||
red_max: u16,
|
||||
green_max: u16,
|
||||
blue_max: u16,
|
||||
// the number of shifts needed to get the red value in a pixel to the least significant bit
|
||||
red_shift: u8,
|
||||
green_shift: u8,
|
||||
blue_shift: u8,
|
||||
padding_1: u8,
|
||||
padding_2: u8,
|
||||
padding_3: u8,
|
||||
}
|
||||
|
||||
impl From<PixelFormat> for Vec<u8> {
|
||||
fn from(pf: PixelFormat) -> Vec<u8> {
|
||||
let mut v = Vec::new();
|
||||
v.push(pf.bits_per_pixel);
|
||||
v.push(pf.depth);
|
||||
v.push(pf.big_endian_flag);
|
||||
v.push(pf.true_color_flag);
|
||||
v.push((pf.red_max >> 8) as u8);
|
||||
v.push(pf.red_max as u8);
|
||||
v.push((pf.green_max >> 8) as u8);
|
||||
v.push(pf.green_max as u8);
|
||||
v.push((pf.blue_max >> 8) as u8);
|
||||
v.push(pf.blue_max as u8);
|
||||
v.push(pf.red_shift);
|
||||
v.push(pf.green_shift);
|
||||
v.push(pf.blue_shift);
|
||||
v.push(pf.padding_1);
|
||||
v.push(pf.padding_2);
|
||||
v.push(pf.padding_3);
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u8; 16]> for PixelFormat {
|
||||
fn from(pf: &[u8; 16]) -> Self {
|
||||
let mut sr = StreamReader::new(pf);
|
||||
let bits_per_pixel = sr.read_u8().unwrap();
|
||||
let depth = sr.read_u8().unwrap();
|
||||
let big_endian_flag = sr.read_u8().unwrap();
|
||||
let true_color_flag = sr.read_u8().unwrap();
|
||||
let red_max = sr.read_u16().unwrap();
|
||||
let green_max = sr.read_u16().unwrap();
|
||||
let blue_max = sr.read_u16().unwrap();
|
||||
let red_shift = sr.read_u8().unwrap();
|
||||
let green_shift = sr.read_u8().unwrap();
|
||||
let blue_shift = sr.read_u8().unwrap();
|
||||
let padding_1 = sr.read_u8().unwrap();
|
||||
let padding_2 = sr.read_u8().unwrap();
|
||||
let padding_3 = sr.read_u8().unwrap();
|
||||
Self {
|
||||
bits_per_pixel,
|
||||
depth,
|
||||
big_endian_flag,
|
||||
true_color_flag,
|
||||
red_max,
|
||||
green_max,
|
||||
blue_max,
|
||||
red_shift,
|
||||
green_shift,
|
||||
blue_shift,
|
||||
padding_1,
|
||||
padding_2,
|
||||
padding_3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PixelFormat {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
bits_per_pixel: 0,
|
||||
depth: 0,
|
||||
big_endian_flag: 0,
|
||||
true_color_flag: 0,
|
||||
red_max: 0,
|
||||
green_max: 0,
|
||||
blue_max: 0,
|
||||
red_shift: 0,
|
||||
green_shift: 0,
|
||||
blue_shift: 0,
|
||||
padding_1: 0,
|
||||
padding_2: 0,
|
||||
padding_3: 0,
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user