fixed shared key lookup by ID
authorMartin Willi <martin@strongswan.org>
Wed, 20 Aug 2008 08:51:18 +0000 (08:51 -0000)
committerMartin Willi <martin@strongswan.org>
Wed, 20 Aug 2008 08:51:18 +0000 (08:51 -0000)
proper auth method selection

src/charon/plugins/nm/gnome/nm-strongswan-service.name.in
src/charon/plugins/nm/gnome/properties/nm-strongswan.c
src/charon/plugins/nm/nm_creds.c
src/charon/plugins/nm/nm_creds.h
src/charon/plugins/nm/nm_service.c

index 1555d48..9d8f0f0 100644 (file)
@@ -4,5 +4,5 @@ service=org.freedesktop.NetworkManager.strongswan
 program=@LIBEXECDIR@/ipsec/charon
 
 [GNOME]
-auth-dialog=nm-strongswan-auth-dialog
+auth-dialog=@LIBEXECDIR@/nm-strongswan-auth-dialog
 properties=libnm-strongswan-properties
index 285a7f7..edaaf03 100644 (file)
@@ -178,12 +178,16 @@ init_plugin_ui (StrongswanPluginUiWidget *self, NMConnection *connection, GError
        widget = glade_xml_get_widget (priv->xml, "method-combo");
        if (!widget)
                return FALSE;
-       gtk_combo_box_append_text (GTK_COMBO_BOX (widget), "EAP");
+       gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("EAP"));
+       gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("PSK (insecure)"));
        value = g_hash_table_lookup (settings->data, "method");
        if (value) {
-               if (g_strcasecmp (value, "EAP") == 0) {
+               if (g_strcasecmp (value, "eap") == 0) {
                        gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
                }
+               if (g_strcasecmp (value, "psk") == 0) {
+                       gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
+               }
        }
        g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
        if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) == -1)
@@ -272,10 +276,19 @@ update_connection (NMVpnPluginUiWidgetInterface *iface,
        }
 
        widget = glade_xml_get_widget (priv->xml, "method-combo");
-       str = (char *) gtk_combo_box_get_active_text (GTK_COMBO_BOX (widget));
-       if (str) {
-               g_hash_table_insert (settings->data, g_strdup ("method"), g_strdup(str));
+       switch (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)))
+       {
+               default:
+                       str = "eap";
+                       break;
+               case 1:
+                       str = "psk";
+                       break;
+               case 2:
+                       str = "pubkey";
+                       break;
        }
+       g_hash_table_insert (settings->data, g_strdup ("method"), g_strdup(str));
        
        widget = glade_xml_get_widget (priv->xml, "virtual-check");
        active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
index ebfc101..cb06c74 100644 (file)
@@ -40,6 +40,11 @@ struct private_nm_creds_t {
        certificate_t *cert;
        
        /**
+        * User name
+        */
+       identification_t *user;
+       
+       /**
         * User password
         */
        char *pass;
@@ -57,33 +62,107 @@ static enumerator_t* create_cert_enumerator(private_nm_creds_t *this,
                                                        certificate_type_t cert, key_type_t key,
                                                        identification_t *id, bool trusted)
 {
-       if (!this->cert ||
-               (cert != CERT_ANY && cert != this->cert->get_type(this->cert)))
+       if (!this->cert)
+       {
+               return NULL;
+       }
+       if (cert != CERT_ANY && cert != this->cert->get_type(this->cert))
        {
                return NULL;
        }
+       if (id && !this->cert->has_subject(this->cert, id))
+       {
+               return NULL;
+       }
+       if (key != KEY_ANY)
+       {
+               public_key_t *public;
+       
+               public = this->cert->get_public_key(this->cert);
+               if (!public)
+               {
+                       return NULL;
+               }
+               if (public->get_type(public) != key)
+               {
+                       public->destroy(public);
+                       return NULL;
+               }
+               public->destroy(public);
+       }
+       pthread_rwlock_rdlock(&this->lock);
        return enumerator_create_cleaner(enumerator_create_single(this->cert, NULL),
                                                                         (void*)pthread_rwlock_unlock, &this->lock);
 }
 
 /**
+ * shared key enumerator implementation
+ */
+typedef struct {
+       enumerator_t public;
+       private_nm_creds_t *this;
+       shared_key_t *key;
+       bool done;
+} shared_enumerator_t;
+
+/**
+ * enumerate function for shared enumerator
+ */
+static bool shared_enumerate(shared_enumerator_t *this, shared_key_t **key,
+                                                        id_match_t *me, id_match_t *other)
+{
+       if (this->done)
+       {
+               return FALSE;
+       }
+       *key = this->key;
+       *me = ID_MATCH_PERFECT;
+       *other = ID_MATCH_ANY;
+       this->done = TRUE;
+       return TRUE;
+}
+
+/**
+ * Destroy function for shared enumerator
+ */
+static void shared_destroy(shared_enumerator_t *this)
+{
+       this->key->destroy(this->key);
+       pthread_rwlock_unlock(&this->this->lock);
+       free(this);
+}
+/**
  * Implements credential_set_t.create_cert_enumerator
  */
 static enumerator_t* create_shared_enumerator(private_nm_creds_t *this, 
                                                        shared_key_type_t type, identification_t *me,
                                                        identification_t *other)
 {
-       shared_key_t *key;
+       shared_enumerator_t *enumerator;
 
-       if (!this->pass || (type != SHARED_EAP && type != SHARED_IKE))
+       if (!this->pass || !this->user)
+       {
+               return NULL;
+       }
+       if (type != SHARED_EAP && type != SHARED_IKE)
        {
                return NULL;
        }
-       key = shared_key_create(type, chunk_clone(
-                                                               chunk_create(this->pass, strlen(this->pass))));
-       return enumerator_create_cleaner(
-                                               enumerator_create_single(key, (void*)key->destroy),
-                                               (void*)pthread_rwlock_unlock, &this->lock);
+       if (me && !me->equals(me, this->user))
+       {
+               return NULL;
+       }
+       
+       enumerator = malloc_thing(shared_enumerator_t);
+       enumerator->public.enumerate = (void*)shared_enumerate;
+       enumerator->public.destroy = (void*)shared_destroy;
+       enumerator->this = this;
+       enumerator->done = FALSE;
+       pthread_rwlock_rdlock(&this->lock);
+       enumerator->key = shared_key_create(type,
+                                                                               chunk_clone(chunk_create(this->pass,
+                                                                                                       strlen(this->pass))));
+       return &enumerator->public;
 }
 
 /**
@@ -100,9 +179,12 @@ static void set_certificate(private_nm_creds_t *this, certificate_t *cert)
 /**
  * Implementation of nm_creds_t.set_password
  */
-static void set_password(private_nm_creds_t *this, char *password)
+static void set_password(private_nm_creds_t *this, identification_t *id,
+                                                char *password)
 {
        pthread_rwlock_wrlock(&this->lock);
+       DESTROY_IF(this->user);
+       this->user = id->clone(id);
        free(this->pass);
        this->pass = strdup(password);
        pthread_rwlock_unlock(&this->lock);
@@ -114,6 +196,7 @@ static void set_password(private_nm_creds_t *this, char *password)
 static void destroy(private_nm_creds_t *this)
 {
        DESTROY_IF(this->cert);
+       DESTROY_IF(this->user);
        free(this->pass);
        pthread_rwlock_destroy(&this->lock);
        free(this);
@@ -132,12 +215,13 @@ nm_creds_t *nm_creds_create()
        this->public.set.create_cdp_enumerator = (void*)return_null;
        this->public.set.cache_cert = (void*)nop;
        this->public.set_certificate = (void(*)(nm_creds_t*, certificate_t *cert))set_certificate;
-       this->public.set_password = (void(*)(nm_creds_t*, char *password))set_password;
+       this->public.set_password = (void(*)(nm_creds_t*, identification_t *id, char *password))set_password;
        this->public.destroy = (void(*)(nm_creds_t*))destroy;
        
        pthread_rwlock_init(&this->lock, NULL);
        
        this->cert = NULL;
+       this->user = NULL;
        this->pass = NULL;
        
        return &this->public;
index 773f241..40cfb77 100644 (file)
@@ -45,11 +45,12 @@ struct nm_creds_t {
        void (*set_certificate)(nm_creds_t *this, certificate_t *cert);
        
        /**
-        * Set the userpassword for authentication.
+        * Set the username/password for authentication.
         *
+        * @param id            ID of the user
         * @param password      password to use for authentication
         */
-       void (*set_password)(nm_creds_t *this, char *password);
+       void (*set_password)(nm_creds_t *this, identification_t *id, char *password);
        
        /**
      * Destroy a nm_creds instance.
index 123251a..2fc4ab2 100644 (file)
@@ -142,10 +142,9 @@ bool listen_bus(bus_listener_t *listener, signal_t signal, level_t level,
                                /* FALL */
                        case IKE_UP_FAILED:
                        case CHD_UP_FAILED:
+                               /* TODO: NM does not handle this failure!? 
                                nm_vpn_plugin_failure(private->plugin,
-                                                                         NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
-                               /* TODO: NM does not react on this failure!? So additionaly
-                                * reset state */
+                                                                         NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); */
                                nm_vpn_plugin_set_state(private->plugin,
                                                                                NM_VPN_SERVICE_STATE_STOPPED);
                                return FALSE;
@@ -172,6 +171,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
        child_cfg_t *child_cfg;
        traffic_selector_t *ts;
        ike_sa_t *ike_sa;
+       config_auth_method_t method = CONF_AUTH_EAP;
        
        /**
         * Read parameters
@@ -207,6 +207,18 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
        encap = str && streq(str, "yes");
        str = g_hash_table_lookup(settings->data, "ipcomp");
        ipcomp = str && streq(str, "yes");
+       str = g_hash_table_lookup(settings->data, "method");
+       if (str)
+       {
+               if (streq(str, "psk"))
+               {
+                       method = CONF_AUTH_PSK;
+               }
+               else if (streq(str, "pubkey"))
+               {
+                       method = CONF_AUTH_PUBKEY;
+               }
+       }
        
        /**
         * Register credentials
@@ -225,7 +237,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
        str = g_hash_table_lookup(settings->data, "password");
        if (str)
        {
-               creds->set_password(creds, str);
+               creds->set_password(creds, user, str);
        }
        
        /**
@@ -235,7 +247,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
        ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
        peer_cfg = peer_cfg_create(CONFIG_NAME, 2, ike_cfg, user,
                                        identification_create_from_encoding(ID_ANY, chunk_empty),
-                                       CERT_SEND_IF_ASKED, UNIQUE_REPLACE, CONF_AUTH_PSK,
+                                       CERT_SEND_IF_ASKED, UNIQUE_REPLACE, method,
                                        0, 0, 1, /* EAP method, vendor, keyingtries */
                                        18000, 0, /* rekey 5h, reauth none */
                                        600, 600, /* jitter, over 10min */