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