1 (* Copyright 2003 pango *)
3 This file is part of mldonkey.
5 mldonkey is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 mldonkey is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with mldonkey; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 Detect clients switching to another client_hash, already is use by
22 someone else (almost certainly a theft).
32 let log_prefix = "[eDThieves]"
35 lprintf_nl2
log_prefix fmt
37 type hash_history
= Ip.t
* Md4.t
* int
39 (* index by client IP *)
40 let (client_hashes
: (Ip.t
, hash_history
ref) Hashtbl.t
) = Hashtbl.create
1023
42 (* index by client hash *)
43 let hash_of_md4 md4
= Hashtbl.hash
(Md4.direct_to_string md4
)
48 let hash = hash_of_md4
51 module Md4_hashtbl
= Hashtbl.Make
( Md4HashType
)
53 let hashes_usage = Md4_hashtbl.create
1023
56 let register_client_hash ip
hash =
59 Hashtbl.find client_hashes ip
61 let new_record = ref (ip
, Md4.null
, 0) in
62 Hashtbl.add client_hashes ip
new_record;
65 let find_by_hash hash =
67 Md4_hashtbl.find
hashes_usage hash
69 let new_record = ref (Ip.null
, hash, 0) in
70 Md4_hashtbl.add
hashes_usage hash new_record;
73 let by_ip = find_by_ip ip
in
74 let by_hash = find_by_hash hash in
75 let new_record = (ip
, hash, last_time
()) in
78 (* no hash was previously known for that IP. We do not check if the
79 hash was previously used somewhere else, as it could be legitimate
80 (client switching IP address). *)
82 by_hash := new_record;
84 | _
, previous_hash
, _
->
85 if Md4.equal previous_hash
hash then begin
86 (* no change, all is fine; just update timestamps *)
88 by_hash := new_record;
91 (* peer changed in hash, what's happening ? *)
94 (* that hash is original, all is fine *)
96 Md4_hashtbl.remove
hashes_usage previous_hash
;
98 by_hash := new_record;
101 (* it switched to a hash that's used somewhere else,
102 that's certainly a theft. *)
104 lprintf_nl "client_md4 %s (ip:%s) was already used somewhere else, that's certainly a theft!"
105 (Md4.to_string
hash) (Ip.to_string ip
);
108 let clean_thieves () =
109 let timelimit = last_time
() - 3 * 3600 in
110 let obsolete_ips = Hashtbl.fold
(fun ip r l
->
111 match !r
with _
, _
, time
->
112 if time
< timelimit then
114 else l
) client_hashes
[] in
115 List.iter
(fun ip
-> Hashtbl.remove client_hashes ip
) obsolete_ips;
116 let obsolete_hashes = Md4_hashtbl.fold
(fun hash r l
->
117 match !r
with _
, _
, time
->
118 if time
< timelimit then
120 else l
) hashes_usage [] in
121 List.iter
(fun hash -> Md4_hashtbl.remove
hashes_usage hash) obsolete_hashes
123 module Marshal
= struct
126 let v = Marshal.to_string v [] in
127 (* The header depends on OCaml version. Remove it. *)
128 let v = String.sub
v (Marshal.header_size
)
129 (String.length
v - Marshal.header_size
) in
137 lprintf "Hashes history by IP:\n";
138 Hashtbl.iter (fun ip r -> match !r with (ip, md4, time) -> lprintf "%s: %s (%d)\n" (Ip.to_string ip) (Md4.to_string md4) time) client_hashes;
139 lprintf "Hashes history by hash:\n";
140 Md4_hashtbl.iter (fun md4 r -> match !r with (ip, md4, time) -> lprintf "%s: %s (%d)\n" (Md4.to_string md4) (Ip.to_string ip) time) hashes_usage;
144 let peer1 = Ip.of_string "1.2.3.4" in
145 let peer2 = Ip.of_string "5.6.7.8" in
146 let peer3 = Ip.of_string "9.10.11.12" in
147 lprintf "Add a peer...\n";
148 assert(register_client_hash peer1 (Md4.of_string "11111111111111111111111111111111"));
150 lprintf "Another peer...\n";
151 assert(register_client_hash peer2 (Md4.of_string "22222222222222222222222222222222"));
153 lprintf "First peer changes of hash, ok...\n";
154 assert(register_client_hash peer1 (Md4.of_string "33333333333333333333333333333333"));
156 lprintf "A third peer appears with the same hash as the first, ok (could be in fact first one switching IP)...\n";
157 assert(register_client_hash peer3 (Md4.of_string "33333333333333333333333333333333"));
159 lprintf "Second peer takes the hash of the first, wrong!...\n";
160 assert(not (register_client_hash peer2 (Md4.of_string "33333333333333333333333333333333")));
162 lprintf "Third peer takes a hash that *was* first's hash, ok (?)...\n";
163 assert(register_client_hash peer3 (Md4.of_string "11111111111111111111111111111111"));