Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: 8c5f73e26b
Fetching contributors…

Cannot retrieve contributors at this time

217 lines (160 sloc) 6.552 kb
/*
- sagan-plog.c is largely based of Marcus J. Ranum (2004) work known as
plog.c. The original source can be located at:
http://www.ranum.com/security/computer_security/code/plog.tar
This code (sagan-plog.c) is redistributed under the same license
Marcus J. Ranum specified in his original work.
-- From the plog.c source code and applies to sagan-plog.c as well:
Marcus J. Ranum, 2004 - All rights reserved
This software may be used and redistributed free of charge,
but may not be incorporated into a commercial product or
offering without the author's permission.
Plog - promiscuous syslog injector. Listens to a pcap/bpf
interface, sucks up UDP syslog messages, finds the message
within the packet, and injects it into /dev/log.
--
Permission to implement the plog functionality was obtain by Champ Clark III from Marcus J. Ranum on Jan. 6th, 2011.
*/
#ifdef HAVE_CONFIG_H
#include "config.h" /* From autoconf */
#endif
#ifdef HAVE_LIBPCAP
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <pcap.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
#include "sagan.h"
struct my_udphdr {
u_int16_t uh_sport; /* source port */
u_int16_t uh_dport; /* destination port */
u_int16_t uh_ulen; /* udp length */
u_int16_t uh_sum; /* udp checksum */
};
static void logpkt(u_char *,const struct pcap_pkthdr *,const u_char *);
static int wiredevlog( _SaganConfig *);
static int outf;
void plog_handler(_SaganSigArgs *args )
{
pcap_t *bp;
struct bpf_program filtr;
char *iface=NULL;
char eb[PCAP_ERRBUF_SIZE];
char filterstr[128];
iface = args->config->plog_interface;
sagan_log(args->config, 0, "");
sagan_log(args->config, 0, "Initalizing Sagan syslog sniffer thread (PLOG)");
sagan_log(args->config, 0, "Interface: %s", iface);
sagan_log(args->config, 0, "UDP port to monitor: %d", args->config->plog_port);
sagan_log(args->config, 0, "Log device: %s", args->config->plog_logdev);
sagan_log(args->config, 0, "");
if(iface == (char *)0) {
if((iface = pcap_lookupdev(eb)) == (char *)0)
sagan_log(args->config, 1, "[%s, line %d] Cannot get device: %s", __FILE__, __LINE__, eb);
}
bp = pcap_open_live(iface,4096,0,0,eb);
if(bp == (pcap_t *)0)
sagan_log(args->config, 1, "[%s, line %d] Cannot open interface %s: %s", __FILE__, __LINE__, iface, eb);
/* compile and install our filter */
/* Port is configurable via int config->plog_port */
snprintf(filterstr, sizeof(filterstr), "udp port %d", args->config->plog_port);
if(pcap_compile(bp,&filtr,filterstr,1,0))
sagan_log(args->config, 1, "[%s, line %d] Cannot compile filter: %s", __FILE__, __LINE__, eb);
if(pcap_setfilter(bp,&filtr))
sagan_log(args->config, 1, "[%s, line %d] Cannot install filter in %s: %s", __FILE__, __LINE__, iface, eb);
/* wireup /dev/log; we can't use openlog() because these are going to be raw inputs */
if(wiredevlog(args->config)) {
removelockfile(args->config);
sagan_log(args->config, 1, "[%s, line %d] Cannot open %s (Syslog not using SOCK_DGRAM?)", __FILE__, __LINE__, args->config->plog_logdev);
}
/* endless loop */
(void)pcap_loop(bp,-1,logpkt, (u_char*)args);
pcap_close(bp);
exit(0);
}
/* take a raw packet and write it to /dev/log... we are evil! */
static void
logpkt(u_char *pass_args,const struct pcap_pkthdr *p,const u_char *pkt)
{
struct ether_header *eh;
struct ip *ih;
struct my_udphdr *u;
int off;
int len;
char *l;
_SaganSigArgs *args = (_SaganSigArgs *) pass_args;
/* crack the ethernet header */
eh = (struct ether_header *)pkt;
if(ntohs(eh->ether_type) != ETHERTYPE_IP)
goto bad;
/* crack the IP header */
ih = (struct ip *)(pkt + sizeof(struct ether_header));
off = ntohs(ih->ip_off);
len = ntohs(ih->ip_len);
/* short packet */
if(len > p->len)
goto bad;
/* frags we don't deal with */
if((off & 0x1fff) != 0)
goto bad;
/* weird - we ASKED for UDP */
if(ih->ip_p != IPPROTO_UDP)
goto bad;
/* line the UDP header up */
u = (struct my_udphdr *)(pkt + sizeof(struct ether_header) + (ih->ip_hl * 4));
/* WTF? */
if(ntohs(u->uh_dport) != 514)
goto bad;
if(ntohs(u->uh_ulen < 8))
goto bad;
/* our log message ought to be just past the UDP header now... */
l = (char *)u + sizeof(struct udphdr);
len = ntohs(u->uh_ulen) - sizeof(struct udphdr);
if(args->debug->debugplog) {
int x;
/* I can't use sagan_log() here, so we dump to strerr.
* have the check the tty (isatty()) before dumping or
* strange things happen if detached and threaded
* - Champ Clark III Jan 7th 2011
*/
for(x = 0; x < len; x++) {
if(isprint(l[x]) && (isatty(1)) )
fprintf(stderr,"%c",(int)(l[x]));
else
fprintf(stderr,"[0x%x]",(int)(l[x]));
}
if (isatty(1)) fprintf(stderr,"\n");
}
/* send it! */
if(send(outf,l,len,0) < 0)
sagan_log(args->config, 1, "[%s, line %d] Send error", __FILE__, __LINE__);
return;
bad:
sagan_log(args->config, 0, "[%s, line %d] Malformed packet received.", __FILE__, __LINE__);
}
static int
wiredevlog( _SaganConfig *config )
{
struct sockaddr s;
s.sa_family = AF_UNIX;
(void)strncpy(s.sa_data,config->plog_logdev,sizeof(s.sa_data));
/* Might want to investigate SOCK_STREAM (see syslog-ng) in the future.
* Right now, the syslog server must use SOCK_DGRAM */
if((outf = socket(AF_UNIX,SOCK_DGRAM,0)) < 0)
return(1);
if(connect(outf,&s,sizeof(s)))
return(1);
return(0);
}
#endif
Jump to Line
Something went wrong with that request. Please try again.