1/*
2 * Copyright (c) 1988, 1990, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if 0
35#ifndef lint
36static const char sccsid[] = "@(#)main.c	8.3 (Berkeley) 5/30/95";
37#endif
38#endif
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD: src/contrib/telnet/telnet/main.c,v 1.20 2005/01/09 10:24:45 maxim Exp $");
41
42#include <sys/param.h>
43#include <sys/socket.h>
44#include <stdlib.h>
45#include <string.h>
46#include <unistd.h>
47
48#include "ring.h"
49#include "externs.h"
50#include "defines.h"
51
52#ifdef	AUTHENTICATION
53#include <libtelnet/auth.h>
54#endif
55#ifdef	ENCRYPTION
56#include <libtelnet/encrypt.h>
57#endif
58
59/* These values need to be the same as defined in libtelnet/kerberos5.c */
60/* Either define them in both places, or put in some common header file. */
61#define OPTS_FORWARD_CREDS	0x00000002
62#define OPTS_FORWARDABLE_CREDS	0x00000001
63
64#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
65char *ipsec_policy_in = NULL;
66char *ipsec_policy_out = NULL;
67#endif
68
69extern int tos;
70
71int family = AF_UNSPEC;
72
73/*
74 * Initialize variables.
75 */
76void
77tninit(void)
78{
79    init_terminal();
80
81    init_network();
82
83    init_telnet();
84
85    init_sys();
86}
87
88static void
89usage(void)
90{
91	fprintf(stderr, "usage: %s %s%s%s%s\n",
92	    prompt,
93#ifdef	AUTHENTICATION
94	    "[-4] [-6] [-8] [-E] [-K] [-L] [-N] [-S tos] [-X atype] [-c] [-d]",
95	    "\n\t[-e char] [-k realm] [-l user] [-f/-F] [-n tracefile] ",
96#else
97	    "[-4] [-6] [-8] [-E] [-L] [-N] [-S tos] [-c] [-d]",
98	    "\n\t[-e char] [-l user] [-n tracefile] ",
99#endif
100	    "[-r] [-s src_addr] [-u] ",
101#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
102	    "[-P policy] "
103#endif
104#ifdef	ENCRYPTION
105	    "[-y] [host-name [port]]"
106#else	/* ENCRYPTION */
107	    "[host-name [port]]"
108#endif	/* ENCRYPTION */
109	);
110	exit(1);
111}
112
113/*
114 * main.  Parse arguments, invoke the protocol or command parser.
115 */
116
117int
118main(int argc, char *argv[])
119{
120	int ch;
121#if (!defined(__BEOS__) && !defined(__HAIKU__))
122	char *ep;
123	u_long ultmp;
124#endif
125	char *user;
126	char *src_addr = NULL;
127#ifdef	FORWARD
128	extern int forward_flags;
129#endif	/* FORWARD */
130
131	tninit();		/* Clear out things */
132
133	TerminalSaveState();
134
135	if ((prompt = strrchr(argv[0], '/')))
136		++prompt;
137	else
138		prompt = argv[0];
139
140	user = NULL;
141
142	rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
143#ifdef AUTHENTICATION
144	autologin = 1;
145#else
146	autologin = -1;
147#endif
148
149#ifdef	ENCRYPTION
150	encrypt_auto(1);
151	decrypt_auto(1);
152#endif
153
154#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
155#define IPSECOPT	"P:"
156#else
157#define IPSECOPT
158#endif
159
160	crlf = 1;
161
162	while ((ch = getopt(argc, argv,
163			    "468EKLNS:X:acde:fFk:l:n:rs:uxy" IPSECOPT)) != -1)
164#undef IPSECOPT
165	{
166		switch(ch) {
167		case '4':
168			family = AF_INET;
169			break;
170#ifdef INET6
171		case '6':
172			family = AF_INET6;
173			break;
174#endif
175		case '8':
176			eight = 3;	/* binary output and input */
177			break;
178		case 'E':
179			rlogin = escape = _POSIX_VDISABLE;
180			break;
181		case 'K':
182#ifdef	AUTHENTICATION
183			autologin = 0;
184#endif
185			break;
186		case 'L':
187			eight |= 2;	/* binary output only */
188			break;
189		case 'N':
190			doaddrlookup = 0;
191			break;
192		case 'S':
193#if (defined(__BEOS__) || defined(__HAIKU__))
194			fprintf(stderr, "-S option is not supported\n");
195#else
196# ifdef	HAS_GETTOS
197
198			if ((tos = parsetos(optarg, "tcp")) < 0)
199				fprintf(stderr, "%s%s%s%s\n",
200					prompt, ": Bad TOS argument '",
201					optarg,
202					"; will try to use default TOS");
203# else
204# define	MAXTOS	255
205			ultmp = strtoul(optarg, &ep, 0);
206			if (*ep || ep == optarg || ultmp > MAXTOS)
207				fprintf(stderr, "%s%s%s%s\n",
208					prompt, ": Bad TOS argument '",
209					optarg,
210					"; will try to use default TOS");
211			else
212				tos = ultmp;
213# endif
214#endif	/* __BEOS__ */
215			break;
216		case 'X':
217#ifdef	AUTHENTICATION
218			auth_disable_name(optarg);
219#endif
220			break;
221		case 'a':
222#ifdef	AUTHENTICATION
223			/* It's the default now, so ignore */
224#else
225			autologin = 1;
226#endif
227			break;
228		case 'c':
229			skiprc = 1;
230			break;
231		case 'd':
232			telnet_debug = 1;
233			break;
234		case 'e':
235			set_escape_char(optarg);
236			break;
237		case 'f':
238#ifdef	AUTHENTICATION
239#if defined(KRB5) && defined(FORWARD)
240			if (forward_flags & OPTS_FORWARD_CREDS) {
241			    fprintf(stderr,
242				    "%s: Only one of -f and -F allowed.\n",
243				    prompt);
244			    usage();
245			}
246			forward_flags |= OPTS_FORWARD_CREDS;
247#else
248			fprintf(stderr,
249			 "%s: Warning: -f ignored, no Kerberos V5 support.\n",
250				prompt);
251#endif
252#else
253			fprintf(stderr,
254			 "%s: Warning: -f ignored, no Kerberos V5 support.\n",
255				prompt);
256#endif
257			break;
258		case 'F':
259#ifdef	AUTHENTICATION
260#if defined(KRB5) && defined(FORWARD)
261			if (forward_flags & OPTS_FORWARD_CREDS) {
262			    fprintf(stderr,
263				    "%s: Only one of -f and -F allowed.\n",
264				    prompt);
265			    usage();
266			}
267			forward_flags |= OPTS_FORWARD_CREDS;
268			forward_flags |= OPTS_FORWARDABLE_CREDS;
269#else
270			fprintf(stderr,
271			 "%s: Warning: -F ignored, no Kerberos V5 support.\n",
272				prompt);
273#endif
274#else
275			fprintf(stderr,
276			 "%s: Warning: -F ignored, no Kerberos V5 support.\n",
277				prompt);
278#endif
279			break;
280		case 'k':
281#ifdef	AUTHENTICATION
282#if defined(KRB4)
283		    {
284			extern char *dest_realm, dst_realm_buf[], dst_realm_sz;
285			dest_realm = dst_realm_buf;
286			(void)strncpy(dest_realm, optarg, dst_realm_sz);
287		    }
288#else
289			fprintf(stderr,
290			   "%s: Warning: -k ignored, no Kerberos V4 support.\n",
291								prompt);
292#endif
293#else
294			fprintf(stderr,
295			   "%s: Warning: -k ignored, no Kerberos V4 support.\n",
296								prompt);
297#endif
298			break;
299		case 'l':
300#ifdef	AUTHENTICATION
301			/* This is the default now, so ignore it */
302#else
303			autologin = 1;
304#endif
305			user = optarg;
306			break;
307		case 'n':
308				SetNetTrace(optarg);
309			break;
310		case 'r':
311			rlogin = '~';
312			break;
313		case 's':
314			src_addr = optarg;
315			break;
316		case 'u':
317			family = AF_UNIX;
318			break;
319		case 'x':
320#ifndef	ENCRYPTION
321			fprintf(stderr,
322			    "%s: Warning: -x ignored, no ENCRYPT support.\n",
323								prompt);
324#endif	/* ENCRYPTION */
325			break;
326		case 'y':
327#ifdef	ENCRYPTION
328			encrypt_auto(0);
329			decrypt_auto(0);
330#else
331			fprintf(stderr,
332			    "%s: Warning: -y ignored, no ENCRYPT support.\n",
333								prompt);
334#endif	/* ENCRYPTION */
335			break;
336#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
337		case 'P':
338			if (!strncmp("in", optarg, 2))
339				ipsec_policy_in = strdup(optarg);
340			else if (!strncmp("out", optarg, 3))
341				ipsec_policy_out = strdup(optarg);
342			else
343				usage();
344			break;
345#endif
346		case '?':
347		default:
348			usage();
349			/* NOTREACHED */
350		}
351	}
352	if (autologin == -1)
353		autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1;
354
355	argc -= optind;
356	argv += optind;
357
358	if (argc) {
359		char *args[9], **argp = args;
360
361		if (argc > 2)
362			usage();
363		*argp++ = prompt;
364		if (user) {
365			*argp++ = strdup("-l");
366			*argp++ = user;
367		}
368		if (src_addr) {
369			*argp++ = strdup("-s");
370			*argp++ = src_addr;
371		}
372		*argp++ = argv[0];		/* host */
373		if (argc > 1)
374			*argp++ = argv[1];	/* port */
375		*argp = 0;
376
377		if (setjmp(toplevel) != 0)
378			Exit(0);
379		if (tn(argp - args, args) == 1)
380			return (0);
381		else
382			return (1);
383	}
384	(void)setjmp(toplevel);
385	for (;;) {
386			command(1, 0, 0);
387	}
388	return 0;
389}
390