Line data Source code
1 : /*
2 : Copyright (c) 2007, Adobe Systems, Incorporated
3 : All rights reserved.
4 :
5 : Redistribution and use in source and binary forms, with or without
6 : modification, are permitted provided that the following conditions are
7 : met:
8 :
9 : * Redistributions of source code must retain the above copyright
10 : notice, this list of conditions and the following disclaimer.
11 :
12 : * Redistributions in binary form must reproduce the above copyright
13 : notice, this list of conditions and the following disclaimer in the
14 : documentation and/or other materials provided with the distribution.
15 :
16 : * Neither the name of Adobe Systems, Network Resonance nor the names of its
17 : contributors may be used to endorse or promote products derived from
18 : this software without specific prior written permission.
19 :
20 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : */
32 :
33 :
34 : static char *RCSSTRING __UNUSED__="$Id: stun_hint.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
35 :
36 :
37 : #include <errno.h>
38 : #include <csi_platform.h>
39 :
40 : #ifdef WIN32
41 : #include <winsock2.h>
42 : #include <stdlib.h>
43 : #include <io.h>
44 : #include <time.h>
45 : #else /* UNIX */
46 : #include <string.h>
47 : #endif /* end UNIX */
48 : #include <assert.h>
49 :
50 : #include "stun.h"
51 :
52 :
53 : /* returns 0 if it's not a STUN message
54 : * 1 if it's likely to be a STUN message
55 : * 2 if it's super likely to be a STUN message
56 : * 3 if it really is a STUN message */
57 : int
58 0 : nr_is_stun_message(UCHAR *buf, int len)
59 : {
60 0 : const UINT4 cookie = htonl(NR_STUN_MAGIC_COOKIE);
61 0 : const UINT4 cookie2 = htonl(NR_STUN_MAGIC_COOKIE2);
62 : #if 0
63 : nr_stun_message msg;
64 : #endif
65 : UINT2 type;
66 : nr_stun_encoded_attribute* attr;
67 : unsigned int attrLen;
68 : int atrType;
69 :
70 0 : if (sizeof(nr_stun_message_header) > len)
71 0 : return 0;
72 :
73 0 : if ((buf[0] & (0x80|0x40)) != 0)
74 0 : return 0;
75 :
76 0 : memcpy(&type, buf, 2);
77 0 : type = ntohs(type);
78 :
79 0 : switch (type) {
80 : case NR_STUN_MSG_BINDING_REQUEST:
81 : case NR_STUN_MSG_BINDING_INDICATION:
82 : case NR_STUN_MSG_BINDING_RESPONSE:
83 : case NR_STUN_MSG_BINDING_ERROR_RESPONSE:
84 :
85 : #ifdef USE_TURN
86 : case NR_STUN_MSG_ALLOCATE_REQUEST:
87 : case NR_STUN_MSG_ALLOCATE_RESPONSE:
88 : case NR_STUN_MSG_ALLOCATE_ERROR_RESPONSE:
89 : case NR_STUN_MSG_REFRESH_REQUEST:
90 : case NR_STUN_MSG_REFRESH_RESPONSE:
91 : case NR_STUN_MSG_REFRESH_ERROR_RESPONSE:
92 : case NR_STUN_MSG_PERMISSION_REQUEST:
93 : case NR_STUN_MSG_PERMISSION_RESPONSE:
94 : case NR_STUN_MSG_PERMISSION_ERROR_RESPONSE:
95 : case NR_STUN_MSG_CHANNEL_BIND_REQUEST:
96 : case NR_STUN_MSG_CHANNEL_BIND_RESPONSE:
97 : case NR_STUN_MSG_CHANNEL_BIND_ERROR_RESPONSE:
98 : case NR_STUN_MSG_SEND_INDICATION:
99 : case NR_STUN_MSG_DATA_INDICATION:
100 : #ifdef NR_STUN_MSG_CONNECT_REQUEST
101 : case NR_STUN_MSG_CONNECT_REQUEST:
102 : #endif
103 : #ifdef NR_STUN_MSG_CONNECT_RESPONSE
104 : case NR_STUN_MSG_CONNECT_RESPONSE:
105 : #endif
106 : #ifdef NR_STUN_MSG_CONNECT_ERROR_RESPONSE
107 : case NR_STUN_MSG_CONNECT_ERROR_RESPONSE:
108 : #endif
109 : #ifdef NR_STUN_MSG_CONNECT_STATUS_INDICATION
110 : case NR_STUN_MSG_CONNECT_STATUS_INDICATION:
111 : #endif
112 : #endif /* USE_TURN */
113 :
114 : /* ok so far, continue */
115 0 : break;
116 : default:
117 0 : return 0;
118 : break;
119 : }
120 :
121 0 : if (!memcmp(&cookie2, &buf[4], sizeof(UINT4))) {
122 : /* return here because if it's an old-style message then there will
123 : * not be a fingerprint in the message */
124 0 : return 1;
125 : }
126 :
127 0 : if (memcmp(&cookie, &buf[4], sizeof(UINT4)))
128 0 : return 0;
129 :
130 : /* the magic cookie was right, so it's pretty darn likely that what we've
131 : * got here is a STUN message */
132 :
133 0 : attr = (nr_stun_encoded_attribute*)(buf + (len - 8));
134 0 : attrLen = ntohs(attr->length);
135 0 : atrType = ntohs(attr->type);
136 :
137 0 : if (atrType != NR_STUN_ATTR_FINGERPRINT || attrLen != 4)
138 0 : return 1;
139 :
140 : /* the fingerprint is in the right place and looks sane, so we can be quite
141 : * sure we've got a STUN message */
142 :
143 : #if 0
144 : /* nevermind this check ... there's a reasonable chance that a NAT has modified
145 : * the message (and thus the fingerprint check will fail), but it's still an
146 : * otherwise-perfectly-good STUN message, so skip the check since we're going
147 : * to return "true" whether the check succeeds or fails */
148 :
149 : if (nr_stun_parse_attr_UINT4(buf + (len - 4), attrLen, &msg.fingerprint))
150 : return 2;
151 :
152 :
153 : if (nr_stun_compute_fingerprint(buf, len - 8, &computedFingerprint))
154 : return 2;
155 :
156 : if (msg.fingerprint.number != computedFingerprint)
157 : return 2;
158 :
159 : /* and the fingerprint is good, so it's gotta be a STUN message */
160 : #endif
161 :
162 0 : return 3;
163 : }
164 :
165 : int
166 0 : nr_is_stun_request_message(UCHAR *buf, int len)
167 : {
168 : UINT2 type;
169 :
170 0 : if (sizeof(nr_stun_message_header) > len)
171 0 : return 0;
172 :
173 0 : if (!nr_is_stun_message(buf, len))
174 0 : return 0;
175 :
176 0 : memcpy(&type, buf, 2);
177 0 : type = ntohs(type);
178 :
179 0 : return NR_STUN_GET_TYPE_CLASS(type) == NR_CLASS_REQUEST;
180 : }
181 :
182 : int
183 0 : nr_is_stun_indication_message(UCHAR *buf, int len)
184 : {
185 : UINT2 type;
186 :
187 0 : if (sizeof(nr_stun_message_header) > len)
188 0 : return 0;
189 :
190 0 : if (!nr_is_stun_message(buf, len))
191 0 : return 0;
192 :
193 0 : memcpy(&type, buf, 2);
194 0 : type = ntohs(type);
195 :
196 0 : return NR_STUN_GET_TYPE_CLASS(type) == NR_CLASS_INDICATION;
197 : }
198 :
199 : int
200 0 : nr_is_stun_response_message(UCHAR *buf, int len)
201 : {
202 : UINT2 type;
203 :
204 0 : if (sizeof(nr_stun_message_header) > len)
205 0 : return 0;
206 :
207 0 : if (!nr_is_stun_message(buf, len))
208 0 : return 0;
209 :
210 0 : memcpy(&type, buf, 2);
211 0 : type = ntohs(type);
212 :
213 0 : return NR_STUN_GET_TYPE_CLASS(type) == NR_CLASS_RESPONSE
214 0 : || NR_STUN_GET_TYPE_CLASS(type) == NR_CLASS_ERROR_RESPONSE;
215 : }
216 :
217 : int
218 0 : nr_has_stun_cookie(UCHAR *buf, int len)
219 : {
220 : static UINT4 cookie;
221 :
222 0 : cookie = htonl(NR_STUN_MAGIC_COOKIE);
223 :
224 0 : if (sizeof(nr_stun_message_header) > len)
225 0 : return 0;
226 :
227 0 : if (memcmp(&cookie, &buf[4], sizeof(UINT4)))
228 0 : return 0;
229 :
230 0 : return 1;
231 : }
232 :
233 : int
234 0 : nr_stun_message_length(UCHAR *buf, int buf_len, int *msg_len)
235 : {
236 : nr_stun_message_header *hdr;
237 :
238 0 : if (!nr_is_stun_message(buf, buf_len))
239 0 : return(R_BAD_DATA);
240 :
241 0 : hdr = (nr_stun_message_header *)buf;
242 :
243 0 : *msg_len = ntohs(hdr->length);
244 :
245 0 : return(0);
246 : }
247 :
248 :
249 :
|