| 211 | } |
| 212 | |
| 213 | int CEncryptedStreamSocket::Read(void* lpBuf, uint32_t nBufLen) |
| 214 | { |
| 215 | m_nObfusicationBytesReceived = CSocketClientProxy::Read(lpBuf, nBufLen); |
| 216 | m_bFullReceive = m_nObfusicationBytesReceived == (uint32)nBufLen; |
| 217 | |
| 218 | //printf("Read %i bytes on %s, socket %p\n", m_nObfusicationBytesReceived, (const char*) unicode2char(GetPeer()), this); |
| 219 | |
| 220 | if (m_nObfusicationBytesReceived == (uint32_t)SOCKET_ERROR || m_nObfusicationBytesReceived <= 0) { |
| 221 | return m_nObfusicationBytesReceived; |
| 222 | } |
| 223 | |
| 224 | switch (m_StreamCryptState) { |
| 225 | case ECS_NONE: // disabled, just pass it through |
| 226 | return m_nObfusicationBytesReceived; |
| 227 | case ECS_PENDING: |
| 228 | case ECS_PENDING_SERVER: |
| 229 | //printf("Received %i bytes before sending?\n", m_nObfusicationBytesReceived); |
| 230 | wxFAIL; |
| 231 | //DebugLogError(_T("CEncryptedStreamSocket Received data before sending on outgoing connection")); |
| 232 | m_StreamCryptState = ECS_NONE; |
| 233 | return m_nObfusicationBytesReceived; |
| 234 | case ECS_UNKNOWN: { |
| 235 | //printf("Receiving encrypted data on ECS_UNKNOWN\n"); |
| 236 | uint32_t nRead = 1; |
| 237 | bool bNormalHeader = false; |
| 238 | switch (((uint8_t*)lpBuf)[0]) { |
| 239 | case OP_EDONKEYPROT: |
| 240 | case OP_PACKEDPROT: |
| 241 | case OP_EMULEPROT: |
| 242 | bNormalHeader = true; |
| 243 | break; |
| 244 | } |
| 245 | |
| 246 | if (!bNormalHeader) { |
| 247 | //printf("Not a normal header, negotiating encryption\n"); |
| 248 | StartNegotiation(false); |
| 249 | const uint32 nNegRes = Negotiate((uint8_t*)lpBuf + nRead, m_nObfusicationBytesReceived - nRead); |
| 250 | if (nNegRes == (uint32_t)(-1)) { |
| 251 | return 0; |
| 252 | } |
| 253 | nRead += nNegRes; |
| 254 | if (nRead != (uint32_t)m_nObfusicationBytesReceived) { |
| 255 | // this means we have more data then the current negotiation step required (or there is a bug) and this should never happen |
| 256 | // (note: even if it just finished the handshake here, there still can be no data left, since the other client didn't receive our response yet) |
| 257 | //DebugLogError(_T("CEncryptedStreamSocket: Client %s sent more data then expected while negotiating, disconnecting (1)"), GetPeer()); |
| 258 | //printf("On error: encryption\n"); |
| 259 | OnError(ERR_ENCRYPTION); |
| 260 | } |
| 261 | return 0; |
| 262 | } else { |
| 263 | // doesn't seem to be encrypted |
| 264 | //printf("Encrypted data doesn't seem to be encrypted\n"); |
| 265 | m_StreamCryptState = ECS_NONE; |
| 266 | |
| 267 | // if we require an encrypted connection, cut the connection here. This shouldn't happen that often |
| 268 | // at least with other up-to-date eMule clients because they check for incompability before connecting if possible |
| 269 | if (thePrefs::IsClientCryptLayerRequired()) { |
| 270 | // TODO: Remove me when I have been solved |
no test coverage detected