|
|
|
@ -35,6 +35,32 @@ |
|
|
|
|
|
|
|
#define CERT_EXPIRY_TIME (60*60*24*30) /* 30 days */ |
|
|
|
|
|
|
|
INLINE struct stream_fd *dtls_primary(struct packet_stream *ps) { |
|
|
|
if (!ps->sfds.length) |
|
|
|
return NULL; |
|
|
|
return ps->sfds.head->data; |
|
|
|
} |
|
|
|
// determine the sfd to hold our DTLS context if we don't know the sfd. |
|
|
|
// it's either the "selected_sfd" for regular multi-homed streams, or |
|
|
|
// the first sfd in the list in case ICE is in use |
|
|
|
struct stream_fd *dtls_sfd(struct packet_stream *ps) { |
|
|
|
if (!ps) |
|
|
|
return NULL; |
|
|
|
if (PS_ISSET(ps, ICE)) |
|
|
|
return dtls_primary(ps); |
|
|
|
return ps->selected_sfd; |
|
|
|
} |
|
|
|
// determine the DTLS context if we do have an sfd. can be sfd->dtls, |
|
|
|
// or in case ICE is in use, the first sfd's context. |
|
|
|
struct dtls_connection *dtls_ptr(struct stream_fd *sfd) { |
|
|
|
if (!sfd) |
|
|
|
return NULL; |
|
|
|
struct packet_stream *ps = sfd->stream; |
|
|
|
if (PS_ISSET(ps, ICE)) // ignore which sfd we were given |
|
|
|
sfd = dtls_primary(ps); |
|
|
|
return &sfd->dtls; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -477,13 +503,13 @@ int dtls_connection_init(struct packet_stream *ps, int active, struct dtls_cert |
|
|
|
struct dtls_connection *d; |
|
|
|
unsigned long err; |
|
|
|
|
|
|
|
if (!ps || !ps->selected_sfd) |
|
|
|
struct stream_fd *sfd = dtls_sfd(ps); |
|
|
|
if (!sfd) |
|
|
|
return 0; |
|
|
|
d = &sfd->dtls; |
|
|
|
|
|
|
|
__DBG("dtls_connection_init(%i)", active); |
|
|
|
|
|
|
|
d = &ps->selected_sfd->dtls; |
|
|
|
|
|
|
|
if (d->init) { |
|
|
|
if ((d->active && active) || (!d->active && !active)) |
|
|
|
goto done; |
|
|
|
@ -522,7 +548,7 @@ int dtls_connection_init(struct packet_stream *ps, int active, struct dtls_cert |
|
|
|
if (!d->r_bio || !d->w_bio) |
|
|
|
goto error; |
|
|
|
|
|
|
|
SSL_set_app_data(d->ssl, ps->selected_sfd); /* XXX obj reference here? */ |
|
|
|
SSL_set_app_data(d->ssl, sfd); /* XXX obj reference here? */ |
|
|
|
SSL_set_bio(d->ssl, d->r_bio, d->w_bio); |
|
|
|
d->init = 1; |
|
|
|
SSL_set_mode(d->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); |
|
|
|
@ -618,15 +644,18 @@ found: |
|
|
|
|
|
|
|
ilog(LOG_INFO, "DTLS-SRTP successfully negotiated"); |
|
|
|
|
|
|
|
if (d->active) { |
|
|
|
/* we're the client */ |
|
|
|
crypto_init(&ps->crypto, &client); |
|
|
|
crypto_init(&ps->selected_sfd->crypto, &server); |
|
|
|
} |
|
|
|
else { |
|
|
|
/* we're the server */ |
|
|
|
crypto_init(&ps->crypto, &server); |
|
|
|
crypto_init(&ps->selected_sfd->crypto, &client); |
|
|
|
for (GList *l = ps->sfds.head; l; l = l->next) { |
|
|
|
struct stream_fd *sfd = l->data; |
|
|
|
if (d->active) { |
|
|
|
/* we're the client */ |
|
|
|
crypto_init(&ps->crypto, &client); |
|
|
|
crypto_init(&sfd->crypto, &server); |
|
|
|
} |
|
|
|
else { |
|
|
|
/* we're the server */ |
|
|
|
crypto_init(&ps->crypto, &server); |
|
|
|
crypto_init(&sfd->crypto, &client); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
crypto_dump_keys(&ps->crypto, &ps->selected_sfd->crypto); |
|
|
|
@ -643,17 +672,18 @@ error: |
|
|
|
} |
|
|
|
|
|
|
|
/* called with call locked in W or R with ps->in_lock held */ |
|
|
|
int dtls(struct packet_stream *ps, const str *s, const endpoint_t *fsin) { |
|
|
|
struct dtls_connection *d; |
|
|
|
int dtls(struct stream_fd *sfd, const str *s, const endpoint_t *fsin) { |
|
|
|
struct packet_stream *ps = sfd->stream; |
|
|
|
int ret; |
|
|
|
unsigned char buf[0x10000]; |
|
|
|
|
|
|
|
if (!ps || !ps->selected_sfd) |
|
|
|
if (!ps) |
|
|
|
return 0; |
|
|
|
if (!MEDIA_ISSET(ps->media, DTLS)) |
|
|
|
return 0; |
|
|
|
|
|
|
|
d = &ps->selected_sfd->dtls; |
|
|
|
struct dtls_connection *d = dtls_ptr(sfd); |
|
|
|
if (!d) |
|
|
|
return 0; |
|
|
|
|
|
|
|
if (s) |
|
|
|
__DBG("dtls packet input: len %u %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", |
|
|
|
@ -675,7 +705,7 @@ int dtls(struct packet_stream *ps, const str *s, const endpoint_t *fsin) { |
|
|
|
|
|
|
|
ret = try_connect(d); |
|
|
|
if (ret == -1) { |
|
|
|
ilog(LOG_ERROR, "DTLS error on local port %u", ps->selected_sfd->socket.local.port); |
|
|
|
ilog(LOG_ERROR, "DTLS error on local port %u", sfd->socket.local.port); |
|
|
|
/* fatal error */ |
|
|
|
dtls_connection_cleanup(d); |
|
|
|
return 0; |
|
|
|
@ -727,7 +757,7 @@ int dtls(struct packet_stream *ps, const str *s, const endpoint_t *fsin) { |
|
|
|
fsin = &ps->endpoint; |
|
|
|
|
|
|
|
ilog(LOG_DEBUG, "Sending DTLS packet"); |
|
|
|
socket_sendto(&ps->selected_sfd->socket, buf, ret, fsin); |
|
|
|
socket_sendto(&sfd->socket, buf, ret, fsin); |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
@ -735,23 +765,29 @@ int dtls(struct packet_stream *ps, const str *s, const endpoint_t *fsin) { |
|
|
|
|
|
|
|
/* call must be locked */ |
|
|
|
void dtls_shutdown(struct packet_stream *ps) { |
|
|
|
struct dtls_connection *d; |
|
|
|
|
|
|
|
if (!ps || !ps->selected_sfd) |
|
|
|
if (!ps) |
|
|
|
return; |
|
|
|
|
|
|
|
__DBG("dtls_shutdown"); |
|
|
|
|
|
|
|
d = &ps->selected_sfd->dtls; |
|
|
|
if (!d->init) |
|
|
|
return; |
|
|
|
for (GList *l = ps->sfds.head; l; l = l->next) { |
|
|
|
struct stream_fd *sfd = l->data; |
|
|
|
|
|
|
|
struct dtls_connection *d = &sfd->dtls; |
|
|
|
if (!d->init) |
|
|
|
continue; |
|
|
|
|
|
|
|
if (d->connected && d->ssl) { |
|
|
|
SSL_shutdown(d->ssl); |
|
|
|
dtls(sfd, NULL, &ps->endpoint); |
|
|
|
} |
|
|
|
|
|
|
|
dtls_connection_cleanup(d); |
|
|
|
|
|
|
|
if (d->connected && d->ssl) { |
|
|
|
SSL_shutdown(d->ssl); |
|
|
|
dtls(ps, NULL, &ps->endpoint); |
|
|
|
crypto_reset(&sfd->crypto); |
|
|
|
} |
|
|
|
|
|
|
|
dtls_connection_cleanup(d); |
|
|
|
|
|
|
|
if (ps->dtls_cert) { |
|
|
|
X509_free(ps->dtls_cert); |
|
|
|
@ -759,7 +795,6 @@ void dtls_shutdown(struct packet_stream *ps) { |
|
|
|
} |
|
|
|
|
|
|
|
crypto_reset(&ps->crypto); |
|
|
|
crypto_reset(&ps->selected_sfd->crypto); |
|
|
|
} |
|
|
|
|
|
|
|
void dtls_connection_cleanup(struct dtls_connection *c) { |
|
|
|
|