Annotation of libwww/Library/src/HTTelnet.c, revision 2.11
1.1 timbl 1: /* Telnet Acees, Roligin, etc HTAccess.c
2: ** ==========================
3: **
4: ** Authors
5: ** TBL Tim Berners-Lee timbl@info.cern.ch
6: ** JFG Jean-Francois Groff jgh@next.com
7: ** DD Denis DeLaRoca (310) 825-4580 <CSP1DWD@mvs.oac.ucla.edu>
8: ** History
9: ** 8 Jun 92 Telnet hopping prohibited as telnet is not secure (TBL)
10: ** 26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. (JFG)
11: ** 6 Oct 92 Moved HTClientHost and logfile into here. (TBL)
12: ** 17 Dec 92 Tn3270 added, bug fix. (DD)
13: ** 2 Feb 93 Split from HTAccess.c. Registration.(TBL)
2.11 ! luotonen 14: ** 2 May 94 Fixed security hole with illegal characters in host
! 15: ** and user names (code from Mosaic/Eric Bina).
1.1 timbl 16: */
17:
18: /* Implements:
19: */
1.2 timbl 20: #include "HTTelnet.h"
1.1 timbl 21:
22: #include "HTParse.h"
23: #include "HTUtils.h"
24: #include "HTAnchor.h"
25: #include "HTTP.h"
26: #include "HTFile.h"
27: #include <errno.h>
28: #include <stdio.h>
29:
30: #include "tcp.h"
31: #include "HText.h"
32:
33: #include "HTAccess.h"
1.3 timbl 34: #include "HTAlert.h"
1.1 timbl 35:
36: #define HT_NO_DATA -9999
37:
38:
2.11 ! luotonen 39: /* make a string secure for passage to the
! 40: ** system() command. Make it contain only alphanumneric
! 41: ** characters, or the characters '.', '-', '_', '+'.
! 42: ** Also remove leading '-' or '+'.
! 43: ** -----------------------------------------------------
! 44: ** Function taken from Mosaic's HTTelnet.c.
! 45: */
! 46: PRIVATE void make_system_secure ARGS1(char *, str)
! 47: {
! 48: char *ptr1, *ptr2;
! 49:
! 50: if ((str == NULL)||(*str == '\0'))
! 51: {
! 52: return;
! 53: }
! 54:
! 55: /*
! 56: * remove leading '-' or '+' by making it into whitespace that
! 57: * will be stripped later.
! 58: */
! 59: if ((*str == '-')||(*str == '+'))
! 60: {
! 61: *str = ' ';
! 62: }
! 63:
! 64: ptr1 = ptr2 = str;
! 65:
! 66: while (*ptr1 != '\0')
! 67: {
! 68: if ((!isalpha((int)*ptr1))&&(!isdigit((int)*ptr1))&&
! 69: (*ptr1 != '.')&&(*ptr1 != '_')&&
! 70: (*ptr1 != '+')&&(*ptr1 != '-'))
! 71: {
! 72: ptr1++;
! 73: }
! 74: else
! 75: {
! 76: *ptr2 = *ptr1;
! 77: ptr2++;
! 78: ptr1++;
! 79: }
! 80: }
! 81: *ptr2 = *ptr1;
! 82: }
! 83:
! 84:
! 85:
1.1 timbl 86: /* Telnet or "rlogin" access
87: ** -------------------------
88: */
89: PRIVATE int remote_session ARGS2(char *, access, char *, host)
90: {
91: char * user = host;
92: char * hostname = strchr(host, '@');
93: char * port = strchr(host, ':');
94: char command[256];
95: enum _login_protocol { telnet, rlogin, tn3270 } login_protocol =
96: strcmp(access, "rlogin") == 0 ? rlogin :
97: strcmp(access, "tn3270") == 0 ? tn3270 : telnet;
98:
99: if (hostname) {
100: *hostname++ = 0; /* Split */
101: } else {
102: hostname = host;
103: user = 0; /* No user specified */
104: }
105: if (port) *port++ = 0; /* Split */
106:
2.11 ! luotonen 107: /*
! 108: * Make user and hostname secure by removing leading '-' or '+'.
! 109: * and allowing only alphanumeric, '.', '_', '+', and '-'.
! 110: */
! 111: make_system_secure(user);
! 112: make_system_secure(hostname);
1.1 timbl 113:
114: /* If the person is already telnetting etc, forbid hopping */
115: /* This is a security precaution, for us and remote site */
116:
2.6 timbl 117: if (HTSecure) {
1.1 timbl 118:
119: #ifdef TELNETHOPPER_MAIL
120: sprintf(command,
121: "finger @%s | mail -s \"**telnethopper %s\" tbl@dxcern.cern.ch",
122: HTClientHost, HTClientHost);
123: system(command);
124: #endif
125: printf("\n\nSorry, but the service you have selected is one\n");
126: printf("to which you have to log in. If you were running www\n");
127: printf("on your own computer, you would be automatically connected.\n");
128: printf("For security reasons, this is not allowed when\n");
129: printf("you log in to this information service remotely.\n\n");
130:
131: printf("You can manually connect to this service using %s\n",
132: access);
133: printf("to host %s", hostname);
134: if (user) printf(", user name %s", user);
135: if (port) printf(", port %s", port);
136: printf(".\n\n");
137: return HT_NO_DATA;
138: }
139:
140: /* Not all telnet servers get it even if user name is specified
141: ** so we always tell the guy what to log in as
142: */
143: if (user) printf("When you are connected, log in as %s\n", user);
144:
145: #ifdef NeXT
146: #define TELNET_MINUS_L
147: #endif
148: #ifdef ultrix
149: #define TELNET_MINUS_L
150: #endif
151:
152: #ifdef TELNET_MINUS_L
153: sprintf(command, "%s%s%s %s %s", access,
154: user ? " -l " : "",
155: user ? user : "",
156: hostname,
157: port ? port : "");
158:
159: if (TRACE) fprintf(stderr, "HTaccess: Command is: %s\n", command);
160: system(command);
161: return HT_NO_DATA; /* Ok - it was done but no data */
162: #define TELNET_DONE
1.2 timbl 163: #endif
1.1 timbl 164:
165: /* Most unix machines suppport username only with rlogin */
166: #ifdef unix
167: #ifndef TELNET_DONE
168: if (login_protocol != rlogin) {
169: sprintf(command, "%s %s %s", access,
170: hostname,
171: port ? port : "");
172: } else {
173: sprintf(command, "%s%s%s %s %s", access,
174: user ? " -l " : "",
175: user ? user : "",
176: hostname,
177: port ? port : "");
178: }
179: if (TRACE) fprintf(stderr, "HTaccess: Command is: %s\n", command);
180: system(command);
181: return HT_NO_DATA; /* Ok - it was done but no data */
182: #define TELNET_DONE
183: #endif
184: #endif
185:
186: #ifdef MULTINET /* VMS varieties */
187: if (login_protocol == telnet) {
188: sprintf(command, "TELNET %s%s %s",
189: port ? "/PORT=" : "",
190: port ? port : "",
191: hostname);
192: } else if (login_protocol == tn3270) {
2.8 duns 193: sprintf(command, "TELNET/TN3270 %s%s %s",
1.1 timbl 194: port ? "/PORT=" : "",
195: port ? port : "",
196: hostname);
197: } else {
2.7 timbl 198: sprintf(command, "RLOGIN%s%s%s%s %s", /*lm 930713 */
1.1 timbl 199: user ? "/USERNAME=" : "",
200: user ? user : "",
201: port ? "/PORT=" : "",
202: port ? port : "",
203: hostname);
204: }
205: if (TRACE) fprintf(stderr, "HTaccess: Command is: %s\n", command);
206: system(command);
207: return HT_NO_DATA; /* Ok - it was done but no data */
208: #define TELNET_DONE
209: #endif
210:
211: #ifdef UCX
212: #define SIMPLE_TELNET
213: #endif
214: #ifdef VM
215: #define SIMPLE_TELNET
216: #endif
217: #ifdef SIMPLE_TELNET
218: if (login_protocol == telnet) { /* telnet only */
219: sprintf(command, "TELNET %s", /* @@ Bug: port ignored */
220: hostname);
221: if (TRACE) fprintf(stderr, "HTaccess: Command is: %s\n", command);
222: system(command);
223: return HT_NO_DATA; /* Ok - it was done but no data */
224: }
225: #endif
226:
227: #ifndef TELNET_DONE
228: fprintf(stderr,
229: "Sorry, this browser was compiled without the %s access option.\n",
230: access);
231: fprintf(stderr,
232: "\nTo access the information you must %s to %s", access, hostname);
233: if (port) fprintf(stderr," (port %s)", port);
234: if (user) fprintf(stderr," logging in with username %s", user);
235: fprintf(stderr, ".\n");
236: return -1;
237: #endif
238: }
239:
240: /* "Load a document" -- establishes a session
241: ** ------------------------------------------
242: **
243: ** On entry,
244: ** addr must point to the fully qualified hypertext reference.
245: **
246: ** On exit,
247: ** returns <0 Error has occured.
248: ** >=0 Value of file descriptor or socket to be used
249: ** to read data.
250: ** *pFormat Set to the format of the file, if known.
251: ** (See WWW.h)
252: **
253: */
2.9 timbl 254: PRIVATE int HTLoadTelnet ARGS1(HTRequest *, request)
1.1 timbl 255: {
1.2 timbl 256: char * access;
2.9 timbl 257: CONST char * addr = HTAnchor_physical(request->anchor);
1.2 timbl 258: char * host;
259: int status;
2.10 luotonen 260:
2.9 timbl 261: if (request->output_stream) {
1.2 timbl 262: HTAlert("Can't output a live session -- it has to be interactive");
263: return HT_NO_ACCESS;
264: }
265: access = HTParse(addr, "file:", PARSE_ACCESS);
1.1 timbl 266:
1.2 timbl 267: host = HTParse(addr, "", PARSE_HOST);
2.10 luotonen 268:
269: /*
270: * Fix a security hole with telnet: URLs that contain semicolon
271: * after the machine name. This would cause system commands to
272: * be executed after the telnet session is finished, e.g.
273: *
274: * telnet://some.host; rm some_important_file
275: *
276: * or even more destructive:
277: *
278: * telnet://some.host; rm -fr * (don't try this!!)
279: */
280: {
281: char * semi = strchr(host,';');
282: if (semi) *semi = 0;
283: }
284:
1.2 timbl 285: status = remote_session(access, host);
1.1 timbl 286:
287: free(host);
288: free(access);
289: return status;
290: }
291:
292:
2.8 duns 293: GLOBALDEF PUBLIC HTProtocol HTTelnet = { "telnet", HTLoadTelnet, NULL };
294: GLOBALDEF PUBLIC HTProtocol HTRlogin = { "rlogin", HTLoadTelnet, NULL };
295: GLOBALDEF PUBLIC HTProtocol HTTn3270 = { "tn3270", HTLoadTelnet, NULL };
1.1 timbl 296:
297:
Webmaster