From 97e234048c282a7d22ccbdaa05f983c21429eb99 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 19 Feb 2014 07:05:29 +0500 Subject: [PATCH] FS-6204 refactor some dtls code to generate a 1024 bit cert suitable for dtls in all version of chrome --- src/include/switch_core_media.h | 14 +---- src/switch_core_cert.c | 99 +++++++++++---------------------- src/switch_core_media.c | 16 +++++- src/switch_rtp.c | 87 ++++++++++++++++++----------- 4 files changed, 102 insertions(+), 114 deletions(-) diff --git a/src/include/switch_core_media.h b/src/include/switch_core_media.h index bc168d1387..37e8df8484 100644 --- a/src/include/switch_core_media.h +++ b/src/include/switch_core_media.h @@ -157,19 +157,6 @@ typedef struct switch_core_media_params_s { } switch_core_media_params_t; -typedef struct xpayload_map_s { - uint32_t pt; - uint32_t send_pt; - uint32_t rate; - uint32_t ptime; - switch_media_type_t type; - uint8_t negotiated; - char *name; - switch_sdp_type_t sdp_type; - unsigned long hash; - struct xpayload_map_s *next; -} xpayload_map_t; - typedef struct payload_map_s { switch_media_type_t type; switch_sdp_type_t sdp_type; @@ -177,6 +164,7 @@ typedef struct payload_map_s { uint32_t rate; uint8_t allocated; uint8_t negotiated; + uint8_t current; unsigned long hash; char *rm_encoding; diff --git a/src/switch_core_cert.c b/src/switch_core_cert.c index 19205e39d4..818d560520 100644 --- a/src/switch_core_cert.c +++ b/src/switch_core_cert.c @@ -194,8 +194,12 @@ SWITCH_DECLARE(int) switch_core_cert_gen_fingerprint(const char *prefix, dtls_fi int ret = 0; char *rsa; + rsa = switch_mprintf("%s%s%s.pem", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, prefix); - rsa = switch_mprintf("%s%s%s.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, prefix); + if (switch_file_exists(rsa, NULL) != SWITCH_STATUS_SUCCESS) { + free(rsa); + rsa = switch_mprintf("%s%s%s.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, prefix); + } if (!(bio = BIO_new(BIO_s_file()))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FP BIO ERR!\n"); @@ -233,7 +237,6 @@ SWITCH_DECLARE(int) switch_core_cert_gen_fingerprint(const char *prefix, dtls_fi static int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days); -static int add_ext(X509 *cert, int nid, char *value); SWITCH_DECLARE(int) switch_core_gen_certs(const char *prefix) { @@ -273,7 +276,7 @@ SWITCH_DECLARE(int) switch_core_gen_certs(const char *prefix) //bio_err=BIO_new_fp(stderr, BIO_NOCLOSE); - mkcert(&x509, &pkey, 2048, 0, 365); + mkcert(&x509, &pkey, 1024, 0, 36500); //RSA_print_fp(stdout, pkey->pkey.rsa, 0); //X509_print_fp(stdout, x509); @@ -318,6 +321,7 @@ SWITCH_DECLARE(int) switch_core_gen_certs(const char *prefix) return(0); } +#if 0 static void callback(int p, int n, void *arg) { char c='B'; @@ -328,6 +332,7 @@ static void callback(int p, int n, void *arg) if (p == 3) c='\n'; fputc(c, stderr); } +#endif static int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days) { @@ -336,46 +341,44 @@ static int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days RSA *rsa; X509_NAME *name=NULL; - if ((pkeyp == NULL) || (*pkeyp == NULL)) - { - if ((pk=EVP_PKEY_new()) == NULL) - { - abort(); - } + if ((pkeyp == NULL) || (*pkeyp == NULL)) { + if ((pk = EVP_PKEY_new()) == NULL) { + abort(); } - else - pk= *pkeyp; + } else { + pk = *pkeyp; + } - if ((x509p == NULL) || (*x509p == NULL)) - { - if ((x=X509_new()) == NULL) - goto err; - } - else - x= *x509p; - - rsa=RSA_generate_key(bits, RSA_F4, callback, NULL); - if (!EVP_PKEY_assign_RSA(pk, rsa)) - { - abort(); + if ((x509p == NULL) || (*x509p == NULL)) { + if ((x = X509_new()) == NULL) { goto err; } - rsa=NULL; + } else { + x = *x509p; + } - X509_set_version(x, 2); + rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL); + + if (!EVP_PKEY_assign_RSA(pk, rsa)) { + abort(); + goto err; + } + + rsa = NULL; + + X509_set_version(x, 0); ASN1_INTEGER_set(X509_get_serialNumber(x), serial); - X509_gmtime_adj(X509_get_notBefore(x), 0); + X509_gmtime_adj(X509_get_notBefore(x), -(long)60*60*24*7); X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days); X509_set_pubkey(x, pk); - name=X509_get_subject_name(x); + name = X509_get_subject_name(x); /* This function creates and adds the entry, working out the * correct string type and performing checks on its length. * Normally we'd check the return value for errors... */ X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0); - X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"FreeSWITCH", -1, -1, 0); @@ -384,49 +387,13 @@ static int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days */ X509_set_issuer_name(x, name); - /* Add various extensions: standard extensions */ - add_ext(x, NID_basic_constraints, "critical, CA:TRUE"); - add_ext(x, NID_key_usage, "critical, keyCertSign, cRLSign"); - - add_ext(x, NID_subject_key_identifier, "hash"); - - /* Some Netscape specific extensions */ - add_ext(x, NID_netscape_cert_type, "sslCA"); - - add_ext(x, NID_netscape_comment, "Self-Signed CERT for DTLS"); - - if (!X509_sign(x, pk, EVP_sha1())) goto err; - *x509p=x; - *pkeyp=pk; + *x509p = x; + *pkeyp = pk; return(1); err: return(0); } -/* Add extension using V3 code: we can set the config file as NULL - * because we wont reference any other sections. - */ - -static int add_ext(X509 *cert, int nid, char *value) -{ - X509_EXTENSION *ex; - X509V3_CTX ctx; - /* This sets the 'context' of the extensions. */ - /* No configuration database */ - X509V3_set_ctx_nodb(&ctx); - /* Issuer and subject certs: both the target since it is self signed, - * no request and no CRL - */ - X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); - ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); - if (!ex) - return 0; - - X509_add_ext(cert, ex, -1); - X509_EXTENSION_free(ex); - return 1; -} - diff --git a/src/switch_core_media.c b/src/switch_core_media.c index aed981d226..77427fe287 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -1255,9 +1255,10 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].payload_map = switch_core_alloc(session->pool, sizeof(payload_map_t)); session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].cur_payload_map = session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].payload_map; + session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].cur_payload_map->current = 1; session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].payload_map = switch_core_alloc(session->pool, sizeof(payload_map_t)); session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].cur_payload_map = session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].payload_map; - + session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].cur_payload_map->current = 1; switch_channel_set_flag(session->channel, CF_DTLS_OK); @@ -1724,7 +1725,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session for (pmap = engine->payload_map; pmap; pmap = pmap->next) { if (engine->read_frame.payload == pmap->recv_pt && pmap->negotiated) { engine->cur_payload_map = pmap; - + engine->cur_payload_map->current = 1; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Changing current codec to %s (payload type %d).\n", pmap->iananame, pmap->pt); @@ -2669,6 +2670,7 @@ static void clear_pmaps(switch_rtp_engine_t *engine) for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) { pmap->negotiated = 0; + pmap->current = 0; } } @@ -3325,6 +3327,10 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s if (j == 0) { a_engine->cur_payload_map = pmap; + a_engine->cur_payload_map->current = 1; + if (a_engine->rtp_session) { + switch_rtp_set_default_payload(a_engine->rtp_session, pmap->pt); + } } pmap->rm_encoding = switch_core_session_strdup(session, (char *) mmap->rm_encoding); @@ -3583,6 +3589,10 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s SWITCH_TRUE); if (j == 0) { v_engine->cur_payload_map = pmap; + v_engine->cur_payload_map->current = 1; + if (v_engine->rtp_session) { + switch_rtp_set_default_payload(v_engine->rtp_session, pmap->pt); + } } mimp = matches[j].imp; @@ -8443,7 +8453,7 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s SWITCH_DECLARE(void) switch_core_media_init(void) { - switch_core_gen_certs(DTLS_SRTP_FNAME); + switch_core_gen_certs(DTLS_SRTP_FNAME ".pem"); } SWITCH_DECLARE(void) switch_core_media_deinit(void) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 2b8dda2200..89426be7ec 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -252,6 +252,7 @@ typedef struct switch_dtls_s { char *rsa; char *pvt; char *ca; + char *pem; struct switch_rtp *rtp_session; } switch_dtls_t; @@ -261,9 +262,9 @@ typedef int (*dtls_state_handler_t)(switch_rtp_t *, switch_dtls_t *); static int dtls_state_handshake(switch_rtp_t *rtp_session, switch_dtls_t *dtls); static int dtls_state_ready(switch_rtp_t *rtp_session, switch_dtls_t *dtls); static int dtls_state_setup(switch_rtp_t *rtp_session, switch_dtls_t *dtls); -static int dtls_state_dummy(switch_rtp_t *rtp_session, switch_dtls_t *dtls); +static int dtls_state_fail(switch_rtp_t *rtp_session, switch_dtls_t *dtls); -dtls_state_handler_t dtls_states[DS_INVALID] = {dtls_state_handshake, dtls_state_setup, dtls_state_ready, dtls_state_dummy}; +dtls_state_handler_t dtls_states[DS_INVALID] = {dtls_state_handshake, dtls_state_setup, dtls_state_ready, dtls_state_fail}; typedef struct ts_normalize_s { uint32_t last_ssrc; @@ -1067,7 +1068,6 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d remote_ip = switch_get_addr(ipbuf, sizeof(ipbuf), from_addr); switch_stun_packet_attribute_add_xor_binded_address(rpacket, (char *) remote_ip, switch_sockaddr_get_port(from_addr)); - if (!switch_cmp_addr(from_addr, ice->addr)) { host = switch_get_addr(buf, sizeof(buf), from_addr); port = switch_sockaddr_get_port(from_addr); @@ -2567,11 +2567,6 @@ static const char *dtls_state_names(dtls_state_t s) #define dtls_set_state(_dtls, _state) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Changing %s DTLS state from %s to %s\n", rtp_type(rtp_session), dtls_state_names(_dtls->state), dtls_state_names(_state)); _dtls->new_state = 1; _dtls->last_state = _dtls->state; _dtls->state = _state -static int dtls_state_dummy(switch_rtp_t *rtp_session, switch_dtls_t *dtls) -{ - return -1; -} - #define cr_keylen 16 #define cr_saltlen 14 #define cr_kslen 30 @@ -2661,6 +2656,17 @@ static int dtls_state_ready(switch_rtp_t *rtp_session, switch_dtls_t *dtls) return 0; } +static int dtls_state_fail(switch_rtp_t *rtp_session, switch_dtls_t *dtls) +{ + if (rtp_session->session) { + switch_channel_t *channel = switch_core_session_get_channel(rtp_session->session); + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + } + + return -1; +} + + static int dtls_state_handshake(switch_rtp_t *rtp_session, switch_dtls_t *dtls) { int ret; @@ -2708,39 +2714,32 @@ static void free_dtls(switch_dtls_t **dtlsp) static int do_dtls(switch_rtp_t *rtp_session, switch_dtls_t *dtls) { int r = 0, ret = 0, len; - void *data; switch_size_t bytes; + unsigned char buf[4096] = ""; + int ready = rtp_session->ice.ice_user ? (rtp_session->ice.rready && rtp_session->ice.ready) : 1; + - if (dtls->bytes) { - - //if (dtls->state == DS_READY) { - // - //} - - if ((ret = BIO_write(dtls->read_bio, dtls->data, (int)dtls->bytes)) != (int)dtls->bytes) { - ret = SSL_get_error(dtls->ssl, ret); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS packet read err %d\n", rtp_type(rtp_session), ret); - dtls_set_state(dtls, DS_FAIL); - return -1; - } + if (!dtls->bytes && !ready) { + printf("SKIP\n"); + return 0; } - if (SSL_read(dtls->ssl, dtls->data, (int)dtls->bytes) == (int)dtls->bytes) { - if (BIO_reset(dtls->read_bio)); + if ((ret = BIO_write(dtls->read_bio, dtls->data, (int)dtls->bytes)) != (int)dtls->bytes && dtls->bytes > 0) { + ret = SSL_get_error(dtls->ssl, ret); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS packet read err %d\n", rtp_type(rtp_session), ret); } r = dtls_states[dtls->state](rtp_session, dtls); - - if ((len = BIO_get_mem_data(dtls->write_bio, &data)) && data) { + if ((len = BIO_read(dtls->write_bio, buf, sizeof(buf))) > 0) { bytes = len; - if (switch_socket_sendto(dtls->sock_output, dtls->remote_addr, 0, data, &bytes ) != SWITCH_STATUS_SUCCESS) { + if (switch_socket_sendto(dtls->sock_output, dtls->remote_addr, 0, (void *)buf, &bytes ) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS packet not written\n", rtp_type(rtp_session)); - } else { - if (BIO_reset(dtls->write_bio)); } } + + return r; } @@ -2874,9 +2873,15 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d dtls = switch_core_alloc(rtp_session->pool, sizeof(*dtls)); - - dtls->pvt = switch_core_sprintf(rtp_session->pool, "%s%s%s.key", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME); - dtls->rsa = switch_core_sprintf(rtp_session->pool, "%s%s%s.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME); + dtls->pem = switch_core_sprintf(rtp_session->pool, "%s%s%s.pem", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME); + + if (switch_file_exists(dtls->pem, rtp_session->pool) == SWITCH_STATUS_SUCCESS) { + dtls->pvt = dtls->rsa = dtls->pem; + } else { + dtls->pvt = switch_core_sprintf(rtp_session->pool, "%s%s%s.key", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME); + dtls->rsa = switch_core_sprintf(rtp_session->pool, "%s%s%s.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME); + } + dtls->ca = switch_core_sprintf(rtp_session->pool, "%s%sca-bundle.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR); dtls->ssl_ctx = SSL_CTX_new(DTLSv1_method()); @@ -2884,7 +2889,6 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d SSL_CTX_set_mode(dtls->ssl_ctx, SSL_MODE_AUTO_RETRY); - //SSL_CTX_set_verify(dtls->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); SSL_CTX_set_verify(dtls->ssl_ctx, SSL_VERIFY_NONE, NULL); @@ -2937,6 +2941,14 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d SSL_set_verify(dtls->ssl, SSL_VERIFY_NONE, NULL); SSL_set_app_data(dtls->ssl, dtls); + BIO_ctrl(dtls->read_bio, BIO_CTRL_DGRAM_SET_MTU, 1400, NULL); + BIO_ctrl(dtls->write_bio, BIO_CTRL_DGRAM_SET_MTU, 1400, NULL); + SSL_set_mtu(dtls->ssl, 1400); + BIO_ctrl(dtls->write_bio, BIO_C_SET_BUFF_SIZE, 1400, NULL); + BIO_ctrl(dtls->read_bio, BIO_C_SET_BUFF_SIZE, 1400, NULL); + + + dtls->local_fp = local_fp; dtls->remote_fp = remote_fp; dtls->rtp_session = rtp_session; @@ -4381,6 +4393,7 @@ static int check_recv_payload(switch_rtp_t *rtp_session) ok = 0; switch_mutex_lock(rtp_session->flag_mutex); + for (pmap = *rtp_session->pmaps; pmap && pmap->allocated; pmap = pmap->next) { if (!pmap->negotiated) { continue; @@ -6569,6 +6582,16 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra } } else { payload = rtp_session->payload; +#if 0 + if (rtp_session->pmaps && *rtp_session->pmaps) { + payload_map_t *pmap; + for (pmap = *rtp_session->pmaps; pmap; pmap = pmap->next) { + if (pmap->current) { + payload = pmap->pt; + } + } + } +#endif } if (switch_test_flag(frame, SFF_RTP_HEADER)) {