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