Skip to content

Commit 515f440

Browse files
committed
update handshake and some data
1 parent 77a6d00 commit 515f440

File tree

6 files changed

+108
-33
lines changed

6 files changed

+108
-33
lines changed

database/.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
data.json
22
file_info.json
3-
trle
43
__pycache__
4+
.mypy_cache
55
trle.tar.gz
6+
trle
7+
trle.sanitized.tar.gz
8+
trle.sanitized

database/get_trle.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,18 @@ else
1212
fi
1313

1414
# Define the download link
15-
url="https://mega.nz/file/xXkV3JqJ#1Ejtd9enidYYpV3FRLO5KSzcUg7-_Jg-vNi66RKo8aI"
15+
url1="https://mega.nz/file/xXkV3JqJ#1Ejtd9enidYYpV3FRLO5KSzcUg7-_Jg-vNi66RKo8aI"
16+
url2="https://mega.nz/file/kDlEVJiB#eRam4FXZBljrfHaurE3qz56VVi7RxPm-7IxG0aBq-uM"
1617

1718
# Download the file using the available tool
1819
echo "Using $downloader to download the file..."
19-
$downloader "$url"
20+
$downloader "$url1"
21+
$downloader "$url2"
2022

2123
# Verify the checksum (assuming you want to compare it to the expected checksum)
2224
echo "Verifying checksum..."
2325
echo "29e7e89bc11ebe77eafbd1c78ca3f1a7 trle.tar.gz" | md5sum -c -
26+
echo "7865bf73f09d531fb0ddc6b654d611f5 trle.sanitized.tar.gz" | md5sum -c -
2427

2528
# Extract the tar.gz file
2629
echo "Extracting the archive..."

database/https.py

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -80,32 +80,35 @@ def validate_url(self, url):
8080
logging.error("Invalid URL domain: %s", url)
8181
sys.exit(1)
8282

83-
def head(self, curl):
83+
def head(self, url):
8484
"""Take the curl object to head state, with redirect."""
85-
if isinstance(curl, pycurl.Curl):
85+
curl = pycurl.Curl()
86+
response = ""
87+
temp_cert_path = None
88+
try:
8689
buffer = BytesIO()
87-
curl.setopt(pycurl.NOBODY, True)
8890
curl.setopt(pycurl.HEADERFUNCTION, buffer.write)
91+
curl.setopt(pycurl.NOBODY, True)
92+
curl.setopt(pycurl.URL, url)
8993
curl.setopt(pycurl.FOLLOWLOCATION, True)
90-
temp_cert_path = None
9194

9295
if self.misconfigured_server:
9396
if not self.leaf_cert:
9497
sys.exit(1)
9598
temp_cert_path = REQUEST_HANDLER.set_leaf(curl)
9699

97-
try:
98-
curl.perform()
99-
except pycurl.error:
100-
print("Error performing request:", pycurl.error)
101-
finally:
102-
curl.close()
100+
curl.perform()
101+
response = buffer.getvalue().decode('utf-8')
103102

104-
if temp_cert_path and os.path.exists(temp_cert_path):
105-
os.remove(temp_cert_path)
103+
except pycurl.error:
104+
print("Error performing request:", pycurl.error)
105+
finally:
106+
curl.close()
106107

107-
return buffer.getvalue().decode('utf-8')
108-
return ""
108+
if temp_cert_path and os.path.exists(temp_cert_path):
109+
os.remove(temp_cert_path)
110+
111+
return response
109112

110113
def validate_data_type(self, content_type):
111114
"""Limit to used data types."""
@@ -167,6 +170,9 @@ def get_response(self, url, content_type):
167170
if content_type == 'application/zip':
168171
return DOWNLOADER.download_file(url)
169172

173+
if content_type == 'head':
174+
return self.head(url)
175+
170176
max_retries = 3
171177
retries = 0
172178
curl = None
@@ -180,10 +186,6 @@ def get_response(self, url, content_type):
180186
headers_buffer = BytesIO()
181187
curl = pycurl.Curl() # pylint: disable=no-member
182188
curl.setopt(pycurl.URL, url)
183-
184-
if content_type == 'application/zip':
185-
return self.head(curl)
186-
187189
curl.setopt(pycurl.WRITEHEADER, headers_buffer)
188190
curl.setopt(pycurl.WRITEDATA, response_buffer)
189191

database/ideas.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,10 @@ like another user on the computer trying to prank another user :)
278278
You're home is a dirty place and no one can help what happens there
279279
but we validate before we open any database there that is has sane
280280
permissions sanitized data in there.
281+
282+
https://www.trlevel.de/index.php?file-download/1/
283+
we can get those also so there will be 3 hosts but they use rar
284+
still the app should support rar also at some point
285+
286+
we need to support this kind of download link also
287+
https://www.trle.net/levels/levels/2020/0620/BtB

database/sanitize_downloads.py

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,37 @@
88
import re
99

1010

11+
def check_file_list(data):
12+
"""Check if there is zip data to prevent crash."""
13+
zip_file_list = data.get('zip_files', [])
14+
if not isinstance(zip_file_list, list) or not zip_file_list:
15+
return False
16+
return True
17+
18+
1119
def new_input(data, file_path):
1220
"""Take new input"""
21+
22+
if not check_file_list(data):
23+
print(f"{file_path} has no zip file.")
24+
return
25+
1326
zip_file = data['zip_files'][0]
1427
print(zip_file)
15-
if input("Do you want to remove the file? y/n: ") == 'y':
28+
if input("Do you want to remove the json file? y/n: ").lower() == 'y':
1629
os.remove(file_path)
1730
print(f"{file_path} has been removed.")
1831
return
1932

20-
zip_file['name'] = input("New name: ")
21-
zip_file['size'] = float(input("New size: "))
22-
zip_file['md5'] = input("New md5: ")
23-
zip_file['url'] = input("New url: ")
33+
if input("Do you want to remove the file object? y/n: ").lower() == 'y':
34+
del data['zip_files'][0]
35+
print("Object has been removed.")
36+
else:
37+
zip_file['name'] = input("New name: ")
38+
zip_file['size'] = float(input("New size: "))
39+
zip_file['md5'] = input("New md5: ")
40+
zip_file['url'] = input("New url: ")
41+
2442
with open(file_path, mode='w', encoding='utf-8') as json_file:
2543
json.dump(data, json_file)
2644

@@ -41,6 +59,10 @@ def sanitize(data, file_path):
4159
Exits:
4260
Exits the program with status 1 if any validation fails.
4361
"""
62+
if not check_file_list(data):
63+
print(f"{file_path} has no zip file.")
64+
return
65+
4466
zip_file = data['zip_files'][0]
4567
errors = []
4668

@@ -65,10 +87,18 @@ def sanitize(data, file_path):
6587
elif not re.fullmatch(r"^[a-fA-F0-9]{32}$", md5):
6688
errors.append("The 'md5' attribute is not a valid 32-character hexadecimal MD5 hash.")
6789

68-
# Validate url
90+
# Force save if not https
6991
url = zip_file.get('url')
92+
if 'http://' in url:
93+
url = url.replace('http://', 'https://')
94+
data['zip_files'][0]['url'] = url
95+
with open(file_path, mode='w', encoding='utf-8') as json_file:
96+
json.dump(data, json_file)
97+
98+
# Validate url
7099
pattern1 = r"^https://trcustoms\.org/api/level_files/\d+/download$"
71-
pattern2 = r"^https://www\.trle\.net/levels/levels/\d{4}/\d{4}/[a-zA-Z0-9%-_\.$]+\.zip$"
100+
pattern2 = r"^https://www\.trle\.net/levels/levels/\d{4}(/(\d{4})?)?/[a-zA-Z0-9%-_\.$]+\.zip$"
101+
72102
if not url:
73103
errors.append("The 'url' attribute is missing.")
74104
elif not re.match(pattern1, url) and not re.match(pattern2, url):

src/Network.cpp

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,61 @@
2424
namespace ssl = boost::asio::ssl;
2525
using tcp = boost::asio::ip::tcp;
2626

27-
std::string get_ssl_certificate(const std::string& host) {
27+
std::string get_ssl_certificate(const std::string& host)
28+
{
2829
boost::asio::io_context io_context;
30+
31+
// Use SSLv23 context (it's compatible with all versions of SSL/TLS)
2932
ssl::context ssl_context(ssl::context::sslv23);
3033

34+
// Restrict supported protocols to TLSv1.3 and TLSv1.2, these are no no
35+
ssl_context.set_options(ssl::context::no_sslv2 | ssl::context::no_sslv3);
36+
ssl_context.set_options(ssl::context::no_tlsv1 | ssl::context::no_tlsv1_1);
37+
38+
// Resolver for HTTPS (default port 443)
3139
tcp::resolver resolver(io_context);
32-
tcp::resolver::results_type endpoints = resolver.resolve(host, "https");
40+
tcp::resolver::results_type endpoints = resolver.resolve(host, "443");
41+
3342
ssl::stream<tcp::socket> stream(io_context, ssl_context);
3443
SSL_set_tlsext_host_name(stream.native_handle(), host.c_str());
35-
boost::asio::connect(stream.lowest_layer(), endpoints);
36-
stream.handshake(ssl::stream_base::client);
3744

45+
try
46+
{
47+
boost::asio::connect(stream.lowest_layer(), endpoints);
48+
stream.handshake(ssl::stream_base::client);
49+
}
50+
catch (const boost::system::system_error& e)
51+
{
52+
std::cerr << "SSL handshake failed: " << e.what() << std::endl;
53+
return "";
54+
}
55+
56+
// Get certificate
3857
X509* cert = SSL_get_peer_certificate(stream.native_handle());
39-
if (!cert) {
58+
if (!cert)
59+
{
4060
std::cerr << "No certificate found." << std::endl;
4161
return "";
4262
}
4363

64+
// Verify the certificate matches the host
65+
if (X509_check_host(cert, host.c_str(), host.length(), 0, nullptr) != 1)
66+
{
67+
std::cerr << "Hostname verification failed." << std::endl;
68+
X509_free(cert);
69+
return "";
70+
}
71+
4472
BIO* bio = BIO_new(BIO_s_mem());
4573
PEM_write_bio_X509(bio, cert);
4674
char* cert_str = nullptr;
4775
qint64 cert_len = BIO_get_mem_data(bio, &cert_str);
4876
std::string cert_buffer(cert_str, cert_len);
4977

78+
// Clean up
5079
BIO_free(bio);
5180
X509_free(cert);
81+
5282
return cert_buffer;
5383
}
5484

0 commit comments

Comments
 (0)