conf.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2001-2009 Alexander Barton (alex@barton.de)
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. * Please read the file COPYING, README and AUTHORS for more information.
  10. *
  11. * Configuration management (reading, parsing & validation)
  12. */
  13. #include "portab.h"
  14. #include "imp.h"
  15. #include <assert.h>
  16. #include <errno.h>
  17. #ifdef PROTOTYPES
  18. # include <stdarg.h>
  19. #else
  20. # include <varargs.h>
  21. #endif
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <strings.h>
  26. #include <unistd.h>
  27. #include <pwd.h>
  28. #include <grp.h>
  29. #include <sys/types.h>
  30. #include <unistd.h>
  31. #ifdef HAVE_CTYPE_H
  32. # include <ctype.h>
  33. #endif
  34. #include "array.h"
  35. #include "ngircd.h"
  36. #include "conn.h"
  37. #include "client.h"
  38. #include "channel.h"
  39. #include "defines.h"
  40. #include "log.h"
  41. #include "match.h"
  42. #include "resolve.h"
  43. #include "tool.h"
  44. #include "exp.h"
  45. #include "conf.h"
  46. static bool Use_Log = true;
  47. static CONF_SERVER New_Server;
  48. static int New_Server_Idx;
  49. static size_t Conf_Channel_Count;
  50. static void Set_Defaults PARAMS(( bool InitServers ));
  51. static bool Read_Config PARAMS(( bool ngircd_starting ));
  52. static bool Validate_Config PARAMS(( bool TestOnly, bool Rehash ));
  53. static void Handle_GLOBAL PARAMS(( int Line, char *Var, char *Arg ));
  54. static void Handle_OPERATOR PARAMS(( int Line, char *Var, char *Arg ));
  55. static void Handle_SERVER PARAMS(( int Line, char *Var, char *Arg ));
  56. static void Handle_CHANNEL PARAMS(( int Line, char *Var, char *Arg ));
  57. static void Config_Error PARAMS(( const int Level, const char *Format, ... ));
  58. static void Config_Error_NaN PARAMS(( const int LINE, const char *Value ));
  59. static void Config_Error_TooLong PARAMS(( const int LINE, const char *Value ));
  60. static void Init_Server_Struct PARAMS(( CONF_SERVER *Server ));
  61. #ifdef WANT_IPV6
  62. #define DEFAULT_LISTEN_ADDRSTR "::,0.0.0.0"
  63. #else
  64. #define DEFAULT_LISTEN_ADDRSTR "0.0.0.0"
  65. #endif
  66. #ifdef SSL_SUPPORT
  67. struct SSLOptions Conf_SSLOptions;
  68. static void
  69. ConfSSL_Init(void)
  70. {
  71. free(Conf_SSLOptions.KeyFile);
  72. Conf_SSLOptions.KeyFile = NULL;
  73. free(Conf_SSLOptions.CertFile);
  74. Conf_SSLOptions.CertFile = NULL;
  75. free(Conf_SSLOptions.DHFile);
  76. Conf_SSLOptions.DHFile = NULL;
  77. array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
  78. }
  79. static bool
  80. ssl_print_configvar(const char *name, const char *file)
  81. {
  82. FILE *fp;
  83. if (!file) {
  84. printf(" %s =\n", name);
  85. return true;
  86. }
  87. fp = fopen(file, "r");
  88. if (fp)
  89. fclose(fp);
  90. else
  91. fprintf(stderr, "ERROR: %s \"%s\": %s\n",
  92. name, file, strerror(errno));
  93. printf(" %s = %s\n", name, file);
  94. return fp != NULL;
  95. }
  96. static bool
  97. ConfSSL_Puts(void)
  98. {
  99. bool ret;
  100. ret = ssl_print_configvar("SSLKeyFile", Conf_SSLOptions.KeyFile);
  101. if (!ssl_print_configvar("SSLCertFile", Conf_SSLOptions.CertFile))
  102. ret = false;
  103. if (!ssl_print_configvar("SSLDHFile", Conf_SSLOptions.DHFile))
  104. ret = false;
  105. if (array_bytes(&Conf_SSLOptions.KeyFilePassword))
  106. puts(" SSLKeyFilePassword = <secret>");
  107. array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
  108. return ret;
  109. }
  110. #endif
  111. static char *
  112. strdup_warn(const char *str)
  113. {
  114. char *ptr = strdup(str);
  115. if (!ptr)
  116. Config_Error(LOG_ERR, "Could not allocate mem for string: %s", str);
  117. return ptr;
  118. }
  119. static void
  120. ports_puts(array *a)
  121. {
  122. size_t len;
  123. UINT16 *ports;
  124. len = array_length(a, sizeof(UINT16));
  125. if (len--) {
  126. ports = (UINT16*) array_start(a);
  127. printf("%u", (unsigned int) *ports);
  128. while (len--) {
  129. ports++;
  130. printf(", %u", (unsigned int) *ports);
  131. }
  132. }
  133. putc('\n', stdout);
  134. }
  135. static void
  136. ports_parse(array *a, int Line, char *Arg)
  137. {
  138. char *ptr;
  139. int port;
  140. UINT16 port16;
  141. array_trunc(a);
  142. /* Ports on that the server should listen. More port numbers
  143. * must be separated by "," */
  144. ptr = strtok( Arg, "," );
  145. while (ptr) {
  146. ngt_TrimStr(ptr);
  147. port = atoi(ptr);
  148. if (port > 0 && port < 0xFFFF) {
  149. port16 = (UINT16) port;
  150. if (!array_catb(a, (char*)&port16, sizeof port16))
  151. Config_Error(LOG_ERR, "%s, line %d Could not add port number %ld: %s",
  152. NGIRCd_ConfFile, Line, port, strerror(errno));
  153. } else {
  154. Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Illegal port number %ld!",
  155. NGIRCd_ConfFile, Line, port );
  156. }
  157. ptr = strtok( NULL, "," );
  158. }
  159. }
  160. GLOBAL void
  161. Conf_Init( void )
  162. {
  163. Read_Config( true );
  164. Validate_Config(false, false);
  165. } /* Config_Init */
  166. GLOBAL bool
  167. Conf_Rehash( void )
  168. {
  169. if (!Read_Config(false))
  170. return false;
  171. Validate_Config(false, true);
  172. /* Update CLIENT structure of local server */
  173. Client_SetInfo(Client_ThisServer(), Conf_ServerInfo);
  174. return true;
  175. } /* Config_Rehash */
  176. static const char*
  177. yesno_to_str(int boolean_value)
  178. {
  179. if (boolean_value)
  180. return "yes";
  181. return "no";
  182. }
  183. GLOBAL int
  184. Conf_Test( void )
  185. {
  186. /* Read configuration, validate and output it. */
  187. struct passwd *pwd;
  188. struct group *grp;
  189. unsigned int i;
  190. bool config_valid;
  191. size_t predef_channel_count;
  192. struct Conf_Channel *predef_chan;
  193. Use_Log = false;
  194. if (! Read_Config(true))
  195. return 1;
  196. config_valid = Validate_Config(true, false);
  197. /* If stdin and stdout ("you can read our nice message and we can
  198. * read in your keypress") are valid tty's, wait for a key: */
  199. if( isatty( fileno( stdin )) && isatty( fileno( stdout ))) {
  200. puts( "OK, press enter to see a dump of your service configuration ..." );
  201. getchar( );
  202. } else {
  203. puts( "Ok, dump of your server configuration follows:\n" );
  204. }
  205. puts( "[GLOBAL]" );
  206. printf( " Name = %s\n", Conf_ServerName );
  207. printf( " Info = %s\n", Conf_ServerInfo );
  208. printf( " Password = %s\n", Conf_ServerPwd );
  209. printf( " AdminInfo1 = %s\n", Conf_ServerAdmin1 );
  210. printf( " AdminInfo2 = %s\n", Conf_ServerAdmin2 );
  211. printf( " AdminEMail = %s\n", Conf_ServerAdminMail );
  212. printf( " MotdFile = %s\n", Conf_MotdFile );
  213. printf( " MotdPhrase = %s\n", Conf_MotdPhrase );
  214. printf( " ChrootDir = %s\n", Conf_Chroot );
  215. printf( " PidFile = %s\n", Conf_PidFile);
  216. printf(" Listen = %s\n", Conf_ListenAddress);
  217. fputs(" Ports = ", stdout);
  218. ports_puts(&Conf_ListenPorts);
  219. #ifdef SSL_SUPPORT
  220. fputs(" SSLPorts = ", stdout);
  221. ports_puts(&Conf_SSLOptions.ListenPorts);
  222. if (!ConfSSL_Puts())
  223. config_valid = false;
  224. #endif
  225. pwd = getpwuid(Conf_UID);
  226. if (pwd)
  227. printf(" ServerUID = %s\n", pwd->pw_name);
  228. else
  229. printf(" ServerUID = %ld\n", (long)Conf_UID);
  230. grp = getgrgid(Conf_GID);
  231. if (grp)
  232. printf(" ServerGID = %s\n", grp->gr_name);
  233. else
  234. printf(" ServerGID = %ld\n", (long)Conf_GID);
  235. printf(" PingTimeout = %d\n", Conf_PingTimeout);
  236. printf(" PongTimeout = %d\n", Conf_PongTimeout);
  237. printf(" ConnectRetry = %d\n", Conf_ConnectRetry);
  238. printf(" OperCanUseMode = %s\n", yesno_to_str(Conf_OperCanMode));
  239. printf(" OperServerMode = %s\n", yesno_to_str(Conf_OperServerMode));
  240. printf(" AllowRemoteOper = %s\n", yesno_to_str(Conf_AllowRemoteOper));
  241. printf(" PredefChannelsOnly = %s\n", yesno_to_str(Conf_PredefChannelsOnly));
  242. printf(" NoDNS = %s\n", yesno_to_str(Conf_NoDNS));
  243. printf(" NoIdent = %s\n", yesno_to_str(Conf_NoIdent));
  244. #ifdef WANT_IPV6
  245. printf(" ConnectIPv4 = %s\n", yesno_to_str(Conf_ConnectIPv6));
  246. printf(" ConnectIPv6 = %s\n", yesno_to_str(Conf_ConnectIPv4));
  247. #endif
  248. printf(" MaxConnections = %ld\n", Conf_MaxConnections);
  249. printf(" MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP);
  250. printf(" MaxJoins = %d\n", Conf_MaxJoins > 0 ? Conf_MaxJoins : -1);
  251. printf(" MaxNickLength = %u\n\n", Conf_MaxNickLength - 1);
  252. for( i = 0; i < Conf_Oper_Count; i++ ) {
  253. if( ! Conf_Oper[i].name[0] ) continue;
  254. /* Valid "Operator" section */
  255. puts( "[OPERATOR]" );
  256. printf( " Name = %s\n", Conf_Oper[i].name );
  257. printf( " Password = %s\n", Conf_Oper[i].pwd );
  258. if ( Conf_Oper[i].mask ) printf( " Mask = %s\n", Conf_Oper[i].mask );
  259. puts( "" );
  260. }
  261. for( i = 0; i < MAX_SERVERS; i++ ) {
  262. if( ! Conf_Server[i].name[0] ) continue;
  263. /* Valid "Server" section */
  264. puts( "[SERVER]" );
  265. printf( " Name = %s\n", Conf_Server[i].name );
  266. printf( " Host = %s\n", Conf_Server[i].host );
  267. printf( " Port = %u\n", (unsigned int)Conf_Server[i].port );
  268. #ifdef SSL_SUPPORT
  269. printf( " SSLConnect = %s\n", Conf_Server[i].SSLConnect?"yes":"no");
  270. #endif
  271. printf( " MyPassword = %s\n", Conf_Server[i].pwd_in );
  272. printf( " PeerPassword = %s\n", Conf_Server[i].pwd_out );
  273. printf( " ServiceMask = %s\n", Conf_Server[i].svs_mask);
  274. printf( " Group = %d\n", Conf_Server[i].group );
  275. printf( " Passive = %s\n\n", Conf_Server[i].flags & CONF_SFLAG_DISABLED ? "yes" : "no");
  276. }
  277. predef_channel_count = array_length(&Conf_Channels, sizeof(*predef_chan));
  278. predef_chan = array_start(&Conf_Channels);
  279. for (i = 0; i < predef_channel_count; i++, predef_chan++) {
  280. if (!predef_chan->name[0])
  281. continue;
  282. /* Valid "Channel" section */
  283. puts( "[CHANNEL]" );
  284. printf(" Name = %s\n", predef_chan->name);
  285. printf(" Modes = %s\n", predef_chan->modes);
  286. printf(" Key = %s\n", predef_chan->key);
  287. printf(" MaxUsers = %lu\n", predef_chan->maxusers);
  288. printf(" Topic = %s\n", predef_chan->topic);
  289. printf(" KeyFile = %s\n\n", predef_chan->keyfile);
  290. }
  291. return (config_valid ? 0 : 1);
  292. } /* Conf_Test */
  293. GLOBAL void
  294. Conf_UnsetServer( CONN_ID Idx )
  295. {
  296. /* Set next time for next connection attempt, if this is a server
  297. * link that is (still) configured here. If the server is set as
  298. * "once", delete it from our configuration.
  299. * Non-Server-Connections will be silently ignored. */
  300. int i;
  301. time_t t;
  302. /* Check all our configured servers */
  303. for( i = 0; i < MAX_SERVERS; i++ ) {
  304. if( Conf_Server[i].conn_id != Idx ) continue;
  305. /* Gotcha! Mark server configuration as "unused": */
  306. Conf_Server[i].conn_id = NONE;
  307. if( Conf_Server[i].flags & CONF_SFLAG_ONCE ) {
  308. /* Delete configuration here */
  309. Init_Server_Struct( &Conf_Server[i] );
  310. } else {
  311. /* Set time for next connect attempt */
  312. t = time(NULL);
  313. if (Conf_Server[i].lasttry < t - Conf_ConnectRetry) {
  314. /* The connection has been "long", so we don't
  315. * require the next attempt to be delayed. */
  316. Conf_Server[i].lasttry =
  317. t - Conf_ConnectRetry + RECONNECT_DELAY;
  318. } else
  319. Conf_Server[i].lasttry = t;
  320. }
  321. }
  322. } /* Conf_UnsetServer */
  323. GLOBAL void
  324. Conf_SetServer( int ConfServer, CONN_ID Idx )
  325. {
  326. /* Set connection for specified configured server */
  327. assert( ConfServer > NONE );
  328. assert( Idx > NONE );
  329. Conf_Server[ConfServer].conn_id = Idx;
  330. } /* Conf_SetServer */
  331. GLOBAL int
  332. Conf_GetServer( CONN_ID Idx )
  333. {
  334. /* Get index of server in configuration structure */
  335. int i = 0;
  336. assert( Idx > NONE );
  337. for( i = 0; i < MAX_SERVERS; i++ ) {
  338. if( Conf_Server[i].conn_id == Idx ) return i;
  339. }
  340. return NONE;
  341. } /* Conf_GetServer */
  342. GLOBAL bool
  343. Conf_EnableServer( const char *Name, UINT16 Port )
  344. {
  345. /* Enable specified server and adjust port */
  346. int i;
  347. assert( Name != NULL );
  348. for( i = 0; i < MAX_SERVERS; i++ ) {
  349. if( strcasecmp( Conf_Server[i].name, Name ) == 0 ) {
  350. /* Gotcha! Set port and enable server: */
  351. Conf_Server[i].port = Port;
  352. Conf_Server[i].flags &= ~CONF_SFLAG_DISABLED;
  353. return (Conf_Server[i].port && Conf_Server[i].host[0]);
  354. }
  355. }
  356. return false;
  357. } /* Conf_EnableServer */
  358. GLOBAL bool
  359. Conf_EnablePassiveServer(const char *Name)
  360. {
  361. /* Enable specified server */
  362. int i;
  363. assert( Name != NULL );
  364. for (i = 0; i < MAX_SERVERS; i++) {
  365. if ((strcasecmp( Conf_Server[i].name, Name ) == 0) && (Conf_Server[i].port > 0)) {
  366. /* BINGO! Enable server */
  367. Conf_Server[i].flags &= ~CONF_SFLAG_DISABLED;
  368. return true;
  369. }
  370. }
  371. return false;
  372. } /* Conf_EnablePassiveServer */
  373. GLOBAL bool
  374. Conf_DisableServer( const char *Name )
  375. {
  376. /* Enable specified server and adjust port */
  377. int i;
  378. assert( Name != NULL );
  379. for( i = 0; i < MAX_SERVERS; i++ ) {
  380. if( strcasecmp( Conf_Server[i].name, Name ) == 0 ) {
  381. /* Gotcha! Disable and disconnect server: */
  382. Conf_Server[i].flags |= CONF_SFLAG_DISABLED;
  383. if( Conf_Server[i].conn_id > NONE ) Conn_Close( Conf_Server[i].conn_id, NULL, "Server link terminated on operator request", true);
  384. return true;
  385. }
  386. }
  387. return false;
  388. } /* Conf_DisableServer */
  389. GLOBAL bool
  390. Conf_AddServer( const char *Name, UINT16 Port, const char *Host, const char *MyPwd, const char *PeerPwd )
  391. {
  392. /* Add new server to configuration */
  393. int i;
  394. assert( Name != NULL );
  395. assert( Host != NULL );
  396. assert( MyPwd != NULL );
  397. assert( PeerPwd != NULL );
  398. /* Search unused item in server configuration structure */
  399. for( i = 0; i < MAX_SERVERS; i++ ) {
  400. /* Is this item used? */
  401. if( ! Conf_Server[i].name[0] ) break;
  402. }
  403. if( i >= MAX_SERVERS ) return false;
  404. Init_Server_Struct( &Conf_Server[i] );
  405. strlcpy( Conf_Server[i].name, Name, sizeof( Conf_Server[i].name ));
  406. strlcpy( Conf_Server[i].host, Host, sizeof( Conf_Server[i].host ));
  407. strlcpy( Conf_Server[i].pwd_out, MyPwd, sizeof( Conf_Server[i].pwd_out ));
  408. strlcpy( Conf_Server[i].pwd_in, PeerPwd, sizeof( Conf_Server[i].pwd_in ));
  409. Conf_Server[i].port = Port;
  410. Conf_Server[i].flags = CONF_SFLAG_ONCE;
  411. return true;
  412. } /* Conf_AddServer */
  413. /**
  414. * Check if the given nick name is an service
  415. */
  416. GLOBAL bool
  417. Conf_IsService(int ConfServer, const char *Nick)
  418. {
  419. return MatchCaseInsensitive(Conf_Server[ConfServer].svs_mask, Nick);
  420. } /* Conf_IsService */
  421. /**
  422. * Initialize configuration settings with their default values.
  423. */
  424. static void
  425. Set_Defaults(bool InitServers)
  426. {
  427. int i;
  428. strcpy(Conf_ServerName, "");
  429. snprintf(Conf_ServerInfo, sizeof Conf_ServerInfo, "%s %s",
  430. PACKAGE_NAME, PACKAGE_VERSION);
  431. strcpy(Conf_ServerPwd, "");
  432. strcpy(Conf_ServerAdmin1, "");
  433. strcpy(Conf_ServerAdmin2, "");
  434. strcpy(Conf_ServerAdminMail, "");
  435. strlcpy(Conf_MotdFile, SYSCONFDIR, sizeof(Conf_MotdFile));
  436. strlcat(Conf_MotdFile, MOTD_FILE, sizeof(Conf_MotdFile));
  437. strlcpy(Conf_MotdPhrase, MOTD_PHRASE, sizeof(Conf_MotdPhrase));
  438. Conf_UID = Conf_GID = 0;
  439. strlcpy(Conf_Chroot, CHROOT_DIR, sizeof(Conf_Chroot));
  440. strlcpy(Conf_PidFile, PID_FILE, sizeof(Conf_PidFile));
  441. free(Conf_ListenAddress);
  442. Conf_ListenAddress = NULL;
  443. Conf_PingTimeout = 120;
  444. Conf_PongTimeout = 20;
  445. Conf_ConnectRetry = 60;
  446. Conf_NoDNS = false;
  447. Conf_NoIdent = false;
  448. Conf_Oper_Count = 0;
  449. Conf_Channel_Count = 0;
  450. Conf_OperCanMode = false;
  451. Conf_OperServerMode = false;
  452. Conf_AllowRemoteOper = false;
  453. Conf_PredefChannelsOnly = false;
  454. Conf_ConnectIPv4 = true;
  455. Conf_ConnectIPv6 = true;
  456. Conf_MaxConnections = 0;
  457. Conf_MaxConnectionsIP = 5;
  458. Conf_MaxJoins = 10;
  459. Conf_MaxNickLength = CLIENT_NICK_LEN_DEFAULT;
  460. /* Initialize server configuration structures */
  461. if (InitServers) {
  462. for (i = 0; i < MAX_SERVERS;
  463. Init_Server_Struct(&Conf_Server[i++]));
  464. }
  465. } /* Set_Defaults */
  466. static bool
  467. no_listenports(void)
  468. {
  469. size_t cnt = array_bytes(&Conf_ListenPorts);
  470. #ifdef SSL_SUPPORT
  471. cnt += array_bytes(&Conf_SSLOptions.ListenPorts);
  472. #endif
  473. return cnt == 0;
  474. }
  475. static bool
  476. Read_Config( bool ngircd_starting )
  477. {
  478. /* Read configuration file. */
  479. char section[LINE_LEN], str[LINE_LEN], *var, *arg, *ptr;
  480. const UINT16 defaultport = 6667;
  481. int line, i, n;
  482. FILE *fd;
  483. /* Open configuration file */
  484. fd = fopen( NGIRCd_ConfFile, "r" );
  485. if( ! fd ) {
  486. /* No configuration file found! */
  487. Config_Error( LOG_ALERT, "Can't read configuration \"%s\": %s",
  488. NGIRCd_ConfFile, strerror( errno ));
  489. if (!ngircd_starting)
  490. return false;
  491. Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME );
  492. exit( 1 );
  493. }
  494. Set_Defaults( ngircd_starting );
  495. Config_Error( LOG_INFO, "Reading configuration from \"%s\" ...", NGIRCd_ConfFile );
  496. /* Clean up server configuration structure: mark all already
  497. * configured servers as "once" so that they are deleted
  498. * after the next disconnect and delete all unused servers.
  499. * And delete all servers which are "duplicates" of servers
  500. * that are already marked as "once" (such servers have been
  501. * created by the last rehash but are now useless). */
  502. for( i = 0; i < MAX_SERVERS; i++ ) {
  503. if( Conf_Server[i].conn_id == NONE ) Init_Server_Struct( &Conf_Server[i] );
  504. else {
  505. /* This structure is in use ... */
  506. if( Conf_Server[i].flags & CONF_SFLAG_ONCE ) {
  507. /* Check for duplicates */
  508. for( n = 0; n < MAX_SERVERS; n++ ) {
  509. if( n == i ) continue;
  510. if( Conf_Server[i].conn_id == Conf_Server[n].conn_id ) {
  511. Init_Server_Struct( &Conf_Server[n] );
  512. #ifdef DEBUG
  513. Log(LOG_DEBUG,"Deleted unused duplicate server %d (kept %d).",
  514. n, i );
  515. #endif
  516. }
  517. }
  518. } else {
  519. /* Mark server as "once" */
  520. Conf_Server[i].flags |= CONF_SFLAG_ONCE;
  521. Log( LOG_DEBUG, "Marked server %d as \"once\"", i );
  522. }
  523. }
  524. }
  525. /* Initialize variables */
  526. line = 0;
  527. strcpy( section, "" );
  528. Init_Server_Struct( &New_Server );
  529. New_Server_Idx = NONE;
  530. #ifdef SSL_SUPPORT
  531. ConfSSL_Init();
  532. #endif
  533. /* Read configuration file */
  534. while( true ) {
  535. if( ! fgets( str, LINE_LEN, fd )) break;
  536. ngt_TrimStr( str );
  537. line++;
  538. /* Skip comments and empty lines */
  539. if( str[0] == ';' || str[0] == '#' || str[0] == '\0' ) continue;
  540. /* Is this the beginning of a new section? */
  541. if(( str[0] == '[' ) && ( str[strlen( str ) - 1] == ']' )) {
  542. strlcpy( section, str, sizeof( section ));
  543. if( strcasecmp( section, "[GLOBAL]" ) == 0 )
  544. continue;
  545. if( strcasecmp( section, "[OPERATOR]" ) == 0 ) {
  546. if( Conf_Oper_Count + 1 > MAX_OPERATORS )
  547. Config_Error( LOG_ERR, "Too many operators configured.");
  548. else {
  549. /* Initialize new operator structure */
  550. Conf_Oper[Conf_Oper_Count].name[0] = '\0';
  551. Conf_Oper[Conf_Oper_Count].pwd[0] = '\0';
  552. if (Conf_Oper[Conf_Oper_Count].mask) {
  553. free(Conf_Oper[Conf_Oper_Count].mask );
  554. Conf_Oper[Conf_Oper_Count].mask = NULL;
  555. }
  556. Conf_Oper_Count++;
  557. }
  558. continue;
  559. }
  560. if( strcasecmp( section, "[SERVER]" ) == 0 ) {
  561. /* Check if there is already a server to add */
  562. if( New_Server.name[0] ) {
  563. /* Copy data to "real" server structure */
  564. assert( New_Server_Idx > NONE );
  565. Conf_Server[New_Server_Idx] = New_Server;
  566. }
  567. /* Re-init structure for new server */
  568. Init_Server_Struct( &New_Server );
  569. /* Search unused item in server configuration structure */
  570. for( i = 0; i < MAX_SERVERS; i++ ) {
  571. /* Is this item used? */
  572. if( ! Conf_Server[i].name[0] ) break;
  573. }
  574. if( i >= MAX_SERVERS ) {
  575. /* Oops, no free item found! */
  576. Config_Error( LOG_ERR, "Too many servers configured." );
  577. New_Server_Idx = NONE;
  578. }
  579. else New_Server_Idx = i;
  580. continue;
  581. }
  582. if (strcasecmp(section, "[CHANNEL]") == 0) {
  583. Conf_Channel_Count++;
  584. continue;
  585. }
  586. Config_Error( LOG_ERR, "%s, line %d: Unknown section \"%s\"!", NGIRCd_ConfFile, line, section );
  587. section[0] = 0x1;
  588. }
  589. if( section[0] == 0x1 ) continue;
  590. /* Split line into variable name and parameters */
  591. ptr = strchr( str, '=' );
  592. if( ! ptr ) {
  593. Config_Error( LOG_ERR, "%s, line %d: Syntax error!", NGIRCd_ConfFile, line );
  594. continue;
  595. }
  596. *ptr = '\0';
  597. var = str; ngt_TrimStr( var );
  598. arg = ptr + 1; ngt_TrimStr( arg );
  599. if( strcasecmp( section, "[GLOBAL]" ) == 0 ) Handle_GLOBAL( line, var, arg );
  600. else if( strcasecmp( section, "[OPERATOR]" ) == 0 ) Handle_OPERATOR( line, var, arg );
  601. else if( strcasecmp( section, "[SERVER]" ) == 0 ) Handle_SERVER( line, var, arg );
  602. else if( strcasecmp( section, "[CHANNEL]" ) == 0 ) Handle_CHANNEL( line, var, arg );
  603. else Config_Error( LOG_ERR, "%s, line %d: Variable \"%s\" outside section!", NGIRCd_ConfFile, line, var );
  604. }
  605. /* Close configuration file */
  606. fclose( fd );
  607. /* Check if there is still a server to add */
  608. if( New_Server.name[0] ) {
  609. /* Copy data to "real" server structure */
  610. assert( New_Server_Idx > NONE );
  611. Conf_Server[New_Server_Idx] = New_Server;
  612. }
  613. /* not a single listening port? Add default. */
  614. if (no_listenports() &&
  615. !array_copyb(&Conf_ListenPorts, (char*) &defaultport, sizeof defaultport))
  616. {
  617. Config_Error(LOG_ALERT, "Could not add default listening Port %u: %s",
  618. (unsigned int) defaultport, strerror(errno));
  619. exit(1);
  620. }
  621. if (!Conf_ListenAddress)
  622. Conf_ListenAddress = strdup_warn(DEFAULT_LISTEN_ADDRSTR);
  623. if (!Conf_ListenAddress) {
  624. Config_Error(LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME);
  625. exit(1);
  626. }
  627. return true;
  628. } /* Read_Config */
  629. static bool
  630. Check_ArgIsTrue( const char *Arg )
  631. {
  632. if( strcasecmp( Arg, "yes" ) == 0 ) return true;
  633. if( strcasecmp( Arg, "true" ) == 0 ) return true;
  634. if( atoi( Arg ) != 0 ) return true;
  635. return false;
  636. } /* Check_ArgIsTrue */
  637. static unsigned int Handle_MaxNickLength(int Line, const char *Arg)
  638. {
  639. unsigned new;
  640. new = (unsigned) atoi(Arg) + 1;
  641. if (new > CLIENT_NICK_LEN) {
  642. Config_Error(LOG_WARNING,
  643. "%s, line %d: Value of \"MaxNickLength\" exceeds %u!",
  644. NGIRCd_ConfFile, Line, CLIENT_NICK_LEN - 1);
  645. return CLIENT_NICK_LEN;
  646. }
  647. if (new < 2) {
  648. Config_Error(LOG_WARNING,
  649. "%s, line %d: Value of \"MaxNickLength\" must be at least 1!",
  650. NGIRCd_ConfFile, Line);
  651. return 2;
  652. }
  653. return new;
  654. } /* Handle_MaxNickLength */
  655. static void
  656. Handle_GLOBAL( int Line, char *Var, char *Arg )
  657. {
  658. struct passwd *pwd;
  659. struct group *grp;
  660. size_t len;
  661. assert( Line > 0 );
  662. assert( Var != NULL );
  663. assert( Arg != NULL );
  664. if( strcasecmp( Var, "Name" ) == 0 ) {
  665. /* Server name */
  666. len = strlcpy( Conf_ServerName, Arg, sizeof( Conf_ServerName ));
  667. if (len >= sizeof( Conf_ServerName ))
  668. Config_Error_TooLong( Line, Var );
  669. return;
  670. }
  671. if( strcasecmp( Var, "Info" ) == 0 ) {
  672. /* Info text of server */
  673. len = strlcpy( Conf_ServerInfo, Arg, sizeof( Conf_ServerInfo ));
  674. if (len >= sizeof( Conf_ServerInfo ))
  675. Config_Error_TooLong ( Line, Var );
  676. return;
  677. }
  678. if( strcasecmp( Var, "Password" ) == 0 ) {
  679. /* Global server password */
  680. len = strlcpy( Conf_ServerPwd, Arg, sizeof( Conf_ServerPwd ));
  681. if (len >= sizeof( Conf_ServerPwd ))
  682. Config_Error_TooLong( Line, Var );
  683. return;
  684. }
  685. if( strcasecmp( Var, "AdminInfo1" ) == 0 ) {
  686. /* Administrative info #1 */
  687. len = strlcpy( Conf_ServerAdmin1, Arg, sizeof( Conf_ServerAdmin1 ));
  688. if (len >= sizeof( Conf_ServerAdmin1 ))
  689. Config_Error_TooLong ( Line, Var );
  690. return;
  691. }
  692. if( strcasecmp( Var, "AdminInfo2" ) == 0 ) {
  693. /* Administrative info #2 */
  694. len = strlcpy( Conf_ServerAdmin2, Arg, sizeof( Conf_ServerAdmin2 ));
  695. if (len >= sizeof( Conf_ServerAdmin2 ))
  696. Config_Error_TooLong ( Line, Var );
  697. return;
  698. }
  699. if( strcasecmp( Var, "AdminEMail" ) == 0 ) {
  700. /* Administrative email contact */
  701. len = strlcpy( Conf_ServerAdminMail, Arg, sizeof( Conf_ServerAdminMail ));
  702. if (len >= sizeof( Conf_ServerAdminMail ))
  703. Config_Error_TooLong( Line, Var );
  704. return;
  705. }
  706. if( strcasecmp( Var, "Ports" ) == 0 ) {
  707. ports_parse(&Conf_ListenPorts, Line, Arg);
  708. return;
  709. }
  710. if( strcasecmp( Var, "MotdFile" ) == 0 ) {
  711. /* "Message of the day" (MOTD) file */
  712. len = strlcpy( Conf_MotdFile, Arg, sizeof( Conf_MotdFile ));
  713. if (len >= sizeof( Conf_MotdFile ))
  714. Config_Error_TooLong( Line, Var );
  715. return;
  716. }
  717. if( strcasecmp( Var, "MotdPhrase" ) == 0 ) {
  718. /* "Message of the day" phrase (instead of file) */
  719. len = strlcpy( Conf_MotdPhrase, Arg, sizeof( Conf_MotdPhrase ));
  720. if (len >= sizeof( Conf_MotdPhrase ))
  721. Config_Error_TooLong( Line, Var );
  722. return;
  723. }
  724. if( strcasecmp( Var, "ChrootDir" ) == 0 ) {
  725. /* directory for chroot() */
  726. len = strlcpy( Conf_Chroot, Arg, sizeof( Conf_Chroot ));
  727. if (len >= sizeof( Conf_Chroot ))
  728. Config_Error_TooLong( Line, Var );
  729. return;
  730. }
  731. if ( strcasecmp( Var, "PidFile" ) == 0 ) {
  732. /* name of pidfile */
  733. len = strlcpy( Conf_PidFile, Arg, sizeof( Conf_PidFile ));
  734. if (len >= sizeof( Conf_PidFile ))
  735. Config_Error_TooLong( Line, Var );
  736. return;
  737. }
  738. if( strcasecmp( Var, "ServerUID" ) == 0 ) {
  739. /* UID the daemon should switch to */
  740. pwd = getpwnam( Arg );
  741. if( pwd ) Conf_UID = pwd->pw_uid;
  742. else {
  743. #ifdef HAVE_ISDIGIT
  744. if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var );
  745. else
  746. #endif
  747. Conf_UID = (unsigned int)atoi( Arg );
  748. }
  749. return;
  750. }
  751. if( strcasecmp( Var, "ServerGID" ) == 0 ) {
  752. /* GID the daemon should use */
  753. grp = getgrnam( Arg );
  754. if( grp ) Conf_GID = grp->gr_gid;
  755. else {
  756. #ifdef HAVE_ISDIGIT
  757. if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var );
  758. else
  759. #endif
  760. Conf_GID = (unsigned int)atoi( Arg );
  761. }
  762. return;
  763. }
  764. if( strcasecmp( Var, "PingTimeout" ) == 0 ) {
  765. /* PING timeout */
  766. Conf_PingTimeout = atoi( Arg );
  767. if( Conf_PingTimeout < 5 ) {
  768. Config_Error( LOG_WARNING, "%s, line %d: Value of \"PingTimeout\" too low!",
  769. NGIRCd_ConfFile, Line );
  770. Conf_PingTimeout = 5;
  771. }
  772. return;
  773. }
  774. if( strcasecmp( Var, "PongTimeout" ) == 0 ) {
  775. /* PONG timeout */
  776. Conf_PongTimeout = atoi( Arg );
  777. if( Conf_PongTimeout < 5 ) {
  778. Config_Error( LOG_WARNING, "%s, line %d: Value of \"PongTimeout\" too low!",
  779. NGIRCd_ConfFile, Line );
  780. Conf_PongTimeout = 5;
  781. }
  782. return;
  783. }
  784. if( strcasecmp( Var, "ConnectRetry" ) == 0 ) {
  785. /* Seconds between connection attempts to other servers */
  786. Conf_ConnectRetry = atoi( Arg );
  787. if( Conf_ConnectRetry < 5 ) {
  788. Config_Error( LOG_WARNING, "%s, line %d: Value of \"ConnectRetry\" too low!",
  789. NGIRCd_ConfFile, Line );
  790. Conf_ConnectRetry = 5;
  791. }
  792. return;
  793. }
  794. if( strcasecmp( Var, "PredefChannelsOnly" ) == 0 ) {
  795. /* Should we only allow pre-defined-channels? (i.e. users cannot create their own channels) */
  796. Conf_PredefChannelsOnly = Check_ArgIsTrue( Arg );
  797. return;
  798. }
  799. if( strcasecmp( Var, "NoDNS" ) == 0 ) {
  800. /* don't do reverse dns lookups when clients connect? */
  801. Conf_NoDNS = Check_ArgIsTrue( Arg );
  802. return;
  803. }
  804. if (strcasecmp(Var, "NoIdent") == 0) {
  805. /* don't do IDENT lookups when clients connect? */
  806. Conf_NoIdent = Check_ArgIsTrue(Arg);
  807. #ifndef IDENTAUTH
  808. if (!Conf_NoIdent) {
  809. /* user has enabled ident lookups explicitly, but ... */
  810. Config_Error(LOG_WARNING,
  811. "%s: line %d: NoIdent=False, but ngircd was built without IDENT support",
  812. NGIRCd_ConfFile, Line);
  813. }
  814. #endif
  815. return;
  816. }
  817. #ifdef WANT_IPV6
  818. /* the default setting for all the WANT_IPV6 special options is 'true' */
  819. if( strcasecmp( Var, "ConnectIPv6" ) == 0 ) {
  820. /* connect to other hosts using ipv6, if they have an AAAA record? */
  821. Conf_ConnectIPv6 = Check_ArgIsTrue( Arg );
  822. return;
  823. }
  824. if( strcasecmp( Var, "ConnectIPv4" ) == 0 ) {
  825. /* connect to other hosts using ipv4.
  826. * again, this can be used for ipv6-only setups */
  827. Conf_ConnectIPv4 = Check_ArgIsTrue( Arg );
  828. return;
  829. }
  830. #endif
  831. if( strcasecmp( Var, "OperCanUseMode" ) == 0 ) {
  832. /* Are IRC operators allowed to use MODE in channels they aren't Op in? */
  833. Conf_OperCanMode = Check_ArgIsTrue( Arg );
  834. return;
  835. }
  836. if( strcasecmp( Var, "OperServerMode" ) == 0 ) {
  837. /* Mask IRC operator as if coming from the server? (ircd-irc2 compat hack) */
  838. Conf_OperServerMode = Check_ArgIsTrue( Arg );
  839. return;
  840. }
  841. if(strcasecmp(Var, "AllowRemoteOper") == 0) {
  842. /* Are remote IRC operators allowed to control this server? */
  843. Conf_AllowRemoteOper = Check_ArgIsTrue(Arg);
  844. return;
  845. }
  846. if( strcasecmp( Var, "MaxConnections" ) == 0 ) {
  847. /* Maximum number of connections. 0 -> "no limit". */
  848. #ifdef HAVE_ISDIGIT
  849. if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var);
  850. else
  851. #endif
  852. Conf_MaxConnections = atol( Arg );
  853. return;
  854. }
  855. if( strcasecmp( Var, "MaxConnectionsIP" ) == 0 ) {
  856. /* Maximum number of simultaneous connections from one IP. 0 -> "no limit" */
  857. #ifdef HAVE_ISDIGIT
  858. if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var );
  859. else
  860. #endif
  861. Conf_MaxConnectionsIP = atoi( Arg );
  862. return;
  863. }
  864. if( strcasecmp( Var, "MaxJoins" ) == 0 ) {
  865. /* Maximum number of channels a user can join. 0 -> "no limit". */
  866. #ifdef HAVE_ISDIGIT
  867. if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var );
  868. else
  869. #endif
  870. Conf_MaxJoins = atoi( Arg );
  871. return;
  872. }
  873. if( strcasecmp( Var, "MaxNickLength" ) == 0 ) {
  874. /* Maximum length of a nick name; must be same on all servers
  875. * within the IRC network! */
  876. Conf_MaxNickLength = Handle_MaxNickLength(Line, Arg);
  877. return;
  878. }
  879. if( strcasecmp( Var, "Listen" ) == 0 ) {
  880. /* IP-Address to bind sockets */
  881. if (Conf_ListenAddress) {
  882. Config_Error(LOG_ERR, "Multiple Listen= options, ignoring: %s", Arg);
  883. return;
  884. }
  885. Conf_ListenAddress = strdup_warn(Arg);
  886. /*
  887. * if allocation fails, we're in trouble:
  888. * we cannot ignore the error -- otherwise ngircd
  889. * would listen on all interfaces.
  890. */
  891. if (!Conf_ListenAddress) {
  892. Config_Error(LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME);
  893. exit(1);
  894. }
  895. return;
  896. }
  897. #ifdef SSL_SUPPORT
  898. if( strcasecmp( Var, "SSLPorts" ) == 0 ) {
  899. ports_parse(&Conf_SSLOptions.ListenPorts, Line, Arg);
  900. return;
  901. }
  902. if( strcasecmp( Var, "SSLKeyFile" ) == 0 ) {
  903. assert(Conf_SSLOptions.KeyFile == NULL );
  904. Conf_SSLOptions.KeyFile = strdup_warn(Arg);
  905. return;
  906. }
  907. if( strcasecmp( Var, "SSLCertFile" ) == 0 ) {
  908. assert(Conf_SSLOptions.CertFile == NULL );
  909. Conf_SSLOptions.CertFile = strdup_warn(Arg);
  910. return;
  911. }
  912. if( strcasecmp( Var, "SSLKeyFilePassword" ) == 0 ) {
  913. assert(array_bytes(&Conf_SSLOptions.KeyFilePassword) == 0);
  914. if (!array_copys(&Conf_SSLOptions.KeyFilePassword, Arg))
  915. Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Could not copy %s: %s!",
  916. NGIRCd_ConfFile, Line, Var, strerror(errno));
  917. return;
  918. }
  919. if( strcasecmp( Var, "SSLDHFile" ) == 0 ) {
  920. assert(Conf_SSLOptions.DHFile == NULL);
  921. Conf_SSLOptions.DHFile = strdup_warn( Arg );
  922. return;
  923. }
  924. #endif
  925. Config_Error(LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!",
  926. NGIRCd_ConfFile, Line, Var);
  927. } /* Handle_GLOBAL */
  928. static void
  929. Handle_OPERATOR( int Line, char *Var, char *Arg )
  930. {
  931. unsigned int opercount;
  932. size_t len;
  933. assert( Line > 0 );
  934. assert( Var != NULL );
  935. assert( Arg != NULL );
  936. assert( Conf_Oper_Count > 0 );
  937. if ( Conf_Oper_Count == 0 )
  938. return;
  939. opercount = Conf_Oper_Count - 1;
  940. if( strcasecmp( Var, "Name" ) == 0 ) {
  941. /* Name of IRC operator */
  942. len = strlcpy( Conf_Oper[opercount].name, Arg, sizeof( Conf_Oper[opercount].name ));
  943. if (len >= sizeof( Conf_Oper[opercount].name ))
  944. Config_Error_TooLong( Line, Var );
  945. return;
  946. }
  947. if( strcasecmp( Var, "Password" ) == 0 ) {
  948. /* Password of IRC operator */
  949. len = strlcpy( Conf_Oper[opercount].pwd, Arg, sizeof( Conf_Oper[opercount].pwd ));
  950. if (len >= sizeof( Conf_Oper[opercount].pwd ))
  951. Config_Error_TooLong( Line, Var );
  952. return;
  953. }
  954. if( strcasecmp( Var, "Mask" ) == 0 ) {
  955. if (Conf_Oper[opercount].mask) return; /* Hostname already configured */
  956. Conf_Oper[opercount].mask = strdup_warn( Arg );
  957. return;
  958. }
  959. Config_Error( LOG_ERR, "%s, line %d (section \"Operator\"): Unknown variable \"%s\"!",
  960. NGIRCd_ConfFile, Line, Var );
  961. } /* Handle_OPERATOR */
  962. static void
  963. Handle_SERVER( int Line, char *Var, char *Arg )
  964. {
  965. long port;
  966. size_t len;
  967. assert( Line > 0 );
  968. assert( Var != NULL );
  969. assert( Arg != NULL );
  970. /* Ignore server block if no space is left in server configuration structure */
  971. if( New_Server_Idx <= NONE ) return;
  972. if( strcasecmp( Var, "Host" ) == 0 ) {
  973. /* Hostname of the server */
  974. len = strlcpy( New_Server.host, Arg, sizeof( New_Server.host ));
  975. if (len >= sizeof( New_Server.host ))
  976. Config_Error_TooLong ( Line, Var );
  977. return;
  978. }
  979. if( strcasecmp( Var, "Name" ) == 0 ) {
  980. /* Name of the server ("Nick"/"ID") */
  981. len = strlcpy( New_Server.name, Arg, sizeof( New_Server.name ));
  982. if (len >= sizeof( New_Server.name ))
  983. Config_Error_TooLong( Line, Var );
  984. return;
  985. }
  986. if (strcasecmp(Var, "Bind") == 0) {
  987. if (ng_ipaddr_init(&New_Server.bind_addr, Arg, 0))
  988. return;
  989. Config_Error(LOG_ERR, "%s, line %d (section \"Server\"): Can't parse IP address \"%s\"",
  990. NGIRCd_ConfFile, Line, Arg);
  991. return;
  992. }
  993. if( strcasecmp( Var, "MyPassword" ) == 0 ) {
  994. /* Password of this server which is sent to the peer */
  995. if (*Arg == ':') {
  996. Config_Error(LOG_ERR,
  997. "%s, line %d (section \"Server\"): MyPassword must not start with ':'!",
  998. NGIRCd_ConfFile, Line);
  999. }
  1000. len = strlcpy( New_Server.pwd_in, Arg, sizeof( New_Server.pwd_in ));
  1001. if (len >= sizeof( New_Server.pwd_in ))
  1002. Config_Error_TooLong( Line, Var );
  1003. return;
  1004. }
  1005. if( strcasecmp( Var, "PeerPassword" ) == 0 ) {
  1006. /* Passwort of the peer which must be received */
  1007. len = strlcpy( New_Server.pwd_out, Arg, sizeof( New_Server.pwd_out ));
  1008. if (len >= sizeof( New_Server.pwd_out ))
  1009. Config_Error_TooLong( Line, Var );
  1010. return;
  1011. }
  1012. if( strcasecmp( Var, "Port" ) == 0 ) {
  1013. /* Port to which this server should connect */
  1014. port = atol( Arg );
  1015. if( port > 0 && port < 0xFFFF )
  1016. New_Server.port = (UINT16)port;
  1017. else
  1018. Config_Error( LOG_ERR, "%s, line %d (section \"Server\"): Illegal port number %ld!",
  1019. NGIRCd_ConfFile, Line, port );
  1020. return;
  1021. }
  1022. #ifdef SSL_SUPPORT
  1023. if( strcasecmp( Var, "SSLConnect" ) == 0 ) {
  1024. New_Server.SSLConnect = Check_ArgIsTrue(Arg);
  1025. return;
  1026. }
  1027. #endif
  1028. if( strcasecmp( Var, "Group" ) == 0 ) {
  1029. /* Server group */
  1030. #ifdef HAVE_ISDIGIT
  1031. if( ! isdigit( (int)*Arg ))
  1032. Config_Error_NaN( Line, Var );
  1033. else
  1034. #endif
  1035. New_Server.group = atoi( Arg );
  1036. return;
  1037. }
  1038. if( strcasecmp( Var, "Passive" ) == 0 ) {
  1039. if (Check_ArgIsTrue(Arg))
  1040. New_Server.flags |= CONF_SFLAG_DISABLED;
  1041. return;
  1042. }
  1043. if (strcasecmp(Var, "ServiceMask") == 0) {
  1044. len = strlcpy(New_Server.svs_mask, ngt_LowerStr(Arg),
  1045. sizeof(New_Server.svs_mask));
  1046. if (len >= sizeof(New_Server.svs_mask))
  1047. Config_Error_TooLong(Line, Var);
  1048. return;
  1049. }
  1050. Config_Error( LOG_ERR, "%s, line %d (section \"Server\"): Unknown variable \"%s\"!",
  1051. NGIRCd_ConfFile, Line, Var );
  1052. } /* Handle_SERVER */
  1053. static bool
  1054. Handle_Channelname(struct Conf_Channel *new_chan, const char *name)
  1055. {
  1056. size_t size = sizeof(new_chan->name);
  1057. char *dest = new_chan->name;
  1058. if (!Channel_IsValidName(name)) {
  1059. /*
  1060. * maybe user forgot to add a '#'.
  1061. * This is only here for user convenience.
  1062. */
  1063. *dest = '#';
  1064. --size;
  1065. ++dest;
  1066. }
  1067. return size > strlcpy(dest, name, size);
  1068. }
  1069. static void
  1070. Handle_CHANNEL(int Line, char *Var, char *Arg)
  1071. {
  1072. size_t len;
  1073. size_t chancount;
  1074. struct Conf_Channel *chan;
  1075. assert( Line > 0 );
  1076. assert( Var != NULL );
  1077. assert( Arg != NULL );
  1078. assert(Conf_Channel_Count > 0);
  1079. chancount = Conf_Channel_Count - 1;
  1080. chan = array_alloc(&Conf_Channels, sizeof(*chan), chancount);
  1081. if (!chan) {
  1082. Config_Error(LOG_ERR, "Could not allocate memory for predefined channel (%d:%s = %s)", Line, Var, Arg);
  1083. return;
  1084. }
  1085. if (strcasecmp(Var, "Name") == 0) {
  1086. if (!Handle_Channelname(chan, Arg))
  1087. Config_Error_TooLong(Line, Var);
  1088. return;
  1089. }
  1090. if (strcasecmp(Var, "Modes") == 0) {
  1091. /* Initial modes */
  1092. len = strlcpy(chan->modes, Arg, sizeof(chan->modes));
  1093. if (len >= sizeof(chan->modes))
  1094. Config_Error_TooLong( Line, Var );
  1095. return;
  1096. }
  1097. if( strcasecmp( Var, "Topic" ) == 0 ) {
  1098. /* Initial topic */
  1099. len = strlcpy(chan->topic, Arg, sizeof(chan->topic));
  1100. if (len >= sizeof(chan->topic))
  1101. Config_Error_TooLong( Line, Var );
  1102. return;
  1103. }
  1104. if( strcasecmp( Var, "Key" ) == 0 ) {
  1105. /* Initial Channel Key (mode k) */
  1106. len = strlcpy(chan->key, Arg, sizeof(chan->key));
  1107. if (len >= sizeof(chan->key))
  1108. Config_Error_TooLong(Line, Var);
  1109. return;
  1110. }
  1111. if( strcasecmp( Var, "MaxUsers" ) == 0 ) {
  1112. /* maximum user limit, mode l */
  1113. chan->maxusers = (unsigned long) atol(Arg);
  1114. if (chan->maxusers == 0)
  1115. Config_Error_NaN(Line, Var);
  1116. return;
  1117. }
  1118. if (strcasecmp(Var, "KeyFile") == 0) {
  1119. /* channel keys */
  1120. len = strlcpy(chan->keyfile, Arg, sizeof(chan->keyfile));
  1121. if (len >= sizeof(chan->keyfile))
  1122. Config_Error_TooLong(Line, Var);
  1123. return;
  1124. }
  1125. Config_Error( LOG_ERR, "%s, line %d (section \"Channel\"): Unknown variable \"%s\"!",
  1126. NGIRCd_ConfFile, Line, Var );
  1127. } /* Handle_CHANNEL */
  1128. static bool
  1129. Validate_Config(bool Configtest, bool Rehash)
  1130. {
  1131. /* Validate configuration settings. */
  1132. #ifdef DEBUG
  1133. int i, servers, servers_once;
  1134. #endif
  1135. bool config_valid = true;
  1136. char *ptr;
  1137. /* Validate configured server name, see RFC 2812 section 2.3.1 */
  1138. ptr = Conf_ServerName;
  1139. do {
  1140. if (*ptr >= 'a' && *ptr <= 'z') continue;
  1141. if (*ptr >= 'A' && *ptr <= 'Z') continue;
  1142. if (*ptr >= '0' && *ptr <= '9') continue;
  1143. if (ptr > Conf_ServerName) {
  1144. if (*ptr == '.' || *ptr == '-')
  1145. continue;
  1146. }
  1147. Conf_ServerName[0] = '\0';
  1148. break;
  1149. } while (*(++ptr));
  1150. if (!Conf_ServerName[0]) {
  1151. /* No server name configured! */
  1152. config_valid = false;
  1153. Config_Error(LOG_ALERT,
  1154. "No (valid) server name configured in \"%s\" (section 'Global': 'Name')!",
  1155. NGIRCd_ConfFile);
  1156. if (!Configtest && !Rehash) {
  1157. Config_Error(LOG_ALERT,
  1158. "%s exiting due to fatal errors!",
  1159. PACKAGE_NAME);
  1160. exit(1);
  1161. }
  1162. }
  1163. if (Conf_ServerName[0] && !strchr(Conf_ServerName, '.')) {
  1164. /* No dot in server name! */
  1165. config_valid = false;
  1166. Config_Error(LOG_ALERT,
  1167. "Invalid server name configured in \"%s\" (section 'Global': 'Name'): Dot missing!",
  1168. NGIRCd_ConfFile);
  1169. if (!Configtest) {
  1170. Config_Error(LOG_ALERT,
  1171. "%s exiting due to fatal errors!",
  1172. PACKAGE_NAME);
  1173. exit(1);
  1174. }
  1175. }
  1176. #ifdef STRICT_RFC
  1177. if (!Conf_ServerAdminMail[0]) {
  1178. /* No administrative contact configured! */
  1179. config_valid = false;
  1180. Config_Error(LOG_ALERT,
  1181. "No administrator email address configured in \"%s\" ('AdminEMail')!",
  1182. NGIRCd_ConfFile);
  1183. if (!Configtest) {
  1184. Config_Error(LOG_ALERT,
  1185. "%s exiting due to fatal errors!",
  1186. PACKAGE_NAME);
  1187. exit(1);
  1188. }
  1189. }
  1190. #endif
  1191. if (!Conf_ServerAdmin1[0] && !Conf_ServerAdmin2[0]
  1192. && !Conf_ServerAdminMail[0]) {
  1193. /* No administrative information configured! */
  1194. Config_Error(LOG_WARNING,
  1195. "No administrative information configured but required by RFC!");
  1196. }
  1197. #ifdef DEBUG
  1198. servers = servers_once = 0;
  1199. for (i = 0; i < MAX_SERVERS; i++) {
  1200. if (Conf_Server[i].name[0]) {
  1201. servers++;
  1202. if (Conf_Server[i].flags & CONF_SFLAG_ONCE)
  1203. servers_once++;
  1204. }
  1205. }
  1206. Log(LOG_DEBUG,
  1207. "Configuration: Operators=%d, Servers=%d[%d], Channels=%d",
  1208. Conf_Oper_Count, servers, servers_once, Conf_Channel_Count);
  1209. #endif
  1210. return config_valid;
  1211. } /* Validate_Config */
  1212. static void
  1213. Config_Error_TooLong ( const int Line, const char *Item )
  1214. {
  1215. Config_Error( LOG_WARNING, "%s, line %d: Value of \"%s\" too long!", NGIRCd_ConfFile, Line, Item );
  1216. }
  1217. static void
  1218. Config_Error_NaN( const int Line, const char *Item )
  1219. {
  1220. Config_Error( LOG_WARNING, "%s, line %d: Value of \"%s\" is not a number!",
  1221. NGIRCd_ConfFile, Line, Item );
  1222. }
  1223. #ifdef PROTOTYPES
  1224. static void Config_Error( const int Level, const char *Format, ... )
  1225. #else
  1226. static void Config_Error( Level, Format, va_alist )
  1227. const int Level;
  1228. const char *Format;
  1229. va_dcl
  1230. #endif
  1231. {
  1232. /* Error! Write to console and/or logfile. */
  1233. char msg[MAX_LOG_MSG_LEN];
  1234. va_list ap;
  1235. assert( Format != NULL );
  1236. #ifdef PROTOTYPES
  1237. va_start( ap, Format );
  1238. #else
  1239. va_start( ap );
  1240. #endif
  1241. vsnprintf( msg, MAX_LOG_MSG_LEN, Format, ap );
  1242. va_end( ap );
  1243. /* During "normal operations" the log functions of the daemon should
  1244. * be used, but during testing of the configuration file, all messages
  1245. * should go directly to the console: */
  1246. if (Use_Log) Log( Level, "%s", msg );
  1247. else puts( msg );
  1248. } /* Config_Error */
  1249. static void
  1250. Init_Server_Struct( CONF_SERVER *Server )
  1251. {
  1252. /* Initialize server configuration structur to default values */
  1253. assert( Server != NULL );
  1254. memset( Server, 0, sizeof (CONF_SERVER) );
  1255. Server->group = NONE;
  1256. Server->lasttry = time( NULL ) - Conf_ConnectRetry + STARTUP_DELAY;
  1257. if( NGIRCd_Passive ) Server->flags = CONF_SFLAG_DISABLED;
  1258. Resolve_Init(&Server->res_stat);
  1259. Server->conn_id = NONE;
  1260. memset(&Server->bind_addr, 0, sizeof(&Server->bind_addr));
  1261. } /* Init_Server_Struct */
  1262. /* -eof- */