1 /* Copyright 2010, 2011 NORDUnet A/S. All rights reserved.
2 See the file COPYING for licensing information. */
4 #if defined HAVE_CONFIG_H
9 #include <openssl/ssl.h>
10 #include <openssl/err.h>
11 #include <openssl/bn.h>
12 #include <openssl/x509v3.h>
13 #include <radsec/radsec.h>
14 #include <radsec/radsec-impl.h>
18 #include "../radsecproxy.h"
21 _get_tlsconf (struct rs_connection *conn, const struct rs_realm *realm)
23 struct tls *c = rs_malloc (conn->ctx, sizeof (struct tls));
27 memset (c, 0, sizeof (struct tls));
28 /* TODO: Make sure old radsecproxy code doesn't free these all
29 of a sudden, or strdup them. */
30 c->name = realm->name;
31 c->cacertfile = realm->cacertfile;
32 c->cacertpath = NULL; /* NYI */
33 c->certfile = realm->certfile;
34 c->certkeyfile = realm->certkeyfile;
35 c->certkeypwd = NULL; /* NYI */
36 c->cacheexpiry = 0; /* NYI */
37 c->crlcheck = 0; /* NYI */
38 c->policyoids = (char **) NULL; /* NYI */
41 rs_err_conn_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL);
46 #if defined RS_ENABLE_TLS_PSK
48 psk_client_cb (SSL *ssl,
51 unsigned int max_identity_len,
53 unsigned int max_psk_len)
55 struct rs_connection *conn = NULL;
56 struct rs_credentials *cred = NULL;
58 conn = SSL_get_ex_data (ssl, 0);
59 assert (conn != NULL);
60 cred = conn->active_peer->realm->transport_cred;
61 assert (cred != NULL);
62 /* NOTE: Ignoring identity hint from server. */
64 if (strlen (cred->identity) + 1 > max_identity_len)
66 rs_err_conn_push (conn, RSE_CRED, "PSK identity longer than max %d",
67 max_identity_len - 1);
70 strcpy (identity, cred->identity);
72 switch (cred->secret_encoding)
74 case RS_KEY_ENCODING_UTF8:
75 cred->secret_len = strlen (cred->secret);
76 if (cred->secret_len > max_psk_len)
78 rs_err_conn_push (conn, RSE_CRED, "PSK secret longer than max %d",
82 memcpy (psk, cred->secret, cred->secret_len);
84 case RS_KEY_ENCODING_ASCII_HEX:
88 if (BN_hex2bn (&bn, cred->secret) == 0)
90 rs_err_conn_push (conn, RSE_CRED, "Unable to convert pskhexstr");
95 if ((unsigned int) BN_num_bytes (bn) > max_psk_len)
97 rs_err_conn_push (conn, RSE_CRED, "PSK secret longer than max %d",
102 cred->secret_len = BN_bn2bin (bn, psk);
107 assert (!"unknown psk encoding");
110 return cred->secret_len;
112 #endif /* RS_ENABLE_TLS_PSK */
115 rs_tls_init (struct rs_connection *conn)
117 struct rs_context *ctx = NULL;
118 struct tls *tlsconf = NULL;
119 SSL_CTX *ssl_ctx = NULL;
121 unsigned long sslerr = 0;
126 tlsconf = _get_tlsconf (conn, conn->active_peer->realm);
129 ssl_ctx = tlsgetctx (RAD_TLS, tlsconf);
132 for (sslerr = ERR_get_error (); sslerr; sslerr = ERR_get_error ())
133 rs_err_conn_push_fl (conn, RSE_SSLERR, __FILE__, __LINE__,
134 ERR_error_string (sslerr, NULL));
137 ssl = SSL_new (ssl_ctx);
140 for (sslerr = ERR_get_error (); sslerr; sslerr = ERR_get_error ())
141 rs_err_conn_push_fl (conn, RSE_SSLERR, __FILE__, __LINE__,
142 ERR_error_string (sslerr, NULL));
146 #if defined RS_ENABLE_TLS_PSK
147 if (conn->active_peer->realm->transport_cred != NULL)
149 SSL_set_psk_client_callback (ssl, psk_client_cb);
150 SSL_set_ex_data (ssl, 0, conn);
152 #endif /* RS_ENABLE_TLS_PSK */
154 conn->tls_ctx = ssl_ctx;
156 rs_free (ctx, tlsconf);
160 /* draft-ietf-radext-radsec-11.txt
162 * Certificate validation MUST include the verification rules as
165 * Implementations SHOULD indicate their acceptable Certification
166 Authorities as per section 7.4.4 (server side) and x.y.z
167 ["Trusted CA Indication"] (client side) of [RFC5246] (see
170 * Implementations SHOULD allow to configure a list of acceptable
171 certificates, identified via certificate fingerprint. When a
172 fingerprint configured, the fingerprint is prepended with an
173 ASCII label identifying the hash function followed by a colon.
174 Implementations MUST support SHA-1 as the hash algorithm and
175 use the ASCII label "sha-1" to identify the SHA-1 algorithm.
176 The length of a SHA-1 hash is 20 bytes and the length of the
177 corresponding fingerprint string is 65 characters. An example
178 certificate fingerprint is: sha-
179 1:E1:2D:53:2B:7C:6B:8A:29:A2:76:C8:64:36:0B:08:4B:7A:F1:9E:9D
181 * Peer validation always includes a check on whether the locally
182 configured expected DNS name or IP address of the server that
183 is contacted matches its presented certificate. DNS names and
184 IP addresses can be contained in the Common Name (CN) or
185 subjectAltName entries. For verification, only one of these
186 entries is to be considered. The following precedence
187 applies: for DNS name validation, subjectAltName:DNS has
188 precedence over CN; for IP address validation, subjectAltName:
189 iPAddr has precedence over CN.
191 * Implementations SHOULD allow to configure a set of acceptable
192 values for subjectAltName:URI.
195 tls_verify_cert (struct rs_connection *conn)
199 X509 *peer_cert = NULL;
200 struct in6_addr addr;
201 const char *hostname = NULL;
203 assert (conn->active_peer->conn == conn);
204 assert (conn->active_peer->hostname != NULL);
205 hostname = conn->active_peer->hostname;
207 /* verifytlscert() performs basic verification as described by
208 OpenSSL VERIFY(1), i.e. verification of the certificate chain. */
209 peer_cert = verifytlscert (conn->tls_ssl);
210 if (peer_cert == NULL)
212 err = rs_err_conn_push (conn, RSE_SSLERR,
213 "basic certificate validation failed");
217 if (inet_pton(AF_INET, hostname, &addr))
218 success = (subjectaltnameaddr (peer_cert, AF_INET, &addr) == 1);
219 else if (inet_pton(AF_INET6, hostname, &addr))
220 success = (subjectaltnameaddr (peer_cert, AF_INET6, &addr) == 1);
222 success = (subjectaltnameregexp (peer_cert, GEN_DNS, hostname, NULL) == 1);
225 success = (cnregexp(peer_cert, hostname, NULL) == 1);
228 err = rs_err_conn_push (conn, RSE_CERT, "server certificate doesn't "
229 "match configured hostname \"%s\"", hostname);
232 if (peer_cert != NULL)
233 X509_free (peer_cert);