| 42 #define PURPLE_SSL_GNUTLS_DATA(gsc) ((PurpleSslGnutlsData *)gsc->private_data) |
42 #define PURPLE_SSL_GNUTLS_DATA(gsc) ((PurpleSslGnutlsData *)gsc->private_data) |
| 43 |
43 |
| 44 static gnutls_certificate_client_credentials xcred = NULL; |
44 static gnutls_certificate_client_credentials xcred = NULL; |
| 45 |
45 |
| 46 #ifdef HAVE_GNUTLS_PRIORITY_FUNCS |
46 #ifdef HAVE_GNUTLS_PRIORITY_FUNCS |
| 47 /* Priority strings. The default one is, well, the default (and is always |
47 |
| |
48 /** |
| |
49 * This string tells GnuTLS the list of ciphers we're ok with using. The goal |
| |
50 * is to disable weaker ciphers while remaining compatible with almost all |
| |
51 * servers. |
| |
52 * |
| |
53 * Ideally this is something we wouldn't do. Ideally the system-wide GnuTLS |
| |
54 * library would use good defaults. But for now I think we can safely be more |
| |
55 * restrictive than the GnuTLS defaults. --Mark Doliner |
| |
56 * |
| |
57 * You can test the priority string using this command: |
| |
58 * > gnutls-cli --priority "<SIGNATURE STRING>" <HOSTNAME> |
| |
59 * Note that on Ubuntu 14.04 gnutls-cli is linked against the older GnuTLS |
| |
60 * 2.12.23, which might be different than what Pidgin is linked against. |
| |
61 * |
| |
62 * Rationale for this string: |
| |
63 * - Start with the SECURE192 keyword and add the SECURE128 keyword. This |
| |
64 * includes both 128 and 192 bit ciphers, giving priority to the 192 bit |
| |
65 * ciphers. We're not too picky about the order... people generally think |
| |
66 * 128 bit ciphers are sufficient for now and 192 bit ciphers are overkill |
| |
67 * (and slower), but the speed impact shouldn't matter much for us and we |
| |
68 * prefer to be resilient into the distant future. |
| |
69 * |
| |
70 * - Remove and re-add RSA ciphers. This gives them a lower priority. We do |
| |
71 * this because they don't support perfect forward secrecy (PFS) and we want |
| |
72 * ciphers that DO support PFS to have a higher priority. An alternate way |
| |
73 * to do this is to add +PFS to the front of the string, but the PFS keyword |
| |
74 * was only added in 3.2.4 and attempting to use it with older GnuTLS causes |
| |
75 * the entire priority string to be discarded. |
| |
76 * |
| |
77 * - Add SIGN-RSA-SHA1. SHA-1 is a weaker hashing algorithm that's not |
| |
78 * included in SECURE128. We'd prefer not to include it, but unfortunately |
| |
79 * as of 2014-09-10 it is required by login.live.com (used by the MSN PRPL). |
| |
80 * |
| |
81 * - Remove DHE-DSS ciphers. This is kind of arbitrary. We think maybe nobody |
| |
82 * uses these and all things being equal a shorter cipher list is preferred. |
| |
83 * |
| |
84 * - Disable SSL 3.0. Everyone should be using at least TLS 1.0 by now. |
| |
85 * |
| |
86 * We only use this string for GnuTLS 3.2.2 and newer. For older versions we |
| |
87 * use NORMAL. Over time the GnuTLS library has changed how it parses priority |
| |
88 * strings and there are some unfortunate quirks: |
| |
89 * - 128 bit ciphers stopped being included in the SECURE256 keyword in 3.0.9. |
| |
90 * - 256 bit ciphers started being included in the SECURE128 keyword in 3.0.12. |
| |
91 * - Support for combining priority string keywords wasn't added until 3.1.0. |
| |
92 * - Adding/removing items from the priority string using plus and minus is |
| |
93 * buggy in GnuTLS 3.2.2 and older. See this commit for details: |
| |
94 * https://gitorious.org/gnutls/gnutls/commit/913f03ccfafc37277f0a88287d02cdbb9bbfb652 |
| |
95 * |
| |
96 * These quirks make it difficult to find a single priority string that works |
| |
97 * well for all versions of GnuTLS that enables 128 and 256 bit ciphers while |
| |
98 * disabling less secure ciphers. In fact it's difficult to come up with ANY |
| |
99 * string that accomplishes this for 3.0.9, 3.0.10, and 3.0.11. And the bug |
| |
100 * with adding/removing items from the priority string means we might get |
| |
101 * unexpected results when using a complicated string, and so we're better off |
| |
102 * just sticking with the default. |
| |
103 * |
| |
104 * For more discussion about this change see bug #8061. |
| |
105 */ |
| |
106 #define GNUTLS_DEFAULT_PRIORITY "SECURE192:+SECURE128:-RSA:+RSA:+SIGN-RSA-SHA1:-DHE-DSS:-VERS-SSL3.0" |
| |
107 |
| |
108 /* |
| |
109 * Priority strings. The default one is, well, the default (and is always |
| 48 * set). The hash table is of the form hostname => priority (both |
110 * set). The hash table is of the form hostname => priority (both |
| 49 * char *). |
111 * char *). |
| 50 * |
112 * |
| 51 * We only use a gnutls_priority_t for the default on the assumption that |
113 * We only use a gnutls_priority_t for the default on the assumption that |
| 52 * that's the more common case. Improvement patches (like matching on |
114 * that's the more common case. Improvement patches (like matching on |
| 59 static void |
121 static void |
| 60 ssl_gnutls_log(int level, const char *str) |
122 ssl_gnutls_log(int level, const char *str) |
| 61 { |
123 { |
| 62 /* GnuTLS log messages include the '\n' */ |
124 /* GnuTLS log messages include the '\n' */ |
| 63 purple_debug_misc("gnutls", "lvl %d: %s", level, str); |
125 purple_debug_misc("gnutls", "lvl %d: %s", level, str); |
| |
126 } |
| |
127 |
| |
128 /** |
| |
129 * set_cipher_priorities: |
| |
130 * @priority_cache: A pointer to a gnutls_priority_t. This will be initialized |
| |
131 * using the given priorities. |
| |
132 * @priorities: A GnuTLS priority string. |
| |
133 * |
| |
134 * A simple convenience wrapper around gnutls_priority_init(). The wrapper |
| |
135 * does a few things: |
| |
136 * - Logs a helpful message if initialization fails. |
| |
137 * - Frees priority_cache if needed if initialization fails. |
| |
138 * - Set priority_cache to NULL if needed if initialization fails. |
| |
139 */ |
| |
140 static void |
| |
141 set_cipher_priorities(gnutls_priority_t *priority_cache, const char *priorities) |
| |
142 { |
| |
143 int ret; |
| |
144 |
| |
145 ret = gnutls_priority_init(priority_cache, priorities, NULL); |
| |
146 if (ret != GNUTLS_E_SUCCESS) { |
| |
147 purple_debug_warning("gnutls", "Unable to set cipher priorities to %s. " |
| |
148 "Error code %d: %s\n", priorities, ret, gnutls_strerror(ret)); |
| |
149 |
| |
150 /* Versions of GnuTLS before 2.9.10 allocate but don't free priority_cache |
| |
151 if there's an error. We free it here to avoid a mem leak. */ |
| |
152 if (!gnutls_check_version("2.9.10")) { |
| |
153 gnutls_free(*priority_cache); |
| |
154 } |
| |
155 |
| |
156 /* Versions of GnuTLS before 3.2.9 leave priority_cache pointing to |
| |
157 freed memory if there's an error. We want our callers to be able to |
| |
158 depend on this being NULL, so set it to NULL ourselves. */ |
| |
159 if (!gnutls_check_version("3.2.9")) { |
| |
160 *priority_cache = NULL; |
| |
161 } |
| |
162 } |
| 64 } |
163 } |
| 65 |
164 |
| 66 static void |
165 static void |
| 67 ssl_gnutls_init_gnutls(void) |
166 ssl_gnutls_init_gnutls(void) |
| 68 { |
167 { |
| 141 } |
240 } |
| 142 } |
241 } |
| 143 } |
242 } |
| 144 |
243 |
| 145 if (default_priority_str) { |
244 if (default_priority_str) { |
| 146 if (gnutls_priority_init(&default_priority, default_priority_str, NULL)) { |
245 /* Note: If the string is invalid then this call will fail and |
| 147 purple_debug_warning("gnutls", "Unable to set default priority to %s\n", |
246 we'll try again with our default priority string later. */ |
| 148 default_priority_str); |
247 set_cipher_priorities(&default_priority, default_priority_str); |
| 149 /* Versions of GnuTLS as of 2.8.6 (2010-03-31) don't free/NULL |
|
| 150 * this on error. |
|
| 151 */ |
|
| 152 gnutls_free(default_priority); |
|
| 153 default_priority = NULL; |
|
| 154 } |
|
| 155 |
|
| 156 g_free(default_priority_str); |
248 g_free(default_priority_str); |
| 157 } |
249 } |
| 158 |
250 |
| 159 g_strfreev(entries); |
251 g_strfreev(entries); |
| 160 #endif /* HAVE_GNUTLS_PRIORITY_FUNCS */ |
252 #endif /* HAVE_GNUTLS_PRIORITY_FUNCS */ |
| 161 } |
253 } |
| 162 |
254 |
| 163 #ifdef HAVE_GNUTLS_PRIORITY_FUNCS |
255 #ifdef HAVE_GNUTLS_PRIORITY_FUNCS |
| 164 /* Make sure we set have a default priority! */ |
256 /* Set a default priority string if we didn't do it above */ |
| 165 if (!default_priority) { |
257 if (!default_priority) { |
| 166 if (gnutls_priority_init(&default_priority, "NORMAL:%SSL3_RECORD_VERSION", NULL)) { |
258 if (gnutls_check_version("3.2.2")) { |
| 167 /* See comment above about memory leak */ |
259 set_cipher_priorities(&default_priority, GNUTLS_DEFAULT_PRIORITY); |
| 168 gnutls_free(default_priority); |
260 } |
| 169 gnutls_priority_init(&default_priority, "NORMAL", NULL); |
261 if (!default_priority) { |
| |
262 /* Try again with an extremely simple priority string. */ |
| |
263 set_cipher_priorities(&default_priority, "NORMAL"); |
| 170 } |
264 } |
| 171 } |
265 } |
| 172 #endif /* HAVE_GNUTLS_PRIORITY_FUNCS */ |
266 #endif /* HAVE_GNUTLS_PRIORITY_FUNCS */ |
| 173 |
267 |
| 174 gnutls_global_init(); |
268 gnutls_global_init(); |
| 240 |
334 |
| 241 purple_input_remove(gnutls_data->handshake_handler); |
335 purple_input_remove(gnutls_data->handshake_handler); |
| 242 gnutls_data->handshake_handler = 0; |
336 gnutls_data->handshake_handler = 0; |
| 243 |
337 |
| 244 if(ret != 0) { |
338 if(ret != 0) { |
| 245 purple_debug_error("gnutls", "Handshake failed. Error %s\n", |
339 purple_debug_error("gnutls", "Handshake failed: %s\n", |
| 246 gnutls_strerror(ret)); |
340 gnutls_strerror(ret)); |
| 247 |
341 |
| 248 if(gsc->error_cb != NULL) |
342 if(gsc->error_cb != NULL) |
| 249 gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, |
343 gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, |
| 250 gsc->connect_cb_data); |
344 gsc->connect_cb_data); |
| 251 |
345 |
| 252 purple_ssl_close(gsc); |
346 purple_ssl_close(gsc); |
| 253 } else { |
347 } else { |
| 254 /* Now we are cooking with gas! */ |
348 /* Now we are cooking with gas! */ |
| 255 PurpleSslOps *ops = purple_ssl_get_ops(); |
349 PurpleSslOps *ops = purple_ssl_get_ops(); |