Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: freeze-exception

Please unblock package ejabberd 2.1.10-5.

It fixes one important bug [1] which prevents certain (correct) XMPP
client implementations (namely, the XMPP library used by git-annex) to
authenticate against the ejabberd server while using the SCRAM SHA-1
SASL authentication mechanism.

The patch has been tested to work OK both with a client which did not
expose the bug (Gajim 0.15.3) and the library which exposed it (the
test case from [2]) so I'm confident it does not break existing clients.

The debdiff between 2.1.10-4 and 2.1.10-5 is attached.

1. http://bugs.debian.org/705613
2. https://support.process-one.net/browse/EJAB-1632
diff -u ejabberd-2.1.10/debian/changelog ejabberd-2.1.10/debian/changelog
--- ejabberd-2.1.10/debian/changelog
+++ ejabberd-2.1.10/debian/changelog
@@ -1,3 +1,12 @@
+ejabberd (2.1.10-5) unstable; urgency=low
+
+  [ Konstantin Khomoutov ]
+  * Add patch fixing parsing of optional parameters in SCRAM SHA-1 headers
+    (closes: #705613, thanks to Stephen Röttger for both writing the
+    original patch and backporting it to 2.1.10).
+
+ -- Konstantin Khomoutov <flatw...@users.sourceforge.net>  Thu, 25 Apr 2013 
15:31:59 +0000
+
 ejabberd (2.1.10-4) unstable; urgency=low
 
   [ Konstantin Khomoutov ]
diff -u ejabberd-2.1.10/debian/patches/series 
ejabberd-2.1.10/debian/patches/series
--- ejabberd-2.1.10/debian/patches/series
+++ ejabberd-2.1.10/debian/patches/series
@@ -9,0 +10 @@
+scram-optional-parameter-parsing-bugfix.patch
only in patch2:
unchanged:
--- 
ejabberd-2.1.10.orig/debian/patches/scram-optional-parameter-parsing-bugfix.patch
+++ ejabberd-2.1.10/debian/patches/scram-optional-parameter-parsing-bugfix.patch
@@ -0,0 +1,99 @@
+Description: Fix parsing SCRAM optional parameters
+ The server gave an authentication error, if optional parameters
+ were present in the GS2 Header. Specifically, the "a=" parameter,
+ that can be used by admins to login as a different user.
+ .
+ This patch is a backport of changes introduced by the commit
+ 9e9b0eae802ee0508db6780426954efd048e7976 in the upstream Git repository
+ to the ejabberd code base as of version 2.1.10.
+Author: Stephen Röttger <stephen.roett...@gmail.com>
+Forwarded: not-needed
+Bug: https://support.process-one.net/browse/EJAB-1632
+Last-Update: 2013-03-25
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/src/cyrsasl_scram.erl
++++ b/src/cyrsasl_scram.erl
+@@ -34,6 +34,8 @@
+ 
+ -include("ejabberd.hrl").
+ 
++-include("jlib.hrl").
++
+ -behaviour(cyrsasl).
+ 
+ -record(state, {step, stored_key, server_key, username, get_password, 
check_password,
+@@ -52,8 +54,12 @@
+     {ok, #state{step = 2, get_password = GetPassword}}.
+ 
+ mech_step(#state{step = 2} = State, ClientIn) ->
+-      case string:tokens(ClientIn, ",") of
+-      [CBind, UserNameAttribute, ClientNonceAttribute] when (CBind == "y") or 
(CBind == "n") ->
++      case re:split(ClientIn, ",", [{return, list}]) of
++      [_CBind, _AuthorizationIdentity, _UserNameAttribute, 
_ClientNonceAttribute, ExtensionAttribute | _]
++      when ExtensionAttribute /= [] ->
++              {error, <<"protocol-error-extension-not-supported">>};
++      [CBind, _AuthorizationIdentity, UserNameAttribute, ClientNonceAttribute 
| _]
++      when (CBind == "y") or (CBind == "n") ->
+               case parse_attribute(UserNameAttribute) of
+                 {error, Reason} ->
+                       {error, Reason};
+@@ -100,32 +106,36 @@
+       case string:tokens(ClientIn, ",") of
+       [GS2ChannelBindingAttribute, NonceAttribute, ClientProofAttribute] ->
+               case parse_attribute(GS2ChannelBindingAttribute) of
+-              {$c, CVal} when (CVal == "biws") or (CVal == "eSws") ->
+-                  %% biws is base64 for n,, => channelbinding not supported
+-                  %% eSws is base64 for y,, => channelbinding supported by 
client only
+-                      Nonce = State#state.client_nonce ++ 
State#state.server_nonce,
+-                      case parse_attribute(NonceAttribute) of
+-                      {$r, CompareNonce} when CompareNonce == Nonce ->
+-                              case parse_attribute(ClientProofAttribute) of
+-                              {$p, ClientProofB64} ->
+-                                      ClientProof = 
base64:decode(ClientProofB64),
+-                                      AuthMessage = State#state.auth_message 
++ "," ++ string:substr(ClientIn, 1, string:str(ClientIn, ",p=")-1),
+-                                      ClientSignature = 
scram:client_signature(State#state.stored_key, AuthMessage),
+-                                      ClientKey = 
scram:client_key(ClientProof, ClientSignature),
+-                                      CompareStoredKey = 
scram:stored_key(ClientKey),
+-                                      if CompareStoredKey == 
State#state.stored_key ->
+-                                              ServerSignature = 
scram:server_signature(State#state.server_key, AuthMessage),
+-                                              {ok, [{username, 
State#state.username}], "v=" ++ base64:encode_to_string(ServerSignature)};
+-                                      true ->
+-                                              {error, "bad-auth"}
++              {$c, CVal} ->
++                      ChannelBindingSupport = 
string:left(jlib:decode_base64(CVal), 1),
++                      if (ChannelBindingSupport == "n")
++                      or (ChannelBindingSupport == "y") ->
++                              Nonce = State#state.client_nonce ++ 
State#state.server_nonce,
++                              case parse_attribute(NonceAttribute) of
++                              {$r, CompareNonce} when CompareNonce == Nonce ->
++                                      case 
parse_attribute(ClientProofAttribute) of
++                                      {$p, ClientProofB64} ->
++                                              ClientProof = 
base64:decode(ClientProofB64),
++                                              AuthMessage = 
State#state.auth_message ++ "," ++ string:substr(ClientIn, 1, 
string:str(ClientIn, ",p=")-1),
++                                              ClientSignature = 
scram:client_signature(State#state.stored_key, AuthMessage),
++                                              ClientKey = 
scram:client_key(ClientProof, ClientSignature),
++                                              CompareStoredKey = 
scram:stored_key(ClientKey),
++                                              if CompareStoredKey == 
State#state.stored_key ->
++                                                      ServerSignature = 
scram:server_signature(State#state.server_key, AuthMessage),
++                                                      {ok, [{username, 
State#state.username}], "v=" ++ base64:encode_to_string(ServerSignature)};
++                                              true ->
++                                                      {error, "bad-auth"}
++                                              end;
++                                      _Else ->
++                                              {error, "bad-protocol"}
+                                       end;
++                              {$r, _} ->
++                                      {error, "bad-nonce"};
+                               _Else ->
+                                       {error, "bad-protocol"}
+                               end;
+-                      {$r, _} ->
+-                              {error, "bad-nonce"};
+-                      _Else ->
+-                              {error, "bad-protocol"}
++                      true ->
++                              {error, "bad-channel-binding"}
+                       end;
+               _Else ->
+                       {error, "bad-protocol"}

Reply via email to