diff options
| author | Wilmer van der Gaast <wilmer@gaast.net> | 2005-12-26 15:02:47 +0100 | 
|---|---|---|
| committer | Wilmer van der Gaast <wilmer@gaast.net> | 2005-12-26 15:02:47 +0100 | 
| commit | d25f6fcbe8e291dd858bf734fa85cde176dc8415 (patch) | |
| tree | 58fffb8b1dd8cc0a3cf3583c0daf7c10271af871 | |
| parent | ffea9b950b183dd54952b56703506508b0984d4b (diff) | |
Added OperPassword and RunMode = ForkDaemon settings. Oper stuff is
*INSECURE* because users can just do /mode +o to become operator.
| -rw-r--r-- | bitlbee.c | 40 | ||||
| -rw-r--r-- | bitlbee.conf | 9 | ||||
| -rw-r--r-- | bitlbee.h | 1 | ||||
| -rw-r--r-- | conf.c | 16 | ||||
| -rw-r--r-- | conf.h | 5 | ||||
| -rw-r--r-- | irc.c | 13 | ||||
| -rw-r--r-- | irc.h | 2 | ||||
| -rw-r--r-- | storage_text.c | 2 | ||||
| -rw-r--r-- | unix.c | 27 | 
9 files changed, 92 insertions, 23 deletions
| @@ -36,12 +36,30 @@ gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpoi  {  	size_t size = sizeof( struct sockaddr_in );  	struct sockaddr_in conn_info; -	int new_socket = accept( global.listen_socket, (struct sockaddr *) &conn_info,  -		                     &size ); +	int new_socket = accept( global.listen_socket, (struct sockaddr *) &conn_info, &size ); +	pid_t client_pid = 0; +	 +	if( global.conf->runmode == RUNMODE_FORKDAEMON ) +		client_pid = fork(); +	 +	if( client_pid == 0 ) +	{ +		log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket ); +		irc_new( new_socket ); +		 +		if( global.conf->runmode == RUNMODE_FORKDAEMON ) +		{ +			/* Close the listening socket, we're a client. */ +			close( global.listen_socket ); +			g_source_remove( global.listen_watch_source_id ); +		} +	} +	else +	{ +		/* We don't need this one, only the client does. */ +		close( new_socket ); +	} -	log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket ); -	irc_new( new_socket ); -  	return TRUE;  } @@ -65,24 +83,24 @@ int bitlbee_daemon_init()  	listen_addr.sin_family = AF_INET;  	listen_addr.sin_port = htons( global.conf->port );  	listen_addr.sin_addr.s_addr = inet_addr( global.conf->iface ); - +	  	i = bind( global.listen_socket, (struct sockaddr *) &listen_addr, sizeof( struct sockaddr ) );  	if( i == -1 )  	{  		log_error( "bind" );  		return( -1 );  	} - +	  	i = listen( global.listen_socket, 10 );  	if( i == -1 )  	{  		log_error( "listen" );  		return( -1 );  	} - +	  	ch = g_io_channel_unix_new( global.listen_socket ); -	g_io_add_watch( ch, G_IO_IN, bitlbee_io_new_client, NULL ); - +	global.listen_watch_source_id = g_io_add_watch( ch, G_IO_IN, bitlbee_io_new_client, NULL ); +	  #ifndef _WIN32  	if( !global.conf->nofork )  	{ @@ -164,6 +182,8 @@ gboolean bitlbee_io_current_client_read( GIOChannel *source, GIOCondition condit  		return FALSE;  	}  +	return TRUE; +	  	/* Very naughty, go read the RFCs! >:) */  	if( irc->readbuffer && ( strlen( irc->readbuffer ) > 1024 ) )  	{ diff --git a/bitlbee.conf b/bitlbee.conf index b0de328d..919cee9d 100644 --- a/bitlbee.conf +++ b/bitlbee.conf @@ -13,6 +13,9 @@  ##    stable enough to serve lots of users from one process. Because of this  ##    and other reasons, the use of daemon-mode is *STRONGLY* discouraged,  ##    don't even *think* of reporting bugs when you use this. +##  ForkDaemon -- Run as a stand-alone daemon, but keep all clients in separate +##    child processes. This should be pretty safe and reliable to use instead +##    of inetd mode.  ##  # RunMode = Inetd @@ -41,6 +44,12 @@  ##  # AuthPassword = ItllBeBitlBee   ## Heh.. Our slogan. ;-) +## OperPassword +## +## Password that unlocks access to special operator commands. +## +# OperPassword = ChangeMe! +  ## HostName  ##  ## Normally, BitlBee gets a hostname using getsockname(). If you have a nicer @@ -113,6 +113,7 @@ extern char *CONF_FILE;  typedef struct global_t {  	int listen_socket; +	gint listen_watch_source_id;  	help_t *help;  	conf_t *conf;  	GList *storage; /* The first backend in the list will be used for saving */ @@ -52,7 +52,8 @@ conf_t *conf_load( int argc, char *argv[] )  	conf->primary_storage = "text";  	conf->runmode = RUNMODE_INETD;  	conf->authmode = AUTHMODE_OPEN; -	conf->password = NULL; +	conf->auth_pass = NULL; +	conf->oper_pass = NULL;  	conf->configdir = g_strdup( CONFIG );  	conf->plugindir = g_strdup( PLUGINDIR );  	conf->motdfile = g_strdup( ETCDIR "/motd.txt" ); @@ -70,7 +71,7 @@ conf_t *conf_load( int argc, char *argv[] )  		fprintf( stderr, "Warning: Unable to read configuration file `%s'.\n", CONF_FILE );  	} -	while( ( opt = getopt( argc, argv, "i:p:nvIDc:d:h" ) ) >= 0 ) +	while( ( opt = getopt( argc, argv, "i:p:nvIDFc:d:h" ) ) >= 0 )  	{  		if( opt == 'i' )  		{ @@ -93,6 +94,8 @@ conf_t *conf_load( int argc, char *argv[] )  			conf->runmode=RUNMODE_INETD;  		else if( opt == 'D' )  			conf->runmode=RUNMODE_DAEMON; +		else if( opt == 'F' ) +			conf->runmode=RUNMODE_FORKDAEMON;  		else if( opt == 'c' )  		{  			if( strcmp( CONF_FILE, optarg ) != 0 ) @@ -117,6 +120,7 @@ conf_t *conf_load( int argc, char *argv[] )  			        "\n"  			        "  -I  Classic/InetD mode. (Default)\n"  			        "  -D  Daemon mode. (Still EXPERIMENTAL!)\n" +			        "  -F  Forking daemon. (one process per client)\n"  			        "  -i  Specify the interface (by IP address) to listen on.\n"  			        "      (Default: 0.0.0.0 (any interface))\n"  			        "  -p  Port number to listen on. (Default: 6667)\n" @@ -156,6 +160,8 @@ static int conf_loadini( conf_t *conf, char *file )  			{  				if( g_strcasecmp( ini->value, "daemon" ) == 0 )  					conf->runmode = RUNMODE_DAEMON; +				else if( g_strcasecmp( ini->value, "forkdaemon" ) == 0 ) +					conf->runmode = RUNMODE_FORKDAEMON;  				else  					conf->runmode = RUNMODE_INETD;  			} @@ -183,7 +189,11 @@ static int conf_loadini( conf_t *conf, char *file )  			}  			else if( g_strcasecmp( ini->key, "authpassword" ) == 0 )  			{ -				conf->password = g_strdup( ini->value ); +				conf->auth_pass = g_strdup( ini->value ); +			} +			else if( g_strcasecmp( ini->key, "operpassword" ) == 0 ) +			{ +				conf->oper_pass = g_strdup( ini->value );  			}  			else if( g_strcasecmp( ini->key, "hostname" ) == 0 )  			{ @@ -26,7 +26,7 @@  #ifndef __CONF_H  #define __CONF_H -typedef enum runmode { RUNMODE_DAEMON, RUNMODE_INETD } runmode_t; +typedef enum runmode { RUNMODE_DAEMON, RUNMODE_FORKDAEMON, RUNMODE_INETD } runmode_t;  typedef enum authmode { AUTHMODE_OPEN, AUTHMODE_CLOSED, AUTHMODE_REGISTERED } authmode_t;  typedef struct conf @@ -37,7 +37,8 @@ typedef struct conf  	int verbose;  	runmode_t runmode;  	authmode_t authmode; -	char *password; +	char *auth_pass; +	char *oper_pass;  	char *hostname;  	char *configdir;  	char *plugindir; @@ -263,7 +263,7 @@ void irc_free(irc_t * irc)  	}  	g_free(irc); -	if( global.conf->runmode == RUNMODE_INETD ) +	if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON )  		g_main_quit( global.loop );  } @@ -421,7 +421,7 @@ int irc_exec( irc_t *irc, char **cmd )  			{  				irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );  			} -			else if( strcmp( cmd[1], (global.conf)->password ) == 0 ) +			else if( strcmp( cmd[1], (global.conf)->auth_pass ) == 0 )  			{  				irc->status = USTATUS_AUTHORIZED;  			} @@ -500,6 +500,15 @@ int irc_exec( irc_t *irc, char **cmd )  	{  		irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost );  	} +	else if( g_strcasecmp( cmd[0], "OPER" ) == 0 ) +	{ +		if( !cmd[2] ) +			irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); +		else if( strcmp( cmd[2], global.conf->oper_pass ) == 0 ) +			irc_umode_set( irc, irc->nick, "+o" ); +		// else +			/* FIXME/TODO: Find out which reply to send now. */ +	}  	else if( g_strcasecmp( cmd[0], "MODE" ) == 0 )  	{  		if( !cmd[1] ) @@ -39,7 +39,7 @@  #define FLOOD_SEND_BYTES (1024*10)  #define FLOOD_SEND_MAXBUFFER (1024*20) -#define UMODES "ais" +#define UMODES "aiso"  #define CMODES "nt"  #define CMODE "t"  #define UMODE "s" diff --git a/storage_text.c b/storage_text.c index 1bf2dcf3..f807cb3e 100644 --- a/storage_text.c +++ b/storage_text.c @@ -70,7 +70,7 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i  	FILE *fp;  	user_t *ru = user_find( irc, ROOT_NICK ); -	if( irc->status == USTATUS_IDENTIFIED ) +	if( irc->status >= USTATUS_IDENTIFIED )  		return( 1 );  	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".accounts" ); @@ -31,6 +31,7 @@  #include <signal.h>  #include <unistd.h>  #include <sys/time.h> +#include <sys/wait.h>  global_t global;	/* Against global namespace pollution */ @@ -45,7 +46,7 @@ int main( int argc, char *argv[] )  	global.loop = g_main_new( FALSE ); -	log_init( ); +	log_init();  	nogaim_init(); @@ -69,11 +70,15 @@ int main( int argc, char *argv[] )  		i = bitlbee_daemon_init();  		log_message( LOGLVL_INFO, "Bitlbee %s starting in daemon mode.", BITLBEE_VERSION );  	} +	else if( global.conf->runmode == RUNMODE_FORKDAEMON ) +	{ +		i = bitlbee_daemon_init(); +		log_message( LOGLVL_INFO, "Bitlbee %s starting in forking daemon mode.", BITLBEE_VERSION ); +	}  	if( i != 0 )  		return( i ); -	global.storage = storage_init( global.conf->primary_storage,  -								   global.conf->migrate_storage ); +	global.storage = storage_init( global.conf->primary_storage, global.conf->migrate_storage );  	if ( global.storage == NULL) {  		log_message( LOGLVL_ERROR, "Unable to load storage backend '%s'", global.conf->primary_storage );  		return( 1 ); @@ -83,6 +88,7 @@ int main( int argc, char *argv[] )  	/* Catch some signals to tell the user what's happening before quitting */  	memset( &sig, 0, sizeof( sig ) );  	sig.sa_handler = sighandler; +	sigaction( SIGCHLD, &sig, &old );  	sigaction( SIGPIPE, &sig, &old );  	sig.sa_flags = SA_RESETHAND;  	sigaction( SIGINT,  &sig, &old ); @@ -106,7 +112,7 @@ int main( int argc, char *argv[] )  static void sighandler( int signal )  { -	/* FIXME: In fact, calling log_message() here can be dangerous. But well, let's take the risk for now. */ +	/* FIXME: Calling log_message() here is not a very good idea! */  	if( signal == SIGTERM )  	{ @@ -132,6 +138,19 @@ static void sighandler( int signal )  			raise( signal );  		}  	} +	else if( signal == SIGCHLD ) +	{ +		pid_t pid; +		int st; +		 +		while( ( pid = waitpid( 0, &st, WNOHANG ) ) > 0 ) +		{ +			if( WIFSIGNALED( st ) ) +				log_message( LOGLVL_INFO, "Client %d terminated normally. (status = %d)", pid, WEXITSTATUS( st ) ); +			else if( WIFEXITED( st ) ) +				log_message( LOGLVL_INFO, "Client %d killed by signal %d.", pid, WTERMSIG( st ) ); +		} +	}  	else if( signal != SIGPIPE )  	{  		log_message( LOGLVL_ERROR, "Fatal signal received: %d. That's probably a bug.", signal ); | 
