diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2007-12-02 23:18:25 +0000 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2007-12-02 23:18:25 +0000 |
commit | aaf92a9eb64327892e39fdbd7113d797d1d68cec (patch) | |
tree | b907c7e55f32b073453a327231a9e76ab1604145 | |
parent | 80e9db97776bfd6c6192135d65027abd8f50887c (diff) |
Imported setuid() patch from Simo Leone <simo@archlinux...> with some
modifications. Also adding some missing g_free()s to conf.c.
-rw-r--r-- | bitlbee.conf | 7 | ||||
-rw-r--r-- | conf.c | 19 | ||||
-rw-r--r-- | conf.h | 1 | ||||
-rw-r--r-- | unix.c | 21 |
4 files changed, 43 insertions, 5 deletions
diff --git a/bitlbee.conf b/bitlbee.conf index e5e0f7de..d9f878c8 100644 --- a/bitlbee.conf +++ b/bitlbee.conf @@ -19,6 +19,13 @@ ## # RunMode = Inetd +## User: +## +## If BitlBee is started by root as a daemon, it can drop root privileges, +## and change to the specified user. +## +# User = bitlbee + ## DaemonPort/DaemonInterface: ## ## For daemon mode, you can specify on what interface and port the daemon @@ -62,6 +62,7 @@ conf_t *conf_load( int argc, char *argv[] ) conf->motdfile = g_strdup( ETCDIR "/motd.txt" ); conf->ping_interval = 180; conf->ping_timeout = 300; + conf->user = NULL; proxytype = 0; i = conf_loadini( conf, CONF_FILE ); @@ -75,7 +76,7 @@ conf_t *conf_load( int argc, char *argv[] ) fprintf( stderr, "Warning: Unable to read configuration file `%s'.\n", CONF_FILE ); } - while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:" ) ) >= 0 ) + while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:u:" ) ) >= 0 ) /* ^^^^ Just to make sure we skip this step from the REHASH handler. */ { if( opt == 'i' ) @@ -131,6 +132,7 @@ conf_t *conf_load( int argc, char *argv[] ) " -I Classic/InetD mode. (Default)\n" " -D Daemon mode. (Still EXPERIMENTAL!)\n" " -F Forking daemon. (one process per client)\n" + " -u Run daemon as specified user.\n" " -P Specify PID-file (not for inetd mode)\n" " -i Specify the interface (by IP address) to listen on.\n" " (Default: 0.0.0.0 (any interface))\n" @@ -150,6 +152,11 @@ conf_t *conf_load( int argc, char *argv[] ) mode anyway!) */ ipc_master_set_statefile( optarg ); } + else if( opt == 'u' ) + { + g_free( conf->user ); + conf->user = g_strdup( optarg ); + } } if( conf->configdir[strlen(conf->configdir)-1] != '/' ) @@ -191,10 +198,12 @@ static int conf_loadini( conf_t *conf, char *file ) } else if( g_strcasecmp( ini->key, "daemoninterface" ) == 0 ) { + g_free( conf->iface ); conf->iface = g_strdup( ini->value ); } else if( g_strcasecmp( ini->key, "daemonport" ) == 0 ) { + g_free( conf->port ); conf->port = g_strdup( ini->value ); } else if( g_strcasecmp( ini->key, "authmode" ) == 0 ) @@ -208,14 +217,17 @@ static int conf_loadini( conf_t *conf, char *file ) } else if( g_strcasecmp( ini->key, "authpassword" ) == 0 ) { + g_free( conf->auth_pass ); conf->auth_pass = g_strdup( ini->value ); } else if( g_strcasecmp( ini->key, "operpassword" ) == 0 ) { + g_free( conf->oper_pass ); conf->oper_pass = g_strdup( ini->value ); } else if( g_strcasecmp( ini->key, "hostname" ) == 0 ) { + g_free( conf->hostname ); conf->hostname = g_strdup( ini->value ); } else if( g_strcasecmp( ini->key, "configdir" ) == 0 ) @@ -280,6 +292,11 @@ static int conf_loadini( conf_t *conf, char *file ) g_free( url ); } + else if( g_strcasecmp( ini->key, "user" ) == 0 ) + { + g_free( conf->user ); + conf->user = g_strdup( ini->value ); + } else { fprintf( stderr, "Error: Unknown setting `%s` in configuration file.\n", ini->key ); @@ -48,6 +48,7 @@ typedef struct conf char **migrate_storage; int ping_interval; int ping_timeout; + char *user; } conf_t; G_GNUC_MALLOC conf_t *conf_load( int argc, char *argv[] ); @@ -33,6 +33,7 @@ #include <unistd.h> #include <sys/time.h> #include <sys/wait.h> +#include <pwd.h> global_t global; /* Against global namespace pollution */ @@ -44,8 +45,6 @@ int main( int argc, char *argv[], char **envp ) char *old_cwd = NULL; struct sigaction sig, old; - memset( &global, 0, sizeof( global_t ) ); - log_init(); CONF_FILE = g_strdup( CONF_FILE_DEF ); global.conf = conf_load( argc, argv ); @@ -86,12 +85,26 @@ int main( int argc, char *argv[], char **envp ) if( i != 0 ) return( i ); + if( ( global.conf->user && *global.conf->user ) && + ( global.conf->runmode == RUNMODE_DAEMON || + global.conf->runmode == RUNMODE_FORKDAEMON ) && + ( !getuid() || !geteuid() ) ) + { + struct passwd *pw = NULL; + pw = getpwnam( global.conf->user ); + if( pw ) + { + setgid( pw->pw_gid ); + setuid( pw->pw_uid ); + } + } + global.storage = storage_init( global.conf->primary_storage, global.conf->migrate_storage ); - if ( global.storage == NULL) { + if( global.storage == NULL ) + { log_message( LOGLVL_ERROR, "Unable to load storage backend '%s'", global.conf->primary_storage ); return( 1 ); } - /* Catch some signals to tell the user what's happening before quitting */ memset( &sig, 0, sizeof( sig ) ); |