xref: /openbsd/usr.bin/telnet/main.c (revision 898184e3)
1 /*	$OpenBSD: main.c,v 1.20 2010/07/03 04:44:51 guenther Exp $	*/
2 /*	$NetBSD: main.c,v 1.5 1996/02/28 21:04:05 thorpej Exp $	*/
3 
4 /*
5  * Copyright (c) 1988, 1990, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include "telnet_locl.h"
34 
35 /* These values need to be the same as defined in libtelnet/kerberos5.c */
36 /* Either define them in both places, or put in some common header file. */
37 #define OPTS_FORWARD_CREDS	0x00000002
38 #define OPTS_FORWARDABLE_CREDS	0x00000001
39 
40 #ifdef KRB5
41 #define FORWARD
42 /* XXX ugly hack to setup dns-proxy stuff */
43 #define Authenticator asn1_Authenticator
44 #include <kerberosV/krb5.h>
45 #endif
46 
47 #ifdef KRB4
48 #include <kerberosIV/krb.h>
49 #endif
50 
51 #ifdef FORWARD
52 int forward_flags;
53 static int default_forward=0;
54 #endif
55 
56 int family = AF_UNSPEC;
57 u_int rtableid;
58 
59 /*
60  * Initialize variables.
61  */
62     void
63 tninit()
64 {
65     init_terminal();
66 
67     init_network();
68 
69     init_telnet();
70 
71     init_sys();
72 
73 #if defined(TN3270)
74     init_3270();
75 #endif
76 }
77 
78 	void
79 usage()
80 {
81 	extern char *__progname;
82 
83 	(void)fprintf(stderr,
84 #if defined(TN3270)
85 	    "usage: %s [-d] [-n filename] [-t commandname] [sysname [port]]\n",
86 # else
87 	    "usage: %s [-468acdEFfKLrx] [-b hostalias] [-e escapechar] "
88 	    "[-k realm]\n"
89 	    "\t[-l user] [-n tracefile] [-V rtable] [-X authtype] "
90 	    "[host [port]]\n",
91 #endif
92 	    __progname);
93 
94 	exit(1);
95 }
96 
97 
98 #ifdef KRB5
99 static void
100 krb5_init(void)
101 {
102     krb5_context context;
103     krb5_error_code ret;
104 
105     ret = krb5_init_context(&context);
106     if (ret)
107 	return;
108 
109 #if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
110     if (krb5_config_get_bool (context, NULL,
111          "libdefaults", "forward", NULL)) {
112            forward_flags |= OPTS_FORWARD_CREDS;
113            default_forward=1;
114     }
115     if (krb5_config_get_bool (context, NULL,
116          "libdefaults", "forwardable", NULL)) {
117            forward_flags |= OPTS_FORWARDABLE_CREDS;
118            default_forward=1;
119     }
120 #endif
121 #ifdef  ENCRYPTION
122     if (krb5_config_get_bool (context, NULL,
123         "libdefaults", "encrypt", NULL)) {
124           encrypt_auto(1);
125           decrypt_auto(1);
126 	  wantencryption = 1;
127           EncryptVerbose(1);
128         }
129 #endif
130 
131     krb5_free_context(context);
132 }
133 #endif
134 
135 /*
136  * main.  Parse arguments, invoke the protocol or command parser.
137  */
138 
139 	int
140 main(argc, argv)
141 	int argc;
142 	char *argv[];
143 {
144 	extern char *optarg;
145 	extern int optind;
146 	int ch;
147 	char *user, *alias;
148 	const char *errstr;
149 #ifdef	FORWARD
150 	extern int forward_flags;
151 #endif	/* FORWARD */
152 
153 #ifdef KRB5
154 	krb5_init();
155 #endif
156 
157 	tninit();		/* Clear out things */
158 
159 	TerminalSaveState();
160 
161 	if ((prompt = strrchr(argv[0], '/')))
162 		++prompt;
163 	else
164 		prompt = argv[0];
165 
166 	user = alias = NULL;
167 
168 	rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
169 
170 	/*
171 	 * if AUTHENTICATION and ENCRYPTION is set autologin will be
172 	 * set to true after the getopt switch; unless the -K option is
173 	 * passed
174 	 */
175 	autologin = -1;
176 
177 	while ((ch = getopt(argc, argv, "4678DEKLS:X:ab:cde:fFk:l:n:rt:V:x"))
178 	    != -1) {
179 		switch(ch) {
180 		case '4':
181 			family = AF_INET;
182 			break;
183 		case '6':
184 			family = AF_INET6;
185 			break;
186 		case '8':
187 			eight = 3;	/* binary output and input */
188 			break;
189 		case '7':
190 			eight = 0;
191 			break;
192 		case 'D': {
193 			/* sometimes we don't want a mangled display */
194 			char *p;
195 			if((p = getenv("DISPLAY")))
196 				env_define("DISPLAY", (unsigned char*)p);
197 			break;
198 		}
199 
200 		case 'E':
201 			rlogin = escape = _POSIX_VDISABLE;
202 			break;
203 		case 'K':
204 #ifdef	AUTHENTICATION
205 			autologin = 0;
206 #endif
207 			break;
208 		case 'L':
209 			eight |= 2;	/* binary output only */
210 			break;
211 		case 'S':
212 		    {
213 #ifdef	HAS_GETTOS
214 			extern int tos;
215 
216 			if ((tos = parsetos(optarg, "tcp")) < 0)
217 				fprintf(stderr, "%s%s%s%s\n",
218 					prompt, ": Bad TOS argument '",
219 					optarg,
220 					"; will try to use default TOS");
221 #else
222 			fprintf(stderr,
223 			   "%s: Warning: -S ignored, no parsetos() support.\n",
224 								prompt);
225 #endif
226 		    }
227 			break;
228 		case 'X':
229 #ifdef	AUTHENTICATION
230 			auth_disable_name(optarg);
231 #endif
232 			break;
233 		case 'a':
234 			autologin = 1;
235 			break;
236 		case 'c':
237 			skiprc = 1;
238 			break;
239 		case 'd':
240 			debug = 1;
241 			break;
242 		case 'e':
243 			set_escape_char(optarg);
244 			break;
245 		case 'f':
246 #if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
247 			if ((forward_flags & OPTS_FORWARD_CREDS) &&
248 			    !default_forward) {
249 			    fprintf(stderr,
250 				    "%s: Only one of -f and -F allowed.\n",
251 				    prompt);
252 			    usage();
253 			}
254 			forward_flags |= OPTS_FORWARD_CREDS;
255 #else
256 			fprintf(stderr,
257 			 "%s: Warning: -f ignored, no Kerberos V5 support.\n",
258 				prompt);
259 #endif
260 			break;
261 		case 'F':
262 #if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
263 			if ((forward_flags & OPTS_FORWARD_CREDS) &&
264 			    !default_forward) {
265 			    fprintf(stderr,
266 				    "%s: Only one of -f and -F allowed.\n",
267 				    prompt);
268 			    usage();
269 			}
270 			forward_flags |= OPTS_FORWARD_CREDS;
271 			forward_flags |= OPTS_FORWARDABLE_CREDS;
272 #else
273 			fprintf(stderr,
274 			 "%s: Warning: -F ignored, no Kerberos V5 support.\n",
275 				prompt);
276 #endif
277 			break;
278 		case 'k':
279 #if defined(AUTHENTICATION) && defined(KRB4)
280 		    {
281 			extern char *dest_realm, dst_realm_buf[];
282 			extern int dst_realm_sz;
283 			dest_realm = dst_realm_buf;
284 			(void)strncpy(dest_realm, optarg, dst_realm_sz);
285 		    }
286 #else
287 			fprintf(stderr,
288 			   "%s: Warning: -k ignored, no Kerberos V4 support.\n",
289 								prompt);
290 #endif
291 			break;
292 		case 'l':
293 			autologin = -1;
294 			user = optarg;
295 			break;
296 		case 'b':
297 			alias = optarg;
298 			break;
299 		case 'n':
300 #if defined(TN3270) && defined(unix)
301 			/* distinguish between "-n oasynch" and "-noasynch" */
302 			if (argv[optind - 1][0] == '-' && argv[optind - 1][1]
303 			    == 'n' && argv[optind - 1][2] == 'o') {
304 				if (!strcmp(optarg, "oasynch")) {
305 					noasynchtty = 1;
306 					noasynchnet = 1;
307 				} else if (!strcmp(optarg, "oasynchtty"))
308 					noasynchtty = 1;
309 				else if (!strcmp(optarg, "oasynchnet"))
310 					noasynchnet = 1;
311 			} else
312 #endif	/* defined(TN3270) && defined(unix) */
313 				SetNetTrace(optarg);
314 			break;
315 		case 'r':
316 			rlogin = '~';
317 			break;
318 		case 't':
319 #if defined(TN3270) && defined(unix)
320 			(void)strlcpy(tline, optarg, sizeof tline);
321 			transcom = tline;
322 #else
323 			fprintf(stderr,
324 			   "%s: Warning: -t ignored, no TN3270 support.\n",
325 								prompt);
326 #endif
327 			break;
328 		case 'V':
329 			rtableid = (unsigned int)strtonum(optarg, 0,
330 			    RT_TABLEID_MAX, &errstr);
331 			if (errstr) {
332 				fprintf(stderr, "%s: Warning: "
333 				    "-V ignored, rtable %s: %s\n",
334 				    prompt, errstr, optarg);
335 			}
336 			break;
337 		case 'x':
338 #ifdef ENCRYPTION
339 			encrypt_auto(1);
340 			decrypt_auto(1);
341 			wantencryption = 1;
342 			EncryptVerbose(1);
343 #else
344 			fprintf(stderr,
345 			    "%s: Warning: -x ignored, no ENCRYPT support.\n",
346 								prompt);
347 #endif
348 			break;
349 		case '?':
350 		default:
351 			usage();
352 			/* NOTREACHED */
353 		}
354 	}
355 
356 	if (autologin == -1) {
357 #if defined(AUTHENTICATION)
358 		if(check_krb4_tickets() || check_krb5_tickets())
359 			autologin = 1;
360 #endif
361 #if defined(ENCRYPTION)
362 		encrypt_auto(1);
363 		decrypt_auto(1);
364 #endif
365 	}
366 
367 	if (autologin == -1)
368 		autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1;
369 
370 	argc -= optind;
371 	argv += optind;
372 
373 	if (argc) {
374 		char *args[7], **argp = args;
375 
376 		if (argc > 2)
377 			usage();
378 		*argp++ = prompt;
379 		if (user) {
380 			*argp++ = "-l";
381 			*argp++ = user;
382 		}
383 		if (alias) {
384 			*argp++ = "-b";
385 			*argp++ = alias;
386 		}
387 		*argp++ = argv[0];		/* host */
388 		if (argc > 1)
389 			*argp++ = argv[1];	/* port */
390 		*argp = 0;
391 
392 		if (setjmp(toplevel) != 0)
393 			Exit(0);
394 		if (tn(argp - args, args) == 1)
395 			return (0);
396 		else
397 			return (1);
398 	}
399 	(void)setjmp(toplevel);
400 	for (;;) {
401 #ifdef TN3270
402 		if (shell_active)
403 			shell_continue();
404 		else
405 #endif
406 			command(1, 0, 0);
407 	}
408 	return 0;
409 }
410