2020-03-29 09:16:53 +00:00
/*
* Unreal Internet Relay Chat Daemon , src / conf . c
* ( C ) 1998 - 2000 Chris Behrens & Fred Jacobs ( comstud , moogle )
* ( C ) 2000 - 2002 Carsten V . Munk and the UnrealIRCd Team
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 1 , or ( at your option )
* any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "unrealircd.h"
/*
* Some typedefs . .
*/
typedef struct ConfigCommand ConfigCommand ;
struct ConfigCommand
{
char * name ;
int ( * conffunc ) ( ConfigFile * conf , ConfigEntry * ce ) ;
int ( * testfunc ) ( ConfigFile * conf , ConfigEntry * ce ) ;
} ;
/* Config commands */
static int _conf_admin ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_me ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_files ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_oper ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_operclass ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_class ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_drpass ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_ulines ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_include ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_tld ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_listen ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_allow ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_except ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_vhost ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_link ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_ban ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_set ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_deny ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_deny_channel ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_deny_version ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_require ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_allow_channel ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_loadmodule ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_alias ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_help ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _conf_offchans ( ConfigFile * conf , ConfigEntry * ce ) ;
2021-01-08 23:15:08 +00:00
static int _conf_sni ( ConfigFile * conf , ConfigEntry * ce ) ;
2022-11-20 04:12:40 +00:00
extern int _conf_security_group ( ConfigFile * conf , ConfigEntry * ce ) ;
2021-06-19 15:52:51 +00:00
static int _conf_secret ( ConfigFile * conf , ConfigEntry * ce ) ;
2020-03-29 09:16:53 +00:00
/*
* Validation commands
*/
static int _test_admin ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_me ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_files ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_oper ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_operclass ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_class ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_drpass ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_ulines ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_include ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_tld ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_listen ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_allow ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_except ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_vhost ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_link ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_ban ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_require ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_set ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_deny ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_allow_channel ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_loadmodule ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_blacklist_module ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_alias ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_help ( ConfigFile * conf , ConfigEntry * ce ) ;
static int _test_offchans ( ConfigFile * conf , ConfigEntry * ce ) ;
2021-01-08 23:15:08 +00:00
static int _test_sni ( ConfigFile * conf , ConfigEntry * ce ) ;
2022-11-20 04:12:40 +00:00
extern int _test_security_group ( ConfigFile * conf , ConfigEntry * ce ) ;
2021-06-19 15:52:51 +00:00
static int _test_secret ( ConfigFile * conf , ConfigEntry * ce ) ;
2020-03-29 09:16:53 +00:00
/* This MUST be alphabetized */
static ConfigCommand _ConfigCommands [ ] = {
{ " admin " , _conf_admin , _test_admin } ,
{ " alias " , _conf_alias , _test_alias } ,
{ " allow " , _conf_allow , _test_allow } ,
{ " ban " , _conf_ban , _test_ban } ,
{ " blacklist-module " , NULL , NULL } ,
{ " class " , _conf_class , _test_class } ,
{ " deny " , _conf_deny , _test_deny } ,
{ " drpass " , _conf_drpass , _test_drpass } ,
{ " except " , _conf_except , _test_except } ,
{ " files " , _conf_files , _test_files } ,
{ " help " , _conf_help , _test_help } ,
{ " include " , NULL , _test_include } ,
{ " link " , _conf_link , _test_link } ,
{ " listen " , _conf_listen , _test_listen } ,
{ " loadmodule " , NULL , _test_loadmodule } ,
2022-01-15 05:16:34 +00:00
{ " log " , config_run_log , config_test_log } ,
2020-03-29 09:16:53 +00:00
{ " me " , _conf_me , _test_me } ,
{ " official-channels " , _conf_offchans , _test_offchans } ,
{ " oper " , _conf_oper , _test_oper } ,
{ " operclass " , _conf_operclass , _test_operclass } ,
{ " require " , _conf_require , _test_require } ,
2021-06-19 15:52:51 +00:00
{ " secret " , _conf_secret , _test_secret } ,
2021-01-08 23:15:08 +00:00
{ " security-group " , _conf_security_group , _test_security_group } ,
2020-03-29 09:16:53 +00:00
{ " set " , _conf_set , _test_set } ,
{ " sni " , _conf_sni , _test_sni } ,
{ " tld " , _conf_tld , _test_tld } ,
{ " ulines " , _conf_ulines , _test_ulines } ,
{ " vhost " , _conf_vhost , _test_vhost } ,
} ;
/* This MUST be alphabetized */
static NameValue _ListenerFlags [ ] = {
{ LISTENER_CLIENTSONLY , " clientsonly " } ,
{ LISTENER_DEFER_ACCEPT , " defer-accept " } ,
{ LISTENER_SERVERSONLY , " serversonly " } ,
{ LISTENER_TLS , " ssl " } ,
{ LISTENER_NORMAL , " standard " } ,
{ LISTENER_TLS , " tls " } ,
} ;
/* This MUST be alphabetized */
static NameValue _LinkFlags [ ] = {
{ CONNECT_AUTO , " autoconnect " } ,
{ CONNECT_INSECURE , " insecure " } ,
{ CONNECT_QUARANTINE , " quarantine " } ,
{ CONNECT_TLS , " ssl " } ,
{ CONNECT_TLS , " tls " } ,
} ;
/* This MUST be alphabetized */
static NameValue _TLSFlags [ ] = {
{ TLSFLAG_FAILIFNOCERT , " fail-if-no-clientcert " } ,
{ TLSFLAG_DISABLECLIENTCERT , " no-client-certificate " } ,
{ TLSFLAG_NOSTARTTLS , " no-starttls " } ,
} ;
struct {
unsigned conf_me : 1 ;
unsigned conf_admin : 1 ;
unsigned conf_listen : 1 ;
} requiredstuff ;
struct {
int min , max ;
} nicklengths ;
struct SetCheck settings ;
/*
* Utilities
*/
2022-01-15 05:16:34 +00:00
void port_range ( const char * string , int * start , int * end ) ;
long config_checkval ( const char * value , unsigned short flags ) ;
2020-03-29 09:16:53 +00:00
/*
* Parser
*/
2022-01-15 05:16:34 +00:00
ConfigFile * config_load ( const char * filename , const char * displayname ) ;
2020-03-29 09:16:53 +00:00
void config_free ( ConfigFile * cfptr ) ;
2022-01-15 05:16:34 +00:00
ConfigFile * config_parse_with_offset ( const char * filename , char * confdata , unsigned int line_offset ) ;
ConfigFile * config_parse ( const char * filename , char * confdata ) ;
ConfigEntry * config_find_entry ( ConfigEntry * ce , const char * name ) ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
extern void add_entropy_configfile ( struct stat * st , const char * buf ) ;
2020-03-29 09:16:53 +00:00
extern void unload_all_unused_umodes ( void ) ;
extern void unload_all_unused_extcmodes ( void ) ;
2022-11-20 04:12:40 +00:00
extern void unload_all_unused_extbans ( void ) ;
2020-03-29 09:16:53 +00:00
extern void unload_all_unused_caps ( void ) ;
extern void unload_all_unused_history_backends ( void ) ;
2023-05-05 22:12:01 +00:00
extern void unload_all_unused_rpc_handlers ( void ) ;
2020-03-29 09:16:53 +00:00
int reloadable_perm_module_unloaded ( void ) ;
int tls_tests ( void ) ;
/* Conf sub-sub-functions */
void test_tlsblock ( ConfigFile * conf , ConfigEntry * cep , int * totalerrors ) ;
void conf_tlsblock ( ConfigFile * conf , ConfigEntry * cep , TLSOptions * tlsoptions ) ;
void free_tls_options ( TLSOptions * tlsoptions ) ;
/*
* Config parser ( IRCd )
*/
2022-01-15 05:16:34 +00:00
int config_read_file ( const char * filename , const char * display_name ) ;
2022-04-03 15:09:29 +00:00
void config_rehash ( void ) ;
int config_run_blocks ( void ) ;
2022-01-15 05:16:34 +00:00
int config_test_blocks ( ) ;
2020-03-29 09:16:53 +00:00
/*
* Configuration linked lists
*/
ConfigItem_me * conf_me = NULL ;
ConfigItem_files * conf_files = NULL ;
ConfigItem_class * conf_class = NULL ;
ConfigItem_class * default_class = NULL ;
ConfigItem_admin * conf_admin = NULL ;
ConfigItem_admin * conf_admin_tail = NULL ;
ConfigItem_drpass * conf_drpass = NULL ;
ConfigItem_ulines * conf_ulines = NULL ;
ConfigItem_tld * conf_tld = NULL ;
ConfigItem_oper * conf_oper = NULL ;
ConfigItem_operclass * conf_operclass = NULL ;
ConfigItem_listen * conf_listen = NULL ;
ConfigItem_sni * conf_sni = NULL ;
ConfigItem_allow * conf_allow = NULL ;
ConfigItem_vhost * conf_vhost = NULL ;
ConfigItem_link * conf_link = NULL ;
ConfigItem_ban * conf_ban = NULL ;
ConfigItem_deny_channel * conf_deny_channel = NULL ;
ConfigItem_allow_channel * conf_allow_channel = NULL ;
ConfigItem_deny_version * conf_deny_version = NULL ;
ConfigItem_alias * conf_alias = NULL ;
2022-01-15 05:16:34 +00:00
ConfigResource * config_resources = NULL ;
2020-03-29 09:16:53 +00:00
ConfigItem_blacklist_module * conf_blacklist_module = NULL ;
ConfigItem_help * conf_help = NULL ;
ConfigItem_offchans * conf_offchans = NULL ;
2021-06-19 15:52:51 +00:00
Secret * secrets = NULL ;
2020-03-29 09:16:53 +00:00
MODVAR Configuration iConf ;
MODVAR Configuration tempiConf ;
MODVAR ConfigFile * conf = NULL ;
extern NameValueList * config_defines ;
MODVAR int ipv6_disabled = 0 ;
MODVAR Client * remote_rehash_client = NULL ;
2023-05-05 22:12:01 +00:00
MODVAR json_t * json_rehash_log = NULL ;
2020-03-29 09:16:53 +00:00
MODVAR int config_error_flag = 0 ;
int config_verbose = 0 ;
int need_operclass_permissions_upgrade = 0 ;
2022-01-15 05:16:34 +00:00
int invalid_snomasks_encountered = 0 ;
2020-03-29 09:16:53 +00:00
int have_tls_listeners = 0 ;
char * port_6667_ip = NULL ;
2022-01-15 05:16:34 +00:00
int add_config_resource ( const char * resource , int type , ConfigEntry * ce ) ;
void resource_download_complete ( const char * url , const char * file , const char * errorbuf , int cached , void * rs_key ) ;
void free_all_config_resources ( void ) ;
int rehash_internal ( Client * client ) ;
int is_blacklisted_module ( const char * name ) ;
2020-03-29 09:16:53 +00:00
/** Return the printable string of a 'cep' location, such as set::something::xyz */
2022-01-15 05:16:34 +00:00
const char * config_var ( ConfigEntry * cep )
2020-03-29 09:16:53 +00:00
{
static char buf [ 256 ] ;
ConfigEntry * e ;
char * elem [ 16 ] ;
int numel = 0 , i ;
if ( ! cep )
return " " ;
buf [ 0 ] = ' \0 ' ;
/* First, walk back to the top */
2022-01-15 05:16:34 +00:00
for ( e = cep ; e ; e = e - > parent )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
elem [ numel + + ] = e - > name ;
2020-03-29 09:16:53 +00:00
if ( numel = = 15 )
break ;
}
/* Now construct the xxx::yyy::zzz string */
for ( i = numel - 1 ; i > = 0 ; i - - )
{
strlcat ( buf , elem [ i ] , sizeof ( buf ) ) ;
if ( i > 0 )
strlcat ( buf , " :: " , sizeof ( buf ) ) ;
}
return buf ;
}
2022-01-15 05:16:34 +00:00
void port_range ( const char * string , int * start , int * end )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
char buf [ 256 ] ;
char * c ;
strlcpy ( buf , string , sizeof ( buf ) ) ;
c = strchr ( buf , ' - ' ) ;
2020-03-29 09:16:53 +00:00
if ( ! c )
{
int tmp = atoi ( string ) ;
* start = tmp ;
* end = tmp ;
return ;
}
* c = ' \0 ' ;
* start = atoi ( string ) ;
* end = atoi ( ( c + 1 ) ) ;
* c = ' - ' ;
}
/** Parses '5:60s' config values.
* orig : original string
* times : pointer to int , first value ( before the : )
* period : pointer to int , second value ( after the : ) in seconds
* RETURNS : 0 for parse error , 1 if ok .
* REMARK : times & period should be ints !
*/
2022-01-15 05:16:34 +00:00
int config_parse_flood ( const char * orig , int * times , int * period )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
char buf [ 256 ] ;
char * x ;
strlcpy ( buf , orig , sizeof ( buf ) ) ;
2020-03-29 09:16:53 +00:00
* times = * period = 0 ;
2022-01-15 05:16:34 +00:00
x = strchr ( buf , ' : ' ) ;
2020-03-29 09:16:53 +00:00
/* 'blah', ':blah', '1:' */
2022-01-15 05:16:34 +00:00
if ( ! x | | ( x = = buf ) | | ( * ( x + 1 ) = = ' \0 ' ) )
2020-03-29 09:16:53 +00:00
return 0 ;
* x = ' \0 ' ;
2022-01-15 05:16:34 +00:00
* times = atoi ( buf ) ;
2020-03-29 09:16:53 +00:00
* period = config_checkval ( x + 1 , CFG_TIME ) ;
* x = ' : ' ; /* restore */
return 1 ;
}
2021-06-19 15:52:51 +00:00
/** Find an anti-flood settings block by name.
* @ param name The name of the set : : anti - flood block
* @ returns The FloodSettings block if found , or NULL if not found .
*/
FloodSettings * find_floodsettings_block_ex ( Configuration * conf , const char * name )
{
FloodSettings * f ;
for ( f = conf - > floodsettings ; f ; f = f - > next )
if ( ! strcmp ( f - > name , name ) )
return f ;
return NULL ;
}
/** Find an anti-flood settings block by name.
* @ param name The name of the set : : anti - flood block
* @ returns The FloodSettings block if found , or NULL if not found .
*/
FloodSettings * find_floodsettings_block ( const char * name )
{
return find_floodsettings_block_ex ( & iConf , name ) ;
}
/** Check if 'name' is in the array 'list'.
* @ param name The name to check
* @ param list The char * list [ ] with the list of valid names .
* @ returns 1 if found , 0 if not
* @ note The array in list must end in a NULL element !
*/
int text_in_array ( const char * name , const char * list [ ] )
{
int i ;
for ( i = 0 ; list [ i ] ; i + + )
if ( ! strcmp ( name , list [ i ] ) )
return 1 ;
return 0 ; /* Not found */
}
int flood_option_is_old ( const char * name )
{
const char * opts [ ] =
{
" max-concurrent-conversations " ,
" unknown-flood-amount " ,
" unknown-flood-bantime " ,
" handshake-data-flood " ,
" away-count " ,
" away-period " ,
" away-flood " ,
" nick-flood " ,
" join-flood " ,
" invite-flood " ,
" knock-flood " ,
" connect-flood " ,
" target-flood " ,
NULL
} ;
return text_in_array ( name , opts ) ;
}
int flood_option_is_for_everyone ( const char * name )
{
const char * opts [ ] =
{
" connect-flood " ,
" handshake-data-flood " ,
" unknown-flood " ,
" target-flood " ,
NULL
} ;
return text_in_array ( name , opts ) ;
}
2022-01-15 05:16:34 +00:00
/** Free a FloodSettings struct */
void free_floodsettings ( FloodSettings * f )
{
safe_free ( f - > name ) ;
safe_free ( f ) ;
}
2021-06-19 15:52:51 +00:00
/** Parses a value like '5:60s' into a flood setting that we can store.
* @ param str The string to parse ( eg : ' 5 : 60 s ' )
* @ param settings The FloodSettings block to store the result in
* @ param opt The option ( eg : FLD_AWAY )
* @ returns 1 if OK , 0 for parse error .
*/
int config_parse_flood_generic ( const char * str , Configuration * conf , char * blockname , FloodOption opt )
{
char buf [ 64 ] , * p ;
FloodSettings * settings = find_floodsettings_block_ex ( conf , blockname ) ;
/* Create a new anti-flood block if it doesn't exist */
if ( ! settings )
{
settings = safe_alloc ( sizeof ( FloodSettings ) ) ;
safe_strdup ( settings - > name , blockname ) ;
AddListItem ( settings , conf - > floodsettings ) ;
}
if ( ! strcmp ( str , " unlimited " ) | | ! strcmp ( str , " max " ) )
{
settings - > limit [ opt ] = - 1 ;
settings - > period [ opt ] = 0 ;
return 1 ;
}
/* Work on a copy so we don't destroy 'str' */
strlcpy ( buf , str , sizeof ( buf ) ) ;
p = strchr ( buf , ' : ' ) ;
/* 'blah', ':blah', '1:' */
if ( ! p | | ( p = = buf ) | | ( * ( p + 1 ) = = ' \0 ' ) )
return 0 ;
* p + + = ' \0 ' ;
settings - > limit [ opt ] = atoi ( buf ) ;
settings - > period [ opt ] = config_checkval ( p , CFG_TIME ) ;
return 1 ;
}
2022-01-15 05:16:34 +00:00
long config_checkval ( const char * orig , unsigned short flags )
{
2022-04-03 15:09:29 +00:00
char * value ;
2020-03-29 09:16:53 +00:00
char * text ;
long ret = 0 ;
2022-04-03 15:09:29 +00:00
/* Handle empty strings early, since we use +1 later in the code etc. */
if ( BadPtr ( orig ) )
return 0 ;
value = raw_strdup ( orig ) ;
2020-03-29 09:16:53 +00:00
if ( flags = = CFG_YESNO ) {
for ( text = value ; * text ; text + + ) {
if ( ! isalnum ( * text ) )
continue ;
if ( tolower ( * text ) = = ' y ' | | ( tolower ( * text ) = = ' o ' & &
tolower ( * ( text + 1 ) ) = = ' n ' ) | | * text = = ' 1 ' | | tolower ( * text ) = = ' t ' ) {
ret = 1 ;
break ;
}
}
}
else if ( flags = = CFG_SIZE ) {
int mfactor = 1 ;
char * sz ;
for ( text = value ; * text ; text + + ) {
if ( isalpha ( * text ) ) {
if ( tolower ( * text ) = = ' k ' )
mfactor = 1024 ;
else if ( tolower ( * text ) = = ' m ' )
mfactor = 1048576 ;
else if ( tolower ( * text ) = = ' g ' )
mfactor = 1073741824 ;
else
mfactor = 1 ;
sz = text ;
while ( isalpha ( * text ) )
text + + ;
* sz = 0 ;
while ( sz - - > value & & * sz ) {
if ( isspace ( * sz ) )
* sz = 0 ;
if ( ! isdigit ( * sz ) )
break ;
}
ret + = atoi ( sz + 1 ) * mfactor ;
if ( * text = = ' \0 ' ) {
text + + ;
break ;
}
}
}
mfactor = 1 ;
sz = text ;
sz - - ; /* -1 because we are PAST the end of the string */
while ( sz - - > value ) {
if ( isspace ( * sz ) )
* sz = 0 ;
if ( ! isdigit ( * sz ) )
break ;
}
ret + = atoi ( sz + 1 ) * mfactor ;
}
else if ( flags = = CFG_TIME ) {
int mfactor = 1 ;
char * sz ;
for ( text = value ; * text ; text + + ) {
if ( isalpha ( * text ) ) {
if ( tolower ( * text ) = = ' w ' )
mfactor = 604800 ;
else if ( tolower ( * text ) = = ' d ' )
mfactor = 86400 ;
else if ( tolower ( * text ) = = ' h ' )
mfactor = 3600 ;
else if ( tolower ( * text ) = = ' m ' )
mfactor = 60 ;
else
mfactor = 1 ;
sz = text ;
while ( isalpha ( * text ) )
text + + ;
* sz = 0 ;
while ( sz - - > value & & * sz ) {
if ( isspace ( * sz ) )
* sz = 0 ;
if ( ! isdigit ( * sz ) )
break ;
}
ret + = atoi ( sz + 1 ) * mfactor ;
if ( * text = = ' \0 ' ) {
text + + ;
break ;
}
}
}
mfactor = 1 ;
sz = text ;
sz - - ; /* -1 because we are PAST the end of the string */
while ( sz - - > value ) {
if ( isspace ( * sz ) )
* sz = 0 ;
if ( ! isdigit ( * sz ) )
break ;
}
ret + = atoi ( sz + 1 ) * mfactor ;
}
safe_free ( value ) ;
return ret ;
}
/** Free configuration setting for set::modes-on-join */
void free_conf_channelmodes ( struct ChMode * store )
{
2022-11-20 04:12:40 +00:00
int i ;
for ( i = 0 ; i < 255 ; i + + )
safe_free ( store - > extparams [ i ] ) ;
2022-01-15 05:16:34 +00:00
memset ( store , 0 , sizeof ( struct ChMode ) ) ;
2020-03-29 09:16:53 +00:00
}
/* Set configuration, used for set::modes-on-join */
2022-01-15 05:16:34 +00:00
void conf_channelmodes ( const char * modes , struct ChMode * store )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
Cmode * cm ;
const char * m ;
2020-03-29 09:16:53 +00:00
char * params = strchr ( modes , ' ' ) ;
char * parambuf = NULL ;
2022-01-15 05:16:34 +00:00
const char * param = NULL ;
const char * param_in ;
2020-03-29 09:16:53 +00:00
char * save = NULL ;
2022-01-15 05:16:34 +00:00
int found ;
2020-03-29 09:16:53 +00:00
/* Free existing parameters first (no inheritance) */
free_conf_channelmodes ( store ) ;
if ( params )
{
params + + ;
safe_strdup ( parambuf , params ) ;
param = strtoken ( & save , parambuf , " " ) ;
}
2022-01-15 05:16:34 +00:00
for ( m = modes ; * m & & * m ! = ' ' ; m + + )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( * m = = ' + ' )
2020-03-29 09:16:53 +00:00
continue ;
2022-01-15 05:16:34 +00:00
if ( * m = = ' - ' )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
/* When a channel is created it has no modes, so just ignore if the
* user asks us to unset anything - - codemastr
*/
while ( * m & & * m ! = ' + ' )
m + + ;
2020-03-29 09:16:53 +00:00
continue ;
}
2022-01-15 05:16:34 +00:00
found = 0 ;
for ( cm = channelmodes ; cm ; cm = cm - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! ( cm - > letter ) )
continue ;
if ( * m = = cm - > letter )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
found = 1 ;
if ( cm - > paracount )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! param )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_warn ( " set::modes-on-join '%s'. Parameter missing for mode %c. " , modes , * m ) ;
break ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
param_in = param ; /* save it */
param = cm - > conv_param ( param , NULL , NULL ) ;
if ( ! param )
{
config_warn ( " set::modes-on-join '%s'. Parameter for mode %c is invalid (%s). " , modes , * m , param_in ) ;
break ; /* invalid parameter fmt, do not set mode. */
}
safe_strdup ( store - > extparams [ cm - > letter ] , param ) ;
/* Get next parameter */
param = strtoken ( & save , NULL , " " ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
store - > extmodes | = cm - > mode ;
break ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
if ( ! found )
config_warn ( " set::modes-on-join '%s'. Channel mode %c not found. " , modes , * m ) ;
2020-03-29 09:16:53 +00:00
}
safe_free ( parambuf ) ;
}
void chmode_str ( struct ChMode * modes , char * mbuf , char * pbuf , size_t mbuf_size , size_t pbuf_size )
{
2022-01-15 05:16:34 +00:00
Cmode * cm ;
2020-03-29 09:16:53 +00:00
if ( ! ( mbuf_size & & pbuf_size ) )
return ;
* pbuf = 0 ;
* mbuf + + = ' + ' ;
2022-01-15 05:16:34 +00:00
for ( cm = channelmodes ; cm ; cm = cm - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! ( cm - > letter ) )
2020-03-29 09:16:53 +00:00
continue ;
2022-01-15 05:16:34 +00:00
if ( modes - > extmodes & cm - > mode )
2020-03-29 09:16:53 +00:00
{
if ( mbuf_size )
{
2022-01-15 05:16:34 +00:00
* mbuf + + = cm - > letter ;
2020-03-29 09:16:53 +00:00
if ( ! - - mbuf_size )
{
* - - mbuf = 0 ;
break ;
}
}
2022-01-15 05:16:34 +00:00
if ( cm - > paracount )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
strlcat ( pbuf , modes - > extparams [ cm - > letter ] , pbuf_size ) ;
2020-03-29 09:16:53 +00:00
strlcat ( pbuf , " " , pbuf_size ) ;
}
}
}
* mbuf = 0 ;
}
2022-01-15 05:16:34 +00:00
const char * channellevel_to_string ( const char * s )
2020-03-29 09:16:53 +00:00
{
/* Requested at http://bugs.unrealircd.org/view.php?id=3852 */
if ( ! strcmp ( s , " none " ) )
2022-01-15 05:16:34 +00:00
return " " ;
2020-03-29 09:16:53 +00:00
if ( ! strcmp ( s , " voice " ) )
2022-01-15 05:16:34 +00:00
return " v " ;
2020-03-29 09:16:53 +00:00
if ( ! strcmp ( s , " halfop " ) )
2022-01-15 05:16:34 +00:00
return " h " ;
2020-03-29 09:16:53 +00:00
if ( ! strcmp ( s , " op " ) | | ! strcmp ( s , " chanop " ) )
2022-01-15 05:16:34 +00:00
return " o " ;
if ( ! strcmp ( s , " protect " ) | | ! strcmp ( s , " chanprot " ) | | ! strcmp ( s , " chanadmin " ) | | ! strcmp ( s , " admin " ) )
return " a " ;
2020-03-29 09:16:53 +00:00
if ( ! strcmp ( s , " owner " ) | | ! strcmp ( s , " chanowner " ) )
2022-01-15 05:16:34 +00:00
return " q " ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
return NULL ; /* unknown or unsupported */
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
Policy policy_strtoval ( const char * s )
2020-03-29 09:16:53 +00:00
{
if ( ! s )
return 0 ;
if ( ! strcmp ( s , " allow " ) )
return POLICY_ALLOW ;
if ( ! strcmp ( s , " warn " ) )
return POLICY_WARN ;
if ( ! strcmp ( s , " deny " ) )
return POLICY_DENY ;
return 0 ;
}
2022-01-15 05:16:34 +00:00
const char * policy_valtostr ( Policy policy )
2020-03-29 09:16:53 +00:00
{
if ( policy = = POLICY_ALLOW )
return " allow " ;
if ( policy = = POLICY_WARN )
return " warn " ;
if ( policy = = POLICY_DENY )
return " deny " ;
return " ??? " ;
}
char policy_valtochar ( Policy policy )
{
if ( policy = = POLICY_ALLOW )
return ' a ' ;
if ( policy = = POLICY_WARN )
return ' w ' ;
if ( policy = = POLICY_DENY )
return ' d ' ;
return ' ? ' ;
}
2022-01-15 05:16:34 +00:00
AllowedChannelChars allowed_channelchars_strtoval ( const char * str )
2020-03-29 09:16:53 +00:00
{
if ( ! strcmp ( str , " ascii " ) )
return ALLOWED_CHANNELCHARS_ASCII ;
else if ( ! strcmp ( str , " utf8 " ) )
return ALLOWED_CHANNELCHARS_UTF8 ;
else if ( ! strcmp ( str , " any " ) )
return ALLOWED_CHANNELCHARS_ANY ;
return 0 ;
}
2022-01-15 05:16:34 +00:00
const char * allowed_channelchars_valtostr ( AllowedChannelChars v )
2020-03-29 09:16:53 +00:00
{
switch ( v )
{
case ALLOWED_CHANNELCHARS_ASCII :
return " ascii " ;
case ALLOWED_CHANNELCHARS_UTF8 :
return " utf8 " ;
case ALLOWED_CHANNELCHARS_ANY :
return " any " ;
default :
/* Not possible */
abort ( ) ;
return " NOTREACHED " ; /* Windows.. */
}
}
/* Used for set::automatic-ban-target and set::manual-ban-target */
2022-01-15 05:16:34 +00:00
BanTarget ban_target_strtoval ( const char * str )
2020-03-29 09:16:53 +00:00
{
if ( ! strcmp ( str , " ip " ) )
return BAN_TARGET_IP ;
else if ( ! strcmp ( str , " userip " ) )
return BAN_TARGET_USERIP ;
else if ( ! strcmp ( str , " host " ) )
return BAN_TARGET_HOST ;
else if ( ! strcmp ( str , " userhost " ) )
return BAN_TARGET_USERHOST ;
else if ( ! strcmp ( str , " account " ) )
return BAN_TARGET_ACCOUNT ;
else if ( ! strcmp ( str , " certfp " ) )
return BAN_TARGET_CERTFP ;
return 0 ; /* invalid */
}
/* Used for set::automatic-ban-target and set::manual-ban-target */
2022-01-15 05:16:34 +00:00
const char * ban_target_valtostr ( BanTarget v )
2020-03-29 09:16:53 +00:00
{
switch ( v )
{
case BAN_TARGET_IP :
return " ip " ;
case BAN_TARGET_USERIP :
return " userip " ;
case BAN_TARGET_HOST :
return " host " ;
case BAN_TARGET_USERHOST :
return " userhost " ;
case BAN_TARGET_ACCOUNT :
return " account " ;
case BAN_TARGET_CERTFP :
return " certfp " ;
default :
return " ??? " ;
}
}
2022-01-15 05:16:34 +00:00
HideIdleTimePolicy hideidletime_strtoval ( const char * str )
2020-04-20 19:12:33 +00:00
{
if ( ! strcmp ( str , " never " ) )
return HIDE_IDLE_TIME_NEVER ;
else if ( ! strcmp ( str , " always " ) )
return HIDE_IDLE_TIME_ALWAYS ;
else if ( ! strcmp ( str , " usermode " ) )
return HIDE_IDLE_TIME_USERMODE ;
else if ( ! strcmp ( str , " oper-usermode " ) )
return HIDE_IDLE_TIME_OPER_USERMODE ;
return 0 ;
}
2022-01-15 05:16:34 +00:00
const char * hideidletime_valtostr ( HideIdleTimePolicy v )
2020-04-20 19:12:33 +00:00
{
switch ( v )
{
case HIDE_IDLE_TIME_NEVER :
return " never " ;
case HIDE_IDLE_TIME_ALWAYS :
return " always " ;
case HIDE_IDLE_TIME_USERMODE :
return " usermode " ;
case HIDE_IDLE_TIME_OPER_USERMODE :
return " oper-usermode " ;
default :
return " INVALID " ;
}
}
2022-01-15 05:16:34 +00:00
ConfigFile * config_load ( const char * filename , const char * displayname )
2020-03-29 09:16:53 +00:00
{
struct stat sb ;
int fd ;
int ret ;
char * buf = NULL ;
ConfigFile * cfptr ;
if ( ! displayname )
displayname = filename ;
# ifndef _WIN32
fd = open ( filename , O_RDONLY ) ;
# else
fd = open ( filename , O_RDONLY | O_BINARY ) ;
# endif
if ( fd = = - 1 )
{
config_error ( " Couldn't open \" %s \" : %s \n " , filename , strerror ( errno ) ) ;
return NULL ;
}
if ( fstat ( fd , & sb ) = = - 1 )
{
config_error ( " Couldn't fstat \" %s \" : %s \n " , filename , strerror ( errno ) ) ;
close ( fd ) ;
return NULL ;
}
if ( ! sb . st_size )
{
/* Workaround for empty files */
cfptr = config_parse ( filename , " " ) ;
close ( fd ) ;
return cfptr ;
}
buf = safe_alloc ( sb . st_size + 1 ) ;
if ( buf = = NULL )
{
config_error ( " Out of memory trying to load \" %s \" \n " , filename ) ;
close ( fd ) ;
return NULL ;
}
ret = read ( fd , buf , sb . st_size ) ;
if ( ret ! = sb . st_size )
{
config_error ( " Error reading \" %s \" : %s \n " , filename ,
ret = = - 1 ? strerror ( errno ) : strerror ( EFAULT ) ) ;
safe_free ( buf ) ;
close ( fd ) ;
return NULL ;
}
/* Just me or could this cause memory corrupted when ret <0 ? */
buf [ ret ] = ' \0 ' ;
close ( fd ) ;
add_entropy_configfile ( & sb , buf ) ;
cfptr = config_parse ( displayname , buf ) ;
safe_free ( buf ) ;
return cfptr ;
}
void config_free ( ConfigFile * cfptr )
{
ConfigFile * nptr ;
for ( ; cfptr ; cfptr = nptr )
{
2022-01-15 05:16:34 +00:00
nptr = cfptr - > next ;
if ( cfptr - > items )
config_entry_free_all ( cfptr - > items ) ;
safe_free ( cfptr - > filename ) ;
2020-03-29 09:16:53 +00:00
safe_free ( cfptr ) ;
}
}
/** Remove quotes so that 'hello \"all\" \\ lala' becomes 'hello "all" \ lala' */
void unreal_del_quotes ( char * i )
{
char * o ;
for ( o = i ; * i ; i + + )
{
if ( * i = = ' \\ ' )
{
if ( ( i [ 1 ] = = ' \\ ' ) | | ( i [ 1 ] = = ' " ' ) )
{
i + + ; /* skip original \ */
if ( * i = = ' \0 ' )
break ;
}
}
* o + + = * i ;
}
* o = ' \0 ' ;
}
/** Add quotes to a line, eg some"thing becomes some\"thing - extended version */
2022-01-15 05:16:34 +00:00
int unreal_add_quotes_r ( const char * i , char * o , size_t len )
2020-03-29 09:16:53 +00:00
{
if ( len = = 0 )
return 0 ;
len - - ; /* reserve room for nul byte */
if ( len = = 0 )
{
* o = ' \0 ' ;
return 0 ;
}
for ( ; * i ; i + + )
{
if ( ( * i = = ' " ' ) | | ( * i = = ' \\ ' ) ) /* only " and \ need to be quoted */
{
if ( len < 2 )
break ;
* o + + = ' \\ ' ;
* o + + = * i ;
len - = 2 ;
} else
{
if ( len = = 0 )
break ;
* o + + = * i ;
len - - ;
}
}
* o = ' \0 ' ;
return 1 ;
}
/** Add quotes to a line, eg some"thing becomes some\"thing */
2022-01-15 05:16:34 +00:00
const char * unreal_add_quotes ( const char * str )
2020-03-29 09:16:53 +00:00
{
static char qbuf [ 2048 ] ;
* qbuf = ' \0 ' ;
unreal_add_quotes_r ( str , qbuf , sizeof ( qbuf ) ) ;
return qbuf ;
}
2022-01-15 05:16:34 +00:00
ConfigFile * config_parse ( const char * filename , char * confdata )
{
2020-03-29 09:16:53 +00:00
return config_parse_with_offset ( filename , confdata , 0 ) ;
}
/* This is the internal parser, made by Chris Behrens & Fred Jacobs <2005.
* Enhanced ( or mutilated ) by Bram Matthys over the years ( 2015 - 2019 ) .
*/
2022-01-15 05:16:34 +00:00
ConfigFile * config_parse_with_offset ( const char * filename , char * confdata , unsigned int line_offset )
2020-03-29 09:16:53 +00:00
{
char * ptr ;
char * start ;
int linenumber = 1 + line_offset ;
int errors = 0 ;
int n ;
ConfigEntry * curce ;
ConfigEntry * * lastce ;
ConfigEntry * cursection ;
ConfigFile * curcf ;
int preprocessor_level = 0 ;
ConditionalConfig * cc , * cc_list = NULL ;
curcf = safe_alloc ( sizeof ( ConfigFile ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( curcf - > filename , filename ) ;
lastce = & ( curcf - > items ) ;
2020-03-29 09:16:53 +00:00
curce = NULL ;
cursection = NULL ;
/* Replace \r's with spaces .. ugly ugly -Stskeeps */
for ( ptr = confdata ; * ptr ; ptr + + )
if ( * ptr = = ' \r ' )
* ptr = ' ' ;
for ( ptr = confdata ; * ptr ; ptr + + )
{
switch ( * ptr )
{
case ' ; ' :
if ( ! curce )
{
config_status ( " %s:%i Ignoring extra semicolon \n " ,
filename , linenumber ) ;
break ;
}
* lastce = curce ;
2022-01-15 05:16:34 +00:00
lastce = & ( curce - > next ) ;
curce - > file_position_end = ( ptr - confdata ) ;
2020-03-29 09:16:53 +00:00
curce = NULL ;
break ;
case ' { ' :
if ( ! curce )
{
config_error ( " %s:%i: New section start detected on line %d but the section has no name. "
" Sections should start with a name like 'oper {' or 'set {'. " ,
filename , linenumber , linenumber ) ;
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
else if ( curce - > items )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: New section start but previous section did not end properly. "
" Check line %d and the line(s) before, you are likely missing a '};' there. \n " ,
filename , linenumber , linenumber ) ;
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
curce - > section_linenumber = linenumber ;
lastce = & ( curce - > items ) ;
2020-03-29 09:16:53 +00:00
cursection = curce ;
curce = NULL ;
break ;
case ' } ' :
if ( curce )
{
config_error ( " %s:%i: Missing semicolon (';') before close brace. Check line %d and the line(s) before. \n " ,
filename , linenumber , linenumber ) ;
config_entry_free_all ( curce ) ;
config_free ( curcf ) ;
errors + + ;
return NULL ;
}
else if ( ! cursection )
{
config_error ( " %s:%i: You have a close brace ('};') too many. "
" Check line %d AND the lines above it from the previous block. \n " ,
filename , linenumber , linenumber ) ;
errors + + ;
continue ;
}
curce = cursection ;
2022-01-15 05:16:34 +00:00
cursection - > file_position_end = ( ptr - confdata ) ;
cursection = cursection - > parent ;
2020-03-29 09:16:53 +00:00
if ( ! cursection )
2022-01-15 05:16:34 +00:00
lastce = & ( curcf - > items ) ;
2020-03-29 09:16:53 +00:00
else
2022-01-15 05:16:34 +00:00
lastce = & ( cursection - > items ) ;
for ( ; * lastce ; lastce = & ( ( * lastce ) - > next ) )
2020-03-29 09:16:53 +00:00
continue ;
if ( * ( ptr + 1 ) ! = ' ; ' )
{
/* Simulate closing ; so you can get away with } instead of ugly }; */
* lastce = curce ;
2022-01-15 05:16:34 +00:00
lastce = & ( curce - > next ) ;
curce - > file_position_end = ( ptr - confdata ) ;
2020-03-29 09:16:53 +00:00
curce = NULL ;
}
break ;
case ' # ' :
ptr + + ;
while ( * ptr & & ( * ptr ! = ' \n ' ) )
ptr + + ;
if ( ! * ptr )
break ;
ptr - - ;
continue ;
case ' / ' :
if ( * ( ptr + 1 ) = = ' / ' )
{
ptr + = 2 ;
while ( * ptr & & ( * ptr ! = ' \n ' ) )
ptr + + ;
if ( ! * ptr )
break ;
ptr - - ; /* grab the \n on next loop thru */
continue ;
}
else if ( * ( ptr + 1 ) = = ' * ' )
{
int commentstart = linenumber ;
for ( ptr + = 2 ; * ptr ; ptr + + )
{
if ( * ptr = = ' \n ' )
{
linenumber + + ;
} else
if ( ( * ptr = = ' * ' ) & & ( * ( ptr + 1 ) = = ' / ' ) )
{
ptr + + ;
break ;
}
}
if ( ! * ptr )
{
config_error ( " %s:%i Comment on line %d does not end \n " ,
filename , commentstart , commentstart ) ;
errors + + ;
config_entry_free_all ( curce ) ;
config_free ( curcf ) ;
return NULL ;
}
}
break ;
2022-01-15 05:16:34 +00:00
case ' \' ' :
if ( curce )
curce - > escaped = 1 ;
/* fallthrough */
2020-03-29 09:16:53 +00:00
case ' \" ' :
2022-01-15 05:16:34 +00:00
if ( curce & & curce - > line_number ! = linenumber & & cursection )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: Missing semicolon (';') at end of line. "
" Line %d must end with a ; character \n " ,
2022-01-15 05:16:34 +00:00
filename , curce - > line_number , curce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
* lastce = curce ;
2022-01-15 05:16:34 +00:00
lastce = & ( curce - > next ) ;
curce - > file_position_end = ( ptr - confdata ) ;
2020-03-29 09:16:53 +00:00
curce = NULL ;
}
start = + + ptr ;
for ( ; * ptr ; ptr + + )
{
if ( * ptr = = ' \\ ' )
{
2022-01-15 05:16:34 +00:00
if ( strchr ( " \\ \" ' " , ptr [ 1 ] ) )
2020-03-29 09:16:53 +00:00
{
/* \\ or \" in config file (escaped) */
ptr + + ; /* skip */
continue ;
}
}
2022-01-15 05:16:34 +00:00
else if ( * ptr = = ' \n ' )
break ;
else if ( curce & & curce - > escaped & & ( * ptr = = ' \' ' ) )
break ;
else if ( ( ! curce | | ! curce - > escaped ) & & ( * ptr = = ' " ' ) )
2020-03-29 09:16:53 +00:00
break ;
}
if ( ! * ptr | | ( * ptr = = ' \n ' ) )
{
config_error ( " %s:%i: Unterminated quote found \n " ,
filename , linenumber ) ;
errors + + ;
config_entry_free_all ( curce ) ;
config_free ( curcf ) ;
return NULL ;
}
if ( curce )
{
2022-01-15 05:16:34 +00:00
if ( curce - > value )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: Extra data detected. Perhaps missing a ';' or one too many? \n " ,
filename , linenumber ) ;
errors + + ;
}
else
{
2022-01-15 05:16:34 +00:00
safe_strldup ( curce - > value , start , ptr - start + 1 ) ;
preprocessor_replace_defines ( & curce - > value , curce ) ;
unreal_del_quotes ( curce - > value ) ;
2020-03-29 09:16:53 +00:00
}
}
else
{
curce = safe_alloc ( sizeof ( ConfigEntry ) ) ;
2022-01-15 05:16:34 +00:00
curce - > line_number = linenumber ;
curce - > file = curcf ;
curce - > parent = cursection ;
curce - > file_position_start = ( start - confdata ) ;
safe_strldup ( curce - > name , start , ptr - start + 1 ) ;
preprocessor_replace_defines ( & curce - > name , curce ) ;
unreal_del_quotes ( curce - > name ) ;
preprocessor_cc_duplicate_list ( cc_list , & curce - > conditional_config ) ;
2020-03-29 09:16:53 +00:00
}
break ;
case ' \n ' :
linenumber + + ;
/* fall through */
case ' \t ' :
case ' ' :
case ' = ' :
case ' \r ' :
break ;
case ' @ ' :
/* Preprocessor item, such as @if, @define, etc. */
start = ptr ;
for ( ; * ptr ; ptr + + )
{
if ( * ptr = = ' \n ' )
break ;
}
cc = NULL ;
n = parse_preprocessor_item ( start , ptr , filename , linenumber , & cc ) ;
linenumber + + ;
if ( n = = PREPROCESSOR_IF )
{
preprocessor_level + + ;
cc - > priority = preprocessor_level ;
AddListItem ( cc , cc_list ) ;
} else
if ( n = = PREPROCESSOR_ENDIF )
{
if ( preprocessor_level = = 0 )
{
config_error ( " %s:%i: @endif unexpected. There was no preciding unclosed @if. " ,
filename , linenumber ) ;
errors + + ;
}
preprocessor_cc_free_level ( & cc_list , preprocessor_level ) ;
preprocessor_level - - ;
} else
if ( n = = PREPROCESSOR_ERROR )
{
errors + + ;
goto breakout ;
}
if ( ! * ptr )
goto breakout ; /* special case, since we don't want the for loop to ptr++ */
break ;
default :
if ( ( * ptr = = ' * ' ) & & ( * ( ptr + 1 ) = = ' / ' ) )
{
config_status ( " %s:%i: Ignoring extra end comment \n " ,
filename , linenumber ) ;
config_status ( " WARNING: Starting with UnrealIRCd 4.2.1 a /*-style comment stops as soon as the first */ is encountered. "
" See https://www.unrealircd.org/docs/FAQ#Nesting_comments for more information. " ) ;
ptr + + ;
break ;
}
start = ptr ;
for ( ; * ptr ; ptr + + )
{
if ( ( * ptr = = ' ' ) | | ( * ptr = = ' = ' ) | | ( * ptr = = ' \t ' ) | | ( * ptr = = ' \n ' ) | | ( * ptr = = ' ; ' ) )
break ;
}
if ( ! * ptr )
{
if ( curce )
config_error ( " %s: End of file reached but directive or block at line %i did not end properly. "
" Perhaps a missing ; (semicolon) somewhere? \n " ,
2022-01-15 05:16:34 +00:00
filename , curce - > line_number ) ;
2020-03-29 09:16:53 +00:00
else if ( cursection )
config_error ( " %s: End of file reached but the section which starts at line %i did never end properly. "
" Perhaps a missing }; ? \n " ,
2022-01-15 05:16:34 +00:00
filename , cursection - > section_linenumber ) ;
2020-03-29 09:16:53 +00:00
else
config_error ( " %s: Unexpected end of file. Some line or block did not end properly. "
" Look for any missing } and }; \n " , filename ) ;
errors + + ;
config_entry_free_all ( curce ) ;
config_free ( curcf ) ;
return NULL ;
}
if ( curce )
{
2022-01-15 05:16:34 +00:00
if ( curce - > value )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: Extra data detected. Check for a missing ; character at or around line %d \n " ,
filename , linenumber , linenumber - 1 ) ;
errors + + ;
}
else
{
2022-01-15 05:16:34 +00:00
safe_strldup ( curce - > value , start , ptr - start + 1 ) ;
preprocessor_replace_defines ( & curce - > value , curce ) ;
2020-03-29 09:16:53 +00:00
}
}
else
{
curce = safe_alloc ( sizeof ( ConfigEntry ) ) ;
memset ( curce , 0 , sizeof ( ConfigEntry ) ) ;
2022-01-15 05:16:34 +00:00
curce - > line_number = linenumber ;
curce - > file = curcf ;
curce - > parent = cursection ;
curce - > file_position_start = ( start - confdata ) ;
safe_strldup ( curce - > name , start , ptr - start + 1 ) ;
preprocessor_replace_defines ( & curce - > name , curce ) ;
if ( curce - > conditional_config )
abort ( ) ;
preprocessor_cc_duplicate_list ( cc_list , & curce - > conditional_config ) ;
2020-03-29 09:16:53 +00:00
}
if ( ( * ptr = = ' ; ' ) | | ( * ptr = = ' \n ' ) )
ptr - - ;
break ;
} /* switch */
if ( ! * ptr ) /* This IS possible. -- Syzop */
break ;
} /* for */
breakout :
if ( curce )
{
config_error ( " %s: End of file reached but directive or block at line %i did not end properly. "
" Perhaps a missing ; (semicolon) somewhere? \n " ,
2022-01-15 05:16:34 +00:00
filename , curce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
config_entry_free_all ( curce ) ;
}
else if ( cursection )
{
config_error ( " %s: End of file reached but the section which starts at line %i did never end properly. "
" Perhaps a missing }; ? \n " ,
2022-01-15 05:16:34 +00:00
filename , cursection - > section_linenumber ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
if ( errors )
{
config_free ( curcf ) ;
return NULL ;
}
return curcf ;
}
/** Free a ConfigEntry struct, all it's children, and all it's next entries.
* Consider calling config_entry_free ( ) instead of this one . . or at least
* check which one of the two you actually need ; )
*/
void config_entry_free_all ( ConfigEntry * ce )
{
ConfigEntry * nptr ;
for ( ; ce ; ce = nptr )
{
2022-01-15 05:16:34 +00:00
nptr = ce - > next ;
if ( ce - > items )
config_entry_free_all ( ce - > items ) ;
safe_free ( ce - > name ) ;
safe_free ( ce - > value ) ;
if ( ce - > conditional_config )
preprocessor_cc_free_list ( ce - > conditional_config ) ;
2020-03-29 09:16:53 +00:00
safe_free ( ce ) ;
}
}
/** Free a specific ConfigEntry struct (and it's children).
* Caller must ensure that the entry is not in the linked list anymore .
*/
void config_entry_free ( ConfigEntry * ce )
{
2022-01-15 05:16:34 +00:00
if ( ce - > items )
config_entry_free_all ( ce - > items ) ;
safe_free ( ce - > name ) ;
safe_free ( ce - > value ) ;
if ( ce - > conditional_config )
preprocessor_cc_free_list ( ce - > conditional_config ) ;
2020-03-29 09:16:53 +00:00
safe_free ( ce ) ;
}
2022-01-15 05:16:34 +00:00
ConfigEntry * config_find_entry ( ConfigEntry * ce , const char * name )
2020-03-29 09:16:53 +00:00
{
ConfigEntry * cep ;
2022-01-15 05:16:34 +00:00
for ( cep = ce ; cep ; cep = cep - > next )
if ( cep - > name & & ! strcmp ( cep - > name , name ) )
2020-03-29 09:16:53 +00:00
break ;
return cep ;
}
void config_error ( FORMAT_STRING ( const char * format ) , . . . )
{
va_list ap ;
char buffer [ 1024 ] ;
char * ptr ;
va_start ( ap , format ) ;
vsnprintf ( buffer , sizeof ( buffer ) , format , ap ) ;
va_end ( ap ) ;
if ( ( ptr = strchr ( buffer , ' \n ' ) ) ! = NULL )
* ptr = ' \0 ' ;
2022-01-15 05:16:34 +00:00
unreal_log_raw ( ULOG_ERROR , " config " , " CONFIG_ERROR_GENERIC " , NULL , buffer ) ;
2020-03-29 09:16:53 +00:00
/* We cannot live with this */
config_error_flag = 1 ;
}
void config_error_missing ( const char * filename , int line , const char * entry )
{
config_error ( " %s:%d: %s is missing " , filename , line , entry ) ;
}
void config_error_unknown ( const char * filename , int line , const char * block ,
const char * entry )
{
config_error ( " %s:%d: Unknown directive '%s::%s' " , filename , line , block , entry ) ;
}
void config_error_unknownflag ( const char * filename , int line , const char * block ,
const char * entry )
{
config_error ( " %s:%d: Unknown %s flag '%s' " , filename , line , block , entry ) ;
}
void config_error_unknownopt ( const char * filename , int line , const char * block ,
const char * entry )
{
config_error ( " %s:%d: Unknown %s option '%s' " , filename , line , block , entry ) ;
}
void config_error_noname ( const char * filename , int line , const char * block )
{
config_error ( " %s:%d: %s block has no name " , filename , line , block ) ;
}
void config_error_blank ( const char * filename , int line , const char * block )
{
config_error ( " %s:%d: Blank %s entry " , filename , line , block ) ;
}
void config_error_empty ( const char * filename , int line , const char * block ,
const char * entry )
{
config_error ( " %s:%d: %s::%s specified without a value " ,
filename , line , block , entry ) ;
}
void config_status ( FORMAT_STRING ( const char * format ) , . . . )
{
va_list ap ;
char buffer [ 1024 ] ;
char * ptr ;
va_start ( ap , format ) ;
vsnprintf ( buffer , 1023 , format , ap ) ;
va_end ( ap ) ;
if ( ( ptr = strchr ( buffer , ' \n ' ) ) ! = NULL )
* ptr = ' \0 ' ;
2022-01-15 05:16:34 +00:00
unreal_log_raw ( ULOG_INFO , " config " , " CONFIG_INFO_GENERIC " , NULL , buffer ) ;
2020-03-29 09:16:53 +00:00
}
void config_warn ( FORMAT_STRING ( const char * format ) , . . . )
{
va_list ap ;
char buffer [ 1024 ] ;
char * ptr ;
va_start ( ap , format ) ;
vsnprintf ( buffer , 1023 , format , ap ) ;
va_end ( ap ) ;
if ( ( ptr = strchr ( buffer , ' \n ' ) ) ! = NULL )
* ptr = ' \0 ' ;
2022-01-15 05:16:34 +00:00
unreal_log_raw ( ULOG_WARNING , " config " , " CONFIG_WARNING_GENERIC " , NULL , buffer ) ;
2020-03-29 09:16:53 +00:00
}
void config_warn_duplicate ( const char * filename , int line , const char * entry )
{
config_warn ( " %s:%d: Duplicate %s directive " , filename , line , entry ) ;
}
/* returns 1 if the test fails */
int config_test_openfile ( ConfigEntry * cep , int flags , mode_t mode , const char * entry , int fatal , int allow_url )
{
int fd ;
2022-01-15 05:16:34 +00:00
if ( ! cep - > value )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( fatal )
2020-03-29 09:16:53 +00:00
config_error ( " %s:%i: %s: <no file specified>: no file specified " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename ,
cep - > line_number ,
2020-03-29 09:16:53 +00:00
entry ) ;
else
config_warn ( " %s:%i: %s: <no file specified>: no file specified " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename ,
cep - > line_number ,
2020-03-29 09:16:53 +00:00
entry ) ;
return 1 ;
}
/* There's not much checking that can be done for asynchronously downloaded files */
2022-01-15 05:16:34 +00:00
if ( url_is_valid ( cep - > value ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( allow_url )
2020-03-29 09:16:53 +00:00
return 0 ;
/* but we can check if a URL is used wrongly :-) */
config_warn ( " %s:%i: %s: %s: URL used where not allowed " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename ,
cep - > line_number ,
entry , cep - > value ) ;
if ( fatal )
2020-03-29 09:16:53 +00:00
return 1 ;
else
return 0 ;
}
/*
* Make sure that files are created with the correct mode . This is
* because we don ' t feel like unlink ( ) ing them . . . which would require
* stat ( ) ing them to make sure that we don ' t delete existing ones
* and that we deal with all of the bugs that come with complexity .
* The only files we may be creating are the tunefile and pidfile so far .
*/
2022-01-15 05:16:34 +00:00
if ( flags & O_CREAT )
fd = open ( cep - > value , flags , mode ) ;
2020-03-29 09:16:53 +00:00
else
2022-01-15 05:16:34 +00:00
fd = open ( cep - > value , flags ) ;
if ( fd = = - 1 )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( fatal )
2020-03-29 09:16:53 +00:00
config_error ( " %s:%i: %s: %s: %s " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename ,
cep - > line_number ,
2020-03-29 09:16:53 +00:00
entry ,
2022-01-15 05:16:34 +00:00
cep - > value ,
2020-03-29 09:16:53 +00:00
strerror ( errno ) ) ;
else
config_warn ( " %s:%i: %s: %s: %s " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename ,
cep - > line_number ,
2020-03-29 09:16:53 +00:00
entry ,
2022-01-15 05:16:34 +00:00
cep - > value ,
2020-03-29 09:16:53 +00:00
strerror ( errno ) ) ;
return 1 ;
}
close ( fd ) ;
return 0 ;
}
int config_is_blankorempty ( ConfigEntry * cep , const char * block )
{
2022-01-15 05:16:34 +00:00
if ( ! cep - > value )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_empty ( cep - > file - > filename , cep - > line_number , block ,
cep - > name ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
return 0 ;
}
2022-01-15 05:16:34 +00:00
ConfigCommand * config_binary_search ( const char * cmd ) {
2020-03-29 09:16:53 +00:00
int start = 0 ;
int stop = ARRAY_SIZEOF ( _ConfigCommands ) - 1 ;
int mid ;
while ( start < = stop ) {
mid = ( start + stop ) / 2 ;
if ( smycmp ( cmd , _ConfigCommands [ mid ] . name ) < 0 ) {
stop = mid - 1 ;
}
else if ( strcmp ( cmd , _ConfigCommands [ mid ] . name ) = = 0 ) {
return & _ConfigCommands [ mid ] ;
}
else
start = mid + 1 ;
}
return NULL ;
}
2022-04-03 15:09:29 +00:00
void free_iConf ( Configuration * i )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
FloodSettings * f , * f_next ;
2020-03-29 09:16:53 +00:00
safe_free ( i - > link_bindip ) ;
safe_free ( i - > kline_address ) ;
safe_free ( i - > gline_address ) ;
safe_free ( i - > oper_snomask ) ;
safe_free ( i - > auto_join_chans ) ;
safe_free ( i - > oper_auto_join_chans ) ;
safe_free ( i - > allow_user_stats ) ;
// allow_user_stats_ext is freed elsewhere
safe_free ( i - > static_quit ) ;
safe_free ( i - > static_part ) ;
free_tls_options ( i - > tls_options ) ;
i - > tls_options = NULL ;
safe_free ( i - > tls_options ) ;
2020-04-20 19:12:33 +00:00
safe_free_multiline ( i - > plaintext_policy_user_message ) ;
safe_free_multiline ( i - > plaintext_policy_oper_message ) ;
2020-03-29 09:16:53 +00:00
safe_free ( i - > outdated_tls_policy_user_message ) ;
safe_free ( i - > outdated_tls_policy_oper_message ) ;
safe_free ( i - > restrict_usermodes ) ;
safe_free ( i - > restrict_channelmodes ) ;
safe_free ( i - > restrict_extendedbans ) ;
safe_free ( i - > channel_command_prefix ) ;
2022-01-15 05:16:34 +00:00
safe_free ( i - > level_on_join ) ;
2020-03-29 09:16:53 +00:00
safe_free ( i - > spamfilter_ban_reason ) ;
safe_free ( i - > spamfilter_virus_help_channel ) ;
// spamexcept is freed elsewhere
safe_free ( i - > spamexcept_line ) ;
safe_free ( i - > reject_message_too_many_connections ) ;
safe_free ( i - > reject_message_server_full ) ;
safe_free ( i - > reject_message_unauthorized ) ;
safe_free ( i - > reject_message_kline ) ;
safe_free ( i - > reject_message_gline ) ;
2022-01-15 05:16:34 +00:00
safe_free ( i - > network_name ) ;
safe_free ( i - > network_name_005 ) ;
safe_free ( i - > default_server ) ;
safe_free ( i - > services_name ) ;
safe_free ( i - > cloak_prefix ) ;
safe_free ( i - > prefix_quit ) ;
safe_free ( i - > helpchan ) ;
safe_free ( i - > stats_server ) ;
safe_free ( i - > sasl_server ) ;
// anti-flood:
for ( f = i - > floodsettings ; f ; f = f_next )
{
f_next = f - > next ;
free_floodsettings ( f ) ;
}
i - > floodsettings = NULL ;
2020-03-29 09:16:53 +00:00
}
void config_setdefaultsettings ( Configuration * i )
{
char tmp [ 512 ] ;
2022-01-15 05:16:34 +00:00
safe_strdup ( i - > oper_snomask , OPER_SNOMASKS ) ;
i - > server_notice_colors = 1 ;
2022-04-03 15:09:29 +00:00
i - > server_notice_show_event = 1 ;
2020-03-29 09:16:53 +00:00
i - > ident_read_timeout = 7 ;
i - > ident_connect_timeout = 3 ;
i - > ban_version_tkl_time = 86400 ; /* 1d */
i - > spamfilter_ban_time = 86400 ; /* 1d */
safe_strdup ( i - > spamfilter_ban_reason , " Spam/advertising " ) ;
safe_strdup ( i - > spamfilter_virus_help_channel , " #help " ) ;
i - > spamfilter_detectslow_warn = 250 ;
i - > spamfilter_detectslow_fatal = 500 ;
i - > spamfilter_stop_on_first_match = 1 ;
i - > maxchannelsperuser = 10 ;
i - > maxdccallow = 10 ;
safe_strdup ( i - > channel_command_prefix , " `!. " ) ;
2020-11-26 16:02:01 +00:00
i - > conn_modes = set_usermode ( " +ixw " ) ;
2020-03-29 09:16:53 +00:00
i - > check_target_nick_bans = 1 ;
i - > maxbans = 60 ;
i - > maxbanlength = 2048 ;
2022-01-15 05:16:34 +00:00
safe_strdup ( i - > level_on_join , " o " ) ;
2020-03-29 09:16:53 +00:00
i - > watch_away_notification = 1 ;
i - > uhnames = 1 ;
i - > ping_cookie = 1 ;
i - > ping_warning = 15 ; /* default ping warning notices 15 seconds */
i - > default_ipv6_clone_mask = 64 ;
nicklengths . min = i - > min_nick_length = 0 ; /* 0 means no minimum required */
nicklengths . max = i - > nick_length = NICKLEN ;
i - > topic_length = 360 ;
i - > away_length = 307 ;
i - > kick_length = 307 ;
i - > quit_length = 307 ;
safe_strdup ( i - > link_bindip , " * " ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( i - > cloak_prefix , " Clk " ) ;
2020-03-29 09:16:53 +00:00
if ( ! ipv6_capable ( ) )
DISABLE_IPV6 = 1 ;
2022-01-15 05:16:34 +00:00
safe_strdup ( i - > prefix_quit , " Quit " ) ;
2020-03-29 09:16:53 +00:00
i - > max_unknown_connections_per_ip = 3 ;
i - > handshake_timeout = 30 ;
i - > sasl_timeout = 15 ;
i - > handshake_delay = - 1 ;
i - > broadcast_channel_messages = BROADCAST_CHANNEL_MESSAGES_AUTO ;
2021-06-19 15:52:51 +00:00
/* Flood options */
/* - everyone */
i - > throttle_count = 3 ; i - > throttle_period = 60 ; /* throttle protection: max 3 per 60s */
i - > handshake_data_flood_amount = 4096 ;
i - > handshake_data_flood_ban_action = BAN_ACT_ZLINE ;
i - > handshake_data_flood_ban_time = 600 ;
// (targetflood is in the targetflood module)
/* - known-users */
config_parse_flood_generic ( " 3:60 " , i , " known-users " , FLD_NICK ) ; /* NICK flood protection: max 3 per 60s */
config_parse_flood_generic ( " 3:90 " , i , " known-users " , FLD_JOIN ) ; /* JOIN flood protection: max 3 per 90s */
2022-04-03 15:09:29 +00:00
config_parse_flood_generic ( " 3:90 " , i , " known-users " , FLD_VHOST ) ; /* MODE -x flood protection: max 3 per 90s */
2021-06-19 15:52:51 +00:00
config_parse_flood_generic ( " 4:120 " , i , " known-users " , FLD_AWAY ) ; /* AWAY flood protection: max 4 per 120s */
config_parse_flood_generic ( " 4:60 " , i , " known-users " , FLD_INVITE ) ; /* INVITE flood protection: max 4 per 60s */
config_parse_flood_generic ( " 4:120 " , i , " known-users " , FLD_KNOCK ) ; /* KNOCK protection: max 4 per 120s */
config_parse_flood_generic ( " 10:15 " , i , " known-users " , FLD_CONVERSATIONS ) ; /* 10 users, new user every 15s */
2022-01-15 05:16:34 +00:00
config_parse_flood_generic ( " 180:750 " , i , " known-users " , FLD_LAG_PENALTY ) ; /* 180 bytes / 750 msec */
2021-06-19 15:52:51 +00:00
/* - unknown-users */
config_parse_flood_generic ( " 2:60 " , i , " unknown-users " , FLD_NICK ) ; /* NICK flood protection: max 2 per 60s */
config_parse_flood_generic ( " 2:90 " , i , " unknown-users " , FLD_JOIN ) ; /* JOIN flood protection: max 2 per 90s */
2022-04-03 15:09:29 +00:00
config_parse_flood_generic ( " 2:90 " , i , " unknown-users " , FLD_VHOST ) ; /* MODE -x flood protection: max 2 per 90s */
2021-06-19 15:52:51 +00:00
config_parse_flood_generic ( " 4:120 " , i , " unknown-users " , FLD_AWAY ) ; /* AWAY flood protection: max 4 per 120s */
config_parse_flood_generic ( " 2:60 " , i , " unknown-users " , FLD_INVITE ) ; /* INVITE flood protection: max 2 per 60s */
config_parse_flood_generic ( " 2:120 " , i , " unknown-users " , FLD_KNOCK ) ; /* KNOCK protection: max 2 per 120s */
config_parse_flood_generic ( " 4:15 " , i , " unknown-users " , FLD_CONVERSATIONS ) ; /* 4 users, new user every 15s */
2022-01-15 05:16:34 +00:00
config_parse_flood_generic ( " 90:1000 " , i , " unknown-users " , FLD_LAG_PENALTY ) ; /* 90 bytes / 1000 msec */
2021-06-19 15:52:51 +00:00
2022-01-15 05:16:34 +00:00
/* TLS options */
2020-03-29 09:16:53 +00:00
i - > tls_options = safe_alloc ( sizeof ( TLSOptions ) ) ;
snprintf ( tmp , sizeof ( tmp ) , " %s/tls/server.cert.pem " , CONFDIR ) ;
safe_strdup ( i - > tls_options - > certificate_file , tmp ) ;
snprintf ( tmp , sizeof ( tmp ) , " %s/tls/server.key.pem " , CONFDIR ) ;
safe_strdup ( i - > tls_options - > key_file , tmp ) ;
snprintf ( tmp , sizeof ( tmp ) , " %s/tls/curl-ca-bundle.crt " , CONFDIR ) ;
safe_strdup ( i - > tls_options - > trusted_ca_file , tmp ) ;
safe_strdup ( i - > tls_options - > ciphers , UNREALIRCD_DEFAULT_CIPHERS ) ;
safe_strdup ( i - > tls_options - > ciphersuites , UNREALIRCD_DEFAULT_CIPHERSUITES ) ;
2023-05-05 22:12:01 +00:00
i - > tls_options - > protocols = TLS_PROTOCOL_TLSV1_2 | TLS_PROTOCOL_TLSV1_3 ; /* TLSv1.2 & TLSv1.3 */
2020-03-29 09:16:53 +00:00
# ifdef HAS_SSL_CTX_SET1_CURVES_LIST
safe_strdup ( i - > tls_options - > ecdh_curves , UNREALIRCD_DEFAULT_ECDH_CURVES ) ;
# endif
safe_strdup ( i - > tls_options - > outdated_protocols , " TLSv1,TLSv1.1 " ) ;
/* the following may look strange but "AES*" matches all
* AES ciphersuites that do not have Forward Secrecy .
* Any decent client using AES will use ECDHE - xx - AES .
*/
safe_strdup ( i - > tls_options - > outdated_ciphers , " AES*,RC4*,DES* " ) ;
i - > plaintext_policy_user = POLICY_ALLOW ;
i - > plaintext_policy_oper = POLICY_DENY ;
i - > plaintext_policy_server = POLICY_DENY ;
i - > outdated_tls_policy_user = POLICY_WARN ;
i - > outdated_tls_policy_oper = POLICY_DENY ;
i - > outdated_tls_policy_server = POLICY_DENY ;
safe_strdup ( i - > reject_message_too_many_connections , " Too many connections from your IP " ) ;
safe_strdup ( i - > reject_message_server_full , " This server is full " ) ;
safe_strdup ( i - > reject_message_unauthorized , " You are not authorized to connect to this server " ) ;
safe_strdup ( i - > reject_message_kline , " You are not welcome on this server. $bantype: $banreason. Email $klineaddr for more information. " ) ;
safe_strdup ( i - > reject_message_gline , " You are not welcome on this network. $bantype: $banreason. Email $glineaddr for more information. " ) ;
i - > topic_setter = SETTER_NICK ;
i - > ban_setter = SETTER_NICK ;
i - > ban_setter_sync = 1 ;
i - > allowed_channelchars = ALLOWED_CHANNELCHARS_UTF8 ;
i - > automatic_ban_target = BAN_TARGET_IP ;
i - > manual_ban_target = BAN_TARGET_HOST ;
2020-04-20 19:12:33 +00:00
i - > hide_idle_time = HIDE_IDLE_TIME_OPER_USERMODE ;
2020-05-29 02:06:50 +00:00
i - > who_limit = 100 ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
i - > named_extended_bans = 1 ;
2020-03-29 09:16:53 +00:00
}
/** Similar to config_setdefaultsettings but this one is applied *AFTER*
* the entire configuration has been ran ( sometimes this is the only way it can be done . . ) .
* NOTE : iConf is thus already populated with ( non - default ) values . Only overwrite if necessary !
*/
void postconf_defaults ( void )
{
TKL * tk ;
char * encoded ;
2022-01-15 05:16:34 +00:00
if ( ! iConf . modes_on_join_set )
{
/* We could not do this in config_setdefaultsettings()
* because the channel mode modules were not initialized yet .
*/
conf_channelmodes ( " +nt " , & iConf . modes_on_join ) ;
}
2020-03-29 09:16:53 +00:00
if ( ! iConf . plaintext_policy_user_message )
{
/* The message depends on whether it's reject or warn.. */
if ( iConf . plaintext_policy_user = = POLICY_DENY )
2022-01-15 05:16:34 +00:00
addmultiline ( & iConf . plaintext_policy_user_message , " Insecure connection. Please reconnect using TLS. " ) ;
2020-03-29 09:16:53 +00:00
else if ( iConf . plaintext_policy_user = = POLICY_WARN )
2022-01-15 05:16:34 +00:00
addmultiline ( & iConf . plaintext_policy_user_message , " WARNING: Insecure connection. Please consider using TLS. " ) ;
2020-03-29 09:16:53 +00:00
}
if ( ! iConf . plaintext_policy_oper_message )
{
/* The message depends on whether it's reject or warn.. */
if ( iConf . plaintext_policy_oper = = POLICY_DENY )
2020-04-20 19:12:33 +00:00
{
2022-01-15 05:16:34 +00:00
addmultiline ( & iConf . plaintext_policy_oper_message , " You need to use a secure connection (TLS) in order to /OPER. " ) ;
2020-04-20 19:12:33 +00:00
addmultiline ( & iConf . plaintext_policy_oper_message , " See https://www.unrealircd.org/docs/FAQ#oper-requires-tls " ) ;
}
2020-03-29 09:16:53 +00:00
else if ( iConf . plaintext_policy_oper = = POLICY_WARN )
2022-01-15 05:16:34 +00:00
addmultiline ( & iConf . plaintext_policy_oper_message , " WARNING: You /OPER'ed up from an insecure connection. Please consider using TLS. " ) ;
2020-03-29 09:16:53 +00:00
}
if ( ! iConf . outdated_tls_policy_user_message )
{
/* The message depends on whether it's reject or warn.. */
if ( iConf . outdated_tls_policy_user = = POLICY_DENY )
2022-01-15 05:16:34 +00:00
safe_strdup ( iConf . outdated_tls_policy_user_message , " Your IRC client is using an outdated TLS protocol or ciphersuite ($protocol-$cipher). Please upgrade your IRC client. " ) ;
2020-03-29 09:16:53 +00:00
else if ( iConf . outdated_tls_policy_user = = POLICY_WARN )
2022-01-15 05:16:34 +00:00
safe_strdup ( iConf . outdated_tls_policy_user_message , " WARNING: Your IRC client is using an outdated TLS protocol or ciphersuite ($protocol-$cipher). Please upgrade your IRC client. " ) ;
2020-03-29 09:16:53 +00:00
}
if ( ! iConf . outdated_tls_policy_oper_message )
{
/* The message depends on whether it's reject or warn.. */
if ( iConf . outdated_tls_policy_oper = = POLICY_DENY )
2022-01-15 05:16:34 +00:00
safe_strdup ( iConf . outdated_tls_policy_oper_message , " Your IRC client is using an outdated TLS protocol or ciphersuite ($protocol-$cipher). Please upgrade your IRC client. " ) ;
2020-03-29 09:16:53 +00:00
else if ( iConf . outdated_tls_policy_oper = = POLICY_WARN )
2022-01-15 05:16:34 +00:00
safe_strdup ( iConf . outdated_tls_policy_oper_message , " WARNING: Your IRC client is using an outdated TLS protocol or ciphersuite ($protocol-$cipher). Please upgrade your IRC client. " ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
postconf_defaults_log_block ( ) ;
2020-03-29 09:16:53 +00:00
}
void postconf_fixes ( void )
{
/* If set::topic-setter is set to "nick-user-host" then the
* maximum topic length becomes shorter .
*/
if ( ( iConf . topic_setter = = SETTER_NICK_USER_HOST ) & &
( iConf . topic_length > 340 ) )
{
config_warn ( " set::topic-length adjusted from %d to 340, which is the maximum because "
" set::topic-setter is set to 'nick-user-host'. " , iConf . topic_length ) ;
iConf . topic_length = 340 ;
}
}
/* Needed for set::options::allow-part-if-shunned,
* we can ' t just make it CMD_SHUN and do a ALLOW_PART_IF_SHUNNED in
* cmd_part itself because that will also block internal calls ( like sapart ) . - - Syzop
*/
static void do_weird_shun_stuff ( )
{
RealCommand * cmptr ;
if ( ( cmptr = find_command_simple ( " PART " ) ) )
{
if ( ALLOW_PART_IF_SHUNNED )
cmptr - > flags | = CMD_SHUN ;
else
cmptr - > flags & = ~ CMD_SHUN ;
}
}
/** Various things that are done at the very end after the configuration file
* has been read and almost all values have been set . This is to deal with
* things like adding a default log { } block if there is none and that kind
* of things .
2022-01-15 05:16:34 +00:00
* This function is called by config_test ( ) , both on boot and on rehash .
2020-03-29 09:16:53 +00:00
*/
void postconf ( void )
{
postconf_defaults ( ) ;
postconf_fixes ( ) ;
do_weird_shun_stuff ( ) ;
isupport_init ( ) ; /* for all the 005 values that changed.. */
2021-01-08 23:15:08 +00:00
tls_check_expiry ( NULL ) ;
2022-01-15 05:16:34 +00:00
# if OPENSSL_VERSION_NUMBER >= 0x10101000L
if ( loop . rehashing )
reinit_tls ( ) ;
# endif
2020-03-29 09:16:53 +00:00
}
int isanyserverlinked ( void )
{
return ! list_empty ( & server_list ) ;
}
void applymeblock ( void )
{
if ( ! conf_me )
return ; /* uh-huh? */
/* Info text may always change, just wouldn't show up on other servers, that's all.. */
strlcpy ( me . info , conf_me - > info , sizeof ( me . info ) ) ;
/* Name can only be set once (on boot) */
if ( ! * me . name )
strlcpy ( me . name , conf_me - > name , sizeof ( me . name ) ) ;
else if ( strcmp ( me . name , conf_me - > name ) )
{
config_warn ( " You changed the servername (me::name). "
" This change will NOT be effective unless you restart the IRC Server. " ) ;
}
if ( ! * me . id )
strlcpy ( me . id , conf_me - > sid , sizeof ( me . id ) ) ;
}
/** Run config test and all post config tests. */
int config_test_all ( void )
{
2022-01-15 05:16:34 +00:00
if ( ( config_test_blocks ( ) < 0 ) | | ( callbacks_check ( ) < 0 ) | | ( efunctions_check ( ) < 0 ) | |
reloadable_perm_module_unloaded ( ) | | ! tls_tests ( ) | | ! log_tests ( ) )
2020-03-29 09:16:53 +00:00
{
return 0 ;
}
special_delayed_unloading ( ) ;
return 1 ;
}
/** Process all loadmodule directives in all includes.
* This was previously done at the same time as ' include ' was called but
* that was too early now that we have blacklist - module , so moved here .
* @ retval 1 on success , 0 on any failed loadmodule directive .
*/
int config_loadmodules ( void )
{
ConfigFile * cfptr ;
ConfigEntry * ce ;
ConfigItem_blacklist_module * blm , * blm_next ;
int fatal_ret = 0 , ret ;
2022-01-15 05:16:34 +00:00
for ( cfptr = conf ; cfptr ; cfptr = cfptr - > next )
2020-03-29 09:16:53 +00:00
{
if ( config_verbose > 1 )
2022-01-15 05:16:34 +00:00
config_status ( " Testing %s " , cfptr - > filename ) ;
for ( ce = cfptr - > items ; ce ; ce = ce - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ce - > name , " loadmodule " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ce - > conditional_config )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%d: Currently you cannot have a 'loadmodule' statement "
" within an @if block, sorry. " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 0 ;
}
ret = _conf_loadmodule ( cfptr , ce ) ;
if ( ret < fatal_ret )
fatal_ret = ret ; /* lowest wins */
}
}
}
/* Let's free the blacklist-module list here as well */
for ( blm = conf_blacklist_module ; blm ; blm = blm_next )
{
blm_next = blm - > next ;
safe_free ( blm - > name ) ;
safe_free ( blm ) ;
}
conf_blacklist_module = NULL ;
/* End of freeing code */
/* If any loadmodule returned a fatal (-1) error code then we return fail status (0) */
if ( fatal_ret < 0 )
return 0 ; /* FAIL */
return 1 ; /* SUCCESS */
}
2022-01-15 05:16:34 +00:00
/** Reject the configuration load.
* This is called both from boot and from rehash .
*/
void config_load_failed ( void )
{
if ( conf )
unreal_log ( ULOG_ERROR , " config " , " CONFIG_NOT_LOADED " , NULL , " IRCd configuration failed to load " ) ;
2023-05-05 22:12:01 +00:00
loop . config_status = CONFIG_STATUS_ROLLBACK ;
2022-01-15 05:16:34 +00:00
Unload_all_testing_modules ( ) ;
free_all_config_resources ( ) ;
config_free ( conf ) ;
conf = NULL ;
free_iConf ( & tempiConf ) ;
# ifdef _WIN32
if ( ! loop . rehashing )
win_error ( ) ; /* GUI popup */
# endif
}
int config_read_start ( void )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
int ret ;
2020-03-29 09:16:53 +00:00
config_status ( " Loading IRCd configuration.. " ) ;
2022-01-15 05:16:34 +00:00
loop . config_load_failed = 0 ;
2020-03-29 09:16:53 +00:00
if ( conf )
{
config_error ( " %s:%i - Someone forgot to clean up " , __FILE__ , __LINE__ ) ;
return - 1 ;
}
2022-01-15 05:16:34 +00:00
/* We set this to 1 because otherwise we may call rehash_internal()
* already from config_read_file ( ) which is too soon ( race ) .
*/
loop . rehash_download_busy = 1 ;
add_config_resource ( configfile , RESOURCE_INCLUDE , NULL ) ;
ret = config_read_file ( configfile , configfile ) ;
loop . rehash_download_busy = 0 ;
if ( ret < 0 )
{
config_load_failed ( ) ;
return - 1 ;
}
return 1 ;
}
int is_config_read_finished ( void )
{
ConfigResource * rs ;
if ( loop . rehash_download_busy )
return 0 ;
for ( rs = config_resources ; rs ; rs = rs - > next )
{
if ( rs - > type & RESOURCE_DLQUEUED )
{
//config_status("Waiting for %s...", rs->url);
return 0 ;
}
}
return 1 ;
}
int config_test ( void )
{
char * old_pid_file = NULL ;
if ( loop . config_load_failed )
{
/* An error was already printed to the user.
* This happens in case of a failed loaded remote URL
*/
config_load_failed ( ) ;
return - 1 ;
}
config_status ( " Testing IRCd configuration.. " ) ;
2023-05-05 22:12:01 +00:00
loop . config_status = CONFIG_STATUS_TEST ;
2022-01-15 05:16:34 +00:00
2020-03-29 09:16:53 +00:00
memset ( & tempiConf , 0 , sizeof ( iConf ) ) ;
memset ( & settings , 0 , sizeof ( settings ) ) ;
memset ( & requiredstuff , 0 , sizeof ( requiredstuff ) ) ;
memset ( & nicklengths , 0 , sizeof ( nicklengths ) ) ;
config_setdefaultsettings ( & tempiConf ) ;
clicap_pre_rehash ( ) ;
2022-01-15 05:16:34 +00:00
log_pre_rehash ( ) ;
2020-03-29 09:16:53 +00:00
free_config_defines ( ) ;
2022-01-15 05:16:34 +00:00
if ( ! config_loadmodules ( ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_load_failed ( ) ;
return - 1 ;
}
2023-05-05 22:12:01 +00:00
loop . config_status = CONFIG_STATUS_POSTTEST ;
2022-01-15 05:16:34 +00:00
preprocessor_resolve_conditionals_all ( PREPROCESSOR_PHASE_MODULE ) ;
if ( ! config_test_all ( ) )
{
config_error ( " IRCd configuration failed to pass testing " ) ;
config_load_failed ( ) ;
return - 1 ;
}
2023-05-05 22:12:01 +00:00
loop . config_status = CONFIG_STATUS_PRE_INIT ;
2022-01-15 05:16:34 +00:00
callbacks_switchover ( ) ;
efunctions_switchover ( ) ;
set_targmax_defaults ( ) ;
set_security_group_defaults ( ) ;
if ( loop . rehashing )
{
Hook * h ;
safe_strdup ( old_pid_file , conf_files - > pid_file ) ;
unrealdns_delasyncconnects ( ) ;
config_rehash ( ) ;
/* Notify permanent modules of the rehash */
for ( h = Hooks [ HOOKTYPE_REHASH ] ; h ; h = h - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! h - > owner )
continue ;
if ( ! ( h - > owner - > options & MOD_OPT_PERM ) )
continue ;
( * ( h - > func . intfunc ) ) ( ) ;
2020-03-29 09:16:53 +00:00
}
2023-05-05 22:12:01 +00:00
/* Last step: */
Unload_all_loaded_modules ( ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
config_pre_run_log ( ) ;
2023-05-05 22:12:01 +00:00
loop . config_status = CONFIG_STATUS_INIT ;
2022-01-15 05:16:34 +00:00
Init_all_testing_modules ( ) ;
2023-05-05 22:12:01 +00:00
loop . config_status = CONFIG_STATUS_RUN_CONFIG ;
2022-01-15 05:16:34 +00:00
if ( config_run_blocks ( ) < 0 )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error ( " Bad case of config errors. Server will now die. This really shouldn't happen " ) ;
2020-03-29 09:16:53 +00:00
# ifdef _WIN32
2022-01-15 05:16:34 +00:00
if ( ! loop . rehashing )
2020-03-29 09:16:53 +00:00
win_error ( ) ;
# endif
2022-01-15 05:16:34 +00:00
abort ( ) ;
}
applymeblock ( ) ;
if ( old_pid_file & & strcmp ( old_pid_file , conf_files - > pid_file ) )
{
write_pidfile ( ) ;
unlink ( old_pid_file ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
safe_free ( old_pid_file ) ;
2020-03-29 09:16:53 +00:00
config_free ( conf ) ;
conf = NULL ;
2022-01-15 05:16:34 +00:00
if ( loop . rehashing )
2020-03-29 09:16:53 +00:00
{
2023-05-05 22:12:01 +00:00
/* loop.config_status = CONFIG_STATUS_LOAD is done by module_loadall() */
2020-03-29 09:16:53 +00:00
module_loadall ( ) ;
2022-01-15 05:16:34 +00:00
RunHook ( HOOKTYPE_REHASH_COMPLETE ) ;
2020-03-29 09:16:53 +00:00
}
2023-05-05 22:12:01 +00:00
loop . config_status = CONFIG_STATUS_POSTLOAD ;
2020-03-29 09:16:53 +00:00
postconf ( ) ;
2022-01-15 05:16:34 +00:00
unreal_log ( ULOG_INFO , " config " , " CONFIG_LOADED " , NULL , " Configuration loaded " ) ;
2020-05-29 02:06:50 +00:00
unload_all_unused_mtag_handlers ( ) ;
2020-03-29 09:16:53 +00:00
return 0 ;
}
2022-01-15 05:16:34 +00:00
void config_parse_and_queue_urls ( ConfigEntry * ce )
{
for ( ; ce ; ce = ce - > next )
{
if ( loop . config_load_failed )
break ;
if ( ce - > name & & ! strcmp ( ce - > name , " include " ) )
continue ; /* handled elsewhere */
if ( ce - > value & & ! ce - > escaped & & url_is_valid ( ce - > value ) )
add_config_resource ( ce - > value , 0 , ce ) ;
if ( ce - > items )
config_parse_and_queue_urls ( ce - > items ) ;
}
}
2020-03-29 09:16:53 +00:00
/**
2022-01-15 05:16:34 +00:00
* Read configuration file into ConfigEntry items and add it to the ' conf '
* list . This checks the file for parse errors , but doesn ' t do much
* otherwise . Only : module blacklist checking and checking for " include "
* items to see if we need to read and parse more configuration files
* that are included from this one .
2020-03-29 09:16:53 +00:00
*
2022-01-15 05:16:34 +00:00
* One _must_ call add_config_resource ( ) before calling config_read_file ( ) .
* This way , include recursion may be detected and reported to the user
* as an error instead of causing the IRCd to hang in an infinite
* recursion , eat up memory , and eventually overflow its stack ; - ) .
2020-03-29 09:16:53 +00:00
*
* @ param filename the file where the conf may be read from
2022-01-15 05:16:34 +00:00
* @ param display_name The path or URL used to refer to this file .
2020-03-29 09:16:53 +00:00
* ( mostly to support remote includes ' URIs for recursive include detection ) .
* @ return 1 on success , a negative number on error
*/
2022-01-15 05:16:34 +00:00
int config_read_file ( const char * filename , const char * display_name )
2020-03-29 09:16:53 +00:00
{
ConfigFile * cfptr , * cfptr2 , * * cfptr3 ;
ConfigEntry * ce ;
2022-01-15 05:16:34 +00:00
ConfigResource * rs ;
2020-03-29 09:16:53 +00:00
int ret ;
int counter ;
if ( config_verbose > 0 )
config_status ( " Loading config file %s .. " , filename ) ;
need_operclass_permissions_upgrade = 0 ;
2022-01-15 05:16:34 +00:00
/* Check if we're accidentally including a file a second
2020-03-29 09:16:53 +00:00
* time . We should expect to find one entry in this list : the
* entry for our current file .
2022-01-15 05:16:34 +00:00
* Note that no user should be able to trigger this , this
* can only happen if we have buggy code somewhere .
2020-03-29 09:16:53 +00:00
*/
counter = 0 ;
2022-01-15 05:16:34 +00:00
for ( rs = config_resources ; rs ; rs = rs - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
# ifndef _WIN32
if ( rs - > file & & ! strcmp ( filename , rs - > file ) )
# else
if ( rs - > file & & ! strcasecmp ( filename , rs - > file ) )
# endif
2020-03-29 09:16:53 +00:00
{
counter + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
if ( rs - > url & & ! strcmp ( display_name , rs - > url ) )
2020-03-29 09:16:53 +00:00
{
counter + + ;
continue ;
}
}
2022-01-15 05:16:34 +00:00
if ( counter > 1 )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
unreal_log ( ULOG_ERROR , " config " , " CONFIG_BUG_DUPLICATE_RESOURCE " , NULL ,
" [BUG] Config file $file has been loaded $counter times. "
" This should not happen. Someone forgot to call "
" add_config_resource() or check its return value! " ,
log_data_string ( " file " , filename ) ,
log_data_integer ( " counter " , counter ) ) ;
2020-03-29 09:16:53 +00:00
return - 1 ;
}
/* end include recursion checking code */
2022-01-15 05:16:34 +00:00
if ( ( cfptr = config_load ( filename , display_name ) ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cfptr3 = & conf , cfptr2 = conf ; cfptr2 ; cfptr2 = cfptr2 - > next )
cfptr3 = & cfptr2 - > next ;
2020-03-29 09:16:53 +00:00
* cfptr3 = cfptr ;
if ( config_verbose > 1 )
config_status ( " Loading module blacklist in %s " , filename ) ;
2022-01-15 05:16:34 +00:00
preprocessor_resolve_conditionals_ce ( & cfptr - > items , PREPROCESSOR_PHASE_INITIAL ) ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
for ( ce = cfptr - > items ; ce ; ce = ce - > next )
if ( ! strcmp ( ce - > name , " blacklist-module " ) )
2020-03-29 09:16:53 +00:00
_test_blacklist_module ( cfptr , ce ) ;
2023-05-05 22:12:01 +00:00
preprocessor_resolve_conditionals_ce ( & cfptr - > items , PREPROCESSOR_PHASE_SECONDARY ) ;
2022-01-15 05:16:34 +00:00
/* Load urls */
config_parse_and_queue_urls ( cfptr - > items ) ;
if ( loop . config_load_failed ) /* something bad happened while processing urls */
return - 1 ;
2020-03-29 09:16:53 +00:00
/* Load includes */
if ( config_verbose > 1 )
config_status ( " Searching through %s for include files.. " , filename ) ;
2022-01-15 05:16:34 +00:00
for ( ce = cfptr - > items ; ce ; ce = ce - > next )
{
if ( ! strcmp ( ce - > name , " include " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ce - > conditional_config )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%d: Currently you cannot have an 'include' statement "
" within an @if block, sorry. However, you CAN do it the other "
" way around, that is: put the @if within the included file itself. " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return - 1 ;
}
ret = _conf_include ( cfptr , ce ) ;
if ( ret < 0 )
return ret ;
}
2022-01-15 05:16:34 +00:00
}
2020-03-29 09:16:53 +00:00
return 1 ;
}
else
{
2022-01-15 05:16:34 +00:00
unreal_log ( ULOG_ERROR , " config " , " CONFIG_LOAD_FILE_FAILED " , NULL ,
" Could not load configuration file: $resource " ,
log_data_string ( " resource " , display_name ) ,
log_data_string ( " filename " , filename ) ) ;
2020-03-29 09:16:53 +00:00
# ifdef _WIN32
if ( ! strcmp ( filename , " conf/unrealircd.conf " ) )
{
if ( file_exists ( " unrealircd.conf " ) )
{
config_error ( " Note that 'unrealircd.conf' now belongs in the 'conf' subdirectory! (So move it to there) " ) ;
} else {
config_error ( " New to UnrealIRCd? Be sure to read https://www.unrealircd.org/docs/Installing_%%28Windows%%29 " ) ;
}
}
# endif
return - 1 ;
}
}
/** Remove all TKL's that were added by the config file(s).
* This is done after config passed testing and right before
* adding the ( new ) entries .
*/
void remove_config_tkls ( void )
{
TKL * tk , * tk_next ;
int index , index2 ;
/* IP hashed TKL list */
for ( index = 0 ; index < TKLIPHASHLEN1 ; index + + )
{
for ( index2 = 0 ; index2 < TKLIPHASHLEN2 ; index2 + + )
{
for ( tk = tklines_ip_hash [ index ] [ index2 ] ; tk ; tk = tk_next )
{
tk_next = tk - > next ;
if ( tk - > flags & TKL_FLAG_CONFIG )
tkl_del_line ( tk ) ;
}
}
}
/* Generic TKL list */
for ( index = 0 ; index < TKLISTLEN ; index + + )
{
for ( tk = tklines [ index ] ; tk ; tk = tk_next )
{
tk_next = tk - > next ;
if ( tk - > flags & TKL_FLAG_CONFIG )
tkl_del_line ( tk ) ;
}
}
}
2022-01-15 05:16:34 +00:00
void config_rehash ( )
2020-03-29 09:16:53 +00:00
{
ConfigItem_oper * oper_ptr ;
ConfigItem_class * class_ptr ;
ConfigItem_ulines * uline_ptr ;
ConfigItem_allow * allow_ptr ;
ConfigItem_ban * ban_ptr ;
ConfigItem_link * link_ptr ;
ConfigItem_listen * listen_ptr ;
ConfigItem_tld * tld_ptr ;
ConfigItem_vhost * vhost_ptr ;
ConfigItem_deny_channel * deny_channel_ptr ;
ConfigItem_allow_channel * allow_channel_ptr ;
ConfigItem_admin * admin_ptr ;
ConfigItem_deny_version * deny_version_ptr ;
ConfigItem_alias * alias_ptr ;
ConfigItem_help * help_ptr ;
ConfigItem_offchans * of_ptr ;
ConfigItem_sni * sni ;
OperStat * os_ptr ;
ListStruct * next , * next2 ;
SpamExcept * spamex_ptr ;
USE_BAN_VERSION = 0 ;
for ( admin_ptr = conf_admin ; admin_ptr ; admin_ptr = ( ConfigItem_admin * ) next )
{
next = ( ListStruct * ) admin_ptr - > next ;
safe_free ( admin_ptr - > line ) ;
DelListItem ( admin_ptr , conf_admin ) ;
safe_free ( admin_ptr ) ;
}
for ( oper_ptr = conf_oper ; oper_ptr ; oper_ptr = ( ConfigItem_oper * ) next )
{
SWhois * s , * s_next ;
next = ( ListStruct * ) oper_ptr - > next ;
safe_free ( oper_ptr - > name ) ;
safe_free ( oper_ptr - > snomask ) ;
safe_free ( oper_ptr - > operclass ) ;
safe_free ( oper_ptr - > vhost ) ;
Auth_FreeAuthConfig ( oper_ptr - > auth ) ;
2022-11-20 04:12:40 +00:00
free_security_group ( oper_ptr - > match ) ;
2020-03-29 09:16:53 +00:00
DelListItem ( oper_ptr , conf_oper ) ;
for ( s = oper_ptr - > swhois ; s ; s = s_next )
{
s_next = s - > next ;
safe_free ( s - > line ) ;
safe_free ( s - > setby ) ;
safe_free ( s ) ;
}
safe_free ( oper_ptr ) ;
}
for ( link_ptr = conf_link ; link_ptr ; link_ptr = ( ConfigItem_link * ) next )
{
next = ( ListStruct * ) link_ptr - > next ;
if ( link_ptr - > refcount = = 0 )
{
delete_linkblock ( link_ptr ) ;
}
else
{
link_ptr - > flag . temporary = 1 ;
}
}
for ( class_ptr = conf_class ; class_ptr ; class_ptr = ( ConfigItem_class * ) next )
{
next = ( ListStruct * ) class_ptr - > next ;
if ( class_ptr - > flag . permanent = = 1 )
continue ;
class_ptr - > flag . temporary = 1 ;
/* We'll wipe it out when it has no clients */
if ( ! class_ptr - > clients & & ! class_ptr - > xrefcount )
{
delete_classblock ( class_ptr ) ;
}
}
for ( uline_ptr = conf_ulines ; uline_ptr ; uline_ptr = ( ConfigItem_ulines * ) next )
{
next = ( ListStruct * ) uline_ptr - > next ;
/* We'll wipe it out when it has no clients */
safe_free ( uline_ptr - > servername ) ;
DelListItem ( uline_ptr , conf_ulines ) ;
safe_free ( uline_ptr ) ;
}
for ( allow_ptr = conf_allow ; allow_ptr ; allow_ptr = ( ConfigItem_allow * ) next )
{
next = ( ListStruct * ) allow_ptr - > next ;
2022-11-20 04:12:40 +00:00
free_security_group ( allow_ptr - > match ) ;
2020-03-29 09:16:53 +00:00
Auth_FreeAuthConfig ( allow_ptr - > auth ) ;
DelListItem ( allow_ptr , conf_allow ) ;
safe_free ( allow_ptr ) ;
}
/* Free ban realname { }, ban server { } and ban version { } */
for ( ban_ptr = conf_ban ; ban_ptr ; ban_ptr = ( ConfigItem_ban * ) next )
{
next = ( ListStruct * ) ban_ptr - > next ;
if ( ban_ptr - > flag . type2 = = CONF_BAN_TYPE_CONF | | ban_ptr - > flag . type2 = = CONF_BAN_TYPE_TEMPORARY )
{
safe_free ( ban_ptr - > mask ) ;
safe_free ( ban_ptr - > reason ) ;
DelListItem ( ban_ptr , conf_ban ) ;
safe_free ( ban_ptr ) ;
}
}
for ( listen_ptr = conf_listen ; listen_ptr ; listen_ptr = listen_ptr - > next )
{
2022-04-03 15:09:29 +00:00
if ( ! ( listen_ptr - > options & LISTENER_CONTROL ) )
listen_ptr - > flag . temporary = 1 ;
2020-03-29 09:16:53 +00:00
}
for ( tld_ptr = conf_tld ; tld_ptr ; tld_ptr = ( ConfigItem_tld * ) next )
{
next = ( ListStruct * ) tld_ptr - > next ;
safe_free ( tld_ptr - > motd_file ) ;
safe_free ( tld_ptr - > rules_file ) ;
safe_free ( tld_ptr - > smotd_file ) ;
safe_free ( tld_ptr - > opermotd_file ) ;
safe_free ( tld_ptr - > botmotd_file ) ;
free_motd ( & tld_ptr - > motd ) ;
free_motd ( & tld_ptr - > rules ) ;
free_motd ( & tld_ptr - > smotd ) ;
free_motd ( & tld_ptr - > opermotd ) ;
free_motd ( & tld_ptr - > botmotd ) ;
2022-11-20 04:12:40 +00:00
free_security_group ( tld_ptr - > match ) ;
2020-03-29 09:16:53 +00:00
DelListItem ( tld_ptr , conf_tld ) ;
safe_free ( tld_ptr ) ;
}
for ( vhost_ptr = conf_vhost ; vhost_ptr ; vhost_ptr = ( ConfigItem_vhost * ) next )
{
SWhois * s , * s_next ;
next = ( ListStruct * ) vhost_ptr - > next ;
safe_free ( vhost_ptr - > login ) ;
Auth_FreeAuthConfig ( vhost_ptr - > auth ) ;
safe_free ( vhost_ptr - > virthost ) ;
safe_free ( vhost_ptr - > virtuser ) ;
2022-11-20 04:12:40 +00:00
free_security_group ( vhost_ptr - > match ) ;
2020-03-29 09:16:53 +00:00
for ( s = vhost_ptr - > swhois ; s ; s = s_next )
{
s_next = s - > next ;
safe_free ( s - > line ) ;
safe_free ( s - > setby ) ;
safe_free ( s ) ;
}
DelListItem ( vhost_ptr , conf_vhost ) ;
safe_free ( vhost_ptr ) ;
}
remove_config_tkls ( ) ;
for ( deny_version_ptr = conf_deny_version ; deny_version_ptr ; deny_version_ptr = ( ConfigItem_deny_version * ) next ) {
next = ( ListStruct * ) deny_version_ptr - > next ;
safe_free ( deny_version_ptr - > mask ) ;
safe_free ( deny_version_ptr - > version ) ;
safe_free ( deny_version_ptr - > flags ) ;
DelListItem ( deny_version_ptr , conf_deny_version ) ;
safe_free ( deny_version_ptr ) ;
}
for ( deny_channel_ptr = conf_deny_channel ; deny_channel_ptr ; deny_channel_ptr = ( ConfigItem_deny_channel * ) next )
{
next = ( ListStruct * ) deny_channel_ptr - > next ;
safe_free ( deny_channel_ptr - > redirect ) ;
safe_free ( deny_channel_ptr - > channel ) ;
safe_free ( deny_channel_ptr - > reason ) ;
safe_free ( deny_channel_ptr - > class ) ;
DelListItem ( deny_channel_ptr , conf_deny_channel ) ;
2022-11-20 04:12:40 +00:00
free_security_group ( deny_channel_ptr - > match ) ;
2020-03-29 09:16:53 +00:00
safe_free ( deny_channel_ptr ) ;
}
for ( allow_channel_ptr = conf_allow_channel ; allow_channel_ptr ; allow_channel_ptr = ( ConfigItem_allow_channel * ) next )
{
next = ( ListStruct * ) allow_channel_ptr - > next ;
safe_free ( allow_channel_ptr - > channel ) ;
safe_free ( allow_channel_ptr - > class ) ;
DelListItem ( allow_channel_ptr , conf_allow_channel ) ;
2022-11-20 04:12:40 +00:00
free_security_group ( allow_channel_ptr - > match ) ;
2020-03-29 09:16:53 +00:00
safe_free ( allow_channel_ptr ) ;
}
if ( conf_drpass )
{
Auth_FreeAuthConfig ( conf_drpass - > restartauth ) ;
conf_drpass - > restartauth = NULL ;
Auth_FreeAuthConfig ( conf_drpass - > dieauth ) ;
conf_drpass - > dieauth = NULL ;
safe_free ( conf_drpass ) ;
}
for ( alias_ptr = conf_alias ; alias_ptr ; alias_ptr = ( ConfigItem_alias * ) next ) {
RealCommand * cmptr = find_command ( alias_ptr - > alias , 0 ) ;
ConfigItem_alias_format * fmt ;
next = ( ListStruct * ) alias_ptr - > next ;
safe_free ( alias_ptr - > nick ) ;
if ( cmptr )
CommandDelX ( NULL , cmptr ) ;
safe_free ( alias_ptr - > alias ) ;
if ( alias_ptr - > format & & ( alias_ptr - > type = = ALIAS_COMMAND ) ) {
for ( fmt = ( ConfigItem_alias_format * ) alias_ptr - > format ; fmt ; fmt = ( ConfigItem_alias_format * ) next2 )
{
next2 = ( ListStruct * ) fmt - > next ;
safe_free ( fmt - > format ) ;
safe_free ( fmt - > nick ) ;
safe_free ( fmt - > parameters ) ;
unreal_delete_match ( fmt - > expr ) ;
DelListItem ( fmt , alias_ptr - > format ) ;
safe_free ( fmt ) ;
}
}
DelListItem ( alias_ptr , conf_alias ) ;
safe_free ( alias_ptr ) ;
}
for ( help_ptr = conf_help ; help_ptr ; help_ptr = ( ConfigItem_help * ) next ) {
MOTDLine * text ;
next = ( ListStruct * ) help_ptr - > next ;
safe_free ( help_ptr - > command ) ;
while ( help_ptr - > text ) {
text = help_ptr - > text - > next ;
safe_free ( help_ptr - > text - > line ) ;
safe_free ( help_ptr - > text ) ;
help_ptr - > text = text ;
}
DelListItem ( help_ptr , conf_help ) ;
safe_free ( help_ptr ) ;
}
for ( os_ptr = iConf . allow_user_stats_ext ; os_ptr ; os_ptr = ( OperStat * ) next )
{
next = ( ListStruct * ) os_ptr - > next ;
safe_free ( os_ptr - > flag ) ;
safe_free ( os_ptr ) ;
}
iConf . allow_user_stats_ext = NULL ;
for ( spamex_ptr = iConf . spamexcept ; spamex_ptr ; spamex_ptr = ( SpamExcept * ) next )
{
next = ( ListStruct * ) spamex_ptr - > next ;
safe_free ( spamex_ptr ) ;
}
iConf . spamexcept = NULL ;
for ( of_ptr = conf_offchans ; of_ptr ; of_ptr = ( ConfigItem_offchans * ) next )
{
next = ( ListStruct * ) of_ptr - > next ;
safe_free ( of_ptr - > topic ) ;
safe_free ( of_ptr ) ;
}
conf_offchans = NULL ;
/* Free sni { } blocks */
for ( sni = conf_sni ; sni ; sni = ( ConfigItem_sni * ) next )
{
next = ( ListStruct * ) sni - > next ;
SSL_CTX_free ( sni - > ssl_ctx ) ;
free_tls_options ( sni - > tls_options ) ;
safe_free ( sni - > name ) ;
safe_free ( sni ) ;
}
conf_sni = NULL ;
free_conf_channelmodes ( & iConf . modes_on_join ) ;
/*
reset conf_files - - should this be in its own function ? no , because
it ' s only used here
*/
safe_free ( conf_files - > motd_file ) ;
safe_free ( conf_files - > smotd_file ) ;
safe_free ( conf_files - > opermotd_file ) ;
safe_free ( conf_files - > svsmotd_file ) ;
safe_free ( conf_files - > botmotd_file ) ;
safe_free ( conf_files - > rules_file ) ;
safe_free ( conf_files - > pid_file ) ;
safe_free ( conf_files - > tune_file ) ;
/*
Don ' t free conf_files - > pid_file here ; the old value is used to determine if
the pidfile location has changed and write_pidfile ( ) needs to be called
again .
*/
safe_free ( conf_files ) ;
conf_files = NULL ;
}
int config_post_test ( )
{
# define Error(x) { config_error((x)); errors++; }
int errors = 0 ;
Hook * h ;
if ( ! requiredstuff . conf_me )
Error ( " me {} block is missing " ) ;
if ( ! requiredstuff . conf_admin )
Error ( " admin {} block is missing " ) ;
if ( ! requiredstuff . conf_listen )
Error ( " listen {} block is missing " ) ;
if ( ! settings . has_kline_address )
Error ( " set::kline-address is missing " ) ;
if ( ! settings . has_default_server )
Error ( " set::default-server is missing " ) ;
if ( ! settings . has_network_name )
Error ( " set::network-name is missing " ) ;
if ( ! settings . has_help_channel )
Error ( " set::help-channel is missing " ) ;
if ( nicklengths . min > nicklengths . max )
Error ( " set::nick-length is smaller than set::min-nick-length " ) ;
for ( h = Hooks [ HOOKTYPE_CONFIGPOSTTEST ] ; h ; h = h - > next )
{
int value , errs = 0 ;
if ( h - > owner & & ! ( h - > owner - > flags & MODFLAG_TESTING ) & &
! ( h - > owner - > options & MOD_OPT_PERM ) )
continue ;
value = ( * ( h - > func . intfunc ) ) ( & errs ) ;
if ( value = = - 1 )
{
errors + = errs ;
break ;
}
if ( value = = - 2 )
errors + = errs ;
}
return errors ;
}
2022-01-15 05:16:34 +00:00
/** Make the "read" config the "live" config */
void config_switchover ( void )
{
free_iConf ( & iConf ) ;
memcpy ( & iConf , & tempiConf , sizeof ( iConf ) ) ;
memset ( & tempiConf , 0 , sizeof ( tempiConf ) ) ;
log_blocks_switchover ( ) ;
}
2022-04-03 15:09:29 +00:00
/** Priority of config blocks during CONFIG_TEST stage */
static const char * config_test_priority_blocks [ ] =
{
" me " ,
" secret " ,
" log " , /* "log" needs to be before "set" in CONFIG_TEST */
" set " ,
" class " ,
} ;
/** Priority of config blocks during CONFIG_RUN stage */
static const char * config_run_priority_blocks [ ] =
{
" me " ,
" secret " ,
" set " ,
" log " , /* "log" needs to be after "set" in CONFIG_RUN */
" class " ,
} ;
int config_test_blocks ( )
2020-03-29 09:16:53 +00:00
{
ConfigEntry * ce ;
ConfigFile * cfptr ;
ConfigCommand * cc ;
int errors = 0 ;
2022-04-03 15:09:29 +00:00
int i ;
2020-03-29 09:16:53 +00:00
Hook * h ;
2022-04-03 15:09:29 +00:00
invalid_snomasks_encountered = 0 ;
2020-03-29 09:16:53 +00:00
2022-04-03 15:09:29 +00:00
/* Stage 1: first the priority blocks, in the order as specified
* in config_test_priority_blocks [ ]
*/
for ( i = 0 ; i < ARRAY_SIZEOF ( config_test_priority_blocks ) ; i + + )
2020-03-29 09:16:53 +00:00
{
2022-04-03 15:09:29 +00:00
const char * config_block = config_test_priority_blocks [ i ] ;
cc = config_binary_search ( config_block ) ;
if ( ! cc )
abort ( ) ; /* internal fuckup */
for ( cfptr = conf ; cfptr ; cfptr = cfptr - > next )
2020-03-29 09:16:53 +00:00
{
2022-04-03 15:09:29 +00:00
if ( config_verbose > 1 )
config_status ( " Running %s " , cfptr - > filename ) ;
for ( ce = cfptr - > items ; ce ; ce = ce - > next )
2020-03-29 09:16:53 +00:00
{
2022-04-03 15:09:29 +00:00
if ( ! strcmp ( ce - > name , config_block ) )
{
int n = cc - > testfunc ( cfptr , ce ) ;
errors + = n ;
if ( ! strcmp ( config_block , " secret " ) & & ( n = = 0 ) )
{
/* Yeah special case: secret { } blocks we run
* immediately here .
*/
_conf_secret ( cfptr , ce ) ;
}
}
2020-03-29 09:16:53 +00:00
}
}
}
2022-04-03 15:09:29 +00:00
/* Stage 2: now all the other config blocks */
2022-01-15 05:16:34 +00:00
for ( cfptr = conf ; cfptr ; cfptr = cfptr - > next )
2020-03-29 09:16:53 +00:00
{
if ( config_verbose > 1 )
2022-01-15 05:16:34 +00:00
config_status ( " Running %s " , cfptr - > filename ) ;
for ( ce = cfptr - > items ; ce ; ce = ce - > next )
2020-03-29 09:16:53 +00:00
{
2022-04-03 15:09:29 +00:00
char skip = 0 ;
for ( i = 0 ; i < ARRAY_SIZEOF ( config_test_priority_blocks ) ; i + + )
2020-03-29 09:16:53 +00:00
{
2022-04-03 15:09:29 +00:00
if ( ! strcmp ( ce - > name , config_test_priority_blocks [ i ] ) )
2020-03-29 09:16:53 +00:00
{
2022-04-03 15:09:29 +00:00
skip = 1 ;
break ;
2020-03-29 09:16:53 +00:00
}
}
2022-04-03 15:09:29 +00:00
if ( skip )
2020-03-29 09:16:53 +00:00
continue ;
2022-04-03 15:09:29 +00:00
2022-01-15 05:16:34 +00:00
if ( ( cc = config_binary_search ( ce - > name ) ) ) {
2020-03-29 09:16:53 +00:00
if ( cc - > testfunc )
errors + = ( cc - > testfunc ( cfptr , ce ) ) ;
}
else
{
int used = 0 ;
for ( h = Hooks [ HOOKTYPE_CONFIGTEST ] ; h ; h = h - > next )
{
int value , errs = 0 ;
if ( h - > owner & & ! ( h - > owner - > flags & MODFLAG_TESTING )
& & ! ( h - > owner - > options & MOD_OPT_PERM ) )
continue ;
value = ( * ( h - > func . intfunc ) ) ( cfptr , ce , CONFIG_MAIN , & errs ) ;
if ( value = = 2 )
used = 1 ;
if ( value = = 1 )
{
used = 1 ;
break ;
}
if ( value = = - 1 )
{
used = 1 ;
errors + = errs ;
break ;
}
if ( value = = - 2 )
{
used = 1 ;
errors + = errs ;
}
}
if ( ! used )
{
config_error ( " %s:%i: unknown directive %s " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ,
ce - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
2022-01-15 05:16:34 +00:00
if ( strchr ( ce - > name , ' : ' ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " You cannot use :: in a directive, you have to write them out. "
2021-06-19 15:52:51 +00:00
" For example 'set::auto-join #something' needs to be written as: "
" set { auto-join \" #something \" ; } " ) ;
2020-03-29 09:16:53 +00:00
config_error ( " See also https://www.unrealircd.org/docs/Set_block#Syntax_used_in_this_documentation " ) ;
}
}
}
}
}
2022-04-03 15:09:29 +00:00
2020-03-29 09:16:53 +00:00
errors + = config_post_test ( ) ;
2022-04-03 15:09:29 +00:00
2020-03-29 09:16:53 +00:00
if ( errors > 0 )
{
config_error ( " %i errors encountered " , errors ) ;
}
2022-01-15 05:16:34 +00:00
if ( invalid_snomasks_encountered )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error ( " It seems your set::snomask-on-oper and/or oper::snomask needs to be updated. Are you perhaps upgrading from an older version to UnrealIRCd 6? " ) ;
config_error ( " See https://www.unrealircd.org/docs/Upgrading_from_5.x#Update_your_snomasks " ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
2020-03-29 09:16:53 +00:00
return ( errors > 0 ? - 1 : 1 ) ;
}
2022-04-03 15:09:29 +00:00
int config_run_blocks ( void )
{
ConfigEntry * ce ;
ConfigFile * cfptr ;
ConfigCommand * cc ;
int errors = 0 ;
int i ;
Hook * h ;
ConfigItem_allow * allow ;
/* Stage 1: first the priority blocks, in the order as specified
* in config_run_priority_blocks [ ]
*/
for ( i = 0 ; i < ARRAY_SIZEOF ( config_run_priority_blocks ) ; i + + )
{
const char * config_block = config_run_priority_blocks [ i ] ;
cc = config_binary_search ( config_block ) ;
if ( ! cc )
abort ( ) ; /* internal fuckup */
if ( ! strcmp ( config_block , " secret " ) )
continue ; /* yeah special case, we already processed the run part in test for these */
for ( cfptr = conf ; cfptr ; cfptr = cfptr - > next )
{
if ( config_verbose > 1 )
config_status ( " Running %s " , cfptr - > filename ) ;
for ( ce = cfptr - > items ; ce ; ce = ce - > next )
{
if ( ! strcmp ( ce - > name , config_block ) )
{
if ( cc - > conffunc ( cfptr , ce ) < 0 )
errors + + ;
}
}
}
}
/* Stage 2: now all the other config blocks */
for ( cfptr = conf ; cfptr ; cfptr = cfptr - > next )
{
if ( config_verbose > 1 )
config_status ( " Running %s " , cfptr - > filename ) ;
for ( ce = cfptr - > items ; ce ; ce = ce - > next )
{
char skip = 0 ;
for ( i = 0 ; i < ARRAY_SIZEOF ( config_run_priority_blocks ) ; i + + )
{
if ( ! strcmp ( ce - > name , config_run_priority_blocks [ i ] ) )
{
skip = 1 ;
break ;
}
}
if ( skip )
continue ;
if ( ( cc = config_binary_search ( ce - > name ) ) ) {
if ( ( cc - > conffunc ) & & ( cc - > conffunc ( cfptr , ce ) < 0 ) )
errors + + ;
}
else
{
int value ;
for ( h = Hooks [ HOOKTYPE_CONFIGRUN ] ; h ; h = h - > next )
{
value = ( * ( h - > func . intfunc ) ) ( cfptr , ce , CONFIG_MAIN ) ;
if ( value = = 1 )
break ;
}
}
}
}
close_unbound_listeners ( ) ;
listen_cleanup ( ) ;
close_unbound_listeners ( ) ;
loop . do_bancheck = 1 ;
config_switchover ( ) ;
update_throttling_timer_settings ( ) ;
/* initialize conf_files with defaults if the block isn't set: */
if ( ! conf_files )
_conf_files ( NULL , NULL ) ;
if ( errors > 0 )
{
config_error ( " %i fatal errors encountered " , errors ) ;
}
return ( errors > 0 ? - 1 : 1 ) ;
}
2020-03-29 09:16:53 +00:00
/*
* Service functions
*/
2022-01-15 05:16:34 +00:00
ConfigItem_alias * find_alias ( const char * name )
2020-03-29 09:16:53 +00:00
{
ConfigItem_alias * e ;
if ( ! name )
return NULL ;
for ( e = conf_alias ; e ; e = e - > next )
{
if ( ! strcasecmp ( e - > alias , name ) )
return e ;
}
return NULL ;
}
2022-01-15 05:16:34 +00:00
ConfigItem_class * find_class ( const char * name )
2020-03-29 09:16:53 +00:00
{
ConfigItem_class * e ;
if ( ! name )
return NULL ;
for ( e = conf_class ; e ; e = e - > next )
{
if ( ! strcmp ( name , e - > name ) )
return e ;
}
return NULL ;
}
2022-01-15 05:16:34 +00:00
ConfigItem_oper * find_oper ( const char * name )
2020-03-29 09:16:53 +00:00
{
ConfigItem_oper * e ;
if ( ! name )
return NULL ;
for ( e = conf_oper ; e ; e = e - > next )
{
if ( ! strcmp ( name , e - > name ) )
return e ;
}
return NULL ;
}
2022-01-15 05:16:34 +00:00
ConfigItem_operclass * find_operclass ( const char * name )
2020-03-29 09:16:53 +00:00
{
ConfigItem_operclass * e ;
if ( ! name )
return NULL ;
for ( e = conf_operclass ; e ; e = e - > next )
{
if ( ! strcmp ( name , e - > classStruct - > name ) )
return e ;
}
return NULL ;
}
2022-01-15 05:16:34 +00:00
int count_oper_sessions ( const char * name )
2020-03-29 09:16:53 +00:00
{
int count = 0 ;
Client * client ;
list_for_each_entry ( client , & oper_list , special_node )
{
if ( client - > user - > operlogin ! = NULL & & ! strcmp ( client - > user - > operlogin , name ) )
count + + ;
}
return count ;
}
2022-04-03 15:09:29 +00:00
ConfigItem_listen * find_listen ( const char * ipmask , int port , SocketType socket_type )
2020-03-29 09:16:53 +00:00
{
ConfigItem_listen * e ;
if ( ! ipmask )
return NULL ;
for ( e = conf_listen ; e ; e = e - > next )
2022-04-03 15:09:29 +00:00
{
if ( e - > socket_type ! = socket_type )
continue ;
if ( e - > socket_type = = SOCKET_TYPE_UNIX )
{
if ( ! strcmp ( e - > file , ipmask ) )
return e ;
} else
{
if ( ( e - > socket_type = = socket_type ) & & ( e - > port = = port ) & & ! strcmp ( e - > ip , ipmask ) )
return e ;
}
}
2020-03-29 09:16:53 +00:00
return NULL ;
}
/** Find an SNI match.
* @ param name The hostname to look for ( eg : irc . xyz . com ) .
*/
2022-01-15 05:16:34 +00:00
ConfigItem_sni * find_sni ( const char * name )
2020-03-29 09:16:53 +00:00
{
ConfigItem_sni * e ;
if ( ! name )
return NULL ;
for ( e = conf_sni ; e ; e = e - > next )
{
if ( match_simple ( e - > name , name ) )
return e ;
}
return NULL ;
}
2022-01-15 05:16:34 +00:00
ConfigItem_ulines * find_uline ( const char * host )
2020-03-29 09:16:53 +00:00
{
ConfigItem_ulines * ulines ;
if ( ! host )
return NULL ;
for ( ulines = conf_ulines ; ulines ; ulines = ulines - > next )
{
if ( ! strcasecmp ( host , ulines - > servername ) )
return ulines ;
}
return NULL ;
}
ConfigItem_tld * find_tld ( Client * client )
{
ConfigItem_tld * tld ;
for ( tld = conf_tld ; tld ; tld = tld - > next )
{
2022-11-20 04:12:40 +00:00
if ( user_allowed_by_security_group ( client , tld - > match ) )
2020-03-29 09:16:53 +00:00
{
if ( ( tld - > options & TLD_TLS ) & & ! IsSecureConnect ( client ) )
continue ;
if ( ( tld - > options & TLD_REMOTE ) & & MyUser ( client ) )
continue ;
return tld ;
}
}
return NULL ;
}
2023-05-05 22:12:01 +00:00
/** Find a link block by server name (but don't check any restrictions like IP or auth) */
ConfigItem_link * find_link ( const char * servername )
2020-03-29 09:16:53 +00:00
{
ConfigItem_link * link ;
for ( link = conf_link ; link ; link = link - > next )
{
2023-05-05 22:12:01 +00:00
if ( ! link - > flag . temporary & & match_simple ( link - > servername , servername ) )
2020-03-29 09:16:53 +00:00
{
return link ;
}
}
return NULL ;
}
/** Find a ban of type CONF_BAN_*, which is currently only
* CONF_BAN_SERVER , CONF_BAN_VERSION and CONF_BAN_REALNAME
*/
2022-01-15 05:16:34 +00:00
ConfigItem_ban * find_ban ( Client * client , const char * host , short type )
2020-03-29 09:16:53 +00:00
{
ConfigItem_ban * ban ;
for ( ban = conf_ban ; ban ; ban = ban - > next )
{
if ( ban - > flag . type = = type )
{
if ( client )
{
if ( match_user ( ban - > mask , client , MATCH_CHECK_REAL ) )
return ban ;
}
else if ( match_simple ( ban - > mask , host ) )
return ban ;
}
}
return NULL ;
}
/** Find a ban of type CONF_BAN_*, which is currently only
* CONF_BAN_SERVER , CONF_BAN_VERSION and CONF_BAN_REALNAME
* This is the extended version , only used by cmd_svsnline .
*/
2022-01-15 05:16:34 +00:00
ConfigItem_ban * find_banEx ( Client * client , const char * host , short type , short type2 )
2020-03-29 09:16:53 +00:00
{
ConfigItem_ban * ban ;
for ( ban = conf_ban ; ban ; ban = ban - > next )
{
if ( ( ban - > flag . type = = type ) & & ( ban - > flag . type2 = = type2 ) )
{
if ( client )
{
if ( match_user ( ban - > mask , client , MATCH_CHECK_REAL ) )
return ban ;
}
else if ( match_simple ( ban - > mask , host ) )
return ban ;
}
}
return NULL ;
}
2022-01-15 05:16:34 +00:00
ConfigItem_vhost * find_vhost ( const char * name )
2020-03-29 09:16:53 +00:00
{
ConfigItem_vhost * vhost ;
for ( vhost = conf_vhost ; vhost ; vhost = vhost - > next )
{
if ( ! strcmp ( name , vhost - > login ) )
return vhost ;
}
return NULL ;
}
/** returns NULL if allowed and struct if denied */
2022-01-15 05:16:34 +00:00
ConfigItem_deny_channel * find_channel_allowed ( Client * client , const char * name )
2020-03-29 09:16:53 +00:00
{
ConfigItem_deny_channel * dchannel ;
ConfigItem_allow_channel * achannel ;
for ( dchannel = conf_deny_channel ; dchannel ; dchannel = dchannel - > next )
{
if ( match_simple ( dchannel - > channel , name ) )
{
if ( dchannel - > class & & strcmp ( client - > local - > class - > name , dchannel - > class ) )
continue ;
2022-11-20 04:12:40 +00:00
if ( dchannel - > match & & ! user_allowed_by_security_group ( client , dchannel - > match ) )
2020-03-29 09:16:53 +00:00
continue ;
break ; /* MATCH deny channel { } */
}
}
if ( dchannel )
{
/* Check exceptions... ('allow channel') */
for ( achannel = conf_allow_channel ; achannel ; achannel = achannel - > next )
{
if ( match_simple ( achannel - > channel , name ) )
{
if ( achannel - > class & & strcmp ( client - > local - > class - > name , achannel - > class ) )
continue ;
2022-11-20 04:12:40 +00:00
if ( achannel - > match & & ! user_allowed_by_security_group ( client , achannel - > match ) )
2020-03-29 09:16:53 +00:00
continue ;
break ; /* MATCH allow channel { } */
}
}
if ( achannel )
return NULL ; /* Matches an 'allow channel' - so not forbidden */
else
return dchannel ;
}
return NULL ;
}
void init_dynconf ( void )
{
memset ( & iConf , 0 , sizeof ( iConf ) ) ;
memset ( & tempiConf , 0 , sizeof ( iConf ) ) ;
}
2022-01-15 05:16:34 +00:00
const char * pretty_time_val_r ( char * buf , size_t buflen , long timeval )
2020-03-29 09:16:53 +00:00
{
if ( timeval = = 0 )
return " 0 " ;
buf [ 0 ] = 0 ;
if ( timeval / 86400 )
2022-01-15 05:16:34 +00:00
snprintf ( buf , buflen , " %ldd " , timeval / 86400 ) ;
2020-03-29 09:16:53 +00:00
if ( ( timeval / 3600 ) % 24 )
2022-01-15 05:16:34 +00:00
snprintf ( buf + strlen ( buf ) , buflen - strlen ( buf ) , " %ldh " , ( timeval / 3600 ) % 24 ) ;
2020-03-29 09:16:53 +00:00
if ( ( timeval / 60 ) % 60 )
2022-01-15 05:16:34 +00:00
snprintf ( buf + strlen ( buf ) , buflen - strlen ( buf ) , " %ldm " , ( timeval / 60 ) % 60 ) ;
2020-03-29 09:16:53 +00:00
if ( ( timeval % 60 ) )
2022-01-15 05:16:34 +00:00
snprintf ( buf + strlen ( buf ) , buflen - strlen ( buf ) , " %lds " , timeval % 60 ) ;
2021-06-19 15:52:51 +00:00
2020-03-29 09:16:53 +00:00
return buf ;
}
2022-01-15 05:16:34 +00:00
const char * pretty_time_val ( long timeval )
{
static char buf [ 512 ] ;
return pretty_time_val_r ( buf , sizeof ( buf ) , timeval ) ;
}
2020-03-29 09:16:53 +00:00
/* This converts a relative path to an absolute path, but only if necessary. */
2022-01-15 05:16:34 +00:00
void convert_to_absolute_path ( char * * path , const char * reldir )
2020-03-29 09:16:53 +00:00
{
char * s ;
if ( ! * path | | ! * * path )
return ; /* NULL or empty */
if ( strstr ( * path , " :// " ) )
return ; /* URL: don't touch */
2022-01-15 05:16:34 +00:00
# ifdef _WIN32
if ( ! strncmp ( * path , " cache/ " , 6 ) )
return ; /* downloaded from URL: don't touch (is only relative path on Windows) */
# endif
2020-03-29 09:16:53 +00:00
if ( ( * * path = = ' / ' ) | | ( * * path = = ' \\ ' ) )
return ; /* already absolute path */
if ( ! strncmp ( * path , reldir , strlen ( reldir ) ) )
return ; /* already contains reldir */
s = safe_alloc ( strlen ( reldir ) + strlen ( * path ) + 2 ) ;
sprintf ( s , " %s/%s " , reldir , * path ) ; /* safe, see line above */
safe_free ( * path ) ;
* path = s ;
}
/* Similar to convert_to_absolute_path() but returns a duplicated string.
* Don ' t forget to free !
*/
char * convert_to_absolute_path_duplicate ( char * path , char * reldir )
{
char * xpath = strdup ( path ) ;
convert_to_absolute_path ( & xpath , reldir ) ;
return xpath ;
}
/*
* Actual config parser funcs
*/
2022-01-15 05:16:34 +00:00
int _conf_include ( ConfigFile * conf , ConfigEntry * ce )
2020-03-29 09:16:53 +00:00
{
int ret = 0 ;
# ifdef GLOBH
glob_t files ;
int i ;
# elif defined(_WIN32)
HANDLE hFind ;
WIN32_FIND_DATA FindData ;
char cPath [ MAX_PATH ] , * cSlash = NULL , * path ;
# endif
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
{
config_status ( " %s:%i: include: no filename given " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename ,
ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return - 1 ;
}
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & ce - > value , CONFDIR ) ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
if ( url_is_valid ( ce - > value ) )
{
add_config_resource ( ce - > value , RESOURCE_INCLUDE , ce ) ;
return 0 ;
2020-03-29 09:16:53 +00:00
}
# if !defined(_WIN32) && !defined(_AMIGA) && !defined(OSXTIGER) && DEFAULT_PERMISSIONS != 0
2022-01-15 05:16:34 +00:00
( void ) chmod ( ce - > value , DEFAULT_PERMISSIONS ) ;
2020-03-29 09:16:53 +00:00
# endif
# ifdef GLOBH
# if defined(__OpenBSD__) && defined(GLOB_LIMIT)
2022-01-15 05:16:34 +00:00
glob ( ce - > value , GLOB_NOSORT | GLOB_NOCHECK | GLOB_LIMIT , NULL , & files ) ;
2020-03-29 09:16:53 +00:00
# else
2022-01-15 05:16:34 +00:00
glob ( ce - > value , GLOB_NOSORT | GLOB_NOCHECK , NULL , & files ) ;
2020-03-29 09:16:53 +00:00
# endif
if ( ! files . gl_pathc ) {
globfree ( & files ) ;
config_status ( " %s:%i: include %s: invalid file given " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ,
ce - > value ) ;
2020-03-29 09:16:53 +00:00
return - 1 ;
}
2022-01-15 05:16:34 +00:00
for ( i = 0 ; i < files . gl_pathc ; i + + )
{
if ( add_config_resource ( files . gl_pathv [ i ] , RESOURCE_INCLUDE , ce ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
ret = config_read_file ( files . gl_pathv [ i ] , files . gl_pathv [ i ] ) ;
if ( ret < 0 )
{
globfree ( & files ) ;
return ret ;
}
2020-03-29 09:16:53 +00:00
}
}
globfree ( & files ) ;
# elif defined(_WIN32)
memset ( cPath , 0 , MAX_PATH ) ;
2022-01-15 05:16:34 +00:00
if ( strchr ( ce - > value , ' / ' ) | | strchr ( ce - > value , ' \\ ' ) ) {
strlcpy ( cPath , ce - > value , MAX_PATH ) ;
2020-03-29 09:16:53 +00:00
cSlash = cPath + strlen ( cPath ) ;
while ( * cSlash ! = ' \\ ' & & * cSlash ! = ' / ' & & cSlash > cPath )
cSlash - - ;
* ( cSlash + 1 ) = 0 ;
}
2022-01-15 05:16:34 +00:00
if ( ( hFind = FindFirstFile ( ce - > value , & FindData ) ) = = INVALID_HANDLE_VALUE )
2020-03-29 09:16:53 +00:00
{
config_status ( " %s:%i: include %s: invalid file given " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ,
ce - > value ) ;
2020-03-29 09:16:53 +00:00
return - 1 ;
}
if ( cPath ) {
path = safe_alloc ( strlen ( cPath ) + strlen ( FindData . cFileName ) + 1 ) ;
strcpy ( path , cPath ) ;
strcat ( path , FindData . cFileName ) ;
2022-01-15 05:16:34 +00:00
if ( add_config_resource ( path , RESOURCE_INCLUDE , ce ) )
{
ret = config_read_file ( path , path ) ;
safe_free ( path ) ;
}
2020-03-29 09:16:53 +00:00
}
else
{
2022-01-15 05:16:34 +00:00
if ( add_config_resource ( FindData . cFileName , RESOURCE_INCLUDE , ce ) )
ret = config_read_file ( FindData . cFileName , FindData . cFileName ) ;
2020-03-29 09:16:53 +00:00
}
if ( ret < 0 )
{
FindClose ( hFind ) ;
return ret ;
}
ret = 0 ;
while ( FindNextFile ( hFind , & FindData ) ! = 0 ) {
if ( cPath ) {
path = safe_alloc ( strlen ( cPath ) + strlen ( FindData . cFileName ) + 1 ) ;
strcpy ( path , cPath ) ;
strcat ( path , FindData . cFileName ) ;
2022-01-15 05:16:34 +00:00
if ( add_config_resource ( path , RESOURCE_INCLUDE , ce ) )
{
ret = config_read_file ( path , path ) ;
safe_free ( path ) ;
if ( ret < 0 )
break ;
}
2020-03-29 09:16:53 +00:00
}
else
{
2022-01-15 05:16:34 +00:00
if ( add_config_resource ( FindData . cFileName , RESOURCE_INCLUDE , ce ) )
ret = config_read_file ( FindData . cFileName , FindData . cFileName ) ;
2020-03-29 09:16:53 +00:00
}
}
FindClose ( hFind ) ;
if ( ret < 0 )
return ret ;
# else
2022-01-15 05:16:34 +00:00
if ( add_config_resource ( ce - > value , RESOURCE_INCLUDE , ce ) )
ret = config_read_file ( ce - > value , ce - > value ) ;
2020-03-29 09:16:53 +00:00
return ret ;
# endif
return 1 ;
}
int _test_include ( ConfigFile * conf , ConfigEntry * ce )
{
return 0 ;
}
int _conf_admin ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
ConfigItem_admin * ca ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
ca = safe_alloc ( sizeof ( ConfigItem_admin ) ) ;
if ( ! conf_admin )
conf_admin_tail = ca ;
2022-01-15 05:16:34 +00:00
safe_strdup ( ca - > line , cep - > name ) ;
2020-03-29 09:16:53 +00:00
AddListItem ( ca , conf_admin ) ;
}
return 1 ;
}
int _test_admin ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
int errors = 0 ;
if ( requiredstuff . conf_admin )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( ce - > file - > filename , ce - > line_number , " admin " ) ;
2020-03-29 09:16:53 +00:00
return 0 ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( strlen ( cep - > name ) > 500 )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: oversized data in admin block " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename ,
cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
requiredstuff . conf_admin = 1 ;
return errors ;
}
int _conf_me ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
if ( ! conf_me )
conf_me = safe_alloc ( sizeof ( ConfigItem_me ) ) ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " name " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( conf_me - > name , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " info " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( conf_me - > info , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " sid " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( conf_me - > sid , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
}
return 1 ;
}
int _test_me ( ConfigFile * conf , ConfigEntry * ce )
{
char has_name = 0 , has_info = 0 , has_sid = 0 ;
ConfigEntry * cep ;
int errors = 0 ;
if ( requiredstuff . conf_me )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( ce - > file - > filename , ce - > line_number , " me " ) ;
2020-03-29 09:16:53 +00:00
return 0 ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " me " ) )
continue ;
/* me::name */
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " name " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_name )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " me::name " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_name = 1 ;
2022-01-15 05:16:34 +00:00
if ( ! strchr ( cep - > value , ' . ' ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: illegal me::name, must be fully qualified hostname " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename ,
cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
if ( strlen ( cep - > value ) > HOSTLEN )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error ( " %s:%i: illegal me::name, must be less or equal to %i characters " ,
cep - > file - > filename ,
cep - > line_number , HOSTLEN ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
if ( ! valid_server_name ( cep - > value ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error ( " %s:%i: illegal me::name contains invalid character(s) [only a-z, 0-9, _, -, . are allowed] " ,
cep - > file - > filename ,
cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
/* me::info */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " info " ) )
2020-03-29 09:16:53 +00:00
{
char * p ;
char valid = 0 ;
if ( has_info )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " me::info " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_info = 1 ;
2022-01-15 05:16:34 +00:00
if ( strlen ( cep - > value ) > ( REALLEN - 1 ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: too long me::info, must be max. %i characters " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ,
2020-03-29 09:16:53 +00:00
REALLEN - 1 ) ;
errors + + ;
}
/* Valid me::info? Any data except spaces is ok */
2022-01-15 05:16:34 +00:00
for ( p = cep - > value ; * p ; p + + )
2020-03-29 09:16:53 +00:00
{
if ( * p ! = ' ' )
{
valid = 1 ;
break ;
}
}
if ( ! valid )
{
config_error ( " %s:%i: empty me::info, should be a server description. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " numeric " ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: me::numeric has been removed, you must now specify a Server ID (SID) instead. "
" Edit your configuration file and change 'numeric' to 'sid' and make up "
" a server id of exactly 3 characters, starting with a digit, eg: \" 001 \" or \" 0AB \" . " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " sid " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_sid )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " me::sid " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_sid = 1 ;
2022-01-15 05:16:34 +00:00
if ( ! valid_sid ( cep - > value ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: me::sid must be 3 characters long, begin with a number, "
" and the 2nd and 3rd character must be a number or uppercase letter. "
" Example: \" 001 \" and \" 0AB \" is good. \" AAA \" and \" 0ab \" are bad. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
if ( ! isdigit ( * cep - > value ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: me::sid must be 3 characters long and begin with a number " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
/* Unknown entry */
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( ce - > file - > filename , ce - > line_number ,
" me " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
if ( ! has_name )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number , " me::name " ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
if ( ! has_info )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number , " me::info " ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
if ( ! has_sid )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number , " me::sid " ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
requiredstuff . conf_me = 1 ;
return errors ;
}
/*
* The files { } block
*/
int _conf_files ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
if ( ! conf_files )
{
conf_files = safe_alloc ( sizeof ( ConfigItem_files ) ) ;
/* set defaults */
safe_strdup ( conf_files - > motd_file , MPATH ) ;
safe_strdup ( conf_files - > rules_file , RPATH ) ;
safe_strdup ( conf_files - > smotd_file , SMPATH ) ;
safe_strdup ( conf_files - > botmotd_file , BPATH ) ;
safe_strdup ( conf_files - > opermotd_file , OPATH ) ;
safe_strdup ( conf_files - > svsmotd_file , VPATH ) ;
safe_strdup ( conf_files - > pid_file , IRCD_PIDFILE ) ;
safe_strdup ( conf_files - > tune_file , IRCDTUNE ) ;
/* we let actual files get read in later by the motd caching mechanism */
}
/*
* hack to allow initialization of conf_files ( above ) when there is no files block in
* CPATH . The caller calls _conf_files ( NULL , NULL ) ; to do this . We return here because
* the for loop ' s initialization of cep would segfault otherwise . We return 1 because
2022-01-15 05:16:34 +00:00
* if config_run_blocks ( ) calls us with a NULL ce , it ' s got a bug . . . but we can ' t detect that .
2020-03-29 09:16:53 +00:00
*/
2022-01-15 05:16:34 +00:00
if ( ! ce )
2020-03-29 09:16:53 +00:00
return 1 ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
{
if ( ! strcmp ( cep - > name , " motd " ) )
safe_strdup ( conf_files - > motd_file , cep - > value ) ;
else if ( ! strcmp ( cep - > name , " shortmotd " ) )
safe_strdup ( conf_files - > smotd_file , cep - > value ) ;
else if ( ! strcmp ( cep - > name , " opermotd " ) )
safe_strdup ( conf_files - > opermotd_file , cep - > value ) ;
else if ( ! strcmp ( cep - > name , " svsmotd " ) )
safe_strdup ( conf_files - > svsmotd_file , cep - > value ) ;
else if ( ! strcmp ( cep - > name , " botmotd " ) )
safe_strdup ( conf_files - > botmotd_file , cep - > value ) ;
else if ( ! strcmp ( cep - > name , " rules " ) )
safe_strdup ( conf_files - > rules_file , cep - > value ) ;
else if ( ! strcmp ( cep - > name , " tunefile " ) )
safe_strdup ( conf_files - > tune_file , cep - > value ) ;
else if ( ! strcmp ( cep - > name , " pidfile " ) )
safe_strdup ( conf_files - > pid_file , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
return 1 ;
}
int _test_files ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
int errors = 0 ;
char has_motd = 0 , has_smotd = 0 , has_rules = 0 ;
char has_botmotd = 0 , has_opermotd = 0 , has_svsmotd = 0 ;
char has_pidfile = 0 , has_tunefile = 0 ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
/* files::motd */
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " motd " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_motd )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " files::motd " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , CONFDIR ) ;
2020-03-29 09:16:53 +00:00
config_test_openfile ( cep , O_RDONLY , 0 , " files::motd " , 0 , 1 ) ;
has_motd = 1 ;
}
/* files::smotd */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " shortmotd " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_smotd )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " files::shortmotd " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , CONFDIR ) ;
2020-03-29 09:16:53 +00:00
config_test_openfile ( cep , O_RDONLY , 0 , " files::shortmotd " , 0 , 1 ) ;
has_smotd = 1 ;
}
/* files::rules */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " rules " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_rules )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " files::rules " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , CONFDIR ) ;
2020-03-29 09:16:53 +00:00
config_test_openfile ( cep , O_RDONLY , 0 , " files::rules " , 0 , 1 ) ;
has_rules = 1 ;
}
/* files::botmotd */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " botmotd " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_botmotd )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " files::botmotd " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , CONFDIR ) ;
2020-03-29 09:16:53 +00:00
config_test_openfile ( cep , O_RDONLY , 0 , " files::botmotd " , 0 , 1 ) ;
has_botmotd = 1 ;
}
/* files::opermotd */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " opermotd " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_opermotd )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " files::opermotd " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , CONFDIR ) ;
2020-03-29 09:16:53 +00:00
config_test_openfile ( cep , O_RDONLY , 0 , " files::opermotd " , 0 , 1 ) ;
has_opermotd = 1 ;
}
/* files::svsmotd
* This config stuff should somehow be inside of modules / svsmotd . c ! ! ! . . . right ?
*/
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " svsmotd " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_svsmotd )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " files::svsmotd " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , CONFDIR ) ;
2020-03-29 09:16:53 +00:00
/* svsmotd can't be a URL because we have to be able to write to it */
config_test_openfile ( cep , O_RDONLY , 0 , " files::svsmotd " , 0 , 0 ) ;
has_svsmotd = 1 ;
}
/* files::pidfile */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " pidfile " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_pidfile )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " files::pidfile " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , PERMDATADIR ) ;
2020-03-29 09:16:53 +00:00
errors + = config_test_openfile ( cep , O_WRONLY | O_CREAT , 0600 , " files::pidfile " , 1 , 0 ) ;
has_pidfile = 1 ;
}
/* files::tunefile */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " tunefile " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_tunefile )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " files::tunefile " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , PERMDATADIR ) ;
2020-03-29 09:16:53 +00:00
errors + = config_test_openfile ( cep , O_RDWR | O_CREAT , 0600 , " files::tunefile " , 1 , 0 ) ;
has_tunefile = 1 ;
}
/* <random directive here> */
else
{
2022-01-15 05:16:34 +00:00
config_error ( " %s:%d: Unknown directive: \" %s \" in files {} " , cep - > file - > filename ,
cep - > line_number , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
return errors ;
}
/*
* The operclass { } block parser
*/
OperClassACLEntry * _conf_parseACLEntry ( ConfigEntry * ce )
{
ConfigEntry * cep ;
OperClassACLEntry * entry = NULL ;
entry = safe_alloc ( sizeof ( OperClassACLEntry ) ) ;
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ce - > name , " allow " ) )
2020-03-29 09:16:53 +00:00
entry - > type = OPERCLASSENTRY_ALLOW ;
else
entry - > type = OPERCLASSENTRY_DENY ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
OperClassACLEntryVar * var = safe_alloc ( sizeof ( OperClassACLEntryVar ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( var - > name , cep - > name ) ;
if ( cep - > value )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( var - > value , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
AddListItem ( var , entry - > variables ) ;
}
return entry ;
}
2022-01-15 05:16:34 +00:00
OperClassACL * _conf_parseACL ( const char * name , ConfigEntry * ce )
2020-03-29 09:16:53 +00:00
{
ConfigEntry * cep ;
OperClassACL * acl = NULL ;
acl = safe_alloc ( sizeof ( OperClassACL ) ) ;
safe_strdup ( acl - > name , name ) ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " deny " ) | | ! strcmp ( cep - > name , " allow " ) )
2020-03-29 09:16:53 +00:00
{
OperClassACLEntry * entry = _conf_parseACLEntry ( cep ) ;
AddListItem ( entry , acl - > entries ) ;
}
else {
2022-01-15 05:16:34 +00:00
OperClassACL * subAcl = _conf_parseACL ( cep - > name , cep ) ;
2020-03-29 09:16:53 +00:00
AddListItem ( subAcl , acl - > acls ) ;
}
}
return acl ;
}
int _conf_operclass ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
ConfigEntry * cepp ;
ConfigItem_operclass * operClass = NULL ;
operClass = safe_alloc ( sizeof ( ConfigItem_operclass ) ) ;
operClass - > classStruct = safe_alloc ( sizeof ( OperClass ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( operClass - > classStruct - > name , ce - > value ) ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " parent " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( operClass - > classStruct - > ISA , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " permissions " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
OperClassACL * acl = _conf_parseACL ( cepp - > name , cepp ) ;
2020-03-29 09:16:53 +00:00
AddListItem ( acl , operClass - > classStruct - > acls ) ;
}
}
}
AddListItem ( operClass , conf_operclass ) ;
return 1 ;
}
void new_permissions_system ( ConfigFile * conf , ConfigEntry * ce )
{
if ( need_operclass_permissions_upgrade )
return ; /* error already shown */
config_error ( " %s:%i: UnrealIRCd 4.2.1 and higher have a new operclass permissions system. " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
config_error ( " Please see https://www.unrealircd.org/docs/FAQ#New_operclass_permissions " ) ;
config_error ( " (additional errors regarding this are suppressed) " ) ;
/*
config_error ( " First of all, operclass::privileges has been renamed to operclass::permissions. " ) ;
config_error ( " However, the permissions themselves have also been changed. You cannot simply "
" rename 'privileges' to 'permissions' and be done with it! " ) ;
config_error ( " See https://www.unrealircd.org/docs/Operclass_permissions for the new list of permissions. " ) ;
config_error ( " Or just use the default operclasses from operclass.default.conf, then no need to change anything. " ) ; */
need_operclass_permissions_upgrade = 1 ;
}
int _test_operclass ( ConfigFile * conf , ConfigEntry * ce )
{
char has_permissions = 0 , has_parent = 0 ;
ConfigEntry * cep ;
int errors = 0 ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_noname ( ce - > file - > filename , ce - > line_number , " operclass " ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " parent " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_parent )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " operclass::parent " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_parent = 1 ;
continue ;
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " permissions " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_permissions )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " oper::permissions " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_permissions = 1 ;
continue ;
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " privileges " ) )
2020-03-29 09:16:53 +00:00
{
new_permissions_system ( conf , cep ) ;
errors + + ;
return errors ;
} else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename ,
cep - > line_number , " operclass " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
if ( ! has_permissions )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" oper::permissions " ) ;
errors + + ;
}
return errors ;
}
/*
* The oper { } block parser
*/
int _conf_oper ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
ConfigEntry * cepp ;
ConfigItem_oper * oper = NULL ;
oper = safe_alloc ( sizeof ( ConfigItem_oper ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( oper - > name , ce - > value ) ;
2022-11-20 04:12:40 +00:00
oper - > match = safe_alloc ( sizeof ( SecurityGroup ) ) ;
2022-01-15 05:16:34 +00:00
2022-04-03 15:09:29 +00:00
/* Inherit some defaults: */
oper - > server_notice_colors = tempiConf . server_notice_colors ;
oper - > server_notice_show_event = tempiConf . server_notice_show_event ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " operclass " ) )
safe_strdup ( oper - > operclass , cep - > value ) ;
if ( ! strcmp ( cep - > name , " password " ) )
2020-03-29 09:16:53 +00:00
oper - > auth = AuthBlockToAuthConfig ( cep ) ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " class " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
oper - > class = find_class ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ! oper - > class | | ( oper - > class - > flag . temporary = = 1 ) )
{
config_status ( " %s:%i: illegal oper::class, unknown class '%s' using default of class 'default' " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ,
cep - > value ) ;
2020-03-29 09:16:53 +00:00
oper - > class = default_class ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " swhois " ) )
2020-03-29 09:16:53 +00:00
{
SWhois * s ;
2022-01-15 05:16:34 +00:00
if ( cep - > items )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
s = safe_alloc ( sizeof ( SWhois ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( s - > line , cepp - > name ) ;
2020-03-29 09:16:53 +00:00
safe_strdup ( s - > setby , " oper " ) ;
AddListItem ( s , oper - > swhois ) ;
}
} else
2022-01-15 05:16:34 +00:00
if ( cep - > value )
2020-03-29 09:16:53 +00:00
{
s = safe_alloc ( sizeof ( SWhois ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( s - > line , cep - > value ) ;
2020-03-29 09:16:53 +00:00
safe_strdup ( s - > setby , " oper " ) ;
AddListItem ( s , oper - > swhois ) ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " snomask " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( oper - > snomask , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " server-notice-colors " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
oper - > server_notice_colors = config_checkval ( cep - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
2022-04-03 15:09:29 +00:00
else if ( ! strcmp ( cep - > name , " server-notice-show-event " ) )
{
oper - > server_notice_show_event = config_checkval ( cep - > value , CFG_YESNO ) ;
}
2022-11-20 04:12:40 +00:00
else if ( ! strcmp ( cep - > name , " auto-login " ) )
{
oper - > auto_login = config_checkval ( cep - > value , CFG_YESNO ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " modes " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
oper - > modes = set_usermode ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " require-modes " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
oper - > require_modes = set_usermode ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " maxlogins " ) )
{
oper - > maxlogins = atoi ( cep - > value ) ;
}
2022-11-20 04:12:40 +00:00
else if ( ! strcmp ( cep - > name , " mask " ) | | ! strcmp ( cep - > name , " match " ) )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
conf_match_block ( conf , cep , & oper - > match ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " vhost " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( oper - > vhost , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
}
AddListItem ( oper , conf_oper ) ;
return 1 ;
}
int _test_oper ( ConfigFile * conf , ConfigEntry * ce )
{
char has_class = 0 , has_password = 0 , has_snomask = 0 ;
2022-11-20 04:12:40 +00:00
char has_modes = 0 , has_require_modes = 0 , has_mask = 0 , has_match = 0 , has_broad_match = 0 ;
char has_maxlogins = 0 , has_operclass = 0 , has_vhost = 0 , has_auto_login = 0 ;
2020-03-29 09:16:53 +00:00
ConfigEntry * cep ;
int errors = 0 ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_noname ( ce - > file - > filename , ce - > line_number , " oper " ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
/* Regular variables */
2022-01-15 05:16:34 +00:00
if ( ! cep - > items )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " oper " ) )
{
errors + + ;
continue ;
}
/* oper::password */
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " password " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_password )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " oper::password " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_password = 1 ;
if ( Auth_CheckError ( cep ) < 0 )
errors + + ;
2022-01-15 05:16:34 +00:00
if ( ce - > value & & cep - > value & &
! strcmp ( ce - > value , " bobsmith " ) & &
! strcmp ( cep - > value , " test " ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: please change the the name and password of the "
" default 'bobsmith' oper block " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
continue ;
}
/* oper::operclass */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " operclass " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_operclass )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " oper::operclass " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_operclass = 1 ;
continue ;
}
/* oper::class */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " class " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_class )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " oper::class " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_class = 1 ;
}
/* oper::swhois */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " swhois " ) )
2020-03-29 09:16:53 +00:00
{
}
/* oper::vhost */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " vhost " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_vhost )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " oper::vhost " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
2023-05-05 22:12:01 +00:00
if ( ! valid_vhost ( cep - > value ) )
{
config_error ( " %s:%i: oper::vhost contains illegal characters or is too long: '%s' " ,
cep - > file - > filename , cep - > line_number , cep - > value ) ;
errors + + ;
}
2020-03-29 09:16:53 +00:00
has_vhost = 1 ;
}
/* oper::snomask */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " snomask " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
char * wrong_snomask ;
2020-03-29 09:16:53 +00:00
if ( has_snomask )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " oper::snomask " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
2022-01-15 05:16:34 +00:00
if ( ! is_valid_snomask_string_testing ( cep - > value , & wrong_snomask ) )
{
config_error ( " %s:%i: oper::snomask contains unknown snomask letter(s) '%s' " ,
cep - > file - > filename , cep - > line_number , wrong_snomask ) ;
errors + + ;
invalid_snomasks_encountered + + ;
}
2020-03-29 09:16:53 +00:00
has_snomask = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " server-notice-colors " ) )
{
}
2022-04-03 15:09:29 +00:00
else if ( ! strcmp ( cep - > name , " server-notice-show-event " ) )
{
}
2022-11-20 04:12:40 +00:00
else if ( ! strcmp ( cep - > name , " auto-login " ) )
{
has_auto_login = config_checkval ( cep - > value , CFG_YESNO ) ;
}
2020-03-29 09:16:53 +00:00
/* oper::modes */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " modes " ) )
2020-03-29 09:16:53 +00:00
{
char * p ;
2022-01-15 05:16:34 +00:00
for ( p = cep - > value ; * p ; p + + )
2020-03-29 09:16:53 +00:00
if ( strchr ( " orzS " , * p ) )
{
config_error ( " %s:%i: oper::modes may not include mode '%c' " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , * p ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
if ( has_modes )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " oper::modes " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_modes = 1 ;
}
/* oper::require-modes */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " require-modes " ) )
2020-03-29 09:16:53 +00:00
{
char * p ;
2022-01-15 05:16:34 +00:00
for ( p = cep - > value ; * p ; p + + )
2020-03-29 09:16:53 +00:00
if ( strchr ( " o " , * p ) )
{
config_warn ( " %s:%i: oper::require-modes probably shouldn't include mode '%c' " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , * p ) ;
2020-03-29 09:16:53 +00:00
}
if ( has_require_modes )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " oper::require-modes " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_require_modes = 1 ;
}
/* oper::maxlogins */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " maxlogins " ) )
2020-03-29 09:16:53 +00:00
{
int l ;
if ( has_maxlogins )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " oper::maxlogins " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_maxlogins = 1 ;
2022-01-15 05:16:34 +00:00
l = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ( l < 0 ) | | ( l > 5000 ) )
{
config_error ( " %s:%i: oper::maxlogins: value out of range (%d) should be 0-5000 " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , l ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( cep - > value | | cep - > items )
2022-11-20 04:12:40 +00:00
{
2020-03-29 09:16:53 +00:00
has_mask = 1 ;
2022-11-20 04:12:40 +00:00
test_match_block ( conf , cep , & errors ) ;
if ( test_match_block_too_broad ( conf , cep ) )
has_broad_match = 1 ;
}
}
else if ( ! strcmp ( cep - > name , " match " ) )
{
if ( cep - > value | | cep - > items )
{
has_match = 1 ;
test_match_block ( conf , cep , & errors ) ;
if ( test_match_block_too_broad ( conf , cep ) )
has_broad_match = 1 ;
}
2020-03-29 09:16:53 +00:00
}
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename ,
cep - > line_number , " oper " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
/* Sections */
else
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " swhois " ) )
2020-03-29 09:16:53 +00:00
{
/* ok */
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( cep - > value | | cep - > items )
2022-11-20 04:12:40 +00:00
{
2020-03-29 09:16:53 +00:00
has_mask = 1 ;
2022-11-20 04:12:40 +00:00
test_match_block ( conf , cep , & errors ) ;
if ( test_match_block_too_broad ( conf , cep ) )
has_broad_match = 1 ;
}
}
else if ( ! strcmp ( cep - > name , " match " ) )
{
if ( cep - > value | | cep - > items )
{
has_match = 1 ;
test_match_block ( conf , cep , & errors ) ;
if ( test_match_block_too_broad ( conf , cep ) )
has_broad_match = 1 ;
}
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " password " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_password )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " oper::password " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_password = 1 ;
if ( Auth_CheckError ( cep ) < 0 )
errors + + ;
}
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename ,
cep - > line_number , " oper " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
}
2022-11-20 04:12:40 +00:00
if ( has_auto_login & & has_broad_match )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
config_error ( " %s:%i: your oper block for '%s' has auto-login but is completely unrestricted (mask *@*)! " ,
ce - > file - > filename , ce - > line_number , ce - > value ) ;
errors + + ;
} else
if ( ! has_password & & has_broad_match )
{
config_error ( " %s:%i: your oper block for '%s' has no password and is completely unrestricted (mask *@*)! " ,
ce - > file - > filename , ce - > line_number , ce - > value ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-11-20 04:12:40 +00:00
/* The rest should NOT be in an 'else'... */
if ( has_password & & has_auto_login )
{
config_error ( " %s:%i: You have auto-login enabled for your oper block '%s' but you also have a password set. "
" Remove the password if you want to use auto-login. " ,
ce - > file - > filename , ce - > line_number , ce - > value ) ;
errors + + ;
}
if ( ! has_mask & & ! has_match )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2022-11-20 04:12:40 +00:00
" oper::match " ) ;
errors + + ;
}
if ( has_mask & & has_match )
{
config_error ( " %s:%d: You cannot have both ::mask and ::match. "
" You should only use oper::match. " ,
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
if ( ! has_class )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" oper::class " ) ;
errors + + ;
}
if ( ! has_operclass )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" oper::operclass " ) ;
errors + + ;
}
return errors ;
}
/*
* The class { } block parser
*/
int _conf_class ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep , * cep2 ;
ConfigItem_class * class ;
unsigned char isnew = 0 ;
2022-01-15 05:16:34 +00:00
if ( ! ( class = find_class ( ce - > value ) ) )
2020-03-29 09:16:53 +00:00
{
class = safe_alloc ( sizeof ( ConfigItem_class ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( class - > name , ce - > value ) ;
2020-03-29 09:16:53 +00:00
isnew = 1 ;
}
else
{
isnew = 0 ;
class - > flag . temporary = 0 ;
class - > options = 0 ; /* RESET OPTIONS */
}
2022-01-15 05:16:34 +00:00
safe_strdup ( class - > name , ce - > value ) ;
2020-03-29 09:16:53 +00:00
class - > connfreq = 15 ; /* default */
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
{
if ( ! strcmp ( cep - > name , " pingfreq " ) )
class - > pingfreq = config_checkval ( cep - > value , CFG_TIME ) ;
else if ( ! strcmp ( cep - > name , " connfreq " ) )
class - > connfreq = config_checkval ( cep - > value , CFG_TIME ) ;
else if ( ! strcmp ( cep - > name , " maxclients " ) )
class - > maxclients = atol ( cep - > value ) ;
else if ( ! strcmp ( cep - > name , " sendq " ) )
class - > sendq = config_checkval ( cep - > value , CFG_SIZE ) ;
else if ( ! strcmp ( cep - > name , " recvq " ) )
class - > recvq = config_checkval ( cep - > value , CFG_SIZE ) ;
else if ( ! strcmp ( cep - > name , " options " ) )
{
for ( cep2 = cep - > items ; cep2 ; cep2 = cep2 - > next )
if ( ! strcmp ( cep2 - > name , " nofakelag " ) )
2020-03-29 09:16:53 +00:00
class - > options | = CLASS_OPT_NOFAKELAG ;
}
}
if ( isnew )
AddListItem ( class , conf_class ) ;
return 1 ;
}
int _test_class ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep , * cep2 ;
int errors = 0 ;
char has_pingfreq = 0 , has_connfreq = 0 , has_maxclients = 0 , has_sendq = 0 ;
char has_recvq = 0 ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_noname ( ce - > file - > filename , ce - > line_number , " class " ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
2022-01-15 05:16:34 +00:00
if ( ! strcasecmp ( ce - > value , " default " ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%d: Class cannot be named 'default', this class name is reserved for internal use. " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " options " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cep2 = cep - > items ; cep2 ; cep2 = cep2 - > next )
2020-03-29 09:16:53 +00:00
{
# ifdef FAKELAG_CONFIGURABLE
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep2 - > name , " nofakelag " ) )
2020-03-29 09:16:53 +00:00
;
else
# endif
{
config_error ( " %s:%d: Unknown option '%s' in class::options " ,
2022-01-15 05:16:34 +00:00
cep2 - > file - > filename , cep2 - > line_number , cep2 - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
}
else if ( config_is_blankorempty ( cep , " class " ) )
{
errors + + ;
continue ;
}
/* class::pingfreq */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " pingfreq " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
int v = config_checkval ( cep - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
if ( has_pingfreq )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " class::pingfreq " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_pingfreq = 1 ;
if ( ( v < 30 ) | | ( v > 600 ) )
{
config_error ( " %s:%i: class::pingfreq should be a reasonable value (30-600) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
/* class::maxclients */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " maxclients " ) )
2020-03-29 09:16:53 +00:00
{
long l ;
if ( has_maxclients )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " class::maxclients " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_maxclients = 1 ;
2022-01-15 05:16:34 +00:00
l = atol ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ( l < 1 ) | | ( l > 1000000 ) )
{
config_error ( " %s:%i: class::maxclients with illegal value " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
/* class::connfreq */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " connfreq " ) )
2020-03-29 09:16:53 +00:00
{
long l ;
if ( has_connfreq )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " class::connfreq " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_connfreq = 1 ;
2022-01-15 05:16:34 +00:00
l = config_checkval ( cep - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
if ( ( l < 5 ) | | ( l > 604800 ) )
{
config_error ( " %s:%i: class::connfreq with illegal value (must be >5 and <7d) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
/* class::sendq */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " sendq " ) )
2020-03-29 09:16:53 +00:00
{
long l ;
if ( has_sendq )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " class::sendq " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_sendq = 1 ;
2022-01-15 05:16:34 +00:00
l = config_checkval ( cep - > value , CFG_SIZE ) ;
2020-03-29 09:16:53 +00:00
if ( ( l < = 0 ) | | ( l > 2000000000 ) )
{
config_error ( " %s:%i: class::sendq with illegal value " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
/* class::recvq */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " recvq " ) )
2020-03-29 09:16:53 +00:00
{
long l ;
if ( has_recvq )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " class::recvq " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_recvq = 1 ;
2022-01-15 05:16:34 +00:00
l = config_checkval ( cep - > value , CFG_SIZE ) ;
2020-03-29 09:16:53 +00:00
if ( ( l < 512 ) | | ( l > 32768 ) )
{
config_error ( " %s:%i: class::recvq with illegal value (must be >512 and <32k) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
/* Unknown */
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename , cep - > line_number ,
" class " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
if ( ! has_pingfreq )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" class::pingfreq " ) ;
errors + + ;
}
if ( ! has_maxclients )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" class::maxclients " ) ;
errors + + ;
}
if ( ! has_sendq )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" class::sendq " ) ;
errors + + ;
}
return errors ;
}
int _conf_drpass ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
if ( ! conf_drpass )
{
conf_drpass = safe_alloc ( sizeof ( ConfigItem_drpass ) ) ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " restart " ) )
2020-03-29 09:16:53 +00:00
{
if ( conf_drpass - > restartauth )
Auth_FreeAuthConfig ( conf_drpass - > restartauth ) ;
conf_drpass - > restartauth = AuthBlockToAuthConfig ( cep ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " die " ) )
2020-03-29 09:16:53 +00:00
{
if ( conf_drpass - > dieauth )
Auth_FreeAuthConfig ( conf_drpass - > dieauth ) ;
conf_drpass - > dieauth = AuthBlockToAuthConfig ( cep ) ;
}
}
return 1 ;
}
int _test_drpass ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
int errors = 0 ;
char has_restart = 0 , has_die = 0 ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " drpass " ) )
{
errors + + ;
continue ;
}
/* drpass::restart */
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " restart " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_restart )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " drpass::restart " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_restart = 1 ;
if ( Auth_CheckError ( cep ) < 0 )
errors + + ;
continue ;
}
/* drpass::die */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " die " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_die )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " drpass::die " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_die = 1 ;
if ( Auth_CheckError ( cep ) < 0 )
errors + + ;
continue ;
}
/* Unknown */
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename , cep - > line_number ,
" drpass " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
return errors ;
}
/*
* The ulines { } block parser
*/
int _conf_ulines ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
ConfigItem_ulines * ca ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
ca = safe_alloc ( sizeof ( ConfigItem_ulines ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( ca - > servername , cep - > name ) ;
2020-03-29 09:16:53 +00:00
AddListItem ( ca , conf_ulines ) ;
}
return 1 ;
}
int _test_ulines ( ConfigFile * conf , ConfigEntry * ce )
{
/* No check needed */
return 0 ;
}
int _conf_tld ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
ConfigItem_tld * ca ;
ca = safe_alloc ( sizeof ( ConfigItem_tld ) ) ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
if ( ! strcmp ( cep - > name , " match " ) | | ! strcmp ( cep - > name , " mask " ) )
conf_match_block ( conf , cep , & ca - > match ) ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " motd " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( ca - > motd_file , cep - > value ) ;
read_motd ( cep - > value , & ca - > motd ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " shortmotd " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( ca - > smotd_file , cep - > value ) ;
read_motd ( cep - > value , & ca - > smotd ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " opermotd " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( ca - > opermotd_file , cep - > value ) ;
read_motd ( cep - > value , & ca - > opermotd ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " botmotd " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( ca - > botmotd_file , cep - > value ) ;
read_motd ( cep - > value , & ca - > botmotd ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " rules " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( ca - > rules_file , cep - > value ) ;
read_motd ( cep - > value , & ca - > rules ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " options " ) )
2020-03-29 09:16:53 +00:00
{
ConfigEntry * cepp ;
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " ssl " ) | | ! strcmp ( cepp - > name , " tls " ) )
2020-03-29 09:16:53 +00:00
ca - > options | = TLD_TLS ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " remote " ) )
2020-03-29 09:16:53 +00:00
ca - > options | = TLD_REMOTE ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " channel " ) )
safe_strdup ( ca - > channel , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
AddListItem ( ca , conf_tld ) ;
return 1 ;
}
int _test_tld ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
int errors = 0 ;
int fd = - 1 ;
2022-11-20 04:12:40 +00:00
char has_mask = 0 , has_match = 0 , has_motd = 0 , has_rules = 0 , has_shortmotd = 0 ;
char has_channel = 0 , has_opermotd = 0 , has_botmotd = 0 , has_options = 0 ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
if ( ! cep - > value & & strcmp ( cep - > name , " options " ) & & strcmp ( cep - > name , " mask " ) & & strcmp ( cep - > name , " match " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_empty ( cep - > file - > filename , cep - > line_number ,
" tld " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
/* tld::mask */
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( cep - > value | | cep - > items )
2022-11-20 04:12:40 +00:00
{
2022-01-15 05:16:34 +00:00
has_mask = 1 ;
2022-11-20 04:12:40 +00:00
test_match_block ( conf , cep , & errors ) ;
}
}
else if ( ! strcmp ( cep - > name , " match " ) )
{
if ( cep - > value | | cep - > items )
{
has_match = 1 ;
test_match_block ( conf , cep , & errors ) ;
}
2020-03-29 09:16:53 +00:00
}
/* tld::motd */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " motd " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_motd )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " tld::motd " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_motd = 1 ;
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , CONFDIR ) ;
if ( ( ( fd = open ( cep - > value , O_RDONLY ) ) = = - 1 ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: tld::motd: %s: %s " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ,
cep - > value , strerror ( errno ) ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
else
close ( fd ) ;
}
/* tld::rules */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " rules " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_rules )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " tld::rules " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_rules = 1 ;
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , CONFDIR ) ;
if ( ( ( fd = open ( cep - > value , O_RDONLY ) ) = = - 1 ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: tld::rules: %s: %s " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ,
cep - > value , strerror ( errno ) ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
else
close ( fd ) ;
}
/* tld::channel */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " channel " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_channel )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " tld::channel " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_channel = 1 ;
}
/* tld::shortmotd */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " shortmotd " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_shortmotd )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " tld::shortmotd " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_shortmotd = 1 ;
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , CONFDIR ) ;
if ( ( ( fd = open ( cep - > value , O_RDONLY ) ) = = - 1 ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: tld::shortmotd: %s: %s " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ,
cep - > value , strerror ( errno ) ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
else
close ( fd ) ;
}
/* tld::opermotd */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " opermotd " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_opermotd )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " tld::opermotd " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_opermotd = 1 ;
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , CONFDIR ) ;
if ( ( ( fd = open ( cep - > value , O_RDONLY ) ) = = - 1 ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: tld::opermotd: %s: %s " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ,
cep - > value , strerror ( errno ) ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
else
close ( fd ) ;
}
/* tld::botmotd */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " botmotd " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_botmotd )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " tld::botmotd " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_botmotd = 1 ;
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , CONFDIR ) ;
if ( ( ( fd = open ( cep - > value , O_RDONLY ) ) = = - 1 ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: tld::botmotd: %s: %s " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ,
cep - > value , strerror ( errno ) ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
else
close ( fd ) ;
}
/* tld::options */
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " options " ) ) {
2020-03-29 09:16:53 +00:00
ConfigEntry * cep2 ;
if ( has_options )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " tld::options " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_options = 1 ;
2022-01-15 05:16:34 +00:00
for ( cep2 = cep - > items ; cep2 ; cep2 = cep2 - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( strcmp ( cep2 - > name , " ssl " ) & &
strcmp ( cep2 - > name , " tls " ) & &
strcmp ( cep2 - > name , " remote " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_unknownopt ( cep2 - > file - > filename ,
cep2 - > line_number , " tld " , cep2 - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
}
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename , cep - > line_number ,
" tld " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
2022-11-20 04:12:40 +00:00
if ( ! has_mask & & ! has_match )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2022-11-20 04:12:40 +00:00
" tld::match " ) ;
errors + + ;
}
if ( has_mask & & has_match )
{
config_error ( " %s:%d: You cannot have both ::mask and ::match. "
" You should only use %s::match. " ,
ce - > file - > filename , ce - > line_number , ce - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2023-05-05 22:12:01 +00:00
return errors ;
}
/* Helper for _conf_listen() */
void conf_listen_configure ( const char * ip , int port , SocketType socket_type , int options , ConfigEntry * ce , ConfigEntry * tlsconfig )
{
ConfigItem_listen * listen ;
ConfigEntry * cep , * cepp ;
Hook * h ;
char isnew = 0 ;
if ( ! ( listen = find_listen ( ip , port , socket_type ) ) )
2020-03-29 09:16:53 +00:00
{
2023-05-05 22:12:01 +00:00
listen = safe_alloc ( sizeof ( ConfigItem_listen ) ) ;
if ( socket_type = = SOCKET_TYPE_UNIX )
{
safe_strdup ( listen - > file , ip ) ;
} else {
safe_strdup ( listen - > ip , ip ) ;
listen - > port = port ;
}
listen - > fd = - 1 ;
listen - > socket_type = socket_type ;
isnew = 1 ;
2020-03-29 09:16:53 +00:00
}
2023-05-05 22:12:01 +00:00
if ( listen - > options & LISTENER_BOUND )
options | = LISTENER_BOUND ;
listen - > options = options ;
if ( isnew )
AddListItem ( listen , conf_listen ) ;
/* Reset all settings of the current listener (free and set defaults): */
listen - > flag . temporary = 0 ;
listen - > start_handshake = start_of_normal_client_handshake ;
if ( listen - > ssl_ctx )
2020-03-29 09:16:53 +00:00
{
2023-05-05 22:12:01 +00:00
SSL_CTX_free ( listen - > ssl_ctx ) ;
listen - > ssl_ctx = NULL ;
}
if ( listen - > tls_options )
{
free_tls_options ( listen - > tls_options ) ;
listen - > tls_options = NULL ;
}
safe_free ( listen - > websocket_forward ) ;
safe_free ( listen - > webserver ) ;
/* Now set the new settings: */
if ( tlsconfig )
{
listen - > tls_options = safe_alloc ( sizeof ( TLSOptions ) ) ;
conf_tlsblock ( conf , tlsconfig , listen - > tls_options ) ;
listen - > ssl_ctx = init_ctx ( listen - > tls_options , 1 ) ;
}
/* For modules that hook CONFIG_LISTEN and CONFIG_LISTEN_OPTIONS.
* Yeah , ugly we have this here . .
* and again about 100 lines down too .
*/
for ( cep = ce - > items ; cep ; cep = cep - > next )
{
if ( ! strcmp ( cep - > name , " mode " ) )
{
/* Yeah, we actually do something with this one.. */
if ( cep - > value )
listen - > mode = strtol ( cep - > value , NULL , 8 ) ; /* octal */
}
else if ( ! strcmp ( cep - > name , " spoof-ip " ) )
safe_strdup ( listen - > spoof_ip , cep - > value ) ;
else if ( ! strcmp ( cep - > name , " ip " ) )
;
else if ( ! strcmp ( cep - > name , " port " ) )
;
else if ( ! strcmp ( cep - > name , " options " ) )
{
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
{
NameValue * ofp ;
if ( ! nv_find_by_name ( _ListenerFlags , cepp - > name ) )
{
for ( h = Hooks [ HOOKTYPE_CONFIGRUN_EX ] ; h ; h = h - > next )
{
int value = ( * ( h - > func . intfunc ) ) ( conf , cepp , CONFIG_LISTEN_OPTIONS , listen ) ;
if ( value = = 1 )
break ;
}
}
}
} else
if ( ! strcmp ( cep - > name , " ssl-options " ) | | ! strcmp ( cep - > name , " tls-options " ) )
;
else
{
for ( h = Hooks [ HOOKTYPE_CONFIGRUN_EX ] ; h ; h = h - > next )
{
int value = ( * ( h - > func . intfunc ) ) ( conf , cep , CONFIG_LISTEN , listen ) ;
if ( value = = 1 )
break ;
}
}
2020-03-29 09:16:53 +00:00
}
}
int _conf_listen ( ConfigFile * conf , ConfigEntry * ce )
{
2023-05-05 22:12:01 +00:00
ConfigEntry * cep , * cepp ;
2020-03-29 09:16:53 +00:00
ConfigEntry * tlsconfig = NULL ;
2022-04-03 15:09:29 +00:00
char * file = NULL ;
2020-03-29 09:16:53 +00:00
char * ip = NULL ;
2023-05-05 22:12:01 +00:00
char * spoof_ip = NULL ;
int start = 0 , end = 0 , port ;
int listener_flags = 0 ;
2020-03-29 09:16:53 +00:00
Hook * h ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-04-03 15:09:29 +00:00
if ( ! strcmp ( cep - > name , " file " ) )
{
2023-05-05 22:12:01 +00:00
convert_to_absolute_path ( & cep - > value , PERMDATADIR ) ;
2022-04-03 15:09:29 +00:00
file = cep - > value ;
} else
2023-05-05 22:12:01 +00:00
if ( ! strcmp ( cep - > name , " mode " ) )
{
// Handled elsewhere, but need to be caught here as noop
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " ip " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
ip = cep - > value ;
2020-03-29 09:16:53 +00:00
} else
2023-05-05 22:12:01 +00:00
if ( ! strcmp ( cep - > name , " spoof-ip " ) )
{
spoof_ip = cep - > value ;
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " port " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
port_range ( cep - > value , & start , & end ) ;
2020-03-29 09:16:53 +00:00
if ( ( start < 0 ) | | ( start > 65535 ) | | ( end < 0 ) | | ( end > 65535 ) )
return - 1 ; /* this is already validated in _test_listen, but okay.. */
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " options " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
long v ;
if ( ( v = nv_find_by_name ( _ListenerFlags , cepp - > name ) ) )
2020-03-29 09:16:53 +00:00
{
2023-05-05 22:12:01 +00:00
listener_flags | = v ;
2020-03-29 09:16:53 +00:00
} else {
for ( h = Hooks [ HOOKTYPE_CONFIGRUN ] ; h ; h = h - > next )
{
int value = ( * ( h - > func . intfunc ) ) ( conf , cepp , CONFIG_LISTEN_OPTIONS ) ;
if ( value = = 1 )
break ;
}
}
}
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " ssl-options " ) | | ! strcmp ( cep - > name , " tls-options " ) )
2020-03-29 09:16:53 +00:00
{
tlsconfig = cep ;
} else
{
for ( h = Hooks [ HOOKTYPE_CONFIGRUN ] ; h ; h = h - > next )
{
int value = ( * ( h - > func . intfunc ) ) ( conf , cep , CONFIG_LISTEN ) ;
if ( value = = 1 )
break ;
}
}
}
2022-04-03 15:09:29 +00:00
2023-05-05 22:12:01 +00:00
/* UNIX domain socket */
2022-04-03 15:09:29 +00:00
if ( file )
{
2023-05-05 22:12:01 +00:00
conf_listen_configure ( file , 0 , SOCKET_TYPE_UNIX , listener_flags , ce , tlsconfig ) ;
2022-04-03 15:09:29 +00:00
return 1 ;
}
2020-03-29 09:16:53 +00:00
for ( port = start ; port < = end ; port + + )
{
/* First deal with IPv4 */
if ( ! strchr ( ip , ' : ' ) )
2023-05-05 22:12:01 +00:00
conf_listen_configure ( ip , port , SOCKET_TYPE_IPV4 , listener_flags , ce , tlsconfig ) ;
2020-03-29 09:16:53 +00:00
/* Then deal with IPv6 (if available/enabled) */
2023-05-05 22:12:01 +00:00
if ( ! DISABLE_IPV6 & & ( strchr ( ip , ' : ' ) | | ( * ip = = ' * ' ) ) )
conf_listen_configure ( ip , port , SOCKET_TYPE_IPV6 , listener_flags , ce , tlsconfig ) ;
2020-03-29 09:16:53 +00:00
}
2023-05-05 22:12:01 +00:00
2020-03-29 09:16:53 +00:00
return 1 ;
}
int _test_listen ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
ConfigEntry * cepp ;
int errors = 0 ;
2023-05-05 22:12:01 +00:00
char has_file = 0 , has_ip = 0 , has_port = 0 , has_options = 0 , port_6667 = 0 , has_spoof_ip = 0 ;
2022-04-03 15:09:29 +00:00
char * file = NULL ;
2020-03-29 09:16:53 +00:00
char * ip = NULL ;
Hook * h ;
2022-01-15 05:16:34 +00:00
if ( ce - > value )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: listen block has a new syntax, see https://www.unrealircd.org/docs/Listen_block " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
int used_by_module = 0 ;
/* First, check if a module knows about this listen::something */
for ( h = Hooks [ HOOKTYPE_CONFIGTEST ] ; h ; h = h - > next )
{
int value , errs = 0 ;
if ( h - > owner & & ! ( h - > owner - > flags & MODFLAG_TESTING )
& & ! ( h - > owner - > options & MOD_OPT_PERM ) )
{
continue ;
}
value = ( * ( h - > func . intfunc ) ) ( conf , cep , CONFIG_LISTEN , & errs ) ;
if ( value = = 2 )
used_by_module = 1 ;
if ( value = = 1 )
{
used_by_module = 1 ;
break ;
}
if ( value = = - 1 )
{
used_by_module = 1 ;
errors + = errs ;
break ;
}
if ( value = = - 2 )
{
used_by_module = 1 ;
errors + = errs ;
}
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " options " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_options )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " listen::options " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_options = 1 ;
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! nv_find_by_name ( _ListenerFlags , cepp - > name ) )
2020-03-29 09:16:53 +00:00
{
/* Check if a module knows about this listen::options::something */
int used_by_module = 0 ;
for ( h = Hooks [ HOOKTYPE_CONFIGTEST ] ; h ; h = h - > next )
{
int value , errs = 0 ;
if ( h - > owner & & ! ( h - > owner - > flags & MODFLAG_TESTING )
& & ! ( h - > owner - > options & MOD_OPT_PERM ) )
{
continue ;
}
value = ( * ( h - > func . intfunc ) ) ( conf , cepp , CONFIG_LISTEN_OPTIONS , & errs ) ;
if ( value = = 2 )
used_by_module = 1 ;
if ( value = = 1 )
{
used_by_module = 1 ;
break ;
}
if ( value = = - 1 )
{
used_by_module = 1 ;
errors + = errs ;
break ;
}
if ( value = = - 2 )
{
used_by_module = 1 ;
errors + = errs ;
}
}
if ( ! used_by_module )
{
2022-01-15 05:16:34 +00:00
config_error_unknownopt ( cepp - > file - > filename ,
cepp - > line_number , " listen::options " , cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " ssl " ) | | ! strcmp ( cepp - > name , " tls " ) )
2020-03-29 09:16:53 +00:00
have_tls_listeners = 1 ; /* for ssl config test */
}
}
else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " ssl-options " ) | | ! strcmp ( cep - > name , " tls-options " ) )
2020-03-29 09:16:53 +00:00
{
test_tlsblock ( conf , cep , & errors ) ;
}
else
2022-01-15 05:16:34 +00:00
if ( ! cep - > value )
2020-03-29 09:16:53 +00:00
{
if ( ! used_by_module )
{
2022-01-15 05:16:34 +00:00
config_error_empty ( cep - > file - > filename ,
cep - > line_number , " listen " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
continue ; /* always */
} else
2022-04-03 15:09:29 +00:00
if ( ! strcmp ( cep - > name , " file " ) )
{
has_file = 1 ;
file = cep - > value ;
} else
2023-05-05 22:12:01 +00:00
if ( ! strcmp ( cep - > name , " spoof-ip " ) )
{
has_spoof_ip = 1 ;
if ( ! is_valid_ip ( cep - > value ) )
{
config_error ( " %s:%i: listen::spoof-ip is not a valid IP address (%s) " ,
cep - > file - > filename , cep - > line_number , cep - > value ) ;
errors + + ;
}
} else
if ( ! strcmp ( cep - > name , " mode " ) )
{
int mode = strtol ( cep - > value , NULL , 8 ) ;
if ( ( mode ! = 0700 ) & & ( mode ! = 0770 ) & & ( mode ! = 0777 ) )
{
config_error ( " %s:%i: listen::mode must be one of: 0700 (user only, the default), "
" 0770 (user and group readable/writable), or "
" 0777 (world readable and writable, not recommended). " ,
cep - > file - > filename , cep - > line_number ) ;
errors + + ;
}
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " ip " ) )
2020-03-29 09:16:53 +00:00
{
has_ip = 1 ;
2022-01-15 05:16:34 +00:00
if ( strcmp ( cep - > value , " * " ) & & ! is_valid_ip ( cep - > value ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: listen: illegal listen::ip (%s). Must be either '*' or contain a valid IP. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , cep - > value ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
2022-01-15 05:16:34 +00:00
ip = cep - > value ;
2020-03-29 09:16:53 +00:00
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " host " ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: listen: unknown option listen::host, did you mean listen::ip? " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " port " ) )
2020-03-29 09:16:53 +00:00
{
int start = 0 , end = 0 ;
has_port = 1 ;
2022-01-15 05:16:34 +00:00
port_range ( cep - > value , & start , & end ) ;
2020-03-29 09:16:53 +00:00
if ( start = = end )
{
if ( ( start < 1 ) | | ( start > 65535 ) )
{
config_error ( " %s:%i: listen: illegal port (must be 1..65535) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
}
else
{
if ( end < start )
{
config_error ( " %s:%i: listen: illegal port range end value is less than starting value " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
if ( end - start > = 100 )
{
config_error ( " %s:%i: listen: you requested port %d-%d, that's %d ports "
" (and thus consumes %d sockets) this is probably not what you want. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , start , end ,
2020-03-29 09:16:53 +00:00
end - start + 1 , end - start + 1 ) ;
return 1 ;
}
if ( ( start < 1 ) | | ( start > 65535 ) | | ( end < 1 ) | | ( end > 65535 ) )
{
config_error ( " %s:%i: listen: illegal port range values must be between 1 and 65535 " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
}
if ( ( 6667 > = start ) & & ( 6667 < = end ) )
port_6667 = 1 ;
} else
{
if ( ! used_by_module )
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename , cep - > line_number ,
" listen " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
continue ; /* always */
}
}
2022-04-03 15:09:29 +00:00
if ( has_file )
2020-03-29 09:16:53 +00:00
{
2022-04-03 15:09:29 +00:00
if ( has_ip | | has_port )
{
config_error ( " %s:%d: listen block should either have a 'file' (for *NIX domain socket), "
" OR have an 'ip' and 'port' (for IPv4/IPv6). You cannot combine both in one listen block. " ,
ce - > file - > filename , ce - > line_number ) ;
errors + + ;
} else {
// TODO: check if file can be created fresh etc.
}
} else
2020-03-29 09:16:53 +00:00
{
2022-04-03 15:09:29 +00:00
if ( ! has_ip )
{
config_error ( " %s:%d: listen block requires an listen::ip " ,
ce - > file - > filename , ce - > line_number ) ;
errors + + ;
}
if ( ! has_port )
{
config_error ( " %s:%d: listen block requires an listen::port " ,
ce - > file - > filename , ce - > line_number ) ;
errors + + ;
}
2020-03-29 09:16:53 +00:00
}
2023-05-05 22:12:01 +00:00
if ( has_spoof_ip & & ! has_file )
{
config_error ( " %s:%d: listen::spoof-ip is only valid when listen::file is used (UNIX domain sockets) " ,
ce - > file - > filename , ce - > line_number ) ;
errors + + ;
}
2020-03-29 09:16:53 +00:00
if ( port_6667 )
safe_strdup ( port_6667_ip , ip ) ;
requiredstuff . conf_listen = 1 ;
return errors ;
}
int _conf_allow ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep , * cepp ;
ConfigItem_allow * allow ;
Hook * h ;
2022-01-15 05:16:34 +00:00
if ( ce - > value )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ce - > value , " channel " ) )
2020-03-29 09:16:53 +00:00
return ( _conf_allow_channel ( conf , ce ) ) ;
else
{
int value ;
for ( h = Hooks [ HOOKTYPE_CONFIGRUN ] ; h ; h = h - > next )
{
value = ( * ( h - > func . intfunc ) ) ( conf , ce , CONFIG_ALLOW ) ;
if ( value = = 1 )
break ;
}
return 0 ;
}
}
allow = safe_alloc ( sizeof ( ConfigItem_allow ) ) ;
2022-01-15 05:16:34 +00:00
allow - > ipv6_clone_mask = tempiConf . default_ipv6_clone_mask ;
2022-11-20 04:12:40 +00:00
allow - > match = safe_alloc ( sizeof ( SecurityGroup ) ) ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
if ( ! strcmp ( cep - > name , " match " ) | | ! strcmp ( cep - > name , " mask " ) | | ! strcmp ( cep - > name , " ip " ) | | ! strcmp ( cep - > name , " hostname " ) )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
conf_match_block ( conf , cep , & allow - > match ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " password " ) )
2020-03-29 09:16:53 +00:00
allow - > auth = AuthBlockToAuthConfig ( cep ) ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " class " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
allow - > class = find_class ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ! allow - > class | | ( allow - > class - > flag . temporary = = 1 ) )
{
config_status ( " %s:%i: illegal allow::class, unknown class '%s' using default of class 'default' " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename ,
cep - > line_number ,
cep - > value ) ;
2020-03-29 09:16:53 +00:00
allow - > class = default_class ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " maxperip " ) )
allow - > maxperip = atoi ( cep - > value ) ;
else if ( ! strcmp ( cep - > name , " global-maxperip " ) )
allow - > global_maxperip = atoi ( cep - > value ) ;
else if ( ! strcmp ( cep - > name , " redirect-server " ) )
safe_strdup ( allow - > server , cep - > value ) ;
else if ( ! strcmp ( cep - > name , " redirect-port " ) )
allow - > port = atoi ( cep - > value ) ;
else if ( ! strcmp ( cep - > name , " ipv6-clone-mask " ) )
2020-03-29 09:16:53 +00:00
{
/*
* If this item isn ' t set explicitly by the
* user , the value will temporarily be
2022-01-15 05:16:34 +00:00
* zero . Defaults are applied in config_run_blocks ( ) .
2020-03-29 09:16:53 +00:00
*/
2022-01-15 05:16:34 +00:00
allow - > ipv6_clone_mask = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " options " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " noident " ) )
2020-03-29 09:16:53 +00:00
allow - > flags . noident = 1 ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " useip " ) )
2020-03-29 09:16:53 +00:00
allow - > flags . useip = 1 ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " ssl " ) | | ! strcmp ( cepp - > name , " tls " ) )
2020-03-29 09:16:53 +00:00
allow - > flags . tls = 1 ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " reject-on-auth-failure " ) )
2021-01-08 23:15:08 +00:00
allow - > flags . reject_on_auth_failure = 1 ;
2020-03-29 09:16:53 +00:00
}
}
}
2021-03-21 17:05:35 +00:00
/* Default: global-maxperip = maxperip+1 */
if ( allow - > global_maxperip = = 0 )
allow - > global_maxperip = allow - > maxperip + 1 ;
/* global-maxperip < maxperip makes no sense */
if ( allow - > global_maxperip < allow - > maxperip )
allow - > global_maxperip = allow - > maxperip ;
2020-03-29 09:16:53 +00:00
AddListItem ( allow , conf_allow ) ;
return 1 ;
}
int _test_allow ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep , * cepp ;
int errors = 0 ;
Hook * h ;
2022-11-20 04:12:40 +00:00
char has_ip = 0 , has_hostname = 0 , has_mask = 0 , has_match = 0 ;
2022-01-15 05:16:34 +00:00
char has_maxperip = 0 , has_global_maxperip = 0 , has_password = 0 , has_class = 0 ;
2020-03-29 09:16:53 +00:00
char has_redirectserver = 0 , has_redirectport = 0 , has_options = 0 ;
int hostname_possible_silliness = 0 ;
2022-01-15 05:16:34 +00:00
if ( ce - > value )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ce - > value , " channel " ) )
2020-03-29 09:16:53 +00:00
return ( _test_allow_channel ( conf , ce ) ) ;
else
{
int used = 0 ;
for ( h = Hooks [ HOOKTYPE_CONFIGTEST ] ; h ; h = h - > next )
{
int value , errs = 0 ;
if ( h - > owner & & ! ( h - > owner - > flags & MODFLAG_TESTING )
& & ! ( h - > owner - > options & MOD_OPT_PERM ) )
continue ;
value = ( * ( h - > func . intfunc ) ) ( conf , ce , CONFIG_ALLOW , & errs ) ;
if ( value = = 2 )
used = 1 ;
if ( value = = 1 )
{
used = 1 ;
break ;
}
if ( value = = - 1 )
{
used = 1 ;
errors + = errs ;
break ;
}
if ( value = = - 2 )
{
used = 1 ;
errors + = errs ;
}
}
if ( ! used ) {
config_error ( " %s:%i: allow item with unknown type " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
return errors ;
}
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( strcmp ( cep - > name , " options " ) & &
2022-11-20 04:12:40 +00:00
strcmp ( cep - > name , " match " ) & &
2022-01-15 05:16:34 +00:00
strcmp ( cep - > name , " mask " ) & &
config_is_blankorempty ( cep , " allow " ) )
2020-03-29 09:16:53 +00:00
{
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " ip " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_ip )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " allow::ip " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_ip = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " hostname " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( has_hostname )
{
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " allow::hostname " ) ;
continue ;
}
has_hostname = 1 ;
if ( ! strcmp ( cep - > value , " *@* " ) | | ! strcmp ( cep - > value , " * " ) )
hostname_possible_silliness = 1 ;
}
else if ( ! strcmp ( cep - > name , " mask " ) )
{
has_mask = 1 ;
2022-11-20 04:12:40 +00:00
test_match_block ( conf , cep , & errors ) ;
}
else if ( ! strcmp ( cep - > name , " match " ) )
{
has_match = 1 ;
test_match_block ( conf , cep , & errors ) ;
2022-01-15 05:16:34 +00:00
}
else if ( ! strcmp ( cep - > name , " maxperip " ) )
{
int v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( has_maxperip )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " allow::maxperip " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_maxperip = 1 ;
2021-03-21 17:05:35 +00:00
if ( ( v < = 0 ) | | ( v > 1000000 ) )
{
config_error ( " %s:%i: allow::maxperip with illegal value (must be 1-1000000) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2021-03-21 17:05:35 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " global-maxperip " ) )
2021-03-21 17:05:35 +00:00
{
2022-01-15 05:16:34 +00:00
int v = atoi ( cep - > value ) ;
2021-03-21 17:05:35 +00:00
if ( has_global_maxperip )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " allow::global-maxperip " ) ;
2021-03-21 17:05:35 +00:00
continue ;
}
has_global_maxperip = 1 ;
if ( ( v < = 0 ) | | ( v > 1000000 ) )
{
config_error ( " %s:%i: allow::global-maxperip with illegal value (must be 1-1000000) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ipv6-clone-mask " ) )
2020-03-29 09:16:53 +00:00
{
/* keep this in sync with _test_set() */
int ipv6mask ;
2022-01-15 05:16:34 +00:00
ipv6mask = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ipv6mask = = 0 )
{
config_error ( " %s:%d: allow::ipv6-clone-mask given a value of zero. This cannnot be correct, as it would treat all IPv6 hosts as one host. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
if ( ipv6mask > 128 )
{
config_error ( " %s:%d: set::default-ipv6-clone-mask was set to %d. The maximum value is 128. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ,
2020-03-29 09:16:53 +00:00
ipv6mask ) ;
errors + + ;
}
if ( ipv6mask < = 32 )
{
config_warn ( " %s:%d: allow::ipv6-clone-mask was given a very small value. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " password " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_password )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " allow::password " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_password = 1 ;
/* some auth check stuff? */
if ( Auth_CheckError ( cep ) < 0 )
errors + + ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " class " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_class )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " allow::class " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_class = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " redirect-server " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_redirectserver )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " allow::redirect-server " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_redirectserver = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " redirect-port " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_redirectport )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " allow::redirect-port " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_redirectport = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " options " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_options )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " allow::options " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_options = 1 ;
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " noident " ) )
2020-03-29 09:16:53 +00:00
{ }
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " useip " ) )
2020-03-29 09:16:53 +00:00
{ }
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " ssl " ) | | ! strcmp ( cepp - > name , " tls " ) )
2020-03-29 09:16:53 +00:00
{ }
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " reject-on-auth-failure " ) )
2021-01-08 23:15:08 +00:00
{ }
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " sasl " ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%d: The option allow::options::sasl no longer exists. "
" Please use a require authentication { } block instead, which "
" is more flexible and provides the same functionality. See "
" https://www.unrealircd.org/docs/Require_authentication_block " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
else
{
2022-01-15 05:16:34 +00:00
config_error_unknownopt ( cepp - > file - > filename ,
cepp - > line_number , " allow " , cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
}
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename , cep - > line_number ,
" allow " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
2022-11-20 04:12:40 +00:00
if ( ( has_mask | | has_match ) & & ( has_ip | | has_hostname ) )
2022-01-15 05:16:34 +00:00
{
2022-11-20 04:12:40 +00:00
config_error ( " %s:%d: The allow block uses allow::match, but you also have an allow::ip and allow::hostname. " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2022-11-20 04:12:40 +00:00
config_error ( " Please delete your allow::ip and allow::hostname entries and/or integrate them into allow::match " ) ;
2022-01-15 05:16:34 +00:00
} else
if ( has_ip )
{
2022-11-20 04:12:40 +00:00
config_warn ( " %s:%d: The allow block uses allow::match nowadays. Rename your allow::ip item to allow::match. " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
config_warn ( " See https://www.unrealircd.org/docs/FAQ#allow-mask for more information " ) ;
} else
if ( has_hostname )
{
2022-11-20 04:12:40 +00:00
config_warn ( " %s:%d: The allow block uses allow::match nowadays. Rename your allow::hostname item to allow::match. " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
config_warn ( " See https://www.unrealircd.org/docs/FAQ#allow-mask for more information " ) ;
} else
2022-11-20 04:12:40 +00:00
if ( has_mask & & has_match )
{
config_error ( " %s:%d: You cannot have both ::mask and ::match. You should only use allow::match. " ,
ce - > file - > filename , ce - > line_number ) ;
errors + + ;
} else
if ( ! has_match & & ! has_mask )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
config_error ( " %s:%d: allow block needs an allow::match " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
if ( has_ip & & has_hostname )
{
2022-01-15 05:16:34 +00:00
config_error ( " %s:%d: allow block has both allow::ip and allow::hostname, this is no longer permitted. " ,
ce - > file - > filename , ce - > line_number ) ;
config_error ( " Please integrate your allow::ip and allow::hostname items into a single allow::mask block " ) ;
errors + + ;
2020-03-29 09:16:53 +00:00
} else
if ( hostname_possible_silliness )
{
2022-01-15 05:16:34 +00:00
config_error ( " %s:%d: allow block contains 'hostname *;'. This means means that users "
" without a valid hostname (unresolved IP's) will be unable to connect. "
" You most likely want to use 'mask *;' instead. " ,
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
}
if ( ! has_class )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" allow::class " ) ;
errors + + ;
}
if ( ! has_maxperip )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" allow::maxperip " ) ;
errors + + ;
}
return errors ;
}
int _conf_allow_channel ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigItem_allow_channel * allow = NULL ;
ConfigEntry * cep ;
char * class = NULL ;
2022-11-20 04:12:40 +00:00
ConfigEntry * match = NULL ;
2020-03-29 09:16:53 +00:00
/* First, search for ::class, if any */
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " class " ) )
class = cep - > value ;
2022-11-20 04:12:40 +00:00
else if ( ! strcmp ( cep - > name , " match " ) | | ! strcmp ( cep - > name , " mask " ) )
match = cep ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " channel " ) )
2020-03-29 09:16:53 +00:00
{
/* This way, we permit multiple ::channel items in one allow block */
allow = safe_alloc ( sizeof ( ConfigItem_allow_channel ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( allow - > channel , cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( class )
safe_strdup ( allow - > class , class ) ;
2022-11-20 04:12:40 +00:00
if ( match )
conf_match_block ( conf , match , & allow - > match ) ;
2020-03-29 09:16:53 +00:00
AddListItem ( allow , conf_allow_channel ) ;
}
}
return 1 ;
}
int _test_allow_channel ( ConfigFile * conf , ConfigEntry * ce )
{
2022-11-20 04:12:40 +00:00
ConfigEntry * cep ;
int errors = 0 ;
char has_match = 0 , has_mask = 0 , has_channel = 0 , has_class = 0 ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " allow channel " ) )
{
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " channel " ) )
2020-03-29 09:16:53 +00:00
{
has_channel = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " class " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_class )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " allow channel::class " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_class = 1 ;
}
2022-11-20 04:12:40 +00:00
else if ( ! strcmp ( cep - > name , " match " ) )
{
has_match = 1 ;
test_match_block ( conf , cep , & errors ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
has_mask = 1 ;
test_match_block ( conf , cep , & errors ) ;
2020-03-29 09:16:53 +00:00
}
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename , cep - > line_number ,
" allow channel " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-11-20 04:12:40 +00:00
if ( has_mask & & has_match )
{
config_error ( " %s:%d: You cannot have both ::mask and ::match. "
" You should only use %s::match. " ,
ce - > file - > filename , ce - > line_number , ce - > name ) ;
errors + + ;
}
2020-03-29 09:16:53 +00:00
if ( ! has_channel )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" allow channel::channel " ) ;
errors + + ;
}
return errors ;
}
int _conf_except ( ConfigFile * conf , ConfigEntry * ce )
{
Hook * h ;
int value ;
for ( h = Hooks [ HOOKTYPE_CONFIGRUN ] ; h ; h = h - > next )
{
value = ( * ( h - > func . intfunc ) ) ( conf , ce , CONFIG_EXCEPT ) ;
if ( value = = 1 )
break ;
}
return 1 ;
}
int _test_except ( ConfigFile * conf , ConfigEntry * ce )
{
int errors = 0 ;
Hook * h ;
int used = 0 ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: except without type " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ce - > value , " tkl " ) )
2020-03-29 09:16:53 +00:00
{
config_warn ( " %s:%i: except tkl { } is now called except ban { }. "
" Simply rename the block from 'except tkl' to 'except ban' "
" to get rid of this warning. " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
safe_strdup ( ce - > value , " ban " ) ; /* awww */
2020-03-29 09:16:53 +00:00
}
for ( h = Hooks [ HOOKTYPE_CONFIGTEST ] ; h ; h = h - > next )
{
int value , errs = 0 ;
if ( h - > owner & & ! ( h - > owner - > flags & MODFLAG_TESTING )
& & ! ( h - > owner - > options & MOD_OPT_PERM ) )
continue ;
value = ( * ( h - > func . intfunc ) ) ( conf , ce , CONFIG_EXCEPT , & errs ) ;
if ( value = = 2 )
used = 1 ;
if ( value = = 1 )
{
used = 1 ;
break ;
}
if ( value = = - 1 )
{
used = 1 ;
errors + = errs ;
break ;
}
if ( value = = - 2 )
{
used = 1 ;
errors + = errs ;
}
}
if ( ! used )
{
config_error ( " %s:%i: unknown except type %s " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ,
ce - > value ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
return errors ;
}
/*
* vhost { } block parser
*/
int _conf_vhost ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigItem_vhost * vhost ;
ConfigEntry * cep , * cepp ;
vhost = safe_alloc ( sizeof ( ConfigItem_vhost ) ) ;
2022-11-20 04:12:40 +00:00
vhost - > match = safe_alloc ( sizeof ( SecurityGroup ) ) ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " vhost " ) )
2020-03-29 09:16:53 +00:00
{
char * user , * host ;
2022-01-15 05:16:34 +00:00
user = strtok ( cep - > value , " @ " ) ;
2020-03-29 09:16:53 +00:00
host = strtok ( NULL , " " ) ;
if ( ! host )
safe_strdup ( vhost - > virthost , user ) ;
else
{
safe_strdup ( vhost - > virtuser , user ) ;
safe_strdup ( vhost - > virthost , host ) ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " login " ) )
safe_strdup ( vhost - > login , cep - > value ) ;
else if ( ! strcmp ( cep - > name , " password " ) )
2020-03-29 09:16:53 +00:00
vhost - > auth = AuthBlockToAuthConfig ( cep ) ;
2022-11-20 04:12:40 +00:00
else if ( ! strcmp ( cep - > name , " match " ) | | ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
conf_match_block ( conf , cep , & vhost - > match ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " swhois " ) )
2020-03-29 09:16:53 +00:00
{
SWhois * s ;
2022-01-15 05:16:34 +00:00
if ( cep - > items )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
s = safe_alloc ( sizeof ( SWhois ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( s - > line , cepp - > name ) ;
2020-03-29 09:16:53 +00:00
safe_strdup ( s - > setby , " vhost " ) ;
AddListItem ( s , vhost - > swhois ) ;
}
} else
2022-01-15 05:16:34 +00:00
if ( cep - > value )
2020-03-29 09:16:53 +00:00
{
s = safe_alloc ( sizeof ( SWhois ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( s - > line , cep - > value ) ;
2020-03-29 09:16:53 +00:00
safe_strdup ( s - > setby , " vhost " ) ;
AddListItem ( s , vhost - > swhois ) ;
}
}
}
AddListItem ( vhost , conf_vhost ) ;
return 1 ;
}
int _test_vhost ( ConfigFile * conf , ConfigEntry * ce )
{
int errors = 0 ;
ConfigEntry * cep ;
2022-11-20 04:12:40 +00:00
char has_vhost = 0 , has_login = 0 , has_password = 0 , has_mask = 0 , has_match = 0 ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " vhost " ) )
2020-03-29 09:16:53 +00:00
{
char * at , * tmp , * host ;
if ( has_vhost )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " vhost::vhost " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_vhost = 1 ;
2022-01-15 05:16:34 +00:00
if ( ! cep - > value )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_empty ( cep - > file - > filename ,
cep - > line_number , " vhost " , " vhost " ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
2023-05-05 22:12:01 +00:00
if ( ! valid_vhost ( cep - > value ) )
2020-03-29 09:16:53 +00:00
{
2023-05-05 22:12:01 +00:00
config_error ( " %s:%i: oper::vhost contains illegal characters or is too long: '%s' " ,
cep - > file - > filename , cep - > line_number , cep - > value ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " login " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_login )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " vhost::login " ) ;
2020-03-29 09:16:53 +00:00
}
has_login = 1 ;
2022-01-15 05:16:34 +00:00
if ( ! cep - > value )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_empty ( cep - > file - > filename ,
cep - > line_number , " vhost " , " login " ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " password " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_password )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " vhost::password " ) ;
2020-03-29 09:16:53 +00:00
}
has_password = 1 ;
2022-01-15 05:16:34 +00:00
if ( ! cep - > value )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_empty ( cep - > file - > filename ,
cep - > line_number , " vhost " , " password " ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
if ( Auth_CheckError ( cep ) < 0 )
errors + + ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
has_mask = 1 ;
2022-11-20 04:12:40 +00:00
test_match_block ( conf , cep , & errors ) ;
}
else if ( ! strcmp ( cep - > name , " match " ) )
{
has_match = 1 ;
test_match_block ( conf , cep , & errors ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " swhois " ) )
2020-03-29 09:16:53 +00:00
{
/* multiple is ok */
}
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename , cep - > line_number ,
" vhost " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
if ( ! has_vhost )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" vhost::vhost " ) ;
errors + + ;
}
if ( ! has_login )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" vhost::login " ) ;
errors + + ;
}
if ( ! has_password )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" vhost::password " ) ;
errors + + ;
}
2022-11-20 04:12:40 +00:00
if ( ! has_mask & & ! has_match )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2022-11-20 04:12:40 +00:00
" vhost::match " ) ;
errors + + ;
}
if ( has_mask & & has_match )
{
config_error ( " %s:%d: You cannot have both ::mask and ::match. "
" You should only use %s::match. " ,
ce - > file - > filename , ce - > line_number , ce - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
return errors ;
}
int _test_sni ( ConfigFile * conf , ConfigEntry * ce )
{
int errors = 0 ;
ConfigEntry * cep ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: sni block needs a name, eg: sni irc.xyz.com { " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " ssl-options " ) | | ! strcmp ( cep - > name , " tls-options " ) )
2020-03-29 09:16:53 +00:00
{
test_tlsblock ( conf , cep , & errors ) ;
} else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename , cep - > line_number ,
" sni " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
return errors ;
}
int _conf_sni ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
ConfigEntry * tlsconfig = NULL ;
char * name ;
ConfigItem_sni * sni = NULL ;
2022-01-15 05:16:34 +00:00
name = ce - > value ;
2020-03-29 09:16:53 +00:00
if ( ! name )
return 0 ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " ssl-options " ) | | ! strcmp ( cep - > name , " tls-options " ) )
2020-03-29 09:16:53 +00:00
{
tlsconfig = cep ;
}
}
if ( ! tlsconfig )
return 0 ;
sni = safe_alloc ( sizeof ( ConfigItem_listen ) ) ;
safe_strdup ( sni - > name , name ) ;
sni - > tls_options = safe_alloc ( sizeof ( TLSOptions ) ) ;
conf_tlsblock ( conf , tlsconfig , sni - > tls_options ) ;
sni - > ssl_ctx = init_ctx ( sni - > tls_options , 1 ) ;
AddListItem ( sni , conf_sni ) ;
return 1 ;
}
int _conf_help ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
ConfigItem_help * ca ;
MOTDLine * last = NULL , * temp ;
ca = safe_alloc ( sizeof ( ConfigItem_help ) ) ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
ca - > command = NULL ;
else
2022-01-15 05:16:34 +00:00
safe_strdup ( ca - > command , ce - > value ) ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
temp = safe_alloc ( sizeof ( MOTDLine ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( temp - > line , cep - > name ) ;
2020-03-29 09:16:53 +00:00
temp - > next = NULL ;
if ( ! last )
ca - > text = temp ;
else
last - > next = temp ;
last = temp ;
}
AddListItem ( ca , conf_help ) ;
return 1 ;
}
int _test_help ( ConfigFile * conf , ConfigEntry * ce ) {
int errors = 0 ;
ConfigEntry * cep ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > items )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: empty help block " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( strlen ( cep - > name ) > 500 )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: oversized help item " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
return errors ;
}
int _conf_link ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep , * cepp , * ceppp ;
ConfigItem_link * link = NULL ;
link = safe_alloc ( sizeof ( ConfigItem_link ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( link - > servername , ce - > value ) ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " incoming " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
if ( ! strcmp ( cepp - > name , " match " ) | | ! strcmp ( cepp - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
conf_match_block ( conf , cepp , & link - > incoming . match ) ;
2020-03-29 09:16:53 +00:00
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " outgoing " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " bind-ip " ) )
safe_strdup ( link - > outgoing . bind_ip , cepp - > value ) ;
2022-11-20 04:12:40 +00:00
else if ( ! strcmp ( cepp - > name , " file " ) )
safe_strdup ( link - > outgoing . file , cepp - > value ) ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " hostname " ) )
safe_strdup ( link - > outgoing . hostname , cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " port " ) )
link - > outgoing . port = atoi ( cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " options " ) )
2020-03-29 09:16:53 +00:00
{
link - > outgoing . options = 0 ;
2022-01-15 05:16:34 +00:00
for ( ceppp = cepp - > items ; ceppp ; ceppp = ceppp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
long v ;
if ( ( v = nv_find_by_name ( _LinkFlags , ceppp - > name ) ) )
link - > outgoing . options | = v ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " ssl-options " ) | | ! strcmp ( cepp - > name , " tls-options " ) )
2020-03-29 09:16:53 +00:00
{
link - > tls_options = safe_alloc ( sizeof ( TLSOptions ) ) ;
conf_tlsblock ( conf , cepp , link - > tls_options ) ;
link - > ssl_ctx = init_ctx ( link - > tls_options , 0 ) ;
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " password " ) )
2020-03-29 09:16:53 +00:00
link - > auth = AuthBlockToAuthConfig ( cep ) ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " hub " ) )
safe_strdup ( link - > hub , cep - > value ) ;
else if ( ! strcmp ( cep - > name , " leaf " ) )
safe_strdup ( link - > leaf , cep - > value ) ;
else if ( ! strcmp ( cep - > name , " leaf-depth " ) | | ! strcmp ( cep - > name , " leafdepth " ) )
link - > leaf_depth = atoi ( cep - > value ) ;
else if ( ! strcmp ( cep - > name , " class " ) )
{
link - > class = find_class ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ! link - > class | | ( link - > class - > flag . temporary = = 1 ) )
{
config_status ( " %s:%i: illegal link::class, unknown class '%s' using default of class 'default' " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename ,
cep - > line_number ,
cep - > value ) ;
2020-03-29 09:16:53 +00:00
link - > class = default_class ;
}
link - > class - > xrefcount + + ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " verify-certificate " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
link - > verify_certificate = config_checkval ( cep - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " options " ) )
2020-03-29 09:16:53 +00:00
{
link - > options = 0 ;
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
long v ;
if ( ( v = nv_find_by_name ( _LinkFlags , cepp - > name ) ) )
link - > options | = v ;
2020-03-29 09:16:53 +00:00
}
}
}
/* The default is 'hub *', unless you specify leaf or hub manually. */
if ( ! link - > hub & & ! link - > leaf )
safe_strdup ( link - > hub , " * " ) ;
2022-01-15 05:16:34 +00:00
AppendListItem ( link , conf_link ) ;
2020-03-29 09:16:53 +00:00
return 0 ;
}
/** Helper function for erroring on duplicate items.
*/
int config_detect_duplicate ( int * var , ConfigEntry * ce , int * errors )
{
if ( * var )
{
config_error ( " %s:%d: Duplicate %s directive " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ,
ce - > name ) ;
2020-03-29 09:16:53 +00:00
( * errors ) + + ;
return 1 ;
} else {
* var = 1 ;
}
return 0 ;
}
int _test_link ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep , * cepp , * ceppp ;
int errors = 0 ;
2022-11-20 04:12:40 +00:00
int has_incoming = 0 , has_incoming_mask = 0 , has_incoming_match = 0 , has_outgoing = 0 , has_outgoing_file = 0 ;
2020-03-29 09:16:53 +00:00
int has_outgoing_bind_ip = 0 , has_outgoing_hostname = 0 , has_outgoing_port = 0 ;
int has_outgoing_options = 0 , has_hub = 0 , has_leaf = 0 , has_leaf_depth = 0 ;
int has_password = 0 , has_class = 0 , has_options = 0 ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: link without servername. Expected: link servername { ... } " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
2022-01-15 05:16:34 +00:00
if ( ! strchr ( ce - > value , ' . ' ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: link: bogus server name. Expected: link servername { ... } " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " incoming " ) )
2020-03-29 09:16:53 +00:00
{
config_detect_duplicate ( & has_incoming , cep , & errors ) ;
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
if ( ! strcmp ( cepp - > name , " match " ) )
{
if ( cepp - > value | | cepp - > items )
{
has_incoming_match = 1 ;
test_match_block ( conf , cepp , & errors ) ;
} else
if ( config_is_blankorempty ( cepp , " link::incoming " ) )
{
errors + + ;
continue ;
}
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( cepp - > value | | cepp - > items )
2022-11-20 04:12:40 +00:00
{
2020-03-29 09:16:53 +00:00
has_incoming_mask = 1 ;
2022-11-20 04:12:40 +00:00
test_match_block ( conf , cepp , & errors ) ;
} else
2020-03-29 09:16:53 +00:00
if ( config_is_blankorempty ( cepp , " link::incoming " ) )
{
errors + + ;
continue ;
}
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " outgoing " ) )
2020-03-29 09:16:53 +00:00
{
config_detect_duplicate ( & has_outgoing , cep , & errors ) ;
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " bind-ip " ) )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cepp , " link::outgoing " ) )
{
errors + + ;
continue ;
}
config_detect_duplicate ( & has_outgoing_bind_ip , cepp , & errors ) ;
// todo: ipv4 vs ipv6
}
2022-11-20 04:12:40 +00:00
else if ( ! strcmp ( cepp - > name , " file " ) )
{
if ( config_is_blankorempty ( cepp , " link::outgoing " ) )
{
errors + + ;
continue ;
}
config_detect_duplicate ( & has_outgoing_file , cepp , & errors ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " hostname " ) )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cepp , " link::outgoing " ) )
{
errors + + ;
continue ;
}
config_detect_duplicate ( & has_outgoing_hostname , cepp , & errors ) ;
2022-01-15 05:16:34 +00:00
if ( strchr ( cepp - > value , ' * ' ) | | strchr ( cepp - > value , ' ? ' ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: hostname in link::outgoing(!) cannot contain wildcards " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " port " ) )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cepp , " link::outgoing " ) )
{
errors + + ;
continue ;
}
config_detect_duplicate ( & has_outgoing_port , cepp , & errors ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " options " ) )
2020-03-29 09:16:53 +00:00
{
config_detect_duplicate ( & has_outgoing_options , cepp , & errors ) ;
2022-01-15 05:16:34 +00:00
for ( ceppp = cepp - > items ; ceppp ; ceppp = ceppp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ceppp - > name , " autoconnect " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " ssl " ) | | ! strcmp ( ceppp - > name , " tls " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " insecure " ) )
2020-03-29 09:16:53 +00:00
;
else
{
2022-01-15 05:16:34 +00:00
config_error_unknownopt ( ceppp - > file - > filename ,
ceppp - > line_number , " link::outgoing " , ceppp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " ssl-options " ) | | ! strcmp ( cepp - > name , " tls-options " ) )
2020-03-29 09:16:53 +00:00
{
test_tlsblock ( conf , cepp , & errors ) ;
}
else
{
config_error ( " %s:%d: Unknown directive '%s' " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number ,
2020-03-29 09:16:53 +00:00
config_var ( cepp ) ) ;
errors + + ;
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " password " ) )
2020-03-29 09:16:53 +00:00
{
config_detect_duplicate ( & has_password , cep , & errors ) ;
if ( Auth_CheckError ( cep ) < 0 )
{
errors + + ;
} else {
AuthConfig * auth = AuthBlockToAuthConfig ( cep ) ;
/* hm. would be nicer if handled @auth-system I think. ah well.. */
if ( ( auth - > type ! = AUTHTYPE_PLAINTEXT ) & & ( auth - > type ! = AUTHTYPE_TLS_CLIENTCERT ) & &
( auth - > type ! = AUTHTYPE_TLS_CLIENTCERTFP ) & & ( auth - > type ! = AUTHTYPE_SPKIFP ) )
{
config_error ( " %s:%i: password in link block should be plaintext OR should be the "
2022-01-15 05:16:34 +00:00
" certificate or SPKI fingerprint of the remote link (=better) " ,
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
Auth_FreeAuthConfig ( auth ) ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " hub " ) )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " link " ) )
{
errors + + ;
continue ;
}
config_detect_duplicate ( & has_hub , cep , & errors ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " leaf " ) )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " link " ) )
{
errors + + ;
continue ;
}
config_detect_duplicate ( & has_leaf , cep , & errors ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " leaf-depth " ) | | ! strcmp ( cep - > name , " leafdepth " ) )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " link " ) )
{
errors + + ;
continue ;
}
config_detect_duplicate ( & has_leaf_depth , cep , & errors ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " class " ) )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " link " ) )
{
errors + + ;
continue ;
}
config_detect_duplicate ( & has_class , cep , & errors ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ciphers " ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%d: link::ciphers has been moved to link::outgoing::ssl-options::ciphers, "
" see https://www.unrealircd.org/docs/FAQ#link::ciphers_no_longer_works " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " verify-certificate " ) )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " link " ) )
{
errors + + ;
continue ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " options " ) )
2020-03-29 09:16:53 +00:00
{
config_detect_duplicate ( & has_options , cep , & errors ) ;
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " quarantine " ) )
2020-03-29 09:16:53 +00:00
;
else
{
config_error ( " %s:%d: link::options only has one possible option ('quarantine', rarely used). "
" Option '%s' is unrecognized. "
" Perhaps you meant to set an outgoing option in link::outgoing::options instead? " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number , cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
}
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename ,
cep - > line_number , " link " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
if ( ! has_incoming & & ! has_outgoing )
{
config_error ( " %s:%d: link block needs at least an incoming or outgoing section. " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
if ( has_incoming )
{
/* If we have an incoming sub-block then we need at least 'mask' and 'password' */
2022-11-20 04:12:40 +00:00
if ( ! has_incoming_mask & & ! has_incoming_match )
{
config_error_missing ( ce - > file - > filename , ce - > line_number , " link::incoming::match " ) ;
errors + + ;
}
if ( has_incoming_mask & & has_incoming_match )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
config_error ( " %s:%d: You cannot have both link::incoming::mask and link::incoming::match. "
" You should only use link::incoming::match. " ,
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
if ( has_outgoing )
{
2022-11-20 04:12:40 +00:00
/* If we have an outgoing sub-block then we need at least a hostname and port or a file */
if ( ! has_outgoing_file )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
if ( ! has_outgoing_hostname )
{
config_error_missing ( ce - > file - > filename , ce - > line_number , " link::outgoing::hostname " ) ;
errors + + ;
}
if ( ! has_outgoing_port )
{
config_error_missing ( ce - > file - > filename , ce - > line_number , " link::outgoing::port " ) ;
errors + + ;
}
2020-03-29 09:16:53 +00:00
}
2022-11-20 04:12:40 +00:00
else if ( has_outgoing_file & & ( has_outgoing_hostname | | has_outgoing_port ) )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
config_error ( " %s:%d: link block should either have a 'file' (for *NIX domain socket), "
" OR have a 'hostname' and 'port' (for IPv4/IPv6). You cannot combine both in one link block. " ,
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
/* The only other generic options that are required are 'class' and 'password' */
if ( ! has_password )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number , " link::password " ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
if ( ! has_class )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" link::class " ) ;
errors + + ;
}
return errors ;
}
int _conf_ban ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
ConfigItem_ban * ca ;
Hook * h ;
ca = safe_alloc ( sizeof ( ConfigItem_ban ) ) ;
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ce - > value , " realname " ) )
2020-03-29 09:16:53 +00:00
ca - > flag . type = CONF_BAN_REALNAME ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ce - > value , " server " ) )
2020-03-29 09:16:53 +00:00
ca - > flag . type = CONF_BAN_SERVER ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ce - > value , " version " ) )
2020-03-29 09:16:53 +00:00
{
ca - > flag . type = CONF_BAN_VERSION ;
tempiConf . use_ban_version = 1 ; /* enable CTCP VERSION on connect */
}
else {
int value ;
safe_free ( ca ) ; /* ca isn't used, modules have their own list. */
for ( h = Hooks [ HOOKTYPE_CONFIGRUN ] ; h ; h = h - > next )
{
value = ( * ( h - > func . intfunc ) ) ( conf , ce , CONFIG_BAN ) ;
if ( value = = 1 )
break ;
}
return 0 ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( ca - > mask , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " reason " ) )
safe_strdup ( ca - > reason , cep - > value ) ;
else if ( ! strcmp ( cep - > name , " action " ) )
ca - > action = banact_stringtoval ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
AddListItem ( ca , conf_ban ) ;
return 0 ;
}
int _test_ban ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
int errors = 0 ;
Hook * h ;
char type = 0 ;
char has_mask = 0 , has_action = 0 , has_reason = 0 ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: ban without type " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ce - > value , " server " ) )
2020-03-29 09:16:53 +00:00
{ }
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ce - > value , " realname " ) )
2020-03-29 09:16:53 +00:00
{ }
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ce - > value , " version " ) )
2020-03-29 09:16:53 +00:00
type = ' v ' ;
else
{
int used = 0 ;
for ( h = Hooks [ HOOKTYPE_CONFIGTEST ] ; h ; h = h - > next )
{
int value , errs = 0 ;
if ( h - > owner & & ! ( h - > owner - > flags & MODFLAG_TESTING )
& & ! ( h - > owner - > options & MOD_OPT_PERM ) )
continue ;
value = ( * ( h - > func . intfunc ) ) ( conf , ce , CONFIG_BAN , & errs ) ;
if ( value = = 2 )
used = 1 ;
if ( value = = 1 )
{
used = 1 ;
break ;
}
if ( value = = - 1 )
{
used = 1 ;
errors + = errs ;
break ;
}
if ( value = = - 2 )
{
used = 1 ;
errors + = errs ;
}
}
if ( ! used ) {
config_error ( " %s:%i: unknown ban type %s " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ,
ce - > value ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
return errors ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " ban " ) )
{
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_mask )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " ban::mask " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_mask = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " reason " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_reason )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " ban::reason " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_reason = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " action " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_action )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " ban::action " ) ;
2020-03-29 09:16:53 +00:00
}
has_action = 1 ;
2022-01-15 05:16:34 +00:00
if ( ! banact_stringtoval ( cep - > value ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: ban::action has unknown action type '%s' " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ,
cep - > value ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
}
if ( ! has_mask )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" ban::mask " ) ;
errors + + ;
}
if ( ! has_reason )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" ban::reason " ) ;
errors + + ;
}
if ( has_action & & type ! = ' v ' )
{
config_error ( " %s:%d: ban::action specified even though type is not 'version' " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
return errors ;
}
int _conf_require ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
Hook * h ;
char * usermask = NULL ;
char * hostmask = NULL ;
char * reason = NULL ;
2022-01-15 05:16:34 +00:00
if ( strcmp ( ce - > value , " authentication " ) & & strcmp ( ce - > value , " sasl " ) )
2020-03-29 09:16:53 +00:00
{
/* Some other block... run modules... */
int value ;
for ( h = Hooks [ HOOKTYPE_CONFIGRUN ] ; h ; h = h - > next )
{
value = ( * ( h - > func . intfunc ) ) ( conf , ce , CONFIG_REQUIRE ) ;
if ( value = = 1 )
break ;
}
return 0 ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
char buf [ 512 ] , * p ;
2022-01-15 05:16:34 +00:00
strlcpy ( buf , cep - > value , sizeof ( buf ) ) ;
2020-03-29 09:16:53 +00:00
p = strchr ( buf , ' @ ' ) ;
if ( p )
{
* p + + = ' \0 ' ;
safe_strdup ( usermask , buf ) ;
safe_strdup ( hostmask , p ) ;
} else {
2022-01-15 05:16:34 +00:00
safe_strdup ( hostmask , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " reason " ) )
safe_strdup ( reason , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
if ( ! usermask )
safe_strdup ( usermask , " * " ) ;
if ( ! reason )
safe_strdup ( reason , " - " ) ;
tkl_add_serverban ( TKL_KILL , usermask , hostmask , reason , " -config- " , 0 , TStime ( ) , 1 , TKL_FLAG_CONFIG ) ;
safe_free ( usermask ) ;
safe_free ( hostmask ) ;
safe_free ( reason ) ;
return 0 ;
}
int _test_require ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
int errors = 0 ;
Hook * h ;
char has_mask = 0 , has_reason = 0 ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: require without type, did you mean 'require authentication'? " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ce - > value , " authentication " ) )
2020-03-29 09:16:53 +00:00
{ }
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ce - > value , " sasl " ) )
2020-03-29 09:16:53 +00:00
{
config_warn ( " %s:%i: the 'require sasl' block is now called 'require authentication' " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
}
else
{
int used = 0 ;
for ( h = Hooks [ HOOKTYPE_CONFIGTEST ] ; h ; h = h - > next )
{
int value , errs = 0 ;
if ( h - > owner & & ! ( h - > owner - > flags & MODFLAG_TESTING )
& & ! ( h - > owner - > options & MOD_OPT_PERM ) )
continue ;
value = ( * ( h - > func . intfunc ) ) ( conf , ce , CONFIG_REQUIRE , & errs ) ;
if ( value = = 2 )
used = 1 ;
if ( value = = 1 )
{
used = 1 ;
break ;
}
if ( value = = - 1 )
{
used = 1 ;
errors + = errs ;
break ;
}
if ( value = = - 2 )
{
used = 1 ;
errors + = errs ;
}
}
if ( ! used ) {
config_error ( " %s:%i: unknown require type '%s' " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ,
ce - > value ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
return errors ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " require " ) )
{
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_mask )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " require::mask " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_mask = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " reason " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_reason )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " require::reason " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_reason = 1 ;
}
}
if ( ! has_mask )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" require::mask " ) ;
errors + + ;
}
if ( ! has_reason )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" require::reason " ) ;
errors + + ;
}
return errors ;
}
2022-01-15 05:16:34 +00:00
# define CheckDuplicate(cep, name, display) if (settings.has_##name) { config_warn_duplicate((cep)->file->filename, cep->line_number, "set::" display); continue; } else settings.has_##name = 1
2020-03-29 09:16:53 +00:00
void test_tlsblock ( ConfigFile * conf , ConfigEntry * cep , int * totalerrors )
{
ConfigEntry * cepp , * ceppp ;
int errors = 0 ;
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " renegotiate-timeout " ) )
2020-03-29 09:16:53 +00:00
{
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " renegotiate-bytes " ) )
2020-03-29 09:16:53 +00:00
{
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " ciphers " ) | | ! strcmp ( cepp - > name , " server-cipher-list " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cepp ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " ciphersuites " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cepp ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " ecdh-curves " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cepp ) ;
# ifndef HAS_SSL_CTX_SET1_CURVES_LIST
config_error ( " ecdh-curves specified but your OpenSSL/LibreSSL library does not "
" support setting curves manually by name. Either upgrade to a "
" newer library version or remove the 'ecdh-curves' directive "
" from your configuration file " ) ;
errors + + ;
# endif
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " protocols " ) )
2020-03-29 09:16:53 +00:00
{
char copy [ 512 ] , * p , * name ;
int v = 0 ;
int option ;
char modifier ;
CheckNull ( cepp ) ;
2022-01-15 05:16:34 +00:00
strlcpy ( copy , cepp - > value , sizeof ( copy ) ) ;
2020-03-29 09:16:53 +00:00
for ( name = strtoken ( & p , copy , " , " ) ; name ; name = strtoken ( & p , NULL , " , " ) )
{
modifier = ' \0 ' ;
option = 0 ;
if ( ( * name = = ' + ' ) | | ( * name = = ' - ' ) )
{
modifier = * name ;
name + + ;
}
if ( ! strcasecmp ( name , " All " ) )
option = TLS_PROTOCOL_ALL ;
else if ( ! strcasecmp ( name , " TLSv1 " ) )
option = TLS_PROTOCOL_TLSV1 ;
else if ( ! strcasecmp ( name , " TLSv1.1 " ) )
option = TLS_PROTOCOL_TLSV1_1 ;
else if ( ! strcasecmp ( name , " TLSv1.2 " ) )
option = TLS_PROTOCOL_TLSV1_2 ;
else if ( ! strcasecmp ( name , " TLSv1.3 " ) )
option = TLS_PROTOCOL_TLSV1_3 ;
else
{
# ifdef SSL_OP_NO_TLSv1_3
config_warn ( " %s:%i: %s: unknown protocol '%s'. "
" Valid protocols are: TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number , config_var ( cepp ) , name ) ;
2020-03-29 09:16:53 +00:00
# else
config_warn ( " %s:%i: %s: unknown protocol '%s'. "
" Valid protocols are: TLSv1,TLSv1.1,TLSv1.2 " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number , config_var ( cepp ) , name ) ;
2020-03-29 09:16:53 +00:00
# endif
}
if ( option )
{
if ( modifier = = ' \0 ' )
v = option ;
else if ( modifier = = ' + ' )
v | = option ;
else if ( modifier = = ' - ' )
v & = ~ option ;
}
}
if ( v = = 0 )
{
config_error ( " %s:%i: %s: no protocols enabled. Hint: set at least TLSv1.2 " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number , config_var ( cepp ) ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " certificate " ) | |
! strcmp ( cepp - > name , " key " ) | |
! strcmp ( cepp - > name , " trusted-ca-file " ) )
2020-03-29 09:16:53 +00:00
{
char * path ;
CheckNull ( cepp ) ;
2022-01-15 05:16:34 +00:00
path = convert_to_absolute_path_duplicate ( cepp - > value , CONFDIR ) ;
2020-03-29 09:16:53 +00:00
if ( ! file_exists ( path ) )
{
config_error ( " %s:%i: %s: could not open '%s': %s " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number , config_var ( cepp ) ,
2020-03-29 09:16:53 +00:00
path , strerror ( errno ) ) ;
safe_free ( path ) ;
errors + + ;
}
safe_free ( path ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " dh " ) )
2020-11-26 16:02:01 +00:00
{
/* Support for this undocumented option was silently dropped in 5.0.0.
* Since 5.0 .7 we print a warning about it , since you never know
* someone may still have it configured . - - Syzop
*/
config_warn ( " %s:%d: Not reading DH file '%s'. UnrealIRCd does not support old DH(E), we use modern ECDHE/EECDH. "
" Just remove the 'dh' directive from your config file to get rid of this warning. " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number ,
cepp - > value ? cepp - > value : " " ) ;
2020-11-26 16:02:01 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " outdated-protocols " ) )
2020-03-29 09:16:53 +00:00
{
char copy [ 512 ] , * p , * name ;
int v = 0 ;
int option ;
char modifier ;
CheckNull ( cepp ) ;
2022-01-15 05:16:34 +00:00
strlcpy ( copy , cepp - > value , sizeof ( copy ) ) ;
2020-03-29 09:16:53 +00:00
for ( name = strtoken ( & p , copy , " , " ) ; name ; name = strtoken ( & p , NULL , " , " ) )
{
if ( ! strcasecmp ( name , " All " ) )
;
else if ( ! strcasecmp ( name , " TLSv1 " ) )
;
else if ( ! strcasecmp ( name , " TLSv1.1 " ) )
;
else if ( ! strcasecmp ( name , " TLSv1.2 " ) )
;
else if ( ! strcasecmp ( name , " TLSv1.3 " ) )
;
else
{
# ifdef SSL_OP_NO_TLSv1_3
config_warn ( " %s:%i: %s: unknown protocol '%s'. "
" Valid protocols are: TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number , config_var ( cepp ) , name ) ;
2020-03-29 09:16:53 +00:00
# else
config_warn ( " %s:%i: %s: unknown protocol '%s'. "
" Valid protocols are: TLSv1,TLSv1.1,TLSv1.2 " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number , config_var ( cepp ) , name ) ;
2020-03-29 09:16:53 +00:00
# endif
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " outdated-ciphers " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cepp ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " options " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( ceppp = cepp - > items ; ceppp ; ceppp = ceppp - > next )
{
if ( ! nv_find_by_name ( _TLSFlags , ceppp - > name ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error ( " %s:%i: unknown TLS option '%s' " ,
ceppp - > file - > filename ,
ceppp - > line_number , ceppp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
}
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " sts-policy " ) )
2020-03-29 09:16:53 +00:00
{
int has_port = 0 ;
int has_duration = 0 ;
2022-01-15 05:16:34 +00:00
for ( ceppp = cepp - > items ; ceppp ; ceppp = ceppp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ceppp - > name , " port " ) )
2020-03-29 09:16:53 +00:00
{
int port ;
CheckNull ( ceppp ) ;
2022-01-15 05:16:34 +00:00
port = atoi ( ceppp - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ( port < 1 ) | | ( port > 65535 ) )
{
config_error ( " %s:%i: invalid port number specified in sts-policy::port (%d) " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number , port ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
has_port = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " duration " ) )
2020-03-29 09:16:53 +00:00
{
long duration ;
CheckNull ( ceppp ) ;
2022-01-15 05:16:34 +00:00
duration = config_checkval ( ceppp - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
if ( duration < 1 )
{
config_error ( " %s:%i: invalid duration specified in sts-policy::duration (%ld seconds) " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number , duration ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
has_duration = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " preload " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( ceppp ) ;
}
}
if ( ! has_port )
{
config_error ( " %s:%i: sts-policy block without port " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
if ( ! has_duration )
{
config_error ( " %s:%i: sts-policy block without duration " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
else
{
config_error ( " %s:%i: unknown directive %s " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number ,
2020-03-29 09:16:53 +00:00
config_var ( cepp ) ) ;
errors + + ;
}
}
* totalerrors + = errors ;
}
void free_tls_options ( TLSOptions * tlsoptions )
{
if ( ! tlsoptions )
return ;
safe_free ( tlsoptions - > certificate_file ) ;
safe_free ( tlsoptions - > key_file ) ;
safe_free ( tlsoptions - > trusted_ca_file ) ;
safe_free ( tlsoptions - > ciphers ) ;
safe_free ( tlsoptions - > ciphersuites ) ;
safe_free ( tlsoptions - > ecdh_curves ) ;
safe_free ( tlsoptions - > outdated_protocols ) ;
safe_free ( tlsoptions - > outdated_ciphers ) ;
memset ( tlsoptions , 0 , sizeof ( TLSOptions ) ) ;
safe_free ( tlsoptions ) ;
}
void conf_tlsblock ( ConfigFile * conf , ConfigEntry * cep , TLSOptions * tlsoptions )
{
ConfigEntry * cepp , * ceppp ;
NameValue * ofl ;
/* First, inherit settings from set::options::tls */
if ( tlsoptions ! = tempiConf . tls_options )
{
safe_strdup ( tlsoptions - > certificate_file , tempiConf . tls_options - > certificate_file ) ;
safe_strdup ( tlsoptions - > key_file , tempiConf . tls_options - > key_file ) ;
safe_strdup ( tlsoptions - > trusted_ca_file , tempiConf . tls_options - > trusted_ca_file ) ;
tlsoptions - > protocols = tempiConf . tls_options - > protocols ;
safe_strdup ( tlsoptions - > ciphers , tempiConf . tls_options - > ciphers ) ;
safe_strdup ( tlsoptions - > ciphersuites , tempiConf . tls_options - > ciphersuites ) ;
safe_strdup ( tlsoptions - > ecdh_curves , tempiConf . tls_options - > ecdh_curves ) ;
safe_strdup ( tlsoptions - > outdated_protocols , tempiConf . tls_options - > outdated_protocols ) ;
safe_strdup ( tlsoptions - > outdated_ciphers , tempiConf . tls_options - > outdated_ciphers ) ;
tlsoptions - > options = tempiConf . tls_options - > options ;
tlsoptions - > renegotiate_bytes = tempiConf . tls_options - > renegotiate_bytes ;
tlsoptions - > renegotiate_timeout = tempiConf . tls_options - > renegotiate_timeout ;
tlsoptions - > sts_port = tempiConf . tls_options - > sts_port ;
tlsoptions - > sts_duration = tempiConf . tls_options - > sts_duration ;
tlsoptions - > sts_preload = tempiConf . tls_options - > sts_preload ;
}
/* Now process the options */
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " ciphers " ) | | ! strcmp ( cepp - > name , " server-cipher-list " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( tlsoptions - > ciphers , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " ciphersuites " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( tlsoptions - > ciphersuites , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " ecdh-curves " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( tlsoptions - > ecdh_curves , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " protocols " ) )
2020-03-29 09:16:53 +00:00
{
char copy [ 512 ] , * p , * name ;
int option ;
char modifier ;
2022-01-15 05:16:34 +00:00
strlcpy ( copy , cepp - > value , sizeof ( copy ) ) ;
2020-03-29 09:16:53 +00:00
tlsoptions - > protocols = 0 ;
for ( name = strtoken ( & p , copy , " , " ) ; name ; name = strtoken ( & p , NULL , " , " ) )
{
modifier = ' \0 ' ;
option = 0 ;
if ( ( * name = = ' + ' ) | | ( * name = = ' - ' ) )
{
modifier = * name ;
name + + ;
}
if ( ! strcasecmp ( name , " All " ) )
option = TLS_PROTOCOL_ALL ;
else if ( ! strcasecmp ( name , " TLSv1 " ) )
option = TLS_PROTOCOL_TLSV1 ;
else if ( ! strcasecmp ( name , " TLSv1.1 " ) )
option = TLS_PROTOCOL_TLSV1_1 ;
else if ( ! strcasecmp ( name , " TLSv1.2 " ) )
option = TLS_PROTOCOL_TLSV1_2 ;
else if ( ! strcasecmp ( name , " TLSv1.3 " ) )
option = TLS_PROTOCOL_TLSV1_3 ;
if ( option )
{
if ( modifier = = ' \0 ' )
tlsoptions - > protocols = option ;
else if ( modifier = = ' + ' )
tlsoptions - > protocols | = option ;
else if ( modifier = = ' - ' )
tlsoptions - > protocols & = ~ option ;
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " certificate " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cepp - > value , CONFDIR ) ;
safe_strdup ( tlsoptions - > certificate_file , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " key " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cepp - > value , CONFDIR ) ;
safe_strdup ( tlsoptions - > key_file , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " trusted-ca-file " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cepp - > value , CONFDIR ) ;
safe_strdup ( tlsoptions - > trusted_ca_file , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " outdated-protocols " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( tlsoptions - > outdated_protocols , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " outdated-ciphers " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( tlsoptions - > outdated_ciphers , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " renegotiate-bytes " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tlsoptions - > renegotiate_bytes = config_checkval ( cepp - > value , CFG_SIZE ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " renegotiate-timeout " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tlsoptions - > renegotiate_timeout = config_checkval ( cepp - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " options " ) )
2020-03-29 09:16:53 +00:00
{
tlsoptions - > options = 0 ;
2022-01-15 05:16:34 +00:00
for ( ceppp = cepp - > items ; ceppp ; ceppp = ceppp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
long v = nv_find_by_name ( _TLSFlags , ceppp - > name ) ;
tlsoptions - > options | = v ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " sts-policy " ) )
2020-03-29 09:16:53 +00:00
{
/* We do not inherit ::sts-policy if there is a specific block for this one... */
tlsoptions - > sts_port = 0 ;
tlsoptions - > sts_duration = 0 ;
tlsoptions - > sts_preload = 0 ;
2022-01-15 05:16:34 +00:00
for ( ceppp = cepp - > items ; ceppp ; ceppp = ceppp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ceppp - > name , " port " ) )
tlsoptions - > sts_port = atoi ( ceppp - > value ) ;
else if ( ! strcmp ( ceppp - > name , " duration " ) )
tlsoptions - > sts_duration = config_checkval ( ceppp - > value , CFG_TIME ) ;
else if ( ! strcmp ( ceppp - > name , " preload " ) )
tlsoptions - > sts_preload = config_checkval ( ceppp - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
}
}
}
int _conf_set ( ConfigFile * conf , ConfigEntry * ce )
{
2021-06-19 15:52:51 +00:00
ConfigEntry * cep , * cepp , * ceppp , * cep4 ;
2020-03-29 09:16:53 +00:00
Hook * h ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " kline-address " ) ) {
safe_strdup ( tempiConf . kline_address , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " gline-address " ) ) {
safe_strdup ( tempiConf . gline_address , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " modes-on-connect " ) ) {
tempiConf . conn_modes = ( long ) set_usermode ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " modes-on-oper " ) ) {
tempiConf . oper_modes = ( long ) set_usermode ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " modes-on-join " ) ) {
conf_channelmodes ( cep - > value , & tempiConf . modes_on_join ) ;
tempiConf . modes_on_join_set = 1 ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " snomask-on-oper " ) ) {
safe_strdup ( tempiConf . oper_snomask , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " server-notice-colors " ) ) {
tempiConf . server_notice_colors = config_checkval ( cep - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
2022-04-03 15:09:29 +00:00
else if ( ! strcmp ( cep - > name , " server-notice-show-event " ) ) {
tempiConf . server_notice_show_event = config_checkval ( cep - > value , CFG_YESNO ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " level-on-join " ) ) {
const char * res = channellevel_to_string ( cep - > value ) ; /* 'halfop', etc */
if ( ! res )
{
/* This check needs to be here, in config run, because
* now the channel modules are initialized and we know
* which ones are available . This same information is
* not available during config test , so we can ' t test
* for it there like we normally do .
*/
if ( ! valid_channel_access_mode_letter ( * cep - > value ) )
{
config_warn ( " %s:%d: set::level-on-join: Unknown mode (access level) '%c'. "
" That mode does not exist or is not a valid access mode "
" like vhoaq. " ,
cep - > file - > filename , cep - > line_number ,
* cep - > value ) ;
config_warn ( " Falling back to to set::level-on-join none; now. "
" This is probably not what you want!!! " ) ;
}
res = cep - > value ; /* if we reach this.. then it is a single letter */
}
safe_strdup ( tempiConf . level_on_join , res ) ;
}
else if ( ! strcmp ( cep - > name , " static-quit " ) ) {
safe_strdup ( tempiConf . static_quit , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " static-part " ) ) {
safe_strdup ( tempiConf . static_part , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " who-limit " ) ) {
tempiConf . who_limit = atol ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " maxbans " ) ) {
tempiConf . maxbans = atol ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " maxbanlength " ) ) {
tempiConf . maxbanlength = atol ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " silence-limit " ) ) {
tempiConf . silence_limit = atol ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " auto-join " ) ) {
safe_strdup ( tempiConf . auto_join_chans , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " oper-auto-join " ) ) {
safe_strdup ( tempiConf . oper_auto_join_chans , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " check-target-nick-bans " ) ) {
tempiConf . check_target_nick_bans = config_checkval ( cep - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ping-cookie " ) ) {
tempiConf . ping_cookie = config_checkval ( cep - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " watch-away-notification " ) ) {
tempiConf . watch_away_notification = config_checkval ( cep - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " uhnames " ) ) {
tempiConf . uhnames = config_checkval ( cep - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " allow-userhost-change " ) ) {
if ( ! strcasecmp ( cep - > value , " always " ) )
2020-03-29 09:16:53 +00:00
tempiConf . userhost_allowed = UHALLOW_ALWAYS ;
2022-01-15 05:16:34 +00:00
else if ( ! strcasecmp ( cep - > value , " never " ) )
2020-03-29 09:16:53 +00:00
tempiConf . userhost_allowed = UHALLOW_NEVER ;
2022-01-15 05:16:34 +00:00
else if ( ! strcasecmp ( cep - > value , " not-on-channels " ) )
2020-03-29 09:16:53 +00:00
tempiConf . userhost_allowed = UHALLOW_NOCHANS ;
else
tempiConf . userhost_allowed = UHALLOW_REJOIN ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " channel-command-prefix " ) ) {
safe_strdup ( tempiConf . channel_command_prefix , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " restrict-usermodes " ) ) {
2020-03-29 09:16:53 +00:00
int i ;
2022-01-15 05:16:34 +00:00
char * p = safe_alloc ( strlen ( cep - > value ) + 1 ) , * x = p ;
2020-03-29 09:16:53 +00:00
/* The data should be something like 'Gw' or something,
* but just in case users use ' + Gw ' then ignore the + ( and - ) .
*/
2022-01-15 05:16:34 +00:00
for ( i = 0 ; i < strlen ( cep - > value ) ; i + + )
if ( ( cep - > value [ i ] ! = ' + ' ) & & ( cep - > value [ i ] ! = ' - ' ) )
* x + + = cep - > value [ i ] ;
2020-03-29 09:16:53 +00:00
* x = ' \0 ' ;
tempiConf . restrict_usermodes = p ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " restrict-channelmodes " ) ) {
2020-03-29 09:16:53 +00:00
int i ;
2022-01-15 05:16:34 +00:00
char * p = safe_alloc ( strlen ( cep - > value ) + 1 ) , * x = p ;
2020-03-29 09:16:53 +00:00
/* The data should be something like 'GL' or something,
* but just in case users use ' + GL ' then ignore the + ( and - ) .
*/
2022-01-15 05:16:34 +00:00
for ( i = 0 ; i < strlen ( cep - > value ) ; i + + )
if ( ( cep - > value [ i ] ! = ' + ' ) & & ( cep - > value [ i ] ! = ' - ' ) )
* x + + = cep - > value [ i ] ;
2020-03-29 09:16:53 +00:00
* x = ' \0 ' ;
tempiConf . restrict_channelmodes = p ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " restrict-extendedbans " ) ) {
safe_strdup ( tempiConf . restrict_extendedbans , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " named-extended-bans " ) ) {
tempiConf . named_extended_bans = config_checkval ( cep - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " anti-spam-quit-message-time " ) ) {
tempiConf . anti_spam_quit_message_time = config_checkval ( cep - > value , CFG_TIME ) ;
}
else if ( ! strcmp ( cep - > name , " allow-user-stats " ) ) {
if ( ! cep - > items )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( tempiConf . allow_user_stats , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
else
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
OperStat * os = safe_alloc ( sizeof ( OperStat ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( os - > flag , cepp - > name ) ;
2020-03-29 09:16:53 +00:00
AddListItem ( os , tempiConf . allow_user_stats_ext ) ;
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " maxchannelsperuser " ) ) {
tempiConf . maxchannelsperuser = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ping-warning " ) ) {
tempiConf . ping_warning = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " maxdccallow " ) ) {
tempiConf . maxdccallow = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " max-targets-per-command " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
int v ;
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > value , " max " ) )
2020-03-29 09:16:53 +00:00
v = MAXTARGETS_MAX ;
else
2022-01-15 05:16:34 +00:00
v = atoi ( cepp - > value ) ;
setmaxtargets ( cepp - > name , v ) ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " network-name " ) ) {
2020-03-29 09:16:53 +00:00
char * tmp ;
2022-01-15 05:16:34 +00:00
safe_strdup ( tempiConf . network_name , cep - > value ) ;
for ( tmp = cep - > value ; * cep - > value ; cep - > value + + ) {
if ( * cep - > value = = ' ' )
* cep - > value = ' - ' ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
safe_strdup ( tempiConf . network_name_005 , tmp ) ;
cep - > value = tmp ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " default-server " ) ) {
safe_strdup ( tempiConf . default_server , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " services-server " ) ) {
safe_strdup ( tempiConf . services_name , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " sasl-server " ) ) {
safe_strdup ( tempiConf . sasl_server , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " stats-server " ) ) {
safe_strdup ( tempiConf . stats_server , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " help-channel " ) ) {
safe_strdup ( tempiConf . helpchan , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " cloak-prefix " ) | | ! strcmp ( cep - > name , " hiddenhost-prefix " ) ) {
safe_strdup ( tempiConf . cloak_prefix , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " hide-ban-reason " ) ) {
tempiConf . hide_ban_reason = config_checkval ( cep - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " prefix-quit " ) ) {
if ( ! strcmp ( cep - > value , " 0 " ) | | ! strcmp ( cep - > value , " no " ) )
safe_free ( tempiConf . prefix_quit ) ;
2020-03-29 09:16:53 +00:00
else
2022-01-15 05:16:34 +00:00
safe_strdup ( tempiConf . prefix_quit , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " link " ) ) {
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next ) {
if ( ! strcmp ( cepp - > name , " bind-ip " ) ) {
safe_strdup ( tempiConf . link_bindip , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " anti-flood " ) ) {
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2021-03-21 17:05:35 +00:00
{
2022-01-15 05:16:34 +00:00
int lag_penalty = - 1 ;
int lag_penalty_bytes = - 1 ;
for ( ceppp = cepp - > items ; ceppp ; ceppp = ceppp - > next )
2021-03-21 17:05:35 +00:00
{
2023-05-05 22:12:01 +00:00
/* Check hooks first */
int used = 0 ;
for ( h = Hooks [ HOOKTYPE_CONFIGRUN ] ; h ; h = h - > next )
{
used = ( * ( h - > func . intfunc ) ) ( conf , ceppp , CONFIG_SET_ANTI_FLOOD ) ;
if ( used = = 1 )
break ;
}
if ( used = = 1 )
continue ; /* module handled it */
if ( used = = 2 )
break ; /* module handled it and we must stop entire block processing */
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ceppp - > name , " handshake-data-flood " ) )
2021-03-21 17:05:35 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cep4 = ceppp - > items ; cep4 ; cep4 = cep4 - > next )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep4 - > name , " amount " ) )
tempiConf . handshake_data_flood_amount = config_checkval ( cep4 - > value , CFG_SIZE ) ;
else if ( ! strcmp ( cep4 - > name , " ban-time " ) )
tempiConf . handshake_data_flood_ban_time = config_checkval ( cep4 - > value , CFG_TIME ) ;
else if ( ! strcmp ( cep4 - > name , " ban-action " ) )
tempiConf . handshake_data_flood_ban_action = banact_stringtoval ( cep4 - > value ) ;
2021-06-19 15:52:51 +00:00
}
2021-03-21 17:05:35 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " away-flood " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_parse_flood_generic ( ceppp - > value , & tempiConf , cepp - > name , FLD_AWAY ) ;
2021-06-19 15:52:51 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " nick-flood " ) )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
config_parse_flood_generic ( ceppp - > value , & tempiConf , cepp - > name , FLD_NICK ) ;
2021-06-19 15:52:51 +00:00
}
2022-04-03 15:09:29 +00:00
else if ( ! strcmp ( ceppp - > name , " vhost-flood " ) )
{
config_parse_flood_generic ( ceppp - > value , & tempiConf , cepp - > name , FLD_VHOST ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " join-flood " ) )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
config_parse_flood_generic ( ceppp - > value , & tempiConf , cepp - > name , FLD_JOIN ) ;
2021-06-19 15:52:51 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " invite-flood " ) )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
config_parse_flood_generic ( ceppp - > value , & tempiConf , cepp - > name , FLD_INVITE ) ;
2021-06-19 15:52:51 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " knock-flood " ) )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
config_parse_flood_generic ( ceppp - > value , & tempiConf , cepp - > name , FLD_KNOCK ) ;
2021-06-19 15:52:51 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " lag-penalty " ) )
{
lag_penalty = atoi ( ceppp - > value ) ;
}
else if ( ! strcmp ( ceppp - > name , " lag-penalty-bytes " ) )
{
lag_penalty_bytes = config_checkval ( ceppp - > value , CFG_SIZE ) ;
if ( lag_penalty_bytes < = 0 )
lag_penalty_bytes = INT_MAX ;
}
else if ( ! strcmp ( ceppp - > name , " connect-flood " ) )
2021-06-19 15:52:51 +00:00
{
int cnt , period ;
2022-01-15 05:16:34 +00:00
config_parse_flood ( ceppp - > value , & cnt , & period ) ;
2021-06-19 15:52:51 +00:00
tempiConf . throttle_count = cnt ;
tempiConf . throttle_period = period ;
}
2023-05-05 22:12:01 +00:00
else if ( ! strcmp ( ceppp - > name , " max-concurrent-conversations " ) )
2021-06-19 15:52:51 +00:00
{
/* We use a hack here to make it fit our storage format */
char buf [ 64 ] ;
int users = 0 ;
long every = 0 ;
2022-01-15 05:16:34 +00:00
for ( cep4 = ceppp - > items ; cep4 ; cep4 = cep4 - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep4 - > name , " users " ) )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
users = atoi ( cep4 - > value ) ;
2021-06-19 15:52:51 +00:00
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep4 - > name , " new-user-every " ) )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
every = config_checkval ( cep4 - > value , CFG_TIME ) ;
2021-06-19 15:52:51 +00:00
}
2020-03-29 09:16:53 +00:00
}
2021-06-19 15:52:51 +00:00
snprintf ( buf , sizeof ( buf ) , " %d:%ld " , users , every ) ;
2022-01-15 05:16:34 +00:00
config_parse_flood_generic ( buf , & tempiConf , cepp - > name , FLD_CONVERSATIONS ) ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
if ( ( lag_penalty ! = - 1 ) & & ( lag_penalty_bytes ! = - 1 ) )
{
/* We use a hack here to make it fit our storage format */
char buf [ 64 ] ;
snprintf ( buf , sizeof ( buf ) , " %d:%d " , lag_penalty_bytes , lag_penalty ) ;
config_parse_flood_generic ( buf , & tempiConf , cepp - > name , FLD_LAG_PENALTY ) ;
}
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " options " ) ) {
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next ) {
if ( ! strcmp ( cepp - > name , " hide-ulines " ) ) {
2020-03-29 09:16:53 +00:00
tempiConf . hide_ulines = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " flat-map " ) ) {
2020-03-29 09:16:53 +00:00
tempiConf . flat_map = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " show-opermotd " ) ) {
tempiConf . show_opermotd = 1 ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " identd-check " ) ) {
2020-03-29 09:16:53 +00:00
tempiConf . ident_check = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " fail-oper-warn " ) ) {
2020-03-29 09:16:53 +00:00
tempiConf . fail_oper_warn = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " show-connect-info " ) ) {
2020-03-29 09:16:53 +00:00
tempiConf . show_connect_info = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " no-connect-tls-info " ) ) {
2020-03-29 09:16:53 +00:00
tempiConf . no_connect_tls_info = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " dont-resolve " ) ) {
2020-03-29 09:16:53 +00:00
tempiConf . dont_resolve = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " mkpasswd-for-everyone " ) ) {
2020-03-29 09:16:53 +00:00
tempiConf . mkpasswd_for_everyone = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " allow-insane-bans " ) ) {
2020-03-29 09:16:53 +00:00
tempiConf . allow_insane_bans = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " allow-part-if-shunned " ) ) {
2020-03-29 09:16:53 +00:00
tempiConf . allow_part_if_shunned = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " disable-cap " ) ) {
2020-03-29 09:16:53 +00:00
tempiConf . disable_cap = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " disable-ipv6 " ) ) {
2020-03-29 09:16:53 +00:00
/* other code handles this */
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " cloak-keys " ) )
2020-03-29 09:16:53 +00:00
{
for ( h = Hooks [ HOOKTYPE_CONFIGRUN ] ; h ; h = h - > next )
{
int value ;
value = ( * ( h - > func . intfunc ) ) ( conf , cep , CONFIG_CLOAKKEYS ) ;
if ( value = = 1 )
break ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ident " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " connect-timeout " ) )
tempiConf . ident_connect_timeout = config_checkval ( cepp - > value , CFG_TIME ) ;
if ( ! strcmp ( cepp - > name , " read-timeout " ) )
tempiConf . ident_read_timeout = config_checkval ( cepp - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " spamfilter " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " ban-time " ) )
tempiConf . spamfilter_ban_time = config_checkval ( cepp - > value , CFG_TIME ) ;
else if ( ! strcmp ( cepp - > name , " ban-reason " ) )
safe_strdup ( tempiConf . spamfilter_ban_reason , cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " virus-help-channel " ) )
safe_strdup ( tempiConf . spamfilter_virus_help_channel , cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " virus-help-channel-deny " ) )
tempiConf . spamfilter_vchan_deny = config_checkval ( cepp - > value , CFG_YESNO ) ;
else if ( ! strcmp ( cepp - > name , " except " ) )
2020-03-29 09:16:53 +00:00
{
char * name , * p ;
SpamExcept * e ;
2022-01-15 05:16:34 +00:00
safe_strdup ( tempiConf . spamexcept_line , cepp - > value ) ;
for ( name = strtoken ( & p , cepp - > value , " , " ) ; name ; name = strtoken ( & p , NULL , " , " ) )
2020-03-29 09:16:53 +00:00
{
if ( * name = = ' ' )
name + + ;
if ( * name )
{
e = safe_alloc ( sizeof ( SpamExcept ) + strlen ( name ) ) ;
strcpy ( e - > name , name ) ;
AddListItem ( e , tempiConf . spamexcept ) ;
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " detect-slow-warn " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . spamfilter_detectslow_warn = atol ( cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " detect-slow-fatal " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . spamfilter_detectslow_fatal = atol ( cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " stop-on-first-match " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . spamfilter_stop_on_first_match = config_checkval ( cepp - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
2023-05-05 22:12:01 +00:00
else if ( ! strcmp ( cepp - > name , " utf8 " ) )
{
tempiConf . spamfilter_utf8 = config_checkval ( cepp - > value , CFG_YESNO ) ;
}
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " default-bantime " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . default_bantime = config_checkval ( cep - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ban-version-tkl-time " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . ban_version_tkl_time = config_checkval ( cep - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " min-nick-length " ) ) {
int v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
tempiConf . min_nick_length = v ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " nick-length " ) ) {
int v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
tempiConf . nick_length = v ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " topic-length " ) ) {
int v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
tempiConf . topic_length = v ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " away-length " ) ) {
int v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
tempiConf . away_length = v ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " kick-length " ) ) {
int v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
tempiConf . kick_length = v ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " quit-length " ) ) {
int v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
tempiConf . quit_length = v ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ssl " ) | | ! strcmp ( cep - > name , " tls " ) ) {
2020-03-29 09:16:53 +00:00
/* no need to alloc tempiConf.tls_options since config_defaults() already ensures it exists */
conf_tlsblock ( conf , cep , tempiConf . tls_options ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " plaintext-policy " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " user " ) )
tempiConf . plaintext_policy_user = policy_strtoval ( cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " oper " ) )
tempiConf . plaintext_policy_oper = policy_strtoval ( cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " server " ) )
tempiConf . plaintext_policy_server = policy_strtoval ( cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " user-message " ) )
addmultiline ( & tempiConf . plaintext_policy_user_message , cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " oper-message " ) )
addmultiline ( & tempiConf . plaintext_policy_oper_message , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " outdated-tls-policy " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " user " ) )
tempiConf . outdated_tls_policy_user = policy_strtoval ( cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " oper " ) )
tempiConf . outdated_tls_policy_oper = policy_strtoval ( cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " server " ) )
tempiConf . outdated_tls_policy_server = policy_strtoval ( cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " user-message " ) )
safe_strdup ( tempiConf . outdated_tls_policy_user_message , cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " oper-message " ) )
safe_strdup ( tempiConf . outdated_tls_policy_oper_message , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " default-ipv6-clone-mask " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . default_ipv6_clone_mask = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " hide-list " ) ) {
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " deny-channel " ) )
2020-03-29 09:16:53 +00:00
{
tempiConf . hide_list = 1 ;
/* if we would expand this later then change this to a bitmask or struct or whatever */
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " max-unknown-connections-per-ip " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . max_unknown_connections_per_ip = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " handshake-timeout " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . handshake_timeout = config_checkval ( cep - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " sasl-timeout " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . sasl_timeout = config_checkval ( cep - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " handshake-delay " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . handshake_delay = config_checkval ( cep - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " automatic-ban-target " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . automatic_ban_target = ban_target_strtoval ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " manual-ban-target " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . manual_ban_target = ban_target_strtoval ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " reject-message " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " too-many-connections " ) )
safe_strdup ( tempiConf . reject_message_too_many_connections , cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " server-full " ) )
safe_strdup ( tempiConf . reject_message_server_full , cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " unauthorized " ) )
safe_strdup ( tempiConf . reject_message_unauthorized , cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " kline " ) )
safe_strdup ( tempiConf . reject_message_kline , cepp - > value ) ;
else if ( ! strcmp ( cepp - > name , " gline " ) )
safe_strdup ( tempiConf . reject_message_gline , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " topic-setter " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > value , " nick " ) )
2020-03-29 09:16:53 +00:00
tempiConf . topic_setter = SETTER_NICK ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > value , " nick-user-host " ) )
2020-03-29 09:16:53 +00:00
tempiConf . topic_setter = SETTER_NICK_USER_HOST ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ban-setter " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > value , " nick " ) )
2020-03-29 09:16:53 +00:00
tempiConf . ban_setter = SETTER_NICK ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > value , " nick-user-host " ) )
2020-03-29 09:16:53 +00:00
tempiConf . ban_setter = SETTER_NICK_USER_HOST ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ban-setter-sync " ) | | ! strcmp ( cep - > name , " ban-setter-synch " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . ban_setter_sync = config_checkval ( cep - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " part-instead-of-quit-on-comment-change " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . part_instead_of_quit_on_comment_change = config_checkval ( cep - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " broadcast-channel-messages " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > value , " auto " ) )
2020-03-29 09:16:53 +00:00
tempiConf . broadcast_channel_messages = BROADCAST_CHANNEL_MESSAGES_AUTO ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > value , " always " ) )
2020-03-29 09:16:53 +00:00
tempiConf . broadcast_channel_messages = BROADCAST_CHANNEL_MESSAGES_ALWAYS ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > value , " never " ) )
2020-03-29 09:16:53 +00:00
tempiConf . broadcast_channel_messages = BROADCAST_CHANNEL_MESSAGES_NEVER ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " allowed-channelchars " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
tempiConf . allowed_channelchars = allowed_channelchars_strtoval ( cep - > value ) ;
2020-04-20 19:12:33 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " hide-idle-time " ) )
2020-04-20 19:12:33 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-04-20 19:12:33 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " policy " ) )
tempiConf . hide_idle_time = hideidletime_strtoval ( cepp - > value ) ;
2020-04-20 19:12:33 +00:00
}
2023-05-05 22:12:01 +00:00
} else if ( ! strcmp ( cep - > name , " limit-svscmds " ) )
{
if ( ! strcmp ( cep - > value , " ulines " ) )
tempiConf . limit_svscmds = LIMIT_SVSCMDS_ULINES ;
else
tempiConf . limit_svscmds = LIMIT_SVSCMDS_SERVERS ;
2022-01-15 05:16:34 +00:00
} else
2020-03-29 09:16:53 +00:00
{
int value ;
for ( h = Hooks [ HOOKTYPE_CONFIGRUN ] ; h ; h = h - > next )
{
value = ( * ( h - > func . intfunc ) ) ( conf , cep , CONFIG_SET ) ;
if ( value = = 1 )
break ;
}
}
}
return 0 ;
}
int _test_set ( ConfigFile * conf , ConfigEntry * ce )
{
2021-06-19 15:52:51 +00:00
ConfigEntry * cep , * cepp , * ceppp , * cep4 ;
2020-03-29 09:16:53 +00:00
int tempi ;
int errors = 0 ;
Hook * h ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " kline-address " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , kline_address , " kline-address " ) ;
2022-01-15 05:16:34 +00:00
if ( ! strchr ( cep - > value , ' @ ' ) & & ! strchr ( cep - > value , ' : ' ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::kline-address must be an e-mail or an URL " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
else if ( match_simple ( " *@unrealircd.com " , cep - > value ) | | match_simple ( " *@unrealircd.org " , cep - > value ) | | match_simple ( " unreal-*@lists.sourceforge.net " , cep - > value ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::kline-address may not be an UnrealIRCd Team address " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ; continue ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " gline-address " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , gline_address , " gline-address " ) ;
2022-01-15 05:16:34 +00:00
if ( ! strchr ( cep - > value , ' @ ' ) & & ! strchr ( cep - > value , ' : ' ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::gline-address must be an e-mail or an URL " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
else if ( match_simple ( " *@unrealircd.com " , cep - > value ) | | match_simple ( " *@unrealircd.org " , cep - > value ) | | match_simple ( " unreal-*@lists.sourceforge.net " , cep - > value ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::gline-address may not be an UnrealIRCd Team address " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ; continue ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " modes-on-connect " ) ) {
2020-03-29 09:16:53 +00:00
char * p ;
CheckNull ( cep ) ;
CheckDuplicate ( cep , modes_on_connect , " modes-on-connect " ) ;
2022-01-15 05:16:34 +00:00
for ( p = cep - > value ; * p ; p + + )
2020-03-29 09:16:53 +00:00
if ( strchr ( " orzSHqtW " , * p ) )
{
config_error ( " %s:%i: set::modes-on-connect may not include mode '%c' " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , * p ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " modes-on-join " ) ) {
2020-03-29 09:16:53 +00:00
char * c ;
struct ChMode temp ;
memset ( & temp , 0 , sizeof ( temp ) ) ;
CheckNull ( cep ) ;
CheckDuplicate ( cep , modes_on_join , " modes-on-join " ) ;
2022-01-15 05:16:34 +00:00
for ( c = cep - > value ; * c ; c + + )
2020-03-29 09:16:53 +00:00
{
if ( * c = = ' ' )
break ; /* don't check the parameter ;p */
switch ( * c )
{
case ' q ' :
case ' a ' :
case ' o ' :
case ' h ' :
case ' v ' :
case ' b ' :
case ' e ' :
case ' I ' :
config_error ( " %s:%i: set::modes-on-join may not contain +%c " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , * c ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
break ;
}
}
2022-01-15 05:16:34 +00:00
/* We can't really verify much here.
* The channel mode modules have not been initialized
* yet at this point , so we can ' t really verify much
* here .
*/
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " modes-on-oper " ) ) {
2020-03-29 09:16:53 +00:00
char * p ;
CheckNull ( cep ) ;
CheckDuplicate ( cep , modes_on_oper , " modes-on-oper " ) ;
2022-01-15 05:16:34 +00:00
for ( p = cep - > value ; * p ; p + + )
2020-03-29 09:16:53 +00:00
if ( strchr ( " orzS " , * p ) )
{
config_error ( " %s:%i: set::modes-on-oper may not include mode '%c' " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , * p ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
set_usermode ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " snomask-on-oper " ) ) {
char * wrong_snomask ;
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , snomask_on_oper , " snomask-on-oper " ) ;
2022-01-15 05:16:34 +00:00
if ( ! is_valid_snomask_string_testing ( cep - > value , & wrong_snomask ) )
{
config_error ( " %s:%i: set::snomask-on-oper contains unknown snomask letter(s) '%s' " ,
cep - > file - > filename , cep - > line_number , wrong_snomask ) ;
errors + + ;
invalid_snomasks_encountered + + ;
}
}
else if ( ! strcmp ( cep - > name , " server-notice-colors " ) ) {
CheckNull ( cep ) ;
2020-03-29 09:16:53 +00:00
}
2022-04-03 15:09:29 +00:00
else if ( ! strcmp ( cep - > name , " server-notice-show-event " ) ) {
CheckNull ( cep ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " level-on-join " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , level_on_join , " level-on-join " ) ;
2022-01-15 05:16:34 +00:00
if ( ! channellevel_to_string ( cep - > value ) & & ( strlen ( cep - > value ) ! = 1 ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error ( " %s:%i: set::level-on-join: unknown value '%s', should be one of: "
" 'none', 'voice', 'halfop', 'op', 'admin', 'owner', or a single letter (eg 'o') " ,
cep - > file - > filename , cep - > line_number , cep - > value ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " static-quit " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , static_quit , " static-quit " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " static-part " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , static_part , " static-part " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " who-limit " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , who_limit , " who-limit " ) ;
2022-01-15 05:16:34 +00:00
if ( ! config_checkval ( cep - > value , CFG_SIZE ) )
2020-07-16 22:06:52 +00:00
{
config_error ( " %s:%i: set::who-limit: value must be at least 1 " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-07-16 22:06:52 +00:00
errors + + ;
}
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " maxbans " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , maxbans , " maxbans " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " maxbanlength " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , maxbanlength , " maxbanlength " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " silence-limit " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , silence_limit , " silence-limit " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " auto-join " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , auto_join , " auto-join " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " oper-auto-join " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , oper_auto_join , " oper-auto-join " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " check-target-nick-bans " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , check_target_nick_bans , " check-target-nick-bans " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " pingpong-warning " ) ) {
2020-03-29 09:16:53 +00:00
config_error ( " %s:%i: set::pingpong-warning no longer exists (the warning is always off) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ping-cookie " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , ping_cookie , " ping-cookie " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " watch-away-notification " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , watch_away_notification , " watch-away-notification " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " uhnames " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , uhnames , " uhnames " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " channel-command-prefix " ) ) {
2020-03-29 09:16:53 +00:00
CheckNullAllowEmpty ( cep ) ;
CheckDuplicate ( cep , channel_command_prefix , " channel-command-prefix " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " allow-userhost-change " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , allow_userhost_change , " allow-userhost-change " ) ;
2022-01-15 05:16:34 +00:00
if ( strcasecmp ( cep - > value , " always " ) & &
strcasecmp ( cep - > value , " never " ) & &
strcasecmp ( cep - > value , " not-on-channels " ) & &
strcasecmp ( cep - > value , " force-rejoin " ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::allow-userhost-change is invalid " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename ,
cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " anti-spam-quit-message-time " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , anti_spam_quit_message_time , " anti-spam-quit-message-time " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " oper-only-stats " ) )
2020-03-29 09:16:53 +00:00
{
config_warn ( " %s:%d: We no longer use a blacklist for stats (set::oper-only-stats) but "
" have a whitelist now instead (set::allow-user-stats). " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
config_warn ( " Simply delete the oper-only-stats line from your configuration file %s around line %d to get rid of this warning " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " allow-user-stats " ) )
2020-03-29 09:16:53 +00:00
{
CheckDuplicate ( cep , allow_user_stats , " allow-user-stats " ) ;
2022-01-15 05:16:34 +00:00
CheckNull ( cep ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " maxchannelsperuser " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , maxchannelsperuser , " maxchannelsperuser " ) ;
2022-01-15 05:16:34 +00:00
tempi = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( tempi < 1 )
{
config_error ( " %s:%i: set::maxchannelsperuser must be > 0 " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename ,
cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ping-warning " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , ping_warning , " ping-warning " ) ;
2022-01-15 05:16:34 +00:00
tempi = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
/* it is pointless to allow setting higher than 170 */
if ( tempi > 170 )
{
config_error ( " %s:%i: set::ping-warning must be < 170 " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename ,
cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " maxdccallow " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , maxdccallow , " maxdccallow " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " max-targets-per-command " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cepp ) ;
2022-01-15 05:16:34 +00:00
if ( ! strcasecmp ( cepp - > name , " NAMES " ) | | ! strcasecmp ( cepp - > name , " WHOWAS " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( atoi ( cepp - > value ) ! = 1 )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::max-targets-per-command::%s: "
" this command is hardcoded at a maximum of 1 "
" and cannot be configured to accept more. " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename ,
cepp - > line_number ,
cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
} else
2022-01-15 05:16:34 +00:00
if ( ! strcasecmp ( cepp - > name , " USERHOST " ) | |
! strcasecmp ( cepp - > name , " USERIP " ) | |
! strcasecmp ( cepp - > name , " ISON " ) | |
! strcasecmp ( cepp - > name , " WATCH " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( strcmp ( cepp - > value , " max " ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::max-targets-per-command::%s: "
" this command is hardcoded at a maximum of 'max' "
" and cannot be changed. This because it is "
" highly discouraged to change it. " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename ,
cepp - > line_number ,
cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
/* Now check the value syntax in general: */
2022-01-15 05:16:34 +00:00
if ( strcmp ( cepp - > value , " max " ) ) /* anything other than 'max'.. */
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
int v = atoi ( cepp - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ( v < 1 ) | | ( v > 20 ) )
{
config_error ( " %s:%i: set::max-targets-per-command::%s: "
" value should be 1-20 or 'max' " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename ,
cepp - > line_number ,
cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " network-name " ) ) {
2020-03-29 09:16:53 +00:00
char * p ;
CheckNull ( cep ) ;
CheckDuplicate ( cep , network_name , " network-name " ) ;
2022-01-15 05:16:34 +00:00
for ( p = cep - > value ; * p ; p + + )
2020-03-29 09:16:53 +00:00
if ( ( * p < ' ' ) | | ( * p > ' ~ ' ) )
{
config_error ( " %s:%i: set::network-name can only contain ASCII characters 33-126. Invalid character = '%c' " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , * p ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
break ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " default-server " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , default_server , " default-server " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " services-server " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , services_server , " services-server " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " sasl-server " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , sasl_server , " sasl-server " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " stats-server " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , stats_server , " stats-server " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " help-channel " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , help_channel , " help-channel " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " cloak-prefix " ) | | ! strcmp ( cep - > name , " hiddenhost-prefix " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
CheckDuplicate ( cep , hiddenhost_prefix , " cloak-prefix " ) ;
if ( strchr ( cep - > value , ' ' ) | | ( * cep - > value = = ' : ' ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error ( " %s:%i: set::cloak-prefix must not contain spaces or be prefixed with ':' " ,
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " prefix-quit " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , prefix_quit , " prefix-quit " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " hide-ban-reason " ) ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cep ) ;
CheckDuplicate ( cep , hide_ban_reason , " hide-ban-reason " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " restrict-usermodes " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cep ) ;
CheckDuplicate ( cep , restrict_usermodes , " restrict-usermodes " ) ;
2022-01-15 05:16:34 +00:00
if ( cep - > name ) {
2020-03-29 09:16:53 +00:00
int warn = 0 ;
char * p ;
2022-01-15 05:16:34 +00:00
for ( p = cep - > value ; * p ; p + + )
2020-03-29 09:16:53 +00:00
if ( ( * p = = ' + ' ) | | ( * p = = ' - ' ) )
warn = 1 ;
if ( warn ) {
config_status ( " %s:%i: warning: set::restrict-usermodes: should only contain modechars, no + or -. \n " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " restrict-channelmodes " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cep ) ;
CheckDuplicate ( cep , restrict_channelmodes , " restrict-channelmodes " ) ;
2022-01-15 05:16:34 +00:00
if ( cep - > name ) {
2020-03-29 09:16:53 +00:00
int warn = 0 ;
char * p ;
2022-01-15 05:16:34 +00:00
for ( p = cep - > value ; * p ; p + + )
2020-03-29 09:16:53 +00:00
if ( ( * p = = ' + ' ) | | ( * p = = ' - ' ) )
warn = 1 ;
if ( warn ) {
config_status ( " %s:%i: warning: set::restrict-channelmodes: should only contain modechars, no + or -. \n " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " restrict-extendedbans " ) )
2020-03-29 09:16:53 +00:00
{
CheckDuplicate ( cep , restrict_extendedbans , " restrict-extendedbans " ) ;
CheckNull ( cep ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " named-extended-bans " ) )
{
CheckNull ( cep ) ;
}
else if ( ! strcmp ( cep - > name , " link " ) ) {
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next ) {
2020-03-29 09:16:53 +00:00
CheckNull ( cepp ) ;
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " bind-ip " ) ) {
2020-03-29 09:16:53 +00:00
CheckDuplicate ( cepp , link_bind_ip , " link::bind-ip " ) ;
2022-01-15 05:16:34 +00:00
if ( strcmp ( cepp - > value , " * " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! is_valid_ip ( cepp - > value ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::link::bind-ip (%s) is not a valid IP " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number ,
cepp - > value ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " throttle " ) ) {
2020-03-29 09:16:53 +00:00
config_error ( " %s:%i: set::throttle has been renamed. you now use "
" set::anti-flood::connect-flood <connections>:<period>. "
" Or just remove the throttle block and you get the default "
" of 3 per 60 seconds. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " anti-flood " ) )
2021-03-21 17:05:35 +00:00
{
2021-06-19 15:52:51 +00:00
int anti_flood_old = 0 ;
int anti_flood_old_and_default = 0 ;
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2021-03-21 17:05:35 +00:00
{
2022-01-15 05:16:34 +00:00
int has_lag_penalty = 0 ;
int has_lag_penalty_bytes = 0 ;
2021-06-19 15:52:51 +00:00
/* Test for old options: */
2022-01-15 05:16:34 +00:00
if ( flood_option_is_old ( cepp - > name ) )
2020-03-29 09:16:53 +00:00
{
2021-06-19 15:52:51 +00:00
/* Special code if the user is using 100% of the defaults */
2022-01-15 05:16:34 +00:00
if ( cepp - > value & &
( ( ! strcmp ( cepp - > name , " nick-flood " ) & & ! strcmp ( cepp - > value , " 3:60 " ) ) | |
( ! strcmp ( cepp - > name , " connect-flood " ) & & cepp - > value & & ! strcmp ( cepp - > value , " 3:60 " ) ) | |
( ! strcmp ( cepp - > name , " away-flood " ) & & cepp - > value & & ! strcmp ( cepp - > value , " 4:120 " ) ) ) )
2020-03-29 09:16:53 +00:00
{
2021-06-19 15:52:51 +00:00
anti_flood_old_and_default = 1 ;
} else
{
anti_flood_old = 1 ;
2020-03-29 09:16:53 +00:00
}
2021-03-21 17:05:35 +00:00
continue ;
2020-03-29 09:16:53 +00:00
}
2021-06-19 15:52:51 +00:00
2022-01-15 05:16:34 +00:00
for ( ceppp = cepp - > items ; ceppp ; ceppp = ceppp - > next )
2020-05-29 02:06:50 +00:00
{
2023-05-05 22:12:01 +00:00
int everyone ;
int for_everyone ;
int used = 0 ;
Hook * h ;
/* First, check hooks... */
for ( h = Hooks [ HOOKTYPE_CONFIGTEST ] ; h ; h = h - > next )
{
int value , errs = 0 ;
if ( h - > owner & & ! ( h - > owner - > flags & MODFLAG_TESTING )
& & ! ( h - > owner - > options & MOD_OPT_PERM ) )
continue ;
value = ( * ( h - > func . intfunc ) ) ( conf , ceppp , CONFIG_SET_ANTI_FLOOD , & errs ) ;
if ( value = = 2 )
{
used = 2 ;
break ;
} else
if ( value = = 1 )
{
used = 1 ;
break ;
} else
if ( value = = - 1 )
{
used = 1 ;
errors + = errs ;
break ;
} else
if ( value = = - 2 )
{
used = 2 ;
errors + = errs ;
break ;
}
}
if ( used = = 1 )
continue ; /* module handled it */
if ( used = = 2 )
break ; /* module handled it and we must stop entire block processing */
2021-06-19 15:52:51 +00:00
2023-05-05 22:12:01 +00:00
/* Prevent users from using options that belong in "everyone"
* at other places , and vice - versa .
*/
everyone = ! strcmp ( cepp - > name , " everyone " ) ? 1 : 0 ;
for_everyone = flood_option_is_for_everyone ( ceppp - > name ) ;
2021-06-19 15:52:51 +00:00
if ( everyone & & ! for_everyone )
{
config_error ( " %s:%i: %s cannot be in the set::anti-flood::everyone block. "
" You can put it in 'known-users' or 'unknown-users' instead. " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number ,
ceppp - > name ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
continue ;
} else
if ( ! everyone & & for_everyone )
2021-03-21 17:05:35 +00:00
{
2021-06-19 15:52:51 +00:00
config_error ( " %s:%i: %s must be in the set::anti-flood::everyone block, not anywhere else. " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number ,
ceppp - > name ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
continue ;
}
/* Now comes the actual config check for each element... */
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ceppp - > name , " max-concurrent-conversations " ) )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cep4 = ceppp - > items ; cep4 ; cep4 = cep4 - > next )
2021-03-21 17:05:35 +00:00
{
2021-06-19 15:52:51 +00:00
CheckNull ( cep4 ) ;
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep4 - > name , " users " ) )
2021-03-21 17:05:35 +00:00
{
2022-01-15 05:16:34 +00:00
int v = atoi ( cep4 - > value ) ;
2021-06-19 15:52:51 +00:00
if ( ( v < 1 ) | | ( v > MAXCCUSERS ) )
{
config_error ( " %s:%i: set::anti-flood::max-concurrent-conversations::users: "
" value should be between 1 and %d " ,
2022-01-15 05:16:34 +00:00
cep4 - > file - > filename , cep4 - > line_number , MAXCCUSERS ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep4 - > name , " new-user-every " ) )
2021-03-21 17:05:35 +00:00
{
2022-01-15 05:16:34 +00:00
long v = config_checkval ( cep4 - > value , CFG_TIME ) ;
2021-06-19 15:52:51 +00:00
if ( ( v < 1 ) | | ( v > 120 ) )
{
config_error ( " %s:%i: set::anti-flood::max-concurrent-conversations::new-user-every: "
" value should be between 1 and 120 seconds " ,
2022-01-15 05:16:34 +00:00
cep4 - > file - > filename , cep4 - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
} else
{
2022-01-15 05:16:34 +00:00
config_error_unknownopt ( cep4 - > file - > filename ,
cep4 - > line_number , " set::anti-flood " ,
cep4 - > name ) ;
2021-03-21 17:05:35 +00:00
errors + + ;
}
}
2021-06-19 15:52:51 +00:00
continue ; /* required here, due to checknull directly below */
2021-03-21 17:05:35 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " unknown-flood-amount " ) | |
! strcmp ( ceppp - > name , " unknown-flood-bantime " ) )
2020-03-29 09:16:53 +00:00
{
2021-06-19 15:52:51 +00:00
config_error ( " %s:%i: set::anti-flood::%s: this setting has been moved. "
" See https://www.unrealircd.org/docs/Anti-flood_settings#handshake-data-flood " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number , ceppp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
2021-06-19 15:52:51 +00:00
continue ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " handshake-data-flood " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cep4 = ceppp - > items ; cep4 ; cep4 = cep4 - > next )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep4 - > name , " amount " ) )
2021-06-19 15:52:51 +00:00
{
long v ;
CheckNull ( cep4 ) ;
2022-01-15 05:16:34 +00:00
v = config_checkval ( cep4 - > value , CFG_SIZE ) ;
2021-06-19 15:52:51 +00:00
if ( v < 1024 )
{
config_error ( " %s:%i: set::anti-flood::handshake-data-flood::amount must be at least 1024 bytes " ,
2022-01-15 05:16:34 +00:00
cep4 - > file - > filename , cep4 - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep4 - > name , " ban-action " ) )
2021-06-19 15:52:51 +00:00
{
CheckNull ( cep4 ) ;
2022-01-15 05:16:34 +00:00
if ( ! banact_stringtoval ( cep4 - > value ) )
2021-06-19 15:52:51 +00:00
{
config_error ( " %s:%i: set::anti-flood::handshake-data-flood::ban-action has unknown action type '%s' " ,
2022-01-15 05:16:34 +00:00
cep4 - > file - > filename , cep4 - > line_number ,
cep4 - > value ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep4 - > name , " ban-time " ) )
2021-06-19 15:52:51 +00:00
{
CheckNull ( cep4 ) ;
} else
{
2022-01-15 05:16:34 +00:00
config_error_unknownopt ( cep4 - > file - > filename ,
cep4 - > line_number , " set::anti-flood::handshake-data-flood " ,
cep4 - > name ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
}
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " away-count " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
int temp = atol ( ceppp - > value ) ;
2021-06-19 15:52:51 +00:00
CheckNull ( ceppp ) ;
if ( temp < 1 | | temp > 255 )
{
config_error ( " %s:%i: set::anti-flood::away-count must be between 1 and 255 " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " away-period " ) )
2020-03-29 09:16:53 +00:00
{
2021-06-19 15:52:51 +00:00
CheckNull ( ceppp ) ;
2022-01-15 05:16:34 +00:00
int temp = config_checkval ( ceppp - > value , CFG_TIME ) ;
2021-06-19 15:52:51 +00:00
if ( temp < 10 )
{
config_error ( " %s:%i: set::anti-flood::away-period must be greater than 9 " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " away-flood " ) )
2020-03-29 09:16:53 +00:00
{
2021-06-19 15:52:51 +00:00
int cnt , period ;
CheckNull ( ceppp ) ;
2022-01-15 05:16:34 +00:00
if ( ! config_parse_flood ( ceppp - > value , & cnt , & period ) | |
2021-06-19 15:52:51 +00:00
( cnt < 1 ) | | ( cnt > 255 ) | | ( period < 10 ) )
{
config_error ( " %s:%i: set::anti-flood::away-flood error. Syntax is '<count>:<period>' (eg 5:60), "
" count should be 1-255, period should be greater than 9 " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " nick-flood " ) )
2020-03-29 09:16:53 +00:00
{
2021-06-19 15:52:51 +00:00
int cnt , period ;
CheckNull ( ceppp ) ;
2022-01-15 05:16:34 +00:00
if ( ! config_parse_flood ( ceppp - > value , & cnt , & period ) | |
2021-06-19 15:52:51 +00:00
( cnt < 1 ) | | ( cnt > 255 ) | | ( period < 5 ) )
{
config_error ( " %s:%i: set::anti-flood::nick-flood error. Syntax is '<count>:<period>' (eg 5:60), "
" count should be 1-255, period should be greater than 4 " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
2020-03-29 09:16:53 +00:00
}
2022-04-03 15:09:29 +00:00
else if ( ! strcmp ( ceppp - > name , " vhost-flood " ) )
{
int cnt , period ;
CheckNull ( ceppp ) ;
if ( ! config_parse_flood ( ceppp - > value , & cnt , & period ) | |
( cnt < 1 ) | | ( cnt > 255 ) | | ( period < 5 ) )
{
config_error ( " %s:%i: set::anti-flood::vhost-flood error. Syntax is '<count>:<period>' (eg 5:60), "
" count should be 1-255, period should be greater than 4 " ,
ceppp - > file - > filename , ceppp - > line_number ) ;
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " join-flood " ) )
2020-03-29 09:16:53 +00:00
{
2021-06-19 15:52:51 +00:00
int cnt , period ;
CheckNull ( ceppp ) ;
2022-01-15 05:16:34 +00:00
if ( ! config_parse_flood ( ceppp - > value , & cnt , & period ) | |
2021-06-19 15:52:51 +00:00
( cnt < 1 ) | | ( cnt > 255 ) | | ( period < 5 ) )
{
config_error ( " %s:%i: join-flood error. Syntax is '<count>:<period>' (eg 5:60), "
" count should be 1-255, period should be greater than 4 " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " invite-flood " ) )
2020-03-29 09:16:53 +00:00
{
2021-06-19 15:52:51 +00:00
int cnt , period ;
CheckNull ( ceppp ) ;
2022-01-15 05:16:34 +00:00
if ( ! config_parse_flood ( ceppp - > value , & cnt , & period ) | |
2021-06-19 15:52:51 +00:00
( cnt < 1 ) | | ( cnt > 255 ) | | ( period < 5 ) )
{
config_error ( " %s:%i: set::anti-flood::invite-flood error. Syntax is '<count>:<period>' (eg 5:60), "
" count should be 1-255, period should be greater than 4 " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " knock-flood " ) )
2020-03-29 09:16:53 +00:00
{
2021-06-19 15:52:51 +00:00
int cnt , period ;
CheckNull ( ceppp ) ;
2022-01-15 05:16:34 +00:00
if ( ! config_parse_flood ( ceppp - > value , & cnt , & period ) | |
2021-06-19 15:52:51 +00:00
( cnt < 1 ) | | ( cnt > 255 ) | | ( period < 5 ) )
{
config_error ( " %s:%i: set::anti-flood::knock-flood error. Syntax is '<count>:<period>' (eg 5:60), "
" count should be 1-255, period should be greater than 4 " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number ) ;
errors + + ;
}
}
else if ( ! strcmp ( ceppp - > name , " lag-penalty " ) )
{
int v ;
CheckNull ( ceppp ) ;
v = atoi ( ceppp - > value ) ;
has_lag_penalty = 1 ;
if ( ( v < 0 ) | | ( v > 10000 ) )
{
config_error ( " %s:%i: set::anti-flood::%s::lag-penalty: value is in milliseconds and should be between 0 and 10000 " ,
ceppp - > file - > filename , ceppp - > line_number , cepp - > name ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ceppp - > name , " lag-penalty-bytes " ) )
{
has_lag_penalty_bytes = 1 ;
CheckNull ( ceppp ) ;
}
else if ( ! strcmp ( ceppp - > name , " connect-flood " ) )
2020-03-29 09:16:53 +00:00
{
2021-06-19 15:52:51 +00:00
int cnt , period ;
CheckNull ( ceppp ) ;
2022-01-15 05:16:34 +00:00
if ( strcmp ( cepp - > name , " everyone " ) )
2021-06-19 15:52:51 +00:00
{
config_error ( " %s:%i: connect-flood must be in the set::anti-flood::everyone block, not anywhere else. " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
2020-03-29 09:16:53 +00:00
continue ;
2021-06-19 15:52:51 +00:00
}
2022-01-15 05:16:34 +00:00
if ( ! config_parse_flood ( ceppp - > value , & cnt , & period ) | |
2021-06-19 15:52:51 +00:00
( cnt < 1 ) | | ( cnt > 255 ) | | ( period < 1 ) | | ( period > 3600 ) )
2020-03-29 09:16:53 +00:00
{
2021-06-19 15:52:51 +00:00
config_error ( " %s:%i: set::anti-flood::connect-flood: Syntax is '<count>:<period>' (eg 5:60), "
" count should be 1-255, period should be 1-3600 " ,
2022-01-15 05:16:34 +00:00
ceppp - > file - > filename , ceppp - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
2020-03-29 09:16:53 +00:00
}
2021-06-19 15:52:51 +00:00
}
else
{
2023-05-05 22:12:01 +00:00
config_error_unknownopt ( ceppp - > file - > filename ,
ceppp - > line_number , " set::anti-flood " ,
ceppp - > name ) ;
errors + + ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
if ( has_lag_penalty + has_lag_penalty_bytes = = 1 )
{
config_error ( " %s:%i: set::anti-flood::%s: if you use lag-penalty then you must also add an lag-penalty-bytes item (and vice-versa) " ,
cepp - > file - > filename , cepp - > line_number , cepp - > name ) ;
errors + + ;
}
2020-03-29 09:16:53 +00:00
}
2021-06-19 15:52:51 +00:00
/* Now the warnings: */
if ( anti_flood_old = = 1 )
{
config_warn ( " %s:%d: the set::anti-flood block has been reorganized to be more flexible. "
" Your custom anti-flood settings have NOT been read. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2021-06-19 15:52:51 +00:00
config_warn ( " See https://www.unrealircd.org/docs/Anti-flood_settings for the new block style, " ) ;
config_warn ( " OR: simply remove all the anti-flood options from the conf to get rid of this "
" warning and use the built-in defaults. " ) ;
} else
if ( anti_flood_old_and_default = = 1 )
{
config_warn ( " %s:%d: the set::anti-flood block has been reorganized to be more flexible. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2021-06-19 15:52:51 +00:00
config_warn ( " To fix this warning, delete the anti-flood block from your configuration file "
" (file %s around line %d), this will make UnrealIRCd use the built-in defaults. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2021-06-19 15:52:51 +00:00
config_warn ( " If you want to learn more about the new functionality you can visit "
" https://www.unrealircd.org/docs/Anti-flood_settings " ) ;
}
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " options " ) ) {
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next ) {
if ( ! strcmp ( cepp - > name , " hide-ulines " ) )
2020-03-29 09:16:53 +00:00
{
CheckDuplicate ( cepp , options_hide_ulines , " options::hide-ulines " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " flat-map " ) ) {
2020-03-29 09:16:53 +00:00
CheckDuplicate ( cepp , options_flat_map , " options::flat-map " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " show-opermotd " ) ) {
2020-03-29 09:16:53 +00:00
CheckDuplicate ( cepp , options_show_opermotd , " options::show-opermotd " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " identd-check " ) ) {
2020-03-29 09:16:53 +00:00
CheckDuplicate ( cepp , options_identd_check , " options::identd-check " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " fail-oper-warn " ) ) {
2020-03-29 09:16:53 +00:00
CheckDuplicate ( cepp , options_fail_oper_warn , " options::fail-oper-warn " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " show-connect-info " ) ) {
2020-03-29 09:16:53 +00:00
CheckDuplicate ( cepp , options_show_connect_info , " options::show-connect-info " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " no-connect-tls-info " ) ) {
2020-03-29 09:16:53 +00:00
CheckDuplicate ( cepp , options_no_connect_tls_info , " options::no-connect-tls-info " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " dont-resolve " ) ) {
2020-03-29 09:16:53 +00:00
CheckDuplicate ( cepp , options_dont_resolve , " options::dont-resolve " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " mkpasswd-for-everyone " ) ) {
2020-03-29 09:16:53 +00:00
CheckDuplicate ( cepp , options_mkpasswd_for_everyone , " options::mkpasswd-for-everyone " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " allow-insane-bans " ) ) {
2020-03-29 09:16:53 +00:00
CheckDuplicate ( cepp , options_allow_insane_bans , " options::allow-insane-bans " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " allow-part-if-shunned " ) ) {
2020-03-29 09:16:53 +00:00
CheckDuplicate ( cepp , options_allow_part_if_shunned , " options::allow-part-if-shunned " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " disable-cap " ) ) {
2020-03-29 09:16:53 +00:00
CheckDuplicate ( cepp , options_disable_cap , " options::disable-cap " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " disable-ipv6 " ) ) {
2020-03-29 09:16:53 +00:00
CheckDuplicate ( cepp , options_disable_ipv6 , " options::disable-ipv6 " ) ;
DISABLE_IPV6 = 1 ; /* ugly ugly. needs to be done here because at conf runtime is too late. */
}
else
{
2022-01-15 05:16:34 +00:00
config_error_unknownopt ( cepp - > file - > filename ,
cepp - > line_number , " set::options " ,
cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " hosts " ) ) {
config_error ( " %s:%i: set::hosts has been removed. You can use oper::vhost now. " ,
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " cloak-keys " ) )
2020-03-29 09:16:53 +00:00
{
CheckDuplicate ( cep , cloak_keys , " cloak-keys " ) ;
for ( h = Hooks [ HOOKTYPE_CONFIGTEST ] ; h ; h = h - > next )
{
int value , errs = 0 ;
if ( h - > owner & & ! ( h - > owner - > flags & MODFLAG_TESTING )
& & ! ( h - > owner - > options & MOD_OPT_PERM ) )
continue ;
value = ( * ( h - > func . intfunc ) ) ( conf , cep , CONFIG_CLOAKKEYS , & errs ) ;
if ( value = = 1 )
break ;
if ( value = = - 1 )
{
errors + = errs ;
break ;
}
if ( value = = - 2 )
errors + = errs ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ident " ) ) {
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
int is_ok = 0 ;
CheckNull ( cepp ) ;
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " connect-timeout " ) )
2020-03-29 09:16:53 +00:00
{
is_ok = 1 ;
CheckDuplicate ( cepp , ident_connect_timeout , " ident::connect-timeout " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " read-timeout " ) )
2020-03-29 09:16:53 +00:00
{
is_ok = 1 ;
CheckDuplicate ( cepp , ident_read_timeout , " ident::read-timeout " ) ;
}
if ( is_ok )
{
2022-01-15 05:16:34 +00:00
int v = config_checkval ( cepp - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
if ( ( v > 60 ) | | ( v < 1 ) )
{
config_error ( " %s:%i: set::ident::%s value out of range (%d), should be between 1 and 60. " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number , cepp - > name , v ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
} else {
2022-01-15 05:16:34 +00:00
config_error_unknown ( cepp - > file - > filename ,
cepp - > line_number , " set::ident " ,
cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " timesync " ) | | ! strcmp ( cep - > name , " timesynch " ) )
2020-03-29 09:16:53 +00:00
{
config_warn ( " %s:%i: Timesync support has been removed from UnrealIRCd. "
" Please remove any set::timesync blocks you may have. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
config_warn ( " Use the time synchronization feature of your OS/distro instead! " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " spamfilter " ) ) {
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cepp ) ;
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " ban-time " ) )
2020-03-29 09:16:53 +00:00
{
long x ;
CheckDuplicate ( cepp , spamfilter_ban_time , " spamfilter::ban-time " ) ;
2022-01-15 05:16:34 +00:00
x = config_checkval ( cepp - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
if ( ( x < 0 ) > ( x > 2000000000 ) )
{
config_error ( " %s:%i: set::spamfilter:ban-time: value '%ld' out of range " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , x ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " ban-reason " ) )
2020-03-29 09:16:53 +00:00
{
CheckDuplicate ( cepp , spamfilter_ban_reason , " spamfilter::ban-reason " ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " virus-help-channel " ) )
2020-03-29 09:16:53 +00:00
{
CheckDuplicate ( cepp , spamfilter_virus_help_channel , " spamfilter::virus-help-channel " ) ;
2022-01-15 05:16:34 +00:00
if ( ( cepp - > value [ 0 ] ! = ' # ' ) | | ( strlen ( cepp - > value ) > CHANNELLEN ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::spamfilter:virus-help-channel: "
" specified channelname is too long or contains invalid characters (%s) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ,
cepp - > value ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " virus-help-channel-deny " ) )
2020-03-29 09:16:53 +00:00
{
CheckDuplicate ( cepp , spamfilter_virus_help_channel_deny , " spamfilter::virus-help-channel-deny " ) ;
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " except " ) )
2020-03-29 09:16:53 +00:00
{
CheckDuplicate ( cepp , spamfilter_except , " spamfilter::except " ) ;
} else
# ifdef SPAMFILTER_DETECTSLOW
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " detect-slow-warn " ) )
2020-03-29 09:16:53 +00:00
{
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " detect-slow-fatal " ) )
2020-03-29 09:16:53 +00:00
{
} else
# endif
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " stop-on-first-match " ) )
2020-03-29 09:16:53 +00:00
{
} else
2023-05-05 22:12:01 +00:00
if ( ! strcmp ( cepp - > name , " utf8 " ) )
{
} else
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cepp - > file - > filename ,
cepp - > line_number , " set::spamfilter " ,
cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " default-bantime " ) )
2020-03-29 09:16:53 +00:00
{
long x ;
CheckDuplicate ( cep , default_bantime , " default-bantime " ) ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
x = config_checkval ( cep - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
if ( ( x < 0 ) > ( x > 2000000000 ) )
{
config_error ( " %s:%i: set::default-bantime: value '%ld' out of range " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , x ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ban-version-tkl-time " ) ) {
2020-03-29 09:16:53 +00:00
long x ;
CheckDuplicate ( cep , ban_version_tkl_time , " ban-version-tkl-time " ) ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
x = config_checkval ( cep - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
if ( ( x < 0 ) > ( x > 2000000000 ) )
{
config_error ( " %s:%i: set::ban-version-tkl-time: value '%ld' out of range " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , x ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " min-nick-length " ) ) {
2020-03-29 09:16:53 +00:00
int v ;
CheckDuplicate ( cep , min_nick_length , " min-nick-length " ) ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ( v < = 0 ) | | ( v > NICKLEN ) )
{
config_error ( " %s:%i: set::min-nick-length: value '%d' out of range (should be 1-%d) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , v , NICKLEN ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
else
nicklengths . min = v ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " nick-length " ) ) {
2020-03-29 09:16:53 +00:00
int v ;
CheckDuplicate ( cep , nick_length , " nick-length " ) ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ( v < = 0 ) | | ( v > NICKLEN ) )
{
config_error ( " %s:%i: set::nick-length: value '%d' out of range (should be 1-%d) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , v , NICKLEN ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
else
nicklengths . max = v ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " topic-length " ) ) {
2020-03-29 09:16:53 +00:00
int v ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ( v < = 0 ) | | ( v > MAXTOPICLEN ) )
{
config_error ( " %s:%i: set::topic-length: value '%d' out of range (should be 1-%d) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , v , MAXTOPICLEN ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " away-length " ) ) {
2020-03-29 09:16:53 +00:00
int v ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ( v < = 0 ) | | ( v > MAXAWAYLEN ) )
{
config_error ( " %s:%i: set::away-length: value '%d' out of range (should be 1-%d) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , v , MAXAWAYLEN ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " kick-length " ) ) {
2020-03-29 09:16:53 +00:00
int v ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ( v < = 0 ) | | ( v > MAXKICKLEN ) )
{
config_error ( " %s:%i: set::kick-length: value '%d' out of range (should be 1-%d) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , v , MAXKICKLEN ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " quit-length " ) ) {
2020-03-29 09:16:53 +00:00
int v ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ( v < = 0 ) | | ( v > MAXQUITLEN ) )
{
config_error ( " %s:%i: set::quit-length: value '%d' out of range (should be 1-%d) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , v , MAXQUITLEN ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ssl " ) | | ! strcmp ( cep - > name , " tls " ) ) {
2020-03-29 09:16:53 +00:00
test_tlsblock ( conf , cep , & errors ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " plaintext-policy " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " user " ) | |
! strcmp ( cepp - > name , " oper " ) | |
! strcmp ( cepp - > name , " server " ) )
2020-03-29 09:16:53 +00:00
{
Policy policy ;
CheckNull ( cepp ) ;
2022-01-15 05:16:34 +00:00
policy = policy_strtoval ( cepp - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ! policy )
{
config_error ( " %s:%i: set::plaintext-policy::%s: needs to be one of: 'allow', 'warn' or 'reject' " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number , cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
} else if ( ! strcmp ( cepp - > name , " user-message " ) | |
! strcmp ( cepp - > name , " oper-message " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cepp ) ;
} else {
2022-01-15 05:16:34 +00:00
config_error_unknown ( cepp - > file - > filename ,
cepp - > line_number , " set::plaintext-policy " ,
cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " outdated-tls-policy " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " user " ) | |
! strcmp ( cepp - > name , " oper " ) | |
! strcmp ( cepp - > name , " server " ) )
2020-03-29 09:16:53 +00:00
{
Policy policy ;
CheckNull ( cepp ) ;
2022-01-15 05:16:34 +00:00
policy = policy_strtoval ( cepp - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ! policy )
{
config_error ( " %s:%i: set::outdated-tls-policy::%s: needs to be one of: 'allow', 'warn' or 'reject' " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number , cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
} else if ( ! strcmp ( cepp - > name , " user-message " ) | |
! strcmp ( cepp - > name , " oper-message " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cepp ) ;
} else {
2022-01-15 05:16:34 +00:00
config_error_unknown ( cepp - > file - > filename ,
cepp - > line_number , " set::outdated-tls-policy " ,
cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " default-ipv6-clone-mask " ) )
2020-03-29 09:16:53 +00:00
{
/* keep this in sync with _test_allow() */
int ipv6mask ;
2022-11-20 04:12:40 +00:00
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
ipv6mask = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( ipv6mask = = 0 )
{
config_error ( " %s:%d: set::default-ipv6-clone-mask given a value of zero. This cannnot be correct, as it would treat all IPv6 hosts as one host. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
if ( ipv6mask > 128 )
{
config_error ( " %s:%d: set::default-ipv6-clone-mask was set to %d. The maximum value is 128. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ,
2020-03-29 09:16:53 +00:00
ipv6mask ) ;
errors + + ;
}
if ( ipv6mask < = 32 )
{
config_warn ( " %s:%d: set::default-ipv6-clone-mask was given a very small value. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " hide-list " ) ) {
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " deny-channel " ) )
2020-03-29 09:16:53 +00:00
{
} else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cepp - > file - > filename ,
cepp - > line_number , " set::hide-list " ,
cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " max-unknown-connections-per-ip " ) ) {
2020-03-29 09:16:53 +00:00
int v ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
v = atoi ( cep - > value ) ;
2020-03-29 09:16:53 +00:00
if ( v < 1 )
{
config_error ( " %s:%i: set::max-unknown-connections-per-ip: value should be at least 1. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " handshake-timeout " ) ) {
2020-03-29 09:16:53 +00:00
int v ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
v = config_checkval ( cep - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
if ( v < 5 )
{
config_error ( " %s:%i: set::handshake-timeout: value should be at least 5 seconds. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " sasl-timeout " ) ) {
2020-03-29 09:16:53 +00:00
int v ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
v = config_checkval ( cep - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
if ( v < 5 )
{
config_error ( " %s:%i: set::sasl-timeout: value should be at least 5 seconds. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " handshake-delay " ) )
2020-03-29 09:16:53 +00:00
{
int v ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
v = config_checkval ( cep - > value , CFG_TIME ) ;
2020-03-29 09:16:53 +00:00
if ( v > = 10 )
{
config_error ( " %s:%i: set::handshake-delay: value should be less than 10 seconds. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ban-include-username " ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::ban-include-username is no longer supported. "
" Use set { automatic-ban-target userip; }; instead. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
config_error ( " See https://www.unrealircd.org/docs/Set_block#set::automatic-ban-target "
" for more information and options. " ) ;
errors + + ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " automatic-ban-target " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
if ( ! ban_target_strtoval ( cep - > value ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::automatic-ban-target: value '%s' is not recognized. "
" See https://www.unrealircd.org/docs/Set_block#set::automatic-ban-target " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , cep - > value ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " manual-ban-target " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
if ( ! ban_target_strtoval ( cep - > value ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::manual-ban-target: value '%s' is not recognized. "
" See https://www.unrealircd.org/docs/Set_block#set::manual-ban-target " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , cep - > value ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " reject-message " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cepp ) ;
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " password-mismatch " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " too-many-connections " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " server-full " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " unauthorized " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " kline " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " gline " ) )
2020-03-29 09:16:53 +00:00
;
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cepp - > file - > filename ,
cepp - > line_number , " set::reject-message " ,
cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " topic-setter " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
if ( strcmp ( cep - > value , " nick " ) & & strcmp ( cep - > value , " nick-user-host " ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::topic-setter: value should be 'nick' or 'nick-user-host' " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ban-setter " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
if ( strcmp ( cep - > value , " nick " ) & & strcmp ( cep - > value , " nick-user-host " ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::ban-setter: value should be 'nick' or 'nick-user-host' " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " ban-setter-sync " ) | | ! strcmp ( cep - > name , " ban-setter-synch " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cep ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " part-instead-of-quit-on-comment-change " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cep ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " broadcast-channel-messages " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
if ( strcmp ( cep - > value , " auto " ) & &
strcmp ( cep - > value , " always " ) & &
strcmp ( cep - > value , " never " ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::broadcast-channel-messages: value should be 'auto', 'always' or 'never' " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " allowed-channelchars " ) )
2020-03-29 09:16:53 +00:00
{
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
if ( ! allowed_channelchars_strtoval ( cep - > value ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: set::allowed-channelchars: value should be one of: 'ascii', 'utf8' or 'any' " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " hide-idle-time " ) )
2020-04-20 19:12:33 +00:00
{
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-04-20 19:12:33 +00:00
{
CheckNull ( cepp ) ;
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " policy " ) )
2020-04-20 19:12:33 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! hideidletime_strtoval ( cepp - > value ) )
2020-04-20 19:12:33 +00:00
{
config_error ( " %s:%i: set::hide-idle-time::policy: value should be one of: 'never', 'always', 'usermode' or 'oper-usermode' " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number ) ;
2020-04-20 19:12:33 +00:00
errors + + ;
}
}
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cepp - > file - > filename ,
cepp - > line_number , " set::hide-idle-time " ,
cepp - > name ) ;
2020-04-20 19:12:33 +00:00
errors + + ;
continue ;
}
}
2023-05-05 22:12:01 +00:00
} else if ( ! strcmp ( cep - > name , " limit-svscmds " ) )
{
CheckNull ( cep ) ;
if ( strcmp ( cep - > value , " servers " ) & & strcmp ( cep - > value , " ulines " ) )
{
config_error ( " %s:%i: set::limit-svscmds: value must be one of: 'servers' or 'ulines' " ,
cep - > file - > filename , cep - > line_number ) ;
errors + + ;
}
2022-01-15 05:16:34 +00:00
} else
2020-03-29 09:16:53 +00:00
{
int used = 0 ;
for ( h = Hooks [ HOOKTYPE_CONFIGTEST ] ; h ; h = h - > next )
{
int value , errs = 0 ;
if ( h - > owner & & ! ( h - > owner - > flags & MODFLAG_TESTING ) & &
! ( h - > owner - > options & MOD_OPT_PERM ) )
continue ;
value = ( * ( h - > func . intfunc ) ) ( conf , cep , CONFIG_SET , & errs ) ;
if ( value = = 2 )
used = 1 ;
if ( value = = 1 )
{
used = 1 ;
break ;
}
if ( value = = - 1 )
{
used = 1 ;
errors + = errs ;
break ;
}
if ( value = = - 2 )
{
used = 1 ;
errors + = errs ;
}
}
if ( ! used ) {
config_error ( " %s:%i: unknown directive set::%s " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ,
cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
}
return errors ;
}
int _conf_loadmodule ( ConfigFile * conf , ConfigEntry * ce )
{
2022-01-15 05:16:34 +00:00
const char * ret ;
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
{
config_status ( " %s:%i: loadmodule without filename " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return - 1 ;
}
2022-01-15 05:16:34 +00:00
if ( is_blacklisted_module ( ce - > value ) )
2020-03-29 09:16:53 +00:00
{
/* config_warn("%s:%i: Module '%s' is blacklisted, not loading",
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number , ce - > value ) ; */
2020-03-29 09:16:53 +00:00
return 1 ;
}
2022-01-15 05:16:34 +00:00
if ( ( ret = Module_Create ( ce - > value ) ) ) {
config_error ( " %s:%i: loadmodule %s: failed to load: %s " ,
ce - > file - > filename , ce - > line_number ,
ce - > value , ret ) ;
2020-03-29 09:16:53 +00:00
return - 1 ;
}
return 1 ;
}
int _test_loadmodule ( ConfigFile * conf , ConfigEntry * ce )
{
return 0 ;
}
int _test_blacklist_module ( ConfigFile * conf , ConfigEntry * ce )
{
2022-01-15 05:16:34 +00:00
const char * path ;
2020-03-29 09:16:53 +00:00
ConfigItem_blacklist_module * m ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
{
config_status ( " %s:%i: blacklist-module: no module name given to blacklist " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return - 1 ;
}
2022-01-15 05:16:34 +00:00
path = Module_TransformPath ( ce - > value ) ;
2020-03-29 09:16:53 +00:00
m = safe_alloc ( sizeof ( ConfigItem_blacklist_module ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( m - > name , ce - > value ) ;
2020-03-29 09:16:53 +00:00
AddListItem ( m , conf_blacklist_module ) ;
return 0 ;
}
2022-01-15 05:16:34 +00:00
int is_blacklisted_module ( const char * name )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
const char * path = Module_TransformPath ( name ) ;
2020-03-29 09:16:53 +00:00
ConfigItem_blacklist_module * m ;
for ( m = conf_blacklist_module ; m ; m = m - > next )
2023-05-05 22:12:01 +00:00
if ( match_simple ( m - > name , name ) | | match_simple ( m - > name , path ) )
2020-03-29 09:16:53 +00:00
return 1 ;
return 0 ;
}
void start_listeners ( void )
{
2022-01-15 05:16:34 +00:00
ConfigItem_listen * listener ;
2020-03-29 09:16:53 +00:00
int failed = 0 , ports_bound = 0 ;
char boundmsg_ipv4 [ 512 ] , boundmsg_ipv6 [ 512 ] ;
2022-01-15 05:16:34 +00:00
int last_errno = 0 ;
2020-03-29 09:16:53 +00:00
* boundmsg_ipv4 = * boundmsg_ipv6 = ' \0 ' ;
2022-01-15 05:16:34 +00:00
for ( listener = conf_listen ; listener ; listener = listener - > next )
2020-03-29 09:16:53 +00:00
{
/* Try to bind to any ports that are not yet bound and not marked as temporary */
2022-01-15 05:16:34 +00:00
if ( ! ( listener - > options & LISTENER_BOUND ) & & ! listener - > flag . temporary )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( add_listener ( listener ) = = - 1 )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
/* Error already printed upstream */
2020-03-29 09:16:53 +00:00
failed = 1 ;
2022-01-15 05:16:34 +00:00
last_errno = ERRNO ;
2020-03-29 09:16:53 +00:00
} else {
2022-01-15 05:16:34 +00:00
if ( loop . booted )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
unreal_log ( ULOG_INFO , " listen " , " LISTEN_ADDED " , NULL ,
" UnrealIRCd is now also listening on $listen_ip:$listen_port " ,
log_data_string ( " listen_ip " , listener - > ip ) ,
log_data_integer ( " listen_port " , listener - > port ) ) ;
2020-03-29 09:16:53 +00:00
} else {
2022-04-03 15:09:29 +00:00
switch ( listener - > socket_type )
{
case SOCKET_TYPE_IPV4 :
snprintf ( boundmsg_ipv4 + strlen ( boundmsg_ipv4 ) , sizeof ( boundmsg_ipv4 ) - strlen ( boundmsg_ipv4 ) ,
" %s:%d%s, " , listener - > ip , listener - > port ,
listener - > options & LISTENER_TLS ? " (TLS) " : " " ) ;
break ;
case SOCKET_TYPE_IPV6 :
snprintf ( boundmsg_ipv6 + strlen ( boundmsg_ipv6 ) , sizeof ( boundmsg_ipv6 ) - strlen ( boundmsg_ipv6 ) ,
" %s:%d%s, " , listener - > ip , listener - > port ,
listener - > options & LISTENER_TLS ? " (TLS) " : " " ) ;
break ;
// TODO: show unix domain sockets ;)
default :
break ;
}
2020-03-29 09:16:53 +00:00
}
}
}
/* NOTE: do not merge this with code above (nor in an else block),
* as add_listener ( ) affects this flag .
*/
2022-01-15 05:16:34 +00:00
if ( listener - > options & LISTENER_BOUND )
2020-03-29 09:16:53 +00:00
ports_bound + + ;
}
if ( ports_bound = = 0 )
{
2022-01-15 05:16:34 +00:00
# ifdef _WIN32
if ( last_errno = = WSAEADDRINUSE )
# else
if ( last_errno = = EADDRINUSE )
# endif
{
/* We can be specific */
unreal_log ( ULOG_FATAL , " listen " , " ALL_LISTEN_PORTS_FAILED " , NULL ,
" Unable to listen on any ports. "
" Most likely UnrealIRCd is already running. " ) ;
} else {
unreal_log ( ULOG_FATAL , " listen " , " ALL_LISTEN_PORTS_FAILED " , NULL ,
" Unable to listen on any ports. "
" Please verify that no other process is using the ports. "
" Also, on some IRCd shells you may have to use listen::bind-ip "
" with a specific IP assigned to you (rather than \" * \" ). " ) ;
}
2020-03-29 09:16:53 +00:00
exit ( - 1 ) ;
}
2022-01-15 05:16:34 +00:00
if ( failed & & ! loop . booted )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
unreal_log ( ULOG_FATAL , " listen " , " SOME_LISTEN_PORTS_FAILED " , NULL ,
" Unable to listen on all ports (some of them succeeded, some of them failed). "
" Please verify that no other process is using the port(s). "
" Also, on some IRCd shells you may have to use listen::bind-ip "
" with a specific IP assigned to you (rather than \" * \" ). " ) ;
2020-03-29 09:16:53 +00:00
exit ( - 1 ) ;
}
2022-01-15 05:16:34 +00:00
if ( ! loop . booted )
2020-03-29 09:16:53 +00:00
{
if ( strlen ( boundmsg_ipv4 ) > 2 )
boundmsg_ipv4 [ strlen ( boundmsg_ipv4 ) - 2 ] = ' \0 ' ;
if ( strlen ( boundmsg_ipv6 ) > 2 )
boundmsg_ipv6 [ strlen ( boundmsg_ipv6 ) - 2 ] = ' \0 ' ;
2022-01-15 05:16:34 +00:00
if ( ! * boundmsg_ipv4 )
strlcpy ( boundmsg_ipv4 , " <none> " , sizeof ( boundmsg_ipv4 ) ) ;
if ( ! * boundmsg_ipv6 )
strlcpy ( boundmsg_ipv6 , " <none> " , sizeof ( boundmsg_ipv6 ) ) ;
unreal_log ( ULOG_INFO , " listen " , " LISTENING " , NULL ,
" UnrealIRCd is now listening on the following addresses/ports: \n "
" IPv4: $ipv4_port_list \n "
" IPv6: $ipv6_port_list \n " ,
log_data_string ( " ipv4_port_list " , boundmsg_ipv4 ) ,
log_data_string ( " ipv6_port_list " , boundmsg_ipv6 ) ) ;
2020-03-29 09:16:53 +00:00
}
}
/* Actually use configuration */
2022-01-15 05:16:34 +00:00
void config_run ( void )
2020-03-29 09:16:53 +00:00
{
2023-05-05 22:12:01 +00:00
loop . config_status = CONFIG_STATUS_POSTLOAD ;
2022-01-15 05:16:34 +00:00
extcmodes_check_for_changes ( ) ;
2020-03-29 09:16:53 +00:00
start_listeners ( ) ;
2023-05-05 22:12:01 +00:00
if ( ! loop . booted )
add_proc_io_server ( ) ;
2022-01-15 05:16:34 +00:00
free_all_config_resources ( ) ;
2020-03-29 09:16:53 +00:00
}
int _conf_offchans ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep , * cepp ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
ConfigItem_offchans * of = safe_alloc ( sizeof ( ConfigItem_offchans ) ) ;
2022-01-15 05:16:34 +00:00
strlcpy ( of - > name , cep - > name , CHANNELLEN + 1 ) ;
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " topic " ) )
safe_strdup ( of - > topic , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
AddListItem ( of , conf_offchans ) ;
}
return 0 ;
}
int _test_offchans ( ConfigFile * conf , ConfigEntry * ce )
{
int errors = 0 ;
ConfigEntry * cep , * cep2 ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > items )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: empty official-channels block " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
2021-01-08 23:15:08 +00:00
config_warn ( " set::official-channels is deprecated. It often does not do what you want. "
2020-03-29 09:16:53 +00:00
" You're better of creating a channel, setting all modes, topic, etc. to your liking "
" and then making the channel permanent (MODE #channel +P). "
" The channel will then be stored in a database to preserve it between restarts. " ) ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( strlen ( cep - > name ) > CHANNELLEN )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: official-channels: '%s' name too long (max %d characters). " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , cep - > name , CHANNELLEN ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
if ( ! valid_channelname ( cep - > name ) )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: official-channels: '%s' is not a valid channel name. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
for ( cep2 = cep - > items ; cep2 ; cep2 = cep2 - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! cep2 - > value )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
config_error_empty ( cep2 - > file - > filename ,
cep2 - > line_number , " official-channels " ,
cep2 - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep2 - > name , " topic " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( strlen ( cep2 - > value ) > MAXTOPICLEN )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: official-channels::%s: topic too long (max %d characters). " ,
2022-01-15 05:16:34 +00:00
cep2 - > file - > filename , cep2 - > line_number , cep - > name , MAXTOPICLEN ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
} else {
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep2 - > file - > filename ,
cep2 - > line_number , " official-channels " ,
cep2 - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
continue ;
}
}
}
return errors ;
}
int _conf_alias ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigItem_alias * alias = NULL ;
ConfigItem_alias_format * format ;
ConfigEntry * cep , * cepp ;
RealCommand * cmptr ;
2022-01-15 05:16:34 +00:00
if ( ( cmptr = find_command ( ce - > value , CMD_ALIAS ) ) )
2020-03-29 09:16:53 +00:00
CommandDelX ( NULL , cmptr ) ;
2022-01-15 05:16:34 +00:00
if ( find_command_simple ( ce - > value ) )
2020-03-29 09:16:53 +00:00
{
config_warn ( " %s:%i: Alias '%s' would conflict with command (or server token) '%s', alias not added. " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ,
ce - > value , ce - > value ) ;
2020-03-29 09:16:53 +00:00
return 0 ;
}
2022-01-15 05:16:34 +00:00
if ( ( alias = find_alias ( ce - > value ) ) )
2020-03-29 09:16:53 +00:00
DelListItem ( alias , conf_alias ) ;
alias = safe_alloc ( sizeof ( ConfigItem_alias ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( alias - > alias , ce - > value ) ;
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " format " ) ) {
2020-03-29 09:16:53 +00:00
format = safe_alloc ( sizeof ( ConfigItem_alias_format ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( format - > format , cep - > value ) ;
format - > expr = unreal_create_match ( MATCH_PCRE_REGEX , cep - > value , NULL ) ;
2020-03-29 09:16:53 +00:00
if ( ! format - > expr )
abort ( ) ; /* Impossible due to _test_alias earlier */
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next ) {
if ( ! strcmp ( cepp - > name , " nick " ) | |
! strcmp ( cepp - > name , " target " ) | |
! strcmp ( cepp - > name , " command " ) ) {
safe_strdup ( format - > nick , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " parameters " ) ) {
safe_strdup ( format - > parameters , cepp - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " type " ) ) {
if ( ! strcmp ( cepp - > value , " services " ) )
2020-03-29 09:16:53 +00:00
format - > type = ALIAS_SERVICES ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > value , " stats " ) )
2020-03-29 09:16:53 +00:00
format - > type = ALIAS_STATS ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > value , " normal " ) )
2020-03-29 09:16:53 +00:00
format - > type = ALIAS_NORMAL ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > value , " channel " ) )
2020-03-29 09:16:53 +00:00
format - > type = ALIAS_CHANNEL ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > value , " real " ) )
2020-03-29 09:16:53 +00:00
format - > type = ALIAS_REAL ;
}
}
AddListItem ( format , alias - > format ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " nick " ) | | ! strcmp ( cep - > name , " target " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( alias - > nick , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " type " ) ) {
if ( ! strcmp ( cep - > value , " services " ) )
2020-03-29 09:16:53 +00:00
alias - > type = ALIAS_SERVICES ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > value , " stats " ) )
2020-03-29 09:16:53 +00:00
alias - > type = ALIAS_STATS ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > value , " normal " ) )
2020-03-29 09:16:53 +00:00
alias - > type = ALIAS_NORMAL ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > value , " channel " ) )
2020-03-29 09:16:53 +00:00
alias - > type = ALIAS_CHANNEL ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > value , " command " ) )
2020-03-29 09:16:53 +00:00
alias - > type = ALIAS_COMMAND ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " spamfilter " ) )
alias - > spamfilter = config_checkval ( cep - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
if ( BadPtr ( alias - > nick ) & & alias - > type ! = ALIAS_COMMAND ) {
safe_strdup ( alias - > nick , alias - > alias ) ;
}
AliasAdd ( NULL , alias - > alias , cmd_alias , 1 , CMD_USER | CMD_ALIAS ) ;
AddListItem ( alias , conf_alias ) ;
return 0 ;
}
int _test_alias ( ConfigFile * conf , ConfigEntry * ce ) {
int errors = 0 ;
ConfigEntry * cep , * cepp ;
char has_type = 0 , has_target = 0 , has_format = 0 ;
char type = 0 ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > items )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: empty alias block " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: alias without name " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
else if ( ! find_command ( ce - > value , CMD_ALIAS ) & & find_command ( ce - > value , 0 ) ) {
2020-03-29 09:16:53 +00:00
config_status ( " %s:%i: %s is an existing command, can not add alias " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number , ce - > value ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " alias " ) )
{
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " format " ) ) {
2020-03-29 09:16:53 +00:00
char * err = NULL ;
Match * expr ;
char has_type = 0 , has_target = 0 , has_parameters = 0 ;
has_format = 1 ;
2022-01-15 05:16:34 +00:00
expr = unreal_create_match ( MATCH_PCRE_REGEX , cep - > value , & err ) ;
2020-03-29 09:16:53 +00:00
if ( ! expr )
{
config_error ( " %s:%i: alias::format contains an invalid regex: %s " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , err ) ;
2020-03-29 09:16:53 +00:00
} else {
unreal_delete_match ( expr ) ;
}
2022-01-15 05:16:34 +00:00
for ( cepp = cep - > items ; cepp ; cepp = cepp - > next ) {
2020-03-29 09:16:53 +00:00
if ( config_is_blankorempty ( cepp , " alias::format " ) )
{
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > name , " nick " ) | |
! strcmp ( cepp - > name , " command " ) | |
! strcmp ( cepp - > name , " target " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_target )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cepp - > file - > filename ,
cepp - > line_number ,
2020-03-29 09:16:53 +00:00
" alias::format::target " ) ;
continue ;
}
has_target = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " type " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_type )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cepp - > file - > filename ,
cepp - > line_number ,
2020-03-29 09:16:53 +00:00
" alias::format::type " ) ;
continue ;
}
has_type = 1 ;
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cepp - > value , " services " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > value , " stats " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > value , " normal " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > value , " channel " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > value , " real " ) )
2020-03-29 09:16:53 +00:00
;
else
{
config_error ( " %s:%i: unknown alias type " ,
2022-01-15 05:16:34 +00:00
cepp - > file - > filename , cepp - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cepp - > name , " parameters " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_parameters )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cepp - > file - > filename ,
cepp - > line_number ,
2020-03-29 09:16:53 +00:00
" alias::format::parameters " ) ;
continue ;
}
has_parameters = 1 ;
}
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cepp - > file - > filename ,
cepp - > line_number , " alias::format " ,
cepp - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
if ( ! has_target )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( cep - > file - > filename ,
cep - > line_number , " alias::format::target " ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
if ( ! has_type )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( cep - > file - > filename ,
cep - > line_number , " alias::format::type " ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
if ( ! has_parameters )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( cep - > file - > filename ,
cep - > line_number , " alias::format::parameters " ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " nick " ) | | ! strcmp ( cep - > name , " target " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_target )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " alias::target " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_target = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " type " ) ) {
2020-03-29 09:16:53 +00:00
if ( has_type )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " alias::type " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_type = 1 ;
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > value , " services " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > value , " stats " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > value , " normal " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > value , " channel " ) )
2020-03-29 09:16:53 +00:00
;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > value , " command " ) )
2020-03-29 09:16:53 +00:00
type = ' c ' ;
else {
config_error ( " %s:%i: unknown alias type " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " spamfilter " ) )
2020-03-29 09:16:53 +00:00
;
else {
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename , cep - > line_number ,
" alias " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
if ( ! has_type )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" alias::type " ) ;
errors + + ;
}
if ( ! has_format & & type = = ' c ' )
{
config_error ( " %s:%d: alias::type is 'command' but no alias::format was specified " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
else if ( has_format & & type ! = ' c ' )
{
config_error ( " %s:%d: alias::format specified when type is not 'command' " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
return errors ;
}
int _conf_deny ( ConfigFile * conf , ConfigEntry * ce )
{
Hook * h ;
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ce - > value , " channel " ) )
2020-03-29 09:16:53 +00:00
_conf_deny_channel ( conf , ce ) ;
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ce - > value , " version " ) )
2020-03-29 09:16:53 +00:00
_conf_deny_version ( conf , ce ) ;
else
{
int value ;
for ( h = Hooks [ HOOKTYPE_CONFIGRUN ] ; h ; h = h - > next )
{
value = ( * ( h - > func . intfunc ) ) ( conf , ce , CONFIG_DENY ) ;
if ( value = = 1 )
break ;
}
return 0 ;
}
return 0 ;
}
int _conf_deny_channel ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigItem_deny_channel * deny = NULL ;
ConfigEntry * cep ;
deny = safe_alloc ( sizeof ( ConfigItem_deny_channel ) ) ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " channel " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( deny - > channel , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " redirect " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( deny - > redirect , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " reason " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( deny - > reason , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " warn " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
deny - > warn = config_checkval ( cep - > value , CFG_YESNO ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " class " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( deny - > class , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-11-20 04:12:40 +00:00
else if ( ! strcmp ( cep - > name , " match " ) | | ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
conf_match_block ( conf , cep , & deny - > match ) ;
2020-03-29 09:16:53 +00:00
}
}
AddListItem ( deny , conf_deny_channel ) ;
return 0 ;
}
int _conf_deny_version ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigItem_deny_version * deny = NULL ;
ConfigEntry * cep ;
deny = safe_alloc ( sizeof ( ConfigItem_deny_version ) ) ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( deny - > mask , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " version " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( deny - > version , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " flags " ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( deny - > flags , cep - > value ) ;
2020-03-29 09:16:53 +00:00
}
}
AddListItem ( deny , conf_deny_version ) ;
return 0 ;
}
int _test_deny ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
int errors = 0 ;
Hook * h ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2020-03-29 09:16:53 +00:00
{
config_error ( " %s:%i: deny without type " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( ce - > value , " channel " ) )
2020-03-29 09:16:53 +00:00
{
char has_channel = 0 , has_warn = 0 , has_reason = 0 , has_redirect = 0 , has_class = 0 ;
2022-11-20 04:12:40 +00:00
char has_mask = 0 , has_match = 0 ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " deny channel " ) )
{
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " channel " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_channel )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " deny channel::channel " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_channel = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " redirect " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_redirect )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " deny channel::redirect " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_redirect = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " reason " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_reason )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " deny channel::reason " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_reason = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " warn " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_warn )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " deny channel::warn " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_warn = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " class " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_class )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " deny channel::class " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_class = 1 ;
}
2022-11-20 04:12:40 +00:00
else if ( ! strcmp ( cep - > name , " match " ) )
{
has_match = 1 ;
test_match_block ( conf , cep , & errors ) ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
2022-11-20 04:12:40 +00:00
has_mask = 1 ;
test_match_block ( conf , cep , & errors ) ;
2020-03-29 09:16:53 +00:00
}
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename ,
cep - > line_number , " deny channel " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
if ( ! has_channel )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" deny channel::channel " ) ;
errors + + ;
}
if ( ! has_reason )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" deny channel::reason " ) ;
errors + + ;
}
2022-11-20 04:12:40 +00:00
if ( has_mask & & has_match )
{
config_error ( " %s:%d: You cannot have both ::mask and ::match. "
" You should only use %s %s::match. " ,
ce - > file - > filename , ce - > line_number , ce - > name , ce - > value ) ;
errors + + ;
}
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( ce - > value , " version " ) )
2020-03-29 09:16:53 +00:00
{
char has_mask = 0 , has_version = 0 , has_flags = 0 ;
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2020-03-29 09:16:53 +00:00
{
if ( config_is_blankorempty ( cep , " deny version " ) )
{
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " mask " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_mask )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " deny version::mask " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_mask = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " version " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_version )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " deny version::version " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_version = 1 ;
}
2022-01-15 05:16:34 +00:00
else if ( ! strcmp ( cep - > name , " flags " ) )
2020-03-29 09:16:53 +00:00
{
if ( has_flags )
{
2022-01-15 05:16:34 +00:00
config_warn_duplicate ( cep - > file - > filename ,
cep - > line_number , " deny version::flags " ) ;
2020-03-29 09:16:53 +00:00
continue ;
}
has_flags = 1 ;
}
else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename ,
cep - > line_number , " deny version " , cep - > name ) ;
2020-03-29 09:16:53 +00:00
errors + + ;
}
}
if ( ! has_mask )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" deny version::mask " ) ;
errors + + ;
}
if ( ! has_version )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" deny version::version " ) ;
errors + + ;
}
if ( ! has_flags )
{
2022-01-15 05:16:34 +00:00
config_error_missing ( ce - > file - > filename , ce - > line_number ,
2020-03-29 09:16:53 +00:00
" deny version::flags " ) ;
errors + + ;
}
}
else
{
int used = 0 ;
for ( h = Hooks [ HOOKTYPE_CONFIGTEST ] ; h ; h = h - > next )
{
int value , errs = 0 ;
if ( h - > owner & & ! ( h - > owner - > flags & MODFLAG_TESTING )
& & ! ( h - > owner - > options & MOD_OPT_PERM ) )
continue ;
value = ( * ( h - > func . intfunc ) ) ( conf , ce , CONFIG_DENY , & errs ) ;
if ( value = = 2 )
used = 1 ;
if ( value = = 1 )
{
used = 1 ;
break ;
}
if ( value = = - 1 )
{
used = 1 ;
errors + = errs ;
break ;
}
if ( value = = - 2 )
{
used = 1 ;
errors + = errs ;
}
}
if ( ! used ) {
config_error ( " %s:%i: unknown deny type %s " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ,
ce - > value ) ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
return errors ;
}
return errors ;
}
2022-01-15 05:16:34 +00:00
Secret * find_secret ( const char * secret_name )
2021-06-19 15:52:51 +00:00
{
Secret * s ;
for ( s = secrets ; s ; s = s - > next )
{
if ( ! strcasecmp ( s - > name , secret_name ) )
return s ;
}
return NULL ;
}
void free_secret_cache ( SecretCache * c )
{
unrealdb_free_config ( c - > config ) ;
safe_free ( c ) ;
}
void free_secret ( Secret * s )
{
SecretCache * c , * c_next ;
for ( c = s - > cache ; c ; c = c_next )
{
c_next = c - > next ;
DelListItem ( c , s - > cache ) ;
free_secret_cache ( c ) ;
}
safe_free ( s - > name ) ;
safe_free_sensitive ( s - > password ) ;
safe_free ( s ) ;
}
2022-01-15 05:16:34 +00:00
char * _conf_secret_read_password_file ( const char * fname )
2021-06-19 15:52:51 +00:00
{
char * pwd , * err ;
int fd , n ;
# ifndef _WIN32
fd = open ( fname , O_RDONLY ) ;
# else
fd = open ( fname , _O_RDONLY | _O_BINARY ) ;
# endif
if ( fd < 0 )
{
/* This should not happen, as we tested for file exists earlier.. */
config_error ( " Could not open file '%s': %s " , fname , strerror ( errno ) ) ;
return NULL ;
}
pwd = safe_alloc_sensitive ( 512 ) ;
n = read ( fd , pwd , 511 ) ;
if ( n < = 0 )
{
close ( fd ) ;
config_error ( " Could not read from file '%s': %s " , fname , strerror ( errno ) ) ;
safe_free_sensitive ( pwd ) ;
return NULL ;
}
close ( fd ) ;
stripcrlf ( pwd ) ;
sodium_stackzero ( 1024 ) ;
if ( ! valid_secret_password ( pwd , & err ) )
{
config_error ( " Key from file '%s' does not meet password complexity requirements: %s " , fname , err ) ;
safe_free_sensitive ( pwd ) ;
return NULL ;
}
return pwd ;
}
2022-01-15 05:16:34 +00:00
char * _conf_secret_read_prompt ( const char * blockname )
2021-06-19 15:52:51 +00:00
{
char * pwd , * pwd_prompt ;
char buf [ 256 ] ;
# ifdef _WIN32
/* FIXME: add windows support? should be possible in GUI no? */
return NULL ;
# else
snprintf ( buf , sizeof ( buf ) , " Enter password for secret '%s': " , blockname ) ;
pwd_prompt = getpass ( buf ) ;
if ( pwd_prompt )
{
pwd = safe_alloc_sensitive ( 512 ) ;
strlcpy ( pwd , pwd_prompt , 512 ) ;
memset ( pwd_prompt , 0 , strlen ( pwd_prompt ) ) ; // zero password out
sodium_stackzero ( 1024 ) ;
return pwd ;
}
return NULL ;
# endif
}
int _test_secret ( ConfigFile * conf , ConfigEntry * ce )
{
int errors = 0 ;
int has_password = 0 , has_password_file = 0 , has_password_prompt = 0 ;
ConfigEntry * cep ;
char * err ;
Secret * existing ;
2022-01-15 05:16:34 +00:00
if ( ! ce - > value )
2021-06-19 15:52:51 +00:00
{
config_error ( " %s:%i: secret block needs a name, eg: secret xyz { " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
2022-01-15 05:16:34 +00:00
return errors ; /* need to return here since we dereference ce->value later.. */
2021-06-19 15:52:51 +00:00
} else {
2022-01-15 05:16:34 +00:00
if ( ! security_group_valid_name ( ce - > value ) )
2021-06-19 15:52:51 +00:00
{
config_error ( " %s:%i: secret block name '%s' contains invalid characters or is too long. "
" Only letters, numbers, underscore and hyphen are allowed. " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number , ce - > value ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
}
2022-01-15 05:16:34 +00:00
existing = find_secret ( ce - > value ) ;
2021-06-19 15:52:51 +00:00
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " password " ) )
2021-06-19 15:52:51 +00:00
{
int n ;
has_password = 1 ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
if ( cep - > items | |
( ( ( n = Auth_AutoDetectHashType ( cep - > value ) ) ) & & ( ( n = = AUTHTYPE_BCRYPT ) | | ( n = = AUTHTYPE_ARGON2 ) ) ) )
2021-06-19 15:52:51 +00:00
{
config_error ( " %s:%d: you cannot use hashed passwords here, see "
" https://www.unrealircd.org/docs/Secret_block#secret-plaintext " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
if ( ! valid_secret_password ( cep - > value , & err ) )
2021-06-19 15:52:51 +00:00
{
config_error ( " %s:%d: secret::password does not meet password complexity requirements: %s " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number , err ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " password-file " ) )
2021-06-19 15:52:51 +00:00
{
char * str ;
has_password_file = 1 ;
CheckNull ( cep ) ;
2022-01-15 05:16:34 +00:00
convert_to_absolute_path ( & cep - > value , CONFDIR ) ;
if ( ! file_exists ( cep - > value ) & & existing & & existing - > password )
2021-06-19 15:52:51 +00:00
{
/* Silently ignore the case where a secret block already
* has the password read and now the file is no longer available .
* This so secret : : password - file can be used only to boot
* and then the media ( eg : USB stick ) can be pulled .
*/
} else
{
2022-01-15 05:16:34 +00:00
str = _conf_secret_read_password_file ( cep - > value ) ;
2021-06-19 15:52:51 +00:00
if ( ! str )
{
config_error ( " %s:%d: secret::password-file: error reading password from file, see error from above. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
safe_free_sensitive ( str ) ;
}
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " password-prompt " ) )
2021-06-19 15:52:51 +00:00
{
# ifdef _WIN32
config_error ( " %s:%d: secret::password-prompt is not implemented in Windows at the moment, sorry! " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2021-06-19 15:52:51 +00:00
config_error ( " Choose a different method to enter passwords or use *NIX " ) ;
errors + + ;
return errors ;
# endif
has_password_prompt = 1 ;
2022-01-15 05:16:34 +00:00
if ( loop . booted & & ! find_secret ( ce - > value ) )
2021-06-19 15:52:51 +00:00
{
config_error ( " %s:%d: you cannot add a new secret { } block that uses password-prompt and then /REHASH. "
" With 'password-prompt' you can only add such a password on boot. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2021-06-19 15:52:51 +00:00
config_error ( " Either use a different method to enter passwords or restart the IRCd on the console. " ) ;
errors + + ;
}
2022-01-15 05:16:34 +00:00
if ( ! loop . booted & & ! running_interactively ( ) )
2021-06-19 15:52:51 +00:00
{
config_error ( " ERROR: IRCd is not running interactively, but via a cron job or something similar. " ) ;
config_error ( " %s:%d: unable to prompt for password since IRCd is not started in a terminal " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2021-06-19 15:52:51 +00:00
config_error ( " Either use a different method to enter passwords or start the IRCd in a terminal/SSH/.. " ) ;
}
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " password-url " ) )
2021-06-19 15:52:51 +00:00
{
config_error ( " %s:%d: secret::password-url is not supported yet in this UnrealIRCd version. " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
} else
{
2022-01-15 05:16:34 +00:00
config_error_unknown ( cep - > file - > filename , cep - > line_number ,
" secret " , cep - > name ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
continue ;
}
2022-01-15 05:16:34 +00:00
if ( cep - > items )
2021-06-19 15:52:51 +00:00
{
config_error ( " %s:%d: secret::%s does not support sub-options (%s) " ,
2022-01-15 05:16:34 +00:00
cep - > file - > filename , cep - > line_number ,
cep - > name , cep - > items - > name ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
}
if ( ! has_password & & ! has_password_file & & ! has_password_prompt )
{
config_error ( " %s:%d: secret { } block must contain 1 of: password OR password-file OR password-prompt " ,
2022-01-15 05:16:34 +00:00
ce - > file - > filename , ce - > line_number ) ;
2021-06-19 15:52:51 +00:00
errors + + ;
}
return errors ;
}
/* NOTE: contrary to all other _conf* stuff, this one actually runs during config_test,
* so during the early CONFIG TEST stage rather than CONFIG RUN .
* This so all secret { } block configuration is available already during TEST / POSTTEST
* stage for modules , so they can check if the password is correct or not .
*/
int _conf_secret ( ConfigFile * conf , ConfigEntry * ce )
{
ConfigEntry * cep ;
Secret * s ;
2022-01-15 05:16:34 +00:00
Secret * existing = find_secret ( ce - > value ) ;
2021-06-19 15:52:51 +00:00
s = safe_alloc ( sizeof ( Secret ) ) ;
2022-01-15 05:16:34 +00:00
safe_strdup ( s - > name , ce - > value ) ;
2021-06-19 15:52:51 +00:00
2022-01-15 05:16:34 +00:00
for ( cep = ce - > items ; cep ; cep = cep - > next )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " password " ) )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup_sensitive ( s - > password , cep - > value ) ;
destroy_string ( cep - > value ) ; /* destroy the original */
2021-06-19 15:52:51 +00:00
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " password-file " ) )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! file_exists ( cep - > value ) & & existing & & existing - > password )
2021-06-19 15:52:51 +00:00
{
/* Silently ignore the case where a secret block already
* has the password read and now the file is no longer available .
* This so secret : : password - file can be used only to boot
* and then the media ( eg : USB stick ) can be pulled .
*/
} else
{
2022-01-15 05:16:34 +00:00
s - > password = _conf_secret_read_password_file ( cep - > value ) ;
2021-06-19 15:52:51 +00:00
}
} else
2022-01-15 05:16:34 +00:00
if ( ! strcmp ( cep - > name , " password-prompt " ) )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
if ( ! loop . booted & & running_interactively ( ) )
2021-06-19 15:52:51 +00:00
{
2022-01-15 05:16:34 +00:00
s - > password = _conf_secret_read_prompt ( ce - > value ) ;
2021-06-19 15:52:51 +00:00
if ( ! s - > password | | ! valid_secret_password ( s - > password , NULL ) )
{
config_error ( " Invalid password entered on console (does not meet complexity requirements) " ) ;
/* This cannot be the correct password, so exit */
exit ( - 1 ) ;
}
}
}
}
/* This may happen if we run twice, due to destroy_string() earlier: */
if ( BadPtr ( s - > password ) )
{
free_secret ( s ) ;
return 1 ;
}
/* If there is an existing secret { } block with this name in memory
* and it has a different password , then free that secret block
*/
if ( existing )
{
if ( ! strcmp ( s - > password , existing - > password ) )
{
free_secret ( s ) ;
return 1 ;
}
/* passwords differ, so free the old existing one,
* including purging the cache for it .
*/
DelListItem ( existing , secrets ) ;
free_secret ( existing ) ;
}
AddListItem ( s , secrets ) ;
return 1 ;
}
2022-01-15 05:16:34 +00:00
void resource_download_complete ( const char * url , const char * file , const char * errorbuf , int cached , void * rs_key )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
ConfigResource * rs = ( ConfigResource * ) rs_key ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
rs - > type & = ~ RESOURCE_DLQUEUED ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
if ( config_verbose )
config_status ( " resource_download_complete() for %s [%s] " , url , errorbuf ? errorbuf : " success " ) ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
if ( ! file & & ! cached )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
/* DOWNLOAD FAILED */
if ( rs - > cache_file )
{
unreal_log ( ULOG_ERROR , " config " , " DOWNLOAD_FAILED_SOFT " , NULL ,
" $file:$line_number: Failed to download '$url': $error_message \n "
" Using a cached copy instead. " ,
log_data_string ( " file " , rs - > wce - > ce - > file - > filename ) ,
log_data_integer ( " line_number " , rs - > wce - > ce - > line_number ) ,
log_data_string ( " url " , displayurl ( url ) ) ,
log_data_string ( " error_message " , errorbuf ) ) ;
safe_strdup ( rs - > file , rs - > cache_file ) ;
} else {
unreal_log ( ULOG_ERROR , " config " , " DOWNLOAD_FAILED_HARD " , NULL ,
" $file:$line_number: Failed to download '$url': $error_message " ,
log_data_string ( " file " , rs - > wce - > ce - > file - > filename ) ,
log_data_integer ( " line_number " , rs - > wce - > ce - > line_number ) ,
log_data_string ( " url " , displayurl ( url ) ) ,
log_data_string ( " error_message " , errorbuf ) ) ;
/* Set error condition, this so config_read_file() later will stop. */
loop . config_load_failed = 1 ;
/* We keep the other transfers running since they may raise (more) errors.
* Which can be helpful so you can differentiate between an error of an
* include on one server , or complete lack of internet connectvitity .
*/
}
2020-03-29 09:16:53 +00:00
}
else
{
if ( cached )
{
2022-01-15 05:16:34 +00:00
/* Copy from cache */
safe_strdup ( rs - > file , rs - > cache_file ) ;
} else {
/* Copy to cache */
const char * cache_file = unreal_mkcache ( url ) ;
unreal_copyfileex ( file , cache_file , 1 ) ;
safe_strdup ( rs - > file , cache_file ) ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
if ( rs - > file )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( rs - > type & RESOURCE_INCLUDE )
{
if ( config_read_file ( rs - > file , ( char * ) displayurl ( rs - > url ) ) < 0 )
loop . config_load_failed = 1 ;
} else {
ConfigEntryWrapper * wce ;
for ( wce = rs - > wce ; wce ; wce = wce - > next )
safe_strdup ( wce - > ce - > value , rs - > file ) ; // now information of url is lost, hm!!
}
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
/** Request to REHASH the configuration file.
2023-05-05 22:12:01 +00:00
* The rehash will not be done immediately , just scheduled .
* This means this function can safely be called from modules or
* other areas .
2022-01-15 05:16:34 +00:00
* @ param client The client requesting the / REHASH .
* If this is NULL then the rehash was requested
* via a signal to the process or GUI .
*/
void request_rehash ( Client * client )
2020-03-29 09:16:53 +00:00
{
2023-05-05 22:12:01 +00:00
json_t * j ;
2022-01-15 05:16:34 +00:00
if ( loop . rehashing )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
if ( client )
2020-03-29 09:16:53 +00:00
sendnotice ( client , " A rehash is already in progress " ) ;
2022-01-15 05:16:34 +00:00
return ;
2020-03-29 09:16:53 +00:00
}
2023-05-05 22:12:01 +00:00
/* Free any old json_rehash_log */
if ( json_rehash_log )
{
json_decref ( json_rehash_log ) ;
json_rehash_log = NULL ;
}
/* Start a new json_rehash_log */
json_rehash_log = json_object ( ) ;
if ( client )
json_expand_client ( json_rehash_log , " rehash_client " , client , 99 ) ;
j = json_array ( ) ;
json_object_set_new ( json_rehash_log , " log " , j ) ;
/* Now actually process the rehash request... */
2022-01-15 05:16:34 +00:00
loop . rehashing = 1 ;
2020-03-29 09:16:53 +00:00
loop . rehash_save_client = client ;
2022-01-15 05:16:34 +00:00
config_read_start ( ) ;
2023-05-05 22:12:01 +00:00
/* More config reading (or network I/O), and the actual rehash will
* happen in " the main loop " . See end of SocketLoop ( ) in src / ircd . c .
2022-01-15 05:16:34 +00:00
*/
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
int rehash_internal ( Client * client )
2020-03-29 09:16:53 +00:00
{
2022-04-03 15:09:29 +00:00
int failure ;
2022-01-15 05:16:34 +00:00
/* Log it here if it is by a signal */
if ( client = = NULL )
2023-05-05 22:12:01 +00:00
unreal_log ( ULOG_INFO , " config " , " CONFIG_RELOAD " , NULL , " Rehashing server configuration file [./unrealircd rehash] " ) ;
2022-01-15 05:16:34 +00:00
2022-04-03 15:09:29 +00:00
loop . rehashing = 2 ; /* now doing the actual rehash */
2022-01-15 05:16:34 +00:00
2022-04-03 15:09:29 +00:00
failure = config_test ( ) ;
if ( failure = = 0 )
2022-01-15 05:16:34 +00:00
config_run ( ) ;
/* TODO: uh.. are we supposed to do all this for a failed rehash too? maybe some but not all? */
reread_motdsandrules ( ) ;
2020-03-29 09:16:53 +00:00
unload_all_unused_umodes ( ) ;
unload_all_unused_extcmodes ( ) ;
2022-11-20 04:12:40 +00:00
unload_all_unused_extbans ( ) ;
2020-03-29 09:16:53 +00:00
unload_all_unused_caps ( ) ;
unload_all_unused_history_backends ( ) ;
2023-05-05 22:12:01 +00:00
unload_all_unused_rpc_handlers ( ) ;
2020-03-29 09:16:53 +00:00
// unload_all_unused_moddata(); -- this will crash
2023-05-05 22:12:01 +00:00
clicap_check_for_changes ( ) ;
2020-03-29 09:16:53 +00:00
umodes_check_for_changes ( ) ;
charsys_check_for_changes ( ) ;
2022-04-03 15:09:29 +00:00
/* Clear everything now that we are done */
2022-01-15 05:16:34 +00:00
loop . rehashing = 0 ;
2020-03-29 09:16:53 +00:00
remote_rehash_client = NULL ;
2022-04-03 15:09:29 +00:00
procio_post_rehash ( failure ) ;
2023-05-05 22:12:01 +00:00
json_object_set_new ( json_rehash_log , " success " , json_boolean ( failure ? 0 : 1 ) ) ;
RunHook ( HOOKTYPE_REHASH_LOG , failure , json_rehash_log ) ;
loop . config_status = CONFIG_STATUS_COMPLETE ;
2020-03-29 09:16:53 +00:00
return 1 ;
}
void link_cleanup ( ConfigItem_link * link_ptr )
{
safe_free ( link_ptr - > servername ) ;
2022-11-20 04:12:40 +00:00
free_security_group ( link_ptr - > incoming . match ) ;
2020-03-29 09:16:53 +00:00
Auth_FreeAuthConfig ( link_ptr - > auth ) ;
2022-11-20 04:12:40 +00:00
safe_free ( link_ptr - > outgoing . file ) ;
2020-03-29 09:16:53 +00:00
safe_free ( link_ptr - > outgoing . bind_ip ) ;
safe_free ( link_ptr - > outgoing . hostname ) ;
safe_free ( link_ptr - > hub ) ;
safe_free ( link_ptr - > leaf ) ;
if ( link_ptr - > ssl_ctx )
{
SSL_CTX_free ( link_ptr - > ssl_ctx ) ;
link_ptr - > ssl_ctx = NULL ;
}
if ( link_ptr - > tls_options )
{
free_tls_options ( link_ptr - > tls_options ) ;
link_ptr - > tls_options = NULL ;
}
}
void delete_linkblock ( ConfigItem_link * link_ptr )
{
if ( link_ptr - > class )
{
link_ptr - > class - > xrefcount - - ;
/* Perhaps the class is temporary too and we need to free it... */
if ( link_ptr - > class - > flag . temporary & &
! link_ptr - > class - > clients & & ! link_ptr - > class - > xrefcount )
{
delete_classblock ( link_ptr - > class ) ;
link_ptr - > class = NULL ;
}
}
link_cleanup ( link_ptr ) ;
DelListItem ( link_ptr , conf_link ) ;
safe_free ( link_ptr ) ;
}
void delete_classblock ( ConfigItem_class * class_ptr )
{
safe_free ( class_ptr - > name ) ;
DelListItem ( class_ptr , conf_class ) ;
safe_free ( class_ptr ) ;
}
void listen_cleanup ( )
{
int i = 0 ;
ConfigItem_listen * listen_ptr , * next ;
for ( listen_ptr = conf_listen ; listen_ptr ; listen_ptr = next )
{
next = listen_ptr - > next ;
if ( listen_ptr - > flag . temporary & & ! listen_ptr - > clients )
{
safe_free ( listen_ptr - > ip ) ;
free_tls_options ( listen_ptr - > tls_options ) ;
DelListItem ( listen_ptr , conf_listen ) ;
2023-05-05 22:12:01 +00:00
safe_free ( listen_ptr - > webserver ) ;
2022-01-15 05:16:34 +00:00
safe_free ( listen_ptr - > websocket_forward ) ;
2020-03-29 09:16:53 +00:00
safe_free ( listen_ptr ) ;
i + + ;
}
}
if ( i )
close_unbound_listeners ( ) ;
}
2022-01-15 05:16:34 +00:00
ConfigResource * find_config_resource ( const char * resource )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
ConfigResource * rs ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
for ( rs = config_resources ; rs ; rs = rs - > next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
# ifdef _WIN32
if ( rs - > file & & ! strcasecmp ( resource , rs - > file ) )
return rs ;
# else
if ( rs - > file & & ! strcmp ( resource , rs - > file ) )
return rs ;
# endif
if ( rs - > url & & ! strcasecmp ( resource , rs - > url ) )
return rs ;
2020-03-29 09:16:53 +00:00
}
return NULL ;
}
2022-01-15 05:16:34 +00:00
/* Add configuration resource to list.
* For files this doesn ' t do terribly much , except that you can use
* the return value to judge on whether you should call config_read_file ( ) or not .
* For urls this adds the resource to the list of links to be downloaded .
* @ param resource File or URL of the resource
* @ param type A RESOURCE_ type such as RESOURCE_INCLUDE
* @ param ce The ConfigEntry where the add_config_resource ( ) happened
* for , such as the include block , etc .
* @ returns 0 if the file is already on our list ( so no need to load it ! )
2020-03-29 09:16:53 +00:00
*/
2022-01-15 05:16:34 +00:00
int add_config_resource ( const char * resource , int type , ConfigEntry * ce )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
ConfigResource * rs ;
ConfigEntryWrapper * wce ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
if ( config_verbose )
config_status ( " add_config_resource() for '%s " , resource ) ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
wce = safe_alloc ( sizeof ( ConfigEntryWrapper ) ) ;
wce - > ce = ce ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
rs = find_config_resource ( resource ) ;
if ( rs )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
/* Existing entry, add us to the list of
* items who are interested in this resource ; )
*/
AddListItem ( wce , rs - > wce ) ;
return 0 ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
/* New entry */
rs = safe_alloc ( sizeof ( ConfigResource ) ) ;
rs - > wce = wce ;
AddListItem ( rs , config_resources ) ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
if ( ! url_is_valid ( resource ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
safe_strdup ( rs - > file , resource ) ;
} else {
const char * cache_file ;
time_t modtime ;
safe_strdup ( rs - > url , resource ) ;
rs - > type = type | RESOURCE_REMOTE | RESOURCE_DLQUEUED ;
cache_file = unreal_mkcache ( rs - > url ) ;
modtime = unreal_getfilemodtime ( cache_file ) ;
if ( modtime > 0 )
{
safe_strdup ( rs - > cache_file , cache_file ) ; /* Cached copy is available */
/* Check if there is an "url-refresh" argument */
ConfigEntry * cep , * prev = NULL ;
for ( cep = ce - > items ; cep ; cep = cep - > next )
{
if ( ! strcmp ( cep - > name , " url-refresh " ) )
{
/* First find out the time value of url-refresh... (eg '7d' -> 86400*7) */
long refresh_time = 0 ;
if ( cep - > value )
refresh_time = config_checkval ( cep - > value , CFG_TIME ) ;
/* Then remove the config item so it is not seen by the rest of unrealircd.
* Can ' t use DelListItem ( ) here as ConfigEntry has no - > prev , only - > next .
*/
if ( prev )
prev - > next = cep - > next ; /* (skip over us) */
else
ce - > items = cep - > next ; /* (new head) */
/* ..and free it */
config_entry_free ( cep ) ;
/* And now check if the current cached copy is recent enough */
if ( TStime ( ) - modtime < refresh_time )
{
/* Don't download, use cached copy */
//config_status("DEBUG: using cached copy due to url-refresh %ld", refresh_time);
resource_download_complete ( rs - > url , NULL , NULL , 1 , rs ) ;
return 1 ;
} else {
//config_status("DEBUG: requires download attempt, out of date url-refresh %ld < %ld", refresh_time, TStime() - modtime);
}
break ; // MUST break now as we touched the linked list.
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
prev = cep ;
2020-03-29 09:16:53 +00:00
}
}
2022-01-15 05:16:34 +00:00
download_file_async ( rs - > url , modtime , resource_download_complete , ( void * ) rs , NULL , DOWNLOAD_MAX_REDIRECTS ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
return 1 ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
void free_all_config_resources ( void )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
ConfigResource * rs , * next ;
ConfigEntryWrapper * wce , * wce_next ;
2020-03-29 09:16:53 +00:00
2022-01-15 05:16:34 +00:00
for ( rs = config_resources ; rs ; rs = next )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
next = rs - > next ;
for ( wce = rs - > wce ; wce ; wce = wce_next )
{
wce_next = wce - > next ;
safe_free ( wce ) ;
}
rs - > wce = NULL ;
if ( rs - > type & RESOURCE_REMOTE )
2020-03-29 09:16:53 +00:00
{
2023-05-05 22:12:01 +00:00
url_cancel_handle_by_callback_data ( rs ) ;
2022-01-15 05:16:34 +00:00
/* Delete the file, but only if it's not a cached version */
if ( rs - > file & & strncmp ( rs - > file , CACHEDIR , strlen ( CACHEDIR ) ) )
2020-03-29 09:16:53 +00:00
{
2022-01-15 05:16:34 +00:00
remove ( rs - > file ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
safe_free ( rs - > url ) ;
2020-03-29 09:16:53 +00:00
}
2022-01-15 05:16:34 +00:00
safe_free ( rs - > file ) ;
safe_free ( rs - > cache_file ) ;
DelListItem ( rs , config_resources ) ;
safe_free ( rs ) ;
2020-03-29 09:16:53 +00:00
}
}
int tls_tests ( void )
{
if ( have_tls_listeners = = 0 )
{
2022-01-15 05:16:34 +00:00
config_error ( " Your server is not listening on any TLS ports. " ) ;
2020-03-29 09:16:53 +00:00
config_status ( " Add this to your unrealircd.conf: listen { ip %s; port 6697; options { tls; }; }; " ,
port_6667_ip ? port_6667_ip : " * " ) ;
2022-01-15 05:16:34 +00:00
config_status ( " See https://www.unrealircd.org/docs/FAQ#no-tls-ports " ) ;
2020-03-29 09:16:53 +00:00
return 0 ;
}
return 1 ;
}
/** Check if the user attempts to unload (eg: by commenting out) a module
* that is currently loaded and is tagged as MOD_OPT_PERM_RELOADABLE
* ( in other words : a module that allows re - loading but not un - loading )
*/
int reloadable_perm_module_unloaded ( void )
{
Module * m , * m2 ;
extern Module * Modules ;
int ret = 0 ;
for ( m = Modules ; m ; m = m - > next )
{
if ( ( m - > options & MOD_OPT_PERM_RELOADABLE ) & & ( m - > flags & MODFLAG_LOADED ) )
{
/* For each module w/MOD_OPT_PERM_RELOADABLE that is currently fully loaded... */
int found = 0 ;
for ( m2 = Modules ; m2 ; m2 = m2 - > next )
{
if ( ( m ! = m2 ) & & ! strcmp ( m - > header - > name , m2 - > header - > name ) )
found = 1 ;
}
if ( ! found )
{
config_error ( " Attempt to unload module '%s' is not permitted. Module is permanent and reloadable only. " , m - > header - > name ) ;
ret = 1 ;
/* we don't return straight away so the user gets to see all errors and not just one */
}
}
}
return ret ;
}
2022-01-15 05:16:34 +00:00
const char * link_generator_spkifp ( TLSOptions * tlsoptions )
2020-03-29 09:16:53 +00:00
{
SSL_CTX * ctx ;
SSL * ssl ;
X509 * cert ;
ctx = init_ctx ( tlsoptions , 1 ) ;
if ( ! ctx )
exit ( 1 ) ;
ssl = SSL_new ( ctx ) ;
if ( ! ssl )
exit ( 1 ) ;
cert = SSL_get_certificate ( ssl ) ;
return spki_fingerprint_ex ( cert ) ;
}
void link_generator ( void )
{
ConfigItem_listen * lstn ;
TLSOptions * tlsopt = iConf . tls_options ; /* never null */
int port = 0 ;
char * ip = NULL ;
2022-01-15 05:16:34 +00:00
const char * spkifp ;
2020-03-29 09:16:53 +00:00
for ( lstn = conf_listen ; lstn ; lstn = lstn - > next )
{
if ( ( lstn - > options & LISTENER_SERVERSONLY ) & &
( lstn - > options & LISTENER_TLS ) )
{
if ( lstn - > tls_options )
tlsopt = lstn - > tls_options ;
port = lstn - > port ;
if ( strcmp ( lstn - > ip , " * " ) )
ip = lstn - > ip ;
/* else NULL */
break ;
}
}
if ( ! port )
{
2022-01-15 05:16:34 +00:00
printf ( " You don't have any listen { } blocks that are serversonly (and have tls enabled). \n " ) ;
2020-03-29 09:16:53 +00:00
printf ( " It is recommended to have at least one. Add this to your configuration file: \n " ) ;
printf ( " listen { ip *; port 6900; options { tls; serversonly; }; }; \n " ) ;
exit ( 1 ) ;
}
spkifp = link_generator_spkifp ( tlsopt ) ;
if ( ! spkifp )
{
2022-01-15 05:16:34 +00:00
printf ( " Could not calculate spkifp. Maybe you have uncommon TLS options set? Odd... \n " ) ;
2020-03-29 09:16:53 +00:00
exit ( 1 ) ;
}
printf ( " \n " ) ;
printf ( " Add the following link block to the unrealircd.conf on the OTHER side of the link \n " ) ;
printf ( " (so NOT in the unrealircd.conf on THIS machine). Here it is, just copy-paste: \n " ) ;
printf ( " ################################################################################ \n " ) ;
printf ( " link %s { \n "
" incoming { \n "
" mask *; \n "
" } \n "
" outgoing { \n "
" hostname %s; \n "
" port %d; \n "
2021-01-08 23:15:08 +00:00
" options { tls; autoconnect; } \n "
2020-03-29 09:16:53 +00:00
" } \n "
" password \" %s \" { spkifp; } \n "
" class servers; \n "
" } \n " ,
conf_me - > name ,
ip ? ip : conf_me - > name ,
port ,
spkifp ) ;
printf ( " ################################################################################ \n " ) ;
exit ( 0 ) ;
}