From cfbd6c8827b6ed1bec3bfb76e1a33cd410917523 Mon Sep 17 00:00:00 2001
From: "psyc://psyced.org/~lynX" <@>
Date: Tue, 2 Nov 2010 15:26:43 +0100
Subject: [PATCH] fippo contributes support for bidirectional xmpp s2s.. try it
out using #define XMPP_BIDI
---
world/net/include/net.h | 1 +
world/net/jabber/active.c | 68 +++++++++++++++++++++++++++++-
world/net/jabber/gateway.c | 77 +++++++++++++++++++++++++++++++++-
world/net/jabber/interserver.c | 4 ++
4 files changed, 147 insertions(+), 3 deletions(-)
diff --git a/world/net/include/net.h b/world/net/include/net.h
index d31a5a3..38b013d 100644
--- a/world/net/include/net.h
+++ b/world/net/include/net.h
@@ -233,6 +233,7 @@
#endif
#ifdef EXPERIMENTAL
+# define XMPP_BIDI
# define USE_AUTOALIAS
// fippo's brilliant single-user channel emulation for jabber MUCs
// unfortunately it provides no advantages over the old method, yet.
diff --git a/world/net/jabber/active.c b/world/net/jabber/active.c
index 65dd116..84c934b 100644
--- a/world/net/jabber/active.c
+++ b/world/net/jabber/active.c
@@ -11,6 +11,10 @@
#endif
inherit NET_PATH "jabber/mixin_render";
+#ifdef XMPP_BIDI
+inherit NET_PATH "jabber/mixin_parse";
+#endif
+
// a derivate of circuit which knows JABBER
inherit NET_PATH "circuit";
@@ -157,6 +161,13 @@ handle_stream_features(XMLNode node) {
return;
}
#endif
+#ifdef XMPP_BIDI
+ if (node["/bidi"] && node["/bidi"]["@xmlns"] == "urn:xmpp:features:bidi") {
+ emitraw("");
+ // we don't expect a reply
+ bidi = 1;
+ }
+#endif
#ifdef WANT_S2S_SASL
// possibly authenticated via sasl?
if (authenticated && !node["/switch"]) {
@@ -360,6 +371,9 @@ jabberMsg(XMLNode node) {
P2(("%O jabber/active got %O\n", ME, node[Tag]))
object o;
string t;
+#ifdef XMPP_BIDI
+ mixed su, tu;
+#endif
switch (node[Tag]) {
case "db:result":
/* 10: Receiving Server informs Originating Server of the result
@@ -374,6 +388,9 @@ jabberMsg(XMLNode node) {
D0( log_file("XMPP_AUTH", "\n%O auth dialback", ME); )
#endif
authenticated = 1;
+#ifdef XMPP_BIDI
+ // sAuthenticated?
+#endif
runQ();
} else {
// else: queue failed
@@ -475,9 +492,58 @@ jabberMsg(XMLNode node) {
o -> logon();
destruct(ME);
return;
+#endif
+#ifdef XMPP_BIDI
+ case "message":
+ case "presence":
+ case "iq":
+ if (!authenticated) {
+ // we have not authenticated with either sasl or dialback
+ P2(("xmpp bidi: we have not authenticated with either sasl or dialback\n"))
+ STREAM_ERROR("invalid-from", "")
+ return;
+ }
+ if (!bidi) {
+ P2(("xmpp bidi: we have not enabled bidi, so why...\n"))
+ STREAM_ERROR("invalid-from", "")
+ return;
+ }
+ // check from and to!
+ // for from: == hostname
+ P2(("xmpp bidi from %O to %O\n", node["@from"], node["@to"]))
+ su = parse_uniform(XMPP + node["@from"]);
+ unless (su) {
+ // jid-malformed?
+ P2(("xmpp bidi: could not parse su for %O", node["@from"]))
+ return;
+ }
+ // qAuthenticated(su[UHost]) ?
+ P2(("xmpp bidi: from host = %O, hostname = %O\n", su[UHost], hostname))
+ unless (su[UHost] == hostname) {
+ P2(("xmpp bidi: source host %O != hostname %O\n", su[UHost], hostname))
+ STREAM_ERROR("invalid-from", "")
+ return;
+ }
+
+ // for to: is_localhost
+ tu = parse_uniform(XMPP + node["@to"]);
+ unless (tu) {
+ // jid-malformed?
+ P2(("xmpp bidi: could not parse tu for %O", node["@to"]))
+ STREAM_ERROR("invalid-from", "")
+ return;
+ }
+ P2(("is_localhost(%O) = %O\n", tu[UHost], is_localhost(tu[UHost])))
+ if (!is_localhost(tu[UHost])) {
+ // ... ?
+ P2(("xmpp bidi: !is_localhost %O\n", node["@to"]))
+ STREAM_ERROR("invalid-from", "")
+ return;
+ }
+ return ::jabberMsg(node);
#endif
default:
- P0(("%O: unexpected %O:%O\n", ME, node["@tag"],
+ P0(("%O: unexpected %O:%O\n", ME, node[Tag],
node["@xmlns"]))
break;
}
diff --git a/world/net/jabber/gateway.c b/world/net/jabber/gateway.c
index 2ed5b28..3c889bb 100644
--- a/world/net/jabber/gateway.c
+++ b/world/net/jabber/gateway.c
@@ -18,6 +18,9 @@
inherit NET_PATH "trust";
inherit NET_PATH "jabber/mixin_parse";
+#ifdef XMPP_BIDI
+inherit NET_PATH "jabber/mixin_render";
+#endif
//inherit NET_PATH "storage";
volatile object active; // currently unused, but you could send w() to it
@@ -41,6 +44,7 @@ volatile string streamfrom;
volatile string resource;
volatile mapping certinfo;
+
v(a, b) {
PT(("%O v(%O, %O)\n", ME, a, b))
return "";
@@ -139,6 +143,12 @@ verify_connection(string to, string from, string type) {
D0( log_file("XMPP_AUTH", "\n%O has authenticated %O via dialback", ME, from); )
#endif
sAuthenticated(from);
+#ifdef XMPP_BIDI
+ if (bidi) {
+ P0(("doing register target for xmpp bidi!!!!\n"))
+ register_target(XMPP + from);
+ }
+#endif
while (remove_call_out(#'quit) != -1);
}
}
@@ -202,6 +212,9 @@ jabberMsg(XMLNode node) {
|| node[Tag] == "auth"
#ifdef SWITCH2PSYC
|| node[Tag] == "switching"
+#endif
+#ifdef XMPP_BIDI
+ || node[Tag] == "bidi"
#endif
|| node[Tag] == "starttls") ) {
// apparently we are the only jabber server to complain about it
@@ -235,6 +248,14 @@ jabberMsg(XMLNode node) {
o -> sAuthHosts(authhosts);
destruct(ME);
return;
+#endif
+#ifdef XMPP_BIDI
+ case "bidi":
+ if (node["@xmlns"] == "urn:xmpp:bidi") {
+ //emit("");
+ bidi = 1;
+ }
+ return;
#endif
case "db:result":
target = NAMEPREP(target);
@@ -263,7 +284,7 @@ jabberMsg(XMLNode node) {
// protect against stolen certificates
if (mappingp(certinfo) && certinfo[0] == 0
&& node["@from"] && certificate_check_jabbername(node["@from"], certinfo)) {
- P2(("dialback without dialback %O\n", certinfo))
+ P0(("dialback without dialback %O\n", certinfo))
verify_connection(node["@to"], node["@from"], "valid");
} else {
sendmsg(origin,
@@ -382,6 +403,13 @@ jabberMsg(XMLNode node) {
P2(("successful sasl external authentication with "
"%O\n", t))
sAuthenticated(t);
+ while (remove_call_out(#'quit) != -1);
+#ifdef XMPP_BIDI
+ if (bidi) {
+ P0(("doing register target for xmpp bidi!!!!\n"))
+ register_target(XMPP + t);
+ }
+#endif
# ifdef LOG_XMPP_AUTH
D0( log_file("XMPP_AUTH", "\n%O has authenticated %O via SASL external", ME, t); )
# endif
@@ -491,7 +519,8 @@ open_stream(XMLNode node) {
// and we have verified it as X509_V_OK (0)
// we offer SASL external (authentication via name
// presented in x509 certificate
- P3(("gateway::certinfo %O\n", certinfo))
+ PT(("gateway::certinfo %O\n", certinfo))
+ P0(("gateway::certinfo valid %d\n", certinfo[0]))
# ifndef DIALBACK_WITHOUT_DIAL_BACK
if (mappingp(certinfo) && certinfo[0] == 0) {
// if from attribute is present we only offer
@@ -513,6 +542,9 @@ open_stream(XMLNode node) {
packet += ""
"psyc"
"";
+#endif
+#ifdef XMPP_BIDI
+ packet += "";
#endif
packet += "";
} else {
@@ -533,3 +565,44 @@ w(string mc, string data, mapping vars, mixed source) {
vars["_INTERNAL_source_jabber"] = objectp(source) ? mkjid(source) : _host_XMPP;
sendmsg(origin, mc, data, vars);
}
+
+#ifdef XMPP_BIDI
+int msg(string source, string mc, string data,
+ mapping vars, int showingLog, string target) {
+ // copy+paste stuff from active.c
+ vars = copy(vars);
+#ifdef DEFLANG
+ unless(vars["_language"]) vars["_language"] = DEFLANG;
+#else
+ unless(vars["_language"]) vars["_language"] = "en";
+#endif
+ /* another note:
+ * instead of queuing the msg()-calls we could simply queue
+ * the output from emit (use the new net/outputb ?)
+ * this avoids bugs with destructed objects
+ */
+#if 0 // !EXPERIMENTAL
+ /* currently, we want _status_person_absent
+ * this may change...
+ */
+ else if (abbrev("_status_person_absent", mc)) return 1;
+#endif
+ switch (mc){
+ case "_message_echo_private":
+ return 1;
+ }
+ // desperate hack
+ unless (vars["_INTERNAL_mood_jabber"])
+ vars["_INTERNAL_mood_jabber"] = "neutral";
+ if (abbrev("_dialback", mc)) {
+ P0(("gateway got dialback method %O, this should not happen...\n", mc))
+ return 1;
+ }
+
+ determine_sourcejid(source, vars);
+ determine_targetjid(target, vars);
+ if (vars["_place"]) vars["_place"] = mkjid(vars["_place"]);
+ // end of copy+paste from active
+ return ::msg(source, mc, data, vars, showingLog, target);
+}
+#endif
diff --git a/world/net/jabber/interserver.c b/world/net/jabber/interserver.c
index c6aeb7d..9c7758b 100644
--- a/world/net/jabber/interserver.c
+++ b/world/net/jabber/interserver.c
@@ -6,6 +6,10 @@
volatile int flags = 0;
+#ifdef XMPP_BIDI
+volatile int bidi; // is this stream bidirectional?
+#endif
+
reboot(reason, restart, pass) {
if (pass == 0) {
if (interactive(ME)) {