comparison libpurple/protocols/jabber/jabber.c @ 31449:1c660ba17ba1

propagate from branch 'im.pidgin.pidgin' (head 6f879669a6513a5c40335bbaefe842389a92b39e) to branch 'im.pidgin.cpw.qulogic.cairo' (head 4ab0199887f74442673fd46dcbb662bc7f070bc4)
author Marcus Lundblad <ml@update.uu.se>
date Sun, 21 Nov 2010 20:30:12 +0000
parents bc0bccdbc28f
children 10aa18ac6774 b07841f6cd15
comparison
equal deleted inserted replaced
31448:9a705087d64e 31449:1c660ba17ba1
49 #include "buddy.h" 49 #include "buddy.h"
50 #include "caps.h" 50 #include "caps.h"
51 #include "chat.h" 51 #include "chat.h"
52 #include "data.h" 52 #include "data.h"
53 #include "disco.h" 53 #include "disco.h"
54 #include "google.h" 54 #include "google/google.h"
55 #include "google/google_roster.h"
56 #include "google/google_session.h"
55 #include "ibb.h" 57 #include "ibb.h"
56 #include "iq.h" 58 #include "iq.h"
57 #include "jutil.h" 59 #include "jutil.h"
58 #include "message.h" 60 #include "message.h"
59 #include "parser.h" 61 #include "parser.h"
216 PurpleAccount *account; 218 PurpleAccount *account;
217 xmlnode *starttls; 219 xmlnode *starttls;
218 220
219 account = purple_connection_get_account(js->gc); 221 account = purple_connection_get_account(js->gc);
220 222
223 #if 0
224 /*
225 * This code DOES NOT EXIST, will never be enabled by default, and
226 * will never ever be supported (by me).
227 * It's literally *only* for developer testing.
228 */
229 {
230 const gchar *connection_security = purple_account_get_string(account, "connection_security", JABBER_DEFAULT_REQUIRE_TLS);
231 if (!g_str_equal(connection_security, "none") &&
232 purple_ssl_is_supported()) {
233 jabber_send_raw(js,
234 "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>", -1);
235 return TRUE;
236 }
237 }
238 #else
221 if(purple_ssl_is_supported()) { 239 if(purple_ssl_is_supported()) {
222 jabber_send_raw(js, 240 jabber_send_raw(js,
223 "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>", -1); 241 "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>", -1);
224 return TRUE; 242 return TRUE;
225 } 243 } else {
244 purple_debug_warning("jabber", "No libpurple TLS/SSL support found.");
245 }
246 #endif
226 247
227 starttls = xmlnode_get_child(packet, "starttls"); 248 starttls = xmlnode_get_child(packet, "starttls");
228 if(xmlnode_get_child(starttls, "required")) { 249 if(xmlnode_get_child(starttls, "required")) {
229 purple_connection_error_reason(js->gc, 250 purple_connection_error_reason(js->gc,
230 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, 251 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
231 _("Server requires TLS/SSL, but no TLS/SSL support was found.")); 252 _("Server requires TLS/SSL, but no TLS/SSL support was found."));
232 return TRUE; 253 return TRUE;
233 } 254 }
234 255
235 if(purple_account_get_bool(account, "require_tls", JABBER_DEFAULT_REQUIRE_TLS)) { 256 if (g_str_equal("require_tls", purple_account_get_string(account, "connection_security", JABBER_DEFAULT_REQUIRE_TLS))) {
236 purple_connection_error_reason(js->gc, 257 purple_connection_error_reason(js->gc,
237 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, 258 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
238 _("You require encryption, but no TLS/SSL support was found.")); 259 _("You require encryption, but no TLS/SSL support was found."));
239 return TRUE; 260 return TRUE;
240 } 261 }
242 return FALSE; 263 return FALSE;
243 } 264 }
244 265
245 void jabber_stream_features_parse(JabberStream *js, xmlnode *packet) 266 void jabber_stream_features_parse(JabberStream *js, xmlnode *packet)
246 { 267 {
247 if(xmlnode_get_child(packet, "starttls")) { 268 PurpleAccount *account = purple_connection_get_account(js->gc);
248 if(jabber_process_starttls(js, packet)) { 269 const char *connection_security =
270 purple_account_get_string(account, "connection_security", JABBER_DEFAULT_REQUIRE_TLS);
271
272 if (xmlnode_get_child(packet, "starttls")) {
273 if (jabber_process_starttls(js, packet)) {
249 jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING_ENCRYPTION); 274 jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING_ENCRYPTION);
250 return; 275 return;
251 } 276 }
252 } else if(purple_account_get_bool(js->gc->account, "require_tls", JABBER_DEFAULT_REQUIRE_TLS) && !jabber_stream_is_ssl(js)) { 277 } else if (g_str_equal(connection_security, "require_tls") && !jabber_stream_is_ssl(js)) {
253 purple_connection_error_reason(js->gc, 278 purple_connection_error_reason(js->gc,
254 PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, 279 PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
255 _("You require encryption, but it is not available on this server.")); 280 _("You require encryption, but it is not available on this server."));
256 return; 281 return;
257 } 282 }
735 760
736 static void 761 static void
737 txt_resolved_cb(GList *responses, gpointer data) 762 txt_resolved_cb(GList *responses, gpointer data)
738 { 763 {
739 JabberStream *js = data; 764 JabberStream *js = data;
765 gboolean found = FALSE;
740 766
741 js->srv_query_data = NULL; 767 js->srv_query_data = NULL;
742
743 if (responses == NULL) {
744 purple_debug_warning("jabber", "Unable to find alternative XMPP connection "
745 "methods after failing to connect directly.\n");
746 purple_connection_error_reason(js->gc,
747 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
748 _("Unable to connect"));
749 return;
750 }
751 768
752 while (responses) { 769 while (responses) {
753 PurpleTxtResponse *resp = responses->data; 770 PurpleTxtResponse *resp = responses->data;
754 gchar **token; 771 gchar **token;
755 token = g_strsplit(purple_txt_response_get_content(resp), "=", 2); 772 token = g_strsplit(purple_txt_response_get_content(resp), "=", 2);
763 purple_txt_response_destroy(resp); 780 purple_txt_response_destroy(resp);
764 responses = g_list_delete_link(responses, responses); 781 responses = g_list_delete_link(responses, responses);
765 } 782 }
766 783
767 if (js->bosh) { 784 if (js->bosh) {
785 found = TRUE;
768 jabber_bosh_connection_connect(js->bosh); 786 jabber_bosh_connection_connect(js->bosh);
769 } else { 787 }
770 purple_debug_info("jabber","Didn't find an alternative connection method.\n"); 788
789 if (!found) {
790 purple_debug_warning("jabber", "Unable to find alternative XMPP connection "
791 "methods after failing to connect directly.\n");
792 purple_connection_error_reason(js->gc,
793 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
794 _("Unable to connect"));
795 return;
771 } 796 }
772 797
773 if (responses) { 798 if (responses) {
774 g_list_foreach(responses, (GFunc)purple_txt_response_destroy, NULL); 799 g_list_foreach(responses, (GFunc)purple_txt_response_destroy, NULL);
775 g_list_free(responses); 800 g_list_free(responses);
940 return NULL; 965 return NULL;
941 } 966 }
942 967
943 js->buddies = g_hash_table_new_full(g_str_hash, g_str_equal, 968 js->buddies = g_hash_table_new_full(g_str_hash, g_str_equal,
944 g_free, (GDestroyNotify)jabber_buddy_free); 969 g_free, (GDestroyNotify)jabber_buddy_free);
970
971 /* This is overridden during binding, but we need it here
972 * in case the server only does legacy non-sasl auth!.
973 */
974 purple_connection_set_display_name(gc, user);
945 975
946 js->user_jb = jabber_buddy_find(js, user, TRUE); 976 js->user_jb = jabber_buddy_find(js, user, TRUE);
947 g_free(user); 977 g_free(user);
948 if (!js->user_jb) { 978 if (!js->user_jb) {
949 /* This basically *can't* fail, but for good measure... */ 979 /* This basically *can't* fail, but for good measure... */
970 js->protocol_version.minor = 0; 1000 js->protocol_version.minor = 0;
971 js->sessions = NULL; 1001 js->sessions = NULL;
972 js->stun_ip = NULL; 1002 js->stun_ip = NULL;
973 js->stun_port = 0; 1003 js->stun_port = 0;
974 js->stun_query = NULL; 1004 js->stun_query = NULL;
1005 js->google_relay_token = NULL;
1006 js->google_relay_host = NULL;
1007 js->google_relay_requests = NULL;
975 1008
976 /* if we are idle, set idle-ness on the stream (this could happen if we get 1009 /* if we are idle, set idle-ness on the stream (this could happen if we get
977 disconnected and the reconnects while being idle. I don't think it makes 1010 disconnected and the reconnects while being idle. I don't think it makes
978 sense to do this when registering a new account... */ 1011 sense to do this when registering a new account... */
979 presence = purple_account_get_presence(account); 1012 presence = purple_account_get_presence(account);
1012 } 1045 }
1013 1046
1014 js->certificate_CN = g_strdup(connect_server[0] ? connect_server : js->user->domain); 1047 js->certificate_CN = g_strdup(connect_server[0] ? connect_server : js->user->domain);
1015 1048
1016 /* if they've got old-ssl mode going, we probably want to ignore SRV lookups */ 1049 /* if they've got old-ssl mode going, we probably want to ignore SRV lookups */
1017 if(purple_account_get_bool(account, "old_ssl", FALSE)) { 1050 if (g_str_equal("old_ssl", purple_account_get_string(account, "connection_security", JABBER_DEFAULT_REQUIRE_TLS))) {
1018 if(purple_ssl_is_supported()) { 1051 if(purple_ssl_is_supported()) {
1019 js->gsc = purple_ssl_connect(account, js->certificate_CN, 1052 js->gsc = purple_ssl_connect(account, js->certificate_CN,
1020 purple_account_get_int(account, "port", 5223), 1053 purple_account_get_int(account, "port", 5223),
1021 jabber_login_callback_ssl, jabber_ssl_connect_failure, gc); 1054 jabber_login_callback_ssl, jabber_ssl_connect_failure, gc);
1022 if (!js->gsc) { 1055 if (!js->gsc) {
1629 if(js->sasl) 1662 if(js->sasl)
1630 sasl_dispose(&js->sasl); 1663 sasl_dispose(&js->sasl);
1631 if(js->sasl_mechs) 1664 if(js->sasl_mechs)
1632 g_string_free(js->sasl_mechs, TRUE); 1665 g_string_free(js->sasl_mechs, TRUE);
1633 g_free(js->sasl_cb); 1666 g_free(js->sasl_cb);
1667 /* Note: _not_ g_free. See auth_cyrus.c:jabber_sasl_cb_secret */
1668 free(js->sasl_secret);
1634 #endif 1669 #endif
1635 g_free(js->serverFQDN); 1670 g_free(js->serverFQDN);
1636 while(js->commands) { 1671 while(js->commands) {
1637 JabberAdHocCommands *cmd = js->commands->data; 1672 JabberAdHocCommands *cmd = js->commands->data;
1638 g_free(cmd->jid); 1673 g_free(cmd->jid);
1669 1704
1670 /* cancel DNS query for STUN, if one is ongoing */ 1705 /* cancel DNS query for STUN, if one is ongoing */
1671 if (js->stun_query) { 1706 if (js->stun_query) {
1672 purple_dnsquery_destroy(js->stun_query); 1707 purple_dnsquery_destroy(js->stun_query);
1673 js->stun_query = NULL; 1708 js->stun_query = NULL;
1709 }
1710
1711 /* remove Google relay-related stuff */
1712 g_free(js->google_relay_token);
1713 g_free(js->google_relay_host);
1714 if (js->google_relay_requests) {
1715 while (js->google_relay_requests) {
1716 PurpleUtilFetchUrlData *url_data =
1717 (PurpleUtilFetchUrlData *) js->google_relay_requests->data;
1718 purple_util_fetch_url_cancel(url_data);
1719 g_free(url_data);
1720 js->google_relay_requests =
1721 g_list_delete_link(js->google_relay_requests,
1722 js->google_relay_requests);
1723 }
1674 } 1724 }
1675 1725
1676 g_free(js); 1726 g_free(js);
1677 1727
1678 gc->proto_data = NULL; 1728 gc->proto_data = NULL;
2613 2663
2614 #define SET_REASON(x) \ 2664 #define SET_REASON(x) \
2615 if(reason != NULL) { *reason = x; } 2665 if(reason != NULL) { *reason = x; }
2616 2666
2617 if((error = xmlnode_get_child(packet, "error"))) { 2667 if((error = xmlnode_get_child(packet, "error"))) {
2668 xmlnode *t = xmlnode_get_child_with_namespace(error, "text", NS_XMPP_STANZAS);
2669 if (t)
2670 cdata = xmlnode_get_data(t);
2671 #if 0
2618 cdata = xmlnode_get_data(error); 2672 cdata = xmlnode_get_data(error);
2673 #endif
2619 code = xmlnode_get_attrib(error, "code"); 2674 code = xmlnode_get_attrib(error, "code");
2620 2675
2621 /* Stanza errors */ 2676 /* Stanza errors */
2622 if(xmlnode_get_child(error, "bad-request")) { 2677 if(xmlnode_get_child(error, "bad-request")) {
2623 text = _("Bad Request"); 2678 text = _("Bad Request");
2624 } else if(xmlnode_get_child(error, "conflict")) { 2679 } else if(xmlnode_get_child(error, "conflict")) {
2680 SET_REASON(PURPLE_CONNECTION_ERROR_NAME_IN_USE);
2625 text = _("Conflict"); 2681 text = _("Conflict");
2626 } else if(xmlnode_get_child(error, "feature-not-implemented")) { 2682 } else if(xmlnode_get_child(error, "feature-not-implemented")) {
2627 text = _("Feature Not Implemented"); 2683 text = _("Feature Not Implemented");
2628 } else if(xmlnode_get_child(error, "forbidden")) { 2684 } else if(xmlnode_get_child(error, "forbidden")) {
2629 text = _("Forbidden"); 2685 text = _("Forbidden");
3227 jb = jabber_buddy_find(js, who, FALSE); 3283 jb = jabber_buddy_find(js, who, FALSE);
3228 jbr = jabber_buddy_find_resource(jb, resource); 3284 jbr = jabber_buddy_find_resource(jb, resource);
3229 g_free(resource); 3285 g_free(resource);
3230 3286
3231 if (type & PURPLE_MEDIA_AUDIO && 3287 if (type & PURPLE_MEDIA_AUDIO &&
3232 !jabber_resource_has_capability(jbr, 3288 !jabber_resource_has_capability(jbr,
3233 JINGLE_APP_RTP_SUPPORT_AUDIO) && 3289 JINGLE_APP_RTP_SUPPORT_AUDIO) &&
3234 jabber_resource_has_capability(jbr, NS_GOOGLE_VOICE)) 3290 jabber_resource_has_capability(jbr, NS_GOOGLE_VOICE))
3235 return jabber_google_session_initiate(js, who, type); 3291 return jabber_google_session_initiate(js, who, type);
3236 else 3292 else
3237 return jingle_rtp_initiate_media(js, who, type); 3293 return jingle_rtp_initiate_media(js, who, type);
3238 } 3294 }
3239 3295