Move .gitignore to lib/ in preparation for moving lib to the root.
[libradsec.git] / 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 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 */
43         return 0;
44     memcpy(buf, userdata, pwdlen);
45     return pwdlen;
46 }
47
48 static int verify_cb(int ok, X509_STORE_CTX *ctx) {
49     char *buf = NULL;
50     X509 *err_cert;
51     int err, depth;
52
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);
56
57     if (depth > MAX_CERT_DEPTH) {
58         ok = 0;
59         err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
60         X509_STORE_CTX_set_error(ctx, err);
61     }
62
63     if (!ok) {
64         if (err_cert)
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 : "");
67         free(buf);
68         buf = NULL;
69
70         switch (err) {
71         case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
72             if (err_cert) {
73                 buf = X509_NAME_oneline(X509_get_issuer_name(err_cert), NULL, 0);
74                 if (buf) {
75                     debug(DBG_WARN, "\tIssuer=%s", buf);
76                     free(buf);
77                     buf = NULL;
78                 }
79             }
80             break;
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");
84             break;
85         case X509_V_ERR_CERT_HAS_EXPIRED:
86             debug(DBG_WARN, "Certificate has expired");
87             break;
88         case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
89             debug(DBG_WARN, "Certificate no longer valid (after notAfter)");
90             break;
91         case X509_V_ERR_NO_EXPLICIT_POLICY:
92             debug(DBG_WARN, "No Explicit Certificate Policy");
93             break;
94         }
95     }
96     return ok;
97 }
98
99 #ifdef DEBUG
100 static void ssl_info_callback(const SSL *ssl, int where, int ret) {
101     const char *s;
102     int w;
103
104     w = where & ~SSL_ST_MASK;
105
106     if (w & SSL_ST_CONNECT)
107         s = "SSL_connect";
108     else if (w & SSL_ST_ACCEPT)
109         s = "SSL_accept";
110     else
111         s = "undefined";
112
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));
118     }
119     else if (where & SSL_CB_EXIT) {
120         if (ret == 0)
121             debug(DBG_DBG, "%s:failed in %s\n", s, SSL_state_string_long(ssl));
122         else if (ret < 0)
123             debug(DBG_DBG, "%s:error in %s\n", s, SSL_state_string_long(ssl));
124     }
125 }
126 #endif
127
128 static X509_VERIFY_PARAM *createverifyparams(char **poids) {
129     X509_VERIFY_PARAM *pm;
130     ASN1_OBJECT *pobject;
131     int i;
132
133     pm = X509_VERIFY_PARAM_new();
134     if (!pm)
135         return NULL;
136
137     for (i = 0; poids[i]; i++) {
138         pobject = OBJ_txt2obj(poids[i], 0);
139         if (!pobject) {
140             X509_VERIFY_PARAM_free(pm);
141             return NULL;
142         }
143         X509_VERIFY_PARAM_add0_policy(pm, pobject);
144     }
145
146     X509_VERIFY_PARAM_set_flags(pm, X509_V_FLAG_POLICY_CHECK | X509_V_FLAG_EXPLICIT_POLICY);
147     return pm;
148 }
149
150 static int tlsaddcacrl(SSL_CTX *ctx, struct tls *conf) {
151     STACK_OF(X509_NAME) *calist;
152     X509_STORE *x509_s;
153     unsigned long error;
154
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);
159         return 0;
160     }
161
162         calist = conf->cacertfile ? SSL_load_client_CA_file(conf->cacertfile) : NULL;
163
164     if (!conf->cacertfile || calist) {
165         if (conf->cacertpath) {
166             if (!calist)
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);
170                 calist = NULL;
171             }
172         }
173     }
174     if (!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);
178         return 0;
179     }
180     ERR_clear_error(); /* add_dir_cert_subj returns errors on success */
181     SSL_CTX_set_client_CA_list(ctx, calist);
182
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);
185
186     if (conf->crlcheck || conf->vpm) {
187         x509_s = SSL_CTX_get_cert_store(ctx);
188         if (conf->crlcheck)
189             X509_STORE_set_flags(x509_s, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
190         if (conf->vpm)
191             X509_STORE_set1_param(x509_s, conf->vpm);
192     }
193
194     debug(DBG_DBG, "tlsaddcacrl: updated TLS context %s", conf->name);
195     return 1;
196 }
197
198 static SSL_CTX *tlscreatectx(uint8_t type, struct tls *conf) {
199     SSL_CTX *ctx = NULL;
200     unsigned long error;
201
202     switch (type) {
203 #ifdef RADPROT_TLS
204     case RAD_TLS:
205         ctx = SSL_CTX_new(TLSv1_method());
206         break;
207 #endif
208 #ifdef RADPROT_DTLS
209     case RAD_DTLS:
210         ctx = SSL_CTX_new(DTLSv1_method());
211         SSL_CTX_set_read_ahead(ctx, 1);
212         break;
213 #endif
214     }
215     if (!ctx) {
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));
219         return NULL;
220     }
221 #ifdef DEBUG
222         SSL_CTX_set_info_callback(ctx, ssl_info_callback);
223 #endif
224
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);
228     }
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);
236             SSL_CTX_free(ctx);
237             return NULL;
238         }
239     }
240
241     if (conf->policyoids) {
242         if (!conf->vpm) {
243             conf->vpm = createverifyparams(conf->policyoids);
244             if (!conf->vpm) {
245                 debug(DBG_ERR, "tlscreatectx: Failed to add policyOIDs in TLS context %s", conf->name);
246                 SSL_CTX_free(ctx);
247                 return NULL;
248             }
249         }
250     }
251
252     if (conf->cacertfile != NULL || conf->cacertpath != NULL)
253         if (!tlsaddcacrl(ctx, conf)) {
254             if (conf->vpm) {
255                 X509_VERIFY_PARAM_free(conf->vpm);
256                 conf->vpm = NULL;
257             }
258             SSL_CTX_free(ctx);
259             return NULL;
260         }
261
262     debug(DBG_DBG, "tlscreatectx: created TLS context %s", conf->name);
263     return ctx;
264 }
265
266 SSL_CTX *tlsgetctx(uint8_t type, struct tls *t) {
267     struct timeval now;
268
269     if (!t)
270         return NULL;
271     gettimeofday(&now, NULL);
272
273     switch (type) {
274 #ifdef RADPROT_TLS
275     case RAD_TLS:
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);
280             }
281         }
282         if (!t->tlsctx) {
283             t->tlsctx = tlscreatectx(RAD_TLS, t);
284             if (t->cacheexpiry)
285                 t->tlsexpiry = now.tv_sec + t->cacheexpiry;
286         }
287         return t->tlsctx;
288 #endif
289 #ifdef RADPROT_DTLS
290     case RAD_DTLS:
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);
295             }
296         }
297         if (!t->dtlsctx) {
298             t->dtlsctx = tlscreatectx(RAD_DTLS, t);
299             if (t->cacheexpiry)
300                 t->dtlsexpiry = now.tv_sec + t->cacheexpiry;
301         }
302         return t->dtlsctx;
303 #endif
304     }
305     return NULL;
306 }
307
308 X509 *verifytlscert(SSL *ssl) {
309     X509 *cert;
310     unsigned long error;
311
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));
316         return NULL;
317     }
318
319     cert = SSL_get_peer_certificate(ssl);
320     if (!cert)
321         debug(DBG_ERR, "verifytlscert: failed to obtain certificate");
322     return cert;
323 }
324
325 int subjectaltnameaddr(X509 *cert, int family, const struct in6_addr *addr) {
326     int loc, i, l, n, r = 0;
327     char *v;
328     X509_EXTENSION *ex;
329     STACK_OF(GENERAL_NAME) *alt;
330     GENERAL_NAME *gn;
331
332     debug(DBG_DBG, "subjectaltnameaddr");
333
334     loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
335     if (loc < 0)
336         return r;
337
338     ex = X509_get_ext(cert, loc);
339     alt = X509V3_EXT_d2i(ex);
340     if (!alt)
341         return r;
342
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)
347             continue;
348         r = -1;
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)) {
353             r = 1;
354             break;
355         }
356     }
357     GENERAL_NAMES_free(alt);
358     return r;
359 }
360
361 int subjectaltnameregexp(X509 *cert, int type, const char *exact,  const regex_t *regex) {
362     int loc, i, l, n, r = 0;
363     char *s, *v;
364     X509_EXTENSION *ex;
365     STACK_OF(GENERAL_NAME) *alt;
366     GENERAL_NAME *gn;
367
368     debug(DBG_DBG, "subjectaltnameregexp");
369
370     loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
371     if (loc < 0)
372         return r;
373
374     ex = X509_get_ext(cert, loc);
375     alt = X509V3_EXT_d2i(ex);
376     if (!alt)
377         return r;
378
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)
383             continue;
384         r = -1;
385         v = (char *)ASN1_STRING_data(gn->d.ia5);
386         l = ASN1_STRING_length(gn->d.ia5);
387         if (l <= 0)
388             continue;
389 #ifdef DEBUG
390         printfchars(NULL, gn->type == GEN_DNS ? "dns" : "uri", NULL, v, l);
391 #endif
392         if (exact) {
393             if (memcmp(v, exact, l))
394                 continue;
395         } else {
396             s = stringcopy((char *)v, l);
397             if (!s) {
398                 debug(DBG_ERR, "malloc failed");
399                 continue;
400             }
401             if (regexec(regex, s, 0, NULL, 0)) {
402                 free(s);
403                 continue;
404             }
405             free(s);
406         }
407         r = 1;
408         break;
409     }
410     GENERAL_NAMES_free(alt);
411     return r;
412 }
413
414 int cnregexp(X509 *cert, const char *exact, const regex_t *regex) {
415     int loc, l;
416     char *v, *s;
417     X509_NAME *nm;
418     X509_NAME_ENTRY *e;
419     ASN1_STRING *t;
420
421     nm = X509_get_subject_name(cert);
422     loc = -1;
423     for (;;) {
424         loc = X509_NAME_get_index_by_NID(nm, NID_commonName, loc);
425         if (loc == -1)
426             break;
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);
431         if (l < 0)
432             continue;
433         if (exact) {
434             if (l == strlen(exact) && !strncasecmp(exact, v, l))
435                 return 1;
436         } else {
437             s = stringcopy((char *)v, l);
438             if (!s) {
439                 debug(DBG_ERR, "malloc failed");
440                 continue;
441             }
442             if (regexec(regex, s, 0, NULL, 0)) {
443                 free(s);
444                 continue;
445             }
446             free(s);
447             return 1;
448         }
449     }
450     return 0;
451 }
452
453 /* Local Variables: */
454 /* c-file-style: "stroustrup" */
455 /* End: */