~ubuntu-branches/ubuntu/jaunty/sip-tester/jaunty

« back to all changes in this revision

Viewing changes to prepare_pcap.c

  • Committer: Bazaar Package Importer
  • Author(s): Nico Golde
  • Date: 2008-05-04 13:58:41 UTC
  • mfrom: (3.1.2 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080504135841-1oykxb0mtrrn7pfu
Tags: 2.0.1-1.2
* Non-maintainer upload by the Security Team.
* CVE-2008-1959: Fix stack-based buffer overflow in the
  get_remote_video_port_media function
* CVE-2008-2085: Fix stack-baseed buffer overflow in the
  get_remote_ip_media and get_remote_ipv6_media
  functions which lead to arbitrary code execution (Closes: #479039).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  This program is free software; you can redistribute it and/or modify
 
3
 *  it under the terms of the GNU General Public License as published by
 
4
 *  the Free Software Foundation; either version 2 of the License, or
 
5
 *  (at your option) any later version.
 
6
 *
 
7
 *  This program is distributed in the hope that it will be useful,
 
8
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
 *  GNU General Public License for more details.
 
11
 *
 
12
 *  You should have received a copy of the GNU General Public License
 
13
 *  along with this program; if not, write to the Free Software
 
14
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
 *
 
16
 *  Author : Guillaume TEISSIER from FTR&D 02/02/2006
 
17
 */
 
18
#include <pcap.h>
 
19
#include <stdlib.h>
 
20
#include <netinet/in.h>
 
21
#include <netinet/udp.h>
 
22
#if defined(__HPUX) || defined(__CYGWIN)
 
23
#include <netinet/in_systm.h>
 
24
#endif
 
25
#include <netinet/ip.h>
 
26
#ifndef __CYGWIN
 
27
#include <netinet/ip6.h>
 
28
#endif
 
29
#include <string.h>
 
30
 
 
31
#include "prepare_pcap.h"
 
32
#include "screen.hpp"
 
33
 
 
34
/* We define our own structures for Ethernet Header and IPv6 Header as they are not available on CYGWIN.
 
35
 * We only need the fields, which are necessary to determine the type of the next header.
 
36
 * we could also define our own structures for UDP and IPv4. We currently use the structures
 
37
 * made available by the platform, as we had no problems to get them on all supported platforms.
 
38
 */
 
39
 
 
40
typedef struct _ether_hdr {
 
41
      char ether_dst[6];
 
42
      char ether_src[6];
 
43
      u_int16_t ether_type; /* we only need the type, so we can determine, if the next header is IPv4 or IPv6 */
 
44
} ether_hdr;
 
45
 
 
46
typedef struct _ipv6_hdr {
 
47
    char dontcare[6];
 
48
    u_int8_t nxt_header; /* we only need the next header, so we can determine, if the next header is UDP or not */
 
49
    char dontcare2[33];
 
50
} ipv6_hdr;
 
51
 
 
52
 
 
53
#ifdef __HPUX
 
54
int check(u_int16_t *buffer, int len){
 
55
#else
 
56
inline int check(u_int16_t *buffer, int len){
 
57
#endif
 
58
  int sum;
 
59
  int i;
 
60
  sum = 0;
 
61
 
 
62
  for (i=0; i<(len&~1); i+= 2)
 
63
    sum += *buffer++;
 
64
 
 
65
  if (len & 1) {
 
66
    sum += htons( (*(const u_int8_t *)buffer) << 8);
 
67
  }
 
68
  return sum;
 
69
}
 
70
 
 
71
#ifdef __HPUX
 
72
u_int16_t checksum_carry(int s) {
 
73
#else
 
74
inline u_int16_t checksum_carry(int s) {
 
75
#endif
 
76
        int s_c = (s >> 16) + (s & 0xffff);
 
77
        return (~(s_c + (s_c >> 16)) & 0xffff);
 
78
}
 
79
 
 
80
char errbuf[PCAP_ERRBUF_SIZE];
 
81
 
 
82
/* prepare a pcap file
 
83
 */
 
84
int prepare_pkts(char *file, pcap_pkts *pkts) {
 
85
  pcap_t *pcap;
 
86
  struct pcap_pkthdr *pkthdr = NULL;
 
87
  u_char *pktdata = NULL;
 
88
  int n_pkts = 0;
 
89
  u_long max_length = 0;
 
90
  u_int16_t base = 0xffff;
 
91
  u_long pktlen;
 
92
  pcap_pkt *pkt_index;
 
93
  ether_hdr *ethhdr;
 
94
  struct iphdr *iphdr;
 
95
  ipv6_hdr *ip6hdr;
 
96
  struct udphdr *udphdr;
 
97
 
 
98
  pkts->pkts = NULL;
 
99
 
 
100
  pcap = pcap_open_offline(file, errbuf);
 
101
  if (!pcap) 
 
102
    ERROR_P1("Can't open PCAP file '%s'", file);
 
103
 
 
104
#if HAVE_PCAP_NEXT_EX
 
105
  while (pcap_next_ex (pcap, &pkthdr, (const u_char **) &pktdata) == 1)
 
106
  {
 
107
#else
 
108
#ifdef __HPUX
 
109
  pkthdr = (pcap_pkthdr *) malloc (sizeof (*pkthdr));
 
110
#else
 
111
  pkthdr = malloc (sizeof (*pkthdr));
 
112
#endif
 
113
  if (!pkthdr)
 
114
    ERROR("Can't allocate memory for pcap pkthdr");
 
115
  while ((pktdata = (u_char *) pcap_next (pcap, pkthdr)) != NULL)
 
116
  {
 
117
#endif
 
118
    ethhdr = (ether_hdr *)pktdata;
 
119
    if (ntohs(ethhdr->ether_type) != 0x0800 /* IPv4 */
 
120
          && ntohs(ethhdr->ether_type) != 0x86dd) /* IPv6 */ {
 
121
      fprintf(stderr, "Ignoring non IP{4,6} packet!\n");
 
122
      continue;
 
123
    }
 
124
    iphdr = (struct iphdr *)((char *)ethhdr + sizeof(*ethhdr));
 
125
    if (iphdr && iphdr->version == 6) {
 
126
      //ipv6
 
127
      pktlen = (u_long) pkthdr->len - sizeof(*ethhdr) - sizeof(*ip6hdr);
 
128
      ip6hdr = (ipv6_hdr *)(void *) iphdr;
 
129
      if (ip6hdr->nxt_header != IPPROTO_UDP) {
 
130
        fprintf(stderr, "prepare_pcap.c: Ignoring non UDP packet!\n");
 
131
             continue;
 
132
      }
 
133
      udphdr = (struct udphdr *)((char *)ip6hdr + sizeof(*ip6hdr));
 
134
    } else {
 
135
      //ipv4
 
136
      if (iphdr->protocol != IPPROTO_UDP) {
 
137
        fprintf(stderr, "prepare_pcap.c: Ignoring non UDP packet!\n");
 
138
        continue;
 
139
      }
 
140
#if defined(__DARWIN) || defined(__CYGWIN)
 
141
      udphdr = (struct udphdr *)((char *)iphdr + (iphdr->ihl << 2) + 4);
 
142
      pktlen = (u_long)(ntohs(udphdr->uh_ulen));
 
143
#elif defined ( __HPUX)
 
144
      udphdr = (struct udphdr *)((char *)iphdr + (iphdr->ihl << 2));
 
145
      pktlen = (u_long) pkthdr->len - sizeof(*ethhdr) - sizeof(*iphdr);
 
146
#else
 
147
      udphdr = (struct udphdr *)((char *)iphdr + (iphdr->ihl << 2));
 
148
      pktlen = (u_long)(ntohs(udphdr->len));
 
149
#endif
 
150
    }
 
151
    if (pktlen > PCAP_MAXPACKET) {
 
152
      ERROR("Packet size is too big! Recompile with bigger PCAP_MAXPACKET in prepare_pcap.h");
 
153
    }
 
154
    pkts->pkts = (pcap_pkt *) realloc(pkts->pkts, sizeof(*(pkts->pkts)) * (n_pkts + 1));
 
155
    if (!pkts->pkts)
 
156
      ERROR("Can't re-allocate memory for pcap pkt");
 
157
    pkt_index = pkts->pkts + n_pkts;
 
158
    pkt_index->pktlen = pktlen;
 
159
    pkt_index->ts = pkthdr->ts;
 
160
    pkt_index->data = (unsigned char *) malloc(pktlen);
 
161
    if (!pkt_index->data) 
 
162
      ERROR("Can't allocate memory for pcap pkt data");
 
163
    memcpy(pkt_index->data, udphdr, pktlen);
 
164
 
 
165
#if defined(__HPUX) || defined(__DARWIN) || (defined __CYGWIN)
 
166
    udphdr->uh_sum = 0 ;      
 
167
#else
 
168
    udphdr->check = 0;
 
169
#endif
 
170
 
 
171
      // compute a partial udp checksum
 
172
      // not including port that will be changed
 
173
      // when sending RTP
 
174
#if defined(__HPUX) || defined(__DARWIN) || (defined __CYGWIN)
 
175
    pkt_index->partial_check = check((u_int16_t *) &udphdr->uh_ulen, pktlen - 4) + ntohs(IPPROTO_UDP + pktlen);
 
176
#else
 
177
    pkt_index->partial_check = check((u_int16_t *) &udphdr->len, pktlen - 4) + ntohs(IPPROTO_UDP + pktlen);
 
178
#endif
 
179
    if (max_length < pktlen)
 
180
      max_length = pktlen;
 
181
#if defined(__HPUX) || defined(__DARWIN) || (defined __CYGWIN)
 
182
    if (base > ntohs(udphdr->uh_dport))
 
183
      base = ntohs(udphdr->uh_dport);
 
184
#else
 
185
    if (base > ntohs(udphdr->dest))
 
186
      base = ntohs(udphdr->dest);
 
187
#endif
 
188
    n_pkts++;
 
189
  }
 
190
  pkts->max = pkts->pkts + n_pkts;
 
191
  pkts->max_length = max_length;
 
192
  pkts->base = base;
 
193
  fprintf(stderr, "In pcap %s, npkts %d\nmax pkt length %ld\nbase port %d\n", file, n_pkts, max_length, base);
 
194
  pcap_close(pcap);
 
195
 
 
196
  return 0;
 
197
}
 
198
 
 
199
void free_pkts(pcap_pkts *pkts) {
 
200
  pcap_pkt *pkt_index;
 
201
  while (pkt_index < pkts->max) {
 
202
    free(pkt_index->data);
 
203
  }
 
204
  free(pkts->pkts);
 
205
}