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)  

trigger.c
Go to the documentation of this file.
1 /*
2  * trigger.c
3  *
4  * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
5  *
6  * $Id: trigger.c,v 1.21 2001/03/15 08:33:05 dugsong Exp $
7  */
8 
9 #include "config.h"
10 
11 #include <sys/types.h>
12 #include <sys/uio.h>
13 #include <netinet/in.h>
14 
15 #include <stdlib.h>
16 #include <err.h>
17 #include <libnet.h>
18 #include <nids.h>
19 
20 #include "decode.h"
21 #include "magic.h"
22 #include "options.h"
23 #include "pathnames.h"
24 #include "record.h"
25 #include "tcp_raw.h"
26 #include "trigger.h"
27 
28 struct trigger {
29  int num;
30  struct decode *decode;
31 };
32 
33 static struct trigger ip_triggers[32];
34 static struct trigger udp_triggers[512];
35 static struct trigger tcp_triggers[512];
36 static struct trigger rpc_triggers[32];
37 
38 static u_int ip_cnt = 0;
39 static u_int udp_cnt = 0;
40 static u_int tcp_cnt = 0;
41 static u_int rpc_cnt = 0;
42 
43 static char obuf[4096];
44 
45 static int
46 trigger_compare(const void *a, const void *b)
47 {
48  struct trigger *p, *q;
49 
50  q = (struct trigger *)a;
51  p = (struct trigger *)b;
52 
53  if (p->num < q->num) {
54  return (-1);
55  }
56  else if (p->num > q->num) {
57  return (1);
58  }
59  return (0);
60 }
61 
62 int
63 trigger_set_ip(int num, char *name)
64 {
65  struct trigger *t, tr;
66 
67  tr.num = num;
68 
69  if ((tr.decode = getdecodebyname(name)) == NULL) {
70  warnx("trigger_set_ip: unknown decode: %s", name);
71  return (0);
72  }
73  t = (struct trigger *) bsearch(&tr, &ip_triggers, ip_cnt,
74  sizeof(tr), trigger_compare);
75  if (t != NULL) {
76  if (Opt_debug)
77  warnx("trigger_set_ip: proto %d already set", num);
78  return (0);
79  }
80  if (ip_cnt == sizeof(ip_triggers) / sizeof(tr)) {
81  warnx("trigger_set_ip: ip_triggers full");
82  return (0);
83  }
84  ip_triggers[ip_cnt++] = tr;
85 
86  qsort(&ip_triggers, ip_cnt, sizeof(tr), trigger_compare);
87 
88  if (Opt_debug)
89  warnx("trigger_set_ip: proto %d -> %s", num, name);
90 
91  return (1);
92 }
93 
94 int
95 trigger_set_udp(int num, char *name)
96 {
97  struct trigger *t, tr;
98 
99  tr.num = num;
100 
101  if ((tr.decode = getdecodebyname(name)) == NULL) {
102  warnx("trigger_set_udp: unknown decode: %s", name);
103  return (0);
104  }
105  t = (struct trigger *) bsearch(&tr, &udp_triggers, udp_cnt,
106  sizeof(tr), trigger_compare);
107  if (t != NULL) {
108  if (Opt_debug)
109  warnx("trigger_set_udp: port %d already set", num);
110  return (0);
111  }
112  if (udp_cnt == sizeof(udp_triggers) / sizeof(tr)) {
113  warnx("trigger_set_udp: udp_triggers full");
114  return (0);
115  }
116  udp_triggers[udp_cnt++] = tr;
117 
118  qsort(&udp_triggers, udp_cnt, sizeof(tr), trigger_compare);
119 
120  if (Opt_debug)
121  warnx("trigger_set_udp: port %d -> %s", num, name);
122 
123  return (1);
124 }
125 
126 int
127 trigger_set_tcp(int num, char *name)
128 {
129  struct trigger *t, tr;
130 
131  tr.num = num;
132 
133  if ((tr.decode = getdecodebyname(name)) == NULL) {
134  warnx("trigger_set_tcp: unknown decode: %s", name);
135  return (0);
136  }
137  t = (struct trigger *) bsearch(&tr, &tcp_triggers, tcp_cnt,
138  sizeof(tr), trigger_compare);
139  if (t != NULL) {
140  if (Opt_debug)
141  warnx("trigger_set_tcp: port %d already set", num);
142  return (0);
143  }
144  if (tcp_cnt == sizeof(tcp_triggers) / sizeof(tr)) {
145  warnx("trigger_set_tcp: tcp_triggers full");
146  return (0);
147  }
148  tcp_triggers[tcp_cnt++] = tr;
149 
150  qsort(&tcp_triggers, tcp_cnt, sizeof(tr), trigger_compare);
151 
152  if (Opt_debug)
153  warnx("trigger_set_tcp: port %d -> %s", num, name);
154 
155  return (1);
156 }
157 
158 int
159 trigger_set_rpc(int num, char *name)
160 {
161  struct trigger *t, tr;
162 
163  tr.num = num;
164 
165  if ((tr.decode = getdecodebyname(name)) == NULL) {
166  warnx("trigger_set_tcp: unknown decode: %s", name);
167  return (0);
168  }
169  t = (struct trigger *) bsearch(&tr, &rpc_triggers, rpc_cnt,
170  sizeof(tr), trigger_compare);
171  if (t != NULL) {
172  if (Opt_debug)
173  warnx("trigger_set_rpc: RPC program %d already set",
174  num);
175  return (0);
176  }
177  if (rpc_cnt == sizeof(rpc_triggers) / sizeof(tr)) {
178  warnx("trigger_set_rpc: rpc_triggers full");
179  return (0);
180  }
181  rpc_triggers[rpc_cnt++] = tr;
182 
183  qsort(&rpc_triggers, rpc_cnt, sizeof(tr), trigger_compare);
184 
185  if (Opt_debug)
186  warnx("trigger_set_rpc: program %d -> %s", num, name);
187 
188  return (1);
189 }
190 
191 static int
192 trigger_set(char *proto, int num, char *name)
193 {
194  if (strcasecmp(proto, "ip") == 0) {
195  return (trigger_set_ip(num, name));
196  }
197  else if (strcasecmp(proto, "udp") == 0) {
198  return (trigger_set_udp(num, name));
199  }
200  else if (strcasecmp(proto, "tcp") == 0) {
201  return (trigger_set_tcp(num, name));
202  }
203  else if (strcasecmp(proto, "rpc") == 0) {
204  return (trigger_set_rpc(num, name));
205  }
206  else warnx("trigger_set: unknown protocol %s", proto);
207 
208  return (0);
209 }
210 
211 static struct trigger *
212 trigger_set_magic(int proto, int num, u_char *buf, int len)
213 {
214  struct trigger *t, tr;
215  char *name;
216 
217  if ((name = magic_match(buf, len)) == NULL)
218  return (NULL);
219 
220  t = NULL;
221  tr.num = num;
222 
223  if (proto == IPPROTO_UDP) {
224  trigger_set_udp(num, name);
225  if (strcmp(name, "portmap") == 0 || /* XXX - hack */
226  strcmp(name, "mountd") == 0 ||
227  strcmp(name, "yppasswd") == 0) {
228  trigger_set_udp(0 - num, name);
229  }
230  t = (struct trigger *) bsearch(&tr, &udp_triggers, udp_cnt,
231  sizeof(tr), trigger_compare);
232  }
233  else if (proto == IPPROTO_TCP) {
234  trigger_set_tcp(num, name);
235  if (strcmp(name, "portmap") == 0 || /* XXX - hack */
236  strcmp(name, "mountd") == 0 ||
237  strcmp(name, "yppasswd") == 0) {
238  trigger_set_tcp(0 - num, name);
239  }
240  t = (struct trigger *) bsearch(&tr, &tcp_triggers, tcp_cnt,
241  sizeof(tr), trigger_compare);
242  }
243  return (t);
244 }
245 
246 void
248 {
249  FILE *f;
250  int i;
251 
252  if ((f = fopen(DSNIFF_SERVICES, "w")) == NULL) {
253  warn("trigger_dump: couldn't open " DSNIFF_SERVICES);
254  return;
255  }
256  fprintf(f, "# $Id: trigger.c,v 1.21 2001/03/15 08:33:05 dugsong Exp $\n"
257  "#\n# Network services, dsniff style\n#\n");
258 
259  for (i = 0; i < ip_cnt; i++) {
260  fprintf(f, "%s\t\t%d/ip\n", ip_triggers[i].decode->dc_name,
261  ip_triggers[i].num);
262  }
263  for (i = 0; i < udp_cnt; i++) {
264  fprintf(f, "%s\t\t%d/udp\n", udp_triggers[i].decode->dc_name,
265  udp_triggers[i].num);
266  }
267  for (i = 0; i < tcp_cnt; i++) {
268  fprintf(f, "%s\t\t%d/tcp\n", tcp_triggers[i].decode->dc_name,
269  tcp_triggers[i].num);
270  }
271  for (i = 0; i < rpc_cnt; i++) {
272  fprintf(f, "%s\t\t%d/rpc\n", rpc_triggers[i].decode->dc_name,
273  rpc_triggers[i].num);
274  }
275  fclose(f);
276 }
277 
278 void
279 trigger_ip(struct libnet_ipv4_hdr *ip)
280 {
281  struct trigger *t, tr;
282  u_char *buf;
283  int len;
284 
285  tr.num = ip->ip_p;
286 
287  t = (struct trigger *) bsearch(&tr, &ip_triggers, ip_cnt,
288  sizeof(tr), trigger_compare);
289 
290  if (t == NULL)
291  return;
292 
293  buf = (u_char *)ip + (ip->ip_hl * 4);
294  len = ntohs(ip->ip_len) - (ip->ip_hl * 4);
295 
296  if (Opt_debug)
297  warnx("trigger_ip: decoding proto %d as %s",
298  tr.num, t->decode->dc_name);
299 
300  if ((len = t->decode->dc_func(buf, len, obuf, sizeof(obuf))) > 0) {
301  record(ip->ip_src.s_addr, ip->ip_dst.s_addr, ip->ip_p,
302  0, 0, t->decode->dc_name, obuf, len);
303  }
304 }
305 
306 /* libnids needs a nids_register_udp()... */
307 void
308 trigger_udp(struct libnet_ipv4_hdr *ip)
309 {
310  struct trigger *t, tr;
311  struct libnet_udp_hdr *udp;
312  u_char *buf;
313  int len, ip_hl = ip->ip_hl * 4;
314 
315  len = ntohs(ip->ip_len) - ip_hl;
316 
317  if (ip->ip_p != IPPROTO_UDP || len < sizeof(*udp))
318  return;
319 
320  buf = (u_char *)ip + ip_hl;
321  udp = (struct libnet_udp_hdr *)buf;
322 
323  if (len != ntohs(udp->uh_ulen))
324  return;
325 
326  buf += sizeof(*udp);
327  len -= sizeof(*udp);
328 
329  tr.num = ntohs(udp->uh_dport);
330  t = (struct trigger *) bsearch(&tr, &udp_triggers, udp_cnt,
331  sizeof(tr), trigger_compare);
332  if (t == NULL) {
333  tr.num = 0 - (int) ntohs(udp->uh_sport);
334  t = (struct trigger *) bsearch(&tr, &udp_triggers, udp_cnt,
335  sizeof(tr), trigger_compare);
336  if (t == NULL && Opt_magic)
337  t = trigger_set_magic(IPPROTO_UDP,
338  ntohs(udp->uh_dport), buf, len);
339  if (t == NULL)
340  return;
341  }
342  if (Opt_debug)
343  warnx("trigger_udp: decoding port %d as %s",
344  tr.num, t->decode->dc_name);
345 
346  if ((len = t->decode->dc_func(buf, len, obuf, sizeof(obuf))) > 0) {
347  record(ip->ip_src.s_addr, ip->ip_dst.s_addr, IPPROTO_UDP,
348  ntohs(udp->uh_sport), ntohs(udp->uh_dport),
349  t->decode->dc_name, obuf, len);
350  }
351 }
352 
353 static void
354 trigger_tcp_half(struct tuple4 *addr, struct half_stream *hs,
355  struct trigger *t)
356 {
357  u_char *buf;
358  int len;
359 
360  buf = hs->data;
361  len = hs->count - hs->offset;
362 
363  if (len == 0 || buf == NULL)
364  return;
365 
366  if (hs->bufsize > len)
367  buf[len] = '\0';
368 
369  if (t == NULL && Opt_magic)
370  t = trigger_set_magic(IPPROTO_TCP, addr->dest, buf, len);
371 
372  if (t != NULL) {
373  if (Opt_debug)
374  warnx("trigger_tcp: decoding port %d as %s",
375  addr->dest, t->decode->dc_name);
376 
377  if ((len = t->decode->dc_func(buf, len,
378  obuf, sizeof(obuf))) > 0) {
379  record(addr->saddr, addr->daddr, IPPROTO_TCP,
380  addr->source, addr->dest, t->decode->dc_name,
381  obuf, len);
382  }
383  }
384  hs->collect = 0;
385 }
386 
387 void
388 trigger_tcp(struct tcp_stream *ts, void **conn_save)
389 {
390  struct trigger *ct, *st, tr;
391 
392  tr.num = ts->addr.dest;
393  ct = (struct trigger *) bsearch(&tr, &tcp_triggers, tcp_cnt,
394  sizeof(tr), trigger_compare);
395 
396  tr.num = 0 - (int) ts->addr.dest;
397  st = (struct trigger *) bsearch(&tr, &tcp_triggers, tcp_cnt,
398  sizeof(tr), trigger_compare);
399 
400  switch (ts->nids_state) {
401 
402  case NIDS_JUST_EST:
403  if (ct != NULL || Opt_magic) {
404  ts->server.collect = 1;
405  }
406  if (st != NULL) {
407  ts->client.collect = 1;
408  }
409  break;
410 
411  case NIDS_DATA:
412  if ((ct != NULL || Opt_magic) && ts->server.count_new) {
413  if (ts->server.count - ts->server.offset >=
414  Opt_snaplen) {
415  trigger_tcp_half(&ts->addr, &ts->server, ct);
416  }
417  else nids_discard(ts, 0);
418  }
419  else if (st != NULL && ts->client.count_new) {
420  if (ts->client.count - ts->client.offset >=
421  Opt_snaplen) {
422  trigger_tcp_half(&ts->addr, &ts->client, st);
423  }
424  else nids_discard(ts, 0);
425  }
426  break;
427 
428  default:
429  if ((ct != NULL || Opt_magic) && ts->server.count > 0) {
430  trigger_tcp_half(&ts->addr, &ts->server, ct);
431  }
432  if (st != NULL && ts->client.count > 0) {
433  trigger_tcp_half(&ts->addr, &ts->client, st);
434  }
435  break;
436  }
437 }
438 
439 void
440 trigger_tcp_raw(struct libnet_ipv4_hdr *ip)
441 {
442  struct trigger *t, tr;
443  struct libnet_tcp_hdr *tcp;
444  struct iovec *iov;
445  int len, ip_hl = ip->ip_hl * 4;
446 
447  len = ntohs(ip->ip_len) - ip_hl;
448 
449  if (ip->ip_p != IPPROTO_TCP || len < sizeof(*tcp))
450  return;
451 
452  tcp = (struct libnet_tcp_hdr *)((u_char *)ip + ip_hl);
453 
454  tr.num = ntohs(tcp->th_dport);
455 
456  t = (struct trigger *) bsearch(&tr, &tcp_triggers, tcp_cnt,
457  sizeof(tr), trigger_compare);
458  if (t == NULL) {
459  tr.num = 0 - (int) ntohs(tcp->th_sport);
460  t = (struct trigger *) bsearch(&tr, &tcp_triggers, tcp_cnt,
461  sizeof(tr), trigger_compare);
462  if (t == NULL && !Opt_magic)
463  return;
464  }
465  if ((iov = tcp_raw_input(ip, tcp, len)) == NULL)
466  return;
467 
468  if (t == NULL && Opt_magic)
469  t = trigger_set_magic(IPPROTO_TCP, ntohs(tcp->th_dport),
470  iov->iov_base, iov->iov_len);
471 
472  if (t != NULL) {
473  if (Opt_debug)
474  warnx("trigger_tcp_raw: decoding port %d as %s",
475  tr.num, t->decode->dc_name);
476 
477  len = t->decode->dc_func(iov->iov_base, iov->iov_len,
478  obuf, sizeof(obuf));
479 
480  if (len > 0) {
481  record(ip->ip_src.s_addr, ip->ip_dst.s_addr,
482  IPPROTO_TCP, ntohs(tcp->th_sport),
483  ntohs(tcp->th_dport), t->decode->dc_name,
484  obuf, len);
485  }
486  }
487  free(iov->iov_base);
488  free(iov);
489 }
490 
491 static void
493  u_short sport, u_short dport,
494  u_char *buf, int len)
495 {
496  struct trigger *t, tr;
497 
498  tr.num = dport;
499 
500  t = (struct trigger *) bsearch(&tr, &tcp_triggers, tcp_cnt,
501  sizeof(tr), trigger_compare);
502  if (t == NULL && Opt_magic)
503  t = trigger_set_magic(IPPROTO_TCP, dport, buf, len);
504 
505  if (t != NULL) {
506  if (Opt_debug)
507  warnx("trigger_tcp_raw_timeout: "
508  "decoding port %d as %s",
509  tr.num, t->decode->dc_name);
510 
511  if ((len = t->decode->dc_func(buf, len,
512  obuf, sizeof(obuf))) > 0) {
513  record(src, dst, IPPROTO_TCP, sport, dport,
514  t->decode->dc_name, obuf, len);
515  }
516  }
517 }
518 
519 void
521 {
524 }
525 
526 void
527 trigger_rpc(int program, int proto, int port)
528 {
529  struct trigger *t, tr;
530 
531  tr.num = program;
532 
533  t = (struct trigger *) bsearch(&tr, &rpc_triggers, rpc_cnt,
534  sizeof(tr), trigger_compare);
535  if (t == NULL)
536  return;
537 
538  if (proto == IPPROTO_UDP) {
539  trigger_set_udp(port, t->decode->dc_name);
540  }
541  else if (proto == IPPROTO_TCP) {
542  trigger_set_tcp(port, t->decode->dc_name);
543  }
544 }
545 
546 void
547 trigger_init_magic(char *filename)
548 {
549  magic_init(filename);
550 }
551 
552 void
553 trigger_init_list(char *list)
554 {
555  char *name, *port, *proto = NULL;
556 
557  while ((name = strsep(&list, ",")) != NULL) {
558  if ((port = strsep(&name, "/")) == NULL ||
559  (proto = strsep(&name, "=")) == NULL) {
560  errx(1, "trigger_init_list: parse error");
561  }
562  trigger_set(proto, atoi(port), name);
563  }
564 }
565 
566 void
567 trigger_init_services(char *services)
568 {
569  FILE *f;
570  char *name, *port, *proto, line[1024];
571 
572  if ((f = fopen(services, "r")) == NULL)
573  errx(1, "couldn't open %s", services);
574 
575  while (fgets(line, sizeof(line), f) != NULL) {
576  if (line[0] == '#' || line[0] == '\n')
577  continue;
578 
579  if ((name = strtok(line, " \t")) == NULL ||
580  (port = strtok(NULL, " \t/")) == NULL ||
581  (proto = strtok(NULL, " \t#\n")) == NULL) {
582  continue;
583  }
584  trigger_set(proto, atoi(port), name);
585  }
586  fclose(f);
587 }
588 
trigger_tcp_raw_timeout
void trigger_tcp_raw_timeout(int signal)
Definition: trigger.c:520
trigger
Definition: trigger.c:28
trigger_set_rpc
int trigger_set_rpc(int num, char *name)
Definition: trigger.c:159
trigger_tcp_half
static void trigger_tcp_half(struct tuple4 *addr, struct half_stream *hs, struct trigger *t)
Definition: trigger.c:354
trigger_rpc
void trigger_rpc(int program, int proto, int port)
Definition: trigger.c:527
Opt_magic
int Opt_magic
Definition: dsniff.c:39
ip_triggers
static struct trigger ip_triggers[32]
Definition: trigger.c:33
warnx
void warnx(const char *fmt,...)
Definition: err.c:89
tcp_triggers
static struct trigger tcp_triggers[512]
Definition: trigger.c:35
trigger_tcp
void trigger_tcp(struct tcp_stream *ts, void **conn_save)
Definition: trigger.c:388
trigger_init_services
void trigger_init_services(char *services)
Definition: trigger.c:567
rpc_triggers
static struct trigger rpc_triggers[32]
Definition: trigger.c:36
buf::offset
int offset
Definition: buf.h:17
getdecodebyname
struct decode * getdecodebyname(const char *name)
Definition: decode.c:97
trigger::decode
struct decode * decode
Definition: trigger.c:30
Opt_debug
int Opt_debug
Definition: dsniff.c:37
strsep
char * strsep(char **stringp, const char *delim)
Definition: strsep.c:52
options.h
buf
static u_char buf[BUFSIZ]
Definition: filenamesnarf.c:29
decode::dc_func
decode_func dc_func
Definition: decode.h:18
trigger_set_tcp
int trigger_set_tcp(int num, char *name)
Definition: trigger.c:127
magic.h
record.h
trigger_dump
void trigger_dump(void)
Definition: trigger.c:247
trigger_init_magic
void trigger_init_magic(char *filename)
Definition: trigger.c:547
trigger_set_udp
int trigger_set_udp(int num, char *name)
Definition: trigger.c:95
decode.h
magic_init
void magic_init(char *filename)
Definition: magic.c:502
trigger_init_list
void trigger_init_list(char *list)
Definition: trigger.c:553
udp_cnt
static u_int udp_cnt
Definition: trigger.c:39
magic_match
char * magic_match(u_char *s, int len)
Definition: magic.c:774
tcp_raw.h
trigger::num
int num
Definition: trigger.c:29
rpc_cnt
static u_int rpc_cnt
Definition: trigger.c:41
err.h
buf
Definition: buf.h:14
trigger_tcp_raw_callback
static void trigger_tcp_raw_callback(u_int32_t src, u_int32_t dst, u_short sport, u_short dport, u_char *buf, int len)
Definition: trigger.c:492
tcp_cnt
static u_int tcp_cnt
Definition: trigger.c:40
decode
Definition: decode.h:16
TRIGGER_TCP_RAW_TIMEOUT
#define TRIGGER_TCP_RAW_TIMEOUT
Definition: trigger.h:14
errx
void errx(int eval, const char *fmt,...)
Definition: err.c:76
line
Definition: sshow.c:62
warn
void warn(const char *fmt,...)
Definition: err.c:62
Opt_snaplen
int Opt_snaplen
Definition: dsniff.c:42
trigger_set
static int trigger_set(char *proto, int num, char *name)
Definition: trigger.c:192
ip_cnt
static u_int ip_cnt
Definition: trigger.c:38
record
int record(u_int32_t src, u_int32_t dst, int proto, u_short sport, u_short dport, char *name, u_char *buf, int len)
Definition: record.c:177
trigger.h
in_addr_t
#define in_addr_t
Definition: config.h:32
decode::dc_name
char * dc_name
Definition: decode.h:17
trigger_set_ip
int trigger_set_ip(int num, char *name)
Definition: trigger.c:63
trigger_udp
void trigger_udp(struct libnet_ipv4_hdr *ip)
Definition: trigger.c:308
config.h
trigger_tcp_raw
void trigger_tcp_raw(struct libnet_ipv4_hdr *ip)
Definition: trigger.c:440
obuf
static char obuf[4096]
Definition: trigger.c:43
tcp_raw_input
struct iovec * tcp_raw_input(struct libnet_ipv4_hdr *ip, struct libnet_tcp_hdr *tcp, int len)
Definition: tcp_raw.c:122
pathnames.h
trigger_compare
static int trigger_compare(const void *a, const void *b)
Definition: trigger.c:46
tcp_raw_timeout
void tcp_raw_timeout(int timeout, tcp_raw_callback_t callback)
Definition: tcp_raw.c:216
trigger_ip
void trigger_ip(struct libnet_ipv4_hdr *ip)
Definition: trigger.c:279
DSNIFF_SERVICES
#define DSNIFF_SERVICES
Definition: pathnames.h:18
trigger_set_magic
static struct trigger * trigger_set_magic(int proto, int num, u_char *buf, int len)
Definition: trigger.c:212
udp_triggers
static struct trigger udp_triggers[512]
Definition: trigger.c:34