+ecore_con_ssl_server_verify_name_set/get
authordiscomfitor <discomfitor@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 8 Dec 2011 01:14:55 +0000 (01:14 +0000)
committerdiscomfitor <discomfitor@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 8 Dec 2011 01:14:55 +0000 (01:14 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@66002 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

ChangeLog
NEWS
src/lib/ecore_con/Ecore_Con.h
src/lib/ecore_con/ecore_con.c
src/lib/ecore_con/ecore_con_private.h
src/lib/ecore_con/ecore_con_ssl.c

index d62ec30..d572522 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 2011-12-07 Mike Blumenkrantz
 
         * Allow SSL certificates to be loaded for STARTTLS
+        * Added functions to set/get the hostname used for SSL certificate verification
diff --git a/NEWS b/NEWS
index bfce1eb..dfe0d87 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,7 @@ Additions:
      - ecore_timer_reset()
     * ecore_con
      - ecore_con_socks api
+     - ecore_con_ssl_server_verify_name_set/get
     * ecore_x:
      - ecore_x_randr_output_backlight_available()
 
index 61f1eb5..56c914b 100644 (file)
@@ -707,6 +707,8 @@ EAPI Eina_Bool         ecore_con_ssl_server_crl_add(Ecore_Con_Server *svr, const
 EAPI Eina_Bool         ecore_con_ssl_server_cafile_add(Ecore_Con_Server *svr, const char *ca_file);
 EAPI void              ecore_con_ssl_server_verify(Ecore_Con_Server *svr);
 EAPI void              ecore_con_ssl_server_verify_basic(Ecore_Con_Server *svr);
+EAPI void              ecore_con_ssl_server_verify_name_set(Ecore_Con_Server *svr, const char *name);
+EAPI const char       *ecore_con_ssl_server_verify_name_get(Ecore_Con_Server *svr);
 EAPI Eina_Bool         ecore_con_ssl_server_upgrade(Ecore_Con_Server *svr, Ecore_Con_Type compl_type);
 EAPI Eina_Bool         ecore_con_ssl_client_upgrade(Ecore_Con_Client *cl, Ecore_Con_Type compl_type);
 
index 5c0fbc1..da59dc5 100644 (file)
@@ -1264,6 +1264,7 @@ _ecore_con_server_free(Ecore_Con_Server *svr)
    free(svr->path);
 
    eina_stringshare_del(svr->ip);
+   eina_stringshare_del(svr->verify_name);
 
    if (svr->ecs_buf) eina_binbuf_free(svr->ecs_buf);
    if (svr->ecs_recvbuf) eina_binbuf_free(svr->ecs_recvbuf);
index 532c1a8..85e4722 100644 (file)
@@ -150,6 +150,7 @@ struct _Ecore_Con_Server
    const char *proxyip;
    int proxyport;
    /* endsocks */
+   const char *verify_name;
 #if USE_GNUTLS
    gnutls_session_t session;
    gnutls_anon_client_credentials_t anoncred_c;
index 3b52846..0461e4b 100644 (file)
@@ -356,6 +356,51 @@ ecore_con_ssl_server_verify_basic(Ecore_Con_Server *svr)
 }
 
 /**
+ * @brief Set the hostname to verify against in certificate verification
+ *
+ * Sometimes the certificate hostname will not match the hostname that you are
+ * connecting to, and will instead match a different name. An example of this is
+ * that if you connect to talk.google.com to use Google Talk, you receive Google's
+ * certificate for gmail.com. This certificate should be trusted, and so you must call
+ * this function with "gmail.com" as @p name.
+ * See RFC2818 for more details.
+ * @param svr The server object
+ * @param name The hostname to verify against
+ * @since 1.2
+ */
+EAPI void
+ecore_con_ssl_server_verify_name_set(Ecore_Con_Server *svr, const char *name)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
+     {
+        ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __func__);
+        return;
+     }
+   eina_stringshare_replace(&svr->verify_name, name);
+}
+
+/**
+ * @brief Get the hostname to verify against in certificate verification
+ *
+ * This function returns the name which will be used to validate the SSL certificate
+ * common name (CN) or alt name (subjectAltName). It will default to the @p name
+ * param in ecore_con_server_connect(), but can be changed with ecore_con_ssl_server_verify_name_set().
+ * @param svr The server object
+ * @return The hostname which will be used
+ * @since 1.2
+ */
+EAPI const char *
+ecore_con_ssl_server_verify_name_get(Ecore_Con_Server *svr)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
+     {
+        ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __func__);
+        return NULL;
+     }
+   return svr->verify_name ?: svr->name;
+}
+
+/**
  * @brief Add an ssl certificate for use in ecore_con functions.
  *
  * Use this function to add a SSL PEM certificate.
@@ -764,8 +809,28 @@ _ecore_con_ssl_server_init_gnutls(Ecore_Con_Server *svr)
 
    SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_init(&cert));
    SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER));
+#ifdef ISCOMFITOR
+   {
+        size_t clen = 0;
+        char *c;
+        gnutls_x509_crt_get_subject_alt_name(cert, 0, NULL, &clen, NULL);
+        if (clen++)
+          {
+             c = alloca(clen);
+             gnutls_x509_crt_get_subject_alt_name(cert, 0, c, &clen, NULL);
+          }
+        else
+          {
+             gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, NULL, &clen);
+             SSL_ERROR_CHECK_GOTO_ERROR(!clen);
+             c = alloca(++clen);
+             gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, c, &clen);
+          }
+        INF("CERT NAME: %s\n", c);
+   }
+#endif
 
-   SSL_ERROR_CHECK_GOTO_ERROR(!gnutls_x509_crt_check_hostname(cert, svr->name));
+   SSL_ERROR_CHECK_GOTO_ERROR(!gnutls_x509_crt_check_hostname(cert, svr->verify_name ?: svr->name));
    gnutls_x509_crt_deinit(cert);
    DBG("SSL certificate verification succeeded!");
    return ECORE_CON_SSL_ERROR_NONE;
@@ -1344,17 +1409,24 @@ _ecore_con_ssl_server_init_openssl(Ecore_Con_Server *svr)
       cert = SSL_get_peer_certificate(svr->ssl);
       if (cert)
         {
-           char buf[256] = {0};
+           char *c;
+           size_t clen;
+           ASN1_OBJECT *obj = NULL;
+
            if (svr->verify)
              SSL_ERROR_CHECK_GOTO_ERROR(SSL_get_verify_result(svr->ssl));
-           X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_subject_alt_name, buf, sizeof(buf));
-           if (buf[0])
-             SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(buf, svr->name));
+           clen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_subject_alt_name, NULL, 0);
+           if (clen)
+             obj = NID_subject_alt_name;
            else
-             {
-                X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, buf, sizeof(buf));
-                SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(buf, svr->name));
-             }
+             clen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, NULL, 0);
+           SSL_ERROR_CHECK_GOTO_ERROR(!clen);
+           if (!obj) obj = NID_commonName;
+           c = alloca(++clen);
+           X509_NAME_get_text_by_NID(X509_get_subject_name(cert), obj, c, clen);
+           INF("CERT NAME: %s\n", c);
+           SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(buf, svr->verify_name ?: svr->name));
+           SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(buf, svr->verify_name ?: svr->name));
         }
    }