[Bug 27622] Pluggable SASL authentication

bugzilla-daemon at freedesktop.org bugzilla-daemon at freedesktop.org
Wed Apr 14 02:14:27 CEST 2010


https://bugs.freedesktop.org/show_bug.cgi?id=27622

Will Thompson <will.thompson at collabora.co.uk> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                URL|                            |http://git.collabora.co.uk/
                   |                            |?p=user/eitan/wocky.git;a=s
                   |                            |hortlog;h=refs/heads/sasl
         AssignedTo|telepathy-bugs at lists.freede |eitan.isaacson at collabora.co
                   |sktop.org                   |.uk

--- Comment #1 from Will Thompson <will.thompson at collabora.co.uk> 2010-04-13 17:14:26 PDT ---
I've reviewed Eitan's branch up to 51d581f. I've got a few patches on top of it
at
http://git.collabora.co.uk/?p=user/wjt/wocky.git;a=shortlog;h=refs/heads/sasl.
They're just trivia; I like the shape of the API and the majority of the
implementation.

== Trivia ==

241bd34 messes with the license header in wocky/wocky-sasl-auth.c.

c28f475 adds a NULL check before calling g_free(), which is unnecessary: g_free
(NULL); is a no-op.

Both wocky_sasl_auth_dispose() and wocky_sasl_auth_finalize() free
priv->selected_mechanism. Only the latter should do it. (Arguably, the freeing
priv->mechanisms should be in _finalize() rather than _dispose() since it's
freeing memory not releasing references, but...).

wocky_sasl_auth_choose_handler(): the coding style checker ought to have
complained that there should be a space after the cast in:

+          (plain_mech = g_slist_find_custom (
+              priv->mechanisms, "PLAIN", (GCompareFunc)strcmp)) != NULL)

But this whole loop could be replaced by a call to g_slist_remove_all()... oh
no it couldn't because we need to call strcmp. Grr anaemic collections.

This is just nit-picking, but in wocky_sasl_auth_authenticate_async():

  /* add built-in handlers */

  builtin_handler = WOCKY_SASL_HANDLER (wocky_sasl_digest_md5_new (
          priv->server, priv->username, priv->password));

  wocky_sasl_auth_add_handler (sasl, builtin_handler);

  g_object_unref (builtin_handler);

  builtin_handler = WOCKY_SASL_HANDLER (wocky_sasl_plain_new (
          priv->username, priv->password));

  wocky_sasl_auth_add_handler (sasl, builtin_handler);

  g_object_unref (builtin_handler);

  priv->state = WOCKY_SASL_AUTH_STATE_NEGOTIATING_MECHANISM;

  mech_node = wocky_xmpp_node_get_child_ns (features->node, "mechanisms",
      WOCKY_XMPP_NS_SASL_AUTH);

  priv->mechanisms = wocky_sasl_auth_mechanisms_to_list (mech_node);

That's a whole lot of single statement paragraphs! I've got a patch in my
branch that makes it (I think) easier to read.

== Remarks ==

Wow, I've never seen g_object_disconnect() before. The signal spec arguments
for that
function are ... odd. :)

Congratulations on removing an actual spaghetti-code goto at the end of
sasl_auth_stanza_received() in ecacc9a! :)

== sasl_auth_got_failure: ==

  if (g_strcmp0 ("aborted", reason->name) == 0)
    {
      g_simple_async_result_propagate_error (priv->result, error);
    }
  else
    {
      g_set_error (error, WOCKY_SASL_AUTH_ERROR, WOCKY_SASL_AUTH_ERROR_FAILURE,
          "Authentication failed: %s",
          reason == NULL ? "Unknown reason" : reason->name);
    }

Firstly, reason may be NULL by the code above, in which case we'll crash when
calling g_strcmp0(). Secondly, why does the name of the node returned by the
server affect whether we should take the error from priv->result or build a new
one? Finally, the one caller of sasl_auth_got_failure() immediatelly calls
auth_failed() which just shoves the error back into priv->result! :)

Reading the code more closely, I think what's happening is: when we abort after
choosing a mechanism, we wait until the server acks our aborting before we
throw an error, and in the meantime stash the reason the handler gave for
aborting the exchange on priv->result (since it's a convenient place to keep it
kicking around). Then when we get an ack from the server, we pull the reason
out again.

But this isn't safe:

• If we abort, but the server returns a different reason for failure, then
  we'll call g_simple_async_result_set_error (priv->result, ...) twice.
  Actually, that turns out to be okay. I'm a bit surprised!
• If we don't abort, but the server erroneously claims that we did, then
  g_simple_async_result_propagate_error() will not in fact propagate an error
  in sasl_auth_got_failure() and then the 
      g_assert (error != NULL);
  in sasl_auth_stanza_received() will fail and the world will end.

I think it might be clearer to have gchar *abort_message in priv and do
something like:

  if (priv->abort_message != NULL)
    {
      g_set_error_literal (error, WOCKY_SASL_AUTH_ERROR,
          WOCKY_SASL_AUTH_ERROR_FAILURE, priv->abort_message);
    }
  else
    {
      g_set_error (error, WOCKY_SASL_AUTH_ERROR, WOCKY_SASL_AUTH_ERROR_FAILURE,
          "Authentication failed: %s",
          reason == NULL ? "Unknown reason" : reason->name);
    }

Relatedly, there's a TODO in this function that I've fixed in my branch of your
branch!

== wocky_sasl_auth_choose_handler: ==

  priv->handler = priv->handlers->data;

  wocky_sasl_handler_handle_mechanisms_advertised (priv->handlers->data,
      priv->mechanisms);

On a first reading, I thought that this meant that only the first handler would
be tried. But of course that's not the case: on_handler_selected_mechanism()
tries the next one if the first gives up, etc. Maybe extract part of
on_handler_selected_mechanism() into a try_next_handler() function which
wocky_sasl_auth_choose_handler() calls, and/or sling in a "kick the first
handler to start the chain" comment or something?

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.


More information about the telepathy-bugs mailing list