📄 mailsnarf.c
字号:
/* mailsnarf.c Sniff mail on a network, saving messages in Berkeley mbox format. Copyright (c) 1999 Dug Song <dugsong@monkey.org> $Id: mailsnarf.c,v 1.37 2000/11/19 19:39:41 dugsong Exp $*/#include "config.h"#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <time.h>#include <regex.h>#include <err.h>#include <libnet.h>#include <nids.h>#include <pcap.h>#include "pcaputil.h"#include "buf.h"#include "version.h"/* bogus SMTP state machine */enum { SMTP_NONE = 0, SMTP_HELO, SMTP_MAIL, SMTP_RCPT, SMTP_DATA};/* likewise, POP. */enum { POP_NONE = 0, POP_RETR, POP_DATA};struct smtp_info { int state; char *from;};struct pop_info { int state;};int Opt_invert = 0;regex_t *pregex = NULL;voidusage(void){ fprintf(stderr, "Version: " VERSION "\n" "Usage: mailsnarf [-i interface] [[-v] pattern [expression]]\n"); exit(1);}intregex_match(char *string){ return (pregex == NULL || ((regexec(pregex, string, 0, NULL, 0) == 0) ^ Opt_invert));}char *grep_mail_address(char *buf){ char *p, *q; if ((p = strchr(buf, '<')) != NULL) { p++; if ((q = strchr(p, '>')) != NULL) *q = '\0'; if (strlen(p) > 0) return (strdup(p)); } return (NULL);}voidprint_mbox_msg(char *from, char *msg){ char *p; time_t t; t = time(NULL); if (from == NULL) from = "mailsnarf"; printf("From %s %s", from, ctime(&t)); while ((p = strsep(&msg, "\n")) != NULL) { if (strncmp(p, "From ", 5) == 0) putchar('>'); for (; *p != '\r' && *p != '\0'; p++) putchar(*p); putchar('\n'); } putchar('\n'); fflush(stdout);}intprocess_pop_client(struct pop_info *pop, char *data, int len){ struct buf *line, buf; int i; buf_init(&buf, data, len); while ((i = buf_index(&buf, "\r\n", 2)) >= 0) { line = buf_tok(&buf, NULL, i + 2); line->base[line->end] = '\0'; if (strncasecmp(buf_ptr(line), "RETR ", 5) == 0) { pop->state = POP_RETR; } else pop->state = POP_NONE; } return (len - buf_len(&buf));}intprocess_pop_server(struct pop_info *pop, char *data, int len){ struct buf *line, *body, buf; int i; buf_init(&buf, data, len); if (pop->state == POP_NONE) return (len); if (pop->state == POP_RETR) { if ((i = buf_index(&buf, "\r\n", 2)) < 0) return (0); line = buf_tok(&buf, NULL, i + 2); if (buf_cmp(line, "+OK", 3) == 0) { pop->state = POP_DATA; } else pop->state = POP_NONE; } if (pop->state == POP_DATA) { if ((i = buf_index(&buf, "\r\n.\r\n", 5)) >= 0) { body = buf_tok(&buf, NULL, i); buf_skip(&buf, 5); body->base[body->end] = '\0'; if (regex_match(buf_ptr(body))) print_mbox_msg(NULL, buf_ptr(body)); pop->state = POP_NONE; } } return (len - buf_len(&buf));}intprocess_smtp_client(struct smtp_info *smtp, char *data, int len){ struct buf *line, *body, buf; char *p; int i; buf_init(&buf, data, len); if (smtp->state != SMTP_DATA) { while ((i = buf_index(&buf, "\r\n", 2)) >= 0) { line = buf_tok(&buf, NULL, i + 2); line->base[line->end] = '\0'; p = buf_ptr(line); if (strncasecmp(p, "RSET", 4) == 0) { smtp->state = SMTP_HELO; } else if (smtp->state == SMTP_NONE && (strncasecmp(p, "HELO", 4) == 0 || strncasecmp(p, "EHLO", 4) == 0)) { smtp->state = SMTP_HELO; } else if (smtp->state == SMTP_HELO && (strncasecmp(p, "MAIL ", 5) == 0 || strncasecmp(p, "SEND ", 5) == 0 || strncasecmp(p, "SAML ", 5) == 0)) { smtp->from = grep_mail_address(p); smtp->state = SMTP_MAIL; } else if (smtp->state == SMTP_MAIL && strncasecmp(p, "RCPT ", 5) == 0) { smtp->state = SMTP_RCPT; } else if (smtp->state == SMTP_RCPT && strncasecmp(p, "DATA", 4) == 0) { smtp->state = SMTP_DATA; break; } } } if (smtp->state == SMTP_DATA) { if ((i = buf_index(&buf, "\r\n.\r\n", 5)) >= 0) { body = buf_tok(&buf, NULL, i); buf_skip(&buf, 5); body->base[body->end] = '\0'; if (regex_match(buf_ptr(body))) print_mbox_msg(smtp->from, buf_ptr(body)); if (smtp->from) { free(smtp->from); smtp->from = NULL; } smtp->state = SMTP_HELO; } } return (len - buf_len(&buf));}voidsniff_pop_session(struct tcp_stream *ts, struct pop_info **pop_save){ struct pop_info *pop; int i; if (ts->addr.dest != 110 && ts->addr.source != 110 && /* POP3 */ ts->addr.dest != 109 && ts->addr.source != 109 && /* POP2 */ ts->addr.dest != 1109 && ts->addr.source != 1109) /* KPOP */ return; switch (ts->nids_state) { case NIDS_JUST_EST: ts->server.collect = 1; ts->client.collect = 1; if ((pop = (struct pop_info *) malloc(sizeof(*pop))) == NULL) nids_params.no_mem("sniff_pop_session"); pop->state = POP_NONE; *pop_save = pop; break; case NIDS_DATA: pop = *pop_save; if (ts->server.count_new > 0) { i = process_pop_client(pop, ts->server.data, ts->server.count - ts->server.offset); nids_discard(ts, i); } else if (ts->client.count_new > 0) { i = process_pop_server(pop, ts->client.data, ts->client.count - ts->client.offset); nids_discard(ts, i); } break; default: pop = *pop_save; if (ts->server.count > 0) process_pop_client(pop, ts->server.data, ts->server.count - ts->server.offset); else if (ts->client.count > 0) process_pop_server(pop, ts->client.data, ts->client.count - ts->client.offset); free(pop); break; }}/* XXX - Minimal SMTP FSM. We don't even consider server responses. */voidsniff_smtp_client(struct tcp_stream *ts, struct smtp_info **smtp_save){ struct smtp_info *smtp; int i; if (ts->addr.dest != 25) return; switch (ts->nids_state) { case NIDS_JUST_EST: ts->server.collect = 1; if ((smtp = (struct smtp_info *)malloc(sizeof(*smtp))) == NULL) nids_params.no_mem("sniff_smtp_client"); smtp->state = SMTP_NONE; smtp->from = NULL; *smtp_save = smtp; break; case NIDS_DATA: smtp = *smtp_save; if (ts->server.count_new > 0) { i = process_smtp_client(smtp, ts->server.data, ts->server.count - ts->server.offset); nids_discard(ts, i); } break; default: smtp = *smtp_save; if (ts->server.count > 0) { process_smtp_client(smtp, ts->server.data, ts->server.count - ts->server.offset); } if (smtp->from) free(smtp->from); free(smtp); break; }}voidnull_syslog(int type, int errnum, struct ip *iph, void *data){}intmain(int argc, char *argv[]){ int c; while ((c = getopt(argc, argv, "i:vh?V")) != -1) { switch (c) { case 'i': nids_params.device = optarg; break; case 'v': Opt_invert = 1; break; default: usage(); } } argc -= optind; argv += optind; if (argc > 0 && strlen(argv[0])) { if ((pregex = (regex_t *) malloc(sizeof(*pregex))) == NULL) err(1, "malloc"); if (regcomp(pregex, argv[0], REG_EXTENDED|REG_NOSUB) != 0) errx(1, "invalid regular expression"); } if (argc > 1) nids_params.pcap_filter = copy_argv(argv + 1); nids_params.scan_num_hosts = 0; nids_params.syslog = null_syslog; if (!nids_init()) errx(1, "%s", nids_errbuf); nids_register_tcp(sniff_smtp_client); nids_register_tcp(sniff_pop_session); if (nids_params.pcap_filter != NULL) { warnx("listening on %s [%s]", nids_params.device, nids_params.pcap_filter); } else warnx("listening on %s", nids_params.device); nids_run(); /* NOTREACHED */ exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -