diff options
-rw-r--r-- | src/libcharon/plugins/nm/gnome/NEWS | 5 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/gnome/auth-dialog/main.c | 14 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/gnome/configure.ac | 2 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/gnome/po/de.po | 30 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/gnome/properties/nm-strongswan.c | 17 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/nm_creds.c | 35 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/nm_creds.h | 8 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/nm_service.c | 88 |
8 files changed, 180 insertions, 19 deletions
diff --git a/src/libcharon/plugins/nm/gnome/NEWS b/src/libcharon/plugins/nm/gnome/NEWS index 762e2f512..f84ccc836 100644 --- a/src/libcharon/plugins/nm/gnome/NEWS +++ b/src/libcharon/plugins/nm/gnome/NEWS @@ -1,3 +1,8 @@ +NetworkManager-strongswan-1.2.0 +------------------------------- + +- Added Smartcard support + NetworkManager-strongswan-1.1.2 ------------------------------- diff --git a/src/libcharon/plugins/nm/gnome/auth-dialog/main.c b/src/libcharon/plugins/nm/gnome/auth-dialog/main.c index f2716f2d0..686ff290f 100644 --- a/src/libcharon/plugins/nm/gnome/auth-dialog/main.c +++ b/src/libcharon/plugins/nm/gnome/auth-dialog/main.c @@ -162,7 +162,7 @@ int main (int argc, char *argv[]) g_object_unref (program); return 1; } - if (!strcmp(type, "eap") || !strcmp(type, "key")) + if (!strcmp(type, "eap") || !strcmp(type, "key") || !strcmp(type, "smartcard")) { pass = lookup_password(name, service); if (!pass || retry) @@ -172,14 +172,22 @@ int main (int argc, char *argv[]) dialog = gnome_password_dialog_new(_("VPN password required"), _("EAP password required to establish VPN connection:"), NULL, NULL, TRUE); + gnome_password_dialog_set_show_remember(GNOME_PASSWORD_DIALOG(dialog), TRUE); } - else + else if (!strcmp(type, "key")) { dialog = gnome_password_dialog_new(_("VPN password required"), _("Private key decryption password required to establish VPN connection:"), NULL, NULL, TRUE); + gnome_password_dialog_set_show_remember(GNOME_PASSWORD_DIALOG(dialog), TRUE); + } + else /* smartcard */ + { + dialog = gnome_password_dialog_new(_("VPN password required"), + _("Smartcard PIN required to establish VPN connection:"), + NULL, NULL, TRUE); + gnome_password_dialog_set_show_remember(GNOME_PASSWORD_DIALOG(dialog), FALSE); } - gnome_password_dialog_set_show_remember(GNOME_PASSWORD_DIALOG(dialog), TRUE); gnome_password_dialog_set_show_username(GNOME_PASSWORD_DIALOG(dialog), FALSE); if (pass) { diff --git a/src/libcharon/plugins/nm/gnome/configure.ac b/src/libcharon/plugins/nm/gnome/configure.ac index b15e6e6cf..148db3e28 100644 --- a/src/libcharon/plugins/nm/gnome/configure.ac +++ b/src/libcharon/plugins/nm/gnome/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ(2.52) -AC_INIT(NetworkManager-strongswan, 1.1.2, martin@strongswan.org, NetworkManager-strongswan) +AC_INIT(NetworkManager-strongswan, 1.2.0, martin@strongswan.org, NetworkManager-strongswan) AM_INIT_AUTOMAKE([subdir-objects]) AM_MAINTAINER_MODE diff --git a/src/libcharon/plugins/nm/gnome/po/de.po b/src/libcharon/plugins/nm/gnome/po/de.po index 52fb7ff5e..e6649e581 100644 --- a/src/libcharon/plugins/nm/gnome/po/de.po +++ b/src/libcharon/plugins/nm/gnome/po/de.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: NetworkManager-strongswan\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-02-18 09:20+0100\n" +"POT-Creation-Date: 2010-08-11 16:12+0200\n" "PO-Revision-Date: 2010-02-18 09:20+0100\n" "Last-Translator: Martin Willi <martin@strongswan.org>\n" "Language-Team: de <martin@strongswan.org>\n" @@ -22,15 +22,19 @@ msgstr "IPsec/IKEv2 (strongswan)" msgid "IPsec with the IKEv2 key exchange protocol." msgstr "IPsec mit dem IKEv2 Protokoll." -#: ../properties/nm-strongswan.c:200 +#: ../properties/nm-strongswan.c:208 msgid "Certificate/private key" msgstr "Zertifikat/Privater Schlüssel" -#: ../properties/nm-strongswan.c:201 +#: ../properties/nm-strongswan.c:209 msgid "Certificate/ssh-agent" msgstr "Zertifikat/ssh-agent" -#: ../properties/nm-strongswan.c:202 +#: ../properties/nm-strongswan.c:210 +msgid "Smartcard" +msgstr "Smartcard" + +#: ../properties/nm-strongswan.c:211 msgid "EAP" msgstr "EAP" @@ -87,8 +91,8 @@ msgid "" "IPComp compresses raw IP packets before they get encrypted. This saves some " "bandwith, but uses more processing power." msgstr "" -"IPComp komprimiert IP-Pakete, bevor sie verschlsselt werden. Diese Option " -"kann Bandbreite sparen, bentigt jedoch zustzliche Rechenleistung." +"IPComp komprimiert IP-Pakete, bevor sie verschlüsselt werden. Diese Option " +"kann Bandbreite sparen, benötigt jedoch zusätzliche Rechenleistung." #: ../properties/nm-strongswan-dialog.glade.h:13 msgid "Private _key:" @@ -126,7 +130,7 @@ msgstr "" #: ../properties/nm-strongswan-dialog.glade.h:18 msgid "The username (identity) to use for authentication against the gateway." -msgstr "Benutzername/Identitt für die Authentisierung gegenüber dem Gateway." +msgstr "Benutzername/Identität für die Authentisierung gegenüber dem Gateway." #: ../properties/nm-strongswan-dialog.glade.h:19 msgid "Use IP c_ompression" @@ -140,7 +144,8 @@ msgstr "_Adresse:" msgid "_Username:" msgstr "_Benutzername:" -#: ../auth-dialog/main.c:172 ../auth-dialog/main.c:178 +#: ../auth-dialog/main.c:172 ../auth-dialog/main.c:179 +#: ../auth-dialog/main.c:186 msgid "VPN password required" msgstr "VPN Passwort notwendig" @@ -148,13 +153,18 @@ msgstr "VPN Passwort notwendig" msgid "EAP password required to establish VPN connection:" msgstr "Für die Erstellung des VPN-Tunnels ist ein EAP-Passwort erforderlich:" -#: ../auth-dialog/main.c:179 +#: ../auth-dialog/main.c:180 msgid "Private key decryption password required to establish VPN connection:" msgstr "" "Der Private Schlüssel für die Erstellung des VPN-Tunnels ist durch ein " "Passwort geschützt:" -#: ../auth-dialog/main.c:225 +#: ../auth-dialog/main.c:187 +#, fuzzy +msgid "Smartcard PIN required to establish VPN connection:" +msgstr "Für die Smartcard ist eine PIN erforderlich:" + +#: ../auth-dialog/main.c:233 msgid "" "Configuration uses ssh-agent for authentication, but ssh-agent is not " "running!" diff --git a/src/libcharon/plugins/nm/gnome/properties/nm-strongswan.c b/src/libcharon/plugins/nm/gnome/properties/nm-strongswan.c index 4b69296b4..45c0df32d 100644 --- a/src/libcharon/plugins/nm/gnome/properties/nm-strongswan.c +++ b/src/libcharon/plugins/nm/gnome/properties/nm-strongswan.c @@ -142,6 +142,14 @@ static void update_layout (GtkWidget *widget, StrongswanPluginUiWidgetPrivate *p gtk_widget_hide (glade_xml_get_widget (priv->xml, "userkey-button")); break; case 2: + gtk_widget_hide (glade_xml_get_widget (priv->xml, "usercert-label")); + gtk_widget_hide (glade_xml_get_widget (priv->xml, "usercert-button")); + gtk_widget_hide (glade_xml_get_widget (priv->xml, "user-label")); + gtk_widget_hide (glade_xml_get_widget (priv->xml, "user-entry")); + gtk_widget_hide (glade_xml_get_widget (priv->xml, "userkey-label")); + gtk_widget_hide (glade_xml_get_widget (priv->xml, "userkey-button")); + break; + case 3: gtk_widget_show (glade_xml_get_widget (priv->xml, "user-label")); gtk_widget_show (glade_xml_get_widget (priv->xml, "user-entry")); gtk_widget_hide (glade_xml_get_widget (priv->xml, "usercert-label")); @@ -199,6 +207,7 @@ init_plugin_ui (StrongswanPluginUiWidget *self, NMConnection *connection, GError widget = glade_xml_get_widget (priv->xml, "method-combo"); gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("Certificate/private key")); gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("Certificate/ssh-agent")); + gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("Smartcard")); gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("EAP")); value = nm_setting_vpn_get_data_item (settings, "method"); if (value) { @@ -208,9 +217,12 @@ init_plugin_ui (StrongswanPluginUiWidget *self, NMConnection *connection, GError if (g_strcmp0 (value, "agent") == 0) { gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1); } - if (g_strcmp0 (value, "eap") == 0) { + if (g_strcmp0 (value, "smartcard") == 0) { gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 2); } + if (g_strcmp0 (value, "eap") == 0) { + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 3); + } } if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) == -1) { @@ -330,6 +342,9 @@ update_connection (NMVpnPluginUiWidgetInterface *iface, str = "agent"; break; case 2: + str = "smartcard"; + break; + case 3: widget = glade_xml_get_widget (priv->xml, "user-entry"); str = (char *) gtk_entry_get_text (GTK_ENTRY (widget)); if (str && strlen (str)) { diff --git a/src/libcharon/plugins/nm/nm_creds.c b/src/libcharon/plugins/nm/nm_creds.c index 4ee94362f..638787019 100644 --- a/src/libcharon/plugins/nm/nm_creds.c +++ b/src/libcharon/plugins/nm/nm_creds.c @@ -51,11 +51,16 @@ struct private_nm_creds_t { char *pass; /** - * Private key decryption password + * Private key decryption password / smartcard pin */ char *keypass; /** + * private key ID of smartcard key + */ + chunk_t keyid; + + /** * users certificate */ certificate_t *usercert; @@ -296,6 +301,14 @@ static enumerator_t* create_shared_enumerator(private_nm_creds_t *this, } key = chunk_create(this->keypass, strlen(this->keypass)); break; + case SHARED_PIN: + if (!this->keypass || !me || + !chunk_equals(me->get_encoding(me), this->keyid)) + { + return NULL; + } + key = chunk_create(this->keypass, strlen(this->keypass)); + break; default: return NULL; } @@ -403,6 +416,19 @@ static void set_key_password(private_nm_creds_t *this, char *password) } /** + * Implementation of nm_creds_t.set_pin + */ +static void set_pin(private_nm_creds_t *this, chunk_t keyid, char *pin) +{ + this->lock->write_lock(this->lock); + free(this->keypass); + free(this->keyid.ptr); + this->keypass = pin ? strdup(pin) : NULL; + this->keyid = chunk_clone(keyid); + this->lock->unlock(this->lock); +} + +/** * Implementation of nm_creds_t.set_cert_and_key */ static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert, @@ -429,12 +455,16 @@ static void clear(private_nm_creds_t *this) } DESTROY_IF(this->user); free(this->pass); + free(this->keypass); + free(this->keyid.ptr); DESTROY_IF(this->usercert); DESTROY_IF(this->key); this->key = NULL; this->usercert = NULL; this->pass = NULL; this->user = NULL; + this->keypass = NULL; + this->keyid = chunk_empty; } /** @@ -464,6 +494,7 @@ nm_creds_t *nm_creds_create() this->public.load_ca_dir = (void(*)(nm_creds_t*, char *dir))load_ca_dir; this->public.set_username_password = (void(*)(nm_creds_t*, identification_t *id, char *password))set_username_password; this->public.set_key_password = (void(*)(nm_creds_t*, char *password))set_key_password; + this->public.set_pin = (void(*)(nm_creds_t*, chunk_t keyid, char *pin))set_pin; this->public.set_cert_and_key = (void(*)(nm_creds_t*, certificate_t *cert, private_key_t *key))set_cert_and_key; this->public.clear = (void(*)(nm_creds_t*))clear; this->public.destroy = (void(*)(nm_creds_t*))destroy; @@ -475,6 +506,8 @@ nm_creds_t *nm_creds_create() this->pass = NULL; this->usercert = NULL; this->key = NULL; + this->keypass = NULL; + this->keyid = chunk_empty; return &this->public; } diff --git a/src/libcharon/plugins/nm/nm_creds.h b/src/libcharon/plugins/nm/nm_creds.h index 44936dd6a..91f645c7e 100644 --- a/src/libcharon/plugins/nm/nm_creds.h +++ b/src/libcharon/plugins/nm/nm_creds.h @@ -67,6 +67,14 @@ struct nm_creds_t { void (*set_key_password)(nm_creds_t *this, char *password); /** + * Set the PIN to unlock a smartcard. + * + * @param keyid keyid of the smartcard key + * @param pin PIN + */ + void (*set_pin)(nm_creds_t *this, chunk_t keyid, char *pin); + + /** * Set the certificate and private key to use for client authentication. * * @param cert client certificate diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c index 910b01cc8..72c5bbbb5 100644 --- a/src/libcharon/plugins/nm/nm_service.c +++ b/src/libcharon/plugins/nm/nm_service.c @@ -204,6 +204,59 @@ static bool ike_rekey(listener_t *listener, ike_sa_t *old, ike_sa_t *new) } /** + * Find a certificate for which we have a private key on a smartcard + */ +static identification_t *find_smartcard_key(NMStrongswanPluginPrivate *priv, + char *pin) +{ + enumerator_t *enumerator, *sans; + identification_t *id = NULL; + certificate_t *cert; + x509_t *x509; + private_key_t *key; + chunk_t keyid; + + enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, + CERT_X509, KEY_ANY, NULL, FALSE); + while (enumerator->enumerate(enumerator, &cert)) + { + x509 = (x509_t*)cert; + + /* there might be a lot of certificates, filter them by usage */ + if ((x509->get_flags(x509) & X509_CLIENT_AUTH) && + !(x509->get_flags(x509) & X509_CA)) + { + keyid = x509->get_subjectKeyIdentifier(x509); + if (keyid.ptr) + { + /* try to find a private key by the certificate keyid */ + priv->creds->set_pin(priv->creds, keyid, pin); + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, + KEY_ANY, BUILD_PKCS11_KEYID, keyid, BUILD_END); + if (key) + { + /* prefer a more convenient subjectAltName */ + sans = x509->create_subjectAltName_enumerator(x509); + if (!sans->enumerate(sans, &id)) + { + id = cert->get_subject(cert); + } + id = id->clone(id); + sans->destroy(sans); + + DBG1(DBG_CFG, "using smartcard certificate '%Y'", id); + priv->creds->set_cert_and_key(priv->creds, + cert->get_ref(cert), key); + break; + } + } + } + } + enumerator->destroy(enumerator); + return id; +} + +/** * Connect function called from NM via DBUS */ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, @@ -224,7 +277,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, auth_class_t auth_class = AUTH_CLASS_EAP; certificate_t *cert = NULL; x509_t *x509; - bool agent = FALSE; + bool agent = FALSE, smartcard = FALSE; lifetime_cfg_t lifetime = { .time = { .life = 10800 /* 3h */, @@ -279,6 +332,11 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, { auth_class = AUTH_CLASS_PUBKEY; } + else if (streq(str, "smartcard")) + { + auth_class = AUTH_CLASS_PUBKEY; + smartcard = TRUE; + } } /** @@ -338,9 +396,26 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, if (auth_class == AUTH_CLASS_PUBKEY) { + if (smartcard) + { + char *pin; + + pin = (char*)nm_setting_vpn_get_secret(vpn, "password"); + if (pin) + { + user = find_smartcard_key(priv, pin); + } + if (!user) + { + g_set_error(err, NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "no usable smartcard certificate found."); + gateway->destroy(gateway); + return FALSE; + } + } /* ... or certificate/private key authenitcation */ - str = nm_setting_vpn_get_data_item(vpn, "usercert"); - if (str) + else if ((str = nm_setting_vpn_get_data_item(vpn, "usercert"))) { public_key_t *public; private_key_t *private = NULL; @@ -534,6 +609,13 @@ static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection, } } } + else if streq(method, "smartcard") + { + if (nm_setting_vpn_get_secret(settings, "password")) + { + return FALSE; + } + } } *setting_name = NM_SETTING_VPN_SETTING_NAME; return TRUE; |