Statistics
| Branch: | Revision:

janus-gateway / dtls.c @ 1d31e31f

History | View | Annotate | Download (30.1 KB)

1
/*! \file    dtls.c
2
 * \author   Lorenzo Miniero <lorenzo@meetecho.com>
3
 * \copyright GNU General Public License v3
4
 * \brief    DTLS/SRTP processing
5
 * \details  Implementation (based on OpenSSL and libsrtp) of the DTLS/SRTP
6
 * transport. The code takes care of the DTLS handshake between peers and
7
 * the gateway, and sets the proper SRTP and SRTCP context up accordingly.
8
 * A DTLS alert from a peer is notified to the plugin handling him/her
9
 * by means of the hangup_media callback.
10
 * 
11
 * \ingroup protocols
12
 * \ref protocols
13
 */
14
 
15
#include "janus.h"
16
#include "debug.h"
17
#include "dtls.h"
18
#include "rtcp.h"
19
#include "events.h"
20

    
21

    
22
/* SRTP stuff (http://tools.ietf.org/html/rfc3711) */
23
static const char *janus_srtp_error[] =
24
{
25
        "err_status_ok",
26
        "err_status_fail",
27
        "err_status_bad_param",
28
        "err_status_alloc_fail",
29
        "err_status_dealloc_fail",
30
        "err_status_init_fail",
31
        "err_status_terminus",
32
        "err_status_auth_fail",
33
        "err_status_cipher_fail",
34
        "err_status_replay_fail",
35
        "err_status_replay_old",
36
        "err_status_algo_fail",
37
        "err_status_no_such_op",
38
        "err_status_no_ctx",
39
        "err_status_cant_check",
40
        "err_status_key_expired",
41
        "err_status_socket_err",
42
        "err_status_signal_err",
43
        "err_status_nonce_bad",
44
        "err_status_read_fail",
45
        "err_status_write_fail",
46
        "err_status_parse_err",
47
        "err_status_encode_err",
48
        "err_status_semaphore_err",
49
        "err_status_pfkey_err",
50
};
51
const gchar *janus_get_srtp_error(int error) {
52
        if(error < 0 || error > 24)
53
                return NULL;
54
        return janus_srtp_error[error];
55
}
56

    
57
const gchar *janus_get_dtls_srtp_state(janus_dtls_state state) {
58
        switch(state) {
59
                case JANUS_DTLS_STATE_CREATED:
60
                        return "created";
61
                case JANUS_DTLS_STATE_TRYING:
62
                        return "trying";
63
                case JANUS_DTLS_STATE_CONNECTED:
64
                        return "connected";
65
                case JANUS_DTLS_STATE_FAILED:
66
                        return "failed";
67
                default:
68
                        return NULL;
69
        }
70
        return NULL;
71
}
72

    
73
const gchar *janus_get_dtls_srtp_role(janus_dtls_role role) {
74
        switch(role) {
75
                case JANUS_DTLS_ROLE_ACTPASS:
76
                        return "actpass";
77
                case JANUS_DTLS_ROLE_SERVER:
78
                        return "passive";
79
                case JANUS_DTLS_ROLE_CLIENT:
80
                        return "active";
81
                default:
82
                        return NULL;
83
        }
84
        return NULL;
85
}
86

    
87

    
88
/* Helper to notify DTLS state changes to the event handlers */
89
static void janus_dtls_notify_state_change(janus_dtls_srtp *dtls) {
90
        if(janus_events_is_enabled())
91
                return;
92
        if(dtls == NULL)
93
                return;
94
        janus_ice_component *component = (janus_ice_component *)dtls->component;
95
        if(component == NULL)
96
                return;
97
        janus_ice_stream *stream = component->stream;
98
        if(stream == NULL)
99
                return;
100
        janus_ice_handle *handle = stream->handle;
101
        if(handle == NULL)
102
                return;
103
        janus_session *session = (janus_session *)handle->session;
104
        if(session == NULL)
105
                return;
106
        json_t *info = json_object();
107
        json_object_set_new(info, "dtls", json_string(janus_get_dtls_srtp_state(dtls->dtls_state)));
108
        json_object_set_new(info, "stream_id", json_integer(stream->stream_id));
109
        json_object_set_new(info, "component_id", json_integer(component->component_id));
110
        janus_events_notify_handlers(JANUS_EVENT_TYPE_WEBRTC, session->session_id, handle->handle_id, info);
111
}
112

    
113

    
114
/* DTLS stuff */
115
#define DTLS_CIPHERS        "ALL:NULL:eNULL:aNULL"
116

    
117
/* SRTP stuff (http://tools.ietf.org/html/rfc3711) */
118
#define SRTP_MASTER_KEY_LENGTH        16
119
#define SRTP_MASTER_SALT_LENGTH        14
120
#define SRTP_MASTER_LENGTH (SRTP_MASTER_KEY_LENGTH + SRTP_MASTER_SALT_LENGTH)
121

    
122

    
123
static SSL_CTX *ssl_ctx = NULL;
124
SSL_CTX *janus_dtls_get_ssl_ctx(void) {
125
        return ssl_ctx;
126
}
127
static gchar local_fingerprint[160];
128
gchar *janus_dtls_get_local_fingerprint(void) {
129
        return (gchar *)local_fingerprint;
130
}
131

    
132

    
133
#ifdef HAVE_SCTP
134
/* Helper thread to create a SCTP association that will use this DTLS stack */
135
void *janus_dtls_sctp_setup_thread(void *data);
136
#endif
137

    
138

    
139
/*
140
 * FIXME DTLS locking stuff to make OpenSSL thread safe
141
 *
142
 * Note: this is an attempt to fix the infamous issue #316:
143
 *                 https://github.com/meetecho/janus-gateway/issues/316
144
 * that is the "tlsv1 alert decrypt error" randomly happening when
145
 * doing handshakes that force Janus to be restarted (issue affecting
146
 * OpenSSL but NOT BoringSSL, apparently). The cause might be related
147
 * to race conditions, and in fact OpenSSL docs state that:
148
 *
149
 *                 "OpenSSL can safely be used in multi-threaded applications
150
 *                 provided that at least two callback functions are set,
151
 *                 locking_function and threadid_func."
152
 *
153
 * See here for the whole docs:
154
 *                 https://www.openssl.org/docs/manmaster/crypto/threads.html
155
 *
156
 * The fix proposed here is heavily derived from a discussion related to
157
 * RTPEngine:
158
 *                 http://lists.sip-router.org/pipermail/sr-dev/2015-January/026860.html
159
 * where it was mentioned the issue was fixed in this commit:
160
 *                 https://github.com/sipwise/rtpengine/commit/935487b66363c9932684d8085f47450d65a8c37e
161
 * which does indeed implement the callbacks the OpenSSL docs suggest.
162
 *
163
 */
164
static janus_mutex *janus_dtls_locks;
165

    
166
static void janus_dtls_cb_openssl_threadid(CRYPTO_THREADID *tid) {
167
        /* FIXME Assuming pthread, which is fine as GLib wraps pthread and
168
         * so that's what we use anyway? */
169
        pthread_t me = pthread_self();
170

    
171
        if(sizeof(me) == sizeof(void *)) {
172
                CRYPTO_THREADID_set_pointer(tid, (void *) me);
173
        } else {
174
                CRYPTO_THREADID_set_numeric(tid, (unsigned long) me);
175
        }
176
}
177

    
178
static void janus_dtls_cb_openssl_lock(int mode, int type, const char *file, int line) {
179
        if((mode & CRYPTO_LOCK)) {
180
                janus_mutex_lock(&janus_dtls_locks[type]);
181
        } else {
182
                janus_mutex_unlock(&janus_dtls_locks[type]);
183
        }
184
}
185

    
186

    
187
/* DTLS-SRTP initialization */
188
gint janus_dtls_srtp_init(gchar *server_pem, gchar *server_key) {
189
        /* FIXME First of all make OpenSSL thread safe (see note above on issue #316) */
190
        janus_dtls_locks = g_malloc0(sizeof(*janus_dtls_locks) * CRYPTO_num_locks());
191
        int l=0;
192
        for(l = 0; l < CRYPTO_num_locks(); l++) {
193
                janus_mutex_init(&janus_dtls_locks[l]);
194
        }
195
        CRYPTO_THREADID_set_callback(janus_dtls_cb_openssl_threadid);
196
        CRYPTO_set_locking_callback(janus_dtls_cb_openssl_lock);
197

    
198
        /* Go on and create the DTLS context */
199
        ssl_ctx = SSL_CTX_new(DTLSv1_method());
200
        if(!ssl_ctx) {
201
                JANUS_LOG(LOG_FATAL, "Ops, error creating DTLS context?\n");
202
                return -1;
203
        }
204
        SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, janus_dtls_verify_callback);
205
        SSL_CTX_set_tlsext_use_srtp(ssl_ctx, "SRTP_AES128_CM_SHA1_80");        /* FIXME Should we support something else as well? */
206
        if(!server_pem || !SSL_CTX_use_certificate_file(ssl_ctx, server_pem, SSL_FILETYPE_PEM)) {
207
                JANUS_LOG(LOG_FATAL, "Certificate error (%s)\n", ERR_reason_error_string(ERR_get_error()));
208
                return -2;
209
        }
210
        if(!server_key || !SSL_CTX_use_PrivateKey_file(ssl_ctx, server_key, SSL_FILETYPE_PEM)) {
211
                JANUS_LOG(LOG_FATAL, "Certificate key error (%s)\n", ERR_reason_error_string(ERR_get_error()));
212
                return -3;
213
        }
214
        if(!SSL_CTX_check_private_key(ssl_ctx)) {
215
                JANUS_LOG(LOG_FATAL, "Certificate check error (%s)\n", ERR_reason_error_string(ERR_get_error()));
216
                return -4;
217
        }
218
        SSL_CTX_set_read_ahead(ssl_ctx,1);
219
        BIO *certbio = BIO_new(BIO_s_file());
220
        if(certbio == NULL) {
221
                JANUS_LOG(LOG_FATAL, "Certificate BIO error...\n");
222
                return -5;
223
        }
224
        if(BIO_read_filename(certbio, server_pem) == 0) {
225
                JANUS_LOG(LOG_FATAL, "Error reading certificate (%s)\n", ERR_reason_error_string(ERR_get_error()));
226
                BIO_free_all(certbio);
227
                return -6;
228
        }
229
        X509 *cert = PEM_read_bio_X509(certbio, NULL, 0, NULL);
230
        if(cert == NULL) {
231
                JANUS_LOG(LOG_FATAL, "Error reading certificate (%s)\n", ERR_reason_error_string(ERR_get_error()));
232
                BIO_free_all(certbio);
233
                return -7;
234
        }
235
        unsigned int size;
236
        unsigned char fingerprint[EVP_MAX_MD_SIZE];
237
        if(X509_digest(cert, EVP_sha256(), (unsigned char *)fingerprint, &size) == 0) {
238
                JANUS_LOG(LOG_FATAL, "Error converting X509 structure (%s)\n", ERR_reason_error_string(ERR_get_error()));
239
                X509_free(cert);
240
                BIO_free_all(certbio);
241
                return -7;
242
        }
243
        char *lfp = (char *)&local_fingerprint;
244
        unsigned int i = 0;
245
        for(i = 0; i < size; i++) {
246
                g_snprintf(lfp, 4, "%.2X:", fingerprint[i]);
247
                lfp += 3;
248
        }
249
        *(lfp-1) = 0;
250
        JANUS_LOG(LOG_INFO, "Fingerprint of our certificate: %s\n", local_fingerprint);
251
        X509_free(cert);
252
        BIO_free_all(certbio);
253
        SSL_CTX_set_cipher_list(ssl_ctx, DTLS_CIPHERS);
254

    
255
        /* Initialize libsrtp */
256
        if(srtp_init() != err_status_ok) {
257
                JANUS_LOG(LOG_FATAL, "Ops, error setting up libsrtp?\n");
258
                return 5;
259
        }
260
        return 0;
261
}
262

    
263

    
264
janus_dtls_srtp *janus_dtls_srtp_create(void *ice_component, janus_dtls_role role) {
265
        janus_ice_component *component = (janus_ice_component *)ice_component;
266
        if(component == NULL) {
267
                JANUS_LOG(LOG_ERR, "No component, no DTLS...\n");
268
                return NULL;
269
        }
270
        janus_ice_stream *stream = component->stream;
271
        if(!stream) {
272
                JANUS_LOG(LOG_ERR, "No stream, no DTLS...\n");
273
                return NULL;
274
        }
275
        janus_ice_handle *handle = stream->handle;
276
        if(!handle || !handle->agent) {
277
                JANUS_LOG(LOG_ERR, "No handle/agent, no DTLS...\n");
278
                return NULL;
279
        }
280
        janus_dtls_srtp *dtls = g_malloc0(sizeof(janus_dtls_srtp));
281
        if(dtls == NULL) {
282
                JANUS_LOG(LOG_FATAL, "Memory error!\n");
283
                return NULL;
284
        }
285
        /* Create SSL context, at last */
286
        dtls->srtp_valid = 0;
287
        dtls->ssl = SSL_new(janus_dtls_get_ssl_ctx());
288
        if(!dtls->ssl) {
289
                JANUS_LOG(LOG_ERR, "[%"SCNu64"]     Error creating DTLS session! (%s)\n",
290
                        handle->handle_id, ERR_reason_error_string(ERR_get_error()));
291
                janus_dtls_srtp_destroy(dtls);
292
                return NULL;
293
        }
294
        SSL_set_ex_data(dtls->ssl, 0, dtls);
295
        SSL_set_info_callback(dtls->ssl, janus_dtls_callback);
296
        dtls->read_bio = BIO_new(BIO_s_mem());
297
        if(!dtls->read_bio) {
298
                JANUS_LOG(LOG_ERR, "[%"SCNu64"]   Error creating read BIO! (%s)\n",
299
                        handle->handle_id, ERR_reason_error_string(ERR_get_error()));
300
                janus_dtls_srtp_destroy(dtls);
301
                return NULL;
302
        }
303
        BIO_set_mem_eof_return(dtls->read_bio, -1);
304
        dtls->write_bio = BIO_new(BIO_s_mem());
305
        if(!dtls->write_bio) {
306
                JANUS_LOG(LOG_ERR, "[%"SCNu64"]   Error creating write BIO! (%s)\n",
307
                        handle->handle_id, ERR_reason_error_string(ERR_get_error()));
308
                janus_dtls_srtp_destroy(dtls);
309
                return NULL;
310
        }
311
        BIO_set_mem_eof_return(dtls->write_bio, -1);
312
        /* The write BIO needs our custom filter, or fragmentation won't work */
313
        dtls->filter_bio = BIO_new(BIO_janus_dtls_filter());
314
        if(!dtls->filter_bio) {
315
                JANUS_LOG(LOG_ERR, "[%"SCNu64"]   Error creating filter BIO! (%s)\n",
316
                        handle->handle_id, ERR_reason_error_string(ERR_get_error()));
317
                janus_dtls_srtp_destroy(dtls);
318
                return NULL;
319
        }
320
        /* Chain filter and write BIOs */
321
        BIO_push(dtls->filter_bio, dtls->write_bio);
322
        /* Set the filter as the BIO to use for outgoing data */
323
        SSL_set_bio(dtls->ssl, dtls->read_bio, dtls->filter_bio);
324
        dtls->dtls_role = role;
325
        if(dtls->dtls_role == JANUS_DTLS_ROLE_CLIENT) {
326
                JANUS_LOG(LOG_VERB, "[%"SCNu64"]   Setting connect state (DTLS client)\n", handle->handle_id);
327
                SSL_set_connect_state(dtls->ssl);
328
        } else {
329
                JANUS_LOG(LOG_VERB, "[%"SCNu64"]   Setting accept state (DTLS server)\n", handle->handle_id);
330
                SSL_set_accept_state(dtls->ssl);
331
        }
332
        /* https://code.google.com/p/chromium/issues/detail?id=406458 
333
         * Specify an ECDH group for ECDHE ciphers, otherwise they cannot be
334
         * negotiated when acting as the server. Use NIST's P-256 which is
335
         * commonly supported.
336
         */
337
        EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
338
        if(ecdh == NULL) {
339
                JANUS_LOG(LOG_ERR, "[%"SCNu64"]   Error creating ECDH group! (%s)\n",
340
                        handle->handle_id, ERR_reason_error_string(ERR_get_error()));
341
                janus_dtls_srtp_destroy(dtls);
342
                return NULL;
343
        }
344
        SSL_set_options(dtls->ssl, SSL_OP_SINGLE_ECDH_USE);
345
        SSL_set_tmp_ecdh(dtls->ssl, ecdh);
346
        EC_KEY_free(ecdh);
347
        dtls->ready = 0;
348
#ifdef HAVE_SCTP
349
        dtls->sctp = NULL;
350
#endif
351
        janus_mutex_init(&dtls->srtp_mutex);
352
        /* Done */
353
        dtls->dtls_connected = 0;
354
        dtls->component = component;
355
        return dtls;
356
}
357

    
358
void janus_dtls_srtp_handshake(janus_dtls_srtp *dtls) {
359
        if(dtls == NULL || dtls->ssl == NULL)
360
                return;
361
        if(dtls->dtls_state == JANUS_DTLS_STATE_CREATED)
362
                dtls->dtls_state = JANUS_DTLS_STATE_TRYING;
363
        SSL_do_handshake(dtls->ssl);
364
        janus_dtls_fd_bridge(dtls);
365

    
366
        /* Notify event handlers */
367
        janus_dtls_notify_state_change(dtls);
368
}
369

    
370
void janus_dtls_srtp_incoming_msg(janus_dtls_srtp *dtls, char *buf, uint16_t len) {
371
        if(dtls == NULL) {
372
                JANUS_LOG(LOG_ERR, "No DTLS-SRTP stack, no incoming message...\n");
373
                return;
374
        }
375
        janus_ice_component *component = (janus_ice_component *)dtls->component;
376
        if(component == NULL) {
377
                JANUS_LOG(LOG_ERR, "No component, no DTLS...\n");
378
                return;
379
        }
380
        janus_ice_stream *stream = component->stream;
381
        if(!stream) {
382
                JANUS_LOG(LOG_ERR, "No stream, no DTLS...\n");
383
                return;
384
        }
385
        janus_ice_handle *handle = stream->handle;
386
        if(!handle || !handle->agent) {
387
                JANUS_LOG(LOG_ERR, "No handle/agent, no DTLS...\n");
388
                return;
389
        }
390
        if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_ALERT)) {
391
                JANUS_LOG(LOG_WARN, "[%"SCNu64"] Alert already triggered, clearing up...\n", handle->handle_id);
392
                return;
393
        }
394
        if(!dtls->ssl || !dtls->read_bio) {
395
                JANUS_LOG(LOG_ERR, "[%"SCNu64"] No DTLS stuff for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
396
                return;
397
        }
398
        janus_dtls_fd_bridge(dtls);
399
        int written = BIO_write(dtls->read_bio, buf, len);
400
        if(written != len) {
401
                JANUS_LOG(LOG_WARN, "[%"SCNu64"]     Only written %d/%d of those bytes on the read BIO...\n", handle->handle_id, written, len);
402
        } else {
403
                JANUS_LOG(LOG_HUGE, "[%"SCNu64"]     Written %d bytes on the read BIO...\n", handle->handle_id, written);
404
        }
405
        janus_dtls_fd_bridge(dtls);
406
        /* Try to read data */
407
        char data[1500];        /* FIXME */
408
        memset(&data, 0, 1500);
409
        int read = SSL_read(dtls->ssl, &data, 1500);
410
        JANUS_LOG(LOG_HUGE, "[%"SCNu64"]     ... and read %d of them from SSL...\n", handle->handle_id, read);
411
        if(read < 0) {
412
                unsigned long err = SSL_get_error(dtls->ssl, read);
413
                if(err == SSL_ERROR_SSL) {
414
                        /* Ops, something went wrong with the DTLS handshake */
415
                        char error[200];
416
                        ERR_error_string_n(ERR_get_error(), error, 200);
417
                        JANUS_LOG(LOG_ERR, "[%"SCNu64"] Handshake error: %s\n", handle->handle_id, error);
418
                        return;
419
                }
420
        }
421
        janus_dtls_fd_bridge(dtls);
422
        if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_STOP) || janus_is_stopping()) {
423
                /* DTLS alert triggered, we should end it here */
424
                JANUS_LOG(LOG_VERB, "[%"SCNu64"] Forced to stop it here...\n", handle->handle_id);
425
                return;
426
        }
427
        if(!SSL_is_init_finished(dtls->ssl)) {
428
                /* Nothing else to do for now */
429
                JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Initialization not finished yet...\n", handle->handle_id);
430
                return;
431
        }
432
        if(dtls->ready) {
433
                /* There's data to be read? */
434
                JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Any data available?\n", handle->handle_id);
435
#ifdef HAVE_SCTP
436
                if(dtls->sctp != NULL && read > 0) {
437
                        JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Sending data (%d bytes) to the SCTP stack...\n", handle->handle_id, read);
438
                        janus_sctp_data_from_dtls(dtls->sctp, data, read);
439
                }
440
#else
441
                if(read > 0) {
442
                        JANUS_LOG(LOG_WARN, "[%"SCNu64"] Data available but Data Channels support disabled...\n", handle->handle_id);
443
                }
444
#endif
445
        } else {
446
                JANUS_LOG(LOG_VERB, "[%"SCNu64"] DTLS established, yay!\n", handle->handle_id);
447
                /* Check the remote fingerprint */
448
                X509 *rcert = SSL_get_peer_certificate(dtls->ssl);
449
                if(!rcert) {
450
                        JANUS_LOG(LOG_ERR, "[%"SCNu64"] No remote certificate?? (%s)\n",
451
                                handle->handle_id, ERR_reason_error_string(ERR_get_error()));
452
                } else {
453
                        unsigned int rsize;
454
                        unsigned char rfingerprint[EVP_MAX_MD_SIZE];
455
                        char remote_fingerprint[160];
456
                        char *rfp = (char *)&remote_fingerprint;
457
                        if(stream->remote_hashing && !strcasecmp(stream->remote_hashing, "sha-1")) {
458
                                JANUS_LOG(LOG_VERB, "[%"SCNu64"] Computing sha-1 fingerprint of remote certificate...\n", handle->handle_id);
459
                                X509_digest(rcert, EVP_sha1(), (unsigned char *)rfingerprint, &rsize);
460
                        } else {
461
                                JANUS_LOG(LOG_VERB, "[%"SCNu64"] Computing sha-256 fingerprint of remote certificate...\n", handle->handle_id);
462
                                X509_digest(rcert, EVP_sha256(), (unsigned char *)rfingerprint, &rsize);
463
                        }
464
                        X509_free(rcert);
465
                        rcert = NULL;
466
                        unsigned int i = 0;
467
                        for(i = 0; i < rsize; i++) {
468
                                g_snprintf(rfp, 4, "%.2X:", rfingerprint[i]);
469
                                rfp += 3;
470
                        }
471
                        *(rfp-1) = 0;
472
                        JANUS_LOG(LOG_VERB, "[%"SCNu64"] Remote fingerprint (%s) of the client is %s\n",
473
                                handle->handle_id, stream->remote_hashing ? stream->remote_hashing : "sha-256", remote_fingerprint);
474
                        if(!strcasecmp(remote_fingerprint, stream->remote_fingerprint ? stream->remote_fingerprint : "(none)")) {
475
                                JANUS_LOG(LOG_VERB, "[%"SCNu64"]  Fingerprint is a match!\n", handle->handle_id);
476
                                dtls->dtls_state = JANUS_DTLS_STATE_CONNECTED;
477
                                dtls->dtls_connected = janus_get_monotonic_time();
478
                                /* Notify event handlers */
479
                                janus_dtls_notify_state_change(dtls);
480
                        } else {
481
                                /* FIXME NOT a match! MITM? */
482
                                JANUS_LOG(LOG_ERR, "[%"SCNu64"]  Fingerprint is NOT a match! got %s, expected %s\n", handle->handle_id, remote_fingerprint, stream->remote_fingerprint);
483
                                dtls->dtls_state = JANUS_DTLS_STATE_FAILED;
484
                                /* Notify event handlers */
485
                                janus_dtls_notify_state_change(dtls);
486
                                goto done;
487
                        }
488
                        if(dtls->dtls_state == JANUS_DTLS_STATE_CONNECTED) {
489
                                if(component->stream_id == handle->audio_id || component->stream_id == handle->video_id) {
490
                                        /* Complete with SRTP setup */
491
                                        unsigned char material[SRTP_MASTER_LENGTH*2];
492
                                        unsigned char *local_key, *local_salt, *remote_key, *remote_salt;
493
                                        /* Export keying material for SRTP */
494
                                        if (!SSL_export_keying_material(dtls->ssl, material, SRTP_MASTER_LENGTH*2, "EXTRACTOR-dtls_srtp", 19, NULL, 0, 0)) {
495
                                                /* Oops... */
496
                                                JANUS_LOG(LOG_ERR, "[%"SCNu64"] Oops, couldn't extract SRTP keying material for component %d in stream %d?? (%s)\n",
497
                                                        handle->handle_id, component->component_id, stream->stream_id, ERR_reason_error_string(ERR_get_error()));
498
                                                goto done;
499
                                        }
500
                                        /* Key derivation (http://tools.ietf.org/html/rfc5764#section-4.2) */
501
                                        if(dtls->dtls_role == JANUS_DTLS_ROLE_CLIENT) {
502
                                                local_key = material;
503
                                                remote_key = local_key + SRTP_MASTER_KEY_LENGTH;
504
                                                local_salt = remote_key + SRTP_MASTER_KEY_LENGTH;
505
                                                remote_salt = local_salt + SRTP_MASTER_SALT_LENGTH;
506
                                        } else {
507
                                                remote_key = material;
508
                                                local_key = remote_key + SRTP_MASTER_KEY_LENGTH;
509
                                                remote_salt = local_key + SRTP_MASTER_KEY_LENGTH;
510
                                                local_salt = remote_salt + SRTP_MASTER_SALT_LENGTH;
511
                                        }
512
                                        /* Build master keys and set SRTP policies */
513
                                                /* Remote (inbound) */
514
                                        crypto_policy_set_rtp_default(&(dtls->remote_policy.rtp));
515
                                        crypto_policy_set_rtcp_default(&(dtls->remote_policy.rtcp));
516
                                        dtls->remote_policy.ssrc.type = ssrc_any_inbound;
517
                                        unsigned char remote_policy_key[SRTP_MASTER_LENGTH];
518
                                        dtls->remote_policy.key = (unsigned char *)&remote_policy_key;
519
                                        memcpy(dtls->remote_policy.key, remote_key, SRTP_MASTER_KEY_LENGTH);
520
                                        memcpy(dtls->remote_policy.key + SRTP_MASTER_KEY_LENGTH, remote_salt, SRTP_MASTER_SALT_LENGTH);
521
#if HAS_DTLS_WINDOW_SIZE
522
                                        dtls->remote_policy.window_size = 128;
523
                                        dtls->remote_policy.allow_repeat_tx = 0;
524
#endif
525
                                        dtls->remote_policy.next = NULL;
526
                                                /* Local (outbound) */
527
                                        crypto_policy_set_rtp_default(&(dtls->local_policy.rtp));
528
                                        crypto_policy_set_rtcp_default(&(dtls->local_policy.rtcp));
529
                                        dtls->local_policy.ssrc.type = ssrc_any_outbound;
530
                                        unsigned char local_policy_key[SRTP_MASTER_LENGTH];
531
                                        dtls->local_policy.key = (unsigned char *)&local_policy_key;
532
                                        memcpy(dtls->local_policy.key, local_key, SRTP_MASTER_KEY_LENGTH);
533
                                        memcpy(dtls->local_policy.key + SRTP_MASTER_KEY_LENGTH, local_salt, SRTP_MASTER_SALT_LENGTH);
534
#if HAS_DTLS_WINDOW_SIZE
535
                                        dtls->local_policy.window_size = 128;
536
                                        dtls->local_policy.allow_repeat_tx = 0;
537
#endif
538
                                        dtls->local_policy.next = NULL;
539
                                        /* Create SRTP sessions */
540
                                        err_status_t res = srtp_create(&(dtls->srtp_in), &(dtls->remote_policy));
541
                                        if(res != err_status_ok) {
542
                                                /* Something went wrong... */
543
                                                JANUS_LOG(LOG_ERR, "[%"SCNu64"] Oops, error creating inbound SRTP session for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
544
                                                JANUS_LOG(LOG_ERR, "[%"SCNu64"]  -- %d (%s)\n", handle->handle_id, res, janus_get_srtp_error(res));
545
                                                goto done;
546
                                        }
547
                                        JANUS_LOG(LOG_VERB, "[%"SCNu64"] Created inbound SRTP session for component %d in stream %d\n", handle->handle_id, component->component_id, stream->stream_id);
548
                                        res = srtp_create(&(dtls->srtp_out), &(dtls->local_policy));
549
                                        if(res != err_status_ok) {
550
                                                /* Something went wrong... */
551
                                                JANUS_LOG(LOG_ERR, "[%"SCNu64"] Oops, error creating outbound SRTP session for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
552
                                                JANUS_LOG(LOG_ERR, "[%"SCNu64"]  -- %d (%s)\n", handle->handle_id, res, janus_get_srtp_error(res));
553
                                                goto done;
554
                                        }
555
                                        dtls->srtp_valid = 1;
556
                                        JANUS_LOG(LOG_VERB, "[%"SCNu64"] Created outbound SRTP session for component %d in stream %d\n", handle->handle_id, component->component_id, stream->stream_id);
557
                                }
558
#ifdef HAVE_SCTP
559
                                if(component->stream_id == handle->data_id ||
560
                                                (janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_BUNDLE) &&
561
                                                janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_DATA_CHANNELS))) {
562
                                        /* FIXME Create SCTP association as well (5000 should be dynamic, from the SDP...) */
563
                                        dtls->sctp = janus_sctp_association_create(dtls, handle->handle_id, 5000);
564
                                        if(dtls->sctp != NULL) {
565
                                                /* FIXME We need to start it in a thread, though, since it has blocking accept/connect stuff */
566
                                                GError *error = NULL;
567
                                                g_thread_try_new("DTLS-SCTP", janus_dtls_sctp_setup_thread, dtls, &error);
568
                                                if(error != NULL) {
569
                                                        /* Something went wrong... */
570
                                                        JANUS_LOG(LOG_ERR, "[%"SCNu64"] Got error %d (%s) trying to launch the DTLS-SCTP thread...\n", handle->handle_id, error->code, error->message ? error->message : "??");
571
                                                }
572
                                                dtls->srtp_valid = 1;
573
                                        }
574
                                }
575
#endif
576
                                dtls->ready = 1;
577
                        }
578
done:
579
                        if(!janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_ALERT) && dtls->srtp_valid) {
580
                                /* Handshake successfully completed */
581
                                janus_ice_dtls_handshake_done(handle, component);
582
                        } else {
583
                                /* Something went wrong in either DTLS or SRTP... tell the plugin about it */
584
                                janus_dtls_callback(dtls->ssl, SSL_CB_ALERT, 0);
585
                                janus_flags_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_CLEANING);
586
                        }
587
                }
588
        }
589
}
590

    
591
void janus_dtls_srtp_send_alert(janus_dtls_srtp *dtls) {
592
        /* Send alert */
593
        if(dtls != NULL && dtls->ssl != NULL) {
594
                SSL_shutdown(dtls->ssl);
595
                janus_dtls_fd_bridge(dtls);
596
        }
597
}
598

    
599
void janus_dtls_srtp_destroy(janus_dtls_srtp *dtls) {
600
        if(dtls == NULL)
601
                return;
602
        dtls->ready = 0;
603
#ifdef HAVE_SCTP
604
        /* Destroy the SCTP association if this is a DataChannel */
605
        if(dtls->sctp != NULL) {
606
                janus_sctp_association_destroy(dtls->sctp);
607
                dtls->sctp = NULL;
608
        }
609
#endif
610
        /* Destroy DTLS stack and free resources */
611
        dtls->component = NULL;
612
        if(dtls->ssl != NULL) {
613
                SSL_free(dtls->ssl);
614
                dtls->ssl = NULL;
615
        }
616
        /* BIOs are destroyed by SSL_free */
617
        dtls->read_bio = NULL;
618
        dtls->write_bio = NULL;
619
        dtls->filter_bio = NULL;
620
        if(dtls->srtp_valid) {
621
                if(dtls->srtp_in) {
622
                        srtp_dealloc(dtls->srtp_in);
623
                        dtls->srtp_in = NULL;
624
                }
625
                if(dtls->srtp_out) {
626
                        srtp_dealloc(dtls->srtp_out);
627
                        dtls->srtp_out = NULL;
628
                }
629
                /* FIXME What about dtls->remote_policy and dtls->local_policy? */
630
        }
631
        g_free(dtls);
632
        dtls = NULL;
633
}
634

    
635
/* DTLS alert callback */
636
void janus_dtls_callback(const SSL *ssl, int where, int ret) {
637
        /* We only care about alerts */
638
        if (!(where & SSL_CB_ALERT)) {
639
                return;
640
        }
641
        janus_dtls_srtp *dtls = SSL_get_ex_data(ssl, 0);
642
        if(!dtls) {
643
                JANUS_LOG(LOG_ERR, "No DTLS session related to this alert...\n");
644
                return;
645
        }
646
        janus_ice_component *component = dtls->component;
647
        if(component == NULL) {
648
                JANUS_LOG(LOG_ERR, "No ICE component related to this alert...\n");
649
                return;
650
        }
651
        janus_ice_stream *stream = component->stream;
652
        if(!stream) {
653
                JANUS_LOG(LOG_ERR, "No ICE stream related to this alert...\n");
654
                return;
655
        }
656
        janus_ice_handle *handle = stream->handle;
657
        if(!handle) {
658
                JANUS_LOG(LOG_ERR, "No ICE handle related to this alert...\n");
659
                return;
660
        }
661
        if(stream->stream_id == handle->data_id) {
662
                /* FIXME BADLY We got a DTLS alert on the Data channel, we ignore it for now */
663
                JANUS_LOG(LOG_WARN, "[%"SCNu64"] DTLS alert triggered on stream %"SCNu16", but it's the data channel so we don't care...\n", handle->handle_id, stream->stream_id);
664
                return;
665
        }
666
        JANUS_LOG(LOG_VERB, "[%"SCNu64"] DTLS alert triggered on stream %"SCNu16" (component %"SCNu16"), closing...\n", handle->handle_id, stream->stream_id, component->component_id);
667
        janus_flags_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_CLEANING);
668
        if(!janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_ALERT)) {
669
                janus_flags_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_ALERT);
670
                if(handle->iceloop)
671
                        g_main_loop_quit(handle->iceloop);
672
                janus_plugin *plugin = (janus_plugin *)handle->app;
673
                if(plugin != NULL) {
674
                        JANUS_LOG(LOG_VERB, "[%"SCNu64"] Telling the plugin about it (%s)\n", handle->handle_id, plugin->get_name());
675
                        if(plugin && plugin->hangup_media)
676
                                plugin->hangup_media(handle->app_handle);
677
                        janus_ice_notify_hangup(handle, "DTLS alert");
678
                }
679
        }
680
}
681

    
682
/* DTLS certificate verification callback */
683
int janus_dtls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
684
        /* We just use the verify_callback to request a certificate from the client */
685
        return 1;
686
}
687

    
688
/* DTLS BIOs to/from socket bridge */
689
void janus_dtls_fd_bridge(janus_dtls_srtp *dtls) {
690
        if(dtls == NULL) {
691
                JANUS_LOG(LOG_ERR, "No DTLS-SRTP stack, no DTLS bridge...\n");
692
                return;
693
        }
694
        janus_ice_component *component = (janus_ice_component *)dtls->component;
695
        if(component == NULL) {
696
                JANUS_LOG(LOG_ERR, "No component, no DTLS bridge...\n");
697
                return;
698
        }
699
        janus_ice_stream *stream = component->stream;
700
        if(!stream) {
701
                JANUS_LOG(LOG_ERR, "No stream, no DTLS bridge...\n");
702
                return;
703
        }
704
        janus_ice_handle *handle = stream->handle;
705
        if(!handle || !handle->agent || !dtls->write_bio) {
706
                JANUS_LOG(LOG_ERR, "No handle/agent/bio, no DTLS bridge...\n");
707
                return;
708
        }
709
        int pending = BIO_ctrl_pending(dtls->filter_bio);
710
        while(pending > 0) {
711
                JANUS_LOG(LOG_HUGE, "[%"SCNu64"] >> Going to send DTLS data: %d bytes\n", handle->handle_id, pending);
712
                char outgoing[pending];
713
                int out = BIO_read(dtls->write_bio, outgoing, sizeof(outgoing));
714
                JANUS_LOG(LOG_HUGE, "[%"SCNu64"] >> >> Read %d bytes from the write_BIO...\n", handle->handle_id, out);
715
                if(out > 1500) {
716
                        /* FIXME Just a warning for now, this will need to be solved with proper fragmentation */
717
                        JANUS_LOG(LOG_WARN, "[%"SCNu64"] The DTLS stack is trying to send a packet of %d bytes, this may be larger than the MTU and get dropped!\n", handle->handle_id, out);
718
                }
719
                int bytes = nice_agent_send(handle->agent, component->stream_id, component->component_id, out, outgoing);
720
                if(bytes < out) {
721
                        JANUS_LOG(LOG_ERR, "[%"SCNu64"] Error sending DTLS message on component %d of stream %d (%d)\n", handle->handle_id, component->component_id, stream->stream_id, bytes);
722
                } else {
723
                        JANUS_LOG(LOG_HUGE, "[%"SCNu64"] >> >> ... and sent %d of those bytes on the socket\n", handle->handle_id, bytes);
724
                }
725
                /* Update stats (TODO Do the same for the last second window as well)
726
                 * FIXME: the Data stats includes the bytes used for the handshake */
727
                if(bytes > 0) {
728
                        component->out_stats.data_packets++;
729
                        component->out_stats.data_bytes += bytes;
730
                }
731
                /* Check if there's anything left to send (e.g., fragmented packets) */
732
                pending = BIO_ctrl_pending(dtls->filter_bio);
733
        }
734
}
735

    
736
#ifdef HAVE_SCTP
737
void janus_dtls_wrap_sctp_data(janus_dtls_srtp *dtls, char *buf, int len) {
738
        if(dtls == NULL || !dtls->ready || dtls->sctp == NULL || buf == NULL || len < 1)
739
                return;
740
        janus_sctp_send_data(dtls->sctp, buf, len);
741
}
742

    
743
int janus_dtls_send_sctp_data(janus_dtls_srtp *dtls, char *buf, int len) {
744
        if(dtls == NULL || !dtls->ready || buf == NULL || len < 1)
745
                return -1;
746
        int res = SSL_write(dtls->ssl, buf, len);
747
        if(res <= 0) {
748
                unsigned long err = SSL_get_error(dtls->ssl, res);
749
                JANUS_LOG(LOG_ERR, "Error sending data: %s\n", ERR_reason_error_string(err));
750
        } else {
751
                janus_dtls_fd_bridge(dtls);
752
        }
753
        return res;
754
}
755

    
756
void janus_dtls_notify_data(janus_dtls_srtp *dtls, char *buf, int len) {
757
        if(dtls == NULL || buf == NULL || len < 1)
758
                return;
759
        janus_ice_component *component = (janus_ice_component *)dtls->component;
760
        if(component == NULL) {
761
                JANUS_LOG(LOG_ERR, "No component...\n");
762
                return;
763
        }
764
        janus_ice_stream *stream = component->stream;
765
        if(!stream) {
766
                JANUS_LOG(LOG_ERR, "No stream...\n");
767
                return;
768
        }
769
        janus_ice_handle *handle = stream->handle;
770
        if(!handle || !handle->agent || !dtls->write_bio) {
771
                JANUS_LOG(LOG_ERR, "No handle...\n");
772
                return;
773
        }
774
        janus_ice_incoming_data(handle, buf, len);
775
}
776
#endif
777

    
778
gboolean janus_dtls_retry(gpointer stack) {
779
        janus_dtls_srtp *dtls = (janus_dtls_srtp *)stack;
780
        if(dtls == NULL)
781
                return FALSE;
782
        janus_ice_component *component = (janus_ice_component *)dtls->component;
783
        if(component == NULL)
784
                return FALSE;
785
        janus_ice_stream *stream = component->stream;
786
        if(!stream)
787
                return FALSE;
788
        janus_ice_handle *handle = stream->handle;
789
        if(!handle)
790
                return FALSE;
791
        if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_STOP))
792
                return FALSE;
793
        if(dtls->dtls_state == JANUS_DTLS_STATE_CONNECTED) {
794
                JANUS_LOG(LOG_VERB, "[%"SCNu64"]  DTLS already set up, disabling retransmission timer!\n", handle->handle_id);
795
                if(component->source != NULL) {
796
                        g_source_destroy(component->source);
797
                        g_source_unref(component->source);
798
                        component->source = NULL;
799
                }
800
                return FALSE;
801
        }
802
        struct timeval timeout = {0};
803
        DTLSv1_get_timeout(dtls->ssl, &timeout);
804
        guint64 timeout_value = timeout.tv_sec*1000 + timeout.tv_usec/1000;
805
        JANUS_LOG(LOG_HUGE, "[%"SCNu64"] DTLSv1_get_timeout: %"SCNu64"\n", handle->handle_id, timeout_value);
806
        if(timeout_value == 0) {
807
                JANUS_LOG(LOG_VERB, "[%"SCNu64"] DTLS timeout on component %d of stream %d, retransmitting\n", handle->handle_id, component->component_id, stream->stream_id);
808
                DTLSv1_handle_timeout(dtls->ssl);
809
                janus_dtls_fd_bridge(dtls);
810
        }
811
        return TRUE;
812
}
813

    
814

    
815
#ifdef HAVE_SCTP
816
/* Helper thread to create a SCTP association that will use this DTLS stack */
817
void *janus_dtls_sctp_setup_thread(void *data) {
818
        if(data == NULL) {
819
                JANUS_LOG(LOG_ERR, "No DTLS stack??\n");
820
                g_thread_unref(g_thread_self());
821
                return NULL;
822
        }
823
        janus_dtls_srtp *dtls = (janus_dtls_srtp *)data;
824
        if(dtls->sctp == NULL) {
825
                JANUS_LOG(LOG_ERR, "No SCTP stack??\n");
826
                g_thread_unref(g_thread_self());
827
                return NULL;
828
        }
829
        janus_sctp_association *sctp = (janus_sctp_association *)dtls->sctp;
830
        /* Do the accept/connect stuff now */
831
        JANUS_LOG(LOG_VERB, "[%"SCNu64"] Started thread: setup of the SCTP association\n", sctp->handle_id);
832
        janus_sctp_association_setup(sctp);
833
        g_thread_unref(g_thread_self());
834
        return NULL;
835
}
836
#endif