parent
01c1c8a436
commit
5090a845fd
@ -0,0 +1,183 @@ |
||||
use std::{fmt::format, io::Read}; |
||||
|
||||
use hyper::{body::HttpBody, Body, Client, Method, Request, Uri}; |
||||
use json::JsonValue; |
||||
use rand::Fill; |
||||
use sha2::Sha512; |
||||
use srp::{ |
||||
client::{srp_private_key, SrpClient}, |
||||
groups::G_2048, |
||||
}; |
||||
|
||||
const AUTH_URI: &'static str = "http://192.168.1.1/authenticate"; |
||||
|
||||
fn get_username<'a>() -> &'a str { |
||||
"admin" |
||||
} |
||||
|
||||
fn get_password<'a>() -> &'a str { |
||||
"admin" |
||||
} |
||||
|
||||
pub async fn try_login(cookie: &str, csrf_token: &str) -> Result<(), ()> { |
||||
let mut a = [0u8; 64]; |
||||
a.try_fill(&mut rand::thread_rng()).unwrap(); |
||||
let srp_client = SrpClient::<Sha512>::new(&a, &G_2048); |
||||
|
||||
let a_pub = srp_client.get_a_pub(); |
||||
let a_pub = base16::encode_lower(&a_pub); |
||||
|
||||
let client = Client::new(); |
||||
|
||||
let uri: Uri = AUTH_URI.parse().unwrap(); |
||||
|
||||
let req_body = format!("CSRFtoken={}&I={}&A={}", csrf_token, get_username(), a_pub); |
||||
|
||||
println!("{}", &req_body); |
||||
|
||||
let request = Request::builder() |
||||
.method(Method::POST) |
||||
.uri(uri.clone()) |
||||
.header("Accept", "application/json, text/javascript, */*; q=0.01") |
||||
.header( |
||||
"Content-Type", |
||||
"application/x-www-form-urlencoded; charset=UTF-8", |
||||
) |
||||
.header("Cookie", format!("sessionID={}", cookie).as_str()) |
||||
.header("Host", "192.168.1.1") |
||||
.header("Origin", "http://192.168.1.1") |
||||
.header("Pragma", "no-cache") |
||||
.header("Referer", "http://192.168.1.1/") |
||||
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 Edg/93.0.961.52") |
||||
.header("X-Requested-With", "XMLHttpRequest") |
||||
.body(Body::from(req_body)) |
||||
.unwrap(); |
||||
|
||||
match client.request(request).await { |
||||
Ok(mut resp) => { |
||||
let mut buffer: Vec<u8> = Vec::new(); |
||||
|
||||
while let Some(chunk) = resp.body_mut().data().await { |
||||
match chunk { |
||||
Ok(bytes) => buffer.append(&mut bytes.to_vec()), |
||||
Err(e) => panic!("{}", e.to_string()), |
||||
} |
||||
} |
||||
|
||||
// TODO: handle errors
|
||||
let buffer = String::from_utf8(buffer).unwrap(); |
||||
println!("{:?}", buffer); |
||||
//let resp = json::parse(&buffer).unwrap();
|
||||
|
||||
if let Some((s, b_pub)) = get_salt_and_b_pub(&buffer) { |
||||
let s = base16::decode(s.as_bytes()).unwrap(); |
||||
|
||||
let b_pub = base16::decode(b_pub.as_bytes()).unwrap(); |
||||
|
||||
let private_key = srp_private_key::<Sha512>( |
||||
get_username().as_bytes(), |
||||
get_password().as_bytes(), |
||||
&s, |
||||
); |
||||
|
||||
let verifier = srp_client.process_reply(&private_key, &b_pub).unwrap(); |
||||
|
||||
let user_proof = verifier.get_proof(); |
||||
|
||||
let m = base16::encode_lower(&user_proof); |
||||
|
||||
let req_body = format!("CSRFtoken={}&M={}", csrf_token, m); |
||||
let request = Request::builder() |
||||
.method(Method::POST) |
||||
.uri(uri) |
||||
.header("Accept", "application/json, text/javascript, */*; q=0.01") |
||||
.header( |
||||
"Content-Type", |
||||
"application/x-www-form-urlencoded; charset=UTF-8", |
||||
) |
||||
.header("Cookie", format!("sessionID={}", cookie).as_str()) |
||||
.header("Host", "192.168.1.1") |
||||
.header("Origin", "http://192.168.1.1") |
||||
.header("Pragma", "no-cache") |
||||
.header("Referer", "http://192.168.1.1/") |
||||
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 Edg/93.0.961.52") |
||||
.header("X-Requested-With", "XMLHttpRequest") |
||||
.body(Body::from(req_body)) |
||||
.unwrap(); |
||||
|
||||
match client.request(request).await { |
||||
Ok(mut resp) => { |
||||
let mut buffer: Vec<u8> = Vec::new(); |
||||
|
||||
while let Some(chunk) = resp.body_mut().data().await { |
||||
match chunk { |
||||
Ok(bytes) => buffer.append(&mut bytes.to_vec()), |
||||
Err(e) => panic!("{}", e.to_string()), |
||||
} |
||||
} |
||||
|
||||
// TODO: handle errors
|
||||
let buffer = String::from_utf8(buffer).unwrap(); |
||||
println!("final resp: {:?}", buffer); |
||||
} |
||||
Err(e) => panic!("{}", e.to_string()), |
||||
} |
||||
//let server_proof = conn.send_proof(user_proof);
|
||||
//let key = verifier.verify_server(server_proof).unwrap();
|
||||
} else { |
||||
println!("{:?}", resp); |
||||
} |
||||
} |
||||
Err(e) => panic!("{}", e.to_string()), |
||||
} |
||||
|
||||
todo!() |
||||
} |
||||
|
||||
fn get_salt_and_b_pub(msg: &str) -> Option<(String, String)> { |
||||
let msg = json::parse(&msg).unwrap(); |
||||
|
||||
//_get_salt_and_b_pub(&msg, None, None)
|
||||
if let JsonValue::Object(obj) = msg { |
||||
println!("{:?}", obj); |
||||
|
||||
let mut s = String::new(); |
||||
let mut b = String::new(); |
||||
|
||||
for (name, val) in obj.iter() { |
||||
if name == "s" { |
||||
s = get_json_string(val).unwrap(); |
||||
} else if name == "B" { |
||||
b = get_json_string(val).unwrap(); |
||||
} |
||||
} |
||||
|
||||
Some((s, b)) |
||||
} else { |
||||
None |
||||
} |
||||
} |
||||
|
||||
fn get_json_string(val: &JsonValue) -> Option<String> { |
||||
match val { |
||||
JsonValue::Short(val) => Some(val.to_string()), |
||||
JsonValue::String(val) => Some(val.to_string()), |
||||
_ => None, |
||||
} |
||||
} |
||||
|
||||
#[cfg(test)] |
||||
mod tests { |
||||
use crate::login::get_salt_and_b_pub; |
||||
|
||||
#[test] |
||||
fn parse_json_resp() { |
||||
let msg = "{ \"s\":\"0DEC99D3\", \"B\":\"2FCDB529BB3F7F02BAD0ED15C62995CB9E76AC0352D91F64AD02A1EF06C533565F64A0B25D7235682E5D732CA8FD1C675231CA205D83FF317E8D7BFBC48D863822A7E9A8ADC7BBD54B54A7D59502479872E4926C6169BDDED2E7FD7BFD1714ECA3FE22511C4F48F8FA33240DB8DD289933FC19A1B7DC0EEB4A56337ADB67FFC08684822D05D2A5EC95A3B21E84B4CB0F2C6195454D1D3B59548987485555E200B5E23B7E89E87C60AF3C2AA5834B284DD182C9A508FE479357BA341750385837241ACA56AAC5E380AB3876F80761E4BE33FAA8BBE60863AFC96FEBDB2AC64636AF3035777624EF2ECC581CA7266D3F11BB30CDEF21E9802973CCC7899E375F3E\" }"; |
||||
println!("{:?}", json::parse(&msg)); |
||||
|
||||
assert_eq!( |
||||
get_salt_and_b_pub(msg), |
||||
Some((String::from("0DEC99D3"), String::from("2FCDB529BB3F7F02BAD0ED15C62995CB9E76AC0352D91F64AD02A1EF06C533565F64A0B25D7235682E5D732CA8FD1C675231CA205D83FF317E8D7BFBC48D863822A7E9A8ADC7BBD54B54A7D59502479872E4926C6169BDDED2E7FD7BFD1714ECA3FE22511C4F48F8FA33240DB8DD289933FC19A1B7DC0EEB4A56337ADB67FFC08684822D05D2A5EC95A3B21E84B4CB0F2C6195454D1D3B59548987485555E200B5E23B7E89E87C60AF3C2AA5834B284DD182C9A508FE479357BA341750385837241ACA56AAC5E380AB3876F80761E4BE33FAA8BBE60863AFC96FEBDB2AC64636AF3035777624EF2ECC581CA7266D3F11BB30CDEF21E9802973CCC7899E375F3E"))) |
||||
) |
||||
} |
||||
} |
||||
Loading…
Reference in new issue