Changeset 5452:934a802dff7f

Show
Ignore:
Timestamp:
2008-07-10 23:47:01 (3 months ago)
Author:
Rocco Rutte <pdmef@…>
Branch:
HEAD
Message:

Verify hostname in (Open)SSL certificate validation

This is based on the patch by gkloepfer attached to #3087 but passes the
proper connection as argument (avoiding adding hostname to struct
sslsockdata) and validates the hostname even in case OpenSSL cannot find
the local issuer certificate. GnuTLS already supports hostname
checking. Closes #3087.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • mutt_ssl.c

    r5010 r5452  
    7575static int ssl_socket_close (CONNECTION * conn); 
    7676static int tls_close (CONNECTION* conn); 
    77 static int ssl_check_certificate (sslsockdata * data); 
     77static int ssl_check_certificate (CONNECTION *conn, sslsockdata * data); 
    7878static void ssl_get_client_cert(sslsockdata *ssldata, CONNECTION *conn); 
    7979static int ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata); 
    80 static int ssl_negotiate (sslsockdata*); 
     80static int ssl_negotiate (CONNECTION *conn, sslsockdata*); 
    8181 
    8282/* mutt_ssl_starttls: Negotiate TLS over an already opened connection. 
     
    112112  } 
    113113 
    114   if (ssl_negotiate (ssldata)) 
     114  if (ssl_negotiate (conn, ssldata)) 
    115115    goto bail_ssl; 
    116116 
     
    291291  SSL_set_fd (data->ssl, conn->fd); 
    292292 
    293   if (ssl_negotiate(data)) 
     293  if (ssl_negotiate(conn, data)) 
    294294  { 
    295295    mutt_socket_close (conn); 
     
    305305/* ssl_negotiate: After SSL state has been initialised, attempt to negotiate 
    306306 *   SSL over the wire, including certificate checks. */ 
    307 static int ssl_negotiate (sslsockdata* ssldata) 
     307static int ssl_negotiate (CONNECTION *conn, sslsockdata* ssldata) 
    308308{ 
    309309  int err; 
     
    344344  } 
    345345 
    346   if (!ssl_check_certificate (ssldata)) 
     346  if (!ssl_check_certificate (conn, ssldata)) 
    347347    return -1; 
    348348 
     
    589589} 
    590590 
    591 static int ssl_check_certificate (sslsockdata * data) 
     591static int check_certificate_hostname(X509 *peercert, const char *host) 
     592{ 
     593  char cert_CN[STRING]; 
     594 
     595  if (!host || !*host) 
     596    return 0; 
     597 
     598  X509_NAME_get_text_by_NID (X509_get_subject_name (peercert), 
     599                             NID_commonName, cert_CN, sizeof (cert_CN)); 
     600 
     601  dprint (2, (debugfile, "check_certificate_hostname: cert=[%s] host=[%s]\n", 
     602              cert_CN, host)); 
     603 
     604  return strcmp (cert_CN, host) == 0; 
     605} 
     606 
     607static int ssl_check_certificate (CONNECTION *conn, sslsockdata * data) 
    592608{ 
    593609  char *part[] = 
     
    596612  char buf[SHORT_STRING]; 
    597613  MUTTMENU *menu; 
    598   int done, row, i; 
     614  int done, row, i, certerr_hostname = 0; 
    599615  FILE *fp; 
    600616  char *name = NULL, *c; 
     
    607623  } 
    608624 
    609   if (check_certificate_by_signer (data->cert)) 
     625  if (check_certificate_hostname (data->cert, conn->account.host)) 
     626  { 
     627    dprint (1, (debugfile, "ssl_check_certificate: hostname check passed\n")); 
     628  } 
     629  else 
     630    certerr_hostname = 1; 
     631 
     632  if (!certerr_hostname && check_certificate_by_signer (data->cert)) 
    610633  { 
    611634    dprint (1, (debugfile, "ssl_check_certificate: signer check passed\n")); 
     
    614637 
    615638  /* automatic check from user's database */ 
    616   if (SslCertFile && check_certificate_by_digest (data->cert)) 
     639  if (!certerr_hostname && SslCertFile && check_certificate_by_digest (data->cert)) 
    617640  { 
    618641    dprint (1, (debugfile, "ssl_check_certificate: digest check passed\n"));