static int ozrtp_rtcp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen){ ZrtpContext *zrtpContext = (ZrtpContext*) t->data; OrtpZrtpContext *userData = (OrtpZrtpContext*) zrtpContext->userData; int rlen = rtp_session_rtp_recv_abstract(t->session->rtcp.socket,m,flags,from,fromlen); if (rlen<=0) { // nothing was received or error: pass the information to caller return rlen; } if (userData->srtpRecv != NULL && zrtp_inState(zrtpContext, SecureState)) { err_status_t err = srtp_unprotect_rtcp(userData->srtpRecv,m->b_wptr,&rlen); if (err != err_status_ok) { ortp_error("srtp_unprotect failed %d ; packet discarded (may be plain RTCP)", err); return 0; } } return rlen; }
/* * get_info() is called to get the transport addresses to be put * in SDP c= line and a=rtcp line. */ static pj_status_t transport_get_info(pjmedia_transport *tp, pjmedia_transport_info *info) { struct tp_zrtp *zrtp = (struct tp_zrtp*)tp; pjmedia_zrtp_info zrtp_info; int spc_info_idx; PJ_ASSERT_RETURN(tp && info, PJ_EINVAL); PJ_ASSERT_RETURN(info->specific_info_cnt < PJMEDIA_TRANSPORT_SPECIFIC_INFO_MAXCNT, PJ_ETOOMANY); zrtp_info.active = zrtp_inState(zrtp->zrtpCtx, SecureState) ? PJ_TRUE : PJ_FALSE; spc_info_idx = info->specific_info_cnt++; info->spc_info[spc_info_idx].type = PJMEDIA_TRANSPORT_TYPE_ZRTP; pj_memcpy(&info->spc_info[spc_info_idx].buffer, &zrtp_info, sizeof(zrtp_info)); return pjmedia_transport_get_info(zrtp->slave_tp, info); }
zrtp_state_info jzrtp_getInfoFromContext(struct jzrtp_allContext ac){ zrtp_state_info info; info.sas.slen = 0; info.sas.ptr = ""; info.sas_verified = PJ_FALSE; info.cipher.slen = 0; info.cipher.ptr = ""; info.secure = PJ_FALSE; info.call_id = PJSUA_INVALID_ID; //PJ_LOG(4, (THIS_FILE, "jzrtp_getInfoFromContext : user data %x", ac.cbUserData)); if(ac.zrtpContext != NULL){ int32_t state = zrtp_inState(ac.zrtpContext, SecureState); info.secure = state ? PJ_TRUE : PJ_FALSE; if(ac.cbUserData){ info.sas_verified = ac.cbUserData->sas_verified; info.call_id = ac.cbUserData->call_id; pj_strassign(&info.sas, &ac.cbUserData->sas); pj_strassign(&info.cipher, &ac.cbUserData->cipher); } } return info; }
static int ozrtp_generic_sendto(stream_type stream, RtpTransport *t, mblk_t *m, int flags, const struct sockaddr *to, socklen_t tolen){ int slen; err_status_t err; ortp_socket_t socket; ZrtpContext *zrtpContext = (ZrtpContext*) t->data; OrtpZrtpContext *userData = (OrtpZrtpContext*) zrtpContext->userData; if (stream == rtp_stream) { socket= t->session->rtp.socket; } else { socket= t->session->rtcp.socket; } if (userData->srtpSend == NULL || !zrtp_inState(zrtpContext, SecureState)) { int size; msgpullup(m,-1); size=msgdsize(m); return sendto(socket,(void*)m->b_rptr,size,flags,to,tolen); } slen=msgdsize(m); // Protect with srtp /* enlarge the buffer for srtp to write its data */ msgpullup(m,msgdsize(m)+SRTP_PAD_BYTES); if (stream == rtp_stream) { err=srtp_protect(userData->srtpSend,m->b_rptr,&slen); } else { err=srtp_protect_rtcp(userData->srtpSend,m->b_rptr,&slen); } if (err==err_status_ok){ return sendto(socket,(void*)m->b_rptr,slen,flags,to,tolen); } else { ortp_error("srtp_protect() failed with status %d", err); } return -1; }
pj_str_t jzrtp_getInfo(pjmedia_transport* tp) { pj_str_t result; char msg[512]; ZrtpContext *ctx = pjmedia_transport_zrtp_getZrtpContext(tp); int32_t state = zrtp_inState(ctx, SecureState); zrtp_cb_user_data* zrtp_cb_data = (zrtp_cb_user_data*) pjmedia_transport_zrtp_getUserData(tp); if (state) { pj_ansi_snprintf(msg, sizeof(msg), "ZRTP - %s\n%.*s\n%.*s", "OK", zrtp_cb_data->sas.slen, zrtp_cb_data->sas.ptr, zrtp_cb_data->cipher.slen, zrtp_cb_data->cipher.ptr); } else { pj_ansi_snprintf(msg, sizeof(msg), ""); } pj_strdup2_with_null(css_var.pool, &result, msg); PJ_LOG(4, (THIS_FILE, "ZRTP getInfos : %s", msg)); return result; }
static int ozrtp_rtp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen){ int rlen; ZrtpContext *zrtpContext = (ZrtpContext*) t->data; OrtpZrtpContext *userData = (OrtpZrtpContext*) zrtpContext->userData; // Do extra stuff first check_timer(zrtpContext, userData); // Check if something to receive rlen=rtp_session_rtp_recv_abstract(t->session->rtp.socket,m,flags,from,fromlen); if (rlen<=0) { // nothing was received or error: pass the information to caller return rlen; } uint8_t* rtp = m->b_rptr; int rtpVersion = ((rtp_header_t*)rtp)->version; // If plain or secured RTP if (rtpVersion == 2) { if (userData->srtpRecv != NULL && zrtp_inState(zrtpContext, SecureState)) { // probably srtp packet, unprotect err_status_t err = srtp_unprotect(userData->srtpRecv,m->b_wptr,&rlen); if (err != err_status_ok) { ortp_warning("srtp_unprotect failed; packet may be plain RTP"); } } // in both cases (RTP plain and deciphered srtp) return rlen; } // if ZRTP packet, send to engine uint32_t *magicField=(uint32_t *)(rtp + 4); if (rlen >= ZRTP_MIN_MSG_LENGTH && rtpVersion==0 && ntohl(*magicField) == ZRTP_MAGIC) { print_zrtp_packet("received", rtp); uint8_t *ext_header = rtp+ZRTP_MESSAGE_OFFSET; uint16_t ext_length = get_zrtp_message_length(ext_header); char messageType[9]; parseZrtpMessageType(messageType, ext_header); // Check max length if (rlen < 12 + ext_length + 4) { ortp_warning("Received malformed ZRTP-like packet: size %d (expected %d)", rlen, 12 + ext_length + 4); return 0; } // Check sequence number uint16_t seq_number = get_rtp_seqnumber(rtp); if (userData->last_recv_zrtp_seq_number != 0 && seq_number <= userData->last_recv_zrtp_seq_number) { // Discard out of order ZRTP packet ortp_message("Discarding received out of order zrtp packet: %d (expected >%d)", seq_number, userData->last_recv_zrtp_seq_number); return 0; } // Check packet checksum uint32_t rcv_crc = get_zrtp_packet_crc((uint32_t*)rtp, ext_length); uint32_t zrtp_total_packet_length = ZRTP_MESSAGE_OFFSET + 4*ext_length + 4; if (!zrtp_CheckCksum(rtp, zrtp_total_packet_length-CRC_SIZE, rcv_crc)) { ortp_warning("Bad ZRTP packet checksum %u total %u", rcv_crc, zrtp_total_packet_length); return 0; } uint32_t peerssrc = ntohl(*(uint32_t*)(rtp+8)); #if HAVE_zrtpcpp_with_len zrtp_processZrtpMessage(zrtpContext, ext_header, peerssrc,rlen); #else zrtp_processZrtpMessage(zrtpContext, ext_header, peerssrc); #endif userData->last_recv_zrtp_seq_number=seq_number; return 0; } else { // Not a ZRTP packet, accept it return rlen; } }