From 25734947cbdba190859fe9d46d03e933efdd3284 Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Tue, 26 Jul 2011 12:29:19 +0200 Subject: [PATCH 1/8] _flag_disable_unauthenticated_users --- world/net/include/net.h | 7 ++++++- world/net/jabber/disco.c | 2 +- world/net/jabber/server.c | 10 +++++----- world/net/jabber/user.c | 2 +- world/net/person.c | 2 +- world/net/root.c | 2 +- world/net/server.c | 6 +++--- 7 files changed, 18 insertions(+), 13 deletions(-) diff --git a/world/net/include/net.h b/world/net/include/net.h index 0c7fa5d..6f731c1 100644 --- a/world/net/include/net.h +++ b/world/net/include/net.h @@ -138,8 +138,13 @@ # define NO_NEWBIES #endif +#ifdef REGISTERED_USERS_ONLY +# echo Please fix your #define REGISTERED_USERS_ONLY +# define _flag_disable_unauthenticated_users +#endif + #ifdef RELAY -# define NO_NEWBIES // same as REGISTERED_USERS_ONLY ? +# define NO_NEWBIES // same as _flag_disable_unauthenticated_users ? // anyway, chance for some ifdef optimizations TODO # define IRCGATE_NICK "PSYC.EU" # undef DEFAULT_USER_OBJECT diff --git a/world/net/jabber/disco.c b/world/net/jabber/disco.c index 757e42f..c6363cb 100644 --- a/world/net/jabber/disco.c +++ b/world/net/jabber/disco.c @@ -18,7 +18,7 @@ disco_info_root(vars) { string featurelist; featurelist = "" -#ifndef REGISTERED_USERS_ONLY +#ifndef _flag_disable_unauthenticated_users # ifndef _flag_disable_registration # ifndef _flag_disable_registration_XMPP "" diff --git a/world/net/jabber/server.c b/world/net/jabber/server.c index db1d43c..a313651 100644 --- a/world/net/jabber/server.c +++ b/world/net/jabber/server.c @@ -187,7 +187,7 @@ jabberMsg(XMLNode node) { case "jabber:iq:register": if (node["@type"] == "get"){ string packet; -#if defined(REGISTERED_USERS_ONLY) || defined(_flag_disable_registration) || defined(_flag_disable_registration_XMPP) +#if defined(_flag_disable_unauthenticated_users) || defined(_flag_disable_registration) || defined(_flag_disable_registration_XMPP) // super dirty.. this should all be in textdb packet = sprintf("" "" @@ -234,7 +234,7 @@ jabberMsg(XMLNode node) { emit(packet); // QUIT } else { -#if defined(REGISTERED_USERS_ONLY) || defined(_flag_disable_registration) || defined(_flag_disable_registration_XMPP) +#if defined(_flag_disable_unauthenticated_users) || defined(_flag_disable_registration) || defined(_flag_disable_registration_XMPP) // TODO: generate some error as above #else user -> vSet("password", t[Cdata]); @@ -358,7 +358,7 @@ jabberMsg(XMLNode node) { # endif break; #endif -#ifndef REGISTERED_USERS_ONLY +#ifndef _flag_disable_unauthenticated_users case "ANONYMOUS": unless(node[Cdata]) { SASL_ERROR("incorrect-encoding") @@ -481,7 +481,7 @@ open_stream(XMLNode node) { "DIGEST-MD5" #endif "PLAIN"; -#ifndef REGISTERED_USERS_ONLY +#ifndef _flag_disable_unauthenticated_users // sasl anonymous "ANONYMOUS"; #endif @@ -494,7 +494,7 @@ open_stream(XMLNode node) { #endif features += ""; features += ""; -#ifndef REGISTERED_USERS_ONLY +#ifndef _flag_disable_unauthenticated_users features += ""; #endif } diff --git a/world/net/jabber/user.c b/world/net/jabber/user.c index 2d70d71..4f43422 100644 --- a/world/net/jabber/user.c +++ b/world/net/jabber/user.c @@ -626,7 +626,7 @@ iq(XMLNode node) { break; } break; -#if !defined(REGISTERED_USERS_ONLY) && !defined(_flag_disable_registration) && !defined(_flag_disable_registration_XMPP) +#if !defined(_flag_disable_unauthenticated_users) && !defined(_flag_disable_registration) && !defined(_flag_disable_registration_XMPP) case "jabber:iq:register": switch(node["@type"]) { case "get": diff --git a/world/net/person.c b/world/net/person.c index a2ce76c..bf6af3a 100644 --- a/world/net/person.c +++ b/world/net/person.c @@ -756,7 +756,7 @@ checkPassword(try, method, salt, args, cb, varargs cbargs) { #endif // why here? //while (remove_call_out(#'quit) != -1); -#ifndef REGISTERED_USERS_ONLY +#ifndef _flag_disable_unauthenticated_users # ifdef AUTH_HMAC_SECRET if (IS_NEWBIE && method != "hmac-sha1-shared") ARETURN(1) # else diff --git a/world/net/root.c b/world/net/root.c index 585c0e0..51a0b93 100644 --- a/world/net/root.c +++ b/world/net/root.c @@ -55,7 +55,7 @@ msg(source, mc, data, vars, showingLog, target) { "version", // _tab "time", "lasttime" #endif -#if !defined(REGISTERED_USERS_ONLY) && !defined(_flag_disable_registration) &&!defined(_flag_disable_registration_XMPP) +#if !defined(_flag_disable_unauthenticated_users) && !defined(_flag_disable_registration) &&!defined(_flag_disable_registration_XMPP) "registration", #endif #ifndef VOLATILE diff --git a/world/net/server.c b/world/net/server.c index 324bb11..80f0e29 100644 --- a/world/net/server.c +++ b/world/net/server.c @@ -81,7 +81,7 @@ hello(ni, elm, try, method, salt) { ni, try, elm); } -#ifdef REGISTERED_USERS_ONLY // TODO: rename into a _flag +#ifdef _flag_disable_unauthenticated_users ohYeah(whatever) { input_to(#'ohYeah, input_to_settings); // input ignore warning? inverting mc's is really a good idea! @@ -120,7 +120,7 @@ authChecked(int result, ni, try, elm) { // return; // } } -#ifdef REGISTERED_USERS_ONLY +#ifdef _flag_disable_unauthenticated_users else { if (user -> isNewbie()) { #ifdef PSYC_SYNCHRONIZE @@ -157,7 +157,7 @@ authChecked(int result, ni, try, elm) { return promptForPassword(user); #endif } -#ifndef REGISTERED_USERS_ONLY +#ifndef _flag_disable_unauthenticated_users // added user->isNewbie() check for ircers if (user->online() && user->isNewbie() #ifdef _flag_log_hosts From 2423c3adc5d1a19228677e5093e89d5f923d776d Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Tue, 26 Jul 2011 14:30:41 +0200 Subject: [PATCH 2/8] _flag_disable_authorization --- world/net/include/net.h | 5 ++--- world/net/include/person.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/world/net/include/net.h b/world/net/include/net.h index 6f731c1..c47bf56 100644 --- a/world/net/include/net.h +++ b/world/net/include/net.h @@ -135,7 +135,7 @@ #endif #ifdef MUD -# define NO_NEWBIES +# define _flag_disable_authorization #endif #ifdef REGISTERED_USERS_ONLY @@ -144,8 +144,7 @@ #endif #ifdef RELAY -# define NO_NEWBIES // same as _flag_disable_unauthenticated_users ? - // anyway, chance for some ifdef optimizations TODO +# define _flag_disable_authorization # define IRCGATE_NICK "PSYC.EU" # undef DEFAULT_USER_OBJECT # define DEFAULT_USER_OBJECT IRC_PATH "ghost" diff --git a/world/net/include/person.h b/world/net/include/person.h index 4eaa3c5..f5d0f43 100644 --- a/world/net/include/person.h +++ b/world/net/include/person.h @@ -39,7 +39,7 @@ # define ONLINE (ME && (interactive(ME) || (member(v("locations"), 0) && sizeof(v("locations")[0])))) #endif -#ifdef NO_NEWBIES +#ifdef _flag_disable_authorization # define IS_NEWBIE 0 #else # define IS_NEWBIE (!v("password")) From 61ef5ce041ec2c4d79bc66ac5ec60b02af102e44 Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Sun, 31 Jul 2011 10:33:35 +0200 Subject: [PATCH 3/8] fippo implements sender_verification --- world/net/psyc/library.i | 3 + world/net/spyc/circuit.c | 162 ++++++++++++++++++--------------------- world/net/spyc/server.c | 33 +++++--- world/net/trust.c | 2 + 4 files changed, 101 insertions(+), 99 deletions(-) diff --git a/world/net/psyc/library.i b/world/net/psyc/library.i index c7b8b4f..538ca4d 100644 --- a/world/net/psyc/library.i +++ b/world/net/psyc/library.i @@ -343,6 +343,9 @@ int psyc_sendmsg(mixed target, string mc, mixed data, mapping vars, // nothing else is possible, but some clients may // no longer be able to connect to you... } +#ifdef USE_SPYC + o -> sender_verification(SERVER_UNIFORM, u[URoot]); +#endif register_target($4, o); register_target(psychopo, o); register_target(psycippo, o); diff --git a/world/net/spyc/circuit.c b/world/net/spyc/circuit.c index e65f5d5..a9a053a 100644 --- a/world/net/spyc/circuit.c +++ b/world/net/spyc/circuit.c @@ -38,6 +38,7 @@ mapping outstate; mapping legal_senders; +array(mixed) verify_queue = ({ }); volatile int flags = 0; @@ -74,24 +75,26 @@ varargs mixed croak(string mc, string data, vamapping vars, vamixed source) { return 0; } -#ifdef USE_VERIFICATION // request sender authentication and/or target acknowledgement // from the remote side -void sender_verification(array(string) sourcehosts, array(string) targethosts) +void sender_verification(string sourcehost, mixed targethost) { - // FIXME: wrong variables here - mapping vars = ([ "_list_sources_hosts" : sourcehosts, - "_list_targets_hosts" : targethosts, - "_tag" : RANDHEXSTRING ]); - // assumption: we have already resolved all targethosts and - // they point to the remote ip - foreach(string ho : targethosts) { - sAuthenticated(ho); + unless(interactive()) { + verify_queue += ({ ({ sourcehost, targethost }) }); + return; } - - msg(0, "_request_verification", 0, vars); + mapping vars = ([ "_uniform_source" : sourcehost, + "_uniform_target" : targethost, + "_tag" : RANDHEXSTRING ]); + P0(("sender_verification(%O, %O)\n", sourcehost, targethost)) + // since we send packets to them we should trust them to + // send packets to us, eh? + if (stringp(targethost)) { + targethost = parse_uniform(targethost); + } + sAuthenticated(targethost[UHost]); + msg(0, "_request_authorization", 0, vars); } -#endif // gets called during socket logon int logon(int failure) { @@ -161,20 +164,12 @@ int logon(int failure) { // FIXME unless(isServer()) { emit("|\n"); // initial greeting -#ifdef USE_FEATURES - // we have no features to request or offer - msg(0, "_request_features", 0); -#else -# ifdef USE_VERIFICATION - // start hostname verification - // rather: look at Q and look for the hostnames we need - sender_verification(({ SERVER_HOST }), ({ peerhost })); -# else - if (function_exists("runQ")) { - runQ(); + if (sizeof(verify_queue)) { + foreach(mixed t : verify_queue) { + sender_verification(t[0], t[1]); + } + verify_queue = ({ }); } -# endif -#endif } return 1; } @@ -209,74 +204,66 @@ first_response() { // receives a msg from the remote side // note: this is circuit-messaging void circuit_msg(string mc, mapping vars, string data) { + mapping rv = ([ ]); + mixed *u; switch(mc) { - case "_request_verification": - if (tls_query_connection_state(ME) == 0) { - array(string) targethosts = ({ }); - foreach(string ho : vars["_list_targets_hosts"]) { - if (is_localhost(ho)) { - targethosts += ({ ho }); - } - } - if (sizeof(vars["_list_sources_hosts"]) == 1) { - // doing multiple resolutions in parallel is more complicated - string ho = vars["_list_sources_hosts"][0]; - if (qAuthenticated(ho)) { - P0(("warning: trying to reverify authenticated host %O",ho)) - } else { - dns_resolve(ho, (: - // FIXME: psyc/parse::deliver is much better here - mixed rv = (["_list_targets_accepted_hosts":targethosts]); + case "_request_authorization": + if (vars["_tag"]) { + rv["_tag_relay"] = vars["_tag"]; + } + if (!vars["_uniform_source"] && vars["_uniform_target"]) { + CIRCUITERROR("_request_authorization without uniform source and/or target?!"); + } - if (vars["_tag"]) rv["_tag_reply"] = vars["_tag"]; - if ($1 == peerip) { - sAuthenticated(NAMEPREP(ho)); - rv["_list_sources_verified_hosts"] = ({ ho }); - } else { - rv["_list_sources_rejected_hosts"] = ({ ho }); - } - msg(0, "_notice_verification", 0, rv); - return; - :)); + rv["_uniform_target"] = vars["_uniform_target"]; + rv["_uniform_source"] = vars["_uniform_source"]; + + u = parse_uniform(vars["_uniform_target"]); + if (!(u && is_localhost(u[UHost]))) { + msg(0, "_error_invalid_uniform_target", "[_uniform_target] is not hosted here.", rv); + return; + } + u = parse_uniform(vars["_uniform_source"]); + u[UHost] = NAMEPREP(u[UHost]); + if (qAuthenticated(u[UHost])) { + // possibly different _uniform_target only + if (flags & TCP_PENDING_TIMEOUT) { + P0(("removing call out\n")) + remove_call_out(#'quit); + flags -= TCP_PENDING_TIMEOUT; } - } else { - // FIXME!!!! - CIRCUITERROR("sorry, no more than one element in _list_sources_hosts currently"); - P0(("more than one element in _list_sources_hosts: %O\n", vars["_list_sources_hosts"])) - } - // keep tag if present!!! - // resolve all of _list_sources_hosts - // look at _list_targets_hosts and determine localhostiness + msg(0, "_status_authorization", 0, rv); + // } else if (tls_query_connection_state(ME) == 1 && ...) { + // FIXME } else { - CIRCUITERROR("_request_verification is not allowed on TLS circuits."); + string ho = u[UHost]; + // FIXME: this actually needs to consider srv, too... + dns_resolve(ho, (: + // FIXME: psyc/parse::deliver is much better here + P0(("resolved %O to %O, expecting %O\n", ho, $1, peerip)) + if ($1 == peerip) { + sAuthenticated(ho); + if (flags & TCP_PENDING_TIMEOUT) { + P0(("removing call out\n")) + remove_call_out(#'quit); + flags -= TCP_PENDING_TIMEOUT; + } + msg(0, "_status_authorization", 0, rv); + } else { + msg(0, "_error_invalid_uniform_source", 0, rv); + } + return; + :)); } break; - case "_notice_features": - // FIXME: watch for _list_using_modules - if (flags & TCP_PENDING_TIMEOUT) { - P0(("removing call out\n")) - remove_call_out(#'quit); - flags -= TCP_PENDING_TIMEOUT; - } - sTextPath(); -#ifdef USE_FEATURES - if (tls_query_connection_state(ME) == 0) { -# ifdef USE_VERIFICATION - // start hostname verification - // rather: look at Q and look for the hostnames we need - sender_verification(({ SERVER_HOST }), ({ peerhost })); -# endif - } else { - if (function_exists("runQ")) { - runQ(); - } - } -#endif - break; - case "_notice_verification": - P0(("_notice verification with %O\n", vars)) + case "_status_authorization": + P0(("_status authorization with %O\n", vars)) + // this means we can send from _uniform_source to _uniform_target + // we already did sAuthenticated _uniform_target before so we can't get + // tricked into it here if (function_exists("runQ")) { - runQ(); + runQ(); + // actually runQ(_uniform_source, _uniform_target) } break; default: @@ -290,6 +277,7 @@ varargs int msg(string source, string mc, string data, mapping vars, int showingLog, mixed target) { string buf = ""; + mixed u; unless(vars) vars = ([ ]); buf = render_psyc(source, mc, data, vars, showingLog, target); diff --git a/world/net/spyc/server.c b/world/net/spyc/server.c index ac0190a..61765f8 100644 --- a/world/net/spyc/server.c +++ b/world/net/spyc/server.c @@ -69,6 +69,7 @@ void greet() { // should be sharing code with net/psyc and do a proper greeting // three separate packets follow (thus three emits) //emit(S_GLYPH_PACKET_DELIMITER "\n"); + /* emit("\ :_source\t"+ SERVER_UNIFORM +"\n\ :_target_peer\tpsyc://"+ peeraddr +"/\n\ @@ -81,6 +82,7 @@ _status_circuit\n" S_GLYPH_PACKET_DELIMITER "\n"); #ifdef _flag_log_sockets_SPYC log_file("RAW_SPYC", "« %O greeted.\n", ME); #endif + */ } static void resolved(mixed host, mixed tag) { @@ -176,20 +178,27 @@ static void resolved(mixed host, mixed tag) { sTextPath(); greet(); - // FIXME: determine response to greeting - // instead of this dummy - msg(0, "_notice_features", 0, tag ? ([ "_tag_reply" : tag ]) : 0); + //msg(0, "_notice_features", 0, tag ? ([ "_tag_reply" : tag ]) : 0); } -void circuit_msg(string mc, mapping vars, string data) { - switch(mc) { - case "_request_features": // only servers handle _request_features - interrupt_parse(); - dns_rresolve(peerip, #'resolved, vars && vars["_tag"]); - break; - default: - return ::circuit_msg(mc, vars, data); - } +int logon(int nothing) { + P2(("%O accepted TCP from %O (%s:%O)\n", ME, + query_ip_name(), query_ip_number(), peerport)) + // we could set the next_input_to and reply with _failure until + // hostname is resolved .. TODO ... no, we need some form + // of queuing for the scripts which do not wait.. why? don't we + // squeeze received packets thru dns-lambdas anyway? + // peerport has either positive or negative value + //peeraddr = peerip+":"+peerport; + ::logon(0); +#if 0 //def EXPERIMENTAL + // added this because greet() happens after dns resolution and + // some quick clients may not be waiting that long.. then again + // if they do, they deserve other treatment + sTextPath(); +#endif + dns_rresolve(peerip, #'resolved); + return 1; // success } #endif // LIBPSYC diff --git a/world/net/trust.c b/world/net/trust.c index 49801af..95f0308 100644 --- a/world/net/trust.c +++ b/world/net/trust.c @@ -29,12 +29,14 @@ volatile mapping authhosts; void sAuthenticated(string hostname) { P3(("sAuthenticated: %O\n", hostname)) unless(authhosts && mappingp(authhosts)) authhosts = ([ ]); + hostname = NAMEPREP(hostname); authhosts[hostname] = 1; } int qAuthenticated(mixed hostname) { P3(("qAuthenticated %O, %O\n", hostname, authhosts)) unless (authhosts && mappingp(authhosts)) return 0; + hostname = NAMEPREP(hostname); return member(authhosts, hostname); } From 9f9bdc4e2093ce6708ae44480df4f3c83757593e Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Sun, 31 Jul 2011 10:46:36 +0200 Subject: [PATCH 4/8] should we do NAMEPREP automatically? --- world/net/jabber/gateway.c | 1 + world/net/jabber/jabber.h | 1 + world/net/jabber/user.c | 1 + world/net/library.i | 9 ++++++--- world/net/psyc/circuit.c | 6 +++--- world/net/psyc/parse.i | 2 +- world/net/spyc/circuit.c | 8 ++++---- world/net/spyc/dispatch.i | 2 +- 8 files changed, 18 insertions(+), 12 deletions(-) diff --git a/world/net/jabber/gateway.c b/world/net/jabber/gateway.c index 3a4a986..6979250 100644 --- a/world/net/jabber/gateway.c +++ b/world/net/jabber/gateway.c @@ -298,6 +298,7 @@ jabberMsg(XMLNode node) { sendmsg(origin, "_dialback_request_verify", 0, ([ "_INTERNAL_target_jabber" : source, + // we shouldnt have to NAMEPREP a static string.. FIXME "_INTERNAL_source_jabber" : NAMEPREP(_host_XMPP), "_dialback_key" : node[Cdata], "_tag" : streamid diff --git a/world/net/jabber/jabber.h b/world/net/jabber/jabber.h index 6232722..b836c11 100644 --- a/world/net/jabber/jabber.h +++ b/world/net/jabber/jabber.h @@ -86,6 +86,7 @@ virtual inherit JABBER_PATH "common"; // net/jabber is not ready for regular is_localhost #define is_localhost(a) (lower_case(a)) == _host_XMPP +// but.. what about NAMEPREP here? #define JABSOURCE "_INTERNAL_source_jabber" diff --git a/world/net/jabber/user.c b/world/net/jabber/user.c index 4f43422..e72c742 100644 --- a/world/net/jabber/user.c +++ b/world/net/jabber/user.c @@ -277,6 +277,7 @@ logon() { #endif nodeHandler = #'jabberMsg; set_prompt(""); + // we shouldn't have to NAMEPREP our SERVER_HOST for each new user.. FIXME myjid = NODEPREP(MYLOWERNICK) +"@" + NAMEPREP(SERVER_HOST); myjidresource = myjid +"/"+ RESOURCEPREP(resource); P2(("%O ready to rumble (%O)\n", myjidresource, ME)) diff --git a/world/net/library.i b/world/net/library.i index 26d57c6..328135d 100644 --- a/world/net/library.i +++ b/world/net/library.i @@ -132,6 +132,8 @@ static varargs void ready_freddie(vamixed ip) { static void create() { PROTECT("CREATE") + string t; + #ifndef __PIKE__ master = previous_object(); restore_object(DATA_PATH "library"); @@ -259,9 +261,10 @@ static void create() { #ifdef JABBER_PATH register_target("xmpp:"+ myLowerCaseHost); # ifdef _host_XMPP - register_localhost(lower_case(_host_XMPP)); - register_target(lower_case(_host_XMPP)); - register_target("xmpp:"+ lower_case(_host_XMPP)); + t = NAMEPREP(_host_XMPP); + register_localhost(t); + register_target(t); + register_target("xmpp:"+ t); # endif #endif // base64decode("test2000"); diff --git a/world/net/psyc/circuit.c b/world/net/psyc/circuit.c index e35d28b..0f82c61 100644 --- a/world/net/psyc/circuit.c +++ b/world/net/psyc/circuit.c @@ -225,8 +225,8 @@ int logon(int neverfails) { P1(("%O believing dNSName %O\n", ME, m)) // probably also: register_target? // but be careful never to register_target wildcards - if (stringp(m)) sAuthenticated(NAMEPREP(m)); - else foreach(t : m) sAuthenticated(NAMEPREP(t)); + if (stringp(m)) sAuthenticated(m); + else foreach(t : m) sAuthenticated(t); } //#ifdef _flag_allow_certificate_name_common // to be switched this year # ifndef _flag_disallow_certificate_name_common @@ -235,7 +235,7 @@ int logon(int neverfails) { // note: CN is deprecated for good reasons. else if (t = cert["2.5.4.3"]) { P1(("%O believing CN %O\n", ME, t)) - sAuthenticated(NAMEPREP(t)); + sAuthenticated(t); } # endif if (m = tls_query_connection_info(ME)) { diff --git a/world/net/psyc/parse.i b/world/net/psyc/parse.i index 94c7dd3..27b5e5d 100644 --- a/world/net/psyc/parse.i +++ b/world/net/psyc/parse.i @@ -598,7 +598,7 @@ vamixed getdata(string a) { #else # ifdef PSYC_TCP // Authenticated - } else if (qAuthenticated(NAMEPREP(u[UHost]))) { + } else if (qAuthenticated(u[UHost])) { if (u[UTransport] && (u[UTransport] != # if __EFUN_DEFINED__(tls_query_connection_state) tls_query_connection_state() ? "s" : diff --git a/world/net/spyc/circuit.c b/world/net/spyc/circuit.c index a9a053a..4fb1cf3 100644 --- a/world/net/spyc/circuit.c +++ b/world/net/spyc/circuit.c @@ -120,10 +120,10 @@ int logon(int failure) { // probably also: register_target? // but be careful never to register_target wildcards if (stringp(m)) - sAuthenticated(NAMEPREP(m)); + sAuthenticated(m); else foreach(t : m) - sAuthenticated(NAMEPREP(t)); + sAuthenticated(t); } //#ifdef _flag_allow_certificate_name_common // to be switched this year #ifndef _flag_disallow_certificate_name_common @@ -132,7 +132,7 @@ int logon(int failure) { // note: CN is deprecated for good reasons. else if (t = cert["2.5.4.3"]) { P1(("%O believing CN %O\n", ME, t)) - sAuthenticated(NAMEPREP(t)); + sAuthenticated(t); } #endif if (m = tls_query_connection_info(ME)) { @@ -224,7 +224,7 @@ void circuit_msg(string mc, mapping vars, string data) { return; } u = parse_uniform(vars["_uniform_source"]); - u[UHost] = NAMEPREP(u[UHost]); + // qAuthenticated does that:u[UHost] = NAMEPREP(u[UHost]); if (qAuthenticated(u[UHost])) { // possibly different _uniform_target only if (flags & TCP_PENDING_TIMEOUT) { diff --git a/world/net/spyc/dispatch.i b/world/net/spyc/dispatch.i index 8a7026e..818693e 100644 --- a/world/net/spyc/dispatch.i +++ b/world/net/spyc/dispatch.i @@ -163,7 +163,7 @@ void dispatch(mapping rvars, mapping evars, mixed method, mixed body) { } #ifdef USE_VERIFICATION # ifdef PSYC_TCP - unless (qAuthenticated(NAMEPREP(u[UHost]))) { + unless (qAuthenticated(u[UHost])) { DISPATCHERROR("non-authenticated host\n") } # else From aa0a33a1c3fc5a325f47b2e06ab803285dc7192f Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Sun, 31 Jul 2011 11:04:06 +0200 Subject: [PATCH 5/8] + --- world/net/library.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/net/library.i b/world/net/library.i index 328135d..a02ebf2 100644 --- a/world/net/library.i +++ b/world/net/library.i @@ -196,7 +196,7 @@ static void create() { #ifdef VOLATILE D("VOLATILE flag set: Server will not save any data.\n"); #endif - myLowerCaseHost = lower_case(SERVER_HOST); + myLowerCaseHost = NAMEPREP(SERVER_HOST); register_localhost(myLowerCaseHost); #ifdef __PIKE__ //debug_write("Creating psyced library in Pike.\n"); From dc5055db449e0895d388dbe77b40b586e199395c Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Sun, 31 Jul 2011 14:19:31 +0200 Subject: [PATCH 6/8] don't quit --- world/net/psyc/parse.i | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/world/net/psyc/parse.i b/world/net/psyc/parse.i index 27b5e5d..4f541fe 100644 --- a/world/net/psyc/parse.i +++ b/world/net/psyc/parse.i @@ -997,17 +997,34 @@ protected int deliver(mixed ip, string host, string mc, string buffer, mapping c } P1(("RELAYING denied from %O to %O (%O)\n", source, t, ME)) -#if 0 monitor_report("_warning_unsupported_relay", S("%O is trying to find %O here. Relaying denied.\n", ME, t)); croak("_failure_unsupported_relay", //"Well done mate, you crashed me."); "Relaying denied: [_host] is not a hostname of ours.", ([ "_host": u[UHost] ])); +#if 0 // TODO: we quit here to not do the same hash-lookup // in rootmsg again. // (didn't get it? nevermind.. it's just el's sick humor) QUIT +#else + // we do not QUIT here as an evil attacker may + // CNAME his evil.com to us and try to disrupt + // our communications with some popular server + // by making us drop an otherwise very popular + // circuit. then again, what if a sender SHOULD + // not send to us with any other hostname but + // the one we announced ourselves as _source + // when we sent our first greeting() ? then we + // could just dump "illegal" transmissions. + // well, we don't need to be so harsh against + // multi domain hosters really: relaying is + // denied by default so the attacker needs to + // be a user on the sending server. in the end + // it's a question of trust: don't let zero + // trust users send funny amounts of data. + return 1; #endif } // .. yes.. add is_localhost check here, but without callback From 85b4d2f1dc41f278207fabd12d409bd9b3c5bc5f Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Sun, 31 Jul 2011 14:21:04 +0200 Subject: [PATCH 7/8] fippo hat es removed --- world/net/spyc/dispatch.i | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/world/net/spyc/dispatch.i b/world/net/spyc/dispatch.i index 818693e..24549eb 100644 --- a/world/net/spyc/dispatch.i +++ b/world/net/spyc/dispatch.i @@ -161,14 +161,12 @@ void dispatch(mapping rvars, mapping evars, mixed method, mixed body) { unless (u = parse_uniform(t)) { DISPATCHERROR("logical source is not a uniform\n") } -#ifdef USE_VERIFICATION -# ifdef PSYC_TCP +#ifdef PSYC_TCP unless (qAuthenticated(u[UHost])) { DISPATCHERROR("non-authenticated host\n") } -# else +#else // TODO? -# endif #endif } From 3c20b2cd379d014555b71d001a85755c630d0b86 Mon Sep 17 00:00:00 2001 From: Philipp Hancke Date: Mon, 1 Aug 2011 10:22:52 +0200 Subject: [PATCH 8/8] replace certificate_check_jabbername by certificate_check_name --- world/net/jabber/active.c | 2 +- world/net/jabber/common.c | 1 + world/net/jabber/gateway.c | 10 ++--- world/net/jabber/server.c | 2 + world/net/library/tls.c | 75 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 6 deletions(-) diff --git a/world/net/jabber/active.c b/world/net/jabber/active.c index 84c934b..acfdc40 100644 --- a/world/net/jabber/active.c +++ b/world/net/jabber/active.c @@ -315,7 +315,7 @@ tls_logon(result) { mixed cert = tls_certificate(ME, 0); P3(("active::certinfo %O\n", cert)) if (mappingp(cert)) { - unless (certificate_check_jabbername(hostname, cert)) { + unless (certificate_check_name(hostname, cert, "xmpp-server")) { #ifdef _flag_report_bogus_certificates monitor_report("_error_invalid_certificate_identity", sprintf("%O presented a certificate that " diff --git a/world/net/jabber/common.c b/world/net/jabber/common.c index 2e4c8de..0f2ab3a 100644 --- a/world/net/jabber/common.c +++ b/world/net/jabber/common.c @@ -393,6 +393,7 @@ xmpp_error(node, xmpperror) { return 0; } +// deprecated - use certificate_check_name from library/tls.c instead #ifdef WANT_S2S_TLS certificate_check_jabbername(name, cert) { mixed t; diff --git a/world/net/jabber/gateway.c b/world/net/jabber/gateway.c index 6979250..c88c0b5 100644 --- a/world/net/jabber/gateway.c +++ b/world/net/jabber/gateway.c @@ -291,8 +291,8 @@ jabberMsg(XMLNode node) { // paranoia note: as with XEP 0178 we might want to check dns anyway to // protect against stolen certificates if (mappingp(certinfo) && certinfo[0] == 0 - && node["@from"] && certificate_check_jabbername(node["@from"], certinfo)) { - P0(("dialback without dialback %O\n", certinfo)) + && node["@from"] && certificate_check_name(node["@from"], certinfo, "xmpp-server")) { + P2(("dialback without dialback %O\n", certinfo)) verify_connection(node["@to"], node["@from"], "valid"); } else { sendmsg(origin, @@ -414,7 +414,7 @@ jabberMsg(XMLNode node) { */ int success = 0; - success = certificate_check_jabbername(t, certinfo); + success = certificate_check_name(t, certinfo, "xmpp-server"); if (success) { emitraw(""); P2(("successful sasl external authentication with " @@ -542,8 +542,8 @@ open_stream(XMLNode node) { // sasl external if we know that it will succeed // later on if (node["@from"] && - certificate_check_jabbername(node["@from"], - certinfo)) { + certificate_check_name(node["@from"], + certinfo, "xmpp-server")) { packet += ""; packet += "EXTERNAL"; packet += ""; diff --git a/world/net/jabber/server.c b/world/net/jabber/server.c index a313651..b1d1625 100644 --- a/world/net/jabber/server.c +++ b/world/net/jabber/server.c @@ -485,6 +485,8 @@ open_stream(XMLNode node) { // sasl anonymous "ANONYMOUS"; #endif + // here it makes sense to use check_jabbername + // but that is currently unused anyway #if __EFUN_DEFINED__(tls_available) if (tls_available() && tls_query_connection_state(ME) > 0 && mappingp(certinfo) && certinfo[0] == 0 diff --git a/world/net/library/tls.c b/world/net/library/tls.c index a90ad77..c975171 100644 --- a/world/net/library/tls.c +++ b/world/net/library/tls.c @@ -82,3 +82,78 @@ mapping tls_certificate(object who, int longnames) { P2(("cert is %O\n", cert)) return cert; } + +// generalized variant of the old certificate_check_jabbername +// RFC 6125 describes the process in more detail +int certificate_check_name(string name, mixed cert, string scheme) { + mixed t; + string idn; + // FIXME: should probably be more careful about internationalized + // domain names - need testcases +#define WILDCARD_MATCH(thing) (strlen(thing) > 2 && thing[0] == '*' && thing[1] == '.' && trail(thing[2..], name)) + /* this does not support wildcards if there is more than one + * id-on-xmppAddr/CN + * API Note: name MUST be an utf8 string + */ + unless(name && cert && mappingp(cert)) return 0; + + name = NAMEPREP(name); + + // subjectAlternativeName - dNSName + if ((t = cert["2.5.29.17:dNSName"])) { + if (stringp(t)) t = ({ t }); + foreach(string t2 : t) { + t2 = NAMEPREP(t2); + if (name == t2 || WILDCARD_MATCH(t2)) + return 1; + } + } + + // subjectAlternativeName - SRV ID - FIXME + // unfortunately, the only ones I have encountered so far were ... unusable + if ((t = cert["2.5.29.17:1.3.6.1.5.5.7.8.7"])) { + P2(("encountered SRVName, please tell fippo: %O\n", t)) + } + + // URI ID - FIXME + // not seen yet + +#if 0 + // id-on-xmppAddr - have not seen them issued by anyone but + // startcom and those usually include dnsname, too + if ((t = cert["2.5.29.17:1.3.6.1.5.5.7.8.5"])) { + if (pointerp(t)) { + if (member(t, name) != -1) return 1; + foreach(string cn : t) { + if (NAMEPREP(cn) == name) return 1; + } + } + else if (name == NAMEPREP(t)) + return 1; + } +#endif + + // commonName - deprecated to put the host here but... + // this is only to be checked if no subjectAlternativeName is present + if (!cert["2.5.29.17"] && (t = cert["2.5.4.3"])) { // common name + if (pointerp(t)) { // does that happen?! I don't think so... + // fast way - works for traditional hostnames + if (member(t, name) != -1) return 1; + + // look for idn encoded stuff + foreach(string cn : t) { + idn = NAMEPREP(idna_to_unicode(cn)); + if (idn == name) return 1; + } + return 0; + } +#ifdef __IDNA__ + idn = NAMEPREP(idna_to_unicode(t)); +#else + idn = NAMEPREP(t); +#endif + if (idn == name || WILDCARD_MATCH(idn)) + return 1; + } + return 0; +}