feat(auth): finish protocol 10 method 2 and 3
This commit is contained in:
parent
8a3f443d85
commit
d18ba43aed
24 changed files with 490 additions and 43 deletions
|
|
@ -1,17 +1,18 @@
|
|||
use std::io::Cursor;
|
||||
use log::error;
|
||||
use crate::nex::account::Account;
|
||||
use crate::protocols::auth::method_login_ex::login_ex;
|
||||
use crate::protocols::auth::AuthProtocolConfig;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponseResult};
|
||||
use crate::rmc::structures::any::Any;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
pub async fn login(rmcmessage: &RMCMessage, name: &str) -> RMCResponseResult{
|
||||
pub async fn login(rmcmessage: &RMCMessage, _name: &str) -> RMCResponseResult{
|
||||
|
||||
|
||||
rmcmessage.error_result_with_code(ErrorCode::Core_NotImplemented)
|
||||
}
|
||||
|
||||
pub async fn login_raw_params(rmcmessage: &RMCMessage, data: (&Account)) -> RMCResponseResult{
|
||||
pub async fn login_raw_params(rmcmessage: &RMCMessage, data: AuthProtocolConfig) -> RMCResponseResult{
|
||||
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
|
||||
|
||||
let Ok(str) = String::deserialize(&mut reader) else {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
use std::io::Cursor;
|
||||
use log::{error, info};
|
||||
use std::io::{Cursor, Write};
|
||||
use bytemuck::bytes_of;
|
||||
use hex::encode;
|
||||
use log::{error};
|
||||
use crate::grpc::account;
|
||||
use crate::kerberos::KerberosDateTime;
|
||||
use crate::nex::account::Account;
|
||||
use crate::protocols::auth::AuthProtocolConfig;
|
||||
use crate::protocols::auth::ticket_generation::generate_ticket;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponseResult};
|
||||
use crate::rmc::structures::{RmcSerialize};
|
||||
use crate::rmc::structures::any::Any;
|
||||
use crate::rmc::structures::connection_data::ConnectionData;
|
||||
use crate::rmc::structures::qresult::QResult;
|
||||
|
||||
pub async fn login_ex(rmcmessage: &RMCMessage, secure_server_account: &Account , pid: u32) -> RMCResponseResult{
|
||||
pub async fn login_ex(rmcmessage: &RMCMessage, proto_data: AuthProtocolConfig, pid: u32) -> RMCResponseResult{
|
||||
// todo: figure out how the AuthenticationInfo struct works, parse it and validate login info
|
||||
|
||||
let Ok(mut client) = account::Client::new().await else {
|
||||
|
|
@ -18,15 +25,35 @@ pub async fn login_ex(rmcmessage: &RMCMessage, secure_server_account: &Account ,
|
|||
return rmcmessage.error_result_with_code(ErrorCode::Core_Exception);
|
||||
};
|
||||
|
||||
|
||||
let source_login_data = (pid, passwd);
|
||||
let destination_login_data = proto_data.secure_server_account.get_login_data();
|
||||
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
let ticket = generate_ticket(source_login_data, destination_login_data);
|
||||
|
||||
let result = QResult::success(ErrorCode::Core_Unknown);
|
||||
|
||||
let connection_data = ConnectionData{
|
||||
station_url: proto_data.station_url,
|
||||
special_station_url: "",
|
||||
date_time: KerberosDateTime::now(),
|
||||
special_protocols: Vec::new()
|
||||
};
|
||||
|
||||
let mut response: Vec<u8> = Vec::new();
|
||||
|
||||
result.serialize(&mut response).expect("failed serializing result");
|
||||
response.write_all(bytes_of(&source_login_data.0)).expect("failed writing pid");
|
||||
ticket.serialize(&mut response).expect("failed serializing ticket");
|
||||
connection_data.serialize(&mut response).expect("failed writing connection data");
|
||||
proto_data.build_name.serialize(&mut response).expect("failed writing build name");
|
||||
|
||||
return rmcmessage.success_with_data(response);
|
||||
}
|
||||
|
||||
pub async fn login_ex_raw_params(rmcmessage: &RMCMessage, (secure_server_account): (&Account)) -> RMCResponseResult{
|
||||
pub async fn login_ex_raw_params(rmcmessage: &RMCMessage, data: AuthProtocolConfig) -> RMCResponseResult{
|
||||
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
|
||||
|
||||
let Ok(_str) = String::deserialize(&mut reader) else {
|
||||
let Ok(str) = String::deserialize(&mut reader) else {
|
||||
error!("error reading packet");
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
|
@ -50,5 +77,5 @@ pub async fn login_ex_raw_params(rmcmessage: &RMCMessage, (secure_server_account
|
|||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
login_ex(rmcmessage, secure_server_account, pid).await
|
||||
login_ex(rmcmessage, data, pid).await
|
||||
}
|
||||
53
src/protocols/auth/method_request_ticket.rs
Normal file
53
src/protocols/auth/method_request_ticket.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
use std::io::Cursor;
|
||||
use log::error;
|
||||
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use crate::grpc::account;
|
||||
use crate::protocols::auth::{AuthProtocolConfig, get_login_data_by_pid};
|
||||
use crate::protocols::auth::method_login_ex::login_ex;
|
||||
use crate::protocols::auth::ticket_generation::generate_ticket;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponseResult};
|
||||
use crate::rmc::response::ErrorCode::Core_Unknown;
|
||||
use crate::rmc::structures::any::Any;
|
||||
use crate::rmc::structures::qresult::QResult;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
pub async fn request_ticket(rmcmessage: &RMCMessage, data: AuthProtocolConfig, source_pid: u32, destination_pid: u32) -> RMCResponseResult{
|
||||
let Some(source_login_data) = get_login_data_by_pid(source_pid).await else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_Exception);
|
||||
};
|
||||
|
||||
let desgination_login_data = if destination_pid == data.secure_server_account.pid{
|
||||
data.secure_server_account.get_login_data()
|
||||
} else {
|
||||
let Some(login) = get_login_data_by_pid(destination_pid).await else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_Exception);
|
||||
};
|
||||
login
|
||||
};
|
||||
|
||||
let result = QResult::success(Core_Unknown);
|
||||
|
||||
let ticket = generate_ticket(source_login_data, desgination_login_data);
|
||||
|
||||
let mut response: Vec<u8> = Vec::new();
|
||||
|
||||
result.serialize(&mut response).expect("failed serializing result");
|
||||
ticket.serialize(&mut response).expect("failed serializing ticket");
|
||||
|
||||
rmcmessage.success_with_data(response)
|
||||
}
|
||||
|
||||
pub async fn request_ticket_raw_params(rmcmessage: &RMCMessage, data: AuthProtocolConfig) -> RMCResponseResult{
|
||||
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
|
||||
|
||||
let Ok(source_pid) = reader.read_struct(IS_BIG_ENDIAN) else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
let Ok(destination_pid) = reader.read_struct(IS_BIG_ENDIAN) else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
request_ticket(rmcmessage, data, source_pid, destination_pid).await
|
||||
}
|
||||
|
|
@ -1,18 +1,42 @@
|
|||
mod method_login_ex;
|
||||
mod method_login;
|
||||
mod ticket_generation;
|
||||
mod method_request_ticket;
|
||||
|
||||
use std::sync::Arc;
|
||||
use log::{error};
|
||||
use crate::define_protocol;
|
||||
use crate::grpc::account;
|
||||
use crate::nex::account::Account;
|
||||
use crate::protocols::auth::method_login::login_raw_params;
|
||||
use crate::protocols::auth::method_login_ex::{login_ex, login_ex_raw_params};
|
||||
use crate::protocols::auth::method_login_ex::login_ex_raw_params;
|
||||
use crate::protocols::auth::method_request_ticket::request_ticket_raw_params;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponse};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct AuthProtocolConfig {
|
||||
pub secure_server_account: &'static Account,
|
||||
pub build_name: &'static str,
|
||||
pub station_url: &'static str
|
||||
}
|
||||
|
||||
define_protocol!{
|
||||
10(secure_server_account: &'static Account) => {
|
||||
10(proto_data: AuthProtocolConfig) => {
|
||||
0x01 => login_raw_params,
|
||||
0x02 => login_ex_raw_params
|
||||
0x02 => login_ex_raw_params,
|
||||
0x03 => request_ticket_raw_params
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_login_data_by_pid(pid: u32) -> Option<(u32, [u8; 16])> {
|
||||
let Ok(mut client) = account::Client::new().await else {
|
||||
return None
|
||||
};
|
||||
|
||||
let Ok(passwd) = client.get_nex_password(pid).await else{
|
||||
return None
|
||||
};
|
||||
|
||||
Some((pid, passwd))
|
||||
}
|
||||
19
src/protocols/auth/ticket_generation.rs
Normal file
19
src/protocols/auth/ticket_generation.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
use crate::kerberos;
|
||||
use crate::kerberos::{derive_key, Ticket};
|
||||
|
||||
|
||||
pub fn generate_ticket(source_act_login_data: (u32, [u8;16]), dest_act_login_data: (u32, [u8;16])) -> Box<[u8]>{
|
||||
let source_key = derive_key(source_act_login_data.0, source_act_login_data.1);
|
||||
let dest_key = derive_key(dest_act_login_data.0, dest_act_login_data.1);
|
||||
|
||||
let internal_data = kerberos::TicketInternalData::new(source_act_login_data.0);
|
||||
|
||||
let encrypted_inner = internal_data.encrypt(dest_key);
|
||||
let encrypted_session_ticket = Ticket{
|
||||
pid: dest_act_login_data.0,
|
||||
session_key: internal_data.session_key,
|
||||
}.encrypt(source_key, &encrypted_inner);
|
||||
|
||||
|
||||
encrypted_session_ticket
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ pub mod server;
|
|||
#[macro_export]
|
||||
macro_rules! define_protocol {
|
||||
($id:literal ($($varname:ident : $ty:ty),*) => {$($func_id:literal => $func:path),*} ) => {
|
||||
#[allow(unused_parens)]
|
||||
async fn protocol (rmcmessage: &RMCMessage, $($varname : $ty),*) -> Option<RMCResponse>{
|
||||
if rmcmessage.protocol_id != $id{
|
||||
return None;
|
||||
|
|
@ -30,7 +31,7 @@ macro_rules! define_protocol {
|
|||
response_result
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(unused_parens)]
|
||||
pub fn bound_protocol($($varname : $ty,)*) -> Box<dyn for<'message_lifetime> Fn(&'message_lifetime RMCMessage) -> ::std::pin::Pin<Box<dyn ::std::future::Future<Output = Option<RMCResponse>> + Send + 'message_lifetime>> + Send + Sync>{
|
||||
Box::new(
|
||||
move |v| {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue