xref: /openbsd-src/usr.bin/telnet/main.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: main.c,v 1.16 2007/03/15 22:51:16 jmc 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 #ifndef lint
34 static char copyright[] =
35 "@(#) Copyright (c) 1988, 1990, 1993\n\
36 	The Regents of the University of California.  All rights reserved.\n";
37 #endif /* not lint */
38 
39 #include "telnet_locl.h"
40 
41 /* These values need to be the same as defined in libtelnet/kerberos5.c */
42 /* Either define them in both places, or put in some common header file. */
43 #define OPTS_FORWARD_CREDS	0x00000002
44 #define OPTS_FORWARDABLE_CREDS	0x00000001
45 
46 #ifdef KRB5
47 #define FORWARD
48 /* XXX ugly hack to setup dns-proxy stuff */
49 #define Authenticator asn1_Authenticator
50 #include <kerberosV/krb5.h>
51 #endif
52 
53 #ifdef KRB4
54 #include <kerberosIV/krb.h>
55 #endif
56 
57 #ifdef FORWARD
58 int forward_flags;
59 static int default_forward=0;
60 #endif
61 
62 int family = AF_UNSPEC;
63 
64 /*
65  * Initialize variables.
66  */
67     void
68 tninit()
69 {
70     init_terminal();
71 
72     init_network();
73 
74     init_telnet();
75 
76     init_sys();
77 
78 #if defined(TN3270)
79     init_3270();
80 #endif
81 }
82 
83 	void
84 usage()
85 {
86 	extern char *__progname;
87 
88 	(void)fprintf(stderr,
89 #if defined(TN3270)
90 	    "usage: %s [-d] [-n filename] [-t commandname] [sysname [port]]\n",
91 # else
92 	    "usage: %s [-468acdEFfKLrx] [-b hostalias] [-e escapechar] "
93 	    "[-k realm]\n"
94 	    "\t[-l user] [-n tracefile] [-X authtype] [host [port]]\n",
95 #endif
96 	    __progname);
97 
98 	exit(1);
99 }
100 
101 
102 #ifdef KRB5
103 static void
104 krb5_init(void)
105 {
106     krb5_context context;
107     krb5_error_code ret;
108 
109     ret = krb5_init_context(&context);
110     if (ret)
111 	return;
112 
113 #if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
114     if (krb5_config_get_bool (context, NULL,
115          "libdefaults", "forward", NULL)) {
116            forward_flags |= OPTS_FORWARD_CREDS;
117            default_forward=1;
118     }
119     if (krb5_config_get_bool (context, NULL,
120          "libdefaults", "forwardable", NULL)) {
121            forward_flags |= OPTS_FORWARDABLE_CREDS;
122            default_forward=1;
123     }
124 #endif
125 #ifdef  ENCRYPTION
126     if (krb5_config_get_bool (context, NULL,
127         "libdefaults", "encrypt", NULL)) {
128           encrypt_auto(1);
129           decrypt_auto(1);
130 	  wantencryption = 1;
131           EncryptVerbose(1);
132         }
133 #endif
134 
135     krb5_free_context(context);
136 }
137 #endif
138 
139 /*
140  * main.  Parse arguments, invoke the protocol or command parser.
141  */
142 
143 	int
144 main(argc, argv)
145 	int argc;
146 	char *argv[];
147 {
148 	extern char *optarg;
149 	extern int optind;
150 	int ch;
151 	char *user, *alias;
152 #ifdef	FORWARD
153 	extern int forward_flags;
154 #endif	/* FORWARD */
155 
156 #ifdef KRB5
157 	krb5_init();
158 #endif
159 
160 	tninit();		/* Clear out things */
161 
162 	TerminalSaveState();
163 
164 	if ((prompt = strrchr(argv[0], '/')))
165 		++prompt;
166 	else
167 		prompt = argv[0];
168 
169 	user = alias = NULL;
170 
171 	rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
172 
173 	/*
174 	 * if AUTHENTICATION and ENCRYPTION is set autologin will be
175 	 * set to true after the getopt switch; unless the -K option is
176 	 * passed
177 	 */
178 	autologin = -1;
179 
180 	while ((ch = getopt(argc, argv, "4678DEKLS:X:ab:cde:fFk:l:n:rt:x"))
181 	    != -1) {
182 		switch(ch) {
183 		case '4':
184 			family = AF_INET;
185 			break;
186 		case '6':
187 			family = AF_INET6;
188 			break;
189 		case '8':
190 			eight = 3;	/* binary output and input */
191 			break;
192 		case '7':
193 			eight = 0;
194 			break;
195 		case 'D': {
196 			/* sometimes we don't want a mangled display */
197 			char *p;
198 			if((p = getenv("DISPLAY")))
199 				env_define("DISPLAY", (unsigned char*)p);
200 			break;
201 		}
202 
203 		case 'E':
204 			rlogin = escape = _POSIX_VDISABLE;
205 			break;
206 		case 'K':
207 #ifdef	AUTHENTICATION
208 			autologin = 0;
209 #endif
210 			break;
211 		case 'L':
212 			eight |= 2;	/* binary output only */
213 			break;
214 		case 'S':
215 		    {
216 #ifdef	HAS_GETTOS
217 			extern int tos;
218 
219 			if ((tos = parsetos(optarg, "tcp")) < 0)
220 				fprintf(stderr, "%s%s%s%s\n",
221 					prompt, ": Bad TOS argument '",
222 					optarg,
223 					"; will try to use default TOS");
224 #else
225 			fprintf(stderr,
226 			   "%s: Warning: -S ignored, no parsetos() support.\n",
227 								prompt);
228 #endif
229 		    }
230 			break;
231 		case 'X':
232 #ifdef	AUTHENTICATION
233 			auth_disable_name(optarg);
234 #endif
235 			break;
236 		case 'a':
237 			autologin = 1;
238 			break;
239 		case 'c':
240 			skiprc = 1;
241 			break;
242 		case 'd':
243 			debug = 1;
244 			break;
245 		case 'e':
246 			set_escape_char(optarg);
247 			break;
248 		case 'f':
249 #if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
250 			if ((forward_flags & OPTS_FORWARD_CREDS) &&
251 			    !default_forward) {
252 			    fprintf(stderr,
253 				    "%s: Only one of -f and -F allowed.\n",
254 				    prompt);
255 			    usage();
256 			}
257 			forward_flags |= OPTS_FORWARD_CREDS;
258 #else
259 			fprintf(stderr,
260 			 "%s: Warning: -f ignored, no Kerberos V5 support.\n",
261 				prompt);
262 #endif
263 			break;
264 		case 'F':
265 #if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
266 			if ((forward_flags & OPTS_FORWARD_CREDS) &&
267 			    !default_forward) {
268 			    fprintf(stderr,
269 				    "%s: Only one of -f and -F allowed.\n",
270 				    prompt);
271 			    usage();
272 			}
273 			forward_flags |= OPTS_FORWARD_CREDS;
274 			forward_flags |= OPTS_FORWARDABLE_CREDS;
275 #else
276 			fprintf(stderr,
277 			 "%s: Warning: -F ignored, no Kerberos V5 support.\n",
278 				prompt);
279 #endif
280 			break;
281 		case 'k':
282 #if defined(AUTHENTICATION) && defined(KRB4)
283 		    {
284 			extern char *dest_realm, dst_realm_buf[];
285 			extern int dst_realm_sz;
286 			dest_realm = dst_realm_buf;
287 			(void)strncpy(dest_realm, optarg, dst_realm_sz);
288 		    }
289 #else
290 			fprintf(stderr,
291 			   "%s: Warning: -k ignored, no Kerberos V4 support.\n",
292 								prompt);
293 #endif
294 			break;
295 		case 'l':
296 			autologin = -1;
297 			user = optarg;
298 			break;
299 		case 'b':
300 			alias = optarg;
301 			break;
302 		case 'n':
303 #if defined(TN3270) && defined(unix)
304 			/* distinguish between "-n oasynch" and "-noasynch" */
305 			if (argv[optind - 1][0] == '-' && argv[optind - 1][1]
306 			    == 'n' && argv[optind - 1][2] == 'o') {
307 				if (!strcmp(optarg, "oasynch")) {
308 					noasynchtty = 1;
309 					noasynchnet = 1;
310 				} else if (!strcmp(optarg, "oasynchtty"))
311 					noasynchtty = 1;
312 				else if (!strcmp(optarg, "oasynchnet"))
313 					noasynchnet = 1;
314 			} else
315 #endif	/* defined(TN3270) && defined(unix) */
316 				SetNetTrace(optarg);
317 			break;
318 		case 'r':
319 			rlogin = '~';
320 			break;
321 		case 't':
322 #if defined(TN3270) && defined(unix)
323 			(void)strlcpy(tline, optarg, sizeof tline);
324 			transcom = tline;
325 #else
326 			fprintf(stderr,
327 			   "%s: Warning: -t ignored, no TN3270 support.\n",
328 								prompt);
329 #endif
330 			break;
331 		case 'x':
332 #ifdef ENCRYPTION
333 			encrypt_auto(1);
334 			decrypt_auto(1);
335 			wantencryption = 1;
336 			EncryptVerbose(1);
337 #else
338 			fprintf(stderr,
339 			    "%s: Warning: -x ignored, no ENCRYPT support.\n",
340 								prompt);
341 #endif
342 			break;
343 		case '?':
344 		default:
345 			usage();
346 			/* NOTREACHED */
347 		}
348 	}
349 
350 	if (autologin == -1) {
351 #if defined(AUTHENTICATION)
352 		if(check_krb4_tickets() || check_krb5_tickets())
353 			autologin = 1;
354 #endif
355 #if defined(ENCRYPTION)
356 		encrypt_auto(1);
357 		decrypt_auto(1);
358 #endif
359 	}
360 
361 	if (autologin == -1)
362 		autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1;
363 
364 	argc -= optind;
365 	argv += optind;
366 
367 	if (argc) {
368 		char *args[7], **argp = args;
369 
370 		if (argc > 2)
371 			usage();
372 		*argp++ = prompt;
373 		if (user) {
374 			*argp++ = "-l";
375 			*argp++ = user;
376 		}
377 		if (alias) {
378 			*argp++ = "-b";
379 			*argp++ = alias;
380 		}
381 		*argp++ = argv[0];		/* host */
382 		if (argc > 1)
383 			*argp++ = argv[1];	/* port */
384 		*argp = 0;
385 
386 		if (setjmp(toplevel) != 0)
387 			Exit(0);
388 		if (tn(argp - args, args) == 1)
389 			return (0);
390 		else
391 			return (1);
392 	}
393 	(void)setjmp(toplevel);
394 	for (;;) {
395 #ifdef TN3270
396 		if (shell_active)
397 			shell_continue();
398 		else
399 #endif
400 			command(1, 0, 0);
401 	}
402 	return 0;
403 }
404