Beispiel #1
0
static int setup_dtls_srtp(struct ast_sip_session *session,
	struct ast_sip_session_media *session_media)
{
	struct ast_rtp_engine_dtls *dtls;

	if (!session->endpoint->media.rtp.dtls_cfg.enabled || !session_media->rtp) {
		return -1;
	}

	dtls = ast_rtp_instance_get_dtls(session_media->rtp);
	if (!dtls) {
		return -1;
	}

	session->endpoint->media.rtp.dtls_cfg.suite = ((session->endpoint->media.rtp.srtp_tag_32) ? AST_AES_CM_128_HMAC_SHA1_32 : AST_AES_CM_128_HMAC_SHA1_80);
	if (dtls->set_configuration(session_media->rtp, &session->endpoint->media.rtp.dtls_cfg)) {
		ast_log(LOG_ERROR, "Attempted to set an invalid DTLS-SRTP configuration on RTP instance '%p'\n",
			session_media->rtp);
		return -1;
	}

	if (setup_srtp(session_media)) {
		return -1;
	}
	return 0;
}
static int parse_dtls_attrib(struct ast_sip_session_media *session_media,
	const struct pjmedia_sdp_media *stream)
{
	int i;
	struct ast_rtp_engine_dtls *dtls = ast_rtp_instance_get_dtls(session_media->rtp);

	for (i = 0; i < stream->attr_count; i++) {
		pjmedia_sdp_attr *attr = stream->attr[i];
		pj_str_t *value;

		if (!attr->value.ptr) {
			continue;
		}

		value = pj_strtrim(&attr->value);

		if (!pj_strcmp2(&attr->name, "setup")) {
			if (!pj_stricmp2(value, "active")) {
				dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTIVE);
			} else if (!pj_stricmp2(value, "passive")) {
				dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_PASSIVE);
			} else if (!pj_stricmp2(value, "actpass")) {
				dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTPASS);
			} else if (!pj_stricmp2(value, "holdconn")) {
				dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_HOLDCONN);
			} else {
				ast_log(LOG_WARNING, "Unsupported setup attribute value '%*s'\n", (int)value->slen, value->ptr);
			}
		} else if (!pj_strcmp2(&attr->name, "connection")) {
			if (!pj_stricmp2(value, "new")) {
				dtls->reset(session_media->rtp);
			} else if (!pj_stricmp2(value, "existing")) {
				/* Do nothing */
			} else {
				ast_log(LOG_WARNING, "Unsupported connection attribute value '%*s'\n", (int)value->slen, value->ptr);
			}
		} else if (!pj_strcmp2(&attr->name, "fingerprint")) {
			char hash_value[256], hash[32];
			char fingerprint_text[value->slen + 1];
			ast_copy_pj_str(fingerprint_text, value, sizeof(fingerprint_text));

			if (sscanf(fingerprint_text, "%31s %255s", hash, hash_value) == 2) {
				if (!strcasecmp(hash, "sha-1")) {
					dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA1, hash_value);
				} else if (!strcasecmp(hash, "sha-256")) {
					dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA256, hash_value);
				} else {
					ast_log(LOG_WARNING, "Unsupported fingerprint hash type '%s'\n",
					hash);
				}
			}
		}
	}
	ast_set_flag(session_media->srtp, AST_SRTP_CRYPTO_OFFER_OK);

	return 0;
}
char *ast_sdp_get_rtp_profile(unsigned int sdes_active, struct ast_rtp_instance *instance, unsigned int using_avpf,
	unsigned int force_avp)
{
	struct ast_rtp_engine_dtls *dtls;

	if ((dtls = ast_rtp_instance_get_dtls(instance)) && dtls->active(instance)) {
		if (force_avp) {
			return using_avpf ? "RTP/SAVPF" : "RTP/SAVP";
		} else {
			return using_avpf ? "UDP/TLS/RTP/SAVPF" : "UDP/TLS/RTP/SAVP";
		}
	} else {
		if (using_avpf) {
			return sdes_active ? "RTP/SAVPF" : "RTP/AVPF";
		} else {
			return sdes_active ? "RTP/SAVP" : "RTP/AVP";
		}
	}
}
Beispiel #4
0
static int add_crypto_to_stream(struct ast_sip_session *session,
	struct ast_sip_session_media *session_media,
	pj_pool_t *pool, pjmedia_sdp_media *media)
{
	pj_str_t stmp;
	pjmedia_sdp_attr *attr;
	enum ast_rtp_dtls_hash hash;
	const char *crypto_attribute;
	struct ast_rtp_engine_dtls *dtls;
	static const pj_str_t STR_NEW = { "new", 3 };
	static const pj_str_t STR_EXISTING = { "existing", 8 };
	static const pj_str_t STR_ACTIVE = { "active", 6 };
	static const pj_str_t STR_PASSIVE = { "passive", 7 };
	static const pj_str_t STR_ACTPASS = { "actpass", 7 };
	static const pj_str_t STR_HOLDCONN = { "holdconn", 8 };

	switch (session_media->encryption) {
	case AST_SIP_MEDIA_ENCRYPT_NONE:
	case AST_SIP_MEDIA_TRANSPORT_INVALID:
		break;
	case AST_SIP_MEDIA_ENCRYPT_SDES:
		if (!session_media->srtp) {
			session_media->srtp = ast_sdp_srtp_alloc();
			if (!session_media->srtp) {
				return -1;
			}
		}

		crypto_attribute = ast_sdp_srtp_get_attrib(session_media->srtp,
			0 /* DTLS running? No */,
			session->endpoint->media.rtp.srtp_tag_32 /* 32 byte tag length? */);
		if (!crypto_attribute) {
			/* No crypto attribute to add, bad news */
			return -1;
		}

		attr = pjmedia_sdp_attr_create(pool, "crypto", pj_cstr(&stmp, crypto_attribute));
		media->attr[media->attr_count++] = attr;
		break;
	case AST_SIP_MEDIA_ENCRYPT_DTLS:
		if (setup_dtls_srtp(session, session_media)) {
			return -1;
		}

		dtls = ast_rtp_instance_get_dtls(session_media->rtp);
		if (!dtls) {
			return -1;
		}

		switch (dtls->get_connection(session_media->rtp)) {
		case AST_RTP_DTLS_CONNECTION_NEW:
			attr = pjmedia_sdp_attr_create(pool, "connection", &STR_NEW);
			media->attr[media->attr_count++] = attr;
			break;
		case AST_RTP_DTLS_CONNECTION_EXISTING:
			attr = pjmedia_sdp_attr_create(pool, "connection", &STR_EXISTING);
			media->attr[media->attr_count++] = attr;
			break;
		default:
			break;
		}

		switch (dtls->get_setup(session_media->rtp)) {
		case AST_RTP_DTLS_SETUP_ACTIVE:
			attr = pjmedia_sdp_attr_create(pool, "setup", &STR_ACTIVE);
			media->attr[media->attr_count++] = attr;
			break;
		case AST_RTP_DTLS_SETUP_PASSIVE:
			attr = pjmedia_sdp_attr_create(pool, "setup", &STR_PASSIVE);
			media->attr[media->attr_count++] = attr;
			break;
		case AST_RTP_DTLS_SETUP_ACTPASS:
			attr = pjmedia_sdp_attr_create(pool, "setup", &STR_ACTPASS);
			media->attr[media->attr_count++] = attr;
			break;
		case AST_RTP_DTLS_SETUP_HOLDCONN:
			attr = pjmedia_sdp_attr_create(pool, "setup", &STR_HOLDCONN);
			media->attr[media->attr_count++] = attr;
			break;
		default:
			break;
		}

		hash = dtls->get_fingerprint_hash(session_media->rtp);
		crypto_attribute = dtls->get_fingerprint(session_media->rtp);
		if (crypto_attribute && (hash == AST_RTP_DTLS_HASH_SHA1 || hash == AST_RTP_DTLS_HASH_SHA256)) {
			RAII_VAR(struct ast_str *, fingerprint, ast_str_create(64), ast_free);
			if (!fingerprint) {
				return -1;
			}

			if (hash == AST_RTP_DTLS_HASH_SHA1) {
				ast_str_set(&fingerprint, 0, "SHA-1 %s", crypto_attribute);
			} else {
				ast_str_set(&fingerprint, 0, "SHA-256 %s", crypto_attribute);
			}

			attr = pjmedia_sdp_attr_create(pool, "fingerprint", pj_cstr(&stmp, ast_str_buffer(fingerprint)));
			media->attr[media->attr_count++] = attr;
		}
		break;
	}