1 /*
2 * TLS/SSL Protocol
3 * Copyright (c) 2011 Martin Storsjo
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg 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 GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <errno.h>
23
24 #include <gnutls/gnutls.h>
25 #include <gnutls/x509.h>
26
37
38 #ifndef GNUTLS_VERSION_NUMBER
39 #define GNUTLS_VERSION_NUMBER LIBGNUTLS_VERSION_NUMBER
40 #endif
41
42 #if HAVE_THREADS && GNUTLS_VERSION_NUMBER <= 0x020b00
43 #include <gcrypt.h>
45 GCRY_THREAD_OPTION_PTHREAD_IMPL;
46 #endif
47
52 gnutls_certificate_credentials_t
cred;
56
58 {
60 #if HAVE_THREADS && GNUTLS_VERSION_NUMBER < 0x020b00
61 if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0)
62 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
63 #endif
64 gnutls_global_init();
66 }
67
69 {
71 gnutls_global_deinit();
73 }
74
76 {
79 case GNUTLS_E_AGAIN:
81 case GNUTLS_E_INTERRUPTED:
82 #ifdef GNUTLS_E_PREMATURE_TERMINATION
83 case GNUTLS_E_PREMATURE_TERMINATION:
84 #endif
85 break;
86 case GNUTLS_E_WARNING_ALERT_RECEIVED:
88 break;
89 default:
91 break;
92 }
98 }
100 }
101
103 {
105 if (
c->need_shutdown)
106 gnutls_bye(
c->session, GNUTLS_SHUT_WR);
108 gnutls_deinit(
c->session);
110 gnutls_certificate_free_credentials(
c->cred);
113 return 0;
114 }
115
117 void *buf,
size_t len)
118 {
124 return 0;
126 errno = EAGAIN;
127 } else {
128 errno = EIO;
130 }
131 return -1;
132 }
133
135 const void *buf,
size_t len)
136 {
142 return 0;
144 errno = EAGAIN;
145 } else {
146 errno = EIO;
148 }
149 return -1;
150 }
151
153 {
157
159
162
163 gnutls_init(&p->
session,
c->listen ? GNUTLS_SERVER : GNUTLS_CLIENT);
164 if (!
c->listen && !
c->numerichost)
165 gnutls_server_name_set(p->
session, GNUTLS_NAME_DNS,
c->host, strlen(
c->host));
166 gnutls_certificate_allocate_credentials(&p->
cred);
168 ret = gnutls_certificate_set_x509_trust_file(p->
cred,
c->ca_file, GNUTLS_X509_FMT_PEM);
171 }
172 #if GNUTLS_VERSION_NUMBER >= 0x030020
173 else
174 gnutls_certificate_set_x509_system_trust(p->
cred);
175 #endif
176 gnutls_certificate_set_verify_flags(p->
cred,
c->verify ?
177 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT : 0);
178 if (
c->cert_file &&
c->key_file) {
179 ret = gnutls_certificate_set_x509_key_file(p->
cred,
180 c->cert_file,
c->key_file,
181 GNUTLS_X509_FMT_PEM);
184 "Unable to set cert/key files %s and %s: %s\n",
185 c->cert_file,
c->key_file, gnutls_strerror(
ret));
188 }
189 }
else if (
c->cert_file ||
c->key_file)
191 gnutls_credentials_set(p->
session, GNUTLS_CRD_CERTIFICATE, p->
cred);
194 gnutls_transport_set_ptr(p->
session, p);
195 gnutls_set_default_priority(p->
session);
196 do {
200 }
201
203 if (gnutls_error_is_fatal(
ret)) {
206 }
210 unsigned int status, cert_list_size;
211 gnutls_x509_crt_t cert;
212 const gnutls_datum_t *cert_list;
215 gnutls_strerror(
ret));
218 }
219 if (
status & GNUTLS_CERT_INVALID) {
223 }
224 if (gnutls_certificate_type_get(p->
session) != GNUTLS_CRT_X509) {
228 }
229 gnutls_x509_crt_init(&cert);
230 cert_list = gnutls_certificate_get_peers(p->
session, &cert_list_size);
231 gnutls_x509_crt_import(cert, cert_list, GNUTLS_X509_FMT_DER);
232 ret = gnutls_x509_crt_check_hostname(cert,
c->host);
233 gnutls_x509_crt_deinit(cert);
236 "The certificate's owner does not match hostname %s\n",
c->host);
239 }
240 }
241
242 return 0;
246 }
247
249 {
252 // Set or clear the AVIO_FLAG_NONBLOCK on c->tls_shared.tcp
255 ret = gnutls_record_recv(
c->session, buf,
size);
261 }
262
264 {
267 // Set or clear the AVIO_FLAG_NONBLOCK on c->tls_shared.tcp
270 ret = gnutls_record_send(
c->session, buf,
size);
276 }
277
279 {
282 }
283
285 {
288 }
289
293 };
294
300 };
301
313 };