conf.c 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
  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. #include "portab.h"
  12. /**
  13. * @file
  14. * Configuration management (reading, parsing & validation)
  15. */
  16. #include "imp.h"
  17. #include <assert.h>
  18. #include <errno.h>
  19. #ifdef PROTOTYPES
  20. # include <stdarg.h>
  21. #else
  22. # include <varargs.h>
  23. #endif
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <strings.h>
  28. #include <unistd.h>
  29. #include <pwd.h>
  30. #include <grp.h>
  31. #include <sys/types.h>
  32. #include <unistd.h>
  33. #ifdef HAVE_CTYPE_H
  34. # include <ctype.h>
  35. #endif
  36. #include "array.h"
  37. #include "ngircd.h"
  38. #include "conn.h"
  39. #include "channel.h"
  40. #include "defines.h"
  41. #include "log.h"
  42. #include "match.h"
  43. #include "tool.h"
  44. #include "exp.h"
  45. #include "conf.h"
  46. static bool Use_Log = true, Using_MotdFile = true;
  47. static CONF_SERVER New_Server;
  48. static int New_Server_Idx;
  49. static char Conf_MotdFile[FNAME_LEN];
  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_LIMITS PARAMS(( int Line, char *Var, char *Arg ));
  55. static void Handle_OPTIONS PARAMS(( int Line, char *Var, char *Arg ));
  56. static void Handle_OPERATOR PARAMS(( int Line, char *Var, char *Arg ));
  57. static void Handle_SERVER PARAMS(( int Line, char *Var, char *Arg ));
  58. static void Handle_CHANNEL PARAMS(( int Line, char *Var, char *Arg ));
  59. static void Config_Error PARAMS(( const int Level, const char *Format, ... ));
  60. static void Config_Error_NaN PARAMS(( const int LINE, const char *Value ));
  61. static void Config_Error_Section PARAMS(( const int Line, const char *Item,
  62. const char *Section ));
  63. static void Config_Error_TooLong PARAMS(( const int LINE, const char *Value ));
  64. static void Init_Server_Struct PARAMS(( CONF_SERVER *Server ));
  65. #ifdef WANT_IPV6
  66. #define DEFAULT_LISTEN_ADDRSTR "::,0.0.0.0"
  67. #else
  68. #define DEFAULT_LISTEN_ADDRSTR "0.0.0.0"
  69. #endif
  70. #ifdef SSL_SUPPORT
  71. static void Handle_SSL PARAMS(( int Line, char *Var, char *Ark ));
  72. struct SSLOptions Conf_SSLOptions;
  73. /**
  74. * Initialize SSL configuration.
  75. */
  76. static void
  77. ConfSSL_Init(void)
  78. {
  79. free(Conf_SSLOptions.KeyFile);
  80. Conf_SSLOptions.KeyFile = NULL;
  81. free(Conf_SSLOptions.CertFile);
  82. Conf_SSLOptions.CertFile = NULL;
  83. free(Conf_SSLOptions.DHFile);
  84. Conf_SSLOptions.DHFile = NULL;
  85. array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
  86. }
  87. /**
  88. * Make sure that a configured file is readable.
  89. *
  90. * Currently, this function is only used for SSL-related options ...
  91. *
  92. * @param Var Configuration variable
  93. * @param Filename Configured filename
  94. */
  95. static void
  96. CheckFileReadable(const char *Var, const char *Filename)
  97. {
  98. FILE *fp;
  99. if (!Filename)
  100. return;
  101. fp = fopen(Filename, "r");
  102. if (fp)
  103. fclose(fp);
  104. else
  105. Config_Error(LOG_ERR, "Can't read \"%s\" (\"%s\"): %s",
  106. Filename, Var, strerror(errno));
  107. }
  108. #endif
  109. /**
  110. * Duplicate string and warn on errors.
  111. *
  112. * @returns Pointer to string on success, NULL otherwise.
  113. */
  114. static char *
  115. strdup_warn(const char *str)
  116. {
  117. char *ptr = strdup(str);
  118. if (!ptr)
  119. Config_Error(LOG_ERR,
  120. "Could not allocate memory for string: %s", str);
  121. return ptr;
  122. }
  123. /**
  124. * Output a comma separated list of ports (integer values).
  125. */
  126. static void
  127. ports_puts(array *a)
  128. {
  129. size_t len;
  130. UINT16 *ports;
  131. len = array_length(a, sizeof(UINT16));
  132. if (len--) {
  133. ports = (UINT16*) array_start(a);
  134. printf("%u", (unsigned int) *ports);
  135. while (len--) {
  136. ports++;
  137. printf(", %u", (unsigned int) *ports);
  138. }
  139. }
  140. putc('\n', stdout);
  141. }
  142. /**
  143. * Parse a comma separated string into an array of port numbers (integers).
  144. */
  145. static void
  146. ports_parse(array *a, int Line, char *Arg)
  147. {
  148. char *ptr;
  149. int port;
  150. UINT16 port16;
  151. array_trunc(a);
  152. ptr = strtok( Arg, "," );
  153. while (ptr) {
  154. ngt_TrimStr(ptr);
  155. port = atoi(ptr);
  156. if (port > 0 && port < 0xFFFF) {
  157. port16 = (UINT16) port;
  158. if (!array_catb(a, (char*)&port16, sizeof port16))
  159. Config_Error(LOG_ERR, "%s, line %d Could not add port number %ld: %s",
  160. NGIRCd_ConfFile, Line, port, strerror(errno));
  161. } else {
  162. Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Illegal port number %ld!",
  163. NGIRCd_ConfFile, Line, port );
  164. }
  165. ptr = strtok( NULL, "," );
  166. }
  167. }
  168. /**
  169. * Initialize configuration module.
  170. */
  171. GLOBAL void
  172. Conf_Init( void )
  173. {
  174. Read_Config( true );
  175. Validate_Config(false, false);
  176. }
  177. /**
  178. * "Rehash" (reload) server configuration.
  179. *
  180. * @returns true if configuration has been re-read, false on errors.
  181. */
  182. GLOBAL bool
  183. Conf_Rehash( void )
  184. {
  185. if (!Read_Config(false))
  186. return false;
  187. Validate_Config(false, true);
  188. /* Update CLIENT structure of local server */
  189. Client_SetInfo(Client_ThisServer(), Conf_ServerInfo);
  190. return true;
  191. }
  192. /**
  193. * Output a boolean value as "yes/no" string.
  194. */
  195. static const char*
  196. yesno_to_str(int boolean_value)
  197. {
  198. if (boolean_value)
  199. return "yes";
  200. return "no";
  201. }
  202. /**
  203. * Free all IRC operator configuration structures.
  204. */
  205. static void
  206. opers_free(void)
  207. {
  208. struct Conf_Oper *op;
  209. size_t len;
  210. len = array_length(&Conf_Opers, sizeof(*op));
  211. op = array_start(&Conf_Opers);
  212. while (len--) {
  213. free(op->mask);
  214. op++;
  215. }
  216. array_free(&Conf_Opers);
  217. }
  218. /**
  219. * Output all IRC operator configuration structures.
  220. */
  221. static void
  222. opers_puts(void)
  223. {
  224. struct Conf_Oper *op;
  225. size_t count, i;
  226. count = array_length(&Conf_Opers, sizeof(*op));
  227. op = array_start(&Conf_Opers);
  228. for (i = 0; i < count; i++, op++) {
  229. if (!op->name[0])
  230. continue;
  231. puts("[OPERATOR]");
  232. printf(" Name = %s\n", op->name);
  233. printf(" Password = %s\n", op->pwd);
  234. printf(" Mask = %s\n\n", op->mask ? op->mask : "");
  235. }
  236. }
  237. /**
  238. * Read configuration, validate and output it.
  239. *
  240. * This function waits for a keypress of the user when stdin/stdout are valid
  241. * tty's ("you can read our nice message and we can read in your keypress").
  242. *
  243. * @return 0 on succes, 1 on failure(s); therefore the result code can
  244. * directly be used by exit() when running "ngircd --configtest".
  245. */
  246. GLOBAL int
  247. Conf_Test( void )
  248. {
  249. struct passwd *pwd;
  250. struct group *grp;
  251. unsigned int i;
  252. bool config_valid;
  253. size_t predef_channel_count;
  254. struct Conf_Channel *predef_chan;
  255. Use_Log = false;
  256. if (! Read_Config(true))
  257. return 1;
  258. config_valid = Validate_Config(true, false);
  259. /* Valid tty? */
  260. if(isatty(fileno(stdin)) && isatty(fileno(stdout))) {
  261. puts("OK, press enter to see a dump of your server configuration ...");
  262. getchar();
  263. } else
  264. puts("Ok, dump of your server configuration follows:\n");
  265. puts("[GLOBAL]");
  266. printf(" Name = %s\n", Conf_ServerName);
  267. printf(" AdminInfo1 = %s\n", Conf_ServerAdmin1);
  268. printf(" AdminInfo2 = %s\n", Conf_ServerAdmin2);
  269. printf(" AdminEMail = %s\n", Conf_ServerAdminMail);
  270. printf(" Info = %s\n", Conf_ServerInfo);
  271. printf(" Listen = %s\n", Conf_ListenAddress);
  272. if (Using_MotdFile) {
  273. printf(" MotdFile = %s\n", Conf_MotdFile);
  274. printf(" MotdPhrase =\n");
  275. } else {
  276. printf(" MotdFile = \n");
  277. printf(" MotdPhrase = %s\n", array_bytes(&Conf_Motd)
  278. ? (const char*) array_start(&Conf_Motd) : "");
  279. }
  280. #ifndef PAM
  281. printf(" Password = %s\n", Conf_ServerPwd);
  282. #endif
  283. printf(" PidFile = %s\n", Conf_PidFile);
  284. printf(" Ports = ");
  285. ports_puts(&Conf_ListenPorts);
  286. grp = getgrgid(Conf_GID);
  287. if (grp)
  288. printf(" ServerGID = %s\n", grp->gr_name);
  289. else
  290. printf(" ServerGID = %ld\n", (long)Conf_GID);
  291. pwd = getpwuid(Conf_UID);
  292. if (pwd)
  293. printf(" ServerUID = %s\n", pwd->pw_name);
  294. else
  295. printf(" ServerUID = %ld\n", (long)Conf_UID);
  296. puts("");
  297. puts("[LIMITS]");
  298. printf(" ConnectRetry = %d\n", Conf_ConnectRetry);
  299. printf(" MaxConnections = %ld\n", Conf_MaxConnections);
  300. printf(" MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP);
  301. printf(" MaxJoins = %d\n", Conf_MaxJoins > 0 ? Conf_MaxJoins : -1);
  302. printf(" MaxNickLength = %u\n", Conf_MaxNickLength - 1);
  303. printf(" PingTimeout = %d\n", Conf_PingTimeout);
  304. printf(" PongTimeout = %d\n", Conf_PongTimeout);
  305. puts("");
  306. puts("[OPTIONS]");
  307. printf(" AllowRemoteOper = %s\n", yesno_to_str(Conf_AllowRemoteOper));
  308. printf(" ChrootDir = %s\n", Conf_Chroot);
  309. printf(" CloakHost = %s\n", Conf_CloakHost);
  310. printf(" CloakUserToNick = %s\n", yesno_to_str(Conf_CloakUserToNick));
  311. #ifdef WANT_IPV6
  312. printf(" ConnectIPv4 = %s\n", yesno_to_str(Conf_ConnectIPv6));
  313. printf(" ConnectIPv6 = %s\n", yesno_to_str(Conf_ConnectIPv4));
  314. #endif
  315. printf(" DNS = %s\n", yesno_to_str(Conf_DNS));
  316. #ifdef IDENT
  317. printf(" Ident = %s\n", yesno_to_str(Conf_Ident));
  318. #endif
  319. printf(" MorePrivacy = %s\n", yesno_to_str(Conf_MorePrivacy));
  320. printf(" NoticeAuth = %s\n", yesno_to_str(Conf_NoticeAuth));
  321. printf(" OperCanUseMode = %s\n", yesno_to_str(Conf_OperCanMode));
  322. printf(" OperServerMode = %s\n", yesno_to_str(Conf_OperServerMode));
  323. #ifdef PAM
  324. printf(" PAM = %s\n", yesno_to_str(Conf_PAM));
  325. printf(" PAMIsOptional = %s\n", yesno_to_str(Conf_PAMIsOptional));
  326. #endif
  327. printf(" PredefChannelsOnly = %s\n", yesno_to_str(Conf_PredefChannelsOnly));
  328. #ifndef STRICT_RFC
  329. printf(" RequireAuthPing = %s\n", yesno_to_str(Conf_AuthPing));
  330. #endif
  331. printf(" ScrubCTCP = %s\n", yesno_to_str(Conf_ScrubCTCP));
  332. #ifdef SYSLOG
  333. printf(" SyslogFacility = %s\n",
  334. ngt_SyslogFacilityName(Conf_SyslogFacility));
  335. #endif
  336. printf(" WebircPassword = %s\n", Conf_WebircPwd);
  337. puts("");
  338. #ifdef SSL_SUPPORT
  339. puts("[SSL]");
  340. printf(" CertFile = %s\n", Conf_SSLOptions.CertFile
  341. ? Conf_SSLOptions.CertFile : "");
  342. printf(" DHFile = %s\n", Conf_SSLOptions.DHFile
  343. ? Conf_SSLOptions.DHFile : "");
  344. printf(" KeyFile = %s\n", Conf_SSLOptions.KeyFile
  345. ? Conf_SSLOptions.KeyFile : "");
  346. if (array_bytes(&Conf_SSLOptions.KeyFilePassword))
  347. puts(" KeyFilePassword = <secret>");
  348. else
  349. puts(" KeyFilePassword = ");
  350. array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
  351. printf(" Ports = ");
  352. ports_puts(&Conf_SSLOptions.ListenPorts);
  353. puts("");
  354. #endif
  355. opers_puts();
  356. for( i = 0; i < MAX_SERVERS; i++ ) {
  357. if( ! Conf_Server[i].name[0] ) continue;
  358. /* Valid "Server" section */
  359. puts( "[SERVER]" );
  360. printf( " Name = %s\n", Conf_Server[i].name );
  361. printf( " Host = %s\n", Conf_Server[i].host );
  362. printf( " Port = %u\n", (unsigned int)Conf_Server[i].port );
  363. #ifdef SSL_SUPPORT
  364. printf( " SSLConnect = %s\n", Conf_Server[i].SSLConnect?"yes":"no");
  365. #endif
  366. printf( " MyPassword = %s\n", Conf_Server[i].pwd_in );
  367. printf( " PeerPassword = %s\n", Conf_Server[i].pwd_out );
  368. printf( " ServiceMask = %s\n", Conf_Server[i].svs_mask);
  369. printf( " Group = %d\n", Conf_Server[i].group );
  370. printf( " Passive = %s\n\n", Conf_Server[i].flags & CONF_SFLAG_DISABLED ? "yes" : "no");
  371. }
  372. predef_channel_count = array_length(&Conf_Channels, sizeof(*predef_chan));
  373. predef_chan = array_start(&Conf_Channels);
  374. for (i = 0; i < predef_channel_count; i++, predef_chan++) {
  375. if (!predef_chan->name[0])
  376. continue;
  377. /* Valid "Channel" section */
  378. puts( "[CHANNEL]" );
  379. printf(" Name = %s\n", predef_chan->name);
  380. printf(" Modes = %s\n", predef_chan->modes);
  381. printf(" Key = %s\n", predef_chan->key);
  382. printf(" MaxUsers = %lu\n", predef_chan->maxusers);
  383. printf(" Topic = %s\n", predef_chan->topic);
  384. printf(" KeyFile = %s\n\n", predef_chan->keyfile);
  385. }
  386. return (config_valid ? 0 : 1);
  387. }
  388. /**
  389. * Remove connection information from configured server.
  390. *
  391. * If the server is set as "once", delete it from our configuration;
  392. * otherwise set the time for the next connection attempt.
  393. *
  394. * Non-server connections will be silently ignored.
  395. */
  396. GLOBAL void
  397. Conf_UnsetServer( CONN_ID Idx )
  398. {
  399. int i;
  400. time_t t;
  401. /* Check all our configured servers */
  402. for( i = 0; i < MAX_SERVERS; i++ ) {
  403. if( Conf_Server[i].conn_id != Idx ) continue;
  404. /* Gotcha! Mark server configuration as "unused": */
  405. Conf_Server[i].conn_id = NONE;
  406. if( Conf_Server[i].flags & CONF_SFLAG_ONCE ) {
  407. /* Delete configuration here */
  408. Init_Server_Struct( &Conf_Server[i] );
  409. } else {
  410. /* Set time for next connect attempt */
  411. t = time(NULL);
  412. if (Conf_Server[i].lasttry < t - Conf_ConnectRetry) {
  413. /* The connection has been "long", so we don't
  414. * require the next attempt to be delayed. */
  415. Conf_Server[i].lasttry =
  416. t - Conf_ConnectRetry + RECONNECT_DELAY;
  417. } else
  418. Conf_Server[i].lasttry = t;
  419. }
  420. }
  421. }
  422. /**
  423. * Set connection information for specified configured server.
  424. */
  425. GLOBAL void
  426. Conf_SetServer( int ConfServer, CONN_ID Idx )
  427. {
  428. assert( ConfServer > NONE );
  429. assert( Idx > NONE );
  430. Conf_Server[ConfServer].conn_id = Idx;
  431. }
  432. /**
  433. * Get index of server in configuration structure.
  434. */
  435. GLOBAL int
  436. Conf_GetServer( CONN_ID Idx )
  437. {
  438. int i = 0;
  439. assert( Idx > NONE );
  440. for( i = 0; i < MAX_SERVERS; i++ ) {
  441. if( Conf_Server[i].conn_id == Idx ) return i;
  442. }
  443. return NONE;
  444. }
  445. /**
  446. * Enable a server by name and adjust its port number.
  447. *
  448. * @returns true if a server has been enabled and now has a valid port
  449. * number and host name for outgoing connections.
  450. */
  451. GLOBAL bool
  452. Conf_EnableServer( const char *Name, UINT16 Port )
  453. {
  454. int i;
  455. assert( Name != NULL );
  456. for( i = 0; i < MAX_SERVERS; i++ ) {
  457. if( strcasecmp( Conf_Server[i].name, Name ) == 0 ) {
  458. /* Gotcha! Set port and enable server: */
  459. Conf_Server[i].port = Port;
  460. Conf_Server[i].flags &= ~CONF_SFLAG_DISABLED;
  461. return (Conf_Server[i].port && Conf_Server[i].host[0]);
  462. }
  463. }
  464. return false;
  465. }
  466. /**
  467. * Enable a server by name.
  468. *
  469. * The server is only usable as outgoing server, if it has set a valid port
  470. * number for outgoing connections!
  471. * If not, you have to use Conf_EnableServer() function to make it available.
  472. *
  473. * @returns true if a server has been enabled; false otherwise.
  474. */
  475. GLOBAL bool
  476. Conf_EnablePassiveServer(const char *Name)
  477. {
  478. int i;
  479. assert( Name != NULL );
  480. for (i = 0; i < MAX_SERVERS; i++) {
  481. if ((strcasecmp( Conf_Server[i].name, Name ) == 0)
  482. && (Conf_Server[i].port > 0)) {
  483. /* BINGO! Enable server */
  484. Conf_Server[i].flags &= ~CONF_SFLAG_DISABLED;
  485. return true;
  486. }
  487. }
  488. return false;
  489. }
  490. /**
  491. * Disable a server by name.
  492. * An already established connection will be disconnected.
  493. *
  494. * @returns true if a server was found and has been disabled.
  495. */
  496. GLOBAL bool
  497. Conf_DisableServer( const char *Name )
  498. {
  499. int i;
  500. assert( Name != NULL );
  501. for( i = 0; i < MAX_SERVERS; i++ ) {
  502. if( strcasecmp( Conf_Server[i].name, Name ) == 0 ) {
  503. /* Gotcha! Disable and disconnect server: */
  504. Conf_Server[i].flags |= CONF_SFLAG_DISABLED;
  505. if( Conf_Server[i].conn_id > NONE )
  506. Conn_Close(Conf_Server[i].conn_id, NULL,
  507. "Server link terminated on operator request",
  508. true);
  509. return true;
  510. }
  511. }
  512. return false;
  513. }
  514. /**
  515. * Add a new remote server to our configuration.
  516. *
  517. * @param Name Name of the new server.
  518. * @param Port Port number to connect to or 0 for incoming connections.
  519. * @param Host Host name to connect to.
  520. * @param MyPwd Password that will be sent to the peer.
  521. * @param PeerPwd Password that must be received from the peer.
  522. * @returns true if the new server has been added; false otherwise.
  523. */
  524. GLOBAL bool
  525. Conf_AddServer(const char *Name, UINT16 Port, const char *Host,
  526. const char *MyPwd, const char *PeerPwd)
  527. {
  528. int i;
  529. assert( Name != NULL );
  530. assert( Host != NULL );
  531. assert( MyPwd != NULL );
  532. assert( PeerPwd != NULL );
  533. /* Search unused item in server configuration structure */
  534. for( i = 0; i < MAX_SERVERS; i++ ) {
  535. /* Is this item used? */
  536. if( ! Conf_Server[i].name[0] ) break;
  537. }
  538. if( i >= MAX_SERVERS ) return false;
  539. Init_Server_Struct( &Conf_Server[i] );
  540. strlcpy( Conf_Server[i].name, Name, sizeof( Conf_Server[i].name ));
  541. strlcpy( Conf_Server[i].host, Host, sizeof( Conf_Server[i].host ));
  542. strlcpy( Conf_Server[i].pwd_out, MyPwd, sizeof( Conf_Server[i].pwd_out ));
  543. strlcpy( Conf_Server[i].pwd_in, PeerPwd, sizeof( Conf_Server[i].pwd_in ));
  544. Conf_Server[i].port = Port;
  545. Conf_Server[i].flags = CONF_SFLAG_ONCE;
  546. return true;
  547. }
  548. /**
  549. * Check if the given nick name is an service.
  550. *
  551. * @returns true if the given nick name belongs to an "IRC service".
  552. */
  553. GLOBAL bool
  554. Conf_IsService(int ConfServer, const char *Nick)
  555. {
  556. return MatchCaseInsensitive(Conf_Server[ConfServer].svs_mask, Nick);
  557. }
  558. /**
  559. * Initialize configuration settings with their default values.
  560. */
  561. static void
  562. Set_Defaults(bool InitServers)
  563. {
  564. int i;
  565. /* Global */
  566. strcpy(Conf_ServerName, "");
  567. strcpy(Conf_ServerAdmin1, "");
  568. strcpy(Conf_ServerAdmin2, "");
  569. strcpy(Conf_ServerAdminMail, "");
  570. snprintf(Conf_ServerInfo, sizeof Conf_ServerInfo, "%s %s",
  571. PACKAGE_NAME, PACKAGE_VERSION);
  572. free(Conf_ListenAddress);
  573. Conf_ListenAddress = NULL;
  574. array_free(&Conf_Motd);
  575. strlcpy(Conf_MotdFile, SYSCONFDIR, sizeof(Conf_MotdFile));
  576. strlcat(Conf_MotdFile, MOTD_FILE, sizeof(Conf_MotdFile));
  577. strcpy(Conf_ServerPwd, "");
  578. strlcpy(Conf_PidFile, PID_FILE, sizeof(Conf_PidFile));
  579. Conf_UID = Conf_GID = 0;
  580. /* Limits */
  581. Conf_ConnectRetry = 60;
  582. Conf_MaxConnections = 0;
  583. Conf_MaxConnectionsIP = 5;
  584. Conf_MaxJoins = 10;
  585. Conf_MaxNickLength = CLIENT_NICK_LEN_DEFAULT;
  586. Conf_PingTimeout = 120;
  587. Conf_PongTimeout = 20;
  588. /* Options */
  589. Conf_AllowRemoteOper = false;
  590. #ifndef STRICT_RFC
  591. Conf_AuthPing = false;
  592. #endif
  593. strlcpy(Conf_Chroot, CHROOT_DIR, sizeof(Conf_Chroot));
  594. strcpy(Conf_CloakHost, "");
  595. Conf_CloakUserToNick = false;
  596. Conf_ConnectIPv4 = true;
  597. #ifdef WANT_IPV6
  598. Conf_ConnectIPv6 = true;
  599. #else
  600. Conf_ConnectIPv6 = false;
  601. #endif
  602. Conf_DNS = true;
  603. #ifdef IDENTAUTH
  604. Conf_Ident = true;
  605. #else
  606. Conf_Ident = false;
  607. #endif
  608. Conf_MorePrivacy = false;
  609. Conf_NoticeAuth = false;
  610. Conf_OperCanMode = false;
  611. Conf_OperServerMode = false;
  612. #ifdef PAM
  613. Conf_PAM = true;
  614. #else
  615. Conf_PAM = false;
  616. #endif
  617. Conf_PAMIsOptional = false;
  618. Conf_PredefChannelsOnly = false;
  619. #ifdef SYSLOG
  620. Conf_ScrubCTCP = false;
  621. #ifdef LOG_LOCAL5
  622. Conf_SyslogFacility = LOG_LOCAL5;
  623. #else
  624. Conf_SyslogFacility = 0;
  625. #endif
  626. #endif
  627. /* Initialize server configuration structures */
  628. if (InitServers) {
  629. for (i = 0; i < MAX_SERVERS;
  630. Init_Server_Struct(&Conf_Server[i++]));
  631. }
  632. }
  633. /**
  634. * Get number of configured listening ports.
  635. *
  636. * @returns The number of ports (IPv4+IPv6) on which the server should listen.
  637. */
  638. static bool
  639. no_listenports(void)
  640. {
  641. size_t cnt = array_bytes(&Conf_ListenPorts);
  642. #ifdef SSL_SUPPORT
  643. cnt += array_bytes(&Conf_SSLOptions.ListenPorts);
  644. #endif
  645. return cnt == 0;
  646. }
  647. /**
  648. * Read MOTD ("message of the day") file.
  649. *
  650. * @param filename Name of the file to read.
  651. */
  652. static void
  653. Read_Motd(const char *filename)
  654. {
  655. char line[127];
  656. FILE *fp;
  657. if (*filename == '\0')
  658. return;
  659. fp = fopen(filename, "r");
  660. if (!fp) {
  661. Config_Error(LOG_WARNING, "Can't read MOTD file \"%s\": %s",
  662. filename, strerror(errno));
  663. return;
  664. }
  665. array_free(&Conf_Motd);
  666. Using_MotdFile = true;
  667. while (fgets(line, (int)sizeof line, fp)) {
  668. ngt_TrimLastChr( line, '\n');
  669. /* add text including \0 */
  670. if (!array_catb(&Conf_Motd, line, strlen(line) + 1)) {
  671. Log(LOG_WARNING, "Cannot add MOTD text: %s", strerror(errno));
  672. break;
  673. }
  674. }
  675. fclose(fp);
  676. }
  677. /**
  678. * Read ngIRCd configuration file.
  679. *
  680. * Please note that this function uses exit(1) on fatal errors and therefore
  681. * can result in ngIRCd terminating!
  682. *
  683. * @param ngircd_starting Flag indicating if ngIRCd is starting or not.
  684. * @returns true when the configuration file has been read
  685. * successfully; false otherwise.
  686. */
  687. static bool
  688. Read_Config( bool ngircd_starting )
  689. {
  690. char section[LINE_LEN], str[LINE_LEN], *var, *arg, *ptr;
  691. const UINT16 defaultport = 6667;
  692. int line, i, n;
  693. size_t count;
  694. FILE *fd;
  695. /* Open configuration file */
  696. fd = fopen( NGIRCd_ConfFile, "r" );
  697. if( ! fd ) {
  698. /* No configuration file found! */
  699. Config_Error( LOG_ALERT, "Can't read configuration \"%s\": %s",
  700. NGIRCd_ConfFile, strerror( errno ));
  701. if (!ngircd_starting)
  702. return false;
  703. Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME );
  704. exit( 1 );
  705. }
  706. opers_free();
  707. Set_Defaults( ngircd_starting );
  708. Config_Error( LOG_INFO, "Reading configuration from \"%s\" ...", NGIRCd_ConfFile );
  709. /* Clean up server configuration structure: mark all already
  710. * configured servers as "once" so that they are deleted
  711. * after the next disconnect and delete all unused servers.
  712. * And delete all servers which are "duplicates" of servers
  713. * that are already marked as "once" (such servers have been
  714. * created by the last rehash but are now useless). */
  715. for( i = 0; i < MAX_SERVERS; i++ ) {
  716. if( Conf_Server[i].conn_id == NONE ) Init_Server_Struct( &Conf_Server[i] );
  717. else {
  718. /* This structure is in use ... */
  719. if( Conf_Server[i].flags & CONF_SFLAG_ONCE ) {
  720. /* Check for duplicates */
  721. for( n = 0; n < MAX_SERVERS; n++ ) {
  722. if( n == i ) continue;
  723. if( Conf_Server[i].conn_id == Conf_Server[n].conn_id ) {
  724. Init_Server_Struct( &Conf_Server[n] );
  725. #ifdef DEBUG
  726. Log(LOG_DEBUG,"Deleted unused duplicate server %d (kept %d).",
  727. n, i );
  728. #endif
  729. }
  730. }
  731. } else {
  732. /* Mark server as "once" */
  733. Conf_Server[i].flags |= CONF_SFLAG_ONCE;
  734. Log( LOG_DEBUG, "Marked server %d as \"once\"", i );
  735. }
  736. }
  737. }
  738. /* Initialize variables */
  739. line = 0;
  740. strcpy( section, "" );
  741. Init_Server_Struct( &New_Server );
  742. New_Server_Idx = NONE;
  743. #ifdef SSL_SUPPORT
  744. ConfSSL_Init();
  745. #endif
  746. /* Read configuration file */
  747. while( true ) {
  748. if( ! fgets( str, LINE_LEN, fd )) break;
  749. ngt_TrimStr( str );
  750. line++;
  751. /* Skip comments and empty lines */
  752. if( str[0] == ';' || str[0] == '#' || str[0] == '\0' ) continue;
  753. /* Is this the beginning of a new section? */
  754. if(( str[0] == '[' ) && ( str[strlen( str ) - 1] == ']' )) {
  755. strlcpy( section, str, sizeof( section ));
  756. if (strcasecmp(section, "[GLOBAL]") == 0
  757. || strcasecmp(section, "[LIMITS]") == 0
  758. || strcasecmp(section, "[OPTIONS]") == 0
  759. #ifdef SSL_SUPPORT
  760. || strcasecmp(section, "[SSL]") == 0
  761. #endif
  762. )
  763. continue;
  764. if( strcasecmp( section, "[SERVER]" ) == 0 ) {
  765. /* Check if there is already a server to add */
  766. if( New_Server.name[0] ) {
  767. /* Copy data to "real" server structure */
  768. assert( New_Server_Idx > NONE );
  769. Conf_Server[New_Server_Idx] = New_Server;
  770. }
  771. /* Re-init structure for new server */
  772. Init_Server_Struct( &New_Server );
  773. /* Search unused item in server configuration structure */
  774. for( i = 0; i < MAX_SERVERS; i++ ) {
  775. /* Is this item used? */
  776. if( ! Conf_Server[i].name[0] ) break;
  777. }
  778. if( i >= MAX_SERVERS ) {
  779. /* Oops, no free item found! */
  780. Config_Error( LOG_ERR, "Too many servers configured." );
  781. New_Server_Idx = NONE;
  782. }
  783. else New_Server_Idx = i;
  784. continue;
  785. }
  786. if (strcasecmp(section, "[CHANNEL]") == 0) {
  787. count = array_length(&Conf_Channels,
  788. sizeof(struct Conf_Channel));
  789. if (!array_alloc(&Conf_Channels,
  790. sizeof(struct Conf_Channel),
  791. count)) {
  792. Config_Error(LOG_ERR,
  793. "Could not allocate memory for new operator (line %d)",
  794. line);
  795. }
  796. continue;
  797. }
  798. if (strcasecmp(section, "[OPERATOR]") == 0) {
  799. count = array_length(&Conf_Opers,
  800. sizeof(struct Conf_Oper));
  801. if (!array_alloc(&Conf_Opers,
  802. sizeof(struct Conf_Oper),
  803. count)) {
  804. Config_Error(LOG_ERR,
  805. "Could not allocate memory for new channel (line &d)",
  806. line);
  807. }
  808. continue;
  809. }
  810. Config_Error(LOG_ERR,
  811. "%s, line %d: Unknown section \"%s\"!",
  812. NGIRCd_ConfFile, line, section);
  813. section[0] = 0x1;
  814. }
  815. if( section[0] == 0x1 ) continue;
  816. /* Split line into variable name and parameters */
  817. ptr = strchr( str, '=' );
  818. if( ! ptr ) {
  819. Config_Error( LOG_ERR, "%s, line %d: Syntax error!", NGIRCd_ConfFile, line );
  820. continue;
  821. }
  822. *ptr = '\0';
  823. var = str; ngt_TrimStr( var );
  824. arg = ptr + 1; ngt_TrimStr( arg );
  825. if(strcasecmp(section, "[GLOBAL]") == 0)
  826. Handle_GLOBAL(line, var, arg);
  827. else if(strcasecmp(section, "[LIMITS]") == 0)
  828. Handle_LIMITS(line, var, arg);
  829. else if(strcasecmp(section, "[OPTIONS]") == 0)
  830. Handle_OPTIONS(line, var, arg);
  831. #ifdef SSL_SUPPORT
  832. else if(strcasecmp(section, "[SSL]") == 0)
  833. Handle_SSL(line, var, arg);
  834. #endif
  835. else if(strcasecmp(section, "[OPERATOR]") == 0)
  836. Handle_OPERATOR(line, var, arg);
  837. else if(strcasecmp(section, "[SERVER]") == 0)
  838. Handle_SERVER(line, var, arg);
  839. else if(strcasecmp(section, "[CHANNEL]") == 0)
  840. Handle_CHANNEL(line, var, arg);
  841. else
  842. Config_Error(LOG_ERR,
  843. "%s, line %d: Variable \"%s\" outside section!",
  844. NGIRCd_ConfFile, line, var);
  845. }
  846. /* Close configuration file */
  847. fclose( fd );
  848. /* Check if there is still a server to add */
  849. if( New_Server.name[0] ) {
  850. /* Copy data to "real" server structure */
  851. assert( New_Server_Idx > NONE );
  852. Conf_Server[New_Server_Idx] = New_Server;
  853. }
  854. /* not a single listening port? Add default. */
  855. if (no_listenports() &&
  856. !array_copyb(&Conf_ListenPorts, (char*) &defaultport, sizeof defaultport))
  857. {
  858. Config_Error(LOG_ALERT, "Could not add default listening Port %u: %s",
  859. (unsigned int) defaultport, strerror(errno));
  860. exit(1);
  861. }
  862. if (!Conf_ListenAddress)
  863. Conf_ListenAddress = strdup_warn(DEFAULT_LISTEN_ADDRSTR);
  864. if (!Conf_ListenAddress) {
  865. Config_Error(LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME);
  866. exit(1);
  867. }
  868. /* No MOTD phrase configured? (re)try motd file. */
  869. if (array_bytes(&Conf_Motd) == 0)
  870. Read_Motd(Conf_MotdFile);
  871. #ifdef SSL_SUPPORT
  872. /* Make sure that all SSL-related files are readable */
  873. CheckFileReadable("CertFile", Conf_SSLOptions.CertFile);
  874. CheckFileReadable("DHFile", Conf_SSLOptions.DHFile);
  875. CheckFileReadable("KeyFile", Conf_SSLOptions.KeyFile);
  876. #endif
  877. return true;
  878. }
  879. /**
  880. * Check whether a string argument is "true" or "false".
  881. *
  882. * @param Arg Input string.
  883. * @returns true if the input string has been parsed as "yes", "true"
  884. * (case insensitive) or a non-zero integer value.
  885. */
  886. static bool
  887. Check_ArgIsTrue(const char *Arg)
  888. {
  889. if (strcasecmp(Arg, "yes") == 0)
  890. return true;
  891. if (strcasecmp(Arg, "true") == 0)
  892. return true;
  893. if (atoi(Arg) != 0)
  894. return true;
  895. return false;
  896. }
  897. /**
  898. * Handle setting of "MaxNickLength".
  899. *
  900. * @param Line Line number in configuration file.
  901. * @raram Arg Input string.
  902. * @returns New configured maximum nick name length.
  903. */
  904. static unsigned int
  905. Handle_MaxNickLength(int Line, const char *Arg)
  906. {
  907. unsigned new;
  908. new = (unsigned) atoi(Arg) + 1;
  909. if (new > CLIENT_NICK_LEN) {
  910. Config_Error(LOG_WARNING,
  911. "%s, line %d: Value of \"MaxNickLength\" exceeds %u!",
  912. NGIRCd_ConfFile, Line, CLIENT_NICK_LEN - 1);
  913. return CLIENT_NICK_LEN;
  914. }
  915. if (new < 2) {
  916. Config_Error(LOG_WARNING,
  917. "%s, line %d: Value of \"MaxNickLength\" must be at least 1!",
  918. NGIRCd_ConfFile, Line);
  919. return 2;
  920. }
  921. return new;
  922. }
  923. /**
  924. * Output a warning messages if IDENT is configured but not compiled in.
  925. */
  926. static void
  927. WarnIdent(int UNUSED Line)
  928. {
  929. #ifndef IDENTAUTH
  930. if (Conf_Ident) {
  931. /* user has enabled ident lookups explicitly, but ... */
  932. Config_Error(LOG_WARNING,
  933. "%s: line %d: \"Ident = yes\", but ngircd was built without IDENT support!",
  934. NGIRCd_ConfFile, Line);
  935. }
  936. #endif
  937. }
  938. /**
  939. * Output a warning messages if IPv6 is configured but not compiled in.
  940. */
  941. static void
  942. WarnIPv6(int UNUSED Line)
  943. {
  944. #ifndef WANT_IPV6
  945. if (Conf_ConnectIPv6) {
  946. /* user has enabled IPv6 explicitly, but ... */
  947. Config_Error(LOG_WARNING,
  948. "%s: line %d: \"ConnectIPv6 = yes\", but ngircd was built without IPv6 support!",
  949. NGIRCd_ConfFile, Line);
  950. }
  951. #endif
  952. }
  953. /**
  954. * Output a warning messages if PAM is configured but not compiled in.
  955. */
  956. static void
  957. WarnPAM(int UNUSED Line)
  958. {
  959. #ifndef PAM
  960. if (Conf_PAM) {
  961. Config_Error(LOG_WARNING,
  962. "%s: line %d: \"PAM = yes\", but ngircd was built without PAM support!",
  963. NGIRCd_ConfFile, Line);
  964. }
  965. #endif
  966. }
  967. /**
  968. * Handle legacy "NoXXX" options in [GLOBAL] section.
  969. *
  970. * TODO: This function and support for "NoXXX" could be removed starting
  971. * with ngIRCd release 19 (one release after marking it "deprecated").
  972. *
  973. * @param Var Variable name.
  974. * @param Arg Argument string.
  975. * @returns true if a NoXXX option has been processed; false otherwise.
  976. */
  977. static bool
  978. CheckLegacyNoOption(const char *Var, const char *Arg)
  979. {
  980. if(strcasecmp(Var, "NoDNS") == 0) {
  981. Conf_DNS = !Check_ArgIsTrue( Arg );
  982. return true;
  983. }
  984. if (strcasecmp(Var, "NoIdent") == 0) {
  985. Conf_Ident = !Check_ArgIsTrue(Arg);
  986. return true;
  987. }
  988. if(strcasecmp(Var, "NoPAM") == 0) {
  989. Conf_PAM = !Check_ArgIsTrue(Arg);
  990. return true;
  991. }
  992. return false;
  993. }
  994. /**
  995. * Handle deprecated legacy options in [GLOBAL] section.
  996. *
  997. * TODO: This function and support for these options in the [Global] section
  998. * could be removed starting with ngIRCd release 19 (one release after
  999. * marking it "deprecated").
  1000. *
  1001. * @param Var Variable name.
  1002. * @param Arg Argument string.
  1003. * @returns true if a legacy option has been processed; false otherwise.
  1004. */
  1005. static const char*
  1006. CheckLegacyGlobalOption(int Line, char *Var, char *Arg)
  1007. {
  1008. if (strcasecmp(Var, "AllowRemoteOper") == 0
  1009. || strcasecmp(Var, "ChrootDir") == 0
  1010. || strcasecmp(Var, "ConnectIPv4") == 0
  1011. || strcasecmp(Var, "ConnectIPv6") == 0
  1012. || strcasecmp(Var, "OperCanUseMode") == 0
  1013. || strcasecmp(Var, "OperServerMode") == 0
  1014. || strcasecmp(Var, "PredefChannelsOnly") == 0
  1015. || strcasecmp(Var, "SyslogFacility") == 0
  1016. || strcasecmp(Var, "WebircPassword") == 0) {
  1017. Handle_OPTIONS(Line, Var, Arg);
  1018. return "[Options]";
  1019. }
  1020. if (strcasecmp(Var, "ConnectRetry") == 0
  1021. || strcasecmp(Var, "MaxConnections") == 0
  1022. || strcasecmp(Var, "MaxConnectionsIP") == 0
  1023. || strcasecmp(Var, "MaxJoins") == 0
  1024. || strcasecmp(Var, "MaxNickLength") == 0
  1025. || strcasecmp(Var, "PingTimeout") == 0
  1026. || strcasecmp(Var, "PongTimeout") == 0) {
  1027. Handle_LIMITS(Line, Var, Arg);
  1028. return "[Limits]";
  1029. }
  1030. #ifdef SSL_SUPPORT
  1031. if (strcasecmp(Var, "SSLCertFile") == 0
  1032. || strcasecmp(Var, "SSLDHFile") == 0
  1033. || strcasecmp(Var, "SSLKeyFile") == 0
  1034. || strcasecmp(Var, "SSLKeyFilePassword") == 0
  1035. || strcasecmp(Var, "SSLPorts") == 0) {
  1036. Handle_SSL(Line, Var + 3, Arg);
  1037. return "[SSL]";
  1038. }
  1039. #endif
  1040. return NULL;
  1041. }
  1042. /**
  1043. * Strip "no" prefix of a string.
  1044. *
  1045. * TODO: This function and support for "NoXXX" should be removed starting
  1046. * with ngIRCd release 19! (One release after marking it "deprecated").
  1047. *
  1048. * @param str Pointer to input string starting with "no".
  1049. * @returns New pointer to string without "no" prefix.
  1050. */
  1051. static const char *
  1052. NoNo(const char *str)
  1053. {
  1054. assert(strncasecmp("no", str, 2) == 0 && str[2]);
  1055. return str + 2;
  1056. }
  1057. /**
  1058. * Invert "boolean" string.
  1059. *
  1060. * TODO: This function and support for "NoXXX" should be removed starting
  1061. * with ngIRCd release 19! (One release after marking it "deprecated").
  1062. *
  1063. * @param arg "Boolean" input string.
  1064. * @returns Pointer to inverted "boolean string".
  1065. */
  1066. static const char *
  1067. InvertArg(const char *arg)
  1068. {
  1069. return yesno_to_str(!Check_ArgIsTrue(arg));
  1070. }
  1071. /**
  1072. * Handle variable in [Global] configuration section.
  1073. *
  1074. * @param Line Line numer in configuration file.
  1075. * @param Var Variable name.
  1076. * @param Arg Variable argument.
  1077. */
  1078. static void
  1079. Handle_GLOBAL( int Line, char *Var, char *Arg )
  1080. {
  1081. struct passwd *pwd;
  1082. struct group *grp;
  1083. size_t len;
  1084. const char *section;
  1085. assert(Line > 0);
  1086. assert(Var != NULL);
  1087. assert(Arg != NULL);
  1088. if (strcasecmp(Var, "Name") == 0) {
  1089. len = strlcpy(Conf_ServerName, Arg, sizeof(Conf_ServerName));
  1090. if (len >= sizeof(Conf_ServerName))
  1091. Config_Error_TooLong(Line, Var);
  1092. return;
  1093. }
  1094. if (strcasecmp(Var, "AdminInfo1") == 0) {
  1095. len = strlcpy(Conf_ServerAdmin1, Arg, sizeof(Conf_ServerAdmin1));
  1096. if (len >= sizeof(Conf_ServerAdmin1))
  1097. Config_Error_TooLong(Line, Var);
  1098. return;
  1099. }
  1100. if (strcasecmp(Var, "AdminInfo2") == 0) {
  1101. len = strlcpy(Conf_ServerAdmin2, Arg, sizeof(Conf_ServerAdmin2));
  1102. if (len >= sizeof(Conf_ServerAdmin2))
  1103. Config_Error_TooLong(Line, Var);
  1104. return;
  1105. }
  1106. if (strcasecmp(Var, "AdminEMail") == 0) {
  1107. len = strlcpy(Conf_ServerAdminMail, Arg,
  1108. sizeof(Conf_ServerAdminMail));
  1109. if (len >= sizeof(Conf_ServerAdminMail))
  1110. Config_Error_TooLong(Line, Var);
  1111. return;
  1112. }
  1113. if (strcasecmp(Var, "Info") == 0) {
  1114. len = strlcpy(Conf_ServerInfo, Arg, sizeof(Conf_ServerInfo));
  1115. if (len >= sizeof(Conf_ServerInfo))
  1116. Config_Error_TooLong(Line, Var);
  1117. return;
  1118. }
  1119. if (strcasecmp(Var, "Listen") == 0) {
  1120. if (Conf_ListenAddress) {
  1121. Config_Error(LOG_ERR,
  1122. "Multiple Listen= options, ignoring: %s",
  1123. Arg);
  1124. return;
  1125. }
  1126. Conf_ListenAddress = strdup_warn(Arg);
  1127. /* If allocation fails, we're in trouble: we cannot ignore the
  1128. * error -- otherwise ngircd would listen on all interfaces. */
  1129. if (!Conf_ListenAddress) {
  1130. Config_Error(LOG_ALERT,
  1131. "%s exiting due to fatal errors!",
  1132. PACKAGE_NAME);
  1133. exit(1);
  1134. }
  1135. return;
  1136. }
  1137. if (strcasecmp(Var, "MotdFile") == 0) {
  1138. len = strlcpy(Conf_MotdFile, Arg, sizeof(Conf_MotdFile));
  1139. if (len >= sizeof(Conf_MotdFile))
  1140. Config_Error_TooLong(Line, Var);
  1141. return;
  1142. }
  1143. if (strcasecmp(Var, "MotdPhrase") == 0) {
  1144. len = strlen(Arg);
  1145. if (len == 0)
  1146. return;
  1147. if (len >= LINE_LEN) {
  1148. Config_Error_TooLong(Line, Var);
  1149. return;
  1150. }
  1151. if (!array_copyb(&Conf_Motd, Arg, len + 1))
  1152. Config_Error(LOG_WARNING,
  1153. "%s, line %d: Could not append MotdPhrase: %s",
  1154. NGIRCd_ConfFile, Line, strerror(errno));
  1155. Using_MotdFile = false;
  1156. return;
  1157. }
  1158. if(strcasecmp(Var, "Password") == 0) {
  1159. len = strlcpy(Conf_ServerPwd, Arg, sizeof(Conf_ServerPwd));
  1160. if (len >= sizeof(Conf_ServerPwd))
  1161. Config_Error_TooLong(Line, Var);
  1162. return;
  1163. }
  1164. if (strcasecmp(Var, "PidFile") == 0) {
  1165. len = strlcpy(Conf_PidFile, Arg, sizeof(Conf_PidFile));
  1166. if (len >= sizeof(Conf_PidFile))
  1167. Config_Error_TooLong(Line, Var);
  1168. return;
  1169. }
  1170. if (strcasecmp(Var, "Ports") == 0) {
  1171. ports_parse(&Conf_ListenPorts, Line, Arg);
  1172. return;
  1173. }
  1174. if (strcasecmp(Var, "ServerGID") == 0) {
  1175. grp = getgrnam(Arg);
  1176. if (grp)
  1177. Conf_GID = grp->gr_gid;
  1178. else {
  1179. Conf_GID = (unsigned int)atoi(Arg);
  1180. if (!Conf_GID && strcmp(Arg, "0"))
  1181. Config_Error(LOG_WARNING,
  1182. "%s, line %d: Value of \"%s\" is not a valid group name or ID!",
  1183. NGIRCd_ConfFile, Line, Var);
  1184. }
  1185. return;
  1186. }
  1187. if (strcasecmp(Var, "ServerUID") == 0) {
  1188. pwd = getpwnam(Arg);
  1189. if (pwd)
  1190. Conf_UID = pwd->pw_uid;
  1191. else {
  1192. Conf_UID = (unsigned int)atoi(Arg);
  1193. if (!Conf_UID && strcmp(Arg, "0"))
  1194. Config_Error(LOG_WARNING,
  1195. "%s, line %d: Value of \"%s\" is not a valid user name or ID!",
  1196. NGIRCd_ConfFile, Line, Var);
  1197. }
  1198. return;
  1199. }
  1200. if (CheckLegacyNoOption(Var, Arg)) {
  1201. /* TODO: This function and support for "NoXXX" could be
  1202. * be removed starting with ngIRCd release 19 (one release
  1203. * after marking it "deprecated"). */
  1204. Config_Error(LOG_WARNING,
  1205. "%s, line %d (section \"Global\"): \"No\"-Prefix is deprecated, use \"%s = %s\" in [Options] section!",
  1206. NGIRCd_ConfFile, Line, NoNo(Var), InvertArg(Arg));
  1207. if (strcasecmp(Var, "NoIdent") == 0)
  1208. WarnIdent(Line);
  1209. else if (strcasecmp(Var, "NoPam") == 0)
  1210. WarnPAM(Line);
  1211. return;
  1212. }
  1213. if ((section = CheckLegacyGlobalOption(Line, Var, Arg))) {
  1214. /** TODO: This function and support for these options in the
  1215. * [Global] section could be removed starting with ngIRCd
  1216. * release 19 (one release after marking it "deprecated"). */
  1217. if (strncasecmp(Var, "SSL", 3) == 0) {
  1218. Config_Error(LOG_WARNING,
  1219. "%s, line %d (section \"Global\"): \"%s\" is deprecated here, move it to %s and rename to \"%s\"!",
  1220. NGIRCd_ConfFile, Line, Var, section,
  1221. Var + 3);
  1222. } else {
  1223. Config_Error(LOG_WARNING,
  1224. "%s, line %d (section \"Global\"): \"%s\" is deprecated here, move it to %s!",
  1225. NGIRCd_ConfFile, Line, Var, section);
  1226. }
  1227. return;
  1228. }
  1229. Config_Error_Section(Line, Var, "Global");
  1230. }
  1231. /**
  1232. * Handle variable in [Limits] configuration section.
  1233. *
  1234. * @param Line Line numer in configuration file.
  1235. * @param Var Variable name.
  1236. * @param Arg Variable argument.
  1237. */
  1238. static void
  1239. Handle_LIMITS(int Line, char *Var, char *Arg)
  1240. {
  1241. assert(Line > 0);
  1242. assert(Var != NULL);
  1243. assert(Arg != NULL);
  1244. if (strcasecmp(Var, "ConnectRetry") == 0) {
  1245. Conf_ConnectRetry = atoi(Arg);
  1246. if (Conf_ConnectRetry < 5) {
  1247. Config_Error(LOG_WARNING,
  1248. "%s, line %d: Value of \"ConnectRetry\" too low!",
  1249. NGIRCd_ConfFile, Line);
  1250. Conf_ConnectRetry = 5;
  1251. }
  1252. return;
  1253. }
  1254. if (strcasecmp(Var, "MaxConnections") == 0) {
  1255. Conf_MaxConnections = atol(Arg);
  1256. if (!Conf_MaxConnections && strcmp(Arg, "0"))
  1257. Config_Error_NaN(Line, Var);
  1258. return;
  1259. }
  1260. if (strcasecmp(Var, "MaxConnectionsIP") == 0) {
  1261. Conf_MaxConnectionsIP = atoi(Arg);
  1262. if (!Conf_MaxConnectionsIP && strcmp(Arg, "0"))
  1263. Config_Error_NaN(Line, Var);
  1264. return;
  1265. }
  1266. if (strcasecmp(Var, "MaxJoins") == 0) {
  1267. Conf_MaxJoins = atoi(Arg);
  1268. if (!Conf_MaxJoins && strcmp(Arg, "0"))
  1269. Config_Error_NaN(Line, Var);
  1270. return;
  1271. }
  1272. if (strcasecmp(Var, "MaxNickLength") == 0) {
  1273. Conf_MaxNickLength = Handle_MaxNickLength(Line, Arg);
  1274. return;
  1275. }
  1276. if (strcasecmp(Var, "PingTimeout") == 0) {
  1277. Conf_PingTimeout = atoi(Arg);
  1278. if (Conf_PingTimeout < 5) {
  1279. Config_Error(LOG_WARNING,
  1280. "%s, line %d: Value of \"PingTimeout\" too low!",
  1281. NGIRCd_ConfFile, Line);
  1282. Conf_PingTimeout = 5;
  1283. }
  1284. return;
  1285. }
  1286. if (strcasecmp(Var, "PongTimeout") == 0) {
  1287. Conf_PongTimeout = atoi(Arg);
  1288. if (Conf_PongTimeout < 5) {
  1289. Config_Error(LOG_WARNING,
  1290. "%s, line %d: Value of \"PongTimeout\" too low!",
  1291. NGIRCd_ConfFile, Line);
  1292. Conf_PongTimeout = 5;
  1293. }
  1294. return;
  1295. }
  1296. Config_Error_Section(Line, Var, "Limits");
  1297. }
  1298. /**
  1299. * Handle variable in [Options] configuration section.
  1300. *
  1301. * @param Line Line numer in configuration file.
  1302. * @param Var Variable name.
  1303. * @param Arg Variable argument.
  1304. */
  1305. static void
  1306. Handle_OPTIONS(int Line, char *Var, char *Arg)
  1307. {
  1308. size_t len;
  1309. assert(Line > 0);
  1310. assert(Var != NULL);
  1311. assert(Arg != NULL);
  1312. if (strcasecmp(Var, "AllowRemoteOper") == 0) {
  1313. Conf_AllowRemoteOper = Check_ArgIsTrue(Arg);
  1314. return;
  1315. }
  1316. if (strcasecmp(Var, "ChrootDir") == 0) {
  1317. len = strlcpy(Conf_Chroot, Arg, sizeof(Conf_Chroot));
  1318. if (len >= sizeof(Conf_Chroot))
  1319. Config_Error_TooLong(Line, Var);
  1320. return;
  1321. }
  1322. if (strcasecmp(Var, "CloakHost") == 0) {
  1323. len = strlcpy(Conf_CloakHost, Arg, sizeof(Conf_CloakHost));
  1324. if (len >= sizeof(Conf_CloakHost))
  1325. Config_Error_TooLong(Line, Var);
  1326. return;
  1327. }
  1328. if (strcasecmp(Var, "CloakUserToNick") == 0) {
  1329. Conf_CloakUserToNick = Check_ArgIsTrue(Arg);
  1330. return;
  1331. }
  1332. if (strcasecmp(Var, "ConnectIPv6") == 0) {
  1333. Conf_ConnectIPv6 = Check_ArgIsTrue(Arg);
  1334. WarnIPv6(Line);
  1335. return;
  1336. }
  1337. if (strcasecmp(Var, "ConnectIPv4") == 0) {
  1338. Conf_ConnectIPv4 = Check_ArgIsTrue(Arg);
  1339. return;
  1340. }
  1341. if (strcasecmp(Var, "DNS") == 0) {
  1342. Conf_DNS = Check_ArgIsTrue(Arg);
  1343. return;
  1344. }
  1345. if (strcasecmp(Var, "Ident") == 0) {
  1346. Conf_Ident = Check_ArgIsTrue(Arg);
  1347. WarnIdent(Line);
  1348. return;
  1349. }
  1350. if (strcasecmp(Var, "MorePrivacy") == 0) {
  1351. Conf_MorePrivacy = Check_ArgIsTrue(Arg);
  1352. return;
  1353. }
  1354. if (strcasecmp(Var, "NoticeAuth") == 0) {
  1355. Conf_NoticeAuth = Check_ArgIsTrue(Arg);
  1356. return;
  1357. }
  1358. if (strcasecmp(Var, "OperCanUseMode") == 0) {
  1359. Conf_OperCanMode = Check_ArgIsTrue(Arg);
  1360. return;
  1361. }
  1362. if (strcasecmp(Var, "OperServerMode") == 0) {
  1363. Conf_OperServerMode = Check_ArgIsTrue(Arg);
  1364. return;
  1365. }
  1366. if (strcasecmp(Var, "PAM") == 0) {
  1367. Conf_PAM = Check_ArgIsTrue(Arg);
  1368. WarnPAM(Line);
  1369. return;
  1370. }
  1371. if (strcasecmp(Var, "PAMIsOptional") == 0 ) {
  1372. Conf_PAMIsOptional = Check_ArgIsTrue(Arg);
  1373. return;
  1374. }
  1375. if (strcasecmp(Var, "PredefChannelsOnly") == 0) {
  1376. Conf_PredefChannelsOnly = Check_ArgIsTrue(Arg);
  1377. return;
  1378. }
  1379. #ifndef STRICT_RFC
  1380. if (strcasecmp(Var, "RequireAuthPing") == 0) {
  1381. Conf_AuthPing = Check_ArgIsTrue(Arg);
  1382. return;
  1383. }
  1384. #endif
  1385. if (strcasecmp(Var, "ScrubCTCP") == 0) {
  1386. Conf_ScrubCTCP = Check_ArgIsTrue(Arg);
  1387. return;
  1388. }
  1389. #ifdef SYSLOG
  1390. if (strcasecmp(Var, "SyslogFacility") == 0) {
  1391. Conf_SyslogFacility = ngt_SyslogFacilityID(Arg,
  1392. Conf_SyslogFacility);
  1393. return;
  1394. }
  1395. #endif
  1396. if (strcasecmp(Var, "WebircPassword") == 0) {
  1397. len = strlcpy(Conf_WebircPwd, Arg, sizeof(Conf_WebircPwd));
  1398. if (len >= sizeof(Conf_WebircPwd))
  1399. Config_Error_TooLong(Line, Var);
  1400. return;
  1401. }
  1402. Config_Error_Section(Line, Var, "Options");
  1403. }
  1404. #ifdef SSL_SUPPORT
  1405. /**
  1406. * Handle variable in [SSL] configuration section.
  1407. *
  1408. * @param Line Line numer in configuration file.
  1409. * @param Var Variable name.
  1410. * @param Arg Variable argument.
  1411. */
  1412. static void
  1413. Handle_SSL(int Line, char *Var, char *Arg)
  1414. {
  1415. assert(Line > 0);
  1416. assert(Var != NULL);
  1417. assert(Arg != NULL);
  1418. if (strcasecmp(Var, "CertFile") == 0) {
  1419. assert(Conf_SSLOptions.CertFile == NULL);
  1420. Conf_SSLOptions.CertFile = strdup_warn(Arg);
  1421. return;
  1422. }
  1423. if (strcasecmp(Var, "DHFile") == 0) {
  1424. assert(Conf_SSLOptions.DHFile == NULL);
  1425. Conf_SSLOptions.DHFile = strdup_warn(Arg);
  1426. return;
  1427. }
  1428. if (strcasecmp(Var, "KeyFile") == 0) {
  1429. assert(Conf_SSLOptions.KeyFile == NULL);
  1430. Conf_SSLOptions.KeyFile = strdup_warn(Arg);
  1431. return;
  1432. }
  1433. if (strcasecmp(Var, "KeyFilePassword") == 0) {
  1434. assert(array_bytes(&Conf_SSLOptions.KeyFilePassword) == 0);
  1435. if (!array_copys(&Conf_SSLOptions.KeyFilePassword, Arg))
  1436. Config_Error(LOG_ERR,
  1437. "%s, line %d (section \"SSL\"): Could not copy %s: %s!",
  1438. NGIRCd_ConfFile, Line, Var,
  1439. strerror(errno));
  1440. return;
  1441. }
  1442. if (strcasecmp(Var, "Ports") == 0) {
  1443. ports_parse(&Conf_SSLOptions.ListenPorts, Line, Arg);
  1444. return;
  1445. }
  1446. Config_Error_Section(Line, Var, "SSL");
  1447. }
  1448. #endif
  1449. /**
  1450. * Handle variable in [Operator] configuration section.
  1451. *
  1452. * @param Line Line numer in configuration file.
  1453. * @param Var Variable name.
  1454. * @param Arg Variable argument.
  1455. */
  1456. static void
  1457. Handle_OPERATOR( int Line, char *Var, char *Arg )
  1458. {
  1459. size_t len;
  1460. struct Conf_Oper *op;
  1461. assert( Line > 0 );
  1462. assert( Var != NULL );
  1463. assert( Arg != NULL );
  1464. op = array_get(&Conf_Opers, sizeof(*op),
  1465. array_length(&Conf_Opers, sizeof(*op)) - 1);
  1466. if (!op)
  1467. return;
  1468. if (strcasecmp(Var, "Name") == 0) {
  1469. /* Name of IRC operator */
  1470. len = strlcpy(op->name, Arg, sizeof(op->name));
  1471. if (len >= sizeof(op->name))
  1472. Config_Error_TooLong(Line, Var);
  1473. return;
  1474. }
  1475. if (strcasecmp(Var, "Password") == 0) {
  1476. /* Password of IRC operator */
  1477. len = strlcpy(op->pwd, Arg, sizeof(op->pwd));
  1478. if (len >= sizeof(op->pwd))
  1479. Config_Error_TooLong(Line, Var);
  1480. return;
  1481. }
  1482. if (strcasecmp(Var, "Mask") == 0) {
  1483. if (op->mask)
  1484. return; /* Hostname already configured */
  1485. op->mask = strdup_warn( Arg );
  1486. return;
  1487. }
  1488. Config_Error_Section(Line, Var, "Operator");
  1489. }
  1490. /**
  1491. * Handle variable in [Server] configuration section.
  1492. *
  1493. * @param Line Line numer in configuration file.
  1494. * @param Var Variable name.
  1495. * @param Arg Variable argument.
  1496. */
  1497. static void
  1498. Handle_SERVER( int Line, char *Var, char *Arg )
  1499. {
  1500. long port;
  1501. size_t len;
  1502. assert( Line > 0 );
  1503. assert( Var != NULL );
  1504. assert( Arg != NULL );
  1505. /* Ignore server block if no space is left in server configuration structure */
  1506. if( New_Server_Idx <= NONE ) return;
  1507. if( strcasecmp( Var, "Host" ) == 0 ) {
  1508. /* Hostname of the server */
  1509. len = strlcpy( New_Server.host, Arg, sizeof( New_Server.host ));
  1510. if (len >= sizeof( New_Server.host ))
  1511. Config_Error_TooLong ( Line, Var );
  1512. return;
  1513. }
  1514. if( strcasecmp( Var, "Name" ) == 0 ) {
  1515. /* Name of the server ("Nick"/"ID") */
  1516. len = strlcpy( New_Server.name, Arg, sizeof( New_Server.name ));
  1517. if (len >= sizeof( New_Server.name ))
  1518. Config_Error_TooLong( Line, Var );
  1519. return;
  1520. }
  1521. if (strcasecmp(Var, "Bind") == 0) {
  1522. if (ng_ipaddr_init(&New_Server.bind_addr, Arg, 0))
  1523. return;
  1524. Config_Error(LOG_ERR, "%s, line %d (section \"Server\"): Can't parse IP address \"%s\"",
  1525. NGIRCd_ConfFile, Line, Arg);
  1526. return;
  1527. }
  1528. if( strcasecmp( Var, "MyPassword" ) == 0 ) {
  1529. /* Password of this server which is sent to the peer */
  1530. if (*Arg == ':') {
  1531. Config_Error(LOG_ERR,
  1532. "%s, line %d (section \"Server\"): MyPassword must not start with ':'!",
  1533. NGIRCd_ConfFile, Line);
  1534. }
  1535. len = strlcpy( New_Server.pwd_in, Arg, sizeof( New_Server.pwd_in ));
  1536. if (len >= sizeof( New_Server.pwd_in ))
  1537. Config_Error_TooLong( Line, Var );
  1538. return;
  1539. }
  1540. if( strcasecmp( Var, "PeerPassword" ) == 0 ) {
  1541. /* Passwort of the peer which must be received */
  1542. len = strlcpy( New_Server.pwd_out, Arg, sizeof( New_Server.pwd_out ));
  1543. if (len >= sizeof( New_Server.pwd_out ))
  1544. Config_Error_TooLong( Line, Var );
  1545. return;
  1546. }
  1547. if( strcasecmp( Var, "Port" ) == 0 ) {
  1548. /* Port to which this server should connect */
  1549. port = atol( Arg );
  1550. if (port >= 0 && port < 0xFFFF)
  1551. New_Server.port = (UINT16)port;
  1552. else
  1553. Config_Error(LOG_ERR,
  1554. "%s, line %d (section \"Server\"): Illegal port number %ld!",
  1555. NGIRCd_ConfFile, Line, port );
  1556. return;
  1557. }
  1558. #ifdef SSL_SUPPORT
  1559. if( strcasecmp( Var, "SSLConnect" ) == 0 ) {
  1560. New_Server.SSLConnect = Check_ArgIsTrue(Arg);
  1561. return;
  1562. }
  1563. #endif
  1564. if( strcasecmp( Var, "Group" ) == 0 ) {
  1565. /* Server group */
  1566. New_Server.group = atoi( Arg );
  1567. if (!New_Server.group && strcmp(Arg, "0"))
  1568. Config_Error_NaN(Line, Var);
  1569. return;
  1570. }
  1571. if( strcasecmp( Var, "Passive" ) == 0 ) {
  1572. if (Check_ArgIsTrue(Arg))
  1573. New_Server.flags |= CONF_SFLAG_DISABLED;
  1574. return;
  1575. }
  1576. if (strcasecmp(Var, "ServiceMask") == 0) {
  1577. len = strlcpy(New_Server.svs_mask, ngt_LowerStr(Arg),
  1578. sizeof(New_Server.svs_mask));
  1579. if (len >= sizeof(New_Server.svs_mask))
  1580. Config_Error_TooLong(Line, Var);
  1581. return;
  1582. }
  1583. Config_Error_Section(Line, Var, "Server");
  1584. }
  1585. /**
  1586. * Copy channel name into channel structure.
  1587. *
  1588. * If the channel name is not valid because of a missing prefix ('#', '&'),
  1589. * a default prefix of '#' will be added.
  1590. *
  1591. * @param new_chan New already allocated channel structure.
  1592. * @param name Name of the new channel.
  1593. * @returns true on success, false otherwise.
  1594. */
  1595. static bool
  1596. Handle_Channelname(struct Conf_Channel *new_chan, const char *name)
  1597. {
  1598. size_t size = sizeof(new_chan->name);
  1599. char *dest = new_chan->name;
  1600. if (!Channel_IsValidName(name)) {
  1601. /*
  1602. * maybe user forgot to add a '#'.
  1603. * This is only here for user convenience.
  1604. */
  1605. *dest = '#';
  1606. --size;
  1607. ++dest;
  1608. }
  1609. return size > strlcpy(dest, name, size);
  1610. }
  1611. /**
  1612. * Handle variable in [Channel] configuration section.
  1613. *
  1614. * @param Line Line numer in configuration file.
  1615. * @param Var Variable name.
  1616. * @param Arg Variable argument.
  1617. */
  1618. static void
  1619. Handle_CHANNEL(int Line, char *Var, char *Arg)
  1620. {
  1621. size_t len;
  1622. struct Conf_Channel *chan;
  1623. assert( Line > 0 );
  1624. assert( Var != NULL );
  1625. assert( Arg != NULL );
  1626. chan = array_get(&Conf_Channels, sizeof(*chan),
  1627. array_length(&Conf_Channels, sizeof(*chan)) - 1);
  1628. if (!chan)
  1629. return;
  1630. if (strcasecmp(Var, "Name") == 0) {
  1631. if (!Handle_Channelname(chan, Arg))
  1632. Config_Error_TooLong(Line, Var);
  1633. return;
  1634. }
  1635. if (strcasecmp(Var, "Modes") == 0) {
  1636. /* Initial modes */
  1637. len = strlcpy(chan->modes, Arg, sizeof(chan->modes));
  1638. if (len >= sizeof(chan->modes))
  1639. Config_Error_TooLong( Line, Var );
  1640. return;
  1641. }
  1642. if( strcasecmp( Var, "Topic" ) == 0 ) {
  1643. /* Initial topic */
  1644. len = strlcpy(chan->topic, Arg, sizeof(chan->topic));
  1645. if (len >= sizeof(chan->topic))
  1646. Config_Error_TooLong( Line, Var );
  1647. return;
  1648. }
  1649. if( strcasecmp( Var, "Key" ) == 0 ) {
  1650. /* Initial Channel Key (mode k) */
  1651. len = strlcpy(chan->key, Arg, sizeof(chan->key));
  1652. if (len >= sizeof(chan->key))
  1653. Config_Error_TooLong(Line, Var);
  1654. return;
  1655. }
  1656. if( strcasecmp( Var, "MaxUsers" ) == 0 ) {
  1657. /* maximum user limit, mode l */
  1658. chan->maxusers = (unsigned long) atol(Arg);
  1659. if (!chan->maxusers && strcmp(Arg, "0"))
  1660. Config_Error_NaN(Line, Var);
  1661. return;
  1662. }
  1663. if (strcasecmp(Var, "KeyFile") == 0) {
  1664. /* channel keys */
  1665. len = strlcpy(chan->keyfile, Arg, sizeof(chan->keyfile));
  1666. if (len >= sizeof(chan->keyfile))
  1667. Config_Error_TooLong(Line, Var);
  1668. return;
  1669. }
  1670. Config_Error_Section(Line, Var, "Channel");
  1671. }
  1672. /**
  1673. * Validate server configuration.
  1674. *
  1675. * Please note that this function uses exit(1) on fatal errors and therefore
  1676. * can result in ngIRCd terminating!
  1677. *
  1678. * @param Configtest true if the daemon has been called with "--configtest".
  1679. * @param Rehash true if re-reading configuration on runtime.
  1680. * @returns true if configuration is valid.
  1681. */
  1682. static bool
  1683. Validate_Config(bool Configtest, bool Rehash)
  1684. {
  1685. /* Validate configuration settings. */
  1686. #ifdef DEBUG
  1687. int i, servers, servers_once;
  1688. #endif
  1689. bool config_valid = true;
  1690. char *ptr;
  1691. /* Validate configured server name, see RFC 2812 section 2.3.1 */
  1692. ptr = Conf_ServerName;
  1693. do {
  1694. if (*ptr >= 'a' && *ptr <= 'z') continue;
  1695. if (*ptr >= 'A' && *ptr <= 'Z') continue;
  1696. if (*ptr >= '0' && *ptr <= '9') continue;
  1697. if (ptr > Conf_ServerName) {
  1698. if (*ptr == '.' || *ptr == '-')
  1699. continue;
  1700. }
  1701. Conf_ServerName[0] = '\0';
  1702. break;
  1703. } while (*(++ptr));
  1704. if (!Conf_ServerName[0]) {
  1705. /* No server name configured! */
  1706. config_valid = false;
  1707. Config_Error(LOG_ALERT,
  1708. "No (valid) server name configured in \"%s\" (section 'Global': 'Name')!",
  1709. NGIRCd_ConfFile);
  1710. if (!Configtest && !Rehash) {
  1711. Config_Error(LOG_ALERT,
  1712. "%s exiting due to fatal errors!",
  1713. PACKAGE_NAME);
  1714. exit(1);
  1715. }
  1716. }
  1717. if (Conf_ServerName[0] && !strchr(Conf_ServerName, '.')) {
  1718. /* No dot in server name! */
  1719. config_valid = false;
  1720. Config_Error(LOG_ALERT,
  1721. "Invalid server name configured in \"%s\" (section 'Global': 'Name'): Dot missing!",
  1722. NGIRCd_ConfFile);
  1723. if (!Configtest) {
  1724. Config_Error(LOG_ALERT,
  1725. "%s exiting due to fatal errors!",
  1726. PACKAGE_NAME);
  1727. exit(1);
  1728. }
  1729. }
  1730. #ifdef STRICT_RFC
  1731. if (!Conf_ServerAdminMail[0]) {
  1732. /* No administrative contact configured! */
  1733. config_valid = false;
  1734. Config_Error(LOG_ALERT,
  1735. "No administrator email address configured in \"%s\" ('AdminEMail')!",
  1736. NGIRCd_ConfFile);
  1737. if (!Configtest) {
  1738. Config_Error(LOG_ALERT,
  1739. "%s exiting due to fatal errors!",
  1740. PACKAGE_NAME);
  1741. exit(1);
  1742. }
  1743. }
  1744. #endif
  1745. if (!Conf_ServerAdmin1[0] && !Conf_ServerAdmin2[0]
  1746. && !Conf_ServerAdminMail[0]) {
  1747. /* No administrative information configured! */
  1748. Config_Error(LOG_WARNING,
  1749. "No administrative information configured but required by RFC!");
  1750. }
  1751. #ifdef PAM
  1752. if (Conf_ServerPwd[0])
  1753. Config_Error(LOG_ERR,
  1754. "This server uses PAM, \"Password\" in [Global] section will be ignored!");
  1755. #endif
  1756. #ifdef DEBUG
  1757. servers = servers_once = 0;
  1758. for (i = 0; i < MAX_SERVERS; i++) {
  1759. if (Conf_Server[i].name[0]) {
  1760. servers++;
  1761. if (Conf_Server[i].flags & CONF_SFLAG_ONCE)
  1762. servers_once++;
  1763. }
  1764. }
  1765. Log(LOG_DEBUG,
  1766. "Configuration: Operators=%ld, Servers=%d[%d], Channels=%ld",
  1767. array_length(&Conf_Opers, sizeof(struct Conf_Oper)),
  1768. servers, servers_once,
  1769. array_length(&Conf_Channels, sizeof(struct Conf_Channel)));
  1770. #endif
  1771. return config_valid;
  1772. }
  1773. /**
  1774. * Output "line too long" warning.
  1775. *
  1776. * @param Line Line number in configuration file.
  1777. * @param Item Affected variable name.
  1778. */
  1779. static void
  1780. Config_Error_TooLong ( const int Line, const char *Item )
  1781. {
  1782. Config_Error( LOG_WARNING, "%s, line %d: Value of \"%s\" too long!", NGIRCd_ConfFile, Line, Item );
  1783. }
  1784. /**
  1785. * Output "unknown variable" warning.
  1786. *
  1787. * @param Line Line number in configuration file.
  1788. * @param Item Affected variable name.
  1789. * @param Section Section name.
  1790. */
  1791. static void
  1792. Config_Error_Section(const int Line, const char *Item, const char *Section)
  1793. {
  1794. Config_Error(LOG_ERR, "%s, line %d (section \"%s\"): Unknown variable \"%s\"!",
  1795. NGIRCd_ConfFile, Line, Section, Item);
  1796. }
  1797. /**
  1798. * Output "not a number" warning.
  1799. *
  1800. * @param Line Line number in configuration file.
  1801. * @param Item Affected variable name.
  1802. */
  1803. static void
  1804. Config_Error_NaN( const int Line, const char *Item )
  1805. {
  1806. Config_Error( LOG_WARNING, "%s, line %d: Value of \"%s\" is not a number!",
  1807. NGIRCd_ConfFile, Line, Item );
  1808. }
  1809. /**
  1810. * Output configuration error to console and/or logfile.
  1811. *
  1812. * On runtime, the normal log functions of the daemon are used. But when
  1813. * testing the configuration ("--configtest"), all messages go directly
  1814. * to the console.
  1815. *
  1816. * @param Level Severity level of the message.
  1817. * @param Format Format string; see printf() function.
  1818. */
  1819. #ifdef PROTOTYPES
  1820. static void Config_Error( const int Level, const char *Format, ... )
  1821. #else
  1822. static void Config_Error( Level, Format, va_alist )
  1823. const int Level;
  1824. const char *Format;
  1825. va_dcl
  1826. #endif
  1827. {
  1828. char msg[MAX_LOG_MSG_LEN];
  1829. va_list ap;
  1830. assert( Format != NULL );
  1831. #ifdef PROTOTYPES
  1832. va_start( ap, Format );
  1833. #else
  1834. va_start( ap );
  1835. #endif
  1836. vsnprintf( msg, MAX_LOG_MSG_LEN, Format, ap );
  1837. va_end( ap );
  1838. if (!Use_Log) {
  1839. if (Level <= LOG_WARNING)
  1840. printf(" - %s\n", msg);
  1841. else
  1842. puts(msg);
  1843. } else
  1844. Log(Level, "%s", msg);
  1845. }
  1846. #ifdef DEBUG
  1847. /**
  1848. * Dump internal state of the "configuration module".
  1849. */
  1850. GLOBAL void
  1851. Conf_DebugDump(void)
  1852. {
  1853. int i;
  1854. Log(LOG_DEBUG, "Configured servers:");
  1855. for (i = 0; i < MAX_SERVERS; i++) {
  1856. if (! Conf_Server[i].name[0])
  1857. continue;
  1858. Log(LOG_DEBUG,
  1859. " - %s: %s:%d, last=%ld, group=%d, flags=%d, conn=%d",
  1860. Conf_Server[i].name, Conf_Server[i].host,
  1861. Conf_Server[i].port, Conf_Server[i].lasttry,
  1862. Conf_Server[i].group, Conf_Server[i].flags,
  1863. Conf_Server[i].conn_id);
  1864. }
  1865. }
  1866. #endif
  1867. /**
  1868. * Initialize server configuration structur to default values.
  1869. *
  1870. * @param Server Pointer to server structure to initialize.
  1871. */
  1872. static void
  1873. Init_Server_Struct( CONF_SERVER *Server )
  1874. {
  1875. assert( Server != NULL );
  1876. memset( Server, 0, sizeof (CONF_SERVER) );
  1877. Server->group = NONE;
  1878. Server->lasttry = time( NULL ) - Conf_ConnectRetry + STARTUP_DELAY;
  1879. if( NGIRCd_Passive ) Server->flags = CONF_SFLAG_DISABLED;
  1880. Proc_InitStruct(&Server->res_stat);
  1881. Server->conn_id = NONE;
  1882. memset(&Server->bind_addr, 0, sizeof(Server->bind_addr));
  1883. }
  1884. /* -eof- */