answer.cpp 12.51 KiB
/* answer.cpp */
/* Synchronet answer "caller" function */
/* $Id$ */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright 2007 Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program 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 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* Anonymous FTP access to the most recent released source is available at *
* ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
* *
* Anonymous CVS access to the development source and modification history *
* is available at cvs.synchro.net:/cvsroot/sbbs, example: *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login *
* (just hit return, no password is necessary) *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* You are encouraged to submit any modifications (preferably in Unix diff *
* format) via e-mail to mods@synchro.net *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include "sbbs.h"
#include "telnet.h"
extern "C" void client_on(SOCKET sock, client_t* client, BOOL update);
bool sbbs_t::answer()
{
char str[MAX_PATH+1],str2[MAX_PATH+1],c;
char tmp[MAX_PATH+1];
char path[MAX_PATH+1];
int i,l,in;
struct tm tm;
struct in_addr addr;
useron.number=0;
answertime=logontime=starttime=now=time(NULL);
/* Caller ID is IP address */
addr.s_addr=client_addr;
SAFECOPY(cid,inet_ntoa(addr));
memset(&tm,0,sizeof(tm));
localtime_r(&now,&tm);
sprintf(str,"%s %s %s %02d %u Node %3u"
,hhmmtostr(&cfg,&tm,str2)
,wday[tm.tm_wday]
,mon[tm.tm_mon],tm.tm_mday,tm.tm_year+1900,cfg.node_num);
logline("@ ",str);
sprintf(str,"%s %s [%s]", connection, client_name, cid);
logline("@+:",str);
if(client_ident[0]) {
sprintf(str,"Identity: %s",client_ident);
logline("@*",str);
}
online=ON_REMOTE;
rlogin_name[0]=0;
if(sys_status&SS_RLOGIN) {
if(incom(1000)==0) {
for(i=0;i<(int)sizeof(str)-1;i++) {
in=incom(1000);
if(in==0 || in==NOINP)
break;
str[i]=in;
}
str[i]=0;
for(i=0;i<(int)sizeof(str2)-1;i++) {
in=incom(1000);
if(in==0 || in==NOINP)
break;
str2[i]=in;
}
str2[i]=0;
for(i=0;i<(int)sizeof(terminal)-1;i++) {
in=incom(1000);
if(in==0 || in==NOINP)
break;
terminal[i]=in;
}
terminal[i]=0;
truncstr(terminal,"/");
lprintf(LOG_DEBUG,"Node %d RLogin: '%.*s' / '%.*s' / '%s'"
,cfg.node_num
,LEN_ALIAS*2,str
,LEN_ALIAS*2,str2
,terminal);
SAFECOPY(rlogin_name
,startup->options&BBS_OPT_USE_2ND_RLOGIN ? str2 : str);
SAFECOPY(rlogin_pass
,startup->options&BBS_OPT_USE_2ND_RLOGIN ? str : str2);
useron.number=userdatdupe(0, U_ALIAS, LEN_ALIAS, rlogin_name, 0);
if(useron.number) {
getuserdat(&cfg,&useron);
useron.misc&=~(ANSI|COLOR|RIP|WIP);
SAFEPRINTF(path,"%srlogin.cfg",cfg.ctrl_dir);
if(!findstr(client.addr,path)) {
SAFECOPY(tmp
,rlogin_pass);
for(i=0;i<3;i++) {
if(stricmp(tmp,useron.pass)) {
rioctl(IOFI); /* flush input buffer */
bputs(text[InvalidLogon]);
if(cfg.sys_misc&SM_ECHO_PW)
sprintf(str,"(%04u) %-25s FAILED Password attempt: '%s'"
,0,useron.alias,tmp);
else
sprintf(str,"(%04u) %-25s FAILED Password attempt"
,0,useron.alias);
logline("+!",str);
bputs(text[PasswordPrompt]);
console|=CON_R_ECHOX;
getstr(tmp,LEN_PASS*2,K_UPPER|K_LOWPRIO|K_TAB);
console&=~(CON_R_ECHOX|CON_L_ECHOX);
}
else {
if(REALSYSOP) {
rioctl(IOFI); /* flush input buffer */
if(!chksyspass())
bputs(text[InvalidLogon]);
else {
i=0;
break;
}
}
else
break;
}
}
if(i) {
if(stricmp(tmp,useron.pass)) {
bputs(text[InvalidLogon]);
if(cfg.sys_misc&SM_ECHO_PW)
sprintf(str,"(%04u) %-25s FAILED Password attempt: '%s'"
,0,useron.alias,tmp);
else
sprintf(str,"(%04u) %-25s FAILED Password attempt"
,0,useron.alias);
logline("+!",str);
}
lprintf(LOG_WARNING,"%04d !CLIENT IP NOT LISTED in %s",client_socket,path);
useron.number=0;
hangup();
}
}
}
else
lprintf(LOG_DEBUG,"Node %d RLogin: Unknown user: %s",cfg.node_num,rlogin_name);
}
if(rlogin_name[0]==0) {
lprintf(LOG_DEBUG,"Node %d !RLogin: No user name received",cfg.node_num);
sys_status&=~SS_RLOGIN;
}
}
if(!(telnet_mode&TELNET_MODE_OFF)) {
/* Disable Telnet Terminal Echo */
request_telnet_opt(TELNET_WILL,TELNET_ECHO);
/* Will suppress Go Ahead */
request_telnet_opt(TELNET_WILL,TELNET_SUP_GA);
/* Retrieve terminal type and speed from telnet client --RS */
request_telnet_opt(TELNET_DO,TELNET_TERM_TYPE);
request_telnet_opt(TELNET_DO,TELNET_TERM_SPEED);
request_telnet_opt(TELNET_DO,TELNET_SEND_LOCATION);
}
#ifdef USE_CRYPTLIB
if(sys_status&SS_SSH) {
cryptGetAttributeString(ssh_session, CRYPT_SESSINFO_USERNAME, rlogin_name, &i);
rlogin_name[i]=0;
cryptGetAttributeString(ssh_session, CRYPT_SESSINFO_PASSWORD, rlogin_pass, &i);
rlogin_pass[i]=0;
lprintf(LOG_DEBUG,"Node %d SSH login: '%s'"
,cfg.node_num, rlogin_name);
useron.number=userdatdupe(0, U_ALIAS, LEN_ALIAS, rlogin_name, 0);
if(useron.number) {
getuserdat(&cfg,&useron);
useron.misc&=~(ANSI|COLOR|RIP|WIP);
SAFECOPY(tmp
,rlogin_pass);
for(i=0;i<3;i++) {
if(stricmp(tmp,useron.pass)) {
rioctl(IOFI); /* flush input buffer */
bputs(text[InvalidLogon]);
if(cfg.sys_misc&SM_ECHO_PW)
sprintf(str,"(%04u) %-25s FAILED Password attempt: '%s'"
,0,useron.alias,tmp);
else
sprintf(str,"(%04u) %-25s FAILED Password attempt"
,0,useron.alias);
logline("+!",str);
bputs(text[PasswordPrompt]);
console|=CON_R_ECHOX;
getstr(tmp,LEN_PASS*2,K_UPPER|K_LOWPRIO|K_TAB);
console&=~(CON_R_ECHOX|CON_L_ECHOX);
}
else {
if(REALSYSOP) {
rioctl(IOFI); /* flush input buffer */
if(!chksyspass())
bputs(text[InvalidLogon]);
else {
i=0;
break;
}
}
else
break;
}
}
if(i) {
if(stricmp(tmp,useron.pass)) {
bputs(text[InvalidLogon]);
if(cfg.sys_misc&SM_ECHO_PW)
sprintf(str,"(%04u) %-25s FAILED Password attempt: '%s'"
,0,useron.alias,tmp);
else
sprintf(str,"(%04u) %-25s FAILED Password attempt"
,0,useron.alias);
logline("+!",str);
}
useron.number=0;
hangup();
}
}
else
lprintf(LOG_DEBUG,"Node %d SSH: Unknown user: %s",cfg.node_num,rlogin_name);
}
#endif
/* Detect terminal type */
mswait(200);
rioctl(IOFI); /* flush input buffer */
putcom( "\r\n" /* locate cursor at column 1 */
"\x1b[s" /* save cursor position (necessary for HyperTerm auto-ANSI) */
"\x1b[99B_" /* locate cursor as far down as possible */
"\x1b[6n" /* Get cursor position */
"\x1b[u" /* restore cursor position */
"\x1b[!_" /* RIP? */
"\x1b[0t_" /* WIP? */
"\2\2?HTML?"/* HTML? */
"\x1b[0m_" /* "Normal" colors */
"\x1b[2J" /* clear screen */
"\x1b[H" /* home cursor */
"\xC" /* clear screen (in case not ANSI) */
"\r" /* Move cursor left (in case previous char printed) */
);
i=l=0;
tos=1;
lncntr=0;
strcpy(str,VERSION_NOTICE);
strcat(str," ");
strcat(str,COPYRIGHT_NOTICE);
strip_ctrl(str);
center(str);
while(i++<50 && l<(int)sizeof(str)-1) { /* wait up to 5 seconds for response */
c=incom(100)&0x7f;
if(c==0)
continue;
i=0;
if(l==0 && c!=ESC) // response must begin with escape char
continue;
str[l++]=c;
if(c=='R') { /* break immediately if ANSI response */
mswait(500);
break;
}
}
while((c=(incom(100)&0x7f))!=0 && l<(int)sizeof(str)-1)
str[l++]=c;
str[l]=0;
if(l) {
if(str[0]==ESC && str[1]=='[') {
if(terminal[0]==0)
SAFECOPY(terminal,"ANSI");
autoterm|=(ANSI|COLOR);
rows=atoi(str+2);
lprintf(LOG_DEBUG,"Node %d ANSI cursor position report: %u rows"
,cfg.node_num, rows);
if(rows<10 || rows>99) rows=24;
}
truncsp(str);
if(strstr(str,"RIPSCRIP")) {
if(terminal[0]==0)
SAFECOPY(terminal,"RIP");
logline("@R",strstr(str,"RIPSCRIP"));
autoterm|=(RIP|COLOR|ANSI); }
else if(strstr(str,"DC-TERM")
&& toupper(*(strstr(str,"DC-TERM")+12))=='W') {
if(terminal[0]==0)
SAFECOPY(terminal,"WIP");
logline("@W",strstr(str,"DC-TERM"));
autoterm|=(WIP|COLOR|ANSI); }
else if(strstr(str,"!HTML!")) {
if(terminal[0]==0)
SAFECOPY(terminal,"HTML");
logline("@H",strstr(str,"!HTML!"));
autoterm|=HTML;
}
}
else if(terminal[0]==0)
SAFECOPY(terminal,"DUMB");
rioctl(IOFI); /* flush left-over or late response chars */
if(!autoterm && str[0]) {
lputs(LOG_DEBUG,"Terminal Auto-detect failed, Response: ");
str2[0]=0;
for(i=0;str[i];i++) {
if(str[i]>=' ' && str[i]<='~')
sprintf(tmp,"%c", str[i]);
else
sprintf(tmp,"<%02X>", (uchar)str[i]);
strcat(str2,tmp);
}
lputs(LOG_DEBUG,str2);
}
/* AutoLogon via IP or Caller ID here */
if(!useron.number && !(sys_status&SS_RLOGIN)
&& startup->options&BBS_OPT_AUTO_LOGON && cid[0]) {
useron.number=userdatdupe(0, U_NOTE, LEN_NOTE, cid, 0);
if(useron.number) {
getuserdat(&cfg, &useron);
if(!(useron.misc&AUTOLOGON) || !(useron.exempt&FLAG('V')))
useron.number=0;
}
}
if(!online)
return(false);
if(stricmp(terminal,"sexpots")==0) { /* dial-up connection (via SexPOTS) */
SAFEPRINTF2(str,"%s connection detected at %lu bps", terminal, cur_rate);
logline("@S",str);
node_connection = (ushort)cur_rate;
SAFEPRINTF(connection,"%lu",cur_rate);
SAFECOPY(cid,"Unknown");
SAFECOPY(client_name,"Unknown");
if(telnet_location[0]) { /* Caller-ID info provided */
SAFEPRINTF(str, "CID: %s", telnet_location);
logline("@*",str);
SAFECOPY(cid,telnet_location);
truncstr(cid," "); /* Only include phone number in CID */
char* p=telnet_location;
FIND_WHITESPACE(p);
SKIP_WHITESPACE(p);
if(*p) {
SAFECOPY(client_name,p); /* CID name, if provided (maybe 'P' or 'O' if private or out-of-area) */
}
}
SAFECOPY(client.addr,cid);
SAFECOPY(client.host,client_name);
client_on(client_socket,&client,TRUE /* update */);
} else {
if(telnet_location[0]) { /* Telnet Location info provided */
SAFEPRINTF(str, "Telnet Location: %s", telnet_location);
logline("@*",str);
}
}
useron.misc&=~(ANSI|COLOR|RIP|WIP);
useron.misc|=autoterm;
SAFECOPY(useron.comp,client_name);
if(!useron.number && sys_status&SS_RLOGIN) {
CRLF;
newuser();
}
if(!useron.number) { /* manual/regular logon */
/* Display ANSWER screen */
sprintf(str,"%sanswer",cfg.text_dir);
sprintf(tmp,"%s.%s",str,autoterm&WIP ? "wip":"rip");
sprintf(path,"%s.html",str);
sprintf(str2,"%s.ans",str);
if(autoterm&(RIP|WIP) && fexist(tmp))
strcat(str,autoterm&WIP ? ".wip":".rip");
else if(autoterm&HTML && fexist(path))
strcat(str,".html");
else if(autoterm&ANSI && fexist(str2))
strcat(str,".ans");
else
strcat(str,".asc");
rioctl(IOSM|PAUSE);
sys_status|=SS_PAUSEON;
printfile(str,P_NOABORT);
sys_status&=~SS_PAUSEON;
exec_bin(cfg.login_mod,&main_csi);
} else /* auto logon here */
if(logon()==false)
return(false);
if(!useron.number)
hangup();
if(!online)
return(false);
/* Save the IP to the user's note */
if(cid[0]) {
SAFECOPY(useron.note,cid);
putuserrec(&cfg,useron.number,U_NOTE,LEN_NOTE,useron.note);
}
/* Save host name to the user's computer description */
if(client_name[0]) {
SAFECOPY(useron.comp,client_name);
putuserrec(&cfg,useron.number,U_COMP,LEN_COMP,useron.comp);
}
if(!(sys_status&SS_USERON)) {
errormsg(WHERE,ERR_CHK,"User not logged on",0);
hangup();
return(false); }
return(true);
}