From 9dd6572ed35db0da2087190fe7eef84491de14df Mon Sep 17 00:00:00 2001 From: Ethan O'Brien <77750390+ethanaobrien@users.noreply.github.com> Date: Mon, 8 Apr 2024 15:29:01 -0500 Subject: [PATCH] Implement jp migration (gree) --- src/main.rs | 24 ++++++ src/router/gree.rs | 210 ++++++++++++++++++++++++++++++++++++++++++++- src/router/home.rs | 3 - src/router/user.rs | 6 +- 4 files changed, 233 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1bcd37f..fbe7089 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,9 +27,27 @@ async fn gree_payment_ticket(req: HttpRequest) -> HttpResponse { router::gree::p #[get("/v1.0/moderate/keywordlist")] async fn gree_moderate_keyword(req: HttpRequest) -> HttpResponse { router::gree::moderate_keyword(req) } +#[post("/v1.0/moderate/filtering/commit")] +async fn gree_moderate_commit(req: HttpRequest, body: String) -> HttpResponse { router::gree::moderate_commit(req, body) } + #[post("/v1.0/auth/authorize")] async fn gree_authorize(req: HttpRequest, body: String) -> HttpResponse { router::gree::authorize(req, body) } +#[get("/v1.0/migration/code")] +async fn gree_migration_code(req: HttpRequest) -> HttpResponse { router::gree::migration_code(req) } + +#[post("/v1.0/migration/code/verify")] +async fn gree_migration_verify(req: HttpRequest, body: String) -> HttpResponse { router::gree::migration_verify(req, body) } + +#[post("/v1.0/migration/password/register")] +async fn gree_migration_password_register(req: HttpRequest, body: String) -> HttpResponse { router::gree::migration_password_register(req, body) } + +#[get("/v1.0/payment/balance")] +async fn gree_balance(req: HttpRequest) -> HttpResponse { router::gree::balance(req) } + +#[post("/v1.0/migration")] +async fn gree_migration(req: HttpRequest, body: String) -> HttpResponse { router::gree::migration(req, body) } + #[post("/api/debug/error")] async fn debug_error(req: HttpRequest, body: String) -> HttpResponse { router::debug::error(req, body) } @@ -161,6 +179,12 @@ async fn main() -> std::io::Result<()> { .service(gree_payment_ticket) .service(gree_payment_sub) .service(gree_moderate_keyword) + .service(gree_moderate_commit) + .service(gree_migration_code) + .service(gree_migration_verify) + .service(gree_migration_password_register) + .service(gree_balance) + .service(gree_migration) .service(debug_error) .service(login_bonus) .service(reward) diff --git a/src/router/gree.rs b/src/router/gree.rs index af3df34..51b8d5a 100644 --- a/src/router/gree.rs +++ b/src/router/gree.rs @@ -8,6 +8,7 @@ use json::object; use hmac::{Hmac, Mac}; use crate::router::userdata; use crate::encryption; +use crate::router::user::{code_to_uid, uid_to_code}; use rusqlite::{Connection, params, ToSql}; use std::sync::{Mutex, MutexGuard}; @@ -108,6 +109,12 @@ fn get_new_uuid() -> String { id } +fn update_cert(uid: &str, cert: &str) { + lock_and_exec( + &format!("UPDATE _{}_ SET cert=?1", uid), + params!(cert), + ); +} fn create_acc(cert: &str) -> String { let uuid = get_new_uuid(); let user = userdata::get_acc(&uuid); @@ -169,6 +176,26 @@ pub fn get_uuid(headers: &HeaderMap, body: &str) -> String { return String::new(); } } +fn rot13(input: &str) -> String { + let mut result = String::new(); + for c in input.chars() { + let shifted = match c { + 'A'..='Z' => ((c as u8 - b'A' + 13) % 26 + b'A') as char, + 'a'..='z' => ((c as u8 - b'a' + 13) % 26 + b'a') as char, + _ => c, + }; + result.push(shifted); + } + result +} +fn decrypt_transfer_password(password: &str) -> String { + let reversed = password.chars().rev().collect::(); + let rot = rot13(&reversed); + let decoded = general_purpose::STANDARD.decode(rot).unwrap_or(vec![]); + + String::from_utf8_lossy(&decoded).to_string() +} + pub fn initialize(req: HttpRequest, body: String) -> HttpResponse { @@ -223,9 +250,21 @@ pub fn moderate_keyword(req: HttpRequest) -> HttpResponse { .insert_header(("X-GREE-Authorization", gree_authorize(&req))) .body(json::stringify(resp)) } +pub fn moderate_commit(req: HttpRequest, _body: String) -> HttpResponse { + let resp = object!{ + result: "OK" + }; + HttpResponse::Ok() + .insert_header(ContentType::json()) + .insert_header(("Expires", "-1")) + .insert_header(("Pragma", "no-cache")) + .insert_header(("Cache-Control", "must-revalidate, no-cache, no-store, private")) + .insert_header(("Vary", "Authorization,Accept-Encoding")) + .insert_header(("X-GREE-Authorization", gree_authorize(&req))) + .body(json::stringify(resp)) +} pub fn uid(req: HttpRequest) -> HttpResponse { - let mut uid = String::new(); let blank_header = HeaderValue::from_static(""); let auth_header = req.headers().get("Authorization").unwrap_or(&blank_header).to_str().unwrap_or(""); @@ -281,6 +320,163 @@ pub fn payment_ticket(req: HttpRequest) -> HttpResponse { entry: [] }; + HttpResponse::Ok() + .insert_header(ContentType::json()) + .insert_header(("Expires", "-1")) + .insert_header(("Pragma", "no-cache")) + .insert_header(("Cache-Control", "must-revalidate, no-cache, no-store, private")) + .insert_header(("Vary", "Authorization"))//AUAWGAPYYUGYYGA7 + .insert_header(("X-GREE-Authorization", gree_authorize(&req))) + .body(json::stringify(resp)) +} + +pub fn migration_verify(req: HttpRequest, body: String) -> HttpResponse { + let body = json::parse(&body).unwrap(); + let password = decrypt_transfer_password(&body["migration_password"].to_string()); + + let uid = code_to_uid(body["migration_code"].to_string()).parse::().unwrap_or(0); + + let user = userdata::get_acc_transfer(uid, &body["migration_code"].to_string(), &password); + + let resp; + if user["success"].as_bool().unwrap() != true || uid == 0 { + resp = object!{ + result: "ERR", + messsage: "User Not Found" + }; + } else { + let data_user = userdata::get_acc(&user["login_token"].to_string()); + resp = object!{ + result: "OK", + src_uuid: user["login_token"].clone(), + src_x_uid: uid.to_string(), + migration_token: user["login_token"].clone(), + balance_charge_gem: data_user["gem"]["charge"].to_string(), + balance_free_gem: data_user["gem"]["free"].to_string(), + balance_total_gem: (data_user["gem"]["charge"].as_i32().unwrap() + data_user["gem"]["free"].as_i32().unwrap()).to_string() + }; + } + + HttpResponse::Ok() + .insert_header(ContentType::json()) + .insert_header(("Expires", "-1")) + .insert_header(("Pragma", "no-cache")) + .insert_header(("Cache-Control", "must-revalidate, no-cache, no-store, private")) + .insert_header(("Vary", "Authorization")) + .insert_header(("X-GREE-Authorization", gree_authorize(&req))) + .body(json::stringify(resp)) +} + +pub fn migration(req: HttpRequest, body: String) -> HttpResponse { + let body = json::parse(&body).unwrap(); + + let user = userdata::get_acc(&body["src_uuid"].to_string()); + update_cert(&user["user"]["id"].to_string(), &body["token"].to_string()); + //clear old token + if !body["dst_uuid"].is_null() { + let user2 = userdata::get_acc(&body["dst_uuid"].to_string()); + update_cert(&user2["user"]["id"].to_string(), "none"); + } + + let resp = object!{ + result: "OK" + }; + + HttpResponse::Ok() + .insert_header(ContentType::json()) + .insert_header(("Expires", "-1")) + .insert_header(("Pragma", "no-cache")) + .insert_header(("Cache-Control", "must-revalidate, no-cache, no-store, private")) + .insert_header(("Vary", "Authorization")) + .insert_header(("X-GREE-Authorization", gree_authorize(&req))) + .body(json::stringify(resp)) +} + +pub fn balance(req: HttpRequest) -> HttpResponse { + let mut uid = String::new(); + let blank_header = HeaderValue::from_static(""); + let auth_header = req.headers().get("Authorization").unwrap_or(&blank_header).to_str().unwrap_or(""); + let uid_data: Vec<&str> = auth_header.split(",xoauth_requestor_id=\"").collect(); + if let Some(uid_data2) = uid_data.get(1) { + let uid_data2: Vec<&str> = uid_data2.split('"').collect(); + if let Some(uid_str) = uid_data2.get(0) { + uid = uid_str.to_string(); + } + } + + let user = userdata::get_acc(&uid); + + let resp = object!{ + result: "OK", + entry: { + balance_charge_gem: user["gem"]["charge"].to_string(), + balance_free_gem: user["gem"]["free"].to_string(), + balance_total_gem: (user["gem"]["charge"].as_i32().unwrap() + user["gem"]["free"].as_i32().unwrap()).to_string() + } + }; + + HttpResponse::Ok() + .insert_header(ContentType::json()) + .insert_header(("Expires", "-1")) + .insert_header(("Pragma", "no-cache")) + .insert_header(("Cache-Control", "must-revalidate, no-cache, no-store, private")) + .insert_header(("Vary", "Authorization")) + .insert_header(("X-GREE-Authorization", gree_authorize(&req))) + .body(json::stringify(resp)) +} + +pub fn migration_code(req: HttpRequest) -> HttpResponse { + let mut uid = String::new(); + let blank_header = HeaderValue::from_static(""); + let auth_header = req.headers().get("Authorization").unwrap_or(&blank_header).to_str().unwrap_or(""); + let uid_data: Vec<&str> = auth_header.split(",xoauth_requestor_id=\"").collect(); + if let Some(uid_data2) = uid_data.get(1) { + let uid_data2: Vec<&str> = uid_data2.split('"').collect(); + if let Some(uid_str) = uid_data2.get(0) { + uid = uid_str.to_string(); + } + } + + let user = userdata::get_acc(&uid); + + let resp = object!{ + result: "OK", + migration_code: uid_to_code(user["user"]["id"].to_string()) + }; + + HttpResponse::Ok() + .insert_header(ContentType::json()) + .insert_header(("Expires", "-1")) + .insert_header(("Pragma", "no-cache")) + .insert_header(("Cache-Control", "must-revalidate, no-cache, no-store, private")) + .insert_header(("Vary", "Authorization")) + .insert_header(("X-GREE-Authorization", gree_authorize(&req))) + .body(json::stringify(resp)) +} + +pub fn migration_password_register(req: HttpRequest, body: String) -> HttpResponse { + let body = json::parse(&body).unwrap(); + let mut uid = String::new(); + let blank_header = HeaderValue::from_static(""); + let auth_header = req.headers().get("Authorization").unwrap_or(&blank_header).to_str().unwrap_or(""); + let uid_data: Vec<&str> = auth_header.split(",xoauth_requestor_id=\"").collect(); + if let Some(uid_data2) = uid_data.get(1) { + let uid_data2: Vec<&str> = uid_data2.split('"').collect(); + if let Some(uid_str) = uid_data2.get(0) { + uid = uid_str.to_string(); + } + } + + let user = userdata::get_acc(&uid); + let code = uid_to_code(user["user"]["id"].to_string()); + let pass = decrypt_transfer_password(&body["migration_password"].to_string()); + + userdata::save_acc_transfer(&code, &pass); + + let resp = object!{ + result: "OK" + }; + HttpResponse::Ok() .insert_header(ContentType::json()) .insert_header(("Expires", "-1")) @@ -314,18 +510,24 @@ fn gree_authorize(req: &HttpRequest) -> String { let hostname = req.headers().get("host").unwrap_or(&blank_header).to_str().unwrap_or(""); let current_url = format!("http://{}{}", hostname, req.path()); + let uri = req.uri().to_string(); + let extra = if uri.contains("?") { + format!("&{}", uri.split('?').nth(1).unwrap_or("")) + } else { String::new() }; + let nonce = format!("{:x}", md5::compute((global::timestamp() * 1000).to_string())); let timestamp = global::timestamp().to_string(); let method = "HMAC-SHA1"; - let validate_data = format!("{}&{}&{}", + let validate_data = format!("{}&{}&{}", req.method(), urlencoding::encode(¤t_url), - urlencoding::encode(&format!("oauth_body_hash={}&oauth_consumer_key={}&oauth_nonce={}&oauth_signature_method={}&oauth_timestamp={}&oauth_version=1.0", + urlencoding::encode(&format!("oauth_body_hash={}&oauth_consumer_key={}&oauth_nonce={}&oauth_signature_method={}&oauth_timestamp={}&oauth_version=1.0{}", header_data.get("oauth_body_hash").unwrap_or(&String::new()), header_data.get("oauth_consumer_key").unwrap_or(&String::new()), nonce, method, - timestamp))); + timestamp, + extra))); let mut hasher = HmacSha1::new_from_slice(&hex::decode("6438663638653238346566646636306262616563326432323563306366643432").unwrap()).unwrap(); hasher.update(validate_data.as_bytes()); let signature = general_purpose::STANDARD.encode(hasher.finalize().into_bytes()); diff --git a/src/router/home.rs b/src/router/home.rs index 19302d8..8a6acda 100644 --- a/src/router/home.rs +++ b/src/router/home.rs @@ -42,9 +42,6 @@ pub fn preset_get(req: HttpRequest) -> HttpResponse { } pub fn home(req: HttpRequest) -> HttpResponse { - for (name, value) in req.headers().iter() { - println!("{}: {}", name, value.to_str().unwrap()); - } let key = global::get_login(req.headers(), ""); let user = userdata::get_acc_home(&key); diff --git a/src/router/user.rs b/src/router/user.rs index 08a41ba..3bbf536 100644 --- a/src/router/user.rs +++ b/src/router/user.rs @@ -76,7 +76,7 @@ pub fn user_post(req: HttpRequest, body: String) -> HttpResponse { global::send(resp) } -fn uid_to_code(uid: String) -> String { +pub fn uid_to_code(uid: String) -> String { //just replace uid with numbers because im too lazy to have a real database and this is close enough anyways return uid .replace("1", "A") @@ -91,7 +91,7 @@ fn uid_to_code(uid: String) -> String { .replace("0", "M") + "7"; } -fn code_to_uid(code: String) -> String { +pub fn code_to_uid(code: String) -> String { //just replace uid with numbers because im too lazy to have a real database and this is close enough anyways return code .replace("7", "") @@ -176,7 +176,7 @@ pub fn request_migration_code(_req: HttpRequest, body: String) -> HttpResponse { let user = userdata::get_acc_transfer(uid, &body["migrationCode"].to_string(), &body["pass"].to_string()); - if user["success"].as_bool().unwrap() == false || uid == 0 { + if user["success"].as_bool().unwrap() != true || uid == 0 { let resp = object!{ "code": 2, "server_time": global::timestamp(),