lic.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. use hbb_common::{bail, log, sodiumoxide::crypto::sign, ResultType};
  2. use serde_derive::{Deserialize, Serialize};
  3. use std::io::prelude::*;
  4. use std::path::Path;
  5. #[derive(Debug, PartialEq, Default, Serialize, Deserialize, Clone)]
  6. pub struct License {
  7. #[serde(default)]
  8. hostname: String,
  9. #[serde(default)]
  10. uid: String,
  11. #[serde(default)]
  12. mac: String,
  13. }
  14. #[derive(Debug, PartialEq, Default, Serialize, Deserialize, Clone)]
  15. pub struct Post {
  16. #[serde(default)]
  17. lic: License,
  18. #[serde(default)]
  19. email: String,
  20. #[serde(default)]
  21. status: String,
  22. }
  23. const LICENSE_FILE: &'static str = ".license.txt";
  24. pub fn check_lic(email: &str) -> bool {
  25. let lic = get_lic();
  26. let path = Path::new(LICENSE_FILE);
  27. if Path::is_file(&path) {
  28. let contents = std::fs::read_to_string(&path).unwrap_or("".to_owned());
  29. if let Ok(old_lic) = dec_lic(&contents) {
  30. if lic == old_lic {
  31. return true;
  32. }
  33. }
  34. }
  35. if email.is_empty() {
  36. log::error!("Registered email required.");
  37. return false;
  38. }
  39. match check_email(lic.clone(), email.to_owned()) {
  40. Ok(v) => {
  41. if v {
  42. write_lic(&lic);
  43. }
  44. return v;
  45. }
  46. Err(err) => {
  47. log::error!("{}", err);
  48. return false;
  49. }
  50. }
  51. }
  52. fn write_lic(lic: &License) {
  53. if let Ok(s) = enc_lic(&lic) {
  54. if let Ok(mut f) = std::fs::File::create(LICENSE_FILE) {
  55. f.write_all(s.as_bytes()).ok();
  56. f.sync_all().ok();
  57. }
  58. }
  59. }
  60. fn check_email(lic: License, email: String) -> ResultType<bool> {
  61. use reqwest::blocking::Client;
  62. let p: Post = Client::new()
  63. .post("http://rustdesk.com/api/check-email")
  64. .json(&Post {
  65. lic,
  66. email,
  67. ..Default::default()
  68. })
  69. .send()?
  70. .json()?;
  71. if !p.status.is_empty() {
  72. bail!("{}", p.status);
  73. }
  74. Ok(true)
  75. }
  76. fn get_lic() -> License {
  77. let hostname = whoami::hostname();
  78. let uid = machine_uid::get().unwrap_or("".to_owned());
  79. let mac = if let Ok(Some(ma)) = mac_address::get_mac_address() {
  80. base64::encode_config(ma.bytes(), base64::URL_SAFE_NO_PAD)
  81. } else {
  82. "".to_owned()
  83. };
  84. License { hostname, uid, mac }
  85. }
  86. fn enc_lic(lic: &License) -> ResultType<String> {
  87. let tmp = serde_json::to_vec::<License>(lic)?;
  88. const SK: &[u64] = &[
  89. 139, 164, 88, 86, 6, 123, 221, 248, 96, 36, 106, 207, 99, 124, 27, 196, 5, 159, 58, 253,
  90. 238, 94, 3, 184, 237, 236, 122, 59, 205, 95, 6, 189, 88, 168, 68, 104, 60, 5, 163, 198,
  91. 165, 38, 12, 85, 114, 203, 96, 163, 70, 48, 0, 131, 57, 12, 46, 129, 83, 17, 84, 193, 119,
  92. 197, 130, 103,
  93. ];
  94. let sk: Vec<u8> = SK.iter().map(|x| *x as u8).collect();
  95. let mut sk_ = [0u8; sign::SECRETKEYBYTES];
  96. sk_[..].copy_from_slice(&sk);
  97. let sk = sign::SecretKey(sk_);
  98. let tmp = base64::encode_config(sign::sign(&tmp, &sk), base64::URL_SAFE_NO_PAD);
  99. let tmp: String = tmp.chars().rev().collect();
  100. Ok(tmp)
  101. }
  102. fn dec_lic(s: &str) -> ResultType<License> {
  103. let tmp: String = s.chars().rev().collect();
  104. const PK: &[u64] = &[
  105. 88, 168, 68, 104, 60, 5, 163, 198, 165, 38, 12, 85, 114, 203, 96, 163, 70, 48, 0, 131, 57,
  106. 12, 46, 129, 83, 17, 84, 193, 119, 197, 130, 103,
  107. ];
  108. let pk: Vec<u8> = PK.iter().map(|x| *x as u8).collect();
  109. let mut pk_ = [0u8; sign::PUBLICKEYBYTES];
  110. pk_[..].copy_from_slice(&pk);
  111. let pk = sign::PublicKey(pk_);
  112. if let Ok(data) = sign::verify(&base64::decode_config(tmp, base64::URL_SAFE_NO_PAD)?, &pk) {
  113. Ok(serde_json::from_slice::<License>(&data)?)
  114. } else {
  115. bail!("sign:verify failed");
  116. }
  117. }
  118. pub const EMAIL_ARG: &'static str =
  119. "-m, --email=[EMAIL] 'Sets your email address registered with RustDesk'";