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 regex::Regex;
|
||||
use std::time::Duration;
|
||||
use std::collections::HashMap;
|
||||
use percent_encoding::percent_decode_str;
|
||||
|
||||
use crate::config::PROXY_TIMEOUT;
|
||||
use crate::config::{ADJ_LIST, NAME_LIST};
|
||||
use crate::config::{PROXY_TIMEOUT, USER_AGENT, ADJ_LIST, NAME_LIST};
|
||||
use crate::debug;
|
||||
use crate::errors::{crash, TrainCrash};
|
||||
use crate::templates::get_lang;
|
||||
|
@ -142,11 +143,11 @@ pub async fn login(
|
|||
) -> Result<HttpResponse, TrainCrash> {
|
||||
debug(&format!("Sending forged login for user {}", user));
|
||||
|
||||
// 1. GET /login
|
||||
// 1. GET /csrftoken
|
||||
let mut login_get = client
|
||||
.get(format!("{}/{}", CONFIG.nextcloud_url, "login"))
|
||||
.get(format!("{}/{}", CONFIG.nextcloud_url, "csrftoken"))
|
||||
.timeout(Duration::new(PROXY_TIMEOUT, 0))
|
||||
.header("User-Agent", "Actix-web")
|
||||
.header("User-Agent", USER_AGENT)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
|
@ -156,20 +157,61 @@ pub async fn login(
|
|||
|
||||
// rewrite cookie headers from GET to POST
|
||||
let mut str_cookiepair = String::new();
|
||||
for h_value in login_get.headers().get_all("set-cookie") {
|
||||
str_cookiepair = format!(
|
||||
"{}; {}",
|
||||
str_cookiepair,
|
||||
h_value.clone().to_str().map_err(|e| {
|
||||
eprintln!("error_login_cookiepair: {}", e);
|
||||
|
||||
// remove duplicate oc<id> cookie (nextcloud bug)
|
||||
// leading to sncf being unable to forge logins
|
||||
let cookie_set = login_get.headers().get_all("set-cookie");
|
||||
let mut cookie_map: HashMap<String, String> = HashMap::new();
|
||||
for c in cookie_set {
|
||||
// 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
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -197,7 +239,7 @@ pub async fn login(
|
|||
let mut login_post = client
|
||||
.post(format!("{}/{}", CONFIG.nextcloud_url, "login"))
|
||||
.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)
|
||||
login_post = login_post.header("Cookie", str_cookiepair);
|
||||
|
@ -219,6 +261,7 @@ pub async fn login(
|
|||
|
||||
// 3. set the same cookies in the user's browser
|
||||
let mut user_response = HttpResponse::SeeOther();
|
||||
|
||||
for item in response_post.headers().clone().get_all("set-cookie") {
|
||||
user_response.header(
|
||||
"Set-Cookie",
|
||||
|
|
Loading…
Reference in a new issue