[libgda/LIBGDA_4.2] LDAP provider: added TLS_REQCERT and TLS_CACERT connection parameters



commit e744505a50719391bae213669a00664ead793c53
Author: Vivien Malerba <malerba gnome-db org>
Date:   Sat Feb 4 12:21:36 2012 +0100

    LDAP provider: added TLS_REQCERT and TLS_CACERT connection parameters
    
    to specify how to handle server certificates for SSL/TLS sessions

 doc/C/limitations.xml                |   24 ++++++++++++++---
 providers/ldap/gda-ldap-provider.c   |   49 +++++++++++++++++++++++++++------
 providers/ldap/ldap_specs_dsn.xml.in |   26 ++++++++++++++++++
 3 files changed, 86 insertions(+), 13 deletions(-)
---
diff --git a/doc/C/limitations.xml b/doc/C/limitations.xml
index 01b8dc2..9f06cb4 100644
--- a/doc/C/limitations.xml
+++ b/doc/C/limitations.xml
@@ -158,10 +158,26 @@
     </para>
   </sect1>
 
-  <sect1 id="limitations_ldap"><title>For LDAP</title>
-    <para>
-      TODO.
-    </para>
+  <sect1 id="limitations_ldap">
+    <title>For LDAP</title>
+    <sect2>
+      <title>SSL/TLS certificate validation</title>
+      <para>
+	The TLS_REQCERT and TLS_CACERT options are taken into account by the LDAP provider, and
+	passed to the OpenLDAP library which is actually used. These options are global and set
+	by the first opened LDAP connection (i.e. all other LDAP connections share the same
+	settings, regardless of their TLS_REQCERT and TLS_CACERT options).
+      </para>
+      <para>
+	The TLS_REQCERT and TLS_CACERT options have a higher priority compared to the
+	options set in the <filename>$HOME/.ldaprc</filename>.
+      </para>
+      <para>
+	If the server certificate can't he checked (i.e. the certification chain established and
+	verified) when it is required that it be, then the connection will not he established and the
+	returned error will be "Can't contact LDAP server".
+      </para>
+    </sect2>
   </sect1>
 
   <sect1 id="limitations_jdbc"><title>For JDBC based providers</title>
diff --git a/providers/ldap/gda-ldap-provider.c b/providers/ldap/gda-ldap-provider.c
index 35428cc..64c742a 100644
--- a/providers/ldap/gda-ldap-provider.c
+++ b/providers/ldap/gda-ldap-provider.c
@@ -258,12 +258,15 @@ gda_ldap_provider_open_connection (GdaServerProvider *provider, GdaConnection *c
 	const gchar *port;
 	const gchar *user = NULL;
         const gchar *pwd = NULL;
+        const gchar *tls_method = NULL;
+        const gchar *tls_cacert = NULL;
+	int rtls_method = -1;
 	gint rport;
 	gboolean use_ssl, use_cache;
 
         base_dn = gda_quark_list_find (params, "DB_NAME");
         if (!base_dn) {
-                gda_connection_add_event_string (cnc,
+                gda_connection_add_event_string (cnc, "%s",
                                                  _("The connection string must contain the DB_NAME value"));
                 return FALSE;
         }
@@ -290,6 +293,26 @@ gda_ldap_provider_open_connection (GdaServerProvider *provider, GdaConnection *c
         if (!pwd)
                 pwd = gda_quark_list_find (params, "PASSWORD");
 
+	tls_cacert = gda_quark_list_find (params, "TLS_CACERT");
+	tls_method = gda_quark_list_find (params, "TLS_REQCERT");
+	if (tls_method && *tls_method) {
+		if (! g_ascii_strcasecmp (tls_method, "never"))
+			rtls_method = LDAP_OPT_X_TLS_NEVER;
+		else if (! g_ascii_strcasecmp (tls_method, "hard"))
+			rtls_method = LDAP_OPT_X_TLS_HARD;
+		else if (! g_ascii_strcasecmp (tls_method, "demand"))
+			rtls_method = LDAP_OPT_X_TLS_DEMAND;
+		else if (! g_ascii_strcasecmp (tls_method, "allow"))
+			rtls_method = LDAP_OPT_X_TLS_ALLOW;
+		else if (! g_ascii_strcasecmp (tls_method, "try"))
+			rtls_method = LDAP_OPT_X_TLS_TRY;
+		else {
+			gda_connection_add_event_string (cnc, "%s",
+							 _("Invalid value for 'TLS_REQCERT'"));
+			return FALSE;
+		}
+	}
+
 	/* open LDAP connection */
 	LdapConnectionData *cdata;
 	LDAP *ld;
@@ -330,7 +353,6 @@ gda_ldap_provider_open_connection (GdaServerProvider *provider, GdaConnection *c
         }
 	res = ldap_set_option (cdata->handle, LDAP_OPT_RESTART, LDAP_OPT_ON);
 
-#ifdef NO
 	if (use_ssl) {
 		/* Configuring SSL/TLS options:
 		 * this is for texting purpose only, and should actually be done through LDAP's conf.
@@ -343,15 +365,24 @@ gda_ldap_provider_open_connection (GdaServerProvider *provider, GdaConnection *c
 		 * Note: if server certificate verification fails,
 		 * the error message is: "Can't contact LDAP server"
 		 */
-		int opt = LDAP_OPT_X_TLS_DEMAND;
-		res = ldap_set_option (cdata->handle, LDAP_OPT_X_TLS_REQUIRE_CERT, &opt);
-		if (res != LDAP_SUCCESS) {
-			gda_connection_add_event_string (cnc, ldap_err2string (res));
-			gda_ldap_free_cnc_data (cdata);
-			return FALSE;
+		if (rtls_method >= 0) {
+			res = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &rtls_method);
+			if (res != LDAP_SUCCESS) {
+				gda_connection_add_event_string (cnc, ldap_err2string (res));
+				gda_ldap_free_cnc_data (cdata);
+				return FALSE;
+			}
+		}
+
+		if (tls_cacert && *tls_cacert) {
+			res = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE, tls_cacert);
+			if (res != LDAP_SUCCESS) {
+				gda_connection_add_event_string (cnc, ldap_err2string (res));
+				gda_ldap_free_cnc_data (cdata);
+				return FALSE;
+			}
 		}
 	}
-#endif
 
 	/* authentication */
 	struct berval cred;
diff --git a/providers/ldap/ldap_specs_dsn.xml.in b/providers/ldap/ldap_specs_dsn.xml.in
index 9e2ca99..b0fd8f4 100644
--- a/providers/ldap/ldap_specs_dsn.xml.in
+++ b/providers/ldap/ldap_specs_dsn.xml.in
@@ -5,8 +5,34 @@
     <parameter id="HOST" _name="Database server" _descr="Host on which the LDAP server is running" gdatype="gchararray"/>
     <parameter id="PORT" _name="Port" _descr="Database server port (leave this field empty to use the default port)" gdatype="gint"/>
     <parameter id="USE_SSL" _name="Require SSL" _descr="Whether or not to use SSL to establish the connection" gdatype="gboolean"/>
+    <parameter id="TLS_REQCERT" _name="Certificate check type" _descr="Specifies what checks to perform on server certificates in a SSL/TLS session" gdatype="string" source="methods:0"/>
+    <parameter id="TLS_CACERT" _name="Certificates file" _descr="Specifies the file that contains certificates for all of the recognized Certificate Authorities, in a SSL/TLS session" gdatype="string" plugin="filesel:MODE=OPEN"/>
     <parameter id="USE_CACHE" _name="Cache server data" _descr="Use a cache to store some static server data (the cached files are in the user's cache directory), default is TRUE" gdatype="gboolean">
       <gda_value>TRUE</gda_value>
     </parameter>
   </parameters>
+  <sources>
+    <gda_array name="methods">
+      <gda_array_field name="id" gdatype="gchararray"/>
+      <gda_array_field name="text" gdatype="gchararray"/>
+      <gda_array_data>
+        <gda_array_row>
+          <gda_value>NEVER</gda_value>
+          <_gda_value>Never: certificate not requested or checked</_gda_value>
+        </gda_array_row>
+        <gda_array_row>
+          <gda_value>ALLOW</gda_value>
+          <_gda_value>Allow: certificate requested, none or a bad one accepted.</_gda_value>
+        </gda_array_row>
+        <gda_array_row>
+          <gda_value>TRY</gda_value>
+          <_gda_value>Try: certificate requested, none accepted, otherwise checked.</_gda_value>
+        </gda_array_row>
+        <gda_array_row>
+          <gda_value>DEMAND</gda_value>
+          <_gda_value>Demand: certificate requested and checked</_gda_value>
+        </gda_array_row>
+      </gda_array_data>
+    </gda_array>
+  </sources>
 </data-set-spec>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]