supplicant: allow with_system_ca_path to be a file name (rh #1236548)
authorJiří Klimeš <jklimes@redhat.com>
Wed, 1 Jul 2015 12:11:12 +0000 (14:11 +0200)
committerJiří Klimeš <jklimes@redhat.com>
Wed, 8 Jul 2015 15:07:02 +0000 (17:07 +0200)
NetworkManager uses wpa_supplicant, which in turn calls OpenSSL for verifying
certificates. wpa_supplicant calls
SSL_CTX_load_verify_locations(ctx, CAfile, CApath)
using its ca_cert and ca_path options as CAfile and CApath parameters.

We have a configure time option with_system_ca_path to override ca_path.
However, it doesn't work when a system (like Fedora) only uses bundled PEM
certificates instead of a directory with hashed certificates ([1], [2]).

So this commit allows setting --with_system_ca_path to a file name (the
trusted certificate bundle). Then the name is used to populate wpa_supplicant's
ca_cert instead of ca_path.

[1] https://bugzilla.redhat.com/show_bug.cgi?id=1053882
[2] https://www.happyassassin.net/2015/01/12/a-note-about-ssltls-trusted-certificate-stores-and-platforms/

https://bugzilla.redhat.com/show_bug.cgi?id=1236548

contrib/fedora/rpm/NetworkManager.spec
libnm-core/nm-setting-8021x.c
src/supplicant-manager/nm-supplicant-config.c

index 0786b30..97621d6 100644 (file)
@@ -423,7 +423,7 @@ by nm-connection-editor and nm-applet in a non-graphical environment.
        --with-suspend-resume=systemd \
        --with-systemdsystemunitdir=%{systemd_dir} \
        --with-udev-dir=%{udev_dir} \
-       --with-system-ca-path=/etc/pki/tls/certs \
+       --with-system-ca-path=/etc/pki/tls/cert.pem \
        --with-tests=yes \
        --with-valgrind=no \
        --enable-ifcfg-rh=yes \
index 244cf55..235be6a 100644 (file)
@@ -3933,7 +3933,10 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
         * specified at configure time with the --system-ca-path switch.  The
         * certificates in this directory are added to the verification chain in
         * addition to any certificates specified by the #NMSetting8021x:ca-cert and
-        * #NMSetting8021x:phase2-ca-cert properties.
+        * #NMSetting8021x:phase2-ca-cert properties. If the path provided with
+        * --system-ca-path is rather a file name (bundle of trusted CA certificates),
+        * it overrides #NMSetting8021x:ca-cert and #NMSetting8021x:phase2-ca-cert
+        * properties instead (sets ca_cert/ca_cert2 options for wpa_supplicant).
         **/
        /* ---ifcfg-rh---
         * property: system-ca-certs
index 5df7b1e..b78a24d 100644 (file)
@@ -733,6 +733,7 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
        gboolean fast = FALSE;
        guint32 i, num_eap;
        gboolean fast_provisoning_allowed = FALSE;
+       const char *ca_path_override = NULL, *ca_cert_override = NULL;
 
        g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
        g_return_val_if_fail (setting != NULL, FALSE);
@@ -870,10 +871,18 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
                }
        }
 
+       /* If user wants to use system CA certs, either populate ca_path (if the path
+        * is a directory) or ca_cert (the path is a file name) */
+       if (nm_setting_802_1x_get_system_ca_certs (setting)) {
+               if (g_file_test (SYSTEM_CA_PATH, G_FILE_TEST_IS_DIR))
+                       ca_path_override = SYSTEM_CA_PATH;
+               else
+                       ca_cert_override = SYSTEM_CA_PATH;
+       }
+
        /* CA path */
        path = nm_setting_802_1x_get_ca_path (setting);
-       if (nm_setting_802_1x_get_system_ca_certs (setting))
-               path = SYSTEM_CA_PATH;
+       path = ca_path_override ? ca_path_override : path;
        if (path) {
                if (!add_string_val (self, path, "ca_path", FALSE, FALSE))
                        return FALSE;
@@ -881,41 +890,50 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
 
        /* Phase2 CA path */
        path = nm_setting_802_1x_get_phase2_ca_path (setting);
-       if (nm_setting_802_1x_get_system_ca_certs (setting))
-               path = SYSTEM_CA_PATH;
+       path = ca_path_override ? ca_path_override : path;
        if (path) {
                if (!add_string_val (self, path, "ca_path2", FALSE, FALSE))
                        return FALSE;
        }
 
        /* CA certificate */
-       switch (nm_setting_802_1x_get_ca_cert_scheme (setting)) {
-       case NM_SETTING_802_1X_CK_SCHEME_BLOB:
-               bytes = nm_setting_802_1x_get_ca_cert_blob (setting);
-               ADD_BLOB_VAL (bytes, "ca_cert", con_uuid);
-               break;
-       case NM_SETTING_802_1X_CK_SCHEME_PATH:
-               path = nm_setting_802_1x_get_ca_cert_path (setting);
-               if (!add_string_val (self, path, "ca_cert", FALSE, FALSE))
+       if (ca_cert_override) {
+               if (!add_string_val (self, ca_cert_override, "ca_cert", FALSE, FALSE))
                        return FALSE;
-               break;
-       default:
-               break;
+       } else {
+               switch (nm_setting_802_1x_get_ca_cert_scheme (setting)) {
+               case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+                       bytes = nm_setting_802_1x_get_ca_cert_blob (setting);
+                       ADD_BLOB_VAL (bytes, "ca_cert", con_uuid);
+                       break;
+               case NM_SETTING_802_1X_CK_SCHEME_PATH:
+                       path = nm_setting_802_1x_get_ca_cert_path (setting);
+                       if (!add_string_val (self, path, "ca_cert", FALSE, FALSE))
+                               return FALSE;
+                       break;
+               default:
+                       break;
+               }
        }
 
        /* Phase 2 CA certificate */
-       switch (nm_setting_802_1x_get_phase2_ca_cert_scheme (setting)) {
-       case NM_SETTING_802_1X_CK_SCHEME_BLOB:
-               bytes = nm_setting_802_1x_get_phase2_ca_cert_blob (setting);
-               ADD_BLOB_VAL (bytes, "ca_cert2", con_uuid);
-               break;
-       case NM_SETTING_802_1X_CK_SCHEME_PATH:
-               path = nm_setting_802_1x_get_phase2_ca_cert_path (setting);
-               if (!add_string_val (self, path, "ca_cert2", FALSE, FALSE))
+       if (ca_cert_override) {
+               if (!add_string_val (self, ca_cert_override, "ca_cert2", FALSE, FALSE))
                        return FALSE;
-               break;
-       default:
-               break;
+       } else {
+               switch (nm_setting_802_1x_get_phase2_ca_cert_scheme (setting)) {
+               case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+                       bytes = nm_setting_802_1x_get_phase2_ca_cert_blob (setting);
+                       ADD_BLOB_VAL (bytes, "ca_cert2", con_uuid);
+                       break;
+               case NM_SETTING_802_1X_CK_SCHEME_PATH:
+                       path = nm_setting_802_1x_get_phase2_ca_cert_path (setting);
+                       if (!add_string_val (self, path, "ca_cert2", FALSE, FALSE))
+                               return FALSE;
+                       break;
+               default:
+                       break;
+               }
        }
 
        /* Subject match */