diff --git a/src/applet-device-gsm.c b/src/applet-device-gsm.c
index 09c4c35..595f546 100644
--- a/src/applet-device-gsm.c
+++ b/src/applet-device-gsm.c
@@ -371,7 +371,8 @@ typedef struct {
 	NMActiveConnection *active_connection;
 	GtkWidget *dialog;
 	NMSettingsConnectionInterface *connection;
-	GtkEntry *secret_entry;
+	GtkEntry *secret_entry; /* first entry -- PIN etc.. */
+	GtkEntry *secret_entry2; /* second entry - used for PUK */
 	char *secret_name;
 } NMGsmInfo;
 
@@ -399,6 +400,34 @@ pin_entry_changed (GtkEditable *editable, gpointer user_data)
 }
 
 static void
+puk_entry_changed (GtkEditable *editable, gpointer user_data)
+{
+    GtkEntry *pin_entry = GTK_ENTRY (user_data);
+    const char *s;
+    int i;
+    gboolean valid = FALSE;
+
+    s = gtk_entry_get_text (GTK_ENTRY (editable));
+    if (s && strlen (s) == 8) {
+        valid = TRUE;
+        for (i = 0; i < 8; i++) {
+            if (!g_ascii_isdigit (s[i])) {
+                valid = FALSE;
+                break;
+            }
+        }
+    }
+
+    if (!valid)
+    {
+        /* clear the pin-entry, which will automatically grey out the OK button */
+        gtk_entry_set_text(pin_entry, "");
+    }
+
+    gtk_widget_set_sensitive (GTK_WIDGET(pin_entry), valid);
+}
+
+static void
 destroy_gsm_dialog (gpointer user_data, GObject *finalized)
 {
 	NMGsmInfo *info = user_data;
@@ -450,10 +479,19 @@ get_gsm_secrets_cb (GtkDialog *dialog,
 	setting = NM_SETTING_GSM (nm_connection_get_setting (NM_CONNECTION (info->connection), NM_TYPE_SETTING_GSM));
 
 	if (!strcmp (info->secret_name, NM_SETTING_GSM_PIN) ||
-	    !strcmp (info->secret_name, NM_SETTING_GSM_PUK) ||
 	    !strcmp (info->secret_name, NM_SETTING_GSM_PASSWORD))
 		g_object_set (setting, info->secret_name, gtk_entry_get_text (info->secret_entry), NULL);
 
+	if (!strcmp (info->secret_name, NM_SETTING_GSM_PUK))
+	{
+	    const gchar * pin = gtk_entry_get_text (info->secret_entry);
+	    const gchar * puk = gtk_entry_get_text (info->secret_entry2);
+
+	    gchar * pukAndNewPin = g_strdup_printf("%s;%s", puk, pin);
+
+	    g_object_set (setting, NM_SETTING_GSM_PUK, pukAndNewPin, NULL);
+	}
+
 	secrets = nm_setting_to_hash (NM_SETTING (setting));
 	if (!secrets) {
 		g_set_error (&err,
@@ -471,6 +509,7 @@ get_gsm_secrets_cb (GtkDialog *dialog,
 								    g_free, (GDestroyNotify) g_hash_table_destroy);
 
 	g_hash_table_insert (settings_hash, g_strdup (nm_setting_get_name (NM_SETTING (setting))), secrets);
+
 	info->callback (info->connection, settings_hash, NULL, info->callback_data);
 	g_hash_table_destroy (settings_hash);
 
@@ -496,30 +535,32 @@ static GtkWidget *
 ask_for_pin_puk (NMDevice *device,
                  NMConnection *connection,
                  const char *secret_name,
-                 GtkEntry **out_secret_entry)
+                 GtkEntry **out_secret_entry,
+                 GtkEntry **out_secret_entry2)
 {
 	GtkDialog *dialog;
-	GtkWidget *w = NULL, *ok_button;
+	GtkWidget *w = NULL, *w2 = NULL, *ok_button;
 	GtkBox *box;
 	char *dev_str;
+    gboolean pin_mode = strcmp (secret_name, NM_SETTING_GSM_PIN) == 0;
+    gboolean puk_mode = strcmp (secret_name, NM_SETTING_GSM_PUK) == 0;
+    g_assert(pin_mode || puk_mode);
 
 	dialog = GTK_DIALOG (gtk_dialog_new ());
 	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
 
-	if (!strcmp (secret_name, NM_SETTING_GSM_PIN))
+	if (pin_mode)
 		gtk_window_set_title (GTK_WINDOW (dialog), _("PIN code required"));
-	else if (!strcmp (secret_name, NM_SETTING_GSM_PUK))
-		gtk_window_set_title (GTK_WINDOW (dialog), _("PUK code required"));
 	else
-		g_assert_not_reached ();
+		gtk_window_set_title (GTK_WINDOW (dialog), _("PUK code required"));
 
 	ok_button = gtk_dialog_add_button (dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
 	ok_button = gtk_dialog_add_button (dialog, GTK_STOCK_OK, GTK_RESPONSE_OK);
 	gtk_window_set_default (GTK_WINDOW (dialog), ok_button);
 
-	if (!strcmp (secret_name, NM_SETTING_GSM_PIN))
+	if (pin_mode)
 		w = gtk_label_new (_("PIN code is needed for the mobile broadband device"));
-	else if (!strcmp (secret_name, NM_SETTING_GSM_PUK))
+	else
 		w = gtk_label_new (_("PUK code is needed for the mobile broadband device"));
 	if (w)
 		gtk_box_pack_start (GTK_BOX (dialog->vbox), w, TRUE, TRUE, 0);
@@ -537,16 +578,44 @@ ask_for_pin_puk (NMDevice *device,
 	gtk_container_set_border_width (GTK_CONTAINER (box), 6);
 	gtk_container_add (GTK_CONTAINER (w), GTK_WIDGET (box));
 
-	gtk_box_pack_start (box, gtk_label_new ("PIN:"), FALSE, FALSE, 0);
-
-	w = gtk_entry_new ();
-	*out_secret_entry = GTK_ENTRY (w);
-	gtk_entry_set_max_length (GTK_ENTRY (w), 4);
-	gtk_entry_set_width_chars (GTK_ENTRY (w), 4);
-	gtk_entry_set_activates_default (GTK_ENTRY (w), TRUE);
-	gtk_box_pack_start (box, w, FALSE, FALSE, 0);
-	g_signal_connect (w, "changed", G_CALLBACK (pin_entry_changed), ok_button);
-	pin_entry_changed (GTK_EDITABLE (w), ok_button);
+	if (puk_mode)
+	{
+	    gtk_box_pack_start (box, gtk_label_new ("PUK:"), FALSE, FALSE, 0);
+
+	    w2 = gtk_entry_new ();
+	    *out_secret_entry2 = GTK_ENTRY (w2);
+	    gtk_entry_set_max_length (GTK_ENTRY (w2), 8);
+	    gtk_entry_set_width_chars (GTK_ENTRY (w2), 8);
+	    gtk_entry_set_activates_default (GTK_ENTRY (w2), TRUE);
+	    gtk_box_pack_start (box, w2, FALSE, FALSE, 0);
+
+        gtk_box_pack_start (box, gtk_label_new ("New PIN:"), FALSE, FALSE, 0);
+
+        w = gtk_entry_new ();
+        *out_secret_entry = GTK_ENTRY (w);
+        gtk_entry_set_max_length (GTK_ENTRY (w), 4);
+        gtk_entry_set_width_chars (GTK_ENTRY (w), 4);
+        gtk_entry_set_activates_default (GTK_ENTRY (w), TRUE);
+        gtk_box_pack_start (box, w, FALSE, FALSE, 0);
+
+        g_signal_connect (w2, "changed", G_CALLBACK (puk_entry_changed), w);
+        g_signal_connect (w, "changed", G_CALLBACK (pin_entry_changed), ok_button);
+        puk_entry_changed (GTK_EDITABLE (w2),w);
+        pin_entry_changed (GTK_EDITABLE (w), ok_button);
+	}
+	else
+	{
+	    gtk_box_pack_start (box, gtk_label_new ("PIN:"), FALSE, FALSE, 0);
+
+	    w = gtk_entry_new ();
+	    *out_secret_entry = GTK_ENTRY (w);
+	    gtk_entry_set_max_length (GTK_ENTRY (w), 4);
+	    gtk_entry_set_width_chars (GTK_ENTRY (w), 4);
+	    gtk_entry_set_activates_default (GTK_ENTRY (w), TRUE);
+	    gtk_box_pack_start (box, w, FALSE, FALSE, 0);
+	    g_signal_connect (w, "changed", G_CALLBACK (pin_entry_changed), ok_button);
+	    pin_entry_changed (GTK_EDITABLE (w), ok_button);
+	}
 
 	gtk_widget_show_all (dialog->vbox);
 	return GTK_WIDGET (dialog);
@@ -619,6 +688,7 @@ gsm_get_secrets (NMDevice *device,
 	NMGsmInfo *info;
 	GtkWidget *widget;
 	GtkEntry *secret_entry = NULL;
+	GtkEntry *secret_entry2 = NULL; /* used for PUK */
 
 	if (!hints || !g_strv_length ((char **) hints)) {
 		g_set_error (error,
@@ -631,7 +701,7 @@ gsm_get_secrets (NMDevice *device,
 
 	if (   !strcmp (hints[0], NM_SETTING_GSM_PIN)
 	    || !strcmp (hints[0], NM_SETTING_GSM_PUK))
-		widget = ask_for_pin_puk (device, NM_CONNECTION (connection), hints[0], &secret_entry);
+		widget = ask_for_pin_puk (device, NM_CONNECTION (connection), hints[0], &secret_entry, &secret_entry2);
 	else if (!strcmp (hints[0], NM_SETTING_GSM_PASSWORD))
 		widget = ask_for_password (device, NM_CONNECTION (connection), &secret_entry);
 	else {
@@ -661,6 +731,7 @@ gsm_get_secrets (NMDevice *device,
 	info->secret_name = g_strdup (hints[0]);
 	info->dialog = widget;
 	info->secret_entry = secret_entry;
+	info->secret_entry2 = secret_entry2;
 
 	g_signal_connect (widget, "response", G_CALLBACK (get_gsm_secrets_cb), info);
 
