summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2010-11-19 17:34:28 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2010-11-23 19:42:53 +0000
commit24b8eba2452f2d881ab99dc366be0e7c1ba6b0d3 (patch)
treeb09bcba71356b6f31909ef191790114f17320087
parent74d160243d6ba936fe7d3449e3e91a3abc5985ed (diff)
Update SASL code to draft 2
This isn't fully correct yet, but it compiles and passes the existing tests (with suitable updates).
-rw-r--r--extensions/Channel_Interface_SASL_Authentication.xml661
-rw-r--r--extensions/Channel_Interface_Sasl_Authentication.xml231
-rw-r--r--extensions/Channel_Type_Server_Authentication.xml143
-rw-r--r--extensions/Makefile.am2
-rw-r--r--extensions/all.xml2
-rw-r--r--src/server-sasl-channel.c438
-rw-r--r--tests/twisted/constants.py15
-rw-r--r--tests/twisted/sasl/abort.py32
-rw-r--r--tests/twisted/sasl/complex.py32
-rw-r--r--tests/twisted/sasl/jabber_auth.py27
-rw-r--r--tests/twisted/sasl/plain.py71
-rw-r--r--tests/twisted/sasl/saslutil.py43
12 files changed, 1099 insertions, 598 deletions
diff --git a/extensions/Channel_Interface_SASL_Authentication.xml b/extensions/Channel_Interface_SASL_Authentication.xml
new file mode 100644
index 00000000..bb25a6b9
--- /dev/null
+++ b/extensions/Channel_Interface_SASL_Authentication.xml
@@ -0,0 +1,661 @@
+<?xml version="1.0" ?>
+<node name="/Channel_Interface_SASL_Authentication"
+ xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
+ <tp:copyright> Copyright © 2010 Collabora Limited </tp:copyright>
+ <tp:license xmlns="http://www.w3.org/1999/xhtml">
+ <p>This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.</p>
+
+<p>This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.</p>
+
+<p>You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p>
+ </tp:license>
+ <interface name="org.freedesktop.Telepathy.Channel.Interface.SASLAuthentication.DRAFT2"
+ tp:causes-havoc="experimental">
+ <tp:added version="0.21.UNRELEASED">(draft 2)</tp:added>
+ <tp:requires interface="org.freedesktop.Telepathy.Channel"/>
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>A channel interface for SASL authentication,
+ as defined by
+ <a href="http://tools.ietf.org/html/rfc4422">RFC 4422</a>.
+ When this interface appears on a <tp:dbus-ref
+ namespace="ofdT.Channel.Type">ServerAuthentication.DRAFT2</tp:dbus-ref>
+ channel, it represents authentication with the server. In future,
+ it could also be used to authenticate with secondary services,
+ or even to authenticate end-to-end connections with contacts.</p>
+
+ <p>In any protocol that requires a password, the connection manager can
+ use this channel to let a user interface carry out a simple SASL-like
+ handshake with it, as a way to get the user's credentials
+ interactively. This can be used to connect to protocols that may
+ require a password, without requiring that the password is saved in
+ the <tp:dbus-ref
+ namespace="ofdT">Account.Parameters</tp:dbus-ref>.</p>
+
+ <p>In some protocols, such as XMPP, authentication with the server
+ is also carried out using SASL. In these protocols, a channel with this
+ interface can provide a simple 1:1 mapping of the SASL negotiations
+ taking place in the protocol, allowing more advanced clients to
+ perform authentication via SASL mechanisms not known to the
+ connection manager.</p>
+
+ <tp:rationale>
+ <p>By providing SASL directly when the protocol supports it, we can
+ use mechanisms like Kerberos or Google's <code>X-GOOGLE-TOKEN</code>
+ without specific support in the connection manager.</p>
+ </tp:rationale>
+
+ <p>For channels managed by a
+ <tp:dbus-ref namespace="ofdT">ChannelDispatcher</tp:dbus-ref>,
+ only the channel's <tp:dbus-ref
+ namespace="ofdT.Client">Handler</tp:dbus-ref> may call the
+ methods on this interface. Other clients MAY observe the
+ authentication process by watching its signals and properties.</p>
+
+ <tp:rationale>
+ <p>There can only be one Handler, which is a good fit for SASL's
+ 1-1 conversation between a client and a server.</p>
+ </tp:rationale>
+ </tp:docstring>
+
+ <tp:simple-type name="SASL_Mechanism" type="s"
+ array-name="SASL_Mechanism_List">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>A SASL mechanism, as defined by
+ <a href="http://tools.ietf.org/html/rfc4422">RFC 4422</a>
+ and registered in
+ <a href="http://www.iana.org/assignments/sasl-mechanisms">the
+ IANA registry of SASL mechanisms</a>, or an unregistered
+ SASL mechanism such as <code>X-GOOGLE-TOKEN</code> used in the
+ same contexts.</p>
+
+ <p>As a special case, pseudo-mechanisms starting with
+ <code>X-TELEPATHY-</code> are defined by this specification.
+ Use of these pseudo-mechanisms indicates that the user's credentials
+ are to be passed to the connection manager, which will then use
+ them for authentication with the service, either by implementing
+ the client side of some SASL mechanisms itself or by using a
+ non-SASL protocol. The only such pseudo-mechanism currently
+ defined is <code>X-TELEPATHY-PASSWORD</code>.</p>
+
+ <p>The <code>X-TELEPATHY-PASSWORD</code> mechanism is extremely
+ simple:</p>
+
+ <ul>
+ <li>The client MUST call
+ <tp:member-ref>StartMechanismWithData</tp:member-ref>, with
+ Initial_Data set to the password encoded in UTF-8.
+ For simplicity, calling <tp:member-ref>StartMechanism</tp:member-ref>
+ followed by calling <tp:member-ref>Respond</tp:member-ref> is not
+ allowed in this mechanism.</li>
+
+ <li>The connection manager uses the password, together with
+ authentication details from the Connection parameters, to
+ authenticate itself to the server.</li>
+
+ <li>When the connection manager finishes its attempt to authenticate
+ to the server, the channel's state changes to
+ either SASL_Status_Server_Succeeded or
+ SASL_Status_Server_Failed as appropriate.</li>
+ </ul>
+ </tp:docstring>
+ </tp:simple-type>
+
+ <property name="AvailableMechanisms"
+ tp:name-for-bindings="Available_Mechanisms"
+ type="as" tp:type="SASL_Mechanism[]"
+ access="read" tp:immutable="yes">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>The SASL mechanisms as offered by the server, plus any
+ pseudo-SASL mechanisms supported by the connection manager for
+ credentials transfer. For instance, in a protocol that
+ natively uses SASL (like XMPP), this might be
+ <code>[ "X-TELEPATHY-PASSWORD", "PLAIN", "DIGEST-MD5",
+ "SCRAM-SHA-1" ]</code>.</p>
+
+ <p>To make it possible to implement a very simple password-querying
+ user interface without knowledge of any particular SASL mechanism,
+ implementations of this interface MUST implement the
+ pseudo-mechanism <code>X-TELEPATHY-PASSWORD</code>.</p>
+ </tp:docstring>
+ </property>
+
+ <property name="HasInitialData" tp:name-for-bindings="Has_Initial_Data"
+ type="b" access="read" tp:immutable="yes">
+ <tp:docstring>
+ If true, <tp:member-ref>StartMechanismWithData</tp:member-ref>
+ can be expected to work (this is the case in most, but not all,
+ protocols). If false, <tp:member-ref>StartMechanism</tp:member-ref>
+ must be used instead.
+ </tp:docstring>
+ </property>
+
+ <property name="CanTryAgain" tp:name-for-bindings="Can_Try_Again"
+ type="b" access="read" tp:immutable="yes">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>If true, <tp:member-ref>StartMechanism</tp:member-ref> and (if
+ supported) <tp:member-ref>StartMechanismWithData</tp:member-ref>
+ can be expected to work when in one of the Failed states. If
+ false, the only thing you can do after failure is to close the
+ channel.</p>
+
+ <tp:rationale>
+ <p>Retrying isn't required to work, although some protocols and
+ implementations allow it.</p>
+ </tp:rationale>
+ </tp:docstring>
+ </property>
+
+ <property name="Encrypted"
+ tp:name-for-bindings="Encrypted" type="b"
+ access="read" tp:immutable="yes">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>True if this authentication process occurs over an encrypted
+ connection. This <strong>does not</strong> imply that steps have
+ been taken to avoid man-in-the-middle attacks.</p>
+
+ <tp:rationale>
+ <p>For future support for <a
+ href="http://tools.ietf.org/html/rfc5056">RFC 5056 Channel
+ Binding</a> it is desirable to be able to use some SASL
+ mechanisms over an encrypted connection to an unverified peer,
+ which can prove that it is the desired destination during
+ the SASL negotiation.</p>
+ </tp:rationale>
+
+ <p>Clients MAY use the combination of this property and
+ <tp:member-ref>Verified</tp:member-ref> to decide whether the
+ <code>PLAIN</code> mechanism is acceptable, for instance.</p>
+ </tp:docstring>
+ </property>
+
+ <property name="Verified"
+ tp:name-for-bindings="Verified" type="b"
+ access="read" tp:immutable="yes">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>True if this authentication process occurs over a connection
+ that is protected against tampering, and has been verified to
+ be with the desired destination: for instance, one where TLS
+ was previously negotiated, and the TLS certificate has been
+ verified against a configured certificate authority or
+ accepted by the user.</p>
+
+ <p>Clients MAY use the combination of this property and
+ <tp:member-ref>Encrypted</tp:member-ref> to decide whether the
+ <code>PLAIN</code> mechanism is acceptable, for instance.</p>
+ </tp:docstring>
+ </property>
+
+ <property type="u" tp:type="SASL_Status" access="read"
+ name="SASLStatus" tp:name-for-bindings="SASL_Status">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ The current status of this channel.
+ Change notification is via the
+ <tp:member-ref>SASLStatusChanged</tp:member-ref> signal.
+ </tp:docstring>
+ </property>
+
+ <property type="s" tp:type="DBus_Error_Name" access="read"
+ name="SASLError" tp:name-for-bindings="SASL_Error">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>The reason for the <tp:member-ref>SASLStatus</tp:member-ref>, or
+ an empty string if the state is neither
+ Server_Failed nor Client_Failed.</p>
+
+ <p>In particular, an ordinary authentication failure (as would
+ be produced for an incorrect password) SHOULD be represented by
+ <tp:error-ref>AuthenticationFailed</tp:error-ref>,
+ cancellation by the user's request SHOULD be represented
+ by <tp:error-ref>Cancelled</tp:error-ref>, and
+ cancellation by a local process due to inconsistent or invalid
+ challenges from the server SHOULD be represented by
+ <tp:error-ref>ServiceConfused</tp:error-ref>.</p>
+
+ <p>If this interface appears on a <tp:dbus-ref
+ namespace="ofdT.Channel.Type">ServerAuthentication.DRAFT2</tp:dbus-ref>
+ channel, and connection to the server fails with an authentication
+ failure, this error code SHOULD be copied into the
+ <tp:dbus-ref
+ namespace="ofdT">Connection.ConnectionError</tp:dbus-ref>
+ signal.</p>
+ </tp:docstring>
+ </property>
+
+ <property name="SASLErrorDetails"
+ tp:name-for-bindings="SASL_Error_Details"
+ access="read" type="a{sv}" tp:type="String_Variant_Map">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>If <tp:member-ref>SASLError</tp:member-ref> is non-empty,
+ any additional information about the last
+ disconnection; otherwise, the empty map. The keys and values are
+ the same as for the second argument of
+ <tp:dbus-ref
+ namespace="ofdT">Connection.ConnectionError</tp:dbus-ref>.</p>
+
+ <p>If this interface appears on a <tp:dbus-ref
+ namespace="ofdT.Channel.Type">ServerAuthentication.DRAFT2</tp:dbus-ref>
+ channel, and connection to the server fails with an authentication
+ failure, these details SHOULD be copied into the
+ <tp:dbus-ref
+ namespace="ofdT">Connection.ConnectionError</tp:dbus-ref>
+ signal.</p>
+ </tp:docstring>
+ </property>
+
+ <property name="AuthorizationIdentity"
+ tp:name-for-bindings="Authorization_Identity"
+ type="s" access="read" tp:immutable="yes">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>The identity for which authorization is being attempted,
+ typically the 'account' from the <tp:dbus-ref
+ namespace="ofdT.ConnectionManager">RequestConnection</tp:dbus-ref>
+ parameters, normalized and formatted according to the
+ conventions used for SASL in this protocol.</p>
+
+ <tp:rationale>
+ <p>The normalization used for SASL might not be the same
+ normalization used elsewhere: for instance, in a protocol
+ with email-like identifiers such as XMPP or SIP, the user
+ "juliet@example.com" might have to authenticate to the
+ example.com server via SASL PLAIN as "juliet".</p>
+ </tp:rationale>
+
+ <p>This is usually achieved by using the authorization identity for
+ authentication, but an advanced Handler could offer the option
+ to authenticate under a different identity.</p>
+
+ <p>The terminology used here is that the authorization identity
+ is who you want to act as, and the authentication identity is
+ used to prove that you may do so. For instance, if Juliet is
+ authorized to access a role account, "sysadmin@example.com",
+ and act on its behalf, it might be possible to authenticate
+ as "juliet@example.com" with her own password, but request to
+ be authorized as "sysadmin@example.com" instead of her own
+ account. See
+ <a href="http://tools.ietf.org/html/rfc4422#section-3.4.1">RFC
+ 4422 §3.4.1</a> for more details.</p>
+
+ <tp:rationale>
+ <p>In SASL the authorization identity is normally guessed from
+ the authentication identity, but the information available
+ to the connection manager is the identity for which
+ authorization is required, such as the desired JID in XMPP,
+ so that's what we signal to UIs; it's up to the UI to
+ choose whether to authenticate as the authorization identity
+ or some other identity.</p>
+
+ <p>As a concrete example, the "sysadmin" XMPP account mentioned
+ above would have <code>{ 'account': 'sysadmin@example.com' }</code>
+ in its Parameters, and this property would also be
+ 'sysadmin@example.com'. A simple Handler would
+ merely prompt for sysadmin@example.com's password,
+ and use that JID as both the authorization and authentication
+ identity, which might result in SASL PLAIN authentication with the
+ initial response
+ '\000sysadmin@example.com\000root'.</p>
+
+ <p>A more advanced Handler might also ask for an authentication
+ identity, defaulting to 'sysadmin@example.com'; if Juliet
+ provided authentication identity 'juliet@example.com' and
+ password 'romeo', the Handler might perform SASL PLAIN
+ authentication using the initial response
+ 'sysadmin@example.com\000juliet@example.com\000romeo'.</p>
+ </tp:rationale>
+ </tp:docstring>
+ </property>
+
+ <property name="DefaultRealm" tp:name-for-bindings="Default_Realm"
+ type="s" access="read" tp:immutable="yes">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>The default realm (as defined in
+ <a href="http://tools.ietf.org/html/rfc2831#section-2.1.1">RFC
+ 2831</a>) to use for authentication, if the server does not
+ supply one.</p>
+
+ <tp:rationale>
+ <p>The server is not required to provide a realm; if it doesn't,
+ the client is expected to ask the user or provide a sensible
+ default, typically the requested DNS name of the server.
+ In some implementations of <code>DIGEST-MD5</code>, the
+ server does not specify a realm, but expects that the client
+ will choose a particular default, and authentication will
+ fail if the client's default is different. Connection
+ managers for protocols where this occurs are more easily able
+ to work around these implementations than a generic client
+ would be.</p>
+ </tp:rationale>
+ </tp:docstring>
+ </property>
+
+ <property name="SASLContext" tp:name-for-bindings="SASL_Context"
+ type="a{sv}" tp:type="String_Variant_Map" access="read"
+ tp:immutable="yes">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>Additional protocol- or mechanism-specific context for the
+ authentication. Only one well-known key is currently defined:</p>
+
+ <dl>
+ <dt>jabber-stream-id (string)</dt>
+ <dd>The <code>id</code> attribute of the XMPP <code>stream</code>
+ element, as used in <a
+ href="http://xmpp.org/extensions/xep-0078.html">the digest
+ mechanism historically used in Jabber</a>.</dd>
+ </dl>
+ </tp:docstring>
+ </property>
+
+ <method name="StartMechanism" tp:name-for-bindings="Start_Mechanism">
+ <arg direction="in" name="Mechanism" type="s" tp:type="SASL_Mechanism">
+ <tp:docstring>
+ The chosen mechanism.
+ </tp:docstring>
+ </arg>
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>Start an authentication try using <var>Mechanism</var>, without
+ sending initial data (an "initial response" as defined in RFC
+ 4422).</p>
+
+ <tp:rationale>
+ <p>This method is appropriate for mechanisms where the client
+ cannot send anything until it receives a challenge from the
+ server, such as <code>DIGEST-MD5</code>.</p>
+ </tp:rationale>
+ </tp:docstring>
+
+ <tp:possible-errors>
+ <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable">
+ <tp:docstring>
+ The channel is not in a state where starting authentication makes
+ sense (i.e. SASL_Status_Not_Started, or (if
+ <tp:member-ref>CanTryAgain</tp:member-ref> is true)
+ SASL_Status_Server_Failed or
+ SASL_Status_Client_Failed). You should call
+ <tp:member-ref>AbortSASL</tp:member-ref> and wait for
+ SASL_Status_Client_Failed before starting another attempt.
+ </tp:docstring>
+ </tp:error>
+ <tp:error name="org.freedesktop.Telepathy.Error.NetworkError"/>
+ <tp:error name="org.freedesktop.Telepathy.Error.NotImplemented">
+ <tp:docstring>
+ The server or connection manager doesn't implement the given
+ SASL mechanism. Choose a SASL mechanism from
+ <tp:member-ref>AvailableMechanisms</tp:member-ref>, or abort
+ authentication if none of them are suitable.
+ </tp:docstring>
+ </tp:error>
+ </tp:possible-errors>
+ </method>
+
+ <method name="StartMechanismWithData"
+ tp:name-for-bindings="Start_Mechanism_With_Data">
+ <arg direction="in" name="Mechanism" type="s" tp:type="SASL_Mechanism">
+ <tp:docstring>
+ The chosen mechanism.
+ </tp:docstring>
+ </arg>
+ <arg direction="in" name="Initial_Data" type="ay">
+ <tp:docstring>
+ Initial data (an "initial response" in RFC 4422's terminology) to send
+ with the mechanism.
+ </tp:docstring>
+ </arg>
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>Start an authentication try using <var>Mechanism</var>, and send
+ <var>Initial_Data</var> as the "initial response" defined in
+ <a href="http://tools.ietf.org/html/rfc4422#section-3.3">RFC 4422
+ §3.3</a>.</p>
+
+ <p>If the underlying protocol does not make it possible to send
+ initial data, this method will fail.</p>
+
+ <tp:rationale>
+ <p>This method is appropriate for mechanisms where the client may
+ send data first, such as <code>PLAIN</code>.</p>
+
+ <p>Having two methods allows any mechanism where it makes a difference
+ to distinguish between the absence of an initial response
+ (<tp:member-ref>StartMechanism</tp:member-ref>) and a zero-byte
+ initial response (StartMechanismWithData, with Initial_Data
+ empty).</p>
+ </tp:rationale>
+ </tp:docstring>
+
+ <tp:possible-errors>
+ <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable">
+ <tp:docstring>
+ The channel is not in a state where starting authentication makes
+ sense (i.e. SASL_Status_Not_Started, or (if
+ <tp:member-ref>CanTryAgain</tp:member-ref> is true)
+ SASL_Status_Server_Failed or
+ SASL_Status_Client_Failed). You should call
+ <tp:member-ref>AbortSASL</tp:member-ref> and wait for
+ SASL_Status_Client_Failed before starting another attempt.
+ </tp:docstring>
+ </tp:error>
+ <tp:error name="org.freedesktop.Telepathy.Error.NetworkError"/>
+ <tp:error name="org.freedesktop.Telepathy.Error.NotImplemented">
+ <tp:docstring>
+ The server or connection manager doesn't implement the given
+ SASL mechanism (choose one from
+ <tp:member-ref>AvailableMechanisms</tp:member-ref>, or abort
+ authentication if none of them are suitable), or doesn't allow
+ initial data to be sent (as indicated by
+ <tp:member-ref>HasInitialData</tp:member-ref>; call
+ <tp:member-ref>StartMechanism</tp:member-ref> instead).
+ </tp:docstring>
+ </tp:error>
+ </tp:possible-errors>
+ </method>
+
+ <method name="Respond" tp:name-for-bindings="Respond">
+ <arg direction="in" name="Response_Data" type="ay">
+ <tp:docstring>
+ The response data.
+ </tp:docstring>
+ </arg>
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>Send a response to the the last challenge received via
+ <tp:member-ref>NewChallenge</tp:member-ref>.</p>
+ </tp:docstring>
+
+ <tp:possible-errors>
+ <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable">
+ <tp:docstring>
+ Either the state is not In_Progress, or no challenge has been
+ received yet, or you have already responded to the last challenge.
+ </tp:docstring>
+ </tp:error>
+ <tp:error name="org.freedesktop.Telepathy.Error.NetworkError"/>
+ </tp:possible-errors>
+ </method>
+
+ <method name="AcceptSASL" tp:name-for-bindings="Accept_SASL">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>If the channel's status is SASL_Status_Server_Succeeded,
+ this method confirms successful authentication and advances
+ the status of the channel to SASL_Status_Succeeded.</p>
+
+ <p>If the channel's status is SASL_Status_In_Progress, calling this
+ method indicates that the last
+ <tp:member-ref>NewChallenge</tp:member-ref> signal was in fact
+ additional data sent after a successful SASL negotiation, and
+ declares that from the client's point of view, authentication
+ was successful. This advances the state of the channel to
+ SASL_Status_Client_Accepted.</p>
+
+ <p>In mechanisms where the server authenticates itself to the client,
+ calling this method indicates that the client considers this to have
+ been successful. In the case of <tp:dbus-ref
+ namespace="ofdT.Channel.Type">ServerAuthentication.DRAFT2</tp:dbus-ref>
+ channels, this means that the connection manager MAY continue to
+ connect, and MAY advance the <tp:dbus-ref
+ namespace="ofdT">Connection.Status</tp:dbus-ref> to Connected.</p>
+ </tp:docstring>
+
+ <tp:possible-errors>
+ <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable">
+ <tp:docstring>
+ Either the state is neither In_Progress nor Server_Succeeded, or no
+ challenge has been received yet, or you have already responded to
+ the last challenge.
+ </tp:docstring>
+ </tp:error>
+ <tp:error name="org.freedesktop.Telepathy.Error.NetworkError"/>
+ </tp:possible-errors>
+ </method>
+
+ <method name="AbortSASL" tp:name-for-bindings="Abort_SASL">
+ <arg direction="in" name="Reason" type="u" tp:type="SASL_Abort_Reason">
+ <tp:docstring>
+ Reason for abort.
+ </tp:docstring>
+ </arg>
+ <arg direction="in" name="Debug_Message" type="s">
+ <tp:docstring>
+ Debug message for abort.
+ </tp:docstring>
+ </arg>
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>Abort the current authentication try.</p>
+
+ <p>If the current status is SASL_Status_Server_Failed or
+ SASL_Status_Client_Failed, this method returns successfully, but has
+ no further effect. Otherwise, it changes the channel's state to
+ SASL_Status_Client_Failed, with an appropriate error name and
+ reason code.</p>
+ </tp:docstring>
+ </method>
+
+ <signal name="SASLStatusChanged" tp:name-for-bindings="SASL_Status_Changed">
+ <tp:docstring>
+ Emitted when the status of the channel changes.
+ </tp:docstring>
+ <arg type="u" tp:type="SASL_Status" name="Status">
+ <tp:docstring>
+ The new value of <tp:member-ref>SASLStatus</tp:member-ref>.
+ </tp:docstring>
+ </arg>
+ <arg type="s" tp:type="DBus_Error_Name" name="Reason">
+ <tp:docstring>
+ The new value of <tp:member-ref>SASLError</tp:member-ref>.
+ </tp:docstring>
+ </arg>
+ <arg type="a{sv}" tp:type="String_Variant_Map" name="Details">
+ <tp:docstring>
+ The new value of <tp:member-ref>SASLErrorDetails</tp:member-ref>.
+ </tp:docstring>
+ </arg>
+ </signal>
+
+ <signal name="NewChallenge" tp:name-for-bindings="New_Challenge">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>Emitted when a new challenge is received from the server, or when
+ a message indicating successful authentication and containing
+ additional data is received from the server.</p>
+
+ <p>When the channel's handler is ready to proceed, it should respond
+ to the challenge by calling <tp:member-ref>Respond</tp:member-ref>,
+ or respond to the additional data by calling
+ <tp:member-ref>AcceptSASL</tp:member-ref>. Alternatively, it may call
+ <tp:member-ref>AbortSASL</tp:member-ref> to abort authentication.</p>
+ </tp:docstring>
+ <arg name="Challenge_Data" type="ay">
+ <tp:docstring>
+ The challenge data or additional data from the server.
+ </tp:docstring>
+ </arg>
+ </signal>
+
+ <tp:enum name="SASL_Abort_Reason" type="u">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>A reason why SASL authentication was aborted by the client.</p>
+ </tp:docstring>
+
+ <tp:enumvalue suffix="Invalid_Challenge" value="0">
+ <tp:docstring>
+ The server sent an invalid challenge or data.
+ </tp:docstring>
+ </tp:enumvalue>
+ <tp:enumvalue suffix="User_Abort" value="1">
+ <tp:docstring>
+ The user aborted the authentication.
+ </tp:docstring>
+ </tp:enumvalue>
+ </tp:enum>
+
+ <tp:enum name="SASL_Status" type="u">
+ <tp:enumvalue suffix="Not_Started" value="0">
+ <tp:docstring>
+ The initial state. The Handler SHOULD either
+ call <tp:member-ref>AbortSASL</tp:member-ref>, or connect to the
+ <tp:member-ref>NewChallenge</tp:member-ref> signal then call
+ <tp:member-ref>StartMechanism</tp:member-ref> or
+ <tp:member-ref>StartMechanismWithData</tp:member-ref>.
+ </tp:docstring>
+ </tp:enumvalue>
+ <tp:enumvalue suffix="In_Progress" value="1">
+ <tp:docstring>
+ The challenge/response exchange is in progress. The Handler SHOULD
+ call either <tp:member-ref>Respond</tp:member-ref> or
+ <tp:member-ref>AcceptSASL</tp:member-ref> exactly once per emission
+ of <tp:member-ref>NewChallenge</tp:member-ref>, or call
+ <tp:member-ref>AbortSASL</tp:member-ref> at any time.
+ </tp:docstring>
+ </tp:enumvalue>
+ <tp:enumvalue suffix="Server_Succeeded" value="2">
+ <tp:docstring>
+ The server has indicated successful authentication, and the
+ connection manager is waiting for confirmation from the Handler.
+ The Handler must call either <tp:member-ref>AcceptSASL</tp:member-ref> or
+ <tp:member-ref>AbortSASL</tp:member-ref> to indicate whether it
+ considers authentication to have been successful.
+ </tp:docstring>
+ </tp:enumvalue>
+ <tp:enumvalue suffix="Client_Accepted" value="3">
+ <tp:docstring>
+ The Handler has indicated successful authentication, and the
+ connection manager is waiting for confirmation from the server.
+ The state will progress to either Succeeded or Server_Failed when
+ confirmation is received.
+ </tp:docstring>
+ </tp:enumvalue>
+ <tp:enumvalue suffix="Succeeded" value="4">
+ <tp:docstring>
+ Everyone is happy (the server sent success, and the client has called
+ <tp:member-ref>AcceptSASL</tp:member-ref>). Connection to the server
+ will proceed as soon as this state is reached. The Handler SHOULD
+ call <tp:dbus-ref
+ namespace="org.freedesktop.Telepathy.Channel">Close</tp:dbus-ref>
+ to close the channel.
+ </tp:docstring>
+ </tp:enumvalue>
+ <tp:enumvalue suffix="Server_Failed" value="5">
+ <tp:docstring>
+ The server has indicated an authentication failure.
+ If <tp:member-ref>CanTryAgain</tp:member-ref> is true,
+ the client may try to authenticate again, by calling
+ <tp:member-ref>StartMechanism</tp:member-ref> or
+ <tp:member-ref>StartMechanismWithData</tp:member-ref> again.
+ Otherwise, it should give up completely, by calling <tp:dbus-ref
+ namespace="org.freedesktop.Telepathy.Channel">Close</tp:dbus-ref>
+ on the channel.
+ </tp:docstring>
+ </tp:enumvalue>
+ <tp:enumvalue suffix="Client_Failed" value="6">
+ <tp:docstring>
+ The client has indicated an authentication failure. The
+ possible actions are the same as for Server_Failed.
+ </tp:docstring>
+ </tp:enumvalue>
+ </tp:enum>
+
+ </interface>
+</node>
+<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/extensions/Channel_Interface_Sasl_Authentication.xml b/extensions/Channel_Interface_Sasl_Authentication.xml
deleted file mode 100644
index 6ae4e1da..00000000
--- a/extensions/Channel_Interface_Sasl_Authentication.xml
+++ /dev/null
@@ -1,231 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Channel_Interface_Sasl_Authentication"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <tp:copyright> Copyright © 2010 Collabora Limited </tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.</p>
-
-<p>This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.</p>
-
-<p>You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p>
- </tp:license>
- <interface name="org.freedesktop.Telepathy.Channel.Interface.SaslAuthentication.DRAFT" tp:causes-havoc="experimental">
- <tp:requires interface="org.freedesktop.Telepathy.Channel"/>
- <tp:requires interface="org.freedesktop.Telepathy.Channel.Type.Server.Authentication.DRAFT"/>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- A channel interface for SASL authentication.
- </tp:docstring>
-
-
- <property name="AvailableMechanisms"
- tp:name-for-bindings="Available_Mechanisms"
- type="as" access="read">
- <tp:docstring>
- Example: [ "PLAIN", "DIGEST-MD5", "SCRAM-SHA-1" ]
- The SASL mechanisms as offered by the server.
- </tp:docstring>
- </property>
-
- <property name="Secure"
- tp:name-for-bindings="Secure" type="b" access="read">
- <tp:docstring>
- Is this exchange secure (ie. TLS)? Good to know if you need to take
- a calculated risk with plaintext.
- </tp:docstring>
- </property>
-
- <property name="CurrentChallenge" tp:name-for-bindings="Current_Challenge"
- type="ay" access="read">
- <tp:docstring>
- The current challenge from the server. change notification via
- <tp:member-ref>NewChallenge</tp:member-ref>. The handler either needs
- to respond by calling <tp:member-ref>Respond</tp:member-ref>
- (if it needs to send reply data), <tp:member-ref>Accept</tp:member-ref>
- (If the challenge contained final data) or
- <tp:member-ref>Abort</tp:member-ref> (in case of errors).
- </tp:docstring>
- </property>
-
- <property name="CurrentState" tp:name-for-bindings="Current_State"
- type="(uss)" tp:type="Sasl_State" access="read">
- <tp:docstring>
- The current state of the authentication.
- Change notification via <tp:member-ref>StateChanged</tp:member-ref>
- signal.
- </tp:docstring>
- </property>
-
- <method name="StartMechanism" tp:name-for-bindings="Start_Mechanism">
- <arg direction="in" name="Mechanism" type="s">
- <tp:docstring>
- The chosen mechanism.
- </tp:docstring>
- </arg>
- <arg direction="in" name="InitialData" type="ay">
- <tp:docstring>
- Initial data to send with the mechanism.
- </tp:docstring>
- </arg>
- <tp:docstring>
- Start an authentication try using Mechanism. If the choosen SASL
- mechanism is client-first then the first data must be passed in
- InitialData, otherwise InitialData must be an empty array.
- </tp:docstring>
- </method>
-
- <method name="Respond" tp:name-for-bindings="Respond">
- <arg direction="in" name="Response_Data" type="ay">
- <tp:docstring>
- The response data.
- </tp:docstring>
- </arg>
- <tp:docstring>
- Our response to the CurrentChallenge if required.
- </tp:docstring>
- </method>
-
- <method name="Accept" tp:name-for-bindings="Accept">
- <tp:docstring>
- Handler accepts the authentication as finished. Can be called
- whenever the Handler considered the authentication process to
- be (successfully) finished from its part.
- </tp:docstring>
- </method>
-
- <method name="Abort" tp:name-for-bindings="Abort">
- <arg direction="in" name="Reason" type="u" tp:type="Abort_Reason">
- <tp:docstring>
- Reason for abort.
- </tp:docstring>
- </arg>
- <arg direction="in" name="Debug_Message" type="s">
- <tp:docstring>
- Debug message for abort.
- </tp:docstring>
- </arg>
- <tp:docstring>
- Abort the current authentication try.
- </tp:docstring>
- </method>
-
- <signal name="StateChanged" tp:name-for-bindings="State_Changed">
- <tp:docstring>
- Notifies of <tp:member-ref>CurrentState</tp:member-ref> changing
- </tp:docstring>
- <arg type="u" tp:type="Sasl_Status" name="Status">
- <tp:docstring>
- The status of the state.
- </tp:docstring>
- </arg>
- <arg type="s" tp:type="DBus_Error_Name" name="Reason">
- <tp:docstring>
- The reason for the state.
- </tp:docstring>
- </arg>
- <arg type="s" name="DebugMessage">
- <tp:docstring>
- A non-localized debug message.
- </tp:docstring>
- </arg>
- </signal>
-
- <signal name="NewChallenge" tp:name-for-bindings="New_Challenge">
- <tp:docstring>
- Recieved a new challenge from the server.
- </tp:docstring>
- <arg name="ChallengeData" type="ay">
- <tp:docstring>
- The challenge data from the server.
- </tp:docstring>
- </arg>
- </signal>
-
- <tp:enum name="Abort_Reason" type="u">
- <tp:enumvalue suffix="Invalid_Challenge" value="0">
- <tp:docstring>
- Server sent an invalid challenge or data.
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="User_Abort" value="1">
- <tp:docstring>
- User aborted the authentication.
- </tp:docstring>
- </tp:enumvalue>
- </tp:enum>
-
- <tp:enum name="Sasl_Status" type="u">
- <tp:enumvalue suffix="Not_Started" value="0">
- <tp:docstring>
- Need to call <tp:member-ref>StartMechanism</tp:member-ref> to start.
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="In_Progress" value="1">
- <tp:docstring>
- Challenge/Response cycle in progress
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Server_Succeeded" value="2">
- <tp:docstring>
- Server indicated successful authentication, handler needs to
- Accept or Abort.
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Client_Accepted" value="3">
- <tp:docstring>
- Handler indicates that from its perspective the
- authentication has successfully finished.
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Succeeded" value="4">
- <tp:docstring>
- Everyone is happy (server sent success, client sent Accept), up to the handler to close the channel.
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Server_Failed" value="5">
- <tp:docstring>
- Server indicated an authentication failure,
- Authentication can be restarted by calling
- StartMechanism again or completely aborted by Closing
- the channel.
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Client_Failed" value="6">
- <tp:docstring>
- Client indicated an authentication failure,
- Authentication can be restarted by calling
- StartMechanism again or completely aborted by Closing
- the channel.
- </tp:docstring>
- </tp:enumvalue>
- </tp:enum>
-
- <tp:struct name="Sasl_State">
- <tp:member type="u" tp:type="Sasl_Status" name="Status">
- <tp:docstring>
- The status of the state.
- </tp:docstring>
- </tp:member>
-
- <tp:member type="s" tp:type="DBus_Error_Name" name="Reason">
- <tp:docstring>
- The reason for the state.
- </tp:docstring>
- </tp:member>
-
- <tp:member type="s" name="DebugMessage">
- <tp:docstring>
- A non-localized debug message.
- </tp:docstring>
- </tp:member>
- </tp:struct>
- </interface>
-</node>
-<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/extensions/Channel_Type_Server_Authentication.xml b/extensions/Channel_Type_Server_Authentication.xml
index bc9ca150..ae5fd061 100644
--- a/extensions/Channel_Type_Server_Authentication.xml
+++ b/extensions/Channel_Type_Server_Authentication.xml
@@ -16,77 +16,96 @@ Lesser General Public License for more details.</p>
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p>
</tp:license>
- <interface name="org.freedesktop.Telepathy.Channel.Type.ServerAuthentication.DRAFT" tp:causes-havoc="experimental">
+ <interface name="org.freedesktop.Telepathy.Channel.Type.ServerAuthentication.DRAFT2"
+ tp:causes-havoc="experimental">
+ <tp:added version="0.21.UNRELEASED">(draft 2)</tp:added>
<tp:requires interface="org.freedesktop.Telepathy.Channel"/>
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- An interface for SASL authentication.
- </tp:docstring>
+ <p>The type for a channel representing an authentication step with the
+ server. The actual authentication functionality is implemented by
+ the additional interface named in
+ <tp:member-ref>AuthenticationMethod</tp:member-ref>,
+ such as <tp:dbus-ref namespace="ofdT"
+ >Channel.Interface.SASLAuthentication.DRAFT2</tp:dbus-ref>.</p>
- <property name="AuthenticationInformation"
- tp:name-for-bindings="Authentication_Information"
- type="a{sv}" access="read">
- <tp:docstring>
- Dictionary of information given by the CM which can be used by the
- handler for authentication.
- </tp:docstring>
- </property>
+ <p>Future authentication steps also supported by this channel type might
+ include solving a captcha and/or agreeing to an EULA or terms-of-use
+ document; each of these would be represented by a channel with this
+ type, but a different
+ <tp:member-ref>AuthenticationMethod</tp:member-ref>.</p>
- <property name="AuthenticationMethod"
- tp:name-for-bindings="Authentication_Method"
- type="u" tp:type="Authentication_Type" access="read">
- <tp:docstring>
- This property defines the Method used for the current
- authentication step. The method also defines which Interfaces
- the channel implements. For exmaple if for the SASL method the
- SaslAuthentication interface needs to be implemented.
- </tp:docstring>
- </property>
+ <p>Channels of this type SHOULD be signalled and dispatched while the
+ <tp:dbus-ref namespace="ofdT">Connection</tp:dbus-ref> owning them is in
+ the CONNECTING state. Normally, only one channel of this type will
+ exist on a given Connection; if there is more than one, the handler
+ must complete authentication with each of them in turn.</p>
- <tp:enum name="Authentication_Type" type="u">
- <tp:enumvalue suffix="Sasl" value="0">
- <tp:docstring>
- SASL authentication.
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Captcha" value="1">
- <tp:docstring>
- Captcha authentication.
- </tp:docstring>
- </tp:enumvalue>
- </tp:enum>
+ <p>Channels of this type cannot be requested with methods such as
+ <tp:dbus-ref
+ namespace="ofdT.Connection.Interface.Requests">CreateChannel</tp:dbus-ref>.
+ They always have <tp:dbus-ref
+ namespace="ofdT.Channel">Requested</tp:dbus-ref> = False,
+ <tp:dbus-ref
+ namespace="ofdT.Channel">TargetHandleType</tp:dbus-ref> = None
+ and <tp:dbus-ref
+ namespace="org.freedesktop.Telepathy.Channel">TargetHandle</tp:dbus-ref>
+ = 0.</p>
- <tp:mapping name="AuthDetails" array-name="AuthDetails_List">
- <tp:docstring>
- An extensible map representing details provided by the server for
- authentication.
- </tp:docstring>
+ <p>The Connection MUST NOT proceed with connection, or signal
+ <tp:dbus-ref namespace="ofdT.Connection">StatusChanged</tp:dbus-ref>
+ to the CONNECTED state, until each channel of this type has either
+ been accepted as having a positive result (for instance, on SASL
+ channels this is done with the <tp:dbus-ref
+ namespace="ofdT.Channel.Interface.SASLAuthentication.DRAFT2"
+ >AcceptSASL</tp:dbus-ref> method), or closed with the <tp:dbus-ref
+ namespace="ofdT.Channel">Close</tp:dbus-ref> method.</p>
+
+ <tp:rationale>
+ <p>ServerAuthentication channels normally represent the client
+ authenticating itself to the server, but can also be used for the
+ server to authenticate itself to the client (i.e. prove that it is
+ in fact the desired server and not an imposter). Until the
+ authentication handler has confirmed this, connection should not
+ continue.</p>
+ </tp:rationale>
- <tp:member type="s" name="Key">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>
- Well-known keys:
- <dl>
- <dt>username</dt>
- <dd>
- string, Username to authenticate with if needed
- </dd>
- <dt>realm</dt>
- <dd>
- string, Realm to use for authentication if needed
- </dd>
- <dt>session-id</dt>
- <dd>
- XMPP session id as needed for the legacy jabber digest method.
- </dd>
- </dl>
- </p>
- </tp:docstring>
- </tp:member>
+ <p>If a channel of this type is closed with the <tp:dbus-ref
+ namespace="ofdT.Channel">Close</tp:dbus-ref> method before
+ authentication has succeeded, this indicates that the Handler has
+ given up its attempts to authenticate or that no Handler is
+ available.</p>
- <tp:member name="Value" type="v">
- </tp:member>
- </tp:mapping>
+ <p>If this occurs, the connection manager MAY attempt to continue
+ connection (for instance, performing SASL authentication by using any
+ credentials passed to <tp:dbus-ref
+ namespace="ofdT.ConnectionManager">RequestConnection</tp:dbus-ref>,
+ for instance from the <tp:dbus-ref
+ namespace="ofdT">Account.Parameters</tp:dbus-ref>). If this fails
+ or has already been tried, the <tp:dbus-ref
+ namespace="ofdT">Connection</tp:dbus-ref> will
+ disconnect.</p>
+
+ <tp:rationale>
+ <p>In particular, the <tp:dbus-ref
+ namespace="ofdT">ChannelDispatcher</tp:dbus-ref> will close the
+ channel if it cannot find a handler.</p>
+ </tp:rationale>
+ </tp:docstring>
+
+ <property name="AuthenticationMethod"
+ tp:name-for-bindings="Authentication_Method"
+ type="s" tp:type="DBus_Interface" access="read">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>This property defines the method used for the authentication step
+ represented by this channel, which MUST be one of this channel's
+ <tp:dbus-ref namespace="ofdT.Channel">Interfaces</tp:dbus-ref>.</p>
+
+ <p>The initially-defined interface that can be used here is
+ <tp:dbus-ref namespace="ofdT"
+ >Channel.Interface.SASLAuthentication.DRAFT2</tp:dbus-ref>.</p>
+ </tp:docstring>
+ </property>
</interface>
</node>
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index e00442db..f217b668 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -17,7 +17,7 @@ EXTRA_DIST = \
Gabble_Plugin_Test.xml \
OLPC_Activity_Properties.xml \
OLPC_Buddy_Info.xml \
- Channel_Interface_Sasl_Authentication.xml \
+ Channel_Interface_SASL_Authentication.xml \
Channel_Type_Server_Authentication.xml
noinst_LTLIBRARIES = libgabble-extensions.la
diff --git a/extensions/all.xml b/extensions/all.xml
index 680ba7b3..00d3f02c 100644
--- a/extensions/all.xml
+++ b/extensions/all.xml
@@ -53,7 +53,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA</p>
<xi:include href="Channel_Type_Call.xml" />
<xi:include href="Channel_Type_Server_Authentication.xml" />
-<xi:include href="Channel_Interface_Sasl_Authentication.xml" />
+<xi:include href="Channel_Interface_SASL_Authentication.xml" />
<tp:generic-types>
<tp:external-type name="Contact_Handle" type="u"
diff --git a/src/server-sasl-channel.c b/src/server-sasl-channel.c
index 5a73c53b..e808826a 100644
--- a/src/server-sasl-channel.c
+++ b/src/server-sasl-channel.c
@@ -145,15 +145,19 @@ enum
PROP_CHANNEL_PROPERTIES,
/* server authentication channel */
- PROP_AUTH_INFO,
PROP_AUTH_METHOD,
/* sasl authentication channel */
- PROP_CURRENT_STATE,
- PROP_MECHANISM,
- PROP_CHALLENGE,
PROP_AVAILABLE_MECHANISMS,
+ PROP_HAS_INITIAL_DATA,
+ PROP_CAN_TRY_AGAIN,
PROP_SECURE,
+ PROP_SASL_STATUS,
+ PROP_SASL_ERROR,
+ PROP_SASL_ERROR_DETAILS,
+ PROP_AUTHORIZATION_IDENTITY,
+ PROP_DEFAULT_REALM,
+ PROP_SASL_CONTEXT,
LAST_PROPERTY,
};
@@ -169,15 +173,17 @@ struct _GabbleServerSaslChannelPrivate
GabbleConnection *conn;
gboolean closed;
- /* Server Authentication Iface*/
- GHashTable *auth_info;
-
- /* SASL Auth Iface */
+ /* Immutable SASL properties */
+ gchar *authorization_identity;
+ gchar *default_realm;
GPtrArray *available_mechanisms;
- GValueArray *current_state;
- GArray *challenge;
- gchar *mechanism;
gboolean secure;
+ GHashTable *sasl_context;
+
+ /* Mutable SASL properties */
+ GabbleSASLStatus sasl_status;
+ gchar *sasl_error;
+ GHashTable *sasl_error_details;
GSimpleAsyncResult *result;
};
@@ -185,39 +191,20 @@ struct _GabbleServerSaslChannelPrivate
static void
gabble_server_sasl_channel_init (GabbleServerSaslChannel *self)
{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ GabbleServerSaslChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
GABBLE_TYPE_SERVER_SASL_CHANNEL, GabbleServerSaslChannelPrivate);
-}
-
-static GObject *
-gabble_server_sasl_channel_constructor (GType type,
- guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- GabbleServerSaslChannel *self;
- GabbleServerSaslChannelPrivate *priv;
-
- obj = G_OBJECT_CLASS (gabble_server_sasl_channel_parent_class)->
- constructor (type, n_props, props);
- self = GABBLE_SERVER_SASL_CHANNEL (obj);
- priv = self->priv;
+ self->priv = priv;
priv->closed = TRUE;
- priv->challenge = g_array_new (FALSE, FALSE, sizeof (gchar));
-
priv->available_mechanisms = g_ptr_array_new_with_free_func (
(GDestroyNotify) g_free);
+ priv->sasl_context = tp_asv_new (NULL, NULL);
- priv->current_state = tp_value_array_build (3,
- G_TYPE_UINT, GABBLE_SASL_STATUS_NOT_STARTED,
- G_TYPE_STRING, "",
- G_TYPE_STRING, "",
- G_TYPE_INVALID);
-
- return obj;
+ priv->sasl_status = GABBLE_SASL_STATUS_NOT_STARTED;
+ priv->sasl_error = NULL;
+ priv->sasl_error_details = tp_asv_new (NULL, NULL);
}
static void
@@ -278,26 +265,40 @@ gabble_server_sasl_channel_get_property (GObject *object,
TP_IFACE_CHANNEL, "Requested",
TP_IFACE_CHANNEL, "Interfaces",
GABBLE_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION,
- "AuthenticationInformation",
- GABBLE_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION,
- "AuthenticationMethod",
+ "AuthenticationMethod",
+ GABBLE_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
+ "AvailableMechanisms",
+ GABBLE_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
+ "HasInitialData",
GABBLE_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
- "AvailableMechanisms",
+ "CanTryAgain",
GABBLE_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
- "Secure",
+ "Encrypted",
+ GABBLE_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
+ "Verified",
+ GABBLE_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
+ "AuthorizationIdentity",
+ GABBLE_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
+ "DefaultRealm",
+ GABBLE_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
+ "SASLContext",
NULL));
break;
- case PROP_CURRENT_STATE:
- g_value_set_boxed (value, priv->current_state);
+ case PROP_SASL_STATUS:
+ g_value_set_uint (value, priv->sasl_status);
break;
- case PROP_AUTH_INFO:
- g_value_set_boxed (value, priv->auth_info);
+ case PROP_SASL_ERROR:
+ g_value_set_string (value, priv->sasl_error);
break;
- case PROP_AUTH_METHOD:
- g_value_set_uint (value, GABBLE_AUTHENTICATION_TYPE_SASL);
+ case PROP_SASL_ERROR_DETAILS:
+ g_value_set_boxed (value, priv->sasl_error_details);
break;
- case PROP_MECHANISM:
- g_value_set_string (value, priv->mechanism);
+ case PROP_SASL_CONTEXT:
+ g_value_set_boxed (value, priv->sasl_context);
+ break;
+ case PROP_AUTH_METHOD:
+ g_value_set_static_string (value,
+ GABBLE_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION);
break;
case PROP_AVAILABLE_MECHANISMS:
g_value_set_boxed (value,
@@ -306,8 +307,19 @@ gabble_server_sasl_channel_get_property (GObject *object,
case PROP_SECURE:
g_value_set_boolean (value, chan->priv->secure);
break;
- case PROP_CHALLENGE:
- g_value_set_boxed (value, chan->priv->challenge);
+ case PROP_CAN_TRY_AGAIN:
+ /* Wocky can't retry SASL authentication (although XMPP can) */
+ g_value_set_boolean (value, FALSE);
+ break;
+ case PROP_HAS_INITIAL_DATA:
+ /* Yes, XMPP has "initial data" in its SASL */
+ g_value_set_boolean (value, TRUE);
+ break;
+ case PROP_AUTHORIZATION_IDENTITY:
+ g_value_set_string (value, priv->authorization_identity);
+ break;
+ case PROP_DEFAULT_REALM:
+ g_value_set_string (value, priv->default_realm);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -355,18 +367,18 @@ gabble_server_sasl_channel_dispose (GObject *object)
priv->dispose_has_run = TRUE;
gabble_server_sasl_channel_close (self);
+ g_assert (priv->result == NULL);
- g_free (priv->mechanism);
-
+ /* FIXME: from here down should really be in finalize since no object refs
+ * are involved */
g_free (priv->object_path);
+ g_free (priv->authorization_identity);
+ g_free (priv->default_realm);
+ g_ptr_array_unref (priv->available_mechanisms);
+ g_hash_table_unref (priv->sasl_context);
- g_ptr_array_free (priv->available_mechanisms, TRUE);
-
- g_value_array_free (priv->current_state);
-
- g_array_free (priv->challenge, TRUE);
-
- tp_clear_pointer (&priv->auth_info, g_hash_table_unref);
+ g_free (priv->sasl_error);
+ g_hash_table_unref (priv->sasl_error_details);
if (G_OBJECT_CLASS (gabble_server_sasl_channel_parent_class)->dispose)
G_OBJECT_CLASS (gabble_server_sasl_channel_parent_class)->dispose (object);
@@ -388,16 +400,24 @@ gabble_server_sasl_channel_class_init (GabbleServerSaslChannelClass *klass)
};
static TpDBusPropertiesMixinPropImpl server_auth_props[] = {
- { "AuthenticationInformation", "auth-info", NULL },
{ "AuthenticationMethod", "auth-method", NULL },
{ NULL }
};
static TpDBusPropertiesMixinPropImpl sasl_auth_props[] = {
- { "CurrentState", "current-state", NULL },
{ "AvailableMechanisms", "available-mechanisms", NULL },
- { "Secure", "secure", NULL },
- { "CurrentChallenge", "challenge", NULL },
+ { "HasInitialData", "has-initial-data", NULL },
+ { "CanTryAgain", "can-try-again", NULL },
+ { "SASLStatus", "sasl-status", NULL },
+ { "SASLError", "sasl-error", NULL },
+ { "SASLErrorDetails", "sasl-error-details", NULL },
+ { "AuthorizationIdentity", "authorization-identity", NULL },
+ { "DefaultRealm", "default-realm", NULL },
+ { "SASLContext", "sasl-context", NULL },
+ /* For the moment we only have a unified "secure" property, which
+ * implies we're both encrypted and verified */
+ { "Encrypted", "secure", NULL },
+ { "Verified", "secure", NULL },
{ NULL }
};
@@ -427,7 +447,6 @@ gabble_server_sasl_channel_class_init (GabbleServerSaslChannelClass *klass)
g_type_class_add_private (klass, sizeof (GabbleServerSaslChannelPrivate));
- object_class->constructor = gabble_server_sasl_channel_constructor;
object_class->get_property = gabble_server_sasl_channel_get_property;
object_class->set_property = gabble_server_sasl_channel_set_property;
object_class->dispose = gabble_server_sasl_channel_dispose;
@@ -501,34 +520,55 @@ gabble_server_sasl_channel_class_init (GabbleServerSaslChannelClass *klass)
g_object_class_install_property (object_class, PROP_INITIATOR_ID,
param_spec);
- param_spec = g_param_spec_boxed ("auth-info",
- "Authentication information",
- "Details used for authentication purposes.",
- GABBLE_HASH_TYPE_AUTHDETAILS,
+ param_spec = g_param_spec_boxed ("sasl-context", "SASLContext",
+ "Extra context for doing SASL",
+ TP_HASH_TYPE_STRING_VARIANT_MAP,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_AUTH_INFO,
+ g_object_class_install_property (object_class, PROP_SASL_CONTEXT,
param_spec);
- param_spec = g_param_spec_uint ("auth-method",
+ param_spec = g_param_spec_string ("auth-method",
"Authentication method",
- "Method of authentication like SASL or Captcha.",
- 0, NUM_GABBLE_AUTHENTICATION_TYPES, GABBLE_AUTHENTICATION_TYPE_SASL,
+ "Method of authentication (D-Bus interface)",
+ GABBLE_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_AUTH_METHOD,
param_spec);
- param_spec = g_param_spec_boxed ("current-state",
- "Current state",
- "The state of the current SASL authentication.",
- GABBLE_STRUCT_TYPE_SASL_STATE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CURRENT_STATE, param_spec);
+ param_spec = g_param_spec_string ("authorization-identity",
+ "AuthorizationIdentity",
+ "Identity for which we wish to be authorized",
+ NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_AUTHORIZATION_IDENTITY,
+ param_spec);
+
+ param_spec = g_param_spec_string ("default-realm",
+ "DefaultRealm",
+ "Default realm if the server does not supply one",
+ NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_DEFAULT_REALM,
+ param_spec);
- param_spec = g_param_spec_string ("mechanism", "Mechanism",
- "Mechanism used for this negotiation.",
- NULL,
+ param_spec = g_param_spec_uint ("sasl-status", "SASLStatus",
+ "Status of this channel",
+ /* FIXME: fix the pluralization in the spec */
+ 0, NUM_GABBLE_SASL_STATUSS, 0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_MECHANISM, param_spec);
+ g_object_class_install_property (object_class, PROP_SASL_STATUS,
+ param_spec);
+
+ param_spec = g_param_spec_string ("sasl-error", "SASLError",
+ "D-Bus error name",
+ "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_SASL_ERROR,
+ param_spec);
+
+ param_spec = g_param_spec_boxed ("sasl-error-details", "SASLErrorDetails",
+ "Extra details of a SASL error",
+ TP_HASH_TYPE_STRING_VARIANT_MAP,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_SASL_ERROR_DETAILS,
+ param_spec);
param_spec = g_param_spec_boxed ("available-mechanisms",
"Available authentication mechanisms",
@@ -538,22 +578,26 @@ gabble_server_sasl_channel_class_init (GabbleServerSaslChannelClass *klass)
g_object_class_install_property (object_class, PROP_AVAILABLE_MECHANISMS,
param_spec);
+ param_spec = g_param_spec_boolean ("can-try-again", "CanTryAgain",
+ "True if failed SASL can be retried without reconnecting",
+ FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CAN_TRY_AGAIN,
+ param_spec);
+
+ param_spec = g_param_spec_boolean ("has-initial-data", "HasInitialData",
+ "True if SASL has initial data",
+ TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_HAS_INITIAL_DATA,
+ param_spec);
+
param_spec = g_param_spec_boolean ("secure",
"Is secure",
- "Is this channel secure (encrypted)?",
+ "Is this channel secure (encrypted and verified)?",
FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_SECURE,
param_spec);
- param_spec = g_param_spec_boxed ("challenge",
- "Challenge",
- "The latest challenge",
- DBUS_TYPE_G_UCHAR_ARRAY,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CHALLENGE,
- param_spec);
-
klass->dbus_props_class.interfaces = prop_interfaces;
tp_dbus_properties_mixin_class_init (object_class,
G_STRUCT_OFFSET (GabbleServerSaslChannelClass, dbus_props_class));
@@ -561,42 +605,24 @@ gabble_server_sasl_channel_class_init (GabbleServerSaslChannelClass *klass)
static void
change_current_state (GabbleServerSaslChannel *self,
- GabbleSaslStatus status,
+ GabbleSASLStatus status,
const gchar *dbus_error,
- const gchar *message)
+ const gchar *debug_message)
{
- GabbleServerSaslChannelPrivate *priv = self->priv;
- GValue *value;
- gboolean status_changed;
-
- value = g_value_array_get_nth (priv->current_state, 0);
- status_changed = (status != g_value_get_uint (value));
- g_value_set_uint (value, status);
-
- if (dbus_error != NULL)
- {
- value = g_value_array_get_nth (priv->current_state, 1);
- g_value_set_string (value, dbus_error);
- }
-
- if (message != NULL)
- {
- value = g_value_array_get_nth (priv->current_state, 2);
- g_value_set_string (value, message);
- }
+ self->priv->sasl_status = status;
- if (status_changed)
- {
- const gchar *current_message;
- const gchar *current_dbus_error;
- GabbleSaslStatus current_status;
+ g_free (self->priv->sasl_error);
+ self->priv->sasl_error = g_strdup (dbus_error);
- tp_value_array_unpack (priv->current_state, 3, &current_status,
- &current_dbus_error, &current_message);
+ g_hash_table_remove_all (self->priv->sasl_error_details);
+ if (debug_message != NULL)
+ tp_asv_set_string (self->priv->sasl_error_details, "debug-message",
+ debug_message);
- gabble_svc_channel_interface_sasl_authentication_emit_state_changed (
- self, current_status, current_dbus_error, current_message);
- }
+ gabble_svc_channel_interface_sasl_authentication_emit_sasl_status_changed (
+ self, self->priv->sasl_status,
+ self->priv->sasl_error,
+ self->priv->sasl_error_details);
}
/**
@@ -641,7 +667,7 @@ channel_iface_init (gpointer g_iface,
}
/**
- * Sasl Authentication Channel Interface
+ * SASL Authentication Channel Interface
*/
static void
@@ -656,19 +682,20 @@ gabble_server_sasl_channel_raise_not_available (DBusGMethodInvocation *context,
g_error_free (error);
}
+/* When called from start_mechanism, initial_data can be NULL. When called
+ * from D-Bus as StartMechanismWithData, it can't. */
static void
-gabble_server_sasl_channel_start_mechanism (
- GabbleSvcChannelInterfaceSaslAuthentication *mechanisms_chooser,
+gabble_server_sasl_channel_start_mechanism_with_data (
+ GabbleSvcChannelInterfaceSASLAuthentication *iface,
const gchar *in_Mechanism,
const GArray *in_InitialData,
DBusGMethodInvocation *context)
{
- GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (
- mechanisms_chooser);
+ GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (iface);
GabbleServerSaslChannelPrivate *priv = self->priv;
WockyAuthRegistryStartData *start_data;
GSimpleAsyncResult *r = priv->result;
- GString *initial_data;
+ GString *initial_data = NULL;
guint i;
gboolean mechanism_available = FALSE;
DEBUG ("");
@@ -697,8 +724,17 @@ gabble_server_sasl_channel_start_mechanism (
{
priv->result = NULL;
- initial_data = g_string_new_len (in_InitialData->data,
- in_InitialData->len);
+ if (in_InitialData != NULL)
+ {
+ initial_data = g_string_new_len (in_InitialData->data,
+ in_InitialData->len);
+ }
+ else if (g_str_has_prefix (in_Mechanism, "X-WOCKY-JABBER-"))
+ {
+ /* FIXME: wocky-jabber-auth asserts there is an initial response,
+ * and will crash otherwise */
+ initial_data = g_string_sized_new (0);
+ }
start_data =
wocky_auth_registry_start_data_new (in_Mechanism, initial_data);
@@ -720,8 +756,18 @@ gabble_server_sasl_channel_start_mechanism (
}
static void
+gabble_server_sasl_channel_start_mechanism (
+ GabbleSvcChannelInterfaceSASLAuthentication *iface,
+ const gchar *mech,
+ DBusGMethodInvocation *context)
+{
+ gabble_server_sasl_channel_start_mechanism_with_data (iface, mech, NULL,
+ context);
+}
+
+static void
gabble_server_sasl_channel_respond (
- GabbleSvcChannelInterfaceSaslAuthentication *channel,
+ GabbleSvcChannelInterfaceSASLAuthentication *channel,
const GArray *in_Response_Data,
DBusGMethodInvocation *context)
{
@@ -758,18 +804,16 @@ gabble_server_sasl_channel_respond (
}
static void
-gabble_server_sasl_channel_accept (
- GabbleSvcChannelInterfaceSaslAuthentication *channel,
+gabble_server_sasl_channel_accept_sasl (
+ GabbleSvcChannelInterfaceSASLAuthentication *channel,
DBusGMethodInvocation *context)
{
GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (channel);
- GabbleSaslStatus current_status = g_value_get_uint (g_value_array_get_nth (
- self->priv->current_state, 0));
GSimpleAsyncResult *r = self->priv->result;
const gchar *message = NULL;
- switch (current_status)
+ switch (self->priv->sasl_status)
{
case GABBLE_SASL_STATUS_NOT_STARTED:
message = "Authentication has not yet begun.";
@@ -815,64 +859,71 @@ gabble_server_sasl_channel_accept (
g_object_unref (r);
}
- gabble_svc_channel_interface_sasl_authentication_return_from_accept (
+ gabble_svc_channel_interface_sasl_authentication_return_from_accept_sasl (
context);
}
static void
-gabble_server_sasl_channel_abort (
- GabbleSvcChannelInterfaceSaslAuthentication *channel,
+gabble_server_sasl_channel_abort_sasl (
+ GabbleSvcChannelInterfaceSASLAuthentication *channel,
guint in_Reason,
const gchar *in_Debug_Message,
DBusGMethodInvocation *context)
{
GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (channel);
GSimpleAsyncResult *r = self->priv->result;
- GabbleSaslStatus current_status = g_value_get_uint (g_value_array_get_nth (
- self->priv->current_state, 0));
guint code;
const gchar *dbus_error;
- if (current_status == GABBLE_SASL_STATUS_SUCCEEDED ||
- current_status == GABBLE_SASL_STATUS_CLIENT_ACCEPTED)
- {
- gabble_server_sasl_channel_raise_not_available (context,
- "Authentication has already succeeded.");
-
- return;
- }
-
- switch (in_Reason)
+ switch (self->priv->sasl_status)
{
- case GABBLE_ABORT_REASON_INVALID_CHALLENGE:
- code = WOCKY_AUTH_ERROR_INVALID_REPLY;
- dbus_error = TP_ERROR_STR_AUTHENTICATION_FAILED;
+ case GABBLE_SASL_STATUS_SERVER_FAILED:
+ case GABBLE_SASL_STATUS_CLIENT_FAILED:
+ /* no effect */
break;
- case GABBLE_ABORT_REASON_USER_ABORT:
- code = WOCKY_AUTH_ERROR_FAILURE;
- dbus_error = TP_ERROR_STR_CANCELLED;
- break;
+ case GABBLE_SASL_STATUS_SUCCEEDED:
+ case GABBLE_SASL_STATUS_CLIENT_ACCEPTED:
+ gabble_server_sasl_channel_raise_not_available (context,
+ "Authentication has already succeeded.");
+ return;
default:
- g_assert_not_reached ();
+ switch (in_Reason)
+ {
+ case GABBLE_SASL_ABORT_REASON_INVALID_CHALLENGE:
+ code = WOCKY_AUTH_ERROR_INVALID_REPLY;
+ /* FIXME: should be ServiceConfused, when it lands in tp-glib */
+ dbus_error = TP_ERROR_STR_AUTHENTICATION_FAILED;
+ break;
+
+ case GABBLE_SASL_ABORT_REASON_USER_ABORT:
+ code = WOCKY_AUTH_ERROR_FAILURE;
+ dbus_error = TP_ERROR_STR_CANCELLED;
+ break;
+
+ default:
+ /* FIXME: should not abort on D-Bus input! */
+ g_assert_not_reached ();
+ }
+
+ if (r != NULL)
+ {
+ self->priv->result = NULL;
+
+ g_simple_async_result_set_error (r, WOCKY_AUTH_ERROR, code,
+ "Authentication aborted: %s", in_Debug_Message);
+
+ g_simple_async_result_complete_in_idle (r);
+ g_object_unref (r);
+ }
+
+ change_current_state (self, GABBLE_SASL_STATUS_CLIENT_FAILED,
+ dbus_error, in_Debug_Message);
}
- if (r != NULL)
- {
- self->priv->result = NULL;
-
- g_simple_async_result_set_error (r, WOCKY_AUTH_ERROR, code,
- "Authentication aborted: %s", in_Debug_Message);
-
- g_simple_async_result_complete_in_idle (r);
- g_object_unref (r);
- }
-
- change_current_state (self, GABBLE_SASL_STATUS_CLIENT_FAILED, dbus_error,
- in_Debug_Message);
-
- gabble_svc_channel_interface_sasl_authentication_return_from_abort (context);
+ gabble_svc_channel_interface_sasl_authentication_return_from_abort_sasl (
+ context);
}
static void
@@ -883,9 +934,10 @@ sasl_auth_iface_init (gpointer klass,
gabble_svc_channel_interface_sasl_authentication_implement_##x ( \
klass, gabble_server_sasl_channel_##x)
IMPLEMENT (start_mechanism);
+ IMPLEMENT (start_mechanism_with_data);
IMPLEMENT (respond);
- IMPLEMENT (accept);
- IMPLEMENT (abort);
+ IMPLEMENT (accept_sasl);
+ IMPLEMENT (abort_sasl);
#undef IMPLEMENT
}
@@ -922,14 +974,15 @@ gabble_server_sasl_channel_start_auth_async_func (
g_ptr_array_set_size (priv->available_mechanisms, 0);
- if (priv->auth_info != NULL)
- g_hash_table_unref (priv->auth_info);
+ g_free (priv->authorization_identity);
+ priv->authorization_identity = g_strdup (username);
- priv->auth_info = tp_asv_new (
- "username", G_TYPE_STRING, username,
- "realm", G_TYPE_STRING, server,
- "session-id", G_TYPE_STRING, session_id,
- NULL);
+ g_free (priv->default_realm);
+ priv->default_realm = g_strdup (server);
+
+ g_hash_table_remove_all (priv->sasl_context);
+ g_hash_table_insert (priv->sasl_context, "jabber-stream-id",
+ tp_g_value_slice_new_string (session_id));
priv->result = g_simple_async_result_new (G_OBJECT (self), callback,
user_data, gabble_server_sasl_channel_start_auth_async_func);
@@ -939,7 +992,7 @@ gabble_server_sasl_channel_start_auth_async_func (
g_ptr_array_add (priv->available_mechanisms, NULL);
- priv->object_path = g_strdup_printf ("%s/SaslChannel",
+ priv->object_path = g_strdup_printf ("%s/SASLChannel",
conn->object_path);
priv->secure = is_secure_channel;
@@ -993,23 +1046,22 @@ gabble_server_sasl_channel_challenge_async_func (
if (!priv->closed)
{
+ GArray *challenge_ay;
+
g_assert (priv->result == NULL);
priv->result = g_simple_async_result_new (G_OBJECT (self), callback,
user_data, gabble_server_sasl_channel_challenge_async_func);
- g_array_free (priv->challenge, TRUE);
-
- priv->challenge = g_array_sized_new (FALSE, FALSE, sizeof (gchar),
+ challenge_ay = g_array_sized_new (FALSE, FALSE, sizeof (gchar),
challenge_data->len);
-
- g_array_append_vals (priv->challenge, challenge_data->str,
+ g_array_append_vals (challenge_ay, challenge_data->str,
challenge_data->len);
change_current_state (self, GABBLE_SASL_STATUS_IN_PROGRESS, NULL, NULL);
gabble_svc_channel_interface_sasl_authentication_emit_new_challenge (
- self, priv->challenge);
+ self, challenge_ay);
}
else
{
@@ -1052,8 +1104,6 @@ gabble_server_sasl_channel_success_async_func (
if (!priv->closed)
{
- GabbleSaslStatus current_status = g_value_get_uint (
- g_value_array_get_nth (priv->current_state, 0));
GSimpleAsyncResult *r = g_simple_async_result_new (G_OBJECT (self),
callback, user_data,
gabble_server_sasl_channel_success_async_func);
@@ -1062,7 +1112,7 @@ gabble_server_sasl_channel_success_async_func (
g_assert (priv->result == NULL);
- if (current_status != GABBLE_SASL_STATUS_CLIENT_ACCEPTED)
+ if (self->priv->sasl_status != GABBLE_SASL_STATUS_CLIENT_ACCEPTED)
{
priv->result = r;
change_current_state (self, GABBLE_SASL_STATUS_SERVER_SUCCEEDED,
diff --git a/tests/twisted/constants.py b/tests/twisted/constants.py
index 1d2edf84..f799101c 100644
--- a/tests/twisted/constants.py
+++ b/tests/twisted/constants.py
@@ -24,7 +24,7 @@ CHANNEL_IFACE_MEDIA_SIGNALLING = CHANNEL + ".Interface.MediaSignalling"
CHANNEL_IFACE_MESSAGES = CHANNEL + ".Interface.Messages"
CHANNEL_IFACE_PASSWORD = CHANNEL + ".Interface.Password"
CHANNEL_IFACE_TUBE = CHANNEL + ".Interface.Tube"
-CHANNEL_IFACE_SASL_AUTH = CHANNEL + ".Interface.SaslAuthentication.DRAFT"
+CHANNEL_IFACE_SASL_AUTH = CHANNEL + ".Interface.SASLAuthentication.DRAFT2"
CHANNEL_IFACE_CONFERENCE = CHANNEL + '.Interface.Conference'
CHANNEL_TYPE_CALL = CHANNEL + ".Type.Call.DRAFT"
@@ -38,7 +38,7 @@ CHANNEL_TYPE_STREAMED_MEDIA = CHANNEL + ".Type.StreamedMedia"
CHANNEL_TYPE_TEXT = CHANNEL + ".Type.Text"
CHANNEL_TYPE_FILE_TRANSFER = CHANNEL + ".Type.FileTransfer"
CHANNEL_TYPE_SERVER_AUTHENTICATION = \
- CHANNEL + ".Type.ServerAuthentication.DRAFT"
+ CHANNEL + ".Type.ServerAuthentication.DRAFT2"
CHANNEL_TYPE_SERVER_TLS_CONNECTION = \
CHANNEL + ".Type.ServerTLSConnection"
@@ -350,10 +350,6 @@ CONTACT_INFO_FLAG_CAN_SET = 1
CONTACT_INFO_FLAG_PUSH = 2
CONTACT_INFO_FIELD_FLAG_PARAMETERS_MANDATORY = 1
-# Channel_Type_ServerAuthentication
-AUTH_TYPE_SASL = 0
-AUTH_TYPE_CAPTCHA = 1
-
# Channel_Interface_SaslAuthentication
SASL_STATUS_NOT_STARTED = 0
SASL_STATUS_IN_PROGRESS = 1
@@ -367,8 +363,13 @@ SASL_ABORT_REASON_INVALID_CHALLENGE = 0
SASL_ABORT_REASON_USER_ABORT = 1
AUTH_METHOD = CHANNEL_TYPE_SERVER_AUTHENTICATION + ".AuthenticationMethod"
-AUTH_INFO = CHANNEL_TYPE_SERVER_AUTHENTICATION + ".AuthenticationInformation"
SASL_AVAILABLE_MECHANISMS = CHANNEL_IFACE_SASL_AUTH + ".AvailableMechanisms"
+SASL_STATUS = CHANNEL_IFACE_SASL_AUTH + ".SASLStatus"
+SASL_ERROR = CHANNEL_IFACE_SASL_AUTH + ".SASLError"
+SASL_ERROR_DETAILS = CHANNEL_IFACE_SASL_AUTH + ".SASLErrorDetails"
+SASL_CONTEXT = CHANNEL_IFACE_SASL_AUTH + ".SASLContext"
+SASL_AUTHORIZATION_IDENTITY = CHANNEL_IFACE_SASL_AUTH + ".AuthorizationIdentity"
+SASL_DEFAULT_REALM = CHANNEL_IFACE_SASL_AUTH + ".DefaultRealm"
# Channel_Type_ServerTLSConnection
TLS_CERT_PATH = CHANNEL_TYPE_SERVER_TLS_CONNECTION + ".ServerCertificate"
diff --git a/tests/twisted/sasl/abort.py b/tests/twisted/sasl/abort.py
index 51c38c8e..0f1615af 100644
--- a/tests/twisted/sasl/abort.py
+++ b/tests/twisted/sasl/abort.py
@@ -21,25 +21,25 @@ def test_abort_early(q, bus, conn, stream):
pass
def test_abort_mid(q, bus, conn, stream):
- chan, auth_info, avail_mechs = connect_and_get_sasl_channel(q, bus, conn)
+ chan, props = connect_and_get_sasl_channel(q, bus, conn)
- chan.SaslAuthentication.StartMechanism("ABORT-TEST", EXCHANGE[0][1])
+ chan.SASLAuthentication.StartMechanismWithData("ABORT-TEST", EXCHANGE[0][1])
- q.expect('dbus-signal', signal='StateChanged',
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_IN_PROGRESS, '', ''])
+ args=[cs.SASL_STATUS_IN_PROGRESS, '', {}])
abort_auth(q, chan, cs.SASL_ABORT_REASON_INVALID_CHALLENGE,
"wrong data from server")
def test_disconnect_mid(q, bus, conn, stream):
- chan, auth_info, avail_mechs = connect_and_get_sasl_channel(q, bus, conn)
+ chan, props = connect_and_get_sasl_channel(q, bus, conn)
- chan.SaslAuthentication.StartMechanism("ABORT-TEST", EXCHANGE[0][1])
+ chan.SASLAuthentication.StartMechanismWithData("ABORT-TEST", EXCHANGE[0][1])
- q.expect('dbus-signal', signal='StateChanged',
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_IN_PROGRESS, '', ''])
+ args=[cs.SASL_STATUS_IN_PROGRESS, '', {}])
call_async(q, conn, 'Disconnect')
q.expect_many(EventPattern('dbus-signal', signal='StatusChanged',
@@ -48,26 +48,26 @@ def test_disconnect_mid(q, bus, conn, stream):
EventPattern('dbus-return', method='Disconnect'))
def test_abort_connected(q, bus, conn, stream):
- chan, auth_info, avail_mechs = connect_and_get_sasl_channel(q, bus, conn)
+ chan, props = connect_and_get_sasl_channel(q, bus, conn)
- chan.SaslAuthentication.StartMechanism(
+ chan.SASLAuthentication.StartMechanismWithData(
'PLAIN', '\0' + JID.split('@')[0] + '\0' + PASSWORD)
- q.expect('dbus-signal', signal='StateChanged',
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', ''])
+ args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}])
- chan.SaslAuthentication.Accept()
+ chan.SASLAuthentication.AcceptSASL()
- q.expect('dbus-signal', signal='StateChanged',
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_SUCCEEDED, '', ''])
+ args=[cs.SASL_STATUS_SUCCEEDED, '', {}])
e = q.expect('dbus-signal', signal='StatusChanged',
args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
try:
- chan.SaslAuthentication.Abort(cs.SASL_ABORT_REASON_USER_ABORT,
+ chan.SASLAuthentication.AbortSASL(cs.SASL_ABORT_REASON_USER_ABORT,
"aborting too late")
except dbus.DBusException:
pass
diff --git a/tests/twisted/sasl/complex.py b/tests/twisted/sasl/complex.py
index eea0f8b0..fe66f85f 100644
--- a/tests/twisted/sasl/complex.py
+++ b/tests/twisted/sasl/complex.py
@@ -3,7 +3,7 @@ Test the server sasl channel with the PLAIN mechanism
"""
import dbus
-from servicetest import EventPattern, assertEquals
+from servicetest import EventPattern, assertEquals, assertSameSets
from gabbletest import exec_test
import constants as cs
from saslutil import SaslComplexAuthenticator, connect_and_get_sasl_channel
@@ -17,12 +17,12 @@ EXCHANGE = [("", "Hi dear"),
MECHANISMS = ["PLAIN", "DIGEST-MD5", "POLITE-TEST"]
def test_complex_success(q, bus, conn, stream):
- chan, auth_info, avail_mechs = connect_and_get_sasl_channel(q, bus, conn)
+ chan, props = connect_and_get_sasl_channel(q, bus, conn)
- assertEquals(MECHANISMS, avail_mechs)
+ assertSameSets(MECHANISMS, props.get(cs.SASL_AVAILABLE_MECHANISMS))
try:
- chan.SaslAuthentication.StartMechanism("FOO", "")
+ chan.SASLAuthentication.StartMechanismWithData("FOO", "")
except dbus.DBusException:
pass
else:
@@ -34,11 +34,11 @@ def test_complex_success(q, bus, conn, stream):
else:
initial_data = ""
- chan.SaslAuthentication.StartMechanism("POLITE-TEST", initial_data)
+ chan.SASLAuthentication.StartMechanismWithData("POLITE-TEST", initial_data)
- q.expect('dbus-signal', signal='StateChanged',
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_IN_PROGRESS, '', ''])
+ args=[cs.SASL_STATUS_IN_PROGRESS, '', {}])
for i, pair in enumerate(EXCHANGE[1:]):
challenge, response = pair
@@ -46,23 +46,17 @@ def test_complex_success(q, bus, conn, stream):
interface=cs.CHANNEL_IFACE_SASL_AUTH,
args=[challenge or 'None'])
- challenge_prop = ''.join(
- map(chr, chan.Properties.Get(
- cs.CHANNEL_IFACE_SASL_AUTH, "CurrentChallenge")))
-
- assertEquals(challenge, challenge_prop)
-
if i == len(EXCHANGE) - 2:
- chan.SaslAuthentication.Accept()
- q.expect('dbus-signal', signal='StateChanged',
+ chan.SASLAuthentication.AcceptSASL()
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_CLIENT_ACCEPTED, '', ''])
+ args=[cs.SASL_STATUS_CLIENT_ACCEPTED, '', {}])
else:
- chan.SaslAuthentication.Respond(response)
+ chan.SASLAuthentication.Respond(response)
- q.expect('dbus-signal', signal='StateChanged',
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_SUCCEEDED, '', ''])
+ args=[cs.SASL_STATUS_SUCCEEDED, '', {}])
q.expect('dbus-signal', signal='StatusChanged',
args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
diff --git a/tests/twisted/sasl/jabber_auth.py b/tests/twisted/sasl/jabber_auth.py
index e83e6c89..9dc56d95 100644
--- a/tests/twisted/sasl/jabber_auth.py
+++ b/tests/twisted/sasl/jabber_auth.py
@@ -9,7 +9,7 @@ import hashlib
import dbus
-from servicetest import EventPattern, assertEquals
+from servicetest import EventPattern, assertEquals, assertSameSets
from gabbletest import exec_test, JabberXmlStream, JabberAuthenticator
import constants as cs
from saslutil import SaslPlainAuthenticator, connect_and_get_sasl_channel, \
@@ -19,26 +19,29 @@ JID = "test@localhost"
PASSWORD = "pass"
def test_jabber_pass_success(q, bus, conn, stream):
- chan, auth_info, avail_mechs = connect_and_get_sasl_channel(q, bus, conn)
+ chan, props = connect_and_get_sasl_channel(q, bus, conn)
- assertEquals (
- avail_mechs, ['X-WOCKY-JABBER-PASSWORD', 'X-WOCKY-JABBER-DIGEST'])
+ assertSameSets(['X-WOCKY-JABBER-PASSWORD', 'X-WOCKY-JABBER-DIGEST'],
+ props.get(cs.SASL_AVAILABLE_MECHANISMS))
- assert auth_info.has_key('session-id')
+ context = props.get(cs.SASL_CONTEXT)
- digest = hashlib.sha1(auth_info['session-id'] + PASSWORD).hexdigest()
+ assert context.has_key('jabber-stream-id')
- chan.SaslAuthentication.StartMechanism('X-WOCKY-JABBER-DIGEST', digest)
+ digest = hashlib.sha1(context['jabber-stream-id'] + PASSWORD).hexdigest()
- q.expect('dbus-signal', signal='StateChanged',
+ chan.SASLAuthentication.StartMechanismWithData('X-WOCKY-JABBER-DIGEST',
+ digest)
+
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', ''])
+ args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}])
- chan.SaslAuthentication.Accept()
+ chan.SASLAuthentication.AcceptSASL()
- q.expect('dbus-signal', signal='StateChanged',
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_SUCCEEDED, '', ''])
+ args=[cs.SASL_STATUS_SUCCEEDED, '', {}])
e = q.expect('dbus-signal', signal='StatusChanged',
args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
diff --git a/tests/twisted/sasl/plain.py b/tests/twisted/sasl/plain.py
index 9b7d0de2..15adf59e 100644
--- a/tests/twisted/sasl/plain.py
+++ b/tests/twisted/sasl/plain.py
@@ -9,7 +9,7 @@ from base64 import b64decode
import dbus
-from servicetest import EventPattern, assertEquals
+from servicetest import EventPattern, assertEquals, assertContains
from gabbletest import exec_test
import constants as cs
from saslutil import SaslPlainAuthenticator, connect_and_get_sasl_channel, \
@@ -19,59 +19,62 @@ JID = "test@example.org"
PASSWORD = "pass"
def test_plain_success(q, bus, conn, stream):
- chan, auth_info, avail_mechs = connect_and_get_sasl_channel(q, bus, conn)
+ chan, props = connect_and_get_sasl_channel(q, bus, conn)
- assertEquals('@'.join((auth_info['username'], auth_info['realm'])), JID)
+ # FIXME: is this realistic? I'd expect this to be the JID
+ assertEquals('test', props.get(cs.SASL_AUTHORIZATION_IDENTITY))
- chan.SaslAuthentication.StartMechanism(
+ # On some servers we can't do DIGEST auth without this information.
+ assertEquals('example.org', props.get(cs.SASL_DEFAULT_REALM))
+
+ chan.SASLAuthentication.StartMechanismWithData(
'PLAIN', '\0' + JID.split('@')[0] + '\0' + PASSWORD)
- q.expect('dbus-signal', signal='StateChanged',
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', ''])
+ args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}])
- chan.SaslAuthentication.Accept()
+ chan.SASLAuthentication.AcceptSASL()
- q.expect('dbus-signal', signal='StateChanged',
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_SUCCEEDED, '', ''])
+ args=[cs.SASL_STATUS_SUCCEEDED, '', {}])
e = q.expect('dbus-signal', signal='StatusChanged',
args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
def test_plain_no_account(q, bus, conn, stream):
- chan, auth_info, avail_mechs = connect_and_get_sasl_channel(q, bus, conn)
+ chan, props = connect_and_get_sasl_channel(q, bus, conn)
- chan.SaslAuthentication.StartMechanism(
+ chan.SASLAuthentication.StartMechanismWithData(
'PLAIN', '\0' + JID.split('@')[0] + '\0' + PASSWORD)
- q.expect('dbus-signal', signal='StateChanged',
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', ''])
+ args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}])
- chan.SaslAuthentication.Accept()
+ chan.SASLAuthentication.AcceptSASL()
- q.expect('dbus-signal', signal='StateChanged',
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_SUCCEEDED, '', ''])
+ args=[cs.SASL_STATUS_SUCCEEDED, '', {}])
e = q.expect('dbus-signal', signal='StatusChanged',
args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
def test_plain_fail(q, bus, conn, stream):
- chan, auth_info, avail_mechs = connect_and_get_sasl_channel(q, bus, conn)
-
- assertEquals('@'.join((auth_info['username'], auth_info['realm'])), JID)
+ chan, props = connect_and_get_sasl_channel(q, bus, conn)
- chan.SaslAuthentication.StartMechanism(
+ chan.SASLAuthentication.StartMechanismWithData(
'PLAIN', '\0' + JID.split('@')[0] + '\0' + 'wrong')
- e = q.expect('dbus-signal', signal='StateChanged',
+ e = q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH)
assertEquals(e.args[:2],
[cs.SASL_STATUS_SERVER_FAILED,
cs.AUTHENTICATION_FAILED])
+ assertContains('debug-message', e.args[2])
e = q.expect('dbus-signal', signal='ConnectionError')
assertEquals(cs.AUTHENTICATION_FAILED, e.args[0])
@@ -79,48 +82,46 @@ def test_plain_fail(q, bus, conn, stream):
args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_AUTHENTICATION_FAILED])
def test_plain_abort(q, bus, conn, stream):
- chan, auth_info, avail_mechs = connect_and_get_sasl_channel(q, bus, conn)
-
- assertEquals('@'.join((auth_info['username'], auth_info['realm'])), JID)
+ chan, props = connect_and_get_sasl_channel(q, bus, conn)
- chan.SaslAuthentication.StartMechanism(
+ chan.SASLAuthentication.StartMechanismWithData(
'PLAIN', '\0' + JID.split('@')[0] + '\0' + PASSWORD)
- q.expect('dbus-signal', signal='StateChanged',
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', ''])
+ args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}])
abort_auth(q, chan, cs.SASL_ABORT_REASON_INVALID_CHALLENGE,
"Something is fishy")
def test_bad_usage(q, bus, conn, stream):
- chan, auth_info, avail_mechs = connect_and_get_sasl_channel(q, bus, conn)
+ chan, props = connect_and_get_sasl_channel(q, bus, conn)
try:
- chan.SaslAuthentication.Respond("This is uncalled for");
+ chan.SASLAuthentication.Respond("This is uncalled for");
except dbus.DBusException, e:
assertEquals (e.get_dbus_name(), cs.NOT_AVAILABLE)
else:
raise AssertionError, \
"Calling Respond() before StartMechanism() should raise an error."
- chan.SaslAuthentication.StartMechanism(
+ chan.SASLAuthentication.StartMechanismWithData(
'PLAIN', '\0' + JID.split('@')[0] + '\0' + PASSWORD)
try:
- chan.SaslAuthentication.StartMechanism('PLAIN', "foo")
+ chan.SASLAuthentication.StartMechanismWithData('PLAIN', "foo")
except dbus.DBusException, e:
assertEquals (e.get_dbus_name(), cs.NOT_AVAILABLE)
else:
raise AssertionError, \
- "Calling StartMechanism() twice should raise an error."
+ "Calling StartMechanismWithData() twice should raise an error."
- q.expect('dbus-signal', signal='StateChanged',
+ q.expect('dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', ''])
+ args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}])
try:
- chan.SaslAuthentication.Respond("Responding after success");
+ chan.SASLAuthentication.Respond("Responding after success");
except dbus.DBusException, e:
assertEquals (e.get_dbus_name(), cs.NOT_AVAILABLE)
else:
diff --git a/tests/twisted/sasl/saslutil.py b/tests/twisted/sasl/saslutil.py
index ad037b8d..a6e05d93 100644
--- a/tests/twisted/sasl/saslutil.py
+++ b/tests/twisted/sasl/saslutil.py
@@ -4,12 +4,12 @@ from base64 import b64decode, b64encode
from twisted.words.xish import domish
import constants as cs
import ns
-from servicetest import ProxyWrapper, EventPattern, assertEquals
+from servicetest import ProxyWrapper, EventPattern, assertEquals, assertLength
class SaslChannelWrapper(ProxyWrapper):
def __init__(self, object, default=cs.CHANNEL, interfaces={
"ServerAuthentication" : cs.CHANNEL_TYPE_SERVER_AUTHENTICATION,
- "SaslAuthentication" : cs.CHANNEL_IFACE_SASL_AUTH}):
+ "SASLAuthentication" : cs.CHANNEL_IFACE_SASL_AUTH}):
ProxyWrapper.__init__(self, object, default, interfaces)
class SaslComplexAuthenticator(XmppAuthenticator):
@@ -121,41 +121,44 @@ def connect_and_get_sasl_channel(q, bus, conn):
args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED])
old_signal, new_signal = q.expect_many(
- EventPattern('dbus-signal', signal='NewChannel'),
- EventPattern('dbus-signal', signal='NewChannels'))
+ EventPattern('dbus-signal', signal='NewChannel',
+ predicate=lambda e:
+ e.args[1] == cs.CHANNEL_TYPE_SERVER_AUTHENTICATION),
+ EventPattern('dbus-signal', signal='NewChannels',
+ predicate=lambda e:
+ e.args[0][0][1].get(cs.CHANNEL_TYPE) ==
+ cs.CHANNEL_TYPE_SERVER_AUTHENTICATION),
+ )
path, type, handle_type, handle, suppress_handler = old_signal.args
chan = SaslChannelWrapper(bus.get_object(conn.bus_name, path))
+ assertLength(1, new_signal.args[0])
+ assertEquals(path, new_signal.args[0][0][0])
+ props = new_signal.args[0][0][1]
- auth_info = {}
- avail_mechs = []
- for obj_path, props in new_signal.args[0]:
- if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_SERVER_AUTHENTICATION:
- assertEquals (props[cs.AUTH_METHOD], cs.AUTH_TYPE_SASL)
- info = props[cs.AUTH_INFO]
- mechs = props[cs.SASL_AVAILABLE_MECHANISMS]
- return chan, info, mechs
-
- raise AssertionError, "SASL channel not created."
+ assertEquals(cs.CHANNEL_IFACE_SASL_AUTH, props.get(cs.AUTH_METHOD))
+ return chan, props
def abort_auth(q, chan, reason, message):
reason_err_map = {
cs.SASL_ABORT_REASON_USER_ABORT : cs.CANCELLED,
cs.SASL_ABORT_REASON_INVALID_CHALLENGE : cs.AUTHENTICATION_FAILED}
- chan.SaslAuthentication.Abort(reason, message)
+ chan.SASLAuthentication.AbortSASL(reason, message)
- q.expect_many(
+ ssc, _, _ = q.expect_many(
EventPattern(
- 'dbus-signal', signal='StateChanged',
+ 'dbus-signal', signal='SASLStatusChanged',
interface=cs.CHANNEL_IFACE_SASL_AUTH,
- args=[cs.SASL_STATUS_CLIENT_FAILED,
- reason_err_map[reason],
- message]),
+ predicate=lambda e:e.args[0] == cs.SASL_STATUS_CLIENT_FAILED),
EventPattern('dbus-signal', signal='ConnectionError',
predicate=lambda e: e.args[0] == reason_err_map[reason]),
EventPattern(
'dbus-signal', signal="StatusChanged",
args=[cs.CONN_STATUS_DISCONNECTED,
cs.CSR_AUTHENTICATION_FAILED]))
+
+ assertEquals(cs.SASL_STATUS_CLIENT_FAILED, ssc.args[0])
+ assertEquals(reason_err_map[reason], ssc.args[1])
+ assertEquals(message, ssc.args[2].get('debug-message')),