0f07e46426050e4d9fe0dba24a59800c07fb1903
[radsecproxy.git] / lib / tls.c
1 /* Copyright 2010, 2011 NORDUnet A/S. All rights reserved.
2    See the file COPYING for licensing information.  */
3
4 #if defined HAVE_CONFIG_H
5 #include <config.h>
6 #endif
7
8 #include <assert.h>
9 #include <openssl/ssl.h>
10 #include <openssl/err.h>
11 #include <openssl/bn.h>
12 #include <radsec/radsec.h>
13 #include <radsec/radsec-impl.h>
14
15 #include <regex.h>
16 #include "rsp_list.h"
17 #include "../radsecproxy.h"
18
19 static struct tls *
20 _get_tlsconf (struct rs_connection *conn, const struct rs_realm *realm)
21 {
22   struct tls *c = rs_malloc (conn->ctx, sizeof (struct tls));
23
24   if (c)
25     {
26       memset (c, 0, sizeof (struct tls));
27       /* TODO: Make sure old radsecproxy code doesn't free these all
28          of a sudden, or strdup them.  */
29       c->name = realm->name;
30       c->cacertfile = realm->cacertfile;
31       c->cacertpath = NULL;     /* NYI */
32       c->certfile = realm->certfile;
33       c->certkeyfile = realm->certkeyfile;
34       c->certkeypwd = NULL;     /* NYI */
35       c->cacheexpiry = 0;       /* NYI */
36       c->crlcheck = 0;          /* NYI */
37       c->policyoids = (char **) NULL; /* NYI */
38     }
39     else
40       rs_err_conn_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL);
41
42   return c;
43 }
44
45 #if defined RS_ENABLE_TLS_PSK
46 static unsigned int
47 psk_client_cb (SSL *ssl,
48                const char *hint,
49                char *identity,
50                unsigned int max_identity_len,
51                unsigned char *psk,
52                unsigned int max_psk_len)
53 {
54   struct rs_connection *conn = NULL;
55   struct rs_credentials *cred = NULL;
56
57   conn = SSL_get_ex_data (ssl, 0);
58   assert (conn != NULL);
59   cred = conn->active_peer->realm->transport_cred;
60   assert (cred != NULL);
61   /* NOTE: Ignoring identity hint from server.  */
62
63   if (strlen (cred->identity) + 1 > max_identity_len)
64     {
65       rs_err_conn_push (conn, RSE_CRED, "PSK identity longer than max %d",
66                         max_identity_len - 1);
67       return 0;
68     }
69   strcpy (identity, cred->identity);
70
71   switch (cred->secret_encoding)
72     {
73     case RS_KEY_ENCODING_UTF8:
74       cred->secret_len = strlen (cred->secret);
75       if (cred->secret_len > max_psk_len)
76         {
77           rs_err_conn_push (conn, RSE_CRED, "PSK secret longer than max %d",
78                             max_psk_len);
79           return 0;
80         }
81       memcpy (psk, cred->secret, cred->secret_len);
82       break;
83     case RS_KEY_ENCODING_ASCII_HEX:
84       {
85         BIGNUM *bn = NULL;
86
87         if (BN_hex2bn (&bn, cred->secret) == 0)
88           {
89             rs_err_conn_push (conn, RSE_CRED, "Unable to convert pskhexstr");
90             if (bn != NULL)
91               BN_clear_free (bn);
92             return 0;
93           }
94         if ((unsigned int) BN_num_bytes (bn) > max_psk_len)
95           {
96             rs_err_conn_push (conn, RSE_CRED, "PSK secret longer than max %d",
97                              max_psk_len);
98             BN_clear_free (bn);
99             return 0;
100           }
101         cred->secret_len = BN_bn2bin (bn, psk);
102         BN_clear_free (bn);
103       }
104       break;
105     default:
106       assert (!"unknown psk encoding");
107     }
108
109   return cred->secret_len;
110 }
111 #endif  /* RS_ENABLE_TLS_PSK */
112
113 int
114 rs_tls_init (struct rs_connection *conn)
115 {
116   struct rs_context *ctx = NULL;
117   struct tls *tlsconf = NULL;
118   SSL_CTX *ssl_ctx = NULL;
119   SSL *ssl = NULL;
120   unsigned long sslerr = 0;
121
122   assert (conn->ctx);
123   ctx = conn->ctx;
124
125   tlsconf = _get_tlsconf (conn, conn->active_peer->realm);
126   if (!tlsconf)
127     return -1;
128   ssl_ctx = tlsgetctx (RAD_TLS, tlsconf);
129   if (!ssl_ctx)
130     {
131       for (sslerr = ERR_get_error (); sslerr; sslerr = ERR_get_error ())
132          rs_err_conn_push_fl (conn, RSE_SSLERR, __FILE__, __LINE__,
133                               ERR_error_string (sslerr, NULL));
134       return -1;
135     }
136   ssl = SSL_new (ssl_ctx);
137   if (!ssl)
138     {
139       for (sslerr = ERR_get_error (); sslerr; sslerr = ERR_get_error ())
140         rs_err_conn_push_fl (conn, RSE_SSLERR, __FILE__, __LINE__,
141                              ERR_error_string (sslerr, NULL));
142       return -1;
143     }
144
145 #if defined RS_ENABLE_TLS_PSK
146   if (conn->active_peer->realm->transport_cred != NULL)
147     {
148       SSL_set_psk_client_callback (ssl, psk_client_cb);
149       SSL_set_ex_data (ssl, 0, conn);
150     }
151 #endif  /* RS_ENABLE_TLS_PSK */
152
153   conn->tls_ctx = ssl_ctx;
154   conn->tls_ssl = ssl;
155   rs_free (ctx, tlsconf);
156   return RSE_OK;
157 }