[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#722250: pu: package telepathy-gabble/0.16.7-0+deb7u1



Package: release.debian.org
Severity: normal
Tags: wheezy
User: release.debian.org@packages.debian.org
Usertags: pu

I'd like to update telepathy-gabble/wheezy to fix inability to connect
to Facebook XMPP chat, for which a fix is on its way to unstable
(<http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=721883>). In principle,
would you be OK with updating to a new upstream "old-stable" release for
this? The changes are small and targeted, and most of the diffstat is in
the regression tests (which we don't install or run in Debian).

If we're able to work around another Facebook server bug that periodically
blanks contacts' nicknames/avatars
<http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=722098> without inflating
the diff too much, we'll include that in the release too.

I attach a preview of what the diff between 0.16.5 (in wheezy) and 0.16.7
should look like, including changes to a git submodule (which is where the
actual bugfix is). The second patch band in gabble-0.16.7pre-wocky.diff is
currently applied as a security patch; I'd drop that patch when updating
to the new upstream.

If you approve in principle, I'll follow up with the real patch after
making the upstream release.

Thanks,
    S
diff --git a/NEWS b/NEWS
index 5cd2165..077aa25 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,52 @@
+telepathy-gabble 0.16.7 (UNRELEASED)
+====================================
+
+Known incompatibilities:
+
+• The regression tests (make check/make distcheck) will not work if
+  the build system is refreshed with Automake 1.13 or later.
+  This is fixed in 0.18.x and newer branches. All tarball releases from this
+  branch should be made using Automake 1.12 or older.
+
+Fixes:
+
+• update Wocky:
+  · fd.o #68829: If we send an IQ to a server allow "from" to be empty
+    (David Edmundson)
+
+• fd.o #65296: initialize libdbus for thread-safety (Simon)
+
+• fd.o #49595: disable an unreliable test-case (Simon)
+
+• fd.o #64285: avoid running the same commands twice in parallel when doing a
+  highly parallel build (Simon)
+
+• fd.o #67828: fix a test failure with telepathy-glib 0.20.3/0.21.1 or later
+  (Simon)
+
+telepathy-gabble 0.16.6 (2013-05-30)
+====================================
+
+The “repeated gas boiler replacement” release.
+
+This release fixes a man-in-the-middle attack. You should upgrade.
+
+If you use an unencrypted connection to a "legacy Jabber" (pre-XMPP)
+server, this version of Gabble will not connect until you make
+one of these configuration changes:
+
+• upgrade the server software to something that supports XMPP 1.0; or
+• use an encrypted "old SSL" connection, typically on port 5223 (old-ssl); or
+• turn off "Encryption required (TLS/SSL)" (require-encryption)
+
+Fixes:
+
+• fd.o #65036 (CVE-2013-1431): update Wocky to respect the tls-required
+  flag on legacy Jabber servers (Simon)
+
+• fd.o #63119: improve regression tests' isolation from the session bus
+  (Simon)
+
 telepathy-gabble 0.16.5 (2013-03-01)
 ====================================
 
diff --git a/configure.ac b/configure.ac
index c8c0211..38b4a55 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,8 +9,8 @@ AC_PREREQ([2.59])
 
 m4_define([gabble_major_version], [0])
 m4_define([gabble_minor_version], [16])
-m4_define([gabble_micro_version], [5])
-m4_define([gabble_nano_version], [0])
+m4_define([gabble_micro_version], [6])
+m4_define([gabble_nano_version], [1])
 
 # Some magic
 m4_define([gabble_base_version],
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index 8e50ffb..001a39d 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -62,8 +62,11 @@ extensions.html: _gen/all.xml $(tools_dir)/doc-generator.xsl Makefile.am
 		$(tools_dir)/doc-generator.xsl \
 		$< > $@
 
-_gen/svc.c _gen/svc.h _gen/svc-gtk-doc.h: _gen/all.xml $(tools_dir)/glib-ginterface-gen.py \
-	Makefile.am
+_gen/svc.h: _gen/svc.c
+	@: # do nothing, output as a side-effect
+_gen/svc-gtk-doc.h: _gen/svc.c
+	@: # do nothing, output as a side-effect
+_gen/svc.c: _gen/all.xml $(tools_dir)/glib-ginterface-gen.py Makefile.am
 	$(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-ginterface-gen.py \
 		--filename=_gen/svc --signal-marshal-prefix=_gabble_ext \
 		--include='<telepathy-glib/dbus.h>' \
@@ -84,18 +87,25 @@ _gen/signals-marshal.c: _gen/signals-marshal.list Makefile.am
 	$(AM_V_GEN){ echo '#include "_gen/signals-marshal.h"' && \
 	$(GLIB_GENMARSHAL) --body --prefix=_gabble_ext_marshal $< ; } > $@
 
-_gen/enums.h _gen/enums-gtk-doc.h: _gen/all.xml $(tools_dir)/c-constants-gen.py \
-	Makefile.am
+_gen/enums-gtk-doc.h: _gen/enums.h
+	@: # do nothing, output as a side-effect
+_gen/enums.h: _gen/all.xml $(tools_dir)/c-constants-gen.py Makefile.am
 	$(AM_V_GEN)$(PYTHON) $(tools_dir)/c-constants-gen.py Gabble $< _gen/enums
 
-_gen/interfaces.h _gen/interfaces-body.h _gen/interfaces-gtk-doc.h: _gen/all.xml \
-	$(tools_dir)/glib-interfaces-gen.py \
-	Makefile.am
+_gen/interfaces-body.h: _gen/interfaces.h
+	@: # do nothing, output as a side-effect
+_gen/interfaces-gtk-doc.h: _gen/interfaces.h
+	@: # do nothing, output as a side-effect
+_gen/interfaces.h: _gen/all.xml $(tools_dir)/glib-interfaces-gen.py Makefile.am
 	$(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-interfaces-gen.py \
 		Gabble _gen/interfaces-body.h _gen/interfaces.h $<
 
-_gen/gtypes.h _gen/gtypes-body.h _gen/gtypes-gtk-doc.h: _gen/all.xml \
-	$(tools_dir)/glib-gtypes-generator.py Makefile.am
+_gen/gtypes.h: _gen/gtypes-body.h
+	@: # do nothing, output as a side-effect
+_gen/gtypes-gtk-doc.h: _gen/gtypes-body.h
+	@: # do nothing, output as a side-effect
+
+_gen/gtypes-body.h: _gen/all.xml $(tools_dir)/glib-gtypes-generator.py Makefile.am
 	$(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-gtypes-generator.py \
 		$< _gen/gtypes Gabble
 
diff --git a/lib/ext/wocky b/lib/ext/wocky
index 565f2ed..853d37f 160000
--- a/lib/ext/wocky
+++ b/lib/ext/wocky
@@ -1 +1 @@
-Subproject commit 565f2ed54f53adc7bd6793a0e746ceb349843408
+Subproject commit 853d37fbb356c2c3e76da7bbe879a0b609bf6f44
diff --git a/src/gabble.c b/src/gabble.c
index 0d2fb6e..31ca342 100644
--- a/src/gabble.c
+++ b/src/gabble.c
@@ -25,6 +25,8 @@
 # include <unistd.h>
 #endif
 
+#include <dbus/dbus.h>
+
 #include <glib/gstdio.h>
 
 #include <telepathy-glib/debug.h>
@@ -116,6 +118,9 @@ gabble_init (void)
     g_thread_init (NULL);
 #endif
 
+  if (!dbus_threads_init_default ())
+    g_error ("Unable to initialize libdbus thread-safety (out of memory?)");
+
   g_type_init ();
   wocky_init ();
 }
diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am
index ba5dcad..f23dc1e 100644
--- a/tests/twisted/Makefile.am
+++ b/tests/twisted/Makefile.am
@@ -21,6 +21,7 @@ TWISTED_TESTS = \
 	client-types.py \
 	cm/protocol.py \
 	connect/disco-error-from-bare-jid.py \
+	connect/disco-facebook.py \
 	connect/disconnect-timeout.py \
 	connect/disco-no-reply.py \
 	connect/network-error.py \
@@ -120,6 +121,7 @@ TWISTED_TESTS = \
 	text/test-text-delayed.py \
 	text/test-text-no-body.py \
 	text/test-text.py \
+	tls/legacy-jabber.py \
 	tls/server-tls-channel.py \
 	version.py \
 	$(NULL)
diff --git a/tests/twisted/connect/disco-facebook.py b/tests/twisted/connect/disco-facebook.py
new file mode 100644
index 0000000..39cd9e6
--- /dev/null
+++ b/tests/twisted/connect/disco-facebook.py
@@ -0,0 +1,51 @@
+"""
+Test that Gabble is tolerant of non-RFC-compliance from Facebook.
+https://bugs.freedesktop.org/show_bug.cgi?id=68829
+"""
+
+from gabbletest import exec_test, XmppXmlStream
+import constants as cs
+import ns
+
+from twisted.words.xish import xpath
+
+def test(q, bus, conn, stream):
+    conn.Connect()
+
+    # everything is fine and actually very boring
+    q.expect('dbus-signal', signal='StatusChanged',
+            args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]),
+    q.expect('dbus-signal', signal='StatusChanged',
+            args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
+
+class XmppXmlStreamFacebook201309(XmppXmlStream):
+    """As of 2013-09, a new version of Facebook's XMPP server (used
+    consistently for beta.chat.facebook.com, and gradually being rolled out
+    for chat.facebook.com users) omits the 'from' attribute in its disco
+    reply. The disco reply is otherwise correct.
+    """
+
+    def _cb_disco_iq(self, iq):
+        nodes = xpath.queryForNodes(
+            "/iq/query[@xmlns='" + ns.DISCO_INFO + "']", iq)
+        query = nodes[0]
+
+        for feature in self.disco_features:
+            query.addChild(elem('feature', var=feature))
+
+        iq['type'] = 'result'
+
+        # The Facebook server's IQ responses have neither 'from' nor 'to'
+        try:
+            del iq['from']
+        except KeyError:
+            pass
+        try:
+            del iq['to']
+        except KeyError:
+            pass
+
+        self.send(iq)
+
+if __name__ == '__main__':
+    exec_test(test, protocol=XmppXmlStreamFacebook201309, do_connect=False)
diff --git a/tests/twisted/gabbletest.py b/tests/twisted/gabbletest.py
index 2ee15dd..aa63c6d 100644
--- a/tests/twisted/gabbletest.py
+++ b/tests/twisted/gabbletest.py
@@ -160,7 +160,7 @@ class JabberAuthenticator(GabbleAuthenticator):
             self._event_func(Event('auth-second-iq', authenticator=self,
                 iq=iq, id=iq["id"]))
         else:
-            self.respondToSecondIq(self, iq)
+            self.respondToSecondIq(iq)
 
     def respondToSecondIq(self, iq):
         username = xpath.queryForNodes('/iq/query/username', iq)
diff --git a/tests/twisted/jingle-share/test-send-file-send-before-accept.py b/tests/twisted/jingle-share/test-send-file-send-before-accept.py
index dd0a028..76b0c37 100644
--- a/tests/twisted/jingle-share/test-send-file-send-before-accept.py
+++ b/tests/twisted/jingle-share/test-send-file-send-before-accept.py
@@ -7,6 +7,10 @@ if not JINGLE_FILE_TRANSFER_ENABLED:
     print "NOTE: built with --disable-file-transfer or --disable-voip"
     raise SystemExit(77)
 
+print("FIXME: test is not stable enough.\n" +
+      "    https://bugs.freedesktop.org/show_bug.cgi?id=49595";)
+raise SystemExit(77)
+
 class SendFileBeforeAccept(SendFileTest):
     def __init__(self, file, address_type,
                  access_control, acces_control_param):
diff --git a/tests/twisted/roster/groups.py b/tests/twisted/roster/groups.py
index d9fd67d..a0ba99b 100644
--- a/tests/twisted/roster/groups.py
+++ b/tests/twisted/roster/groups.py
@@ -53,24 +53,35 @@ def test(q, bus, conn, stream):
 
     stream.send(event.stanza)
 
-    # slight implementation detail: TpBaseContactList emits ContactsChanged
-    # etc. before it announces its channels, and it emits one CGC per group.
-    s1, s2 = q.expect_many(
-        EventPattern('dbus-signal', signal='GroupsChanged',
-            interface=cs.CONN_IFACE_CONTACT_GROUPS, path=conn.object_path,
-            predicate=lambda e: 'women' in e.args[1]),
-        EventPattern('dbus-signal', signal='GroupsChanged',
-            interface=cs.CONN_IFACE_CONTACT_GROUPS, path=conn.object_path,
-            predicate=lambda e: 'men' in e.args[1]),
-        )
+    # Avoid relying on the implementation detail of exactly when
+    # TpBaseContactList emits ContactsChanged, relative to when it
+    # announces its channels. Prior to 0.20.3, 0.21.1 it would
+    # announce the channels, emit GroupsChanged, then announce the channels
+    # again... which was a bug, but it turned out this test relied on it.
+    #
+    # We do still rely on the implementation detail that we emit GroupsChanged
+    # once per group with all of its members, not once per contact with all
+    # of their groups. On a typical contact list, there are more contacts
+    # than groups, so that'll work out smaller.
+
+    pairs, groups_changed = expect_contact_list_signals(q, bus, conn, [],
+            ['men', 'women'],
+            [
+                EventPattern('dbus-signal', signal='GroupsChanged',
+                    interface=cs.CONN_IFACE_CONTACT_GROUPS,
+                    path=conn.object_path,
+                    predicate=lambda e: 'women' in e.args[1]),
+                EventPattern('dbus-signal', signal='GroupsChanged',
+                    interface=cs.CONN_IFACE_CONTACT_GROUPS,
+                    path=conn.object_path,
+                    predicate=lambda e: 'men' in e.args[1]),
+            ])
 
     amy, bob, che = conn.RequestHandles(cs.HT_CONTACT,
             ['amy@foo.com', 'bob@foo.com', 'che@foo.com'])
 
-    assertEquals([[amy], ['women'], []], s1.args)
-    assertEquals([[bob, che], ['men'], []], s2.args)
-
-    pairs = expect_contact_list_signals(q, bus, conn, [], ['men', 'women'])
+    assertEquals([[amy], ['women'], []], groups_changed[0].args)
+    assertEquals([[bob, che], ['men'], []], groups_changed[1].args)
 
     q.expect('dbus-signal', signal='ContactListStateChanged',
             args=[cs.CONTACT_LIST_STATE_SUCCESS])
diff --git a/tests/twisted/rostertest.py b/tests/twisted/rostertest.py
index 3d31ad4..7e9f121 100644
--- a/tests/twisted/rostertest.py
+++ b/tests/twisted/rostertest.py
@@ -68,10 +68,14 @@ def get_contact_list_event_patterns(q, bus, conn, expected_handle_type, name):
                 predicate=new_channels_predicate)
             )
 
-def expect_contact_list_signals(q, bus, conn, lists, groups=[]):
+def expect_contact_list_signals(q, bus, conn, lists, groups=[],
+        expect_more=None):
     assert lists or groups
 
-    eps = []
+    if expect_more is None:
+        eps = []
+    else:
+        eps = expect_more[:]
 
     for name in lists:
         eps.extend(get_contact_list_event_patterns(q, bus, conn,
@@ -83,6 +87,11 @@ def expect_contact_list_signals(q, bus, conn, lists, groups=[]):
 
     events = q.expect_many(*eps)
     ret = []
+    more = []
+
+    if expect_more is not None:
+        for ep in expect_more:
+            more.append(events.pop(0))
 
     for name in lists:
         old_signal = events.pop(0)
@@ -95,6 +104,10 @@ def expect_contact_list_signals(q, bus, conn, lists, groups=[]):
         ret.append((old_signal, new_signal))
 
     assert len(events) == 0
+
+    if expect_more is not None:
+        return ret, more
+
     return ret
 
 def check_contact_list_signals(q, bus, conn, signals,
diff --git a/tests/twisted/tls/legacy-jabber.py b/tests/twisted/tls/legacy-jabber.py
new file mode 100644
index 0000000..e2090bb
--- /dev/null
+++ b/tests/twisted/tls/legacy-jabber.py
@@ -0,0 +1,36 @@
+"""
+fd.o #65036: connecting to legacy Jabber servers should respect
+    require-encryption
+"""
+
+from servicetest import assertEquals
+from gabbletest import exec_test, JabberXmlStream, JabberAuthenticator
+import constants as cs
+
+JID = 'alice@example.com'
+PASSWORD = 's3kr1t'
+
+def test_require_encryption(q, bus, conn, stream):
+    conn.Connect()
+    q.expect('dbus-signal', signal='StatusChanged',
+        args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED])
+
+    # FIXME: arrange to get a better error
+    new = q.expect('dbus-signal', signal='ConnectionError')
+    assertEquals(cs.NETWORK_ERROR, new.args[0])
+
+    q.expect('dbus-signal', signal='StatusChanged',
+        args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_NETWORK_ERROR])
+
+if __name__ == '__main__':
+    exec_test(test_require_encryption,
+            {
+                'password': PASSWORD,
+                'account': JID,
+                'require-encryption': True,
+                'old-ssl': False,
+                'resource': 'legacy-require-encryption',
+            },
+        protocol=JabberXmlStream,
+        authenticator=JabberAuthenticator(JID.split('@')[0], PASSWORD),
+        do_connect=False)
diff --git a/tests/twisted/tools/with-session-bus.sh b/tests/twisted/tools/with-session-bus.sh
index 1b8990e..68aec5d 100644
--- a/tests/twisted/tools/with-session-bus.sh
+++ b/tests/twisted/tools/with-session-bus.sh
@@ -81,6 +81,12 @@ if [ -n "$CHECK_TWISTED_VERBOSE" ] || [ -n "$VERBOSE_TESTS" ]; then
 fi
 
 e=0
+
+# These might be non-null when run from e.g. gnome-terminal 3.8, which uses
+# an activatable service for its windows; we don't want to inherit them either
+unset DBUS_STARTER_ADDRESS
+unset DBUS_STARTER_BUS_TYPE
+
 DBUS_SESSION_BUS_ADDRESS="`cat $me-$$.address`"
 export DBUS_SESSION_BUS_ADDRESS
 
]7;file:///home/smcv/src/fdo/gabble%2D0%2E16/lib/ext/wockydiff --git a/wocky/wocky-c2s-porter.c b/wocky/wocky-c2s-porter.c
index ec89c4b..6a58c43 100644
--- a/wocky/wocky-c2s-porter.c
+++ b/wocky/wocky-c2s-porter.c
@@ -858,6 +858,16 @@ check_spoofing (WockyC2SPorter *self,
         goto finally;
     }
 
+  /* If we sent an IQ to the server itself, allow it to
+   * omit 'from' in its reply, which is normally used
+   * for messages from the server on behalf of our own
+   * account (as of 2013-09-02, the Facebook beta server
+   * does this). See fd.o #68829 */
+
+  if (from == NULL && !wocky_strdiff (should_be_from, self->priv->domain)) {
+      goto finally;
+  }
+
   /* if we sent an IQ to our full or bare JID, allow our server to omit 'to'
    * in the reply (Prosody 0.6.1 does this with the resulting error if we
    * send disco#info to our own bare JID), or to use our full JID. */
diff --git a/wocky/wocky-connector.c b/wocky/wocky-connector.c
index 133b9fd..3287285 100644
--- a/wocky/wocky-connector.c
+++ b/wocky/wocky-connector.c
@@ -1135,6 +1135,9 @@ xmpp_init_recv_cb (GObject *source,
       if (!priv->legacy_support)
         abort_connect_code (self, WOCKY_CONNECTOR_ERROR_NON_XMPP_V1_SERVER,
             "Server not XMPP 1.0 Compliant");
+      else if (priv->tls_required && !priv->encrypted)
+        abort_connect_code (data, WOCKY_CONNECTOR_ERROR_TLS_UNAVAILABLE,
+            "TLS requested but server is not XMPP 1.0 compliant (try using \"old SSL\")");
       else
         jabber_request_auth (self);
     }

Reply to: