auth-helpers.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
  2. /***************************************************************************
  3. *
  4. * Copyright (C) 2008 Dan Williams, <dcbw@redhat.com>
  5. * Copyright (C) 2008 - 2011 Red Hat, Inc.
  6. * Copyright (C) 2008 Tambet Ingo, <tambet@gmail.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. *
  22. **************************************************************************/
  23. #ifdef HAVE_CONFIG_H
  24. #include <config.h>
  25. #endif
  26. #include <string.h>
  27. #include <sys/types.h>
  28. #include <stdlib.h>
  29. #include <sys/stat.h>
  30. #include <fcntl.h>
  31. #include <unistd.h>
  32. #include <errno.h>
  33. #include <glib/gi18n-lib.h>
  34. #include "auth-helpers.h"
  35. #include "nm-openconnect.h"
  36. #include "../src/nm-openconnect-service.h"
  37. void
  38. tls_pw_init_auth_widget (GtkBuilder *builder,
  39. GtkSizeGroup *group,
  40. NMSettingVPN *s_vpn,
  41. ChangedCallback changed_cb,
  42. gpointer user_data)
  43. {
  44. GtkWidget *widget;
  45. const char *value;
  46. GtkFileFilter *filter;
  47. g_return_if_fail (builder != NULL);
  48. g_return_if_fail (group != NULL);
  49. g_return_if_fail (changed_cb != NULL);
  50. widget = GTK_WIDGET (gtk_builder_get_object (builder, "ca_cert_chooser"));
  51. gtk_size_group_add_widget (group, widget);
  52. filter = tls_file_chooser_filter_new ();
  53. gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
  54. gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
  55. gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
  56. _("Choose a Certificate Authority certificate..."));
  57. g_signal_connect (G_OBJECT (widget), "selection-changed", G_CALLBACK (changed_cb), user_data);
  58. if (s_vpn) {
  59. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_CACERT);
  60. if (value && strlen (value))
  61. gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), value);
  62. }
  63. widget = GTK_WIDGET (gtk_builder_get_object (builder, "cert_user_cert_chooser"));
  64. gtk_size_group_add_widget (group, widget);
  65. filter = tls_file_chooser_filter_new ();
  66. gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
  67. gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
  68. gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
  69. _("Choose your personal certificate..."));
  70. g_signal_connect (G_OBJECT (widget), "selection-changed", G_CALLBACK (changed_cb), user_data);
  71. if (s_vpn) {
  72. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_USERCERT);
  73. if (value && strlen (value))
  74. gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), value);
  75. }
  76. widget = GTK_WIDGET (gtk_builder_get_object (builder, "cert_private_key_chooser"));
  77. gtk_size_group_add_widget (group, widget);
  78. filter = tls_file_chooser_filter_new ();
  79. gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
  80. gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
  81. gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
  82. _("Choose your private key..."));
  83. g_signal_connect (G_OBJECT (widget), "selection-changed", G_CALLBACK (changed_cb), user_data);
  84. if (s_vpn) {
  85. value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_PRIVKEY);
  86. if (value && strlen (value))
  87. gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), value);
  88. }
  89. }
  90. gboolean
  91. auth_widget_check_validity (GtkBuilder *builder, GError **error)
  92. {
  93. return TRUE;
  94. }
  95. static void
  96. update_from_filechooser (GtkBuilder *builder,
  97. const char *key,
  98. const char *widget_name,
  99. NMSettingVPN *s_vpn)
  100. {
  101. GtkWidget *widget;
  102. char *filename;
  103. char *authtype;
  104. g_return_if_fail (builder != NULL);
  105. g_return_if_fail (key != NULL);
  106. g_return_if_fail (widget_name != NULL);
  107. g_return_if_fail (s_vpn != NULL);
  108. widget = GTK_WIDGET (gtk_builder_get_object (builder, widget_name));
  109. filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
  110. if (filename && strlen(filename)) {
  111. nm_setting_vpn_add_data_item (s_vpn, key, filename);
  112. authtype = "cert";
  113. } else {
  114. nm_setting_vpn_remove_data_item (s_vpn, key);
  115. authtype = "password";
  116. }
  117. /* Hack to keep older nm-auth-dialog working */
  118. if (!strcmp(key, NM_OPENCONNECT_KEY_USERCERT))
  119. nm_setting_vpn_add_data_item (s_vpn, NM_OPENCONNECT_KEY_AUTHTYPE, authtype);
  120. g_free (filename);
  121. }
  122. gboolean
  123. auth_widget_update_connection (GtkBuilder *builder,
  124. const char *contype,
  125. NMSettingVPN *s_vpn)
  126. {
  127. update_from_filechooser (builder, NM_OPENCONNECT_KEY_CACERT, "ca_cert_chooser", s_vpn);
  128. update_from_filechooser (builder, NM_OPENCONNECT_KEY_USERCERT, "cert_user_cert_chooser", s_vpn);
  129. update_from_filechooser (builder, NM_OPENCONNECT_KEY_PRIVKEY, "cert_private_key_chooser", s_vpn);
  130. return TRUE;
  131. }
  132. static const char *
  133. find_tag (const char *tag, const char *buf, gsize len)
  134. {
  135. gsize i, taglen;
  136. taglen = strlen (tag);
  137. if (len < taglen)
  138. return NULL;
  139. for (i = 0; i < len - taglen + 1; i++) {
  140. if (memcmp (buf + i, tag, taglen) == 0)
  141. return buf + i;
  142. }
  143. return NULL;
  144. }
  145. static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----";
  146. static const char *pem_dsa_key_begin = "-----BEGIN DSA PRIVATE KEY-----";
  147. static const char *pem_key_begin = "-----BEGIN PRIVATE KEY-----";
  148. static const char *pem_enc_key_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
  149. static const char *pem_tss_keyblob_begin = "-----BEGIN TSS KEY BLOB-----";
  150. static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----";
  151. static gboolean
  152. tls_default_filter (const GtkFileFilterInfo *filter_info, gpointer data)
  153. {
  154. char *contents = NULL, *p, *ext;
  155. gsize bytes_read = 0;
  156. gboolean show = FALSE;
  157. struct stat statbuf;
  158. if (!filter_info->filename)
  159. return FALSE;
  160. p = strrchr (filter_info->filename, '.');
  161. if (!p)
  162. return FALSE;
  163. ext = g_ascii_strdown (p, -1);
  164. if (!ext)
  165. return FALSE;
  166. if (strcmp (ext, ".pem") && strcmp (ext, ".crt") && strcmp (ext, ".key")) {
  167. g_free (ext);
  168. return FALSE;
  169. }
  170. g_free (ext);
  171. /* Ignore files that are really large */
  172. if (!stat (filter_info->filename, &statbuf)) {
  173. if (statbuf.st_size > 500000)
  174. return FALSE;
  175. }
  176. if (!g_file_get_contents (filter_info->filename, &contents, &bytes_read, NULL))
  177. return FALSE;
  178. if (bytes_read < 400) /* needs to be lower? */
  179. goto out;
  180. /* Check for PEM signatures */
  181. if (find_tag (pem_rsa_key_begin, (const char *) contents, bytes_read)) {
  182. show = TRUE;
  183. goto out;
  184. }
  185. if (find_tag (pem_dsa_key_begin, (const char *) contents, bytes_read)) {
  186. show = TRUE;
  187. goto out;
  188. }
  189. if (find_tag (pem_key_begin, (const char *) contents, bytes_read)) {
  190. show = TRUE;
  191. goto out;
  192. }
  193. if (find_tag (pem_enc_key_begin, (const char *) contents, bytes_read)) {
  194. show = TRUE;
  195. goto out;
  196. }
  197. if (find_tag (pem_tss_keyblob_begin, (const char *) contents, bytes_read)) {
  198. show = TRUE;
  199. goto out;
  200. }
  201. if (find_tag (pem_cert_begin, (const char *) contents, bytes_read)) {
  202. show = TRUE;
  203. goto out;
  204. }
  205. out:
  206. g_free (contents);
  207. return show;
  208. }
  209. GtkFileFilter *
  210. tls_file_chooser_filter_new (void)
  211. {
  212. GtkFileFilter *filter;
  213. filter = gtk_file_filter_new ();
  214. gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME, tls_default_filter, NULL, NULL);
  215. gtk_file_filter_set_name (filter, _("PEM certificates (*.pem, *.crt, *.key)"));
  216. return filter;
  217. }