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)) {