002788db84f64e8718df58bee4567ebfe724caea
[radsecproxy.git] / lib / radsecproxy / tlscommon.c
1 /* Copyright (c) 2007-2009, UNINETT AS
2  * Copyright (c) 2010-2011, NORDUnet A/S */
3 /* See LICENSE for licensing information. */
4
5 #if defined HAVE_CONFIG_H
6 #include <config.h>
7 #endif
8
9 #include <sys/types.h>
10 #include <signal.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <netdb.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <limits.h>
17 #ifdef SYS_SOLARIS9
18 #include <fcntl.h>
19 #endif
20 #include <sys/time.h>
21 #include <sys/select.h>
22 #include <ctype.h>
23 #include <sys/wait.h>
24 #include <arpa/inet.h>
25 #include <regex.h>
26 #include <libgen.h>
27 #include <pthread.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>
33 #include "debug.h"
34 #include "list.h"
35 #include "hash.h"
36 #include "util.h"
37 #include "hostport_types.h"
38 #include "radsecproxy.h"
39
40 static struct hash *tlsconfs = NULL;
41
42 void ssl_init(void) {
43     time_t t;
44     pid_t pid;
45
46     SSL_load_error_strings();
47     SSL_library_init();
48
49     while (!RAND_status()) {
50         t = time(NULL);
51         pid = getpid();
52         RAND_seed((unsigned char *)&t, sizeof(time_t));
53         RAND_seed((unsigned char *)&pid, sizeof(pid));
54     }
55 }
56
57 static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) {
58     int pwdlen = strlen(userdata);
59     if (rwflag != 0 || pwdlen > size) /* not for decryption or too large */
60         return 0;
61     memcpy(buf, userdata, pwdlen);
62     return pwdlen;
63 }
64
65 static int verify_cb(int ok, X509_STORE_CTX *ctx) {
66     char *buf = NULL;
67     X509 *err_cert;
68     int err, depth;
69
70     err_cert = X509_STORE_CTX_get_current_cert(ctx);
71     err = X509_STORE_CTX_get_error(ctx);
72     depth = X509_STORE_CTX_get_error_depth(ctx);
73
74     if (depth > MAX_CERT_DEPTH) {
75         ok = 0;
76         err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
77         X509_STORE_CTX_set_error(ctx, err);
78     }
79
80     if (!ok) {
81         if (err_cert)
82             buf = X509_NAME_oneline(X509_get_subject_name(err_cert), NULL, 0);
83         debug(DBG_WARN, "verify error: num=%d:%s:depth=%d:%s", err, X509_verify_cert_error_string(err), depth, buf ? buf : "");
84         free(buf);
85         buf = NULL;
86
87         switch (err) {
88         case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
89             if (err_cert) {
90                 buf = X509_NAME_oneline(X509_get_issuer_name(err_cert), NULL, 0);
91                 if (buf) {
92                     debug(DBG_WARN, "\tIssuer=%s", buf);
93                     free(buf);
94                     buf = NULL;
95                 }
96             }
97             break;
98         case X509_V_ERR_CERT_NOT_YET_VALID:
99         case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
100             debug(DBG_WARN, "\tCertificate not yet valid");
101             break;
102         case X509_V_ERR_CERT_HAS_EXPIRED:
103             debug(DBG_WARN, "Certificate has expired");
104             break;
105         case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
106             debug(DBG_WARN, "Certificate no longer valid (after notAfter)");
107             break;
108         case X509_V_ERR_NO_EXPLICIT_POLICY:
109             debug(DBG_WARN, "No Explicit Certificate Policy");
110             break;
111         }
112     }
113     return ok;
114 }
115
116 #ifdef DEBUG
117 static void ssl_info_callback(const SSL *ssl, int where, int ret) {
118     const char *s;
119     int w;
120
121     w = where & ~SSL_ST_MASK;
122
123     if (w & SSL_ST_CONNECT)
124         s = "SSL_connect";
125     else if (w & SSL_ST_ACCEPT)
126         s = "SSL_accept";
127     else
128         s = "undefined";
129
130     if (where & SSL_CB_LOOP)
131         debug(DBG_DBG, "%s:%s\n", s, SSL_state_string_long(ssl));
132     else if (where & SSL_CB_ALERT) {
133         s = (where & SSL_CB_READ) ? "read" : "write";
134         debug(DBG_DBG, "SSL3 alert %s:%s:%s\n", s, SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
135     }
136     else if (where & SSL_CB_EXIT) {
137         if (ret == 0)
138             debug(DBG_DBG, "%s:failed in %s\n", s, SSL_state_string_long(ssl));
139         else if (ret < 0)
140             debug(DBG_DBG, "%s:error in %s\n", s, SSL_state_string_long(ssl));
141     }
142 }
143 #endif
144
145 static X509_VERIFY_PARAM *createverifyparams(char **poids) {
146     X509_VERIFY_PARAM *pm;
147     ASN1_OBJECT *pobject;
148     int i;
149
150     pm = X509_VERIFY_PARAM_new();
151     if (!pm)
152         return NULL;
153
154     for (i = 0; poids[i]; i++) {
155         pobject = OBJ_txt2obj(poids[i], 0);
156         if (!pobject) {
157             X509_VERIFY_PARAM_free(pm);
158             return NULL;
159         }
160         X509_VERIFY_PARAM_add0_policy(pm, pobject);
161     }
162
163     X509_VERIFY_PARAM_set_flags(pm, X509_V_FLAG_POLICY_CHECK | X509_V_FLAG_EXPLICIT_POLICY);
164     return pm;
165 }
166
167 static int tlsaddcacrl(SSL_CTX *ctx, struct tls *conf) {
168     STACK_OF(X509_NAME) *calist;
169     X509_STORE *x509_s;
170     unsigned long error;
171
172     if (!SSL_CTX_load_verify_locations(ctx, conf->cacertfile, conf->cacertpath)) {
173         while ((error = ERR_get_error()))
174             debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
175         debug(DBG_ERR, "tlsaddcacrl: Error updating TLS context %s", conf->name);
176         return 0;
177     }
178
179         calist = conf->cacertfile ? SSL_load_client_CA_file(conf->cacertfile) : NULL;
180
181     if (!conf->cacertfile || calist) {
182         if (conf->cacertpath) {
183             if (!calist)
184                 calist = sk_X509_NAME_new_null();
185             if (!SSL_add_dir_cert_subjects_to_stack(calist, conf->cacertpath)) {
186                 sk_X509_NAME_free(calist);
187                 calist = NULL;
188             }
189         }
190     }
191     if (!calist) {
192         while ((error = ERR_get_error()))
193             debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
194         debug(DBG_ERR, "tlsaddcacrl: Error adding CA subjects in TLS context %s", conf->name);
195         return 0;
196     }
197     ERR_clear_error(); /* add_dir_cert_subj returns errors on success */
198     SSL_CTX_set_client_CA_list(ctx, calist);
199
200     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb);
201     SSL_CTX_set_verify_depth(ctx, MAX_CERT_DEPTH + 1);
202
203     if (conf->crlcheck || conf->vpm) {
204         x509_s = SSL_CTX_get_cert_store(ctx);
205         if (conf->crlcheck)
206             X509_STORE_set_flags(x509_s, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
207         if (conf->vpm)
208             X509_STORE_set1_param(x509_s, conf->vpm);
209     }
210
211     debug(DBG_DBG, "tlsaddcacrl: updated TLS context %s", conf->name);
212     return 1;
213 }
214
215 static SSL_CTX *tlscreatectx(uint8_t type, struct tls *conf) {
216     SSL_CTX *ctx = NULL;
217     unsigned long error;
218
219     switch (type) {
220 #ifdef RADPROT_TLS
221     case RAD_TLS:
222         ctx = SSL_CTX_new(TLSv1_method());
223         break;
224 #endif
225 #ifdef RADPROT_DTLS
226     case RAD_DTLS:
227         ctx = SSL_CTX_new(DTLSv1_method());
228         SSL_CTX_set_read_ahead(ctx, 1);
229         break;
230 #endif
231     }
232     if (!ctx) {
233         debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS in TLS context %s", conf->name);
234         while ((error = ERR_get_error()))
235             debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
236         return NULL;
237     }
238 #ifdef DEBUG
239         SSL_CTX_set_info_callback(ctx, ssl_info_callback);
240 #endif
241
242     if (conf->certkeypwd) {
243         SSL_CTX_set_default_passwd_cb_userdata(ctx, conf->certkeypwd);
244         SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
245     }
246     if (conf->certfile || conf->certkeyfile) {
247         if (!SSL_CTX_use_certificate_chain_file(ctx, conf->certfile) ||
248             !SSL_CTX_use_PrivateKey_file(ctx, conf->certkeyfile, SSL_FILETYPE_PEM) ||
249             !SSL_CTX_check_private_key(ctx)) {
250             while ((error = ERR_get_error()))
251                 debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
252             debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS (certfile issues) in TLS context %s", conf->name);
253             SSL_CTX_free(ctx);
254             return NULL;
255         }
256     }
257
258     if (conf->policyoids) {
259         if (!conf->vpm) {
260             conf->vpm = createverifyparams(conf->policyoids);
261             if (!conf->vpm) {
262                 debug(DBG_ERR, "tlscreatectx: Failed to add policyOIDs in TLS context %s", conf->name);
263                 SSL_CTX_free(ctx);
264                 return NULL;
265             }
266         }
267     }
268
269     if (conf->cacertfile != NULL || conf->cacertpath != NULL)
270         if (!tlsaddcacrl(ctx, conf)) {
271             if (conf->vpm) {
272                 X509_VERIFY_PARAM_free(conf->vpm);
273                 conf->vpm = NULL;
274             }
275             SSL_CTX_free(ctx);
276             return NULL;
277         }
278
279     debug(DBG_DBG, "tlscreatectx: created TLS context %s", conf->name);
280     return ctx;
281 }
282
283 struct tls *tlsgettls(char *alt1, char *alt2) {
284     struct tls *t;
285
286     t = hash_read(tlsconfs, alt1, strlen(alt1));
287     if (!t)
288         t = hash_read(tlsconfs, alt2, strlen(alt2));
289     return t;
290 }
291
292 SSL_CTX *tlsgetctx(uint8_t type, struct tls *t) {
293     struct timeval now;
294
295     if (!t)
296         return NULL;
297     gettimeofday(&now, NULL);
298
299     switch (type) {
300 #ifdef RADPROT_TLS
301     case RAD_TLS:
302         if (t->tlsexpiry && t->tlsctx) {
303             if (t->tlsexpiry < now.tv_sec) {
304                 t->tlsexpiry = now.tv_sec + t->cacheexpiry;
305                 tlsaddcacrl(t->tlsctx, t);
306             }
307         }
308         if (!t->tlsctx) {
309             t->tlsctx = tlscreatectx(RAD_TLS, t);
310             if (t->cacheexpiry)
311                 t->tlsexpiry = now.tv_sec + t->cacheexpiry;
312         }
313         return t->tlsctx;
314 #endif
315 #ifdef RADPROT_DTLS
316     case RAD_DTLS:
317         if (t->dtlsexpiry && t->dtlsctx) {
318             if (t->dtlsexpiry < now.tv_sec) {
319                 t->dtlsexpiry = now.tv_sec + t->cacheexpiry;
320                 tlsaddcacrl(t->dtlsctx, t);
321             }
322         }
323         if (!t->dtlsctx) {
324             t->dtlsctx = tlscreatectx(RAD_DTLS, t);
325             if (t->cacheexpiry)
326                 t->dtlsexpiry = now.tv_sec + t->cacheexpiry;
327         }
328         return t->dtlsctx;
329 #endif
330     }
331     return NULL;
332 }
333
334 X509 *verifytlscert(SSL *ssl) {
335     X509 *cert;
336     unsigned long error;
337
338     if (SSL_get_verify_result(ssl) != X509_V_OK) {
339         debug(DBG_ERR, "verifytlscert: basic validation failed");
340         while ((error = ERR_get_error()))
341             debug(DBG_ERR, "verifytlscert: TLS: %s", ERR_error_string(error, NULL));
342         return NULL;
343     }
344
345     cert = SSL_get_peer_certificate(ssl);
346     if (!cert)
347         debug(DBG_ERR, "verifytlscert: failed to obtain certificate");
348     return cert;
349 }
350
351 int subjectaltnameaddr(X509 *cert, int family, const struct in6_addr *addr) {
352     int loc, i, l, n, r = 0;
353     char *v;
354     X509_EXTENSION *ex;
355     STACK_OF(GENERAL_NAME) *alt;
356     GENERAL_NAME *gn;
357
358     debug(DBG_DBG, "subjectaltnameaddr");
359
360     loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
361     if (loc < 0)
362         return r;
363
364     ex = X509_get_ext(cert, loc);
365     alt = X509V3_EXT_d2i(ex);
366     if (!alt)
367         return r;
368
369     n = sk_GENERAL_NAME_num(alt);
370     for (i = 0; i < n; i++) {
371         gn = sk_GENERAL_NAME_value(alt, i);
372         if (gn->type != GEN_IPADD)
373             continue;
374         r = -1;
375         v = (char *)ASN1_STRING_data(gn->d.ia5);
376         l = ASN1_STRING_length(gn->d.ia5);
377         if (((family == AF_INET && l == sizeof(struct in_addr)) || (family == AF_INET6 && l == sizeof(struct in6_addr)))
378             && !memcmp(v, &addr, l)) {
379             r = 1;
380             break;
381         }
382     }
383     GENERAL_NAMES_free(alt);
384     return r;
385 }
386
387 int subjectaltnameregexp(X509 *cert, int type, const char *exact,  const regex_t *regex) {
388     int loc, i, l, n, r = 0;
389     char *s, *v;
390     X509_EXTENSION *ex;
391     STACK_OF(GENERAL_NAME) *alt;
392     GENERAL_NAME *gn;
393
394     debug(DBG_DBG, "subjectaltnameregexp");
395
396     loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
397     if (loc < 0)
398         return r;
399
400     ex = X509_get_ext(cert, loc);
401     alt = X509V3_EXT_d2i(ex);
402     if (!alt)
403         return r;
404
405     n = sk_GENERAL_NAME_num(alt);
406     for (i = 0; i < n; i++) {
407         gn = sk_GENERAL_NAME_value(alt, i);
408         if (gn->type != type)
409             continue;
410         r = -1;
411         v = (char *)ASN1_STRING_data(gn->d.ia5);
412         l = ASN1_STRING_length(gn->d.ia5);
413         if (l <= 0)
414             continue;
415 #ifdef DEBUG
416         printfchars(NULL, gn->type == GEN_DNS ? "dns" : "uri", NULL, v, l);
417 #endif
418         if (exact) {
419             if (memcmp(v, exact, l))
420                 continue;
421         } else {
422             s = stringcopy((char *)v, l);
423             if (!s) {
424                 debug(DBG_ERR, "malloc failed");
425                 continue;
426             }
427             if (regexec(regex, s, 0, NULL, 0)) {
428                 free(s);
429                 continue;
430             }
431             free(s);
432         }
433         r = 1;
434         break;
435     }
436     GENERAL_NAMES_free(alt);
437     return r;
438 }
439
440 int cnregexp(X509 *cert, const char *exact, const regex_t *regex) {
441     int loc, l;
442     char *v, *s;
443     X509_NAME *nm;
444     X509_NAME_ENTRY *e;
445     ASN1_STRING *t;
446
447     nm = X509_get_subject_name(cert);
448     loc = -1;
449     for (;;) {
450         loc = X509_NAME_get_index_by_NID(nm, NID_commonName, loc);
451         if (loc == -1)
452             break;
453         e = X509_NAME_get_entry(nm, loc);
454         t = X509_NAME_ENTRY_get_data(e);
455         v = (char *) ASN1_STRING_data(t);
456         l = ASN1_STRING_length(t);
457         if (l < 0)
458             continue;
459         if (exact) {
460             if (l == strlen(exact) && !strncasecmp(exact, v, l))
461                 return 1;
462         } else {
463             s = stringcopy((char *)v, l);
464             if (!s) {
465                 debug(DBG_ERR, "malloc failed");
466                 continue;
467             }
468             if (regexec(regex, s, 0, NULL, 0)) {
469                 free(s);
470                 continue;
471             }
472             free(s);
473             return 1;
474         }
475     }
476     return 0;
477 }
478
479 /* this is a bit sloppy, should not always accept match to any */
480 int certnamecheck(X509 *cert, struct list *hostports) {
481     struct list_node *entry;
482     struct hostportres *hp;
483     int r;
484     uint8_t type = 0; /* 0 for DNS, AF_INET for IPv4, AF_INET6 for IPv6 */
485     struct in6_addr addr;
486
487     for (entry = list_first(hostports); entry; entry = list_next(entry)) {
488         hp = (struct hostportres *)entry->data;
489         if (hp->prefixlen != 255) {
490             /* we disable the check for prefixes */
491             return 1;
492         }
493         if (inet_pton(AF_INET, hp->host, &addr))
494             type = AF_INET;
495         else if (inet_pton(AF_INET6, hp->host, &addr))
496             type = AF_INET6;
497         else
498             type = 0;
499
500         r = type ? subjectaltnameaddr(cert, type, &addr) : subjectaltnameregexp(cert, GEN_DNS, hp->host, NULL);
501         if (r) {
502             if (r > 0) {
503                 debug(DBG_DBG, "certnamecheck: Found subjectaltname matching %s %s", type ? "address" : "host", hp->host);
504                 return 1;
505             }
506             debug(DBG_WARN, "certnamecheck: No subjectaltname matching %s %s", type ? "address" : "host", hp->host);
507         } else {
508             if (cnregexp(cert, hp->host, NULL)) {
509                 debug(DBG_DBG, "certnamecheck: Found cn matching host %s", hp->host);
510                 return 1;
511             }
512             debug(DBG_WARN, "certnamecheck: cn not matching host %s", hp->host);
513         }
514     }
515     return 0;
516 }
517
518 int verifyconfcert(X509 *cert, struct clsrvconf *conf) {
519     if (conf->certnamecheck) {
520         if (!certnamecheck(cert, conf->hostports)) {
521             debug(DBG_WARN, "verifyconfcert: certificate name check failed");
522             return 0;
523         }
524         debug(DBG_WARN, "verifyconfcert: certificate name check ok");
525     }
526     if (conf->certcnregex) {
527         if (cnregexp(cert, NULL, conf->certcnregex) < 1) {
528             debug(DBG_WARN, "verifyconfcert: CN not matching regex");
529             return 0;
530         }
531         debug(DBG_DBG, "verifyconfcert: CN matching regex");
532     }
533     if (conf->certuriregex) {
534         if (subjectaltnameregexp(cert, GEN_URI, NULL, conf->certuriregex) < 1) {
535             debug(DBG_WARN, "verifyconfcert: subjectaltname URI not matching regex");
536             return 0;
537         }
538         debug(DBG_DBG, "verifyconfcert: subjectaltname URI matching regex");
539     }
540     return 1;
541 }
542
543 /* Local Variables: */
544 /* c-file-style: "stroustrup" */
545 /* End: */