author | unC0Rr |
Thu, 29 Sep 2022 16:30:02 +0200 | |
changeset 15882 | f185e7367dd3 |
parent 15848 | 3d05bada4799 |
child 15937 | e514ceb5e7d6 |
permissions | -rw-r--r-- |
15833 | 1 |
use mysql_async::{self, from_row_opt, params, prelude::*, Pool}; |
2 |
use sha1::{Digest, Sha1}; |
|
14779
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
3 |
|
15075 | 4 |
use crate::handlers::{AccountInfo, Sha1Digest}; |
14456 | 5 |
|
15103
823052e66611
check for account existence before asking passwords
alfadur
parents:
15075
diff
changeset
|
6 |
const CHECK_ACCOUNT_EXISTS_QUERY: &str = |
823052e66611
check for account existence before asking passwords
alfadur
parents:
15075
diff
changeset
|
7 |
r"SELECT 1 FROM users WHERE users.name = :username LIMIT 1"; |
823052e66611
check for account existence before asking passwords
alfadur
parents:
15075
diff
changeset
|
8 |
|
15517 | 9 |
const GET_ACCOUNT_QUERY: &str = r"SELECT CASE WHEN users.status = 1 THEN users.pass ELSE '' END, |
14779
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
10 |
(SELECT COUNT(users_roles.rid) FROM users_roles WHERE users.uid = users_roles.uid AND users_roles.rid = 3), |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
11 |
(SELECT COUNT(users_roles.rid) FROM users_roles WHERE users.uid = users_roles.uid AND users_roles.rid = 13) |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
12 |
FROM users WHERE users.name = :username"; |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
13 |
|
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
14 |
const STORE_STATS_QUERY: &str = r"INSERT INTO gameserver_stats |
15103
823052e66611
check for account existence before asking passwords
alfadur
parents:
15075
diff
changeset
|
15 |
(players, rooms, last_update) |
823052e66611
check for account existence before asking passwords
alfadur
parents:
15075
diff
changeset
|
16 |
VALUES |
823052e66611
check for account existence before asking passwords
alfadur
parents:
15075
diff
changeset
|
17 |
(:players, :rooms, UNIX_TIMESTAMP())"; |
14456 | 18 |
|
14785
a1077e8d26f4
implement watch message apart from replay deserializing
alfadur
parents:
14779
diff
changeset
|
19 |
const GET_REPLAY_NAME_QUERY: &str = r"SELECT filename FROM achievements WHERE id = :id"; |
a1077e8d26f4
implement watch message apart from replay deserializing
alfadur
parents:
14779
diff
changeset
|
20 |
|
15121 | 21 |
pub struct ServerStatistics { |
14456 | 22 |
rooms: u32, |
23 |
players: u32, |
|
24 |
} |
|
25 |
||
15121 | 26 |
pub struct Achievements {} |
14456 | 27 |
|
14779
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
28 |
pub struct Database { |
15833 | 29 |
pool: Pool, |
14456 | 30 |
} |
31 |
||
32 |
impl Database { |
|
15833 | 33 |
pub fn new(url: &str) -> Self { |
34 |
Self { |
|
35 |
pool: Pool::new(url), |
|
15103
823052e66611
check for account existence before asking passwords
alfadur
parents:
15075
diff
changeset
|
36 |
} |
823052e66611
check for account existence before asking passwords
alfadur
parents:
15075
diff
changeset
|
37 |
} |
823052e66611
check for account existence before asking passwords
alfadur
parents:
15075
diff
changeset
|
38 |
|
15833 | 39 |
pub async fn get_is_registered(&mut self, nick: &str) -> mysql_async::Result<bool> { |
40 |
let mut connection = self.pool.get_conn().await?; |
|
41 |
let result = CHECK_ACCOUNT_EXISTS_QUERY |
|
42 |
.with(params! { "username" => nick }) |
|
43 |
.first(&mut connection) |
|
44 |
.await?; |
|
45 |
Ok(!result.is_empty()) |
|
46 |
} |
|
47 |
||
48 |
pub async fn get_account( |
|
14779
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
49 |
&mut self, |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
50 |
nick: &str, |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
51 |
protocol: u16, |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
52 |
password_hash: &str, |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
53 |
client_salt: &str, |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
54 |
server_salt: &str, |
15833 | 55 |
) -> mysql_async::Result<Option<AccountInfo>> { |
56 |
let mut connection = self.pool.get_conn().await?; |
|
57 |
if let Some((mut password, is_admin, is_contributor)) = GET_ACCOUNT_QUERY |
|
58 |
.with(params! { "username" => nick }) |
|
59 |
.first::<(String, i32, i32), _>(&mut connection) |
|
60 |
.await? |
|
61 |
{ |
|
62 |
let client_hash = get_hash(protocol, &password, &client_salt, &server_salt); |
|
63 |
let server_hash = get_hash(protocol, &password, &server_salt, &client_salt); |
|
64 |
password.replace_range(.., "🦔🦔🦔🦔🦔🦔🦔🦔"); |
|
14779
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
65 |
|
15833 | 66 |
if client_hash == password_hash { |
67 |
Ok(Some(AccountInfo { |
|
68 |
is_registered: true, |
|
69 |
is_admin: is_admin == 1, |
|
70 |
is_contributor: is_contributor == 1, |
|
71 |
server_hash, |
|
72 |
})) |
|
14779
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
73 |
} else { |
15110 | 74 |
Ok(None) |
14779
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
75 |
} |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
76 |
} else { |
15833 | 77 |
Ok(None) |
14456 | 78 |
} |
79 |
} |
|
80 |
||
15833 | 81 |
pub async fn get_checker_account( |
15532 | 82 |
&mut self, |
83 |
nick: &str, |
|
84 |
checker_password: &str, |
|
15833 | 85 |
) -> mysql_async::Result<bool> { |
86 |
let mut connection = self.pool.get_conn().await?; |
|
87 |
if let Some((password, _, _)) = GET_ACCOUNT_QUERY |
|
88 |
.with(params! { "username" => nick }) |
|
89 |
.first::<(String, i32, i32), _>(&mut connection) |
|
90 |
.await? |
|
91 |
{ |
|
92 |
Ok(checker_password == password) |
|
15532 | 93 |
} else { |
15833 | 94 |
Ok(false) |
15532 | 95 |
} |
96 |
} |
|
97 |
||
15833 | 98 |
pub async fn store_stats(&mut self, stats: &ServerStatistics) -> mysql_async::Result<()> { |
99 |
let mut connection = self.pool.get_conn().await?; |
|
100 |
STORE_STATS_QUERY |
|
101 |
.with(params! { |
|
102 |
"players" => stats.players, |
|
103 |
"rooms" => stats.rooms, |
|
104 |
}) |
|
105 |
.ignore(&mut connection) |
|
106 |
.await |
|
14456 | 107 |
} |
108 |
||
15848 | 109 |
pub async fn store_achievements( |
110 |
&mut self, |
|
111 |
achievements: &Achievements, |
|
112 |
) -> mysql_async::Result<()> { |
|
14456 | 113 |
Ok(()) |
114 |
} |
|
115 |
||
15833 | 116 |
pub async fn get_replay_name(&mut self, replay_id: u32) -> mysql_async::Result<Option<String>> { |
117 |
let mut connection = self.pool.get_conn().await?; |
|
118 |
GET_REPLAY_NAME_QUERY |
|
119 |
.with(params! { "id" => replay_id }) |
|
120 |
.first::<String, _>(&mut connection) |
|
121 |
.await |
|
14456 | 122 |
} |
123 |
} |
|
14779
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
124 |
|
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
125 |
fn get_hash(protocol_number: u16, web_password: &str, salt1: &str, salt2: &str) -> Sha1Digest { |
15833 | 126 |
let data = format!( |
14779
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
127 |
"{}{}{}{}{}", |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
128 |
salt1, salt2, web_password, protocol_number, "!hedgewars" |
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
129 |
); |
15833 | 130 |
|
131 |
let mut sha1 = Sha1::new(); |
|
132 |
sha1.update(&data); |
|
133 |
Sha1Digest::new(sha1.finalize().try_into().unwrap()) |
|
14779
f43ab2bd76ae
add a thread for internal server IO and implement account checking with it
alfadur
parents:
14457
diff
changeset
|
134 |
} |