keyauth_obf/
v1_2.rs

1/*!
2unofficial [keyauth](https://keyauth.cc) library that uses 1.2 api version
3
4basic usage:
5```rust
6let mut auth = keyauth::v1_2::KeyauthApi::new("application name", "ownerid", "application secret", "application version", "api url"); // if you dont have a custom domain for api use "https://keyauth.win/api/1.2/"
7auth.init().unwrap();
8auth.login("username", "password", Some("hwid".to_string()).unwrap()); // if you want to automaticly generate hwid use None insted.
9```
10
11also if you want to use an obfuscator for rust i recommend using [obfstr](https://crates.io/crates/obfstr) and [llvm obfuscator](https://github.com/eshard/obfuscator-llvm/wiki/Rust-obfuscation-guide)
12*/
13
14use base16::decode;
15use debugoff::multi_ptraceme_or_die;
16use goldberg::goldberg_stmts;
17use hmac_sha256::HMAC;
18use httparse::Header;
19use reqwest::header::HeaderMap;
20use reqwest::Client;
21use reqwest::Response;
22use std::collections::HashMap;
23use std::io::Read;
24use std::net::TcpListener;
25use uuid::Uuid;
26
27macro_rules! nodebug {
28    () => {
29        #[cfg(target_os = "linux")]
30        #[cfg(not(debug_assertions))]
31        multi_ptraceme_or_die();
32    };
33}
34
35pub struct Res<T>(Result<T, String>);
36
37impl Default for Res<()> {
38    fn default() -> Self {
39        Res(Err("Default Error".to_string()))
40    }
41}
42
43impl<T> Res<T> {
44    pub fn inner(self) -> Result<T, String> {
45        self.0
46    }
47}
48
49impl<T: Clone> Res<T> {
50    pub fn clone_inner(&self) -> Result<T, String> {
51        self.0.clone()
52    }
53}
54
55struct Resp {
56    res: String,
57    head: HeaderMap,
58}
59
60impl Default for Resp {
61    fn default() -> Self {
62        Resp {
63            res: "Default Resp Error".to_string(),
64            head: HeaderMap::new(),
65        }
66    }
67}
68
69struct Data(String);
70
71impl Data {
72    fn insert<T: ToString, G: ToString>(&mut self, key: T, val: G) {
73        self.0
74            .push_str(&format!("{}={}&", key.to_string(), val.to_string()));
75    }
76}
77
78fn copy_string(bytes: &[u8]) -> String {
79    let bytes: Vec<u8> = bytes.to_vec();
80    let bytes = bytes.clone();
81    let mut string = String::new();
82    for byte in bytes {
83        string.push(byte as char);
84    }
85    string
86}
87
88/// every function in this struct (accept log) returns a Result and Err("Request was tampered with") will be returned if the request signature doesnt mathc the sha256 hmac of the message
89#[derive(Default, Clone)]
90pub struct KeyauthApi {
91    name: String,
92    owner_id: String,
93    secret: String,
94    version: String,
95    enckey: String,
96    enckey_s: String,
97    session_id: String,
98    pub api_url: String,
99    pub num_keys: String,
100    pub num_online_users: String,
101    pub num_users: String,
102    pub app_version: String,
103    pub customer_panel_link: String,
104    pub username: String,
105    pub ip: String,
106    pub hwid: String,
107    pub create_date: String,
108    pub last_login: String,
109    pub subscription: String,
110    pub message: String,
111    pub success: bool,
112    pub blacklisted: bool,
113    pub response: String,
114}
115
116impl KeyauthApi {
117    /// creats a new KeyauthApi and its defaults, api_url has to be api version 1.2 example: "https://keyauth.win/api/1.2/" or if you have a custom api domain: "https://api.example.com/1.2/"
118    pub fn new(name: &str, owner_id: &str, secret: &str, version: &str, api_url: &str) -> Self {
119        let res: Self = goldberg_stmts! {{
120            nodebug!();
121        Self {
122            name: name.to_string(),
123            owner_id: owner_id.to_string(),
124            secret: secret.to_string(),
125            version: version.to_string(),
126            enckey: String::new(),
127            enckey_s: String::new(),
128            session_id: String::new(),
129            num_keys: String::new(),
130            api_url: api_url.to_string(),
131            num_online_users: String::new(),
132            num_users: String::new(),
133            app_version: version.to_string(),
134            customer_panel_link: String::new(),
135            username: String::new(),
136            ip: String::new(),
137            hwid: machine_uuid::get(),
138            create_date: String::new(),
139            last_login: String::new(),
140            subscription: String::new(),
141            message: String::new(),
142            success: false,
143            blacklisted: false,
144            response: String::new(),
145        }}};
146        res
147    }
148
149    /// initializes a session, **required to run before any other function in this struct!!!** accept new
150    pub async fn init(&mut self, hash: Option<&str>) -> Res<()> {
151        let res = goldberg_stmts! {{
152            nodebug!();
153        self.enckey = Uuid::new_v4().simple().to_string();
154        self.enckey_s = format!("{}-{}", self.enckey, self.secret);
155            let mut data = Data(String::new());
156            data.insert("type", "init");
157            if hash.is_some() {
158                data.insert("hash", hash.unwrap());
159            }
160            data.insert("ver", &self.version);
161            data.insert("name", &self.name);
162            data.insert("ownerid", &self.owner_id);
163            data.insert("enckey", &self.enckey);
164
165        let req = Self::request(data, &self.api_url).await;
166            let resp = req.res;
167            let head = req.head;
168
169        if resp == "KeyAuth_Invalid" {
170            return Res(Err("The application doesn't exist".to_string()));
171        }
172        if !head.contains_key("signature") {
173
174            return Res(Err("response was tampered with".to_string()));
175        }
176        let sig = head.get("signature").unwrap().to_str().unwrap();
177        if sig != Self::make_hmac(&resp, &self.secret) {
178
179            return Res(Err("response was tampered with".to_string()));
180        }
181        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
182            nodebug!();
183        if json_rep["success"].as_bool().unwrap() {
184            self.session_id = json_rep["sessionid"].as_str().unwrap().to_string();
185            self.num_keys = json_rep["appinfo"]["numKeys"].as_str().unwrap().to_string();
186            self.num_online_users = json_rep["appinfo"]["numOnlineUsers"].as_str().unwrap().to_string();
187            self.num_users = json_rep["appinfo"]["numUsers"].as_str().unwrap().to_string();
188            self.customer_panel_link = json_rep["appinfo"]["customerPanelLink"].as_str().unwrap_or("").to_string();
189            Res(Ok(()))
190        } else {
191            if json_rep["message"].as_str().unwrap() == "invalidver" {
192                let download_url = json_rep["download"].as_str().unwrap();
193                if !download_url.is_empty() {
194                    webbrowser::open(download_url).unwrap();
195                }
196            }
197            Res(Err(json_rep["message"].as_str().unwrap().to_string()))
198        }}};
199        res
200    }
201
202    /// registeres a new user
203    pub async fn register(
204        &mut self,
205        username: String,
206        password: String,
207        license: String,
208        hwid: Option<String>,
209    ) -> Res<()> {
210        let res = goldberg_stmts! {{
211            nodebug!();
212        let hwidd = match hwid {
213            Some(hwid) => hwid,
214            None => machine_uuid::get(),
215        };
216            let mut req_data = Data(String::new());
217            req_data.insert("type", "register");
218            req_data.insert("username", &username);
219            req_data.insert("pass", &password);
220            req_data.insert("key", &license);
221            req_data.insert("sessionid", &self.session_id);
222            req_data.insert("name", &self.name);
223            req_data.insert("ownerid", &self.owner_id);
224            req_data.insert("hwid", &hwidd);
225
226
227        let req = Self::request(req_data, &self.api_url).await;
228            let resp = req.res;
229            let head = req.head;
230
231        if !head.contains_key("signature") {
232
233            return Res(Err("response was tampered with".to_string()));
234        }
235        let sig = head.get("signature").unwrap().to_str().unwrap();
236        if sig != Self::make_hmac(&resp, &self.enckey_s) {
237
238            return Res(Err("response was tampered with".to_string()));
239        }
240        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
241            nodebug!();
242        if json_rep["success"].as_bool().unwrap() {
243            self.username = copy_string(username.as_bytes());
244            self.ip = json_rep["info"]["ip"].as_str().unwrap().to_string();
245            self.create_date = json_rep["info"]["createdate"].as_str().unwrap().to_string();
246            self.last_login = json_rep["info"]["lastlogin"].as_str().unwrap().to_string();
247            self.subscription = json_rep["info"]["subscriptions"][0]["subscription"].as_str().unwrap().to_string();
248            Res(Ok(()))
249        } else {
250            Res(Err(json_rep["message"].as_str().unwrap().to_string()))
251        }}};
252        res
253    }
254
255    /// upgrades a user license level or extends a license
256    pub async fn upgrade(&mut self, username: String, license: String) -> Res<()> {
257        let res = goldberg_stmts! {{
258            nodebug!();
259            let mut req_data = Data(String::new());
260            req_data.insert("type", "upgrade");
261            req_data.insert("username", &username);
262            req_data.insert("key", &license);
263            req_data.insert("sessionid", &self.session_id);
264            req_data.insert("name", &self.name);
265            req_data.insert("ownerid", &self.owner_id);
266
267
268        let req = Self::request(req_data, &self.api_url).await;
269            let resp = req.res;
270            let head = req.head;
271
272        if !head.contains_key("signature") {
273
274            return Res(Err("response was tampered with".to_string()));
275        }
276        let sig = head.get("signature").unwrap().to_str().unwrap();
277        if sig != Self::make_hmac(&resp, &self.enckey_s) {
278
279            return Res(Err("response was tampered with".to_string()));
280        }
281        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
282            nodebug!();
283        if json_rep["success"].as_bool().unwrap() {
284            Res(Ok(()))
285        } else {
286            Res(Err(json_rep["message"].as_str().unwrap().to_string()))
287        }}};
288        res
289    }
290
291    /// login self explanatory
292    pub async fn login(
293        &mut self,
294        username: String,
295        password: String,
296        hwid: Option<String>,
297    ) -> Res<()> {
298        let res = goldberg_stmts! {{
299            nodebug!();
300        let hwidd = match hwid {
301            Some(hwid) => hwid,
302            None => machine_uuid::get(),
303        };
304
305            let mut req_data = Data(String::new());
306            req_data.insert("type", "login");
307            req_data.insert("username", &username);
308            req_data.insert("pass", &password);
309            req_data.insert("hwid", &hwidd);
310            req_data.insert("sessionid", &self.session_id);
311            req_data.insert("name", &self.name);
312            req_data.insert("ownerid", &self.owner_id);
313
314
315        let req = Self::request(req_data, &self.api_url).await;
316            let resp = req.res;
317            let head = req.head;
318
319        if !head.contains_key("signature") {
320
321            return Res(Err("response was tampered with".to_string()));
322        }
323        let sig = head.get("signature").unwrap().to_str().unwrap();
324        if sig != Self::make_hmac(&resp, &self.enckey_s) {
325
326            return Res(Err("response was tampered with".to_string()));
327        }
328        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
329
330            nodebug!();
331        if json_rep["success"].as_bool().unwrap() {
332            self.username = copy_string(username.as_bytes());
333            self.ip = json_rep["info"]["ip"].as_str().unwrap().to_string();
334            self.hwid = copy_string(hwidd.as_bytes());
335            self.create_date = json_rep["info"]["createdate"].as_str().unwrap().to_string();
336            self.last_login = json_rep["info"]["lastlogin"].as_str().unwrap().to_string();
337            self.subscription = json_rep["info"]["subscriptions"][0]["subscription"].as_str().unwrap().to_string();
338            Res(Ok(()))
339        } else {
340            Res(Err(json_rep["message"].as_str().unwrap().to_string()))
341        }}};
342        res
343    }
344
345    /// <https://docs.keyauth.cc/api/license>
346    pub async fn license(&mut self, license: String, hwid: Option<String>) -> Res<()> {
347        let res = goldberg_stmts! {{
348            nodebug!();
349        let hwidd = match hwid {
350            Some(hwid) => hwid,
351            None => machine_uuid::get(),
352        };
353
354            let mut req_data = Data(String::new());
355            req_data.insert("type", "license");
356            req_data.insert("key", &license);
357            req_data.insert("hwid", &hwidd);
358            req_data.insert("sessionid", &self.session_id);
359            req_data.insert("name", &self.name);
360            req_data.insert("ownerid", &self.owner_id);
361
362
363        let req = Self::request(req_data, &self.api_url).await;
364            let resp = req.res;
365            let head = req.head;
366
367        if !head.contains_key("signature") {
368
369            return Res(Err("response was tampered with".to_string()));
370        }
371        let sig = head.get("signature").unwrap().to_str().unwrap();
372        if sig != Self::make_hmac(&resp, &self.enckey_s) {
373
374            return Res(Err("response was tampered with".to_string()));
375        }
376        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
377
378            nodebug!();
379        if json_rep["success"].as_bool().unwrap() {
380            self.username = json_rep["info"]["username"].as_str().unwrap().to_string();
381            self.ip = json_rep["info"]["ip"].as_str().unwrap().to_string();
382            self.hwid = copy_string(hwidd.as_bytes());
383            self.create_date = json_rep["info"]["createdate"].as_str().unwrap().to_string();
384            self.last_login = json_rep["info"]["lastlogin"].as_str().unwrap().to_string();
385            self.subscription = json_rep["info"]["subscriptions"][0]["subscription"].as_str().unwrap().to_string();
386            Res(Ok(()))
387        } else {
388            Res(Err(json_rep["message"].as_str().unwrap().to_string()))
389        }}};
390        res
391    }
392
393    /// this will get a global variable (not user) and return it
394    pub async fn var(&mut self, varid: String) -> Res<String> {
395        let res = goldberg_stmts! {{
396            nodebug!();
397            let mut req_data = Data(String::new());
398            req_data.insert("type", "var");
399            req_data.insert("varid", &varid);
400            req_data.insert("sessionid", &self.session_id);
401            req_data.insert("name", &self.name);
402            req_data.insert("ownerid", &self.owner_id);
403
404
405        let req = Self::request(req_data, &self.api_url).await;
406            let resp = req.res;
407            let head = req.head;
408
409        if !head.contains_key("signature") {
410
411            return Res(Err("response was tampered with".to_string()));
412        }
413        let sig = head.get("signature").unwrap().to_str().unwrap();
414        if sig != Self::make_hmac(&resp, &self.enckey_s) {
415
416            return Res(Err("response was tampered with".to_string()));
417        }
418        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
419
420            nodebug!();
421        if json_rep["success"].as_bool().unwrap() {
422            Res(Ok(json_rep["message"].as_str().unwrap().to_string()))
423        } else {
424            Res(Err(json_rep["message"].as_str().unwrap().to_string()))
425        }}};
426        res
427    }
428
429    /// downloads a file, and decodes using base16::decode
430    pub async fn file(&mut self, fileid: String) -> Res<Vec<u8>> {
431        let res = goldberg_stmts! {{
432            nodebug!();
433            let mut req_data = Data(String::new());
434            req_data.insert("type", "file");
435            req_data.insert("fileid", &fileid);
436            req_data.insert("sessionid", &self.session_id);
437            req_data.insert("name", &self.name);
438            req_data.insert("ownerid", &self.owner_id);
439
440
441        let req = Self::request(req_data, &self.api_url).await;
442            let resp = req.res;
443            let head = req.head;
444
445        if !head.contains_key("signature") {
446
447            return Res(Err("response was tampered with".to_string()));
448        }
449        let sig = head.get("signature").unwrap().to_str().unwrap();
450        if sig != Self::make_hmac(&resp, &self.enckey_s) {
451
452            return Res(Err("response was tampered with".to_string()));
453        }
454        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
455
456            nodebug!();
457        if json_rep["success"].as_bool().unwrap() {
458            Res(Ok(decode(json_rep["contents"].as_str().unwrap()).unwrap()))
459        } else {
460            Res(Err(json_rep["message"].as_str().unwrap().to_string()))
461        }}};
462        res
463    }
464
465    /// sends a webhook from keyauth's servers so the url isnt exposed
466    pub async fn webhook(&mut self, webid: String, params: String) -> Res<String> {
467        let res = goldberg_stmts! {{
468            nodebug!();
469            let mut req_data = Data(String::new());
470            req_data.insert("type", "webhook");
471            req_data.insert("webid", &webid);
472            req_data.insert("params", &params);
473            req_data.insert("sessionid", &self.session_id);
474            req_data.insert("name", &self.name);
475            req_data.insert("ownerid", &self.owner_id);
476
477
478        let req = Self::request(req_data, &self.api_url).await;
479            let resp = req.res;
480            let head = req.head;
481
482        if !head.contains_key("signature") {
483
484            return Res(Err("response was tampered with".to_string()));
485        }
486        let sig = head.get("signature").unwrap().to_str().unwrap();
487        if sig != Self::make_hmac(&resp, &self.enckey_s) {
488
489            return Res(Err("response was tampered with".to_string()));
490        }
491        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
492
493            nodebug!();
494        if json_rep["success"].as_bool().unwrap() {
495            Res(Ok(json_rep["message"].as_str().unwrap().to_string()))
496        } else {
497            Res(Err(json_rep["message"].as_str().unwrap().to_string()))
498        }}};
499        res
500    }
501
502    /// checks if the user is blacklisted and sets self.blacklisted acordingly
503    pub async fn checkblacklist(&mut self) -> Res<()> {
504        let res = goldberg_stmts! {{
505            nodebug!();
506        let mut req_data = Data(String::new());
507        req_data.insert("type", "checkblacklist");
508        req_data.insert("sessionid", &self.session_id);
509        req_data.insert("name", &self.name);
510        req_data.insert("ownerid", &self.owner_id);
511
512        let req = Self::request(req_data, &self.api_url).await;
513            let resp = req.res;
514            let head = req.head;
515
516        if !head.contains_key("signature") {
517
518            return Res(Err("response was tampered with".to_string()));
519        }
520        let sig = head.get("signature").unwrap().to_str().unwrap();
521        if sig != Self::make_hmac(&resp, &self.enckey_s) {
522
523            return Res(Err("response was tampered with".to_string()));
524        }
525        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
526
527            nodebug!();
528        if json_rep["success"].as_bool().unwrap() {
529            self.blacklisted = true;
530            Res(Ok(()))
531        } else {
532            self.blacklisted = false;
533            Res(Ok(()))
534        }}};
535        res
536    }
537
538    /// checks if the session is still active or if it expired
539    pub async fn check_session(&mut self) -> Res<bool> {
540        let res = goldberg_stmts! {{
541            nodebug!();
542        let mut req_data = Data(String::new());
543        req_data.insert("type", "check");
544        req_data.insert("sessionid", &self.session_id);
545        req_data.insert("name", &self.name);
546        req_data.insert("ownerid", &self.owner_id);
547
548        let req = Self::request(req_data, &self.api_url).await;
549            let resp = req.res;
550            let head = req.head;
551
552        if !head.contains_key("signature") {
553
554            return Res(Err("response was tampered with".to_string()));
555        }
556        let sig = head.get("signature").unwrap().to_str().unwrap();
557        if sig != Self::make_hmac(&resp, &self.enckey_s) {
558
559            return Res(Err("response was tampered with".to_string()));
560        }
561        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
562
563            nodebug!();
564        Res(Ok(json_rep["success"].as_bool().unwrap()))
565            }};
566        res
567    }
568
569    /// gets json of online users
570    pub async fn fetch_online(&mut self) -> Res<serde_json::Value> {
571        let res = goldberg_stmts! {{
572            nodebug!();
573        let mut req_data = Data(String::new());
574        req_data.insert("type", "fetchOnline");
575        req_data.insert("sessionid", &self.session_id);
576        req_data.insert("name", &self.name);
577        req_data.insert("ownerid", &self.owner_id);
578
579        let req = Self::request(req_data, &self.api_url).await;
580            let resp = req.res;
581            let head = req.head;
582
583        if !head.contains_key("signature") {
584
585            return Res(Err("response was tampered with".to_string()));
586        }
587        let sig = head.get("signature").unwrap().to_str().unwrap();
588        if sig != Self::make_hmac(&resp, &self.enckey_s) {
589
590            return Res(Err("response was tampered with".to_string()));
591        }
592        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
593
594            nodebug!();
595        if json_rep["success"].as_bool().unwrap() {
596            Res(Ok(json_rep["users"].clone()))
597        } else {
598            Res(Err(json_rep["message"].as_str().unwrap().to_string()))
599        }}};
600        res
601    }
602
603    /// gets the arry of messages in a channel
604    pub async fn get_chat(&mut self, channel: String) -> Res<serde_json::Value> {
605        let res = goldberg_stmts! {{
606            nodebug!();
607        let mut req_data = Data(String::new());
608        req_data.insert("type", "chatget");
609        req_data.insert("channel", &channel);
610        req_data.insert("sessionid", &self.session_id);
611        req_data.insert("name", &self.name);
612        req_data.insert("ownerid", &self.owner_id);
613
614        let req = Self::request(req_data, &self.api_url).await;
615            let resp = req.res;
616            let head = req.head;
617
618        if !head.contains_key("signature") {
619
620            return Res(Err("response was tampered with".to_string()));
621        }
622        let sig = head.get("signature").unwrap().to_str().unwrap();
623        if sig != Self::make_hmac(&resp, &self.enckey_s) {
624
625            return Res(Err("response was tampered with".to_string()));
626        }
627        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
628
629            nodebug!();
630        if json_rep["success"].as_bool().unwrap() {
631            Res(Ok(json_rep["messages"].clone()))
632        } else {
633            Res(Err(json_rep["message"].as_str().unwrap().to_string()))
634        }}};
635        res
636    }
637
638    /// sends a chat message in a channel
639    pub async fn send_chat_message(&mut self, channel: String, message: String) -> Res<()> {
640        let res = goldberg_stmts! {{
641            nodebug!();
642        let mut req_data = Data(String::new());
643        req_data.insert("type", "chatsend");
644        req_data.insert("channel", &channel);
645        req_data.insert("message", &message);
646        req_data.insert("sessionid", &self.session_id);
647        req_data.insert("name", &self.name);
648        req_data.insert("ownerid", &self.owner_id);
649
650        let req = Self::request(req_data, &self.api_url).await;
651            let resp = req.res;
652            let head = req.head;
653
654        if !head.contains_key("signature") {
655
656            return Res(Err("response was tampered with".to_string()));
657        }
658        let sig = head.get("signature").unwrap().to_str().unwrap();
659        if sig != Self::make_hmac(&resp, &self.enckey_s) {
660
661            return Res(Err("response was tampered with".to_string()));
662        }
663        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
664
665            nodebug!();
666        if json_rep["success"].as_bool().unwrap() {
667            Res(Ok(()))
668        } else {
669            Res(Err(json_rep["message"].as_str().unwrap().to_string()))
670        }}};
671        res
672    }
673
674    /// self explanatory
675    pub async fn ban(&mut self) {
676        goldberg_stmts! {{
677            nodebug!();
678        let mut req_data = Data(String::new());
679        req_data.insert("type", "ban");
680        req_data.insert("sessionid", &self.session_id);
681        req_data.insert("name", &self.name);
682        req_data.insert("ownerid", &self.owner_id);
683
684            nodebug!();
685        Self::request(req_data, &self.api_url).await;}};
686    }
687
688    /// sets a user variable to varvalue
689    pub async fn setvar(&mut self, varname: String, varvalue: String) -> Res<()> {
690        let res = goldberg_stmts! {{
691            nodebug!();
692        let mut req_data = Data(String::new());
693        req_data.insert("type", "setvar");
694        req_data.insert("var", &varname);
695        req_data.insert("data", &varvalue);
696        req_data.insert("sessionid", &self.session_id);
697        req_data.insert("name", &self.name);
698        req_data.insert("ownerid", &self.owner_id);
699
700        let req = Self::request(req_data, &self.api_url).await;
701            let resp = req.res;
702            let head = req.head;
703
704        if !head.contains_key("signature") {
705
706            return Res(Err("response was tampered with".to_string()));
707        }
708        let sig = head.get("signature").unwrap().to_str().unwrap();
709        if sig != Self::make_hmac(&resp, &self.enckey_s) {
710
711            return Res(Err("response was tampered with".to_string()));
712        }
713        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
714
715        self.message = json_rep["message"].as_str().unwrap().to_string();
716        self.success = json_rep["success"].as_bool().unwrap();
717            nodebug!();
718        Res(Ok(()))}};
719        res
720    }
721
722    /// gets a user variable
723    pub async fn getvar(&mut self, varname: String) -> Res<String> {
724        let res = goldberg_stmts! {{
725            nodebug!();
726        let mut req_data = Data(String::new());
727        req_data.insert("type", "getvar");
728        req_data.insert("var", &varname);
729        req_data.insert("sessionid", &self.session_id);
730        req_data.insert("name", &self.name);
731        req_data.insert("ownerid", &self.owner_id);
732
733        let req = Self::request(req_data, &self.api_url).await;
734            let resp = req.res;
735            let head = req.head;
736
737        if !head.contains_key("signature") {
738
739            return Res(Err("response was tampered with".to_string()));
740        }
741        let sig = head.get("signature").unwrap().to_str().unwrap();
742        if sig != Self::make_hmac(&resp, &self.enckey_s) {
743
744            return Res(Err("response was tampered with".to_string()));
745        }
746        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
747
748            nodebug!();
749        if json_rep["success"].as_bool().unwrap() {
750            Res(Ok(json_rep["response"].as_str().unwrap().to_string()))
751        } else {
752            Res(Err(json_rep["message"].as_str().unwrap().to_string()))
753        }}};
754        res
755    }
756
757    /// logs somethink to keyauth
758    pub async fn log(&mut self, message: String, pcuser: Option<String>) {
759        goldberg_stmts! {{
760            nodebug!();
761        let usr = match pcuser {
762            Some(pcuser) => pcuser,
763            None => self.username.clone(),
764        };
765
766        let mut req_data = Data(String::new());
767        req_data.insert("type", "log");
768        req_data.insert("message", &message);
769        req_data.insert("pcuser", &usr);
770        req_data.insert("sessionid", &self.session_id);
771        req_data.insert("name", &self.name);
772        req_data.insert("ownerid", &self.owner_id);
773
774            nodebug!();
775        Self::request(req_data, &self.api_url).await;}}
776    }
777
778    /// changes Username,
779    pub async fn change_username(&mut self, new_username: String) -> Res<String> {
780        let res: Res<String> = goldberg_stmts! {{
781            nodebug!();
782        let mut req_data = Data(String::new());
783        req_data.insert("type", "changeUsername");
784        req_data.insert("newUsername", &new_username);
785        req_data.insert("sessionid", &self.session_id);
786        req_data.insert("name", &self.name);
787        req_data.insert("ownerid", &self.owner_id);
788
789        let req = Self::request(req_data, &self.api_url).await;
790            let resp = req.res;
791            let head = req.head;
792
793        if !head.contains_key("signature") {
794
795            return Res(Err("response was tampered with".to_string()));
796        }
797        let sig = head.get("signature").unwrap().to_str().unwrap();
798        if sig != Self::make_hmac(&resp, &self.enckey_s) {
799
800            return Res(Err("response was tampered with".to_string()));
801        }
802        let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
803
804            nodebug!();
805        if json_rep["success"].as_bool().unwrap() {
806            Res(Ok(json_rep["message"].as_str().unwrap().to_string()))
807        } else {
808            Res(Err(json_rep["message"].as_str().unwrap().to_string()))
809        }
810        }};
811        res
812    }
813
814    /// WARNING THIS FUNCTION ISNT OBFUSCATED DUE TO ERRORS
815    #[cfg(feature = "web_loader")]
816    pub async fn web_login(&mut self, hwid: Option<String>) -> Res<()> {
817        use std::io::Write;
818
819        let hwidd = match hwid {
820            Some(hwid) => hwid,
821            None => self.hwid.clone(),
822        };
823
824        let listener = TcpListener::bind("127.0.0.1:1337");
825        if listener.is_err() {
826            return Res(Err("Couldnt bind to port 1337".to_string()));
827        }
828        let listener = listener.unwrap();
829
830        for stream in listener.incoming() {
831            if stream.is_err() {
832                continue;
833            }
834            let mut stream = stream.unwrap();
835            let mut buf = [0u8; 4096];
836            stream.read(&mut buf).unwrap();
837            let mut headers = [httparse::EMPTY_HEADER; 16];
838            let mut req = httparse::Request::new(&mut headers);
839            req.parse(&buf).unwrap();
840            if req.path.unwrap().starts_with("/handshake") {
841                let s = req.path.unwrap();
842                let start = s.find("?user=").unwrap_or(0) + 6;
843                let end = s.rfind("&token=").unwrap_or(s.len());
844                let user = &s[start..end];
845                let start = s.find("&token=").unwrap_or(0) + 7;
846                let token = &s[start..];
847                let mut req_data = Data(String::new());
848                req_data.insert("type", "login");
849                req_data.insert("username", &user);
850                req_data.insert("token", &token);
851                req_data.insert("name", &self.name);
852                req_data.insert("ownerid", &self.owner_id);
853                req_data.insert("hwid", &self.hwid);
854                req_data.insert("sessionid", &self.session_id);
855
856                let req = Self::request(req_data, &self.api_url).await;
857                let resp = req.res;
858                let head = req.head;
859
860                if !head.contains_key("signature") {
861                    return Res(Err("response was tampered with".to_string()));
862                }
863                let sig = head.get("signature").unwrap().to_str().unwrap();
864                if sig != Self::make_hmac(&resp, &self.enckey_s) {
865                    return Res(Err("Response was tampered with".to_string()));
866                }
867                let json_rep: serde_json::Value = serde_json::from_str(&resp).unwrap();
868                let (status, body) = if json_rep["success"].as_bool().unwrap() {
869                    self.username = copy_string(user.as_bytes());
870                    self.ip = json_rep["info"]["ip"].as_str().unwrap().to_string();
871                    self.hwid = copy_string(hwidd.as_bytes());
872                    self.create_date = json_rep["info"]["createdate"].as_str().unwrap().to_string();
873                    self.last_login = json_rep["info"]["lastlogin"].as_str().unwrap().to_string();
874                    self.subscription = json_rep["info"]["subscriptions"][0]["subscription"]
875                        .as_str()
876                        .unwrap()
877                        .to_string();
878
879                    ("420", "SHEESH")
880                } else {
881                    ("200", json_rep["message"].as_str().unwrap())
882                };
883                let response = format!(
884                    r#"HTTP/1.1 {} OK
885Access-Control-Allow-Methods: Get, Post
886Access-Control-Allow-Origin: *
887Via: hugzho's big brain
888Location: your kernel ;)
889Retry-After: never lmao
890Server: \r\n\r\n
891{}"#,
892                    status, body
893                );
894                stream.write_all(response.as_bytes()).unwrap();
895                return Res(Ok(()));
896            }
897        }
898        Res(Ok(()))
899    }
900
901    #[cfg(feature = "web_loader")]
902    pub async fn button(&self, button: &str) -> Res<()> {
903        let res = goldberg_stmts! {{
904        use std::io::Write;
905
906        let listener = TcpListener::bind("127.0.0.1:1337");
907        if listener.is_err() {
908            return Res(Err("Couldnt bind to port 1337".to_string()));
909        }
910        let listener = listener.unwrap();
911
912        for stream in listener.incoming() {
913            if stream.is_err() {
914                continue;
915            }
916            let mut stream = stream.unwrap();
917            let mut buf = [0u8; 4096];
918            stream.read(&mut buf).unwrap();
919            let mut headers = [httparse::EMPTY_HEADER; 16];
920            let mut req = httparse::Request::new(&mut headers);
921            req.parse(&buf).unwrap();
922            if req.path.unwrap().starts_with(format!("/{}", button).as_str()) {
923                let response = format!(r#"HTTP/1.1 {} OK
924Access-Control-Allow-Methods: Get, Post
925Access-Control-Allow-Origin: *
926Via: hugzho's big brain
927Location: your kernel ;)
928Retry-After: never lmao
929Server: \r\n\r\n
930
931{}"#, 420, "SHEESH");
932                stream.write_all(response.as_bytes()).unwrap();
933                return Res(Ok(()));
934            }
935        }
936        Res(Ok(()))}};
937        res
938    }
939
940    async fn request(req_data: Data, url: &str) -> Resp {
941        let res: Resp = goldberg_stmts! {{
942        let client = Client::new();
943        let req_data_str = req_data.0.strip_suffix("&").unwrap().to_string();
944            nodebug!();
945        let res = client.post(url.to_string())
946            .body(req_data_str)
947            .header("User-Agent", "KeyAuth")
948            .header("Content-Type", "application/x-www-form-urlencoded")
949            .send().await.unwrap();
950        let resp = Resp {
951            head: res.headers().clone(),
952            res: res.text().await.unwrap()
953        };
954        resp}};
955        res
956    }
957
958    fn make_hmac(message: &str, key: &str) -> String {
959        let res: String = goldberg_stmts! {{ hex::encode(HMAC::mac(message, key)).to_string()}};
960        res
961    }
962}