New "chroot" feature (from Benjamin Pineau), introducing new configuration

variables "ChrootDir" and "MotdPhrase".
This commit is contained in:
Alexander Barton 2004-05-07 11:19:20 +00:00
parent 39fc76c4e4
commit 7281b8dd4d
13 changed files with 139 additions and 46 deletions

View File

@ -19,6 +19,7 @@ Contributors
~~~~~~~~~~~~
Goetz Hoffart, <goetz@hoffart.de> (goetz)
Ilja Osthoff, <i.osthoff@gmx.net> (ilja)
Benjamin Pineau, <ben@zouh.org>
Sean Reifschneider, <jafo-rpms@tummy.com>
@ -30,4 +31,4 @@ Andrew Tridgell & Martin Pool: strl{cpy|cat}()-functions
--
$Id: AUTHORS,v 1.8 2004/01/26 02:23:54 alex Exp $
$Id: AUTHORS,v 1.9 2004/05/07 11:19:20 alex Exp $

View File

@ -12,6 +12,11 @@
ngIRCd CVSHEAD
- Two new configuration options: "ChrootDir" and "MotdPhrase", thanks to
Benjamin Pineau <ben@zouh.org>. Now you can force the daemon to change
its root and working directory to something "safe". MotdPhrase is used
to define an "MOTD string" instead of a whole file, useful if the
"real" MOTD file would be outside the "jail".
- INVITE- and BAN-lists become synchronized between IRC+ servers when
establishing new connections, if the peer supports this as well.
- Reorganized autogen.sh and configure scripts.
@ -516,4 +521,4 @@ ngIRCd 0.0.1, 31.12.2001
--
$Id: ChangeLog,v 1.233 2004/04/25 15:51:15 alex Exp $
$Id: ChangeLog,v 1.234 2004/05/07 11:19:20 alex Exp $

View File

@ -75,6 +75,11 @@ In addition, you can pass some command line options to "configure" to enable
and/or disable some features of ngIRCd. All these options are shown using
"./configure --help", too.
Compiling a static binary will avoid you the hassle of feeding a chroot dir
(if you want use the chroot feature). Just do something like:
CFLAGS=-static ./configure [--your-options ...]
Then you can use a void directory as ChrootDir (like OpenSSH's /var/empty).
3): "make"
@ -158,4 +163,4 @@ number. In both cases the server exits after the output.
--
$Id: INSTALL,v 1.18 2004/02/22 22:12:44 alex Exp $
$Id: INSTALL,v 1.19 2004/05/07 11:19:20 alex Exp $

7
NEWS
View File

@ -12,6 +12,11 @@
ngIRCd CVSHEAD
- Two new configuration options: "ChrootDir" and "MotdPhrase", thanks to
Benjamin Pineau <ben@zouh.org>. Now you can force the daemon to change
its root and working directory to something "safe". MotdPhrase is used
to define an "MOTD string" instead of a whole file, useful if the
"real" MOTD file would be outside the "jail".
- INVITE- and BAN-lists become synchronized between IRC+ servers when
establishing new connections, if the peer supports this as well.
- The type of service (TOS) of all sockets is set to "interactive" now.
@ -184,4 +189,4 @@ ngIRCd 0.0.1, 31.12.2001
--
$Id: NEWS,v 1.64 2004/04/25 15:51:15 alex Exp $
$Id: NEWS,v 1.65 2004/05/07 11:19:20 alex Exp $

5
README
View File

@ -45,7 +45,8 @@ III. Features (or: why use ngIRCd?)
- ngIRCd will be developed on in the future.
- supported platforms (tested versions): AIX (3.2.5), A/UX (3.0.1), FreeBSD
(4.5), HP-UX (10.20), IRIX (6.5), Linux (2.x), Mac OS X (10.x), NetBSD
(1.5.2/i386, 1.5.3/m68k), Solaris (2.5.1, 2.6), and Windows with Cygwin.
(1.5.2/i386, 1.5.3/m68k), Solaris (2.5.1, 2.6), Windows with Cygwin, and
OpenBSD (3.4/i386).
IV. Documentation
@ -83,4 +84,4 @@ mail to: <alex@barton.de> or <alex@arthur.ath.cx>
--
$Id: README,v 1.18 2004/01/26 02:23:54 alex Exp $
$Id: README,v 1.19 2004/05/07 11:19:20 alex Exp $

View File

@ -1,4 +1,4 @@
# $Id: sample-ngircd.conf,v 1.25 2003/12/19 14:32:59 alex Exp $
# $Id: sample-ngircd.conf,v 1.26 2004/05/07 11:19:20 alex Exp $
#
# This is a sample configuration file for the ngIRCd, which must be adepted
@ -45,6 +45,10 @@
# be shown to all users connecting to the server:
;MotdFile = /usr/local/etc/ngircd.motd
# A simple Phrase (<256 chars) if you don't want to use a motd file.
# If it is set no MotdFile will be read at all.
;MotdPhrase = "Hello world!"
# User ID under which the server should run; you can use the name
# of the user or the numerical ID. ATTENTION: For this to work the
# server must have been started with root privileges! In addition,
@ -57,6 +61,13 @@
# server must have been started with root privileges!
;ServerGID = 65534
# A directory to chroot in when everything is initialized. It
# doesn't need to be populated if ngIRCd is compiled as a static
# binary. By default ngIRCd won't use the chroot() feature.
# ATTENTION: For this to work the server must have been started
# with root privileges!
;ChrootDir = /var/empty
# After <PingTimeout> seconds of inactivity the server will send a
# PING to the peer to test whether it is alive or not.
;PingTimeout = 120

View File

@ -1,5 +1,5 @@
.\"
.\" $Id: ngircd.conf.5,v 1.12 2003/11/05 21:41:02 alex Exp $
.\" $Id: ngircd.conf.5,v 1.13 2004/05/07 11:19:20 alex Exp $
.\"
.TH ngircd.conf 5 "Mai 2003" ngircd "ngIRCd Manual"
.SH NAME
@ -75,6 +75,10 @@ the server listens on all configured ip addresses and interfaces.
Text file with the "message of the day" (MOTD). This message will be shown
to all users connecting to the server.
.TP
\fBMotdPhrase\fR
A simple Phrase (<256 chars) if you don't want to use a motd file.
If it is set no MotdFile will be read at all.
.TP
\fBServerUID\fR
User ID under which the server should run; you can use the name of the user
or the numerical ID.
@ -98,6 +102,18 @@ For this to work the server must have
been started with root privileges!
.RE
.TP
\fBChrootDir\fR
A directory to chroot in when everything is initialized. It doesn't need
to be populated if ngIRCd is compiled as a static binary. By default ngIRCd
won't use the chroot() feature.
.PP
.RS
.B Attention:
.br
For this to work the server must have
been started with root privileges!
.RE
.TP
\fBPingTimeout\fR
After <PingTimeout> seconds of inactivity the server will send a PING to
the peer to test whether it is alive or not. Default: 120.

View File

@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: conf.c,v 1.63 2004/01/17 03:17:00 alex Exp $";
static char UNUSED id[] = "$Id: conf.c,v 1.64 2004/05/07 11:19:21 alex Exp $";
#include "imp.h"
#include <assert.h>
@ -114,6 +114,8 @@ Conf_Test( VOID )
printf( " AdminInfo2 = %s\n", Conf_ServerAdmin2 );
printf( " AdminEMail = %s\n", Conf_ServerAdminMail );
printf( " MotdFile = %s\n", Conf_MotdFile );
printf( " MotdPhrase = %s\n", Conf_MotdPhrase );
printf( " ChrootDir= %s\n", Conf_Chroot );
printf( " Ports = " );
for( i = 0; i < Conf_ListenPorts_Count; i++ )
{
@ -343,6 +345,10 @@ Set_Defaults( BOOLEAN InitServers )
strlcpy( Conf_MotdFile, SYSCONFDIR, sizeof( Conf_MotdFile ));
strlcat( Conf_MotdFile, MOTD_FILE, sizeof( Conf_MotdFile ));
strlcpy( Conf_MotdPhrase, MOTD_PHRASE, sizeof( Conf_MotdPhrase ));
strlcpy( Conf_Chroot, CHROOT_DIR, sizeof( Conf_Chroot ));
Conf_ListenPorts_Count = 0;
strcpy( Conf_ListenAddress, "" );
@ -613,6 +619,18 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
if( strlcpy( Conf_MotdFile, Arg, sizeof( Conf_MotdFile )) >= sizeof( Conf_MotdFile )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MotdFile\" too long!", NGIRCd_ConfFile, Line );
return;
}
if( strcasecmp( Var, "MotdPhrase" ) == 0 )
{
/* "Message of the day" phrase (instead of file) */
if( strlcpy( Conf_MotdPhrase, Arg, sizeof( Conf_MotdPhrase )) >= sizeof( Conf_MotdPhrase )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MotdPhrase\" too long!", NGIRCd_ConfFile, Line );
return;
}
if( strcasecmp( Var, "ChrootDir" ) == 0 )
{
/* directory for chroot() */
if( strlcpy( Conf_Chroot, Arg, sizeof( Conf_Chroot )) >= sizeof( Conf_Chroot )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"ChrootDir\" too long!", NGIRCd_ConfFile, Line );
return;
}
if( strcasecmp( Var, "ServerUID" ) == 0 )
{
/* UID the daemon should switch to */

View File

@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: conf.h,v 1.28 2003/11/05 21:41:02 alex Exp $
* $Id: conf.h,v 1.29 2004/05/07 11:19:21 alex Exp $
*
* Configuration management (header)
*/
@ -72,6 +72,9 @@ GLOBAL CHAR Conf_ServerAdminMail[CLIENT_INFO_LEN];
/* File with MOTD text */
GLOBAL CHAR Conf_MotdFile[FNAME_LEN];
/* Phrase with MOTD text */
GLOBAL CHAR Conf_MotdPhrase[LINE_LEN];
/* Ports the server should listen on */
GLOBAL UINT Conf_ListenPorts[MAX_LISTEN_PORTS];
GLOBAL INT Conf_ListenPorts_Count;
@ -83,6 +86,9 @@ GLOBAL CHAR Conf_ListenAddress[16];
GLOBAL UINT Conf_UID;
GLOBAL UINT Conf_GID;
/* A directory to chroot() in */
GLOBAL CHAR Conf_Chroot[FNAME_LEN];
/* Timeouts for PING and PONG */
GLOBAL INT Conf_PingTimeout;
GLOBAL INT Conf_PongTimeout;

View File

@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: defines.h,v 1.45 2004/04/25 15:46:50 alex Exp $
* $Id: defines.h,v 1.46 2004/05/07 11:19:21 alex Exp $
*
* Global defines of ngIRCd.
*/
@ -83,6 +83,8 @@
#define CONFIG_FILE "/ngircd.conf"
#define MOTD_FILE "/ngircd.motd"
#define MOTD_PHRASE ""
#define CHROOT_DIR ""
#define ERROR_DIR "/tmp"

View File

@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: irc-info.c,v 1.21 2004/01/17 03:17:49 alex Exp $";
static char UNUSED id[] = "$Id: irc-info.c,v 1.22 2004/05/07 11:19:21 alex Exp $";
#include "imp.h"
#include <assert.h>
@ -773,6 +773,13 @@ IRC_Show_MOTD( CLIENT *Client )
assert( Client != NULL );
if( Conf_MotdPhrase[0] )
{
if( ! IRC_WriteStrClient( Client, RPL_MOTDSTART_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return DISCONNECTED;
if( ! IRC_WriteStrClient( Client, RPL_MOTD_MSG, Client_ID( Client ), Conf_MotdPhrase )) return DISCONNECTED;
return IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ));
}
fd = fopen( Conf_MotdFile, "r" );
if( ! fd )
{
@ -780,7 +787,7 @@ IRC_Show_MOTD( CLIENT *Client )
return IRC_WriteStrClient( Client, ERR_NOMOTD_MSG, Client_ID( Client ) );
}
IRC_WriteStrClient( Client, RPL_MOTDSTART_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )));
if( ! IRC_WriteStrClient( Client, RPL_MOTDSTART_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return DISCONNECTED;
while( TRUE )
{
if( ! fgets( line, 126, fd )) break;

View File

@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: log.c,v 1.44 2003/12/26 15:55:07 alex Exp $";
static char UNUSED id[] = "$Id: log.c,v 1.45 2004/05/07 11:19:21 alex Exp $";
#include "imp.h"
#include <assert.h>
@ -85,6 +85,8 @@ Log_Init( VOID )
}
#endif
if( Init_Txt[0] ) Log( LOG_INFO, "Activating: %s.", Init_Txt );
Error_File[0] = '\0';
} /* Log_Init */
@ -122,8 +124,11 @@ Log_Exit( VOID )
if( NGIRCd_SignalRestart ) Log( LOG_NOTICE, "%s done (restarting).", PACKAGE_NAME );
else Log( LOG_NOTICE, "%s done.", PACKAGE_NAME );
/* Error-File (stderr) loeschen */
if( unlink( Error_File ) != 0 ) Log( LOG_ERR, "Can't delete \"%s\": %s", Error_File, strerror( errno ));
if( Error_File[0] )
{
/* Error-File (stderr) loeschen */
if( unlink( Error_File ) != 0 ) Log( LOG_ERR, "Can't delete \"%s\": %s", Error_File, strerror( errno ));
}
#ifdef SYSLOG
/* syslog abmelden */

View File

@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: ngircd.c,v 1.83 2004/01/19 21:54:59 alex Exp $";
static char UNUSED id[] = "$Id: ngircd.c,v 1.84 2004/05/07 11:19:21 alex Exp $";
#include "imp.h"
#include <assert.h>
@ -228,6 +228,38 @@ main( int argc, const char *argv[] )
while( ! NGIRCd_SignalQuit )
{
/* Initialize global variables */
NGIRCd_Start = time( NULL );
(VOID)strftime( NGIRCd_StartStr, 64, "%a %b %d %Y at %H:%M:%S (%Z)", localtime( &NGIRCd_Start ));
NGIRCd_SignalRehash = FALSE;
NGIRCd_SignalRestart = FALSE;
NGIRCd_SignalQuit = FALSE;
/* Initialize modules, part I */
Log_Init( );
Conf_Init( );
if( Conf_Chroot[0] )
{
/* Chroot */
if( chdir( Conf_Chroot ) != 0 ) Log( LOG_ERR, "Can't chdir() in ChrootDir (%s): %s", Conf_Chroot, strerror( errno ));
if( chroot( Conf_Chroot ) != 0 ) Log( LOG_ERR, "Can't change root directory to \"%s\": %s", Conf_Chroot, strerror( errno ));
else Log( LOG_INFO, "Changed root and working directory to \"%s\".", Conf_Chroot );
}
if( Conf_GID != 0 )
{
/* Set new group ID */
if( setgid( Conf_GID ) != 0 ) Log( LOG_ERR, "Can't change group ID to %u: %s", Conf_GID, strerror( errno ));
}
if( Conf_UID != 0 )
{
/* Set new user ID */
if( setuid( Conf_UID ) != 0 ) Log( LOG_ERR, "Can't change user ID to %u: %s", Conf_UID, strerror( errno ));
}
/* In der Regel wird ein Sub-Prozess ge-fork()'t, der
* nicht mehr mit dem Terminal verbunden ist. Mit der
* Option "--nodaemon" kann dies (z.B. zum Debuggen)
@ -252,18 +284,10 @@ main( int argc, const char *argv[] )
(VOID)setsid( );
chdir( "/" );
}
/* Globale Variablen initialisieren */
NGIRCd_Start = time( NULL );
(VOID)strftime( NGIRCd_StartStr, 64, "%a %b %d %Y at %H:%M:%S (%Z)", localtime( &NGIRCd_Start ));
NGIRCd_SignalRehash = FALSE;
NGIRCd_SignalRestart = FALSE;
NGIRCd_SignalQuit = FALSE;
/* Module initialisieren */
Log_Init( );
/* Initialize modules, part II: these functions are eventually
* called with already dropped privileges ... */
Resolve_Init( );
Conf_Init( );
Lists_Init( );
Channel_Init( );
Client_Init( );
@ -272,28 +296,15 @@ main( int argc, const char *argv[] )
#endif
Conn_Init( );
/* Wenn als root ausgefuehrt und eine andere UID
* konfiguriert ist, jetzt zu dieser wechseln */
if( getuid( ) == 0 )
{
if( Conf_GID != 0 )
{
/* Neue Group-ID setzen */
if( setgid( Conf_GID ) != 0 ) Log( LOG_ERR, "Can't change Group-ID to %u: %s", Conf_GID, strerror( errno ));
}
if( Conf_UID != 0 )
{
/* Neue User-ID setzen */
if( setuid( Conf_UID ) != 0 ) Log( LOG_ERR, "Can't change User-ID to %u: %s", Conf_UID, strerror( errno ));
}
}
/* User, Gruppe und Prozess-ID des Daemon ausgeben */
/* Show user, group, and PID of the running daemon */
pwd = getpwuid( getuid( )); grp = getgrgid( getgid( ));
Log( LOG_INFO, "Running as user %s(%ld), group %s(%ld), with PID %ld.", pwd ? pwd->pw_name : "unknown", (LONG)getuid( ), grp ? grp->gr_name : "unknown", (LONG)getgid( ), (LONG)getpid( ));
/* stderr in "Error-File" umlenken */
Log_InitErrorfile( );
/* Redirect stderr handle to "error file" for debugging.
* But don't try to write in the chroot jail, since it's more
* secure to have a chroot dir not writable by the daemon.
*/
if( ! Conf_Chroot[0] ) Log_InitErrorfile( );
/* Signal-Handler initialisieren */
Initialize_Signal_Handler( );