|
|
1.1 root 1: /* answer.cpp */
2:
3: /* Synchronet answer "caller" function */
4:
5: /* $Id: answer.cpp,v 1.51 2006/12/29 19:32:36 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include "sbbs.h"
39: #include "telnet.h"
40:
41: bool sbbs_t::answer()
42: {
43: char str[MAX_PATH+1],str2[MAX_PATH+1],c;
44: char tmp[MAX_PATH+1];
45: char path[MAX_PATH+1];
46: int i,l,in;
47: struct tm tm;
48: struct in_addr addr;
49:
50: useron.number=0;
51: answertime=logontime=starttime=now=time(NULL);
52: /* Caller ID is IP address */
53: addr.s_addr=client_addr;
54: SAFECOPY(cid,inet_ntoa(addr));
55:
56: memset(&tm,0,sizeof(tm));
57: localtime_r(&now,&tm);
58:
59: sprintf(str,"%s %s %s %02d %u Node %3u"
60: ,hhmmtostr(&cfg,&tm,str2)
61: ,wday[tm.tm_wday]
62: ,mon[tm.tm_mon],tm.tm_mday,tm.tm_year+1900,cfg.node_num);
63: logline("@ ",str);
64:
65: sprintf(str,"%s %s [%s]", connection, client_name, cid);
66: logline("@+:",str);
67:
68: if(client_ident[0]) {
69: sprintf(str,"Identity: %s",client_ident);
70: logline("@*",str);
71: }
72:
73: online=ON_REMOTE;
74:
75: rlogin_name[0]=0;
76: if(sys_status&SS_RLOGIN) {
77: if(incom(1000)==0) {
78: for(i=0;i<(int)sizeof(str)-1;i++) {
79: in=incom(1000);
80: if(in==0 || in==NOINP)
81: break;
82: str[i]=in;
83: }
84: str[i]=0;
85: for(i=0;i<(int)sizeof(str2)-1;i++) {
86: in=incom(1000);
87: if(in==0 || in==NOINP)
88: break;
89: str2[i]=in;
90: }
91: str2[i]=0;
92: for(i=0;i<(int)sizeof(terminal)-1;i++) {
93: in=incom(1000);
94: if(in==0 || in==NOINP)
95: break;
96: terminal[i]=in;
97: }
98: terminal[i]=0;
99: truncstr(terminal,"/");
100: lprintf(LOG_DEBUG,"Node %d RLogin: '%.*s' / '%.*s' / '%s'"
101: ,cfg.node_num
102: ,LEN_ALIAS*2,str
103: ,LEN_ALIAS*2,str2
104: ,terminal);
105: SAFECOPY(rlogin_name
106: ,startup->options&BBS_OPT_USE_2ND_RLOGIN ? str2 : str);
107: SAFECOPY(rlogin_pass
108: ,startup->options&BBS_OPT_USE_2ND_RLOGIN ? str : str2);
109: useron.number=userdatdupe(0, U_ALIAS, LEN_ALIAS, rlogin_name, 0);
110: if(useron.number) {
111: getuserdat(&cfg,&useron);
112: useron.misc&=~(ANSI|COLOR|RIP|WIP);
113: SAFEPRINTF(path,"%srlogin.cfg",cfg.ctrl_dir);
114: if(!findstr(client.addr,path)) {
115: SAFECOPY(tmp
116: ,rlogin_pass);
117: for(i=0;i<3;i++) {
118: if(stricmp(tmp,useron.pass)) {
119: rioctl(IOFI); /* flush input buffer */
120: bputs(text[InvalidLogon]);
121: if(cfg.sys_misc&SM_ECHO_PW)
122: sprintf(str,"(%04u) %-25s FAILED Password attempt: '%s'"
123: ,0,useron.alias,tmp);
124: else
125: sprintf(str,"(%04u) %-25s FAILED Password attempt"
126: ,0,useron.alias);
127: logline("+!",str);
128: bputs(text[PasswordPrompt]);
129: console|=CON_R_ECHOX;
130: getstr(tmp,LEN_PASS*2,K_UPPER|K_LOWPRIO|K_TAB);
131: console&=~(CON_R_ECHOX|CON_L_ECHOX);
132: }
133: else {
134: if(REALSYSOP) {
135: rioctl(IOFI); /* flush input buffer */
136: if(!chksyspass())
137: bputs(text[InvalidLogon]);
138: else {
139: i=0;
140: break;
141: }
142: }
143: else
144: break;
145: }
146: }
147: if(i) {
148: if(stricmp(tmp,useron.pass)) {
149: bputs(text[InvalidLogon]);
150: if(cfg.sys_misc&SM_ECHO_PW)
151: sprintf(str,"(%04u) %-25s FAILED Password attempt: '%s'"
152: ,0,useron.alias,tmp);
153: else
154: sprintf(str,"(%04u) %-25s FAILED Password attempt"
155: ,0,useron.alias);
156: logline("+!",str);
157: }
158: lprintf(LOG_WARNING,"%04d !CLIENT IP NOT LISTED in %s",client_socket,path);
159: useron.number=0;
160: hangup();
161: }
162: }
163: }
164: else
165: lprintf(LOG_DEBUG,"Node %d RLogin: Unknown user: %s",cfg.node_num,rlogin_name);
166: }
167: if(rlogin_name[0]==0) {
168: lprintf(LOG_DEBUG,"Node %d !RLogin: No user name received",cfg.node_num);
169: sys_status&=~SS_RLOGIN;
170: }
171: }
172:
173: if(!(telnet_mode&TELNET_MODE_OFF)) {
174: /* Disable Telnet Terminal Echo */
175: request_telnet_opt(TELNET_WILL,TELNET_ECHO);
176: /* Will suppress Go Ahead */
177: request_telnet_opt(TELNET_WILL,TELNET_SUP_GA);
178: /* Retrieve terminal type from telnet client --RS */
179: request_telnet_opt(TELNET_DO,TELNET_TERM_TYPE);
180: }
181: #ifdef USE_CRYPTLIB
182: if(sys_status&SS_SSH) {
183: cryptGetAttributeString(ssh_session, CRYPT_SESSINFO_USERNAME, rlogin_name, &i);
184: rlogin_name[i]=0;
185: cryptGetAttributeString(ssh_session, CRYPT_SESSINFO_PASSWORD, rlogin_pass, &i);
186: rlogin_pass[i]=0;
187: lprintf(LOG_DEBUG,"Node %d SSH login: '%s'"
188: ,cfg.node_num, rlogin_name);
189: useron.number=userdatdupe(0, U_ALIAS, LEN_ALIAS, rlogin_name, 0);
190: if(useron.number) {
191: getuserdat(&cfg,&useron);
192: useron.misc&=~(ANSI|COLOR|RIP|WIP);
193: SAFECOPY(tmp
194: ,rlogin_pass);
195: for(i=0;i<3;i++) {
196: if(stricmp(tmp,useron.pass)) {
197: rioctl(IOFI); /* flush input buffer */
198: bputs(text[InvalidLogon]);
199: if(cfg.sys_misc&SM_ECHO_PW)
200: sprintf(str,"(%04u) %-25s FAILED Password attempt: '%s'"
201: ,0,useron.alias,tmp);
202: else
203: sprintf(str,"(%04u) %-25s FAILED Password attempt"
204: ,0,useron.alias);
205: logline("+!",str);
206: bputs(text[PasswordPrompt]);
207: console|=CON_R_ECHOX;
208: getstr(tmp,LEN_PASS*2,K_UPPER|K_LOWPRIO|K_TAB);
209: console&=~(CON_R_ECHOX|CON_L_ECHOX);
210: }
211: else {
212: if(REALSYSOP) {
213: rioctl(IOFI); /* flush input buffer */
214: if(!chksyspass())
215: bputs(text[InvalidLogon]);
216: else {
217: i=0;
218: break;
219: }
220: }
221: else
222: break;
223: }
224: }
225: if(i) {
226: if(stricmp(tmp,useron.pass)) {
227: bputs(text[InvalidLogon]);
228: if(cfg.sys_misc&SM_ECHO_PW)
229: sprintf(str,"(%04u) %-25s FAILED Password attempt: '%s'"
230: ,0,useron.alias,tmp);
231: else
232: sprintf(str,"(%04u) %-25s FAILED Password attempt"
233: ,0,useron.alias);
234: logline("+!",str);
235: }
236: useron.number=0;
237: hangup();
238: }
239: }
240: else
241: lprintf(LOG_DEBUG,"Node %d SSH: Unknown user: %s",cfg.node_num,rlogin_name);
242: }
243: #endif
244:
245: /* Detect terminal type */
246: mswait(200);
247: rioctl(IOFI); /* flush input buffer */
248: putcom( "\r\n" /* locate cursor at column 1 */
249: "\x1b[s" /* save cursor position (necessary for HyperTerm auto-ANSI) */
250: "\x1b[99B_" /* locate cursor as far down as possible */
251: "\x1b[6n" /* Get cursor position */
252: "\x1b[u" /* restore cursor position */
253: "\x1b[!_" /* RIP? */
254: "\x1b[0t_" /* WIP? */
255: "\2\2?HTML?"/* HTML? */
256: "\x1b[0m_" /* "Normal" colors */
257: "\x1b[2J" /* clear screen */
258: "\x1b[H" /* home cursor */
259: "\xC" /* clear screen (in case not ANSI) */
260: "\r" /* Move cursor left (in case previous char printed) */
261: );
262: i=l=0;
263: tos=1;
264: lncntr=0;
265: strcpy(str,VERSION_NOTICE);
266: strcat(str," ");
267: strcat(str,COPYRIGHT_NOTICE);
268: strip_ctrl(str);
269: center(str);
270:
271: while(i++<50 && l<(int)sizeof(str)-1) { /* wait up to 5 seconds for response */
272: c=incom(100)&0x7f;
273: if(c==0)
274: continue;
275: i=0;
276: if(l==0 && c!=ESC) // response must begin with escape char
277: continue;
278: str[l++]=c;
279: if(c=='R') { /* break immediately if ANSI response */
280: mswait(500);
281: break;
282: }
283: }
284:
285: while((c=(incom(100)&0x7f))!=0 && l<(int)sizeof(str)-1)
286: str[l++]=c;
287: str[l]=0;
288:
289: if(l) {
290: if(str[0]==ESC && str[1]=='[') {
291: if(terminal[0]==0)
292: SAFECOPY(terminal,"ANSI");
293: autoterm|=(ANSI|COLOR);
294: rows=atoi(str+2);
295: lprintf(LOG_DEBUG,"Node %d ANSI cursor position report: %u rows"
296: ,cfg.node_num, rows);
297: if(rows<10 || rows>99) rows=24;
298: }
299: truncsp(str);
300: if(strstr(str,"RIPSCRIP")) {
301: if(terminal[0]==0)
302: SAFECOPY(terminal,"RIP");
303: logline("@R",strstr(str,"RIPSCRIP"));
304: autoterm|=(RIP|COLOR|ANSI); }
305: else if(strstr(str,"DC-TERM")
306: && toupper(*(strstr(str,"DC-TERM")+12))=='W') {
307: if(terminal[0]==0)
308: SAFECOPY(terminal,"WIP");
309: logline("@W",strstr(str,"DC-TERM"));
310: autoterm|=(WIP|COLOR|ANSI); }
311: else if(strstr(str,"!HTML!")) {
312: if(terminal[0]==0)
313: SAFECOPY(terminal,"HTML");
314: logline("@H",strstr(str,"!HTML!"));
315: autoterm|=HTML;
316: }
317: }
318: else if(terminal[0]==0)
319: SAFECOPY(terminal,"DUMB");
320:
321: rioctl(IOFI); /* flush left-over or late response chars */
322:
323: if(!autoterm && str[0]) {
324: lputs(LOG_DEBUG,"Terminal Auto-detect failed, Response: ");
325: str2[0]=0;
326: for(i=0;str[i];i++) {
327: if(str[i]>=' ' && str[i]<='~')
328: sprintf(tmp,"%c", str[i]);
329: else
330: sprintf(tmp,"<%02X>", (uchar)str[i]);
331: strcat(str2,tmp);
332: }
333: lputs(LOG_DEBUG,str2);
334: }
335:
336: /* AutoLogon via IP or Caller ID here */
337: if(!useron.number && !(sys_status&SS_RLOGIN)
338: && startup->options&BBS_OPT_AUTO_LOGON && cid[0]) {
339: useron.number=userdatdupe(0, U_NOTE, LEN_NOTE, cid, 0);
340: if(useron.number) {
341: getuserdat(&cfg, &useron);
342: if(!(useron.misc&AUTOLOGON) || !(useron.exempt&FLAG('V')))
343: useron.number=0;
344: }
345: }
346:
347: if(!online)
348: return(false);
349:
350: useron.misc&=~(ANSI|COLOR|RIP|WIP);
351: useron.misc|=autoterm;
352: SAFECOPY(useron.comp,client_name);
353:
354: if(!useron.number && sys_status&SS_RLOGIN) {
355: CRLF;
356: newuser();
357: }
358:
359: if(!useron.number) { /* manual/regular logon */
360:
361: /* Display ANSWER screen */
362: sprintf(str,"%sanswer",cfg.text_dir);
363: sprintf(tmp,"%s.%s",str,autoterm&WIP ? "wip":"rip");
364: sprintf(path,"%s.html",str);
365: sprintf(str2,"%s.ans",str);
366: if(autoterm&(RIP|WIP) && fexist(tmp))
367: strcat(str,autoterm&WIP ? ".wip":".rip");
368: else if(autoterm&HTML && fexist(path))
369: strcat(str,".html");
370: else if(autoterm&ANSI && fexist(str2))
371: strcat(str,".ans");
372: else
373: strcat(str,".asc");
374: rioctl(IOSM|PAUSE);
375: sys_status|=SS_PAUSEON;
376: printfile(str,P_NOABORT);
377: sys_status&=~SS_PAUSEON;
378: exec_bin(cfg.login_mod,&main_csi);
379: } else /* auto logon here */
380: if(logon()==false)
381: return(false);
382:
383:
384: if(!useron.number)
385: hangup();
386: if(!online)
387: return(false);
388:
389: /* Save the IP to the user's note */
390: if(cid[0]) {
391: SAFECOPY(useron.note,cid);
392: putuserrec(&cfg,useron.number,U_NOTE,LEN_NOTE,useron.note);
393: }
394:
395: /* Save host name to the user's computer description */
396: if(client_name[0]) {
397: SAFECOPY(useron.comp,client_name);
398: putuserrec(&cfg,useron.number,U_COMP,LEN_COMP,useron.comp);
399: }
400:
401: if(!(sys_status&SS_USERON)) {
402: errormsg(WHERE,ERR_CHK,"User not logged on",0);
403: hangup();
404: return(false); }
405:
406: return(true);
407: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.