1 /**
2 *@internal
3 *
4 *@file teredoplugin.c
5 *
6 * @brief this is a protocol classifier for the Teredo Tunneling Protocol
7 *
8 * Teredo is a tunneling protocol designed to grant IPv6 connectivity to
9 * nodes that are located behind IPv6-unaware NAT devices. It is a way to
10 * encapsulate IPv6 pkts within IPv4 UDP datagrams.
11 *
12 * @sa rfc 4380 href="http://tools.ietf.org/html/rfc4380"
13 *
14 *
15 * @author $Author: ecoff_svn $
16 * @date $Date: 2010-01-20 15:54:44 -0500 (Wed, 20 Jan 2010) $
17 * @version $Revision: 15242 $
18 *
19 *
20 ** ------------------------------------------------------------------------
21 ** Copyright (C) 2007-2015 Carnegie Mellon University. All Rights Reserved.
22 ** ------------------------------------------------------------------------
23 ** Authors: Dan Ruef <druef@cert.org>
24 ** ------------------------------------------------------------------------
25 ** @OPENSOURCE_HEADER_START@
26 ** Use of the YAF system and related source code is subject to the terms
27 ** of the following licenses:
28 **
29 ** GNU Public License (GPL) Rights pursuant to Version 2, June 1991
30 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013
31 **
32 ** NO WARRANTY
33 **
34 ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER
35 ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY
36 ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN
37 ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
38 ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT
39 ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE,
40 ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE
41 ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT,
42 ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY
43 ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF
44 ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
45 ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF
46 ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON
47 ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE
48 ** DELIVERABLES UNDER THIS LICENSE.
49 **
50 ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie
51 ** Mellon University, its trustees, officers, employees, and agents from
52 ** all claims or demands made against them (and any related losses,
53 ** expenses, or attorney's fees) arising out of, or relating to Licensee's
54 ** and/or its sub licensees' negligent use or willful misuse of or
55 ** negligent conduct or willful misconduct regarding the Software,
56 ** facilities, or other rights or assistance granted by Carnegie Mellon
57 ** University under this License, including, but not limited to, any
58 ** claims of product liability, personal injury, death, damage to
59 ** property, or violation of any laws or regulations.
60 **
61 ** Carnegie Mellon University Software Engineering Institute authored
62 ** documents are sponsored by the U.S. Department of Defense under
63 ** Contract FA8721-05-C-0003. Carnegie Mellon University retains
64 ** copyrights in all material produced under this contract. The U.S.
65 ** Government retains a non-exclusive, royalty-free license to publish or
66 ** reproduce these documents, or allow others to do so, for U.S.
67 ** Government purposes only pursuant to the copyright license under the
68 ** contract clause at 252.227.7013.
69 **
70 ** @OPENSOURCE_HEADER_END@
71 ** ------------------------------------------------------------------------
72 *
73 */
74
75
76 #define _YAF_SOURCE_
77 #include <yaf/autoinc.h>
78 #include <yaf/yafcore.h>
79 #include <yaf/decode.h>
80
81 #include <arpa/inet.h>
82
83 /**
84 * IPv6 header structure.
85 */
86 typedef struct yfHdrIPv6_st {
87 /** Version, traffic class, and flow ID. Use YF_VCF6_ macros to access. */
88 uint32_t ip6_vcf;
89
90 /**
91 * Payload length. Does NOT include IPv6 header (40 bytes), but does
92 * include subsequent extension headers, upper layer headers, and payload.
93 */
94 uint16_t ip6_plen;
95 /** Next header identifier. Use YF_PROTO_ macros. */
96 uint8_t ip6_nxt;
97 /** Hop limit */
98 uint8_t ip6_hlim;
99 /** Source IPv6 address */
100 uint8_t ip6_src[16];
101 /** Destination IPv6 address */
102 uint8_t ip6_dst[16];
103 } yfHdrIPv6_t;
104
105 #define AUTH_HEADER_LEN 13
106 typedef struct yfIPv6AuthIndicator_st {
107 /* indicator type, set to 1 for auth */
108 uint16_t ipv6_indicatorType;
109 /* length of the client ID string that follows auth data length */
110 uint8_t ipv6_clientIdLen;
111 /* length of the authentication data that follow client id string */
112 uint8_t ipv6_authenticationDataLen;
113 /* char * clientId. There is a char array of variable length next */
114 /* uint8_t *authenticationData. There is a variable array of auth data */
115 uint64_t nonce;
116 uint8_t confirmation;
117 } yfIPv6AuthIndicator_t;
118
119 typedef struct yfIPv6OriginIndicator_st {
120 /* indicator type, set to 0 for origin */
121 uint16_t ipv6_indicatorType;
122 uint16_t ipv6_obscuredPortNum;
123 uint32_t ipv6_obscuredOriginAddress;
124 } yfIPv6OriginIndicator_t;
125
126 static uint16_t lookForIPv6HdrAndTeredoAddrs(yfHdrIPv6_t *ipv6Hdr);
127
128 #define TEREDO_PORT_NUMBER 3544
129
130 /**
131 * teredoplugin_LTX_ycTeredoScan
132 *
133 * returns TEREDO_PORT_NUMBER if the passed in payload matches
134 * a teredo IPv6 tunneling protocol packet
135 *
136 * @param argc number of string arguments in argv
137 * @param argv string arguments for this plugin
138 * @param payload the packet payload
139 * @param payloadSize size of the packet payload
140 * @param flow a pointer to the flow state structure
141 * @param val a pointer to biflow state (used for forward vs reverse)
142 *
143 *
144 * return 0 if no match
145 */
146
147 uint16_t
teredoplugin_LTX_ycTeredoScanScan(int argc,char * argv[],uint8_t * payload,unsigned int payloadSize,yfFlow_t * flow,yfFlowVal_t * val)148 teredoplugin_LTX_ycTeredoScanScan (
149 int argc,
150 char *argv[],
151 uint8_t * payload,
152 unsigned int payloadSize,
153 yfFlow_t * flow,
154 yfFlowVal_t * val)
155 {
156 yfHdrIPv6_t *ipv6Hdr;
157 yfIPv6AuthIndicator_t *authHdr;
158 yfIPv6OriginIndicator_t *originHdr;
159 int retval;
160 int authHdrLength = 0;
161 uint16_t indicator;
162
163 if (payloadSize < sizeof(yfHdrIPv6_t)){
164 return 0;
165 }
166
167 ipv6Hdr = (yfHdrIPv6_t*) payload;
168
169 retval = lookForIPv6HdrAndTeredoAddrs(ipv6Hdr);
170 if (retval == TEREDO_PORT_NUMBER) {
171 return TEREDO_PORT_NUMBER;
172 }
173
174 authHdr = (yfIPv6AuthIndicator_t *) payload;
175
176 indicator = ntohs(authHdr->ipv6_indicatorType);
177 if (authHdr->ipv6_indicatorType == 1) {
178 authHdrLength = AUTH_HEADER_LEN +
179 authHdr->ipv6_clientIdLen +
180 authHdr->ipv6_authenticationDataLen;
181
182 if (payloadSize < (authHdrLength + sizeof(yfHdrIPv6_t))) {
183 return 0;
184 }
185
186 originHdr = (yfIPv6OriginIndicator_t*)(payload + authHdrLength);
187 indicator = ntohs(originHdr->ipv6_indicatorType);
188 if (indicator == 0) {
189 if (payloadSize < (authHdrLength +
190 sizeof(yfHdrIPv6_t) +
191 sizeof(yfIPv6OriginIndicator_t)))
192 {
193 return 0;
194 }
195 ipv6Hdr = (yfHdrIPv6_t*)(originHdr + 1);
196
197 } else {
198 ipv6Hdr = (yfHdrIPv6_t*)originHdr;
199 }
200 } else {
201 originHdr = (yfIPv6OriginIndicator_t*)payload;
202 indicator = ntohs(originHdr->ipv6_indicatorType);
203 if (indicator != 0) {
204 return 0;
205 }
206
207 if (payloadSize < sizeof(yfIPv6OriginIndicator_t) +
208 sizeof(yfHdrIPv6_t))
209 {
210 return 0;
211 }
212
213 ipv6Hdr = (yfHdrIPv6_t*)(originHdr + 1);
214 }
215
216 return lookForIPv6HdrAndTeredoAddrs(ipv6Hdr);
217 }
218
lookForIPv6HdrAndTeredoAddrs(yfHdrIPv6_t * ipv6Hdr)219 static uint16_t lookForIPv6HdrAndTeredoAddrs(
220 yfHdrIPv6_t *ipv6Hdr)
221 {
222 uint32_t teredoPrefix = htonl(0x20010000);
223 uint32_t vcf = 0;
224
225 vcf = ntohl(ipv6Hdr->ip6_vcf);
226
227 if (((vcf & 0xF0000000) >> 28) != 6) {
228 return 0;
229 }
230
231 /* try teredo data...prefix...then try icmp for router solicitation */
232 if (memcmp(&teredoPrefix, ipv6Hdr->ip6_src, 4) != 0) {
233 if (memcmp(&teredoPrefix, ipv6Hdr->ip6_dst, 4) != 0) {
234 return 0;
235 }
236 }
237
238 return TEREDO_PORT_NUMBER;
239 }
240