Skip to content

Instantly share code, notes, and snippets.

@Et7f3
Last active June 10, 2023 15:02
Show Gist options
  • Save Et7f3/894f09d27b17c980a5bd6ba085dd804a to your computer and use it in GitHub Desktop.
Save Et7f3/894f09d27b17c980a5bd6ba085dd804a to your computer and use it in GitHub Desktop.
diff --git a/auth-dialog/main.c b/auth-dialog/main.c
index 459802a..37bdf4b 100644
--- a/auth-dialog/main.c
+++ b/auth-dialog/main.c
@@ -93,6 +93,9 @@ typedef gboolean (*AskUserFunc) (const char *vpn_name,
gboolean need_password,
const char *existing_password,
char **out_new_password,
+ gboolean need_pin,
+ const char *existing_pin,
+ char **out_new_pin,
gboolean need_certpass,
const char *existing_certpass,
char **out_new_certpass,
@@ -105,6 +108,8 @@ typedef void (*FinishFunc) (const char *vpn_name,
gboolean allow_interaction,
gboolean need_password,
const char *password,
+ gboolean need_pin,
+ const char *pin,
gboolean need_certpass,
const char *certpass,
gboolean need_proxypass,
@@ -159,6 +164,8 @@ eui_finish (const char *vpn_name,
gboolean allow_interaction,
gboolean need_password,
const char *existing_password,
+ gboolean need_pin,
+ const char *existing_pin,
gboolean need_certpass,
const char *existing_certpass,
gboolean need_proxypass,
@@ -183,6 +190,13 @@ eui_finish (const char *vpn_name,
TRUE,
need_password && allow_interaction);
+ keyfile_add_entry_info (keyfile,
+ NM_OPENVPN_KEY_PKCS11_PIN,
+ existing_pin ? existing_pin : "",
+ _("PIN:"),
+ TRUE,
+ need_pin && allow_interaction);
+
keyfile_add_entry_info (keyfile,
NM_OPENVPN_KEY_CERTPASS,
existing_certpass ? existing_certpass : "",
@@ -215,6 +229,9 @@ std_ask_user (const char *vpn_name,
gboolean need_password,
const char *existing_password,
char **out_new_password,
+ gboolean need_pin,
+ const char *existing_pin,
+ char **out_new_pin,
gboolean need_certpass,
const char *existing_certpass,
char **out_new_certpass,
@@ -228,6 +245,7 @@ std_ask_user (const char *vpn_name,
g_return_val_if_fail (vpn_name != NULL, FALSE);
g_return_val_if_fail (prompt != NULL, FALSE);
g_return_val_if_fail (out_new_password != NULL, FALSE);
+ g_return_val_if_fail (out_new_pin != NULL, FALSE);
g_return_val_if_fail (out_new_certpass != NULL, FALSE);
g_return_val_if_fail (out_new_proxypass != NULL, FALSE);
@@ -240,10 +258,13 @@ std_ask_user (const char *vpn_name,
if (need_password)
nma_vpn_password_dialog_set_password (dialog, existing_password);
- nma_vpn_password_dialog_set_show_password_secondary (dialog, need_certpass);
+ nma_vpn_password_dialog_set_show_password_secondary (dialog, need_certpass || need_pin);
if (need_certpass) {
nma_vpn_password_dialog_set_password_secondary_label (dialog, _("Certificate pass_word:") );
nma_vpn_password_dialog_set_password_secondary (dialog, existing_certpass);
+ } else if (need_pin) {
+ nma_vpn_password_dialog_set_password_secondary_label (dialog, _("PKCS#11 PIN:") );
+ nma_vpn_password_dialog_set_password_secondary (dialog, existing_pin);
}
nma_vpn_password_dialog_set_show_password_ternary (dialog, need_proxypass);
@@ -256,6 +277,8 @@ std_ask_user (const char *vpn_name,
if (nma_vpn_password_dialog_run_and_block (dialog)) {
if (need_password)
*out_new_password = g_strdup (nma_vpn_password_dialog_get_password (dialog));
+ if (need_pin)
+ *out_new_pin = g_strdup (nma_vpn_password_dialog_get_password_secondary (dialog));
if (need_certpass)
*out_new_certpass = g_strdup (nma_vpn_password_dialog_get_password_secondary (dialog));
if (need_proxypass)
@@ -299,6 +322,8 @@ std_finish (const char *vpn_name,
gboolean allow_interaction,
gboolean need_password,
const char *password,
+ gboolean need_pin,
+ const char *pin,
gboolean need_certpass,
const char *certpass,
gboolean need_proxypass,
@@ -307,6 +332,8 @@ std_finish (const char *vpn_name,
/* Send the passwords back to our parent */
if (password)
printf ("%s\n%s\n", NM_OPENVPN_KEY_PASSWORD, password);
+ if (pin)
+ printf ("%s\n%s\n", NM_OPENVPN_KEY_PKCS11_PIN, pin);
if (certpass)
printf ("%s\n%s\n", NM_OPENVPN_KEY_CERTPASS, certpass);
if (proxypass)
@@ -327,9 +354,11 @@ get_existing_passwords (GHashTable *vpn_data,
GHashTable *existing_secrets,
const char *vpn_uuid,
gboolean need_password,
+ gboolean need_pin,
gboolean need_certpass,
gboolean need_proxypass,
char **out_password,
+ char **out_pin,
char **out_certpass,
char **out_proxypass)
{
@@ -338,6 +367,7 @@ get_existing_passwords (GHashTable *vpn_data,
NMSettingSecretFlags proxy_flags = NM_SETTING_SECRET_FLAG_NONE;
g_return_if_fail (out_password != NULL);
+ g_return_if_fail (out_pin != NULL);
g_return_if_fail (out_certpass != NULL);
g_return_if_fail (out_proxypass != NULL);
@@ -350,6 +380,15 @@ get_existing_passwords (GHashTable *vpn_data,
}
}
+ nm_vpn_service_plugin_get_secret_flags (vpn_data, NM_OPENVPN_KEY_PKCS11_PIN, &pw_flags);
+ if (need_pin) {
+ if (!(pw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)) {
+ *out_pin = g_strdup (g_hash_table_lookup (existing_secrets, NM_OPENVPN_KEY_PKCS11_PIN));
+ if (!*out_pin)
+ *out_pin = keyring_lookup_secret (vpn_uuid, NM_OPENVPN_KEY_PKCS11_PIN);
+ }
+ }
+
nm_vpn_service_plugin_get_secret_flags (vpn_data, NM_OPENVPN_KEY_CERTPASS, &cp_flags);
if (need_certpass) {
if (!(cp_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)) {
@@ -375,6 +414,7 @@ static char *
get_passwords_required (GHashTable *data,
const char *const*hints,
gboolean *out_need_password,
+ gboolean *out_need_pin,
gboolean *out_need_certpass,
gboolean *out_need_proxypass)
{
@@ -384,6 +424,7 @@ get_passwords_required (GHashTable *data,
const char *const*iter;
*out_need_password = FALSE;
+ *out_need_pin = FALSE;
*out_need_certpass = FALSE;
*out_need_proxypass = FALSE;
@@ -405,11 +446,19 @@ get_passwords_required (GHashTable *data,
ctype = g_hash_table_lookup (data, NM_OPENVPN_KEY_CONNECTION_TYPE);
g_return_val_if_fail (ctype != NULL, NULL);
- if (!strcmp (ctype, NM_OPENVPN_CONTYPE_TLS) || !strcmp (ctype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
+ if ( !strcmp (ctype, NM_OPENVPN_CONTYPE_TLS)
+ || !strcmp (ctype, NM_OPENVPN_CONTYPE_TLS_PKCS11)
+ || !strcmp (ctype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)
+ || !strcmp (ctype, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11)) {
+ /* PKCS11 PIN */
+ if ( !strcmp (ctype, NM_OPENVPN_CONTYPE_TLS_PKCS11)
+ || !strcmp (ctype, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11))
+ *out_need_pin = TRUE;
+
/* Normal user password */
flags = NM_SETTING_SECRET_FLAG_NONE;
nm_vpn_service_plugin_get_secret_flags (data, NM_OPENVPN_KEY_PASSWORD, &flags);
- if ( !strcmp (ctype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)
+ if ( (!strcmp (ctype, NM_OPENVPN_CONTYPE_PASSWORD_TLS) || !strcmp (ctype, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11))
&& !(flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED))
*out_need_password = TRUE;
@@ -445,14 +494,17 @@ main (int argc, char *argv[])
gs_unref_hashtable GHashTable *data = NULL;
gs_unref_hashtable GHashTable *secrets = NULL;
gboolean need_password = FALSE;
+ gboolean need_pin = FALSE;
gboolean need_certpass = FALSE;
gboolean need_proxypass = FALSE;
gs_strfreev char **hints = NULL;
gs_free char *prompt = NULL;
nm_auto_free_secret char *new_password = NULL;
+ nm_auto_free_secret char *new_pin = NULL;
nm_auto_free_secret char *new_certpass = NULL;
nm_auto_free_secret char *new_proxypass = NULL;
nm_auto_free_secret char *existing_password = NULL;
+ nm_auto_free_secret char *existing_pin = NULL;
nm_auto_free_secret char *existing_certpass = NULL;
nm_auto_free_secret char *existing_proxypass = NULL;
gboolean external_ui_mode = FALSE;
@@ -512,12 +564,12 @@ main (int argc, char *argv[])
/* Determine which passwords are actually required, either from hints or
* from looking at the VPN configuration.
*/
- prompt = get_passwords_required (data, (const char *const*) hints, &need_password, &need_certpass, &need_proxypass);
+ prompt = get_passwords_required (data, (const char *const*) hints, &need_password, &need_pin, &need_certpass, &need_proxypass);
if (!prompt)
prompt = g_strdup_printf (_("You need to authenticate to access the Virtual Private Network “%s”."), vpn_name);
/* Exit early if we don't need any passwords */
- if (!need_password && !need_certpass && !need_proxypass) {
+ if (!need_password && !need_pin && !need_certpass && !need_proxypass) {
no_secrets_required_func ();
return EXIT_SUCCESS;
}
@@ -526,13 +578,17 @@ main (int argc, char *argv[])
secrets,
vpn_uuid,
need_password,
+ need_pin,
need_certpass,
need_proxypass,
&existing_password,
+ &existing_pin,
&existing_certpass,
&existing_proxypass);
if (need_password && !existing_password)
ask_user = TRUE;
+ else if (need_pin && !existing_pin)
+ ask_user = TRUE;
else if (need_certpass && !existing_certpass)
ask_user = TRUE;
else if (need_proxypass && !existing_proxypass)
@@ -551,6 +607,9 @@ main (int argc, char *argv[])
need_password,
existing_password,
&new_password,
+ need_pin,
+ existing_pin,
+ &new_pin,
need_certpass,
existing_certpass,
&new_certpass,
@@ -565,6 +624,8 @@ main (int argc, char *argv[])
allow_interaction,
need_password,
new_password ? new_password : existing_password,
+ need_pin,
+ new_pin ? new_pin : existing_pin,
need_certpass,
new_certpass ? new_certpass : existing_certpass,
need_proxypass,
diff --git a/properties/import-export.c b/properties/import-export.c
index db453e9..3883b18 100644
--- a/properties/import-export.c
+++ b/properties/import-export.c
@@ -792,7 +792,7 @@ do_import (const char *path, const char *contents, gsize contents_len, GError **
char *tmp, *tmp2;
const char *ta_direction = NULL, *secret_direction = NULL;
gboolean allow_ta_direction = FALSE, allow_secret_direction = FALSE;
- gboolean have_cert = FALSE, have_key = FALSE, have_ca = FALSE, have_pkcs12 = FALSE;
+ gboolean have_cert = FALSE, have_key = FALSE, have_ca = FALSE, have_pkcs12 = FALSE, have_pkcs11 = FALSE;
const char *cert_path = NULL, *key_path = NULL, *ca_path = NULL;
GSList *inline_blobs = NULL;
GSList *sl_iter;
@@ -1515,6 +1515,27 @@ do_import (const char *path, const char *contents, gsize contents_len, GError **
nm_ip_route_unref (route);
}
+ if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_PKCS11_ID)) {
+ if (!args_params_check_nargs_n (params, 1, &line_error))
+ goto handle_line_error;
+ if (!args_params_check_arg_nonempty (params, 1, NULL, &line_error))
+ goto handle_line_error;
+ setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_PKCS11_ID, params[1]);
+
+ have_pkcs11 = TRUE;
+ continue;
+ }
+
+ if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_PKCS11_PROVIDERS)) {
+ if (!args_params_check_nargs_n (params, 1, &line_error))
+ goto handle_line_error;
+ if (!args_params_check_arg_nonempty (params, 1, NULL, &line_error))
+ goto handle_line_error;
+ setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_PKCS11_PROVIDERS, params[1]);
+ continue;
+ }
+
+
if (params[0][0] == '<' && params[0][strlen (params[0]) - 1] == '>') {
gs_free char *token = g_strndup (&params[0][1], strlen (params[0]) - 2);
gs_free char *end_token = NULL;
@@ -1730,11 +1751,19 @@ handle_line_error:
/* Determine connection type */
if (have_pass) {
if (have_cert || have_pkcs12)
- ctype = NM_OPENVPN_CONTYPE_PASSWORD_TLS;
+ if (have_pkcs11) {
+ ctype = NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11;
+ } else {
+ ctype = NM_OPENVPN_CONTYPE_PASSWORD_TLS;
+ }
else if (have_ca)
ctype = NM_OPENVPN_CONTYPE_PASSWORD;
} else if (have_cert || have_pkcs12) {
- ctype = NM_OPENVPN_CONTYPE_TLS;
+ if (have_pkcs11) {
+ ctype = NM_OPENVPN_CONTYPE_TLS_PKCS11;
+ } else {
+ ctype = NM_OPENVPN_CONTYPE_TLS;
+ }
} else if (have_sk)
ctype = NM_OPENVPN_CONTYPE_STATIC_KEY;
@@ -2049,8 +2078,10 @@ do_export_create (NMConnection *connection, const char *path, GError **error)
const char *cacert = NULL, *user_cert = NULL, *private_key = NULL;
if (NM_IN_STRSET (connection_type, NM_OPENVPN_CONTYPE_TLS,
+ NM_OPENVPN_CONTYPE_TLS_PKCS11,
NM_OPENVPN_CONTYPE_PASSWORD,
- NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS,
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11)) {
value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CA);
if (nmovpn_arg_is_set (value))
cacert = nm_utils_str_utf8safe_unescape (value, &cacert_free);
@@ -2085,7 +2116,8 @@ do_export_create (NMConnection *connection, const char *path, GError **error)
}
if (NM_IN_STRSET (connection_type, NM_OPENVPN_CONTYPE_PASSWORD,
- NM_OPENVPN_CONTYPE_PASSWORD_TLS))
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS,
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11))
args_write_line (f, NMV_OVPN_TAG_AUTH_USER_PASS);
if (NM_IN_STRSET (connection_type, NM_OPENVPN_CONTYPE_STATIC_KEY)) {
@@ -2191,7 +2223,9 @@ do_export_create (NMConnection *connection, const char *path, GError **error)
if (NM_IN_STRSET (connection_type,
NM_OPENVPN_CONTYPE_TLS,
- NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
+ NM_OPENVPN_CONTYPE_TLS_PKCS11,
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS,
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11)) {
const char *x509_name, *key;
args_write_line_setting_value (f, NMV_OVPN_TAG_REMOTE_CERT_TLS, s_vpn, NM_OPENVPN_KEY_REMOTE_CERT_TLS);
@@ -2259,6 +2293,10 @@ do_export_create (NMConnection *connection, const char *path, GError **error)
}
}
+ args_write_line_setting_value (f, NMV_OVPN_TAG_PKCS11_ID, s_vpn, NM_OPENVPN_KEY_PKCS11_ID);
+
+ args_write_line_setting_value (f, NMV_OVPN_TAG_PKCS11_PROVIDERS, s_vpn, NM_OPENVPN_KEY_PKCS11_PROVIDERS);
+
proxy_type = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_PROXY_TYPE);
if (nmovpn_arg_is_set (proxy_type)) {
const char *proxy_server;
diff --git a/properties/nm-openvpn-dialog.ui b/properties/nm-openvpn-dialog.ui
index 9f6a2c8..a8191e3 100644
--- a/properties/nm-openvpn-dialog.ui
+++ b/properties/nm-openvpn-dialog.ui
@@ -316,6 +316,135 @@ config: remote</property>
<property name="tab_fill">False</property>
</packing>
</child>
+ <child>
+ <object class="GtkBox" id="tls_pkcs11">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label37">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">PKCS#11 id:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label38">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label"
+ translatable="yes">PKCS#11 providers:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label40">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label"
+ translatable="yes">PKCS#11 pin:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="tls_pkcs11_pin_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text"
+ translatable="yes">PIN of PKCS#11 token</property>
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="tls_pkcs11_id_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text"
+ translatable="yes">ID of certificate to use
+config: pkcs11-id</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="tls_pkcs11_providers_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text"
+ translatable="yes">Shared lib used to access the pkc#11 functions
+config: pkcs11-providers</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="NMACertChooser" id="tls_pkcs11_ca_cert">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">CA</property>
+ <property name="flags">5</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label36">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">page 2</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
<child>
<object class="GtkBox" id="pw">
<property name="visible">True</property>
@@ -408,10 +537,10 @@ config: auth-user-pass</property>
<object class="GtkLabel" id="label15">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label">page 2</property>
+ <property name="label">page 3</property>
</object>
<packing>
- <property name="position">1</property>
+ <property name="position">2</property>
<property name="tab_fill">False</property>
</packing>
</child>
@@ -520,13 +649,209 @@ config: auth-user-pass</property>
<object class="GtkLabel" id="label16">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label">page 3</property>
+ <property name="label">page 4</property>
</object>
<packing>
- <property name="position">2</property>
+ <property name="position">3</property>
<property name="tab_fill">False</property>
</packing>
</child>
+ <child>
+ <object class="GtkBox" id="pw_tls_pkcs11">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <!-- YYY 1 -->
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label41">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Password:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label42">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">User name:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="pw_tls_pkcs11_password_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Password passed to OpenVPN when prompted for it.
+config: auth-user-pass</property>
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="pw_tls_pkcs11_username_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Username passed to OpenVPN when prompted for it. If omitted, use the name of the system user that activates the connection.
+config: auth-user-pass</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="NMACertChooser" id="pw_tls_pkcs11_ca_cert">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">CA</property>
+ <property name="flags">5</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label43">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">PKCS#11 id:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label44">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label"
+ translatable="yes">PKCS#11 providers:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label45">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label"
+ translatable="yes">PKCS#11 pin:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="pw_tls_pkcs11_pin_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text"
+ translatable="yes">PIN of PKCS#11 token</property>
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="pw_tls_pkcs11_id_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text"
+ translatable="yes">ID of certificate to use
+config: pkcs11-id</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="pw_tls_pkcs11_providers_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text"
+ translatable="yes">Shared lib used to access the pkc#11 functions
+config: pkcs11-providers</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label39">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">page 5</property>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
<child>
<object class="GtkGrid" id="psk">
<property name="visible">True</property>
@@ -688,10 +1013,10 @@ config: static &lt;file&gt; [direction]</property>
<object class="GtkLabel" id="label17">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label">page 4</property>
+ <property name="label">page 6</property>
</object>
<packing>
- <property name="position">3</property>
+ <property name="position">5</property>
<property name="tab_fill">False</property>
</packing>
</child>
@@ -806,6 +1131,10 @@ config: static &lt;file&gt; [direction]</property>
<widget name="label20"/>
<widget name="label12"/>
<widget name="label11"/>
+ <widget name="label37"/>
+ <widget name="label38"/>
+ <widget name="label42"/>
+ <widget name="label44"/>
<widget name="auth_label"/>
</widgets>
</object>
diff --git a/properties/nm-openvpn-editor.c b/properties/nm-openvpn-editor.c
index f5ec4fd..6dbcad0 100644
--- a/properties/nm-openvpn-editor.c
+++ b/properties/nm-openvpn-editor.c
@@ -266,6 +266,54 @@ pw_setup (GtkBuilder *builder,
TRUE, FALSE);
}
+static void
+pkcs11_setup (GtkBuilder *builder,
+ NMSettingVpn *s_vpn,
+ const char *prefix,
+ ChangedCallback changed_cb,
+ gpointer user_data)
+{
+ GtkWidget *widget;
+ const char *value;
+ char namebuf[150];
+
+ /* Fill in providers */
+ nm_sprintf_buf (namebuf, "%s_providers_entry", prefix);
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, namebuf));
+
+ if (s_vpn) {
+ value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_PKCS11_PROVIDERS);
+ if (value && *value)
+ gtk_editable_set_text (GTK_EDITABLE (widget), value);
+ }
+ g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (changed_cb), user_data);
+
+ /* Fill in id */
+ nm_sprintf_buf (namebuf, "%s_id_entry", prefix);
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, namebuf));
+
+ if (s_vpn) {
+ value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_PKCS11_ID);
+ if (value && *value)
+ gtk_editable_set_text (GTK_EDITABLE (widget), value);
+ }
+ g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (changed_cb), user_data);
+
+ /* Fill in the pin */
+ nm_sprintf_buf (namebuf, "%s_pin_entry", prefix);
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, namebuf));
+ g_signal_connect (widget, "changed", G_CALLBACK (changed_cb), user_data);
+
+ if (s_vpn) {
+ value = nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_PKCS11_PIN);
+ if (value)
+ gtk_editable_set_text (GTK_EDITABLE (widget), value);
+ }
+
+ nma_utils_setup_password_storage (widget, 0, (NMSetting *) s_vpn, NM_OPENVPN_KEY_PKCS11_PIN,
+ TRUE, FALSE);
+}
+
static void
tls_pw_init_auth_widget (GtkBuilder *builder,
NMSettingVpn *s_vpn,
@@ -277,7 +325,7 @@ tls_pw_init_auth_widget (GtkBuilder *builder,
NMACertChooser *ca;
const char *value;
char namebuf[150];
- gboolean tls = FALSE, pw = FALSE;
+ gboolean tls = FALSE, pw = FALSE, pkcs11 = FALSE;
g_return_if_fail (builder != NULL);
g_return_if_fail (changed_cb != NULL);
@@ -288,10 +336,17 @@ tls_pw_init_auth_widget (GtkBuilder *builder,
nma_cert_chooser_add_to_size_group (ca, GTK_SIZE_GROUP (gtk_builder_get_object (builder, "labels")));
/* Three major connection types here: TLS-only, PW-only, and TLS + PW */
- if (!strcmp (contype, NM_OPENVPN_CONTYPE_TLS) || !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS))
+ if ( !strcmp (contype, NM_OPENVPN_CONTYPE_TLS)
+ || !strcmp (contype, NM_OPENVPN_CONTYPE_TLS_PKCS11)
+ || !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)
+ || !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11))
tls = TRUE;
- if (!strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD) || !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS))
+ if ( !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD)
+ || !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)
+ || !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11))
pw = TRUE;
+ if (!strcmp (contype, NM_OPENVPN_CONTYPE_TLS_PKCS11) || !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11))
+ pkcs11 = TRUE;
g_signal_connect (ca, "changed", G_CALLBACK (changed_cb), user_data);
if (s_vpn) {
@@ -305,6 +360,8 @@ tls_pw_init_auth_widget (GtkBuilder *builder,
tls_setup (builder, s_vpn, prefix, ca, changed_cb, user_data);
if (pw)
pw_setup (builder, s_vpn, prefix, changed_cb, user_data);
+ if (pkcs11)
+ pkcs11_setup (builder, s_vpn, prefix, changed_cb, user_data);
}
static void
@@ -476,6 +533,40 @@ validate_tls (GtkBuilder *builder, const char *prefix, GError **error)
return TRUE;
}
+static gboolean
+validate_pkcs11 (GtkBuilder *builder, const char *prefix, GError **error)
+{
+ GtkWidget *widget;
+ char namebuf[150];
+ const char *str;
+
+ /* We need a provider */
+ nm_sprintf_buf (namebuf, "%s_providers_entry", prefix);
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, namebuf));
+ str = gtk_editable_get_text (GTK_EDITABLE (widget));
+ if (!str || !*str) {
+ g_set_error (error,
+ NMV_EDITOR_PLUGIN_ERROR,
+ NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
+ NM_OPENVPN_KEY_PKCS11_PROVIDERS);
+ return FALSE;
+ }
+
+ /* We need an id */
+ nm_sprintf_buf (namebuf, "%s_id_entry", prefix);
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, namebuf));
+ str = gtk_editable_get_text (GTK_EDITABLE (widget));
+ if (!str || !*str) {
+ g_set_error (error,
+ NMV_EDITOR_PLUGIN_ERROR,
+ NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
+ NM_OPENVPN_KEY_PKCS11_ID);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static gboolean
auth_widget_check_validity (GtkBuilder *builder, const char *contype, GError **error)
{
@@ -490,6 +581,12 @@ auth_widget_check_validity (GtkBuilder *builder, const char *contype, GError **e
} else if (!strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
if (!validate_tls (builder, "pw_tls", error))
return FALSE;
+ } else if (!strcmp (contype, NM_OPENVPN_CONTYPE_TLS_PKCS11)) {
+ if (!validate_tls (builder, "tls_pkcs11", error) || !validate_pkcs11 (builder, "tls_pkcs11", error))
+ return FALSE;
+ } else if (!strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11)) {
+ if (!validate_tls (builder, "tls_pkcs11", error) || !validate_pkcs11 (builder, "pw_tls_pkcs11", error))
+ return FALSE;
} else if (!strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD)) {
if (!validate_cert_chooser (builder, "pw_ca_cert", &local)) {
g_set_error (error,
@@ -626,6 +723,39 @@ update_pw (GtkBuilder *builder, const char *prefix, NMSettingVpn *s_vpn)
nm_setting_set_secret_flags (NM_SETTING (s_vpn), NM_OPENVPN_KEY_PASSWORD, pw_flags, NULL);
}
+static void
+update_pkcs11 (GtkBuilder *builder, const char *prefix, NMSettingVpn *s_vpn)
+{
+ GtkWidget *widget;
+ NMSettingSecretFlags pw_flags;
+ char namebuf[150];
+ const char *str;
+
+ g_return_if_fail (builder != NULL);
+ g_return_if_fail (prefix != NULL);
+ g_return_if_fail (s_vpn != NULL);
+
+ nm_sprintf_buf (namebuf, "%s_providers_entry", prefix);
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, namebuf));
+ str = gtk_editable_get_text (GTK_EDITABLE (widget));
+ if (str && *str)
+ nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_PKCS11_PROVIDERS, str);
+
+ nm_sprintf_buf (namebuf, "%s_id_entry", prefix);
+ widget = (GtkWidget *) gtk_builder_get_object (builder, namebuf);
+ str = gtk_editable_get_text (GTK_EDITABLE (widget));
+ if (str && *str)
+ nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_PKCS11_ID, str);
+
+ nm_sprintf_buf (namebuf, "%s_pin_entry", prefix);
+ widget = (GtkWidget *) gtk_builder_get_object (builder, namebuf);
+ str = gtk_editable_get_text (GTK_EDITABLE (widget));
+ if (str && *str)
+ nm_setting_vpn_add_secret (s_vpn, NM_OPENVPN_KEY_PKCS11_PIN, str);
+ pw_flags = nma_utils_menu_to_secret_flags (widget);
+ nm_setting_set_secret_flags (NM_SETTING (s_vpn), NM_OPENVPN_KEY_PKCS11_PIN, pw_flags, NULL);
+}
+
static gboolean
auth_widget_update_connection (GtkBuilder *builder,
const char *contype,
@@ -640,6 +770,9 @@ auth_widget_update_connection (GtkBuilder *builder,
if (!strcmp (contype, NM_OPENVPN_CONTYPE_TLS)) {
update_tls (builder, "tls", s_vpn);
+ } else if (!strcmp (contype, NM_OPENVPN_CONTYPE_TLS_PKCS11)) {
+ update_tls (builder, "tls_pkcs11", s_vpn);
+ update_pkcs11 (builder, "tls_pkcs11", s_vpn);
} else if (!strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD)) {
update_from_cert_chooser (builder, NM_OPENVPN_KEY_CA, NULL, NULL,
"pw", "ca_cert", s_vpn);
@@ -647,6 +780,10 @@ auth_widget_update_connection (GtkBuilder *builder,
} else if (!strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
update_tls (builder, "pw_tls", s_vpn);
update_pw (builder, "pw_tls", s_vpn);
+ } else if (!strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11)) {
+ update_tls (builder, "pw_tls_pkcs11", s_vpn);
+ update_pw (builder, "pw_tls_pkcs11", s_vpn);
+ update_pkcs11 (builder, "pw_tls_pkcs11", s_vpn);
} else if (!strcmp (contype, NM_OPENVPN_CONTYPE_STATIC_KEY)) {
/* Update static key */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "sk_key_chooser"));
@@ -1810,7 +1947,9 @@ advanced_dialog_new (GHashTable *hash, const char *contype)
"clicked", G_CALLBACK (gtk_widget_show), chooser);
if (NM_IN_STRSET (contype,
NM_OPENVPN_CONTYPE_TLS,
+ NM_OPENVPN_CONTYPE_TLS_PKCS11,
NM_OPENVPN_CONTYPE_PASSWORD_TLS,
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11,
NM_OPENVPN_CONTYPE_PASSWORD)) {
/* Initialize direction combo */
combo = GTK_WIDGET (gtk_builder_get_object (builder, "direction_combo"));
@@ -2251,7 +2390,9 @@ advanced_dialog_new_hash_from_dialog (GtkWidget *dialog)
contype = g_object_get_data (G_OBJECT (dialog), "connection-type");
if ( !strcmp (contype, NM_OPENVPN_CONTYPE_TLS)
+ || !strcmp (contype, NM_OPENVPN_CONTYPE_TLS_PKCS11)
|| !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)
+ || !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11)
|| !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD)) {
char *filename;
GFile *file;
@@ -2707,9 +2848,11 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection)
if (s_vpn) {
contype = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE);
if (!NM_IN_STRSET (contype, NM_OPENVPN_CONTYPE_TLS,
+ NM_OPENVPN_CONTYPE_TLS_PKCS11,
NM_OPENVPN_CONTYPE_STATIC_KEY,
NM_OPENVPN_CONTYPE_PASSWORD,
- NM_OPENVPN_CONTYPE_PASSWORD_TLS))
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS,
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11))
contype = NM_OPENVPN_CONTYPE_TLS;
}
@@ -2724,6 +2867,19 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection)
COL_AUTH_TYPE, NM_OPENVPN_CONTYPE_TLS,
-1);
+ /* TLS auth widget (PKCS11-mode) */
+ tls_pw_init_auth_widget (priv->builder, s_vpn,
+ NM_OPENVPN_CONTYPE_TLS_PKCS11, "tls_pkcs11",
+ stuff_changed_cb, self);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_AUTH_NAME, _("Certificates (TLS), PKCS#11"),
+ COL_AUTH_PAGE, 1,
+ COL_AUTH_TYPE, NM_OPENVPN_CONTYPE_TLS_PKCS11,
+ -1);
+ if ((active < 0) && !strcmp (contype, NM_OPENVPN_CONTYPE_TLS_PKCS11))
+ active = 1;
+
/* Password auth widget */
tls_pw_init_auth_widget (priv->builder, s_vpn,
NM_OPENVPN_CONTYPE_PASSWORD, "pw",
@@ -2731,12 +2887,12 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection)
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COL_AUTH_NAME, _("Password"),
- COL_AUTH_PAGE, 1,
+ COL_AUTH_PAGE, 2,
COL_AUTH_TYPE, NM_OPENVPN_CONTYPE_PASSWORD,
-1);
if ( active < 0
&& nm_streq (contype, NM_OPENVPN_CONTYPE_PASSWORD))
- active = 1;
+ active = 2;
/* Password+TLS auth widget */
tls_pw_init_auth_widget (priv->builder, s_vpn,
@@ -2745,12 +2901,26 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection)
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COL_AUTH_NAME, _("Password with Certificates (TLS)"),
- COL_AUTH_PAGE, 2,
+ COL_AUTH_PAGE, 3,
COL_AUTH_TYPE, NM_OPENVPN_CONTYPE_PASSWORD_TLS,
-1);
if ( active < 0
&& nm_streq (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS))
- active = 2;
+ active = 3;
+
+ /* Password+TLS auth widget (PKCS11-mode) */
+ tls_pw_init_auth_widget (priv->builder, s_vpn,
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11, "pw_tls_pkcs11",
+ stuff_changed_cb, self);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_AUTH_NAME, _("Password with Certificates (TLS), PKCS#11"),
+ COL_AUTH_PAGE, 4,
+ COL_AUTH_TYPE, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11,
+ -1);
+ if ( active < 0
+ && nm_streq (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11))
+ active = 4;
/* Static key auth widget */
sk_init_auth_widget (priv->builder, s_vpn, stuff_changed_cb, self);
@@ -2758,12 +2928,12 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection)
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COL_AUTH_NAME, _("Static Key"),
- COL_AUTH_PAGE, 3,
+ COL_AUTH_PAGE, 5,
COL_AUTH_TYPE, NM_OPENVPN_CONTYPE_STATIC_KEY,
-1);
if ( active < 0
&& nm_streq (contype, NM_OPENVPN_CONTYPE_STATIC_KEY))
- active = 3;
+ active = 5;
gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (store));
g_object_unref (store);
diff --git a/properties/tests/test-import-export.c b/properties/tests/test-import-export.c
index fdc9e50..6dc064e 100644
--- a/properties/tests/test-import-export.c
+++ b/properties/tests/test-import-export.c
@@ -548,6 +548,82 @@ test_tls_inline_import (void)
g_assert (unlink (TMPDIR"/tls-inline-crl-verify.pem") == 0);
}
+static void
+test_pkcs11_import (void)
+{
+ _CREATE_PLUGIN (plugin);
+ gs_unref_object NMConnection *connection = NULL;
+ NMSettingConnection *s_con;
+ NMSettingVpn *s_vpn;
+ const char *expected_id = "pkcs11";
+
+ connection = get_basic_connection (plugin, SRCDIR, "pkcs11.ovpn");
+
+ s_con = _get_setting_connection (connection);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+ g_assert (!nm_setting_connection_get_uuid (s_con));
+
+ s_vpn = _get_setting_vpn (connection);
+
+ _check_item (s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE, NM_OPENVPN_CONTYPE_TLS_PKCS11);
+ _check_item (s_vpn, NM_OPENVPN_KEY_DEV, "tun");
+ _check_item (s_vpn, NM_OPENVPN_KEY_PROTO_TCP, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_FLOAT, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_REMOTE, "173.8.149.245:1194");
+ _check_item (s_vpn, NM_OPENVPN_KEY_PORT, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY_DIRECTION, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_CIPHER, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_LOCAL_IP, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_REMOTE_IP, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_AUTH, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_PKCS11_ID, "magic-id");
+ _check_item (s_vpn, NM_OPENVPN_KEY_PKCS11_PROVIDERS, "/pkcs11/provider/path");
+
+ _check_item (s_vpn, NM_OPENVPN_KEY_CA, SRCDIR"/cacert.pem");
+
+ _check_secret (s_vpn, NM_OPENVPN_KEY_PASSWORD, NULL);
+ _check_secret (s_vpn, NM_OPENVPN_KEY_CERTPASS, NULL);
+}
+
+static void
+test_pkcs11_pw_import (void)
+{
+ _CREATE_PLUGIN (plugin);
+ gs_unref_object NMConnection *connection = NULL;
+ NMSettingConnection *s_con;
+ NMSettingVpn *s_vpn;
+ const char *expected_id = "pkcs11_pw";
+
+ connection = get_basic_connection (plugin, SRCDIR, "pkcs11_pw.ovpn");
+
+ s_con = _get_setting_connection (connection);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+ g_assert (!nm_setting_connection_get_uuid (s_con));
+
+ s_vpn = _get_setting_vpn (connection);
+
+ _check_item (s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11);
+ _check_item (s_vpn, NM_OPENVPN_KEY_DEV, "tun");
+ _check_item (s_vpn, NM_OPENVPN_KEY_PROTO_TCP, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_FLOAT, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_REMOTE, "173.8.149.245:1194");
+ _check_item (s_vpn, NM_OPENVPN_KEY_PORT, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY_DIRECTION, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_CIPHER, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_LOCAL_IP, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_REMOTE_IP, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_AUTH, NULL);
+ _check_item (s_vpn, NM_OPENVPN_KEY_PKCS11_ID, "magic-id");
+ _check_item (s_vpn, NM_OPENVPN_KEY_PKCS11_PROVIDERS, "/pkcs11/provider/path");
+
+ _check_item (s_vpn, NM_OPENVPN_KEY_CA, SRCDIR"/cacert.pem");
+
+ _check_secret (s_vpn, NM_OPENVPN_KEY_PASSWORD, NULL);
+ _check_secret (s_vpn, NM_OPENVPN_KEY_CERTPASS, NULL);
+}
+
static void
test_pkcs12_import (void)
{
@@ -1307,6 +1383,12 @@ int main (int argc, char **argv)
_add_test_func_simple (test_pkcs12_with_ca_import);
_add_test_func ("pkcs12-with-ca-export", test_export_compare, "pkcs12-with-ca.ovpn", "pkcs12-with-ca.ovpntest");
+ _add_test_func_simple (test_pkcs11_import);
+ _add_test_func ("pkcs11-export", test_export_compare, "pkcs11.ovpn", "pkcs11.ovpntest");
+
+ _add_test_func_simple (test_pkcs11_pw_import);
+ _add_test_func ("pkcs11_pw-export", test_export_compare, "pkcs11_pw.ovpn", "pkcs11_pw.ovpntest");
+
_add_test_func_simple (test_non_utf8_import);
_add_test_func ("static-import-1", test_static_key_import, "static.ovpn", "static", "1");
diff --git a/shared/nm-service-defines.h b/shared/nm-service-defines.h
index c63c255..50c2e5e 100644
--- a/shared/nm-service-defines.h
+++ b/shared/nm-service-defines.h
@@ -58,6 +58,8 @@
#define NM_OPENVPN_KEY_PING "ping"
#define NM_OPENVPN_KEY_PING_EXIT "ping-exit"
#define NM_OPENVPN_KEY_PING_RESTART "ping-restart"
+#define NM_OPENVPN_KEY_PKCS11_ID "pkcs11-id"
+#define NM_OPENVPN_KEY_PKCS11_PROVIDERS "pkcs11-providers"
#define NM_OPENVPN_KEY_PORT "port"
#define NM_OPENVPN_KEY_PROTO_TCP "proto-tcp"
#define NM_OPENVPN_KEY_PROXY_PORT "proxy-port"
@@ -90,10 +92,12 @@
#define NM_OPENVPN_KEY_PASSWORD "password"
#define NM_OPENVPN_KEY_CERTPASS "cert-pass"
+#define NM_OPENVPN_KEY_PKCS11_PIN "pkcs11-pin"
#define NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD "http-proxy-password"
#define NM_OPENVPN_KEY_PASSWORD_FLAGS "password-flags"
#define NM_OPENVPN_KEY_CERTPASS_FLAGS "cert-pass-flags"
+#define NM_OPENVPN_KEY_PKCS11_PIN_FLAGS "pkcs11-pin-flags"
#define NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD_FLAGS "http-proxy-password-flags"
@@ -113,10 +117,12 @@
#define NM_OPENVPN_AUTH_SHA384 "SHA384"
#define NM_OPENVPN_AUTH_SHA512 "SHA512"
-#define NM_OPENVPN_CONTYPE_PASSWORD "password"
-#define NM_OPENVPN_CONTYPE_PASSWORD_TLS "password-tls"
-#define NM_OPENVPN_CONTYPE_STATIC_KEY "static-key"
-#define NM_OPENVPN_CONTYPE_TLS "tls"
+#define NM_OPENVPN_CONTYPE_PASSWORD "password"
+#define NM_OPENVPN_CONTYPE_PASSWORD_TLS "password-tls"
+#define NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11 "password-tls-pkcs11"
+#define NM_OPENVPN_CONTYPE_STATIC_KEY "static-key"
+#define NM_OPENVPN_CONTYPE_TLS "tls"
+#define NM_OPENVPN_CONTYPE_TLS_PKCS11 "tls-pkcs11"
/* arguments of "--remote-cert-tls" */
#define NM_OPENVPN_REM_CERT_TLS_CLIENT "client"
diff --git a/shared/utils.h b/shared/utils.h
index 064da72..d57333f 100644
--- a/shared/utils.h
+++ b/shared/utils.h
@@ -57,6 +57,8 @@
#define NMV_OVPN_TAG_NS_CERT_TYPE "ns-cert-type"
#define NMV_OVPN_TAG_PERSIST_KEY "persist-key"
#define NMV_OVPN_TAG_PERSIST_TUN "persist-tun"
+#define NMV_OVPN_TAG_PKCS11_ID "pkcs11-id"
+#define NMV_OVPN_TAG_PKCS11_PROVIDERS "pkcs11-providers"
#define NMV_OVPN_TAG_PING "ping"
#define NMV_OVPN_TAG_PING_EXIT "ping-exit"
#define NMV_OVPN_TAG_PING_RESTART "ping-restart"
diff --git a/src/nm-openvpn-service.c b/src/nm-openvpn-service.c
index c5c6eee..e08d891 100644
--- a/src/nm-openvpn-service.c
+++ b/src/nm-openvpn-service.c
@@ -105,6 +105,7 @@ typedef struct {
char *default_username;
char *username;
char *password;
+ char *pin;
char *priv_key_pass;
char *proxy_username;
char *proxy_password;
@@ -196,8 +197,11 @@ static const ValidProperty valid_properties[] = {
{ NM_OPENVPN_KEY_USERNAME, G_TYPE_STRING, 0, 0, FALSE },
{ NM_OPENVPN_KEY_PASSWORD_FLAGS, G_TYPE_STRING, 0, 0, FALSE },
{ NM_OPENVPN_KEY_CERTPASS_FLAGS, G_TYPE_STRING, 0, 0, FALSE },
+ { NM_OPENVPN_KEY_PKCS11_PIN_FLAGS, G_TYPE_STRING, 0, 0, FALSE },
{ NM_OPENVPN_KEY_NOSECRET, G_TYPE_STRING, 0, 0, FALSE },
{ NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD_FLAGS, G_TYPE_STRING, 0, 0, FALSE },
+ { NM_OPENVPN_KEY_PKCS11_ID, G_TYPE_STRING, 0, 0, FALSE },
+ { NM_OPENVPN_KEY_PKCS11_PROVIDERS, G_TYPE_STRING, 0, 0, FALSE },
{ NM_OPENVPN_KEY_TLS_VERSION_MIN, G_TYPE_STRING, 0, 0, FALSE },
{ NM_OPENVPN_KEY_TLS_VERSION_MIN_OR_HIGHEST,G_TYPE_BOOLEAN, 0, 0, FALSE },
{ NM_OPENVPN_KEY_TLS_VERSION_MAX, G_TYPE_STRING, 0, 0, FALSE },
@@ -205,6 +209,7 @@ static const ValidProperty valid_properties[] = {
};
static const ValidProperty valid_secrets[] = {
+ { NM_OPENVPN_KEY_PKCS11_PIN, G_TYPE_STRING, 0, 0, FALSE },
{ NM_OPENVPN_KEY_PASSWORD, G_TYPE_STRING, 0, 0, FALSE },
{ NM_OPENVPN_KEY_CERTPASS, G_TYPE_STRING, 0, 0, FALSE },
{ NM_OPENVPN_KEY_NOSECRET, G_TYPE_STRING, 0, 0, FALSE },
@@ -240,17 +245,21 @@ static gboolean
validate_connection_type (const char *ctype)
{
return NM_IN_STRSET (ctype, NM_OPENVPN_CONTYPE_TLS,
+ NM_OPENVPN_CONTYPE_TLS_PKCS11,
NM_OPENVPN_CONTYPE_STATIC_KEY,
NM_OPENVPN_CONTYPE_PASSWORD,
- NM_OPENVPN_CONTYPE_PASSWORD_TLS);
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS,
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11);
}
static gboolean
connection_type_is_tls_mode (const char *connection_type)
{
return NM_IN_STRSET (connection_type, NM_OPENVPN_CONTYPE_TLS,
+ NM_OPENVPN_CONTYPE_TLS_PKCS11,
NM_OPENVPN_CONTYPE_PASSWORD,
- NM_OPENVPN_CONTYPE_PASSWORD_TLS);
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS,
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11);
}
/*****************************************************************************/
@@ -374,6 +383,13 @@ args_add_vpn_certs (GPtrArray *args, NMSettingVpn *s_vpn)
}
}
+static void
+args_add_pkcs11 (GPtrArray *args, NMSettingVpn *s_vpn)
+{
+ args_add_vpn_data (args, s_vpn, NM_OPENVPN_KEY_PKCS11_ID, "--pkcs11-id");
+ args_add_vpn_data (args, s_vpn, NM_OPENVPN_KEY_PKCS11_PROVIDERS, "--pkcs11-providers");
+}
+
/*****************************************************************************/
static gboolean
@@ -789,6 +805,10 @@ nm_openvpn_disconnect_management_socket (NMOpenvpnPlugin *plugin)
memset (io_data->password, 0, strlen (io_data->password));
g_free (io_data->password);
+ if (io_data->pin)
+ memset (io_data->pin, 0, strlen (io_data->pin));
+ g_free (io_data->pin);
+
if (io_data->priv_key_pass)
memset (io_data->priv_key_pass, 0, strlen (io_data->priv_key_pass));
g_free (io_data->priv_key_pass);
@@ -995,6 +1015,26 @@ handle_auth (NMOpenvpnPluginIOData *io_data,
*out_message = _("An HTTP Proxy username and password are required.");
}
handled = TRUE;
+ } else if (strlen(requested_auth) > 3 && !strncmp(requested_auth, "PIV", 3)) {
+ if (io_data->pin) {
+ char *pin, *buf;
+
+ /* Quote strings passed back to openvpn */
+ pin = ovpn_quote_string (io_data->pin);
+ buf = g_strdup_printf ("password \"%s\" \"%s\"\n", requested_auth, pin);
+ memset (pin, 0, strlen (pin));
+ g_free (pin);
+
+ /* Will always write everything in blocking channels (on success) */
+ g_io_channel_write_chars (io_data->socket_channel, buf, strlen (buf), NULL, NULL);
+ g_io_channel_flush (io_data->socket_channel, NULL);
+ g_free (buf);
+ } else {
+ hints = g_new0 (const char *, 2);
+ hints[i++] = NM_OPENVPN_KEY_PKCS11_PIN;
+ *out_message = _("A PKCS#11 PIN is required.");
+ }
+ handled = TRUE;
}
*out_hints = g_steal_pointer (&hints);
@@ -1105,6 +1145,17 @@ handle_management_socket (NMOpenvpnPlugin *plugin,
g_free (auth);
}
+ /*
+ * Handle >NEED-OK:Need statements,
+ * for example: >NEED-OK:Need 'token-insertion-request' confirmation MSG:Please insert PIV Card Holder pin (PIV_II) token
+ */
+ auth = get_detail (str, ">NEED-OK:Need '");
+ if (auth) {
+ _LOGW ("Unhandled management socket request '%s'", auth);
+ *out_failure = NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED;
+ again = FALSE;
+ }
+
out:
g_free (str);
return again;
@@ -1240,6 +1291,12 @@ update_io_data_from_vpn_setting (NMOpenvpnPluginIOData *io_data,
}
io_data->password = g_strdup (nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_PASSWORD));
+ if (io_data->pin) {
+ memset (io_data->pin, 0, strlen (io_data->pin));
+ g_free (io_data->pin);
+ }
+ io_data->pin = g_strdup (nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_PKCS11_PIN));
+
if (io_data->priv_key_pass) {
memset (io_data->priv_key_pass, 0, strlen (io_data->priv_key_pass));
g_free (io_data->priv_key_pass);
@@ -1945,6 +2002,10 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
if (nm_streq (connection_type, NM_OPENVPN_CONTYPE_TLS)) {
args_add_strv (args, "--client");
args_add_vpn_certs (args, s_vpn);
+ } else if (nm_streq (connection_type, NM_OPENVPN_CONTYPE_TLS_PKCS11)) {
+ args_add_strv (args, "--client");
+ args_add_vpn_certs (args, s_vpn);
+ args_add_pkcs11 (args, s_vpn);
} else if (nm_streq (connection_type, NM_OPENVPN_CONTYPE_STATIC_KEY)) {
tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY);
if (nmovpn_arg_is_set (tmp)) {
@@ -1970,6 +2031,12 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
args_add_vpn_certs (args, s_vpn);
/* Use user/path authentication */
args_add_strv (args, "--auth-user-pass");
+ } else if (nm_streq (connection_type, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11)) {
+ args_add_strv (args, "--client");
+ args_add_vpn_certs (args, s_vpn);
+ /* Use user/path authentication */
+ args_add_strv (args, "--auth-user-pass");
+ args_add_pkcs11 (args, s_vpn);
} else {
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
@@ -2041,8 +2108,10 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
X509: May require certificate password
*/
if ( NM_IN_STRSET (connection_type, NM_OPENVPN_CONTYPE_TLS,
+ NM_OPENVPN_CONTYPE_TLS_PKCS11,
NM_OPENVPN_CONTYPE_PASSWORD,
- NM_OPENVPN_CONTYPE_PASSWORD_TLS)
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS,
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11)
|| nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_HTTP_PROXY_USERNAME)) {
priv->io_data = g_malloc0 (sizeof (NMOpenvpnPluginIOData));
@@ -2084,6 +2153,32 @@ check_need_secrets (NMSettingVpn *s_vpn, gboolean *need_secrets)
*need_secrets = FALSE;
}
}
+ } else if (nm_streq (ctype, NM_OPENVPN_CONTYPE_PASSWORD_TLS_PKCS11)) {
+ /* Will require a password and maybe private key password and PKCS#11 PIN*/
+ key = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_KEY);
+ key = nm_utils_str_utf8safe_unescape (key, &key_free);
+ if (is_encrypted (key) && !nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_CERTPASS)) {
+ *need_secrets = TRUE;
+ }
+
+ if (!nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_PASSWORD)) {
+ *need_secrets = TRUE;
+ if (nm_setting_get_secret_flags (NM_SETTING (s_vpn), NM_OPENVPN_KEY_PASSWORD, &secret_flags, NULL)) {
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) {
+ *need_secrets = FALSE;
+ }
+ }
+ }
+
+ if (!nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_PKCS11_PIN)) {
+ *need_secrets = TRUE;
+ if (nm_setting_get_secret_flags (NM_SETTING (s_vpn), NM_OPENVPN_KEY_PKCS11_PIN, &secret_flags, NULL)) {
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) {
+ *need_secrets = FALSE;
+ }
+ }
+ }
+
} else if (nm_streq (ctype, NM_OPENVPN_CONTYPE_PASSWORD)) {
/* Will require a password */
if (!nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_PASSWORD)) {
@@ -2099,6 +2194,20 @@ check_need_secrets (NMSettingVpn *s_vpn, gboolean *need_secrets)
key = nm_utils_str_utf8safe_unescape (key, &key_free);
if (is_encrypted (key) && !nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_CERTPASS))
*need_secrets = TRUE;
+ } else if (nm_streq (ctype, NM_OPENVPN_CONTYPE_TLS_PKCS11)) {
+ /* May require private key password and PKCS#11 PIN */
+ key = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_KEY);
+ key = nm_utils_str_utf8safe_unescape (key, &key_free);
+ if (is_encrypted (key) && !nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_CERTPASS))
+ *need_secrets = TRUE;
+
+ if (!nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_PKCS11_PIN)) {
+ *need_secrets = TRUE;
+ if (nm_setting_get_secret_flags (NM_SETTING (s_vpn), NM_OPENVPN_KEY_PKCS11_PIN, &secret_flags, NULL)) {
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
+ *need_secrets = FALSE;
+ }
+ }
} else {
/* Static key doesn't need passwords */
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment