1/*
2 *  OpenVPN -- An application to securely tunnel IP networks
3 *             over a single TCP/UDP port, with support for SSL/TLS-based
4 *             session authentication and key exchange,
5 *             packet encryption, packet authentication, and
6 *             packet compression.
7 *
8 *  Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
9 *  Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com>
10 *
11 *  This program is free software; you can redistribute it and/or modify
12 *  it under the terms of the GNU General Public License version 2
13 *  as published by the Free Software Foundation.
14 *
15 *  This program is distributed in the hope that it will be useful,
16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 *  GNU General Public License for more details.
19 *
20 *  You should have received a copy of the GNU General Public License
21 *  along with this program (see the file COPYING included with this
22 *  distribution); if not, write to the Free Software Foundation, Inc.,
23 *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 */
25
26/**
27 * @file Control Channel Verification Module OpenSSL implementation
28 */
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#elif defined(_MSC_VER)
33#include "config-msvc.h"
34#endif
35
36#include "syshead.h"
37
38#if defined(ENABLE_SSL) && defined(ENABLE_CRYPTO_OPENSSL)
39
40#include "ssl_verify.h"
41#include "ssl_verify_backend.h"
42#include "ssl_openssl.h"
43#include <openssl/x509v3.h>
44#include <openssl/err.h>
45
46int
47verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
48{
49  int ret = 0;
50  struct tls_session *session;
51  SSL *ssl;
52  struct gc_arena gc = gc_new();
53
54  /* get the tls_session pointer */
55  ssl = X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
56  ASSERT (ssl);
57  session = (struct tls_session *) SSL_get_ex_data (ssl, mydata_index);
58  ASSERT (session);
59
60  cert_hash_remember (session, ctx->error_depth,
61      x509_get_sha1_hash(ctx->current_cert, &gc));
62
63  /* did peer present cert which was signed by our root cert? */
64  if (!preverify_ok)
65    {
66      /* get the X509 name */
67      char *subject = x509_get_subject(ctx->current_cert, &gc);
68
69      if (subject)
70	{
71	  /* Remote site specified a certificate, but it's not correct */
72	  msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, error=%s: %s",
73	      ctx->error_depth,
74	      X509_verify_cert_error_string (ctx->error),
75	      subject);
76	}
77
78      ERR_clear_error();
79
80      session->verified = false;
81      goto cleanup;
82    }
83
84  if (SUCCESS != verify_cert(session, ctx->current_cert, ctx->error_depth))
85    goto cleanup;
86
87  ret = 1;
88
89cleanup:
90  gc_free(&gc);
91
92  return ret;
93}
94
95#ifdef ENABLE_X509ALTUSERNAME
96static
97bool extract_x509_extension(X509 *cert, char *fieldname, char *out, int size)
98{
99  bool retval = false;
100  X509_EXTENSION *pExt;
101  char *buf = 0;
102  int length = 0;
103  GENERAL_NAMES *extensions;
104  int nid = OBJ_txt2nid(fieldname);
105
106  extensions = (GENERAL_NAMES *)X509_get_ext_d2i(cert, nid, NULL, NULL);
107  if ( extensions )
108    {
109      int numalts;
110      int i;
111      /* get amount of alternatives,
112       * RFC2459 claims there MUST be at least
113       * one, but we don't depend on it...
114       */
115
116      numalts = sk_GENERAL_NAME_num(extensions);
117
118      /* loop through all alternatives */
119      for (i=0; i<numalts; i++)
120        {
121          /* get a handle to alternative name number i */
122          const GENERAL_NAME *name = sk_GENERAL_NAME_value (extensions, i );
123
124          switch (name->type)
125            {
126              case GEN_EMAIL:
127                ASN1_STRING_to_UTF8((unsigned char**)&buf, name->d.ia5);
128                if ( strlen (buf) != name->d.ia5->length )
129                  {
130                    msg (D_TLS_ERRORS, "ASN1 ERROR: string contained terminating zero");
131                    OPENSSL_free (buf);
132                  } else {
133                    strncpynt(out, buf, size);
134                    OPENSSL_free(buf);
135                    retval = true;
136                  }
137                break;
138              default:
139                msg (D_TLS_ERRORS, "ASN1 ERROR: can not handle field type %i",
140                     name->type);
141                break;
142            }
143          }
144        sk_GENERAL_NAME_free (extensions);
145    }
146  return retval;
147}
148#endif /* ENABLE_X509ALTUSERNAME */
149
150/*
151 * Extract a field from an X509 subject name.
152 *
153 * Example:
154 *
155 * /C=US/ST=CO/L=Denver/O=ORG/CN=First-CN/CN=Test-CA/Email=jim@yonan.net
156 *
157 * The common name is 'Test-CA'
158 *
159 * Return true on success, false on error (insufficient buffer size in 'out'
160 * to contain result is grounds for error).
161 */
162static result_t
163extract_x509_field_ssl (X509_NAME *x509, const char *field_name, char *out,
164    int size)
165{
166  int lastpos = -1;
167  int tmp = -1;
168  X509_NAME_ENTRY *x509ne = 0;
169  ASN1_STRING *asn1 = 0;
170  unsigned char *buf = (unsigned char *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */
171  int nid = OBJ_txt2nid((char *)field_name);
172
173  ASSERT (size > 0);
174  *out = '\0';
175  do {
176    lastpos = tmp;
177    tmp = X509_NAME_get_index_by_NID(x509, nid, lastpos);
178  } while (tmp > -1);
179
180  /* Nothing found */
181  if (lastpos == -1)
182    return FAILURE;
183
184  x509ne = X509_NAME_get_entry(x509, lastpos);
185  if (!x509ne)
186    return FAILURE;
187
188  asn1 = X509_NAME_ENTRY_get_data(x509ne);
189  if (!asn1)
190    return FAILURE;
191  tmp = ASN1_STRING_to_UTF8(&buf, asn1);
192  if (tmp <= 0)
193    return FAILURE;
194
195  strncpynt(out, (char *)buf, size);
196
197  {
198    const result_t ret = (strlen ((char *)buf) < size) ? SUCCESS: FAILURE;
199    OPENSSL_free (buf);
200    return ret;
201  }
202}
203
204result_t
205x509_get_username (char *common_name, int cn_len,
206    char * x509_username_field, X509 *peer_cert)
207{
208#ifdef ENABLE_X509ALTUSERNAME
209  if (strncmp("ext:",x509_username_field,4) == 0)
210    {
211      if (!extract_x509_extension (peer_cert, x509_username_field+4, common_name, cn_len))
212	return FAILURE;
213    } else
214#endif
215  if (FAILURE == extract_x509_field_ssl (X509_get_subject_name (peer_cert),
216      x509_username_field, common_name, cn_len))
217      return FAILURE;
218
219  return SUCCESS;
220}
221
222char *
223x509_get_serial (openvpn_x509_cert_t *cert, struct gc_arena *gc)
224{
225  ASN1_INTEGER *asn1_i;
226  BIGNUM *bignum;
227  char *openssl_serial, *serial;
228
229  asn1_i = X509_get_serialNumber(cert);
230  bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
231  openssl_serial = BN_bn2dec(bignum);
232
233  serial = string_alloc(openssl_serial, gc);
234
235  BN_free(bignum);
236  OPENSSL_free(openssl_serial);
237
238  return serial;
239}
240
241unsigned char *
242x509_get_sha1_hash (X509 *cert, struct gc_arena *gc)
243{
244  char *hash = gc_malloc(SHA_DIGEST_LENGTH, false, gc);
245  memcpy(hash, cert->sha1_hash, SHA_DIGEST_LENGTH);
246  return hash;
247}
248
249char *
250x509_get_subject (X509 *cert, struct gc_arena *gc)
251{
252  BIO *subject_bio = NULL;
253  BUF_MEM *subject_mem;
254  char *subject = NULL;
255  int maxlen = 0;
256
257  /*
258   * Generate the subject string in OpenSSL proprietary format,
259   * when in --compat-names mode
260   */
261  if (compat_flag (COMPAT_FLAG_QUERY | COMPAT_NAMES))
262    {
263      subject = gc_malloc (256, false, gc);
264      X509_NAME_oneline (X509_get_subject_name (cert), subject, 256);
265      subject[255] = '\0';
266      return subject;
267    }
268
269  subject_bio = BIO_new (BIO_s_mem ());
270  if (subject_bio == NULL)
271    goto err;
272
273  X509_NAME_print_ex (subject_bio, X509_get_subject_name (cert),
274                      0, XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_FN_SN |
275                      ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_CTRL);
276
277  if (BIO_eof (subject_bio))
278    goto err;
279
280  BIO_get_mem_ptr (subject_bio, &subject_mem);
281
282  maxlen = subject_mem->length + 1;
283  subject = gc_malloc (maxlen, false, gc);
284
285  memcpy (subject, subject_mem->data, maxlen);
286  subject[maxlen - 1] = '\0';
287
288err:
289  if (subject_bio)
290    BIO_free (subject_bio);
291
292  return subject;
293}
294
295
296#ifdef ENABLE_X509_TRACK
297
298void
299x509_track_add (const struct x509_track **ll_head, const char *name, int msglevel, struct gc_arena *gc)
300{
301  struct x509_track *xt;
302  ALLOC_OBJ_CLEAR_GC (xt, struct x509_track, gc);
303  if (*name == '+')
304    {
305      xt->flags |= XT_FULL_CHAIN;
306      ++name;
307    }
308  xt->name = name;
309  xt->nid = OBJ_txt2nid(name);
310  if (xt->nid != NID_undef)
311    {
312      xt->next = *ll_head;
313      *ll_head = xt;
314    }
315  else
316    msg(msglevel, "x509_track: no such attribute '%s'", name);
317}
318
319/* worker method for setenv_x509_track */
320static void
321do_setenv_x509 (struct env_set *es, const char *name, char *value, int depth)
322{
323  char *name_expand;
324  size_t name_expand_size;
325
326  string_mod (value, CC_ANY, CC_CRLF, '?');
327  msg (D_X509_ATTR, "X509 ATTRIBUTE name='%s' value='%s' depth=%d", name, value, depth);
328  name_expand_size = 64 + strlen (name);
329  name_expand = (char *) malloc (name_expand_size);
330  check_malloc_return (name_expand);
331  openvpn_snprintf (name_expand, name_expand_size, "X509_%d_%s", depth, name);
332  setenv_str (es, name_expand, value);
333  free (name_expand);
334}
335
336void
337x509_setenv_track (const struct x509_track *xt, struct env_set *es, const int depth, X509 *x509)
338{
339  X509_NAME *x509_name = X509_get_subject_name (x509);
340  const char nullc = '\0';
341  int i;
342
343  while (xt)
344    {
345      if (depth == 0 || (xt->flags & XT_FULL_CHAIN))
346	{
347	  i = X509_NAME_get_index_by_NID(x509_name, xt->nid, -1);
348	  if (i >= 0)
349	    {
350	      X509_NAME_ENTRY *ent = X509_NAME_get_entry(x509_name, i);
351	      if (ent)
352		{
353		  ASN1_STRING *val = X509_NAME_ENTRY_get_data (ent);
354		  unsigned char *buf;
355		  buf = (unsigned char *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */
356		  if (ASN1_STRING_to_UTF8 (&buf, val) > 0)
357		    {
358		      do_setenv_x509(es, xt->name, (char *)buf, depth);
359		      OPENSSL_free (buf);
360		    }
361		}
362	    }
363	  else
364	    {
365	      i = X509_get_ext_by_NID(x509, xt->nid, -1);
366	      if (i >= 0)
367		{
368		  X509_EXTENSION *ext = X509_get_ext(x509, i);
369		  if (ext)
370		    {
371		      BIO *bio = BIO_new(BIO_s_mem());
372		      if (bio)
373			{
374			  if (X509V3_EXT_print(bio, ext, 0, 0))
375			    {
376			      if (BIO_write(bio, &nullc, 1) == 1)
377				{
378				  char *str;
379				  BIO_get_mem_data(bio, &str);
380				  do_setenv_x509(es, xt->name, str, depth);
381				}
382			    }
383			  BIO_free(bio);
384			}
385		    }
386		}
387	    }
388	}
389      xt = xt->next;
390    }
391}
392#endif
393
394/*
395 * Save X509 fields to environment, using the naming convention:
396 *
397 *  X509_{cert_depth}_{name}={value}
398 */
399void
400x509_setenv (struct env_set *es, int cert_depth, openvpn_x509_cert_t *peer_cert)
401{
402  int i, n;
403  int fn_nid;
404  ASN1_OBJECT *fn;
405  ASN1_STRING *val;
406  X509_NAME_ENTRY *ent;
407  const char *objbuf;
408  unsigned char *buf;
409  char *name_expand;
410  size_t name_expand_size;
411  X509_NAME *x509 = X509_get_subject_name (peer_cert);
412
413  n = X509_NAME_entry_count (x509);
414  for (i = 0; i < n; ++i)
415    {
416      ent = X509_NAME_get_entry (x509, i);
417      if (!ent)
418	continue;
419      fn = X509_NAME_ENTRY_get_object (ent);
420      if (!fn)
421	continue;
422      val = X509_NAME_ENTRY_get_data (ent);
423      if (!val)
424	continue;
425      fn_nid = OBJ_obj2nid (fn);
426      if (fn_nid == NID_undef)
427	continue;
428      objbuf = OBJ_nid2sn (fn_nid);
429      if (!objbuf)
430	continue;
431      buf = (unsigned char *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */
432      if (ASN1_STRING_to_UTF8 (&buf, val) <= 0)
433	continue;
434      name_expand_size = 64 + strlen (objbuf);
435      name_expand = (char *) malloc (name_expand_size);
436      check_malloc_return (name_expand);
437      openvpn_snprintf (name_expand, name_expand_size, "X509_%d_%s", cert_depth,
438	  objbuf);
439      string_mod (name_expand, CC_PRINT, CC_CRLF, '_');
440      string_mod ((char*)buf, CC_PRINT, CC_CRLF, '_');
441      setenv_str (es, name_expand, (char*)buf);
442      free (name_expand);
443      OPENSSL_free (buf);
444    }
445}
446
447result_t
448x509_verify_ns_cert_type(const openvpn_x509_cert_t *peer_cert, const int usage)
449{
450  if (usage == NS_CERT_CHECK_NONE)
451    return SUCCESS;
452  if (usage == NS_CERT_CHECK_CLIENT)
453    return ((peer_cert->ex_flags & EXFLAG_NSCERT)
454	&& (peer_cert->ex_nscert & NS_SSL_CLIENT)) ? SUCCESS: FAILURE;
455  if (usage == NS_CERT_CHECK_SERVER)
456    return ((peer_cert->ex_flags & EXFLAG_NSCERT)
457	&& (peer_cert->ex_nscert & NS_SSL_SERVER))  ? SUCCESS: FAILURE;
458
459  return FAILURE;
460}
461
462#if OPENSSL_VERSION_NUMBER >= 0x00907000L
463
464result_t
465x509_verify_cert_ku (X509 *x509, const unsigned * const expected_ku,
466    int expected_len)
467{
468  ASN1_BIT_STRING *ku = NULL;
469  result_t fFound = FAILURE;
470
471  if ((ku = (ASN1_BIT_STRING *) X509_get_ext_d2i (x509, NID_key_usage, NULL,
472      NULL)) == NULL)
473    {
474      msg (D_HANDSHAKE, "Certificate does not have key usage extension");
475    }
476  else
477    {
478      unsigned nku = 0;
479      int i;
480      for (i = 0; i < 8; i++)
481	{
482	  if (ASN1_BIT_STRING_get_bit (ku, i))
483	    nku |= 1 << (7 - i);
484	}
485
486      /*
487       * Fixup if no LSB bits
488       */
489      if ((nku & 0xff) == 0)
490	{
491	  nku >>= 8;
492	}
493
494      msg (D_HANDSHAKE, "Validating certificate key usage");
495      for (i = 0; fFound != SUCCESS && i < expected_len; i++)
496	{
497	  if (expected_ku[i] != 0)
498	    {
499	      msg (D_HANDSHAKE, "++ Certificate has key usage  %04x, expects "
500		  "%04x", nku, expected_ku[i]);
501
502	      if (nku == expected_ku[i])
503		fFound = SUCCESS;
504	    }
505	}
506    }
507
508  if (ku != NULL)
509    ASN1_BIT_STRING_free (ku);
510
511  return fFound;
512}
513
514result_t
515x509_verify_cert_eku (X509 *x509, const char * const expected_oid)
516{
517  EXTENDED_KEY_USAGE *eku = NULL;
518  result_t fFound = FAILURE;
519
520  if ((eku = (EXTENDED_KEY_USAGE *) X509_get_ext_d2i (x509, NID_ext_key_usage,
521      NULL, NULL)) == NULL)
522    {
523      msg (D_HANDSHAKE, "Certificate does not have extended key usage extension");
524    }
525  else
526    {
527      int i;
528
529      msg (D_HANDSHAKE, "Validating certificate extended key usage");
530      for (i = 0; SUCCESS != fFound && i < sk_ASN1_OBJECT_num (eku); i++)
531	{
532	  ASN1_OBJECT *oid = sk_ASN1_OBJECT_value (eku, i);
533	  char szOid[1024];
534
535	  if (SUCCESS != fFound && OBJ_obj2txt (szOid, sizeof(szOid), oid, 0) != -1)
536	    {
537	      msg (D_HANDSHAKE, "++ Certificate has EKU (str) %s, expects %s",
538		  szOid, expected_oid);
539	      if (!strcmp (expected_oid, szOid))
540		fFound = SUCCESS;
541	    }
542	  if (SUCCESS != fFound && OBJ_obj2txt (szOid, sizeof(szOid), oid, 1) != -1)
543	    {
544	      msg (D_HANDSHAKE, "++ Certificate has EKU (oid) %s, expects %s",
545		  szOid, expected_oid);
546	      if (!strcmp (expected_oid, szOid))
547		fFound = SUCCESS;
548	    }
549	}
550    }
551
552  if (eku != NULL)
553    sk_ASN1_OBJECT_pop_free (eku, ASN1_OBJECT_free);
554
555  return fFound;
556}
557
558result_t
559x509_write_pem(FILE *peercert_file, X509 *peercert)
560{
561  if (PEM_write_X509(peercert_file, peercert) < 0)
562    {
563      msg (M_ERR, "Failed to write peer certificate in PEM format");
564      return FAILURE;
565    }
566  return SUCCESS;
567}
568
569#endif /* OPENSSL_VERSION_NUMBER */
570
571/*
572 * check peer cert against CRL
573 */
574result_t
575x509_verify_crl(const char *crl_file, X509 *peer_cert, const char *subject)
576{
577  X509_CRL *crl=NULL;
578  X509_REVOKED *revoked;
579  BIO *in=NULL;
580  int n,i;
581  result_t retval = FAILURE;
582
583  in = BIO_new_file (crl_file, "r");
584
585  if (in == NULL) {
586    msg (M_ERR, "CRL: cannot read: %s", crl_file);
587    goto end;
588  }
589  crl=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
590  if (crl == NULL) {
591    msg (M_ERR, "CRL: cannot read CRL from file %s", crl_file);
592    goto end;
593  }
594
595  if (X509_NAME_cmp(X509_CRL_get_issuer(crl), X509_get_issuer_name(peer_cert)) != 0) {
596    msg (M_WARN, "CRL: CRL %s is from a different issuer than the issuer of "
597	"certificate %s", crl_file, subject);
598    retval = SUCCESS;
599    goto end;
600  }
601
602  n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
603  for (i = 0; i < n; i++) {
604    revoked = (X509_REVOKED *)sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
605    if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(peer_cert)) == 0) {
606      msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED",subject);
607      goto end;
608    }
609  }
610
611  retval = SUCCESS;
612  msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject);
613
614end:
615  BIO_free(in);
616  if (crl)
617    X509_CRL_free (crl);
618
619  return retval;
620}
621
622#endif /* defined(ENABLE_SSL) && defined(ENABLE_CRYPTO_OPENSSL) */
623