Configuration.C 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. //
  2. // Configuration.C -- News configuration class
  3. //
  4. // Copyright 2003-2013 Michael Sweet
  5. // Copyright 2002-2013 Greg Ercolano
  6. //
  7. // This program is free software; you can redistribute it and/or modify
  8. // it under the terms of the GNU General Public Licensse as published by
  9. // the Free Software Foundation; either version 2 of the License, or
  10. // (at your option) any later version.
  11. //
  12. // This program is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. // GNU General Public License for more details.
  16. //
  17. // You should have received a copy of the GNU General Public License
  18. // along with this program; if not, write to the Free Software
  19. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. //
  21. // 80 //////////////////////////////////////////////////////////////////////////
  22. #include "everything.H"
  23. #include <stdarg.h>
  24. #include <syslog.h>
  25. #include <limits.h>
  26. // Initialize default configuration values...
  27. Configuration::Configuration()
  28. {
  29. char name[1024]; // Hostname string
  30. // Set defaults...
  31. HostnameLookups(0);
  32. norecurse_msgdir = 1;
  33. msgmod_dirs = 0;
  34. Listen(119);
  35. log = stderr;
  36. errorlog = "stderr";
  37. log_ino = 0;
  38. LogLevel(L_INFO);
  39. MaxClients(0);
  40. MaxLogSize("1m");
  41. gethostname(name, sizeof(name));
  42. ServerName(name);
  43. SendMail(SENDMAIL " -t");
  44. SpamFilter("");
  45. SpoolDir(SPOOL_DIR);
  46. Timeout(12 * 3600);
  47. User("news");
  48. auth_user = "-";
  49. auth_pass = "-";
  50. auth_sleep = 5;
  51. auth_flags = AUTH_NOAUTH;
  52. auth_protect = 0;
  53. }
  54. // Listen on a specific address and port...
  55. void Configuration::Listen(const char *l)
  56. {
  57. char hostname[256]; // Hostname or IP
  58. char portname[256]; // Port number or name
  59. char *ptr; // Pointer into port
  60. struct hostent *host; // Host address
  61. struct servent *port; // Service data
  62. long p; // Port number
  63. // Initialize the listen address to "nntp"...
  64. listen.sin_family = AF_INET;
  65. listen.sin_addr.s_addr = INADDR_ANY;
  66. listen.sin_port = htons(119);
  67. // Try to grab a hostname and port number...
  68. switch (sscanf(l, "%255[^:]:%255s", hostname, portname))
  69. {
  70. case 1 :
  71. // Hostname is a port number...
  72. strcpy(portname, hostname);
  73. strcpy(hostname, "*");
  74. break;
  75. case 2 :
  76. break;
  77. default :
  78. fprintf(stderr, "news: Unable to decode address '%s'\n", l);
  79. return;
  80. }
  81. // Decode the hostname and port number as needed...
  82. if (hostname[0] && strcmp(hostname, "*"))
  83. {
  84. if ((host = gethostbyname(hostname)) == NULL)
  85. {
  86. fprintf(stderr,
  87. "newsd: gethostbyname(%s) failed - %s\n"
  88. "newsd: Using address 127.0.0.1 (localhost)\n",
  89. hostname, hstrerror(h_errno));
  90. }
  91. else if (host->h_length != 4 || host->h_addrtype != AF_INET)
  92. {
  93. fprintf(stderr,
  94. "newsd: gethostbyname(%s) did not return an IPv4 address!\n"
  95. "newsd: Using address 127.0.0.1 (localhost)\n",
  96. hostname);
  97. }
  98. else
  99. memcpy(&(listen.sin_addr), host->h_addr, 4);
  100. }
  101. else if (!strcmp(hostname, "*"))
  102. listen.sin_addr.s_addr = INADDR_ANY;
  103. if (portname[0] != '\0')
  104. {
  105. if (isdigit(portname[0]))
  106. {
  107. p = strtol(portname, &ptr, 10);
  108. if (p <= 0 || *ptr)
  109. {
  110. fprintf(stderr,
  111. "newsd: Bad port number '%s'\n"
  112. "newsd: Using port 119 (nntp)\n",
  113. portname);
  114. }
  115. else
  116. listen.sin_port = htons(p);
  117. }
  118. else
  119. {
  120. if ((port = getservbyname(portname, "tcp")) == NULL)
  121. {
  122. fprintf(stderr,
  123. "newsd: getservbyname(\"%s\", \"tcp\") failed!\n"
  124. "newsd: Using port 119 (nntp)\n",
  125. portname);
  126. }
  127. else
  128. listen.sin_port = port->s_port;
  129. }
  130. }
  131. }
  132. // Listen on a port...
  133. void Configuration::Listen(int p)
  134. {
  135. // Listen on the "any" address with the specified port; needs to be
  136. // updated for IPv6 at some point...
  137. listen.sin_family = AF_INET;
  138. listen.sin_addr.s_addr = INADDR_ANY;
  139. listen.sin_port = htons(p);
  140. }
  141. #define BAD_VALUE() \
  142. fprintf(stderr, \
  143. "newsd: Bad %s value '%s' on line %d of '%s'\n", \
  144. name, value, linenum, conffile)
  145. #define WARN_DEPRECATED(new_name) \
  146. fprintf(stderr, \
  147. "newsd: %s on line %d of '%s' is deprecated; use '%s' instead\n", \
  148. name, linenum, conffile, new_name)
  149. // Load configuration values from a file...
  150. void Configuration::Load(const char *conffile)
  151. {
  152. FILE *fp; // Config file
  153. int linenum; // Line number
  154. char line[1024], // Line from config file
  155. *ptr, // Pointer into line
  156. *name, // Config directive
  157. *value; // Config value
  158. long lvalue; // Integer value
  159. if ((fp = fopen(conffile, "r")) == NULL)
  160. {
  161. fprintf(stderr,
  162. "newsd: Unable to open configuration file '%s' - %s!\n",
  163. conffile, strerror(errno));
  164. return;
  165. }
  166. linenum = 0;
  167. while (fgets(line, sizeof(line), fp))
  168. {
  169. // Increment line counter...
  170. linenum ++;
  171. // Strip comments...
  172. if ((ptr = strchr(line, '#')) != NULL)
  173. *ptr = '\0';
  174. // Strip trailing whitespace...
  175. for (ptr = line + strlen(line)-1; ptr >= line && isspace(*ptr); ptr--)
  176. *ptr = '\0';
  177. // Ignore blank lines...
  178. if (!line[0])
  179. continue;
  180. // Find directive name...
  181. for (name = line; isspace(*name); name ++);
  182. // Separate directive from value...
  183. for (value = name + 1; !isspace(*value) && *value; value ++);
  184. while (isspace(*value))
  185. *value++ = '\0';
  186. if (!*value)
  187. {
  188. fprintf(stderr, "newsd: %s missing value on line %d of '%s'\n",
  189. name, linenum, conffile);
  190. continue;
  191. }
  192. // Decode configuration directive...
  193. if (!strcasecmp(name, "HostnameLookups"))
  194. {
  195. if (!strcasecmp(value, "off") || !strcasecmp(value, "no"))
  196. {
  197. HostnameLookups(0);
  198. }
  199. else if (!strcasecmp(value, "on") || !strcasecmp(value, "yes"))
  200. {
  201. HostnameLookups(1);
  202. }
  203. else if (!strcasecmp(value, "double"))
  204. {
  205. HostnameLookups(2);
  206. }
  207. else
  208. BAD_VALUE();
  209. }
  210. else if (!strcasecmp(name, "NoRecurseMsgDir"))
  211. {
  212. if (!strcasecmp(value, "off") || !strcasecmp(value, "no")) norecurse_msgdir = 0;
  213. else if (!strcasecmp(value, "on") || !strcasecmp(value, "yes")) norecurse_msgdir = 1;
  214. else BAD_VALUE();
  215. }
  216. else if (!strcasecmp(name, "MsgModDirs"))
  217. {
  218. if (!strcasecmp(value, "off") || !strcasecmp(value, "no")) msgmod_dirs = 0;
  219. else if (!strcasecmp(value, "on") || !strcasecmp(value, "yes")) msgmod_dirs = 1;
  220. else BAD_VALUE();
  221. }
  222. else if (!strcasecmp(name, "Listen"))
  223. {
  224. Listen(value);
  225. }
  226. else if (!strcasecmp(name, "LogFile"))
  227. {
  228. WARN_DEPRECATED("ErrorLog");
  229. ErrorLog(value);
  230. }
  231. else if (!strcasecmp(name, "ErrorLog"))
  232. {
  233. ErrorLog(value);
  234. }
  235. else if (!strcasecmp(name, "LogLevel"))
  236. {
  237. if (!strcasecmp(value, "error"))
  238. LogLevel(L_ERROR);
  239. else if (!strcasecmp(value, "info"))
  240. LogLevel(L_INFO);
  241. else if (!strcasecmp(value, "debug"))
  242. LogLevel(L_DEBUG);
  243. else
  244. BAD_VALUE();
  245. }
  246. else if (!strcasecmp(name, "MaxClients"))
  247. {
  248. lvalue = strtol(value, &ptr, 10);
  249. if (lvalue < 0 || *ptr)
  250. BAD_VALUE();
  251. else
  252. MaxClients(lvalue);
  253. }
  254. else if (!strcasecmp(name, "MaxLogSize"))
  255. {
  256. MaxLogSize(value);
  257. }
  258. else if (!strcasecmp(name, "NewsHostname"))
  259. {
  260. WARN_DEPRECATED("ErrorLog");
  261. ServerName(value);
  262. }
  263. else if (!strcasecmp(name, "ServerName"))
  264. {
  265. ServerName(value);
  266. }
  267. else if (!strcasecmp(name, "SendMail"))
  268. {
  269. SendMail(value);
  270. }
  271. else if (!strcasecmp(name, "SpamFilter"))
  272. {
  273. SpamFilter(value);
  274. }
  275. else if (!strcasecmp(name, "SpoolDir"))
  276. {
  277. SpoolDir(value);
  278. }
  279. else if (!strcasecmp(name, "Timeout"))
  280. {
  281. lvalue = strtol(value, &ptr, 10);
  282. if (lvalue < 0 || *ptr)
  283. BAD_VALUE();
  284. else
  285. Timeout(lvalue);
  286. }
  287. else if (!strcasecmp(name, "User"))
  288. {
  289. User(value);
  290. if (bad_user)
  291. BAD_VALUE();
  292. }
  293. else if (!strcasecmp(name, "Auth.User"))
  294. {
  295. auth_user = value;
  296. auth_flags = ( auth_user == "-" ) ? AUTH_NOAUTH : AUTH_FAIL;
  297. }
  298. else if (!strcasecmp(name, "Auth.Pass"))
  299. {
  300. auth_pass = value;
  301. auth_flags = ( auth_pass == "-" ) ? AUTH_NOAUTH : AUTH_FAIL;
  302. }
  303. else if (!strcasecmp(name, "Auth.Protect"))
  304. {
  305. if (!strcasecmp(value, "post")) auth_protect = AUTH_POST;
  306. else if (!strcasecmp(value, "read")) auth_protect = AUTH_READ;
  307. else if (!strcasecmp(value, "all" )) auth_protect = AUTH_POST | AUTH_READ;
  308. else if (!strcasecmp(value, "-" )) auth_protect = 0;
  309. else BAD_VALUE();
  310. }
  311. else if (!strcasecmp(name, "Auth.Sleep"))
  312. {
  313. unsigned lval;
  314. if ( sscanf(value, "%u", &lval) == 1 )
  315. auth_sleep = lval;
  316. else
  317. BAD_VALUE();
  318. }
  319. else
  320. {
  321. fprintf(stderr,
  322. "newsd: Unknown config file command '%s' on line %d of '%s'\n",
  323. line, linenum, conffile);
  324. }
  325. }
  326. // Close the config file and return...
  327. fclose(fp);
  328. }
  329. // CREATE THE NEWS LOG DIRECTORY IF IT DOESNT EXIST
  330. // Help zero admin for users using 'all defaults'.
  331. // (If they change any of the defaults, assume they know what they're doing)
  332. // No return; all of this is optional.
  333. // Assumes config file has already been loaded.
  334. //
  335. void Configuration::FixNewsLogDir(const char* newslogdir)
  336. {
  337. int statok = 1;
  338. int domkdir = 0;
  339. struct stat logdir_stat;
  340. // Does log dir exist?
  341. if ( stat(newslogdir, &logdir_stat) == 0 )
  342. {
  343. // Stat ok, is the newslogdir a file instead of a directory?
  344. if ( ! S_ISDIR(logdir_stat.st_mode) )
  345. {
  346. // Rename away old news file, then create dir
  347. // Rename /var/log/news -> /var/log/news.old
  348. //
  349. string oldfile;
  350. oldfile = newslogdir;
  351. oldfile += ".old";
  352. if ( rename(newslogdir, oldfile.c_str()) < 0 )
  353. {
  354. fprintf(stderr,
  355. "newsd: Can't rename away old news file to make log dir:\n"
  356. "newsd: rename(%s,%s): %s\n",
  357. newslogdir, oldfile.c_str(), strerror(errno));
  358. }
  359. domkdir = 1;
  360. }
  361. }
  362. else
  363. // Stat failed? Dir does not exist
  364. { domkdir = 1; }
  365. // Need to create directory?
  366. if ( domkdir )
  367. {
  368. // Logdir does not exist? Create it
  369. if ( mkdir(newslogdir, 0755) )
  370. fprintf(stderr, "newsd: mkdir(%s): %s\n",
  371. newslogdir, strerror(errno));
  372. // Redo stat to get perms etc.
  373. if ( stat(newslogdir, &logdir_stat) < 0 )
  374. {
  375. statok = 0;
  376. fprintf(stderr, "newsd: stat(%s): %s\n",
  377. newslogdir, strerror(errno));
  378. }
  379. }
  380. // Now check perms on newslogdir
  381. if ( statok )
  382. {
  383. // Dir owned by "news" user?
  384. if ( UID() != logdir_stat.st_uid || GID() != logdir_stat.st_gid )
  385. {
  386. // No? change it
  387. if ( chown(newslogdir, UID(), GID()) < 0 )
  388. {
  389. fprintf(stderr,
  390. "newsd: Can't change perms on log directory '%s': "
  391. "chown(%s,%u,%u) failed: %s\n",
  392. newslogdir, newslogdir, (unsigned)UID(), (unsigned)GID(), strerror(errno));
  393. }
  394. }
  395. }
  396. }
  397. // INITIALIZE LOGGING
  398. void Configuration::InitLog()
  399. {
  400. if (log)
  401. {
  402. if (log != stderr)
  403. fclose(log);
  404. log = 0;
  405. }
  406. if (errorlog == "syslog")
  407. openlog("newsd", LOG_PID, LOG_NEWS);
  408. else if (errorlog == "stderr")
  409. log = stderr;
  410. else if (errorlog.c_str()[0] == '|')
  411. {
  412. log = popen(errorlog.c_str() + 1, "w");
  413. if (!log)
  414. {
  415. fprintf(stderr, "newsd: Unable to open log pipe to \"%s\" - %s.\n",
  416. errorlog.c_str() + 1, strerror(errno));
  417. log = stderr;
  418. }
  419. }
  420. else
  421. OpenLogAppend();
  422. }
  423. // OPEN LOG FILE FOR APPENDING
  424. // o Closing existing log if open, new one is opened.
  425. // o Any LogLock()s are automatically unlocked.
  426. // o Log will be *UNLOCKED* on return.
  427. // o This function does *nothing* if errorlog == "stderr" or "syslog"
  428. //
  429. // Returns -1 on error, error msgs are printed to stderr
  430. //
  431. int Configuration::OpenLogAppend()
  432. {
  433. // Non-logfile? skip
  434. if ( errorlog == "stderr" || errorlog == "syslog" ||
  435. errorlog.c_str()[0] == '|' )
  436. return(0);
  437. // Close log (if open)
  438. if ( log )
  439. {
  440. if (log != stderr)
  441. fclose(log); // (also clears Lock()s, if any)
  442. log = 0;
  443. }
  444. // Open log for append, do NOT apply locks
  445. log = fopen(errorlog.c_str(), "a");
  446. if ( !log )
  447. {
  448. fprintf(stderr, "newsd: Unable to open log file \"%s\": %s.\n",
  449. errorlog.c_str(), strerror(errno));
  450. log = stderr;
  451. return(-1);
  452. }
  453. setbuf(log, NULL);
  454. // Save inode# for log rotation checks
  455. {
  456. struct stat buf;
  457. log_ino = ( fstat(fileno(log), &buf) == 0 ) ? buf.st_ino : 0;
  458. }
  459. // This will fail when running as non-root, so don't bother checking
  460. // the status here...
  461. fchmod(fileno(log), 0600);
  462. fchown(fileno(log), uid, gid);
  463. return(0);
  464. }
  465. // LOCK THE LOG FILE FOR WRITING/ROTATING
  466. // Returns -1 on error, error msg sent to stderr
  467. //
  468. int Configuration::LogLock()
  469. {
  470. if ( !log_ino ) return(0);
  471. if ( flock(fileno(log), LOCK_EX) < 0 )
  472. {
  473. fprintf(stderr, "newsd: LogLock(): flock(LOCK_EX): %s",
  474. strerror(errno));
  475. return(-1);
  476. }
  477. return(0);
  478. }
  479. // UNLOCK THE LOG FILE
  480. // Returns -1 on error, error msg sent to stderr
  481. //
  482. int Configuration::LogUnlock()
  483. {
  484. if ( !log_ino ) return(0);
  485. if ( flock(fileno(log), LOCK_UN) < 0 )
  486. {
  487. fprintf(stderr, "newsd: LogUnlock(): flock(LOCK_UN): %s",
  488. strerror(errno));
  489. return(-1);
  490. }
  491. return(0);
  492. }
  493. // RETURN PATHNAME OF 'OLD' LOGFILE
  494. string Configuration::OldLogFilename()
  495. {
  496. // Append .O
  497. return(errorlog + ".O");
  498. }
  499. // PRINT MESSAGE TO LOG WITH DATE STAMP
  500. // Appends crlf if none specified.
  501. //
  502. void Configuration::DateStampedMessage(FILE *fp, const char *msg)
  503. {
  504. time_t secs; // Current UNIX time
  505. struct tm *date; // Current date/time
  506. char datestr[1024]; // Date/time string
  507. time(&secs);
  508. date = localtime(&secs);
  509. strftime(datestr, sizeof(datestr), "%c", date);
  510. fprintf(fp, "%s newsd[%d]: %s%s",
  511. datestr, getpid(), msg,
  512. (msg[strlen(msg)-1] != '\n') ? "\n" : "");
  513. fflush(fp);
  514. }
  515. // HANDLE LOG ROTATION
  516. // Assumes Lock() already applied.
  517. // On return, Lock() will be applied to new log.
  518. //
  519. // force:
  520. // true = force log to be rotated (regardless of size)
  521. // false = rotate only if logsize > maxlogsize
  522. //
  523. // Returns:
  524. // 0 - no error, log not rotated
  525. // 1 - no error, log rotated
  526. // -1 - error occurred, error msg printed to log or stderr
  527. //
  528. int Configuration::Rotate(bool force)
  529. {
  530. // Don't rotate if we aren't logging to file...
  531. if ( !log_ino ) return (0);
  532. // Check size of log
  533. if ( ! force && maxlogsize > 0)
  534. {
  535. struct stat buf;
  536. if ( stat(errorlog.c_str(), &buf) < 0 )
  537. {
  538. string msg = "Log file size check failed: stat(" +
  539. errorlog + "): " + strerror(errno);
  540. DateStampedMessage(log, msg.c_str());
  541. return(-1);
  542. }
  543. // fprintf(stderr, "LOG SIZE CHECK: %lu <= %lu\n", //DEBUG
  544. // (unsigned long)buf.st_size, (unsigned long)maxlogsize); //DEBUG
  545. // Log too small? ignore
  546. if ( buf.st_size <= maxlogsize )
  547. { return(0); }
  548. }
  549. // Rotate log (lock will follow renamed log)
  550. string oerrorlog = OldLogFilename();
  551. if ( rename(errorlog.c_str(), oerrorlog.c_str()) < 0 )
  552. {
  553. string msg = "Log file rotation failed: rename(" +
  554. errorlog + "," + oerrorlog + "): " + strerror(errno);
  555. // Include uid/euid info, incase error is permission related
  556. {
  557. char junk[256];
  558. snprintf(junk, sizeof(junk), " (uid=%u euid=%u)",
  559. (unsigned)getuid(), (unsigned)geteuid());
  560. msg += junk;
  561. }
  562. DateStampedMessage(log, msg.c_str());
  563. return(-1);
  564. }
  565. // Indicate log rotated in old log
  566. // Log file is still locked, even though renamed
  567. //
  568. DateStampedMessage(log, "*** Log file rotated. ***");
  569. // Create new log
  570. // This will close log (removing any locks)
  571. //
  572. if ( OpenLogAppend() < 0 )
  573. return(-1);
  574. // Leave with log locked
  575. // Another process might sneak some msgs in before us.
  576. //
  577. LogLock();
  578. // Indicate log rotated in new log
  579. DateStampedMessage(log, "*** Log was rotated. ***");
  580. return(0);
  581. }
  582. // WAS LOG RECENTLY ROTATED?
  583. // Returns true if so, false if not.
  584. // Checks to see if inode number changed.
  585. //
  586. bool Configuration::WasLogRotated()
  587. {
  588. if ( !log_ino ) return(false);
  589. struct stat buf;
  590. if ( stat(errorlog.c_str(), &buf) < 0 )
  591. {
  592. fprintf(stderr, "newsd: stat(%s): %s\n",
  593. errorlog.c_str(), strerror(errno));
  594. return(false);
  595. }
  596. return(buf.st_ino != log_ino);
  597. }
  598. // Log a message...
  599. void Configuration::LogMessage(int l, const char *m, ...)
  600. {
  601. // Only log messages as needed...
  602. if (l > loglevel)
  603. return;
  604. // Format the message...
  605. va_list ap; // Argument list pointer
  606. char buffer[1024]; // Message buffer
  607. unsigned int bytes; // Size of message
  608. va_start(ap, m);
  609. bytes = vsnprintf(buffer, sizeof(buffer), m, ap);
  610. va_end(ap);
  611. // Send it to the log file or syslog...
  612. if (log)
  613. {
  614. LogLock();
  615. {
  616. // Was log recently rotated? Reopen to write to correct log
  617. if ( WasLogRotated() )
  618. { OpenLogAppend(); LogLock(); }
  619. // Automatic log rotation?
  620. if ( maxlogsize > 0 )
  621. Rotate(false); // Handle log rotations
  622. DateStampedMessage(log, buffer); // Log message
  623. }
  624. LogUnlock();
  625. }
  626. else
  627. syslog(loglevel == L_ERROR ? LOG_ERR :
  628. loglevel == L_INFO ? LOG_INFO : LOG_DEBUG, "%s", buffer);
  629. }
  630. void Configuration::LogSelf(int myloglevel)
  631. {
  632. LogMessage(myloglevel, "ErrorLog %s", ErrorLog());
  633. LogMessage(myloglevel, "HostnameLookups %s",
  634. HostnameLookups() == 0 ? "off" :
  635. HostnameLookups() == 1 ? "on" : " double");
  636. struct sockaddr_in *addr = Listen();
  637. unsigned ipaddr = ntohl(addr->sin_addr.s_addr);
  638. LogMessage(myloglevel, "Listen %u.%u.%u.%u:%d",
  639. (ipaddr >> 24) & 255, (ipaddr >> 16) & 255,
  640. (ipaddr >> 8) & 255, ipaddr & 255,
  641. ntohs(addr->sin_port));
  642. LogMessage(myloglevel, "LogLevel %s",
  643. LogLevel() == L_ERROR ? "error" :
  644. LogLevel() == L_INFO ? "info" : "debug");
  645. LogMessage(myloglevel, "MaxClients %u", MaxClients());
  646. LogMessage(myloglevel, "MaxLogSize %ld", MaxLogSize());
  647. LogMessage(myloglevel, "SendMail %s", SendMail());
  648. LogMessage(myloglevel, "ServerName %s", ServerName());
  649. LogMessage(myloglevel, "SpamFilter %s", SpamFilter());
  650. LogMessage(myloglevel, "SpoolDir %s", SpoolDir());
  651. LogMessage(myloglevel, "Timeout %u", Timeout());
  652. LogMessage(myloglevel, "User %s", User());
  653. }
  654. void Configuration::MaxLogSize(const char *val)
  655. {
  656. double number; // Number
  657. char units[255]; // Units
  658. switch (sscanf(val, "%lf%254s", &number, units))
  659. {
  660. default :
  661. fprintf(stderr, "newsd: Bad MaxLogSize value \"%s\"!\n", val);
  662. maxlogsize = 0;
  663. break;
  664. case 1 :
  665. maxlogsize = (long)number;
  666. break;
  667. case 2 :
  668. if (!strcasecmp(units, "k"))
  669. maxlogsize = (long)(number * 1024.0);
  670. else if (!strcasecmp(units, "m"))
  671. maxlogsize = (long)(number * 1024.0 * 1024.0);
  672. else if (!strcasecmp(units, "g"))
  673. maxlogsize = (long)(number * 1024.0 * 1024.0 * 1024.0);
  674. else
  675. maxlogsize = (long)number;
  676. break;
  677. }
  678. }
  679. int Configuration::lookup_user(const char *name)
  680. {
  681. struct passwd *pw = getpwnam(name);
  682. if (pw == NULL )
  683. {
  684. uid = UINT_MAX;
  685. gid = UINT_MAX;
  686. bad_user = true;
  687. return(-1);
  688. }
  689. uid = pw->pw_uid;
  690. gid = pw->pw_gid;
  691. bad_user = false;
  692. endpwent();
  693. return(0);
  694. }
  695. // Handle authentication login
  696. // Returns:
  697. // 1 on success
  698. // -1 on error, sleeps auth_sleep (if configured)
  699. //
  700. int Configuration::AuthLogin(const string& myuser, const string& mypass)
  701. {
  702. // SUCCESS
  703. if ( auth_user == myuser && auth_pass == mypass )
  704. { auth_flags = auth_protect; return(1); }
  705. // FAILURE
  706. if ( auth_sleep > 0 )
  707. sleep(auth_sleep);
  708. auth_flags = AUTH_FAIL;
  709. return(-1);
  710. }