Exemple #1
0
/* This is our RTP callback, that is called by the slave transport when it
 * receives RTP packet.
 */
static void transport_rtp_cb(void *user_data, void *pkt, pj_ssize_t size)
{
    struct tp_zrtp *zrtp = (struct tp_zrtp*)user_data;

    pj_uint8_t* buffer = (pj_uint8_t*)pkt;
    int32_t newLen = 0;
    pj_status_t rc = PJ_SUCCESS;

    pj_assert(zrtp && zrtp->stream_rtcp_cb && pkt);

    // check if this could be a real RTP/SRTP packet.
    if ((*buffer & 0xf0) != 0x10)
    {
        //  Could be real RTP, check if we are in secure mode
        if (zrtp->srtpReceive == NULL || size < 0)
        {
            zrtp->stream_rtp_cb(zrtp->stream_user_data, pkt, size);
        }
        else
        {
            rc = zsrtp_unprotect(zrtp->srtpReceive, pkt, size, &newLen);
            if (rc == 1)
            {
                zrtp->unprotect++;
                zrtp->stream_rtp_cb(zrtp->stream_user_data, pkt,
                                    newLen);
                zrtp->unprotect_err = 0;
            }
            else
            {
                if (zrtp->userCallback != NULL)
                {
                    if (rc == -1) {
                        zrtp->userCallback->zrtp_showMessage(zrtp->userCallback->userData,
                                                            zrtp_Warning, 
                                                            zrtp_WarningSRTPauthError);
                    }
                    else {
                        zrtp->userCallback->zrtp_showMessage(zrtp->userCallback->userData,
                                                            zrtp_Warning,
                                                            zrtp_WarningSRTPreplayError);
                    }
                }
                zrtp->unprotect_err = rc;
            }
        }
        if (!zrtp->started && zrtp->enableZrtp)
            pjmedia_transport_zrtp_startZrtp((pjmedia_transport *)zrtp);

        return;
    }

    // We assume all other packets are ZRTP packets here. Process
    // if ZRTP processing is enabled. Because valid RTP packets are
    // already handled we delete any packets here after processing.
    if (zrtp->enableZrtp && zrtp->zrtpCtx != NULL)
    {
        // Get CRC value into crc (see above how to compute the offset)
        pj_uint16_t temp = size - CRC_SIZE;
        pj_uint32_t crc = *(uint32_t*)(buffer + temp);
        crc = pj_ntohl(crc);

        if (!zrtp_CheckCksum(buffer, temp, crc))
        {
            if (zrtp->userCallback != NULL)
                zrtp->userCallback->zrtp_showMessage(zrtp->userCallback->userData, zrtp_Warning, zrtp_WarningCRCmismatch);
            return;
        }

        pj_uint32_t magic = *(pj_uint32_t*)(buffer + 4);
        magic = pj_ntohl(magic);

        // Check if it is really a ZRTP packet, return, no further processing
        if (magic != ZRTP_MAGIC || zrtp->zrtpCtx == NULL)
        {
            return;
        }
        // cover the case if the other party sends _only_ ZRTP packets at the
        // beginning of a session. Start ZRTP in this case as well.
        if (!zrtp->started)
        {
            pjmedia_transport_zrtp_startZrtp((pjmedia_transport *)zrtp);
        }
        // this now points beyond the undefined and length field.
        // We need them, thus adjust
        unsigned char* zrtpMsg = (buffer + 12);

        // store peer's SSRC in host order, used when creating the CryptoContext
        zrtp->peerSSRC = *(pj_uint32_t*)(buffer + 8);
        zrtp->peerSSRC = pj_ntohl(zrtp->peerSSRC);
        zrtp_processZrtpMessage(zrtp->zrtpCtx, zrtpMsg, zrtp->peerSSRC, size);
    }
}
Exemple #2
0
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;
	}
}