lightmelody

changeset 701:f3af48b569ed objectify

Begin new SASL implementation
author Arc Riley <arcriley@gmail.com>
date Mon, 31 Dec 2012 15:38:22 -0500
parents f7ddbb8a16d0
children 4c7a5e58a5a8
files src/Connection.gs src/SASL.gs src/Sasl.gs src/SaslPlain.gs src/lm-sasl.c src/lm-sasl.h
diffstat 6 files changed, 82 insertions(+), 1320 deletions(-) [+]
line diff
     1.1 --- a/src/Connection.gs	Fri Dec 28 09:04:20 2012 -0500
     1.2 +++ b/src/Connection.gs	Mon Dec 31 15:38:22 2012 -0500
     1.3 @@ -34,7 +34,7 @@
     1.4      delegate ResultFunction (connection : Lm.Connection, success : bool)
     1.5  
     1.6  
     1.7 -class Lm.Connection
     1.8 +class Lm.Connection : Object
     1.9  
    1.10      enum State
    1.11          CLOSED
    1.12 @@ -76,7 +76,7 @@
    1.13  
    1.14      // Authentication
    1.15      use_sasl : bool // We're just going to ignore this
    1.16 -    sasl : SASLA
    1.17 +    //sasl : SASLA
    1.18      tls_started : bool
    1.19  
    1.20      // Keep Alive
    1.21 @@ -207,7 +207,7 @@
    1.22          _auth_func = (owned) function
    1.23  
    1.24          self.resource = resource
    1.25 -        self.effective_jid = self.jid + resource
    1.26 +        self._effective_jid = self.jid + resource
    1.27  
    1.28          /* TODO get domain
    1.29             TODO convert sasl.authenticate to a real async call
     2.1 --- a/src/SASL.gs	Fri Dec 28 09:04:20 2012 -0500
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,88 +0,0 @@
     2.4 -/*
     2.5 - *  LightMelody - Lightweight XMPP/Jingle Client Library
     2.6 - *  Copyright (C) 2012 Copyleft Games Group
     2.7 - *
     2.8 - *  This program is free software; you can redistribute it and/or modify
     2.9 - *  it under the terms of the GNU Affero General Public License as published
    2.10 - *  by the Free Software Foundation, either version 3 of the License, or
    2.11 - *  (at your option) any later version.
    2.12 - *
    2.13 - *  This program is distributed in the hope that it will be useful,
    2.14 - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.16 - *  GNU Affero General Public License for more details.
    2.17 - *
    2.18 - *  You should have received a copy of the GNU Affero General Public License
    2.19 - *  along with this program; if not, see http://www.gnu.org/licenses
    2.20 - *
    2.21 - */
    2.22 -
    2.23 -[indent=4]
    2.24 -
    2.25 -class Lm.SASLA
    2.26 -    connection : Connection
    2.27 -    features_received : bool
    2.28 -    start_auth : bool
    2.29 -    auth_type : int
    2.30 -    features_cb : MessageHandler
    2.31 -
    2.32 -    [CCode (cprefix="AUTH_TYPE_")]
    2.33 -    enum AuthType
    2.34 -        PLAIN  = 1
    2.35 -        DIGEST = 2
    2.36 -        WEB = 4
    2.37 -
    2.38 -    [CCode (has_target=false)]
    2.39 -    delegate ResultHandler (sasl : SASLA, connection : Connection,
    2.40 -                            success : bool, reason : string)
    2.41 -
    2.42 -    construct (connection : Connection)
    2.43 -        self.connection = connection
    2.44 -        self.features_received = false
    2.45 -        self.start_auth = false
    2.46 -
    2.47 -        // Create and register handler for stream features
    2.48 -        self.features_cb = new MessageHandler (self._features_handler)
    2.49 -        connection.register_message_handler(self.features_cb,
    2.50 -                                            MessageType.STREAM_FEATURES,
    2.51 -                                            HandlerPriority.LAST)
    2.52 -
    2.53 -    def authenticate (auth_params : AuthParameters, server : string,
    2.54 -                      handler : ResultHandler)
    2.55 -        return
    2.56 -
    2.57 -    def inline _is_sasl (mechanisms : MessageNode?) : bool
    2.58 -        sasl_ns : string = "urn:ietf:params:xml:ns:xmpp-sasl"
    2.59 -        if mechanisms is null
    2.60 -            return false
    2.61 -        return mechanisms.get_attribute("xmlns") == sasl_ns
    2.62 -
    2.63 -    def _features_handler (handler : MessageHandler, connection : Connection,
    2.64 -                           message : Message): HandlerResult
    2.65 -        mechanism : MessageNode?
    2.66 -        mechanisms : MessageNode? = message.node.find_child ("mechanisms")
    2.67 -        if self._is_sasl(mechanisms)
    2.68 -            self.features_received = true
    2.69 -            self.auth_type = 0
    2.70 -
    2.71 -            mechanism = mechanisms.children
    2.72 -            while mechanism is not null
    2.73 -                case mechanism.value
    2.74 -                    when "PLAIN"
    2.75 -                        self.auth_type |= AuthType.PLAIN
    2.76 -                    when "DIGEST-MD5"
    2.77 -                        self.auth_type |= AuthType.DIGEST
    2.78 -                    when "WEB"
    2.79 -                        self.auth_type |= AuthType.WEB
    2.80 -
    2.81 -                // Iterate to next mechanism
    2.82 -                mechanism = mechanism.next
    2.83 -
    2.84 -            if self.start_auth
    2.85 -                pass // self.authenticate()
    2.86 -
    2.87 -        return HandlerResult.ALLOW_MORE_HANDLERS
    2.88 -
    2.89 -
    2.90 -
    2.91 -
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/Sasl.gs	Mon Dec 31 15:38:22 2012 -0500
     3.3 @@ -0,0 +1,28 @@
     3.4 +/*
     3.5 + *  LightMelody - Lightweight XMPP/Jingle Client Library
     3.6 + *  Copyright (C) 2012 Copyleft Games Group
     3.7 + *
     3.8 + *  This program is free software; you can redistribute it and/or modify
     3.9 + *  it under the terms of the GNU Affero General Public License as published
    3.10 + *  by the Free Software Foundation, either version 3 of the License, or
    3.11 + *  (at your option) any later version.
    3.12 + *
    3.13 + *  This program is distributed in the hope that it will be useful,
    3.14 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.15 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.16 + *  GNU Affero General Public License for more details.
    3.17 + *
    3.18 + *  You should have received a copy of the GNU Affero General Public License
    3.19 + *  along with this program; if not, see http://www.gnu.org/licenses
    3.20 + *
    3.21 + */
    3.22 +
    3.23 +[indent=4]
    3.24 +
    3.25 +interface Lm.Sasl
    3.26 +
    3.27 +    def abstract auth () : string
    3.28 +    prop abstract readonly name : string
    3.29 +    prop abstract readonly priority : int
    3.30 +    prop abstract readonly secure : bool
    3.31 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/SaslPlain.gs	Mon Dec 31 15:38:22 2012 -0500
     4.3 @@ -0,0 +1,51 @@
     4.4 +/*
     4.5 + *  LightMelody - Lightweight XMPP/Jingle Client Library
     4.6 + *  Copyright (C) 2012 Copyleft Games Group
     4.7 + *
     4.8 + *  This program is free software; you can redistribute it and/or modify
     4.9 + *  it under the terms of the GNU Affero General Public License as published
    4.10 + *  by the Free Software Foundation, either version 3 of the License, or
    4.11 + *  (at your option) any later version.
    4.12 + *
    4.13 + *  This program is distributed in the hope that it will be useful,
    4.14 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.15 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.16 + *  GNU Affero General Public License for more details.
    4.17 + *
    4.18 + *  You should have received a copy of the GNU Affero General Public License
    4.19 + *  along with this program; if not, see http://www.gnu.org/licenses
    4.20 + *
    4.21 + */
    4.22 +
    4.23 +[indent=4]
    4.24 +
    4.25 +class Lm.SaslPlain : Object implements Lm.Sasl
    4.26 +
    4.27 +    construct (username : string, password : string)
    4.28 +        self.username = username
    4.29 +        self.password = password
    4.30 +
    4.31 +
    4.32 +    def auth () : string
    4.33 +        return ""
    4.34 +
    4.35 +
    4.36 +    ///////////////////////////////////////////////////////////////////////
    4.37 +    // Properties
    4.38 +
    4.39 +    prop readonly name : string
    4.40 +        get
    4.41 +            return "PLAIN"
    4.42 +
    4.43 +    prop readonly priority : int
    4.44 +        get
    4.45 +            return 0
    4.46 +
    4.47 +    prop readonly secure : bool
    4.48 +        get
    4.49 +            return false
    4.50 +
    4.51 +    prop username : string
    4.52 +
    4.53 +    prop password : string
    4.54 +
     5.1 --- a/src/lm-sasl.c	Fri Dec 28 09:04:20 2012 -0500
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,1174 +0,0 @@
     5.4 -/*
     5.5 - *  Copyright (C) 2012 Copyleft Games Group
     5.6 - *  Copyright (C) 2007 Collabora Ltd.
     5.7 - *
     5.8 - *  This program is free software; you can redistribute it and/or modify
     5.9 - *  it under the terms of the GNU Affero General Public License as published
    5.10 - *  by the Free Software Foundation, either version 3 of the License, or
    5.11 - *  (at your option) any later version.
    5.12 - *
    5.13 - *  This program is distributed in the hope that it will be useful,
    5.14 - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.15 - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.16 - *  GNU Affero General Public License for more details.
    5.17 - *
    5.18 - *  You should have received a copy of the GNU Affero General Public License
    5.19 - *  along with this program; if not, see http://www.gnu.org/licenses
    5.20 - *
    5.21 - */
    5.22 -
    5.23 -#include <config.h>
    5.24 -
    5.25 -#include <stdio.h>
    5.26 -#include <string.h>
    5.27 -#include <glib.h>
    5.28 -
    5.29 -#ifdef HAVE_GSSAPI
    5.30 -#include <gssapi.h>
    5.31 -#endif
    5.32 -
    5.33 -#include <lightmelody.h>
    5.34 -#include "lm-sock.h"
    5.35 -#include "lm-debug.h"
    5.36 -#include "lm-internals.h"
    5.37 -#include "lm-misc.h"
    5.38 -#include "lm-ssl-internals.h"
    5.39 -#include "lm-parser.h"
    5.40 -#include <loudmouth/lm-utils.h>
    5.41 -#include "lm-old-socket.h"
    5.42 -#include "lm-sasl.h"
    5.43 -
    5.44 -typedef enum {
    5.45 -    SASL_AUTH_STATE_NO_MECH,
    5.46 -    SASL_AUTH_STATE_PLAIN_STARTED,
    5.47 -    SASL_AUTH_STATE_DIGEST_MD5_STARTED,
    5.48 -    SASL_AUTH_STATE_DIGEST_MD5_SENT_AUTH_RESPONSE,
    5.49 -    SASL_AUTH_STATE_DIGEST_MD5_SENT_FINAL_RESPONSE,
    5.50 -    SASL_AUTH_STATE_GSSAPI_STARTED,
    5.51 -    SASL_AUTH_STATE_GSSAPI_SENT_AUTH_RESPONSE,
    5.52 -    SASL_AUTH_STATE_GSSAPI_SENT_FINAL_RESPONSE,
    5.53 -} SaslAuthState;
    5.54 -
    5.55 -struct _LmSASL {
    5.56 -    LmConnection        *connection;
    5.57 -    LmSASLAAuthType       auth_type;
    5.58 -    SaslAuthState        state;
    5.59 -    LmAuthParameters    *auth_params;
    5.60 -    gchar               *server;
    5.61 -    gchar               *digest_md5_rspauth;
    5.62 -    LmMessageHandler    *features_cb;
    5.63 -    LmMessageHandler    *challenge_cb;
    5.64 -    LmMessageHandler    *success_cb;
    5.65 -    LmMessageHandler    *failure_cb;
    5.66 -
    5.67 -    gboolean             features_received;
    5.68 -    gboolean             start_auth;
    5.69 -
    5.70 -    LmSASLResultHandler  handler;
    5.71 -
    5.72 -#ifdef HAVE_GSSAPI
    5.73 -    gss_ctx_id_t         gss_ctx;
    5.74 -    gss_name_t           gss_service;
    5.75 -#endif
    5.76 -};
    5.77 -
    5.78 -#define XMPP_NS_SASL_AUTH "urn:ietf:params:xml:ns:xmpp-sasl"
    5.79 -
    5.80 -static LmHandlerResult     sasl_features_cb  (LmMessageHandler *handler,
    5.81 -                                              LmConnection     *connection,
    5.82 -                                              LmMessage        *message,
    5.83 -                                              gpointer          user_data);
    5.84 -
    5.85 -static LmHandlerResult     sasl_challenge_cb (LmMessageHandler *handler,
    5.86 -                                              LmConnection     *connection,
    5.87 -                                              LmMessage        *message,
    5.88 -                                              gpointer          user_data);
    5.89 -
    5.90 -static LmHandlerResult     sasl_success_cb   (LmMessageHandler *handler,
    5.91 -                                              LmConnection     *connection,
    5.92 -                                              LmMessage        *message,
    5.93 -                                              gpointer          user_data);
    5.94 -
    5.95 -static LmHandlerResult     sasl_failure_cb   (LmMessageHandler *handler,
    5.96 -                                              LmConnection     *connection,
    5.97 -                                              LmMessage        *message,
    5.98 -                                              gpointer          user_data);
    5.99 -
   5.100 -
   5.101 -#ifdef HAVE_GSSAPI
   5.102 -static gboolean
   5.103 -sasl_gssapi_handle_challenge (LmSASL *sasl, LmMessageNode *node);
   5.104 -
   5.105 -static void
   5.106 -sasl_gssapi_fail (LmSASL     *sasl,
   5.107 -                  const char *message,
   5.108 -                  guint32     major_status,
   5.109 -                  guint32     minor_status)
   5.110 -{
   5.111 -    guint32         err_major_status;
   5.112 -    guint32         err_minor_status;
   5.113 -    guint32         msg_ctx = 0;
   5.114 -    gss_buffer_desc major_status_string = GSS_C_EMPTY_BUFFER;
   5.115 -    gss_buffer_desc minor_status_string = GSS_C_EMPTY_BUFFER;
   5.116 -
   5.117 -    err_major_status = gss_display_status (&err_minor_status, major_status,
   5.118 -                                           GSS_C_GSS_CODE, GSS_C_NO_OID,
   5.119 -                                           &msg_ctx, &major_status_string);
   5.120 -
   5.121 -    if (!GSS_ERROR(err_major_status)) {
   5.122 -        err_major_status = gss_display_status (&err_minor_status, minor_status,
   5.123 -                                               GSS_C_MECH_CODE, GSS_C_NULL_OID,
   5.124 -                                               &msg_ctx, &minor_status_string);
   5.125 -    }
   5.126 -
   5.127 -    g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL, "GSSAPI: %s: %s, %s", message,
   5.128 -           (char *)major_status_string.value,
   5.129 -           (char *)minor_status_string.value);
   5.130 -
   5.131 -    if (sasl->handler) {
   5.132 -        sasl->handler (sasl, sasl->connection, FALSE, "GSSAPI failure");
   5.133 -    }
   5.134 -
   5.135 -    gss_release_buffer (&err_minor_status, &major_status_string);
   5.136 -    gss_release_buffer (&err_minor_status, &minor_status_string);
   5.137 -}
   5.138 -
   5.139 -static gss_name_t
   5.140 -sasl_gssapi_get_creds (LmSASL *sasl)
   5.141 -{
   5.142 -    gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
   5.143 -    gss_name_t      service_name = GSS_C_NO_NAME;
   5.144 -    guint32         major_status;
   5.145 -    guint32         minor_status;
   5.146 -
   5.147 -    token.value	= g_strdup_printf ("xmpp@%s", sasl->server);
   5.148 -    token.length = strlen ((char *)token.value);
   5.149 -
   5.150 -    if (token.value == NULL) {
   5.151 -        return GSS_C_NO_NAME;
   5.152 -    }
   5.153 -
   5.154 -    major_status = gss_import_name (&minor_status, &token,
   5.155 -                                    GSS_C_NT_HOSTBASED_SERVICE,
   5.156 -                                    &service_name);
   5.157 -
   5.158 -    if (GSS_ERROR(major_status)) {
   5.159 -        sasl_gssapi_fail (sasl, "while obtaining service principal",
   5.160 -                          major_status, minor_status);
   5.161 -        return GSS_C_NO_NAME;
   5.162 -    }
   5.163 -
   5.164 -    return service_name;
   5.165 -}
   5.166 -
   5.167 -static gboolean
   5.168 -sasl_gssapi_start (LmSASL *sasl, LmMessageNode *node)
   5.169 -{
   5.170 -    gchar           *response64;
   5.171 -    gss_buffer_desc  input_buffer_desc;
   5.172 -    gss_buffer_t     input_buffer;
   5.173 -    gss_buffer_desc  output_buffer_desc;
   5.174 -    gss_buffer_t     output_buffer;
   5.175 -    guint32          major_status;
   5.176 -    guint32          minor_status;
   5.177 -
   5.178 -    sasl->gss_ctx = GSS_C_NO_CONTEXT;
   5.179 -    sasl->gss_service = sasl_gssapi_get_creds (sasl);
   5.180 -    if (sasl->gss_service == GSS_C_NO_NAME) {
   5.181 -        return FALSE;
   5.182 -    }
   5.183 -
   5.184 -    sasl->state = SASL_AUTH_STATE_GSSAPI_STARTED;
   5.185 -
   5.186 -    input_buffer_desc.value = NULL;
   5.187 -    input_buffer_desc.length = 0;
   5.188 -
   5.189 -    input_buffer = &input_buffer_desc;
   5.190 -
   5.191 -    output_buffer_desc.value = NULL;
   5.192 -    output_buffer_desc.length = 0;
   5.193 -    output_buffer = &output_buffer_desc;
   5.194 -
   5.195 -    major_status = gss_init_sec_context (&minor_status,
   5.196 -                                         GSS_C_NO_CREDENTIAL,
   5.197 -                                         &sasl->gss_ctx,
   5.198 -                                         sasl->gss_service,
   5.199 -                                         GSS_C_NO_OID,
   5.200 -                                         GSS_C_MUTUAL_FLAG |
   5.201 -                                         GSS_C_REPLAY_FLAG |
   5.202 -                                         GSS_C_SEQUENCE_FLAG |
   5.203 -                                         GSS_C_INTEG_FLAG |
   5.204 -                                         GSS_C_CONF_FLAG,
   5.205 -                                         0,
   5.206 -                                         GSS_C_NO_CHANNEL_BINDINGS,
   5.207 -                                         input_buffer, NULL, output_buffer, NULL, NULL);
   5.208 -
   5.209 -    if (GSS_ERROR(major_status)) {
   5.210 -        sasl_gssapi_fail (sasl, "during challenge/response",
   5.211 -                          major_status, minor_status);
   5.212 -        return FALSE;
   5.213 -    }
   5.214 -
   5.215 -    if (major_status != GSS_S_CONTINUE_NEEDED) {
   5.216 -        sasl->state = SASL_AUTH_STATE_GSSAPI_SENT_AUTH_RESPONSE;
   5.217 -    }
   5.218 -
   5.219 -    response64 = g_base64_encode ((const guchar *) output_buffer_desc.value,
   5.220 -                                  (gsize) output_buffer_desc.length);
   5.221 -
   5.222 -    lm_message_node_set_value (node, response64);
   5.223 -
   5.224 -    g_free (response64);
   5.225 -
   5.226 -    return TRUE;
   5.227 -}
   5.228 -
   5.229 -static gboolean
   5.230 -sasl_gssapi_handle_challenge (LmSASL *sasl, LmMessageNode *node)
   5.231 -{
   5.232 -    const gchar     *encoded;
   5.233 -    gchar           *response64;
   5.234 -    gss_buffer_t     input_buffer;
   5.235 -    gss_buffer_desc  input_buffer_desc;
   5.236 -    gss_buffer_t     output_buffer;
   5.237 -    gss_buffer_desc  output_buffer_desc;
   5.238 -    guint32          major_status;
   5.239 -    guint32          minor_status;
   5.240 -    gboolean         result;
   5.241 -    LmMessage       *msg;
   5.242 -
   5.243 -    encoded = lm_message_node_get_value (node);
   5.244 -    if (encoded == NULL) {
   5.245 -        input_buffer_desc.value = NULL;
   5.246 -        input_buffer_desc.length = 0;
   5.247 -    } else {
   5.248 -        input_buffer_desc.value = g_base64_decode (encoded,
   5.249 -                                                 &input_buffer_desc.length);
   5.250 -    }
   5.251 -
   5.252 -    input_buffer = &input_buffer_desc;
   5.253 -
   5.254 -    output_buffer_desc.value = NULL;
   5.255 -    output_buffer_desc.length = 0;
   5.256 -    output_buffer = &output_buffer_desc;
   5.257 -
   5.258 -    if (sasl->state == SASL_AUTH_STATE_GSSAPI_STARTED) {
   5.259 -        major_status = gss_init_sec_context (&minor_status,
   5.260 -                                             GSS_C_NO_CREDENTIAL,
   5.261 -                                             &sasl->gss_ctx,
   5.262 -                                             sasl->gss_service,
   5.263 -                                             GSS_C_NO_OID,
   5.264 -                                             GSS_C_MUTUAL_FLAG |
   5.265 -                                             GSS_C_REPLAY_FLAG |
   5.266 -                                             GSS_C_SEQUENCE_FLAG |
   5.267 -                                             GSS_C_INTEG_FLAG |
   5.268 -                                             GSS_C_CONF_FLAG,
   5.269 -                                             0,
   5.270 -                                             GSS_C_NO_CHANNEL_BINDINGS,
   5.271 -                                             input_buffer, NULL, output_buffer, NULL, NULL);
   5.272 -
   5.273 -        if (GSS_ERROR(major_status)) {
   5.274 -            sasl_gssapi_fail (sasl, "during challenge/response",
   5.275 -                              major_status, minor_status);
   5.276 -            return FALSE;
   5.277 -        }
   5.278 -
   5.279 -        if (major_status != GSS_S_CONTINUE_NEEDED) {
   5.280 -            sasl->state = SASL_AUTH_STATE_GSSAPI_SENT_AUTH_RESPONSE;
   5.281 -        }
   5.282 -
   5.283 -        major_status = gss_release_buffer (&minor_status, input_buffer);
   5.284 -        if (major_status != GSS_S_COMPLETE) {
   5.285 -            return FALSE;
   5.286 -        }
   5.287 -    } else if (sasl->state == SASL_AUTH_STATE_GSSAPI_SENT_AUTH_RESPONSE) {
   5.288 -        gchar *features;
   5.289 -
   5.290 -        major_status = gss_unwrap (&minor_status, sasl->gss_ctx,
   5.291 -                                   input_buffer, output_buffer,
   5.292 -                                   NULL, NULL);
   5.293 -
   5.294 -        if (GSS_ERROR(major_status)) {
   5.295 -            sasl_gssapi_fail (sasl, "while unwrapping server capabilities",
   5.296 -                              major_status, minor_status);
   5.297 -            return FALSE;
   5.298 -        }
   5.299 -
   5.300 -        major_status = gss_release_buffer (&minor_status, input_buffer);
   5.301 -        if (major_status != GSS_S_COMPLETE) {
   5.302 -            return FALSE;
   5.303 -        }
   5.304 -
   5.305 -        major_status = gss_release_buffer (&minor_status, output_buffer);
   5.306 -        if (major_status != GSS_S_COMPLETE) {
   5.307 -            return FALSE;
   5.308 -        }
   5.309 -
   5.310 -        input_buffer_desc.length = 4 + strlen(lm_auth_parameters_get_username (sasl->auth_params));
   5.311 -        features = g_malloc (input_buffer_desc.length);
   5.312 -
   5.313 -        features[0] = 1;
   5.314 -        features[1] = 0xFF;
   5.315 -        features[2] = 0xFF;
   5.316 -        features[3] = 0xFF;
   5.317 -        strcpy(features+4, lm_auth_parameters_get_username (sasl->auth_params));
   5.318 -
   5.319 -        input_buffer_desc.value = features;
   5.320 -        major_status = gss_wrap (&minor_status, sasl->gss_ctx,
   5.321 -                                 0, /* Just integrity checking here */
   5.322 -                                 GSS_C_QOP_DEFAULT,
   5.323 -                                 input_buffer,
   5.324 -                                 NULL,
   5.325 -                                 output_buffer);
   5.326 -        g_free (features);
   5.327 -        if (GSS_ERROR(major_status)) {
   5.328 -            sasl_gssapi_fail (sasl, "while wrapping required features",
   5.329 -                              major_status, minor_status);
   5.330 -            return FALSE;
   5.331 -        }
   5.332 -    } else {
   5.333 -        g_assert_not_reached ();
   5.334 -    }
   5.335 -
   5.336 -    msg = lm_message_new (NULL, LM_MESSAGE_TYPE_RESPONSE);
   5.337 -    lm_message_node_set_attributes (msg->node,
   5.338 -                                    "xmlns", XMPP_NS_SASL_AUTH,
   5.339 -                                    NULL);
   5.340 -
   5.341 -    if (output_buffer_desc.value != NULL) {
   5.342 -        response64 = g_base64_encode ((const guchar *) output_buffer_desc.value,
   5.343 -                                      (gsize) output_buffer_desc.length);
   5.344 -
   5.345 -    } else {
   5.346 -        response64 = g_strdup ("");
   5.347 -    }
   5.348 -
   5.349 -    major_status = gss_release_buffer (&minor_status, output_buffer);
   5.350 -    if (major_status != GSS_S_COMPLETE) {
   5.351 -        g_free (response64);
   5.352 -        lm_message_unref (msg);
   5.353 -        return FALSE;
   5.354 -    }
   5.355 -
   5.356 -    lm_message_node_set_value (msg->node, response64);
   5.357 -
   5.358 -    result = lm_connection_send (sasl->connection, msg, NULL);
   5.359 -
   5.360 -    g_free (response64);
   5.361 -    lm_message_unref (msg);
   5.362 -
   5.363 -    if (!result) {
   5.364 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
   5.365 -               "Failed to send SASL response\n");
   5.366 -        return FALSE;
   5.367 -    }
   5.368 -
   5.369 -    return TRUE;
   5.370 -}
   5.371 -
   5.372 -static gboolean
   5.373 -sasl_gssapi_finish (LmSASL *sasl, LmMessageNode *node)
   5.374 -{
   5.375 -    OM_uint32 /* major_status, */ minor_status;
   5.376 -
   5.377 -    if (sasl->gss_service != GSS_C_NO_NAME) {
   5.378 -        /* major_status = */
   5.379 -        (void) gss_release_name (&minor_status, &sasl->gss_service);
   5.380 -    }
   5.381 -
   5.382 -    if (sasl->gss_ctx != GSS_C_NO_CONTEXT) {
   5.383 -        /* major_status = */
   5.384 -        (void) gss_delete_sec_context (&minor_status, &sasl->gss_ctx,
   5.385 -                                       GSS_C_NO_BUFFER);
   5.386 -    }
   5.387 -
   5.388 -    return TRUE;
   5.389 -}
   5.390 -#endif
   5.391 -
   5.392 -
   5.393 -/* DIGEST-MD5 mechanism code from libgibber */
   5.394 -
   5.395 -static gchar *
   5.396 -sasl_strndup_unescaped (const gchar *str, gsize len)
   5.397 -{
   5.398 -    const gchar *s;
   5.399 -    gchar       *d;
   5.400 -    gchar       *ret;
   5.401 -
   5.402 -    ret = g_malloc0 (len + 1);
   5.403 -    for (s = str, d = ret ; s < (str + len) ; s++, d++) {
   5.404 -        if (*s == '\\') s++;
   5.405 -        *d = *s;
   5.406 -    }
   5.407 -
   5.408 -    return ret;
   5.409 -}
   5.410 -
   5.411 -static GHashTable *
   5.412 -sasl_digest_md5_challenge_to_hash (const gchar * challenge)
   5.413 -{
   5.414 -    const gchar *keystart, *keyend, *valstart;
   5.415 -    const gchar *c = challenge;
   5.416 -    gchar       *key, *val;
   5.417 -    GHashTable  *result;
   5.418 -
   5.419 -    result = g_hash_table_new_full (g_str_hash, g_str_equal,
   5.420 -                                    g_free, g_free);
   5.421 -
   5.422 -    do {
   5.423 -        while (g_ascii_isspace(*c)) c++;
   5.424 -
   5.425 -        keystart = c;
   5.426 -        for (; *c != '\0' && *c != '='; c++);
   5.427 -
   5.428 -        if (*c == '\0' || c == keystart) goto error;
   5.429 -
   5.430 -        keyend = c;
   5.431 -        c++;
   5.432 -
   5.433 -        if (*c == '"') {
   5.434 -            c++;
   5.435 -            valstart = c;
   5.436 -            for (; *c != '\0' && *c != '"'; c++);
   5.437 -            if (*c == '\0' || c == valstart) goto error;
   5.438 -            val = sasl_strndup_unescaped (valstart, c - valstart);
   5.439 -            c++;
   5.440 -        } else {
   5.441 -            valstart = c;
   5.442 -            for (; *c !=  '\0' && *c != ','; c++);
   5.443 -            if (c == valstart) goto error;
   5.444 -            val = g_strndup (valstart, c - valstart);
   5.445 -        }
   5.446 -
   5.447 -        key = g_strndup (keystart, keyend - keystart);
   5.448 -
   5.449 -        g_hash_table_insert (result, key, val);
   5.450 -
   5.451 -        if (*c == ',') c++;
   5.452 -    } while (*c != '\0');
   5.453 -
   5.454 -    return result;
   5.455 - error:
   5.456 -    g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
   5.457 -           "Failed to parse challenge: %s", challenge);
   5.458 -
   5.459 -    g_hash_table_destroy (result);
   5.460 -    return NULL;
   5.461 -}
   5.462 -
   5.463 -static gchar *
   5.464 -sasl_md5_hex_hash (gchar *value, gsize len)
   5.465 -{
   5.466 -    GChecksum*   checksum;
   5.467 -    guint8       digest[16];
   5.468 -    gchar*       md5;
   5.469 -
   5.470 -    checksum = g_checksum_new(G_CHECKSUM_MD5);
   5.471 -    g_checksum_update(checksum, (guchar *) value, len);
   5.472 -    md5 = g_strdup(g_checksum_get_string(checksum));
   5.473 -    g_checksum_free(checksum);
   5.474 -
   5.475 -    return md5;
   5.476 -}
   5.477 -
   5.478 -static gchar *
   5.479 -sasl_digest_md5_generate_cnonce(void)
   5.480 -{
   5.481 -    /* RFC 2831 recommends the the nonce to be either hexadecimal or base64 with
   5.482 -     * at least 64 bits of entropy */
   5.483 -#define NR 8
   5.484 -    guint32 n[NR];
   5.485 -    int i;
   5.486 -
   5.487 -    for (i = 0; i < NR; i++) {
   5.488 -        n[i] = g_random_int();
   5.489 -    }
   5.490 -
   5.491 -    return g_base64_encode ((const guchar *)n, (gsize)sizeof(n));
   5.492 -}
   5.493 -
   5.494 -static gchar *
   5.495 -sasl_md5_prepare_response (LmSASL *sasl, GHashTable *challenge)
   5.496 -{
   5.497 -    GString     *response;
   5.498 -    const gchar *realm, *nonce;
   5.499 -    gchar       *a1, *a1h, *a2, *a2h, *kd, *kdh;
   5.500 -    gchar       *cnonce = NULL;
   5.501 -    gchar       *tmp;
   5.502 -    GChecksum*   checksum;
   5.503 -    guint8       digest_md5[16];
   5.504 -    gsize        len     =  16;
   5.505 -
   5.506 -    response = g_string_new ("");
   5.507 -
   5.508 -    if (sasl->auth_params == NULL) {
   5.509 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
   5.510 -               "%s: no authentication parameters provided", G_STRFUNC);
   5.511 -        if (sasl->handler) {
   5.512 -            sasl->handler (sasl, sasl->connection,
   5.513 -                           FALSE, "no username/password provided");
   5.514 -        }
   5.515 -        goto error;
   5.516 -    }
   5.517 -
   5.518 -    nonce = g_hash_table_lookup (challenge, "nonce");
   5.519 -    if (nonce == NULL || nonce == '\0') {
   5.520 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
   5.521 -               "%s: server didn't provide a nonce in the challenge",
   5.522 -               G_STRFUNC);
   5.523 -        if (sasl->handler) {
   5.524 -            sasl->handler (sasl, sasl->connection,
   5.525 -                           FALSE, "server error");
   5.526 -        }
   5.527 -        goto error;
   5.528 -    }
   5.529 -
   5.530 -    cnonce = sasl_digest_md5_generate_cnonce ();
   5.531 -
   5.532 -    /* FIXME challenge can contain multiple realms */
   5.533 -    realm = g_hash_table_lookup (challenge, "realm");
   5.534 -    if (realm == NULL) {
   5.535 -        realm = sasl->server;
   5.536 -    }
   5.537 -
   5.538 -    /* FIXME properly escape values */
   5.539 -    g_string_append_printf (response, "username=\"%s\"", lm_auth_parameters_get_username (sasl->auth_params));
   5.540 -    g_string_append_printf (response, ",realm=\"%s\"", realm);
   5.541 -    g_string_append_printf (response, ",digest-uri=\"xmpp/%s\"", realm);
   5.542 -    g_string_append_printf (response, ",nonce=\"%s\",nc=00000001", nonce);
   5.543 -    g_string_append_printf (response, ",cnonce=\"%s\"", cnonce);
   5.544 -    /* FIXME should check if auth is in the cop challenge val */
   5.545 -    g_string_append_printf (response, ",qop=auth,charset=utf-8");
   5.546 -
   5.547 -    tmp = g_strdup_printf ("%s:%s:%s",
   5.548 -                           lm_auth_parameters_get_username (sasl->auth_params),
   5.549 -                           realm, lm_auth_parameters_get_password (sasl->auth_params));
   5.550 -
   5.551 -
   5.552 -    checksum = g_checksum_new(G_CHECKSUM_MD5);
   5.553 -    g_checksum_update(checksum, (guchar *) tmp, strlen(tmp));
   5.554 -    g_checksum_get_digest(checksum, digest_md5, &len);
   5.555 -    g_checksum_free(checksum);
   5.556 -    g_free (tmp);
   5.557 -
   5.558 -    a1 = g_strdup_printf ("0123456789012345:%s:%s", nonce, cnonce);
   5.559 -    len = strlen (a1);
   5.560 -    memcpy (a1, digest_md5, 16);
   5.561 -    a1h = sasl_md5_hex_hash (a1, len);
   5.562 -
   5.563 -    a2 = g_strdup_printf ("AUTHENTICATE:xmpp/%s", realm);
   5.564 -    a2h = sasl_md5_hex_hash (a2, strlen(a2));
   5.565 -
   5.566 -    kd = g_strdup_printf ("%s:%s:00000001:%s:auth:%s",
   5.567 -                          a1h, nonce, cnonce, a2h);
   5.568 -    kdh = sasl_md5_hex_hash (kd, strlen(kd));
   5.569 -    g_string_append_printf (response, ",response=%s", kdh);
   5.570 -
   5.571 -    g_free (kd);
   5.572 -    g_free (kdh);
   5.573 -    g_free (a2);
   5.574 -    g_free (a2h);
   5.575 -
   5.576 -    /* Calculate the response we expect from the server */
   5.577 -    a2 = g_strdup_printf (":xmpp/%s", realm);
   5.578 -    a2h = sasl_md5_hex_hash (a2, strlen(a2));
   5.579 -
   5.580 -    kd = g_strdup_printf ("%s:%s:00000001:%s:auth:%s", a1h, nonce, cnonce, a2h);
   5.581 -    g_free (sasl->digest_md5_rspauth);
   5.582 -    sasl->digest_md5_rspauth = sasl_md5_hex_hash (kd, strlen(kd));
   5.583 -
   5.584 -    g_free (a1);
   5.585 -    g_free (a1h);
   5.586 -    g_free (a2);
   5.587 -    g_free (a2h);
   5.588 -    g_free (kd);
   5.589 -
   5.590 - out:
   5.591 -    g_free (cnonce);
   5.592 -    if (response) {
   5.593 -        return g_string_free (response, FALSE);
   5.594 -    } else {
   5.595 -        return NULL;
   5.596 -    }
   5.597 -
   5.598 - error:
   5.599 -    g_string_free (response, TRUE);
   5.600 -    response = NULL;
   5.601 -    goto out;
   5.602 -}
   5.603 -
   5.604 -static gboolean
   5.605 -sasl_digest_md5_send_initial_response (LmSASL *sasl, GHashTable *challenge)
   5.606 -{
   5.607 -    LmMessage *msg;
   5.608 -    gchar     *response;
   5.609 -    gchar     *response64;
   5.610 -    int        result;
   5.611 -
   5.612 -    response = sasl_md5_prepare_response (sasl, challenge);
   5.613 -    if (response == NULL) {
   5.614 -        return FALSE;
   5.615 -    }
   5.616 -
   5.617 -    response64 = g_base64_encode ((const guchar *) response,
   5.618 -                                  (gsize) strlen(response));
   5.619 -
   5.620 -    msg = lm_message_new (NULL, LM_MESSAGE_TYPE_RESPONSE);
   5.621 -    lm_message_node_set_attributes (msg->node,
   5.622 -                                    "xmlns", XMPP_NS_SASL_AUTH,
   5.623 -                                    NULL);
   5.624 -    lm_message_node_set_value (msg->node, response64);
   5.625 -
   5.626 -    result = lm_connection_send (sasl->connection, msg, NULL);
   5.627 -
   5.628 -    g_free (response);
   5.629 -    g_free (response64);
   5.630 -    lm_message_unref (msg);
   5.631 -
   5.632 -    if (!result) {
   5.633 -        return FALSE;
   5.634 -    }
   5.635 -
   5.636 -    sasl->state = SASL_AUTH_STATE_DIGEST_MD5_SENT_AUTH_RESPONSE;
   5.637 -
   5.638 -    return TRUE;
   5.639 -}
   5.640 -
   5.641 -static gboolean
   5.642 -sasl_digest_md5_check_server_response(LmSASL *sasl, GHashTable *challenge)
   5.643 -{
   5.644 -    LmMessage   *msg;
   5.645 -    const gchar *rspauth;
   5.646 -    int          result;
   5.647 -
   5.648 -    rspauth = g_hash_table_lookup (challenge, "rspauth");
   5.649 -    if (rspauth == NULL) {
   5.650 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
   5.651 -               "%s: server sent an invalid reply (no rspauth)\n",
   5.652 -               G_STRFUNC);
   5.653 -
   5.654 -        if (sasl->handler) {
   5.655 -            sasl->handler (sasl, sasl->connection,
   5.656 -                           TRUE, "server error");
   5.657 -        }
   5.658 -        return FALSE;
   5.659 -    }
   5.660 -
   5.661 -    if (strcmp (sasl->digest_md5_rspauth, rspauth) != 0) {
   5.662 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
   5.663 -               "%s: server sent an invalid reply (rspauth not matching)\n",
   5.664 -               G_STRFUNC);
   5.665 -
   5.666 -        if (sasl->handler) {
   5.667 -            sasl->handler (sasl, sasl->connection,
   5.668 -                           TRUE, "server error");
   5.669 -        }
   5.670 -        return FALSE;
   5.671 -    }
   5.672 -
   5.673 -    msg = lm_message_new (NULL, LM_MESSAGE_TYPE_RESPONSE);
   5.674 -    lm_message_node_set_attributes (msg->node,
   5.675 -                                    "xmlns", XMPP_NS_SASL_AUTH,
   5.676 -                                    NULL);
   5.677 -
   5.678 -    result = lm_connection_send (sasl->connection, msg, NULL);
   5.679 -    lm_message_unref (msg);
   5.680 -
   5.681 -    if (!result) {
   5.682 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
   5.683 -               "Failed to send SASL response\n");
   5.684 -        return FALSE;
   5.685 -    }
   5.686 -
   5.687 -    sasl->state = SASL_AUTH_STATE_DIGEST_MD5_SENT_FINAL_RESPONSE;
   5.688 -
   5.689 -    return TRUE;
   5.690 -}
   5.691 -
   5.692 -static gboolean
   5.693 -sasl_digest_md5_handle_challenge (LmSASL *sasl, LmMessageNode *node)
   5.694 -{
   5.695 -    const gchar *encoded;
   5.696 -    gchar       *challenge;
   5.697 -    gsize        len;
   5.698 -    GHashTable  *h;
   5.699 -
   5.700 -    encoded = lm_message_node_get_value (node);
   5.701 -    if (!encoded) {
   5.702 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
   5.703 -               "%s: got empty challenge!", G_STRFUNC);
   5.704 -        return FALSE;
   5.705 -    }
   5.706 -
   5.707 -    challenge = (gchar *) g_base64_decode (encoded, &len);
   5.708 -    h = sasl_digest_md5_challenge_to_hash (challenge);
   5.709 -    g_free(challenge);
   5.710 -
   5.711 -    if (!h) {
   5.712 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
   5.713 -               "%s: server sent an invalid challenge", G_STRFUNC);
   5.714 -        if (sasl->handler) {
   5.715 -            sasl->handler (sasl, sasl->connection,
   5.716 -                           FALSE, "server error");
   5.717 -        }
   5.718 -        return FALSE;
   5.719 -    }
   5.720 -
   5.721 -    switch (sasl->state) {
   5.722 -    case SASL_AUTH_STATE_DIGEST_MD5_STARTED:
   5.723 -        sasl_digest_md5_send_initial_response (sasl, h);
   5.724 -        break;
   5.725 -    case SASL_AUTH_STATE_DIGEST_MD5_SENT_AUTH_RESPONSE:
   5.726 -        sasl_digest_md5_check_server_response (sasl, h);
   5.727 -        break;
   5.728 -    default:
   5.729 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
   5.730 -               "%s: server sent a challenge at the wrong time",
   5.731 -               G_STRFUNC);
   5.732 -        if (sasl->handler) {
   5.733 -            sasl->handler (sasl, sasl->connection,
   5.734 -                           FALSE, "server error");
   5.735 -        }
   5.736 -
   5.737 -        return FALSE;
   5.738 -    }
   5.739 -
   5.740 -    g_hash_table_destroy(h);
   5.741 -
   5.742 -    return TRUE;
   5.743 -}
   5.744 -
   5.745 -static LmHandlerResult
   5.746 -sasl_challenge_cb (LmMessageHandler *handler,
   5.747 -                   LmConnection     *connection,
   5.748 -                   LmMessage        *message,
   5.749 -                   gpointer          user_data)
   5.750 -{
   5.751 -    LmSASL      *sasl;
   5.752 -    const gchar *ns;
   5.753 -
   5.754 -    ns = lm_message_node_get_attribute (message->node, "xmlns");
   5.755 -    if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH) != 0) {
   5.756 -        return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
   5.757 -    }
   5.758 -
   5.759 -    sasl = (LmSASL *) user_data;
   5.760 -
   5.761 -    switch (sasl->auth_type) {
   5.762 -    case AUTH_TYPE_PLAIN:
   5.763 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
   5.764 -               "%s: server sent challenge for PLAIN mechanism",
   5.765 -               G_STRFUNC);
   5.766 -
   5.767 -        if (sasl->handler) {
   5.768 -            sasl->handler (sasl, sasl->connection,
   5.769 -                           FALSE, "server error");
   5.770 -        }
   5.771 -        break;
   5.772 -    case AUTH_TYPE_DIGEST:
   5.773 -        sasl_digest_md5_handle_challenge (sasl, message->node);
   5.774 -        break;
   5.775 -#ifdef HAVE_GSSAPI
   5.776 -    case AUTH_TYPE_GSSAPI:
   5.777 -        sasl_gssapi_handle_challenge(sasl, message->node);
   5.778 -        break;
   5.779 -#endif
   5.780 -    default:
   5.781 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "Wrong auth type");
   5.782 -        break;
   5.783 -    }
   5.784 -
   5.785 -    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
   5.786 -}
   5.787 -
   5.788 -static LmHandlerResult
   5.789 -sasl_success_cb (LmMessageHandler *handler,
   5.790 -                 LmConnection     *connection,
   5.791 -                 LmMessage        *message,
   5.792 -                 gpointer          user_data)
   5.793 -{
   5.794 -    LmSASL      *sasl;
   5.795 -    const gchar *ns;
   5.796 -
   5.797 -    ns = lm_message_node_get_attribute (message->node, "xmlns");
   5.798 -    if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH) != 0) {
   5.799 -        return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
   5.800 -    }
   5.801 -
   5.802 -    sasl = (LmSASL *) user_data;
   5.803 -
   5.804 -    switch (sasl->auth_type) {
   5.805 -    case AUTH_TYPE_PLAIN:
   5.806 -        if (sasl->state != SASL_AUTH_STATE_PLAIN_STARTED) {
   5.807 -            g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
   5.808 -                   "%s: server sent success before finishing auth",
   5.809 -                   G_STRFUNC);
   5.810 -            if (sasl->handler) {
   5.811 -                sasl->handler (sasl, sasl->connection,
   5.812 -                               FALSE, "server error");
   5.813 -            }
   5.814 -        }
   5.815 -        break;
   5.816 -    case AUTH_TYPE_DIGEST:
   5.817 -        if (sasl->state != SASL_AUTH_STATE_DIGEST_MD5_SENT_AUTH_RESPONSE &&
   5.818 -            sasl->state != SASL_AUTH_STATE_DIGEST_MD5_SENT_FINAL_RESPONSE) {
   5.819 -            g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
   5.820 -                   "%s: server sent success before finishing auth",
   5.821 -                   G_STRFUNC);
   5.822 -            if (sasl->handler) {
   5.823 -                sasl->handler (sasl, sasl->connection,
   5.824 -                               FALSE, "server error");
   5.825 -            }
   5.826 -        }
   5.827 -        break;
   5.828 -#ifdef HAVE_GSSAPI
   5.829 -    case AUTH_TYPE_GSSAPI:
   5.830 -        if (sasl->state != SASL_AUTH_STATE_GSSAPI_SENT_AUTH_RESPONSE &&
   5.831 -            sasl->state != SASL_AUTH_STATE_GSSAPI_SENT_FINAL_RESPONSE) {
   5.832 -            sasl_gssapi_finish(sasl, message->node);
   5.833 -            g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
   5.834 -                   "%s: server sent success before starting auth",
   5.835 -                   G_STRFUNC);
   5.836 -            if (sasl->handler) {
   5.837 -                sasl->handler (sasl, sasl->connection,
   5.838 -                               FALSE, "server error");
   5.839 -            }
   5.840 -        }
   5.841 -        break;
   5.842 -#endif
   5.843 -    default:
   5.844 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "Wrong auth type");
   5.845 -        break;
   5.846 -    }
   5.847 -
   5.848 -    g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
   5.849 -           "%s: SASL authentication successful", G_STRFUNC);
   5.850 -
   5.851 -    if (sasl->handler) {
   5.852 -        sasl->handler (sasl, sasl->connection, TRUE, NULL);
   5.853 -    }
   5.854 -
   5.855 -    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
   5.856 -
   5.857 -}
   5.858 -
   5.859 -static LmHandlerResult
   5.860 -sasl_failure_cb (LmMessageHandler *handler,
   5.861 -                 LmConnection     *connection,
   5.862 -                 LmMessage        *message,
   5.863 -                 gpointer          user_data)
   5.864 -{
   5.865 -    LmSASL      *sasl;
   5.866 -    const gchar *ns;
   5.867 -    const gchar *reason = "unknown reason";
   5.868 -
   5.869 -    ns = lm_message_node_get_attribute (message->node, "xmlns");
   5.870 -    if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH) != 0) {
   5.871 -        return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
   5.872 -    }
   5.873 -
   5.874 -    sasl = (LmSASL *) user_data;
   5.875 -
   5.876 -    if (message->node->children) {
   5.877 -        const gchar *r;
   5.878 -
   5.879 -        r = lm_message_node_get_value (message->node->children);
   5.880 -        if (r) {
   5.881 -            reason = r;
   5.882 -        }
   5.883 -    }
   5.884 -
   5.885 -    g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
   5.886 -           "%s: SASL authentication failed: %s", G_STRFUNC, reason);
   5.887 -
   5.888 -    if (sasl->handler) {
   5.889 -        sasl->handler (sasl, sasl->connection, FALSE, reason);
   5.890 -    }
   5.891 -
   5.892 -    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
   5.893 -}
   5.894 -
   5.895 -
   5.896 -static gboolean
   5.897 -sasl_start (LmSASL *sasl)
   5.898 -{
   5.899 -    LmMessage  *auth_msg;
   5.900 -    gboolean    result;
   5.901 -    const char *mech = NULL;
   5.902 -
   5.903 -    auth_msg = lm_message_new (NULL, LM_MESSAGE_TYPE_AUTH);
   5.904 -
   5.905 -    if (sasl->auth_type == AUTH_TYPE_PLAIN) {
   5.906 -        GString *str;
   5.907 -        gchar   *cstr;
   5.908 -
   5.909 -        str = g_string_new ("");
   5.910 -
   5.911 -        mech = "PLAIN";
   5.912 -        sasl->state = SASL_AUTH_STATE_PLAIN_STARTED;
   5.913 -
   5.914 -        if (sasl->auth_params == NULL) {
   5.915 -            g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
   5.916 -                   "%s: no authentication parameters provided",
   5.917 -                   G_STRFUNC);
   5.918 -            if (sasl->handler) {
   5.919 -                sasl->handler (sasl, sasl->connection, FALSE, "no username/password provided");
   5.920 -            }
   5.921 -
   5.922 -            return FALSE;
   5.923 -        }
   5.924 -
   5.925 -        g_string_append_c (str, '\0');
   5.926 -        g_string_append (str, lm_auth_parameters_get_username (sasl->auth_params));
   5.927 -        g_string_append_c (str, '\0');
   5.928 -        g_string_append (str, lm_auth_parameters_get_password (sasl->auth_params));
   5.929 -        cstr = g_base64_encode ((const guchar *) str->str,
   5.930 -                                (gsize) str->len);
   5.931 -
   5.932 -        lm_message_node_set_value (auth_msg->node, cstr);
   5.933 -
   5.934 -        g_string_free (str, TRUE);
   5.935 -        g_free (cstr);
   5.936 -
   5.937 -        /* Here we say the Google magic word. Bad Google. */
   5.938 -        lm_message_node_set_attributes (auth_msg->node,
   5.939 -                                        "xmlns:ga", "http://www.google.com/talk/protocol/auth",
   5.940 -                                        "ga:client-uses-full-bind-result", "true",
   5.941 -                                        NULL);
   5.942 -
   5.943 -    }
   5.944 -    else if (sasl->auth_type == AUTH_TYPE_DIGEST) {
   5.945 -        mech = "DIGEST-MD5";
   5.946 -        sasl->state = SASL_AUTH_STATE_DIGEST_MD5_STARTED;
   5.947 -    }
   5.948 -#ifdef HAVE_GSSAPI
   5.949 -    else if (sasl->auth_type == AUTH_TYPE_GSSAPI) {
   5.950 -        mech = "GSSAPI";
   5.951 -        sasl_gssapi_start (sasl, auth_msg->node);
   5.952 -    }
   5.953 -#endif
   5.954 -
   5.955 -    lm_message_node_set_attributes (auth_msg->node,
   5.956 -                                    "xmlns", XMPP_NS_SASL_AUTH,
   5.957 -                                    "mechanism", mech,
   5.958 -                                    NULL);
   5.959 -
   5.960 -    result = lm_connection_send (sasl->connection, auth_msg, NULL);
   5.961 -    lm_message_unref (auth_msg);
   5.962 -
   5.963 -    if (!result) {
   5.964 -        return FALSE;
   5.965 -    }
   5.966 -
   5.967 -    return TRUE;
   5.968 -}
   5.969 -
   5.970 -static gboolean
   5.971 -sasl_set_auth_type (LmSASL *sasl, LmMessageNode *mechanisms)
   5.972 -{
   5.973 -    LmMessageNode *m;
   5.974 -    const gchar   *ns;
   5.975 -
   5.976 -    sasl->auth_type = 0;
   5.977 -
   5.978 -    ns = lm_message_node_get_attribute (mechanisms, "xmlns");
   5.979 -    if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH) != 0) {
   5.980 -        return FALSE;
   5.981 -    }
   5.982 -
   5.983 -    for (m = mechanisms->children; m; m = m->next) {
   5.984 -        const gchar *name;
   5.985 -
   5.986 -        name = lm_message_node_get_value (m);
   5.987 -
   5.988 -        if (!name) {
   5.989 -            continue;
   5.990 -        }
   5.991 -        if (strcmp (name, "PLAIN") == 0) {
   5.992 -            sasl->auth_type |= AUTH_TYPE_PLAIN;
   5.993 -            continue;
   5.994 -        }
   5.995 -        if (strcmp (name, "DIGEST-MD5") == 0) {
   5.996 -            sasl->auth_type |= AUTH_TYPE_DIGEST;
   5.997 -            continue;
   5.998 -        }
   5.999 -#ifdef HAVE_GSSAPI
  5.1000 -        if (strcmp (name, "GSSAPI") == 0) {
  5.1001 -            sasl->auth_type |= AUTH_TYPE_GSSAPI;
  5.1002 -            continue;
  5.1003 -        }
  5.1004 -#endif
  5.1005 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
  5.1006 -               "%s: unknown SASL auth mechanism: %s", G_STRFUNC, name);
  5.1007 -    }
  5.1008 -
  5.1009 -    return TRUE;
  5.1010 -}
  5.1011 -
  5.1012 -static gboolean
  5.1013 -sasl_authenticate (LmSASL *sasl)
  5.1014 -{
  5.1015 -    if (sasl->auth_type == 0) {
  5.1016 -        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
  5.1017 -               "%s: no supported SASL auth mechanisms found",
  5.1018 -               G_STRFUNC);
  5.1019 -
  5.1020 -        return FALSE;
  5.1021 -    }
  5.1022 -
  5.1023 -    /* Prefer GSSAPI if available */
  5.1024 -#ifdef HAVE_GSSAPI
  5.1025 -    if (sasl->auth_type & AUTH_TYPE_GSSAPI) {
  5.1026 -        sasl->auth_type = AUTH_TYPE_GSSAPI;
  5.1027 -        return sasl_start (sasl);
  5.1028 -    }
  5.1029 -#endif
  5.1030 -    /* Otherwise prefer DIGEST */
  5.1031 -    else if (sasl->auth_type & AUTH_TYPE_DIGEST) {
  5.1032 -        sasl->auth_type = AUTH_TYPE_DIGEST;
  5.1033 -        return sasl_start (sasl);
  5.1034 -    }
  5.1035 -    else if (sasl->auth_type & AUTH_TYPE_PLAIN) {
  5.1036 -        sasl->auth_type = AUTH_TYPE_PLAIN;
  5.1037 -        return sasl_start (sasl);
  5.1038 -    }
  5.1039 -
  5.1040 -    return FALSE;
  5.1041 -}
  5.1042 -
  5.1043 -static LmHandlerResult
  5.1044 -sasl_features_cb (LmMessageHandler *handler,
  5.1045 -                  LmConnection     *connection,
  5.1046 -                  LmMessage        *message,
  5.1047 -                  gpointer          user_data)
  5.1048 -{
  5.1049 -    LmMessageNode *mechanisms;
  5.1050 -    LmSASL        *sasl;
  5.1051 -
  5.1052 -    g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL, "Stream features received\n");
  5.1053 -    mechanisms = lm_message_node_find_child (message->node, "mechanisms");
  5.1054 -    if (!mechanisms) {
  5.1055 -        return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
  5.1056 -    }
  5.1057 -
  5.1058 -    sasl = (LmSASL *) user_data;
  5.1059 -    sasl->features_received = TRUE;
  5.1060 -
  5.1061 -    sasl_set_auth_type (sasl, mechanisms);
  5.1062 -
  5.1063 -    if (sasl->start_auth) {
  5.1064 -        sasl_authenticate (sasl);
  5.1065 -    }
  5.1066 -
  5.1067 -    return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
  5.1068 -}
  5.1069 -
  5.1070 -LmSASL *
  5.1071 -lm_sasl_new (LmConnection *connection)
  5.1072 -{
  5.1073 -    LmSASL *sasl;
  5.1074 -
  5.1075 -    sasl = g_new0 (LmSASL, 1);
  5.1076 -
  5.1077 -    sasl->connection = connection;
  5.1078 -    sasl->features_received = FALSE;
  5.1079 -    sasl->start_auth = FALSE;
  5.1080 -
  5.1081 -    sasl->features_cb = lm_message_handler_new (sasl_features_cb,
  5.1082 -                                                sasl,
  5.1083 -                                                NULL);
  5.1084 -
  5.1085 -    lm_connection_register_message_handler (connection,
  5.1086 -                                            sasl->features_cb,
  5.1087 -                                            LM_MESSAGE_TYPE_STREAM_FEATURES,
  5.1088 -                                            LM_HANDLER_PRIORITY_LAST);
  5.1089 -    return sasl;
  5.1090 -}
  5.1091 -
  5.1092 -void
  5.1093 -lm_sasl_authenticate (LmSASL              *sasl,
  5.1094 -                      LmAuthParameters    *auth_params,
  5.1095 -                      const gchar         *server,
  5.1096 -                      LmSASLResultHandler  handler)
  5.1097 -{
  5.1098 -    sasl->auth_params = lm_auth_parameters_ref (auth_params);
  5.1099 -    sasl->server      = g_strdup (server);
  5.1100 -    sasl->handler     = handler;
  5.1101 -
  5.1102 -    sasl->challenge_cb = lm_message_handler_new (sasl_challenge_cb,
  5.1103 -                                                 sasl,
  5.1104 -                                                 NULL);
  5.1105 -    lm_connection_register_message_handler (sasl->connection,
  5.1106 -                                            sasl->challenge_cb,
  5.1107 -                                            LM_MESSAGE_TYPE_CHALLENGE,
  5.1108 -                                            LM_HANDLER_PRIORITY_FIRST);
  5.1109 -
  5.1110 -    sasl->success_cb = lm_message_handler_new (sasl_success_cb,
  5.1111 -                                               sasl,
  5.1112 -                                               NULL);
  5.1113 -    lm_connection_register_message_handler (sasl->connection,
  5.1114 -                                            sasl->success_cb,
  5.1115 -                                            LM_MESSAGE_TYPE_SUCCESS,
  5.1116 -                                            LM_HANDLER_PRIORITY_FIRST);
  5.1117 -
  5.1118 -    sasl->failure_cb = lm_message_handler_new (sasl_failure_cb,
  5.1119 -                                               sasl,
  5.1120 -                                               NULL);
  5.1121 -    lm_connection_register_message_handler (sasl->connection,
  5.1122 -                                            sasl->failure_cb,
  5.1123 -                                            LM_MESSAGE_TYPE_FAILURE,
  5.1124 -                                            LM_HANDLER_PRIORITY_FIRST);
  5.1125 -
  5.1126 -    if (sasl->features_received) {
  5.1127 -        sasl_authenticate (sasl);
  5.1128 -    } else {
  5.1129 -        sasl->start_auth = TRUE;
  5.1130 -    }
  5.1131 -}
  5.1132 -
  5.1133 -void
  5.1134 -lm_sasl_free (LmSASL *sasl)
  5.1135 -{
  5.1136 -    g_return_if_fail (sasl != NULL);
  5.1137 -
  5.1138 -    if (sasl->auth_params) {
  5.1139 -        lm_auth_parameters_unref (sasl->auth_params);
  5.1140 -    }
  5.1141 -
  5.1142 -    g_free (sasl->server);
  5.1143 -
  5.1144 -    if (sasl->features_cb) {
  5.1145 -        lm_connection_unregister_message_handler (sasl->connection,
  5.1146 -                                                  sasl->features_cb,
  5.1147 -                                                  LM_MESSAGE_TYPE_STREAM_FEATURES);
  5.1148 -    }
  5.1149 -
  5.1150 -    if (sasl->challenge_cb) {
  5.1151 -        lm_connection_unregister_message_handler (sasl->connection,
  5.1152 -                                                  sasl->challenge_cb,
  5.1153 -                                                  LM_MESSAGE_TYPE_CHALLENGE);
  5.1154 -    }
  5.1155 -
  5.1156 -    if (sasl->success_cb) {
  5.1157 -        lm_connection_unregister_message_handler (sasl->connection,
  5.1158 -                                                  sasl->success_cb,
  5.1159 -                                                  LM_MESSAGE_TYPE_SUCCESS);
  5.1160 -    }
  5.1161 -
  5.1162 -    if (sasl->failure_cb) {
  5.1163 -        lm_connection_unregister_message_handler (sasl->connection,
  5.1164 -                                                  sasl->failure_cb,
  5.1165 -                                                  LM_MESSAGE_TYPE_FAILURE);
  5.1166 -    }
  5.1167 -
  5.1168 -    g_free (sasl);
  5.1169 -}
  5.1170 -
  5.1171 -
  5.1172 -LmAuthParameters *
  5.1173 -lm_sasl_get_auth_params (LmSASL *sasl)
  5.1174 -{
  5.1175 -    return sasl->auth_params;
  5.1176 -}
  5.1177 -
     6.1 --- a/src/lm-sasl.h	Fri Dec 28 09:04:20 2012 -0500
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,55 +0,0 @@
     6.4 -/*
     6.5 - *  Copyright (C) 2012 Copyleft Games Group
     6.6 - *  Copyright (C) 2007 Collabora Ltd.
     6.7 - *
     6.8 - *  This program is free software; you can redistribute it and/or modify
     6.9 - *  it under the terms of the GNU Affero General Public License as published
    6.10 - *  by the Free Software Foundation, either version 3 of the License, or
    6.11 - *  (at your option) any later version.
    6.12 - *
    6.13 - *  This program is distributed in the hope that it will be useful,
    6.14 - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.15 - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.16 - *  GNU Affero General Public License for more details.
    6.17 - *
    6.18 - *  You should have received a copy of the GNU Affero General Public License
    6.19 - *  along with this program; if not, see http://www.gnu.org/licenses
    6.20 - *
    6.21 - */
    6.22 -
    6.23 -#ifndef __LM_SASL_H__
    6.24 -#define __LM_SASL_H__
    6.25 -
    6.26 -#if !defined (LM_INSIDE_LIGHTMELODY_H) && !defined (LM_COMPILATION)
    6.27 -#error "Only <lightmelody/lightmelody.h> can be included directly, this file may disappear or change contents."
    6.28 -#endif
    6.29 -
    6.30 -#include <glib.h>
    6.31 -
    6.32 -#include <lightmelody.h>
    6.33 -
    6.34 -G_BEGIN_DECLS
    6.35 -
    6.36 -typedef struct _LmSASL LmSASL;
    6.37 -
    6.38 -typedef void (*LmSASLResultHandler) (LmSASL               *sasl,
    6.39 -                                     LmConnection         *connection,
    6.40 -                                     gboolean              success,
    6.41 -                                     const gchar          *reason);
    6.42 -
    6.43 -LmSASL *           lm_sasl_new              (LmConnection         *connection);
    6.44 -
    6.45 -void               lm_sasl_authenticate     (LmSASL               *sasl,
    6.46 -                                             LmAuthParameters     *auth_params,
    6.47 -                                             const gchar          *server,
    6.48 -                                             LmSASLResultHandler   handler);
    6.49 -
    6.50 -void               lm_sasl_free             (LmSASL               *sasl);
    6.51 -
    6.52 -LmAuthParameters * lm_sasl_get_auth_params  (LmSASL               *sasl);
    6.53 -
    6.54 -
    6.55 -G_END_DECLS
    6.56 -
    6.57 -#endif /* __LM_SASL_H__ */
    6.58 -