1 /* Copyright 2010-2013 NORDUnet A/S. All rights reserved.
2 See LICENSE for licensing information. */
4 #if defined HAVE_CONFIG_H
10 #include <openssl/ssl.h>
11 #include <openssl/err.h>
12 #include <openssl/bn.h>
13 #include <openssl/x509v3.h>
14 #include <radsec/radsec.h>
15 #include <radsec/radsec-impl.h>
18 #include "radsecproxy/list.h"
19 #include "radsecproxy/radsecproxy.h"
22 _get_tlsconf (struct rs_connection *conn, const struct rs_realm *realm)
24 struct tls *c = rs_malloc (conn->ctx, sizeof (struct tls));
28 memset (c, 0, sizeof (struct tls));
29 /* TODO: Make sure old radsecproxy code doesn't free these all
30 of a sudden, or strdup them. */
31 c->name = realm->name;
32 c->cacertfile = realm->cacertfile;
33 c->cacertpath = NULL; /* NYI */
34 c->certfile = realm->certfile;
35 c->certkeyfile = realm->certkeyfile;
36 c->certkeypwd = NULL; /* NYI */
37 c->cacheexpiry = 0; /* NYI */
38 c->crlcheck = 0; /* NYI */
39 c->policyoids = (char **) NULL; /* NYI */
42 rs_err_conn_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL);
47 #if defined RS_ENABLE_TLS_PSK
49 psk_client_cb (SSL *ssl,
52 unsigned int max_identity_len,
54 unsigned int max_psk_len)
56 struct rs_connection *conn = NULL;
57 struct rs_credentials *cred = NULL;
59 conn = SSL_get_ex_data (ssl, 0);
60 assert (conn != NULL);
61 cred = conn->active_peer->realm->transport_cred;
62 assert (cred != NULL);
63 /* NOTE: Ignoring identity hint from server. */
65 if (strlen (cred->identity) + 1 > max_identity_len)
67 rs_err_conn_push (conn, RSE_CRED, "PSK identity longer than max %d",
68 max_identity_len - 1);
71 strcpy (identity, cred->identity);
73 switch (cred->secret_encoding)
75 case RS_KEY_ENCODING_UTF8:
76 cred->secret_len = strlen (cred->secret);
77 if (cred->secret_len > max_psk_len)
79 rs_err_conn_push (conn, RSE_CRED, "PSK secret longer than max %d",
83 memcpy (psk, cred->secret, cred->secret_len);
85 case RS_KEY_ENCODING_ASCII_HEX:
89 if (BN_hex2bn (&bn, cred->secret) == 0)
91 rs_err_conn_push (conn, RSE_CRED, "Unable to convert pskhexstr");
96 if ((unsigned int) BN_num_bytes (bn) > max_psk_len)
98 rs_err_conn_push (conn, RSE_CRED, "PSK secret longer than max %d",
103 cred->secret_len = BN_bn2bin (bn, psk);
108 assert (!"unknown psk encoding");
111 return cred->secret_len;
113 #endif /* RS_ENABLE_TLS_PSK */
116 rs_tls_init (struct rs_connection *conn)
118 struct rs_context *ctx = NULL;
119 struct tls *tlsconf = NULL;
120 SSL_CTX *ssl_ctx = NULL;
122 unsigned long sslerr = 0;
127 tlsconf = _get_tlsconf (conn, conn->active_peer->realm);
130 ssl_ctx = tlsgetctx (RAD_TLS, tlsconf);
133 for (sslerr = ERR_get_error (); sslerr; sslerr = ERR_get_error ())
134 rs_err_conn_push_fl (conn, RSE_SSLERR, __FILE__, __LINE__,
135 ERR_error_string (sslerr, NULL));
138 ssl = SSL_new (ssl_ctx);
141 for (sslerr = ERR_get_error (); sslerr; sslerr = ERR_get_error ())
142 rs_err_conn_push_fl (conn, RSE_SSLERR, __FILE__, __LINE__,
143 ERR_error_string (sslerr, NULL));
147 #if defined RS_ENABLE_TLS_PSK
148 if (conn->active_peer->realm->transport_cred != NULL)
150 SSL_set_psk_client_callback (ssl, psk_client_cb);
151 SSL_set_ex_data (ssl, 0, conn);
153 #endif /* RS_ENABLE_TLS_PSK */
155 conn->tls_ctx = ssl_ctx;
157 rs_free (ctx, tlsconf);
161 /* draft-ietf-radext-radsec-11.txt
163 * Certificate validation MUST include the verification rules as
166 * Implementations SHOULD indicate their acceptable Certification
167 Authorities as per section 7.4.4 (server side) and x.y.z
168 ["Trusted CA Indication"] (client side) of [RFC5246] (see
171 * Implementations SHOULD allow to configure a list of acceptable
172 certificates, identified via certificate fingerprint. When a
173 fingerprint configured, the fingerprint is prepended with an
174 ASCII label identifying the hash function followed by a colon.
175 Implementations MUST support SHA-1 as the hash algorithm and
176 use the ASCII label "sha-1" to identify the SHA-1 algorithm.
177 The length of a SHA-1 hash is 20 bytes and the length of the
178 corresponding fingerprint string is 65 characters. An example
179 certificate fingerprint is: sha-
180 1:E1:2D:53:2B:7C:6B:8A:29:A2:76:C8:64:36:0B:08:4B:7A:F1:9E:9D
182 * Peer validation always includes a check on whether the locally
183 configured expected DNS name or IP address of the server that
184 is contacted matches its presented certificate. DNS names and
185 IP addresses can be contained in the Common Name (CN) or
186 subjectAltName entries. For verification, only one of these
187 entries is to be considered. The following precedence
188 applies: for DNS name validation, subjectAltName:DNS has
189 precedence over CN; for IP address validation, subjectAltName:
190 iPAddr has precedence over CN.
192 * Implementations SHOULD allow to configure a set of acceptable
193 values for subjectAltName:URI.
196 tls_verify_cert (struct rs_connection *conn)
200 X509 *peer_cert = NULL;
201 struct in6_addr addr;
202 const char *hostname = NULL;
204 assert (conn->active_peer->conn == conn);
205 assert (conn->active_peer->hostname != NULL);
206 hostname = conn->active_peer->hostname;
208 /* verifytlscert() performs basic verification as described by
209 OpenSSL VERIFY(1), i.e. verification of the certificate chain. */
210 peer_cert = verifytlscert (conn->tls_ssl);
211 if (peer_cert == NULL)
213 err = rs_err_conn_push (conn, RSE_SSLERR,
214 "basic certificate validation failed");
218 if (inet_pton (AF_INET, hostname, &addr))
219 success = (subjectaltnameaddr (peer_cert, AF_INET, &addr) == 1);
220 else if (inet_pton (AF_INET6, hostname, &addr))
221 success = (subjectaltnameaddr (peer_cert, AF_INET6, &addr) == 1);
223 success = (subjectaltnameregexp (peer_cert, GEN_DNS, hostname, NULL) == 1);
226 success = (cnregexp (peer_cert, hostname, NULL) == 1);
228 if (conn->realm->disable_hostname_check)
231 err = rs_err_conn_push (conn, RSE_CERT, "server certificate doesn't "
232 "match configured hostname \"%s\"", hostname);
235 if (peer_cert != NULL)
236 X509_free (peer_cert);