mirror of
git://git.psyced.org/git/psyced
synced 2024-08-15 03:25:10 +00:00
328 lines
9 KiB
C
328 lines
9 KiB
C
// vim:foldmethod=marker:syntax=lpc:noexpandtab
|
|
// $Id: common.c,v 1.64 2008/02/06 18:13:16 lynx Exp $
|
|
//
|
|
// common code for UDP and TCP server
|
|
|
|
#include <net.h>
|
|
#include <url.h>
|
|
#include <psyc.h>
|
|
|
|
#ifdef __MCCP__
|
|
# include <telnet.h>
|
|
#endif
|
|
|
|
#ifndef __PIKE__
|
|
#ifdef FORK
|
|
virtual inherit NET_PATH "state";
|
|
#endif
|
|
virtual inherit NET_PATH "trust";
|
|
#endif
|
|
|
|
// protos.
|
|
varargs mixed croak(string mc, string data, vamapping vars, vamixed source);
|
|
void connect_failure(string mc, string reason);
|
|
void runQ();
|
|
|
|
// microspect0rs.
|
|
string qScheme() { return "psyc"; }
|
|
|
|
int isServer() { return 0; }
|
|
|
|
int greet() { return 0; }
|
|
|
|
// rootMsg: handles messages to the psyc server root node
|
|
// lynX:
|
|
// i dont want this to be call_other'd, so i decided to inherit it
|
|
// into all psyc servers
|
|
// fippo:
|
|
// maybe we need a more generic root object to be inherited by
|
|
// all psyc and jabber servers
|
|
// it's there: net/root - yet it is not suitable for everything in here
|
|
|
|
varargs int rootMsg(mixed source, string mc, string data,
|
|
vamapping vars, vamixed target) {
|
|
string t;
|
|
#ifdef SCHWAN
|
|
mixed *u;
|
|
#endif
|
|
//PT((">>> %O::rootMsg(%O, %O, %O, %O, %O)\n", ME, source, mc, data, vars, target))
|
|
switch(mc) {
|
|
case "_status_circuit":
|
|
if (member(vars, "_understand_modules")) {
|
|
unless (pointerp(vars["_understand_modules"]))
|
|
vars["_understand_modules"] =
|
|
explode(vars["_understand_modules"], ";");
|
|
#ifdef __MCCP__
|
|
if (member(vars["_understand_modules"], "_compress") != -1) {
|
|
if(query_mccp(ME) || tls_query_connection_state(ME) > 0) break;
|
|
#ifdef FORK
|
|
croak("", "", ([ "+_using_modules" : "_compress" ]));
|
|
#else
|
|
croak("", "", ([ "_using_modules" : "_compress" ]));
|
|
#endif
|
|
enable_telnet(0);
|
|
start_mccp_compress(TELOPT_COMPRESS2);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
break;
|
|
case "_notice_link_established":
|
|
case "_notice_circuit_established":
|
|
#if 0
|
|
// note: module negotation is started by client
|
|
if (pointerp(vars["_understand_modules"]) && !isServer()) {
|
|
string module;
|
|
foreach(module : vars["_understand_modules"]) {
|
|
#ifdef __MCCP__
|
|
if (module == "_compress") {
|
|
croak("_request_compression",
|
|
"Requesting compression using [_method]",
|
|
([ "_method" : "zlib" ]),
|
|
query_server_unl());
|
|
return;
|
|
}
|
|
#endif
|
|
#ifdef __TLS__
|
|
// sigh... we need tls client functionality for that!
|
|
if (module == "_encrypt") {
|
|
croak("_request_circuit_encrypt",
|
|
"Requesting transport layer security",
|
|
([ ]), query_server_unl());
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
if (source == query_server_unl()) {
|
|
#ifndef __PIKE__ // TPD
|
|
if (function_exists("connect_failure"))
|
|
connect_failure("_self",
|
|
"That sender claims to be me!\n");
|
|
#endif
|
|
// It may look tempting to do a register_localhost
|
|
// here, but since we didn't make a serious attempt
|
|
// to ensure we are talking to ourselves an outside
|
|
// host may want to fool us into thinking an address
|
|
// is us, then inject messages with localhost trust
|
|
// level. We're not going to do that. For automatic
|
|
// virtual host detection we need to smarten up still!
|
|
PT(("SUICIDE %O\n", ME))
|
|
destruct(ME);
|
|
return 1;
|
|
}
|
|
#ifndef __PIKE__ // TPD
|
|
if (function_exists("runQ")) {
|
|
P2(("%s in %O: runQ()\n", mc, ME));
|
|
runQ();
|
|
} else
|
|
#endif
|
|
{
|
|
P2(("%s in %O: no runQ to execute\n", mc, ME));
|
|
}
|
|
#ifdef SCHWAN
|
|
if (vars["_source_verbatim"]
|
|
&& u = parse_uniform(vars["_source_verbatim"])) {
|
|
if (u[UHost]) {
|
|
register_host(u[UHost]);
|
|
}
|
|
}
|
|
#endif
|
|
break;
|
|
#ifdef EXPERIMENTAL
|
|
case "_notice_authentication":
|
|
P0(("rootMsg got a _notice_authentication. never happens since entity.c\n"))
|
|
register_location(vars["_location"], source, 1);
|
|
break;
|
|
case "_error_invalid_authentication":
|
|
monitor_report(mc, psyctext("Breach: [_source] reports invalid authentication provided by [_location]", vars, data, source));
|
|
break;
|
|
#endif
|
|
#if 0
|
|
case "_request_session_compression":
|
|
case "_request_session_compress":
|
|
#ifdef __MCCP__
|
|
// dont try to compress an already compressed stream...
|
|
// and compressing an sslified stream is pretty
|
|
// meaningless
|
|
if(query_mccp(ME) || tls_query_connection_state(ME) > 0) break;
|
|
// reply with a _status_compression and start compression
|
|
croak("_notice_circuit_compress",
|
|
"Will restart with compression using [_method]",
|
|
([ "_method" : vars["_method"] || "zlib" ]),
|
|
query_server_unl());
|
|
enable_telnet(0);
|
|
start_mccp_compress(TELOPT_COMPRESS2);
|
|
// greet(); // TODO: calling it directly kills pypsyc
|
|
call_out(#'greet, 1);
|
|
break;
|
|
case "_notice_circuit_compress":
|
|
// TODO: we have to make sure that we had wanted to do
|
|
// compression to this host
|
|
//start_mccp_compress(TELOPT_COMPRESS2);
|
|
P0(("%O is getting compressed from the other side. ouch!\n", ME))
|
|
#else
|
|
croak("_error_unavailable_circuit_compress",
|
|
"Did I really flaunt compression to you?",
|
|
([ ]), query_server_unl());
|
|
#endif
|
|
break;
|
|
case "_request_circuit_encryption":
|
|
case "_request_circuit_encrypt":
|
|
#ifdef __TLS__
|
|
// answer with either _status_tls and go ahead, we are
|
|
// server side of the handshake
|
|
// or reply _error_tls_unavailable
|
|
int t;
|
|
if (t = tls_query_connection_state(ME) == 0) {
|
|
croak("_notice_circuit_encrypt",
|
|
"Enabling TLS encryption.", ([ ]),
|
|
query_server_unl());
|
|
tls_init_connection(ME);
|
|
// here we could actually need lars style
|
|
// to call greet when ready()
|
|
} else if (t > 0) {
|
|
/* sendmsg(source, "_error_tls_active",
|
|
"TLS is already active",
|
|
([ ]), query_server_unl()); */
|
|
P0(("received %O for %O who already has TLS\n", mc, ME))
|
|
} else {
|
|
// negative numbers (current behaviour of ldmud)
|
|
// should never make it here
|
|
P0(("negative numbers are impossible here :)\n"))
|
|
}
|
|
#else
|
|
// we can not be advertising it
|
|
croak("_error_unavailable_circuit_encrypt",
|
|
"Can not remember telling you I had TLS.",
|
|
([ ]), query_server_unl());
|
|
#endif
|
|
break;
|
|
case "_notice_circuit_encrypt":
|
|
#if __EFUN_DEFINED__(tls_init_connection)
|
|
PT(("is my connection secure %O\n", tls_query_connection_state()))
|
|
// we just leave the socket to verreck, because closing it
|
|
// would probably only incite the other side to reconnect
|
|
tls_init_connection(ME, #'greet);
|
|
#endif
|
|
break;
|
|
#endif
|
|
case 0: // this is kinda funky!
|
|
if (member(vars, "_using_modules")) {
|
|
unless (pointerp(vars["_using_modules"]))
|
|
vars["_using_modules"] = ({ vars["_using_modules"] });
|
|
|
|
#ifdef __TLS__
|
|
if (member(vars["_using_modules"], "_encrypt") != -1) {
|
|
if (tls_query_connection_state(ME) == 0) {
|
|
croak("", "", ([ "_using_modules" : "_encrypt" ]));
|
|
tls_init_connection(ME);
|
|
}
|
|
# ifdef __MCCP__
|
|
} else
|
|
# else
|
|
}
|
|
# endif
|
|
#endif
|
|
#ifdef __MCCP__
|
|
if (member(vars["_using_modules"], "_compress") != -1) {
|
|
P0(("%O is getting compressed from the other side."
|
|
"ouch! Closing Connection!\n", ME))
|
|
croak("_error_compress_unavailable",
|
|
"I don't want to receive compressed data.");
|
|
destruct(ME);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
break;
|
|
default:
|
|
// sendmsg(source, "_error_unsupported_method",
|
|
// "Don't know what to do with '[_method]'.",
|
|
// ([ "_method" : mc ]), "");
|
|
P1(("rootMsg(%O,%O,%O,%O,%O)\n", source,mc,data,vars,target))
|
|
#if 0 //def EXPERIMENTAL
|
|
// circuit root wasn't successful, let's pass the message
|
|
// on to the server root entity
|
|
return sendmsg("/", mc, data, vars, source);
|
|
#else
|
|
t = "Circuit got "+ mc;
|
|
if (target) t += " to "+ target;
|
|
unless (source) source = vars["_INTERNAL_source"]
|
|
|| vars["_INTERNAL_origin"];
|
|
if (source) t += " from "+ to_string(source);
|
|
monitor_report("_notice_forward"+ mc, psyctext(data ?
|
|
t+": "+data : t, vars, "", source));
|
|
return 0;
|
|
#endif
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void internalError() {
|
|
write("_failure_broken_parser\n.\n\n");
|
|
#ifndef __PIKE__ // TPD
|
|
// reicht das schon, oder müssen wir weitere maßnahmen ergreifen?
|
|
remove_interactive(ME);
|
|
#endif
|
|
}
|
|
|
|
#ifdef FORK // {{{
|
|
void Assign(mixed source, string key, mixed value) {
|
|
}
|
|
void negotiate(mixed modules) {
|
|
#ifdef __TLS__
|
|
unless (pointerp(modules))
|
|
modules = ({ modules });
|
|
foreach (string key : modules) {
|
|
if ("_encrypt" == key) {
|
|
if (tls_query_connection_state(ME) == 0) {
|
|
|
|
croak("", "", "", ([ "+_using_modules" : "_encrypt", "_target" : "" ]));
|
|
|
|
tls_init_connection(ME);
|
|
}
|
|
return;
|
|
}
|
|
#ifdef __MCCP__
|
|
if ("_compress" == key) {
|
|
P0(("%O is getting compressed from the other side."
|
|
"ouch! Closing Connection!\n", ME))
|
|
croak("_error_compress_unavailable",
|
|
"I don't want to receive compressed data.");
|
|
destruct(ME);
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void gotiate(mixed modules) {
|
|
unless (pointerp(modules))
|
|
modules = ({ modules });
|
|
foreach (string key : modules) {
|
|
#ifdef __MCCP__
|
|
if ("_compress" == key) {
|
|
if(query_mccp(ME)
|
|
#ifdef __TLS__
|
|
|| tls_query_connection_state(ME) > 0
|
|
#endif
|
|
) break;
|
|
croak("", "", "", ([ "+_using_modules" : "_compress" ]));
|
|
enable_telnet(0);
|
|
start_mccp_compress(TELOPT_COMPRESS2);
|
|
}
|
|
return;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void Diminish(mixed source, string key, mixed value) {
|
|
}
|
|
void Reset() {
|
|
|
|
}
|
|
|
|
#endif // FORK }}}
|