835c6c2001-06-17Martin Nilsson // This file is part of Roxen WebServer.
b655bf2004-06-30Martin Stjernholm // Copyright © 1996 - 2004, Roxen IS.
835c6c2001-06-17Martin Nilsson // // The Roxen WebServer main program.
24c6c12000-02-20Martin Nilsson //
02ee412000-12-17Henrik Grubbström (Grubba) // Per Hedbor, Henrik Grubbström, Pontus Hagland, David Hedbor and others.
edc9af1998-07-11David Hedbor // ABS and suicide systems contributed freely by Francesco Chemolli
835c6c2001-06-17Martin Nilsson 
4029da2007-03-02Henrik Grubbström (Grubba) constant cvs_version="$Id: roxen.pike,v 1.959 2007/03/02 18:03:38 grubba Exp $";
5d3e442002-12-09Henrik Grubbström (Grubba)  //! @appears roxen //! //! The Roxen WebServer main program.
8fb5172000-05-27Per Hedbor  // The argument cache. Used by the image cache.
855c391999-11-29Per Hedbor ArgCache argcache;
1720541998-10-04Henrik Grubbström (Grubba)  // Some headerfiles
4dd97c1996-12-04Per Hedbor #define IN_ROXEN
8540e11997-06-14Francesco Chemolli #include <roxen.h> #include <config.h>
b1fca01996-11-12Per Hedbor #include <module.h> #include <variables.h>
753a831999-08-30Per Hedbor #include <stat.h>
9c19002001-02-27Per Hedbor #include <timers.h>
14179b1997-01-29Per Hedbor 
1720541998-10-04Henrik Grubbström (Grubba) // Inherits
753a831999-08-30Per Hedbor inherit "global_variables";
6897c92001-06-27Honza Petrous #ifdef SNMP_AGENT inherit "snmpagent"; #endif
4029da2007-03-02Henrik Grubbström (Grubba) #ifdef SMTP_RELAY inherit "smtprelay"; #endif
b1fca01996-11-12Per Hedbor inherit "hosts"; inherit "disk_cache";
970e242000-09-12Per Hedbor // inherit "language";
2ff8461999-09-02Per Hedbor inherit "supports";
08eba62000-07-09Per Hedbor inherit "module_support";
970e242000-09-12Per Hedbor inherit "config_userdb";
7c92b91998-11-19Per Hedbor 
79c3a62001-04-25Jonas Wallden #ifdef THREADS // Used when running threaded to find out which thread is the backend thread. Thread.Thread backend_thread; #endif /* THREADS */
23414a2000-07-21Andreas Lange // --- Locale defines --- //<locale-token project="roxen_start"> LOC_S </locale-token> //<locale-token project="roxen_message"> LOC_M </locale-token> #define LOC_S(X,Y) _STR_LOCALE("roxen_start",X,Y) #define LOC_M(X,Y) _STR_LOCALE("roxen_message",X,Y) #define CALL_M(X,Y) _LOCALE_FUN("roxen_message",X,Y)
be788e2000-03-27Martin Nilsson // --- Debug defines ---
81f8af1999-12-20Martin Nilsson  #ifdef SSL3_DEBUG
fe1c132005-05-25Martin Stjernholm # define SSL3_WERR(X) report_debug("TLS port %s: %s\n", get_url(), X)
81f8af1999-12-20Martin Nilsson #else
bfb4d41999-12-28Martin Nilsson # define SSL3_WERR(X)
81f8af1999-12-20Martin Nilsson #endif #ifdef THREAD_DEBUG
3e6f6b2001-03-11Martin Nilsson # define THREAD_WERR(X) report_debug("Thread: "+X+"\n")
81f8af1999-12-20Martin Nilsson #else
bfb4d41999-12-28Martin Nilsson # define THREAD_WERR(X)
81f8af1999-12-20Martin Nilsson #endif
60a9121999-10-10Henrik Grubbström (Grubba) 
8cc5fc2003-03-05Martin Stjernholm // Needed to get core dumps of seteuid()'ed processes on Linux. #if constant(System.dumpable) #define enable_coredumps(X) System.dumpable(X) #elif constant(system.dumpable) // Pike 7.2. #define enable_coredumps(X) system.dumpable(X) #else #define enable_coredumps(X) #endif
8514832000-11-27Per Hedbor #define DDUMP(X) sol( combine_path( __FILE__, "../../" + X ), dump ) static function sol = master()->set_on_load;
aa78722001-08-24Martin Stjernholm #ifdef TEST_EUID_CHANGE int test_euid_change; #endif
50b6972001-08-31Per Hedbor string md5( string what ) { return Gmp.mpz(Crypto.md5()->update( what )->digest(),256) ->digits(32); }
970e242000-09-12Per Hedbor string query_configuration_dir() { return configuration_dir; }
855c391999-11-29Per Hedbor 
5964251999-11-19Per Hedbor string filename( program|object o )
95b69e1999-09-05Per Hedbor {
5964251999-11-19Per Hedbor  if( objectp( o ) ) o = object_program( o );
2537c32000-02-14Per Hedbor  string fname = master()->program_name( o );
5964251999-11-19Per Hedbor  if( !fname ) fname = "Unknown Program"; return fname-(getcwd()+"/");
95b69e1999-09-05Per Hedbor }
b215032004-05-04Henrik Grubbström (Grubba) static int once_mode;
8cbc5f2002-09-03Martin Stjernholm // Note that 2.5 is a nonexisting version. It's only used for the // cache static optimization for tags such as <if> and <emit> inside // <cache> since that optimization can give tricky incompatibilities // with 2.4.
3be6fd2006-10-30Martin Stjernholm array(string) compat_levels = ({"2.1", "2.2", "2.4", "2.5", "3.3", "3.4", "4.0", "4.5", "4.6"});
b0a9ea2001-04-18Martin Stjernholm 
0f8b2f1999-03-27Henrik Grubbström (Grubba) #ifdef THREADS
6664122001-02-23Per Hedbor mapping(string:string) thread_names = ([]); string thread_name( object thread ) { string tn; if( thread_names[ tn=sprintf("%O",thread) ] ) return thread_names[tn]; return tn; } void name_thread( object thread, string name ) { catch(thread->set_name( name )); thread_names[ sprintf( "%O", thread ) ] = name; }
0f8b2f1999-03-27Henrik Grubbström (Grubba) // This mutex is used by Privs
855c391999-11-29Per Hedbor Thread.Mutex euid_egid_lock = Thread.Mutex();
0f8b2f1999-03-27Henrik Grubbström (Grubba) #endif /* THREADS */
c5e0961999-10-04Per Hedbor /*
8fb5172000-05-27Per Hedbor  * The privilege changer. Works like a mutex lock, but changes the UID/GID * while held. Blocks all threads. *
c5e0961999-10-04Per Hedbor  * Based on privs.pike,v 1.36. */
0f8b2f1999-03-27Henrik Grubbström (Grubba) int privs_level;
81f8af1999-12-20Martin Nilsson static class Privs
c5e0961999-10-04Per Hedbor {
0f8b2f1999-03-27Henrik Grubbström (Grubba) #if efun(seteuid) int saved_uid; int saved_gid; int new_uid; int new_gid;
7b798d2000-07-04Per Hedbor #define LOGP (variables && variables->audit && variables->audit->query())
0f8b2f1999-03-27Henrik Grubbström (Grubba)  #if constant(geteuid) && constant(getegid) && constant(seteuid) && constant(setegid) #define HAVE_EFFECTIVE_USER #endif static private string _getcwd() { if (catch{return(getcwd());}) { return("Unknown directory (no x-bit on current directory?)"); } } static private string dbt(array t) { if(!arrayp(t) || (sizeof(t)<2)) return ""; return (((t[0]||"Unknown program")-(_getcwd()+"/"))-"base_server/")+":"+t[1]+"\n"; } #ifdef THREADS
b84a161999-06-07Martin Stjernholm  static mixed mutex_key; // Only one thread may modify the euid/egid at a time.
d3a71c1999-04-20Martin Stjernholm  static object threads_disabled;
0f8b2f1999-03-27Henrik Grubbström (Grubba) #endif /* THREADS */ int p_level; void create(string reason, int|string|void uid, int|string|void gid) {
f198282001-09-27Henrik Grubbström (Grubba)  // No need for Privs if the uid has been changed permanently. if(getuid()) return;
0f8b2f1999-03-27Henrik Grubbström (Grubba) #ifdef PRIVS_DEBUG
3e6f6b2001-03-11Martin Nilsson  report_debug(sprintf("Privs(%O, %O, %O)\n" "privs_level: %O\n", reason, uid, gid, privs_level));
0f8b2f1999-03-27Henrik Grubbström (Grubba) #endif /* PRIVS_DEBUG */ #ifdef HAVE_EFFECTIVE_USER array u; #ifdef THREADS if (euid_egid_lock) { catch { mutex_key = euid_egid_lock->lock(); }; }
d3a71c1999-04-20Martin Stjernholm  threads_disabled = _disable_threads();
0f8b2f1999-03-27Henrik Grubbström (Grubba) #endif /* THREADS */ p_level = privs_level++; /* Needs to be here since root-priviliges may be needed to * use getpw{uid,nam}. */ saved_uid = geteuid(); saved_gid = getegid(); seteuid(0); /* A string of digits? */
c5e0961999-10-04Per Hedbor  if(stringp(uid) && (replace(uid,"0123456789"/"",({""})*10)==""))
0f8b2f1999-03-27Henrik Grubbström (Grubba)  uid = (int)uid;
c5e0961999-10-04Per Hedbor 
3a4b9a1999-12-27Martin Nilsson  if(stringp(gid) && (replace(gid, "0123456789"/"", ({"" })*10) == ""))
0f8b2f1999-03-27Henrik Grubbström (Grubba)  gid = (int)gid;
c5e0961999-10-04Per Hedbor  if(!stringp(uid))
0f8b2f1999-03-27Henrik Grubbström (Grubba)  u = getpwuid(uid);
81f8af1999-12-20Martin Nilsson  else
c5e0961999-10-04Per Hedbor  {
0f8b2f1999-03-27Henrik Grubbström (Grubba)  u = getpwnam(uid);
81f8af1999-12-20Martin Nilsson  if(u)
0f8b2f1999-03-27Henrik Grubbström (Grubba)  uid = u[2]; }
eae43a2001-08-13Per Hedbor 
81f8af1999-12-20Martin Nilsson  if(u && !gid)
c5e0961999-10-04Per Hedbor  gid = u[3];
81f8af1999-12-20Martin Nilsson  if(!u)
c5e0961999-10-04Per Hedbor  {
81f8af1999-12-20Martin Nilsson  if (uid && (uid != "root"))
c5e0961999-10-04Per Hedbor  {
81f8af1999-12-20Martin Nilsson  if (intp(uid) && (uid >= 60000))
c5e0961999-10-04Per Hedbor  {
b84a161999-06-07Martin Stjernholm  report_warning(sprintf("Privs: User %d is not in the password database.\n" "Assuming nobody.\n", uid));
0f8b2f1999-03-27Henrik Grubbström (Grubba)  // Nobody. gid = gid || uid; // Fake a gid also. u = ({ "fake-nobody", "x", uid, gid, "A real nobody", "/", "/sbin/sh" }); } else { error("Unknown user: "+uid+"\n"); } } else { u = ({ "root", "x", 0, gid, "The super-user", "/", "/sbin/sh" }); } } if(LOGP)
49cd282000-08-11Andreas Lange  report_notice(