int icem_stund_recv(struct icem_comp *comp, const struct sa *src, struct stun_msg *req, size_t presz) { struct icem *icem = comp->icem; struct ice *ice = icem->ice; struct stun_attr *attr; struct pl lu, ru; enum role rrole = ROLE_UNKNOWN; uint64_t tiebrk = 0; uint32_t prio_prflx; bool use_cand = false; int err; /* RFC 5389: Fingerprint errors are silently discarded */ err = stun_msg_chk_fingerprint(req); if (err) return err; err = stun_msg_chk_mi(req, (uint8_t *)ice->lpwd, strlen(ice->lpwd)); if (err) { if (err == EBADMSG) goto unauth; else goto badmsg; } attr = stun_msg_attr(req, STUN_ATTR_USERNAME); if (!attr) goto badmsg; err = re_regex(attr->v.username, strlen(attr->v.username), "[^:]+:[^]+", &lu, &ru); if (err) { DEBUG_WARNING("could not parse USERNAME attribute (%s)\n", attr->v.username); goto unauth; } if (pl_strcmp(&lu, ice->lufrag)) goto unauth; if (str_isset(icem->rufrag) && pl_strcmp(&ru, icem->rufrag)) goto unauth; attr = stun_msg_attr(req, STUN_ATTR_CONTROLLED); if (attr) { rrole = ROLE_CONTROLLED; tiebrk = attr->v.uint64; } attr = stun_msg_attr(req, STUN_ATTR_CONTROLLING); if (attr) { rrole = ROLE_CONTROLLING; tiebrk = attr->v.uint64; } if (rrole == ice->lrole) { if (ice->tiebrk >= tiebrk) ice_switch_local_role(ice); else goto conflict; } attr = stun_msg_attr(req, STUN_ATTR_PRIORITY); if (attr) prio_prflx = attr->v.uint32; else goto badmsg; attr = stun_msg_attr(req, STUN_ATTR_USE_CAND); if (attr) use_cand = true; err = handle_stun(ice, icem, comp, src, prio_prflx, use_cand, presz > 0); if (err) goto badmsg; return stun_reply(icem->proto, comp->sock, src, presz, req, (uint8_t *)ice->lpwd, strlen(ice->lpwd), true, 2, STUN_ATTR_XOR_MAPPED_ADDR, src, STUN_ATTR_SOFTWARE, sw); badmsg: return stunsrv_ereply(comp, src, presz, req, 400, "Bad Request"); unauth: return stunsrv_ereply(comp, src, presz, req, 401, "Unauthorized"); conflict: return stunsrv_ereply(comp, src, presz, req, 487, "Role Conflict"); }
int krx_udp_receive(udp_conn* c) { socklen_t len = sizeof(c->client); ssize_t nread = recvfrom(c->sock, c->buf, KRX_UDP_BUF_LEN, 0, (struct sockaddr*)&c->client, &len); if(nread < 0) { printf("Error: cannot receive.\n"); return -1; } if(nread < 2) { printf("Only received 2 bytes?\n"); return 0; } if((c->buf[0] == 0x00 || c->buf[0] == 0x01) && (c->buf[1] == 0x00 || c->buf[1] == 0x01) ) { handle_stun(c, c->buf, nread); } else { if(krx_dtls_is_handshake_done(&c->dtls) > 0) { if(c->state == KRX_STATE_NONE) { // when done, we pass on the data libsrtp c->state = KRX_STATE_SSL_INIT_READY; printf("---------------------- finished --------------------------\n"); uint8_t material[KRX_SRTP_MASTER_LEN * 2]; int r = SSL_export_keying_material(c->dtls.ssl, material, KRX_SRTP_MASTER_LEN * 2, "EXTRACTOR-dtls_srtp", 19, NULL, 0, 0); if(r == 0) { printf("Error: cannot export the SSL keying material.\n"); exit(EXIT_FAILURE); } // extracking keying example https://github.com/traviscross/baresip/blob/8974d662c942b10a9bb05223ddc7881896dd4c2f/modules/dtls_srtp/tls_udp.c /* Keys:: http://tools.ietf.org/html/rfc5764#section-4.2, note: client <> server use different keying, we handle server for now. */ uint8_t* remote_key = material; uint8_t* local_key = remote_key + KRX_SRTP_MASTER_KEY_LEN; uint8_t* remote_salt = local_key + KRX_SRTP_MASTER_KEY_LEN; uint8_t* local_salt = remote_salt + KRX_SRTP_MASTER_SALT_LEN;; memcpy(c->srtp.policy.key, remote_key, KRX_SRTP_MASTER_KEY_LEN); memcpy(c->srtp.policy.key + KRX_SRTP_MASTER_KEY_LEN, remote_salt, KRX_SRTP_MASTER_SALT_LEN); SRTP_PROTECTION_PROFILE *p = SSL_get_selected_srtp_profile(c->dtls.ssl); if(!p) { printf("Error: cannot extract the srtp_profile.\n"); exit(EXIT_FAILURE); } printf(">>>>>>> %s <<<<<\n", p->name); // TLS_RSA_WITH_AES_128_CBC_SHA printf("---> cipher: %s\n", SSL_CIPHER_get_name(SSL_get_current_cipher(c->dtls.ssl))); /* create SRTP session */ err_status_t sr = srtp_create(&c->srtp.session, &c->srtp.policy); if(sr != err_status_ok) { printf("Error: cannot create srtp session: %d.\n", sr); exit(EXIT_FAILURE); } /* @TODO --- CLEANUP! - WE NEED TO UNPROTECT THIS DIRECTLY!!! SEE "MARKER-MARKER" below*/ int buflen = nread; sr = srtp_unprotect(c->srtp.session, c->buf, &buflen); if(sr != err_status_ok) { printf("Error: cannot unprotect, err: %d. len: %d <> %d\n", sr, len, buflen); } else { //printf("~ %zd bytes read // buflen: %d.\n", nread, buflen); krx_rtp_decode(&c->rtp, c->buf, buflen); } } else if(c->state == KRX_STATE_SSL_INIT_READY) { /* @TODO --- CLEANUP! duplicate, see a couple of line above */ /* MARKER-MARKER */ int buflen = nread; err_status_t sr = srtp_unprotect(c->srtp.session, c->buf, &buflen); if(sr != err_status_ok) { printf("Error: cannot unprotect, err: %d. len: %d <> %d\n", sr, len, buflen); } else { //printf("~ %zd bytes read // buflen: %d.\n", nread, buflen); krx_rtp_decode(&c->rtp, c->buf, buflen); } } } else { krx_dtls_handle_traffic(&c->dtls, c->buf, nread); } } return 0; }