Added incoming telnet proxy

This commit is contained in:
Michiel Broek
2003-11-22 21:42:44 +00:00
parent 202719cb45
commit 24cd311b9c
23 changed files with 660 additions and 22 deletions

View File

@@ -1 +1 @@
filelist mbcico mbout
filelist mbcico mbout mbtelnetd

View File

@@ -12,7 +12,7 @@ SRCS = zmmisc.c zmrle.c zmrecv.c zmsend.c binkp.c md5b.c \
filetime.c ftsc.c atoul.c portsel.c \
ttyio.c lutil.c scanout.c emsi.c ulock.c \
callstat.c session.c call.c mbcico.c \
outstat.c nlinfo.c mbout.c
outstat.c nlinfo.c mbout.c mbtelnetd.c
HDRS = zmodem.h binkp.h config.h statetbl.h md5b.h \
xmsend.h xmrecv.h m7recv.h m7send.h hydra.h inbound.h \
answer.h chat.h dial.h dietifna.h emsidat.h filelist.h \
@@ -21,7 +21,7 @@ HDRS = zmodem.h binkp.h config.h statetbl.h md5b.h \
filetime.h ftsc.h atoul.h portsel.h \
ttyio.h lutil.h scanout.h emsi.h ulock.h \
callstat.h session.h call.h mbcico.h \
outstat.h nlinfo.h
outstat.h nlinfo.h mbtelnetd.h
MBCICO_OBJS = zmmisc.o zmrle.o zmrecv.o zmsend.o binkp.o md5b.o \
xmsend.o xmrecv.o m7recv.o m7send.o hydra.o inbound.o \
answer.o chat.o dial.o dietifna.o emsidat.o filelist.o \
@@ -31,10 +31,11 @@ MBCICO_OBJS = zmmisc.o zmrle.o zmrecv.o zmsend.o binkp.o md5b.o \
ttyio.o lutil.o scanout.o emsi.o ulock.o \
callstat.o session.o call.o mbcico.o
MBOUT_OBJS = outstat.o nlinfo.o mbout.o scanout.o callstat.o
MBTEL_OBJS = mbtelnetd.o
LIBS += ../lib/libclcomm.a ../lib/libcommon.a \
../lib/libmsgbase.a ../lib/libdbase.a ../lib/libnodelist.a
OTHER = Makefile README
TARGET = mbcico mbout
TARGET = mbcico mbout mbtelnetd
#############################################################################
@@ -47,8 +48,9 @@ clean:
rm -f ${TARGET} *.o *.h~ *.c~ core filelist Makefile.bak
install: all
${INSTALL} -c -s -g ${GROUP} -o ${OWNER} -m 4751 mbcico ${BINDIR}
${INSTALL} -c -s -g ${GROUP} -o ${OWNER} -m 0755 mbout ${BINDIR}
${INSTALL} -c -s -g ${GROUP} -o ${OWNER} -m 4751 mbcico ${BINDIR}
${INSTALL} -c -s -g ${GROUP} -o ${OWNER} -m 0755 mbout ${BINDIR}
${INSTALL} -c -s -g ${GROUP} -o ${OWNER} -m 0755 mbtelnetd ${BINDIR}
mbcico: ${MBCICO_OBJS} ${LIBS}
${CC} -o mbcico ${MBCICO_OBJS} ${LIBS}
@@ -58,6 +60,10 @@ mbout: ${MBOUT_OBJS} ${LIBS}
${CC} -o mbout ${MBOUT_OBJS} ${LIBS}
strip mbout
mbtelnetd: ${MBTEL_OBJS} ${LIBS}
${CC} -o mbtelnetd ${MBTEL_OBJS} ${LIBS}
strip mbtelnetd
filelist: Makefile
BASE=`pwd`; \
BASE=`basename $${BASE}`; \
@@ -126,10 +132,11 @@ scanout.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/reco
emsi.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/nodelist.h ../lib/dbnode.h ../lib/clcomm.h ../lib/mberrors.h ttyio.h session.h statetbl.h config.h emsi.h emsidat.h hydra.h rdoptions.h tcp.h wazoo.h inbound.h
ulock.o: ../config.h ../lib/libs.h ../lib/clcomm.h
callstat.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/clcomm.h ../lib/common.h callstat.h
session.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/nodelist.h ../lib/mberrors.h ttyio.h statetbl.h emsi.h ftsc.h session.h yoohoo.h mbcico.h binkp.h callstat.h inbound.h
session.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/nodelist.h ../lib/mberrors.h ttyio.h statetbl.h emsi.h ftsc.h session.h yoohoo.h mbcico.h binkp.h callstat.h inbound.h opentcp.h
call.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/nodelist.h ../lib/clcomm.h ../lib/dbnode.h ../lib/mberrors.h session.h callstat.h call.h config.h dial.h lutil.h portsel.h openport.h opentcp.h rdoptions.h inbound.h
mbcico.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/nodelist.h ../lib/clcomm.h ../lib/dbcfg.h ../lib/dbnode.h ../lib/dbftn.h ../lib/mberrors.h config.h answer.h call.h lutil.h mbcico.h session.h
outstat.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/nodelist.h ../lib/clcomm.h ../lib/dbcfg.h ../lib/dbnode.h ../lib/dbftn.h ../lib/mberrors.h scanout.h callstat.h outstat.h
nlinfo.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/common.h ../lib/nodelist.h ../lib/clcomm.h nlinfo.h
mbout.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/nodelist.h ../lib/clcomm.h ../lib/dbcfg.h ../lib/dbnode.h ../lib/dbftn.h ../lib/mberrors.h outstat.h nlinfo.h
mbtelnetd.o: ../config.h ../lib/libs.h ../lib/structs.h ../lib/users.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/dbcfg.h ../lib/mberrors.h mbtelnetd.h
# End of generated dependencies

View File

@@ -175,6 +175,10 @@ int call(faddr *addr)
tcp_mode = TCPMODE_IBN;
} else if (strcmp(protocol, "fido") == 0) {
tcp_mode = TCPMODE_IFC;
#ifdef USE_TELNET
} else if (strcmp(protocol, "telnet") == 0) {
tcp_mode = TCPMODE_ITN;
#endif
} else {
Syslog('+', "No common TCP/IP protocols for node %s", nlent->name);
free(inetaddr);

View File

@@ -65,6 +65,7 @@ unsigned long sentbytes = 0;
unsigned long rcvdbytes = 0;
int tcp_mode = TCPMODE_NONE;
int Loaded = FALSE;
int telnet = FALSE;
extern char *myname;
@@ -85,7 +86,11 @@ void usage(void)
fprintf(stderr,"-a<inetaddr> <node>\n");
fprintf(stderr,"-n<phone> forced phone number\n");
fprintf(stderr,"-l<ttydevice> forced tty device\n");
#ifdef USE_TELNET
fprintf(stderr,"-t<tcpmode> must be one of ifc|itn|ibn, forces TCP/IP\n");
#else
fprintf(stderr,"-t<tcpmode> must be one of ifc|ibn, forces TCP/IP\n");
#endif
fprintf(stderr,"-a<inetaddr> supply internet hostname if not in nodelist\n");
fprintf(stderr," <node> should be in domain form, e.g. f11.n22.z3\n");
fprintf(stderr," (this implies master mode)\n");
@@ -246,6 +251,10 @@ int main(int argc, char *argv[])
} else if (strncmp(p, "ibn", 3) == 0) {
tcp_mode = TCPMODE_IBN;
protocol = xstrcpy((char *)"binkp");
} else if (strncmp(p, "itn", 3) == 0) {
tcp_mode = TCPMODE_ITN;
protocol = xstrcpy((char *)"tfido");
telnet = TRUE;
} else {
usage();
die(MBERR_COMMANDLINE);
@@ -355,6 +364,11 @@ int main(int argc, char *argv[])
if (rc > maxrc)
maxrc=rc;
} else {
if (telnet) {
WriteError("Incoming telnet call is not supported anymore");
WriteError("Install mbtelnetd to handle telnet inbound traffic");
die(MBERR_COMMANDLINE);
}
/* slave */
if (!answermode && tcp_mode == TCPMODE_IBN)
answermode = xstrcpy((char *)"ibn");

390
mbcico/mbtelnetd.c Normal file
View File

@@ -0,0 +1,390 @@
/*****************************************************************************
*
* $Id$
* Purpose ...............: Fidonet telnet proxy
*
*****************************************************************************
* Copyright (C) 1997-2003
*
* 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.
*****************************************************************************/
/*
Simple proxy daemon for ifcico to work with SIO/VMODEM.
========================================================
Written by: Vadim Zaliva, lord@crocodile.kiev.ua, 2:463/80
This software is provided ``as is'' without express or implied warranty.
Feel free to distribute it.
Feel free to contact me with improovments request
and bug reports.
Some parts of this code are taken from
1. serge terekhov, 2:5000/13@fidonet path for ifmail
2. Vadim Kurland, vadim@gu.kiev.ua transl daemon.
Thanks them.
*/
#include "../config.h"
#include "../lib/libs.h"
#include "../lib/structs.h"
#include "../lib/users.h"
#include "../lib/records.h"
#include "../lib/common.h"
#include "../lib/clcomm.h"
#include "../lib/dbcfg.h"
#include "../lib/mberrors.h"
#include "mbtelnetd.h"
#define MBT_BUFSIZ 8192
#define MBT_TIMEOUT 3600
void die(int);
int init_telnet(void);
void answer(int, int);
int read0(char *, int);
int write1(char *, int);
void com_gw(int);
#define WILL 251
#define WONT 252
#define DO 253
#define DONT 254
#define IAC 255
#define TN_TRANSMIT_BINARY 0
#define TN_ECHO 1
#define TN_SUPPRESS_GA 3
static int tellen;
char *envptr = NULL;
time_t t_start, t_end;
void die(int onsig)
{
signal(onsig, SIG_IGN);
if (onsig) {
if (onsig <= NSIG)
WriteError("Terminated on signal %d (%s)", onsig, SigName[onsig]);
else
Syslog('+', "Terminated with error %d", onsig);
}
t_end = time(NULL);
Syslog(' ', "MBTELNETD finished in %s", t_elapsed(t_start, t_end));
if (envptr)
free(envptr);
ExitClient(onsig);
}
int main(int ac, char **av)
{
struct sockaddr_in peeraddr;
int addrlen = sizeof(struct sockaddr_in);
char *remote_name = NULL;
char *remote_port = NULL;
int s; /* socket to remote*/
int i;
struct hostent *hp;
struct servent *sp;
struct sockaddr_in server;
char *tmp = NULL;
struct passwd *pw;
/*
* The next trick is to supply a fake environment variable
* MBSE_ROOT in case we are started from inetd or mgetty,
* this will setup the variable so InitConfig() will work.
* The /etc/passwd must point to the correct homedirectory.
*/
pw = getpwuid(getuid());
if (getenv("MBSE_ROOT") == NULL) {
envptr = xstrcpy((char *)"MBSE_ROOT=");
envptr = xstrcat(envptr, pw->pw_dir);
putenv(envptr);
}
InitConfig();
t_start = time(NULL);
InitClient(pw->pw_name, (char *)"mbtelnetd", CFG.location, CFG.logfile,
CFG.util_loglevel, CFG.error_log, CFG.mgrlog, CFG.debuglog);
Syslog(' ', " ");
Syslog(' ', "MBTELNETDv%s", VERSION);
/*
* Catch all signals we can, and ignore the rest.
*/
for (i = 0; i < NSIG; i++) {
if ((i == SIGINT) || (i == SIGBUS) || (i == SIGILL) || (i == SIGSEGV) || (i == SIGTERM) || (i == SIGKILL)) {
signal(i, (void (*))die);
} else {
signal(i, SIG_IGN);
}
}
remote_name = xstrcpy((char *)"localhost");
remote_port = xstrcpy((char *)"fido");
if (getpeername(0,(struct sockaddr*)&peeraddr,&addrlen) == 0) {
tmp = strdup(inet_ntoa(peeraddr.sin_addr));
Syslog('+', "Incoming TCP connection from %s", tmp ? tmp : "Unknown");
Syslog('+', "Rerouting to %s:%s", remote_name, remote_port);
}
if (tmp)
free(tmp);
if ((sp = getservbyname(remote_port, "tcp")) == NULL) {
WriteError("Can't find service: %s", remote_port);
free(remote_name);
free(remote_port);
die(MBERR_INIT_ERROR);
}
if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) {
WriteError("Can't create Internet domain socket");
free(remote_name);
free(remote_port);
die(MBERR_INIT_ERROR);
}
if ((hp = gethostbyname(remote_name)) == NULL) {
WriteError("%s - Unknown host", remote_name);
free(remote_name);
free(remote_port);
die(MBERR_INIT_ERROR);
}
memset(&server,0,sizeof(server));
memcpy((char *)&server.sin_addr,hp->h_addr,hp->h_length);
server.sin_family=hp->h_addrtype;
server.sin_port = sp->s_port;
if (connect(s,(struct sockaddr *)&server,sizeof(server)) == -1) {
WriteError("Can't connect %s", remote_name);
free(remote_name);
free(remote_port);
die(MBERR_INIT_ERROR);
}
init_telnet();
tmp = calloc(81, sizeof(char ));
sprintf(tmp, "mbtelnetd v%s\r\n", VERSION);
write1(tmp, strlen(tmp));
free(tmp);
com_gw(s);
free(remote_name);
free(remote_port);
close(s);
die(0);
return 0;
}
/* --- This is an artwork of serge terekhov, 2:5000/13@fidonet :) --- */
void answer (int tag, int opt)
{
char buf[3];
char *r = (char *)"???";
switch (tag) {
case WILL:
r = (char *)"WILL";
break;
case WONT:
r = (char *)"WONT";
break;
case DO:
r = (char *)"DO";
break;
case DONT:
r = (char *)"DONT";
break;
}
Syslog('s', "TELNET send %s %d", r, opt);
buf[0] = IAC;
buf[1] = tag;
buf[2] = opt;
if (write (1, buf, 3) != 3)
WriteError("$answer cant send");
}
int init_telnet(void)
{
tellen = 0;
answer (DO, TN_SUPPRESS_GA);
answer (WILL, TN_SUPPRESS_GA);
answer (DO, TN_TRANSMIT_BINARY);
answer (WILL, TN_TRANSMIT_BINARY);
answer (DO, TN_ECHO);
answer (WILL, TN_ECHO);
return 1;
}
int read0 (char *buf, int len)
{
int n = 0, m;
char *q, *p;
static char telbuf[4];
while ((n == 0) && (n = read (0, buf + tellen, MBT_BUFSIZ - tellen)) > 0) {
if (tellen) {
memcpy(buf, telbuf, tellen);
n += tellen;
tellen = 0;
}
if (memchr (buf, IAC, n)) {
for (p = q = buf; n--; )
if ((m = (unsigned char)*q++) != IAC)
*p++ = m;
else {
if (n < 2) {
memcpy (telbuf, q - 1, tellen = n + 1);
break;
}
--n;
switch (m = (unsigned char)*q++) {
case WILL: m = (unsigned char)*q++; --n;
Syslog('s', "TELNET: recv WILL %d", m);
if (m != TN_TRANSMIT_BINARY && m != TN_SUPPRESS_GA && m != TN_ECHO)
answer (DONT, m);
break;
case WONT: m = *q++;
--n;
Syslog('s', "TELNET: recv WONT %d", m);
break;
case DO: m = (unsigned char)*q++;
--n;
Syslog('s', "TELNET: recv DO %d", m);
if (m != TN_TRANSMIT_BINARY && m != TN_SUPPRESS_GA && m != TN_ECHO)
answer (WONT, m);
break;
case DONT: m = (unsigned char)*q++;
--n;
Syslog('s', "TELNET: recv DONT %d", m);
break;
case IAC: *p++ = IAC;
break;
default: Syslog('s', "TELNET: recv IAC %d", m);
break;
}
}
n = p - buf;
}
}
return n;
}
int write1 (char *buf, int len)
{
char *q;
int k, l;
l = len;
while ((len > 0) && (q = memchr(buf, IAC, len))) {
k = (q - buf) + 1;
if ((write (1, buf, k) != k) || (write (1, q, 1) != 1)) {
return -1;
}
buf += k;
len -= k;
}
if ((len > 0) && write (1, buf, len) != len) {
return -1;
}
return l;
}
void com_gw(int in)
{
fd_set fds;
int n, fdsbits;
static struct timeval tout = { MBT_TIMEOUT, 0 };
unsigned char buf[MBT_BUFSIZ];
alarm(0);
fdsbits = in + 1;
while (TRUE) {
FD_ZERO(& fds);
FD_SET (in, &fds);
FD_SET (0 , &fds);
FD_SET (1 , &fds);
tout.tv_sec = MBT_TIMEOUT;
tout.tv_usec = 0;
if ((n = select(fdsbits, &fds, NULL, NULL, &tout)) > 0) {
if (FD_ISSET(in, &fds)) {
if ((n = read(in, buf, sizeof buf)) > 0) {
if (write1(buf, n) < 0) {
goto bad;
}
} else {
goto bad;
}
}
if (FD_ISSET(0, &fds)) {
if ((n = read0(buf, sizeof buf)) > 0) {
if (write(in, buf, n) < 0) goto bad;
} else {
goto bad;
}
}
} else {
goto bad;
}
}
bad: ;
}

7
mbcico/mbtelnetd.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef _MBTELNETD_H
#define _MBTELNETD_H
/* $Id$ */
#endif

View File

@@ -44,7 +44,7 @@
#define BINKPORT 24554
// #define TELNPORT 23
#define TELNPORT 23
#define FIDOPORT 60179 /* Eugene G. Crossers birthday */
@@ -103,6 +103,13 @@ int opentcp(char *name)
else
server.sin_port = htons(FIDOPORT);
break;
#ifdef USE_TELNET
case TCPMODE_ITN: if ((se = getservbyname("tfido", "tcp")))
server.sin_port = se->s_port;
else
server.sin_port = htons(TELNPORT);
break;
#endif
case TCPMODE_IBN: if ((se = getservbyname("binkd", "tcp")))
server.sin_port = se->s_port;
else
@@ -214,3 +221,42 @@ void closetcp(void)
}
#ifdef USE_TELNET
#define WILL 251
#define WONT 252
#define DO 253
#define DONT 254
#define IAC 255
#define TOPT_BIN 0
#define TOPT_ECHO 1
#define TOPT_SUPP 3
static void telnet_answer(int tag, int opt)
{
char buf[3];
Syslog('s', "telnet_answer(%d, %d)", tag, opt);
buf[0]=IAC;
buf[1]=tag;
buf[2]=opt;
tty_put(buf, 3);
}
void telnet_init(void)
{
Syslog('s', "telnet_init()");
telnet_answer(DO,TOPT_SUPP);
telnet_answer(WILL,TOPT_SUPP);
telnet_answer(DO,TOPT_BIN);
telnet_answer(WILL,TOPT_BIN);
telnet_answer(DO,TOPT_ECHO);
telnet_answer(WILL,TOPT_ECHO);
}
#endif

View File

@@ -6,5 +6,8 @@
int opentcp(char *);
void closetcp(void);
#ifdef USE_TELNET
void telnet_init(void);
#endif
#endif

View File

@@ -47,9 +47,13 @@
#include "binkp.h"
#include "callstat.h"
#include "inbound.h"
#include "opentcp.h"
extern int tcp_mode;
#ifdef USE_TELNET
extern int telnet;
#endif
node *nlent;
@@ -99,6 +103,11 @@ int session(faddr *a, node *nl, int role, int tp, char *dt)
} else if (tcp_mode == TCPMODE_IFC) {
Syslog('+', "Incoming IFC/TCP connection from %s", inet_ntoa(peeraddr.sin_addr));
IsDoing("Incoming IFC/TCP");
#ifdef USE_TELNET
} else if (tcp_mode == TCPMODE_ITN) {
Syslog('+', "Incoming ITN/TCP connection from %s", inet_ntoa(peeraddr.sin_addr));
IsDoing("Incoming ITN/TCP");
#endif
} else if (tcp_mode == TCPMODE_NONE) {
WriteError("Unknown TCP connection, parameter missing");
die(MBERR_COMMANDLINE);
@@ -106,6 +115,10 @@ int session(faddr *a, node *nl, int role, int tp, char *dt)
}
session_flags |= SESSION_TCP;
}
#ifdef USE_TELNET
if (telnet && (session_flags & SESSION_TCP))
telnet_init();
#endif
if (data)
free(data);

View File

@@ -5,6 +5,9 @@
#define TCPMODE_NONE 0
#define TCPMODE_IFC 1 /* ifcico native EMSI on raw TCP */
#ifdef USE_TELNET
#define TCPMODE_ITN 2 /* EMSI encapsulation through telnet */
#endif
#define TCPMODE_IBN 3 /* Binkp protocol */
#define SESSION_UNKNOWN 0

View File

@@ -178,7 +178,7 @@ static int tty_read(char *buf, int size, int tot)
now = time(NULL);
timeout = (time_t)300; /* maximum of 5 minutes */
for (i = 0; i < 2; i++) {
for (i = 0; i < NUMTIMERS; i++) {
if (timer[i]) {
if (now >= timer[i]) {
tty_status=STAT_TIMEOUT;