diff lib/sslcommon.c @ 199:75eebb3b0592

2003-6-24 Brian Masney <masneyb@gftp.org> * lib/config_file.c lib/gftp.h lib/protocols.c - added backend for overriding options on a per bookmark basis. Also added gftp_copy_local_options() to config_file.c * lib/gftp.h lib/misc.c src/gtk/bookmarks.c - added gftp_free_bookmark() to misc.c. It was taken from the function free_bookmark_entry_items() in bookmarks.c * lib/sslcommon.c - formatting fixes. Added thread functions (mostly from the OReilly SSL book)
author masneyb
date Wed, 25 Jun 2003 01:53:45 +0000
parents 13ca1defdc75
children 82ebd1b05345
line wrap: on
line diff
--- a/lib/sslcommon.c	Mon Jun 23 01:07:05 2003 +0000
+++ b/lib/sslcommon.c	Wed Jun 25 01:53:45 2003 +0000
@@ -42,9 +42,15 @@
   {NULL, NULL, 0, NULL, NULL, 0, NULL, 0, NULL}
 };  
 
+static GMutex ** gftp_ssl_mutexes = NULL;
+static volatile int gftp_ssl_initialized = 0;
 static SSL_CTX * ctx = NULL;
 
-static volatile int gftp_ssl_initialized = 0;
+struct CRYPTO_dynlock_value
+{ 
+  GMutex * mutex;
+};
+
 
 void
 ssl_register_module (void)
@@ -71,7 +77,6 @@
 }
 
 
-
 static int 
 gftp_ssl_verify_callback (int ok, X509_STORE_CTX *store)
 {
@@ -126,62 +131,136 @@
  
           if (strcmp (extstr, "subjectAltName") == 0)
             {
-    unsigned char  *data;
-    STACK_OF(CONF_VALUE) *val;
-    CONF_VALUE   *nval;
-    X509V3_EXT_METHOD *meth;
-    void     *ext_str = NULL;
+              unsigned char  *data;
+              STACK_OF(CONF_VALUE) *val;
+              CONF_VALUE   *nval;
+              X509V3_EXT_METHOD *meth;
+              void *ext_str = NULL;
  
-    if (!(meth = X509V3_EXT_get(ext)))
-     break;
-    data = ext->value->data;
+              if (!(meth = X509V3_EXT_get (ext)))
+                break;
+
+              data = ext->value->data;
 
 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
-    if (meth->it)
-     ext_str = ASN1_item_d2i(NULL, &data, ext->value->length,
-           ASN1_ITEM_ptr(meth->it));
-    else
-     ext_str = meth->d2i(NULL, &data, ext->value->length);
+              if (meth->it)
+                ext_str = ASN1_item_d2i (NULL, &data, ext->value->length,
+                                        ASN1_ITEM_ptr (meth->it));
+              else
+                ext_str = meth->d2i (NULL, &data, ext->value->length);
 #else
-    ext_str = meth->d2i(NULL, &data, ext->value->length);
+              ext_str = meth->d2i(NULL, &data, ext->value->length);
 #endif
-    val = meth->i2v(meth, ext_str, NULL);
-    for (j = 0; j < sk_CONF_VALUE_num(val); j++)
-    {
-     nval = sk_CONF_VALUE_value(val, j);
-     if (strcmp(nval->name, "DNS") == 0 && strcmp(nval->value, request->hostname) == 0)
-     {
-      ok = 1;
-      break;
-     }
+              val = meth->i2v(meth, ext_str, NULL);
+
+              for (j = 0; j < sk_CONF_VALUE_num(val); j++)
+                {
+                  nval = sk_CONF_VALUE_value (val, j);
+                  if (strcmp (nval->name, "DNS") == 0 && 
+                      strcmp (nval->value, request->hostname) == 0)
+                    {
+                      ok = 1;
+                      break;
+                    }
+                }
+            }
+
+          if (ok)
+            break;
+        }
     }
-   }
-   if (ok)
-    break;
-  }
- }
  
-/* FIXME
- if (!ok && (subj = X509_get_subject_name (cert)) &&
-     X509_NAME_get_text_by_NID (subj, NID_commonName, data, 256) > 0)
-   {
-     data[sizeof (data) - 1] = '\0';
-     if (strcasecmp (data, request->hostname) != 0)
-       {
-         request->logging_function (gftp_logging_error, request,
-                                    _("The SSL certificate's host %s does not match the host %s that we connected to\n"),
-                                    data, request->hostname);
-         X509_free (cert);
-         return (X509_V_ERR_APPLICATION_VERIFICATION);
-       }
-   }
-*/
+  if (!ok && (subj = X509_get_subject_name (cert)) &&
+      X509_NAME_get_text_by_NID (subj, NID_commonName, data, 256) > 0)
+    {
+      data[sizeof (data) - 1] = '\0';
+      if (strcasecmp (data, request->hostname) != 0)
+        {
+          request->logging_function (gftp_logging_error, request,
+                                     _("ERROR: The host in the SSL certificate (%s) does not match the host that we connected to (%s). Aborting connection.\n"),
+                                     data, request->hostname);
+          X509_free (cert);
+          return (X509_V_ERR_APPLICATION_VERIFICATION);
+        }
+    }
  
   X509_free (cert);
+
   return (SSL_get_verify_result(request->ssl));
 }
 
 
+static void
+_gftp_ssl_locking_function (int mode, int n, const char * file, int line)
+{
+  if (mode & CRYPTO_LOCK)
+    g_mutex_lock (gftp_ssl_mutexes[n]);
+  else
+    g_mutex_unlock (gftp_ssl_mutexes[n]);
+}
+
+
+static unsigned long
+_gftp_ssl_id_function (void)
+{ 
+#if GLIB_MAJOR_VERSION > 1
+  return ((unsigned long) g_thread_self ());
+#else
+  /* FIXME _ call pthread version */
+  return (0);
+#endif
+} 
+
+
+static struct CRYPTO_dynlock_value *
+_gftp_ssl_create_dyn_mutex (const char *file, int line)
+{ 
+  struct CRYPTO_dynlock_value *value;
+
+  value = g_malloc (sizeof (*value));
+  value->mutex = g_mutex_new ();
+  return (value);
+}
+
+
+static void
+_gftp_ssl_dyn_mutex_lock (int mode, struct CRYPTO_dynlock_value *l,
+                          const char *file, int line)
+{
+  if (mode & CRYPTO_LOCK)
+    g_mutex_lock (l->mutex);
+  else
+    g_mutex_unlock (l->mutex);
+}
+
+
+static void
+_gftp_ssl_destroy_dyn_mutex (struct CRYPTO_dynlock_value *l,
+                             const char *file, int line)
+{
+  g_mutex_free (l->mutex);
+  g_free (l);
+}
+
+
+static void
+_gftp_ssl_thread_setup (void)
+{
+  int i;
+
+  gftp_ssl_mutexes = g_malloc (CRYPTO_num_locks( ) * sizeof (*gftp_ssl_mutexes));
+
+  for (i = 0; i < CRYPTO_num_locks ( ); i++)
+    gftp_ssl_mutexes[i] = g_mutex_new ();
+
+  CRYPTO_set_id_callback (_gftp_ssl_id_function);
+  CRYPTO_set_locking_callback (_gftp_ssl_locking_function);
+  CRYPTO_set_dynlock_create_callback (_gftp_ssl_create_dyn_mutex);
+  CRYPTO_set_dynlock_lock_callback (_gftp_ssl_dyn_mutex_lock);
+  CRYPTO_set_dynlock_destroy_callback (_gftp_ssl_destroy_dyn_mutex);
+} 
+
+
 int
 gftp_ssl_startup (gftp_request * request)
 {
@@ -193,7 +272,9 @@
 
   gftp_ssl_initialized = 1;
 
-  /* FIXME _ thread setup */
+  if (g_thread_supported ())
+    _gftp_ssl_thread_setup ();
+
   if (!SSL_library_init ())
     {
       request->logging_function (gftp_logging_error, request,
@@ -246,7 +327,10 @@
       return (GFTP_EFATAL);
     }
 
-  if (gftp_fd_set_sockblocking (request, request->datafd, 0) < 0) /* FIXME */
+  /* FIXME - take this out. I need to find out how to do timeouts with the SSL
+     functions (a select() or poll() like function) */
+
+  if (gftp_fd_set_sockblocking (request, request->datafd, 0) < 0)
     {
       gftp_disconnect (request);
       return (GFTP_ERETRYABLE);
@@ -276,9 +360,10 @@
 
   if ((ret = gftp_ssl_post_connection_check (request)) != X509_V_OK)
     {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Error with peer certificate: %s\n"),
-                                 X509_verify_cert_error_string (ret));
+      if (ret != X509_V_ERR_APPLICATION_VERIFICATION)
+        request->logging_function (gftp_logging_error, request,
+                                   _("Error with peer certificate: %s\n"),
+                                   X509_verify_cert_error_string (ret));
       return (GFTP_EFATAL);
     }
 
@@ -311,7 +396,6 @@
       if ((ret = SSL_read (request->ssl, ptr, size)) < 0)
         { 
           err = SSL_get_error (request->ssl, ret);
-           printf ("error is %d\n", err);
           if (errno == EINTR)
             {
               if (request != NULL && request->cancel)