void Gobby::AuthCommands::on_response(int response_id, InfSaslContextSession* session, InfXmppConnection* xmpp) { RetryMap::iterator i = m_retries.find(xmpp); g_assert(i != m_retries.end()); RetryInfo& info(i->second); if(response_id == Gtk::RESPONSE_ACCEPT) info.last_password = info.password_dialog->get_password(); else info.last_password = ""; delete info.password_dialog; info.password_dialog = NULL; ++info.retries; if(info.last_password.empty()) { inf_sasl_context_session_continue(session, GSASL_NO_PASSWORD); } else { inf_sasl_context_session_set_property( session, GSASL_PASSWORD, info.last_password.c_str()); inf_sasl_context_session_continue(session, GSASL_OK); } }
static void infd_xmpp_server_sasl_cb(InfSaslContextSession* session, Gsasl_property property, gpointer session_data, gpointer user_data) { InfdXmppServer* xmpp; InfdXmppServerPrivate* priv; xmpp = INFD_XMPP_SERVER(user_data); priv = INFD_XMPP_SERVER_PRIVATE(xmpp); switch(property) { case GSASL_ANONYMOUS_TOKEN: inf_sasl_context_session_set_property( session, GSASL_ANONYMOUS_TOKEN, priv->local_hostname ); inf_sasl_context_session_continue(session, GSASL_OK); break; case GSASL_VALIDATE_ANONYMOUS: /* Authentaction always successful */ inf_sasl_context_session_continue(session, GSASL_OK); break; default: /* This is only used when using built-in SASL context, and this one * only supports anonymous authentication. */ g_assert_not_reached(); inf_sasl_context_session_continue(session, GSASL_NO_CALLBACK); break; } }
void Gobby::AuthCommands::sasl_callback(InfSaslContextSession* session, InfXmppConnection* xmpp, Gsasl_property prop) { const Glib::ustring username = m_preferences.user.name; const std::string correct_password = m_preferences.user.password; const char* password; gsize password_len; gchar cmp; switch(prop) { case GSASL_ANONYMOUS_TOKEN: inf_sasl_context_session_set_property( session, GSASL_ANONYMOUS_TOKEN, username.c_str()); inf_sasl_context_session_continue(session, GSASL_OK); break; case GSASL_AUTHID: inf_sasl_context_session_set_property( session, GSASL_AUTHID, username.c_str()); inf_sasl_context_session_continue(session, GSASL_OK); break; case GSASL_PASSWORD: { RetryMap::iterator i = m_retries.find(xmpp); if(i == m_retries.end()) i = insert_retry_info(xmpp); RetryInfo& info(i->second); if(!info.last_password.empty()) { inf_sasl_context_session_set_property( session, GSASL_PASSWORD, info.last_password.c_str()); inf_sasl_context_session_continue(session, GSASL_OK); } else { // Query user for password g_assert(info.password_dialog == NULL); gchar* remote_id; g_object_get(G_OBJECT(xmpp), "remote-hostname", &remote_id, NULL); Glib::ustring remote_id_(remote_id); g_free(remote_id); info.password_dialog = new PasswordDialog( m_parent, remote_id_, info.retries); info.password_dialog->add_button( _("_Cancel"), Gtk::RESPONSE_CANCEL); info.password_dialog->add_button( _("_Ok"), Gtk::RESPONSE_ACCEPT); Gtk::Dialog& dialog = *info.password_dialog; dialog.signal_response().connect(sigc::bind( sigc::mem_fun( *this, &AuthCommands::on_response), session, xmpp)); info.password_dialog->present(); } } break; case GSASL_VALIDATE_ANONYMOUS: if(m_preferences.user.require_password) { inf_sasl_context_session_continue( session, GSASL_AUTHENTICATION_ERROR ); set_sasl_error(xmpp, _("Password required")); } else { inf_sasl_context_session_continue(session, GSASL_OK); } break; case GSASL_VALIDATE_SIMPLE: password = inf_sasl_context_session_get_property( session, GSASL_PASSWORD); /* length-independent string compare */ cmp = 0; password_len = strlen(password); for(unsigned i = 0; i < correct_password.size(); ++i) { if(i < password_len) cmp |= (password[i] ^ correct_password[i]); else cmp |= (0x00 ^ correct_password[i]); } if(password_len != correct_password.size()) cmp = 0xFF; if(cmp != 0) { inf_sasl_context_session_continue( session, GSASL_AUTHENTICATION_ERROR ); set_sasl_error(xmpp, _("Incorrect password")); } else { inf_sasl_context_session_continue(session, GSASL_OK); } break; default: inf_sasl_context_session_continue(session, GSASL_NO_CALLBACK); break; } }