[Pkg-javascript-commits] [ltx] 17/469: oops, all this c2s auth stuff belongs into client not connection
Jonas Smedegaard
dr at jones.dk
Wed Aug 31 13:00:52 UTC 2016
This is an automated email from the git hooks/post-receive script.
js pushed a commit to branch master
in repository ltx.
commit 7baf775d990b227a07a939e7b7e9a289d914e7cb
Author: Astro <astro at spaceboyz.net>
Date: Sun May 30 16:38:56 2010 +0200
oops, all this c2s auth stuff belongs into client not connection
---
lib/xmpp/client.js | 143 ++++++++++++++++++++++++++++++++++++++++-
lib/xmpp/connection.js | 168 +++++++------------------------------------------
2 files changed, 163 insertions(+), 148 deletions(-)
diff --git a/lib/xmpp/client.js b/lib/xmpp/client.js
index 5831e02..5c71c0b 100644
--- a/lib/xmpp/client.js
+++ b/lib/xmpp/client.js
@@ -1,7 +1,23 @@
var Connection = require('./connection').Connection;
var JID = require('./jid').JID;
+var xml = require('./xml');
+var sasl = require('./sasl');
var sys = require('sys');
var dns = require('dns');
+var b64 = require('base64');
+
+var NS_XMPP_SASL = 'urn:ietf:params:xml:ns:xmpp-sasl';
+var NS_XMPP_BIND = 'urn:ietf:params:xml:ns:xmpp-bind';
+var NS_XMPP_SESSION = 'urn:ietf:params:xml:ns:xmpp-session';
+
+var STATE_PREAUTH = 0,
+ STATE_AUTH = 1,
+ STATE_AUTHED = 2,
+ STATE_BIND = 3,
+ STATE_SESSION = 4,
+ STATE_ONLINE = 5;
+var IQID_SESSION = 'sess',
+ IQID_BIND = 'bind';
/**
* params:
@@ -21,6 +37,8 @@ function Client(params) {
this.xmlns = "jabber:client";
this.xmppVersion = "1.0";
this.streamTo = this.jid.domain;
+ this.state = STATE_PREAUTH;
+ this.addListener('rawStanza', this.onRawStanza);
if (params.host) {
this.connect(params.port || 5222, params.host);
@@ -41,7 +59,11 @@ function Client(params) {
else
return 0;
});
- /* Design fail: */
+ /* Epic design fail: we cannot retry
+ with another SRV result because that
+ will confuse the user with
+ non-terminal 'error' & 'end' events.
+ */
self.connect(addrs[0].port, addrs[0].name);
}
});
@@ -50,3 +72,122 @@ function Client(params) {
sys.inherits(Client, Connection);
exports.Client = Client;
+
+Client.prototype.onRawStanza = function(stanza) {
+ /* Actually, we shouldn't wait for <stream:features/> if
+ this.streamAttrs.version is missing, but who uses pre-XMPP-1.0
+ these days anyway? */
+ if (this.state != STATE_ONLINE &&
+ stanza.name == 'stream:features') {
+ this.streamFeatures = stanza;
+ this.useFeatures();
+ } else if (this.state == STATE_AUTH) {
+ if (stanza.is('success', NS_XMPP_SASL)) {
+ this.state = STATE_AUTHED;
+ this.startStream();
+ } else {
+ this.emit('authFail');
+ this.end();
+ }
+ } else if (this.state == STATE_BIND &&
+ stanza.is('iq') &&
+ stanza.attrs.id == IQID_BIND) {
+ if (stanza.attrs.type == 'result') {
+ this.state = STATE_AUTHED;
+ this.did_bind = true;
+
+ var bindEl = stanza.getChild('bind', NS_XMPP_BIND);
+ if (bindEl && bindEl.getChild('jid')) {
+ this.jid = new JID(bindEl.getChild('jid').getText());
+ }
+
+ /* no stream restart, but next feature */
+ this.useFeatures();
+ } else {
+ this.emit('error', 'Cannot bind resource');
+ this.end();
+ }
+ } else if (this.state == STATE_SESSION &&
+ stanza.is('iq') &&
+ stanza.attrs.id == IQID_SESSION) {
+ if (stanza.attrs.type == 'result') {
+ this.state = STATE_AUTHED;
+ this.did_session = true;
+
+ /* no stream restart, but next feature (most probably
+ we'll go online next) */
+ this.useFeatures();
+ } else {
+ this.emit('error', 'Cannot bind resource');
+ this.end();
+ }
+ } else if (stanza.name == 'stream:error') {
+ this.emit('error', stanza);
+ this.end();
+ }
+};
+
+/**
+ * Either we just received <stream:features/>, or we just enabled a
+ * feature and are looking for the next.
+ */
+Connection.prototype.useFeatures = function() {
+ if (this.state == STATE_PREAUTH &&
+ this.streamFeatures.getChild('mechanisms', NS_XMPP_SASL)) {
+ this.state = STATE_AUTH;
+ var mech = selectAuthMechanism(this.streamFeatures.
+ getChild('mechanisms', NS_XMPP_SASL).
+ getChildren('mechanism', NS_XMPP_SASL).
+ map(function(el) { return el.getText(); }));
+ if (mech) {
+ mech.authzid = this.jid.bare().toString();
+ mech.authcid = this.jid.user;
+ mech.password = this.password;
+ this.send(new xml.Element('auth',
+ { xmlns: NS_XMPP_SASL,
+ mechanism: mech.name
+ }).t(b64.encode(mech.auth())));
+ } else {
+ this.emit('authFail');
+ this.end();
+ }
+ } else if (this.state == STATE_AUTHED &&
+ !this.did_bind &&
+ this.streamFeatures.getChild('bind', NS_XMPP_BIND)) {
+ this.state = STATE_BIND;
+ var bindEl = new xml.Element('iq',
+ { type: 'set',
+ id: IQID_BIND
+ }).c('bind',
+ { xmlns: NS_XMPP_BIND
+ });
+ if (this.jid.resource)
+ bindEl.c('resource').t(this.jid.resource);
+ this.send(bindEl);
+ } else if (this.state == STATE_AUTHED &&
+ !this.did_session &&
+ this.streamFeatures.getChild('session', NS_XMPP_SESSION)) {
+ this.state = STATE_SESSION;
+ this.send(new xml.Element('iq',
+ { type: 'set',
+ to: this.jid.domain,
+ id: IQID_SESSION
+ }).c('session',
+ { xmlns: NS_XMPP_SESSION
+ }));
+ } else if (this.state == STATE_AUTHED) {
+ /* Ok, we're authenticated and all features have been
+ processed */
+ this.state = STATE_ONLINE;
+ this.emit('online');
+ }
+};
+
+function selectAuthMechanism(mechs) {
+ /*if (mechs.indexOf("DIGEST-MD5") >= 0)
+ return "DIGEST-MD5";
+ else*/ if (mechs.indexOf("PLAIN") >= 0)
+ return new sasl.Mechanism("PLAIN");
+ else
+ return null;
+}
diff --git a/lib/xmpp/connection.js b/lib/xmpp/connection.js
index e671ede..af14f8f 100644
--- a/lib/xmpp/connection.js
+++ b/lib/xmpp/connection.js
@@ -2,29 +2,16 @@ var net = require('net');
var sys = require('sys');
var expat = require('expat');
var xml = require('./xml');
-var sasl = require('./sasl');
-var JID = require('./jid').JID;
-var b64 = require('base64');
var NS_XMPP_TLS = 'urn:ietf:params:xml:ns:xmpp-tls';
-var NS_XMPP_SASL = 'urn:ietf:params:xml:ns:xmpp-sasl';
-var NS_XMPP_BIND = 'urn:ietf:params:xml:ns:xmpp-bind';
-var NS_XMPP_SESSION = 'urn:ietf:params:xml:ns:xmpp-session';
-
-var STATE_PREAUTH = 0,
- STATE_TLS = 1,
- STATE_AUTH = 2,
- STATE_AUTHED = 3,
- STATE_BIND = 4,
- STATE_SESSION = 5,
- STATE_ONLINE = 6;
-var IQID_SESSION = 'sess',
- IQID_BIND = 'bind';
+/** A note on events: this base class will emit 'rawStanza' and leaves
+ 'stanza' to Client & Component. Therefore we won't confuse the
+ user with stanzas before authentication has finished.
+*/
function Connection() {
- net.Stream.call(this);
+net.Stream.call(this);
- this.state = STATE_PREAUTH;
this.charset = 'UTF-8';
this.allowTLS = true; /* can be set by user */
this.addListener('connect', this.startStream);
@@ -108,139 +95,26 @@ Connection.prototype.onData = function(data) {
};
/**
- * This is not an event listener, but takes care of the authentication
- * before 'stanza' events are emitted to the user.
+ * This is not an event listener, but takes care of the TLS handshake
+ * before 'rawStanza' events are emitted to the derived classes.
*/
Connection.prototype.onStanza = function(stanza) {
- if (this.state == STATE_ONLINE) {
- this.emit('stanza', this.element);
- } else if (stanza.name == 'stream:features') {
- this.streamFeatures = stanza;
- this.useFeatures();
- } else if (this.state == STATE_TLS) {
- if (stanza.is('proceed', NS_XMPP_TLS)) {
- this.setSecure();
- this.addListener('secure',
- function() {
- this.state = STATE_PREAUTH;
- this.startStream();
- });
- } else {
- this.emit('error', 'Cannot begin TLS handshake');
- this.end();
- }
- } else if (this.state == STATE_AUTH) {
- if (stanza.is('success', NS_XMPP_SASL)) {
- this.state = STATE_AUTHED;
- this.startStream();
- } else {
- this.emit('authFail');
- this.end();
- }
- } else if (this.state == STATE_BIND &&
- stanza.is('iq') &&
- stanza.attrs.id == IQID_BIND) {
- if (stanza.attrs.type == 'result') {
- this.state = STATE_AUTHED;
- this.did_bind = true;
-
- var bindEl = stanza.getChild('bind', NS_XMPP_BIND);
- if (bindEl && bindEl.getChild('jid')) {
- this.jid = new JID(bindEl.getChild('jid').getText());
- }
-
- /* no stream restart, but next feature */
- this.useFeatures();
- } else {
- this.emit('error', 'Cannot bind resource');
- this.end();
- }
- } else if (this.state == STATE_SESSION &&
- stanza.is('iq') &&
- stanza.attrs.id == IQID_SESSION) {
- if (stanza.attrs.type == 'result') {
- this.state = STATE_AUTHED;
- this.did_session = true;
-
- /* no stream restart, but next feature (most probably
- we'll go online next) */
- this.useFeatures();
- } else {
- this.emit('error', 'Cannot bind resource');
- this.end();
- }
- } else if (stanza.name == 'stream:error') {
+ if (stanza.name == 'stream:error') {
+ /* TODO: extract error text */
this.emit('error', stanza);
- this.end();
- }
-};
-
-/**
- * Either onStanza just received <stream:features/>, or we just
- * enabled a feature and are looking for the next.
- */
-Connection.prototype.useFeatures = function() {
- if (this.allowTLS &&
- this.state == STATE_PREAUTH &&
- this.streamFeatures.getChild('starttls', NS_XMPP_TLS)) {
- this.state = STATE_TLS;
+ } else if (stanza.name == 'stream:features' &&
+ this.allowTLS &&
+ stanza.getChild('starttls', NS_XMPP_TLS)) {
+ /* Signal willingness to perform TLS handshake */
this.send(new xml.Element('starttls', { xmlns: NS_XMPP_TLS }));
- } else if (this.state == STATE_PREAUTH &&
- this.streamFeatures.getChild('mechanisms', NS_XMPP_SASL)) {
- this.state = STATE_AUTH;
- var mech = selectAuthMechanism(this.streamFeatures.
- getChild('mechanisms', NS_XMPP_SASL).
- getChildren('mechanism', NS_XMPP_SASL).
- map(function(el) { return el.getText(); }));
- if (mech) {
- mech.authzid = this.jid.bare().toString();
- mech.authcid = this.jid.user;
- mech.password = this.password;
- this.send(new xml.Element('auth',
- { xmlns: NS_XMPP_SASL,
- mechanism: mech.name
- }).t(b64.encode(mech.auth())));
- } else {
- this.emit('authFail');
- this.end();
- }
- } else if (this.state == STATE_AUTHED &&
- !this.did_bind &&
- this.streamFeatures.getChild('bind', NS_XMPP_BIND)) {
- this.state = STATE_BIND;
- var bindEl = new xml.Element('iq',
- { type: 'set',
- id: IQID_BIND
- }).c('bind',
- { xmlns: NS_XMPP_BIND
- });
- if (this.jid.resource)
- bindEl.c('resource').t(this.jid.resource);
- this.send(bindEl);
- } else if (this.state == STATE_AUTHED &&
- !this.did_session &&
- this.streamFeatures.getChild('session', NS_XMPP_SESSION)) {
- this.state = STATE_SESSION;
- this.send(new xml.Element('iq',
- { type: 'set',
- to: this.jid.domain,
- id: IQID_SESSION
- }).c('session',
- { xmlns: NS_XMPP_SESSION
- }));
- } else if (this.state == STATE_AUTHED) {
- /* Ok, we're authenticated and all features have been
- processed */
- this.state = STATE_ONLINE;
- this.emit('online');
+ } else if (this.allowTLS &&
+ stanza.is('proceed', NS_XMPP_TLS)) {
+ /* Server is waiting for TLS handshake */
+ this.setSecure();
+ this.addListener('secure', this.startStream);
+ } else {
+ this.emit('rawStanza', stanza);
}
};
-function selectAuthMechanism(mechs) {
- /*if (mechs.indexOf("DIGEST-MD5") >= 0)
- return "DIGEST-MD5";
- else*/ if (mechs.indexOf("PLAIN") >= 0)
- return new sasl.Mechanism("PLAIN");
- else
- return null;
-}
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/ltx.git
More information about the Pkg-javascript-commits
mailing list