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