Licode-DtlsSocket源码分析

Posted tongwlipi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Licode-DtlsSocket源码分析相关的知识,希望对你有一定的参考价值。

// 通过mSocketContext拿到设置了证书和私钥的ssl Context,创建ssl对象,分配输入和输出BioDtlsSocket::DtlsSocket(DtlsSocketContext* socketContext, enum SocketType type): mSocketContext(socketContext), mSocketType(type), mHandshakeCompleted(false) { ELOG_DEBUG("Creating Dtls Socket"); mSocketContext->setDtlsSocket(this); SSL_CTX* mContext = mSocketContext->getSSLContext(); assert(mContext); mSsl = SSL_new(mContext); assert(mSsl != 0); SSL_set_mtu(mSsl, DTLS_MTU); mSsl->ctx = mContext; mSsl->session_ctx = mContext;
switch (type) { case Client: SSL_set_connect_state(mSsl); // SSL_set_mode(mSsl, SSL_MODE_ENABLE_PARTIAL_WRITE | // SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); break; case Server: SSL_set_accept_state(mSsl); SSL_set_verify(mSsl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, dummy_cb); break; default: assert(0); } BIO* memBIO1 = BIO_new(BIO_s_mem()); mInBio = BIO_new(BIO_f_dwrap()); BIO_push(mInBio, memBIO1);
BIO* memBIO2 = BIO_new(BIO_s_mem()); mOutBio = BIO_new(BIO_f_dwrap()); BIO_push(mOutBio, memBIO2);
SSL_set_bio(mSsl, mInBio, mOutBio); SSL_accept(mSsl); ELOG_DEBUG("Dtls Socket created");}
// 析构函数,关闭ssl对象DtlsSocket::~DtlsSocket() { close();}
// 释放ssl对象void DtlsSocket::close() { // Properly shutdown the socket and free it - note: this also free's the BIO's if (mSsl != NULL) { ELOG_DEBUG("SSL Shutdown"); SSL_shutdown(mSsl); SSL_free(mSsl); mSsl = NULL; }}
// 开启ssl客户端握手操作void DtlsSocket::startClient() { assert(mSocketType == Client); doHandshakeIteration();}
// 处理包bool DtlsSocket::handlePacketMaybe(const unsigned char* bytes, unsigned int len) { if (mSsl == NULL) { ELOG_WARN("handlePacketMaybe called after DtlsSocket closed: %p", this); return false; } DtlsSocketContext::PacketType pType = DtlsSocketContext::demuxPacket(bytes, len);
if (pType != DtlsSocketContext::dtls) { return false; }
if (mSsl == nullptr) { return false; }
(void) BIO_reset(mInBio); (void) BIO_reset(mOutBio);
int r = BIO_write(mInBio, bytes, len); assert(r == static_cast<int>(len)); // Can't happen
// Note: we must catch any below exceptions--if there are any try { doHandshakeIteration(); } catch (int e) { return false; } return true;}
// 强制重传void DtlsSocket::forceRetransmit() { (void) BIO_reset(mInBio); (void) BIO_reset(mOutBio); BIO_ctrl(mInBio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, 0);
doHandshakeIteration();}
// DTLS ssl握手操作,握手完成拿到协商后 srtp的秘钥void DtlsSocket::doHandshakeIteration() { boost::mutex::scoped_lock lock(handshakeMutex_); char errbuf[1024]; int sslerr;
if (mHandshakeCompleted) return;
int r = SSL_do_handshake(mSsl); errbuf[0] = 0; ERR_error_string_n(ERR_peek_error(), errbuf, sizeof(errbuf));
// See what was written unsigned char *outBioData; int outBioLen = BIO_get_mem_data(mOutBio, &outBioData); if (outBioLen > DTLS_MTU) { ELOG_WARN("message: BIO data bigger than MTU - packet could be lost, outBioLen %u, MTU %u", outBioLen, DTLS_MTU); }
// Now handle handshake errors */ switch (sslerr = SSL_get_error(mSsl, r)) { case SSL_ERROR_NONE: mHandshakeCompleted = true; mSocketContext->handshakeCompleted(); break; case SSL_ERROR_WANT_READ: break; default: ELOG_ERROR("SSL error %d", sslerr);
mSocketContext->handshakeFailed(errbuf); // Note: need to fall through to propagate alerts, if any break; }
// If mOutBio is now nonzero-length, then we need to write the // data to the network. TODO(pedro): warning, MTU issues! if (outBioLen) { mSocketContext->write(outBioData, outBioLen); }}
// 拿到远端认证指纹bool DtlsSocket::getRemoteFingerprint(char *fprint) { X509* x = SSL_get_peer_certificate(mSsl); if (!x) { // No certificate return false; }
computeFingerprint(x, fprint); X509_free(x); return true;}
// 将传入指纹与远端指纹进行对比验证bool DtlsSocket::checkFingerprint(const char* fingerprint, unsigned int len) { char fprint[100];
if (getRemoteFingerprint(fprint) == false) { return false; }
// used to be strncasecmp if (strncmp(fprint, fingerprint, len)) { ELOG_WARN("Fingerprint mismatch, got %s expecting %s", fprint, fingerprint); return false; }
return true;}
// 获取本地指纹信息void DtlsSocket::getMyCertFingerprint(char *fingerprint) { mSocketContext->getMyCertFingerprint(fingerprint);}
// 获取srtp的秘钥信息SrtpSessionKeys* DtlsSocket::getSrtpSessionKeys() { // TODO(pedro): probably an exception candidate assert(mHandshakeCompleted);
SrtpSessionKeys* keys = new SrtpSessionKeys();
unsigned char material[SRTP_MASTER_KEY_LEN << 1]; if (!SSL_export_keying_material(mSsl, material, sizeof(material), "EXTRACTOR-dtls_srtp", 19, NULL, 0, 0)) { return keys; }
size_t offset = 0;
memcpy(keys->clientMasterKey, &material[offset], SRTP_MASTER_KEY_KEY_LEN); offset += SRTP_MASTER_KEY_KEY_LEN; memcpy(keys->serverMasterKey, &material[offset], SRTP_MASTER_KEY_KEY_LEN); offset += SRTP_MASTER_KEY_KEY_LEN; memcpy(keys->clientMasterSalt, &material[offset], SRTP_MASTER_KEY_SALT_LEN); offset += SRTP_MASTER_KEY_SALT_LEN; memcpy(keys->serverMasterSalt, &material[offset], SRTP_MASTER_KEY_SALT_LEN); offset += SRTP_MASTER_KEY_SALT_LEN; keys->clientMasterKeyLen = SRTP_MASTER_KEY_KEY_LEN; keys->serverMasterKeyLen = SRTP_MASTER_KEY_KEY_LEN; keys->clientMasterSaltLen = SRTP_MASTER_KEY_SALT_LEN; keys->serverMasterSaltLen = SRTP_MASTER_KEY_SALT_LEN;
return keys;}
// 获取srtp的profileSRTP_PROTECTION_PROFILE* DtlsSocket::getSrtpProfile() { // TODO(pedro): probably an exception candidate assert(mHandshakeCompleted); return SSL_get_selected_srtp_profile(mSsl);}
// Fingerprint is assumed to be long enoughvoid DtlsSocket::computeFingerprint(X509 *cert, char *fingerprint) { unsigned char md[EVP_MAX_MD_SIZE]; int r; unsigned int i, n;
// r = X509_digest(cert, EVP_sha1(), md, &n); r = X509_digest(cert, EVP_sha256(), md, &n); // TODO(javier) - is sha1 vs sha256 supposed to come from DTLS handshake? // fixing to to SHA-256 for compatibility with current web-rtc implementations assert(r == 1);
for (i = 0; i < n; i++) { sprintf(fingerprint, "%02X", md[i]); // NOLINT fingerprint += 2;
if (i < (n-1)) *fingerprint++ = ':'; else *fingerprint++ = 0; }}
void DtlsSocket::handleTimeout() { (void) BIO_reset(mInBio); (void) BIO_reset(mOutBio); if (DTLSv1_handle_timeout(mSsl) > 0) { ELOG_DEBUG("Dtls timeout occurred!");
// See what was written unsigned char *outBioData; int outBioLen = BIO_get_mem_data(mOutBio, &outBioData); if (outBioLen > DTLS_MTU) { ELOG_WARN("message: BIO data bigger than MTU - packet could be lost, outBioLen %u, MTU %u", outBioLen, DTLS_MTU); }
// If mOutBio is now nonzero-length, then we need to write the // data to the network. TODO(pedro): warning, MTU issues! if (outBioLen) { mSocketContext->write(outBioData, outBioLen); } }}


以上是关于Licode-DtlsSocket源码分析的主要内容,如果未能解决你的问题,请参考以下文章

Android 逆向整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )(代码片段

Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段

《Docker 源码分析》全球首发啦!

mysql jdbc源码分析片段 和 Tomcat's JDBC Pool

Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | DexClassLoader 构造函数 | 参考 Dalvik 的 DexClassLoader 类加载流程 )(代码片段

Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | DexClassLoader 构造函数 | 参考 Dalvik 的 DexClassLoader 类加载流程 )(代码片段