[PATCH] Re: [Exim] TLS and certificate chains

Top Page
Delete this message
Reply to this message
Author: John Holman
Date:  
To: exim-users
Subject: [PATCH] Re: [Exim] TLS and certificate chains
This is a multi-part message in MIME format.
--
After some investigation, I patched tls.c from exim 3.35 so that it will
send the client any necessary intermediate certificates as well as the
server certificate itself. The recommended approach seems to be to call
SSL_CTX_use_certificate_chain_file(ctx, file) rather than
SSL_CTX_use_certificate_file(ctx, file, type) when initialising the SSL
context. You can then include any intermediate certificates (and the
root certificate too, though that is optional) in the certificate file
and OpenSSL will automatically send them all as part of the SSL handshake.

In principle the change is quite trivial - just change the function name
and remove the third argument (since only PEM certificates are supported
by SSL_CTX_use_certificate_path_file). In practice it's a bit more
complicated because setup_certkey() in tls.c assumes the setup functions
for the private key and the certificate have the same signature - and
that is no longer the case. Anyway, I've attached a patch for 3.35.
Changes for 4.02 would be essentially the same.

None of this really has much to do with the problem described by Sheldon
Hearn of clients not wanting to be presented with a server certificate
that is self-signed and marked as a CA certificate.

By the way, although overview documentation for OpenSSL is somewhat
sparse, there is a helpful article and sample code by Eric Rescorla at
www.rtfm.com/openssl-examples. (He's an authority on the subject and has
written a book called "SSL and TLS: Designing and Building Secure
Systems" published by Addison and Wesley, ISBN 0-201-61598-3. Not that
I've seen it).

John


Philip Hazel wrote:
> On Wed, 3 Apr 2002, John Holman wrote:
>
>
>>I've obtained a server certificate from GlobalSign (under the UKERNA
>>deal for UK HE institutions, in fact) but am having difficulty
>>configuring Exim to use it. I think the problem is that the client needs
>>to receive not only the server certificate itself, but also a couple of
>>intermediate GlobalSign certificates linking it with the root
>>certificate known to the client.
>
>
> All I know about this was what I learned from Sheldon Hearn, who posted
> stuff on this list some time ago when he was chasing this. The Exim 4
> manual has a summary, which is this:
>
> ------------------------------------------------------------------------
> A self-signed certificate made in this way is sufficient for testing, and may
> be adequate for all your requirements if you are mainly interested in
> encrypting transfers, and not in secure identification.
>
> However, many clients require that the certificate presented by the server be
> a user (also called 'leaf' or 'site') certificate, and not a self-signed
> certificate. In this situation, the self-signed certificate described above
> must be installed on the client host as a trusted root "certification
> authority" (CA), and the certificate used by Exim must be a user certificate
> signed with that self-signed certificate.
>
> For information on creating self-signed CA certificates and using them to sign
> user certificates, see the "General implementation overview" chapter of the
> Open-source PKI book, available online at http://ospkibook.sourceforge.net/.
> ------------------------------------------------------------------------
>
> Now, you don't have a self-signed certificate, but this commentary
> suggests that you have to have a GlobalSign certificate installed as a
> CA on your host. No, I don't know the details of how to do this...
>


--
*** tls.c.orig    Tue Feb 19 10:10:45 2002
--- tls.c    Thu Apr  4 12:55:26 2002
***************
*** 308,323 ****



  /*************************************************
! *       Set up certificate or key                *
  *************************************************/


! /* Expand a file name for a certificate or a key, and get it set up.

  Arguments:
    name        file name to be expanded
    name_txt    file name for error message
-   func        setup function to call
-   func_txt    name of function for errors
    host        NULL if in a server; the remote host if in a client


  Returns:      TRUE if no configured file name,
--- 308,321 ----



  /*************************************************
! *       Set up certificate                       *
  *************************************************/


! /* Expand a file name for a certificate, and get it set up.

  Arguments:
    name        file name to be expanded
    name_txt    file name for error message
    host        NULL if in a server; the remote host if in a client


  Returns:      TRUE if no configured file name,
***************
*** 326,334 ****
  */


static BOOL
! setup_certkey(char *name, char *name_txt,
! int (*func)(SSL_CTX *, const char *, int),
! char *func_txt, host_item *host)
{
char *expanded;
if (!expand_check(name, name_txt, &expanded, host == NULL)) return FALSE;
--- 324,330 ----
*/

  static BOOL
! setup_cert(char *name, char *name_txt, host_item *host)
  {
  char *expanded;
  if (!expand_check(name, name_txt, &expanded, host == NULL)) return FALSE;
***************
*** 335,349 ****
  if (expanded != NULL)
    {
    DEBUG(5) debug_printf("using %s %s\n", name_txt, expanded);
!   if (!(func)(ctx, expanded, SSL_FILETYPE_PEM))
!     return tls_error(func_txt, host);
    }
  return TRUE;
  }





  /*************************************************
  *            Initialize for TLS                  *
  *************************************************/
--- 331,374 ----
  if (expanded != NULL)
    {
    DEBUG(5) debug_printf("using %s %s\n", name_txt, expanded);
!   if (!SSL_CTX_use_certificate_chain_file(ctx, expanded))
!     return tls_error("SSL_CTX_use_certificate_chain_file", host);
    }
  return TRUE;
  }



+ /*************************************************
+ *       Set up key                               *
+ *************************************************/


+ /* Expand a file name for a key, and get it set up.

+ Arguments:
+   name        file name to be expanded
+   name_txt    file name for error message
+   host        NULL if in a server; the remote host if in a client
+
+ Returns:      TRUE if no configured file name,
+               or expansion forced failure,
+               or setup was successful
+ */
+
+ static BOOL
+ setup_key(char *name, char *name_txt, host_item *host)
+ {
+ char *expanded;
+ if (!expand_check(name, name_txt, &expanded, host == NULL)) return FALSE;
+ if (expanded != NULL)
+   {
+   DEBUG(5) debug_printf("using %s %s\n", name_txt, expanded);
+   if (!SSL_CTX_use_PrivateKey_file(ctx, expanded, SSL_FILETYPE_PEM))
+     return tls_error("SSL_CTX_use_PrivateKey_file", host);
+   }
+ return TRUE;
+ }
+
+
  /*************************************************
  *            Initialize for TLS                  *
  *************************************************/
***************
*** 460,471 ****


/* Set up keys, certificates, and the RSA callback. */

! if (!setup_certkey(certificate, "tls_certificate",
!      SSL_CTX_use_certificate_file, "SSL_CTX_use_certificate_file", host))
    return FALSE;


! if (!setup_certkey(privatekey, "tls_privatekey",
!      SSL_CTX_use_PrivateKey_file, "SSL_CTX_use_PrivateKey_file", host))
    return FALSE;


SSL_CTX_set_tmp_rsa_callback(ctx, rsa_callback);
--- 485,494 ----

/* Set up keys, certificates, and the RSA callback. */

!  if (!setup_cert(certificate, "tls_certificate", host))
    return FALSE;


!  if (!setup_key(privatekey, "tls_privatekey", host))
    return FALSE;


SSL_CTX_set_tmp_rsa_callback(ctx, rsa_callback);
--