From 3ddd56e7c5c28acb04f27bae694e41c20f1b921b Mon Sep 17 00:00:00 2001 From: Michiel Broek Date: Mon, 12 Apr 2004 11:50:34 +0000 Subject: [PATCH] Updates for mbnntp --- mbnntp/Makefile | 9 +- mbnntp/auth.c | 171 ++++++++++++++++++++++ mbnntp/auth.h | 10 ++ mbnntp/mbnntp.c | 109 +++++++++----- mbnntp/mbnntp.h | 2 + mbnntp/ttyio.c | 380 ------------------------------------------------ mbnntp/ttyio.h | 33 ----- 7 files changed, 261 insertions(+), 453 deletions(-) create mode 100644 mbnntp/auth.c create mode 100644 mbnntp/auth.h diff --git a/mbnntp/Makefile b/mbnntp/Makefile index 1f9476e6..d1f74c73 100644 --- a/mbnntp/Makefile +++ b/mbnntp/Makefile @@ -3,9 +3,9 @@ include ../Makefile.global -SRCS = mbnntp.c openport.c ttyio.c -HDRS = mbnntp.h openport.h ttyio.h -OBJS = mbnntp.o openport.o ttyio.o +SRCS = mbnntp.c openport.c ttyio.c auth.c +HDRS = mbnntp.h openport.h ttyio.h auth.h +OBJS = mbnntp.o openport.o ttyio.o auth.o LIBS += ../lib/libmbse.a ../lib/libdbase.a ../lib/libmsgbase.a OTHER = Makefile @@ -55,7 +55,8 @@ depend: # DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT # Dependencies generated by make depend -mbnntp.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/mbsedb.h openport.h ttyio.h mbnntp.h +mbnntp.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/mbsedb.h openport.h ttyio.h auth.h mbnntp.h openport.o: ../config.h ../lib/mbselib.h openport.h ttyio.o: ../config.h ../lib/mbselib.h ttyio.h +auth.o: ../config.h ../lib/mbselib.h mbnntp.h auth.h # End of generated dependencies diff --git a/mbnntp/auth.c b/mbnntp/auth.c new file mode 100644 index 00000000..d976394c --- /dev/null +++ b/mbnntp/auth.c @@ -0,0 +1,171 @@ +/***************************************************************************** + * + * $Id$ + * + ***************************************************************************** + * 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 "mbnntp.h" +#include "auth.h" + + +int authorized = FALSE; /* Authentication status */ +int got_username = FALSE; /* Did we get a username? */ +int grecno = 0; /* User record number */ +char username[9]; /* Cached username */ + +extern pid_t mypid; + + +int check_auth(char *cmd) +{ + if (authorized) + return TRUE; + + send_nntp("480 Authentication required"); + return FALSE; +} + + + +void auth_user(char *cmd) +{ + char *p; + + p = strtok(cmd, " \0"); + p = strtok(NULL, " \0"); + p = strtok(NULL, " \0"); + if (strlen(p) > 8) { + /* + * Username too long + */ + WriteError("Got a username of %d characters", sizeof(p)); + send_nntp("482 Authentication rejected"); + return; + } + memset(&username, 0, sizeof(username)); + strncpy(username, p, 8); + Syslog('n', "Cache username \"%s\"", printable(username, 0)); + send_nntp("381 More authentication information required"); + got_username = TRUE; +} + + + +void auth_pass(char *cmd) +{ + char *p, *temp; + FILE *fp; + int FoundName = FALSE; + + if (! got_username) { + WriteError("Got AUTHINFO PASS before AUTHINFO USER"); + send_nntp("482 Authentication rejected"); + return; + } + + p = strtok(cmd, " \0"); + p = strtok(NULL, " \0"); + p = strtok(NULL, " \0"); + + temp = calloc(PATH_MAX, sizeof(char)); + sprintf(temp, "%s/etc/users.data", getenv("MBSE_ROOT")); + if ((fp = fopen(temp,"r+")) == NULL) { + /* + * This should not happen + */ + WriteError("$Can't open %s", temp); + send_nntp("482 Authentication rejected"); + free(temp); + got_username = FALSE; + return; + } + free(temp); + + grecno = 0; + fread(&usrconfighdr, sizeof(usrconfighdr), 1, fp); + while (fread(&usrconfig, usrconfighdr.recsize, 1, fp) == 1) { + if (strcmp(usrconfig.Name, username) == 0) { + FoundName = TRUE; + break; + } + grecno++; + } + + if (!FoundName) { + fclose(fp); + Syslog('+', "Unknown user \"%s\", reject", username); + send_nntp("482 Authentication rejected"); + got_username = FALSE; + memset(&usrconfig, 0, sizeof(usrconfig)); + return; + } + + if (strcasecmp(usrconfig.Password, p)) { + Syslog('+', "Password error, reject user \"%s\"", username); + send_nntp("482 Authentication rejected"); + fclose(fp); + got_username = FALSE; + memset(&usrconfig, 0, sizeof(usrconfig)); + return; + } + + /* + * Update user record + */ + usrconfig.tLastLoginDate = time(NULL); /* Login date is current date */ + usrconfig.iTotalCalls++; /* Increase calls */ + + /* + * Update user record. + */ + if (fseek(fp, usrconfighdr.hdrsize + (grecno * usrconfighdr.recsize), 0) != 0) { + WriteError("Can't seek in %s/etc/users.data", getenv("MBSE_ROOT")); + } else { + fwrite(&usrconfig, sizeof(usrconfig), 1, fp); + } + fclose(fp); + + /* + * User logged in, tell it to the server. Check if a location is + * set, if Ask User location for new users is off, this field is + * empty but we have to send something to the server. + */ + if (strlen(usrconfig.sLocation)) + UserCity(mypid, usrconfig.Name, usrconfig.sLocation); + else + UserCity(mypid, usrconfig.Name, (char *)"N/A"); + + IsDoing("Logged in"); + Syslog('+', "User %s logged in", username); + authorized = TRUE; + got_username = FALSE; + send_nntp("281 Authentication accepted"); +} + + diff --git a/mbnntp/auth.h b/mbnntp/auth.h new file mode 100644 index 00000000..a7ab900f --- /dev/null +++ b/mbnntp/auth.h @@ -0,0 +1,10 @@ +#ifndef _MBAUTH_H +#define _MBAUTH_H + +/* $Id$ */ + +int check_auth(char *); /* Check user is authorized */ +void auth_user(char *); /* Auth username */ +void auth_pass(char *); /* Auth password */ + +#endif diff --git a/mbnntp/mbnntp.c b/mbnntp/mbnntp.c index 5315c249..a35a4aa3 100644 --- a/mbnntp/mbnntp.c +++ b/mbnntp/mbnntp.c @@ -34,17 +34,17 @@ #include "../lib/mbsedb.h" #include "openport.h" #include "ttyio.h" +#include "auth.h" #include "mbnntp.h" time_t t_start; time_t t_end; char *envptr = NULL; struct sockaddr_in peeraddr; +pid_t mypid; extern char *ttystat[]; - - -void send_nntp(const char *, ...); +extern int authorized; void die(int onsig) @@ -87,7 +87,7 @@ int main(int argc, char *argv[]) envptr = xstrcat(envptr, pw->pw_dir); putenv(envptr); } - + mypid = getpid(); /* * Read the global configuration data, registrate connection @@ -97,11 +97,13 @@ int main(int argc, char *argv[]) InitUser(); InitFidonet(); umask(002); + memset(&usrconfig, 0, sizeof(usrconfig)); t_start = time(NULL); InitClient(pw->pw_name, (char *)"mbnntp", CFG.location, CFG.logfile, CFG.util_loglevel, CFG.error_log, CFG.mgrlog, CFG.debuglog); Syslog(' ', "MBNNTP v%s", VERSION); + IsDoing("Loging in"); /* * Catch all the signals we can, and ignore the rest. @@ -123,7 +125,7 @@ int main(int argc, char *argv[]) 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)); - send_nntp("200 Welcome to MBNNTP v%s (posting may or may not be allowed, try your luck)", VERSION); + send_nntp("200 MBNNTP v%s server ready -- no posting allowed", VERSION); nntp(); } } @@ -136,6 +138,46 @@ int main(int argc, char *argv[]) +/* + * 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 + */ + send_nntp("400 Service discontinued"); + } + Syslog('+', "Receiver status %s", ttystat[- c]); + return c; + } + if ((c == '\r') || (c == '\n')) + return len; + else { + buf[len] = c; + len++; + buf[len] = '\0'; + } + if (len >= max) { + WriteError("Input buffer full"); + return len; + } + } + return 0; /* Not reached */ +} + + + void send_nntp(const char *format, ...) { char *out; @@ -155,7 +197,7 @@ void send_nntp(const char *format, ...) -void command_list(void) +void command_list(char *cmd) { send_nntp("215 List of newsgroups follows"); @@ -167,36 +209,14 @@ void command_list(void) void nntp(void) { char buf[4096]; - int len, c; + int len; while (TRUE) { - len = 0; - memset(&buf, 0, sizeof(buf)); - while (TRUE) { - c = tty_getc(180); - if (c <= 0) { - if (c == -2) { - /* - * Timeout - */ - send_nntp("500 Timeout"); - } - Syslog('+', "Receiver status %s", ttystat[- c]); - return; - } - if ((c == '\r') || (c == '\n')) - break; - else { - buf[len] = c; - len++; - buf[len] = '\0'; - } - if (len == sizeof(buf)) { - WriteError("Input buffer full"); - break; - } - } - if (strlen(buf) == 0) + + len = get_nntp(buf, sizeof(buf) -1); + if (len < 0) + return; + if (len == 0) continue; /* @@ -206,8 +226,13 @@ void nntp(void) if (strncasecmp(buf, "QUIT", 4) == 0) { send_nntp("205 Goodbye\r\n"); return; + } else if (strncasecmp(buf, "AUTHINFO USER", 13) == 0) { + auth_user(buf); + } else if (strncasecmp(buf, "AUTHINFO PASS", 13) == 0) { + auth_pass(buf); } else if (strncasecmp(buf, "LIST", 4) == 0) { - command_list(); + if (check_auth(buf)) + command_list(buf); } else if (strncasecmp(buf, "IHAVE", 5) == 0) { send_nntp("435 Article not wanted - do not send it"); } else if (strncasecmp(buf, "NEWGROUPS", 9) == 0) { @@ -217,11 +242,23 @@ void nntp(void) send_nntp("230 Warning: NEWNEWS not implemented, returning empty list"); send_nntp("."); } else if (strncasecmp(buf, "SLAVE", 5) == 0) { - send_nntp("202 Slave status noted (but ignored)"); + send_nntp("202 Slave status noted"); + } else if (strncasecmp(buf, "MODE READER", 11) == 0) { + if (authorized) + send_nntp("200 Server ready, posting allowed"); + else + send_nntp("201 Server ready, no posting allowed"); } else if (strncasecmp(buf, "HELP", 4) == 0) { send_nntp("100 Help text follows"); send_nntp("Recognized commands:"); + send_nntp(""); + send_nntp("AUTHINFO"); + 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)"); send_nntp("QUIT"); + send_nntp("SLAVE (has no effect)"); send_nntp(""); send_nntp("MBNNTP supports most of RFC-977 and also has support for AUTHINFO and"); send_nntp("limited XOVER support (RFC-2980)"); diff --git a/mbnntp/mbnntp.h b/mbnntp/mbnntp.h index f05e5919..3396fe80 100644 --- a/mbnntp/mbnntp.h +++ b/mbnntp/mbnntp.h @@ -3,6 +3,8 @@ /* $Id$ */ +void send_nntp(const char *, ...); +int get_nntp(char *, int); void nntp(void); #endif diff --git a/mbnntp/ttyio.c b/mbnntp/ttyio.c index b46c3f6c..85c6f3ee 100644 --- a/mbnntp/ttyio.c +++ b/mbnntp/ttyio.c @@ -55,101 +55,6 @@ char *ttystat[]= {(char *)"Ok", (char *)"Empty", (char *)"UnCompress"}; -int tty_resettimer(int tno); -void tty_resettimers(void); -int tty_settimer(int,int); -int tty_expired(int); -int tty_running(int); - -#define RESETTIMER(x) tty_resettimer(x) -#define RESETTIMERS() tty_resettimers() -#define SETTIMER(x,y) tty_settimer(x,y) -#define EXPIRED(x) tty_expired(x) -#define RUNNING(x) tty_running(x) - - - -/* - * timer functions - */ - -int tty_resettimer(int tno) -{ - if (tno >= NUMTIMERS) { - errno = EINVAL; - WriteError("ttyio: invalid timer No for resettimer(%d)", tno); - return -1; - } - - timer[tno] = (time_t) 0; - return 0; -} - - - -void tty_resettimers(void) -{ - int i; - - for (i = 0; i < NUMTIMERS; i++) - timer[i] = (time_t)0; -} - - - -int tty_settimer(int tno, int interval) -{ - if (tno >= NUMTIMERS) { - errno = EINVAL; - WriteError("ttyio: invalid timer No for settimer(%d)", tno); - return -1; - } - - timer[tno]=time((time_t*)NULL)+interval; - return 0; -} - - - -int tty_expired(int tno) -{ - time_t now; - - if (tno >= NUMTIMERS) { - errno = EINVAL; - WriteError("ttyio: invalid timer No for expired(%d)", tno); - return -1; - } - - /* - * Check if timer is running - */ - if (timer[tno] == (time_t) 0) - return 0; - - now = time(NULL); - return (now >= timer[tno]); -} - - - -int tty_running(int tno) -{ - if (tno > NUMTIMERS) { - errno = EINVAL; - WriteError("ttyio: invalid timer for tty_running(%d)", tno); - return -1; - } - - /* - * check if timer is running - */ - if (timer[tno] == (time_t) 0) - return 0; - else - return 1; -} - /* @@ -264,141 +169,6 @@ int tty_write(char *buf, int size) -/* public r/w functions */ - -/* - * Check if there is data available on stdin. - */ -int tty_check(void) -{ - int rc; - - // try to read available (timeout = 0) data if we have no data in - // our buffer - - if (!left) { - rc = tty_read(buffer, TT_BUFSIZ, 0); - if (rc > 0) { - left = rc; - } - } - - return (left > 0); -} - - - -int tty_putcheck(int size) -{ - fd_set set; - struct timeval timeout; - - /* - * Initialize the file descriptor set. - */ - FD_ZERO(&set); - FD_SET(1, &set); - - /* - * Initialize the timeout data structure. - */ - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - /* - * `select' returns 0 if timeout, 1 if input available, -1 if error. - */ - return select(FD_SETSIZE, NULL, &set, NULL, &timeout); -} - - - -int tty_waitputget(int tot) -{ - int i, rc; - time_t timeout, now; - fd_set readfds, writefds, exceptfds; - struct timeval seltimer; - - tty_status=0; - now = time(NULL); - timeout=(time_t)300; /* maximum of 5 minutes */ - - for (i = 0; i < NUMTIMERS; i++) { - if (timer[i]) { - if (now >= timer[i]) { - tty_status = STAT_TIMEOUT; - WriteError("tty_waitputget: timer %d already expired, return",i); - return -tty_status; - } else { - if (timeout > (timer[i]-now)) - timeout = timer[i]-now; - } - } - } - if ((tot != -1) && (timeout > tot)) - timeout=tot; - Syslog('t', "tty_waitputget: timeout=%d",timeout); - - /* - * Initialize the file descriptor set. - */ - FD_ZERO(&readfds); - FD_ZERO(&writefds); - FD_ZERO(&exceptfds); - - FD_SET(0, &readfds); - FD_SET(1, &writefds); - FD_SET(0, &exceptfds); - FD_SET(1, &exceptfds); - - /* - * Initialize the timeout data structure. - */ - seltimer.tv_sec = timeout; - seltimer.tv_usec = 0; - - /* - * `select' returns 0 if timeout, 1 if input available, -1 if error. - */ - rc = select(FD_SETSIZE, &readfds, &writefds, &exceptfds, &seltimer); - - if (rc < 0) { - if (hanged_up) { - tty_status=STAT_HANGUP; - WriteError("tty_waitputget: hanged_up flag"); - } else { - WriteError("$tty_waitputget: select failed"); - tty_status=STAT_ERROR; - } - } else if (rc == 0) { - tty_status=STAT_TIMEOUT; - } else { - /* rc > 0 */ - if ((FD_ISSET(0,&exceptfds)) || (FD_ISSET(1,&exceptfds))) { - WriteError("$tty_waitputget: exeption error"); - tty_status=STAT_ERROR; - } - } - - if (tty_status) { - Syslog('t', "tty_waitputget: return after select status %s",ttystat[tty_status]); - return -tty_status; - } - - rc = 0; - - if (FD_ISSET(0,&readfds)) - rc |= 1; - - if (FD_ISSET(1,&writefds)) - rc |= 2; - - return rc; -} - - - void tty_flushin(void) { tcflush(0, TCIFLUSH); @@ -412,27 +182,6 @@ void tty_flushout(void) } - -int tty_ungetc(int c) -{ - if (next == buffer) { - if (left >= TT_BUFSIZ) { - return -1; - } - - next = buffer + TT_BUFSIZ - left; - memcpy(next, buffer, left); - } - - next--; - *next = c; - left++; - - return 0; -} - - - int tty_getc(int tot) { if (!left) { @@ -450,138 +199,9 @@ int tty_getc(int tot) } - -int tty_get(char *buf, int size, int tot) -{ - int result=0; - - if (left >= size) { - memcpy(buf,next,size); - next += size; - left -= size; - return 0; - } - - if (left > 0) { - memcpy(buf,next,left); - buf += left; - next += left; - size -= left; - left=0; - } - - while ((result=tty_read(buf,size,tot)) > 0) { - buf += result; - size -= result; - } - - return result; -} - - - -int tty_putc(int c) -{ - char buf = c; - - return tty_write(&buf,1); -} - - - int tty_put(char *buf, int size) { return tty_write(buf,size); } - -int tty_putget(char **obuf, int *osize, char **ibuf, int *isize) -{ - time_t timeout, now; - int i, rc; - fd_set readfds, writefds, exceptfds; - struct timeval seltimer; - - tty_status = 0; - now = time(NULL); - timeout = (time_t)300; /* maximum of 5 minutes */ - - for (i = 0; i < NUMTIMERS; i++) { - if (timer[i]) { - if (now >= timer[i]) { - tty_status = STAT_TIMEOUT; - WriteError("tty_putget: timer %d already expired, return",i); - return -tty_status; - } else { - if (timeout > (timer[i]-now)) - timeout=timer[i]-now; - } - } - } - - Syslog('t', "tty_putget: timeout=%d",timeout); - - FD_ZERO(&readfds); - FD_ZERO(&writefds); - FD_ZERO(&exceptfds); - FD_SET(0,&readfds); - FD_SET(1,&writefds); - FD_SET(0,&exceptfds); - FD_SET(1,&exceptfds); - seltimer.tv_sec=timeout; - seltimer.tv_usec=0; - - rc=select(2,&readfds,&writefds,&exceptfds,&seltimer); - if (rc < 0) { - if (hanged_up) { - tty_status=STAT_HANGUP; - WriteError("tty_putget: hanged_up flag"); - } else { - WriteError("$tty_putget: select failed"); - tty_status=STAT_ERROR; - } - } else if (rc == 0) { - tty_status=STAT_TIMEOUT; - } else { - /* rc > 0 */ - if ((FD_ISSET(0,&exceptfds)) || (FD_ISSET(1,&exceptfds))) { - WriteError("$tty_putget: exeption error"); - tty_status=STAT_ERROR; - } - } - - if (tty_status) { - Syslog('t', "tty_putget: return after select status %s",ttystat[tty_status]); - return -tty_status; - } - - if (FD_ISSET(0,&readfds) && *isize) { - rc = read(0, *ibuf, *isize); - if (rc < 0) { - WriteError("$tty_putget: read failed"); - tty_status=STAT_ERROR; - } else { - (*ibuf)+=rc; - (*isize)-=rc; - } - } - - if (FD_ISSET(1,&writefds) && *osize) { - rc=write(1, *obuf, *osize); - if (rc < 0) { - WriteError("$tty_putget: write failed"); - tty_status=STAT_ERROR; - } else { - (*obuf)+=rc; - (*osize)-=rc; - } - } - - if (tty_status) - return -tty_status; - else - return ((*isize == 0) | ((*osize == 0) << 1)); -} - - diff --git a/mbnntp/ttyio.h b/mbnntp/ttyio.h index 1f0ac7e7..845fda10 100644 --- a/mbnntp/ttyio.h +++ b/mbnntp/ttyio.h @@ -3,28 +3,11 @@ /* $Id$ */ -#define TIMERNO_BRAIN 0 /* BRAIN timerno */ -#define TIMERNO_RX 1 /* Receiver timerno */ -#define TIMERNO_TX 2 /* Transmitter timerno */ - -#define RESETTIMER(x) tty_resettimer(x) -#define RESETTIMERS() tty_resettimers() -#define SETTIMER(x,y) tty_settimer(x,y) -#define EXPIRED(x) tty_expired(x) -#define RUNNING(x) tty_running(x) - -#define TCHECK() tty_check() -#define PUTCHECK(x) tty_putcheck(x) -#define WAITPUTGET(x) tty_waitputget(x) #define FLUSHOUT() tty_flushout() #define FLUSHIN() tty_flushin() -#define PUTCHAR(x) tty_putc(x) #define PUT(x,y) tty_put(x,y) #define PUTSTR(x) tty_put(x,strlen(x)) #define GETCHAR(x) tty_getc(x) -#define UNGETCHAR(x) tty_ungetc(x) -#define GET(x,y,z) tty_get(x,y,z) -#define PUTGET(a,b,x,y) tty_putget(a,b,x,y) #define STATUS tty_status #define STAT_SUCCESS 0 @@ -42,27 +25,11 @@ #define HANGUP (-STAT_HANGUP) #define EMPTY (-STAT_EMPTY) -#define GET_COMPLETE(x) (x & 1) -#define PUT_COMPLETE(x) (x & 2) - extern int tty_status; -extern int tty_resettimer(int tno); -extern void tty_resettimers(void); -extern int tty_settimer(int,int); -extern int tty_expired(int); -extern int tty_running(int); -extern int tty_check(void); -extern int tty_waitputget(int); -extern int tty_ungetc(int); extern int tty_getc(int); -extern int tty_get(char*,int,int); -extern int tty_putcheck(int); -extern int tty_putc(int); extern int tty_put(char*,int); -extern int tty_putget(char**,int*,char**,int*); extern void tty_flushout(void); extern void tty_flushin(void); -extern void sendbrk(void); #endif