aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bitlbee.conf7
-rw-r--r--conf.c19
-rw-r--r--conf.h1
-rw-r--r--unix.c21
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
diff --git a/conf.c b/conf.c
index 82487ddf..94c673cc 100644
--- a/conf.c
+++ b/conf.c
@@ -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 );
diff --git a/conf.h b/conf.h
index 5138ce11..d21ec577 100644
--- a/conf.h
+++ b/conf.h
@@ -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[] );
diff --git a/unix.c b/unix.c
index 0abf43ea..75ffcf95 100644
--- a/unix.c
+++ b/unix.c
@@ -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 ) );