Enable tls psk
[libradsec.git] / tls.c
1 /* Copyright 2010-2013 NORDUnet A/S. All rights reserved.
2    See LICENSE for licensing information. */
3
4 #if defined HAVE_CONFIG_H
5 #include <config.h>
6 #endif
7
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <assert.h>
11 #include <fcntl.h>
12 #include <limits.h>
13 #if defined HAVE_PTHREAD_H
14 #include <pthread.h>
15 #endif
16 #include <openssl/ssl.h>
17 #include <openssl/err.h>
18 #include <openssl/bn.h>
19 #include <openssl/x509v3.h>
20 #include <openssl/rand.h>
21 #include <openssl/crypto.h>
22 #include <radsec/radsec.h>
23 #include <radsec/radsec-impl.h>
24
25 #include <regex.h>
26 #include "radsecproxy/list.h"
27 #include "radsecproxy/radsecproxy.h"
28
29 #include "tls.h"
30
31 static struct tls *
32 _get_tlsconf (struct rs_connection *conn, const struct rs_realm *realm)
33 {
34   struct tls *c = rs_malloc (conn->ctx, sizeof (struct tls));
35
36   if (c)
37     {
38       memset (c, 0, sizeof (struct tls));
39       /* TODO: Make sure old radsecproxy code doesn't free these all
40          of a sudden, or strdup them.  */
41       c->name = realm->name;
42       c->cacertfile = realm->cacertfile;
43       c->cacertpath = NULL;     /* NYI */
44       c->certfile = realm->certfile;
45       c->certkeyfile = realm->certkeyfile;
46       c->certkeypwd = NULL;     /* NYI */
47       c->cacheexpiry = 0;       /* NYI */
48       c->crlcheck = 0;          /* NYI */
49       c->policyoids = (char **) NULL; /* NYI */
50     }
51     else
52       rs_err_conn_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL);
53
54   return c;
55 }
56
57 #if defined RS_ENABLE_TLS_PSK
58 static unsigned int
59 psk_client_cb (SSL *ssl,
60                const char *hint,
61                char *identity,
62                unsigned int max_identity_len,
63                unsigned char *psk,
64                unsigned int max_psk_len)
65 {
66   struct rs_connection *conn = NULL;
67   struct rs_credentials *cred = NULL;
68
69   conn = SSL_get_ex_data (ssl, 0);
70   assert (conn != NULL);
71   cred = conn->active_peer->realm->transport_cred;
72   assert (cred != NULL);
73   /* NOTE: Ignoring identity hint from server.  */
74
75   if (strlen (cred->identity) + 1 > max_identity_len)
76     {
77       rs_err_conn_push (conn, RSE_CRED, "PSK identity longer than max %d",
78                         max_identity_len - 1);
79       return 0;
80     }
81   strcpy (identity, cred->identity);
82
83   switch (cred->secret_encoding)
84     {
85     case RS_KEY_ENCODING_UTF8:
86       cred->secret_len = strlen (cred->secret);
87       if (cred->secret_len > max_psk_len)
88         {
89           rs_err_conn_push (conn, RSE_CRED, "PSK secret longer than max %d",
90                             max_psk_len);
91           return 0;
92         }
93       memcpy (psk, cred->secret, cred->secret_len);
94       break;
95     case RS_KEY_ENCODING_ASCII_HEX:
96       {
97         BIGNUM *bn = NULL;
98
99         if (BN_hex2bn (&bn, cred->secret) == 0)
100           {
101             rs_err_conn_push (conn, RSE_CRED, "Unable to convert pskhexstr");
102             if (bn != NULL)
103               BN_clear_free (bn);
104             return 0;
105           }
106         if ((unsigned int) BN_num_bytes (bn) > max_psk_len)
107           {
108             rs_err_conn_push (conn, RSE_CRED, "PSK secret longer than max %d",
109                              max_psk_len);
110             BN_clear_free (bn);
111             return 0;
112           }
113         cred->secret_len = BN_bn2bin (bn, psk);
114         BN_clear_free (bn);
115       }
116       break;
117     default:
118       assert (!"unknown psk encoding");
119     }
120
121   return cred->secret_len;
122 }
123 #endif  /* RS_ENABLE_TLS_PSK */
124
125 /** Read \a buf_len bytes from one of the random devices into \a
126     buf. Return 0 on success and -1 on failure. */
127 static int
128 load_rand_ (uint8_t *buf, size_t buf_len)
129 {
130   static const char *fns[] = {"/dev/urandom", "/dev/random", NULL};
131   int i;
132
133   if (buf_len > SSIZE_MAX)
134     return -1;
135
136   for (i = 0; fns[i] != NULL; i++)
137     {
138       size_t nread = 0;
139       int fd = open (fns[i], O_RDONLY);
140       if (fd < 0)
141         continue;
142       while (nread != buf_len)
143         {
144           ssize_t r = read (fd, buf + nread, buf_len - nread);
145           if (r < 0)
146             return -1;
147           if (r == 0)
148             break;
149           nread += r;
150         }
151       close (fd);
152       if (nread != buf_len)
153         return -1;
154       return 0;
155     }
156   return -1;
157 }
158
159 /** Initialise OpenSSL's PRNG by possibly invoking RAND_poll() and by
160     feeding RAND_seed() data from one of the random devices. If either
161     succeeds, we're happy and return 0. */
162 static int
163 init_openssl_rand_ (void)
164 {
165   long openssl_version = 0;
166   int openssl_random_init_flag = 0;
167   int our_random_init_flag = 0;
168   uint8_t buf[32];
169
170   /* Older OpenSSL has a crash bug in RAND_poll (when a file it opens
171      gets a file descriptor with a number higher than FD_SETSIZE) so
172      use it only for newer versions. */
173   openssl_version = SSLeay ();
174   if (openssl_version >= OPENSSL_V (0,9,8,'c'))
175     openssl_random_init_flag = RAND_poll ();
176
177   our_random_init_flag = !load_rand_ (buf, sizeof(buf));
178   if (our_random_init_flag)
179     RAND_seed (buf, sizeof(buf));
180   memset (buf, 0, sizeof(buf)); /* FIXME: What if memset() is optimised out? */
181
182   if (!openssl_random_init_flag && !our_random_init_flag)
183     return -1;
184   if (!RAND_bytes (buf, sizeof(buf)))
185     return -1;
186   return 0;
187 }
188
189 #if defined HAVE_PTHREADS
190 /** Array of pthread_mutex_t for OpenSSL. Allocated and initialised in
191     \a init_locking_ and never freed. */
192 static pthread_mutex_t *s_openssl_mutexes = NULL;
193 /** Number of pthread_mutex_t's allocated at s_openssl_mutexes. */
194 static int s_openssl_mutexes_count = 0;
195
196 /** Callback for OpenSSL when a lock is to be held or released. */
197 static void
198 openssl_locking_cb_ (int mode, int i, const char *file, int line)
199 {
200   if (s_openssl_mutexes == NULL || i >= s_openssl_mutexes_count)
201     return;
202   if (mode & CRYPTO_LOCK)
203     pthread_mutex_lock (&s_openssl_mutexes[i]);
204   else
205     pthread_mutex_unlock (&s_openssl_mutexes[i]);
206 }
207
208 /** Initialise any locking needed for being thread safe. Libradsec has
209     all its own state in one or more struct rs_context and doesn't
210     need locks but libraries used by libradsec may need protection. */
211 static int
212 init_locking_ ()
213 {
214   int i, n;
215   n = CRYPTO_num_locks ();
216
217   s_openssl_mutexes = calloc (n, sizeof(pthread_mutex_t));
218   if (s_openssl_mutexes == NULL)
219     return -RSE_NOMEM;
220   for (i = 0; i < n; i++)
221     pthread_mutex_init (&s_openssl_mutexes[i], NULL);
222   s_openssl_mutexes_count = n;
223
224   return 0;
225 }
226 #endif  /* HAVE_PTHREADS */
227
228 /** Initialise the TLS library. Return 0 on success, -1 on failure. */
229 int
230 tls_init ()
231 {
232   SSL_load_error_strings ();
233 #if defined HAVE_PTHREADS
234   if (CRYPTO_get_locking_callback () == NULL)
235     {
236       assert (s_openssl_mutexes_count == 0);
237       /* Allocate and initialise mutexes. We will never free
238          these. FIXME: Is there a portable way of having a function
239          invoked when a solib is unloaded? -ln */
240       if (init_locking_ ())
241         return -1;
242       CRYPTO_set_locking_callback (openssl_locking_cb_);
243     }
244 #endif  /* HAVE_PTHREADS */
245   SSL_library_init ();
246   return init_openssl_rand_ ();
247 }
248
249 int
250 tls_init_conn (struct rs_connection *conn)
251 {
252   struct rs_context *ctx = NULL;
253   struct tls *tlsconf = NULL;
254   SSL_CTX *ssl_ctx = NULL;
255   SSL *ssl = NULL;
256   unsigned long sslerr = 0;
257
258   assert (conn->ctx);
259   ctx = conn->ctx;
260
261   tlsconf = _get_tlsconf (conn, conn->active_peer->realm);
262   if (!tlsconf)
263     return -1;
264   ssl_ctx = tlsgetctx (RAD_TLS, tlsconf);
265   if (!ssl_ctx)
266     {
267       for (sslerr = ERR_get_error (); sslerr; sslerr = ERR_get_error ())
268          rs_err_conn_push_fl (conn, RSE_SSLERR, __FILE__, __LINE__,
269                               ERR_error_string (sslerr, NULL));
270       return -1;
271     }
272   ssl = SSL_new (ssl_ctx);
273   if (!ssl)
274     {
275       for (sslerr = ERR_get_error (); sslerr; sslerr = ERR_get_error ())
276         rs_err_conn_push_fl (conn, RSE_SSLERR, __FILE__, __LINE__,
277                              ERR_error_string (sslerr, NULL));
278       return -1;
279     }
280
281 #if defined RS_ENABLE_TLS_PSK
282   if (conn->active_peer->realm->transport_cred != NULL)
283     {
284       SSL_set_psk_client_callback (ssl, psk_client_cb);
285       SSL_set_ex_data (ssl, 0, conn);
286     }
287 #endif  /* RS_ENABLE_TLS_PSK */
288
289   conn->tls_ctx = ssl_ctx;
290   conn->tls_ssl = ssl;
291   rs_free (ctx, tlsconf);
292   return RSE_OK;
293 }
294
295 /* draft-ietf-radext-radsec-11.txt
296
297        *  Certificate validation MUST include the verification rules as
298           per [RFC5280].
299
300        *  Implementations SHOULD indicate their acceptable Certification
301           Authorities as per section 7.4.4 (server side) and x.y.z
302           ["Trusted CA Indication"] (client side) of [RFC5246] (see
303           Section 3.2)
304
305        *  Implementations SHOULD allow to configure a list of acceptable
306           certificates, identified via certificate fingerprint.  When a
307           fingerprint configured, the fingerprint is prepended with an
308           ASCII label identifying the hash function followed by a colon.
309           Implementations MUST support SHA-1 as the hash algorithm and
310           use the ASCII label "sha-1" to identify the SHA-1 algorithm.
311           The length of a SHA-1 hash is 20 bytes and the length of the
312           corresponding fingerprint string is 65 characters.  An example
313           certificate fingerprint is: sha-
314           1:E1:2D:53:2B:7C:6B:8A:29:A2:76:C8:64:36:0B:08:4B:7A:F1:9E:9D
315
316        *  Peer validation always includes a check on whether the locally
317           configured expected DNS name or IP address of the server that
318           is contacted matches its presented certificate.  DNS names and
319           IP addresses can be contained in the Common Name (CN) or
320           subjectAltName entries.  For verification, only one of these
321           entries is to be considered.  The following precedence
322           applies: for DNS name validation, subjectAltName:DNS has
323           precedence over CN; for IP address validation, subjectAltName:
324           iPAddr has precedence over CN.
325
326        *  Implementations SHOULD allow to configure a set of acceptable
327           values for subjectAltName:URI.
328  */
329 int
330 tls_verify_cert (struct rs_connection *conn)
331 {
332   int err = 0;
333   int success = 0;
334   X509 *peer_cert = NULL;
335   struct in6_addr addr;
336   const char *hostname = NULL;
337
338   assert (conn->active_peer->conn == conn);
339   assert (conn->active_peer->hostname != NULL);
340   hostname = conn->active_peer->hostname;
341
342   /* verifytlscert() performs basic verification as described by
343      OpenSSL VERIFY(1), i.e. verification of the certificate chain.  */
344   peer_cert = verifytlscert (conn->tls_ssl);
345   if (peer_cert == NULL)
346     {
347       err = rs_err_conn_push (conn, RSE_SSLERR,
348                               "basic certificate validation failed");
349       goto out;
350     }
351
352   if (inet_pton (AF_INET, hostname, &addr))
353     success = (subjectaltnameaddr (peer_cert, AF_INET, &addr) == 1);
354   else if (inet_pton (AF_INET6, hostname, &addr))
355     success = (subjectaltnameaddr (peer_cert, AF_INET6, &addr) == 1);
356   else
357     success = (subjectaltnameregexp (peer_cert, GEN_DNS, hostname, NULL) == 1);
358
359   if (!success)
360     success = (cnregexp (peer_cert, hostname, NULL) == 1);
361
362   if (conn->realm->disable_hostname_check)
363     success = 1;
364   if (!success)
365     err = rs_err_conn_push (conn, RSE_CERT, "server certificate doesn't "
366                             "match configured hostname \"%s\"", hostname);
367
368  out:
369   if (peer_cert != NULL)
370     X509_free (peer_cert);
371   return err;
372 }