mirror of
https://git.42l.fr/neil/sncf.git
synced 2024-05-04 06:53:12 +02:00
fixing the login forgery process to work around nextcloud issue
This commit is contained in:
parent
3b82283cfd
commit
31bf380e12
|
@ -6,9 +6,10 @@ use rand::Rng;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use percent_encoding::percent_decode_str;
|
||||||
|
|
||||||
use crate::config::PROXY_TIMEOUT;
|
use crate::config::{PROXY_TIMEOUT, USER_AGENT, ADJ_LIST, NAME_LIST};
|
||||||
use crate::config::{ADJ_LIST, NAME_LIST};
|
|
||||||
use crate::debug;
|
use crate::debug;
|
||||||
use crate::errors::{crash, TrainCrash};
|
use crate::errors::{crash, TrainCrash};
|
||||||
use crate::templates::get_lang;
|
use crate::templates::get_lang;
|
||||||
|
@ -142,11 +143,11 @@ pub async fn login(
|
||||||
) -> Result<HttpResponse, TrainCrash> {
|
) -> Result<HttpResponse, TrainCrash> {
|
||||||
debug(&format!("Sending forged login for user {}", user));
|
debug(&format!("Sending forged login for user {}", user));
|
||||||
|
|
||||||
// 1. GET /login
|
// 1. GET /csrftoken
|
||||||
let mut login_get = client
|
let mut login_get = client
|
||||||
.get(format!("{}/{}", CONFIG.nextcloud_url, "login"))
|
.get(format!("{}/{}", CONFIG.nextcloud_url, "csrftoken"))
|
||||||
.timeout(Duration::new(PROXY_TIMEOUT, 0))
|
.timeout(Duration::new(PROXY_TIMEOUT, 0))
|
||||||
.header("User-Agent", "Actix-web")
|
.header("User-Agent", USER_AGENT)
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
|
@ -156,22 +157,63 @@ pub async fn login(
|
||||||
|
|
||||||
// rewrite cookie headers from GET to POST
|
// rewrite cookie headers from GET to POST
|
||||||
let mut str_cookiepair = String::new();
|
let mut str_cookiepair = String::new();
|
||||||
for h_value in login_get.headers().get_all("set-cookie") {
|
|
||||||
str_cookiepair = format!(
|
// remove duplicate oc<id> cookie (nextcloud bug)
|
||||||
"{}; {}",
|
// leading to sncf being unable to forge logins
|
||||||
str_cookiepair,
|
let cookie_set = login_get.headers().get_all("set-cookie");
|
||||||
h_value.clone().to_str().map_err(|e| {
|
let mut cookie_map: HashMap<String, String> = HashMap::new();
|
||||||
eprintln!("error_login_cookiepair: {}", e);
|
for c in cookie_set {
|
||||||
crash(get_lang(&req), "error_login_cookiepair")
|
// get str version of cookie header
|
||||||
})?
|
let c_str = c.to_str().map_err(|e| {
|
||||||
);
|
eprintln!("error_login_cookiepair (1): {}", e);
|
||||||
|
crash(get_lang(&req), "error_login_cookiepair")
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// percent decode
|
||||||
|
let c_str = percent_decode_str(c_str).decode_utf8_lossy();
|
||||||
|
|
||||||
|
//then remove values after ';'
|
||||||
|
let c_str_arr = c_str.split(';').collect::<Vec<&str>>();
|
||||||
|
|
||||||
|
let c_str = c_str_arr.first()
|
||||||
|
.expect("error: cookiepair split does not have a first value. shouldn't happen.");
|
||||||
|
|
||||||
|
// split cookie key and cookie value
|
||||||
|
// split_once would work best but it's nightly-only for now
|
||||||
|
let c_str_arr = c_str.split('=').collect::<Vec<&str>>();
|
||||||
|
|
||||||
|
let c_key = c_str_arr.first()
|
||||||
|
.expect("error: cookie key split does not have a first value, shouldn't happen.");
|
||||||
|
|
||||||
|
let c_value = c_str.replace(&format!("{}=", c_key), "");
|
||||||
|
|
||||||
|
if c_key != c_str {
|
||||||
|
// if the key already exists in hashmap, replace its value
|
||||||
|
// else, insert it
|
||||||
|
if let Some(c_sel) = cookie_map.get_mut(*c_key) {
|
||||||
|
*c_sel = c_value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cookie_map.insert(c_key.to_string(), c_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
eprintln!("error_login_cookiepair (2)");
|
||||||
|
return Err(crash(get_lang(&req), "error_login_cookiepair"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (cookie_k, cookie_v) in cookie_map {
|
||||||
|
str_cookiepair.push_str(&format!("{}={}; ", cookie_k, cookie_v));
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("SET-COOKIE: {}", str_cookiepair);
|
||||||
|
|
||||||
// load requesttoken regex
|
// load requesttoken regex
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref RE: Regex = Regex::new(r#"requesttoken="(?P<token>.*)""#)
|
static ref RE: Regex = Regex::new(r#"\{"token":"(?P<token>[^"]*)"\}"#)
|
||||||
.expect("Error while parsing the requesttoken regex");
|
.expect("Error while parsing the requesttoken regex");
|
||||||
}
|
}
|
||||||
|
|
||||||
let post_body = login_get.body().await.map_err(|e| {
|
let post_body = login_get.body().await.map_err(|e| {
|
||||||
eprintln!("error_login_get_body: {}", e);
|
eprintln!("error_login_get_body: {}", e);
|
||||||
|
@ -186,18 +228,18 @@ pub async fn login(
|
||||||
eprintln!("error_login_regex (no capture)");
|
eprintln!("error_login_regex (no capture)");
|
||||||
crash(get_lang(&req), "error_login_regex")
|
crash(get_lang(&req), "error_login_regex")
|
||||||
})?
|
})?
|
||||||
.name("token")
|
.name("token")
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
eprintln!("error_login_regex (no capture named token)");
|
eprintln!("error_login_regex (no capture named token)");
|
||||||
crash(get_lang(&req), "error_login_regex")
|
crash(get_lang(&req), "error_login_regex")
|
||||||
})?
|
})?
|
||||||
.as_str();
|
.as_str();
|
||||||
|
|
||||||
// 2. POST /login
|
// 2. POST /login
|
||||||
let mut login_post = client
|
let mut login_post = client
|
||||||
.post(format!("{}/{}", CONFIG.nextcloud_url, "login"))
|
.post(format!("{}/{}", CONFIG.nextcloud_url, "login"))
|
||||||
.timeout(Duration::new(PROXY_TIMEOUT, 0))
|
.timeout(Duration::new(PROXY_TIMEOUT, 0))
|
||||||
.header("User-Agent", "Actix-web");
|
.header("User-Agent", USER_AGENT);
|
||||||
|
|
||||||
// include all NC cookies in one cookie (cookie pair)
|
// include all NC cookies in one cookie (cookie pair)
|
||||||
login_post = login_post.header("Cookie", str_cookiepair);
|
login_post = login_post.header("Cookie", str_cookiepair);
|
||||||
|
@ -211,7 +253,7 @@ pub async fn login(
|
||||||
timezone_offset: "2",
|
timezone_offset: "2",
|
||||||
requesttoken,
|
requesttoken,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
eprintln!("error_login_post: {}", e);
|
eprintln!("error_login_post: {}", e);
|
||||||
crash(get_lang(&req), "error_login_post")
|
crash(get_lang(&req), "error_login_post")
|
||||||
|
@ -219,6 +261,7 @@ pub async fn login(
|
||||||
|
|
||||||
// 3. set the same cookies in the user's browser
|
// 3. set the same cookies in the user's browser
|
||||||
let mut user_response = HttpResponse::SeeOther();
|
let mut user_response = HttpResponse::SeeOther();
|
||||||
|
|
||||||
for item in response_post.headers().clone().get_all("set-cookie") {
|
for item in response_post.headers().clone().get_all("set-cookie") {
|
||||||
user_response.header(
|
user_response.header(
|
||||||
"Set-Cookie",
|
"Set-Cookie",
|
||||||
|
|
Loading…
Reference in a new issue