diff options
| -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 ) ); | 
