@@ -512,7 +512,7 @@ namespace {
512
512
#endif
513
513
514
514
m_dh_key_exchange.reset (new (std::nothrow) dh_key_exchange);
515
- if (!m_dh_key_exchange || !m_dh_key_exchange-> good () )
515
+ if (!m_dh_key_exchange)
516
516
{
517
517
disconnect (errors::no_memory, operation_t ::encryption);
518
518
return ;
@@ -2714,6 +2714,44 @@ namespace {
2714
2714
on_receive_impl (bytes_transferred);
2715
2715
}
2716
2716
2717
+ #if !defined TORRENT_DISABLE_ENCRYPTION
2718
+ void bt_peer_connection::init_bt_handshake ()
2719
+ {
2720
+ m_encrypted = true ;
2721
+ if (m_rc4_encrypted)
2722
+ {
2723
+ switch_send_crypto (m_rc4);
2724
+ switch_recv_crypto (m_rc4);
2725
+ }
2726
+
2727
+ // decrypt remaining received bytes
2728
+ if (m_rc4_encrypted)
2729
+ {
2730
+ span<char > const remaining = m_recv_buffer.mutable_buffer ()
2731
+ .subspan (m_recv_buffer.packet_size ());
2732
+ rc4_decrypt (remaining);
2733
+
2734
+ #ifndef TORRENT_DISABLE_LOGGING
2735
+ peer_log (peer_log_alert::info, " ENCRYPTION"
2736
+ , " decrypted remaining %d bytes" , int (remaining.size ()));
2737
+ #endif
2738
+ }
2739
+ m_rc4.reset ();
2740
+
2741
+ // encrypted portion of handshake completed, toggle
2742
+ // peer_info pe_support flag back to true
2743
+ if (is_outgoing () &&
2744
+ m_settings.get_int (settings_pack::out_enc_policy)
2745
+ == settings_pack::pe_enabled)
2746
+ {
2747
+ torrent_peer* pi = peer_info_struct ();
2748
+ TORRENT_ASSERT (pi );
2749
+
2750
+ pi ->pe_support = true ;
2751
+ }
2752
+ }
2753
+ #endif
2754
+
2717
2755
void bt_peer_connection::on_receive_impl (std::size_t bytes_transferred)
2718
2756
{
2719
2757
auto t = associated_torrent ().lock ();
@@ -3104,30 +3142,28 @@ namespace {
3104
3142
m_rc4_encrypted = true ;
3105
3143
}
3106
3144
3107
- int const len_pad = aux::read_int16 (recv_buffer);
3145
+ int len_pad = aux::read_int16 (recv_buffer);
3108
3146
if (len_pad < 0 || len_pad > 512 )
3109
3147
{
3110
3148
disconnect (errors::invalid_pad_size, operation_t ::encryption, peer_error);
3111
3149
return ;
3112
3150
}
3113
3151
3114
- m_state = state_t ::read_pe_pad;
3152
+ // len(IA) at the end of pad
3115
3153
if (!is_outgoing ())
3116
- m_recv_buffer.reset (len_pad + 2 ); // len(IA) at the end of pad
3154
+ len_pad += 2 ;
3155
+
3156
+ if (len_pad > 0 )
3157
+ {
3158
+ m_state = state_t ::read_pe_pad;
3159
+ m_recv_buffer.reset (len_pad);
3160
+ }
3117
3161
else
3118
3162
{
3119
- if (len_pad == 0 )
3120
- {
3121
- m_encrypted = true ;
3122
- if (m_rc4_encrypted)
3123
- {
3124
- switch_send_crypto (m_rc4);
3125
- switch_recv_crypto (m_rc4);
3126
- }
3127
- m_state = state_t ::init_bt_handshake;
3128
- }
3129
- else
3130
- m_recv_buffer.reset (len_pad);
3163
+ TORRENT_ASSERT (len_pad == 0 );
3164
+ init_bt_handshake ();
3165
+ m_state = state_t ::read_protocol_identifier;
3166
+ m_recv_buffer.reset (20 );
3131
3167
}
3132
3168
}
3133
3169
@@ -3149,55 +3185,51 @@ namespace {
3149
3185
recv_buffer = recv_buffer.subspan (pad_size);
3150
3186
int const len_ia = aux::read_int16 (recv_buffer);
3151
3187
3152
- if (len_ia < 0 )
3188
+ #ifndef TORRENT_DISABLE_LOGGING
3189
+ peer_log (peer_log_alert::info, " ENCRYPTION" , " len(IA) : %d" , len_ia);
3190
+ #endif
3191
+ if (len_ia < 0 || len_ia > 68 )
3153
3192
{
3154
3193
disconnect (errors::invalid_encrypt_handshake, operation_t ::encryption, peer_error);
3155
3194
return ;
3156
3195
}
3157
3196
3158
- #ifndef TORRENT_DISABLE_LOGGING
3159
- peer_log (peer_log_alert::info, " ENCRYPTION" , " len(IA) : %d" , len_ia);
3160
- #endif
3161
3197
if (len_ia == 0 )
3162
3198
{
3163
- // everything after this is Encrypt2
3164
- m_encrypted = true ;
3165
- if (m_rc4_encrypted)
3166
- {
3167
- switch_send_crypto (m_rc4);
3168
- switch_recv_crypto (m_rc4);
3169
- }
3170
- m_state = state_t ::init_bt_handshake;
3199
+ // everything after this is encrypted
3200
+ init_bt_handshake ();
3201
+ m_state = state_t ::read_protocol_identifier;
3202
+ m_recv_buffer.reset (20 );
3171
3203
}
3172
3204
else
3173
3205
{
3206
+ // The other peer indicated that a non-zero bytes will be
3207
+ // encrypted at the start of the underlying bittorrent
3208
+ // protocol. This number of bytes, len_ia, is not
3209
+ // necessarily aligned to message boundaries. We first read
3210
+ // that many bytes, decrypt it, and then pass it back into
3211
+ // the regular protocol parser
3174
3212
m_state = state_t ::read_pe_ia;
3175
3213
m_recv_buffer.reset (len_ia);
3176
3214
}
3177
3215
}
3178
3216
else // is_outgoing()
3179
3217
{
3180
- // everything that arrives after this is Encrypt2
3181
- m_encrypted = true ;
3182
- if (m_rc4_encrypted)
3183
- {
3184
- switch_send_crypto (m_rc4);
3185
- switch_recv_crypto (m_rc4);
3186
- }
3187
- m_state = state_t ::init_bt_handshake;
3218
+ // everything that arrives after this is encrypted
3219
+ init_bt_handshake ();
3220
+ m_state = state_t ::read_protocol_identifier;
3221
+ m_recv_buffer.reset (20 );
3188
3222
}
3189
3223
}
3190
3224
3191
3225
if (m_state == state_t ::read_pe_ia)
3192
3226
{
3193
- received_bytes (0 , int (bytes_transferred));
3194
- bytes_transferred = 0 ;
3195
3227
TORRENT_ASSERT (!is_outgoing ());
3196
3228
TORRENT_ASSERT (!m_encrypted);
3197
3229
3198
3230
if (!m_recv_buffer.packet_finished ()) return ;
3199
3231
3200
- // ia is always rc4, so decrypt it
3232
+ // the IA bytes are always rc4, so decrypt it
3201
3233
rc4_decrypt (m_recv_buffer.mutable_buffer ().first (m_recv_buffer.packet_size ()));
3202
3234
3203
3235
#ifndef TORRENT_DISABLE_LOGGING
@@ -3214,47 +3246,14 @@ namespace {
3214
3246
}
3215
3247
m_rc4.reset ();
3216
3248
3249
+ // now that we have decrypted IA length of bytes, we
3250
+ // reinterpret the receive buffer as the very start of a normal
3251
+ // connection. First we expect to find the protocol identifier
3252
+ // (i.e. "BitTorrent Protocol")
3217
3253
m_state = state_t ::read_protocol_identifier;
3218
3254
m_recv_buffer.cut (0 , 20 );
3219
3255
}
3220
3256
3221
- if (m_state == state_t ::init_bt_handshake)
3222
- {
3223
- received_bytes (0 , int (bytes_transferred));
3224
- bytes_transferred = 0 ;
3225
- TORRENT_ASSERT (m_encrypted);
3226
-
3227
- // decrypt remaining received bytes
3228
- if (m_rc4_encrypted)
3229
- {
3230
- span<char > const remaining = m_recv_buffer.mutable_buffer ()
3231
- .subspan (m_recv_buffer.packet_size ());
3232
- rc4_decrypt (remaining);
3233
-
3234
- #ifndef TORRENT_DISABLE_LOGGING
3235
- peer_log (peer_log_alert::info, " ENCRYPTION"
3236
- , " decrypted remaining %d bytes" , int (remaining.size ()));
3237
- #endif
3238
- }
3239
- m_rc4.reset ();
3240
-
3241
- // payload stream, start with 20 handshake bytes
3242
- m_state = state_t ::read_protocol_identifier;
3243
- m_recv_buffer.reset (20 );
3244
-
3245
- // encrypted portion of handshake completed, toggle
3246
- // peer_info pe_support flag back to true
3247
- if (is_outgoing () &&
3248
- m_settings.get_int (settings_pack::out_enc_policy)
3249
- == settings_pack::pe_enabled)
3250
- {
3251
- torrent_peer* pi = peer_info_struct ();
3252
- TORRENT_ASSERT (pi );
3253
-
3254
- pi ->pe_support = true ;
3255
- }
3256
- }
3257
-
3258
3257
#endif // #if !defined TORRENT_DISABLE_ENCRYPTION
3259
3258
3260
3259
if (m_state == state_t ::read_protocol_identifier)
@@ -3312,6 +3311,10 @@ namespace {
3312
3311
peer_log (peer_log_alert::info, " ENCRYPTION" , " attempting encrypted connection" );
3313
3312
#endif
3314
3313
m_state = state_t ::read_pe_dhkey;
3314
+ // we're "cutting" off 0 bytes from the receive buffer here
3315
+ // because we want to interpret it as something else. It didn't
3316
+ // contain the expected bittorrent handshake string, so let's
3317
+ // try again to interpret it as an encrypted handshake
3315
3318
m_recv_buffer.cut (0 , dh_key_len);
3316
3319
TORRENT_ASSERT (!m_recv_buffer.packet_finished ());
3317
3320
return ;
0 commit comments