Standards-Version: 3.9.6 (no changes)
[ckermit.git] / ck_ssl.c
index 561e056..cc8a4ed 100644 (file)
--- a/ck_ssl.c
+++ b/ck_ssl.c
@@ -1,8 +1,8 @@
-char *cksslv = "SSL/TLS support, 9.0.227, 04 Aug 2020";
+char *cksslv = "SSL/TLS support, 9.0.232, 5 Feb 2015";
 /*
   C K _ S S L . C --  OpenSSL Interface for C-Kermit
 
-  Copyright (C) 1985, 2010,
+  Copyright (C) 1985, 2015,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -19,7 +19,7 @@ char *cksslv = "SSL/TLS support, 9.0.227, 04 Aug 2020";
   . Client certificate to user id routine
 
   Note: This code is written to be compatible with OpenSSL 0.9.6[abcdefgh]
-  and 0.9.7 beta 5 (and, presumably, later).
+  and 0.9.7 beta 5 and later, and (since July 2012) 1.0.x.
   It will also compile with version 0.9.5 although that is discouraged
   due to security weaknesses in that release.
 */
@@ -1363,6 +1363,7 @@ ssl_once_init()
     if ( !ck_ssleay_is_installed() )
         return;
 /*
+  Pre-OpenSSL 1.0.0 comment:
   OpenSSL does not provide for ABI compatibility between releases prior
   to version 1.0.0.  If the version does not match, it is not safe to
   assume that any function you call takes the same parameters or does
@@ -1371,6 +1372,20 @@ ssl_once_init()
   The test should be revised once OpenSSL 1.0.0 is released and we see what
   its claims are as to ABI compatibility.
 */
+/*
+  Post-OpenSSL 1.0.0 comment:
+  OpenSSL does not provide for ABI compatibility between releases prior
+  to version 1.0.0.  After 1.0, the following holds:
+
+  Changes to last letter: security and bugfix only, no new features.
+  E.g.  1.0.0->1.0.0a
+  Changes to last number: new ABI compatible features.
+  E.g. 1.0.0->1.0.1
+  Changes to middle number: major release, ABI compatibility not guaranteed.
+  E.g. 1.0.0->1.1.0
+
+  (per Dr. Stephen Henson)
+*/
     debug(F111,"Kermit built for OpenSSL",OPENSSL_VERSION_TEXT,SSLEAY_VERSION_NUMBER);
 #ifndef OS2ONLY
     debug(F111,"OpenSSL Library",SSLeay_version(SSLEAY_VERSION),
@@ -1380,7 +1395,10 @@ ssl_once_init()
     debug(F110,"OpenSSL Library",SSLeay_version(SSLEAY_PLATFORM),0);
 
     /* The following test is suggested by Richard Levitte */
-    if (((OPENSSL_VERSION_NUMBER ^ SSLeay()) & 0xffffff0f) 
+    /* if (((OPENSSL_VERSION_NUMBER ^ SSLeay()) & 0xffffff0f) */
+    /* Modified by Adam Friedlander for OpenSSL >= 1.0.0 */
+    if (OPENSSL_VERSION_NUMBER > SSLeay()
+         || ((OPENSSL_VERSION_NUMBER ^ SSLeay()) & COMPAT_VERSION_MASK)
 #ifdef OS2
          || ckstrcmp(OPENSSL_VERSION_TEXT,(char *)SSLeay_version(SSLEAY_VERSION),-1,1)
 #endif /* OS2 */
@@ -1391,7 +1409,14 @@ ssl_once_init()
         printf("?OpenSSL libraries do not match required version:\r\n");
         printf("  . C-Kermit built with %s\r\n",OPENSSL_VERSION_TEXT);
         printf("  . Version found  %s\r\n",SSLeay_version(SSLEAY_VERSION));
-        printf("  OpenSSL versions prior to 1.0.0 must be the same.\r\n");    
+#ifdef OPENSSL_100
+       printf("  OpenSSL versions 1.0.0 or newer must be the same\r\n");
+       printf("  major and minor version number, and Kermit may not\r\n");
+       printf("  be used with a version of OpenSSL older than the one\r\n");
+       printf("  supplied at compile time.\r\n");
+#else
+        printf("  OpenSSL versions prior to 1.0.0 must be the same.\r\n");
+#endif /* OPENSSL_100 */
 
        s = "R";
 #ifdef SOLARIS
@@ -1579,27 +1604,48 @@ ssl_tn_init(mode) int mode;
             /* This can fail because we do not have RSA available */
             if ( !ssl_ctx ) {
                 debug(F110,"ssl_tn_init","SSLv23_client_method failed",0);
+#ifndef DISABLE_SSLV3
                 ssl_ctx=(SSL_CTX *)SSL_CTX_new(SSLv3_client_method());
             }
             if ( !ssl_ctx ) {
                 debug(F110,"ssl_tn_init","SSLv3_client_method failed",0);
+#endif
                 last_ssl_mode = -1;
                 return(0);
             }
-#ifndef COMMENT
+            /*
+              TLS 1.0 is the new default as of 5 Feb 2015.
+              Previously this was commented out because 
+              "too many web servers still do not support TLSv1".
+              Now we try TLS 1.0 first, falling back to SSL 2.3
+              and SSL 3.0 in that order.  Maybe there should be
+              an option not to fall back.
+            */ 
             tls_ctx=(SSL_CTX *)SSL_CTX_new(TLSv1_client_method());
-#else /* COMMENT */
-            tls_ctx=(SSL_CTX *)SSL_CTX_new(SSLv23_client_method());
-            /* This can fail because we do not have RSA available */
-            if ( !tls_ctx ) {
-                debug(F110,"ssl_tn_init","SSLv23_client_method failed",0);
-                tls_ctx=(SSL_CTX *)SSL_CTX_new(SSLv3_client_method());
-            }
-#endif /* COMMENT */
-            if ( !tls_ctx ) {
+            if ( tls_ctx ) {
+                debug(F110,"ssl_tn_init","TLSv1_client_method OK",0);
+            } else {
                 debug(F110,"ssl_tn_init","TLSv1_client_method failed",0);
-                last_ssl_mode = -1;
-                return(0);
+                /* This can fail because we do not have RSA available */
+                tls_ctx=(SSL_CTX *)SSL_CTX_new(SSLv23_client_method());
+                if ( !tls_ctx ) {
+                    debug(F110,"ssl_tn_init","SSLv23_client_method OK",0);
+                } else {
+                    debug(F110,"ssl_tn_init","SSLv23_client_method failed",0);
+#ifndef DISABLE_SSLV3
+                    tls_ctx=(SSL_CTX *)SSL_CTX_new(SSLv3_client_method());
+#endif /* DISABLE_SSLV3 */
+                    if ( !tls_ctx ) {
+#ifndef DISABLE_SSLV3
+                        debug(F110,
+                              "ssl_tn_init","SSLv3_client_method failed",0);
+#endif /* DISABLE_SSLV3 */
+                        debug(F110,
+                              "ssl_tn_init","All SSL client methods failed",0);
+                        last_ssl_mode = -1;
+                        return(0);
+                    }
+                }
             }
 #ifdef USE_CERT_CB
             SSL_CTX_set_client_cert_cb(ssl_ctx,ssl_client_cert_callback);
@@ -1611,10 +1657,12 @@ ssl_tn_init(mode) int mode;
             /* This can fail because we do not have RSA available */
             if ( !ssl_ctx ) {
                 debug(F110,"ssl_tn_init","SSLv23_server_method failed",0);
+#ifndef DISABLE_SSLV3
                 ssl_ctx=(SSL_CTX *)SSL_CTX_new(SSLv3_server_method());
             }
             if ( !ssl_ctx ) {
                 debug(F110,"ssl_tn_init","SSLv3_server_method failed",0);
+#endif
                 last_ssl_mode = -1;
                 return(0);
             }
@@ -1648,9 +1696,17 @@ ssl_tn_init(mode) int mode;
          * that cannot read poorly written specs :-)
          * for TLS be sure to prevent use of SSLv2
          */
-        SSL_CTX_set_options(ssl_ctx,SSL_OP_ALL|SSL_OP_NO_SSLv2);
+        SSL_CTX_set_options(ssl_ctx,SSL_OP_ALL|SSL_OP_NO_SSLv2
+#ifdef DISABLE_SSLV3
+                                    |SSL_OP_NO_SSLv3
+#endif
+            );
         SSL_CTX_set_options(tls_ctx,
-                 SSL_OP_NO_SSLv2|SSL_OP_SINGLE_DH_USE|SSL_OP_EPHEMERAL_RSA);
+                 SSL_OP_NO_SSLv2|SSL_OP_SINGLE_DH_USE|SSL_OP_EPHEMERAL_RSA
+#ifdef DISABLE_SSLV3
+                 |SSL_OP_NO_SSLv3
+#endif
+            );
 
         SSL_CTX_set_info_callback(ssl_ctx,ssl_client_info_callback);
         SSL_CTX_set_info_callback(tls_ctx,ssl_client_info_callback);
@@ -2153,36 +2209,33 @@ ssl_http_init(hostname) char * hostname;
         printf("SSL_DEBUG_FLAG on\r\n");
 
     if (!tls_http_ctx ) {
-#ifdef COMMENT
-        /* too many web servers still do not support TLSv1 */
+        /*
+          TLS 1.0 is the new default as of 5 Feb 2015.
+          Previously this was commented out because 
+          "too many web servers still do not support TLSv1".
+          Now we try TLS 1.0 first, falling back to SSL 2.3
+          and SSL 3.0 in that order.  Maybe there should be
+          an option not to fall back.
+        */ 
         tls_http_ctx=(SSL_CTX *)SSL_CTX_new(TLSv1_client_method());
-#else /* COMMENT */
-        tls_http_ctx=(SSL_CTX *)SSL_CTX_new(SSLv23_client_method());
-        /* This can fail because we do not have RSA available */
-        if ( !tls_http_ctx ) {
-            debug(F110,"ssl_http_init","SSLv23_client_method failed",0);
-            tls_http_ctx=(SSL_CTX *)SSL_CTX_new(SSLv3_client_method());
-        }
-#endif /* COMMENT */
-        if ( !tls_http_ctx ) {
-            debug(F110,"ssl_http_init","TLSv1_client_method failed",0);
-            return(0);
+        if ( tls_http_ctx ) {
+            debug(F110,"ssl_http_init","TLSv1_client_method OK",0);
         }
-#ifdef USE_CERT_CB
-        SSL_CTX_set_client_cert_cb(tls_http_ctx,ssl_client_cert_callback);
-#endif /* USE_CERT_CB */
     }
-
     SSL_CTX_set_default_passwd_cb(tls_http_ctx,
                                   (pem_password_cb *)ssl_passwd_callback);
 
     /* for SSL switch on all the interoperability and bug
      * workarounds so that we will communicate with people
-     * that cannot read poorly written specs :-)
+     * who cannot read poorly written specs :-)
      * for TLS be sure to prevent use of SSLv2
      */
     SSL_CTX_set_options(tls_http_ctx,
-            SSL_OP_NO_SSLv2|SSL_OP_SINGLE_DH_USE|SSL_OP_EPHEMERAL_RSA);
+            SSL_OP_NO_SSLv2|SSL_OP_SINGLE_DH_USE|SSL_OP_EPHEMERAL_RSA
+#ifdef DISABLE_SSLV3
+            |SSL_OP_NO_SSLv3
+#endif
+        );
 
     SSL_CTX_set_info_callback(tls_http_ctx,ssl_client_info_callback);
 
@@ -2457,7 +2510,7 @@ ssl_get_dNSName(ssl) SSL * ssl;
             if (gen->type == GEN_DNS) {
                 if (!gen->d.ia5 || !gen->d.ia5->length)
                  break;
-                if (strlen(gen->d.ia5->data) != gen->d.ia5->length) {
+                if (strlen((char *)gen->d.ia5->data) != gen->d.ia5->length) {
                     /* Ignoring IA5String containing null character */
                     continue;
                 }
@@ -2770,7 +2823,7 @@ tls_get_SAN_objs(SSL * ssl, int type)
             if ((gen->type | V_ASN1_CONTEXT_SPECIFIC) == (type | V_ASN1_CONTEXT_SPECIFIC)) {
                 if (!gen->d.ia5 || !gen->d.ia5->length)
                  break;
-                if (strlen(gen->d.ia5->data) != gen->d.ia5->length) {
+                if (strlen((char *)gen->d.ia5->data) != gen->d.ia5->length) {
                     /* Ignoring IA5String containing null character */
                     continue;
                 }