156893Sfenner/*	$NetBSD: print-telnet.c,v 1.2 1999/10/11 12:40:12 sjg Exp $ 	*/
256893Sfenner
356893Sfenner/*-
456893Sfenner * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
556893Sfenner * All rights reserved.
656893Sfenner *
756893Sfenner * This code is derived from software contributed to The NetBSD Foundation
856893Sfenner * by Simon J. Gerraty.
956893Sfenner *
1056893Sfenner * Redistribution and use in source and binary forms, with or without
1156893Sfenner * modification, are permitted provided that the following conditions
1256893Sfenner * are met:
1356893Sfenner * 1. Redistributions of source code must retain the above copyright
1456893Sfenner *    notice, this list of conditions and the following disclaimer.
1556893Sfenner * 2. Redistributions in binary form must reproduce the above copyright
1656893Sfenner *    notice, this list of conditions and the following disclaimer in the
1756893Sfenner *    documentation and/or other materials provided with the distribution.
1856893Sfenner * 3. All advertising materials mentioning features or use of this software
1956893Sfenner *    must display the following acknowledgement:
2056893Sfenner *        This product includes software developed by the NetBSD
2156893Sfenner *        Foundation, Inc. and its contributors.
2256893Sfenner * 4. Neither the name of The NetBSD Foundation nor the names of its
2356893Sfenner *    contributors may be used to endorse or promote products derived
2456893Sfenner *    from this software without specific prior written permission.
2556893Sfenner *
2656893Sfenner * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2756893Sfenner * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2856893Sfenner * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2956893Sfenner * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
3056893Sfenner * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3156893Sfenner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3256893Sfenner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3356893Sfenner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3456893Sfenner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3556893Sfenner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3656893Sfenner * POSSIBILITY OF SUCH DAMAGE.
3756893Sfenner */
3856893Sfenner/*
3956893Sfenner *      @(#)Copyright (c) 1994, Simon J. Gerraty.
40127668Sbms *
4156893Sfenner *      This is free software.  It comes with NO WARRANTY.
42127668Sbms *      Permission to use, modify and distribute this source code
4356893Sfenner *      is granted subject to the following conditions.
44127668Sbms *      1/ that the above copyright notice and this notice
4556893Sfenner *      are preserved in all copies.
4656893Sfenner */
4756893Sfenner
4856893Sfenner#ifdef HAVE_CONFIG_H
4956893Sfenner#include "config.h"
5056893Sfenner#endif
5156893Sfenner
5256893Sfenner#ifndef lint
53127668Sbmsstatic const char rcsid[] _U_ =
54190207Srpaulo     "@(#) $Header: /tcpdump/master/tcpdump/print-telnet.c,v 1.24 2003-12-29 11:05:10 hannes Exp $";
5556893Sfenner#endif
5656893Sfenner
57127668Sbms#include <tcpdump-stdinc.h>
5856893Sfenner
5956893Sfenner#include <stdio.h>
6056893Sfenner#include <stdlib.h>
6156893Sfenner#include <string.h>
6256893Sfenner
6356893Sfenner#include "interface.h"
6456893Sfenner#include "addrtoname.h"
6556893Sfenner
6698524Sfenner#define TELCMDS
6798524Sfenner#define TELOPTS
6898524Sfenner#include "telnet.h"
6956893Sfenner
7098524Sfenner/* normal */
7198524Sfennerstatic const char *cmds[] = {
7298524Sfenner	"IS", "SEND", "INFO",
7398524Sfenner};
7498524Sfenner
7598524Sfenner/* 37: Authentication */
7698524Sfennerstatic const char *authcmd[] = {
7798524Sfenner	"IS", "SEND", "REPLY", "NAME",
7898524Sfenner};
7998524Sfennerstatic const char *authtype[] = {
8098524Sfenner	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK",
8198524Sfenner	"SRP", "RSA", "SSL", NULL, NULL,
8298524Sfenner	"LOKI", "SSA", "KEA_SJ", "KEA_SJ_INTEG", "DSS",
8398524Sfenner	"NTLM",
8498524Sfenner};
8598524Sfenner
8698524Sfenner/* 38: Encryption */
8798524Sfennerstatic const char *enccmd[] = {
8898524Sfenner	"IS", "SUPPORT", "REPLY", "START", "END",
8998524Sfenner	"REQUEST-START", "REQUEST-END", "END_KEYID", "DEC_KEYID",
9098524Sfenner};
9198524Sfennerstatic const char *enctype[] = {
9298524Sfenner	"NULL", "DES_CFB64", "DES_OFB64", "DES3_CFB64", "DES3_OFB64",
9398524Sfenner	NULL, "CAST5_40_CFB64", "CAST5_40_OFB64", "CAST128_CFB64", "CAST128_OFB64",
9498524Sfenner};
9598524Sfenner
9698524Sfenner#define STR_OR_ID(x, tab) \
9798524Sfenner	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
9898524Sfenner
9998524Sfennerstatic char *
10098524Sfennernumstr(int x)
10156893Sfenner{
10298524Sfenner	static char buf[20];
10356893Sfenner
10498524Sfenner	snprintf(buf, sizeof(buf), "%#x", x);
10598524Sfenner	return buf;
10698524Sfenner}
10798524Sfenner
10898524Sfenner/* sp points to IAC byte */
10998524Sfennerstatic int
11098524Sfennertelnet_parse(const u_char *sp, u_int length, int print)
11198524Sfenner{
112127668Sbms	int i, x;
113127668Sbms	u_int c;
11498524Sfenner	const u_char *osp, *p;
11598524Sfenner#define FETCH(c, sp, length) \
11698524Sfenner	do { \
11798524Sfenner		if (length < 1) \
11898524Sfenner			goto pktend; \
11998524Sfenner		TCHECK(*sp); \
12098524Sfenner		c = *sp++; \
12198524Sfenner		length--; \
12298524Sfenner	} while (0)
12398524Sfenner
12498524Sfenner	osp = sp;
12598524Sfenner
12698524Sfenner	FETCH(c, sp, length);
12798524Sfenner	if (c != IAC)
12898524Sfenner		goto pktend;
12998524Sfenner	FETCH(c, sp, length);
13098524Sfenner	if (c == IAC) {		/* <IAC><IAC>! */
13198524Sfenner		if (print)
13298524Sfenner			printf("IAC IAC");
13398524Sfenner		goto done;
13498524Sfenner	}
13598524Sfenner
13698524Sfenner	i = c - TELCMD_FIRST;
13798524Sfenner	if (i < 0 || i > IAC - TELCMD_FIRST)
13898524Sfenner		goto pktend;
13998524Sfenner
14098524Sfenner	switch (c) {
14198524Sfenner	case DONT:
14298524Sfenner	case DO:
14398524Sfenner	case WONT:
14498524Sfenner	case WILL:
14598524Sfenner	case SB:
14698524Sfenner		/* DONT/DO/WONT/WILL x */
14798524Sfenner		FETCH(x, sp, length);
14898524Sfenner		if (x >= 0 && x < NTELOPTS) {
14998524Sfenner			if (print)
15098524Sfenner				(void)printf("%s %s", telcmds[i], telopts[x]);
15198524Sfenner		} else {
15298524Sfenner			if (print)
15398524Sfenner				(void)printf("%s %#x", telcmds[i], x);
15498524Sfenner		}
15598524Sfenner		if (c != SB)
15656893Sfenner			break;
15798524Sfenner		/* IAC SB .... IAC SE */
15898524Sfenner		p = sp;
159127668Sbms		while (length > (u_int)(p + 1 - sp)) {
16098524Sfenner			if (p[0] == IAC && p[1] == SE)
16198524Sfenner				break;
16298524Sfenner			p++;
16398524Sfenner		}
16498524Sfenner		if (*p != IAC)
16598524Sfenner			goto pktend;
16698524Sfenner
16798524Sfenner		switch (x) {
16898524Sfenner		case TELOPT_AUTHENTICATION:
16998524Sfenner			if (p <= sp)
17098524Sfenner				break;
17198524Sfenner			FETCH(c, sp, length);
17298524Sfenner			if (print)
17398524Sfenner				(void)printf(" %s", STR_OR_ID(c, authcmd));
17498524Sfenner			if (p <= sp)
17598524Sfenner				break;
17698524Sfenner			FETCH(c, sp, length);
17798524Sfenner			if (print)
17898524Sfenner				(void)printf(" %s", STR_OR_ID(c, authtype));
17998524Sfenner			break;
18098524Sfenner		case TELOPT_ENCRYPT:
18198524Sfenner			if (p <= sp)
18298524Sfenner				break;
18398524Sfenner			FETCH(c, sp, length);
18498524Sfenner			if (print)
18598524Sfenner				(void)printf(" %s", STR_OR_ID(c, enccmd));
18698524Sfenner			if (p <= sp)
18798524Sfenner				break;
18898524Sfenner			FETCH(c, sp, length);
18998524Sfenner			if (print)
19098524Sfenner				(void)printf(" %s", STR_OR_ID(c, enctype));
19198524Sfenner			break;
19256893Sfenner		default:
19398524Sfenner			if (p <= sp)
19456893Sfenner				break;
19598524Sfenner			FETCH(c, sp, length);
19698524Sfenner			if (print)
19798524Sfenner				(void)printf(" %s", STR_OR_ID(c, cmds));
19856893Sfenner			break;
19956893Sfenner		}
20098524Sfenner		while (p > sp) {
20198524Sfenner			FETCH(x, sp, length);
20298524Sfenner			if (print)
20398524Sfenner				(void)printf(" %#x", x);
20498524Sfenner		}
20598524Sfenner		/* terminating IAC SE */
20698524Sfenner		if (print)
20798524Sfenner			(void)printf(" SE");
20898524Sfenner		sp += 2;
20998524Sfenner		length -= 2;
21098524Sfenner		break;
21198524Sfenner	default:
21298524Sfenner		if (print)
21398524Sfenner			(void)printf("%s", telcmds[i]);
21498524Sfenner		goto done;
21598524Sfenner	}
21698524Sfenner
21798524Sfennerdone:
21898524Sfenner	return sp - osp;
21998524Sfenner
22098524Sfennertrunc:
22198524Sfenner	(void)printf("[|telnet]");
22298524Sfennerpktend:
22398524Sfenner	return -1;
22498524Sfenner#undef FETCH
22598524Sfenner}
22698524Sfenner
22798524Sfennervoid
22898524Sfennertelnet_print(const u_char *sp, u_int length)
22998524Sfenner{
23098524Sfenner	int first = 1;
23198524Sfenner	const u_char *osp;
23298524Sfenner	int l;
23398524Sfenner
23498524Sfenner	osp = sp;
235127668Sbms
23698524Sfenner	while (length > 0 && *sp == IAC) {
23798524Sfenner		l = telnet_parse(sp, length, 0);
23898524Sfenner		if (l < 0)
23998524Sfenner			break;
24098524Sfenner
24156893Sfenner		/*
24256893Sfenner		 * now print it
24356893Sfenner		 */
24456893Sfenner		if (Xflag && 2 < vflag) {
24556893Sfenner			if (first)
24698524Sfenner				printf("\nTelnet:");
247127668Sbms			hex_print_with_offset("\n", sp, l, sp - osp);
24898524Sfenner			if (l > 8)
24975115Sfenner				printf("\n\t\t\t\t");
25056893Sfenner			else
25198524Sfenner				printf("%*s\t", (8 - l) * 3, "");
25298524Sfenner		} else
25375115Sfenner			printf("%s", (first) ? " [telnet " : ", ");
25498524Sfenner
25598524Sfenner		(void)telnet_parse(sp, length, 1);
25656893Sfenner		first = 0;
25798524Sfenner
25898524Sfenner		sp += l;
25998524Sfenner		length -= l;
26056893Sfenner	}
26156893Sfenner	if (!first) {
26256893Sfenner		if (Xflag && 2 < vflag)
26356893Sfenner			printf("\n");
26456893Sfenner		else
26556893Sfenner			printf("]");
26656893Sfenner	}
26756893Sfenner}
268