Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
MTProxy2
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
MTProxy2
Commits
e4c6b8bc
Commit
e4c6b8bc
authored
Jul 03, 2019
by
levlam
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement TLS transport for MTProto-proxy.
parent
2c942119
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
362 additions
and
57 deletions
+362
-57
sha256.c
common/sha256.c
+11
-1
sha256.h
common/sha256.h
+2
-0
net-connections.h
net/net-connections.h
+24
-22
net-tcp-connections.c
net/net-tcp-connections.c
+45
-8
net-tcp-rpc-common.c
net/net-tcp-rpc-common.c
+5
-0
net-tcp-rpc-common.h
net/net-tcp-rpc-common.h
+10
-10
net-tcp-rpc-ext-server.c
net/net-tcp-rpc-ext-server.c
+265
-13
net-tcp-rpc-server.c
net/net-tcp-rpc-server.c
+0
-3
No files found.
common/sha256.c
View file @
e4c6b8bc
...
@@ -18,9 +18,12 @@
...
@@ -18,9 +18,12 @@
2016 Nikolai Durov
2016 Nikolai Durov
*/
*/
#include <assert.h>
#include "sha256.h"
#include "sha256.h"
#include <assert.h>
#include <openssl/hmac.h>
void
sha256_starts
(
sha256_context
*
ctx
)
{
void
sha256_starts
(
sha256_context
*
ctx
)
{
EVP_MD_CTX_init
(
ctx
);
EVP_MD_CTX_init
(
ctx
);
EVP_DigestInit_ex
(
ctx
,
EVP_sha256
(),
NULL
);
EVP_DigestInit_ex
(
ctx
,
EVP_sha256
(),
NULL
);
...
@@ -52,3 +55,10 @@ void sha256_two_chunks (const unsigned char *input1, int ilen1, const unsigned c
...
@@ -52,3 +55,10 @@ void sha256_two_chunks (const unsigned char *input1, int ilen1, const unsigned c
sha256_finish
(
ctx
,
output
);
sha256_finish
(
ctx
,
output
);
EVP_MD_CTX_free
(
ctx
);
EVP_MD_CTX_free
(
ctx
);
}
}
void
sha256_hmac
(
unsigned
char
*
key
,
int
keylen
,
unsigned
char
*
input
,
int
ilen
,
unsigned
char
output
[
32
])
{
unsigned
int
len
=
0
;
unsigned
char
*
result
=
HMAC
(
EVP_sha256
(),
key
,
keylen
,
input
,
ilen
,
output
,
&
len
);
assert
(
result
==
output
);
assert
(
len
==
32
);
}
common/sha256.h
View file @
e4c6b8bc
...
@@ -35,3 +35,5 @@ void sha256_update (sha256_context *ctx, const unsigned char *input, int ilen);
...
@@ -35,3 +35,5 @@ void sha256_update (sha256_context *ctx, const unsigned char *input, int ilen);
void
sha256_finish
(
sha256_context
*
ctx
,
unsigned
char
output
[
32
]);
void
sha256_finish
(
sha256_context
*
ctx
,
unsigned
char
output
[
32
]);
void
sha256
(
const
unsigned
char
*
input
,
int
ilen
,
unsigned
char
output
[
32
]);
void
sha256
(
const
unsigned
char
*
input
,
int
ilen
,
unsigned
char
output
[
32
]);
void
sha256_two_chunks
(
const
unsigned
char
*
input1
,
int
ilen1
,
const
unsigned
char
*
input2
,
int
ilen2
,
unsigned
char
output
[
32
]);
void
sha256_two_chunks
(
const
unsigned
char
*
input1
,
int
ilen1
,
const
unsigned
char
*
input2
,
int
ilen2
,
unsigned
char
output
[
32
]);
void
sha256_hmac
(
unsigned
char
*
key
,
int
keylen
,
unsigned
char
*
input
,
int
ilen
,
unsigned
char
output
[
32
]);
net/net-connections.h
View file @
e4c6b8bc
...
@@ -54,35 +54,36 @@
...
@@ -54,35 +54,36 @@
/* for connection flags */
/* for connection flags */
#define
C_WANTRD 1
#define
C_WANTRD 1
#define
C_WANTWR 2
#define
C_WANTWR 2
#define
C_WANTRW (C_WANTRD | C_WANTWR)
#define
C_WANTRW (C_WANTRD | C_WANTWR)
#define
C_INCONN 4
#define
C_INCONN 4
#define
C_ERROR 8
#define
C_ERROR 8
#define
C_NORD 0x10
#define
C_NORD 0x10
#define
C_NOWR 0x20
#define
C_NOWR 0x20
#define
C_NORW (C_NORD | C_NOWR)
#define
C_NORW (C_NORD | C_NOWR)
#define
C_INQUERY 0x40
#define
C_INQUERY 0x40
#define
C_FAILED 0x80
#define
C_FAILED 0x80
#define
C_ALARM 0x100
#define
C_ALARM 0x100
#define C_AIO 0x200
#define C_AIO 0x200
#define C_INTIMEOUT 0x400
#define C_INTIMEOUT 0x400
#define
C_STOPREAD 0x800
#define
C_STOPREAD 0x800
#define
C_REPARSE 0x1000
#define
C_REPARSE 0x1000
#define C_DFLUSH 0x2000
#define C_DFLUSH 0x2000
#define
C_IPV6 0x4000
#define
C_IPV6 0x4000
#define C_EXTERNAL 0x8000
#define C_EXTERNAL 0x8000
#define C_SPECIAL 0x10000
#define C_SPECIAL 0x10000
#define
C_NOQACK 0x20000
#define
C_NOQACK 0x20000
#define
C_RAWMSG 0x40000
#define
C_RAWMSG 0x40000
#define C_NET_FAILED
0x80000
#define C_NET_FAILED
0x80000
#define
C_CRYPTOIN 0x100000
#define
C_CRYPTOIN 0x100000
#define
C_CRYPTOOUT 0x200000
#define
C_CRYPTOOUT 0x200000
#define C_STOPPARSE
0x400000
#define C_STOPPARSE
0x400000
#define C_ISDH 0x800000
#define C_ISDH 0x800000
#define C_READY_PENDING 0x1000000
#define C_READY_PENDING 0x1000000
#define C_CONNECTED 0x2000000
#define C_CONNECTED 0x2000000
#define C_STOPWRITE 0x4000000
#define C_STOPWRITE 0x4000000
#define C_IS_TLS 0x8000000
#define C_PERMANENT (C_IPV6 | C_RAWMSG)
#define C_PERMANENT (C_IPV6 | C_RAWMSG)
/* for connection status */
/* for connection status */
...
@@ -232,6 +233,7 @@ struct connection_info {
...
@@ -232,6 +233,7 @@ struct connection_info {
void
*
crypto_temp
;
void
*
crypto_temp
;
int
listening
,
listening_generation
;
int
listening
,
listening_generation
;
int
window_clamp
;
int
window_clamp
;
int
left_tls_packet_length
;
struct
raw_message
in_u
,
in
,
out
,
out_p
;
struct
raw_message
in_u
,
in
,
out
,
out_p
;
...
...
net/net-tcp-connections.c
View file @
e4c6b8bc
...
@@ -238,11 +238,22 @@ int cpu_tcp_aes_crypto_ctr128_encrypt_output (connection_job_t C) /* {{{ */ {
...
@@ -238,11 +238,22 @@ int cpu_tcp_aes_crypto_ctr128_encrypt_output (connection_job_t C) /* {{{ */ {
struct
aes_crypto
*
T
=
c
->
crypto
;
struct
aes_crypto
*
T
=
c
->
crypto
;
assert
(
c
->
crypto
);
assert
(
c
->
crypto
);
struct
raw_message
*
out
=
&
c
->
out
;
int
l
=
out
->
total_bytes
;
while
(
c
->
out
.
total_bytes
)
{
if
(
l
)
{
int
len
=
c
->
out
.
total_bytes
;
assert
(
rwm_encrypt_decrypt_to
(
&
c
->
out
,
&
c
->
out_p
,
l
,
&
T
->
write_aeskey
,
(
void
*
)
T
->
write_aeskey
.
type
->
ctr128_crypt
,
T
->
write_iv
,
1
,
T
->
write_ebuf
,
&
T
->
write_num
)
==
l
);
if
(
c
->
flags
&
C_IS_TLS
)
{
assert
(
c
->
left_tls_packet_length
>=
0
);
const
int
MAX_PACKET_LENGTH
=
1425
;
if
(
MAX_PACKET_LENGTH
<
len
)
{
len
=
MAX_PACKET_LENGTH
;
}
unsigned
char
header
[
5
]
=
{
0x17
,
0x03
,
0x03
,
len
>>
8
,
len
&
255
};
rwm_push_data
(
&
c
->
out_p
,
header
,
5
);
vkprintf
(
2
,
"Send TLS-packet of length %d
\n
"
,
len
);
}
assert
(
rwm_encrypt_decrypt_to
(
&
c
->
out
,
&
c
->
out_p
,
len
,
&
T
->
write_aeskey
,
(
void
*
)
T
->
write_aeskey
.
type
->
ctr128_crypt
,
T
->
write_iv
,
1
,
T
->
write_ebuf
,
&
T
->
write_num
)
==
len
);
}
}
return
0
;
return
0
;
...
@@ -254,11 +265,37 @@ int cpu_tcp_aes_crypto_ctr128_decrypt_input (connection_job_t C) /* {{{ */ {
...
@@ -254,11 +265,37 @@ int cpu_tcp_aes_crypto_ctr128_decrypt_input (connection_job_t C) /* {{{ */ {
struct
connection_info
*
c
=
CONN_INFO
(
C
);
struct
connection_info
*
c
=
CONN_INFO
(
C
);
struct
aes_crypto
*
T
=
c
->
crypto
;
struct
aes_crypto
*
T
=
c
->
crypto
;
assert
(
c
->
crypto
);
assert
(
c
->
crypto
);
struct
raw_message
*
in
=
&
c
->
in_u
;
int
l
=
in
->
total_bytes
;
while
(
c
->
in_u
.
total_bytes
)
{
if
(
l
)
{
int
len
=
c
->
in_u
.
total_bytes
;
assert
(
rwm_encrypt_decrypt_to
(
&
c
->
in_u
,
&
c
->
in
,
l
,
&
T
->
read_aeskey
,
(
void
*
)
T
->
read_aeskey
.
type
->
ctr128_crypt
,
T
->
read_iv
,
1
,
T
->
read_ebuf
,
&
T
->
read_num
)
==
l
);
if
(
c
->
flags
&
C_IS_TLS
)
{
assert
(
c
->
left_tls_packet_length
>=
0
);
if
(
c
->
left_tls_packet_length
==
0
)
{
if
(
len
<
5
)
{
vkprintf
(
2
,
"Need %d more bytes to parse TLS header
\n
"
,
5
-
len
);
return
5
-
len
;
}
unsigned
char
header
[
5
];
assert
(
rwm_fetch_lookup
(
&
c
->
in_u
,
header
,
5
)
==
5
);
if
(
memcmp
(
header
,
"
\x17\x03\x03
"
,
3
)
!=
0
)
{
vkprintf
(
1
,
"error while parsing packet: expect TLS header
\n
"
);
fail_connection
(
C
,
-
1
);
return
0
;
}
c
->
left_tls_packet_length
=
256
*
header
[
3
]
+
header
[
4
];
vkprintf
(
2
,
"Receive TLS-packet of length %d
\n
"
,
c
->
left_tls_packet_length
);
assert
(
rwm_skip_data
(
&
c
->
in_u
,
5
)
==
5
);
len
-=
5
;
}
if
(
c
->
left_tls_packet_length
<
len
)
{
len
=
c
->
left_tls_packet_length
;
}
c
->
left_tls_packet_length
-=
len
;
}
vkprintf
(
2
,
"Read %d bytes out of %d available
\n
"
,
len
,
c
->
in_u
.
total_bytes
);
assert
(
rwm_encrypt_decrypt_to
(
&
c
->
in_u
,
&
c
->
in
,
len
,
&
T
->
read_aeskey
,
(
void
*
)
T
->
read_aeskey
.
type
->
ctr128_crypt
,
T
->
read_iv
,
1
,
T
->
read_ebuf
,
&
T
->
read_num
)
==
len
);
}
}
return
0
;
return
0
;
...
...
net/net-tcp-rpc-common.c
View file @
e4c6b8bc
...
@@ -180,6 +180,11 @@ int tcp_rpc_write_packet_compact (connection_job_t C, struct raw_message *raw) {
...
@@ -180,6 +180,11 @@ int tcp_rpc_write_packet_compact (connection_job_t C, struct raw_message *raw) {
rwm_union
(
&
CONN_INFO
(
C
)
->
out
,
raw
);
rwm_union
(
&
CONN_INFO
(
C
)
->
out
,
raw
);
return
0
;
return
0
;
}
}
if
((
CONN_INFO
(
C
)
->
flags
&
C_IS_TLS
)
&&
CONN_INFO
(
C
)
->
left_tls_packet_length
==
-
1
)
{
// uninited TLS connection
rwm_union
(
&
CONN_INFO
(
C
)
->
out
,
raw
);
return
0
;
}
if
(
!
(
TCP_RPC_DATA
(
C
)
->
flags
&
(
RPC_F_COMPACT
|
RPC_F_MEDIUM
)))
{
if
(
!
(
TCP_RPC_DATA
(
C
)
->
flags
&
(
RPC_F_COMPACT
|
RPC_F_MEDIUM
)))
{
return
tcp_rpc_write_packet
(
C
,
raw
);
return
tcp_rpc_write_packet
(
C
,
raw
);
...
...
net/net-tcp-rpc-common.h
View file @
e4c6b8bc
...
@@ -94,18 +94,18 @@ void tcp_rpc_conn_send_data_im (JOB_REF_ARG (C), int len, void *Q);
...
@@ -94,18 +94,18 @@ void tcp_rpc_conn_send_data_im (JOB_REF_ARG (C), int len, void *Q);
int
tcp_rpc_default_execute
(
connection_job_t
C
,
int
op
,
struct
raw_message
*
raw
);
int
tcp_rpc_default_execute
(
connection_job_t
C
,
int
op
,
struct
raw_message
*
raw
);
/* for crypto_flags in struct tcp_rpc_data */
/* for crypto_flags in struct tcp_rpc_data */
#define RPCF_ALLOW_UNENC 1
#define RPCF_ALLOW_UNENC 1
// allow unencrypted
#define RPCF_ALLOW_ENC 2
#define RPCF_ALLOW_ENC 2
// allow encrypted
#define RPCF_REQ_DH 4
#define RPCF_REQ_DH 4
// require DH
#define RPCF_ALLOW_SKIP_DH 8
#define RPCF_ALLOW_SKIP_DH 8
// crypto NONCE packet sent
#define RPCF_ENC_SENT 16
#define RPCF_ENC_SENT 16
#define RPCF_SEQNO_HOLES 256
#define RPCF_SEQNO_HOLES 256
// packet numbers not sequential
#define RPCF_QUICKACK 512
#define RPCF_QUICKACK 512
// allow quick ack packets
#define RPCF_COMPACT_OFF 1024
#define RPCF_COMPACT_OFF 1024
// compact mode off
#define RPCF_USE_CRC32C 2048
#define RPCF_USE_CRC32C 2048
// use CRC32-C instead of CRC32
/* for flags in struct tcp_rpc_data */
/* for flags in struct tcp_rpc_data */
#define RPC_F_PAD
0x8000000
#define RPC_F_PAD
0x8000000
#define RPC_F_DROPPED 0x10000000
#define RPC_F_DROPPED 0x10000000
#define RPC_F_MEDIUM 0x20000000
#define RPC_F_MEDIUM 0x20000000
#define RPC_F_COMPACT 0x40000000
#define RPC_F_COMPACT 0x40000000
...
@@ -124,7 +124,7 @@ struct tcp_rpc_data {
...
@@ -124,7 +124,7 @@ struct tcp_rpc_data {
int
flags
;
int
flags
;
int
in_packet_num
;
int
in_packet_num
;
int
out_packet_num
;
int
out_packet_num
;
int
crypto_flags
;
/* 1 = allow unencrypted, 2 = allow encrypted, 4 = require DH, 8 = crypto NONCE packet sent, 256 = packet numbers not sequential, 512 = allow quick ack packets, 1024 = compact mode off, 2048 = use CRC32-C instead of CRC32
*/
int
crypto_flags
;
/* RPCF_* flags
*/
struct
process_id
remote_pid
;
struct
process_id
remote_pid
;
char
nonce
[
16
];
char
nonce
[
16
];
int
nonce_time
;
int
nonce_time
;
...
...
net/net-tcp-rpc-ext-server.c
View file @
e4c6b8bc
...
@@ -33,23 +33,21 @@
...
@@ -33,23 +33,21 @@
#include <time.h>
#include <time.h>
#include <unistd.h>
#include <unistd.h>
#include "crc32.h"
#include <openssl/rand.h>
#include "crc32c.h"
#include "common/kprintf.h"
#include "common/precise-time.h"
#include "common/rpc-const.h"
#include "common/sha256.h"
#include "common/sha256.h"
#include "net/net-events.h"
#include "kprintf.h"
#include "precise-time.h"
#include "net/net-connections.h"
#include "net/net-connections.h"
#include "net/net-tcp-rpc-ext-server.h"
#include "net/net-crypto-aes.h"
#include "net/net-events.h"
#include "net/net-tcp-connections.h"
#include "net/net-tcp-connections.h"
#include "net/net-tcp-rpc-ext-server.h"
#include "net/net-thread.h"
#include "net/net-thread.h"
#include "rpc-const.h"
#include "net/net-crypto-aes.h"
//#include "net/net-config.h"
#include "vv/vv-io.h"
#include "vv/vv-io.h"
/*
/*
*
*
* EXTERNAL RPC SERVER INTERFACE
* EXTERNAL RPC SERVER INTERFACE
...
@@ -100,6 +98,125 @@ struct tcp_rpc_server_functions default_tcp_rpc_ext_server = {
...
@@ -100,6 +98,125 @@ struct tcp_rpc_server_functions default_tcp_rpc_ext_server = {
};
};
*/
*/
#define MAX_TLS_SERVER_EXTENSIONS 3
static
int
tls_server_extensions
[
MAX_TLS_SERVER_EXTENSIONS
+
1
]
=
{
0x33
,
0x2b
,
-
1
};
int
get_tls_server_hello_encrypted_size
()
{
int
r
=
rand
();
return
2509
+
((
r
>>
1
)
&
1
)
-
(
r
&
1
);
}
struct
client_random
{
unsigned
char
random
[
16
];
struct
client_random
*
next_by_time
;
struct
client_random
*
next_by_hash
;
int
time
;
};
#define RANDOM_HASH_BITS 14
static
struct
client_random
*
client_randoms
[
1
<<
RANDOM_HASH_BITS
];
static
struct
client_random
*
first_client_random
;
static
struct
client_random
*
last_client_random
;
static
struct
client_random
**
get_bucket
(
unsigned
char
random
[
16
])
{
int
i
=
RANDOM_HASH_BITS
;
int
pos
=
0
;
int
id
=
0
;
while
(
i
>
0
)
{
int
bits
=
i
<
8
?
i
:
8
;
id
=
(
id
<<
bits
)
|
(
random
[
pos
++
]
&
((
1
<<
bits
)
-
1
));
i
-=
bits
;
}
assert
(
0
<=
id
&&
id
<
(
1
<<
RANDOM_HASH_BITS
));
return
client_randoms
+
id
;
}
static
int
have_client_random
(
unsigned
char
random
[
16
])
{
struct
client_random
*
cur
=
*
get_bucket
(
random
);
while
(
cur
!=
NULL
)
{
if
(
memcmp
(
random
,
cur
->
random
,
16
)
==
0
)
{
return
1
;
}
cur
=
cur
->
next_by_hash
;
}
return
0
;
}
static
void
add_client_random
(
unsigned
char
random
[
16
])
{
struct
client_random
*
entry
=
malloc
(
sizeof
(
struct
client_random
));
memcpy
(
entry
->
random
,
random
,
16
);
entry
->
time
=
now
;
entry
->
next_by_time
=
NULL
;
if
(
last_client_random
==
NULL
)
{
assert
(
first_client_random
==
NULL
);
first_client_random
=
last_client_random
=
entry
;
}
else
{
last_client_random
->
next_by_time
=
entry
;
last_client_random
=
entry
;
}
struct
client_random
**
bucket
=
get_bucket
(
random
);
entry
->
next_by_hash
=
*
bucket
;
*
bucket
=
entry
;
}
#define MAX_CLIENT_RANDOM_CACHE_TIME 2 * 86400
static
void
delete_old_client_randoms
()
{
while
(
first_client_random
!=
last_client_random
)
{
assert
(
first_client_random
!=
NULL
);
if
(
first_client_random
->
time
>
now
-
MAX_CLIENT_RANDOM_CACHE_TIME
)
{
return
;
}
struct
client_random
*
entry
=
first_client_random
;
assert
(
entry
->
next_by_hash
==
NULL
);
first_client_random
=
first_client_random
->
next_by_time
;
struct
client_random
**
cur
=
get_bucket
(
entry
->
random
);
while
(
*
cur
!=
entry
)
{
cur
=
&
(
*
cur
)
->
next_by_hash
;
}
*
cur
=
NULL
;
free
(
entry
);
}
}
static
int
is_allowed_timestamp
(
int
timestamp
)
{
if
(
timestamp
>
now
+
3
)
{
// do not allow timestamps in the future
// after time synchronization client should always have time in the past
vkprintf
(
1
,
"Disallow request with timestamp %d from the future
\n
"
,
timestamp
);
return
0
;
}
// first_client_random->time is an exact time when corresponding request was received
// if the timestamp is bigger than (first_client_random->time + 3), then the current request could be accepted
// only after the request with first_client_random, so the client random still must be cached
// if the request wasn't accepted, then the client_random still will be cached for MAX_CLIENT_RANDOM_CACHE_TIME seconds,
// so we can miss duplicate request only after a lot of time has passed
if
(
first_client_random
!=
NULL
&&
timestamp
>
first_client_random
->
time
+
3
)
{
vkprintf
(
1
,
"Allow new request with timestamp %d
\n
"
,
timestamp
);
return
1
;
}
// allow all requests with timestamp recently in past, regardless of ability to check repeating client random
// the allowed error must be big enough to allow requests after time synchronization
const
int
MAX_ALLOWED_TIMESTAMP_ERROR
=
10
*
60
;
if
(
timestamp
>
now
-
MAX_ALLOWED_TIMESTAMP_ERROR
)
{
// this can happen only first (MAX_ALLOWED_TIMESTAMP_ERROR + 3) sceonds after first_client_random->time
vkprintf
(
1
,
"Allow recent request with timestamp %d without full check for client random duplication
\n
"
,
timestamp
);
return
1
;
}
// the request is too old to check client random, do not allow it to force client to synchronize it's time
vkprintf
(
1
,
"Disallow too old request with timestamp %d
\n
"
,
timestamp
);
return
0
;
}
int
tcp_rpcs_compact_parse_execute
(
connection_job_t
C
)
{
int
tcp_rpcs_compact_parse_execute
(
connection_job_t
C
)
{
struct
tcp_rpc_data
*
D
=
TCP_RPC_DATA
(
C
);
struct
tcp_rpc_data
*
D
=
TCP_RPC_DATA
(
C
);
if
(
D
->
crypto_flags
&
RPCF_COMPACT_OFF
)
{
if
(
D
->
crypto_flags
&
RPCF_COMPACT_OFF
)
{
...
@@ -124,7 +241,6 @@ int tcp_rpcs_compact_parse_execute (connection_job_t C) {
...
@@ -124,7 +241,6 @@ int tcp_rpcs_compact_parse_execute (connection_job_t C) {
}
}
int
min_len
=
(
D
->
flags
&
RPC_F_MEDIUM
)
?
4
:
1
;
int
min_len
=
(
D
->
flags
&
RPC_F_MEDIUM
)
?
4
:
1
;
if
(
len
<
min_len
+
8
)
{
if
(
len
<
min_len
+
8
)
{
return
min_len
+
8
-
len
;
return
min_len
+
8
-
len
;
}
}
...
@@ -163,10 +279,145 @@ int tcp_rpcs_compact_parse_execute (connection_job_t C) {
...
@@ -163,10 +279,145 @@ int tcp_rpcs_compact_parse_execute (connection_job_t C) {
vkprintf
(
1
,
"HTTP type
\n
"
);
vkprintf
(
1
,
"HTTP type
\n
"
);
return
tcp_rpcs_parse_execute
(
C
);
return
tcp_rpcs_parse_execute
(
C
);
}
}
#endif
// fake tls
if
(
c
->
flags
&
C_IS_TLS
)
{
if
(
len
<
11
)
{
return
11
-
len
;
}
vkprintf
(
1
,
"Established TLS connection
\n
"
);
unsigned
char
header
[
11
];
assert
(
rwm_fetch_lookup
(
&
c
->
in
,
header
,
11
)
==
11
);
if
(
memcmp
(
header
,
"
\x14\x03\x03\x00\x01\x01\x17\x03\x03
"
,
9
)
!=
0
)
{
vkprintf
(
1
,
"error while parsing packet: bad client dummy ChangeCipherSpec
\n
"
);
fail_connection
(
C
,
-
1
);
return
0
;
}
min_len
=
11
+
256
*
header
[
9
]
+
header
[
10
];
if
(
len
<
min_len
)
{
vkprintf
(
2
,
"Need %d bytes, but have only %d
\n
"
,
min_len
,
len
);
return
min_len
-
len
;
}
assert
(
rwm_skip_data
(
&
c
->
in
,
11
)
==
11
);
len
-=
11
;
c
->
left_tls_packet_length
=
256
*
header
[
9
]
+
header
[
10
];
// store left length of current TLS packet in extra_int3
vkprintf
(
2
,
"Receive first TLS packet of length %d
\n
"
,
c
->
left_tls_packet_length
);
if
(
c
->
left_tls_packet_length
<
64
)
{
vkprintf
(
1
,
"error while parsing packet: too short first TLS packet: %d
\n
"
,
c
->
left_tls_packet_length
);
fail_connection
(
C
,
-
1
);
return
0
;
}
// now len >= c->left_tls_packet_length >= 64
assert
(
rwm_fetch_lookup
(
&
c
->
in
,
&
packet_len
,
4
)
==
4
);
c
->
left_tls_packet_length
-=
64
;
// skip header length
}
else
if
(
packet_len
==
*
(
int
*
)
"
\x16\x03\x01\x02
"
&&
ext_secret_cnt
>
0
)
{
unsigned
char
header
[
5
];
assert
(
rwm_fetch_lookup
(
&
c
->
in
,
header
,
5
)
==
5
);
min_len
=
5
+
256
*
header
[
3
]
+
header
[
4
];
if
(
len
<
min_len
)
{
return
min_len
-
len
;
}
if
(
len
>
min_len
)
{
vkprintf
(
1
,
"Too much data in ClientHello, receive %d instead of %d
\n
"
,
len
,
min_len
);
return
(
-
1
<<
28
);
}
vkprintf
(
1
,
"TLS type
\n
"
);
unsigned
char
client_hello
[
len
];
// VLA
assert
(
rwm_fetch_lookup
(
&
c
->
in
,
client_hello
,
len
)
==
len
);
unsigned
char
client_random
[
32
];
memcpy
(
client_random
,
client_hello
+
11
,
32
);
memset
(
client_hello
+
11
,
'\0'
,
32
);
if
(
have_client_random
(
client_random
))
{
vkprintf
(
1
,
"Receive again request with the same client random
\n
"
);
return
(
-
1
<<
28
);
}
add_client_random
(
client_random
);
delete_old_client_randoms
();
unsigned
char
expected_random
[
32
];
int
secret_id
;
for
(
secret_id
=
0
;
secret_id
<
ext_secret_cnt
;
secret_id
++
)
{
sha256_hmac
(
ext_secret
[
secret_id
],
16
,
client_hello
,
len
,
expected_random
);
if
(
memcmp
(
expected_random
,
client_random
,
28
)
==
0
)
{
break
;
}
}
if
(
secret_id
==
ext_secret_cnt
)
{
vkprintf
(
1
,
"Receive request with unmatched client random
\n
"
);
return
(
-
1
<<
28
);
}
int
timestamp
=
*
(
int
*
)(
expected_random
+
28
)
^
*
(
int
*
)(
client_random
+
28
);
if
(
!
is_allowed_timestamp
(
timestamp
))
{
return
(
-
1
<<
28
);
}
assert
(
rwm_skip_data
(
&
c
->
in
,
len
)
==
len
);
c
->
flags
|=
C_IS_TLS
;
c
->
left_tls_packet_length
=
-
1
;
int
encrypted_size
=
get_tls_server_hello_encrypted_size
();
int
response_size
=
127
+
6
+
5
+
encrypted_size
;
unsigned
char
*
buffer
=
malloc
(
32
+
response_size
);
assert
(
buffer
!=
NULL
);
memcpy
(
buffer
,
client_random
,
32
);
unsigned
char
*
response_buffer
=
buffer
+
32
;
memcpy
(
response_buffer
,
"
\x16\x03\x03\x00\x7a\x02\x00\x00\x76\x03\x03
"
,
11
);
memset
(
response_buffer
+
11
,
'\0'
,
32
);
response_buffer
[
43
]
=
'\x20'
;
memcpy
(
response_buffer
+
44
,
client_random
,
32
);
memcpy
(
response_buffer
+
76
,
"
\x13\x01\x00\x00\x2e
"
,
5
);
int
i
;
int
pos
=
81
;
for
(
i
=
0
;
tls_server_extensions
[
i
]
!=
-
1
;
i
++
)
{
if
(
tls_server_extensions
[
i
]
==
0x33
)
{
assert
(
pos
+
40
<=
response_size
);
memcpy
(
response_buffer
+
pos
,
"
\x00\x33\x00\x24\x00\x1d\x00\x20
"
,
8
);
RAND_bytes
(
response_buffer
+
pos
+
8
,
32
);
pos
+=
40
;
}
else
if
(
tls_server_extensions
[
i
]
==
0x2b
)
{
assert
(
pos
+
5
<=
response_size
);
memcpy
(
response_buffer
+
pos
,
"
\x00\x2b\x00\x02\x03\x04
"
,
6
);
pos
+=
6
;
}
else
{
assert
(
0
);
}
}
assert
(
pos
==
127
);
memcpy
(
response_buffer
+
127
,
"
\x14\x03\x03\x00\x01\x01\x17\x03\x03
"
,
9
);
pos
+=
9
;
response_buffer
[
pos
++
]
=
encrypted_size
/
256
;
response_buffer
[
pos
++
]
=
encrypted_size
%
256
;
assert
(
pos
+
encrypted_size
==
response_size
);
RAND_bytes
(
response_buffer
+
pos
,
encrypted_size
);
unsigned
char
server_random
[
32
];
sha256_hmac
(
ext_secret
[
secret_id
],
16
,
buffer
,
32
+
response_size
,
server_random
);
memcpy
(
response_buffer
+
11
,
server_random
,
32
);
struct
raw_message
*
m
=
calloc
(
sizeof
(
struct
raw_message
),
1
);
rwm_create
(
m
,
response_buffer
,
response_size
);
mpq_push_w
(
c
->
out_queue
,
m
,
0
);
job_signal
(
JOB_REF_CREATE_PASS
(
C
),
JS_RUN
);
free
(
buffer
);
return
11
;
// waiting for dummy ChangeCipherSpec and first packet
}
#if __ALLOW_UNOBFS__
int
tmp
[
2
];
int
tmp
[
2
];
assert
(
rwm_fetch_lookup
(
&
c
->
in
,
&
tmp
,
8
)
==
8
);
assert
(
rwm_fetch_lookup
(
&
c
->
in
,
&
tmp
,
8
)
==
8
);
if
(
!
tmp
[
1
])
{
if
(
!
tmp
[
1
]
&&
!
(
c
->
flags
&
C_IS_TLS
)
)
{
D
->
crypto_flags
|=
RPCF_COMPACT_OFF
;
D
->
crypto_flags
|=
RPCF_COMPACT_OFF
;
vkprintf
(
1
,
"Long type
\n
"
);
vkprintf
(
1
,
"Long type
\n
"
);
return
tcp_rpcs_parse_execute
(
C
);
return
tcp_rpcs_parse_execute
(
C
);
...
@@ -174,6 +425,7 @@ int tcp_rpcs_compact_parse_execute (connection_job_t C) {
...
@@ -174,6 +425,7 @@ int tcp_rpcs_compact_parse_execute (connection_job_t C) {
#endif
#endif
if
(
len
<
64
)
{
if
(
len
<
64
)
{
assert
(
!
(
c
->
flags
&
C_IS_TLS
));
#if __ALLOW_UNOBFS__
#if __ALLOW_UNOBFS__
vkprintf
(
1
,
"random 64-byte header: first 0x%08x 0x%08x, need %d more bytes to distinguish
\n
"
,
tmp
[
0
],
tmp
[
1
],
64
-
len
);
vkprintf
(
1
,
"random 64-byte header: first 0x%08x 0x%08x, need %d more bytes to distinguish
\n
"
,
tmp
[
0
],
tmp
[
1
],
64
-
len
);
#else
#else
...
...
net/net-tcp-rpc-server.c
View file @
e4c6b8bc
...
@@ -547,9 +547,6 @@ int tcp_rpcs_init_fake_crypto (connection_job_t c) {
...
@@ -547,9 +547,6 @@ int tcp_rpcs_init_fake_crypto (connection_job_t c) {
return
1
;
return
1
;
}
}
#include "net/net-crypto-aes.h"
#include "net/net-config.h"
int
tcp_rpcs_default_check_perm
(
connection_job_t
C
)
{
int
tcp_rpcs_default_check_perm
(
connection_job_t
C
)
{
return
RPCF_ALLOW_ENC
|
RPCF_REQ_DH
|
tcp_get_default_rpc_flags
();
return
RPCF_ALLOW_ENC
|
RPCF_REQ_DH
|
tcp_get_default_rpc_flags
();
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment