1 /* $Id$ */
2 /*
3 * Copyright (C) 2018-2018 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2014-2017 Savoir-faire Linux.
5 * (https://www.savoirfairelinux.com)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include <pj/ssl_sock.h>
23 #include <pj/activesock.h>
24 #include <pj/compat/socket.h>
25 #include <pj/assert.h>
26 #include <pj/errno.h>
27 #include <pj/list.h>
28 #include <pj/lock.h>
29 #include <pj/log.h>
30 #include <pj/math.h>
31 #include <pj/os.h>
32 #include <pj/pool.h>
33 #include <pj/string.h>
34 #include <pj/timer.h>
35 #include <pj/file_io.h>
36
37 #if GNUTLS_VERSION_NUMBER < 0x030306 && !defined(_MSC_VER)
38 # include <dirent.h>
39 #endif
40
41 #include <errno.h>
42
43 /* Only build when PJ_HAS_SSL_SOCK and the implementation is GnuTLS. */
44 #if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0 && \
45 (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_GNUTLS)
46
47 #define SSL_SOCK_IMP_USE_CIRC_BUF
48
49 #include "ssl_sock_imp_common.h"
50 #include "ssl_sock_imp_common.c"
51
52 #define THIS_FILE "ssl_sock_gtls.c"
53
54 /* Maximum ciphers */
55 #define MAX_CIPHERS 100
56
57 /* Standard trust locations */
58 #define TRUST_STORE_FILE1 "/etc/ssl/certs/ca-certificates.crt"
59 #define TRUST_STORE_FILE2 "/etc/ssl/certs/ca-bundle.crt"
60
61 /* Debugging output level for GnuTLS only */
62 #define GNUTLS_LOG_LEVEL 0
63
64 /* GnuTLS includes */
65 #include <gnutls/gnutls.h>
66 #include <gnutls/x509.h>
67 #include <gnutls/abstract.h>
68
69 #ifdef _MSC_VER
70 # pragma comment( lib, "libgnutls")
71 #endif
72
73
74 /* Secure socket structure definition. */
75 typedef struct gnutls_sock_t {
76 pj_ssl_sock_t base;
77
78 gnutls_session_t session;
79 gnutls_certificate_credentials_t xcred;
80
81 int tls_init_count; /* library initialization counter */
82 } gnutls_sock_t;
83
84 /* Last error reported somehow */
85 static int tls_last_error;
86
87
88 /*
89 *******************************************************************
90 * Static/internal functions.
91 *******************************************************************
92 */
93
94 /* Convert from GnuTLS error to pj_status_t. */
tls_status_from_err(pj_ssl_sock_t * ssock,int err)95 static pj_status_t tls_status_from_err(pj_ssl_sock_t *ssock, int err)
96 {
97 pj_status_t status;
98
99 switch (err) {
100 case GNUTLS_E_SUCCESS:
101 status = PJ_SUCCESS;
102 break;
103 case GNUTLS_E_MEMORY_ERROR:
104 status = PJ_ENOMEM;
105 break;
106 case GNUTLS_E_LARGE_PACKET:
107 status = PJ_ETOOBIG;
108 break;
109 case GNUTLS_E_NO_CERTIFICATE_FOUND:
110 status = PJ_ENOTFOUND;
111 break;
112 case GNUTLS_E_SESSION_EOF:
113 status = PJ_EEOF;
114 break;
115 case GNUTLS_E_HANDSHAKE_TOO_LARGE:
116 status = PJ_ETOOBIG;
117 break;
118 case GNUTLS_E_EXPIRED:
119 status = PJ_EGONE;
120 break;
121 case GNUTLS_E_TIMEDOUT:
122 status = PJ_ETIMEDOUT;
123 break;
124 case GNUTLS_E_PREMATURE_TERMINATION:
125 status = PJ_ECANCELLED;
126 break;
127 case GNUTLS_E_INTERNAL_ERROR:
128 case GNUTLS_E_UNIMPLEMENTED_FEATURE:
129 status = PJ_EBUG;
130 break;
131 case GNUTLS_E_AGAIN:
132 case GNUTLS_E_INTERRUPTED:
133 case GNUTLS_E_REHANDSHAKE:
134 status = PJ_EPENDING;
135 break;
136 case GNUTLS_E_TOO_MANY_EMPTY_PACKETS:
137 case GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS:
138 case GNUTLS_E_RECORD_LIMIT_REACHED:
139 status = PJ_ETOOMANY;
140 break;
141 case GNUTLS_E_UNSUPPORTED_VERSION_PACKET:
142 case GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM:
143 case GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE:
144 case GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE:
145 case GNUTLS_E_X509_UNSUPPORTED_EXTENSION:
146 case GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION:
147 status = PJ_ENOTSUP;
148 break;
149 case GNUTLS_E_INVALID_SESSION:
150 case GNUTLS_E_INVALID_REQUEST:
151 case GNUTLS_E_INVALID_PASSWORD:
152 case GNUTLS_E_ILLEGAL_PARAMETER:
153 case GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION:
154 case GNUTLS_E_UNEXPECTED_PACKET:
155 case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
156 case GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET:
157 case GNUTLS_E_UNWANTED_ALGORITHM:
158 case GNUTLS_E_USER_ERROR:
159 status = PJ_EINVAL;
160 break;
161 default:
162 status = PJ_EUNKNOWN;
163 break;
164 }
165
166 /* Not thread safe */
167 tls_last_error = err;
168 if (ssock)
169 ssock->last_err = err;
170 return status;
171 }
172
173
174 /* Get error string from GnuTLS using tls_last_error */
tls_strerror(pj_status_t status,char * buf,pj_size_t bufsize)175 static pj_str_t tls_strerror(pj_status_t status,
176 char *buf, pj_size_t bufsize)
177 {
178 pj_str_t errstr;
179 const char *tmp = gnutls_strerror(tls_last_error);
180
181 #if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0)
182 if (tmp) {
183 pj_ansi_strncpy(buf, tmp, bufsize);
184 errstr = pj_str(buf);
185 return errstr;
186 }
187 #endif /* PJ_HAS_ERROR_STRING */
188
189 errstr.ptr = buf;
190 errstr.slen = pj_ansi_snprintf(buf, bufsize, "GnuTLS error %d: %s",
191 tls_last_error, tmp);
192 if (errstr.slen < 1 || errstr.slen >= (int) bufsize)
193 errstr.slen = bufsize - 1;
194
195 return errstr;
196 }
197
198
199 /* GnuTLS way of reporting internal operations. */
tls_print_logs(int level,const char * msg)200 static void tls_print_logs(int level, const char* msg)
201 {
202 PJ_LOG(3, (THIS_FILE, "GnuTLS [%d]: %s", level, msg));
203 }
204
205
206 /* Initialize GnuTLS. */
tls_init(void)207 static pj_status_t tls_init(void)
208 {
209 /* Register error subsystem */
210 pj_status_t status = pj_register_strerror(PJ_ERRNO_START_USER +
211 PJ_ERRNO_SPACE_SIZE * 6,
212 PJ_ERRNO_SPACE_SIZE,
213 &tls_strerror);
214 pj_assert(status == PJ_SUCCESS);
215
216 /* Init GnuTLS library */
217 int ret = gnutls_global_init();
218 if (ret < 0)
219 return tls_status_from_err(NULL, ret);
220
221 gnutls_global_set_log_level(GNUTLS_LOG_LEVEL);
222 gnutls_global_set_log_function(tls_print_logs);
223
224 /* Init available ciphers */
225 if (!ssl_cipher_num) {
226 unsigned int i;
227
228 for (i = 0; i<PJ_ARRAY_SIZE(ssl_ciphers); i++) {
229 unsigned char id[2];
230 const char *suite;
231
232 suite = gnutls_cipher_suite_info(i, (unsigned char *)id,
233 NULL, NULL, NULL, NULL);
234 ssl_ciphers[i].id = 0;
235 /* usually the array size is bigger than the number of available
236 * ciphers anyway, so by checking here we can exit the loop as soon
237 * as either all ciphers have been added or the array is full */
238 if (suite) {
239 ssl_ciphers[i].id = (pj_ssl_cipher)
240 (pj_uint32_t) ((id[0] << 8) | id[1]);
241 ssl_ciphers[i].name = suite;
242 } else
243 break;
244 }
245
246 ssl_cipher_num = i;
247 }
248
249 return PJ_SUCCESS;
250 }
251
252
253 /* Shutdown GnuTLS */
tls_deinit(void)254 static void tls_deinit(void)
255 {
256 gnutls_global_deinit();
257 }
258
259
260 /* Callback invoked every time a certificate has to be validated. */
tls_cert_verify_cb(gnutls_session_t session)261 static int tls_cert_verify_cb(gnutls_session_t session)
262 {
263 pj_ssl_sock_t *ssock;
264 unsigned int status;
265 int ret;
266
267 /* Get SSL socket instance */
268 ssock = (pj_ssl_sock_t *)gnutls_session_get_ptr(session);
269 pj_assert(ssock);
270
271 /* Support only x509 format */
272 ret = gnutls_certificate_type_get(session) != GNUTLS_CRT_X509;
273 if (ret < 0) {
274 ssock->verify_status |= PJ_SSL_CERT_EINVALID_FORMAT;
275 return GNUTLS_E_CERTIFICATE_ERROR;
276 }
277
278 /* Store verification status */
279 ret = gnutls_certificate_verify_peers2(session, &status);
280 if (ret < 0) {
281 ssock->verify_status |= PJ_SSL_CERT_EUNKNOWN;
282 return GNUTLS_E_CERTIFICATE_ERROR;
283 }
284 if (ssock->param.verify_peer) {
285 if (status & GNUTLS_CERT_INVALID) {
286 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
287 ssock->verify_status |= PJ_SSL_CERT_EISSUER_NOT_FOUND;
288 else if (status & GNUTLS_CERT_EXPIRED ||
289 status & GNUTLS_CERT_NOT_ACTIVATED)
290 ssock->verify_status |= PJ_SSL_CERT_EVALIDITY_PERIOD;
291 else if (status & GNUTLS_CERT_SIGNER_NOT_CA ||
292 status & GNUTLS_CERT_INSECURE_ALGORITHM)
293 ssock->verify_status |= PJ_SSL_CERT_EUNTRUSTED;
294 else if (status & GNUTLS_CERT_UNEXPECTED_OWNER ||
295 status & GNUTLS_CERT_MISMATCH)
296 ssock->verify_status |= PJ_SSL_CERT_EISSUER_MISMATCH;
297 else if (status & GNUTLS_CERT_REVOKED)
298 ssock->verify_status |= PJ_SSL_CERT_EREVOKED;
299 else
300 ssock->verify_status |= PJ_SSL_CERT_EUNKNOWN;
301
302 return GNUTLS_E_CERTIFICATE_ERROR;
303 }
304
305 /* When verification is not requested just return ok here, however
306 * applications can still get the verification status. */
307 gnutls_x509_crt_t cert;
308 unsigned int cert_list_size;
309 const gnutls_datum_t *cert_list;
310 int ret;
311
312 ret = gnutls_x509_crt_init(&cert);
313 if (ret < 0)
314 goto out;
315
316 cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
317 if (cert_list == NULL) {
318 ret = GNUTLS_E_NO_CERTIFICATE_FOUND;
319 goto out;
320 }
321
322 /* TODO: verify whole chain perhaps? */
323 ret = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
324 if (ret < 0)
325 ret = gnutls_x509_crt_import(cert, &cert_list[0],
326 GNUTLS_X509_FMT_PEM);
327 if (ret < 0) {
328 ssock->verify_status |= PJ_SSL_CERT_EINVALID_FORMAT;
329 goto out;
330 }
331 ret = gnutls_x509_crt_check_hostname(cert,
332 ssock->param.server_name.ptr);
333 if (ret < 0)
334 goto out;
335
336 gnutls_x509_crt_deinit(cert);
337
338 /* notify GnuTLS to continue handshake normally */
339 return GNUTLS_E_SUCCESS;
340
341 out:
342 tls_last_error = ret;
343 ssock->verify_status |= PJ_SSL_CERT_EUNKNOWN;
344 return GNUTLS_E_CERTIFICATE_ERROR;
345 }
346
347 return GNUTLS_E_SUCCESS;
348 }
349
350
351 /* gnutls_handshake() and gnutls_record_send() will call this function to
352 * send/write (encrypted) data */
tls_data_push(gnutls_transport_ptr_t ptr,const void * data,size_t len)353 static ssize_t tls_data_push(gnutls_transport_ptr_t ptr,
354 const void *data, size_t len)
355 {
356 pj_ssl_sock_t *ssock = (pj_ssl_sock_t *)ptr;
357 gnutls_sock_t *gssock = (gnutls_sock_t *)ssock;
358
359 pj_lock_acquire(ssock->circ_buf_output_mutex);
360 if (circ_write(&ssock->circ_buf_output, data, len) != PJ_SUCCESS) {
361 pj_lock_release(ssock->circ_buf_output_mutex);
362
363 gnutls_transport_set_errno(gssock->session, ENOMEM);
364 return -1;
365 }
366
367 pj_lock_release(ssock->circ_buf_output_mutex);
368
369 return len;
370 }
371
372
373 /* gnutls_handshake() and gnutls_record_recv() will call this function to
374 * receive/read (encrypted) data */
tls_data_pull(gnutls_transport_ptr_t ptr,void * data,pj_size_t len)375 static ssize_t tls_data_pull(gnutls_transport_ptr_t ptr,
376 void *data, pj_size_t len)
377 {
378 pj_ssl_sock_t *ssock = (pj_ssl_sock_t *)ptr;
379 gnutls_sock_t *gssock = (gnutls_sock_t *)ssock;
380
381 pj_lock_acquire(ssock->circ_buf_input_mutex);
382
383 if (circ_empty(&ssock->circ_buf_input)) {
384 pj_lock_release(ssock->circ_buf_input_mutex);
385
386 /* Data buffers not yet filled */
387 gnutls_transport_set_errno(gssock->session, EAGAIN);
388 return -1;
389 }
390
391 pj_size_t circ_buf_size = circ_size(&ssock->circ_buf_input);
392 pj_size_t read_size = PJ_MIN(circ_buf_size, len);
393
394 circ_read(&ssock->circ_buf_input, data, read_size);
395
396 pj_lock_release(ssock->circ_buf_input_mutex);
397
398 return read_size;
399 }
400
401
402 /* Append a string to the priority string, only once. */
tls_str_append_once(pj_str_t * dst,pj_str_t * src)403 static pj_status_t tls_str_append_once(pj_str_t *dst, pj_str_t *src)
404 {
405 if (pj_strstr(dst, src) == NULL) {
406 /* Check buffer size */
407 if (dst->slen + src->slen + 3 > 1024)
408 return PJ_ETOOMANY;
409
410 pj_strcat2(dst, ":+");
411 pj_strcat(dst, src);
412 }
413 return PJ_SUCCESS;
414 }
415
416
417 /* Generate priority string with user preference order. */
tls_priorities_set(pj_ssl_sock_t * ssock)418 static pj_status_t tls_priorities_set(pj_ssl_sock_t *ssock)
419 {
420 gnutls_sock_t *gssock = (gnutls_sock_t *)ssock;
421 char buf[1024];
422 char priority_buf[256];
423 pj_str_t cipher_list;
424 pj_str_t compression = pj_str("COMP-NULL");
425 pj_str_t server = pj_str(":%SERVER_PRECEDENCE");
426 int i, j, ret;
427 pj_str_t priority;
428 const char *err;
429
430 pj_strset(&cipher_list, buf, 0);
431 pj_strset(&priority, priority_buf, 0);
432
433 /* For each level, enable only the requested protocol */
434 pj_strcat2(&priority, "NORMAL:");
435 if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_2) {
436 pj_strcat2(&priority, "+VERS-TLS1.2:");
437 }
438 if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_1) {
439 pj_strcat2(&priority, "+VERS-TLS1.1:");
440 }
441 if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1) {
442 pj_strcat2(&priority, "+VERS-TLS1.0:");
443 }
444 pj_strcat2(&priority, "-VERS-SSL3.0:");
445 pj_strcat2(&priority, "%LATEST_RECORD_VERSION");
446
447 pj_strcat(&cipher_list, &priority);
448 for (i = 0; i < ssock->param.ciphers_num; i++) {
449 for (j = 0; ; j++) {
450 pj_ssl_cipher c;
451 const char *suite;
452 unsigned char id[2];
453 gnutls_protocol_t proto;
454 gnutls_kx_algorithm_t kx;
455 gnutls_mac_algorithm_t mac;
456 gnutls_cipher_algorithm_t algo;
457
458 suite = gnutls_cipher_suite_info(j, (unsigned char *)id,
459 &kx, &algo, &mac, &proto);
460 if (!suite)
461 break;
462
463 c = (pj_ssl_cipher) (pj_uint32_t) ((id[0] << 8) | id[1]);
464 if (ssock->param.ciphers[i] == c) {
465 char temp[256];
466 pj_str_t cipher_entry;
467
468 /* Protocol version */
469 pj_strset(&cipher_entry, temp, 0);
470 pj_strcat2(&cipher_entry, "VERS-");
471 pj_strcat2(&cipher_entry, gnutls_protocol_get_name(proto));
472 ret = tls_str_append_once(&cipher_list, &cipher_entry);
473 if (ret != PJ_SUCCESS)
474 return ret;
475
476 /* Cipher */
477 pj_strset(&cipher_entry, temp, 0);
478 pj_strcat2(&cipher_entry, gnutls_cipher_get_name(algo));
479 ret = tls_str_append_once(&cipher_list, &cipher_entry);
480 if (ret != PJ_SUCCESS)
481 return ret;
482
483 /* Mac */
484 pj_strset(&cipher_entry, temp, 0);
485 pj_strcat2(&cipher_entry, gnutls_mac_get_name(mac));
486 ret = tls_str_append_once(&cipher_list, &cipher_entry);
487 if (ret != PJ_SUCCESS)
488 return ret;
489
490 /* Key exchange */
491 pj_strset(&cipher_entry, temp, 0);
492 pj_strcat2(&cipher_entry, gnutls_kx_get_name(kx));
493 ret = tls_str_append_once(&cipher_list, &cipher_entry);
494 if (ret != PJ_SUCCESS)
495 return ret;
496
497 /* Compression is always disabled */
498 /* Signature is level-default */
499 break;
500 }
501 }
502 }
503
504 /* Disable compression, it's a TLS-only extension after all */
505 tls_str_append_once(&cipher_list, &compression);
506
507 /* Server will be the one deciding which crypto to use */
508 if (ssock->is_server) {
509 if (cipher_list.slen + server.slen + 1 > sizeof(buf))
510 return PJ_ETOOMANY;
511 else
512 pj_strcat(&cipher_list, &server);
513 }
514
515 /* End the string and print it */
516 cipher_list.ptr[cipher_list.slen] = '\0';
517 PJ_LOG(5, (ssock->pool->obj_name, "Priority string: %s", cipher_list.ptr));
518
519 /* Set our priority string */
520 ret = gnutls_priority_set_direct(gssock->session,
521 cipher_list.ptr, &err);
522 if (ret < 0) {
523 tls_last_error = GNUTLS_E_INVALID_REQUEST;
524 return PJ_EINVAL;
525 }
526
527 return PJ_SUCCESS;
528 }
529
530
531 /* Load root CA file or load the installed ones. */
tls_trust_set(pj_ssl_sock_t * ssock)532 static pj_status_t tls_trust_set(pj_ssl_sock_t *ssock)
533 {
534 gnutls_sock_t *gssock = (gnutls_sock_t *)ssock;
535 int ntrusts = 0;
536 int err;
537
538 err = gnutls_certificate_set_x509_system_trust(gssock->xcred);
539 if (err > 0)
540 ntrusts += err;
541 err = gnutls_certificate_set_x509_trust_file(gssock->xcred,
542 TRUST_STORE_FILE1,
543 GNUTLS_X509_FMT_PEM);
544 if (err > 0)
545 ntrusts += err;
546
547 err = gnutls_certificate_set_x509_trust_file(gssock->xcred,
548 TRUST_STORE_FILE2,
549 GNUTLS_X509_FMT_PEM);
550 if (err > 0)
551 ntrusts += err;
552
553 if (ntrusts > 0)
554 return PJ_SUCCESS;
555 else if (!ntrusts)
556 return PJ_ENOTFOUND;
557 else
558 return PJ_EINVAL;
559 }
560
561 #if GNUTLS_VERSION_NUMBER < 0x030306
562
563 #ifdef _POSIX_PATH_MAX
564 # define GNUTLS_PATH_MAX _POSIX_PATH_MAX
565 #else
566 # define GNUTLS_PATH_MAX 256
567 #endif
568
gnutls_certificate_set_x509_trust_dir(gnutls_certificate_credentials_t cred,const char * dirname,unsigned type)569 static int gnutls_certificate_set_x509_trust_dir(
570 gnutls_certificate_credentials_t cred,
571 const char *dirname, unsigned type)
572 {
573 DIR *dirp;
574 struct dirent *d;
575 int ret;
576 int r = 0;
577 char path[GNUTLS_PATH_MAX];
578 #ifndef _WIN32
579 struct dirent e;
580 #endif
581
582 dirp = opendir(dirname);
583 if (dirp != NULL) {
584 do {
585 #ifdef _WIN32
586 d = readdir(dirp);
587 if (d != NULL) {
588 #else
589 ret = readdir_r(dirp, &e, &d);
590 if (ret == 0 && d != NULL
591 #ifdef _DIRENT_HAVE_D_TYPE
592 && (d->d_type == DT_REG || d->d_type == DT_LNK ||
593 d->d_type == DT_UNKNOWN)
594 #endif
595 ) {
596 #endif
597 snprintf(path, sizeof(path), "%s/%s",
598 dirname, d->d_name);
599
600 ret = gnutls_certificate_set_x509_trust_file(cred, path, type);
601 if (ret >= 0)
602 r += ret;
603 }
604 } while (d != NULL);
605 closedir(dirp);
606 }
607
608 return r;
609 }
610
611 #endif
612
613 static pj_ssl_sock_t *ssl_alloc(pj_pool_t *pool)
614 {
615 return (pj_ssl_sock_t *)PJ_POOL_ZALLOC_T(pool, gnutls_sock_t);
616 }
617
618 /* Create and initialize new GnuTLS context and instance */
619 static pj_status_t ssl_create(pj_ssl_sock_t *ssock)
620 {
621 gnutls_sock_t *gssock = (gnutls_sock_t *)ssock;
622 pj_ssl_cert_t *cert;
623 pj_status_t status;
624 int ret;
625
626 pj_assert(ssock);
627
628 cert = ssock->cert;
629
630 /* Even if reopening is harmless, having one instance only simplifies
631 * deallocating it later on */
632 if (!gssock->tls_init_count) {
633 gssock->tls_init_count++;
634 ret = tls_init();
635 if (ret < 0)
636 return ret;
637 } else
638 return PJ_SUCCESS;
639
640 /* Start this socket session */
641 ret = gnutls_init(&gssock->session, ssock->is_server ? GNUTLS_SERVER
642 : GNUTLS_CLIENT);
643 if (ret < 0)
644 goto out;
645
646 /* Set the ssock object to be retrieved by transport (send/recv) and by
647 * user data from this session */
648 gnutls_transport_set_ptr(gssock->session,
649 (gnutls_transport_ptr_t) (uintptr_t) ssock);
650 gnutls_session_set_ptr(gssock->session,
651 (gnutls_transport_ptr_t) (uintptr_t) ssock);
652
653 /* Initialize input circular buffer */
654 status = circ_init(ssock->pool->factory, &ssock->circ_buf_input, 512);
655 if (status != PJ_SUCCESS)
656 return status;
657
658 /* Initialize output circular buffer */
659 status = circ_init(ssock->pool->factory, &ssock->circ_buf_output, 512);
660 if (status != PJ_SUCCESS)
661 return status;
662
663 /* Set the callback that allows GnuTLS to PUSH and PULL data
664 * TO and FROM the transport layer */
665 gnutls_transport_set_push_function(gssock->session, tls_data_push);
666 gnutls_transport_set_pull_function(gssock->session, tls_data_pull);
667
668 /* Determine which cipher suite to support */
669 status = tls_priorities_set(ssock);
670 if (status != PJ_SUCCESS)
671 return status;
672
673 /* Allocate credentials for handshaking and transmission */
674 ret = gnutls_certificate_allocate_credentials(&gssock->xcred);
675 if (ret < 0)
676 goto out;
677 gnutls_certificate_set_verify_function(gssock->xcred, tls_cert_verify_cb);
678
679 /* Load system trust file(s) */
680 status = tls_trust_set(ssock);
681 if (status != PJ_SUCCESS)
682 return status;
683
684 /* Load user-provided CA, certificate and key if available */
685 if (cert) {
686 /* Load CA if one is specified. */
687 if (cert->CA_file.slen) {
688 ret = gnutls_certificate_set_x509_trust_file(gssock->xcred,
689 cert->CA_file.ptr,
690 GNUTLS_X509_FMT_PEM);
691 if (ret < 0)
692 ret = gnutls_certificate_set_x509_trust_file(
693 gssock->xcred,
694 cert->CA_file.ptr,
695 GNUTLS_X509_FMT_DER);
696 if (ret < 0)
697 goto out;
698 }
699 if (cert->CA_path.slen) {
700 ret = gnutls_certificate_set_x509_trust_dir(gssock->xcred,
701 cert->CA_path.ptr,
702 GNUTLS_X509_FMT_PEM);
703 if (ret < 0)
704 ret = gnutls_certificate_set_x509_trust_dir(
705 gssock->xcred,
706 cert->CA_path.ptr,
707 GNUTLS_X509_FMT_DER);
708 if (ret < 0)
709 goto out;
710 }
711
712 /* Load certificate, key and pass if one is specified */
713 if (cert->cert_file.slen && cert->privkey_file.slen) {
714 const char *prikey_file = cert->privkey_file.ptr;
715 const char *prikey_pass = cert->privkey_pass.slen
716 ? cert->privkey_pass.ptr
717 : NULL;
718 ret = gnutls_certificate_set_x509_key_file2(gssock->xcred,
719 cert->cert_file.ptr,
720 prikey_file,
721 GNUTLS_X509_FMT_PEM,
722 prikey_pass,
723 0);
724 if (ret != GNUTLS_E_SUCCESS)
725 ret = gnutls_certificate_set_x509_key_file2(gssock->xcred,
726 cert->cert_file.ptr,
727 prikey_file,
728 GNUTLS_X509_FMT_DER,
729 prikey_pass,
730 0);
731 if (ret < 0)
732 goto out;
733 }
734
735 if (cert->CA_buf.slen) {
736 gnutls_datum_t ca;
737 ca.data = (unsigned char*)cert->CA_buf.ptr;
738 ca.size = cert->CA_buf.slen;
739 ret = gnutls_certificate_set_x509_trust_mem(gssock->xcred,
740 &ca,
741 GNUTLS_X509_FMT_PEM);
742 if (ret < 0)
743 ret = gnutls_certificate_set_x509_trust_mem(
744 gssock->xcred, &ca, GNUTLS_X509_FMT_DER);
745 if (ret < 0)
746 goto out;
747 }
748
749 if (cert->cert_buf.slen && cert->privkey_buf.slen) {
750 gnutls_datum_t cert_buf;
751 gnutls_datum_t privkey_buf;
752
753 cert_buf.data = (unsigned char*)cert->CA_buf.ptr;
754 cert_buf.size = cert->CA_buf.slen;
755 privkey_buf.data = (unsigned char*)cert->privkey_buf.ptr;
756 privkey_buf.size = cert->privkey_buf.slen;
757
758 const char *prikey_pass = cert->privkey_pass.slen
759 ? cert->privkey_pass.ptr
760 : NULL;
761 ret = gnutls_certificate_set_x509_key_mem2(gssock->xcred,
762 &cert_buf,
763 &privkey_buf,
764 GNUTLS_X509_FMT_PEM,
765 prikey_pass,
766 0);
767 /* Load DER format */
768 /*
769 if (ret != GNUTLS_E_SUCCESS)
770 ret = gnutls_certificate_set_x509_key_mem2(gssock->xcred,
771 &cert_buf,
772 &privkey_buf,
773 GNUTLS_X509_FMT_DER,
774 prikey_pass,
775 0);
776 */
777 if (ret < 0)
778 goto out;
779 }
780 }
781
782 /* Require client certificate if asked */
783 if (ssock->is_server && ssock->param.require_client_cert)
784 gnutls_certificate_server_set_request(gssock->session,
785 GNUTLS_CERT_REQUIRE);
786
787 /* Finally set credentials for this session */
788 ret = gnutls_credentials_set(gssock->session,
789 GNUTLS_CRD_CERTIFICATE, gssock->xcred);
790 if (ret < 0)
791 goto out;
792
793 ret = GNUTLS_E_SUCCESS;
794 out:
795 return tls_status_from_err(ssock, ret);
796 }
797
798
799 /* Destroy GnuTLS credentials and session. */
800 static void ssl_destroy(pj_ssl_sock_t *ssock)
801 {
802 gnutls_sock_t *gssock = (gnutls_sock_t *)ssock;
803
804 if (gssock->session) {
805 gnutls_bye(gssock->session, GNUTLS_SHUT_RDWR);
806 gnutls_deinit(gssock->session);
807 gssock->session = NULL;
808 }
809
810 if (gssock->xcred) {
811 gnutls_certificate_free_credentials(gssock->xcred);
812 gssock->xcred = NULL;
813 }
814
815 /* Free GnuTLS library */
816 if (gssock->tls_init_count) {
817 gssock->tls_init_count--;
818 tls_deinit();
819 }
820
821 /* Destroy circular buffers */
822 circ_deinit(&ssock->circ_buf_input);
823 circ_deinit(&ssock->circ_buf_output);
824 }
825
826
827 /* Reset socket state. */
828 static void ssl_reset_sock_state(pj_ssl_sock_t *ssock)
829 {
830 pj_lock_acquire(ssock->circ_buf_output_mutex);
831 ssock->ssl_state = SSL_STATE_NULL;
832 pj_lock_release(ssock->circ_buf_output_mutex);
833
834 ssl_close_sockets(ssock);
835
836 ssock->last_err = tls_last_error = GNUTLS_E_SUCCESS;
837 }
838
839
840 static void ssl_ciphers_populate(void)
841 {
842 if (!ssl_cipher_num) {
843 tls_init();
844 tls_deinit();
845 }
846 }
847
848
849 static pj_ssl_cipher ssl_get_cipher(pj_ssl_sock_t *ssock)
850 {
851 gnutls_sock_t *gssock = (gnutls_sock_t *)ssock;
852 int i;
853 gnutls_cipher_algorithm_t lookup;
854 gnutls_cipher_algorithm_t cipher;
855
856 /* Current cipher */
857 cipher = gnutls_cipher_get(gssock->session);
858 for (i = 0; ; i++) {
859 unsigned char id[2];
860 const char *suite;
861
862 suite = gnutls_cipher_suite_info(i,(unsigned char *)id, NULL,
863 &lookup, NULL, NULL);
864 if (suite) {
865 if (lookup == cipher) {
866 return (pj_uint32_t) ((id[0] << 8) | id[1]);
867 }
868 } else {
869 break;
870 }
871 }
872
873 return PJ_TLS_UNKNOWN_CIPHER;
874 }
875
876
877 /* Get Common Name field string from a general name string */
878 static void tls_cert_get_cn(const pj_str_t *gen_name, pj_str_t *cn)
879 {
880 pj_str_t CN_sign = {"CN=", 3};
881 char *p, *q;
882
883 pj_bzero(cn, sizeof(cn));
884
885 p = pj_strstr(gen_name, &CN_sign);
886 if (!p)
887 return;
888
889 p += 3; /* shift pointer to value part */
890 pj_strset(cn, p, gen_name->slen - (p - gen_name->ptr));
891 q = pj_strchr(cn, ',');
892 if (q)
893 cn->slen = q - p;
894 }
895
896
897 /* Get certificate info; in case the certificate info is already populated,
898 * this function will check if the contents need updating by inspecting the
899 * issuer and the serial number. */
900 static void tls_cert_get_info(pj_pool_t *pool, pj_ssl_cert_info *ci,
901 gnutls_x509_crt_t cert)
902 {
903 pj_bool_t update_needed;
904 char buf[512] = { 0 };
905 size_t bufsize = sizeof(buf);
906 pj_uint8_t serial_no[64] = { 0 }; /* should be >= sizeof(ci->serial_no) */
907 size_t serialsize = sizeof(serial_no);
908 size_t len = sizeof(buf);
909 int i, ret, seq = 0;
910 pj_ssl_cert_name_type type;
911
912 pj_assert(pool && ci && cert);
913
914 /* Get issuer */
915 gnutls_x509_crt_get_issuer_dn(cert, buf, &bufsize);
916
917 /* Get serial no */
918 gnutls_x509_crt_get_serial(cert, serial_no, &serialsize);
919
920 /* Check if the contents need to be updated */
921 update_needed = pj_strcmp2(&ci->issuer.info, buf) ||
922 pj_memcmp(ci->serial_no, serial_no, serialsize);
923 if (!update_needed)
924 return;
925
926 /* Update cert info */
927
928 pj_bzero(ci, sizeof(pj_ssl_cert_info));
929
930 /* Version */
931 ci->version = gnutls_x509_crt_get_version(cert);
932
933 /* Issuer */
934 pj_strdup2(pool, &ci->issuer.info, buf);
935 tls_cert_get_cn(&ci->issuer.info, &ci->issuer.cn);
936
937 /* Serial number */
938 pj_memcpy(ci->serial_no, serial_no, sizeof(ci->serial_no));
939
940 /* Subject */
941 bufsize = sizeof(buf);
942 gnutls_x509_crt_get_dn(cert, buf, &bufsize);
943 pj_strdup2(pool, &ci->subject.info, buf);
944 tls_cert_get_cn(&ci->subject.info, &ci->subject.cn);
945
946 /* Validity */
947 ci->validity.end.sec = gnutls_x509_crt_get_expiration_time(cert);
948 ci->validity.start.sec = gnutls_x509_crt_get_activation_time(cert);
949 ci->validity.gmt = 0;
950
951 /* Subject Alternative Name extension */
952 if (ci->version >= 3) {
953 char out[256] = { 0 };
954 /* Get the number of all alternate names so that we can allocate
955 * the correct number of bytes in subj_alt_name */
956 while (gnutls_x509_crt_get_subject_alt_name(cert, seq, out, &len,
957 NULL) !=
958 GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
959 {
960 seq++;
961 }
962
963 ci->subj_alt_name.entry = pj_pool_calloc(pool, seq,
964 sizeof(*ci->subj_alt_name.entry));
965 if (!ci->subj_alt_name.entry) {
966 tls_last_error = GNUTLS_E_MEMORY_ERROR;
967 return;
968 }
969
970 /* Now populate the alternative names */
971 for (i = 0; i < seq; i++) {
972 len = sizeof(out) - 1;
973 ret = gnutls_x509_crt_get_subject_alt_name(cert, i, out,
974 &len, NULL);
975
976 switch (ret) {
977 case GNUTLS_SAN_IPADDRESS:
978 type = PJ_SSL_CERT_NAME_IP;
979 pj_inet_ntop2(len == sizeof(pj_in6_addr) ? pj_AF_INET6()
980 : pj_AF_INET(),
981 out, buf, sizeof(buf));
982 break;
983 case GNUTLS_SAN_URI:
984 type = PJ_SSL_CERT_NAME_URI;
985 break;
986 case GNUTLS_SAN_RFC822NAME:
987 type = PJ_SSL_CERT_NAME_RFC822;
988 break;
989 case GNUTLS_SAN_DNSNAME:
990 type = PJ_SSL_CERT_NAME_DNS;
991 break;
992 default:
993 type = PJ_SSL_CERT_NAME_UNKNOWN;
994 break;
995 }
996
997 if (len && type != PJ_SSL_CERT_NAME_UNKNOWN) {
998 ci->subj_alt_name.entry[ci->subj_alt_name.cnt].type = type;
999 pj_strdup2(pool,
1000 &ci->subj_alt_name.entry[ci->subj_alt_name.cnt].name,
1001 type == PJ_SSL_CERT_NAME_IP ? buf : out);
1002 ci->subj_alt_name.cnt++;
1003 }
1004 }
1005 /* TODO: if no DNS alt. names were found, we could check against
1006 * the commonName as per RFC3280. */
1007 }
1008 }
1009
1010 static void tls_cert_get_chain_raw(pj_pool_t *pool, pj_ssl_cert_info *ci,
1011 const gnutls_datum_t *certs,
1012 size_t certs_num)
1013 {
1014 size_t i=0;
1015 ci->raw_chain.cert_raw = pj_pool_calloc(pool, certs_num,
1016 sizeof(*ci->raw_chain.cert_raw));
1017 ci->raw_chain.cnt = certs_num;
1018 for (i=0; i < certs_num; ++i) {
1019 const pj_str_t crt_raw = {(char*)certs[i].data,
1020 (pj_ssize_t)certs[i].size};
1021 pj_strdup(pool, ci->raw_chain.cert_raw+i, &crt_raw);
1022 }
1023 }
1024
1025 /* Update local & remote certificates info. This function should be
1026 * called after handshake or renegotiation successfully completed. */
1027 static void ssl_update_certs_info(pj_ssl_sock_t *ssock)
1028 {
1029 gnutls_sock_t *gssock = (gnutls_sock_t *)ssock;
1030 gnutls_x509_crt_t cert = NULL;
1031 const gnutls_datum_t *us;
1032 const gnutls_datum_t *certs;
1033 unsigned int certslen = 0;
1034 int ret = GNUTLS_CERT_INVALID;
1035
1036 pj_assert(ssock->ssl_state == SSL_STATE_ESTABLISHED);
1037
1038 /* Get active local certificate */
1039 us = gnutls_certificate_get_ours(gssock->session);
1040 if (!us)
1041 goto us_out;
1042
1043 ret = gnutls_x509_crt_init(&cert);
1044 if (ret < 0)
1045 goto us_out;
1046 ret = gnutls_x509_crt_import(cert, us, GNUTLS_X509_FMT_DER);
1047 if (ret < 0)
1048 ret = gnutls_x509_crt_import(cert, us, GNUTLS_X509_FMT_PEM);
1049 if (ret < 0)
1050 goto us_out;
1051
1052 tls_cert_get_info(ssock->pool, &ssock->local_cert_info, cert);
1053 pj_pool_reset(ssock->info_pool);
1054 tls_cert_get_chain_raw(ssock->info_pool, &ssock->local_cert_info, us, 1);
1055
1056 us_out:
1057 tls_last_error = ret;
1058 if (cert)
1059 gnutls_x509_crt_deinit(cert);
1060 else
1061 pj_bzero(&ssock->local_cert_info, sizeof(pj_ssl_cert_info));
1062
1063 cert = NULL;
1064
1065 /* Get active remote certificate */
1066 certs = gnutls_certificate_get_peers(gssock->session, &certslen);
1067 if (certs == NULL || certslen == 0)
1068 goto peer_out;
1069
1070 ret = gnutls_x509_crt_init(&cert);
1071 if (ret < 0)
1072 goto peer_out;
1073
1074 ret = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_PEM);
1075 if (ret < 0)
1076 ret = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER);
1077 if (ret < 0)
1078 goto peer_out;
1079
1080 tls_cert_get_info(ssock->pool, &ssock->remote_cert_info, cert);
1081 pj_pool_reset(ssock->info_pool);
1082 tls_cert_get_chain_raw(ssock->info_pool, &ssock->remote_cert_info, certs,
1083 certslen);
1084
1085 peer_out:
1086 tls_last_error = ret;
1087 if (cert)
1088 gnutls_x509_crt_deinit(cert);
1089 else
1090 pj_bzero(&ssock->remote_cert_info, sizeof(pj_ssl_cert_info));
1091 }
1092
1093 static void ssl_set_state(pj_ssl_sock_t *ssock, pj_bool_t is_server)
1094 {
1095 PJ_UNUSED_ARG(ssock);
1096 PJ_UNUSED_ARG(is_server);
1097 }
1098
1099 static void ssl_set_peer_name(pj_ssl_sock_t *ssock)
1100 {
1101 gnutls_sock_t *gssock = (gnutls_sock_t *)ssock;
1102
1103 /* Set server name to connect */
1104 if (ssock->param.server_name.slen &&
1105 get_ip_addr_ver(&ssock->param.server_name) == 0)
1106 {
1107 int ret;
1108 /* Server name is null terminated already */
1109 ret = gnutls_server_name_set(gssock->session, GNUTLS_NAME_DNS,
1110 ssock->param.server_name.ptr,
1111 ssock->param.server_name.slen);
1112 if (ret < 0) {
1113 PJ_LOG(3, (ssock->pool->obj_name,
1114 "gnutls_server_name_set() failed: %s",
1115 gnutls_strerror(ret)));
1116 }
1117 }
1118 }
1119
1120 /* Try to perform an asynchronous handshake */
1121 static pj_status_t ssl_do_handshake(pj_ssl_sock_t *ssock)
1122 {
1123 gnutls_sock_t *gssock = (gnutls_sock_t *)ssock;
1124 int ret;
1125 pj_status_t status;
1126
1127 /* Perform SSL handshake */
1128 ret = gnutls_handshake(gssock->session);
1129
1130 status = flush_circ_buf_output(ssock, &ssock->handshake_op_key, 0, 0);
1131 if (status != PJ_SUCCESS)
1132 return status;
1133
1134 if (ret == GNUTLS_E_SUCCESS) {
1135 /* System are GO */
1136 ssock->ssl_state = SSL_STATE_ESTABLISHED;
1137 status = PJ_SUCCESS;
1138 } else if (!gnutls_error_is_fatal(ret)) {
1139 /* Non fatal error, retry later (busy or again) */
1140 status = PJ_EPENDING;
1141 } else {
1142 /* Fatal error invalidates session, no fallback */
1143 status = PJ_EINVAL;
1144 }
1145
1146 tls_last_error = ret;
1147
1148 return status;
1149 }
1150
1151 static pj_status_t ssl_read(pj_ssl_sock_t *ssock, void *data, int *size)
1152 {
1153 gnutls_sock_t *gssock = (gnutls_sock_t *)ssock;
1154 int decrypted_size;
1155
1156 /* Decrypt received data using GnuTLS (will read our input
1157 * circular buffer) */
1158 decrypted_size = gnutls_record_recv(gssock->session, data, *size);
1159 *size = 0;
1160 if (decrypted_size > 0) {
1161 *size = decrypted_size;
1162 return PJ_SUCCESS;
1163 } else if (decrypted_size == 0) {
1164 /* Nothing more to read */
1165 return PJ_SUCCESS;
1166 } else if (decrypted_size == GNUTLS_E_REHANDSHAKE) {
1167 return PJ_EEOF;
1168 } else if (decrypted_size == GNUTLS_E_AGAIN ||
1169 decrypted_size == GNUTLS_E_INTERRUPTED ||
1170 !gnutls_error_is_fatal(decrypted_size))
1171 {
1172 /* non-fatal error, let's just continue */
1173 return PJ_SUCCESS;
1174 } else {
1175 return PJ_ECANCELLED;
1176 }
1177 }
1178
1179 /*
1180 * Write the plain data to GnuTLS, it will be encrypted by gnutls_record_send()
1181 * and sent via tls_data_push. Note that re-negotitation may be on progress, so
1182 * sending data should be delayed until re-negotiation is completed.
1183 */
1184 static pj_status_t ssl_write(pj_ssl_sock_t *ssock, const void *data,
1185 pj_ssize_t size, int *nwritten)
1186 {
1187 gnutls_sock_t *gssock = (gnutls_sock_t *)ssock;
1188 int nwritten_;
1189 pj_ssize_t total_written = 0;
1190
1191 /* Ask GnuTLS to encrypt our plaintext now. GnuTLS will use the push
1192 * callback to actually write the encrypted bytes into our output circular
1193 * buffer. GnuTLS may refuse to "send" everything at once, but since we are
1194 * not really sending now, we will just call it again now until it succeeds
1195 * (or fails in a fatal way). */
1196 while (total_written < size) {
1197 /* Try encrypting using GnuTLS */
1198 nwritten_ = gnutls_record_send(gssock->session,
1199 ((read_data_t *)data) + total_written,
1200 size - total_written);
1201
1202 if (nwritten_ > 0) {
1203 /* Good, some data was encrypted and written */
1204 total_written += nwritten_;
1205 } else {
1206 /* Normally we would have to retry record_send but our internal
1207 * state has not changed, so we have to ask for more data first.
1208 * We will just try again later, although this should never happen.
1209 */
1210 *nwritten = nwritten_;
1211 return tls_status_from_err(ssock, nwritten_);
1212 }
1213 }
1214
1215 /* All encrypted data is written to the output circular buffer;
1216 * now send it on the socket (or notify problem). */
1217 *nwritten = total_written;
1218 return PJ_SUCCESS;
1219 }
1220
1221 static pj_status_t ssl_renegotiate(pj_ssl_sock_t *ssock)
1222 {
1223 gnutls_sock_t *gssock = (gnutls_sock_t *)ssock;
1224 int status;
1225
1226 /* First call gnutls_rehandshake() to see if this is even possible */
1227 status = gnutls_rehandshake(gssock->session);
1228
1229 if (status == GNUTLS_E_SUCCESS) {
1230 /* Rehandshake is possible, so try a GnuTLS handshake now. The eventual
1231 * gnutls_record_recv() calls could return a few specific values during
1232 * this state:
1233 *
1234 * - GNUTLS_E_REHANDSHAKE: rehandshake message processing
1235 * - GNUTLS_E_WARNING_ALERT_RECEIVED: client does not wish to
1236 * renegotiate
1237 */
1238 return PJ_SUCCESS;
1239 } else {
1240 return tls_status_from_err(ssock, status);
1241 }
1242 }
1243
1244 #endif /* PJ_HAS_SSL_SOCK */
1245