xref: /freebsd/contrib/tcpdump/print-telnet.c (revision a90e161be323456b08b7fe13acb201536809510f)
1b0453382SBill Fenner /*	$NetBSD: print-telnet.c,v 1.2 1999/10/11 12:40:12 sjg Exp $ 	*/
2b0453382SBill Fenner 
3b0453382SBill Fenner /*-
4b0453382SBill Fenner  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5b0453382SBill Fenner  * All rights reserved.
6b0453382SBill Fenner  *
7b0453382SBill Fenner  * This code is derived from software contributed to The NetBSD Foundation
8b0453382SBill Fenner  * by Simon J. Gerraty.
9b0453382SBill Fenner  *
10b0453382SBill Fenner  * Redistribution and use in source and binary forms, with or without
11b0453382SBill Fenner  * modification, are permitted provided that the following conditions
12b0453382SBill Fenner  * are met:
13b0453382SBill Fenner  * 1. Redistributions of source code must retain the above copyright
14b0453382SBill Fenner  *    notice, this list of conditions and the following disclaimer.
15b0453382SBill Fenner  * 2. Redistributions in binary form must reproduce the above copyright
16b0453382SBill Fenner  *    notice, this list of conditions and the following disclaimer in the
17b0453382SBill Fenner  *    documentation and/or other materials provided with the distribution.
18b0453382SBill Fenner  * 3. All advertising materials mentioning features or use of this software
19b0453382SBill Fenner  *    must display the following acknowledgement:
20b0453382SBill Fenner  *        This product includes software developed by the NetBSD
21b0453382SBill Fenner  *        Foundation, Inc. and its contributors.
22b0453382SBill Fenner  * 4. Neither the name of The NetBSD Foundation nor the names of its
23b0453382SBill Fenner  *    contributors may be used to endorse or promote products derived
24b0453382SBill Fenner  *    from this software without specific prior written permission.
25b0453382SBill Fenner  *
26b0453382SBill Fenner  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27b0453382SBill Fenner  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28b0453382SBill Fenner  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29b0453382SBill Fenner  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30b0453382SBill Fenner  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31b0453382SBill Fenner  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32b0453382SBill Fenner  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33b0453382SBill Fenner  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34b0453382SBill Fenner  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35b0453382SBill Fenner  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36b0453382SBill Fenner  * POSSIBILITY OF SUCH DAMAGE.
37b0453382SBill Fenner  */
38b0453382SBill Fenner /*
39b0453382SBill Fenner  *      @(#)Copyright (c) 1994, Simon J. Gerraty.
40b0453382SBill Fenner  *
41b0453382SBill Fenner  *      This is free software.  It comes with NO WARRANTY.
42b0453382SBill Fenner  *      Permission to use, modify and distribute this source code
43b0453382SBill Fenner  *      is granted subject to the following conditions.
44b0453382SBill Fenner  *      1/ that the above copyright notice and this notice
45b0453382SBill Fenner  *      are preserved in all copies.
46b0453382SBill Fenner  */
47b0453382SBill Fenner 
48b0453382SBill Fenner #ifdef HAVE_CONFIG_H
49b0453382SBill Fenner #include "config.h"
50b0453382SBill Fenner #endif
51b0453382SBill Fenner 
52b0453382SBill Fenner #ifndef lint
53b0453382SBill Fenner static const char rcsid[] =
54a90e161bSBill Fenner      "@(#) $Header: /tcpdump/master/tcpdump/print-telnet.c,v 1.18 2001/09/10 06:40:08 fenner Exp $";
55b0453382SBill Fenner #endif
56b0453382SBill Fenner 
57b0453382SBill Fenner #include <sys/param.h>
58b0453382SBill Fenner #include <sys/time.h>
59b0453382SBill Fenner #include <sys/types.h>
60685295f4SBill Fenner #include <ctype.h>
61b0453382SBill Fenner 
62b0453382SBill Fenner #include <netinet/in.h>
63b0453382SBill Fenner 
64b0453382SBill Fenner #include <stdio.h>
65b0453382SBill Fenner #include <stdlib.h>
66b0453382SBill Fenner #include <unistd.h>
67b0453382SBill Fenner #include <string.h>
68b0453382SBill Fenner 
69b0453382SBill Fenner #include "interface.h"
70b0453382SBill Fenner #include "addrtoname.h"
71b0453382SBill Fenner 
72a90e161bSBill Fenner #define TELCMDS
73a90e161bSBill Fenner #define TELOPTS
74a90e161bSBill Fenner #include "telnet.h"
75b0453382SBill Fenner 
76a90e161bSBill Fenner /* normal */
77a90e161bSBill Fenner static const char *cmds[] = {
78a90e161bSBill Fenner 	"IS", "SEND", "INFO",
79a90e161bSBill Fenner };
80a90e161bSBill Fenner 
81a90e161bSBill Fenner /* 37: Authentication */
82a90e161bSBill Fenner static const char *authcmd[] = {
83a90e161bSBill Fenner 	"IS", "SEND", "REPLY", "NAME",
84a90e161bSBill Fenner };
85a90e161bSBill Fenner static const char *authtype[] = {
86a90e161bSBill Fenner 	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK",
87a90e161bSBill Fenner 	"SRP", "RSA", "SSL", NULL, NULL,
88a90e161bSBill Fenner 	"LOKI", "SSA", "KEA_SJ", "KEA_SJ_INTEG", "DSS",
89a90e161bSBill Fenner 	"NTLM",
90a90e161bSBill Fenner };
91a90e161bSBill Fenner 
92a90e161bSBill Fenner /* 38: Encryption */
93a90e161bSBill Fenner static const char *enccmd[] = {
94a90e161bSBill Fenner 	"IS", "SUPPORT", "REPLY", "START", "END",
95a90e161bSBill Fenner 	"REQUEST-START", "REQUEST-END", "END_KEYID", "DEC_KEYID",
96a90e161bSBill Fenner };
97a90e161bSBill Fenner static const char *enctype[] = {
98a90e161bSBill Fenner 	"NULL", "DES_CFB64", "DES_OFB64", "DES3_CFB64", "DES3_OFB64",
99a90e161bSBill Fenner 	NULL, "CAST5_40_CFB64", "CAST5_40_OFB64", "CAST128_CFB64", "CAST128_OFB64",
100a90e161bSBill Fenner };
101a90e161bSBill Fenner 
102a90e161bSBill Fenner #define STR_OR_ID(x, tab) \
103a90e161bSBill Fenner 	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
104a90e161bSBill Fenner 
105a90e161bSBill Fenner static char *
106a90e161bSBill Fenner numstr(int x)
107b0453382SBill Fenner {
108a90e161bSBill Fenner 	static char buf[20];
109b0453382SBill Fenner 
110a90e161bSBill Fenner 	snprintf(buf, sizeof(buf), "%#x", x);
111a90e161bSBill Fenner 	return buf;
112b0453382SBill Fenner }
113a90e161bSBill Fenner 
114a90e161bSBill Fenner /* sp points to IAC byte */
115a90e161bSBill Fenner static int
116a90e161bSBill Fenner telnet_parse(const u_char *sp, u_int length, int print)
117a90e161bSBill Fenner {
118a90e161bSBill Fenner 	int i, c, x;
119a90e161bSBill Fenner 	const u_char *osp, *p;
120a90e161bSBill Fenner #define FETCH(c, sp, length) \
121a90e161bSBill Fenner 	do { \
122a90e161bSBill Fenner 		if (length < 1) \
123a90e161bSBill Fenner 			goto pktend; \
124a90e161bSBill Fenner 		TCHECK(*sp); \
125a90e161bSBill Fenner 		c = *sp++; \
126a90e161bSBill Fenner 		length--; \
127a90e161bSBill Fenner 	} while (0)
128a90e161bSBill Fenner 
129a90e161bSBill Fenner 	osp = sp;
130a90e161bSBill Fenner 
131a90e161bSBill Fenner 	FETCH(c, sp, length);
132a90e161bSBill Fenner 	if (c != IAC)
133a90e161bSBill Fenner 		goto pktend;
134a90e161bSBill Fenner 	FETCH(c, sp, length);
135a90e161bSBill Fenner 	if (c == IAC) {		/* <IAC><IAC>! */
136a90e161bSBill Fenner 		if (print)
137a90e161bSBill Fenner 			printf("IAC IAC");
138a90e161bSBill Fenner 		goto done;
139b0453382SBill Fenner 	}
140a90e161bSBill Fenner 
141a90e161bSBill Fenner 	i = c - TELCMD_FIRST;
142a90e161bSBill Fenner 	if (i < 0 || i > IAC - TELCMD_FIRST)
143a90e161bSBill Fenner 		goto pktend;
144a90e161bSBill Fenner 
145b0453382SBill Fenner 	switch (c) {
146b0453382SBill Fenner 	case DONT:
147b0453382SBill Fenner 	case DO:
148b0453382SBill Fenner 	case WONT:
149b0453382SBill Fenner 	case WILL:
150b0453382SBill Fenner 	case SB:
151a90e161bSBill Fenner 		/* DONT/DO/WONT/WILL x */
152a90e161bSBill Fenner 		FETCH(x, sp, length);
153b0453382SBill Fenner 		if (x >= 0 && x < NTELOPTS) {
154a90e161bSBill Fenner 			if (print)
155a90e161bSBill Fenner 				(void)printf("%s %s", telcmds[i], telopts[x]);
156b0453382SBill Fenner 		} else {
157a90e161bSBill Fenner 			if (print)
158a90e161bSBill Fenner 				(void)printf("%s %#x", telcmds[i], x);
159b0453382SBill Fenner 		}
160a90e161bSBill Fenner 		if (c != SB)
161a90e161bSBill Fenner 			break;
162a90e161bSBill Fenner 		/* IAC SB .... IAC SE */
163a90e161bSBill Fenner 		p = sp;
164a90e161bSBill Fenner 		while (length > p + 1 - sp) {
165a90e161bSBill Fenner 			if (p[0] == IAC && p[1] == SE)
166a90e161bSBill Fenner 				break;
167a90e161bSBill Fenner 			p++;
168a90e161bSBill Fenner 		}
169a90e161bSBill Fenner 		if (*p != IAC)
170a90e161bSBill Fenner 			goto pktend;
171a90e161bSBill Fenner 
172a90e161bSBill Fenner 		switch (x) {
173a90e161bSBill Fenner 		case TELOPT_AUTHENTICATION:
174a90e161bSBill Fenner 			if (p <= sp)
175a90e161bSBill Fenner 				break;
176a90e161bSBill Fenner 			FETCH(c, sp, length);
177a90e161bSBill Fenner 			if (print)
178a90e161bSBill Fenner 				(void)printf(" %s", STR_OR_ID(c, authcmd));
179a90e161bSBill Fenner 			if (p <= sp)
180a90e161bSBill Fenner 				break;
181a90e161bSBill Fenner 			FETCH(c, sp, length);
182a90e161bSBill Fenner 			if (print)
183a90e161bSBill Fenner 				(void)printf(" %s", STR_OR_ID(c, authtype));
184a90e161bSBill Fenner 			break;
185a90e161bSBill Fenner 		case TELOPT_ENCRYPT:
186a90e161bSBill Fenner 			if (p <= sp)
187a90e161bSBill Fenner 				break;
188a90e161bSBill Fenner 			FETCH(c, sp, length);
189a90e161bSBill Fenner 			if (print)
190a90e161bSBill Fenner 				(void)printf(" %s", STR_OR_ID(c, enccmd));
191a90e161bSBill Fenner 			if (p <= sp)
192a90e161bSBill Fenner 				break;
193a90e161bSBill Fenner 			FETCH(c, sp, length);
194a90e161bSBill Fenner 			if (print)
195a90e161bSBill Fenner 				(void)printf(" %s", STR_OR_ID(c, enctype));
196b0453382SBill Fenner 			break;
197b0453382SBill Fenner 		default:
198a90e161bSBill Fenner 			if (p <= sp)
199a90e161bSBill Fenner 				break;
200a90e161bSBill Fenner 			FETCH(c, sp, length);
201a90e161bSBill Fenner 			if (print)
202a90e161bSBill Fenner 				(void)printf(" %s", STR_OR_ID(c, cmds));
203b0453382SBill Fenner 			break;
204b0453382SBill Fenner 		}
205a90e161bSBill Fenner 		while (p > sp) {
206a90e161bSBill Fenner 			FETCH(x, sp, length);
207a90e161bSBill Fenner 			if (print)
208a90e161bSBill Fenner 				(void)printf(" %#x", x);
209a90e161bSBill Fenner 		}
210a90e161bSBill Fenner 		/* terminating IAC SE */
211a90e161bSBill Fenner 		if (print)
212a90e161bSBill Fenner 			(void)printf(" SE");
213a90e161bSBill Fenner 		sp += 2;
214a90e161bSBill Fenner 		length -= 2;
215a90e161bSBill Fenner 		break;
216a90e161bSBill Fenner 	default:
217a90e161bSBill Fenner 		if (print)
218a90e161bSBill Fenner 			(void)printf("%s", telcmds[i]);
219a90e161bSBill Fenner 		goto done;
220a90e161bSBill Fenner 	}
221a90e161bSBill Fenner 
222a90e161bSBill Fenner done:
223a90e161bSBill Fenner 	return sp - osp;
224a90e161bSBill Fenner 
225a90e161bSBill Fenner trunc:
226a90e161bSBill Fenner 	(void)printf("[|telnet]");
227a90e161bSBill Fenner pktend:
228a90e161bSBill Fenner 	return -1;
229a90e161bSBill Fenner #undef FETCH
230a90e161bSBill Fenner }
231a90e161bSBill Fenner 
232a90e161bSBill Fenner void
233a90e161bSBill Fenner telnet_print(const u_char *sp, u_int length)
234a90e161bSBill Fenner {
235a90e161bSBill Fenner 	int first = 1;
236a90e161bSBill Fenner 	const u_char *osp;
237a90e161bSBill Fenner 	int l;
238a90e161bSBill Fenner 
239a90e161bSBill Fenner 	osp = sp;
240a90e161bSBill Fenner 
241a90e161bSBill Fenner 	while (length > 0 && *sp == IAC) {
242a90e161bSBill Fenner 		l = telnet_parse(sp, length, 0);
243a90e161bSBill Fenner 		if (l < 0)
244a90e161bSBill Fenner 			break;
245a90e161bSBill Fenner 
246b0453382SBill Fenner 		/*
247b0453382SBill Fenner 		 * now print it
248b0453382SBill Fenner 		 */
249b0453382SBill Fenner 		if (Xflag && 2 < vflag) {
250b0453382SBill Fenner 			if (first)
251a90e161bSBill Fenner 				printf("\nTelnet:");
252a90e161bSBill Fenner 			hex_print_with_offset(sp, l, sp - osp);
253a90e161bSBill Fenner 			if (l > 8)
254685295f4SBill Fenner 				printf("\n\t\t\t\t");
255b0453382SBill Fenner 			else
256a90e161bSBill Fenner 				printf("%*s\t", (8 - l) * 3, "");
257a90e161bSBill Fenner 		} else
258685295f4SBill Fenner 			printf("%s", (first) ? " [telnet " : ", ");
259a90e161bSBill Fenner 
260a90e161bSBill Fenner 		(void)telnet_parse(sp, length, 1);
261b0453382SBill Fenner 		first = 0;
262a90e161bSBill Fenner 
263a90e161bSBill Fenner 		sp += l;
264a90e161bSBill Fenner 		length -= l;
265b0453382SBill Fenner 	}
266b0453382SBill Fenner 	if (!first) {
267b0453382SBill Fenner 		if (Xflag && 2 < vflag)
268b0453382SBill Fenner 			printf("\n");
269b0453382SBill Fenner 		else
270b0453382SBill Fenner 			printf("]");
271b0453382SBill Fenner 	}
272b0453382SBill Fenner }
273