dsniff  2.4b2
About: A collection of tools for network auditing
  Fossies Dox: dsniff-2.4b2.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

urlsnarf.c
Go to the documentation of this file.
1 /*
2  * urlsnarf.c
3  *
4  * Sniff the network for HTTP request URLs, output in CLF format.
5  *
6  * Copyright (c) 1999 Dug Song <dugsong@monkey.org>
7  *
8  * $Id: urlsnarf.c,v 1.35 2001/03/15 09:26:13 dugsong Exp $
9  */
10 
11 #include "config.h"
12 
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <netinet/in.h>
16 #include <arpa/inet.h>
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <regex.h>
23 #include <time.h>
24 #include <err.h>
25 #include <libnet.h>
26 #include <nids.h>
27 #include <pcap.h>
28 
29 #include "pcaputil.h"
30 #include "buf.h"
31 #include "base64.h"
32 #include "version.h"
33 
34 #define DEFAULT_PCAP_FILTER "tcp port 80 or port 8080 or port 3128"
35 
36 u_short Opt_dns = 1;
37 int Opt_invert = 0;
38 regex_t *pregex = NULL;
39 
40 static void
41 usage(void)
42 {
43  fprintf(stderr, "Version: " VERSION "\n"
44  "Usage: urlsnarf [-n] [-i interface] [[-v] pattern [expression]]\n");
45  exit(1);
46 }
47 
48 static int
49 regex_match(char *string)
50 {
51  return (pregex == NULL ||
52  ((regexec(pregex, string, 0, NULL, 0) == 0) ^ Opt_invert));
53 }
54 
55 static char *
56 timestamp(void)
57 {
58  static char tstr[32], sign;
59  struct tm *t, gmt;
60  time_t tt = time(NULL);
61  int days, hours, tz, len;
62 
63  gmt = *gmtime(&tt);
64  t = localtime(&tt);
65 
66  days = t->tm_yday - gmt.tm_yday;
67  hours = ((days < -1 ? 24 : 1 < days ? -24 : days * 24) +
68  t->tm_hour - gmt.tm_hour);
69  tz = hours * 60 + t->tm_min - gmt.tm_min;
70 
71  len = strftime(tstr, sizeof(tstr), "%e/%b/%Y:%X", t);
72  if (len < 0 || len > sizeof(tstr) - 5)
73  return (NULL);
74 
75  if (tz < 0) {
76  sign = '-';
77  tz = -tz;
78  }
79  else sign = '+';
80 
81  snprintf(tstr + len, sizeof(tstr) - len, " %c%.2d%.2d",
82  sign, tz / 60, tz % 60);
83 
84  return (tstr);
85 }
86 
87 static int
88 process_http_request(struct tuple4 *addr, u_char *data, int len)
89 {
90  struct buf *msg, buf;
91  char *p, *req, *uri, *user, *vhost, *referer, *agent;
92  int i;
93 
94  buf_init(&buf, data, len);
95 
96  while ((i = buf_index(&buf, "\r\n\r\n", 4)) >= 0) {
97  msg = buf_tok(&buf, NULL, i);
98  msg->base[msg->end] = '\0';
99  buf_skip(&buf, 4);
100 
101  if (!regex_match(buf_ptr(msg)))
102  continue;
103 
104  if ((req = strtok(buf_ptr(msg), "\r\n")) == NULL)
105  continue;
106 
107  if (strncmp(req, "GET ", 4) != 0 &&
108  strncmp(req, "POST ", 5) != 0 &&
109  strncmp(req, "CONNECT ", 8) != 0)
110  continue;
111 
112  if ((uri = strchr(req, ' ')) == NULL)
113  continue;
114 
115  *uri++ = '\0';
116  if (strncmp(uri, "http://", 7) == 0) {
117  for (uri += 7; *uri != '/'; uri++)
118  ;
119  }
120  user = vhost = referer = agent = NULL;
121 
122  while ((p = strtok(NULL, "\r\n")) != NULL) {
123  if (strncasecmp(p, "Authorization: Basic ", 21) == 0) {
124  p += 21;
125  i = base64_pton(p, p, strlen(p));
126  p[i] = '\0';
127  user = p;
128  if ((p = strchr(p, ':')) != NULL)
129  *p = '\0';
130  }
131  else if (strncasecmp(p, "Host: ", 6) == 0) {
132  vhost = p + 6;
133  }
134  else if (strncasecmp(p, "Referer: ", 9) == 0) {
135  referer = p + 9;
136  }
137  else if (strncasecmp(p, "User-Agent: ", 12) == 0) {
138  agent = p + 12;
139  }
140  else if (strncasecmp(p, "Content-length: ", 16) == 0) {
141  i = atoi(p + 16);
142  buf_tok(NULL, NULL, i);
143  }
144  }
145  if (user == NULL)
146  user = "-";
147  if (vhost == NULL)
148  vhost = libnet_addr2name4(addr->daddr, Opt_dns);
149  if (referer == NULL)
150  referer = "-";
151  if (agent == NULL)
152  agent = "-";
153 
154  printf("%s - %s [%s] \"%s http://%s%s\" - - \"%s\" \"%s\"\n",
155  libnet_addr2name4(addr->saddr, Opt_dns),
156  user, timestamp(), req, vhost, uri, referer, agent);
157  }
158  fflush(stdout);
159 
160  return (len - buf_len(&buf));
161 }
162 
163 static void
164 sniff_http_client(struct tcp_stream *ts, void **yoda)
165 {
166  int i;
167 
168  switch (ts->nids_state) {
169 
170  case NIDS_JUST_EST:
171  ts->server.collect = 1;
172 
173  case NIDS_DATA:
174  if (ts->server.count_new != 0) {
175  i = process_http_request(&ts->addr, ts->server.data,
176  ts->server.count -
177  ts->server.offset);
178  nids_discard(ts, i);
179  }
180  break;
181 
182  default:
183  if (ts->server.count != 0) {
184  process_http_request(&ts->addr, ts->server.data,
185  ts->server.count -
186  ts->server.offset);
187  }
188  break;
189  }
190 }
191 
192 static void
193 null_syslog(int type, int errnum, struct ip *iph, void *data)
194 {
195 }
196 
197 int
198 main(int argc, char *argv[])
199 {
200  extern char *optarg;
201  extern int optind;
202  int c;
203 
204  while ((c = getopt(argc, argv, "i:nvh?V")) != -1) {
205  switch (c) {
206  case 'i':
207  nids_params.device = optarg;
208  break;
209  case 'n':
210  Opt_dns = 0;
211  break;
212  case 'v':
213  Opt_invert = 1;
214  break;
215  default:
216  usage();
217  }
218  }
219  argc -= optind;
220  argv += optind;
221 
222  if (argc > 0 && strlen(argv[0])) {
223  if ((pregex = (regex_t *) malloc(sizeof(*pregex))) == NULL)
224  err(1, "malloc");
225  if (regcomp(pregex, argv[0], REG_EXTENDED|REG_NOSUB) != 0)
226  errx(1, "invalid regular expression");
227  }
228  if (argc > 1) {
229  nids_params.pcap_filter = copy_argv(argv + 1);
230  }
231  else nids_params.pcap_filter = DEFAULT_PCAP_FILTER;
232 
233  nids_params.scan_num_hosts = 0;
234  nids_params.syslog = null_syslog;
235 
236  if (!nids_init())
237  errx(1, "%s", nids_errbuf);
238 
239  nids_register_tcp(sniff_http_client);
240 
241  warnx("listening on %s [%s]", nids_params.device,
242  nids_params.pcap_filter);
243 
244  nids_run();
245 
246  /* NOTREACHED */
247 
248  exit(0);
249 }
warnx
void warnx(const char *fmt,...)
Definition: err.c:89
null_syslog
static void null_syslog(int type, int errnum, struct ip *iph, void *data)
Definition: urlsnarf.c:193
pregex
regex_t * pregex
Definition: urlsnarf.c:38
buf_init
void buf_init(buf_t buf, u_char *data, int len)
Definition: buf.c:24
timestamp
static char * timestamp(void)
Definition: urlsnarf.c:56
pcaputil.h
buf::base
u_char * base
Definition: buf.h:15
buf
static u_char buf[BUFSIZ]
Definition: filenamesnarf.c:29
version.h
DEFAULT_PCAP_FILTER
#define DEFAULT_PCAP_FILTER
Definition: urlsnarf.c:34
buf.h
sniff_http_client
static void sniff_http_client(struct tcp_stream *ts, void **yoda)
Definition: urlsnarf.c:164
process_http_request
static int process_http_request(struct tuple4 *addr, u_char *data, int len)
Definition: urlsnarf.c:88
err.h
VERSION
#define VERSION
Definition: version.h:1
buf
Definition: buf.h:14
err
void err(int eval, const char *fmt,...)
Definition: err.c:47
base64.h
buf_tok
buf_t buf_tok(buf_t buf, void *sep, int len)
Definition: buf.c:167
buf_ptr
#define buf_ptr(b)
Definition: buf.h:31
Opt_invert
int Opt_invert
Definition: urlsnarf.c:37
copy_argv
char * copy_argv(char **argv)
Definition: pcaputil.c:101
errx
void errx(int eval, const char *fmt,...)
Definition: err.c:76
main
int main(int argc, char *argv[])
Definition: urlsnarf.c:198
base64_pton
int base64_pton(char const *src, u_char *target, size_t targsize)
Definition: base64.c:128
regex_match
static int regex_match(char *string)
Definition: urlsnarf.c:49
buf_skip
#define buf_skip(b, l)
Definition: buf.h:47
buf::end
int end
Definition: buf.h:18
usage
static void usage(void)
Definition: urlsnarf.c:41
config.h
buf_len
#define buf_len(b)
Definition: buf.h:34
Opt_dns
u_short Opt_dns
Definition: urlsnarf.c:36
buf_index
int buf_index(buf_t buf, void *ptr, int len)
Definition: buf.c:128