From 0c482f510499194d1afa4b6c5d03d7e14ddf2a8f Mon Sep 17 00:00:00 2001 From: Philipp Hancke Date: Tue, 2 Aug 2011 16:51:47 +0200 Subject: [PATCH 01/13] --- world/net/library/tls.c | 2 + world/net/spyc/circuit.c | 92 ++++++++++++++++------------------------ 2 files changed, 39 insertions(+), 55 deletions(-) diff --git a/world/net/library/tls.c b/world/net/library/tls.c index c975171..bfad4bc 100644 --- a/world/net/library/tls.c +++ b/world/net/library/tls.c @@ -111,6 +111,8 @@ int certificate_check_name(string name, mixed cert, string scheme) { // subjectAlternativeName - SRV ID - FIXME // unfortunately, the only ones I have encountered so far were ... unusable + // what they should like is "_psyc.name" - i.e. "_" + scheme + "." + name + // no wildcards probably 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)) } diff --git a/world/net/spyc/circuit.c b/world/net/spyc/circuit.c index 4fb1cf3..33c536c 100644 --- a/world/net/spyc/circuit.c +++ b/world/net/spyc/circuit.c @@ -36,9 +36,13 @@ volatile string netloc; mapping instate = ([ ]); mapping outstate; -mapping legal_senders; +volatile mapping legal_senders; -array(mixed) verify_queue = ({ }); +volatile array(mixed) verify_queue = ({ }); + +#ifdef __TLS__ +volatile mixed certinfo; +#endif volatile int flags = 0; @@ -103,52 +107,17 @@ int logon(int failure) { instate = ([ "_INTERNAL_origin" : ME ]); outstate = ([ ]); #ifdef __TLS__ - mixed cert; - if (tls_available() && tls_query_connection_state(ME) == 1 && mappingp(cert = tls_certificate(ME, 0))) { - mixed m, t; - if (cert[0] != 0) { - // log error 17 + cert here - // and goodbye. - P0(("%O encountered a cert verify error %O in %O\n", ME, - cert[0], cert)) - remove_interactive(ME); - return 0; - } - if (m = cert["2.5.29.17:dNSName"]) { - // FIXME: this does not yet handle wildcard DNS names - P1(("%O believing dNSName %O\n", ME, m)) - // probably also: register_target? - // but be careful never to register_target wildcards - 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 - // assume that CN is a host - // as this is an assumption only, we may NEVER register_target it - // note: CN is deprecated for good reasons. - else if (t = cert["2.5.4.3"]) { - P1(("%O believing CN %O\n", ME, t)) - sAuthenticated(t); - } -#endif - if (m = tls_query_connection_info(ME)) { - P2(("%O is using the %O cipher.\n", ME, m[TLS_CIPHER])) - // shouldn't our negotiation have ensured we have PFS? - if (stringp(t = m[TLS_CIPHER]) &&! abbrev("DHE", t)) { -// croak("_warning_circuit_encryption_cipher", -// "Your cipher choice does not provide forward secrecy."); - monitor_report( - "_warning_circuit_encryption_cipher_details", - object_name(ME) +" · using "+ t +" cipher"); - //debug_message(sprintf( - // "TLS connection info for %O is %O\n", ME, m)); - //QUIT // are we ready for *this* !??? + P0(("circuit logon %O %O\n", tls_available(), tls_query_connection_state(ME))) + // FIXME: needs to handle the not-detected case + if (tls_available()) { + if (tls_query_connection_state(ME) == 0 && !isServer()) { + P0(("%O turning on TLS\n", ME)) + tls_init_connection(ME, #'logon); + return 1; + } else if (tls_query_connection_state(ME) == 1) { + certinfo = tls_certificate(ME, 0); + P0(("certinfo: %O\n", certinfo)) } - } } #endif @@ -205,7 +174,8 @@ first_response() { // note: this is circuit-messaging void circuit_msg(string mc, mapping vars, string data) { mapping rv = ([ ]); - mixed *u; + mixed *su; + mixed *tu; switch(mc) { case "_request_authorization": if (vars["_tag"]) { @@ -218,14 +188,14 @@ void circuit_msg(string mc, mapping vars, string data) { rv["_uniform_target"] = vars["_uniform_target"]; rv["_uniform_source"] = vars["_uniform_source"]; - u = parse_uniform(vars["_uniform_target"]); - if (!(u && is_localhost(u[UHost]))) { + tu = parse_uniform(vars["_uniform_target"]); + if (!(tu && is_localhost(tu[UHost]))) { msg(0, "_error_invalid_uniform_target", "[_uniform_target] is not hosted here.", rv); return; } - u = parse_uniform(vars["_uniform_source"]); + su = parse_uniform(vars["_uniform_source"]); // qAuthenticated does that:u[UHost] = NAMEPREP(u[UHost]); - if (qAuthenticated(u[UHost])) { + if (qAuthenticated(su[UHost])) { // possibly different _uniform_target only if (flags & TCP_PENDING_TIMEOUT) { P0(("removing call out\n")) @@ -233,10 +203,22 @@ void circuit_msg(string mc, mapping vars, string data) { flags -= TCP_PENDING_TIMEOUT; } msg(0, "_status_authorization", 0, rv); - // } else if (tls_query_connection_state(ME) == 1 && ...) { - // FIXME +#ifdef __TLS__ + } else if (tls_query_connection_state(ME) == 1 + && mappingp(certinfo) + && certinfo[0] == 0 + && certificate_check_name(su[UHost], certinfo, "psyc") == 1) { + sAuthenticated(su[UHost]); + if (flags & TCP_PENDING_TIMEOUT) { + P0(("removing call out\n")) + remove_call_out(#'quit); + flags -= TCP_PENDING_TIMEOUT; + } + msg(0, "_status_authorization", 0, rv); +#endif } else { - string ho = u[UHost]; + // FIXME: lynX wants to do that only for trusted hosts + string ho = su[UHost]; // FIXME: this actually needs to consider srv, too... dns_resolve(ho, (: // FIXME: psyc/parse::deliver is much better here From da6ce9252920c54b5ed9fa712010ee0ddb782dd7 Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Tue, 2 Aug 2011 17:43:05 +0200 Subject: [PATCH 02/13] paying more attention to TLS --- .gitmodules | 2 +- world/default/de/plain.textdb | 9 +++++ world/default/en/plain.textdb | 9 +++++ world/default/it/plain.textdb | 9 +++++ world/net/jabber/active.c | 2 +- world/net/jabber/common.c | 3 +- world/net/jabber/gateway.c | 8 ++-- world/net/jabber/server.c | 1 + world/net/library/tls.c | 22 ++++++++++- world/net/psyc/circuit.c | 71 ++++++++++++++++------------------- world/net/spyc/circuit.c | 8 +++- world/net/user.c | 10 +++++ 12 files changed, 106 insertions(+), 48 deletions(-) diff --git a/.gitmodules b/.gitmodules index 2d33dcf..8c4fa01 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "psyclpc"] path = psyclpc - url = git://git.tgbit.net/psyclpc + url = git://git.psyced.org/git/psyclpc diff --git a/world/default/de/plain.textdb b/world/default/de/plain.textdb index 3d2405e..74f4db2 100644 --- a/world/default/de/plain.textdb +++ b/world/default/de/plain.textdb @@ -1,6 +1,15 @@ ## vim:syntax=mail ## Check utf-8: Praise Atatürk! +_status_circuit_encryption_cipher +|Gratuliere! Deine Verbindung ist mit Folgenlosigkeit verschlüsselt. + +_warning_circuit_encryption_cipher +|Deine Verbindung ist leider ohne Folgenlosigkeit verschlüsselt. + +_error_circuit_encryption_cipher +|Deine Verbindung ist ohne Folgenlosigkeit verschlüsselt. + _failure_disabled_function_register |Registrierung ist auf diesem Server deaktiviert. diff --git a/world/default/en/plain.textdb b/world/default/en/plain.textdb index 552f0bc..151d789 100644 --- a/world/default/en/plain.textdb +++ b/world/default/en/plain.textdb @@ -1,6 +1,15 @@ ## vim:syntax=mail ## Check utf-8: Praise Atatürk! +_status_circuit_encryption_cipher +|Congratulations. Your connection is encrypted with forward secrecy. + +_warning_circuit_encryption_cipher +|Your cipher choice does not provide forward secrecy. + +_error_circuit_encryption_cipher +|Unfortunately your cipher choice does not provide forward secrecy. + _failure_disabled_function_register |Registration disabled on this server. diff --git a/world/default/it/plain.textdb b/world/default/it/plain.textdb index ce34307..d1a94cc 100644 --- a/world/default/it/plain.textdb +++ b/world/default/it/plain.textdb @@ -1,6 +1,15 @@ ## vim:syntax=mail ## tradotto al 30% ... cerca /TODO/ per continuare +_status_circuit_encryption_cipher +|Muy bueno! La tua connessione è crittata senza conseguenze. + +_warning_circuit_encryption_cipher +|La tua connessione non è crittata senza conseguenze. + +_error_circuit_encryption_cipher +|Purtroppo la tua connessione non è crittata senza conseguenze. + _failure_disabled_function_register |Registrazione di nuovi utenti disabilitata su questo server. diff --git a/world/net/jabber/active.c b/world/net/jabber/active.c index acfdc40..9754a7f 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_name(hostname, cert, "xmpp-server")) { + unless (tls_check_certificate_data(cert, hostname, "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 0f2ab3a..569b714 100644 --- a/world/net/jabber/common.c +++ b/world/net/jabber/common.c @@ -393,7 +393,8 @@ xmpp_error(node, xmpperror) { return 0; } -// deprecated - use certificate_check_name from library/tls.c instead +// deprecated - use tls_check_certificate_data from library/tls.c instead +// is this being used at all? #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 c88c0b5..2e2a387 100644 --- a/world/net/jabber/gateway.c +++ b/world/net/jabber/gateway.c @@ -291,7 +291,7 @@ 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_name(node["@from"], certinfo, "xmpp-server")) { + && node["@from"] && tls_check_certificate_data(certinfo, node["@from"], "xmpp-server")) { P2(("dialback without dialback %O\n", certinfo)) verify_connection(node["@to"], node["@from"], "valid"); } else { @@ -414,7 +414,7 @@ jabberMsg(XMLNode node) { */ int success = 0; - success = certificate_check_name(t, certinfo, "xmpp-server"); + success = tls_check_certificate_data(certinfo, t, "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_name(node["@from"], - certinfo, "xmpp-server")) { + tls_check_certificate_data(certinfo, node["@from"], + "xmpp-server")) { packet += ""; packet += "EXTERNAL"; packet += ""; diff --git a/world/net/jabber/server.c b/world/net/jabber/server.c index b1d1625..9cadc16 100644 --- a/world/net/jabber/server.c +++ b/world/net/jabber/server.c @@ -490,6 +490,7 @@ open_stream(XMLNode node) { #if __EFUN_DEFINED__(tls_available) if (tls_available() && tls_query_connection_state(ME) > 0 && mappingp(certinfo) && certinfo[0] == 0 + // why do we use the old one here? && certificate_check_jabbername(0, certinfo)) { features += "EXTERNAL"; } diff --git a/world/net/library/tls.c b/world/net/library/tls.c index bfad4bc..5d59f5a 100644 --- a/world/net/library/tls.c +++ b/world/net/library/tls.c @@ -1,4 +1,7 @@ #include // vim syntax=lpc +#include +#include + mapping tls_certificate(object who, int longnames) { mixed *extra, extensions; mapping cert; @@ -85,7 +88,7 @@ mapping tls_certificate(object who, int longnames) { // 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) { +int tls_check_certificate_data(mixed cert, string name, string scheme) { mixed t; string idn; // FIXME: should probably be more careful about internationalized @@ -159,3 +162,20 @@ int certificate_check_name(string name, mixed cert, string scheme) { } return 0; } + +int tls_check_cipher(object sock, string scheme) { + string t; + mixed m = tls_query_connection_info(sock); + + P3(("%O is using the %O cipher.\n", sock, m[TLS_CIPHER])) + // shouldn't our negotiation have ensured we have PFS? + + if (stringp(t = m[TLS_CIPHER]) &&! abbrev("DHE", t)) { + monitor_report("_warning_circuit_encryption_cipher_details", + object_name(sock) +" · using "+ t +" cipher"); + // we can't expect that degree of privacy from jabber, for now + if (scheme != "xmpp") return 0; + } + return 1; +} + diff --git a/world/net/psyc/circuit.c b/world/net/psyc/circuit.c index 0f82c61..97515a7 100644 --- a/world/net/psyc/circuit.c +++ b/world/net/psyc/circuit.c @@ -209,48 +209,41 @@ int logon(int neverfails) { #ifdef __TLS__ sAuthHosts(([ ])); // reset authhosts - if (tls_available() && tls_query_connection_state(ME) == 1 && mappingp(cert = tls_certificate(ME, 0))) { - if (cert[0] != 0) { - // log error 17 or 18 + cert here - P0(("%O encountered a cert verify error %O in %O\n", ME, - cert[0], cert)) - // and goodbye. + if (tls_available() && tls_query_connection_state(ME) == 1) { + unless (tls_check_cipher(ME, "psyc")) { + croak("_error_circuit_encryption_cipher", + "Your cipher choice does not provide forward secrecy."); + QUIT + } + if (mappingp(cert = tls_certificate(ME, 0))) { + if (cert[0] != 0) { + // log error 17 or 18 + cert here + P0(("%O encountered a cert verify error %O in %O\n", ME, + cert[0], cert)) + // and goodbye. # ifdef _flag_enable_certificate_any - remove_interactive(ME); - return 0; + remove_interactive(ME); + return 0; # endif - } - if (m = cert["2.5.29.17:dNSName"]) { - // FIXME: this does not yet handle wildcard DNS names - P1(("%O believing dNSName %O\n", ME, m)) - // probably also: register_target? - // but be careful never to register_target wildcards - 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 - // assume that CN is a host - // as this is an assumption only, we may NEVER register_target it - // note: CN is deprecated for good reasons. - else if (t = cert["2.5.4.3"]) { - P1(("%O believing CN %O\n", ME, t)) - sAuthenticated(t); - } -# endif - if (m = tls_query_connection_info(ME)) { - P2(("%O is using the %O cipher.\n", ME, m[TLS_CIPHER])) - // shouldn't our negotiation have ensured we have PFS? - if (stringp(t = m[TLS_CIPHER]) &&! abbrev("DHE", t)) { -// croak("_warning_circuit_encryption_cipher", -// "Your cipher choice does not provide forward secrecy."); - monitor_report( - "_warning_circuit_encryption_cipher_details", - object_name(ME) +" · using "+ t +" cipher"); - //debug_message(sprintf( - // "TLS connection info for %O is %O\n", ME, m)); - //QUIT // are we ready for *this* !??? } + if (m = cert["2.5.29.17:dNSName"]) { + // FIXME: this does not yet handle wildcard DNS names + P1(("%O believing dNSName %O\n", ME, m)) + // probably also: register_target? + // but be careful never to register_target wildcards + 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 + // assume that CN is a host + // as this is an assumption only, we may NEVER register_target it + // note: CN is deprecated for good reasons. + else if (t = cert["2.5.4.3"]) { + P1(("%O believing CN %O\n", ME, t)) + sAuthenticated(t); + } +# endif } } #endif diff --git a/world/net/spyc/circuit.c b/world/net/spyc/circuit.c index 33c536c..c9409a9 100644 --- a/world/net/spyc/circuit.c +++ b/world/net/spyc/circuit.c @@ -117,6 +117,12 @@ int logon(int failure) { } else if (tls_query_connection_state(ME) == 1) { certinfo = tls_certificate(ME, 0); P0(("certinfo: %O\n", certinfo)) + unless (tls_check_cipher(ME, "psyc")) { + croak("_error_circuit_encryption_cipher", + "Your cipher choice does not provide forward secrecy."); + //destruct(ME); + } + } } #endif @@ -207,7 +213,7 @@ void circuit_msg(string mc, mapping vars, string data) { } else if (tls_query_connection_state(ME) == 1 && mappingp(certinfo) && certinfo[0] == 0 - && certificate_check_name(su[UHost], certinfo, "psyc") == 1) { + && tls_check_certificate_data(certinfo, su[UHost], "psyc") == 1) { sAuthenticated(su[UHost]); if (flags & TCP_PENDING_TIMEOUT) { P0(("removing call out\n")) diff --git a/world/net/user.c b/world/net/user.c index 8544738..8c7aea0 100644 --- a/world/net/user.c +++ b/world/net/user.c @@ -1555,6 +1555,16 @@ logon() { return remove_interactive(ME); // and the object will deteriorate when user gives up.. } +#ifdef __TLS__ + if (tls_query_connection_state(ME) == 1) { + if (tls_check_cipher(ME, v("scheme"))) { + w("_status_circuit_encryption_cipher"); + } else { + w("_warning_circuit_encryption_cipher"); + //return remove_interactive(ME); + } + } +#endif // shouldn't this be qScheme() instead? little paranoid TODO // but then we would have to move qScheme() from the server.c's // into the common.c's .. well, we could do that some day From 46963f77680c0a0be4e12a6c8cdd2a3d44e343be Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Tue, 2 Aug 2011 17:52:53 +0200 Subject: [PATCH 03/13] make those w's visible --- world/net/user.c | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/world/net/user.c b/world/net/user.c index 8c7aea0..b043218 100644 --- a/world/net/user.c +++ b/world/net/user.c @@ -1545,26 +1545,6 @@ logon() { string t; P2(("LOGON %O from %O\n", ME, query_ip_name() )) - unless (legal_host(query_ip_number(), 0, 0, 0)) { - // this happens when people reconnect during the shutdown - // procedure.. and also when they are banned, but huh.. - // that hardly ever happens :) - w("_error_rejected_address", - "You are temporarily not permitted to connect here."); - //"I'm afraid you are no longer welcome here."); - return remove_interactive(ME); - // and the object will deteriorate when user gives up.. - } -#ifdef __TLS__ - if (tls_query_connection_state(ME) == 1) { - if (tls_check_cipher(ME, v("scheme"))) { - w("_status_circuit_encryption_cipher"); - } else { - w("_warning_circuit_encryption_cipher"); - //return remove_interactive(ME); - } - } -#endif // shouldn't this be qScheme() instead? little paranoid TODO // but then we would have to move qScheme() from the server.c's // into the common.c's .. well, we could do that some day @@ -1574,7 +1554,32 @@ logon() { beQuiet = -1; // never turn off less interesting enter/leave echoes // makeToken() isn't a good idea here, apparently sTextPath(v("layout"), v("language"), t); - // cannot if (greeting) this since jabber:iq:auth depends on this + unless (legal_host(query_ip_number(), 0, 0, 0)) { + // this happens when people reconnect during the shutdown + // procedure.. and also when they are banned, but huh.. + // that hardly ever happens :) + // + // w() needs to be called *after* sTextPath + w("_error_rejected_address", + "You are currently not permitted to connect here."); + return remove_interactive(ME); + // and the object will deteriorate when user gives up.. + // + // with the #'quit call_out.. or was it meant to + // deteriorate differently? + } +#ifdef __TLS__ + if (tls_query_connection_state(ME) == 1) { + if (tls_check_cipher(ME, t)) { + unless (beQuiet) w("_status_circuit_encryption_cipher"); + } else { + // i bet jabber users will love this + w("_warning_circuit_encryption_cipher"); + //return remove_interactive(ME); + } + } +#endif + // cannot if (greeting) here this since jabber:iq:auth depends on this // also greeting will only be defined after ::logon() // (use another w() maybe?) w("_notice_login", 0, ([ "_nick": MYNICK, From 7897992f053097354be086f321505596688e5888 Mon Sep 17 00:00:00 2001 From: Philipp Hancke Date: Wed, 3 Aug 2011 10:20:35 +0200 Subject: [PATCH 04/13] support for internationalized domain names in srv, too --- world/net/library/dns.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/world/net/library/dns.c b/world/net/library/dns.c index 5337487..02f1df7 100644 --- a/world/net/library/dns.c +++ b/world/net/library/dns.c @@ -614,6 +614,13 @@ void dns_srv_resolve(string hostname, string service, string proto, closure call // dumme bevormundung. wegen der musste ich jetzt ewig lang suchen: //unless (proto == "tcp" || proto == "udp") return; // da wir mit nem String arbeiten muessen + +#ifdef __IDNA__ + if (catch(hostname = idna_to_ascii(TO_UTF8(hostname)); nolog)) { + P0(("catch: punycode %O in %O\n", hostname, ME)) + return; + } +#endif req = sprintf("_%s._%s.%s", service, proto, hostname); rc = send_erq(ERQ_LOOKUP_SRV, req, lambda(({ 'wu }), ({ (#',), From c6503028859149f3f22bc8b85aa53f1d7b4ef05e Mon Sep 17 00:00:00 2001 From: Philipp Hancke Date: Wed, 3 Aug 2011 13:38:00 +0200 Subject: [PATCH 05/13] tls_check_certificate_data re-renamed to tls_check_service_identity and minor fixes --- world/net/jabber/active.c | 11 ++++++----- world/net/jabber/common.c | 5 +++-- world/net/jabber/gateway.c | 6 +++--- world/net/jabber/server.c | 1 + world/net/library/tls.c | 7 ++++++- world/net/spyc/circuit.c | 4 ++-- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/world/net/jabber/active.c b/world/net/jabber/active.c index 9754a7f..0c0cb9b 100644 --- a/world/net/jabber/active.c +++ b/world/net/jabber/active.c @@ -31,6 +31,7 @@ inherit NET_PATH "name"; volatile mixed gateways; volatile mixed *dialback_queue; +volatile mapping certinfo; volatile string streamid; volatile float streamversion; @@ -312,10 +313,10 @@ tls_logon(result) { // // if the cert is ok, we can set authenticated to 1 // to skip dialback - mixed cert = tls_certificate(ME, 0); - P3(("active::certinfo %O\n", cert)) - if (mappingp(cert)) { - unless (tls_check_certificate_data(cert, hostname, "xmpp-server")) { + certinfo = tls_certificate(ME, 0); + P3(("active::certinfo %O\n", certinfo)) + if (mappingp(certinfo)) { + unless (tls_check_service_identity(hostname, certinfo, "xmpp-server")) { #ifdef _flag_report_bogus_certificates monitor_report("_error_invalid_certificate_identity", sprintf("%O presented a certificate that " @@ -334,7 +335,7 @@ tls_logon(result) { return 1; #endif } - else if (cert[0] != 0) { + else if (certinfo[0] != 0) { #ifdef _flag_report_bogus_certificates monitor_report("_error_untrusted_certificate", sprintf("%O certificate could not be verified", diff --git a/world/net/jabber/common.c b/world/net/jabber/common.c index 569b714..877e82a 100644 --- a/world/net/jabber/common.c +++ b/world/net/jabber/common.c @@ -393,8 +393,9 @@ xmpp_error(node, xmpperror) { return 0; } -// deprecated - use tls_check_certificate_data from library/tls.c instead -// is this being used at all? +// deprecated - use tls_check_service_identity from library/tls.c instead +// is this being used at all? -- no longer, but keep it around a little +// for backward compat #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 2e2a387..89f86fc 100644 --- a/world/net/jabber/gateway.c +++ b/world/net/jabber/gateway.c @@ -291,7 +291,7 @@ 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"] && tls_check_certificate_data(certinfo, node["@from"], "xmpp-server")) { + && node["@from"] && tls_check_service_identity(node["@from"], certinfo, "xmpp-server")) { P2(("dialback without dialback %O\n", certinfo)) verify_connection(node["@to"], node["@from"], "valid"); } else { @@ -414,7 +414,7 @@ jabberMsg(XMLNode node) { */ int success = 0; - success = tls_check_certificate_data(certinfo, t, "xmpp-server"); + success = tls_check_service_identity(t, certinfo, "xmpp-server"); if (success) { emitraw(""); P2(("successful sasl external authentication with " @@ -542,7 +542,7 @@ open_stream(XMLNode node) { // sasl external if we know that it will succeed // later on if (node["@from"] && - tls_check_certificate_data(certinfo, node["@from"], + tls_check_service_identity(node["@from"], certinfo "xmpp-server")) { packet += ""; packet += "EXTERNAL"; diff --git a/world/net/jabber/server.c b/world/net/jabber/server.c index 9cadc16..ae3767e 100644 --- a/world/net/jabber/server.c +++ b/world/net/jabber/server.c @@ -513,5 +513,6 @@ certificate_check_jabbername(name, certinfo) { // plan: prefer subjectAltName:id-on-xmppAddr, // but allow email (1.2.840.113549.1.9.1) // and subjectAltName:rfc822Name + // FIXME: do something useful here... return 0; } diff --git a/world/net/library/tls.c b/world/net/library/tls.c index 5d59f5a..eb5e70a 100644 --- a/world/net/library/tls.c +++ b/world/net/library/tls.c @@ -88,7 +88,7 @@ mapping tls_certificate(object who, int longnames) { // generalized variant of the old certificate_check_jabbername // RFC 6125 describes the process in more detail -int tls_check_certificate_data(mixed cert, string name, string scheme) { +int tls_check_service_identity(string name, mixed cert, string scheme) { mixed t; string idn; // FIXME: should probably be more careful about internationalized @@ -126,6 +126,7 @@ int tls_check_certificate_data(mixed cert, string name, string scheme) { #if 0 // id-on-xmppAddr - have not seen them issued by anyone but // startcom and those usually include dnsname, too + // utf8-encoded 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; @@ -147,7 +148,11 @@ int tls_check_certificate_data(mixed cert, string name, string scheme) { // look for idn encoded stuff foreach(string cn : t) { +#ifdef __IDNA__ idn = NAMEPREP(idna_to_unicode(cn)); +#else + idn = NAMEPREP(cn); +#endif if (idn == name) return 1; } return 0; diff --git a/world/net/spyc/circuit.c b/world/net/spyc/circuit.c index c9409a9..8c3946c 100644 --- a/world/net/spyc/circuit.c +++ b/world/net/spyc/circuit.c @@ -41,7 +41,7 @@ volatile mapping legal_senders; volatile array(mixed) verify_queue = ({ }); #ifdef __TLS__ -volatile mixed certinfo; +volatile mapping certinfo; #endif volatile int flags = 0; @@ -213,7 +213,7 @@ void circuit_msg(string mc, mapping vars, string data) { } else if (tls_query_connection_state(ME) == 1 && mappingp(certinfo) && certinfo[0] == 0 - && tls_check_certificate_data(certinfo, su[UHost], "psyc") == 1) { + && tls_check_service_identity(su[UHost], certinfo, "psyc") == 1) { sAuthenticated(su[UHost]); if (flags & TCP_PENDING_TIMEOUT) { P0(("removing call out\n")) From 47fe829aee93aff9694f929f6c2dc4813156d109 Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Wed, 3 Aug 2011 18:30:44 +0200 Subject: [PATCH 06/13] thanks to prosody.im for the certificate generator --- install.sh | 1 + utility/gencert/Makefile | 32 ++++++++++++++++++++++ utility/gencert/openssl.cnf | 53 +++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 utility/gencert/Makefile create mode 100644 utility/gencert/openssl.cnf diff --git a/install.sh b/install.sh index 77108f7..243c77b 100755 --- a/install.sh +++ b/install.sh @@ -955,6 +955,7 @@ _path_configuration = $CONFIG_DIR ; (absolute or relative to _path_configuration) _path_PEM_key = key.pem _path_PEM_certificate = cert.pem +; You can run 'make' in the 'utility/gencert' folder to create a pair ; Path to the TLS trust directory where certs are kept. ; If unset this will default to your system installation's defaults. diff --git a/utility/gencert/Makefile b/utility/gencert/Makefile new file mode 100644 index 0000000..57bd015 --- /dev/null +++ b/utility/gencert/Makefile @@ -0,0 +1,32 @@ +# taken from prosody.im, originally written by zash. MIT license +# +.DEFAULT: localhost.cert +keysize=2048 + +# How to: +# First, `make yourhost.cnf` which creates a openssl config file. +# Then edit this file and fill in the details you want it to have, +# and add or change hosts and components it should cover. +# Then `make yourhost.key` to create your private key, you can +# include keysize=number to change the size of the key. +# Then you can either `make yourhost.csr` to generate a certificate +# signing request that you can submit to a CA, or `make yourhost.cert` +# to generate a self signed certificate. + +.PRECIOUS: %.cnf %.key + +# To request a cert +%.csr: %.cnf %.key + openssl req -new -key $(lastword $^) -out $@ -utf8 -config $(firstword $^) + +# Self signed +%.cert: %.cnf %.key + openssl req -new -x509 -nodes -key $(lastword $^) -days 365 \ + -sha1 -out $@ -utf8 -config $(firstword $^) + +%.cnf: + sed 's,example\.com,$*,g' openssl.cnf > $@ + +%.key: + openssl genrsa $(keysize) > $@ + @chmod 400 -c $@ diff --git a/utility/gencert/openssl.cnf b/utility/gencert/openssl.cnf new file mode 100644 index 0000000..49e5305 --- /dev/null +++ b/utility/gencert/openssl.cnf @@ -0,0 +1,53 @@ +# based on the prosody certs/openssl.cnf by zash - MIT license +# +# note: if you have an internationalized domain name, be very careful +# about encoding it properly. +oid_section = new_oids + +[ new_oids ] + +# RFC 3920 section 5.1.1 defines this OID +xmppAddr = 1.3.6.1.5.5.7.8.5 + +# RFC 4985 defines this OID +SRVName = 1.3.6.1.5.5.7.8.7 + +[ req ] + +default_bits = 4096 +default_keyfile = example.com.key +distinguished_name = distinguished_name +req_extensions = v3_extensions +x509_extensions = v3_extensions +string_mask = utf8only + +# ask about the DN? +prompt = no + +[ distinguished_name ] + +commonName = example.com +countryName = GB +localityName = The Internet +organizationName = Your Organisation +organizationalUnitName = IT Department +emailAddress = psycmaster@example.com + +[ v3_extensions ] + +# for certificate requests (req_extensions) +# and self-signed certificates (x509_extensions) +# note: setting keyUsage does not work for self-signed certs +basicConstraints = CA:FALSE +keyUsage = digitalSignature,keyEncipherment +extendedKeyUsage = serverAuth,clientAuth +subjectAltName = @subject_alternative_name + +[ subject_alternative_name ] + +# See http://tools.ietf.org/html/rfc6120#section-13.7.1.2 for more info + +DNS.0 = example.com +otherName.0 = SRVName;IA5STRING:_xmpp-client.example.com +otherName.1 = SRVName;IA5STRING:_xmpp-server.example.com +otherName.2 = SRVName;IA5STRING:_psyc.example.com From 0cd6cbcb48d7684f857a49ac50c66dd57d9dcb41 Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Wed, 3 Aug 2011 18:31:46 +0200 Subject: [PATCH 07/13] remember to always test before you commit.... --- world/net/jabber/gateway.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/net/jabber/gateway.c b/world/net/jabber/gateway.c index 89f86fc..a4ae72e 100644 --- a/world/net/jabber/gateway.c +++ b/world/net/jabber/gateway.c @@ -542,7 +542,7 @@ open_stream(XMLNode node) { // sasl external if we know that it will succeed // later on if (node["@from"] && - tls_check_service_identity(node["@from"], certinfo + tls_check_service_identity(node["@from"], certinfo, "xmpp-server")) { packet += ""; packet += "EXTERNAL"; From 0748ec28f50bd691c910e062ab0c5623d4e9aa66 Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Sat, 20 Aug 2011 08:55:58 +0200 Subject: [PATCH 08/13] evil probe --- CHANGESTODO | 2 ++ world/net/usercmd.i | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGESTODO b/CHANGESTODO index a53834b..ba6631f 100644 --- a/CHANGESTODO +++ b/CHANGESTODO @@ -184,6 +184,8 @@ problems that should disappear when we move away from _nick's: - IRC shows "*** k kindly asks for your friendship." for remote friendship requests. eh! where's the uniform!? - remote /topic shows wrong nick ++ allow newbies to use /nick and switch to a different newbie name? + (also, forbid +alias from being used by newbies?) > PRESENCE STATUS + all _status_person need to be upgraded to _status_presence with diff --git a/world/net/usercmd.i b/world/net/usercmd.i index 1057027..c7b4b5c 100644 --- a/world/net/usercmd.i +++ b/world/net/usercmd.i @@ -2455,9 +2455,15 @@ friend(rm, entity, ni, trustee) { // normally auto-acknowledge this request sendmsg(entity, "_request_friendship_implied", 0, ([ "_nick": MYNICK, "_degree_availability": availability ]) ); - sendmsg(entity, "_request_status_person", - 0, ([ "_nick": MYNICK ]) ); - // did i just say something about symmetry? + // don't know how this hack got here but it drives some + // jabber servers nuts as you are not supposed to probe + // people that you aren't subscribed to, yet + //sendmsg(entity, "_request_status_person", + // 0, ([ "_nick": MYNICK ]) ); + // we should instead ensure we are always sending our presence + // status once a subscription is completed.. FIXME + // or we just scrap it all and redo context subscription + // strictly as suggested by the new specs.. sigh #ifdef TRY_THIS // currently friend() only gets called from // online commands. so we skip the if From 5f18048fdbd0abb56929154dc6af2d485c32db29 Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Sat, 20 Aug 2011 10:42:13 +0200 Subject: [PATCH 09/13] let's not recommend non-deniable encryption any longer --- world/default/de/html.textdb | 8 -------- world/default/en/html.textdb | 7 ------- 2 files changed, 15 deletions(-) diff --git a/world/default/de/html.textdb b/world/default/de/html.textdb index b94ba36..4af5112 100644 --- a/world/default/de/html.textdb +++ b/world/default/de/html.textdb @@ -795,14 +795,6 @@ _PAGES_help_settings |

/set miniphotofile http://<Web-Adresse>

|A thumbnail size photo of yours, to be used for lists of friends. | -| -|

/set keyfile http://<Web-Adresse>

-|Für die Freunde der verschlüsselten Kommunikation, hier kann die -|Adresse der eigenen public-key Datei abgelegt werden wonach -|Freunde verschlüsselte Email austauschen oder, mit einem -|geeigneten PSYC -|client, direkt verschlüsselt chatten können. -| | |

/set startpage http://<Web-Adresse>

|Hiermit kann eine Startseite eingestellt werden, welche sofort nach diff --git a/world/default/en/html.textdb b/world/default/en/html.textdb index d8a08a4..76d0e7a 100644 --- a/world/default/en/html.textdb +++ b/world/default/en/html.textdb @@ -877,13 +877,6 @@ _PAGES_help_settings |

/set miniphotofile http://<web-address>

|A thumbnail size photo of yours, to be used for lists of friends. | -|

/set keyfile http://<web-address>

-|invites you to store the address of your public key file, -|allowing for encrypted communication to happen between you and -|your friends, provided you are both using an encryption capable -|PSYC client, -|or at least email. -| |

/set stylefile http://<web-address>

|lets you specify a cascading style sheet file for personalized |presentation of your profile! From aaa3e946238cc5d3002944bc305b214a48a1f9f2 Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Mon, 22 Aug 2011 23:44:39 +0200 Subject: [PATCH 10/13] is it too hard to do a proper search & replace? --- world/net/jabber/active.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/world/net/jabber/active.c b/world/net/jabber/active.c index 0c0cb9b..4419e1f 100644 --- a/world/net/jabber/active.c +++ b/world/net/jabber/active.c @@ -321,14 +321,14 @@ tls_logon(result) { monitor_report("_error_invalid_certificate_identity", sprintf("%O presented a certificate that " "contains %O/%O", - hostname, cert["2.5.4.3"], - cert["2.5.29.17:1.3.6.1.5.5.7.8.5"])); + hostname, certinfo["2.5.4.3"], + certinfo["2.5.29.17:1.3.6.1.5.5.7.8.5"])); #endif #ifdef _flag_log_bogus_certificates - log_file("CERTS", S("%O %O %O id?\n", ME, hostname, cert)); + log_file("CERTS", S("%O %O %O id?\n", ME, hostname, certinfo)); #else P1(("TLS: %s presented a certificate with unexpected identity.\n", hostname)) - P2(("%O\n", cert)) + P2(("%O\n", certinfo)) #endif #if 0 //def _flag_reject_bogus_certificates QUIT @@ -342,10 +342,10 @@ tls_logon(result) { hostname)); #endif #ifdef _flag_log_bogus_certificates - log_file("CERTS", S("%O %O %O\n", ME, hostname, cert)); + log_file("CERTS", S("%O %O %O\n", ME, hostname, certinfo)); #else P1(("TLS: %s presented untrusted certificate.\n", hostname)) - P2(("%O\n", cert)) + P2(("%O\n", certinfo)) #endif #if 0 //def _flag_reject_bogus_certificates // QUIT is wrong... From 35810767f687c850a89c8d5b17aff42b8ac58ca8 Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Tue, 23 Aug 2011 19:47:54 +0200 Subject: [PATCH 11/13] enabled TLS autodetect on HTTP port --- world/drivers/ldmud/master/accept.c | 45 +++++++++++++++++------------ world/net/twitter/client.c | 2 +- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/world/drivers/ldmud/master/accept.c b/world/drivers/ldmud/master/accept.c index 11b96c1..afac3f0 100644 --- a/world/drivers/ldmud/master/accept.c +++ b/world/drivers/ldmud/master/accept.c @@ -46,16 +46,22 @@ void notify_shutdown_first(int progress) { * input_to() can't be called from here. * * uid is only passed if USE_AUTHLOCAL is built into the driver. + * + * strange how int port and string service came into existence here + * since the driver isn't passing such arguments and there is no + * reason to call this from anywhere else. i presume they are a + * mistake! */ object connect(int uid, int port, string service) { int peerport; mixed arg, t; + unless (port) port = query_mud_port(); // now that's a bit of preprocessor magic you don't need to understand.. ;) - D2( if (uid) D("master:connected on port "+ query_mud_port() +" by uid " - + uid +"\n"); + D2( if (uid) D("master:connected on port "+ port +" by uid " + + uid +"("+ service + ")\n"); else) { - D3(D("master:connected on port "+query_mud_port() + D3(D("master:connected on port "+port +" by "+query_ip_name()+"\n");) } #ifndef H_DEFAULT_PROMPT @@ -71,7 +77,7 @@ object connect(int uid, int port, string service) { // we dont want the telnet machine most of the time // but disabling and re-enabling it for telnet doesn't work - switch(port || query_mud_port()) { + switch(port) { #if HAS_PORT(PSYC_PORT, PSYC_PATH) && AUTODETECT case PSYC_PORT: #endif @@ -84,7 +90,7 @@ object connect(int uid, int port, string service) { # endif t = tls_init_connection(this_object()); if (t < 0 && t != ERR_TLS_NOT_DETECTED) { - PP(( "TLS on %O: %O\n", query_mud_port(), tls_error(t) )); + PP(( "TLS on %O: %O\n", port, tls_error(t) )); } } #endif // fall thru @@ -125,7 +131,7 @@ object connect(int uid, int port, string service) { # endif t = tls_init_connection(this_object()); if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - query_mud_port(), tls_error(t) )); + port, tls_error(t) )); #endif // fall thru #if HAS_PORT(SPYC_PORT, SPYC_PATH) case SPYC_PORT: @@ -162,7 +168,7 @@ object connect(int uid, int port, string service) { case POP3S_PORT: t = tls_init_connection(this_object()); if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - query_mud_port(), tls_error(t) )); + port, tls_error(t) )); return clone_object(POP3_PATH "server"); #endif #if HAS_PORT(POP3_PORT, POP3_PATH) @@ -174,7 +180,7 @@ object connect(int uid, int port, string service) { case SMTPS_PORT: t = tls_init_connection(this_object()); if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - query_mud_port(), tls_error(t) )); + port, tls_error(t) )); return clone_object(SMTP_PATH "server"); #endif #if HAS_PORT(SMTP_PORT, SMTP_PATH) @@ -192,7 +198,7 @@ object connect(int uid, int port, string service) { case NNTPS_PORT: t = tls_init_connection(this_object()); if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - query_mud_port(), tls_error(t) )); + port, tls_error(t) )); return clone_object(NNTP_PATH "server"); #endif #if HAS_PORT(NNTP_PORT, NNTP_PATH) @@ -204,7 +210,7 @@ object connect(int uid, int port, string service) { case JABBERS_PORT: t = tls_init_connection(this_object()); if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - query_mud_port(), tls_error(t) )); + port, tls_error(t) )); return clone_object(JABBER_PATH "server"); #endif #if HAS_PORT(JABBER_PORT, JABBER_PATH) @@ -262,7 +268,7 @@ object connect(int uid, int port, string service) { case IRCS_PORT: t = tls_init_connection(this_object()); if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - query_mud_port(), tls_error(t) )); + port, tls_error(t) )); return clone_object(IRC_PATH "server"); #endif #if HAS_PORT(IRC_PORT, IRC_PATH) @@ -285,7 +291,7 @@ object connect(int uid, int port, string service) { case TELNETS_PORT: t = tls_init_connection(this_object()); if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - query_mud_port(), tls_error(t) )); + port, tls_error(t) )); // we could do the UID2NICK thing here, too, but why should we? // what do you need tls for on a localhost tcp link? return clone_object(TELNET_PATH "server"); @@ -300,12 +306,15 @@ object connect(int uid, int port, string service) { return t; #endif +#if HAS_PORT(HTTP_PORT, HTTP_PATH) && AUTODETECT + case HTTP_PORT: // AUTODETECT on the HTTP port +#endif #if HAS_PORT(HTTPS_PORT, HTTP_PATH) case HTTPS_PORT: t = tls_init_connection(this_object()); if (t < 0) { D1( if (t != ERR_TLS_NOT_DETECTED) PP(( "TLS(%O) on %O: %O\n", - t, query_mud_port(), tls_error(t) )); ) + t, port, tls_error(t) )); ) #if !HAS_PORT(HTTP_PORT, HTTP_PATH) // if we have no http port, it may be intentional return (object)0; @@ -316,8 +325,8 @@ object connect(int uid, int port, string service) { return clone_object(HTTP_PATH "server"); #endif /* don't fall thru. allow for https: to be available without http: */ -#if HAS_PORT(HTTP_PORT, HTTP_PATH) - case HTTP_PORT: // AUTODETECT on the HTTP port? we could do that too +#if HAS_PORT(HTTP_PORT, HTTP_PATH) &&! AUTODETECT + case HTTP_PORT: return clone_object(HTTP_PATH "server"); #endif @@ -325,7 +334,7 @@ object connect(int uid, int port, string service) { case MUDS_PORT: t = tls_init_connection(this_object()); if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - query_mud_port(), tls_error(t) )); + port, tls_error(t) )); return clone_object(MUD_PATH "login"); #endif #if HAS_PORT(MUD_PORT, MUD_PATH) @@ -337,7 +346,7 @@ object connect(int uid, int port, string service) { } PP(("Received connection on port %O which isn't configured.\n", - query_mud_port())); + port)); return (object)0; } @@ -345,10 +354,10 @@ object connect(int uid, int port, string service) { #ifdef DRIVER_HAS_RENAMED_CLONES // named clones -lynx object compile_object(string file) { - P3((">> compile_object(%O)\n", file)) string path, name; object rob; + P3((">> compile_object(%O)\n", file)) # ifdef PSYC_PATH if (abbrev("S:psyc:", file)) { rob = clone_object(PSYC_PATH "server"); diff --git a/world/net/twitter/client.c b/world/net/twitter/client.c index e3a46ee..c4afce9 100644 --- a/world/net/twitter/client.c +++ b/world/net/twitter/client.c @@ -34,7 +34,7 @@ object load(object usr, string key, string secret, string request, string access void parse_status_update(string body, string headers, int http_status) { P3(("twitter/client:parse_status_update(%O, %O, %O)\n", body, headers, http_status)) if (http_status != R_OK) - sendmsg(user, "_error_"+name+"_status_update", "Error: failed to post status update on [_name].", (["_name": display_name])); + sendmsg(user, "_failure_update_"+ name, "Unable to post status update on [_name].", (["_name": display_name])); } void status_update(string text) { From 2fb613538ca3782bd635177224ebb45f97deb91f Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Wed, 24 Aug 2011 08:03:11 +0200 Subject: [PATCH 12/13] allow TLS autodetect on IRC, telnet, HTTP --- world/drivers/ldmud/master/accept.c | 93 +++++++++++++++-------------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/world/drivers/ldmud/master/accept.c b/world/drivers/ldmud/master/accept.c index afac3f0..60f087d 100644 --- a/world/drivers/ldmud/master/accept.c +++ b/world/drivers/ldmud/master/accept.c @@ -75,25 +75,47 @@ object connect(int uid, int port, string service) { return clone_object(NET_PATH "utility/onhold"); } +#define TLS_INIT \ + if (tls_available()) { \ + t = tls_init_connection(ME); \ + if (t < 0 && t != ERR_TLS_NOT_DETECTED) { \ + P2(( "TLS(%O) on port %O: %O\n", t, port, tls_error(t) )); \ + } \ + } + +#if __EFUN_DEFINED__(tls_want_peer_certificate) +// Specify that a subsequent call to tls_init_connection +// should request a peer certificate. +# define TLS_INIT_GET_CERT \ + if (tls_available()) { \ + tls_want_peer_certificate(ME); \ + t = tls_init_connection(ME); \ + if (t < 0 && t != ERR_TLS_NOT_DETECTED) { \ + P2(( "TLS(%O) on port %O: %O\n", t, port, tls_error(t) )); \ + } \ + } +#else +# define TLS_INIT_GET_CERT TLS_INIT +#endif + +#if AUTODETECT +# define TLS_INIT_AUTODETECT TLS_INIT +#else +# define TLS_INIT_AUTODETECT // do nothing +#endif + // we dont want the telnet machine most of the time // but disabling and re-enabling it for telnet doesn't work switch(port) { #if HAS_PORT(PSYC_PORT, PSYC_PATH) && AUTODETECT case PSYC_PORT: + // make TLS available even on the default psyc port using the autodetection feature #endif #if HAS_PORT(PSYCS_PORT, PSYC_PATH) case PSYCS_PORT: // inofficial & temporary - // make TLS available even on the default psyc port using the autodetection feature - if (tls_available()) { -# if __EFUN_DEFINED__(tls_want_peer_certificate) - tls_want_peer_certificate(ME); -# endif - t = tls_init_connection(this_object()); - if (t < 0 && t != ERR_TLS_NOT_DETECTED) { - PP(( "TLS on %O: %O\n", port, tls_error(t) )); - } - } -#endif // fall thru +#endif + TLS_INIT_GET_CERT + // fall thru #if HAS_PORT(PSYC_PORT, PSYC_PATH) &&! AUTODETECT case PSYC_PORT: #endif @@ -129,9 +151,7 @@ object connect(int uid, int port, string service) { # if __EFUN_DEFINED__(tls_want_peer_certificate) tls_want_peer_certificate(ME); # endif - t = tls_init_connection(this_object()); - if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - port, tls_error(t) )); + TLS_INIT #endif // fall thru #if HAS_PORT(SPYC_PORT, SPYC_PATH) case SPYC_PORT: @@ -166,9 +186,7 @@ object connect(int uid, int port, string service) { #if HAS_PORT(POP3S_PORT, POP3_PATH) case POP3S_PORT: - t = tls_init_connection(this_object()); - if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - port, tls_error(t) )); + TLS_INIT return clone_object(POP3_PATH "server"); #endif #if HAS_PORT(POP3_PORT, POP3_PATH) @@ -178,9 +196,7 @@ object connect(int uid, int port, string service) { #if HAS_PORT(SMTPS_PORT, NNTP_PATH) case SMTPS_PORT: - t = tls_init_connection(this_object()); - if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - port, tls_error(t) )); + TLS_INIT return clone_object(SMTP_PATH "server"); #endif #if HAS_PORT(SMTP_PORT, SMTP_PATH) @@ -196,9 +212,7 @@ object connect(int uid, int port, string service) { #if HAS_PORT(NNTPS_PORT, NNTP_PATH) case NNTPS_PORT: - t = tls_init_connection(this_object()); - if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - port, tls_error(t) )); + TLS_INIT return clone_object(NNTP_PATH "server"); #endif #if HAS_PORT(NNTP_PORT, NNTP_PATH) @@ -208,9 +222,7 @@ object connect(int uid, int port, string service) { #if HAS_PORT(JABBERS_PORT, JABBER_PATH) case JABBERS_PORT: - t = tls_init_connection(this_object()); - if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - port, tls_error(t) )); + TLS_INIT return clone_object(JABBER_PATH "server"); #endif #if HAS_PORT(JABBER_PORT, JABBER_PATH) @@ -253,6 +265,7 @@ object connect(int uid, int port, string service) { P3(("%O -> load(%O, %O)\n", t, query_ip_number(), -peerport)) return t -> load(query_ip_number(), -peerport); #endif + #if 0 //__EFUN_DEFINED__(enable_binary) // work in progress case 8888: @@ -264,18 +277,15 @@ object connect(int uid, int port, string service) { enable_telnet(0); return clone_object(NET_PATH "rtmp/protocol"); #endif + #if HAS_PORT(IRCS_PORT, IRC_PATH) case IRCS_PORT: - t = tls_init_connection(this_object()); - if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - port, tls_error(t) )); + TLS_INIT return clone_object(IRC_PATH "server"); #endif #if HAS_PORT(IRC_PORT, IRC_PATH) - case IRC_PORT: // we could enable AUTODETECT for this.. -# if 0 // __EFUN_DEFINED__(enable_telnet) - enable_telnet(0); // shouldn't harm.. but it does!!! -# endif + case IRC_PORT: + TLS_INIT_AUTODETECT return clone_object(IRC_PATH "server"); #endif @@ -289,16 +299,14 @@ object connect(int uid, int port, string service) { #if HAS_PORT(TELNETS_PORT, TELNET_PATH) case TELNETS_PORT: - t = tls_init_connection(this_object()); - if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - port, tls_error(t) )); + TLS_INIT // we could do the UID2NICK thing here, too, but why should we? // what do you need tls for on a localhost tcp link? return clone_object(TELNET_PATH "server"); #endif #if HAS_PORT(TELNET_PORT, TELNET_PATH) - case TELNET_PORT: // we could enable AUTODETECT for this.. (wait 4s) -// set_prompt("> "); + case TELNET_PORT: + TLS_INIT_AUTODETECT t = clone_object(TELNET_PATH "server"); # ifdef UID2NICK if (uid && (arg = UID2NICK(uid))) { t -> sName(arg); } @@ -306,9 +314,6 @@ object connect(int uid, int port, string service) { return t; #endif -#if HAS_PORT(HTTP_PORT, HTTP_PATH) && AUTODETECT - case HTTP_PORT: // AUTODETECT on the HTTP port -#endif #if HAS_PORT(HTTPS_PORT, HTTP_PATH) case HTTPS_PORT: t = tls_init_connection(this_object()); @@ -327,19 +332,19 @@ object connect(int uid, int port, string service) { /* don't fall thru. allow for https: to be available without http: */ #if HAS_PORT(HTTP_PORT, HTTP_PATH) &&! AUTODETECT case HTTP_PORT: + TLS_INIT_AUTODETECT return clone_object(HTTP_PATH "server"); #endif #if HAS_PORT(MUDS_PORT, MUD_PATH) case MUDS_PORT: - t = tls_init_connection(this_object()); - if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n", - port, tls_error(t) )); + TLS_INIT return clone_object(MUD_PATH "login"); #endif #if HAS_PORT(MUD_PORT, MUD_PATH) default: // if you want to multiplex psyced with an LPMUD game + TLS_INIT_AUTODETECT // set_prompt("> "); return clone_object(MUD_PATH "login"); #endif From 86f6ec17493206710e1c21eefb87395dc6cef181 Mon Sep 17 00:00:00 2001 From: "psyc://psyced.org/~lynX" <@> Date: Wed, 24 Aug 2011 09:13:43 +0200 Subject: [PATCH 13/13] general autodetect --- world/drivers/ldmud/master/accept.c | 172 +++++++++++++++------------- 1 file changed, 93 insertions(+), 79 deletions(-) diff --git a/world/drivers/ldmud/master/accept.c b/world/drivers/ldmud/master/accept.c index 60f087d..16c42dc 100644 --- a/world/drivers/ldmud/master/accept.c +++ b/world/drivers/ldmud/master/accept.c @@ -83,6 +83,13 @@ object connect(int uid, int port, string service) { } \ } +// doesn't work. at this point autodetect hasn't completed.. so to +// make sure TLS is enabled we need to check again later in the +// server object.. FIXME :( +#define TLS_ENFORCE \ + if (tls_query_connection_state(ME) == 0) \ + return (object) 0; + #if __EFUN_DEFINED__(tls_want_peer_certificate) // Specify that a subsequent call to tls_init_connection // should request a peer certificate. @@ -98,25 +105,81 @@ object connect(int uid, int port, string service) { # define TLS_INIT_GET_CERT TLS_INIT #endif -#if AUTODETECT -# define TLS_INIT_AUTODETECT TLS_INIT -#else -# define TLS_INIT_AUTODETECT // do nothing -#endif - - // we dont want the telnet machine most of the time - // but disabling and re-enabling it for telnet doesn't work + // in the first switch we handle ports that MUST not support + // immediate TLS (currently that's just 5269) or that want a + // peer certificate from the other side (PSYC). for all other + // ports the default is to attempt a TLS autodetection. switch(port) { -#if HAS_PORT(PSYC_PORT, PSYC_PATH) && AUTODETECT - case PSYC_PORT: - // make TLS available even on the default psyc port using the autodetection feature +#if HAS_PORT(JABBER_S2S_PORT, JABBER_PATH) + case JABBER_S2S_PORT: +# ifdef DRIVER_HAS_CALL_BY_REFERENCE + arg = ME; + query_ip_number(&arg); + // this assumes network byte order provided by driver + peerport = pointerp(arg) ? (arg[2]*256 + arg[3]) : 0; + if (peerport < 0) peerport = 65536 + peerport; + if (peerport == JABBER_S2S_SERVICE) peerport = 0; +# else + // as long as the object names don't collide, this is okay too + peerport = 65536 + random(9999999); +# endif +# if __EFUN_DEFINED__(enable_telnet) + enable_telnet(0); +# endif + t = "S:xmpp:"+query_ip_number(); + // it's just an object name, but let's be consequent minus peerport + if (peerport) t += ":-"+peerport; +# ifdef _flag_log_sockets_XMPP + SIMUL_EFUN_FILE -> log_file("RAW_XMPP", "\n\n%O: %O -> load(%O, %O)", + ME, t, +# ifdef _flag_log_hosts + query_ip_number(), +# else + "?", +# endif + -peerport); +# endif + P3(("%O -> load(%O, %O)\n", t, query_ip_number(), -peerport)) + return t -> load(query_ip_number(), -peerport); #endif #if HAS_PORT(PSYCS_PORT, PSYC_PATH) case PSYCS_PORT: // inofficial & temporary -#endif TLS_INIT_GET_CERT - // fall thru -#if HAS_PORT(PSYC_PORT, PSYC_PATH) &&! AUTODETECT + break; +#endif +#if HAS_PORT(PSYC_PORT, PSYC_PATH) && AUTODETECT + case PSYC_PORT: + // make TLS available on the default PSYC port + // using the autodetection feature (official approach) + TLS_INIT_GET_CERT + break; +#endif +#if HAS_PORT(SPYCS_PORT, SPYC_PATH) + case SPYCS_PORT: // even more inofficial + TLS_INIT_GET_CERT + break; +#endif +#if HAS_PORT(SPYC_PORT, SPYC_PATH) && AUTODETECT + case SPYC_PORT: // even more inofficial + TLS_INIT_GET_CERT + break; +#endif + default: +#if AUTODETECT + // if autodetect is available, let's check if this connection + // has TLS enabled and activate it, no matter which protocol. + TLS_INIT +#endif + break; + } + + // if we got here, we may have initialized TLS successfully + switch(port) { +#if HAS_PORT(PSYCS_PORT, PSYC_PATH) + case PSYCS_PORT: // inofficial & temporary + TLS_ENFORCE +#endif +#if HAS_PORT(PSYC_PORT, PSYC_PATH) case PSYC_PORT: #endif #if HAS_PORT(PSYC_PORT, PSYC_PATH) || HAS_PORT(PSYCS_PORT, PSYC_PATH) @@ -145,13 +208,10 @@ object connect(int uid, int port, string service) { return t -> load(query_ip_number(), -peerport); #endif -// dedicated SPYC port.. should not be used, we have AUTODETECT +// dedicated SPYC port.. should not be used #if HAS_PORT(SPYCS_PORT, SPYC_PATH) case SPYCS_PORT: // interim name for PSYC 1.0 according to SPEC -# if __EFUN_DEFINED__(tls_want_peer_certificate) - tls_want_peer_certificate(ME); -# endif - TLS_INIT + TLS_ENFORCE #endif // fall thru #if HAS_PORT(SPYC_PORT, SPYC_PATH) case SPYC_PORT: @@ -186,7 +246,7 @@ object connect(int uid, int port, string service) { #if HAS_PORT(POP3S_PORT, POP3_PATH) case POP3S_PORT: - TLS_INIT + TLS_ENFORCE return clone_object(POP3_PATH "server"); #endif #if HAS_PORT(POP3_PORT, POP3_PATH) @@ -196,7 +256,7 @@ object connect(int uid, int port, string service) { #if HAS_PORT(SMTPS_PORT, NNTP_PATH) case SMTPS_PORT: - TLS_INIT + TLS_ENFORCE return clone_object(SMTP_PATH "server"); #endif #if HAS_PORT(SMTP_PORT, SMTP_PATH) @@ -212,7 +272,7 @@ object connect(int uid, int port, string service) { #if HAS_PORT(NNTPS_PORT, NNTP_PATH) case NNTPS_PORT: - TLS_INIT + TLS_ENFORCE return clone_object(NNTP_PATH "server"); #endif #if HAS_PORT(NNTP_PORT, NNTP_PATH) @@ -222,50 +282,19 @@ object connect(int uid, int port, string service) { #if HAS_PORT(JABBERS_PORT, JABBER_PATH) case JABBERS_PORT: - TLS_INIT + TLS_ENFORCE return clone_object(JABBER_PATH "server"); #endif #if HAS_PORT(JABBER_PORT, JABBER_PATH) case JABBER_PORT: # if __EFUN_DEFINED__(enable_telnet) + // we dont want the telnet machine most of the time + // but disabling and re-enabling it for telnet doesn't work enable_telnet(0); // are you sure!??? # endif return clone_object(JABBER_PATH "server"); #endif -#if HAS_PORT(JABBER_S2S_PORT, JABBER_PATH) - case JABBER_S2S_PORT: -# ifdef DRIVER_HAS_CALL_BY_REFERENCE - arg = ME; - query_ip_number(&arg); - // this assumes network byte order provided by driver - peerport = pointerp(arg) ? (arg[2]*256 + arg[3]) : 0; - if (peerport < 0) peerport = 65536 + peerport; - if (peerport == JABBER_S2S_SERVICE) peerport = 0; -# else - // as long as the object names don't collide, this is okay too - peerport = 65536 + random(9999999); -# endif -# if __EFUN_DEFINED__(enable_telnet) - enable_telnet(0); -# endif - t = "S:xmpp:"+query_ip_number(); - // it's just an object name, but let's be consequent minus peerport - if (peerport) t += ":-"+peerport; -# ifdef _flag_log_sockets_XMPP - SIMUL_EFUN_FILE -> log_file("RAW_XMPP", "\n\n%O: %O -> load(%O, %O)", - ME, t, -# ifdef _flag_log_hosts - query_ip_number(), -# else - "?", -# endif - -peerport); -# endif - P3(("%O -> load(%O, %O)\n", t, query_ip_number(), -peerport)) - return t -> load(query_ip_number(), -peerport); -#endif - #if 0 //__EFUN_DEFINED__(enable_binary) // work in progress case 8888: @@ -280,12 +309,11 @@ object connect(int uid, int port, string service) { #if HAS_PORT(IRCS_PORT, IRC_PATH) case IRCS_PORT: - TLS_INIT + TLS_ENFORCE return clone_object(IRC_PATH "server"); #endif #if HAS_PORT(IRC_PORT, IRC_PATH) case IRC_PORT: - TLS_INIT_AUTODETECT return clone_object(IRC_PATH "server"); #endif @@ -299,14 +327,13 @@ object connect(int uid, int port, string service) { #if HAS_PORT(TELNETS_PORT, TELNET_PATH) case TELNETS_PORT: - TLS_INIT + TLS_ENFORCE // we could do the UID2NICK thing here, too, but why should we? // what do you need tls for on a localhost tcp link? return clone_object(TELNET_PATH "server"); #endif #if HAS_PORT(TELNET_PORT, TELNET_PATH) case TELNET_PORT: - TLS_INIT_AUTODETECT t = clone_object(TELNET_PATH "server"); # ifdef UID2NICK if (uid && (arg = UID2NICK(uid))) { t -> sName(arg); } @@ -316,42 +343,29 @@ object connect(int uid, int port, string service) { #if HAS_PORT(HTTPS_PORT, HTTP_PATH) case HTTPS_PORT: - t = tls_init_connection(this_object()); - if (t < 0) { - D1( if (t != ERR_TLS_NOT_DETECTED) PP(( "TLS(%O) on %O: %O\n", - t, port, tls_error(t) )); ) -#if !HAS_PORT(HTTP_PORT, HTTP_PATH) - // if we have no http port, it may be intentional - return (object)0; -#endif - } - D2( else if (t > 0) PP(( "Setting up TLS connection in the background.\n" )); ) - D2( else PP(( "Oh yeah, I'm initializing an https session!\n" )); ) + TLS_ENFORCE return clone_object(HTTP_PATH "server"); #endif - /* don't fall thru. allow for https: to be available without http: */ -#if HAS_PORT(HTTP_PORT, HTTP_PATH) &&! AUTODETECT + // don't fall thru. allow for https: to be available without http: +#if HAS_PORT(HTTP_PORT, HTTP_PATH) case HTTP_PORT: - TLS_INIT_AUTODETECT return clone_object(HTTP_PATH "server"); #endif #if HAS_PORT(MUDS_PORT, MUD_PATH) case MUDS_PORT: - TLS_INIT + TLS_ENFORCE return clone_object(MUD_PATH "login"); #endif #if HAS_PORT(MUD_PORT, MUD_PATH) default: // if you want to multiplex psyced with an LPMUD game - TLS_INIT_AUTODETECT // set_prompt("> "); return clone_object(MUD_PATH "login"); #endif } - - PP(("Received connection on port %O which isn't configured.\n", - port)); + + P0(("Received connection on port %O which isn't configured.\n", port)); return (object)0; }