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)  

filesnarf.c
Go to the documentation of this file.
1 /*
2  * filesnarf.c
3  *
4  * Sniff files from NFS traffic.
5  *
6  * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
7  *
8  * $Id: filesnarf.c,v 1.13 2001/03/15 08:33:03 dugsong Exp $
9  */
10 
11 #include "config.h"
12 
13 #include <sys/types.h>
14 #include <rpc/rpc.h>
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <fcntl.h>
20 #include <regex.h>
21 #include <err.h>
22 #include <libnet.h>
23 #include <nids.h>
24 #include <pcap.h>
25 
26 #include "decode.h"
27 #include "pcaputil.h"
28 #include "nfs_prot.h"
29 #include "rpc.h"
30 #include "version.h"
31 
32 struct myreadargs {
33  char *filename;
34  u_int offset;
35 };
36 
37 struct fh_map {
38  u_char fh[NFS3_FHSIZE];
39  char *filename;
40 };
41 
42 #define FH_MAP_SIZE 128
43 
45 int fh_map_next = 0;
46 int fh_map_hint = 0;
47 int Opt_invert = 0;
48 regex_t *pregex = NULL;
49 
50 static void
51 usage(void)
52 {
53  fprintf(stderr, "Version: " VERSION "\n"
54  "Usage: filesnarf [-i interface] [[-v] pattern [expression]]\n");
55  exit(1);
56 }
57 
58 /* XXX - for nfs_prot_xdr.c */
59 bool_t
60 xdr_u_int64_t(XDR *xdrs, u_int64_t *nump)
61 {
62  int i = 1;
63  u_char *p = (u_char *)nump;
64 
65  if (*(char *)&i == 1) { /* endian haack. */
66  if (xdr_u_long(xdrs, (u_long *)(p + 4)))
67  return (xdr_u_long(xdrs, (u_long *)p));
68  }
69  else {
70  if (xdr_u_long(xdrs, (u_long *)p))
71  return (xdr_u_long(xdrs, (u_long *)(p + 4)));
72  }
73  return (FALSE);
74 }
75 
76 bool_t
77 xdr_int64_t(XDR *xdrs, int64_t *nump)
78 {
79  return (xdr_u_int64_t(xdrs, (u_int64_t *)nump));
80 }
81 
82 static void
84 {
85  memset(&fh_maps, 0, sizeof(fh_maps));
86 }
87 
88 static void
89 fh_map_add(char *filename, u_char *fh, int len)
90 {
91  struct fh_map *fm;
92 
93  fm = &fh_maps[fh_map_next];
94 
95  if (++fh_map_next > FH_MAP_SIZE)
96  fh_map_next = 0;
97 
98  memcpy(fm->fh, fh, len);
99 
100  if ((fm->filename = strdup(filename)) == NULL)
101  err(1, "fh_map_add: malloc");
102 }
103 
104 static char *
105 fh_map_find(u_char *fh, int len)
106 {
107  struct fh_map *fm;
108  int i;
109 
110  i = fh_map_hint;
111  do {
112  fm = &fh_maps[i];
113  if (memcmp(fm->fh, fh, len) == 0) {
114  fh_map_hint = i;
115  return (fm->filename);
116  }
117  if (++i > FH_MAP_SIZE)
118  i = 0;
119  } while (i != fh_map_hint);
120 
121  return (NULL);
122 }
123 
124 static int
125 regex_match(char *string)
126 {
127  return (pregex == NULL ||
128  ((regexec(pregex, string, 0, NULL, 0) == 0) ^ Opt_invert));
129 }
130 
131 static void
132 nfs_save(struct tuple4 *addr, struct myreadargs *ma, u_char *buf, int len)
133 {
134  int fd;
135 
136  warnx("%s.%d > %s.%d: %s (%d@%d)",
137  libnet_addr2name4(addr->daddr, 0), addr->dest,
138  libnet_addr2name4(addr->saddr, 0), addr->source,
139  ma->filename, len, ma->offset);
140 
141  if ((fd = open(ma->filename, O_WRONLY|O_CREAT, 0644)) >= 0) {
142  if (lseek(fd, ma->offset, SEEK_SET) == ma->offset)
143  write(fd, buf, len);
144  }
145  close(fd);
146 }
147 
148 static void
149 nfs2_call(u_int32_t xid, u_int32_t proc, u_char *buf, int len)
150 {
151  XDR xdrs;
152  struct diropargs dargs;
153  struct readargs rargs;
154  struct myreadargs *ma;
155  char *fname;
156 
157  switch (proc) {
158 
159  case NFSPROC_LOOKUP:
160  memset(&dargs, 0, sizeof(dargs));
161  xdrmem_create(&xdrs, buf, len, XDR_DECODE);
162 
163  if (xdr_diropargs(&xdrs, &dargs)) {
164  if (regex_match(dargs.name)) {
165  xid_map_enter(xid, NFS_PROGRAM, NFS_VERSION,
166  proc, (void *)dargs.name);
167  }
168  }
169  xdr_destroy(&xdrs);
170  break;
171 
172  case NFSPROC_READ:
173  memset(&rargs, 0, sizeof(rargs));
174  xdrmem_create(&xdrs, buf, len, XDR_DECODE);
175 
176  if (xdr_readargs(&xdrs, &rargs)) {
177  fname = fh_map_find(rargs.file.data, NFS_FHSIZE);
178  if (fname != NULL) {
179  ma = (struct myreadargs *) malloc(sizeof(*ma));
180  if (ma != NULL) {
181  ma->filename = fname;
182  ma->offset = rargs.offset;
183  xid_map_enter(xid, NFS_PROGRAM,
184  NFS_VERSION,
185  NFSPROC_READ,
186  (void *)ma);
187  }
188  }
189  }
190  xdr_destroy(&xdrs);
191  break;
192  }
193 }
194 
195 static void
196 nfs2_reply(struct xid_map *xm, struct tuple4 *addr, u_char *buf, int len)
197 {
198  XDR xdrs;
199  struct diropres dres;
200  struct readres rres;
201 
202  switch (xm->proc) {
203 
204  case NFSPROC_LOOKUP:
205  xdrmem_create(&xdrs, buf, len, XDR_DECODE);
206  memset(&dres, 0, sizeof(dres));
207 
208  if (xdr_diropres(&xdrs, &dres)) {
209  if (dres.status == NFS_OK)
210  fh_map_add((char *)xm->data,
211  dres.diropres_u.diropres.file.data,
212  NFS_FHSIZE);
213  }
214  xdr_destroy(&xdrs);
215  break;
216 
217  case NFSPROC_READ:
218  xdrmem_create(&xdrs, buf, len, XDR_DECODE);
219  memset(&rres, 0, sizeof(rres));
220 
221  if (xdr_readres(&xdrs, &rres)) {
222  if (rres.status == NFS_OK) {
223  nfs_save(addr, (struct myreadargs *)xm->data,
224  rres.readres_u.reply.data.data_val,
225  rres.readres_u.reply.data.data_len);
226  }
227  }
228  xdr_destroy(&xdrs);
229  break;
230  }
231 }
232 
233 static void
234 nfs3_call(u_int32_t xid, u_int32_t proc, u_char *buf, int len)
235 {
236  XDR xdrs;
237  struct LOOKUP3args largs;
238  struct READ3args rargs;
239  struct myreadargs *ma;
240  char *fname;
241 
242  switch (proc) {
243 
244  case NFSPROC3_LOOKUP:
245  memset(&largs, 0, sizeof(largs));
246  xdrmem_create(&xdrs, buf, len, XDR_DECODE);
247 
248  if (xdr_LOOKUP3args(&xdrs, &largs)) {
249  if (regex_match(largs.what.name)) {
250  xid_map_enter(xid, NFS_PROGRAM, NFS_V3,
251  proc, (void *)largs.what.name);
252  }
253  }
254  xdr_destroy(&xdrs);
255  break;
256 
257  case NFSPROC3_READ:
258  memset(&rargs, 0, sizeof(rargs));
259  xdrmem_create(&xdrs, buf, len, XDR_DECODE);
260 
261  if (xdr_READ3args(&xdrs, &rargs)) {
262  fname = fh_map_find(rargs.file.data.data_val,
263  rargs.file.data.data_len);
264  if (fname != NULL) {
265  ma = (struct myreadargs *) malloc(sizeof(*ma));
266  if (ma != NULL) {
267  ma->filename = fname;
268  ma->offset = rargs.offset;
269  xid_map_enter(xid, NFS_PROGRAM, NFS_V3,
270  NFSPROC_READ,
271  (void *)ma);
272  }
273  }
274  }
275  xdr_destroy(&xdrs);
276  break;
277  }
278 }
279 
280 static void
281 nfs3_reply(struct xid_map *xm, struct tuple4 *addr, u_char *buf, int len)
282 {
283  XDR xdrs;
284  struct LOOKUP3res lres;
285  struct READ3res rres;
286 
287  switch (xm->proc) {
288 
289  case NFSPROC3_LOOKUP:
290  xdrmem_create(&xdrs, buf, len, XDR_DECODE);
291  memset(&lres, 0, sizeof(lres));
292 
293  if (xdr_LOOKUP3res(&xdrs, &lres)) {
294  if (lres.status == NFS3_OK) {
295  fh_map_add((char *)xm->data,
296  lres.LOOKUP3res_u.resok.object.data.data_val,
297  lres.LOOKUP3res_u.resok.object.data.data_len);
298  }
299  }
300  xdr_destroy(&xdrs);
301  break;
302 
303  case NFSPROC3_READ:
304  xdrmem_create(&xdrs, buf, len, XDR_DECODE);
305  memset(&rres, 0, sizeof(rres));
306 
307  if (xdr_READ3res(&xdrs, &rres)) {
308  if (rres.status == NFS3_OK) {
309  nfs_save(addr, (struct myreadargs *)xm->data,
310  rres.READ3res_u.resok.data.data_val,
311  rres.READ3res_u.resok.data.data_len);
312  }
313  }
314  xdr_destroy(&xdrs);
315  break;
316  }
317 }
318 
319 static void
320 decode_nfs(struct tuple4 *addr, u_char *buf, int len)
321 {
322  struct rpc_msg msg;
323  struct xid_map *xm;
324  int hdrlen;
325 
326  memset(&msg, 0, sizeof(msg));
327 
328  if ((hdrlen = rpc_decode(buf, len, &msg)) == 0)
329  return;
330 
331  buf += hdrlen;
332  len -= hdrlen;
333 
334  if (msg.rm_direction == CALL && msg.rm_call.cb_prog == NFS_PROGRAM) {
335  if (msg.rm_call.cb_vers == NFS_VERSION)
336  nfs2_call(msg.rm_xid, msg.rm_call.cb_proc, buf, len);
337  else if (msg.rm_call.cb_vers == NFS_V3)
338  nfs3_call(msg.rm_xid, msg.rm_call.cb_proc, buf, len);
339  }
340  else if ((xm = xid_map_find(msg.rm_xid)) != NULL &&
341  msg.rm_direction == REPLY &&
342  msg.rm_reply.rp_stat == MSG_ACCEPTED &&
343  msg.acpted_rply.ar_stat == SUCCESS) {
344 
345  if (xm->vers == NFS_VERSION)
346  nfs2_reply(xm, addr, buf, len);
347  else if (xm->vers == NFS_V3)
348  nfs3_reply(xm, addr, buf, len);
349 
350  free(xm->data);
351  memset(xm, 0, sizeof(*xm));
352  }
353 }
354 
355 static void
356 decode_udp_nfs(struct libnet_ipv4_hdr *ip)
357 {
358  static struct tuple4 addr;
359  struct libnet_udp_hdr *udp;
360  u_char *buf;
361  int len, ip_hl = ip->ip_hl * 4;
362 
363  len = ntohs(ip->ip_len) - ip_hl;
364 
365  if (ip->ip_p != IPPROTO_UDP || len < sizeof(*udp))
366  return;
367 
368  buf = (u_char *)ip + ip_hl;
369  udp = (struct libnet_udp_hdr *)buf;
370 
371  if (ntohs(udp->uh_sport) != 2049 && ntohs(udp->uh_dport) != 2049)
372  return;
373 
374  if (len != ntohs(udp->uh_ulen))
375  return;
376 
377  buf += sizeof(*udp);
378  len -= sizeof(*udp);
379 
380  addr.saddr = ip->ip_dst.s_addr;
381  addr.daddr = ip->ip_src.s_addr;
382  addr.source = ntohs(udp->uh_dport);
383  addr.dest = ntohs(udp->uh_sport);
384 
385  decode_nfs(&addr, buf, len);
386 }
387 
388 static int
389 decode_tcp_nfs_half(struct tuple4 *addr, struct half_stream *hs)
390 {
391  u_char *p, *buf;
392  int i, len, discard;
393  u_int32_t fraghdr;
394 
395  buf = hs->data;
396  len = hs->count - hs->offset;
397  discard = 0;
398 
399  for (p = buf; p + 4 < buf + len; ) {
400  fraghdr = pntohl(p);
401  p += 4 + FRAGLEN(fraghdr);
402 
403  if (p > buf + len)
404  return (0);
405 
406  if (LASTFRAG(fraghdr)) {
407  i = p - buf;
408 
409  decode_nfs(addr, buf, i);
410 
411  buf += i;
412  len -= i;
413  discard += i;
414  }
415  }
416  return (discard);
417 }
418 
419 static void
420 decode_tcp_nfs(struct tcp_stream *ts, void **darth)
421 {
422  int len = 0;
423 
424  if (ts->addr.dest != 2049 && ts->addr.source != 2049)
425  return;
426 
427  switch (ts->nids_state) {
428 
429  case NIDS_JUST_EST:
430  ts->server.collect = 1;
431  ts->client.collect = 1;
432  break;
433 
434  case NIDS_DATA:
435  if (ts->server.count_new > 0) {
436  len = decode_tcp_nfs_half(&ts->addr, &ts->server);
437  }
438  else if (ts->client.count_new > 0) {
439  len = decode_tcp_nfs_half(&ts->addr, &ts->client);
440  }
441  nids_discard(ts, len);
442  break;
443 
444  default:
445  if (ts->server.count > 0) {
446  decode_tcp_nfs_half(&ts->addr, &ts->server);
447  }
448  else if (ts->client.count > 0) {
449  decode_tcp_nfs_half(&ts->addr, &ts->client);
450  }
451  break;
452  }
453 }
454 
455 static void
456 null_syslog(int type, int errnum, struct ip *iph, void *data)
457 {
458 }
459 
460 int
461 main(int argc, char *argv[])
462 {
463  extern char *optarg;
464  extern int optind;
465  int c;
466 
467  while ((c = getopt(argc, argv, "i:vh?V")) != -1) {
468  switch (c) {
469  case 'i':
470  nids_params.device = optarg;
471  break;
472  case 'v':
473  Opt_invert = 1;
474  break;
475  default:
476  usage();
477  }
478  }
479  argc -= optind;
480  argv += optind;
481 
482  if (argc > 0 && strlen(argv[0])) {
483  if ((pregex = (regex_t *) malloc(sizeof(*pregex))) == NULL)
484  err(1, "malloc");
485  if (regcomp(pregex, argv[0], REG_EXTENDED|REG_NOSUB) != 0)
486  errx(1, "invalid regular expression");
487  }
488  if (argc > 1)
489  nids_params.pcap_filter = copy_argv(argv + 1);
490  nids_params.scan_num_hosts = 0;
491  nids_params.syslog = null_syslog;
492 
493  fh_map_init();
494 
495  if (!nids_init())
496  errx(1, "nids_init: %s", nids_errbuf);
497 
498  nids_register_ip(decode_udp_nfs);
499  nids_register_tcp(decode_tcp_nfs);
500 
501  if (nids_params.pcap_filter != NULL) {
502  warnx("listening on %s [%s]", nids_params.device,
503  nids_params.pcap_filter);
504  }
505  else warnx("listening on %s", nids_params.device);
506 
507  nids_run();
508 
509  /* NOTREACHED */
510 
511  exit(0);
512 }
fh_map_next
int fh_map_next
Definition: filesnarf.c:45
myreadargs::offset
u_int offset
Definition: filesnarf.c:34
warnx
void warnx(const char *fmt,...)
Definition: err.c:89
fh_map_init
static void fh_map_init(void)
Definition: filesnarf.c:83
nfs2_reply
static void nfs2_reply(struct xid_map *xm, struct tuple4 *addr, u_char *buf, int len)
Definition: filesnarf.c:196
xid_map
Definition: rpc.h:17
buf::offset
int offset
Definition: buf.h:17
regex_match
static int regex_match(char *string)
Definition: filesnarf.c:125
xid_map::vers
u_int32_t vers
Definition: rpc.h:20
pcaputil.h
xid_map_enter
void xid_map_enter(u_int32_t xid, u_int32_t prog, u_int32_t vers, u_int32_t proc, void *data)
Definition: rpc.c:30
buf
static u_char buf[BUFSIZ]
Definition: filenamesnarf.c:29
decode_tcp_nfs_half
static int decode_tcp_nfs_half(struct tuple4 *addr, struct half_stream *hs)
Definition: filesnarf.c:389
fh_map::filename
char * filename
Definition: filesnarf.c:39
xid_map_find
struct xid_map * xid_map_find(int xid)
Definition: rpc.c:48
version.h
fh_map
Definition: filesnarf.c:37
pntohl
#define pntohl(p)
Definition: decode.h:37
fh_maps
struct fh_map fh_maps[128]
Definition: filesnarf.c:44
myreadargs::filename
char * filename
Definition: filesnarf.c:33
nfs3_call
static void nfs3_call(u_int32_t xid, u_int32_t proc, u_char *buf, int len)
Definition: filesnarf.c:234
decode_tcp_nfs
static void decode_tcp_nfs(struct tcp_stream *ts, void **darth)
Definition: filesnarf.c:420
decode.h
pregex
regex_t * pregex
Definition: filesnarf.c:48
decode_udp_nfs
static void decode_udp_nfs(struct libnet_ipv4_hdr *ip)
Definition: filesnarf.c:356
fh_map_find
static char * fh_map_find(u_char *fh, int len)
Definition: filesnarf.c:105
fh_map::fh
u_char fh[NFS3_FHSIZE]
Definition: filesnarf.c:38
null_syslog
static void null_syslog(int type, int errnum, struct ip *iph, void *data)
Definition: filesnarf.c:456
nfs3_reply
static void nfs3_reply(struct xid_map *xm, struct tuple4 *addr, u_char *buf, int len)
Definition: filesnarf.c:281
Opt_invert
int Opt_invert
Definition: filesnarf.c:47
rpc.h
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
usage
static void usage(void)
Definition: filesnarf.c:51
main
int main(int argc, char *argv[])
Definition: filesnarf.c:461
copy_argv
char * copy_argv(char **argv)
Definition: pcaputil.c:101
errx
void errx(int eval, const char *fmt,...)
Definition: err.c:76
fh_map_add
static void fh_map_add(char *filename, u_char *fh, int len)
Definition: filesnarf.c:89
fh_map_hint
int fh_map_hint
Definition: filesnarf.c:46
decode_nfs
static void decode_nfs(struct tuple4 *addr, u_char *buf, int len)
Definition: filesnarf.c:320
nfs2_call
static void nfs2_call(u_int32_t xid, u_int32_t proc, u_char *buf, int len)
Definition: filesnarf.c:149
FH_MAP_SIZE
#define FH_MAP_SIZE
Definition: filesnarf.c:42
nfs_save
static void nfs_save(struct tuple4 *addr, struct myreadargs *ma, u_char *buf, int len)
Definition: filesnarf.c:132
xid_map::data
void * data
Definition: rpc.h:22
LASTFRAG
#define LASTFRAG(x)
Definition: rpc.h:15
memcmp
int memcmp(void *s1, void *s2, size_t n) const
Definition: memcmp.c:44
myreadargs
Definition: filesnarf.c:32
xid_map::proc
u_int32_t proc
Definition: rpc.h:21
FRAGLEN
#define FRAGLEN(x)
Definition: rpc.h:14
config.h
xdr_u_int64_t
bool_t xdr_u_int64_t(XDR *xdrs, u_int64_t *nump)
Definition: filesnarf.c:60
xdr_int64_t
bool_t xdr_int64_t(XDR *xdrs, int64_t *nump)
Definition: filesnarf.c:77
rpc_decode
int rpc_decode(u_char *buf, int len, struct rpc_msg *msg)
Definition: rpc.c:70