Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /*
2 Copyright (c) 2007, Adobe Systems, Incorporated
3 All rights reserved.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
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.
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.
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 */
35 static char *RCSSTRING __UNUSED__="$Id: ice_parser.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
37 #include <csi_platform.h>
38 #include <sys/types.h>
39 #ifdef WIN32
40 #include <winsock2.h>
41 #else
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 #include <strings.h>
46 #endif
47 #include <string.h>
48 #include <assert.h>
49 #include <ctype.h>
50 #include "nr_api.h"
51 #include "ice_ctx.h"
52 #include "ice_candidate.h"
53 #include "ice_reg.h"
55 static void
56 skip_whitespace(char **str)
57 {
58 char *c = *str;
59 while (*c == ' ')
60 ++c;
62 *str = c;
63 }
65 static void
66 fast_forward(char **str, int skip)
67 {
68 char *c = *str;
69 while (*c != '\0' && skip-- > 0)
70 ++c;
72 *str = c;
73 }
75 static void
76 skip_to_past_space(char **str)
77 {
78 char *c = *str;
79 while (*c != ' ' && *c != '\0')
80 ++c;
82 *str = c;
84 skip_whitespace(str);
85 }
87 static int
88 grab_token(char **str, char **out)
89 {
90 int _status;
91 char *c = *str;
92 int len;
93 char *tmp;
95 while (*c != ' ' && *c != '\0')
96 ++c;
98 len = c - *str;
100 tmp = RMALLOC(len + 1);
101 if (!tmp)
102 ABORT(R_NO_MEMORY);
104 memcpy(tmp, *str, len);
105 tmp[len] = '\0';
107 *str = c;
108 *out = tmp;
110 _status = 0;
111 abort:
112 return _status;
113 }
115 int
116 nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *orig,nr_ice_media_stream *stream,nr_ice_candidate **candp)
117 {
118 int r,_status;
119 char* str = orig;
120 nr_ice_candidate *cand;
121 char *connection_address=0;
122 unsigned int port;
123 in_addr_t addr;
124 int i;
125 unsigned int component_id;
126 char *rel_addr=0;
128 if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
129 ABORT(R_NO_MEMORY);
131 if(!(cand->label=r_strdup(orig)))
132 ABORT(R_NO_MEMORY);
134 cand->ctx=ctx;
135 cand->isock=0;
136 cand->state=NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED;
137 cand->stream=stream;
138 skip_whitespace(&str);
140 /* Candidate attr */
141 if (strncasecmp(str, "candidate:", 10))
142 ABORT(R_BAD_DATA);
144 fast_forward(&str, 10);
145 if (*str == '\0')
146 ABORT(R_BAD_DATA);
148 skip_whitespace(&str);
149 if (*str == '\0')
150 ABORT(R_BAD_DATA);
152 /* Foundation */
153 if ((r=grab_token(&str, &cand->foundation)))
154 ABORT(r);
156 if (*str == '\0')
157 ABORT(R_BAD_DATA);
159 skip_whitespace(&str);
160 if (*str == '\0')
161 ABORT(R_BAD_DATA);
163 /* component */
164 if (sscanf(str, "%u", &component_id) != 1)
165 ABORT(R_BAD_DATA);
167 if (component_id < 1 || component_id > 256)
168 ABORT(R_BAD_DATA);
170 cand->component_id = (UCHAR)component_id;
172 skip_to_past_space(&str);
173 if (*str == '\0')
174 ABORT(R_BAD_DATA);
176 /* Protocol */
177 if (strncasecmp(str, "UDP", 3))
178 ABORT(R_BAD_DATA);
180 fast_forward(&str, 3);
181 if (*str == '\0')
182 ABORT(R_BAD_DATA);
184 skip_whitespace(&str);
185 if (*str == '\0')
186 ABORT(R_BAD_DATA);
188 /* priority */
189 if (sscanf(str, "%u", &cand->priority) != 1)
190 ABORT(R_BAD_DATA);
192 if (cand->priority < 1)
193 ABORT(R_BAD_DATA);
195 skip_to_past_space(&str);
196 if (*str == '\0')
197 ABORT(R_BAD_DATA);
199 /* Peer address/port */
200 if ((r=grab_token(&str, &connection_address)))
201 ABORT(r);
203 if (*str == '\0')
204 ABORT(R_BAD_DATA);
206 addr = inet_addr(connection_address);
207 if (addr == INADDR_NONE)
208 ABORT(R_BAD_DATA);
210 skip_whitespace(&str);
211 if (*str == '\0')
212 ABORT(R_BAD_DATA);
214 if (sscanf(str, "%u", &port) != 1)
215 ABORT(R_BAD_DATA);
217 if (port < 1 || port > 0x0FFFF)
218 ABORT(R_BAD_DATA);
220 /* Assume v4 for now */
221 if(r=nr_ip4_port_to_transport_addr(ntohl(addr),port,IPPROTO_UDP,&cand->addr))
222 ABORT(r);
224 skip_to_past_space(&str);
225 if (*str == '\0')
226 ABORT(R_BAD_DATA);
228 /* Type */
229 if (strncasecmp("typ", str, 3))
230 ABORT(R_BAD_DATA);
232 fast_forward(&str, 3);
233 if (*str == '\0')
234 ABORT(R_BAD_DATA);
236 skip_whitespace(&str);
237 if (*str == '\0')
238 ABORT(R_BAD_DATA);
240 assert(nr_ice_candidate_type_names[0] == 0);
241 #if __STDC_VERSION__ >= 201112L
242 _Static_assert(nr_ice_candidate_type_names[0] == 0,"Candidate name array is misformatted");
243 #endif
245 for (i = 1; nr_ice_candidate_type_names[i]; ++i) {
246 if(!strncasecmp(nr_ice_candidate_type_names[i], str, strlen(nr_ice_candidate_type_names[i]))) {
247 cand->type=i;
248 break;
249 }
250 }
251 if (nr_ice_candidate_type_names[i] == 0)
252 ABORT(R_BAD_DATA);
254 fast_forward(&str, strlen(nr_ice_candidate_type_names[i]));
256 /* Look for the other side's raddr, rport */
257 /* raddr, rport */
258 switch (cand->type) {
259 case HOST:
260 break;
261 case SERVER_REFLEXIVE:
262 case PEER_REFLEXIVE:
263 case RELAYED:
265 skip_whitespace(&str);
266 if (*str == '\0')
267 ABORT(R_BAD_DATA);
269 if (strncasecmp("raddr", str, 5))
270 ABORT(R_BAD_DATA);
272 fast_forward(&str, 5);
273 if (*str == '\0')
274 ABORT(R_BAD_DATA);
276 skip_whitespace(&str);
277 if (*str == '\0')
278 ABORT(R_BAD_DATA);
280 if ((r=grab_token(&str, &rel_addr)))
281 ABORT(r);
283 if (*str == '\0')
284 ABORT(R_BAD_DATA);
286 addr = inet_addr(rel_addr);
287 if (addr == INADDR_NONE)
288 ABORT(R_BAD_DATA);
290 skip_whitespace(&str);
291 if (*str == '\0')
292 ABORT(R_BAD_DATA);
294 if (strncasecmp("rport", str, 5))
295 ABORT(R_BAD_DATA);
297 fast_forward(&str, 5);
298 if (*str == '\0')
299 ABORT(R_BAD_DATA);
301 skip_whitespace(&str);
302 if (*str == '\0')
303 ABORT(R_BAD_DATA);
305 if (sscanf(str, "%u", &port) != 1)
306 ABORT(R_BAD_DATA);
308 if (port < 1 || port > 0x0FFFF)
309 ABORT(R_BAD_DATA);
311 /* Assume v4 for now */
312 if(r=nr_ip4_port_to_transport_addr(ntohl(addr),port,IPPROTO_UDP,&cand->base))
313 ABORT(r);
315 skip_to_past_space(&str);
316 /* it's expected to be at EOD at this point */
318 break;
319 default:
320 ABORT(R_INTERNAL);
321 break;
322 }
324 skip_whitespace(&str);
326 /* Ignore extensions per RFC 5245 S 15.1 */
327 #if 0
328 /* This used to be an assert, but we don't want to exit on invalid
329 remote data */
330 if (strlen(str) != 0) {
331 ABORT(R_BAD_DATA);
332 }
333 #endif
335 nr_ice_candidate_compute_codeword(cand);
337 *candp=cand;
339 _status=0;
340 abort:
341 if (_status){
342 r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Error parsing attribute: %s",ctx->label,orig);
343 nr_ice_candidate_destroy(&cand);
344 }
346 RFREE(connection_address);
347 RFREE(rel_addr);
348 return(_status);
349 }
352 int
353 nr_ice_peer_ctx_parse_media_stream_attribute(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *attr)
354 {
355 int r,_status;
356 char *orig = 0;
357 char *str;
359 orig = str = attr;
361 if (!strncasecmp(str, "ice-ufrag:", 10)) {
362 fast_forward(&str, 10);
363 if (*str == '\0')
364 ABORT(R_BAD_DATA);
366 skip_whitespace(&str);
367 if (*str == '\0')
368 ABORT(R_BAD_DATA);
370 if ((r=grab_token(&str, &stream->ufrag)))
371 ABORT(r);
372 }
373 else if (!strncasecmp(str, "ice-pwd:", 8)) {
374 fast_forward(&str, 8);
375 if (*str == '\0')
376 ABORT(R_BAD_DATA);
378 skip_whitespace(&str);
379 if (*str == '\0')
380 ABORT(R_BAD_DATA);
382 if ((r=grab_token(&str, &stream->pwd)))
383 ABORT(r);
384 }
385 else {
386 ABORT(R_BAD_DATA);
387 }
389 skip_whitespace(&str);
391 /* RFC 5245 grammar doesn't have an extension point for ice-pwd or
392 ice-ufrag: if there's anything left on the line, we treat it as bad. */
393 if (str[0] != '\0') {
394 ABORT(R_BAD_DATA);
395 }
397 _status=0;
398 abort:
399 if (_status) {
400 if (orig)
401 r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): Error parsing attribute: %s",pctx->label,orig);
402 }
404 return(_status);
405 }
407 int
408 nr_ice_peer_ctx_parse_global_attributes(nr_ice_peer_ctx *pctx, char **attrs, int attr_ct)
409 {
410 int r,_status;
411 int i;
412 char *orig = 0;
413 char *str;
414 char *component_id = 0;
415 char *connection_address = 0;
416 unsigned int port;
417 in_addr_t addr;
418 char *ice_option_tag = 0;
420 for(i=0;i<attr_ct;i++){
421 orig = str = attrs[i];
423 component_id = 0;
424 connection_address = 0;
425 ice_option_tag = 0;
427 if (!strncasecmp(str, "remote-candidates:", 18)) {
428 fast_forward(&str, 18);
429 skip_whitespace(&str);
431 while (*str != '\0') {
432 if ((r=grab_token(&str, &component_id)))
433 ABORT(r);
435 if (*str == '\0')
436 ABORT(R_BAD_DATA);
438 skip_whitespace(&str);
439 if (*str == '\0')
440 ABORT(R_BAD_DATA);
442 if ((r=grab_token(&str, &connection_address)))
443 ABORT(r);
445 if (*str == '\0')
446 ABORT(R_BAD_DATA);
448 addr = inet_addr(connection_address);
449 if (addr == INADDR_NONE)
450 ABORT(R_BAD_DATA);
452 skip_whitespace(&str);
453 if (*str == '\0')
454 ABORT(R_BAD_DATA);
456 if (sscanf(str, "%u", &port) != 1)
457 ABORT(R_BAD_DATA);
459 if (port < 1 || port > 0x0FFFF)
460 ABORT(R_BAD_DATA);
462 skip_to_past_space(&str);
464 #if 0
465 /* TODO: !nn! just drop on the floor for now, later put somewhere */
466 /* Assume v4 for now */
467 if(r=nr_ip4_port_to_transport_addr(ntohl(addr),port,IPPROTO_UDP,&candidate->base))
468 ABORT(r);
470 TAILQ_INSERT_TAIL(head, elm, field);
471 #endif
473 component_id = 0; /* prevent free */
474 RFREE(connection_address);
475 connection_address = 0; /* prevent free */
476 }
477 }
478 else if (!strncasecmp(str, "ice-lite", 8)) {
479 pctx->peer_lite = 1;
481 fast_forward(&str, 8);
482 }
483 else if (!strncasecmp(str, "ice-mismatch", 12)) {
484 pctx->peer_ice_mismatch = 1;
486 fast_forward(&str, 12);
487 }
488 else if (!strncasecmp(str, "ice-ufrag:", 10)) {
489 fast_forward(&str, 10);
490 if (*str == '\0')
491 ABORT(R_BAD_DATA);
493 skip_whitespace(&str);
494 if (*str == '\0')
495 ABORT(R_BAD_DATA);
497 RFREE(pctx->peer_ufrag);
498 pctx->peer_ufrag = 0;
499 if ((r=grab_token(&str, &pctx->peer_ufrag)))
500 ABORT(r);
501 }
502 else if (!strncasecmp(str, "ice-pwd:", 8)) {
503 fast_forward(&str, 8);
504 if (*str == '\0')
505 ABORT(R_BAD_DATA);
507 skip_whitespace(&str);
508 if (*str == '\0')
509 ABORT(R_BAD_DATA);
511 RFREE(pctx->peer_pwd);
512 pctx->peer_pwd = 0;
513 if ((r=grab_token(&str, &pctx->peer_pwd)))
514 ABORT(r);
515 }
516 else if (!strncasecmp(str, "ice-options:", 12)) {
517 fast_forward(&str, 12);
518 skip_whitespace(&str);
520 while (*str != '\0') {
521 if ((r=grab_token(&str, &ice_option_tag)))
522 ABORT(r);
524 skip_whitespace(&str);
526 //TODO: for now, just throw away; later put somewhere
527 RFREE(ice_option_tag);
529 ice_option_tag = 0; /* prevent free */
530 }
531 }
532 else {
533 ABORT(R_BAD_DATA);
534 }
536 skip_whitespace(&str);
538 /* RFC 5245 grammar doesn't have an extension point for any of the
539 preceding attributes: if there's anything left on the line, we
540 treat it as bad data. */
541 if (str[0] != '\0') {
542 ABORT(R_BAD_DATA);
543 }
544 }
546 _status=0;
547 abort:
548 if (_status) {
549 if (orig)
550 r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): Error parsing attribute: %s",pctx->label,orig);
551 }
553 RFREE(connection_address);
554 RFREE(component_id);
555 RFREE(ice_option_tag);
556 return(_status);
557 }