diff --git a/CHANGELOG b/CHANGELOG index 57c0528f..2ba2d75a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,19 @@ This file lists all changes made to the game driver in all gory detail. See the file HISTORY for a user-oriented summary of all the changes. +06-Mar-2006 (Lars Duening) + - (backend, comm.c, object) The logon(obj) function moved from + backend.c into object.c, and was renamed logon_object() - it's + more sensical this way. + - (comm.c) If the master::connect() initiates a secure connection + which gets stuck in the handshake, neither logon() is called nor + is the prompt printed. Also, if the tls_init_connection() didn't + set a callback, the driver will provide a callback to logon(). + This way logon() won't be called unless the connection is up + and running. + - (mudlib/psyc-tls.c) Example for using the tls_check_certificate() + efun (thanks, Philipp). + 03-Mar-2006 (Lars Duening) - (pkg-tls.c) tls_check_certificate() does more interpretation of the result and returns better data (provided by Philipp). diff --git a/HISTORY b/HISTORY index 7fd05055..c2af1e32 100644 --- a/HISTORY +++ b/HISTORY @@ -4,7 +4,7 @@ the host system. For a detailed list of all changes see the file CHANGELOG. -03-Mar-2006 (Lars Duening) -- Release 3.3.713 +06-Mar-2006 (Lars Duening) -- Release 3.3.713 - New Efuns: + sl_close(), sl_open(), sl_exec(), sl_insert_id(): Optional SQLite @@ -46,6 +46,12 @@ For a detailed list of all changes see the file CHANGELOG. automatically anyway. + Missing returns are logged at runtime only once per function and occurance. + + If the master:;connect() initiates a secure connection + which gets stuck in the handshake, neither logon() is called nor + is the prompt printed. Also, if the tls_init_connection() didn't + set a callback, the driver will provide a callback to logon(). + This way logon() won't be called unless the connection is up + and running. - Other: + The makefile is able to install the driver's LPC header diff --git a/doc/applied/logon b/doc/applied/logon index 6e4c6177..97f0373f 100644 --- a/doc/applied/logon +++ b/doc/applied/logon @@ -14,8 +14,15 @@ DESCRIPTION background and failed, it will call logon(-1) in the intended object to inform the mudlib about the failure. + If the master attempted a secure connection in connect(E) and + did not set an explicit TLS callback, the call to logon() won't + happen until the TLS handshake is complete. If the master set + a TLS callback, that will be executed in place of logon(). + HISTORY LDMud 3.2.10 added the extended meaning for net_connect(). + LDMud 3.2.13/3.3.713 streamlined the handling of secure connections + during logon. SEE ALSO - connect(M), net_connect(E), exec(E) + connect(M), net_connect(E), exec(E), tls_init_connection(E) diff --git a/doc/efun/tls_check_certificate b/doc/efun/tls_check_certificate index 86080133..f5df50dd 100644 --- a/doc/efun/tls_check_certificate +++ b/doc/efun/tls_check_certificate @@ -46,4 +46,4 @@ HISTORY SEE ALSO tls_init_connection(E), tls_deinit_connection(E), tls_error(E), tls_query_connection_state(E), tls_query_connection_info(E), - tls_available(E) + tls_available(E), mudlib/psyc-tls.c diff --git a/doc/efun/tls_init_connection b/doc/efun/tls_init_connection index a891bf24..e5819924 100644 --- a/doc/efun/tls_init_connection +++ b/doc/efun/tls_init_connection @@ -32,10 +32,17 @@ DESCRIPTION The driver automatically suppresses the printing of the prompt while the TLS handshake is in progress. + If tls_init_connection() is called in the master::connect() function, + the driver will either call the set callback in place of logon(), or + if not callback has been set, delay the call of logon() until the + state of the connection is clear. + HISTORY Introduced in LDMud 3.3.474 and following, backported to 3.2.11. + LDMud 3.2.13/3.3.713 streamlined the handling of secure connections + during logon. SEE ALSO tls_deinit_connection(E), tls_error(E), tls_query_connection_state(E), tls_query_connection_info(E), tls_available(E), - tls_check_certificate(E) + tls_check_certificate(E), connect(M), logon(A) diff --git a/doc/master/connect b/doc/master/connect index 970bffe4..03423be5 100644 --- a/doc/master/connect +++ b/doc/master/connect @@ -12,6 +12,15 @@ DESCRIPTION binding the connection to it. That lfun has to return != 0 to indicate success. + If connect() initiates a secure connection without setting a callback, + and the connection is still handshaking at the time connect() returns, + the driver will delay the call to logon() until the handshake either + succeeds or fails. + +HISTORY + LDMud 3.2.13/3.3.713 streamlined the handling of secure connections + during logon. + SEE ALSO logon(A), disconnect(M), interactive(E), exec(E), - net_connect(E) + net_connect(E), tls_init_connection(E) diff --git a/mudlib/master_skeleton.c b/mudlib/master_skeleton.c index 1686abf8..a7cba6f8 100644 --- a/mudlib/master_skeleton.c +++ b/mudlib/master_skeleton.c @@ -417,6 +417,12 @@ object connect () // // The gamedriver will call the lfun 'logon()' in the login object after // binding the connection to it. That lfun has to return !=0 to succeed. +// +// If connect() initiates a secure connection without setting a callback, +// and the connection is still handshaking at the time connect() returns, +// the driver will delay the call to logon() until the handshake either +// succeeds or fails. + //--------------------------------------------------------------------------- diff --git a/mudlib/psyc-tls.c b/mudlib/psyc-tls.c new file mode 100644 index 00000000..63d90119 --- /dev/null +++ b/mudlib/psyc-tls.c @@ -0,0 +1,128 @@ +#include // vim syntax=lpc + +/* Wrapper for using the tls_check_certificate() efun. + * + * If for example the efun returns this raw data: + * + * ({ + * 20, + * ({ + * "2.5.4.6", + * "countryName", + * "DE", + * "2.5.4.10", + * "organizationName", + * "mabber.com", + * "2.5.4.11", + * "organizationalUnitName", + * "businessprofile.geotrust.com/get.jsp?GT94033690", + * "2.5.4.11", + * "organizationalUnitName", + * "See www.rapidssl.com/cps (c)05", + * "2.5.4.11", + * "organizationalUnitName", + * "Domain Control Validated - RapidSSL(R)", + * "2.5.4.3", + * "commonName", + * "mabber.com" + * }), + * ({ + * 0, + * 0, + * 0, + * 0, + * 0, + * 0, + * 0, + * 0, + * 0, + * 0, + * 0, + * 0, + * 0, + * 0, + * 0, + * 0, + * 0, + * 0 + * }) + * }) + * + * the wrapper will transform it into: + * + * ([ + * 0: 20, + * "2.5.4.10": "mabber.com", + * "2.5.4.11": ({ + * "businessprofile.geotrust.com/get.jsp?GT94033690", + * "See www.rapidssl.com/cps (c)05", + * "Domain Control Validated - RapidSSL(R)" + * }), + * "2.5.4.3": "mabber.com", + * "2.5.4.6": "DE" + * ]) + * + * + */ + +mapping tls_certificate(object who, int longnames) { + mixed *extra, extensions; + mapping cert; + int i, j; + + cert = ([ ]); +#if __EFUN_DEFINED__(tls_check_certificate) +# ifdef WANT_S2S_SASL + extra = tls_check_certificate(who, 1); + unless (extra) return 0; + cert[0] = extra[0]; + extensions = extra[2]; + extra = extra[1]; + + for (i = 0; i < sizeof(extra); i += 3) { + mixed t; + + t = cert[extra[i]]; + unless (t) { + cert[extra[i]] = extra[i+2]; + } else if (stringp(t)) { + cert[extra[i]] = ({ t, extra[i+2] }); + } else if (pointerp(t)) { + cert[extra[i]] += ({ extra[i+2] }); + } else { + // should not happen + } + } + if (longnames) { + // set up short/long names + for (i = 0; i < sizeof(extra); i +=3) { + cert[extra[i+1]] = cert[extra[i]]; + } + } + for (i = 0; i < sizeof(extensions); i += 3) { + string key, mkey; + mixed *val; + + unless(extensions[i]) continue; + key = extensions[i]; + val = extensions[i+2]; + for (j = 0; j < sizeof(val); j += 3) { + mixed t; + + mkey = key + ":" + val[j]; + t = cert[mkey]; + unless (t) { + cert[mkey] = val[j+2]; + } else if (stringp(t)) { + cert[mkey] = ({ t, val[j+2] }); + } else if (pointerp(t)) { + cert[mkey] += ({ val[j+2] }); + } else { + // should not happen + } + } + } +# endif +#endif + return cert; +} diff --git a/src/Makefile.in b/src/Makefile.in index ce65a286..501383e8 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -292,9 +292,10 @@ comm.o : util/erq/erq.h ../mudlib/sys/input_to.h \ ../mudlib/sys/driver_hook.h ../mudlib/sys/comm.h xalloc.h wiz_list.h \ swap.h svalue.h stdstrings.h simulate.h sent.h pkg-tls.h pkg-pgsql.h \ pkg-mccp.h object.h mstrings.h main.h interpret.h gcollect.h filestat.h \ - exec.h ed.h closure.h backend.h array.h actions.h access_check.h comm.h \ + exec.h ed.h closure.h array.h actions.h access_check.h comm.h \ ../mudlib/sys/telnet.h my-alloca.h typedefs.h driver.h strfuns.h \ - bytecode.h hash.h config.h port.h hosts/unix.h hosts/be/be.h machine.h + bytecode.h hash.h backend.h config.h port.h hosts/unix.h hosts/be/be.h \ + machine.h dumpstat.o : xalloc.h svalue.h structs.h stdstrings.h simulate.h ptrtable.h \ object.h mstrings.h mapping.h instrs.h filestat.h exec.h closure.h \ @@ -428,6 +429,11 @@ pkg-alists.o : i-svalue_cmp.h xalloc.h svalue.h simulate.h mstrings.h \ closure.h strfuns.h sent.h bytecode.h hash.h backend.h port.h config.h \ hosts/unix.h hosts/be/be.h machine.h +pkg-idna.o : ../mudlib/sys/idn.h xalloc.h simulate.h mstrings.h interpret.h \ + typedefs.h pkg-idna.h driver.h svalue.h strfuns.h sent.h bytecode.h \ + hash.h backend.h port.h config.h main.h hosts/unix.h hosts/be/be.h \ + machine.h + pkg-mccp.o : ../mudlib/sys/telnet.h xalloc.h svalue.h object.h mstrings.h \ comm.h array.h pkg-mccp.h typedefs.h driver.h strfuns.h sent.h hash.h \ pkg-tls.h simulate.h port.h config.h bytecode.h hosts/unix.h \ diff --git a/src/backend.c b/src/backend.c index ea35e8c0..ae96173f 100644 --- a/src/backend.c +++ b/src/backend.c @@ -296,32 +296,6 @@ do_state_check (int minlvl, const char *where) #endif -/*-------------------------------------------------------------------------*/ -void -logon (object_t *ob) - -/* Call the logon() lfun in the object . - * - * current_object is temporarily set to in order to allow logon() - * to be static (security measure). Doing so is harmless as there is no - * previous_object to consider. - * - * TODO: This should go into simulate.c or comm.c - */ - -{ - svalue_t *ret; - object_t *save = current_object; - - current_object = ob; - ret = apply(STR_LOGON, ob, 0); - if (ret == 0) { - /* add_message("prog %s:\n", get_txt(ob->name)); */ - errorf("Could not find logon() on the player %s\n", get_txt(ob->name)); - } - current_object = save; -} /* logon() */ - /*-------------------------------------------------------------------------*/ static RETSIGTYPE handle_hup (int sig UNUSED) diff --git a/src/backend.h b/src/backend.h index 5309126c..6c9d2bdd 100644 --- a/src/backend.h +++ b/src/backend.h @@ -47,7 +47,6 @@ extern Bool mud_is_up; extern void clear_state (void); extern void check_alarm (void); -extern void logon (object_t *ob); extern void backend (void); extern void preload_objects (int eflag); extern svalue_t *f_debug_message (svalue_t *sp); diff --git a/src/comm.c b/src/comm.c index b50c4114..c653179b 100644 --- a/src/comm.c +++ b/src/comm.c @@ -116,7 +116,6 @@ #include "access_check.h" #include "actions.h" #include "array.h" -#include "backend.h" #include "closure.h" #include "ed.h" #include "exec.h" @@ -3981,7 +3980,39 @@ new_player ( object_t *ob, SOCKET_T new_socket (void) lookup_ip_entry(new_interactive->addr.sin_addr, MY_TRUE); /* TODO: We could pass the retrieved hostname right to login */ #endif - logon(ob); +#ifdef USE_TLS + /* If we're using secure connections and the connect() triggered + * a handshake which is still going on, we call logon() as + * the default TLS callback. This way, logon() is callled only + * if the connection could be established, secure or not. + */ + if (new_interactive->tls_status != TLS_HANDSHAKING) + { + /* Connection not secure, or already established: logon. */ + logon_object(ob); + } + else if (new_interactive->tls_cb == NULL) + { + /* Connection in TLS handshake, but not callback: set a callback + * to the logon function. + */ + if (find_function(STR_LOGON, current_interactive->prog) < 0) + { + errorf("Could not find %s() on the player %s\n", get_txt(STR_LOGON), get_txt(current_interactive->name)); + /* NOTREACHED */ + } + + callback_t * cb; + + xallocate(cb, sizeof(*cb), "logon tls-callback structure"); + setup_function_callback(cb, current_interactive, STR_LOGON, 0, NULL, MY_TRUE); + new_interactive->tls_cb = cb; + + } + /* else: Connection in TLS handshake and callback set by connect(). */ +#else + logon_object(ob); +#endif /* USE_TLS */ if (!(ob->flags & O_DESTRUCTED)) print_prompt(); flush_all_player_mess(); @@ -8970,7 +9001,7 @@ check_for_out_connections (void) */ outconn[i].status = ocLoggingOn; push_number(inter_sp, -1); - logon(outconn[i].curr_obj); + logon_object(outconn[i].curr_obj); outconn[i].status = ocNotUsed; free_object(outconn[i].curr_obj, "net_connect"); diff --git a/src/hosts/be/Makefile b/src/hosts/be/Makefile index 214fdce0..f90291f2 100644 --- a/src/hosts/be/Makefile +++ b/src/hosts/be/Makefile @@ -450,9 +450,10 @@ $(OBJ)/comm.o : util/erq/erq.h ../mudlib/sys/input_to.h \ ../mudlib/sys/driver_hook.h ../mudlib/sys/comm.h xalloc.h wiz_list.h \ swap.h svalue.h stdstrings.h simulate.h sent.h pkg-tls.h pkg-pgsql.h \ pkg-mccp.h object.h mstrings.h main.h interpret.h gcollect.h filestat.h \ - exec.h ed.h closure.h backend.h array.h actions.h access_check.h comm.h \ + exec.h ed.h closure.h array.h actions.h access_check.h comm.h \ ../mudlib/sys/telnet.h my-alloca.h typedefs.h driver.h strfuns.h \ - bytecode.h hash.h config.h port.h hosts/unix.h hosts/be/be.h machine.h + bytecode.h hash.h backend.h config.h port.h hosts/unix.h hosts/be/be.h \ + machine.h $(OBJ)/dumpstat.o : xalloc.h svalue.h structs.h stdstrings.h simulate.h \ ptrtable.h object.h mstrings.h mapping.h instrs.h filestat.h exec.h \ @@ -587,6 +588,11 @@ $(OBJ)/pkg-alists.o : i-svalue_cmp.h xalloc.h svalue.h simulate.h \ typedefs.h driver.h closure.h strfuns.h sent.h bytecode.h hash.h \ backend.h port.h config.h hosts/unix.h hosts/be/be.h machine.h +$(OBJ)/pkg-idna.o : ../mudlib/sys/idn.h xalloc.h simulate.h mstrings.h \ + interpret.h typedefs.h pkg-idna.h driver.h svalue.h strfuns.h sent.h \ + bytecode.h hash.h backend.h port.h config.h main.h hosts/unix.h \ + hosts/be/be.h machine.h + $(OBJ)/pkg-mccp.o : ../mudlib/sys/telnet.h xalloc.h svalue.h object.h \ mstrings.h comm.h array.h pkg-mccp.h typedefs.h driver.h strfuns.h \ sent.h hash.h pkg-tls.h simulate.h port.h config.h bytecode.h \ diff --git a/src/object.c b/src/object.c index 427ec1ad..bfebcbec 100644 --- a/src/object.c +++ b/src/object.c @@ -905,6 +905,31 @@ reset_object (object_t *ob, int arg) ob->flags |= O_RESET_STATE; } /* reset_object() */ +/*-------------------------------------------------------------------------*/ +void +logon_object (object_t *ob) + +/* Call the logon() lfun in the object . + * + * current_object is temporarily set to in order to allow logon() + * to be static (security measure). Doing so is harmless as there is no + * previous_object to consider. + */ + +{ + svalue_t *ret; + object_t *save = current_object; + + current_object = ob; + ret = apply(STR_LOGON, ob, 0); + if (ret == 0) + { + errorf("Could not find %s() on the player %s\n", get_txt(STR_LOGON), get_txt(ob->name)); + /* NOTREACHED */ + } + current_object = save; +} /* logon_object() */ + /*-------------------------------------------------------------------------*/ void replace_programs (void) diff --git a/src/object.h b/src/object.h index 67c9a1ae..8ae21f06 100644 --- a/src/object.h +++ b/src/object.h @@ -285,6 +285,7 @@ extern void free_prog(program_t *progp, Bool free_all); extern void _free_prog(program_t *progp, Bool free_all, const char * file, int line); #endif extern void reset_object(object_t *ob, int arg); +extern void logon_object (object_t *ob); extern void replace_programs(void); extern Bool shadow_catch_message(object_t *ob, const char *str); diff --git a/src/simulate.c b/src/simulate.c index 96e96d37..216e2168 100644 --- a/src/simulate.c +++ b/src/simulate.c @@ -3916,7 +3916,7 @@ setup_efun_callback_base ( callback_t *cb, svalue_t *args, int nargs } return error_index; -} /* setup_efun_callback() */ +} /* setup_efun_callback_base() */ /*-------------------------------------------------------------------------*/ void diff --git a/src/version.sh b/src/version.sh index 91c3d52b..00c013e6 100644 --- a/src/version.sh +++ b/src/version.sh @@ -17,7 +17,7 @@ version_longtype="development" # A timestamp, to be used by bumpversion and other scripts. # It can be used, for example, to 'touch' this file on every build, thus # forcing revision control systems to add it on every checkin automatically. -version_stamp="Sat Mar 4 00:17:17 MST 2006" +version_stamp="Mon Mar 6 00:08:11 MST 2006" # The version number information version_micro=712