mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-03-26 07:10:19 +00:00
Add one-click client cert tools, switch to P-256
This commit is contained in:
@@ -20,6 +20,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <gdk/gdkkeysyms.h>
|
#include <gdk/gdkkeysyms.h>
|
||||||
|
|
||||||
@@ -89,6 +90,9 @@ static GtkWidget *edit_label_nick2;
|
|||||||
static GtkWidget *edit_label_real;
|
static GtkWidget *edit_label_real;
|
||||||
static GtkWidget *edit_label_user;
|
static GtkWidget *edit_label_user;
|
||||||
static GtkWidget *edit_trees[N_TREES];
|
static GtkWidget *edit_trees[N_TREES];
|
||||||
|
static GtkWidget *edit_button_cert_generate;
|
||||||
|
static GtkWidget *edit_button_cert_info;
|
||||||
|
static GtkWidget *edit_button_cert_delete;
|
||||||
|
|
||||||
static ircnet *selected_net = NULL;
|
static ircnet *selected_net = NULL;
|
||||||
static ircserver *selected_serv = NULL;
|
static ircserver *selected_serv = NULL;
|
||||||
@@ -99,6 +103,270 @@ static session *servlist_sess;
|
|||||||
static void servlist_network_row_cb (GtkTreeSelection *sel, gpointer user_data);
|
static void servlist_network_row_cb (GtkTreeSelection *sel, gpointer user_data);
|
||||||
static GtkWidget *servlist_open_edit (GtkWidget *parent, ircnet *net);
|
static GtkWidget *servlist_open_edit (GtkWidget *parent, ircnet *net);
|
||||||
|
|
||||||
|
static char *
|
||||||
|
servlist_get_cert_file (ircnet *net)
|
||||||
|
{
|
||||||
|
if (!net || !net->name || !net->name[0])
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_strdup_printf ("%s" G_DIR_SEPARATOR_S "certs" G_DIR_SEPARATOR_S "%s.pem",
|
||||||
|
get_xdir (), net->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
servlist_network_cert_exists (ircnet *net)
|
||||||
|
{
|
||||||
|
char *cert_file;
|
||||||
|
gboolean exists;
|
||||||
|
|
||||||
|
cert_file = servlist_get_cert_file (net);
|
||||||
|
if (!cert_file)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
exists = g_file_test (cert_file, G_FILE_TEST_IS_REGULAR);
|
||||||
|
g_free (cert_file);
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
servlist_update_cert_buttons (ircnet *net)
|
||||||
|
{
|
||||||
|
gboolean has_cert = servlist_network_cert_exists (net);
|
||||||
|
|
||||||
|
if (edit_button_cert_generate)
|
||||||
|
gtk_widget_set_visible (edit_button_cert_generate, !has_cert);
|
||||||
|
if (edit_button_cert_info)
|
||||||
|
gtk_widget_set_visible (edit_button_cert_info, has_cert);
|
||||||
|
if (edit_button_cert_delete)
|
||||||
|
gtk_widget_set_visible (edit_button_cert_delete, has_cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
servlist_generate_client_cert_cb (GtkWidget *button, gpointer userdata)
|
||||||
|
{
|
||||||
|
#ifdef USE_OPENSSL
|
||||||
|
ircnet *net = (ircnet *)userdata;
|
||||||
|
GtkWidget *dialog;
|
||||||
|
char *cert_dir;
|
||||||
|
char *cert_file;
|
||||||
|
char *key_file;
|
||||||
|
char *crt_file;
|
||||||
|
char *subject;
|
||||||
|
char *key_data;
|
||||||
|
char *crt_data;
|
||||||
|
char *pem_data;
|
||||||
|
char *stderr_data;
|
||||||
|
char *stdout_data;
|
||||||
|
gsize key_len;
|
||||||
|
gsize crt_len;
|
||||||
|
gboolean spawned;
|
||||||
|
gboolean success;
|
||||||
|
gint status;
|
||||||
|
char *argv[18];
|
||||||
|
|
||||||
|
if (!net || !net->name || !net->name[0])
|
||||||
|
return;
|
||||||
|
|
||||||
|
cert_dir = g_build_filename (get_xdir (), "certs", NULL);
|
||||||
|
cert_file = servlist_get_cert_file (net);
|
||||||
|
key_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.key", cert_dir, net->name);
|
||||||
|
crt_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.crt", cert_dir, net->name);
|
||||||
|
subject = g_strdup_printf ("/CN=%s", net->name);
|
||||||
|
key_data = NULL;
|
||||||
|
crt_data = NULL;
|
||||||
|
pem_data = NULL;
|
||||||
|
stderr_data = NULL;
|
||||||
|
stdout_data = NULL;
|
||||||
|
key_len = 0;
|
||||||
|
crt_len = 0;
|
||||||
|
success = FALSE;
|
||||||
|
status = 0;
|
||||||
|
|
||||||
|
if (g_mkdir_with_parents (cert_dir, 0700) == 0)
|
||||||
|
{
|
||||||
|
argv[0] = "openssl";
|
||||||
|
argv[1] = "req";
|
||||||
|
argv[2] = "-x509";
|
||||||
|
argv[3] = "-newkey";
|
||||||
|
argv[4] = "ec";
|
||||||
|
argv[5] = "-pkeyopt";
|
||||||
|
argv[6] = "ec_paramgen_curve:P-256";
|
||||||
|
argv[7] = "-sha256";
|
||||||
|
argv[8] = "-days";
|
||||||
|
argv[9] = "3650";
|
||||||
|
argv[10] = "-nodes";
|
||||||
|
argv[11] = "-keyout";
|
||||||
|
argv[12] = key_file;
|
||||||
|
argv[13] = "-out";
|
||||||
|
argv[14] = crt_file;
|
||||||
|
argv[15] = "-subj";
|
||||||
|
argv[16] = subject;
|
||||||
|
argv[17] = NULL;
|
||||||
|
|
||||||
|
spawned = g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
|
||||||
|
&stdout_data, &stderr_data, &status, NULL);
|
||||||
|
if (spawned && g_spawn_check_exit_status (status, NULL) &&
|
||||||
|
g_file_get_contents (key_file, &key_data, &key_len, NULL) &&
|
||||||
|
g_file_get_contents (crt_file, &crt_data, &crt_len, NULL))
|
||||||
|
{
|
||||||
|
pem_data = g_strconcat (key_data, crt_data, NULL);
|
||||||
|
if (pem_data && g_file_set_contents (cert_file, pem_data, -1, NULL))
|
||||||
|
{
|
||||||
|
chmod (cert_file, 0600);
|
||||||
|
success = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_remove (key_file);
|
||||||
|
g_remove (crt_file);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
servlist_update_cert_buttons (net);
|
||||||
|
dialog = gtk_message_dialog_new (GTK_WINDOW (edit_win),
|
||||||
|
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
|
||||||
|
GTK_MESSAGE_INFO,
|
||||||
|
GTK_BUTTONS_CLOSE,
|
||||||
|
_("Client certificate generated for \"%s\"."),
|
||||||
|
net->name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dialog = gtk_message_dialog_new (GTK_WINDOW (edit_win),
|
||||||
|
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
|
||||||
|
GTK_MESSAGE_ERROR,
|
||||||
|
GTK_BUTTONS_CLOSE,
|
||||||
|
_("Failed to generate the client certificate for \"%s\"."),
|
||||||
|
net->name);
|
||||||
|
if (stderr_data && stderr_data[0])
|
||||||
|
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", stderr_data);
|
||||||
|
}
|
||||||
|
theme_manager_attach_window (dialog);
|
||||||
|
g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog);
|
||||||
|
gtk_widget_show (dialog);
|
||||||
|
|
||||||
|
g_free (stdout_data);
|
||||||
|
g_free (stderr_data);
|
||||||
|
g_free (pem_data);
|
||||||
|
g_free (key_data);
|
||||||
|
g_free (crt_data);
|
||||||
|
g_free (subject);
|
||||||
|
g_free (crt_file);
|
||||||
|
g_free (key_file);
|
||||||
|
g_free (cert_file);
|
||||||
|
g_free (cert_dir);
|
||||||
|
#else
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
servlist_cert_info_cb (GtkWidget *button, gpointer userdata)
|
||||||
|
{
|
||||||
|
#ifdef USE_OPENSSL
|
||||||
|
ircnet *net = (ircnet *)userdata;
|
||||||
|
GtkWidget *dialog;
|
||||||
|
char *cert_file;
|
||||||
|
char *stdout_data;
|
||||||
|
char *stderr_data;
|
||||||
|
gboolean spawned;
|
||||||
|
gint status;
|
||||||
|
char *argv[12];
|
||||||
|
|
||||||
|
cert_file = servlist_get_cert_file (net);
|
||||||
|
if (!cert_file)
|
||||||
|
return;
|
||||||
|
|
||||||
|
stdout_data = NULL;
|
||||||
|
stderr_data = NULL;
|
||||||
|
status = 0;
|
||||||
|
argv[0] = "openssl";
|
||||||
|
argv[1] = "x509";
|
||||||
|
argv[2] = "-in";
|
||||||
|
argv[3] = cert_file;
|
||||||
|
argv[4] = "-noout";
|
||||||
|
argv[5] = "-subject";
|
||||||
|
argv[6] = "-issuer";
|
||||||
|
argv[7] = "-startdate";
|
||||||
|
argv[8] = "-enddate";
|
||||||
|
argv[9] = "-fingerprint";
|
||||||
|
argv[10] = "-sha256";
|
||||||
|
argv[11] = NULL;
|
||||||
|
|
||||||
|
spawned = g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
|
||||||
|
&stdout_data, &stderr_data, &status, NULL);
|
||||||
|
|
||||||
|
if (spawned && g_spawn_check_exit_status (status, NULL) && stdout_data && stdout_data[0])
|
||||||
|
{
|
||||||
|
dialog = gtk_message_dialog_new (GTK_WINDOW (edit_win),
|
||||||
|
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
|
||||||
|
GTK_MESSAGE_INFO,
|
||||||
|
GTK_BUTTONS_CLOSE,
|
||||||
|
_("Client certificate information for \"%s\"."),
|
||||||
|
net->name);
|
||||||
|
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", stdout_data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dialog = gtk_message_dialog_new (GTK_WINDOW (edit_win),
|
||||||
|
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
|
||||||
|
GTK_MESSAGE_ERROR,
|
||||||
|
GTK_BUTTONS_CLOSE,
|
||||||
|
_("Failed to read client certificate information for \"%s\"."),
|
||||||
|
net->name);
|
||||||
|
if (stderr_data && stderr_data[0])
|
||||||
|
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", stderr_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
theme_manager_attach_window (dialog);
|
||||||
|
g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog);
|
||||||
|
gtk_widget_show (dialog);
|
||||||
|
g_free (stdout_data);
|
||||||
|
g_free (stderr_data);
|
||||||
|
g_free (cert_file);
|
||||||
|
#else
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
servlist_delete_client_cert_cb (GtkWidget *button, gpointer userdata)
|
||||||
|
{
|
||||||
|
ircnet *net = (ircnet *)userdata;
|
||||||
|
GtkWidget *dialog;
|
||||||
|
char *cert_file;
|
||||||
|
|
||||||
|
cert_file = servlist_get_cert_file (net);
|
||||||
|
if (!cert_file)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_remove (cert_file) == 0)
|
||||||
|
{
|
||||||
|
servlist_update_cert_buttons (net);
|
||||||
|
dialog = gtk_message_dialog_new (GTK_WINDOW (edit_win),
|
||||||
|
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
|
||||||
|
GTK_MESSAGE_INFO,
|
||||||
|
GTK_BUTTONS_CLOSE,
|
||||||
|
_("Client certificate removed for \"%s\"."),
|
||||||
|
net->name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dialog = gtk_message_dialog_new (GTK_WINDOW (edit_win),
|
||||||
|
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
|
||||||
|
GTK_MESSAGE_ERROR,
|
||||||
|
GTK_BUTTONS_CLOSE,
|
||||||
|
_("Failed to remove client certificate for \"%s\"."),
|
||||||
|
net->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
theme_manager_attach_window (dialog);
|
||||||
|
g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog);
|
||||||
|
gtk_widget_show (dialog);
|
||||||
|
g_free (cert_file);
|
||||||
|
}
|
||||||
|
|
||||||
static GtkWidget *
|
static GtkWidget *
|
||||||
servlist_icon_button_new (const char *label, const char *icon_name)
|
servlist_icon_button_new (const char *label, const char *icon_name)
|
||||||
{
|
{
|
||||||
@@ -1783,6 +2051,7 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
|
|||||||
GtkWidget *buttonadd;
|
GtkWidget *buttonadd;
|
||||||
GtkWidget *buttonremove;
|
GtkWidget *buttonremove;
|
||||||
GtkWidget *buttonedit;
|
GtkWidget *buttonedit;
|
||||||
|
GtkWidget *hbox_cert_buttons;
|
||||||
GtkWidget *hseparator2;
|
GtkWidget *hseparator2;
|
||||||
GtkWidget *hbuttonbox4;
|
GtkWidget *hbuttonbox4;
|
||||||
GtkWidget *button10;
|
GtkWidget *button10;
|
||||||
@@ -1947,7 +2216,7 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
|
|||||||
|
|
||||||
|
|
||||||
/* Checkboxes and entries */
|
/* Checkboxes and entries */
|
||||||
table3 = gtkutil_grid_new (13, 2, FALSE);
|
table3 = gtkutil_grid_new (14, 2, FALSE);
|
||||||
gtk_box_pack_start (GTK_BOX (vbox5), table3, FALSE, FALSE, 0);
|
gtk_box_pack_start (GTK_BOX (vbox5), table3, FALSE, FALSE, 0);
|
||||||
gtk_grid_set_row_spacing (GTK_GRID (table3), 2);
|
gtk_grid_set_row_spacing (GTK_GRID (table3), 2);
|
||||||
gtk_grid_set_column_spacing (GTK_GRID (table3), 8);
|
gtk_grid_set_column_spacing (GTK_GRID (table3), 8);
|
||||||
@@ -2002,6 +2271,27 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
|
|||||||
SERVLIST_ALIGN_FILL, SERVLIST_ALIGN_FILL,
|
SERVLIST_ALIGN_FILL, SERVLIST_ALIGN_FILL,
|
||||||
4, 2);
|
4, 2);
|
||||||
|
|
||||||
|
hbox_cert_buttons = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 6);
|
||||||
|
edit_button_cert_generate = gtk_button_new_with_mnemonic (_("Generate client SSL cert"));
|
||||||
|
g_signal_connect (G_OBJECT (edit_button_cert_generate), "clicked",
|
||||||
|
G_CALLBACK (servlist_generate_client_cert_cb), net);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox_cert_buttons), edit_button_cert_generate, FALSE, FALSE, 0);
|
||||||
|
|
||||||
|
edit_button_cert_info = gtk_button_new_with_mnemonic (_("Client SSL cert info"));
|
||||||
|
g_signal_connect (G_OBJECT (edit_button_cert_info), "clicked",
|
||||||
|
G_CALLBACK (servlist_cert_info_cb), net);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox_cert_buttons), edit_button_cert_info, FALSE, FALSE, 0);
|
||||||
|
|
||||||
|
edit_button_cert_delete = gtk_button_new_with_mnemonic (_("Delete cert"));
|
||||||
|
g_signal_connect (G_OBJECT (edit_button_cert_delete), "clicked",
|
||||||
|
G_CALLBACK (servlist_delete_client_cert_cb), net);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox_cert_buttons), edit_button_cert_delete, FALSE, FALSE, 0);
|
||||||
|
|
||||||
|
servlist_table_attach (table3, hbox_cert_buttons, 0, 2, 13, 14,
|
||||||
|
FALSE, FALSE,
|
||||||
|
SERVLIST_ALIGN_START, SERVLIST_ALIGN_CENTER,
|
||||||
|
SERVLIST_X_PADDING, SERVLIST_Y_PADDING);
|
||||||
|
|
||||||
|
|
||||||
/* Rule and Close button */
|
/* Rule and Close button */
|
||||||
hseparator2 = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
|
hseparator2 = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
|
||||||
@@ -2026,6 +2316,7 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
|
|||||||
gtk_widget_grab_default (button10);
|
gtk_widget_grab_default (button10);
|
||||||
|
|
||||||
gtk_widget_show_all (editwindow);
|
gtk_widget_show_all (editwindow);
|
||||||
|
servlist_update_cert_buttons (net);
|
||||||
|
|
||||||
/* We can't set the active tab without child elements being shown, so this must be *after* gtk_widget_show()s! */
|
/* We can't set the active tab without child elements being shown, so this must be *after* gtk_widget_show()s! */
|
||||||
gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), netedit_active_tab);
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), netedit_active_tab);
|
||||||
|
|||||||
Reference in New Issue
Block a user