1 /* Copyright (c) 2007-2009, UNINETT AS
2 * Copyright (c) 2010-2011, NORDUnet A/S */
3 /* See LICENSE for licensing information. */
5 #if defined HAVE_CONFIG_H
11 #include <sys/socket.h>
12 #include <netinet/in.h>
21 #include <sys/select.h>
24 #include <arpa/inet.h>
28 #include <openssl/ssl.h>
29 #include <openssl/rand.h>
30 #include <openssl/err.h>
31 #include <openssl/md5.h>
32 #include <openssl/x509v3.h>
37 #include "hostport_types.h"
38 #include "radsecproxy.h"
40 static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) {
41 int pwdlen = strlen(userdata);
42 if (rwflag != 0 || pwdlen > size) /* not for decryption or too large */
44 memcpy(buf, userdata, pwdlen);
48 static int verify_cb(int ok, X509_STORE_CTX *ctx) {
53 err_cert = X509_STORE_CTX_get_current_cert(ctx);
54 err = X509_STORE_CTX_get_error(ctx);
55 depth = X509_STORE_CTX_get_error_depth(ctx);
57 if (depth > MAX_CERT_DEPTH) {
59 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
60 X509_STORE_CTX_set_error(ctx, err);
65 buf = X509_NAME_oneline(X509_get_subject_name(err_cert), NULL, 0);
66 debug(DBG_WARN, "verify error: num=%d:%s:depth=%d:%s", err, X509_verify_cert_error_string(err), depth, buf ? buf : "");
71 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
73 buf = X509_NAME_oneline(X509_get_issuer_name(err_cert), NULL, 0);
75 debug(DBG_WARN, "\tIssuer=%s", buf);
81 case X509_V_ERR_CERT_NOT_YET_VALID:
82 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
83 debug(DBG_WARN, "\tCertificate not yet valid");
85 case X509_V_ERR_CERT_HAS_EXPIRED:
86 debug(DBG_WARN, "Certificate has expired");
88 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
89 debug(DBG_WARN, "Certificate no longer valid (after notAfter)");
91 case X509_V_ERR_NO_EXPLICIT_POLICY:
92 debug(DBG_WARN, "No Explicit Certificate Policy");
100 static void ssl_info_callback(const SSL *ssl, int where, int ret) {
104 w = where & ~SSL_ST_MASK;
106 if (w & SSL_ST_CONNECT)
108 else if (w & SSL_ST_ACCEPT)
113 if (where & SSL_CB_LOOP)
114 debug(DBG_DBG, "%s:%s\n", s, SSL_state_string_long(ssl));
115 else if (where & SSL_CB_ALERT) {
116 s = (where & SSL_CB_READ) ? "read" : "write";
117 debug(DBG_DBG, "SSL3 alert %s:%s:%s\n", s, SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
119 else if (where & SSL_CB_EXIT) {
121 debug(DBG_DBG, "%s:failed in %s\n", s, SSL_state_string_long(ssl));
123 debug(DBG_DBG, "%s:error in %s\n", s, SSL_state_string_long(ssl));
128 static X509_VERIFY_PARAM *createverifyparams(char **poids) {
129 X509_VERIFY_PARAM *pm;
130 ASN1_OBJECT *pobject;
133 pm = X509_VERIFY_PARAM_new();
137 for (i = 0; poids[i]; i++) {
138 pobject = OBJ_txt2obj(poids[i], 0);
140 X509_VERIFY_PARAM_free(pm);
143 X509_VERIFY_PARAM_add0_policy(pm, pobject);
146 X509_VERIFY_PARAM_set_flags(pm, X509_V_FLAG_POLICY_CHECK | X509_V_FLAG_EXPLICIT_POLICY);
150 static int tlsaddcacrl(SSL_CTX *ctx, struct tls *conf) {
151 STACK_OF(X509_NAME) *calist;
155 if (!SSL_CTX_load_verify_locations(ctx, conf->cacertfile, conf->cacertpath)) {
156 while ((error = ERR_get_error()))
157 debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
158 debug(DBG_ERR, "tlsaddcacrl: Error updating TLS context %s", conf->name);
162 calist = conf->cacertfile ? SSL_load_client_CA_file(conf->cacertfile) : NULL;
164 if (!conf->cacertfile || calist) {
165 if (conf->cacertpath) {
167 calist = sk_X509_NAME_new_null();
168 if (!SSL_add_dir_cert_subjects_to_stack(calist, conf->cacertpath)) {
169 sk_X509_NAME_free(calist);
175 while ((error = ERR_get_error()))
176 debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
177 debug(DBG_ERR, "tlsaddcacrl: Error adding CA subjects in TLS context %s", conf->name);
180 ERR_clear_error(); /* add_dir_cert_subj returns errors on success */
181 SSL_CTX_set_client_CA_list(ctx, calist);
183 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb);
184 SSL_CTX_set_verify_depth(ctx, MAX_CERT_DEPTH + 1);
186 if (conf->crlcheck || conf->vpm) {
187 x509_s = SSL_CTX_get_cert_store(ctx);
189 X509_STORE_set_flags(x509_s, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
191 X509_STORE_set1_param(x509_s, conf->vpm);
194 debug(DBG_DBG, "tlsaddcacrl: updated TLS context %s", conf->name);
198 static SSL_CTX *tlscreatectx(uint8_t type, struct tls *conf) {
205 ctx = SSL_CTX_new(TLSv1_method());
210 ctx = SSL_CTX_new(DTLSv1_method());
211 SSL_CTX_set_read_ahead(ctx, 1);
216 debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS in TLS context %s", conf->name);
217 while ((error = ERR_get_error()))
218 debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
222 SSL_CTX_set_info_callback(ctx, ssl_info_callback);
225 if (conf->certkeypwd) {
226 SSL_CTX_set_default_passwd_cb_userdata(ctx, conf->certkeypwd);
227 SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
229 if (conf->certfile || conf->certkeyfile) {
230 if (!SSL_CTX_use_certificate_chain_file(ctx, conf->certfile) ||
231 !SSL_CTX_use_PrivateKey_file(ctx, conf->certkeyfile, SSL_FILETYPE_PEM) ||
232 !SSL_CTX_check_private_key(ctx)) {
233 while ((error = ERR_get_error()))
234 debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
235 debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS (certfile issues) in TLS context %s", conf->name);
241 if (conf->policyoids) {
243 conf->vpm = createverifyparams(conf->policyoids);
245 debug(DBG_ERR, "tlscreatectx: Failed to add policyOIDs in TLS context %s", conf->name);
252 if (conf->cacertfile != NULL || conf->cacertpath != NULL)
253 if (!tlsaddcacrl(ctx, conf)) {
255 X509_VERIFY_PARAM_free(conf->vpm);
262 debug(DBG_DBG, "tlscreatectx: created TLS context %s", conf->name);
266 SSL_CTX *tlsgetctx(uint8_t type, struct tls *t) {
271 gettimeofday(&now, NULL);
276 if (t->tlsexpiry && t->tlsctx) {
277 if (t->tlsexpiry < now.tv_sec) {
278 t->tlsexpiry = now.tv_sec + t->cacheexpiry;
279 tlsaddcacrl(t->tlsctx, t);
283 t->tlsctx = tlscreatectx(RAD_TLS, t);
285 t->tlsexpiry = now.tv_sec + t->cacheexpiry;
291 if (t->dtlsexpiry && t->dtlsctx) {
292 if (t->dtlsexpiry < now.tv_sec) {
293 t->dtlsexpiry = now.tv_sec + t->cacheexpiry;
294 tlsaddcacrl(t->dtlsctx, t);
298 t->dtlsctx = tlscreatectx(RAD_DTLS, t);
300 t->dtlsexpiry = now.tv_sec + t->cacheexpiry;
308 X509 *verifytlscert(SSL *ssl) {
312 if (SSL_get_verify_result(ssl) != X509_V_OK) {
313 debug(DBG_ERR, "verifytlscert: basic validation failed");
314 while ((error = ERR_get_error()))
315 debug(DBG_ERR, "verifytlscert: TLS: %s", ERR_error_string(error, NULL));
319 cert = SSL_get_peer_certificate(ssl);
321 debug(DBG_ERR, "verifytlscert: failed to obtain certificate");
325 int subjectaltnameaddr(X509 *cert, int family, const struct in6_addr *addr) {
326 int loc, i, l, n, r = 0;
329 STACK_OF(GENERAL_NAME) *alt;
332 debug(DBG_DBG, "subjectaltnameaddr");
334 loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
338 ex = X509_get_ext(cert, loc);
339 alt = X509V3_EXT_d2i(ex);
343 n = sk_GENERAL_NAME_num(alt);
344 for (i = 0; i < n; i++) {
345 gn = sk_GENERAL_NAME_value(alt, i);
346 if (gn->type != GEN_IPADD)
349 v = (char *)ASN1_STRING_data(gn->d.ia5);
350 l = ASN1_STRING_length(gn->d.ia5);
351 if (((family == AF_INET && l == sizeof(struct in_addr)) || (family == AF_INET6 && l == sizeof(struct in6_addr)))
352 && !memcmp(v, &addr, l)) {
357 GENERAL_NAMES_free(alt);
361 int subjectaltnameregexp(X509 *cert, int type, const char *exact, const regex_t *regex) {
362 int loc, i, l, n, r = 0;
365 STACK_OF(GENERAL_NAME) *alt;
368 debug(DBG_DBG, "subjectaltnameregexp");
370 loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
374 ex = X509_get_ext(cert, loc);
375 alt = X509V3_EXT_d2i(ex);
379 n = sk_GENERAL_NAME_num(alt);
380 for (i = 0; i < n; i++) {
381 gn = sk_GENERAL_NAME_value(alt, i);
382 if (gn->type != type)
385 v = (char *)ASN1_STRING_data(gn->d.ia5);
386 l = ASN1_STRING_length(gn->d.ia5);
390 printfchars(NULL, gn->type == GEN_DNS ? "dns" : "uri", NULL, v, l);
393 if (memcmp(v, exact, l))
396 s = stringcopy((char *)v, l);
398 debug(DBG_ERR, "malloc failed");
401 if (regexec(regex, s, 0, NULL, 0)) {
410 GENERAL_NAMES_free(alt);
414 int cnregexp(X509 *cert, const char *exact, const regex_t *regex) {
421 nm = X509_get_subject_name(cert);
424 loc = X509_NAME_get_index_by_NID(nm, NID_commonName, loc);
427 e = X509_NAME_get_entry(nm, loc);
428 t = X509_NAME_ENTRY_get_data(e);
429 v = (char *) ASN1_STRING_data(t);
430 l = ASN1_STRING_length(t);
434 if (l == strlen(exact) && !strncasecmp(exact, v, l))
437 s = stringcopy((char *)v, l);
439 debug(DBG_ERR, "malloc failed");
442 if (regexec(regex, s, 0, NULL, 0)) {
453 /* Local Variables: */
454 /* c-file-style: "stroustrup" */