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 ) );
rdoc/parser.rb?h=release/0.6.3&id=c8983b923e4dc7db9ba22156daaddd94d2b5ed4d'>plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138