[Gpa-commits] r961 - trunk/src
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Thu Mar 5 19:22:19 CET 2009
Author: werner
Date: 2009-03-05 19:22:15 +0100 (Thu, 05 Mar 2009)
New Revision: 961
Modified:
trunk/src/ChangeLog
trunk/src/cm-netkey.c
Log:
Finished PIN management for NetKey cards. Requires GnuPG from SVN.
Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog 2009-03-04 16:36:58 UTC (rev 960)
+++ trunk/src/ChangeLog 2009-03-05 18:22:15 UTC (rev 961)
@@ -1,3 +1,9 @@
+2009-03-05 Werner Koch <wk at g10code.com>
+
+ * cm-netkey.c (check_nullpin, check_nullpin_data_cb): Remove.
+ (update_entry_chv_status): New.
+ (reload_data): Use CHV-STATUS attribute.
+
2009-03-04 Werner Koch <wk at g10code.com>
* cm-openpgp.c (add_table_row): Allow for GtkLabel as widget.
Modified: trunk/src/cm-netkey.c
===================================================================
--- trunk/src/cm-netkey.c 2009-03-04 16:36:58 UTC (rev 960)
+++ trunk/src/cm-netkey.c 2009-03-05 18:22:15 UTC (rev 961)
@@ -44,6 +44,8 @@
ENTRY_PIN_RETRYCOUNTER,
ENTRY_PUK_RETRYCOUNTER,
+ ENTRY_SIGG_PIN_RETRYCOUNTER,
+ ENTRY_SIGG_PUK_RETRYCOUNTER,
ENTRY_LAST
};
@@ -55,6 +57,7 @@
int valid; /* Valid information. */
int nullpin; /* The NullPIN is activ. */
int blocked; /* The PIN is blocked. */
+ int nopin; /* No such PIN. */
int tries_left; /* How many verification tries are left. */
};
@@ -76,11 +79,17 @@
GtkWidget *entries[ENTRY_LAST];
- GtkWidget *change_pin_btn; /* The button to change the PIN. */
- GtkWidget *change_puk_btn; /* The button to change the PUK. */
+ GtkWidget *change_pin_btn; /* The button to change the PIN for NKS. */
+ GtkWidget *change_puk_btn; /* The button to change the PUK for NKS. */
+ GtkWidget *change_sigg_pin_btn; /* The button to change the PIN for SigG. */
+ GtkWidget *change_sigg_puk_btn; /* The button to change the PUK for SigG. */
/* Information about the PINs. */
- struct pininfo_s pininfo[3];
+ struct pininfo_s pininfo[4];
+
+
+ int reloading; /* Sentinel to avoid recursive reloads. */
+
};
/* The parent class. */
@@ -111,12 +120,123 @@
}
+/* Put the PIN information into the field with ENTRY_ID. If BUTTON is
+ not NULL its sensitivity is set as well. */
+static void
+update_entry_retry_counter (GpaCMNetkey *card, int entry_id,
+ struct pininfo_s *info, int any_isnull,
+ int is_puk, GtkWidget *button)
+{
+ char numbuf[50];
+ const char *string;
+
+ if (!info->valid)
+ string = _("unknown");
+ else if (info->nullpin)
+ string = "NullPIN";
+ else if (info->blocked)
+ string = _("blocked");
+ else if (info->nopin)
+ string = "n/a";
+ else
+ {
+ snprintf (numbuf, sizeof numbuf, "%d", info->tries_left);
+ string = numbuf;
+ }
+ gtk_label_set_text (GTK_LABEL (card->entries[entry_id]), string);
+ if (button)
+ {
+ gtk_button_set_label (GTK_BUTTON (button),
+ (info->valid && !info->nullpin
+ && (info->blocked || !info->tries_left))
+ ? (is_puk? _("Reset PUK") : _("Reset PIN"))
+ : (is_puk? _("Change PUK"): _("Change PIN")));
+ gtk_widget_set_sensitive (button,
+ (info->valid && !any_isnull
+ && !info->nullpin && !info->blocked
+ && !info->nopin));
+ }
+}
+
+
+
+/* Update the CHV status fields. This function may modify STRING. */
+static void
+update_entry_chv_status (GpaCMNetkey *card, int entry_id, char *string)
+{
+ struct {
+ int info_idx;
+ int is_puk;
+ int entry_id;
+ GtkWidget *widget;
+ } tbl[] =
+ {
+ { 0, 0, ENTRY_PIN_RETRYCOUNTER },
+ { 1, 1, ENTRY_PUK_RETRYCOUNTER },
+ { 2, 0, ENTRY_SIGG_PIN_RETRYCOUNTER },
+ { 3, 1, ENTRY_SIGG_PUK_RETRYCOUNTER },
+ { -1, 0 }
+ };
+ int idx;
+ int any_isnull = 0;
+
+ tbl[0].widget = card->change_pin_btn;
+ tbl[1].widget = card->change_puk_btn;
+ tbl[2].widget = card->change_sigg_pin_btn;
+ tbl[3].widget = card->change_sigg_puk_btn;
+
+ (void)entry_id; /* Not used. */
+
+ for (idx=0; idx < DIM (card->pininfo); idx++)
+ memset (&card->pininfo[idx], 0, sizeof card->pininfo[0]);
+
+ while (spacep (string))
+ string++;
+ for (idx=0; *string && idx < DIM (card->pininfo); idx++)
+ {
+ int value = atoi (string);
+ while (*string && !spacep (string))
+ string++;
+ while (spacep (string))
+ string++;
+
+ card->pininfo[idx].valid = 1;
+ if (value >= 0)
+ card->pininfo[idx].tries_left = value;
+ else if (value == -4)
+ {
+ card->pininfo[idx].nullpin = 1;
+ any_isnull = 1;
+ }
+ else if (value == -3)
+ card->pininfo[idx].blocked = 1;
+ else if (value == -2)
+ card->pininfo[idx].nopin = 1;
+ else
+ card->pininfo[idx].valid = 0;
+ }
+
+ for (idx=0; tbl[idx].info_idx != -1; idx++)
+ if (tbl[idx].info_idx < DIM (card->pininfo))
+ update_entry_retry_counter (card, tbl[idx].entry_id,
+ &card->pininfo[tbl[idx].info_idx],
+ any_isnull,
+ tbl[idx].is_puk, tbl[idx].widget);
+
+ if (any_isnull)
+ gtk_widget_show_all (card->warning_frame);
+ else
+ gtk_widget_hide_all (card->warning_frame);
+}
+
+
+
struct scd_getattr_parm
{
GpaCMNetkey *card; /* The object. */
- const char *name; /* Name of expected attribute. */
- int entry_id; /* The identifier for the entry. */
- void (*updfnc) (GpaCMNetkey *card, int entry_id, const char *string);
+ const char *name; /* Name of expected attribute. */
+ int entry_id; /* The identifier for the entry. */
+ void (*updfnc) (GpaCMNetkey *card, int entry_id, char *string);
};
@@ -134,14 +254,18 @@
if (entry_id < ENTRY_LAST)
{
+ char *tmp = xstrdup (args);
+
+ percent_unescape (tmp, 1);
if (parm->updfnc)
- parm->updfnc (parm->card, entry_id, args);
+ parm->updfnc (parm->card, entry_id, tmp);
else if (GTK_IS_LABEL (parm->card->entries[entry_id]))
gtk_label_set_text
- (GTK_LABEL (parm->card->entries[entry_id]), args);
+ (GTK_LABEL (parm->card->entries[entry_id]), tmp);
else
gtk_entry_set_text
- (GTK_ENTRY (parm->card->entries[entry_id]), args);
+ (GTK_ENTRY (parm->card->entries[entry_id]), tmp);
+ xfree (tmp);
}
}
@@ -149,107 +273,6 @@
}
-/* Data callback used by check_nullpin. */
-static gpg_error_t
-check_nullpin_data_cb (void *opaque, const void *data_arg, size_t datalen)
-{
- int *pinstat = opaque;
- const unsigned char *data = data_arg;
-
- if (datalen >= 2)
- {
- unsigned int sw = ((data[datalen-2] << 8) | data[datalen-1]);
-
- if (sw == 0x6985)
- *pinstat = -2; /* NullPIN is activ. */
- else if (sw == 0x6983)
- *pinstat = -3; /* PIN is blocked. */
- else if ((sw & 0xfff0) == 0x63C0)
- *pinstat = (sw & 0x000f); /* PIN has N tries left. */
- else
- ; /* Probably no such PIN. */
- }
- return 0;
-}
-
-
-/* Check whether the NullPIN is still active. */
-static void
-check_nullpin (GpaCMNetkey *card)
-{
- gpg_error_t err;
- gpgme_ctx_t gpgagent;
- int idx;
-
- gpgagent = GPA_CM_OBJECT (card)->agent_ctx;
- g_return_if_fail (gpgagent);
-
- for (idx=0; idx < DIM (card->pininfo); idx++)
- memset (&card->pininfo[idx], 0, sizeof card->pininfo[0]);
-
- /* A TCOS card responds to a verify with empty data (i.e. without
- the Lc byte) with the status of the PIN. The PIN is given as
- usual as P2. */
- for (idx=0; idx < DIM (card->pininfo) && idx < 2; idx++)
- {
- int pinstat = -1;
- char command[100];
-
- snprintf (command, sizeof command, "SCD APDU 00:20:00:%02x", idx);
-
- err = gpgme_op_assuan_transact (gpgagent, command,
- check_nullpin_data_cb, &pinstat,
- NULL, NULL,
- NULL, NULL);
- if (!err)
- err = gpgme_op_assuan_result (gpgagent)->err;
- if (err)
- g_debug ("assuan empty verify command failed: %s <%s>\n",
- gpg_strerror (err), gpg_strsource (err));
- else
- {
- card->pininfo[idx].valid = 1;
- if (pinstat == -2)
- card->pininfo[idx].nullpin = 1;
- else if (pinstat == -3)
- card->pininfo[idx].blocked = 1;
- else if (pinstat >= 0)
- card->pininfo[idx].tries_left = pinstat;
- else
- card->pininfo[idx].valid = 0;
- }
- }
-}
-
-
-/* Put the PIN information into the field with ENTRY_ID. If BUTTON is
- not NULL its sensitivity is set as well. */
-static void
-update_entry_retry_counter (GpaCMNetkey *card, int entry_id,
- struct pininfo_s *info, int pin0_isnull,
- GtkWidget *button)
-{
- char numbuf[50];
- const char *string;
-
- if (!info->valid)
- string = _("unknown");
- else if (info->nullpin)
- string = "NullPIN";
- else if (info->blocked)
- string = _("blocked");
- else
- {
- snprintf (numbuf, sizeof numbuf, "%d", info->tries_left);
- string = numbuf;
- }
- gtk_label_set_text (GTK_LABEL (card->entries[entry_id]), string);
- if (button)
- gtk_widget_set_sensitive (button, (info->valid && !pin0_isnull
- && !info->nullpin && !info->blocked));
-}
-
-
/* Use the assuan machinery to load the bulk of the OpenPGP card data. */
static void
reload_data (GpaCMNetkey *card)
@@ -257,10 +280,11 @@
static struct {
const char *name;
int entry_id;
- void (*updfnc) (GpaCMNetkey *card, int entry_id, const char *string);
+ void (*updfnc) (GpaCMNetkey *card, int entry_id, char *string);
} attrtbl[] = {
{ "SERIALNO", ENTRY_SERIALNO },
{ "NKS-VERSION", ENTRY_NKS_VERSION },
+ { "CHV-STATUS", ENTRY_PIN_RETRYCOUNTER, update_entry_chv_status },
{ NULL }
};
int attridx;
@@ -268,13 +292,11 @@
char command[100];
struct scd_getattr_parm parm;
gpgme_ctx_t gpgagent;
- int pin0_isnull;
gpgagent = GPA_CM_OBJECT (card)->agent_ctx;
g_return_if_fail (gpgagent);
- check_nullpin (card);
-
+ card->reloading++;
parm.card = card;
for (attridx=0; attrtbl[attridx].name; attridx++)
{
@@ -311,59 +333,75 @@
break;
}
}
-
- pin0_isnull = (card->pininfo[0].valid && card->pininfo[0].nullpin);
- if (pin0_isnull)
- gtk_widget_show_all (card->warning_frame);
- else
- gtk_widget_hide_all (card->warning_frame);
-
- update_entry_retry_counter (card, ENTRY_PIN_RETRYCOUNTER, &card->pininfo[0],
- pin0_isnull, card->change_pin_btn);
- update_entry_retry_counter (card, ENTRY_PUK_RETRYCOUNTER, &card->pininfo[1],
- pin0_isnull, card->change_puk_btn);
+ card->reloading--;
}
static void
change_nullpin (GpaCMNetkey *card)
{
- GtkMessageDialog *dialog;
+ gpg_error_t err;
+ GtkWidget *dialog;
gpgme_ctx_t gpgagent;
- gpg_error_t err;
+ int is_sigg;
+ char *string;
+ int okay;
gpgagent = GPA_CM_OBJECT (card)->agent_ctx;
g_return_if_fail (gpgagent);
-
+
+ if (card->pininfo[0].valid && card->pininfo[0].nullpin)
+ is_sigg = 0;
+ else if (card->pininfo[2].valid && card->pininfo[2].nullpin)
+ is_sigg = 1;
+ else
+ return; /* Oops: No NullPIN. */
+
+ string = g_strdup_printf
+ (_("<b>Setting the Initial PIN</b> (%s)\n\n"
+ "You selected to set the initial PIN of your card. "
+ "The PIN is currently set to the NullPIN. Setting an "
+ "initial PIN is <b>required but can't be reverted</b>.\n\n"
+ "Please check the documentation of your card to learn "
+ "for what the NullPIN is good.\n\n"
+ "If you proceeed you will be asked to enter a new PIN "
+ "and later to repeat that PIN. Make sure that you "
+ "will remember that PIN - it will not be possible to "
+ "recover the PIN if it has been entered wrongly more "
+ "than %d times.\n\n%s"),
+ is_sigg? "SigG" : "NKS",
+ 2,
+ is_sigg
+ ? _("You are now setting the PIN for the SigG key used to create "
+ "<b>qualified signatures</b>. You may want to set the "
+ "PIN to the same value as used for the NKS keys.")
+ : _("You are now setting the PIN for the NKS keys used for standard "
+ "signatures, encryption and authentication."));
+
/* FIXME: How do we figure out our GtkWindow? */
- dialog = GTK_MESSAGE_DIALOG (gtk_message_dialog_new
- (NULL /*GTK_WINDOW (card)*/,
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_OK_CANCEL, NULL));
- gtk_message_dialog_set_markup
- (dialog, _("<b>Setting the Initial PIN</b>\n\n"
- "You selected to set the initial PIN of your card. "
- "The PIN is currently set to the NullPIN, setting an "
- "initial PIN is thus <b>required but can't be reverted</b>.\n\n"
- "Please check the documentation of your card to learn "
- "for what the NullPIN is good.\n\n"
- "If you proceeed you will be asked to enter a new PIN "
- "and later to repeat that PIN. Make sure that you "
- "will remember that PIN - it will not be possible to "
- "recover the PIN if it has been entered wrongly more "
- "than 2 times." ));
-
- if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK )
+ dialog = gtk_message_dialog_new_with_markup (NULL /*GTK_WINDOW (card)*/,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK_CANCEL,
+ NULL);
+ gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), string);
+ g_free (string);
+
+ okay = (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK);
+ if (okay)
{
err = gpgme_op_assuan_transact (gpgagent,
- "SCD PASSWD --nullpin 0",
+ is_sigg
+ ? "SCD PASSWD --nullpin PW1.CH.SIG"
+ : "SCD PASSWD --nullpin PW1.CH",
NULL, NULL,
NULL, NULL,
NULL, NULL);
if (!err)
err = gpgme_op_assuan_result (gpgagent)->err;
- if (err && gpg_err_code (err) != GPG_ERR_CANCELED)
+ if (gpg_err_code (err) == GPG_ERR_CANCELED)
+ okay = 0; /* No need to reload the data. */
+ else if (err)
{
char *message = g_strdup_printf
(_("Error changing the NullPIN.\n"
@@ -373,10 +411,123 @@
}
}
gtk_widget_destroy (GTK_WIDGET (dialog));
+ if (okay)
+ reload_data (card);
}
+
static void
+change_or_reset_pin (GpaCMNetkey *card, int info_idx)
+{
+ gpg_error_t err;
+ GtkWidget *dialog;
+ gpgme_ctx_t gpgagent;
+ int reset_mode;
+ const char *string;
+ int is_puk;
+ int okay;
+ const char *pwidstr;
+
+ gpgagent = GPA_CM_OBJECT (card)->agent_ctx;
+ g_return_if_fail (gpgagent);
+ g_return_if_fail (info_idx < DIM (card->pininfo));
+
+ if (!card->pininfo[info_idx].valid
+ || card->pininfo[info_idx].nopin
+ || card->pininfo[info_idx].nullpin)
+ {
+ g_debug ("oops: NullPIN or not valid");
+ return;
+ }
+ reset_mode = (card->pininfo[info_idx].blocked
+ || !card->pininfo[info_idx].tries_left);
+ is_puk = !!(info_idx & 1);
+ g_debug ("%s PIN at idx %d", reset_mode?"Resetting":"Changing", info_idx);
+ switch (info_idx)
+ {
+ case 0: pwidstr = "PW1.CH"; break;
+ case 1: pwidstr = "PW2.CH"; break;
+ case 2: pwidstr = "PW1.CH.SIG"; break;
+ case 3: pwidstr = "PW2.CH.SIG"; break;
+ default: return; /* Ooops. */
+ }
+
+ string = (!reset_mode
+ ? _("<b>Changing a PIN or PUK</b>\n"
+ "\n"
+ "If you proceed you will be asked to enter "
+ "the current value and then to enter a new "
+ "value and repeat that value at another prompt.\n"
+ "\n"
+ "Entering a wrong value for the current value "
+ "decrements the retry counter. If the retry counters "
+ "of the PIN and the corresponding PUK are both down "
+ "to zero, the keys controlled by the PIN are not anymore "
+ "usable and there is no way to unblock them!")
+ : is_puk
+ ? _("<b>Resetting a PUK</b>\n"
+ "\n"
+ "Although <i>PUK</i> stands for <i>PIN Unblocking Code</i> "
+ "the TCOS operating system of the NetKey card implements it "
+ "as an alternative PIN and thus it is possible to use the "
+ "PIN to unblock the PUK.\n"
+ "\n"
+ "If the PUK is blocked (the retry counter is down to zero), "
+ "you may unblock it by using the non-blocked PIN. The retry "
+ "counter is then set back to its initial value.\n"
+ "\n"
+ "If you proceed you will be asked to enter the current "
+ "value of the PIN and then to enter a new value for the "
+ "blocked PUK and repeat that new value at another prompt.")
+ : _("<b>Resetting a PIN</b>\n"
+ "\n"
+ "If the PIN is blocked (the retry counter is down to zero), "
+ "you may unblock it by using the non-blocked PUK. The retry "
+ "counter is then set back to its initial value.\n"
+ "\n"
+ "If you proceed you will be asked to enter the current "
+ "value of the PUK and then to enter a new value for the "
+ "blocked PIN and repeat that new value at another prompt.")
+ );
+
+ /* FIXME: How do we figure out our GtkWindow? */
+ dialog = gtk_message_dialog_new_with_markup (NULL /*GTK_WINDOW (card)*/,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK_CANCEL,
+ NULL);
+ gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), string);
+ okay = (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK);
+ if (okay)
+ {
+ char command[100];
+
+ snprintf (command, sizeof command, "SCD PASSWD%s %s",
+ reset_mode? " --reset":"", pwidstr);
+ err = gpgme_op_assuan_transact (gpgagent, command,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ if (!err)
+ err = gpgme_op_assuan_result (gpgagent)->err;
+ if (gpg_err_code (err) == GPG_ERR_CANCELED)
+ okay = 0; /* No need to reload the data. */
+ else if (err)
+ {
+ char *message = g_strdup_printf
+ (_("Error changing or resetting the PIN/PUK.\n"
+ "(%s <%s>)"), gpg_strerror (err), gpg_strsource (err));
+ gpa_window_error (message, NULL);
+ xfree (message);
+ }
+ }
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ if (okay)
+ reload_data (card);
+}
+
+
+
+static void
set_initial_pin_clicked_cb (GtkButton *widget, void *user_data)
{
GpaCMNetkey *card = user_data;
@@ -385,6 +536,22 @@
}
+static void
+change_pin_clicked_cb (void *widget, void *user_data)
+{
+ GpaCMNetkey *card = user_data;
+
+ if (widget == card->change_pin_btn)
+ change_or_reset_pin (card, 0);
+ else if (widget == card->change_puk_btn)
+ change_or_reset_pin (card, 1);
+ else if (widget == card->change_sigg_pin_btn)
+ change_or_reset_pin (card, 2);
+ else if (widget == card->change_sigg_puk_btn)
+ change_or_reset_pin (card, 3);
+}
+
+
/* Helper for construct_data_widget. Returns the label widget. */
static GtkLabel *
add_table_row (GtkWidget *table, int *rowidx,
@@ -467,7 +634,7 @@
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
vbox = gtk_vbox_new (FALSE, 5);
label = gtk_label_new
- (_("<b>The NullPIN is still active on this card</b>.\n"
+ (_("<b>A NullPIN is still active on this card</b>.\n"
"You need to set a real PIN before you can make use of the card."));
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
@@ -491,27 +658,43 @@
label = gtk_label_new (_("<b>PIN</b>"));
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
gtk_frame_set_label_widget (GTK_FRAME (frame), label);
- table = gtk_table_new (2, 3, FALSE);
+ table = gtk_table_new (4, 3, FALSE);
gtk_container_set_border_width (GTK_CONTAINER (table), 10);
gtk_container_add (GTK_CONTAINER (frame), table);
rowidx = 0;
card->entries[ENTRY_PIN_RETRYCOUNTER] = gtk_label_new (NULL);
- button = gtk_button_new_with_label (_("Change PIN"));
- gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NORMAL);
- add_table_row (table, &rowidx,
- _("PIN retry counter:"),
+ button = gtk_button_new ();
+ add_table_row (table, &rowidx, _("PIN retry counter:"),
card->entries[ENTRY_PIN_RETRYCOUNTER], button, 1);
card->change_pin_btn = button;
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (change_pin_clicked_cb), card);
card->entries[ENTRY_PUK_RETRYCOUNTER] = gtk_label_new (NULL);
- button = gtk_button_new_with_label (_("Change PUK"));
- gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_HALF);
- add_table_row (table, &rowidx,
- _("PUK retry counter:"),
+ button = gtk_button_new ();
+ add_table_row (table, &rowidx, _("PUK retry counter:"),
card->entries[ENTRY_PUK_RETRYCOUNTER], button, 1);
card->change_puk_btn = button;
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (change_pin_clicked_cb), card);
+ card->entries[ENTRY_SIGG_PIN_RETRYCOUNTER] = gtk_label_new (NULL);
+ button = gtk_button_new ();
+ add_table_row (table, &rowidx, _("SigG PIN retry counter:"),
+ card->entries[ENTRY_SIGG_PIN_RETRYCOUNTER], button, 1);
+ card->change_sigg_pin_btn = button;
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (change_pin_clicked_cb), card);
+
+ card->entries[ENTRY_SIGG_PUK_RETRYCOUNTER] = gtk_label_new (NULL);
+ button = gtk_button_new ();
+ add_table_row (table, &rowidx, _("SigG PUK retry counter:"),
+ card->entries[ENTRY_SIGG_PUK_RETRYCOUNTER], button, 1);
+ card->change_sigg_puk_btn = button;
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (change_pin_clicked_cb), card);
+
gtk_box_pack_start (GTK_BOX (card), frame, FALSE, TRUE, 0);
}
More information about the Gpa-commits
mailing list