1 /*
2  * $LynxId: HTTelnet.c,v 1.41 2013/11/28 11:15:19 tom Exp $
3  *
4  *		Telnet Access, Rlogin, etc			HTTelnet.c
5  *		==========================
6  *
7  * Authors
8  *	TBL	Tim Berners-Lee timbl@info.cern.ch
9  *	JFG	Jean-Francois Groff jgh@next.com
10  *	DD	Denis DeLaRoca (310) 825-4580  <CSP1DWD@mvs.oac.ucla.edu>
11  * History
12  *	 8 Jun 92 Telnet hopping prohibited as telnet is not secure (TBL)
13  *	26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. (JFG)
14  *	 6 Oct 92 Moved HTClientHost and logfile into here. (TBL)
15  *	17 Dec 92 Tn3270 added, bug fix. (DD)
16  *	 2 Feb 93 Split from HTAccess.c.  Registration.(TBL)
17  */
18 
19 #include <HTUtils.h>
20 #include <LYUtils.h>
21 
22 /* Implements:
23 */
24 #include <HTTelnet.h>
25 
26 #include <HTParse.h>
27 #include <HTAnchor.h>
28 #include <HTTP.h>
29 #include <HTFile.h>
30 
31 #include <HTTCP.h>
32 #include <HText.h>
33 
34 #include <HTAccess.h>
35 #include <HTAlert.h>
36 
37 #include <LYStrings.h>
38 #include <LYClean.h>
39 #include <LYLeaks.h>
40 
41 #ifdef __GNUC__
42 static void do_system(char *) GCC_UNUSED;
43 #endif
44 
do_system(char * command)45 static void do_system(char *command)
46 {
47     if (non_empty(command)) {
48 	CTRACE((tfp, "HTTelnet: Command is: %s\n\n", command));
49 	LYSystem(command);
50     }
51     FREE(command);
52 }
53 
54 /*	Telnet or "rlogin" access
55  *	-------------------------
56  */
remote_session(char * acc_method,char * host)57 static int remote_session(char *acc_method, char *host)
58 {
59     const char *program;
60     char *user = host;
61     char *password = NULL;
62     char *cp;
63     char *hostname;
64     char *port;
65     char *command = NULL;
66     enum _login_protocol {
67 	telnet,
68 	rlogin,
69 	tn3270
70     } login_protocol =
71       strcmp(acc_method, "rlogin") == 0 ? rlogin :
72       strcmp(acc_method, "tn3270") == 0 ? tn3270 : telnet;
73 
74     /*
75      * Modified to allow for odd chars in a username only if exists.
76      * 05-28-94 Lynx 2-3-1 Garrett Arch Blythe
77      */
78     /* prevent telnet://hostname;rm -rf *  URL's (VERY BAD)
79      *  *cp=0;        // terminate at any ;,<,>,`,|,",' or space or return
80      * or tab to prevent security hole
81      */
82     for (cp = (StrChr(host, '@') ? StrChr(host, '@') : host); *cp != '\0';
83 	 cp++) {
84 	if (!isalnum(UCH(*cp)) && *cp != '_' && *cp != '-' &&
85 	    *cp != ':' && *cp != '.' && *cp != '@') {
86 	    *cp = '\0';
87 	    break;
88 	}
89     }
90 
91     hostname = StrChr(host, '@');
92 
93     if (hostname) {
94 	*hostname++ = '\0';	/* Split */
95     } else {
96 	hostname = host;
97 	user = NULL;		/* No user specified */
98     }
99 
100     port = StrChr(hostname, ':');
101     if (port)
102 	*port++ = '\0';		/* Split */
103 
104     if (*hostname == '\0') {
105 	CTRACE((tfp, "HTTelnet: No host specified!\n"));
106 	return HT_NO_DATA;
107     } else if (!valid_hostname(hostname)) {
108 	char *prefix = NULL;
109 	char *line = NULL;
110 
111 	CTRACE((tfp, "HTTelnet: Invalid hostname %s!\n", host));
112 	HTSprintf0(&prefix,
113 		   gettext("remote %s session:"), acc_method);
114 	HTSprintf0(&line,
115 		   gettext("Invalid hostname %s"), host);
116 	HTAlwaysAlert(prefix, line);
117 	FREE(prefix);
118 	FREE(line);
119 	return HT_NO_DATA;
120     }
121 
122     if (user) {
123 	password = StrChr(user, ':');
124 	if (password) {
125 	    *password++ = '\0';
126 	}
127     }
128 
129     /* If the person is already telnetting etc, forbid hopping */
130     /* This is a security precaution, for us and remote site */
131 
132     if (HTSecure) {
133 
134 #ifdef TELNETHOPPER_MAIL
135 	HTSprintf0(&command,
136 		   "finger @%s | mail -s \"**telnethopper %s\" tbl@dxcern.cern.ch",
137 		   HTClientHost, HTClientHost);
138 	do_system(command);
139 #endif
140 	printf("\n\nSorry, but the service you have selected is one\n");
141 	printf("to which you have to log in.  If you were running www\n");
142 	printf("on your own computer, you would be automatically connected.\n");
143 	printf("For security reasons, this is not allowed when\n");
144 	printf("you log in to this information service remotely.\n\n");
145 
146 	printf("You can manually connect to this service using %s\n",
147 	       acc_method);
148 	printf("to host %s", hostname);
149 	if (user)
150 	    printf(", user name %s", user);
151 	if (password)
152 	    printf(", password %s", password);
153 	if (port)
154 	    printf(", port %s", port);
155 	printf(".\n\n");
156 	return HT_NO_DATA;
157     }
158 
159     /* Not all telnet servers get it even if user name is specified so we
160      * always tell the guy what to log in as.
161      */
162     if (user && login_protocol != rlogin)
163 	printf("When you are connected, log in as:  %s\n", user);
164     if (password && login_protocol != rlogin)
165 	printf("                  The password is:  %s\n", password);
166     fflush(stdout);
167 
168 /*
169  *	NeXTSTEP is the implied version of the NeXT operating system.
170  *		You may need to define this yourself.
171  */
172 #if	!defined(TELNET_DONE) && (defined(NeXT) && defined(NeXTSTEP) && NeXTSTEP<=20100)
173 #define FMT_TELNET "%s%s%s %s %s"
174 
175     if ((program = HTGetProgramPath(ppTELNET)) != NULL) {
176 	HTAddParam(&command, FMT_TELNET, 1, program);
177 	HTOptParam(&command, FMT_TELNET, 2, user ? " -l " : "");
178 	HTAddParam(&command, FMT_TELNET, 3, user);
179 	HTAddParam(&command, FMT_TELNET, 4, hostname);
180 	HTAddParam(&command, FMT_TELNET, 5, port);
181 	HTEndParam(&command, FMT_TELNET, 5);
182     }
183     do_system(command);
184 #define TELNET_DONE
185 #endif
186 
187 /* Most unix machines support username only with rlogin */
188 #if !defined(TELNET_DONE) && (defined(UNIX) || defined(DOSPATH) || defined(__CYGWIN__))
189 
190 #define FMT_RLOGIN "%s %s%s%s"
191 #define FMT_TN3270 "%s %s %s"
192 #define FMT_TELNET "%s %s %s"
193 
194     switch (login_protocol) {
195     case rlogin:
196 	if ((program = HTGetProgramPath(ppRLOGIN)) != NULL) {
197 	    HTAddParam(&command, FMT_RLOGIN, 1, program);
198 	    HTAddParam(&command, FMT_RLOGIN, 2, hostname);
199 	    HTOptParam(&command, FMT_RLOGIN, 3, user ? " -l " : "");
200 	    HTAddParam(&command, FMT_RLOGIN, 4, user);
201 	    HTEndParam(&command, FMT_RLOGIN, 4);
202 	}
203 	break;
204 
205     case tn3270:
206 	if ((program = HTGetProgramPath(ppTN3270)) != NULL) {
207 	    HTAddParam(&command, FMT_TN3270, 1, program);
208 	    HTAddParam(&command, FMT_TN3270, 2, hostname);
209 	    HTAddParam(&command, FMT_TN3270, 3, port);
210 	    HTEndParam(&command, FMT_TN3270, 3);
211 	}
212 	break;
213 
214     case telnet:
215 	if ((program = HTGetProgramPath(ppTELNET)) != NULL) {
216 	    HTAddParam(&command, FMT_TELNET, 1, program);
217 	    HTAddParam(&command, FMT_TELNET, 2, hostname);
218 	    HTAddParam(&command, FMT_TELNET, 3, port);
219 	    HTEndParam(&command, FMT_TELNET, 3);
220 	}
221 	break;
222     }
223 
224     LYSystem(command);
225 #define TELNET_DONE
226 #endif /* unix */
227 
228 /* VMS varieties */
229 #if !defined(TELNET_DONE) && (defined(MULTINET))
230     if (login_protocol == rlogin) {
231 	HTSprintf0(&command, "RLOGIN%s%s%s%s%s %s",	/*lm 930713 */
232 		   user ? "/USERNAME=\"" : "",
233 		   NonNull(user),
234 		   user ? "\"" : "",
235 		   port ? "/PORT=" : "",
236 		   NonNull(port),
237 		   hostname);
238 
239     } else if (login_protocol == tn3270) {
240 	HTSprintf0(&command, "TELNET/TN3270 %s%s %s",
241 		   port ? "/PORT=" : "",
242 		   NonNull(port),
243 		   hostname);
244 
245     } else {			/* TELNET */
246 	HTSprintf0(&command, "TELNET %s%s %s",
247 		   port ? "/PORT=" : "",
248 		   NonNull(port),
249 		   hostname);
250     }
251 
252     do_system(command);
253 #define TELNET_DONE
254 #endif /* MULTINET */
255 
256 #if !defined(TELNET_DONE) && defined(WIN_TCP)
257     if ((cp = getenv("WINTCP_COMMAND_STYLE")) != NULL &&
258 	0 == strncasecomp(cp, "VMS", 3)) {	/* VMS command syntax */
259 	if (login_protocol == rlogin) {
260 	    HTSprintf0(&command, "RLOGIN%s%s%s%s%s %s",		/*lm 930713 */
261 		       user ? "/USERNAME=\"" : "",
262 		       NonNull(user),
263 		       user ? "\"" : "",
264 		       port ? "/PORT=" : "",
265 		       NonNull(port),
266 		       hostname);
267 
268 	} else if (login_protocol == tn3270) {
269 	    HTSprintf0(&command, "TELNET/TN3270 %s%s %s",
270 		       port ? "/PORT=" : "",
271 		       NonNull(port),
272 		       hostname);
273 
274 	} else {		/* TELNET */
275 	    HTSprintf0(&command, "TELNET %s%s %s",
276 		       port ? "/PORT=" : "",
277 		       NonNull(port),
278 		       hostname);
279 	}
280 
281     } else {			/* UNIX command syntax */
282 	if (login_protocol == rlogin) {
283 	    HTSprintf0(&command, "RLOGIN %s%s%s%s%s",
284 		       hostname,
285 		       user ? " -l " : "",
286 		       user ? "\"" : "",
287 		       NonNull(user),
288 		       user ? "\"" : "");
289 
290 	} else if (login_protocol == tn3270) {
291 	    HTSprintf0(&command, "TN3270 %s %s",
292 		       hostname,
293 		       NonNull(port));
294 
295 	} else {		/* TELNET */
296 	    HTSprintf0(&command, "TELNET %s %s",
297 		       hostname,
298 		       NonNull(port));
299 	}
300     }
301 
302     do_system(command);
303 #define TELNET_DONE
304 #endif /* WIN_TCP */
305 
306 #if !defined(TELNET_DONE) && defined(UCX)
307     if (login_protocol == rlogin) {
308 	HTSprintf0(&command, "RLOGIN%s%s%s %s %s",
309 		   user ? "/USERNAME=\"" : "",
310 		   NonNull(user),
311 		   user ? "\"" : "",
312 		   hostname,
313 		   NonNull(port));
314 
315     } else if (login_protocol == tn3270) {
316 	HTSprintf0(&command, "TN3270 %s %s",
317 		   hostname,
318 		   NonNull(port));
319 
320     } else {			/* TELNET */
321 	HTSprintf0(&command, "TELNET %s %s",
322 		   hostname,
323 		   NonNull(port));
324     }
325 
326     do_system(command);
327 #define TELNET_DONE
328 #endif /* UCX */
329 
330 #if !defined(TELNET_DONE) && defined(CMU_TCP)
331     if (login_protocol == telnet) {
332 	HTSprintf0(&command, "TELNET %s%s %s",
333 		   port ? "/PORT=" : "",
334 		   NonNull(port),
335 		   hostname);
336 	do_system(command);
337     } else {
338 	printf("\nSorry, this browser was compiled without the %s access option.\n",
339 	       acc_method);
340 	printf("\nPress <return> to return to Lynx.");
341 	LYgetch();
342 	HadVMSInterrupt = FALSE;
343     }
344 #define TELNET_DONE
345 #endif /* CMU_TCP */
346 
347 #if !defined(TELNET_DONE) && defined(SOCKETSHR_TCP)
348     if (getenv("MULTINET_SOCKET_LIBRARY") != NULL) {
349 	if (login_protocol == rlogin) {
350 	    HTSprintf0(&command, "MULTINET RLOGIN%s%s%s%s %s",	/*lm 930713 */
351 		       user ? "/USERNAME=" : "",
352 		       NonNull(user),
353 		       port ? "/PORT=" : "",
354 		       NonNull(port),
355 		       hostname);
356 
357 	} else if (login_protocol == tn3270) {
358 	    HTSprintf0(&command, "MULTINET TELNET/TN3270 %s%s %s",
359 		       port ? "/PORT=" : "",
360 		       NonNull(port),
361 		       hostname);
362 
363 	} else {		/* TELNET */
364 	    HTSprintf0(&command, "MULTINET TELNET %s%s %s",
365 		       port ? "/PORT=" : "",
366 		       NonNull(port),
367 		       hostname);
368 	}
369 
370 	do_system(command);
371 	return HT_NO_DATA;	/* Ok - it was done but no data */
372     } else if ((cp = getenv("WINTCP_COMMAND_STYLE")) != NULL) {
373 	if (0 == strncasecomp(cp, "VMS", 3)) {	/* VMS command syntax */
374 	    if (login_protocol == rlogin) {
375 		HTSprintf0(&command, "RLOGIN%s%s%s%s %s",	/*lm 930713 */
376 			   user ? "/USERNAME=" : "",
377 			   NonNull(user),
378 			   port ? "/PORT=" : "",
379 			   NonNull(port),
380 			   hostname);
381 	    } else if (login_protocol == tn3270) {
382 		HTSprintf0(&command, "TELNET/TN3270 %s%s %s",
383 			   port ? "/PORT=" : "",
384 			   NonNull(port),
385 			   hostname);
386 	    } else {		/* TELNET */
387 		HTSprintf0(&command, "TELNET %s%s %s",
388 			   port ? "/PORT=" : "",
389 			   NonNull(port),
390 			   hostname);
391 	    }
392 	} else {		/* UNIX command syntax */
393 	    if (login_protocol == rlogin) {
394 		HTSprintf0(&command, "RLOGIN %s%s%s",
395 			   hostname,
396 			   user ? " -l " : "",
397 			   NonNull(user));
398 	    } else if (login_protocol == tn3270) {
399 		HTSprintf0(&command, "TN3270 %s %s",
400 			   hostname,
401 			   NonNull(port));
402 	    } else {		/* TELNET */
403 		HTSprintf0(&command, "TELNET %s %s",
404 			   hostname,
405 			   NonNull(port));
406 	    }
407 	}
408 
409 	do_system(command);
410 	return HT_NO_DATA;	/* Ok - it was done but no data */
411     } else if (getenv("UCX$DEVICE") != NULL
412 	       || getenv("TCPIP$DEVICE") != NULL) {
413 	if (login_protocol == rlogin) {
414 	    HTSprintf0(&command, "RLOGIN%s%s %s %s",
415 		       user ? "/USERNAME=" : "",
416 		       NonNull(user),
417 		       hostname,
418 		       NonNull(port));
419 
420 	} else if (login_protocol == tn3270) {
421 	    HTSprintf0(&command, "TN3270 %s %s",
422 		       hostname,
423 		       NonNull(port));
424 
425 	} else {		/* TELNET */
426 	    HTSprintf0(&command, "TELNET %s %s",
427 		       hostname,
428 		       NonNull(port));
429 	}
430 
431 	do_system(command);
432 	return HT_NO_DATA;	/* Ok - it was done but no data */
433     } else if (getenv("CMUTEK_ROOT") != NULL) {
434 	if (login_protocol == telnet) {
435 	    HTSprintf0(&command, "TELNET %s%s %s",
436 		       port ? "/PORT=" : "",
437 		       NonNull(port),
438 		       hostname);
439 	    do_system(command);
440 	} else {
441 	    printf("\nSorry, this browser was compiled without the %s access option.\n",
442 		   acc_method);
443 	    printf("\nPress <return> to return to Lynx.");
444 	    LYgetch();
445 	    HadVMSInterrupt = FALSE;
446 	}
447     } else {
448 	if (login_protocol == telnet) {
449 	    HTSprintf0(&command, "TELNET %s%s %s",
450 		       port ? "/PORT=" : "",
451 		       NonNull(port),
452 		       hostname);
453 	    do_system(command);
454 	} else {
455 	    printf("\nSorry, this browser was compiled without the %s access option.\n",
456 		   acc_method);
457 	    printf("\nPress <return> to return to Lynx.");
458 	    LYgetch();
459 	    HadVMSInterrupt = FALSE;
460 	}
461     }
462 #define TELNET_DONE
463 #endif /* SOCKETSHR_TCP */
464 
465 #if !defined(TELNET_DONE) && (defined(SIMPLE_TELNET) || defined(VM))
466     if (login_protocol == telnet) {	/* telnet only */
467 	HTSprintf0(&command, "TELNET  %s",	/* @@ Bug: port ignored */
468 		   hostname);
469 	do_system(command);
470 	return HT_NO_DATA;	/* Ok - it was done but no data */
471     }
472 #define TELNET_DONE
473 #endif
474 
475 #ifndef TELNET_DONE
476     printf("\nSorry, this browser was compiled without the %s access option.\n",
477 	   acc_method);
478     printf("\nTo access the information you must %s to %s", acc_method, hostname);
479     if (port)
480 	printf(" (port %s)", port);
481     if (user)
482 	printf("\nlogging in with username %s", user);
483     printf(".\n");
484     {
485 	printf("\nPress <return> to return to Lynx.");
486 	fflush(stdout);
487 	LYgetch();
488 #ifdef VMS
489 	HadVMSInterrupt = FALSE;
490 #endif /* VMS */
491     }
492 #endif /* !TELNET_DONE */
493     return HT_NO_DATA;
494 }
495 
496 /*	"Load a document" -- establishes a session
497  *	------------------------------------------
498  *
499  * On entry,
500  *	addr		must point to the fully qualified hypertext reference.
501  *
502  * On exit,
503  *	returns		<0	Error has occurred.
504  *			>=0	Value of file descriptor or socket to be used
505  *				 to read data.
506  *	*pFormat	Set to the format of the file, if known.
507  *			(See WWW.h)
508  *
509  */
HTLoadTelnet(const char * addr,HTParentAnchor * anchor GCC_UNUSED,HTFormat format_out GCC_UNUSED,HTStream * sink)510 static int HTLoadTelnet(const char *addr,
511 			HTParentAnchor *anchor GCC_UNUSED,
512 			HTFormat format_out GCC_UNUSED,
513 			HTStream *sink)		/* Ignored */
514 {
515     char *acc_method;
516     char *host;
517     int status;
518 
519     if (sink) {
520 	CTRACE((tfp,
521 		"HTTelnet: Can't output a live session -- must be interactive!\n"));
522 	return HT_NO_DATA;
523     }
524     acc_method = HTParse(addr, STR_FILE_URL, PARSE_ACCESS);
525 
526     host = HTParse(addr, "", PARSE_HOST);
527     if (!host || *host == '\0') {
528 	status = HT_NO_DATA;
529 	CTRACE((tfp, "HTTelnet: No host specified!\n"));
530     } else {
531 	status = remote_session(acc_method, host);
532     }
533 
534     FREE(host);
535     FREE(acc_method);
536     return status;
537 }
538 
539 #ifdef GLOBALDEF_IS_MACRO
540 #define _HTTELNET_C_1_INIT { "telnet", HTLoadTelnet, NULL }
541 #define _HTTELNET_C_2_INIT { "rlogin", HTLoadTelnet, NULL }
542 #define _HTTELNET_C_3_INIT { "tn3270", HTLoadTelnet, NULL }
543 GLOBALDEF(HTProtocol, HTTelnet, _HTTELNET_C_1_INIT);
544 GLOBALDEF(HTProtocol, HTRlogin, _HTTELNET_C_2_INIT);
545 GLOBALDEF(HTProtocol, HTTn3270, _HTTELNET_C_3_INIT);
546 #else
547 GLOBALDEF HTProtocol HTTelnet =
548 {"telnet", HTLoadTelnet, NULL};
549 GLOBALDEF HTProtocol HTRlogin =
550 {"rlogin", HTLoadTelnet, NULL};
551 GLOBALDEF HTProtocol HTTn3270 =
552 {"tn3270", HTLoadTelnet, NULL};
553 #endif /* GLOBALDEF_IS_MACRO */
554