~ubuntu-branches/debian/stretch/libnice/stretch

« back to all changes in this revision

Viewing changes to stun/stunmessage.c

  • Committer: Package Import Robot
  • Author(s): Simon McVittie
  • Date: 2014-05-14 12:00:13 UTC
  • mfrom: (1.2.9) (5.1.13 sid)
  • Revision ID: package-import@ubuntu.com-20140514120013-fi5mh9bexrjnwnd8
Tags: 0.1.7-1
* New upstream release 0.1.6, 0.1.7
  - fixes various compiler warnings that were mistakenly fatal in 0.1.5
    (Closes: #743232, #743233)
  - update symbols file for new API
* Explicitly disable -Werror, even if we package a non-release in future
* Don't run tests during the build. We were ignoring failures already,
  and they sometimes hang until the buildd terminates them.
  Upstream (Olivier Crête) says they are stable enough to be useful
  for developers, but not for integration testing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
124
124
      case STUN_ATTRIBUTE_FINGERPRINT:
125
125
        /* Nothing may come after FPR */
126
126
        return NULL;
 
127
 
 
128
      default:
 
129
        /* Nothing misordered. */
 
130
        break;
127
131
    }
128
132
 
129
133
    if (!(msg->agent &&
219
223
 
220
224
StunMessageReturn
221
225
stun_message_find_addr (const StunMessage *msg, StunAttribute type,
222
 
    struct sockaddr *addr, socklen_t *addrlen)
 
226
    struct sockaddr_storage *addr, socklen_t *addrlen)
223
227
{
224
228
  const uint8_t *ptr;
225
229
  uint16_t len = 0;
272
276
        memcpy (&ip6->sin6_addr, ptr + 4, 16);
273
277
        return STUN_MESSAGE_RETURN_SUCCESS;
274
278
      }
 
279
 
 
280
    default:
 
281
      return STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS;
275
282
  }
276
 
 
277
 
  return STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS;
278
283
}
279
284
 
280
285
StunMessageReturn
281
286
stun_message_find_xor_addr (const StunMessage *msg, StunAttribute type,
282
 
    struct sockaddr *addr,
283
 
    socklen_t *addrlen)
 
287
    struct sockaddr_storage *addr, socklen_t *addrlen)
284
288
{
285
289
  StunMessageReturn val = stun_message_find_addr (msg, type, addr, addrlen);
286
290
  if (val)
291
295
 
292
296
StunMessageReturn
293
297
stun_message_find_xor_addr_full (const StunMessage *msg, StunAttribute type,
294
 
    struct sockaddr *addr,  socklen_t *addrlen,
295
 
    uint32_t magic_cookie)
 
298
    struct sockaddr_storage *addr, socklen_t *addrlen, uint32_t magic_cookie)
296
299
{
297
300
  StunMessageReturn val = stun_message_find_addr (msg, type, addr, addrlen);
298
301
  if (val)
352
355
     * to a multiple of 4 for compatibility with old RFC3489 */
353
356
    a = stun_setw (a, stun_message_has_cookie (msg) ? length : stun_align (length));
354
357
 
355
 
    /* Add padding if needed */
356
 
    memset (a + length, ' ', stun_padding (length));
357
 
    mlen += stun_padding (length);
 
358
    /* Add padding if needed. Avoid a zero-length memset() call. */
 
359
    if (stun_padding (length) > 0) {
 
360
      memset (a + length, ' ', stun_padding (length));
 
361
      mlen += stun_padding (length);
 
362
    }
358
363
  }
359
364
 
360
365
  mlen +=  4 + length;
372
377
  if (ptr == NULL)
373
378
    return STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE;
374
379
 
375
 
  memcpy (ptr, data, len);
 
380
  if (len > 0)
 
381
    memcpy (ptr, data, len);
 
382
 
376
383
  return STUN_MESSAGE_RETURN_SUCCESS;
377
384
}
378
385
 
466
473
 
467
474
StunMessageReturn
468
475
stun_message_append_xor_addr (StunMessage *msg, StunAttribute type,
469
 
    const struct sockaddr *addr, socklen_t addrlen)
 
476
    const struct sockaddr_storage *addr, socklen_t addrlen)
470
477
{
471
478
  StunMessageReturn val;
472
479
  /* Must be big enough to hold any supported address: */
473
 
  struct sockaddr_storage xor;
474
 
 
475
 
  if ((size_t) addrlen > sizeof (xor))
476
 
    addrlen = sizeof (xor);
477
 
  memcpy (&xor, addr, addrlen);
478
 
 
479
 
  val = stun_xor_address (msg, (struct sockaddr *)&xor, addrlen,
 
480
  struct sockaddr_storage tmpaddr;
 
481
 
 
482
  if ((size_t) addrlen > sizeof (tmpaddr))
 
483
    addrlen = sizeof (tmpaddr);
 
484
  memcpy (&tmpaddr, addr, addrlen);
 
485
 
 
486
  val = stun_xor_address (msg, &tmpaddr, addrlen,
480
487
      STUN_MAGIC_COOKIE);
481
488
  if (val)
482
489
    return val;
483
490
 
484
 
  return stun_message_append_addr (msg, type, (struct sockaddr *)&xor,
 
491
  return stun_message_append_addr (msg, type, (struct sockaddr *) &tmpaddr,
485
492
      addrlen);
486
493
}
487
494
 
488
495
StunMessageReturn
489
496
stun_message_append_xor_addr_full (StunMessage *msg, StunAttribute type,
490
 
    const struct sockaddr *addr, socklen_t addrlen,
 
497
    const struct sockaddr_storage *addr, socklen_t addrlen,
491
498
    uint32_t magic_cookie)
492
499
{
493
500
  StunMessageReturn val;
494
501
  /* Must be big enough to hold any supported address: */
495
 
  struct sockaddr_storage xor;
496
 
 
497
 
  if ((size_t) addrlen > sizeof (xor))
498
 
    addrlen = sizeof (xor);
499
 
  memcpy (&xor, addr, addrlen);
500
 
 
501
 
  val = stun_xor_address (msg, (struct sockaddr *)&xor, addrlen, magic_cookie);
 
502
  struct sockaddr_storage tmpaddr;
 
503
 
 
504
  if ((size_t) addrlen > sizeof (tmpaddr))
 
505
    addrlen = sizeof (tmpaddr);
 
506
  memcpy (&tmpaddr, addr, addrlen);
 
507
 
 
508
  val = stun_xor_address (msg, &tmpaddr, addrlen, magic_cookie);
502
509
  if (val)
503
510
    return val;
504
511
 
505
 
  return stun_message_append_addr (msg, type, (struct sockaddr *)&xor,
 
512
  return stun_message_append_addr (msg, type, (struct sockaddr *) &tmpaddr,
506
513
      addrlen);
507
514
}
508
515
 
513
520
{
514
521
  const char *str = stun_strerror (code);
515
522
  size_t len = strlen (str);
516
 
  div_t d = div (code, 100);
517
523
 
518
524
  uint8_t *ptr = stun_message_append (msg, STUN_ATTRIBUTE_ERROR_CODE, 4 + len);
519
525
  if (ptr == NULL)
520
526
    return STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE;
521
527
 
522
528
  memset (ptr, 0, 2);
523
 
  ptr[2] = d.quot;
524
 
  ptr[3] = d.rem;
 
529
  ptr[2] = code / 100;
 
530
  ptr[3] = code % 100;
525
531
  memcpy (ptr + 4, str, len);
526
532
  return STUN_MESSAGE_RETURN_SUCCESS;
527
533
}
528
534
 
529
 
int stun_message_validate_buffer_length (const uint8_t *msg, size_t length,
530
 
    bool has_padding)
 
535
/* Fast validity check for a potential STUN packet. Examines the type and
 
536
 * length, but none of the attributes. Designed to allow vectored I/O on all
 
537
 * incoming packets, filtering packets for closer inspection as to whether
 
538
 * they’re STUN packets. If they look like they might be, their buffers are
 
539
 * compacted to allow a more thorough check. */
 
540
ssize_t stun_message_validate_buffer_length_fast (StunInputVector *buffers,
 
541
    unsigned int n_buffers, size_t total_length, bool has_padding)
531
542
{
532
543
  size_t mlen;
533
 
  size_t len;
534
544
 
535
 
  if (length < 1)
 
545
  if (total_length < 1 || n_buffers < 1)
536
546
  {
537
547
    stun_debug ("STUN error: No data!\n");
538
548
    return STUN_MESSAGE_BUFFER_INVALID;
539
549
  }
540
550
 
541
 
  if (msg[0] >> 6)
 
551
  if (buffers[0].buffer[0] >> 6)
542
552
  {
543
553
    stun_debug ("STUN error: RTP or other non-protocol packet!\n");
544
554
    return STUN_MESSAGE_BUFFER_INVALID; // RTP or other non-STUN packet
545
555
  }
546
556
 
547
 
  if (length < 4)
 
557
  if (total_length < STUN_MESSAGE_LENGTH_POS + STUN_MESSAGE_LENGTH_LEN)
548
558
  {
549
559
    stun_debug ("STUN error: Incomplete STUN message header!\n");
550
560
    return STUN_MESSAGE_BUFFER_INCOMPLETE;
551
561
  }
552
562
 
553
 
  mlen = stun_getw (msg + STUN_MESSAGE_LENGTH_POS) +
554
 
      STUN_MESSAGE_HEADER_LENGTH;
555
 
 
556
 
  if (has_padding && stun_padding (mlen))
557
 
  {
 
563
  if (buffers[0].size >= STUN_MESSAGE_LENGTH_POS + STUN_MESSAGE_LENGTH_LEN) {
 
564
    /* Fast path. */
 
565
    mlen = stun_getw (buffers[0].buffer + STUN_MESSAGE_LENGTH_POS);
 
566
  } else {
 
567
    /* Slow path. Tiny buffers abound. */
 
568
    size_t skip_remaining = STUN_MESSAGE_LENGTH_POS;
 
569
    unsigned int i;
 
570
 
 
571
    /* Skip bytes. */
 
572
    for (i = 0; i < n_buffers; i++) {
 
573
      if (buffers[i].size <= skip_remaining)
 
574
        skip_remaining -= buffers[i].size;
 
575
      else
 
576
        break;
 
577
    }
 
578
 
 
579
    /* Read bytes. May be split over two buffers. We’ve already checked that
 
580
     * @total_length is long enough, so @n_buffers should be too. */
 
581
    if (buffers[i].size - skip_remaining > 1) {
 
582
      mlen = stun_getw (buffers[i].buffer + skip_remaining);
 
583
    } else {
 
584
      mlen = (*(buffers[i].buffer + skip_remaining) << 8) |
 
585
             (*(buffers[i + 1].buffer));
 
586
    }
 
587
  }
 
588
 
 
589
  mlen += STUN_MESSAGE_HEADER_LENGTH;
 
590
 
 
591
  if (has_padding && stun_padding (mlen)) {
558
592
    stun_debug ("STUN error: Invalid message length: %u!\n", (unsigned)mlen);
559
593
    return STUN_MESSAGE_BUFFER_INVALID; // wrong padding
560
594
  }
561
595
 
562
 
  if (length < mlen)
563
 
  {
 
596
  if (total_length < mlen) {
564
597
    stun_debug ("STUN error: Incomplete message: %u of %u bytes!\n",
565
 
        (unsigned)length, (unsigned)mlen);
 
598
        (unsigned) total_length, (unsigned) mlen);
566
599
    return STUN_MESSAGE_BUFFER_INCOMPLETE; // partial message
567
600
  }
568
601
 
 
602
  return mlen;
 
603
}
 
604
 
 
605
int stun_message_validate_buffer_length (const uint8_t *msg, size_t length,
 
606
    bool has_padding)
 
607
{
 
608
  ssize_t fast_retval;
 
609
  size_t mlen;
 
610
  size_t len;
 
611
  StunInputVector input_buffer = { msg, length };
 
612
 
 
613
  /* Fast pre-check first. */
 
614
  fast_retval = stun_message_validate_buffer_length_fast (&input_buffer, 1,
 
615
      length, has_padding);
 
616
  if (fast_retval <= 0)
 
617
    return fast_retval;
 
618
 
 
619
  mlen = fast_retval;
 
620
 
 
621
  /* Skip past the header (validated above). */
569
622
  msg += 20;
570
623
  len = mlen - 20;
571
624
 
572
625
  /* from then on, we know we have the entire packet in buffer */
573
626
  while (len > 0)
574
627
  {
575
 
    size_t alen = stun_getw (msg + STUN_ATTRIBUTE_TYPE_LEN);
 
628
    size_t alen;
 
629
 
 
630
    if (len < 4)
 
631
    {
 
632
      stun_debug ("STUN error: Incomplete STUN attribute header of length "
 
633
          "%u bytes!\n", (unsigned)len);
 
634
      return STUN_MESSAGE_BUFFER_INVALID;
 
635
    }
 
636
 
 
637
    alen = stun_getw (msg + STUN_ATTRIBUTE_TYPE_LEN);
576
638
    if (has_padding)
577
639
      alen = stun_align (alen);
578
640