This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-mbse/mbnntp/mbnntp.c

339 lines
8.4 KiB
C
Raw Normal View History

2004-04-11 19:38:51 +00:00
/*****************************************************************************
*
* $Id$
* Purpose ...............: MBSE NNTP Server
*
*****************************************************************************
* Copyright (C) 1997-2004
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include "../lib/mbselib.h"
#include "../lib/users.h"
#include "../lib/mbsedb.h"
2004-04-13 18:25:50 +00:00
#include "../lib/msg.h"
2004-04-11 19:38:51 +00:00
#include "openport.h"
#include "ttyio.h"
2004-04-12 11:50:34 +00:00
#include "auth.h"
2004-04-12 13:01:51 +00:00
#include "commands.h"
2004-04-11 19:38:51 +00:00
#include "mbnntp.h"
2004-04-11 21:35:25 +00:00
time_t t_start;
time_t t_end;
char *envptr = NULL;
2004-04-11 19:38:51 +00:00
struct sockaddr_in peeraddr;
2004-04-12 11:50:34 +00:00
pid_t mypid;
2004-04-13 18:25:50 +00:00
unsigned long rcvdbytes = 0L;
unsigned long sentbytes = 0L;
2004-05-11 12:25:34 +00:00
int do_mailout = FALSE;
2004-04-11 19:38:51 +00:00
2004-04-11 21:35:25 +00:00
extern char *ttystat[];
2004-04-12 11:50:34 +00:00
extern int authorized;
2004-04-11 21:35:25 +00:00
2004-04-11 19:38:51 +00:00
void die(int onsig)
{
signal(onsig, SIG_IGN);
CloseDupes();
2004-04-13 18:25:50 +00:00
Msg_Close();
2004-04-11 19:38:51 +00:00
if (onsig) {
if (onsig <= NSIG)
WriteError("Terminated on signal %d (%s)", onsig, SigName[onsig]);
else
WriteError("Terminated with error %d", onsig);
}
2004-05-11 12:25:34 +00:00
if (do_mailout)
CreateSema((char *)"mailout");
2004-04-11 19:38:51 +00:00
t_end = time(NULL);
2004-04-13 18:25:50 +00:00
Syslog('+', "Send [%6lu] Received [%6lu]", sentbytes, rcvdbytes);
2004-04-11 19:38:51 +00:00
Syslog(' ', "MBNNTP finished in %s", t_elapsed(t_start, t_end));
if (envptr)
free(envptr);
ExitClient(onsig);
}
2004-04-15 21:29:59 +00:00
/*
* Check if the system is available.
*/
int check_free(void);
int check_free(void)
{
char buf[128];
strcpy(buf, SockR("SBBS:0;"));
if (strncmp(buf, "100:2,1", 7) == 0) {
Syslog('+', "The system is closed");
return FALSE;
}
return TRUE;
}
2004-04-11 19:38:51 +00:00
int main(int argc, char *argv[])
{
struct passwd *pw;
int i, rc, addrlen = sizeof(struct sockaddr_in);
/*
* The next trick is to supply a fake environment variable
* MBSE_ROOT because this program is started from inetd.
* This will setup the variable so InitConfig() will work.
* The /etc/passwd must point to the correct homedirectory.
*/
pw = getpwuid(geteuid());
if (getenv("MBSE_ROOT") == NULL) {
envptr = xstrcpy((char *)"MBSE_ROOT=");
envptr = xstrcat(envptr, pw->pw_dir);
putenv(envptr);
}
2004-04-12 11:50:34 +00:00
mypid = getpid();
2004-04-11 19:38:51 +00:00
/*
* Read the global configuration data, registrate connection
*/
InitConfig();
InitMsgs();
InitUser();
InitFidonet();
2004-05-10 19:52:41 +00:00
InitNode();
2004-04-11 19:38:51 +00:00
umask(002);
2004-04-12 11:50:34 +00:00
memset(&usrconfig, 0, sizeof(usrconfig));
2004-04-11 19:38:51 +00:00
t_start = time(NULL);
2004-04-11 21:35:25 +00:00
InitClient(pw->pw_name, (char *)"mbnntp", CFG.location, CFG.logfile,
2004-04-11 19:38:51 +00:00
CFG.util_loglevel, CFG.error_log, CFG.mgrlog, CFG.debuglog);
Syslog(' ', "MBNNTP v%s", VERSION);
2004-04-12 11:50:34 +00:00
IsDoing("Loging in");
2004-04-11 19:38:51 +00:00
/*
* Catch all the signals we can, and ignore the rest.
*/
for(i = 0; i < NSIG; i++) {
if ((i == SIGINT) || (i == SIGBUS) || (i == SIGILL) || (i == SIGSEGV) || (i == SIGTERM))
signal(i, (void (*))die);
else if (i == SIGCHLD)
signal(i, SIG_DFL);
else if ((i != SIGKILL) && (i != SIGSTOP))
signal(i, SIG_IGN);
}
if ((rc = rawport()) != 0)
WriteError("Unable to set raw mode");
else {
if (getpeername(0,(struct sockaddr*)&peeraddr,&addrlen) == 0) {
Syslog('s', "TCP connection: len=%d, family=%hd, port=%hu, addr=%s",
addrlen,peeraddr.sin_family, peeraddr.sin_port, inet_ntoa(peeraddr.sin_addr));
Syslog('+', "Incoming connection from %s", inet_ntoa(peeraddr.sin_addr));
2004-04-15 21:29:59 +00:00
if (! check_free()) {
send_nntp("400 Server closed");
} else {
send_nntp("200 MBNNTP v%s server ready -- posting allowed", VERSION);
nntp();
}
2004-04-11 19:38:51 +00:00
}
}
cookedport();
die(0);
return 0;
}
2004-04-11 21:35:25 +00:00
2004-04-12 11:50:34 +00:00
/*
* Get command from the client.
* return < 0: error
* return >= 0: size of buffer
*/
int get_nntp(char *buf, int max)
{
int c, len;
len = 0;
memset(buf, 0, sizeof(buf));
while (TRUE) {
c = tty_getc(180);
if (c <= 0) {
if (c == -2) {
/*
* Timeout
*/
2004-04-15 21:29:59 +00:00
send_nntp("400 Service discontinued, timeout");
2004-04-12 11:50:34 +00:00
}
Syslog('+', "Receiver status %s", ttystat[- c]);
return c;
}
2004-04-13 18:25:50 +00:00
if ((c == '\r') || (c == '\n')) {
rcvdbytes += (len + 1);
2004-04-12 11:50:34 +00:00
return len;
2004-04-13 18:25:50 +00:00
}
2004-04-12 11:50:34 +00:00
else {
buf[len] = c;
len++;
buf[len] = '\0';
}
if (len >= max) {
WriteError("Input buffer full");
return len;
}
}
2004-04-13 18:25:50 +00:00
return 0; /* Not reached */
2004-04-12 11:50:34 +00:00
}
2004-04-11 21:35:25 +00:00
void send_nntp(const char *format, ...)
{
char *out;
va_list va_ptr;
out = calloc(4096, sizeof(char));
va_start(va_ptr, format);
vsprintf(out, format, va_ptr);
va_end(va_ptr);
Syslog('n', "> \"%s\"", printable(out, 0));
PUTSTR(out);
PUTSTR((char *)"\r\n");
2004-04-13 18:25:50 +00:00
FLUSHOUT();
sentbytes += (strlen(out) + 2);
2004-04-11 21:35:25 +00:00
free(out);
}
void nntp(void)
{
char buf[4096];
2004-04-12 11:50:34 +00:00
int len;
2004-04-11 21:35:25 +00:00
while (TRUE) {
2004-04-12 11:50:34 +00:00
2004-04-13 18:25:50 +00:00
IsDoing("Waiting");
2004-04-12 11:50:34 +00:00
len = get_nntp(buf, sizeof(buf) -1);
if (len < 0)
return;
if (len == 0)
2004-04-11 21:35:25 +00:00
continue;
2004-04-13 18:25:50 +00:00
Syslog('n', "< \"%s\"", printable(buf, 0));
2004-04-15 21:29:59 +00:00
if (! check_free()) {
send_nntp("400 server closed");
return;
}
2004-04-13 18:25:50 +00:00
2004-04-11 21:35:25 +00:00
/*
* Process received command
*/
if (strncasecmp(buf, "QUIT", 4) == 0) {
send_nntp("205 Goodbye\r\n");
return;
2004-04-12 11:50:34 +00:00
} else if (strncasecmp(buf, "AUTHINFO USER", 13) == 0) {
auth_user(buf);
} else if (strncasecmp(buf, "AUTHINFO PASS", 13) == 0) {
auth_pass(buf);
2004-04-13 18:25:50 +00:00
} else if (strncasecmp(buf, "ARTICLE", 7) == 0) {
if (check_auth(buf))
command_abhs(buf);
} else if (strncasecmp(buf, "BODY", 4) == 0) {
if (check_auth(buf))
command_abhs(buf);
2004-04-11 21:35:25 +00:00
} else if (strncasecmp(buf, "LIST", 4) == 0) {
2004-04-12 11:50:34 +00:00
if (check_auth(buf))
command_list(buf);
2004-04-13 18:25:50 +00:00
} else if (strncasecmp(buf, "GROUP", 5) == 0) {
if (check_auth(buf))
command_group(buf);
} else if (strncasecmp(buf, "HEAD", 4) == 0) {
if (check_auth(buf))
command_abhs(buf);
2004-05-10 19:52:41 +00:00
} else if (strncasecmp(buf, "POST", 4) == 0) {
2004-05-10 13:44:21 +00:00
if (check_auth(buf))
command_post(buf);
2004-04-11 21:35:25 +00:00
} else if (strncasecmp(buf, "IHAVE", 5) == 0) {
send_nntp("435 Article not wanted - do not send it");
} else if (strncasecmp(buf, "NEWGROUPS", 9) == 0) {
send_nntp("235 Warning: NEWGROUPS not implemented, returning empty list");
send_nntp(".");
} else if (strncasecmp(buf, "NEWNEWS", 7) == 0) {
send_nntp("230 Warning: NEWNEWS not implemented, returning empty list");
send_nntp(".");
} else if (strncasecmp(buf, "SLAVE", 5) == 0) {
2004-04-12 11:50:34 +00:00
send_nntp("202 Slave status noted");
2004-04-13 18:25:50 +00:00
} else if (strncasecmp(buf, "STAT", 4) == 0) {
if (check_auth(buf))
command_abhs(buf);
2004-04-12 11:50:34 +00:00
} else if (strncasecmp(buf, "MODE READER", 11) == 0) {
2004-04-14 19:45:43 +00:00
if (check_auth(buf)) {
if (authorized)
send_nntp("200 Server ready, posting allowed");
else
send_nntp("201 Server ready, no posting allowed");
}
2004-04-13 18:25:50 +00:00
} else if (strncasecmp(buf, "XOVER", 5) == 0) {
if (check_auth(buf))
command_xover(buf);
2004-04-11 21:35:25 +00:00
} else if (strncasecmp(buf, "HELP", 4) == 0) {
send_nntp("100 Help text follows");
send_nntp("Recognized commands:");
2004-04-12 11:50:34 +00:00
send_nntp("");
2004-04-13 18:25:50 +00:00
send_nntp("ARTICLE");
2004-04-12 11:50:34 +00:00
send_nntp("AUTHINFO");
2004-04-13 18:25:50 +00:00
send_nntp("BODY");
send_nntp("GROUP");
send_nntp("HEAD");
2004-04-12 11:50:34 +00:00
send_nntp("IHAVE (not implemented, messages are always rejected)");
send_nntp("LIST");
send_nntp("NEWGROUPS (not implemented, always returns an empty list)");
send_nntp("NEWNEWS (not implemented, always returns an empty list)");
2004-05-10 13:44:21 +00:00
send_nntp("POST");
2004-04-11 21:35:25 +00:00
send_nntp("QUIT");
2004-04-12 11:50:34 +00:00
send_nntp("SLAVE (has no effect)");
2004-04-13 18:25:50 +00:00
send_nntp("STAT");
send_nntp("XOVER");
2004-04-11 21:35:25 +00:00
send_nntp("");
send_nntp("MBNNTP supports most of RFC-977 and also has support for AUTHINFO and");
send_nntp("limited XOVER support (RFC-2980)");
send_nntp(".");
} else {
send_nntp("500 Unknown command");
}
}
}